diff --git a/apps/api/src/team-chat-bridge.test.ts b/apps/api/src/team-chat-bridge.test.ts index 3c56b3f..809f628 100644 --- a/apps/api/src/team-chat-bridge.test.ts +++ b/apps/api/src/team-chat-bridge.test.ts @@ -41,6 +41,52 @@ describe("team chat bridge", () => { expect(teamChatResponseText([])).toBe("Bot completed the request without a written reply."); }); + it("retries delegated replies when the external origin is temporarily missing", async () => { + const send = vi.fn(async () => ({ handle: "reply-delegated" })); + const runUpdateMany = vi.fn(async () => ({ count: 1 })); + const bridge = new TeamChatBridge({ + prisma: { + run: { + findMany: vi.fn(async () => [ + { + id: "run-delegated", + status: "completed", + sourceMessageId: "msg-source", + }, + ]), + findUnique: vi.fn(async () => null), + updateMany: runUpdateMany, + }, + message: { + findUnique: vi.fn(async () => null), + findFirst: vi.fn(async () => ({ + blocks: [{ kind: "text", text: "Delegated work finished." }], + })), + }, + externalMessage: { findUnique: vi.fn(async () => null) }, + } as unknown as PrismaClient, + events: { sendUserMessage: vi.fn() }, + jobs: { enqueue: vi.fn() }, + send, + providerId: "slack", + botId: "bot-1", + }); + ( + bridge as unknown as { + target: { id: string; spaceId: string; userId: string; name: string }; + } + ).target = { id: "bot-1", spaceId: "space-1", userId: "owner-1", name: "Analyst" }; + + await ( + bridge as unknown as { + deliverDelegatedReplies: (target: { id: string; name: string }) => Promise; + } + ).deliverDelegatedReplies({ id: "bot-1", name: "Analyst" }); + + expect(send).not.toHaveBeenCalled(); + expect(runUpdateMany).not.toHaveBeenCalled(); + }); + it("delivers delegated tool-only replies before marking them mirrored", async () => { const send = vi.fn(async () => ({ handle: "reply-delegated" })); const runUpdateMany = vi.fn(async () => ({ count: 1 })); diff --git a/apps/api/src/team-chat-bridge.ts b/apps/api/src/team-chat-bridge.ts index f7c6221..0c6e00f 100644 --- a/apps/api/src/team-chat-bridge.ts +++ b/apps/api/src/team-chat-bridge.ts @@ -695,7 +695,11 @@ export class TeamChatBridge { for (const run of runs) { const origin = await this.findExternalOrigin(run.sourceMessageId); if (!origin) { - await this.markTeamChatMirrored(run.id); + // Keep teamChatMirroredAt unset when the wake chain is missing so reconciliation + // retries once the external origin can be resolved again. + if (!run.sourceMessageId) { + await this.markTeamChatMirrored(run.id); + } continue; } const response =