




















@@ -227,6 +227,7 @@ const telegramDepsForTest: TelegramBotDeps = {
227227228228describe("dispatchTelegramMessage draft streaming", () => {
229229type TelegramMessageContext = Parameters<typeof dispatchTelegramMessage>[0]["context"];
230+const trailingFinalStatusText = "Post-final plugin status";
230231231232beforeAll(async () => {
232233({ dispatchTelegramMessage, resetTelegramReplyFenceForTests } =
@@ -1605,6 +1606,30 @@ describe("dispatchTelegramMessage draft streaming", () => {
16051606expect(editMessageTelegram).not.toHaveBeenCalled();
16061607});
160716081609+it("sends trailing verbose status after streamed final answer without replacing the answer draft", async () => {
1610+const { answerDraftStream } = setupDraftStreams({ answerMessageId: 2001 });
1611+dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
1612+async ({ dispatcherOptions, replyOptions }) => {
1613+await replyOptions?.onPartialReply?.({ text: "Normal reply" });
1614+await dispatcherOptions.deliver({ text: "Normal reply" }, { kind: "final" });
1615+await dispatcherOptions.deliver({ text: trailingFinalStatusText }, { kind: "final" });
1616+return { queuedFinal: true };
1617+},
1618+);
1619+1620+await dispatchWithContext({ context: createContext() });
1621+1622+expect(answerDraftStream.update).toHaveBeenCalledTimes(3);
1623+expect(answerDraftStream.update).toHaveBeenNthCalledWith(1, "Normal reply");
1624+expect(answerDraftStream.update).toHaveBeenNthCalledWith(2, "Normal reply");
1625+expect(answerDraftStream.update).toHaveBeenNthCalledWith(3, trailingFinalStatusText);
1626+expect(answerDraftStream.forceNewMessage).toHaveBeenCalledTimes(1);
1627+expect(answerDraftStream.forceNewMessage.mock.invocationCallOrder[0]).toBeLessThan(
1628+answerDraftStream.update.mock.invocationCallOrder[2],
1629+);
1630+expect(deliverReplies).not.toHaveBeenCalled();
1631+});
1632+16081633it("applies partial deltas while preserving the first-preview debounce", async () => {
16091634const { answerDraftStream } = setupDraftStreams({ answerMessageId: 2001 });
16101635dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
@@ -2075,6 +2100,33 @@ describe("dispatchTelegramMessage draft streaming", () => {
20752100expect(editMessageTelegram).not.toHaveBeenCalled();
20762101});
207721022103+it("sends trailing verbose status after a progress-mode final answer", async () => {
2104+const { answerDraftStream } = setupDraftStreams({ answerMessageId: 2001 });
2105+dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
2106+async ({ dispatcherOptions, replyOptions }) => {
2107+await replyOptions?.onToolStart?.({ name: "exec", phase: "start" });
2108+await dispatcherOptions.deliver({ text: "Branch is up to date" }, { kind: "final" });
2109+await dispatcherOptions.deliver({ text: trailingFinalStatusText }, { kind: "final" });
2110+return { queuedFinal: true };
2111+},
2112+);
2113+2114+await dispatchWithContext({
2115+context: createContext(),
2116+streamMode: "progress",
2117+telegramCfg: { streaming: { mode: "progress" } },
2118+});
2119+2120+expect(answerDraftStream.update).toHaveBeenCalledTimes(2);
2121+expect(answerDraftStream.update).toHaveBeenNthCalledWith(1, "Cracking\n\n`🛠️ Exec`");
2122+expect(answerDraftStream.update).toHaveBeenNthCalledWith(2, trailingFinalStatusText);
2123+expect(answerDraftStream.forceNewMessage).toHaveBeenCalledTimes(2);
2124+expect(answerDraftStream.forceNewMessage.mock.invocationCallOrder[1]).toBeLessThan(
2125+answerDraftStream.update.mock.invocationCallOrder[1],
2126+);
2127+expectDeliveredReply(0, { text: "Branch is up to date" });
2128+});
2129+20782130it("does not stream text-only tool results into progress drafts", async () => {
20792131const { answerDraftStream } = setupDraftStreams({ answerMessageId: 2001 });
20802132dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。