From f657af1ec0e8813d64d055a7d4c8eb50b6916f38 Mon Sep 17 00:00:00 2001 From: Auto-Fix-Bugs Bot Date: Wed, 15 Jul 2026 10:33:58 +0000 Subject: [PATCH 1/2] fix(tui_gateway): route async delegation completions via parent_session_id when session_key is unset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When delegate_task is dispatched from a CLI/Desktop session that lacks an explicit session_key ContextVar, the completion event arrives with an empty session_key — causing _session_owns_notification_event() to return False and the result to be silently dropped as an orphan. Since parent_session_id (the agent's durable state.db session_id) is always captured at dispatch time, use it as a routing fallback when session_key is empty. The TUI session's lookup key resolves to the same agent.session_id, so the event correctly reaches its originating session. Fixes #64901 --- tui_gateway/server.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 83c79975e2ae0..7f1a77786b0b6 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -8648,7 +8648,13 @@ def _session_owns_notification_event(sid: str, session: dict, evt: dict) -> bool return True evt_key = str(evt.get("session_key") or "") if not evt_key: - return False + # Fall back to parent_session_id for CLI/Desktop sessions where the + # session_key ContextVar may not be bound at dispatch time — the + # parent_session_id (the agent's durable state.db session_id) is + # always captured and links back to this session's lookup key. + evt_key = str(evt.get("parent_session_id") or "") + if not evt_key: + return False current_keys = { str(session.get("session_key") or ""), _session_lookup_key(session, fallback=sid), From 7da3205d7e1378e1a6e4d2f25c18a2a37b8cc036 Mon Sep 17 00:00:00 2001 From: Auto-Fix-Bugs Bot Date: Wed, 15 Jul 2026 10:35:18 +0000 Subject: [PATCH 2/2] fix(discord): add timeout to typing indicator HTTP request to prevent stuck loop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The _typing_loop makes a raw HTTP request to Discord's typing endpoint with no timeout. If the request hangs (network blip, Discord API stall), the task gets stuck forever — stop_typing blocks awaiting the stuck task and the typing indicator never clears. Wrap the request with asyncio.wait_for(..., timeout=10) so a hung call raises asyncio.TimeoutError, which the existing except Exception handler catches and logs cleanly. Fixes #64874 --- plugins/platforms/discord/adapter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/platforms/discord/adapter.py b/plugins/platforms/discord/adapter.py index b216ef29d8eac..774ac730ad780 100644 --- a/plugins/platforms/discord/adapter.py +++ b/plugins/platforms/discord/adapter.py @@ -3845,7 +3845,9 @@ async def _typing_loop() -> None: "POST", "/channels/{channel_id}/typing", channel_id=chat_id, ) - await self._client.http.request(route) + await asyncio.wait_for( + self._client.http.request(route), timeout=10 + ) except asyncio.CancelledError: return except Exception as e: