Skip to content

fix(gateway): clear typing indicator when cancel_session_processing gives up - #20696

Closed
vincent-wen789 wants to merge 1 commit into
NousResearch:mainfrom
vincent-wen789:fix/telegram-typing-stuck-timeout
Closed

fix(gateway): clear typing indicator when cancel_session_processing gives up#20696
vincent-wen789 wants to merge 1 commit into
NousResearch:mainfrom
vincent-wen789:fix/telegram-typing-stuck-timeout

Conversation

@vincent-wen789

Copy link
Copy Markdown

Problem

When an agent processing task gets stuck in blocking I/O (e.g. a hung web_extract call lasting 961s), the inactivity watchdog fires, cancel_session_processing cancels the task, waits 5s, then unblocks dispatch — but the _keep_typing refresh loop keeps running. The user sees an infinite "typing…" indicator in Telegram with no way to stop it short of restarting the gateway.

Root cause: the cancelled task's finally block (which normally calls _stop_typing_task) may never run when the task is wedged in C-level blocking I/O. The _keep_typing asyncio task continues its 2-second refresh cycle forever.

Fix

In cancel_session_processing, when the task refuses to unwind within the 5s window, proactively call interrupt_session_activity(session_key, chat_id). This does two things:

  1. Sets the interrupt event_keep_typing checks stop_event.is_set() on each tick, so it exits within 2 seconds
  2. Calls stop_typing on the adapter — platform-level cleanup (relevant for platforms with persistent typing loops like Discord/Slack)

Also passes chat_id through the existing call site in _handle_slash_command so command-initiated session cancels (/new, /reset, etc.) get this cleanup too.

Changes

  • gateway/platforms/base.pycancel_session_processing: +21 lines
    • New optional chat_id parameter (backward compatible, defaults to None)
    • On 5s timeout, calls interrupt_session_activity if chat_id is provided
    • Existing call site in _handle_slash_command passes event.source.chat_id

Testing

  • Tested locally on macOS with Telegram supergroup — typing indicator now clears within 2s of gateway inactivity timeout
  • Backward compatible — existing callers without chat_id behave identically
  • No new dependencies or config changes required

…ives up

When a background task is stuck in blocking I/O (e.g. a hung tool call),
cancel_session_processing waits 5s then unblocks dispatch — but the
_keep_typing refresh loop kept running, leaving an infinite 'typing…'
bubble on Telegram and other platforms.

Now, when the task refuses to unwind within the 5s window, proactively
call interrupt_session_activity — which sets the interrupt_event (so
_keep_typing exits on its next tick) and invokes stop_typing on the
adapter.

Also: pass chat_id through the existing call site in
_handle_slash_command to enable this cleanup on command-initiated
session cancels.
@alt-glitch alt-glitch added type/bug Something isn't working comp/gateway Gateway runner, session dispatch, delivery P2 Medium — degraded but workaround exists labels May 6, 2026
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for tracing the orphaned typing-loop failure mode. The timeout cleanup gap still exists on current main (gateway/platforms/base.py:4471-4476), but this patch needs adaptation to the current session-handoff ownership.

Problems

  • _dispatch_active_session_command replaces _active_sessions[session_key] with command_guard before calling cancellation (gateway/platforms/base.py:4533-4535, :4568-4572). The original processing task already captured the prior event for _keep_typing (:4825, :4840-4846), while interrupt_session_activity reads the current map entry (:3911-3913). The proposed call would therefore set command_guard, not the event that stops the old typing loop.
  • No test covers this timeout plus command-guard handoff. The existing event test is isolated (tests/gateway/test_run_progress_topics.py:1332-1354).

Suggested changes

  • Preserve/pass the old processing event into the timeout cleanup and set that event directly.
  • Add a regression test for a non-unwinding task during /stop, /new, or /reset, asserting the original typing task exits and stop_typing runs.

Automated hermes-sweeper review.

@teknium1 teknium1 added sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 13, 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 sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-message-delivery Sweeper risk: may drop, duplicate, misroute, or suppress messages sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants