Fix multi-account channel binding drift for #836 (#841)

This commit is contained in:
Lingxuan Zuo
2026-04-13 15:30:13 +08:00
committed by GitHub
Unverified
parent 4ff6861042
commit b2c478d554
5 changed files with 600 additions and 19 deletions

View File

@@ -280,29 +280,33 @@ function upsertBindingsForChannel(
agentId: string | null,
accountId?: string,
): BindingConfig[] | undefined {
const normalizedAgentId = agentId ? normalizeAgentIdForBinding(agentId) : '';
const normalizedAccountId = accountId?.trim() || '';
const nextBindings = Array.isArray(bindings)
? [...bindings as BindingConfig[]].filter((binding) => {
if (!isChannelBinding(binding)) return true;
if (binding.match?.channel !== channelType) return true;
// Keep a single account binding per (agent, channelType). Rebinding to
// another account should replace the previous one.
if (normalizedAgentId && normalizeAgentIdForBinding(binding.agentId || '') === normalizedAgentId) {
return false;
}
// Only remove binding that matches the exact accountId scope
if (accountId) {
return binding.match?.accountId !== accountId;
const bindingAccountId = typeof binding.match?.accountId === 'string'
? binding.match.accountId.trim()
: '';
// Account-scoped updates must only replace the exact account owner.
// Otherwise rebinding one Feishu/Lark account can silently drop a
// sibling account binding on the same agent, which looks like routing
// or model config "drift" in multi-account setups.
if (normalizedAccountId) {
return bindingAccountId !== normalizedAccountId;
}
// No accountId: remove channel-wide binding (legacy)
return Boolean(binding.match?.accountId);
return Boolean(bindingAccountId);
})
: [];
if (agentId) {
const match: BindingMatch = { channel: channelType };
if (accountId) {
match.accountId = accountId;
if (normalizedAccountId) {
match.accountId = normalizedAccountId;
}
nextBindings.push({ agentId, match });
}