fix(channels): harden tool progress previews

This commit is contained in:
Peter Steinberger
2026-04-25 04:52:10 +01:00
parent da89108b82
commit 70fd1c91aa
12 changed files with 300 additions and 54 deletions

View File

@@ -499,7 +499,7 @@ describe("dispatchTelegramMessage draft streaming", () => {
);
});
it("suppresses Telegram tool progress by default", async () => {
it("streams Telegram tool progress by default when preview streaming is active", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
@@ -510,6 +510,33 @@ describe("dispatchTelegramMessage draft streaming", () => {
await dispatchWithContext({ context: createContext(), streamMode: "partial" });
expect(draftStream.update).toHaveBeenCalledWith(
"Working…\n• `tool: exec`\n• `exec ls ~/Desktop`",
);
expect(dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledWith(
expect.objectContaining({
replyOptions: expect.objectContaining({
suppressDefaultToolProgressMessages: true,
}),
}),
);
});
it("suppresses Telegram tool progress when explicitly disabled", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
await replyOptions?.onToolStart?.({ name: "exec", phase: "start" });
await replyOptions?.onItemEvent?.({ progressText: "exec ls ~/Desktop" });
return { queuedFinal: false };
});
await dispatchWithContext({
context: createContext(),
streamMode: "partial",
telegramCfg: { streaming: { preview: { toolProgress: false } } },
});
expect(draftStream.update).not.toHaveBeenCalled();
expect(dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledWith(
expect.objectContaining({
@@ -520,7 +547,7 @@ describe("dispatchTelegramMessage draft streaming", () => {
);
});
it("streams Telegram tool progress only when explicitly enabled", async () => {
it("keeps Telegram tool progress links inside code formatting", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
@@ -532,7 +559,6 @@ describe("dispatchTelegramMessage draft streaming", () => {
await dispatchWithContext({
context: createContext(),
streamMode: "partial",
telegramCfg: { streaming: { preview: { toolProgress: true } } },
});
const lastPreviewText = draftStream.update.mock.calls.at(-1)?.[0];
@@ -566,11 +592,32 @@ describe("dispatchTelegramMessage draft streaming", () => {
const progressLine = lastPreviewText.split("\n").at(1) ?? "";
expect(lastPreviewText.length).toBeLessThan(340);
expect(progressLine).toMatch(/^• `{10}/);
expect(progressLine).toMatch(/^• `'{10}/);
expect(progressLine).toContain("…");
expect(renderTelegramHtmlText(lastPreviewText)).not.toContain("<a ");
});
it("does not let Telegram tool progress backticks break out of code formatting", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);
const breakoutProgress = `${"`".repeat(10)} [label](tg://user?id=123)`;
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
await replyOptions?.onItemEvent?.({ progressText: breakoutProgress });
return { queuedFinal: false };
});
await dispatchWithContext({
context: createContext(),
streamMode: "partial",
telegramCfg: { streaming: { preview: { toolProgress: true } } },
});
const lastPreviewText = draftStream.update.mock.calls.at(-1)?.[0] ?? "";
expect(lastPreviewText).toContain(`\`'''''''''' [label](tg://user?id=123)\``);
expect(renderTelegramHtmlText(lastPreviewText)).not.toContain("<a ");
});
it("keeps block streaming enabled when account config enables it", async () => {
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ dispatcherOptions }) => {
await dispatcherOptions.deliver({ text: "Hello" }, { kind: "final" });