Skip to content

fix: recover agent threads after laptop sleep instead of erroring - #56

Merged
vedranjukic merged 1 commit into
mainfrom
fix/sleep-reconnect-recovery
Apr 14, 2026
Merged

vedranjukic merged 1 commit into
mainfrom
fix/sleep-reconnect-recovery

Conversation

@vedranjukic

Copy link
Copy Markdown
Owner

Summary

After laptop sleep, running agent threads would show "Error connecting to bridge" or "Agent stopped responding after 90 seconds" even though the agent was still alive in the sandbox. This happened because:

  1. Stale timers from before sleep fire immediately on wake
  2. The bridge WebSocket died during sleep, so health checks fail
  3. Activity timeouts fire as expired, marking the thread as error

Three changes fix this:

  • Activity timeout recovery: Before erroring, attempts to reconnect the bridge and request replay. If the bridge is reachable (common — it just needs a new WebSocket), recovers the thread with replay instead of failing.
  • Grace timer deferral: On reconnect failure, silently cleans up the handler instead of marking the thread as error. Recovery is deferred to reconcileAndReconnect on the next subscribe_project.
  • Stale handler cleanup: reconcileAndReconnect now cleans up all stale active handlers and their timers before reconnecting, preventing ghost timeouts from the pre-sleep session.

Test plan

  • Start an agent run, close laptop lid for 2+ minutes, reopen — thread should recover (not error)
  • Start an agent run, disconnect WiFi for 60s, reconnect — thread should recover
  • Verify normal timeouts still work (kill the bridge process manually — should eventually error after retry)
  • Verify reconcileAndReconnect properly restores running threads after sleep

Made with Cursor

After laptop sleep, stale timers fire immediately and mark running
threads as error even though the agent is still alive in the sandbox.
Three changes prevent this:

1. Activity timeout: before erroring, attempts to reconnect the bridge
   and request replay. If the bridge is reachable, recovers the thread
   instead of marking it as failed.

2. Grace timer: on reconnect failure, silently cleans up the handler
   instead of marking the thread as error. Recovery is deferred to the
   next subscribe_project via reconcileAndReconnect.

3. reconcileAndReconnect: cleans up all stale active handlers and their
   timers for the project's threads before reconnecting. This prevents
   ghost timeouts from the pre-sleep session from firing during recovery.

Made-with: Cursor
@vedranjukic
vedranjukic merged commit 9a5e6ea into main Apr 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant