From 25490d4c42122ae6ada20947dda908f8dfc52ef5 Mon Sep 17 00:00:00 2001 From: Masato Hoshino Date: Mon, 29 Jun 2026 03:58:36 +0900 Subject: [PATCH] fix(matrix): sanitize internal tool-trace lines from outbound text (#97372) Wrap the matrix outbound sanitizeText hook with sanitizeAssistantVisibleText so assistant internal tool-trace scaffolding is stripped before delivery, matching the sibling channel fixes under #90684 (Telegram #95774, Google Chat #95084, IRC #97214). --- extensions/matrix/src/channel.ts | 6 +++++- .../src/outbound-tool-trace-sanitize.test.ts | 20 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 extensions/matrix/src/outbound-tool-trace-sanitize.test.ts diff --git a/extensions/matrix/src/channel.ts b/extensions/matrix/src/channel.ts index b8667b97b8c..b2e765b7a7b 100644 --- a/extensions/matrix/src/channel.ts +++ b/extensions/matrix/src/channel.ts @@ -32,7 +32,10 @@ import { normalizeLowercaseStringOrEmpty, normalizeOptionalString, } from "openclaw/plugin-sdk/string-coerce-runtime"; -import { chunkTextForOutbound } from "openclaw/plugin-sdk/text-chunking"; +import { + chunkTextForOutbound, + sanitizeAssistantVisibleText, +} from "openclaw/plugin-sdk/text-chunking"; import { matrixMessageActions } from "./actions.js"; import { matrixApprovalCapability } from "./approval-native.js"; import { createMatrixPairingText, createMatrixProbeAccount } from "./channel-account-paths.js"; @@ -336,6 +339,7 @@ const matrixChannelOutbound: ChannelOutboundAdapter = { chunker: chunkTextForOutbound, chunkerMode: "markdown", textChunkLimit: 4000, + sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text), deliveryCapabilities: { durableFinal: { text: true, diff --git a/extensions/matrix/src/outbound-tool-trace-sanitize.test.ts b/extensions/matrix/src/outbound-tool-trace-sanitize.test.ts new file mode 100644 index 00000000000..5bf41b2a7d9 --- /dev/null +++ b/extensions/matrix/src/outbound-tool-trace-sanitize.test.ts @@ -0,0 +1,20 @@ +// Matrix outbound must strip assistant internal tool-trace scaffolding, matching +// the sibling channel fixes tracked under #90684 (Telegram #95774 / Google Chat +// #95084 / IRC #97214). The hook runs before the markdown->HTML render, so a +// single sanitize cleans both the plain body and the formatted_body. +import { describe, expect, it } from "vitest"; +import { matrixPlugin } from "./channel.js"; + +describe("matrix outbound sanitizeText", () => { + it("strips internal tool-trace banners before outbound delivery", () => { + const text = "Done.\n⚠️ 🛠️ `search repos (agent)` failed"; + + expect(matrixPlugin.outbound?.sanitizeText?.({ text, payload: { text } })).toBe("Done."); + }); + + it("preserves ordinary assistant prose while sanitizing", () => { + const text = "The pipeline has 3 open deals."; + + expect(matrixPlugin.outbound?.sanitizeText?.({ text, payload: { text } })).toBe(text); + }); +});