fix(twitch): strip internal tool-trace banners from outbound text#102992
fix(twitch): strip internal tool-trace banners from outbound text#102992masatohoshino wants to merge 2 commits into
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 9, 2026, 12:28 PM ET / 16:28 UTC. Summary PR surface: Source +4, Tests +27. Total +31 across 2 files. Reproducibility: yes. source-level reproduction is high confidence: current main's Twitch adapter lacks Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Next step before merge
Security Review detailsBest possible solution: Land the narrow Twitch hook after normal exact-head review and checks, while keeping the umbrella issue open for remaining channel slices or a later shared-default decision. Do we have a high-confidence way to reproduce the issue? Yes, source-level reproduction is high confidence: current main's Twitch adapter lacks Is this the best way to solve the issue? Yes, this is the best narrow fix for this PR: the existing outbound adapter hook is the owner boundary, and sibling channels already use the same sanitizer pattern. A shared default may be a future umbrella decision, but it is a broader contract change than this Twitch repair needs. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against d18e48c928ee. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +4, Tests +27. Total +31 across 2 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
@clawsweeper automerge |
|
ClawSweeper 🐠 reef update Thanks for the work here. ClawSweeper could not write to the source branch, so it opened a replacement PR rather than letting the fix drift. attribution still points back here. Why replacement: ClawSweeper could not update the source PR branch directly; GitHub did not grant sufficient push rights to the bot for that branch.
fish notes: reasoning high; reviewed against 5dad685. |
Related: #90684
What Problem This Solves
Fixes an issue where assistant internal tool-trace scaffolding —
<tool_call>-style XML blocks and⚠️ 🛠️ … failedtool banners, among the scaffolding formssanitizeAssistantVisibleText()strips — leaks verbatim into Twitch chat when a model emits it as plain text (common with models that render tool calls as text, e.g. after a failed exec whose error output echoes the prompt's tool XML). Twitch chat is public: every viewer of the channel sees the internal scaffolding, not just the addressed user.sanitizeAssistantVisibleText()exists for exactly this, but the Twitch outbound adapter never declares thesanitizeTexthook, so core delivery sends the raw text through.Why This Change Was Made
This is the Twitch sibling of the per-channel fixes tracked under #90684: the same adapter hook pattern is already merged for Google Chat, IRC, Signal, Slack, Matrix, SMS, Mattermost, and Feishu (all linked from that issue). ClickClack, the only other bundled channel still missing the hook without an open PR, will follow separately, keeping the family's one-channel-per-PR shape.
The fix adds the family-standard hook to
twitchOutbound:Core delivery wires this adapter hook once and applies it before chunk planning, so the 500-char word-boundary Twitch chunker only ever sees sanitized text. The markdown-stripping chunker itself, delivery mode, and all send paths are unchanged.
User Impact
Twitch viewers no longer see internal tool-call XML or tool-failure banners in public chat when a model leaks scaffolding into its reply text. Ordinary assistant prose is delivered unchanged. No config, schema, or API changes.
Evidence
Boundary capture drives the composed production plugin object (
twitchPlugin.outbound.sanitizeText, exactly what core delivery reads) undernode --import tsx; no sanitizer or plugin code is faked. A live Twitch chat send is not exercised (infeasible here).Focused regression tests (
extensions/twitch/src/outbound-tool-trace-sanitize.test.ts, 3 cases): tool banner stripped, XML<tool_call>block stripped, ordinary prose preserved. All 3 fail without the production change (the adapter exposes no hook).Local: targeted suite 3/3; full twitch extension suite 16 files / 188 tests green;
oxfmtandoxlintclean;tsgo:extensionsclean.check:changedlanes run on CI.