feat(ws): backend heartbeat in WebSocketCommunicator + useWebSocketReconnect React hook - #634
Open
AseemPrasad wants to merge 4 commits into
Open
feat(ws): backend heartbeat in WebSocketCommunicator + useWebSocketReconnect React hook #634AseemPrasad wants to merge 4 commits into
AseemPrasad wants to merge 4 commits into
Conversation
…red output mode Adds three inter-related improvements to the agentic tool-call runtime, all gated behind the new AGENT_STRUCTURED_OUTPUT opt-in flag.
…connect React hook
Author
|
@abi |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Backend: backend/routes/generate_code.py
The WebSocketCommunicator class now maintains a keepalive heartbeat for every active WebSocket connection:
timeout commonly enforced by corporate proxies, ensuring the connection is kept alive before the proxy kills
it.
before any user code runs.
empty frame exercises the TCP connection (triggering a TCP keepalive probe at the transport layer) without
adding protocol-level noise. When Starlette is upgraded to ≥ 0.40 (which exposes a real websocket.ping()
API), the implementation should switch to that.
repeated inline cancellation logic that was duplicated across close() and throw_error().
the heartbeat task is cancelled on normal shutdown.
heartbeat is cancelled even on the error path.
The heartbeat is intentionally fire-and-forget from the pipeline's perspective — the pipeline code is
unchanged; the WebSocketCommunicator encapsulates the lifecycle.
────────────────────────────────────────────────────────────────────────────────
Frontend: frontend/src/lib/useWebSocketReconnect.ts (new file)
A general-purpose React hook for WebSocket connections that need automatic reconnection:
API surface:
status — one of "disconnected" | "connecting" | "connected". Callers can use this to render a "Reconnecting…"
banner or disable the send button.
send(data) — wraps JSON.stringify and sends only when readyState === OPEN. Safe to call in any render phase; a
no-op when the socket is not open.
reconnect() — tears down the current socket and retries immediately. Intended for use by a "Retry now" UI
button after all automatic retries are exhausted.
disconnect() — permanently closes the socket and stops all timers. Use this when the user navigates away or
explicitly cancels a generation.
Reconnection strategy:
onDisconnect / onConnect callbacks allow the host component to persist generation state (prompt, file content)
before retrying — a prerequisite for the state-resume feature (tracked separately in PR 5's backlog).
────────────────────────────────────────────────────────────────────────────────
What Is NOT Included in This PR
The following were in the original PR 5 proposal and are intentionally deferred to a follow-up:
State resume protocol — Persisting and replaying file_state, prompt_messages, and variant_index across
reconnects requires a protocol extension ("resumeState" message type) and agent snapshot logic. The
useWebSocketReconnect hook is designed to call resumeState once the protocol is defined.
Frontend integration — Wiring useWebSocketReconnect into the main generateCode flow requires careful
coordination with the existing project-store state machine. That integration is safer to do as a dedicated
follow-up PR once the heartbeat-only changes have been in production.
Frontend reconnection UI — A "Connection lost — retrying (3/10)…" banner and "Give up" / "Retry now"
controls are deferred to the integration PR.
────────────────────────────────────────────────────────────────────────────────
Rollout Notes
heartbeat is invisible to the client.
free. Set SCREENSHOT_CACHE_ENABLED=0 in .env to disable.
explicitly use it.
────────────────────────────────────────────────────────────────────────────────
Files Changed
┌──────────────────────────────────────────┬─────────────────────────────────────────────────────────────────┐
│ File │ Change │
├──────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ backend/routes/generate_code.py │ WebSocketCommunicator heartbeat (accept/close/throw_error │
│ │ paths) │
├──────────────────────────────────────────┼─────────────────────────────────────────────────────────────────┤
│ frontend/src/lib/useWebSocketReconnect.t │ New — reconnect hook with back-off, status, │
│ s │ send/reconnect/disconnect │
└──────────────────────────────────────────┴─────────────────────────────────────────────────────────────────┘