The extension emits the literal event string "system.heartbeat";
assert the daemon-side serde name serialises to the same value and
round-trips from the exact frame shape the extension sends, so a
future rename cannot silently break keepalive and liveness.
Co-authored-by: Cursor <cursoragent@cursor.com>
Introduce a `system.heartbeat` protocol event and use it as a
liveness signal on the daemon side.
- Track `last_seen` per connected browser, bumped on every inbound
WS frame (tool response, event, ping/pong, or heartbeat).
- Add a reaper task that drops any browser silent past a 60s window
and purges its sessions, mirroring the WS disconnect cleanup. This
releases half-open connections left behind when the OS resumes from
sleep and kills the service worker without delivering a close frame,
so the daemon no longer pins a phantom "connected" browser and can
idle-exit normally.
- Wire the reaper into both the foreground daemon and the test/embed
entry point, aborting it on shutdown.
Co-authored-by: Cursor <cursoragent@cursor.com>