fix: resolve small triage issues

This commit is contained in:
Peter Steinberger
2026-05-04 07:38:34 +01:00
parent deffd11a43
commit fa689295c6
40 changed files with 739 additions and 61 deletions

View File

@@ -780,14 +780,14 @@ describe("dispatchTelegramMessage draft streaming", () => {
);
});
it("keeps the Telegram progress draft across post-tool assistant boundaries", async () => {
it("keeps non-command Telegram progress draft lines across post-tool assistant boundaries", async () => {
const draftStream = createSequencedDraftStream(2001);
createTelegramDraftStream.mockReturnValue(draftStream);
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(
async ({ dispatcherOptions, replyOptions }) => {
await replyOptions?.onReplyStart?.();
await replyOptions?.onAssistantMessageStart?.();
await replyOptions?.onItemEvent?.({ progressText: "exec ls ~/Desktop" });
await replyOptions?.onItemEvent?.({ kind: "search", progressText: "docs lookup" });
await replyOptions?.onItemEvent?.({ progressText: "tests passed" });
await replyOptions?.onAssistantMessageStart?.();
await dispatcherOptions.deliver({ text: "Final after tool" }, { kind: "final" });
@@ -802,7 +802,7 @@ describe("dispatchTelegramMessage draft streaming", () => {
});
expect(draftStream.update).toHaveBeenCalledWith(
expect.stringMatching(/^Shelling\n• `exec ls ~\/Desktop`\n• `tests passed`$/),
expect.stringMatching(/^Shelling\n`🔎 Web Search: docs lookup`\n• `tests passed`$/),
);
expect(draftStream.forceNewMessage).not.toHaveBeenCalled();
expect(draftStream.materialize).not.toHaveBeenCalled();
@@ -815,19 +815,23 @@ describe("dispatchTelegramMessage draft streaming", () => {
expect(draftStream.clear).not.toHaveBeenCalled();
});
it("streams Telegram tool progress by default when preview streaming is active", async () => {
it("streams Telegram command progress text by default when preview streaming is active", 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" });
await replyOptions?.onItemEvent?.({
kind: "command",
name: "exec",
progressText: "exec ls ~/Desktop",
});
return { queuedFinal: false };
});
await dispatchWithContext({ context: createContext(), streamMode: "partial" });
expect(draftStream.update).toHaveBeenCalledWith(
expect.stringMatching(/\n`🛠️ Exec`\n• `exec ls ~\/Desktop`$/),
expect.stringMatching(/\n`🛠️ Exec`\n`🛠️ Exec: exec ls ~\/Desktop`$/),
);
expect(dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledWith(
expect.objectContaining({
@@ -838,6 +842,36 @@ describe("dispatchTelegramMessage draft streaming", () => {
);
});
it("can hide Telegram command progress text by config", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
await replyOptions?.onToolStart?.({ name: "exec", phase: "start" });
await replyOptions?.onItemEvent?.({
kind: "command",
name: "exec",
progressText: "exec ls ~/Desktop",
});
return { queuedFinal: false };
});
await dispatchWithContext({
context: createContext(),
streamMode: "partial",
telegramCfg: { streaming: { mode: "partial", preview: { commandText: "status" } } },
});
expect(draftStream.update).toHaveBeenCalledWith(expect.stringMatching(/\n`🛠️ Exec`$/));
expect(draftStream.update.mock.calls.at(-1)?.[0]).not.toContain("exec ls");
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);
@@ -882,12 +916,15 @@ describe("dispatchTelegramMessage draft streaming", () => {
);
});
it("keeps Telegram tool progress links inside code formatting", async () => {
it("keeps non-command Telegram tool progress links inside code formatting", async () => {
const draftStream = createDraftStream();
createTelegramDraftStream.mockReturnValue(draftStream);
dispatchReplyWithBufferedBlockDispatcher.mockImplementation(async ({ replyOptions }) => {
await replyOptions?.onToolStart?.({ name: "exec", phase: "start" });
await replyOptions?.onItemEvent?.({ progressText: "read [label](tg://user?id=123)" });
await replyOptions?.onItemEvent?.({
kind: "search",
progressText: "read [label](tg://user?id=123)",
});
return { queuedFinal: false };
});
@@ -897,7 +934,9 @@ describe("dispatchTelegramMessage draft streaming", () => {
});
const lastPreviewText = draftStream.update.mock.calls.at(-1)?.[0];
expect(lastPreviewText).toMatch(/\n`🛠️ Exec`\n• `read \[label\]\(tg:\/\/user\?id=123\)`$/);
expect(lastPreviewText).toMatch(
/\n`🛠️ Exec`\n`🔎 Web Search: read \[label\]\(tg:\/\/user\?id=123\)`$/,
);
expect(renderTelegramHtmlText(lastPreviewText ?? "")).not.toContain("<a ");
expect(dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledWith(
expect.objectContaining({
@@ -927,7 +966,7 @@ describe("dispatchTelegramMessage draft streaming", () => {
const progressLine = lastPreviewText.split("\n").at(1) ?? "";
expect(lastPreviewText.length).toBeLessThan(340);
expect(progressLine).toMatch(/^• `'{10}/);
expect(progressLine).toMatch(/^• `.*…`$/);
expect(progressLine).toContain("…");
expect(renderTelegramHtmlText(lastPreviewText)).not.toContain("<a ");
});

View File

@@ -9,6 +9,7 @@ import { createChannelReplyPipeline } from "openclaw/plugin-sdk/channel-reply-pi
import {
createChannelProgressDraftGate,
formatChannelProgressDraftLine,
formatChannelProgressDraftLineForEntry,
formatChannelProgressDraftText,
isChannelProgressDraftWorkToolName,
resolveChannelProgressDraftMaxLines,
@@ -1173,7 +1174,8 @@ export const dispatchTelegramMessage = async ({
await statusReactionController.setTool(toolName);
}
await pushPreviewToolProgress(
formatChannelProgressDraftLine(
formatChannelProgressDraftLineForEntry(
telegramCfg,
{
event: "tool",
name: toolName,
@@ -1187,7 +1189,7 @@ export const dispatchTelegramMessage = async ({
},
onItemEvent: async (payload) => {
await pushPreviewToolProgress(
formatChannelProgressDraftLine({
formatChannelProgressDraftLineForEntry(telegramCfg, {
event: "item",
itemKind: payload.kind,
title: payload.title,

View File

@@ -73,6 +73,10 @@ export const telegramChannelConfigUiHints = {
label: "Telegram Draft Tool Progress",
help: "Show tool/progress activity in the live draft preview message (default: true when preview streaming is active). Set false to keep tool updates out of the edited Telegram preview.",
},
"streaming.preview.commandText": {
label: "Telegram Draft Command Text",
help: 'Command/exec detail in preview tool-progress lines: "raw" preserves released behavior; "status" shows only the tool label.',
},
"streaming.progress.label": {
label: "Telegram Progress Label",
help: 'Initial progress draft title. Use "auto" for built-in single-word labels, a custom string, or false to hide the title.',
@@ -89,6 +93,10 @@ export const telegramChannelConfigUiHints = {
label: "Telegram Progress Tool Lines",
help: "Show compact tool/progress lines in progress draft mode (default: true). Set false to keep only the label until final delivery.",
},
"streaming.progress.commandText": {
label: "Telegram Progress Command Text",
help: 'Command/exec detail in progress draft lines: "raw" preserves released behavior; "status" shows only the tool label.',
},
"retry.attempts": {
label: "Telegram Retry Attempts",
help: "Max retry attempts for outbound Telegram API calls (default: 3).",