diff --git a/extensions/irc/src/channel.test.ts b/extensions/irc/src/channel.test.ts index 113bc08854b..96703e2a749 100644 --- a/extensions/irc/src/channel.test.ts +++ b/extensions/irc/src/channel.test.ts @@ -15,3 +15,21 @@ describe("irc outbound chunking", () => { expect(ircOutboundBaseAdapter.textChunkLimit).toBe(350); }); }); + +describe("irc outbound sanitizeText", () => { + afterEach(() => { + clearIrcRuntime(); + }); + + it("strips internal tool-trace banners before outbound delivery", () => { + const text = "Done.\n⚠️ 🛠️ `search repos (agent)` failed"; + + expect(ircOutboundBaseAdapter.sanitizeText({ text })).toBe("Done."); + }); + + it("preserves ordinary assistant prose while sanitizing", () => { + const text = "The pipeline has 3 open deals."; + + expect(ircOutboundBaseAdapter.sanitizeText({ text })).toBe(text); + }); +}); diff --git a/extensions/irc/src/outbound-base.ts b/extensions/irc/src/outbound-base.ts index e6990259775..e2bbef3bc95 100644 --- a/extensions/irc/src/outbound-base.ts +++ b/extensions/irc/src/outbound-base.ts @@ -1,5 +1,6 @@ // Irc plugin module implements outbound base behavior. import { sanitizeForPlainText } from "openclaw/plugin-sdk/channel-outbound"; +import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking"; import { chunkTextForOutbound } from "./channel-api.js"; export const ircOutboundBaseAdapter = { @@ -7,5 +8,9 @@ export const ircOutboundBaseAdapter = { chunker: chunkTextForOutbound, chunkerMode: "markdown" as const, textChunkLimit: 350, - sanitizeText: ({ text }: { text: string }) => sanitizeForPlainText(text), + // IRC's plain-text pass does not remove assistant scaffolding. Run the + // canonical delivery sanitizer first so internal tool traces are dropped + // before channel formatting. + sanitizeText: ({ text }: { text: string }) => + sanitizeForPlainText(sanitizeAssistantVisibleText(text)), };