Skip to content

fix(nextcloud-talk): strip internal tool-trace banners from outbound text#103355

Closed
miorbnli wants to merge 2 commits into
openclaw:mainfrom
miorbnli:fix/nextcloud-talk-outbound-tool-trace-sanitize
Closed

fix(nextcloud-talk): strip internal tool-trace banners from outbound text#103355
miorbnli wants to merge 2 commits into
openclaw:mainfrom
miorbnli:fix/nextcloud-talk-outbound-tool-trace-sanitize

Conversation

@miorbnli

@miorbnli miorbnli commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

The Nextcloud Talk outbound adapter had no sanitizeText hook. Core delivery (src/infra/outbound/deliver.ts:889-896) only runs the per-channel assistant-text sanitizer when the adapter provides one; without it, internal assistant tool-trace scaffolding is delivered verbatim to the chat. Users see raw banners like ⚠️ 🛠️ exec (agent)`` failedand raw<tool_call>`/`<function_response>` XML in their Nextcloud Talk messages.

Why This Change Was Made

User Impact

Internal tool-trace banners and leaked XML scaffolding no longer reach Nextcloud Talk users. Ordinary assistant prose is preserved unchanged.

Linked context

N/A (no existing issue). Sibling fixes: #103109, #98693, #98705.

Evidence

Terminal capture of node --import tsx runtime verification calling the patched adapter hook nextcloudTalkPlugin.outbound.sanitizeText (the exact hook added by this PR) on the exact PR head:

sanitizeText hook exists: true
[PASS] tool-trace banner: "Done."
[PASS] xml tool-call: "Meeting notes sent."
[PASS] plain prose: "The agenda has 3 open action items."

This calls the real nextcloudTalkPlugin.outbound.sanitizeText (resolved from { base: { sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) } } via resolveChatChannelOutbound), proving the patched Nextcloud Talk adapter routes assistant text through the sanitizer before delivery.

# Field Value
1 Behavior or issue addressed Nextcloud Talk outbound delivers internal tool-trace scaffolding verbatim (no sanitizeText hook).
2 Real environment tested Linux x64, Node 22; the patched adapter hook invoked on the exact PR head (fad7fab).
3 Exact steps or command run node --import tsx script that imports nextcloudTalkPlugin and calls outbound.sanitizeText directly, plus colocated vitest node scripts/run-vitest.mjs extensions/<channel>/src/outbound-tool-trace-sanitize.test.ts.
4 Evidence after fix Terminal output above: the patched adapter hook strips banners, XML tool-call scaffolding, while preserving ordinary prose.
5 Observed result after fix The channel outbound hook removes tool-trace scaffolding; ordinary text unchanged.
6 What was not tested Live channel server delivery (no server in this env); the adapter hook itself is exercised directly on the real plugin object.

Tests and validation

$ node scripts/run-vitest.mjs extensions/nextcloud-talk/src/channel.core.test.ts
✓ extensions/nextcloud-talk/src/channel.core.test.ts (3 tests)
Test Files  1 passed (1)
     Tests  3 passed (3)

New outbound-tool-trace-sanitize.test.ts mirrors the twitch #103109 test: asserts the hook strips banners, XML tool-call scaffolding, multiline function-response scaffolding, and preserves ordinary prose.

Risk checklist

  • One concern, one PR — only the Nextcloud Talk outbound sanitizeText hook.

  • No config/env/default surface change.

  • No SDK/protocol/auth/provider behavior change (reuses an already-exported SDK helper).

  • Backward compatible — only internal scaffolding is removed; user-visible prose is unchanged.

  • No new deps (helper already in the SDK barrel).

  • No CHANGELOG edit (per release policy).

  • Tests added.

  • Allow edits by maintainers

@openclaw-barnacle openclaw-barnacle Bot added channel: nextcloud-talk Channel integration: nextcloud-talk size: XS labels Jul 10, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P1 High-priority user-facing bug, regression, or broken workflow. labels Jul 10, 2026
@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs maintainer review before merge. Reviewed July 10, 2026, 9:04 AM ET / 13:04 UTC.

Summary
The PR adds sanitizeAssistantVisibleText to Nextcloud Talk outbound delivery and adds regression tests for trace banners, tool-call XML, multiline function responses, and ordinary prose.

PR surface: Source +2, Tests +41. Total +43 across 2 files.

Reproducibility: yes. Current main lacks the optional hook, core's conditional call is explicit, merged sibling fixes establish the same failure mode, and exact-head terminal output demonstrates the corrected adapter result.

Review metrics: none identified.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #90684
Summary: This PR is the Nextcloud Talk candidate fix for one channel slice of the canonical cross-channel outbound sanitizer gap.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Risk before merge

  • [P1] The PR head is behind current main, so the branch should be refreshed and required checks confirmed on the resulting exact head before merge.
  • [P1] Merging intentionally changes delivered text by removing patterns recognized as internal scaffolding; the shared sanitizer's existing preservation coverage and the new ordinary-prose test mitigate accidental over-stripping.

Maintainer options:

  1. Refresh and land the focused fix (recommended)
    Rebase onto current main, retain the sanitizer and preservation tests, and merge after required exact-head checks pass.
  2. Pause for channel-specific counterevidence
    Hold the PR only if a Nextcloud Talk owner identifies legitimate outbound content that the shared delivery sanitizer incorrectly removes.

Next step before merge

  • [P2] No code repair is identified; the maintainer next action is to refresh the branch and complete normal exact-head landing validation.

Security
Cleared: The patch adds no dependencies, permissions, secrets handling, workflow changes, downloads, publishing changes, or other concrete security or supply-chain concern.

Review details

Best possible solution:

Keep the channel-owned public SDK sanitizer hook and focused adapter tests, then refresh the branch onto current main and land after exact-head checks pass.

Do we have a high-confidence way to reproduce the issue?

Yes. Current main lacks the optional hook, core's conditional call is explicit, merged sibling fixes establish the same failure mode, and exact-head terminal output demonstrates the corrected adapter result.

Is this the best way to solve the issue?

Yes. Reusing the established public SDK sanitizer through the standard channel-owned outbound hook is narrower and more maintainable than new configuration, channel-local parsing, or a new global delivery path.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 5a451f92f993.

Label changes

Label changes:

  • add merge-risk: 🚨 message-delivery: The patch intentionally transforms the exact text delivered to Nextcloud Talk before chunking, so preservation behavior matters beyond green CI.
  • add proof: sufficient: Contributor real behavior proof is sufficient. The PR body contains exact-head terminal output from the real resolved Nextcloud Talk outbound adapter hook, demonstrating the after-fix transformation and preserved prose.
  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • add status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body contains exact-head terminal output from the real resolved Nextcloud Talk outbound adapter hook, demonstrating the after-fix transformation and preserved prose.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.
  • remove status: 📣 needs proof: Current PR status label is status: 👀 ready for maintainer look.

Label justifications:

  • P1: The missing sanitizer can expose internal execution traces and tool XML in a user-facing Nextcloud Talk workflow.
  • merge-risk: 🚨 message-delivery: The patch intentionally transforms the exact text delivered to Nextcloud Talk before chunking, so preservation behavior matters beyond green CI.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (terminal): The PR body contains exact-head terminal output from the real resolved Nextcloud Talk outbound adapter hook, demonstrating the after-fix transformation and preserved prose.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body contains exact-head terminal output from the real resolved Nextcloud Talk outbound adapter hook, demonstrating the after-fix transformation and preserved prose.
Evidence reviewed

PR surface:

Source +2, Tests +41. Total +43 across 2 files.

View PR surface stats
Area Files Added Removed Net
Source 1 2 0 +2
Tests 1 41 0 +41
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 2 43 0 +43

What I checked:

Likely related people:

  • steipete: Peter Steinberger has the largest commit count on the Nextcloud Talk channel module and authored the most recent commit currently owning the outbound block. (role: recent area contributor; confidence: high; commits: abbd5ae3ea73; files: extensions/nextcloud-talk/src/channel.ts, src/infra/outbound/deliver.ts)
  • vincentkoc: Vincent Koc is the second-most frequent contributor in the followed history of the Nextcloud Talk channel module and is a strong routing candidate for channel-specific behavior. (role: feature contributor; confidence: medium; files: extensions/nextcloud-talk/src/channel.ts)
  • cpojer: cpojer has multiple historical commits in the Nextcloud Talk channel path and is relevant for earlier structure and behavior context. (role: adjacent owner; confidence: medium; files: extensions/nextcloud-talk/src/channel.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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 keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (2 earlier review cycles)
  • reviewed 2026-07-10T10:25:59.564Z sha ac1e405 :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-10T12:57:08.548Z sha fad7fab :: needs maintainer review before merge. :: none

miorbnli and others added 2 commits July 10, 2026 20:07
…text

The Nextcloud Talk outbound adapter had no sanitizeText hook, so internal
assistant tool-trace scaffolding (e.g. "⚠️ 🛠️ `exec (agent)` failed", raw
<tool_call>/<function_response> XML) leaked verbatim into delivered chat
messages. The same one-line sanitizeText hook was already shipped to 13 sibling
channels (mattermost openclaw#98693, feishu openclaw#98705, twitch openclaw#103109, signal openclaw#97360,
slack openclaw#97367, matrix openclaw#97372, irc openclaw#97214, telegram, googlechat openclaw#90684,
qqbot openclaw#90132, discord, whatsapp openclaw#71830, sms).

Add sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text) to the
outbound base adapter, matching those precedents.

Co-Authored-By: Claude <[email protected]>
createChatChannelPlugin resolves the { base, attachedResults } outbound shape
into a flat ChannelOutboundAdapter (resolveChatChannelOutbound spreads base to
the top level), so the test must read outbound.sanitizeText directly, not
outbound.base.sanitizeText. The previous access failed check-test-types with
TS2339 (Property 'base' does not exist on type 'ChannelOutboundAdapter').

Co-Authored-By: Claude <[email protected]>
@miorbnli
miorbnli force-pushed the fix/nextcloud-talk-outbound-tool-trace-sanitize branch from ac1e405 to fad7fab Compare July 10, 2026 12:08
@miorbnli

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

The PR body Evidence section has been updated with exact-head output from the patched adapter: the colocated test imports nextcloudTalkPlugin and asserts on nextcloudTalkPlugin.outbound.sanitizeText directly (the hook added by this PR). Branch rebased onto current main. Requesting a fresh review.

@clawsweeper

clawsweeper Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@miorbnli

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

@clawsweeper clawsweeper Bot added proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jul 10, 2026
@steipete steipete self-assigned this Jul 10, 2026
@steipete

Copy link
Copy Markdown
Contributor

Closing as a duplicate of #101712, now landed in 8a93d288e2f57db13251e7d3f059e72a411b228a.

The canonical fix covers both Nextcloud Talk delivery surfaces: the standard outbound adapter and the custom inbound reply path. It also preserves attachments/reply IDs, leaves low-level caller-authored text literal, and reports fully stripped internal-only replies as non-visible.

Thank you @miorbnli — the useful regression coverage from this PR was folded into #101712, and your co-author credit is preserved in the landed commit alongside @Pick-cat.

@steipete steipete closed this Jul 10, 2026
@miorbnli
miorbnli deleted the fix/nextcloud-talk-outbound-tool-trace-sanitize branch July 16, 2026 02:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

channel: nextcloud-talk Channel integration: nextcloud-talk merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P1 High-priority user-facing bug, regression, or broken workflow. proof: sufficient ClawSweeper judged the real behavior proof convincing. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. size: XS status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants