Skip to content

fix(gateway): clean up stale telegram stream previews after fresh fin… - #40162

Closed
Swarmplestill wants to merge 1 commit into
NousResearch:mainfrom
Swarmplestill:fix/telegram-stale-stream-preview-cleanup
Closed

fix(gateway): clean up stale telegram stream previews after fresh fin…#40162
Swarmplestill wants to merge 1 commit into
NousResearch:mainfrom
Swarmplestill:fix/telegram-stale-stream-preview-cleanup

Conversation

@Swarmplestill

@Swarmplestill Swarmplestill commented Jun 5, 2026

Copy link
Copy Markdown

What does this PR do?

Fixes a visible UX bug where Telegram users receive two near-identical messages — a stale streamed preview bubble and a fresh final bubble — when the final edit_message(finalize=True) hits long flood control (retry_after > 5s).

Root cause: When Telegram's edit_message(finalize=True) fails with flood control, the adapter returns SendResult(success=False). The stream consumer does not mark _final_response_sent / _final_content_delivered, so the gateway falls back to a normal final send — producing a duplicate instead of replacing the preview.

Fix: Register a post_delivery_callback that deletes the stale preview bubble after the fresh final message lands. Uses existing register_post_delivery_callback and safe_schedule_threadsafe APIs — no new dependencies.

Related Issue

No existing issue — bug discovered and reproduced in production.

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)

Changes Made

  • gateway/run.py: Added elif block (~line 19246) that detects stale streamed previews (already_sent=True but no _streamed/_previewed/_content_delivered confirmation) and registers a post-delivery callback to delete the stale bubble after the fresh final message lands
  • tests/gateway/test_run_progress_topics.py: Added FailingFinalizePreviewAdapter, StreamingFinalizeFailureAgent, and test_run_agent_registers_cleanup_for_stale_stream_preview

How to Test

  1. pytest tests/gateway/test_run_progress_topics.py -q — 29 passed
  2. pytest tests/gateway/test_stream_consumer.py tests/gateway/test_run_progress_topics.py -q — 121 passed
  3. scripts/check-windows-footguns.py gateway/run.py tests/gateway/test_run_progress_topics.py — no issues
  4. Manual: send a long streamed response via Telegram, observe that only one final message appears (stale preview is cleaned up)

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: Ubuntu 24.04, Python 3.11

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A (change is async/scheduling logic only)
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

…al send

When a Telegram streamed preview is visible but the final
edit_message(finalize=True) hits long flood control (retry_after > 5s),
the adapter returns SendResult(success=False). The stream consumer does
not mark _final_response_sent / _final_content_delivered, so the gateway
falls back to a normal final send, producing a near-duplicate message.

Register a post_delivery_callback that deletes the stale preview bubble
after the fresh final message lands. This ensures users see one canonical
answer instead of preview + near-duplicate final.

Test: FailingFinalizePreviewAdapter + StreamingFinalizeFailureAgent verify
callback registration and stale preview deletion.
@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/gateway Gateway runner, session dispatch, delivery platform/telegram Telegram bot adapter labels Jun 5, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the focused reproduction and cleanup proposal. This is now implemented on main through a more complete stream-consumer recovery path.

  • Commit 04898631cb72dbf84f5c066c3f87fc8c94df53a7 (fix(telegram): recover final delivery after stream flood) enables immediate Telegram fallback after a turn-final flood-control edit failure (plugins/platforms/telegram/adapter.py:460-467, gateway/stream_consumer.py:1871-1904).
  • The empty-tail path sends a fresh final and deletes stale preview IDs before marking final delivery complete (gateway/stream_consumer.py:993-1023, 1156-1226).
  • Regression coverage verifies the fresh final and stale-preview deletion (tests/gateway/test_telegram_final_delivery.py:100-140).
  • The cross-referenced fix(telegram): recover final delivery after stream flood #62253 discussion identified this same final-delivery family and its consolidated stream-consumer approach.

Automated hermes-sweeper review.

@teknium1 teknium1 closed this Jul 14, 2026
@teknium1 teknium1 added the sweeper:implemented-on-main Sweeper: behavior already present on current main label Jul 14, 2026
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 P2 Medium — degraded but workaround exists platform/telegram Telegram bot adapter sweeper:implemented-on-main Sweeper: behavior already present on current main type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants