feat(telegram): opt-in interleaved progress lane#87072
Conversation
|
Codex review: needs real behavior proof before merge. Reviewed June 3, 2026, 4:48 AM ET / 08:48 UTC. Summary PR surface: Source +128, Tests +148, Docs +1, Generated 0. Total +277 across 13 files. Reproducibility: yes. for the review finding: source inspection shows current main forwards preamble item events into Telegram progress drafts, while the PR returns before that fallback when Review metrics: 1 noteworthy metric.
Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Preserve the existing Telegram progress visibility by default, or get an explicit maintainer decision for a breaking opt-in, then align schema/docs/tests and attach current-head Telegram proof for both enabled and default paths. Do we have a high-confidence way to reproduce the issue? Yes for the review finding: source inspection shows current main forwards preamble item events into Telegram progress drafts, while the PR returns before that fallback when Is this the best way to solve the issue? No. The commentary renderer path is plausible and matches the Discord pattern, but making Telegram preamble progress opt-in silently changes an existing documented default; the safer fix preserves the default unless maintainers explicitly approve the break. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against 0b98aea71a52. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +128, Tests +148, Docs +1, Generated 0. Total +277 across 13 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 PR egg: 🎁 locked until real behavior proof passes. Details
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Updated the PR body with current-head proof for all four behaviors:
The send-log facts are message-level metrics (ids, lengths, ok/timing) with no command/path/host content; the screenshot is redacted. Remaining non-code item: maintainer acceptance of the two default-off config keys. |
|
🦞👀 Command router queued. I will update this comment with the next step. |
|
@clawsweeper re-review Pushed
Local: oxlint clean, tsgo clean, 48/48 telegram interleaved tests green. Remaining item is the Telegram maintainer sign-off on the two default-off config keys. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Pushed
Local: oxlint clean, tsgo clean, reasoning-lane-coordinator tests green. Remaining item is the Telegram maintainer sign-off on the two default-off config keys. |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review Refreshed the live proof to the current head (
Code is unchanged since the last review (patch already platinum); this only updates the proof to current head. Remaining item is the Telegram maintainer sign-off on the two default-off config keys. |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
@clawsweeper re-review (Prior re-review run failed to finish — re-triggering. No changes since; the body already carries the refreshed current-head proof: continuation spill 34783→34786, no-dup, no empty Thinking, 20s timer cadence, and 0 429s across two concurrent threads.) |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
🦞🧹 I asked ClawSweeper to review this item again. |
|
@clawsweeper re-review |
|
🦞👀 Command router queued. I will update this comment with the next step. Re-review progress:
|
|
I fully support this as normalisation of behaviours across similar channels. This would bring Telegram in line with Discord, which finally got fixed to show equivalent information to TUIs like Claude Code etc.. #85200, amongst others...
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
Mantis Telegram Desktop ProofSummary: Mantis captured native Telegram Desktop before/after GIFs for the Telegram reasoning preview.
Motion-trimmed clips: Raw QA files: https://artifacts.openclaw.ai/mantis/telegram-desktop/pr-87072/run-26852608089-1/index.json |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
|
Landed via rebase onto
Thanks @anagnorisis2peripeteia! |





Summary
Add an opt-in Telegram renderer that projects reasoning text and structured runtime events into a single durable live message on the reasoning lane, matching CLI ergonomics without changing execution semantics.
Gated on three conditions:
toolProgressEnabled && interleavedProgress === true && hasReasoningLane— inherits every existing group/DM/visibility gate.What it does
When
channels.telegram.streaming.preview.interleavedProgressis enabled:pushStreamToolProgresslane when the flag is offKey design choices
interleavedToolArgsis a separate opt-in for sanitized argsonReasoningStream,onToolStart,onItemEvent,onPlanUpdate,onApprovalEvent,onCommandOutput,onPatchSummarycallbacks unchangedonReasoningStream) and tool/event lines; the model's reply prose is not folded into it. Folding reply text in and stripping it back out at delivery proved unreliable — the model often drafts an answer, runs tools, then re-emits a revised one, leaving several answer-like copies of which only the last matches the polished final text. So the reply is delivered exactly once, as the answer. For the interactive backend the proxy restores real thinking on its ownonReasoningStream, so reasoning is unaffected; a defensive final-answer strip remains for redacted-thinking backends that bridge assistant text into the reasoning lane. Tagged payloads (<think>reason</think>answer) keep only the in-tag reasoning, so answer prose after</think>never lands in the lane.<think>etc.) are unwrapped so the lane shows the model's prose, never raw tagsPrerequisite
onToolStartlifecycle events the tool lines render. This branch should be rebased onto currentmain(which now contains it) before merge.The renderer otherwise consumes only existing callbacks and is default-off, so it depends on no unmerged work. (On the standard
claude-clibackend, CLI-native reasoning text additionally benefits from #85381'sthinking_delta; without it the lane simply shows tool/event lines. The interactive backend restores thinking via its proxy, so reasoning appears regardless. Either way the default tool-progress lane is unaffected — this is not a hard dependency.)Changed files
extensions/telegram/src/interleaved-progress.ts— pure render helpers (gate, sanitize, header-strip, message render with length cap + no-content guard + wall-clock timer stamp, delta-append with cumulative-snapshot handling + guarded overlap fold, continuation-spill computation, defensive final-answer strip, status-line append, timer-interval constant)extensions/telegram/src/bot-message-dispatch.ts— wire callbacks through the renderer with fallback; single reasoning-stream delta append (reply prose kept out of the lane); spill into a continuation message before the length cap; suppress an empty Thinking flush at final delivery; 20s rolling-timer cadence; reasoning-tag unwrapping; clear rolling timer infinallyextensions/telegram/src/reasoning-lane-coordinator.ts—stripReasoningTagsForInterleaved(extract only in-<think>reasoning, dropping answer prose after</think>, preserving code regions)src/config/types.telegram.ts+src/config/zod-schema.providers-core.ts— opt-in flag schemaTest plan
</think>dropped; streaming/code cases), defensive final-answer stripVerification
Local checks at the current head:
Real behavior proof
Behavior addressed: Opt-in Telegram interleaved progress renders reasoning plus tool/progress events in one durable Thinking message, without duplicating the final answer or freezing at Telegram message limits.
Real environment tested: Real OpenClaw Telegram gateway against Telegram, default-off feature explicitly enabled, two concurrent Telegram threads in one chat.
Exact steps or command run after this patch: Rebuilt and ran the gateway from the PR head, enabled channels.telegram.streaming.preview.interleavedProgress, sent concurrent Telegram prompts that produced reasoning, tool progress, long Thinking output, and idle tool waits, then inspected Telegram messages and the gateway outbound Telegram send log.
Evidence after fix: Screenshot embedded below plus redacted outbound Telegram send-log metrics copied below: continuation msg=34783 -> msg=34786, final answer absent from every Thinking edit, zero bare Thinking sends, 20s timer edits at 04:20:15 -> 04:20:35 -> 04:20:55, and 99 outbound calls with 0 failures.
Observed result after fix: Thinking lane showed reasoning plus tool line, rolled into a continuation before the cap, sent the polished answer once as its own message, cleared empty Thinking output, and avoided Telegram 429s under the two-thread concurrent run.
What was not tested: No broad channel matrix or release package lane in this PR; focused local proof covers the Telegram renderer helpers, schema, lint, and extension typecheck.
Live proof (current head)
Captured on the current head with the default-off feature enabled, over a two-thread concurrent session. The screenshot shows the visible lane; the rest is verified from the gateway's outbound Telegram send log — every
sendMessage/editMessageTextthe bot issues — which shows message-level behavior a screenshot can't (message ids, edit cadence, final-state content, timing). Wire-level facts below are message-level metrics (ids, lengths, ok/timing) and contain no command/path/host content.Normal interleaving — reasoning + tool-use line in the Thinking lane, with the rolling timer:
Wire-level verification (gateway send log, current head, one two-thread concurrent session):
msg=34783grew to the 4000-char cap and rolled into a fresh continuationmsg=34786(carrying the next tool line) instead of freezing; clean seam, no garble.34783/34786.Thinking-header sends across the session.429s, no oversized-preview stop) — the exact concurrency that previously drew 429s.