fix(gateway): stop stale Telegram typing refreshes - #29919
Conversation
Give each typing loop a per-chat generation lease so stale tasks cannot keep refreshing chat actions after cleanup or newer turns take ownership. Avoid re-triggering Telegram typing after final notified responses while preserving progress-message typing refreshes.
|
I ran into the same failure mode on a local macOS gateway and did a small health check against current Observed symptom:
That made it look like an orphaned typing refresh loop rather than an active agent. Current This PR’s generation lease approach looks like the right direction for that class of bug. One extra regression that may be worth adding is the dynamic case where the typing loop starts as the current owner, then loses ownership while it is sleeping: @pytest.mark.asyncio
async def test_invalidated_typing_generation_stops_running_loop(monkeypatch):
adapter = _StubAdapter()
calls = []
async def recording_send_typing(chat_id, metadata=None):
calls.append(chat_id)
monkeypatch.setattr(adapter, "send_typing", recording_send_typing)
adapter.stop_typing = MagicMock(return_value=asyncio.sleep(0))
adapter._typing_generations["chat"] = 1
task = asyncio.create_task(
adapter._keep_typing(
chat_id="chat",
interval=0.2,
typing_generation=1,
)
)
await asyncio.sleep(0.45)
assert calls
adapter._typing_generations["chat"] = 2
await asyncio.wait_for(task, timeout=1.0)
calls_after_exit = len(calls)
await asyncio.sleep(0.4)
assert len(calls) == calls_after_exitAs a cross-check, I tested an alternative minimal session-guard ownership patch on top of python -m pytest \
tests/gateway/test_keep_typing_timeout.py \
tests/gateway/test_pending_drain_no_recursion.py \
tests/gateway/test_pending_drain_race.py \
tests/gateway/test_session_split_brain_11016.py \
-qResult: So the issue is reproducible as an upstream typing lifecycle gap, and this PR appears to target the right area. I would mainly suggest making sure the test coverage includes a typing loop that becomes stale after it has already started, not only one that is stale before the first refresh. |
|
Thanks for this. A fix for the post-delivery typing-stop boundary in This PR overlaps that area but also touches paths #37556 didn't (e.g. the stream-consumer / final-delivery path), so I'm not closing it — could you rebase on current |
|
Thanks for the focused typing-lifecycle work. Automated hermes-sweeper review found that the requested behavior is now implemented on
The later mainline implementation covers the PR's final-response and stale-refresh guarantees, so this is redundant. |
Summary
_keep_typingloops exit before refreshing platform typing indicatorsTest Plan
./venv/bin/python -m pytest tests/gateway/test_keep_typing_timeout.py tests/gateway/test_telegram_thread_fallback.py tests/gateway/test_telegram_network.py tests/gateway/test_telegram_noise_filter.py -qNotes
This addresses cases where Telegram can keep showing typing after the final response because a stale keep-typing task survived cleanup or because
send()refreshed typing after the final notified response.