fix(telegram): prevent preview duplication in partial and block streaming modes#88634
Conversation
|
Codex review: needs maintainer review before merge. Reviewed June 3, 2026, 8:57 AM ET / 12:57 UTC. Summary PR surface: Source +101, Tests +227. Total +328 across 4 files. Reproducibility: yes. Current main is source-reproducible: retained overflow previews are possible in draft-stream, while the main finalizer still starts from the first final chunk and lacks retained active-chunk accounting. Review metrics: none identified. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review detailsBest possible solution: Land the Telegram-layer retained-preview accounting after maintainer acceptance of the visible delivery risk and required checks, then close the linked bug through the merge. Do we have a high-confidence way to reproduce the issue? Yes. Current main is source-reproducible: retained overflow previews are possible in draft-stream, while the main finalizer still starts from the first final chunk and lacks retained active-chunk accounting. Is this the best way to solve the issue? Yes. The PR keeps the repair in the Telegram streaming owner boundary and addresses retained preview accounting directly; a broader core outbound refactor would be larger than needed for this bug. AGENTS.md: found and applied where relevant. Codex review notes: model gpt-5.5, reasoning high; reviewed against a61c94b1f179. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +101, Tests +227. Total +328 across 4 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
|
|
Landed via squash in e4993ec from head a83bfd2. Verification:
Behavior addressed: Telegram streamed replies in partial and block modes finalize preview chunks once instead of replaying duplicate preview bodies. Changelog: not edited; Thanks @jmao0001. |
Summary
What problem does this PR solve?
In Telegram,
channels.telegram.streaming.mode: "partial"and"block"modes duplicated the entire stream preview content on final emit if the reply size exceeded the ~4096 characters per-message cap. When the message was block-rotated into a new message, the draft stream controller unknowingly replayed chunks that were already delivered in preceding block/partial transmissions because it received the full cumulative text for final emit processing.Why does this matter now?
This created broken and frustrating user experiences where long responses on Telegram were sent twice, interrupting reading flow and visually inflating output length.
What is the intended outcome?
The final stream text delivery respects the current
activeChunkIndextracked across stream rotations. The system now accurately targets the current active preview chunk for inline finalization and accurately distributes the remainder of the payload downstream sequentially. Additionally,partialstreaming skips redundant text-only block deliveries that were needlessly stepping over incremental partial streaming.What is intentionally out of scope?
Refactoring the larger core outbound block delivery protocol is out of scope. This addresses the Telegram-specific
lane-deliverymodule interface handling.What does success look like?
Long Telegram responses (>4096 characters) seamlessly transition to multiple paginated messages without repeating the initial content.
What should reviewers focus on?
lane.activeChunkIndexis scoped securely toonSupersededPreviewso it only increments for retained overflow chunks.isDeliveredPrefixandsuffixhandling changes, ensuring they useactiveFullTextrather thantext.Linked context
Which issue does this close?
Closes #87624
Which issues, PRs, or discussions are related?
Related #84885
Was this requested by a maintainer or owner?
Yes.
Real behavior proof (required for external PRs)
pnpm gateway:dev(using OpenRouter/GLM for generation).streaming.mode: "partial",chunkMode: "length", and artificially loweredtextChunkLimit: 15to force the chunking behavior on a short prompt.Tests and validation
Which commands did you run?
pnpm test:extensions&pnpm test:unitWhat regression coverage was added or updated?
Coverage checks updated inside
lane-delivery.test.tsandbot-message-dispatch.test.tsto properly account for the internal track increment valueactiveChunkIndex. Additional regressions created targeting long finals post-rotation.What failed before this fix, if known?
The final delivery loops assumed message sequences weren't rotated locally by previous block triggers inside
deliverLaneText. Text-only blocks would also get silently dropped if streams weren't properly enabled.If no test was added, why not?
Tests were successfully added.
Risk checklist
Did user-visible behavior change? (
Yes/No)Yes(duplicate spam was removed)Did config, environment, or migration behavior change? (
Yes/No)NoDid security, auth, secrets, network, or tool execution behavior change? (
Yes/No)NoWhat is the highest-risk area?
Draft lane text rotation bounds targeting potentially non-existent sequence indexes.
How is that risk mitigated?
Indices are firmly clamped against
0andchunks.length - 1with logical fallbacks handling edge-case length disparities securely.Current review state
What is the next action?
Maintainer review and functional verification.
What is still waiting on author, maintainer, CI, or external proof?
CI success.
Which bot or reviewer comments were addressed?
Codex recommendation to provide concrete source-backed bounds correction targeting the final delivery overflow chunks. Re-scoped
activeChunkIndexincrements toonSupersededPreviewspecifically, ensured it isn't incremented in generic resets, and modified text-block delivery skips so they only suppress when an active partial draft exists.AI Assistance Transparency
activeChunkIndexand how it correctly targets the active stream without duplicating already-delivered final chunks. I confirm I understand how this code works.Maintainer update (2026-06-01)
Maintainer repair pushed to this PR branch at
5d9f143b5f7811a1199315d0f84a0fcc1647b1f3.Additional fixes on top of the contributor patch:
stop().Maintainer verification:
node scripts/run-vitest.mjs extensions/telegram/src/lane-delivery.test.ts extensions/telegram/src/bot-message-dispatch.test.ts extensions/telegram/src/draft-stream.test.ts(170 tests)node scripts/run-oxlint.mjs extensions/telegram/src/lane-delivery-text-deliverer.ts extensions/telegram/src/bot-message-dispatch.ts extensions/telegram/src/lane-delivery.test.ts extensions/telegram/src/bot-message-dispatch.test.tsgit diff --check origin/main...HEAD.agents/skills/autoreview/scripts/autoreview --mode branch --base origin/mainclean on the repaired branch before the final unrelated main rebase5d9f143b5f7:L2_TELEGRAM_EXIT=0 vitest=0 lint=0 diff=0tbx_01kt0wfts5fck0xvqp05zg9erx, lanesextensions, extensionTests, exit 0