From bb43c7b89fbfe22e67253c736b74ed53d2f82eb1 Mon Sep 17 00:00:00 2001 From: lawrence3699 Date: Wed, 22 Apr 2026 11:44:23 +1000 Subject: [PATCH] fix(mattermost): suppress reasoning previews --- .../mattermost/src/mattermost/monitor.test.ts | 23 +++++++++++++++++++ .../mattermost/src/mattermost/monitor.ts | 7 ++++-- .../src/mattermost/reply-delivery.ts | 4 ++-- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/extensions/mattermost/src/mattermost/monitor.test.ts b/extensions/mattermost/src/mattermost/monitor.test.ts index 663d7f0a95e..27965ac0417 100644 --- a/extensions/mattermost/src/mattermost/monitor.test.ts +++ b/extensions/mattermost/src/mattermost/monitor.test.ts @@ -252,6 +252,29 @@ describe("shouldClearMattermostDraftPreview", () => { }); describe("deliverMattermostReplyWithDraftPreview", () => { + it("suppresses reasoning-prefixed finals before preview finalization", async () => { + const draftStream = createDraftStreamMock(); + const deliverFinal = vi.fn(async () => {}); + + await deliverMattermostReplyWithDraftPreview({ + payload: { text: " \n Reasoning:\n_hidden_" } as never, + info: { kind: "final" }, + client: createMattermostClientMock(), + draftStream, + effectiveReplyToId: "thread-root-1", + resolvePreviewFinalText: (text) => text?.trim(), + previewState: { finalizedViaPreviewPost: false }, + logVerboseMessage: vi.fn(), + deliverFinal, + }); + + expect(deliverFinal).not.toHaveBeenCalled(); + expect(draftStream.flush).not.toHaveBeenCalled(); + expect(draftStream.discardPending).not.toHaveBeenCalled(); + expect(draftStream.clear).not.toHaveBeenCalled(); + expect(updateMattermostPostSpy).not.toHaveBeenCalled(); + }); + it("deletes the preview after a successful normal final send", async () => { const draftStream = createDraftStreamMock(); const deliverFinal = vi.fn(async () => {}); diff --git a/extensions/mattermost/src/mattermost/monitor.ts b/extensions/mattermost/src/mattermost/monitor.ts index 83ea786ad98..090a12ac889 100644 --- a/extensions/mattermost/src/mattermost/monitor.ts +++ b/extensions/mattermost/src/mattermost/monitor.ts @@ -55,7 +55,10 @@ import { type MattermostWebSocketFactory, } from "./monitor-websocket.js"; import { runWithReconnect } from "./reconnect.js"; -import { deliverMattermostReplyPayload } from "./reply-delivery.js"; +import { + deliverMattermostReplyPayload, + shouldSuppressMattermostReasoningReply, +} from "./reply-delivery.js"; import type { ChannelAccountSnapshot, ChatType, @@ -289,7 +292,7 @@ type MattermostDraftPreviewDeliverParams = { export async function deliverMattermostReplyWithDraftPreview( params: MattermostDraftPreviewDeliverParams, ): Promise { - if (params.payload.isReasoning) { + if (shouldSuppressMattermostReasoningReply(params.payload)) { return; } diff --git a/extensions/mattermost/src/mattermost/reply-delivery.ts b/extensions/mattermost/src/mattermost/reply-delivery.ts index 6ec685b4b33..6fd10d8fd6c 100644 --- a/extensions/mattermost/src/mattermost/reply-delivery.ts +++ b/extensions/mattermost/src/mattermost/reply-delivery.ts @@ -26,7 +26,7 @@ type SendMattermostMessage = ( const REASONING_PREFIX = "reasoning:"; -function shouldSuppressReasoningReply(payload: ReplyPayload): boolean { +export function shouldSuppressMattermostReasoningReply(payload: ReplyPayload): boolean { if (payload.isReasoning === true) { return true; } @@ -49,7 +49,7 @@ export async function deliverMattermostReplyPayload(params: { tableMode: MarkdownTableMode; sendMessage: SendMattermostMessage; }): Promise { - if (shouldSuppressReasoningReply(params.payload)) { + if (shouldSuppressMattermostReasoningReply(params.payload)) { return; } const reply = resolveSendableOutboundReplyParts(params.payload, {