fix(acp): preserve Telegram topic-bound conversation ids

This commit is contained in:
Ayaan Zaidi 2026-03-31 10:31:01 +05:30
parent 81b777c768
commit aeee17a689
No known key found for this signature in database
2 changed files with 61 additions and 4 deletions

View File

@ -1319,6 +1319,57 @@ describe("spawnAcpDirect", () => {
expect(agentCall?.params?.channel).toBe("telegram");
});
it("preserves topic-qualified Telegram targets without a separate threadId", async () => {
replaceSpawnConfig({
...hoisted.state.cfg,
channels: {
...hoisted.state.cfg.channels,
telegram: {
threadBindings: {
enabled: true,
},
},
},
});
registerSessionBindingAdapter({
channel: "telegram",
accountId: "default",
capabilities: createSessionBindingCapabilities(),
bind: async (input) => await hoisted.sessionBindingBindMock(input),
listBySession: (targetSessionKey) =>
hoisted.sessionBindingListBySessionMock(targetSessionKey),
resolveByConversation: (ref) => hoisted.sessionBindingResolveByConversationMock(ref),
unbind: async (input) => await hoisted.sessionBindingUnbindMock(input),
});
const result = await spawnAcpDirect(
{
task: "Investigate flaky tests",
agentId: "codex",
mode: "session",
thread: true,
},
{
agentSessionKey: "agent:main:telegram:group:-1003342490704:topic:2",
agentChannel: "telegram",
agentAccountId: "default",
agentTo: "telegram:group:-1003342490704:topic:2",
},
);
expect(result.status).toBe("accepted");
expect(hoisted.sessionBindingBindMock).toHaveBeenCalledWith(
expect.objectContaining({
placement: "current",
conversation: expect.objectContaining({
channel: "telegram",
accountId: "default",
conversationId: "-1003342490704:topic:2",
}),
}),
);
});
it("disposes pre-registered parent relay when initial ACP dispatch fails", async () => {
const relayHandle = createRelayHandle();
hoisted.startAcpSpawnParentStreamRelayMock.mockReturnValueOnce(relayHandle);

View File

@ -385,10 +385,16 @@ function resolveConversationIdForThreadBinding(params: {
}
chatId = next;
}
chatId = chatId
.replace(/:topic:\d+$/i, "")
.replace(/:\d+$/i, "")
.trim();
const topicMatch = /^(.*?):topic:(\d+)$/i.exec(chatId);
if (topicMatch?.[1] && /^-?\d+$/.test(topicMatch[1].trim())) {
const topicId = normalizedThreadId ?? topicMatch[2];
return `${topicMatch[1].trim()}:topic:${topicId}`;
}
const shorthandTopicMatch = /^(.*?):(\d+)$/i.exec(chatId);
if (shorthandTopicMatch?.[1] && /^-?\d+$/.test(shorthandTopicMatch[1].trim())) {
const topicId = normalizedThreadId ?? shorthandTopicMatch[2];
return `${shorthandTopicMatch[1].trim()}:topic:${topicId}`;
}
if (/^-?\d+$/.test(chatId)) {
return normalizedThreadId ? `${chatId}:topic:${normalizedThreadId}` : chatId;
}