Skip to content

fix(stream_consumer): handle overflow when no message exists yet - #6828

Merged
teknium1 merged 1 commit into
mainfrom
hermes/hermes-95b15f6e
Apr 9, 2026
Merged

fix(stream_consumer): handle overflow when no message exists yet#6828
teknium1 merged 1 commit into
mainfrom
hermes/hermes-95b15f6e

Conversation

@teknium1

@teknium1 teknium1 commented Apr 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Salvage of #6816 by @dangelo352 — fixes silent message truncation on Telegram for long streamed responses.

Root cause

The overflow split loop in stream_consumer.py required self._message_id is not None to enter, but _message_id starts as None on the first streamed message (and after segment breaks). When the first accumulated text exceeded ~3993 chars:

  1. Overflow loop skipped (message_id is None)
  2. Full oversized text sent via _send_or_edit()adapter.send()
  3. Telegram adapter internally split via truncate_message(), but returned only chunk 1's message_id
  4. Subsequent edits tried to stuff growing text into chunk 1 → Telegram rejected with 'message_too_long'
  5. Telegram adapter silently truncated to 4076 chars + '…' and returned success=True
  6. User sees message cut off with '…'

Fix

Add a new code path before the existing while loop for the _message_id is None case:

  • Uses truncate_message() (same helper the non-streaming path uses) for proper word/code-fence boundary splitting with chunk indicators like (1/2)
  • Sends each chunk as a new message via new _send_new_chunk() helper
  • Properly handles got_done (returns immediately) and got_segment_break

The existing while loop for the _message_id is not None case is preserved untouched.

Changes from original PR #6816

  • Kept the original while loop (handles existing-message overflow correctly)
  • Dropped broken regex that produced garbled output ((1/\2\) instead of (1/3))
  • Fixed continue that would skip got_done handling (causing infinite loop when final message overflows)
  • Used _safe_limit instead of _raw_limit for truncate_message to account for formatting expansion

Test

  • 24/24 existing stream consumer tests pass
  • E2E: 6840-char message correctly split into 2 chunks (3982 + 2869), consumer terminates cleanly

The overflow split loop required _message_id to be set, but on the
first streamed message (or after a segment break) _message_id is None.
Oversized text fell through to _send_or_edit → adapter.send(), which
split internally — but subsequent edits hit Telegram's 'message too
long' and were silently truncated with '…', cutting off the response.

Add a new code path for the _message_id is None case that uses
truncate_message() (same as the non-streaming path) to split with
proper word/code-fence boundaries and chunk indicators. Each chunk
is sent as a new message via _send_new_chunk().

Properly handles got_done (returns immediately after sending chunks
instead of continuing into an infinite loop) and got_segment_break.

Original cherry-picked from PR #6816 by dangelo352.

Fixes silent message truncation on Telegram for long streamed responses.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants