{"repo":"NousResearch/hermes-agent","public_id":"57025","display_label":"cua-driver session timeout and reconnect fixes","summary":"These issues and PRs address cua-driver session startup timeouts, dead session reconnection, and improved error messaging when sessions fail to become ready. Multiple timeout increases and a reconnect mechanism are proposed or discussed.","subsystem":"agent","counts":{"members":4,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":1,"merged_prs":2,"attempt_prs":1},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":58760,"merged_at":"2026-07-05T10:15:50+00:00"},"resolution":{"state":"resolved","by":"pr-58801"},"freshness":{"state":"verified","last_verified_at":"2026-07-05T10:15:50+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.5},"fix_edges":[{"issue_number":47865,"pr_number":58760,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-07-05T10:15:50+00:00"},{"issue_number":57025,"pr_number":58760,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-07-05T10:15:50+00:00"}],"members":[{"kind":"issue","number":57025,"title":"Windows/Desktop computer_use wrapper times out while cua-driver doctor and MCP test pass","url":null,"state":"closed"},{"kind":"pr","number":57034,"title":"fix(computer-use): increase cua-driver session startup timeout from 15s to 30s","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#58760","number":58760}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":58760,"title":"fix(computer-use): raise cua-driver session startup timeout to 30s + phase timing log (salvage #57034)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["tools/computer_use/cua_backend.py"],"fix_hunks":[{"file":"tools/computer_use/cua_backend.py","hunks":["@@ -567,6 +567,7 @@ async def _lifecycle_coro(self) -> None:\n         different task than it was entered in\" warning emitted by the\n         previous _aenter/_aexit split.\n         \"\"\"\n+        import time as _time\n         from mcp import ClientSession, StdioServerParameters\n         from mcp.client.stdio import stdio_client\n         from tools.environments.local import _sanitize_subprocess_env","@@ -574,6 +575,7 @@ async def _lifecycle_coro(self) -> None:\n         # Build the shutdown event on the loop's thread so the asyncio\n         # primitive belongs to the correct loop.\n         self._shutdown_event = asyncio.Event()\n+        _t0 = _time.monotonic()\n \n         try:\n             if not cua_driver_binary_available():","@@ -583,6 +585,7 @@ async def _lifecycle_coro(self) -> None:\n             # the MCP server, instead of hardcoding [\"mcp\"]. Falls back\n             # transparently for older drivers / any discovery failure.\n             command, args = _resolve_mcp_invocation(_CUA_DRIVER_CMD)\n+            _t_manifest = _time.monotonic()\n             params = StdioServerParameters(\n                 command=command,\n                 args=args,","@@ -594,12 +597,20 @@ async def _lifecycle_coro(self) -> None:\n             async with stdio_client(params) as (read, write):\n                 async with ClientSession(read, write) as session:\n                     await session.initialize()\n+                    _t_init = _time.monotonic()\n                     # Populate capabilities + capability_version BEFORE\n                     # exposing the session to callers, so the first\n                     # tool call already sees them.\n                     await self._populate_capabilities(session)\n                     self._session = session\n                     self._ready_event.set()\n+                    logger.info(\n+                        \"cua-driver session ready in %.1fs \"\n+                        \"(manifest=%.1fs, mcp_init=%.1fs)\",\n+                        _time.monotonic() - _t0,\n+                        _t_manifest - _t0,\n+                        _t_init - _t_manifest,\n+                    )\n                     # Hold the contexts open until stop() / restart asks\n                     # us to wind down. Tool calls run as their own tasks\n                     # on the same loop and touch self._session directly.","@@ -677,10 +688,10 @@ def _start_lifecycle_locked(self) -> None:\n         self._lifecycle_future = asyncio.run_coroutine_threadsafe(\n             self._lifecycle_coro(), loop\n         )\n-        if not self._ready_event.wait(timeout=15.0):\n+        if not self._ready_event.wait(timeout=30.0):\n             # Best-effort: signal shutdown if the future is still alive.\n             self._signal_shutdown_locked()\n-            raise RuntimeError(\"cua-driver session never reached ready (timeout 15s)\")\n+            raise RuntimeError(\"cua-driver session never reached ready (timeout 30s)\")\n         # If setup failed, the lifecycle coroutine set _setup_error\n         # before setting _ready_event. Re-raise it on the caller's thread.\n         if self._setup_error is not None:\n"]}]},{"kind":"pr","number":58801,"title":"fix(computer-use): name the wedged startup phase in the session ready-timeout error","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true}],"trust":{"default_tier":"verified","includes_suggested":false}}