Web Active Sessions Integration Guide
This page explains two things:
- How the desktop frontend currently discovers active sessions.
- How the web frontend can provide the same behavior using the existing backend API.
Goal
We want the web app to behave like the desktop app:
- while a session is running, show it in the sidebar automatically
- refresh the sidebar when the session ends
- let the user jump back into the live session from the sidebar
- keep
last_indexso resumed streaming continues from the right position
Backend Contract
The backend already exposes:
- route:
GET /api/stream/active_sessions - response:
text/event-stream - event format: each push is
data: <json>\n\n
Implementation lives in app/server/routers/chat.py.
Important behavior:
- the connection sends a full snapshot immediately after connect
- the full snapshot is pushed again when the active session list changes
- the client should treat each snapshot as the source of truth
Desktop Behavior
The desktop implementation is split into four layers:
- Sidebar mount starts the subscription.
- A shared cache keeps
activeSessions, offsets, and the SSE source. - Native
EventSourceis used. - The sidebar only renders and routes to the session.
That design keeps the sidebar live as long as the UI shell is present.
Web Difference
The main web difference is authentication.
The web request layer adds a bearer token header automatically, but browser-native EventSource cannot add custom headers. For this reason, the web side should use a streamed fetch-style reader and parse SSE manually.
Recommended Web Layout
1. API layer
Create a subscribeActiveSessions helper in:
app/server/web/src/api/chat.js
It should:
- call the existing authenticated streaming request helper
- parse
data:lines from the SSE stream - expose a lightweight
onmessage/onerror/close()interface
2. State layer
Keep a shared cache for:
activeSessionssessionStreamOffsetssseSourcesubscriberCount
When a snapshot arrives:
- normalize records for the UI
- preserve existing
last_index - mark missing live sessions as completed
- update local storage
- notify the UI with a custom event
3. Lifecycle layer
The most important integration point is where the SSE subscription starts.
If the subscription only lives inside the Chat page, it stops when the user leaves the page. If it lives in the sidebar shell, the list stays fresh as long as the app is open.
4. Sidebar layer
The sidebar should only:
- render the active session list
- sort by
lastUpdate - show status
- route into
Chat?session_id=...
Suggested Product Behavior
- start the subscription when the app shell loads
- keep it alive while the app is open
- treat the active session list as a real-time sidebar index