Skip to content

fix(telegram): streaming finalize — drop preview-deletion race, finalize MarkdownV2, accept nested config (salvage of #13542, #25724, #25694)#25923

Merged
teknium1 merged 3 commits into
mainfrom
hermes/hermes-61bc4838
May 14, 2026
Merged

fix(telegram): streaming finalize — drop preview-deletion race, finalize MarkdownV2, accept nested config (salvage of #13542, #25724, #25694)#25923
teknium1 merged 3 commits into
mainfrom
hermes/hermes-61bc4838

Conversation

@teknium1

Copy link
Copy Markdown
Contributor

Fixes the Telegram streaming class of bugs where a streamed response would visibly disappear, duplicate, or render with raw Markdown syntax. Salvages three contributor PRs onto current main.

Cherry-picks

Conflict resolution

#13542 conflicted in two spots against current main:

  1. gateway/stream_consumer.py — main already has the stricter _final_response_sent = chunks_delivered check (fix(gateway): streaming mode silently drops final response when already_sent is true #10748). Kept that; layered _final_content_delivered = True on top, gated on chunks_delivered rather than _already_sent so it inherits the stricter precondition. The PR's looser _already_sent gate would have re-introduced the very bug fix(gateway): streaming mode silently drops final response when already_sent is true #10748 fixed.
  2. gateway/run.py — main already had the _content_delivered field wired into the suppression predicate; the conflict was a log-format mismatch. Kept main's log format with the new content_delivered=%s field appended.

Validation

Suite Result
Targeted test_duplicate_reply_suppression, test_gateway_streaming_nested_config, test_stream_consumer, test_stream_consumer_fresh_final 131/131
Broader tests/gateway/ -k "stream or telegram or duplicate" 754/754

Co-authored-by preserved via cherry-pick; authorship visible per-commit.

Closes #25710, #25676. Likely fixes user-visible regression of #16668.

luyao618 and others added 3 commits May 14, 2026 12:54
… not skipped

When the final streamed text is identical to the last plain-text edit,
stream_consumer._send_or_edit short-circuits and never calls
adapter.edit_message(finalize=True).  For Telegram, this skips the
plain-text → MarkdownV2 conversion, leaving raw Markdown syntax visible
to the user.

Set REQUIRES_EDIT_FINALIZE = True on TelegramAdapter so the finalize
edit is always delivered, matching the existing DingTalk pattern.

Fixes #25710
`hermes config set gateway.streaming.*` writes the streaming block
nested under a `gateway:` key in config.yaml, but the config loader
only checked for a top-level `streaming:` key — silently ignoring
the nested variant.

Fall back to `yaml_cfg['gateway']['streaming']` when the top-level
key is absent, matching the pattern already used for other nested
config sections.

Closes #25676
…iled

When the stream consumer's got_done handler successfully delivers the
final response content via _send_or_edit but the subsequent edit
(e.g. cursor removal) fails, final_response_sent remains False even
though the user has already received the final answer. The gateway's
fallback send path then re-delivers the same content, causing the
user to see the response twice on Telegram.

Introduce a new _final_content_delivered flag on the stream consumer,
set by the got_done handler when the final content has reached the
user. The _run_agent suppression logic now treats this flag as an
additional signal (alongside final_response_sent and
response_previewed) that final delivery is already complete.

This preserves the existing behavior for intermediate-text-only
streams (where already_sent=True but no final content has been
delivered) — those still receive the gateway's fallback send, matching
the test expectation in test_partial_stream_output_does_not_set_already_sent.

Adds TestFinalContentDeliveredSuppression with two cases covering
both the suppression (content delivered + edit failed) and the
non-suppression (intermediate text only) branches.
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-61bc4838 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 8341 on HEAD, 8340 on base (🆕 +1)

🆕 New issues (1):

Rule Count
unresolved-import 1
First entries
tests/test_gateway_streaming_nested_config.py:6: [unresolved-import] unresolved-import: Cannot resolve imported module `pytest`

✅ Fixed issues: none

Unchanged: 4388 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working P1 High — major feature broken, no workaround comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels May 14, 2026
@teknium1 teknium1 merged commit bc42e62 into main May 14, 2026
18 of 19 checks passed
@teknium1 teknium1 deleted the hermes/hermes-61bc4838 branch May 14, 2026 21:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/gateway Gateway runner, session dispatch, delivery P1 High — major feature broken, no workaround platform/telegram Telegram bot adapter type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Telegram streaming skips final MarkdownV2 formatting when raw text is unchanged

4 participants