fix(telegram): stop cutting long streamed responses (lost tails, deleted heads, raw markdown) - #43761
Merged
Merged
Conversation
…ly delete guard Follow-ups on top of the two salvaged GodsBoy commits, all live-validated against the real Telegram Bot API: - _edit_overflow_split finalize fallbacks degrade to _strip_mdv2() clean text instead of putting raw **markdown** markers on screen (salvaged from PR #43463 minus its format-first sizing — live probes show Telegram's 4096 limit counts PARSED text, so MarkdownV2 escape inflation cannot cause MESSAGE_TOO_LONG and sizing against formatted wire length only causes premature splits and fragment messages). - Skip the redundant requires-finalize edit after a got_done edit that split-and-delivered (salvaged from PR #43463): re-finalizing re-splits the full text into the adopted continuation and duplicates chunks. - _send_fallback_final only deletes the stale partial message when the fallback re-sent the COMPLETE final text. When the prefix dedup sent only the missing tail, the partial IS the head of the answer; deleting it left users with only the second half of long responses (live- reproduced: flood-control during a long stream -> head deleted, ratio 0.54 of content visible). This is the third bug behind the 'Telegram cut messages' reports and was present on main and both PRs.
Contributor
🔎 Lint report:
|
| Rule | Count |
|---|---|
unresolved-attribute |
1 |
unresolved-import |
1 |
First entries
tests/gateway/test_telegram_overflow_partial.py:137: [unresolved-attribute] unresolved-attribute: Attribute `kwargs` is not defined on `None` in union `_Call | None`
tests/gateway/test_telegram_overflow_partial.py:6: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`
✅ Fixed issues: none
Unchanged: 5600 pre-existing issues carried over.
Diagnostics are surfaced as warnings — this check never fails the build.
This was referenced Jun 10, 2026
|
Same issue here — Telegram user in Russia, seeing raw |
1 task
12 tasks
This was referenced Jul 30, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Telegram users stop receiving cut-off model responses: long streamed replies no longer lose their tail when a continuation send fails, no longer lose their head when flood-control fallback kicks in, and no longer freeze as raw
**markdown**when the stream is cancelled.Salvages and extends two PRs by @GodsBoy (#42766, #43463), with every claim and fix live-validated against the real Telegram Bot API using the real
TelegramAdapter+GatewayStreamConsumerwith fault injection.The three bugs (all reproduced live on main)
_edit_overflow_splitreturnedsuccess=Trueafter delivering 1/3 chunks. The consumer marked the turn delivered; the tail was gone forever._send_fallback_finalcomputes a tail-only continuation against the visible prefix, sends the tail, then deletes the partial message containing the head ("so the user only sees the complete fallback response" — but it wasn't a complete re-send). Live repro: flood control during a long stream → head deleted → 54% of content visible. Neither open PR fixed this path.finalize=False, leaving the entire reply as a raw plain-text preview while the success flags suppressed the gateway's formatted re-send.What was salvaged vs. dropped (and why)
Salvaged from #42766 (as-is): partial-overflow
SendResultcontract — failed continuations returnsuccess=False+raw_response["partial_overflow"]metadata; consumer enters fallback, sends only the missing tail, preserves the visible prefix.Salvaged from #43463: cancel-path
finalize=Truedelivery; re-finalize skip after a split edit (prevents chunk duplication);_strip_mdv2()degradation in all overflow-split fallbacks (raw**/```markers never hit the screen).Dropped from #43463 — wrong premise, live-disproved: sizing finalize splits against the formatted text. Live API probes show Telegram's 4096 limit counts the text after entities parsing: a payload with wire length 6120 but parsed length 4080 is accepted; parsing only removes characters, so raw-text sizing can never produce MESSAGE_TOO_LONG. The format-first sizing over-estimates and caused premature splits with 100-char fragment messages in live testing. The raw-marker symptom in #43463's screenshot is fully explained by the cancel path + parse-failure fallbacks, both fixed here.
New fix (bug 2):
_send_fallback_finalonly deletes the stale partial when the fallback re-sent the complete final text (continuation == final_text). Tail-only sends keep the head on screen.Changes
gateway/platforms/telegram.py: partial-overflow SendResult (GodsBoy);_strip_mdv2degradation in overflow-split fallbacks (first-chunk edit, continuations, reply-not-found retry)gateway/stream_consumer.py: partial-overflow recovery + tail-only fallback (GodsBoy); cancel-path finalize (GodsBoy); re-finalize skip after split (_last_edit_overflowed); delete-guard for tail-only fallbackgateway/platforms/base.py:SendResult.raw_responsepartial-overflow contract doc (GodsBoy)test_telegram_overflow_partial.py(new, GodsBoy), cancel-path + re-finalize classes intest_stream_consumer_fresh_final.py(GodsBoy), delete-guard pair intest_stream_consumer.py(ours, replacing the over-broad delete-always assertion)Validation
success=True, tail lost foreversuccess=False+ metadata, tail re-sent**markdown**frozenTargeted suites: 231 passed (
test_stream_consumer.py,test_stream_consumer_fresh_final.py,test_telegram_overflow_partial.py,test_telegram_format.py,test_stream_consumer_thread_routing.py). Ruff clean.Closes #42766. Closes #43463. Fixes #42765. Fixes #43441.
Contributor commits cherry-picked with authorship preserved (@GodsBoy); merge via rebase.
Infographic