fix(signal): sanitize internal tool-trace lines from outbound text (#97360)

Wrap the signal 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).
This commit is contained in:
Masato Hoshino
2026-06-28 12:14:45 -07:00
committed by GitHub
parent cd6d0f9b00
commit c026546063
2 changed files with 21 additions and 0 deletions
+2
View File
@@ -22,6 +22,7 @@ import {
createDefaultChannelRuntimeState,
} from "openclaw/plugin-sdk/status-helpers";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
import { resolveSignalAccount, type ResolvedSignalAccount } from "./accounts.js";
import {
shouldSuppressLocalSignalExecApprovalPrompt,
@@ -461,6 +462,7 @@ export const signalPlugin: ChannelPlugin<ResolvedSignalAccount, SignalProbe> =
chunker: chunkText,
chunkerMode: "text",
textChunkLimit: 4000,
sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text),
shouldSuppressLocalPayloadPrompt: ({ cfg, accountId, payload, hint }) =>
shouldSuppressLocalSignalExecApprovalPrompt({
cfg,
@@ -0,0 +1,19 @@
// Signal outbound must strip assistant internal tool-trace scaffolding, matching
// the sibling channel fixes tracked under #90684 (Telegram #95774 / Google Chat
// #95084 / IRC #97214). Signal is plaintext-only, so leaked traces are verbatim.
import { describe, expect, it } from "vitest";
import { signalPlugin } from "./channel.js";
describe("signal outbound sanitizeText", () => {
it("strips internal tool-trace banners before outbound delivery", () => {
const text = "Done.\n⚠️ 🛠️ `search repos (agent)` failed";
expect(signalPlugin.outbound?.sanitizeText?.({ text, payload: { text } })).toBe("Done.");
});
it("preserves ordinary assistant prose while sanitizing", () => {
const text = "The pipeline has 3 open deals.";
expect(signalPlugin.outbound?.sanitizeText?.({ text, payload: { text } })).toBe(text);
});
});