From 454d6cbe5250964e1e98cf44ae7d06d71a895b33 Mon Sep 17 00:00:00 2001 From: Ali Zakaee Date: Thu, 4 Jun 2026 06:03:05 -0700 Subject: [PATCH] fix(telegram): finalize sealed overflow chunk so split streamed replies render formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The existing-message overflow split path in stream_consumer.run() sealed the first chunk via _send_or_edit(chunk) (finalize=False) then reset _message_id to None — so that chunk was never edited again and never received the adapter's final rich-text pass. On Telegram, MarkdownV2 formatting is applied on the finalize edit, so early split messages of a long multi-part streamed reply rendered raw markdown (##, **bold**, code fences) while only the last chunk rendered correctly. Fix: seal the overflow chunk with finalize=True so it gets its final formatting pass before _message_id is cleared. Salvaged from #32609 (the streaming-format portion only; the PR's send_draft parse_mode change is already superseded on main, and its media-roots change conflicts with the current denylist + recency-window delivery model). --- gateway/stream_consumer.py | 14 +++++++++++++- scripts/release.py | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/gateway/stream_consumer.py b/gateway/stream_consumer.py index 16d1cecd3..33910c7b4 100644 --- a/gateway/stream_consumer.py +++ b/gateway/stream_consumer.py @@ -530,7 +530,19 @@ class GatewayStreamConsumer: if split_at < _safe_limit // 2: split_at = _safe_limit chunk = self._accumulated[:split_at] - ok = await self._send_or_edit(chunk) + # finalize=True so the adapter applies platform-specific + # rich-text markup (e.g. Telegram MarkdownV2). This + # sealed chunk will never be edited again — _message_id + # is reset to None right below — so it must receive its + # final formatting pass now, or early split messages + # render raw markdown while only the last chunk renders. + # is_turn_final=False: this is the first of several split + # messages, NOT the turn-final answer, so the fresh-final + # path (opt-in fresh_final_after_seconds) must not mark + # the turn delivered on it (#29346 semantics). + ok = await self._send_or_edit( + chunk, finalize=True, is_turn_final=False, + ) if self._fallback_final_send or not ok: # Edit failed (or backed off due to flood control) # while attempting to split an oversized message. diff --git a/scripts/release.py b/scripts/release.py index 6fa874afd..adf20ceaa 100755 --- a/scripts/release.py +++ b/scripts/release.py @@ -48,6 +48,7 @@ AUTHOR_MAP = { "zhaolei.vc@bytedance.com": "zhaoleibd", "jeffrobodie@gmail.com": "jeffrobodie-glitch", "kyssta-exe@users.noreply.github.com": "kyssta-exe", + "ali.zakaee.1997@gmail.com": "ITheEqualizer", "copii.list@gmail.com": "stremtec", "solaiagent@gmail.com": "solaitken", "cryptoworlldz@gmail.com": "worlldz",