Skip to content

Backend: WebSocket endpoint for streaming agent chat (/ws/sessions/{id}/chat) #502

Description

@frankbria

Parent Issue

Part of #500 — depends on #501

Context

The existing /ws WebSocket (in codeframe/ui/routers/websocket.py) handles project-level status broadcasts (subscribe/unsubscribe). This issue adds a dedicated per-session WebSocket endpoint that handles bidirectional chat with a coding agent — receiving user messages and relaying streamed agent tokens back to the browser.

What to Build

New file: codeframe/ui/routers/session_chat_ws.py

New WebSocket endpoint:

WS /ws/sessions/{session_id}/chat?token=<JWT>

Message protocol (client → server):

{ "type": "message", "content": "Add error handling to the auth module" }
{ "type": "interrupt" }
{ "type": "ping" }

Message protocol (server → client):

{ "type": "text_delta", "content": "Sure, I'll " }
{ "type": "text_delta", "content": "add try/except..." }
{ "type": "tool_use_start", "tool_name": "Read", "tool_input": {"file_path": "..."} }
{ "type": "tool_result", "tool_name": "Read", "content": "..." }
{ "type": "thinking", "content": "I need to check..." }
{ "type": "cost_update", "cost_usd": 0.0031, "input_tokens": 1200, "output_tokens": 340 }
{ "type": "done" }
{ "type": "error", "message": "..." }
{ "type": "pong" }

Endpoint logic

  1. Authenticate JWT (same pattern as websocket.py)
  2. Load session from DB — return 4008 if session not found or ended
  3. Accept connection, set session state to active in DB
  4. Start a background task that calls the streaming chat adapter (see issue Backend: WebSocket endpoint for streaming agent chat (/ws/sessions/{id}/chat) #502) and relays token events to the WebSocket
  5. Accept incoming message events and route them to the running adapter
  6. Accept interrupt events and signal the adapter to stop mid-generation
  7. On adapter completion: write cost/token update to DB, send done event
  8. On disconnect or session end: clean up gracefully

File to modify: codeframe/ui/server.py

Register the new router.

Connection manager

Reuse or extend codeframe/ui/shared.py manager pattern to track active session WebSockets so the streaming adapter can push to them.

Acceptance Criteria

  • WebSocket endpoint accepts connections with valid JWT
  • Rejects invalid/expired JWT with close code 1008
  • Rejects connections to non-existent or ended sessions
  • Relays streamed text deltas as individual text_delta events (not buffered to complete)
  • Relays tool use start and result events
  • Accepts interrupt message and stops generation
  • Updates session cost/token counts in DB after each turn
  • Handles client disconnect cleanly (no leaked coroutines)
  • Integration test in tests/api/test_session_chat_ws.py using FastAPI WebSocket test client

Out of Scope

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions