Preserve Feishu binding delivery metadata

This commit is contained in:
Tak Hoffman
2026-04-10 19:07:01 -05:00
parent f43140a50f
commit 2c9c6207fa
2 changed files with 62 additions and 8 deletions

View File

@@ -91,4 +91,53 @@ describe("Feishu thread bindings", () => {
}),
).toBeNull();
});
it("preserves delivery routing metadata when rebinding the same conversation", async () => {
const manager = createFeishuThreadBindingManager({ cfg: baseCfg, accountId: "default" });
manager.bindConversation({
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_sender_1",
parentConversationId: "oc_group_chat",
targetKind: "subagent",
targetSessionKey: "agent:main:subagent:child",
metadata: {
agentId: "codex",
label: "child",
boundBy: "system",
deliveryTo: "user:ou_sender_1",
deliveryThreadId: "om_topic_root",
},
});
await getSessionBindingService().bind({
targetSessionKey: "agent:main:subagent:child",
targetKind: "subagent",
conversation: {
channel: "feishu",
accountId: "default",
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_sender_1",
parentConversationId: "oc_group_chat",
},
placement: "current",
metadata: {
label: "child",
},
});
expect(
getSessionBindingService().resolveByConversation({
channel: "feishu",
accountId: "default",
conversationId: "oc_group_chat:topic:om_topic_root:sender:ou_sender_1",
}),
).toMatchObject({
metadata: expect.objectContaining({
agentId: "codex",
label: "child",
boundBy: "system",
deliveryTo: "user:ou_sender_1",
deliveryThreadId: "om_topic_root",
}),
});
});
});

View File

@@ -159,36 +159,41 @@ export function createFeishuThreadBindingManager(params: {
metadata,
}) => {
const normalizedConversationId = conversationId.trim();
if (!normalizedConversationId || !targetSessionKey.trim()) {
const normalizedTargetSessionKey = targetSessionKey.trim();
if (!normalizedConversationId || !normalizedTargetSessionKey) {
return null;
}
const existing = getState().bindingsByAccountConversation.get(
resolveBindingKey({ accountId, conversationId: normalizedConversationId }),
);
const now = Date.now();
const record: FeishuThreadBindingRecord = {
accountId,
conversationId: normalizedConversationId,
parentConversationId: normalizeOptionalString(parentConversationId),
parentConversationId:
normalizeOptionalString(parentConversationId) ?? existing?.parentConversationId,
deliveryTo:
typeof metadata?.deliveryTo === "string" && metadata.deliveryTo.trim()
? metadata.deliveryTo.trim()
: undefined,
: existing?.deliveryTo,
deliveryThreadId:
typeof metadata?.deliveryThreadId === "string" && metadata.deliveryThreadId.trim()
? metadata.deliveryThreadId.trim()
: undefined,
: existing?.deliveryThreadId,
targetKind: toFeishuTargetKind(targetKind),
targetSessionKey: targetSessionKey.trim(),
targetSessionKey: normalizedTargetSessionKey,
agentId:
typeof metadata?.agentId === "string" && metadata.agentId.trim()
? metadata.agentId.trim()
: resolveAgentIdFromSessionKey(targetSessionKey),
: (existing?.agentId ?? resolveAgentIdFromSessionKey(normalizedTargetSessionKey)),
label:
typeof metadata?.label === "string" && metadata.label.trim()
? metadata.label.trim()
: undefined,
: existing?.label,
boundBy:
typeof metadata?.boundBy === "string" && metadata.boundBy.trim()
? metadata.boundBy.trim()
: undefined,
: existing?.boundBy,
boundAt: now,
lastActivityAt: now,
};