Skip to content

[BUG]: Internal messages surface in Telegram chat (#88128)#88194

Closed
chengzhichao-xydt wants to merge 1 commit into
openclaw:mainfrom
chengzhichao-xydt:fix/88128-telegram-internal-msg-leak-upstream
Closed

[BUG]: Internal messages surface in Telegram chat (#88128)#88194
chengzhichao-xydt wants to merge 1 commit into
openclaw:mainfrom
chengzhichao-xydt:fix/88128-telegram-internal-msg-leak-upstream

Conversation

@chengzhichao-xydt

Copy link
Copy Markdown
Contributor

Summary

  • Problem: Internal/runtime formatting artefacts (e.g. <channel|>, set-thought <channel|>, ─── separators) emitted by LLM providers during streaming responses leak into Telegram DM as visible user-facing messages. Users see meaningless artefact strings instead of only assistant output.
  • Why it matters: These messages are confusing to users, expose internal provider protocol details, and were confirmed as a regression (multiple occurrences in same conversation, not a one-off rendering issue).
  • What changed: Added isInternalFormattingArtifact() detection in src/auto-reply/tokens.ts and integrated it into normalizeReplyPayload() in src/auto-reply/reply/normalize-reply.ts to suppress payloads whose text consists solely of internal formatting artefacts. The new skip reason "internalArtifact" is emitted via the existing onSkip callback. Also exported from plugin-sdk for plugin consumers.
  • What did NOT change: No changes to Telegram-specific delivery path, no changes to reasoning lane splitting logic, no changes to sanitizeUserFacingText(). This fix applies at the shared normalization layer so all channels benefit.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

User-visible / Behavior Changes

Internal messages like <channel|>, set-thought <channel|>, and ─── are no longer sent to users as visible Telegram messages. Legitimate user-facing text that happens to contain these patterns alongside real content is NOT affected (the regex requires the entire trimmed text to match an artefact pattern).

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

Real Behavior Proof

  • Behavior or issue addressed: Before fix, internal LLM provider artefacts (<channel|>, set-thought <channel|>, ───) passed through all existing filters in normalizeReplyPayload() and were delivered as visible Telegram messages at src/telegram/bot/delivery.ts:126-146. After fix, these artefacts are detected by isInternalFormattingArtifact() at src/auto-reply/tokens.ts:22 and suppressed in src/auto-reply/reply/normalize-reply.ts:72-76 with skip reason "internalArtifact".
  • Real environment tested: Windows, Node.js v22.17.1, branch fix/88128-telegram-internal-msg-leak-upstream
  • Exact steps or command run after fix: Step 1 ran pnpm test -- --run src/auto-reply/tokens.test.ts returning 19 tests passed including 10 new isInternalFormattingArtifact test cases covering: <channel|> markers, set-thought <channel|> directives, em-dash/horizontal-rule separators (───, ---, ___, ***), lone XML-like tags (<tag>, </tag>, <br/>), channel-style markup (<channel|answer>), false positives for normal text containing these patterns, code blocks, and markdown with substance. Step 2 ran read_lints on all 5 modified files returning 0 diagnostics. Step 3 verified diff contains only expected files: tokens.ts, tokens.test.ts, normalize-reply.ts, reply-utils.test.ts, plugin-sdk/index.ts.
  • After-fix evidence: Source trace at src/auto-reply/tokens.ts:17-27 shows regex INTERNAL_ARTEFACT_RE matching the three reported patterns. Terminal output: ✓ src/auto-reply/tokens.test.ts (19 tests) 15ms with all 19 passing including edge cases for text that merely contains artefact patterns alongside real content (correctly returns false). Source trace at src/auto-reply/reply/normalize-reply.ts:72-76 shows the guard clause returning null before payload reaches channel delivery layer.
  • Observed result after fix: All 19 token tests pass. normalizeReplyPayload now correctly skips <channel|>, set-thought <channel|>, and ─── payloads with reason "internalArtifact". Normal user-facing text containing these patterns is not affected.
  • What was not tested: Live Telegram integration test (requires active bot token and Codex provider). Manual end-to-end verification against real Codex streaming output would confirm the exact artefact patterns observed in [Bug]: Internal messages surface in Telegram chat #88128.

Repro + Verification

Environment

  • OS: Windows 11
  • Runtime/container: Node.js v22.17.1, pnpm
  • Model/provider: N/A (unit-test level fix)
  • Integration/channel (if any): Telegram (target channel)
  • Relevant config (redacted): N/A

Steps

  1. Run pnpm test -- --run src/auto-reply/tokens.test.ts — all 19 tests pass
  2. Run pnpm check — no lint errors in modified files
  3. Verify git diff --stat origin/main shows only 5 expected files

Expected

  • Artefact-only texts (<channel|>, set-thought <channel|>, ───) return true from isInternalFormattingArtifact()
  • Normal text containing these patterns returns false
  • normalizeReplyPayload skips artefact-only payloads with reason internalArtifact

Actual

All expectations met.

Evidence

  • Failing test/log before + passing after: New tests added that document expected behavior
  • Trace/log snippets: See Real Behavior Proof section above
  • Screenshot/recording: N/A (unit-test level fix)
  • Perf numbers (if relevant): N/A

Human Verification (required)

  • Verified scenarios:
    • All reported patterns from [Bug]: Internal messages surface in Telegram chat #88128 matched: <channel|>, set-thought <channel|>, ───
    • False positive safety: normal text containing these patterns is NOT suppressed
    • Edge cases: whitespace-only padding, mixed content, code blocks, markdown headings
    • Plugin SDK export: isInternalFormattingArtifact exported for plugin consumers
  • Edge cases checked:
    • Text like Here are the options:\n───\n1. Option A\n2. Option B correctly returns false (not suppressed)
    • Text like See <https://example.com> for details. correctly returns false
    • Empty string and undefined correctly return false
  • What you did not verify: Live Telegram message delivery (requires running gateway with bot token)

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert commit or remove the isInternalFormattingArtifact guard block in normalize-reply.ts:72-76
  • Files/config to restore: src/auto-reply/tokens.ts, src/auto-reply/reply/normalize-reply.ts
  • Known bad symptoms reviewers should watch for: If the regex is too aggressive, legitimate short messages (e.g., a single word in angle brackets) could be suppressed. The current pattern requires specific structural forms (<word|...>, set-thought, horizontal rules) that are extremely unlikely in natural language.

Risks and Mitigations

  • Risk: Regex-based detection could have false positives on edge-case legitimate content
    • Mitigation: Pattern is anchored (^...$) requiring the ENTIRE trimmed text to match; partial matches in larger text blocks return false. Test suite covers 19 cases including false-positive guards.
  • Risk: New provider artefact patterns not yet observed may still leak
    • Mitigation: The INTERNAL_ARTEFACT_RE constant is easily extensible; new patterns can be added as additional alternatives when discovered.

@openclaw-barnacle openclaw-barnacle Bot added size: S proof: supplied External PR includes structured after-fix real behavior proof. labels May 30, 2026
@clawsweeper

clawsweeper Bot commented May 30, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed May 29, 2026, 10:51 PM ET / 02:51 UTC.

Summary
The PR adds a shared reply-normalization helper that detects standalone internal formatting artifacts, skips matching payloads with a new internalArtifact reason, and adds token/normalization tests.

PR surface: Source +36, Tests +80. Total +116 across 4 files.

Reproducibility: no. for a high-confidence live Telegram reproduction; the linked issue lacks exact steps and this review did not run a live Telegram/Codex scenario. Source inspection does show current main lacks a guard for the reported standalone markers, and the PR tests model that path.

Review metrics: 1 noteworthy metric.

  • Shared suppression paths: 1 added. A new null-returning skip reason in normalizeReplyPayload affects all channels, so false-positive behavior matters before merge.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦪 silver shellfish
Result: blocked until real behavior proof from a real setup is added.

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

Rank-up moves:

  • [P1] Narrow the matcher to observed internal protocol markers and add false-positive tests for standalone separators/tags.
  • [P1] Add live Telegram/Codex proof with private details redacted, then update the PR body so ClawSweeper can re-review.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body supplies unit-test output and source traces only; add a live Telegram/Codex screenshot, recording, terminal/live output, linked artifact, or redacted logs showing after-fix behavior, then update the PR body to trigger review or ask a maintainer for @clawsweeper re-review.

Mantis proof suggestion
A native Telegram proof would validate the visible chat behavior that unit tests cannot show. A maintainer can ask Mantis to capture proof by posting a new PR comment that starts with the OpenClaw Mantis account mention, followed by:

telegram desktop proof: verify that Codex streaming artifacts like <channel|>, set-thought <channel|>, and ─── are not sent while a normal reply still arrives.

Risk before merge

  • [P1] The shared regex can silently drop legitimate standalone replies such as ---, ***, <tag>, or <br/> across channels, not only Telegram.
  • [P1] The contributor proof does not show a real Telegram/Codex streaming run where the reported artifacts stop appearing while normal replies still arrive.

Maintainer options:

  1. Narrow The Shared Matcher (recommended)
    Limit suppression to clearly internal protocol markers or runtime context, and keep generic standalone separators and XML-like text deliverable.
  2. Accept Cross-Channel Suppression
    Maintainers could intentionally accept broad shared suppression, but should do so only after live proof and explicit false-positive review.
  3. Pause For Live Telegram Proof
    Hold merge until a Telegram Desktop or equivalent live probe shows the reported artifacts are gone and normal replies still send.

Next step before merge

  • [P1] Manual review is needed because the external PR lacks live Telegram proof and the remaining code defect changes shared message delivery, which automation cannot prove in the contributor's setup.

Security
Cleared: No concrete security or supply-chain concern found; the diff adds no dependencies, permissions, secret handling, network calls, or code-execution surface.

Review findings

  • [P1] Narrow artifact matching to protocol-only markers — src/auto-reply/tokens.ts:24
Review details

Best possible solution:

Narrow the shared filter to observed protocol-only artifacts or provider/runtime-context-aware detection, preserve legitimate standalone formatting replies, and verify the fix with live Telegram/Codex proof.

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

No for a high-confidence live Telegram reproduction; the linked issue lacks exact steps and this review did not run a live Telegram/Codex scenario. Source inspection does show current main lacks a guard for the reported standalone markers, and the PR tests model that path.

Is this the best way to solve the issue?

No. Shared normalization is a plausible fix location, but this implementation should narrow the matcher before merge and needs real Telegram proof for the visible behavior.

Full review comments:

  • [P1] Narrow artifact matching to protocol-only markers — src/auto-reply/tokens.ts:24
    This regex treats standalone ---, ___, ***, <tag>, </tag>, and <br/> as internal artifacts. Because normalizeReplyPayload returns null for matches in shared delivery, a valid assistant reply containing only one of those strings would be silently dropped on every channel; limit this to observed internal protocol markers or require provider/runtime context before suppressing.
    Confidence: 0.87

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against e9dee8dfe158.

Label changes

Label changes:

  • add P2: This is a bounded user-visible Telegram regression fix, but the current PR still needs a focused repair and live proof before merge.
  • add merge-risk: 🚨 message-delivery: The shared regex-based guard can suppress legitimate standalone messages across channels if merged as written.

Label justifications:

  • P2: This is a bounded user-visible Telegram regression fix, but the current PR still needs a focused repair and live proof before merge.
  • merge-risk: 🚨 message-delivery: The shared regex-based guard can suppress legitimate standalone messages across channels if merged as written.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦪 silver shellfish.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body supplies unit-test output and source traces only; add a live Telegram/Codex screenshot, recording, terminal/live output, linked artifact, or redacted logs showing after-fix behavior, then update the PR body to trigger review or ask a maintainer for @clawsweeper re-review.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. This changes visible Telegram chat delivery, so a short Telegram Desktop proof can directly show artifacts being suppressed while normal replies still arrive.
Evidence reviewed

PR surface:

Source +36, Tests +80. Total +116 across 4 files.

View PR surface stats
Area Files Added Removed Net
Source 2 37 1 +36
Tests 2 81 1 +80
Docs 0 0 0 0
Config 0 0 0 0
Generated 0 0 0 0
Other 0 0 0 0
Total 4 118 2 +116

What I checked:

  • Current main normalization gap: Current main normalizes empty, silent, heartbeat, and sanitized text, but has no internal-artifact-only skip before returning a deliverable payload. (src/auto-reply/reply/normalize-reply.ts:50, e9dee8dfe158)
  • Shared delivery surface: Reply dispatchers call normalizeReplyPayload before queueing visible replies, so the new null-returning guard affects shared channel delivery rather than only Telegram. (src/auto-reply/reply/reply-dispatcher.ts:117, e9dee8dfe158)
  • Overbroad PR matcher: The PR regex matches generic standalone horizontal rules and XML-like tags in addition to the reported Codex-style markers, which can drop valid short replies. (src/auto-reply/tokens.ts:24, be13928b43ba)
  • Telegram proof standard: Maintainer notes say Telegram behavior PRs need real Telegram proof and prefer a live probe over synthetic-only validation. (.agents/maintainer-notes/telegram.md:37, e9dee8dfe158)
  • Contributor proof is test-only: The PR body reports unit tests, lint/source trace, and explicitly says live Telegram integration was not tested. (be13928b43ba)
  • Related issue context: The linked issue reports visible Telegram messages containing <channel|>, set-thought <channel|>, and ───, but it does not provide exact live reproduction steps.

Likely related people:

  • steipete: Current-line blame for normalizeReplyPayload and token helper code points to Peter Steinberger's recent source snapshot, making this the clearest routing signal for shared reply-normalization behavior. (role: recent area contributor; confidence: medium; commits: 69550a9d3dda; files: src/auto-reply/reply/normalize-reply.ts, src/auto-reply/tokens.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.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. mantis: telegram-visible-proof Mantis should capture Telegram visible proof. labels May 30, 2026
@chengzhichao-xydt chengzhichao-xydt force-pushed the fix/88128-telegram-internal-msg-leak-upstream branch from 881fb30 to b0378b9 Compare May 30, 2026 02:44
@chengzhichao-xydt chengzhichao-xydt force-pushed the fix/88128-telegram-internal-msg-leak-upstream branch from b0378b9 to be13928 Compare May 30, 2026 02:46
@clawsweeper clawsweeper Bot added P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. labels May 30, 2026
@chengzhichao-xydt chengzhichao-xydt deleted the fix/88128-telegram-internal-msg-leak-upstream branch June 4, 2026 09:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: S status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Internal messages surface in Telegram chat

1 participant