diff --git a/scripts/dev/channel-message-flows.ts b/scripts/dev/channel-message-flows.ts index a664210c248f..6ec4c011b6e5 100644 --- a/scripts/dev/channel-message-flows.ts +++ b/scripts/dev/channel-message-flows.ts @@ -56,6 +56,14 @@ function toError(value: unknown): Error { return value instanceof Error ? value : new Error(String(value)); } +function requireFinalMessageId(final: { messageId?: string }, flow: SupportedFlow): string { + const messageId = final.messageId?.trim(); + if (!messageId) { + throw new Error(`${flow} final send did not return a durable Telegram message id`); + } + return messageId; +} + type TelegramThinkingFinalDeps = { createDraftStream?: (params: { accountId?: string; @@ -352,8 +360,9 @@ export async function runTelegramThinkingFinalFlow( threadId: options.threadId, }); + const finalMessageId = requireFinalMessageId(final, "thinking-final"); return { - finalMessageId: final.messageId, + finalMessageId, previewUpdates: thinkingUpdates.length, }; } @@ -416,8 +425,9 @@ export async function runTelegramWorkingFinalFlow( threadId: options.threadId, }); + const finalMessageId = requireFinalMessageId(final, "working-final"); return { - finalMessageId: final.messageId, + finalMessageId, previewUpdates, }; } diff --git a/test/scripts/channel-message-flows.test.ts b/test/scripts/channel-message-flows.test.ts index 70a0981c130f..1d5a1f9765b1 100644 --- a/test/scripts/channel-message-flows.test.ts +++ b/test/scripts/channel-message-flows.test.ts @@ -141,6 +141,33 @@ describe("channel message flows dev runner", () => { expect(sendFinal).not.toHaveBeenCalled(); }); + it("fails thinking-final when the final send does not return a message id", async () => { + const stream = { + update: vi.fn(() => {}), + flush: vi.fn(async () => {}), + clear: vi.fn(async () => {}), + stop: vi.fn(async () => {}), + messageId: vi.fn(() => 17), + forceNewMessage: vi.fn(), + }; + + await expect( + runTelegramThinkingFinalFlow( + { + cfg: {} as OpenClawConfig, + delayMs: 0, + target: "123", + thinkingUpdates: ["Checking the request."], + }, + { + createDraftStream: vi.fn(() => stream), + sendFinal: vi.fn(async () => ({})), + sleep: vi.fn(async () => {}), + }, + ), + ).rejects.toThrow("thinking-final final send did not return a durable Telegram message id"); + }); + it("streams working updates through native message drafts before the final answer", async () => { const draft = { update: vi.fn(async () => true), @@ -214,6 +241,29 @@ describe("channel message flows dev runner", () => { expect(sendFinal).not.toHaveBeenCalled(); }); + it("fails working-final when the final send does not return a message id", async () => { + const draft = { + update: vi.fn(async () => true), + stop: vi.fn(async () => {}), + }; + + await expect( + runTelegramWorkingFinalFlow( + { + cfg: {} as OpenClawConfig, + delayMs: 0, + durationMs: 12_000, + target: "123", + }, + { + createNativeToolProgressDraft: vi.fn(() => draft), + sendFinal: vi.fn(async () => ({})), + sleep: vi.fn(async () => {}), + }, + ), + ).rejects.toThrow("working-final final send did not return a durable Telegram message id"); + }); + it("uses two second progress update cadence by default", async () => { const draft = { update: vi.fn(async () => true),