From df39e611f89a5509632a59ae30b5ee569a6d7812 Mon Sep 17 00:00:00 2001 From: Vincent Koc Date: Sun, 3 May 2026 18:32:53 -0700 Subject: [PATCH] fix(channels): quiet disabled preview tool progress --- CHANGELOG.md | 1 + .../discord/src/monitor/message-handler.process.test.ts | 4 ++-- .../message-handler/dispatch.preview-fallback.test.ts | 7 +++++-- src/plugin-sdk/channel-streaming.test.ts | 2 +- src/plugin-sdk/channel-streaming.ts | 3 +++ 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 524c1458379..7528b297064 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,7 @@ Docs: https://docs.openclaw.ai - Google Meet: avoid treating repeated participant words as multiple assistant-overlap matches when suppressing realtime echo transcripts. Thanks @vincentkoc. - QA/cache: require the full `CACHE-OK ` marker before live cache probes stop retrying, so suffix-only prose cannot hide a broken probe response. Thanks @vincentkoc. - Slack/Matrix: avoid creating blank progress-draft messages when `streaming.progress.label=false` and progress tool lines are disabled. Thanks @vincentkoc. +- Slack/Discord: suppress standalone tool-progress chatter when partial preview streaming has `streaming.preview.toolProgress: false`, matching the documented quiet-preview behavior. Thanks @vincentkoc. - QA/Matrix: keep the mock OpenAI tool-progress provider aligned with exact-marker Matrix prompts so the hardened live preview scenario still forces a deterministic read before final delivery. Thanks @vincentkoc. - Google Meet: make realtime talk-back agent-driven by default with `realtime.strategy: "agent"`, keep the previous direct bidirectional model behavior available as `realtime.strategy: "bidi"`, route the Meet tab speaker output to `BlackHole 2ch` automatically for local Chrome realtime joins, coalesce nearby speech transcript fragments before consulting the agent, and avoid cutting off agent speech from server VAD or stale playback pipe errors. - Google Meet: suppress queued assistant playback and assistant-like transcript echoes from the realtime input path, so the meeting does not hear the agent's own speech as a new user turn and loop or cut itself off. diff --git a/extensions/discord/src/monitor/message-handler.process.test.ts b/extensions/discord/src/monitor/message-handler.process.test.ts index 6ff3d080e6b..4f51b681940 100644 --- a/extensions/discord/src/monitor/message-handler.process.test.ts +++ b/extensions/discord/src/monitor/message-handler.process.test.ts @@ -1561,7 +1561,7 @@ describe("processDiscordMessage draft streaming", () => { expect(draftStream.forceNewMessage).not.toHaveBeenCalled(); }); - it("keeps standalone Discord tool progress when partial preview lines are disabled", async () => { + it("suppresses standalone Discord tool progress when partial preview lines are disabled", async () => { createMockDraftStreamForTest(); dispatchInboundMessage.mockImplementationOnce(async () => createNoQueuedDispatchResult()); @@ -1581,7 +1581,7 @@ describe("processDiscordMessage draft streaming", () => { expect( dispatchInboundMessage.mock.calls[0]?.[0]?.replyOptions?.suppressDefaultToolProgressMessages, - ).toBeUndefined(); + ).toBe(true); }); it("strips reply tags from preview partials", async () => { diff --git a/extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.ts b/extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.ts index bbdfd043ef0..05240b001e9 100644 --- a/extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.ts +++ b/extensions/slack/src/monitor/message-handler/dispatch.preview-fallback.test.ts @@ -301,6 +301,9 @@ vi.mock("openclaw/plugin-sdk/channel-streaming", () => ({ if (entry?.streaming?.mode === "progress") { return true; } + if (options?.draftStreamActive === true) { + return true; + } return options?.previewToolProgressEnabled ?? true; }, isChannelProgressDraftWorkToolName: (name?: string) => @@ -765,7 +768,7 @@ describe("dispatchPreparedSlackMessage preview fallback", () => { expect(draftStream.update).not.toHaveBeenCalled(); }); - it("keeps standalone Slack tool progress when partial preview lines are disabled", async () => { + it("suppresses standalone Slack tool progress when partial preview lines are disabled", async () => { mockedSlackStreamingMode = "partial"; mockedSlackDraftMode = "replace"; mockedDispatchSequence = []; @@ -776,7 +779,7 @@ describe("dispatchPreparedSlackMessage preview fallback", () => { }), ); - expect(capturedReplyOptions?.suppressDefaultToolProgressMessages).toBeUndefined(); + expect(capturedReplyOptions?.suppressDefaultToolProgressMessages).toBe(true); expect(capturedReplyOptions?.onItemEvent).toBeDefined(); }); diff --git a/src/plugin-sdk/channel-streaming.test.ts b/src/plugin-sdk/channel-streaming.test.ts index b83dd8c1ec0..51426647cc9 100644 --- a/src/plugin-sdk/channel-streaming.test.ts +++ b/src/plugin-sdk/channel-streaming.test.ts @@ -118,7 +118,7 @@ describe("channel-streaming", () => { { streaming: { mode: "partial", preview: { toolProgress: false } } }, { draftStreamActive: true }, ), - ).toBe(false); + ).toBe(true); expect( resolveChannelStreamingSuppressDefaultToolProgressMessages( { streaming: { mode: "partial", preview: { toolProgress: false } } }, diff --git a/src/plugin-sdk/channel-streaming.ts b/src/plugin-sdk/channel-streaming.ts index 8ac805c2b1b..bfcd51cba52 100644 --- a/src/plugin-sdk/channel-streaming.ts +++ b/src/plugin-sdk/channel-streaming.ts @@ -448,6 +448,9 @@ export function resolveChannelStreamingSuppressDefaultToolProgressMessages( if (mode === "progress") { return true; } + if (options?.draftStreamActive === true) { + return true; + } return options?.previewToolProgressEnabled ?? resolveChannelStreamingPreviewToolProgress(entry); }