Repository navigation
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
A visible connection-health surface in the web UI: stream status, reconnect progress, and client/server version mismatch.
Today, when the event stream is degraded, the UI gives no signal: the stream either works or the app silently goes stale (#39030 family). The client implementation that was merged in #47571 already tracked a connected | connecting | reconnecting status internally — it was just never surfaced, and the code has since been lost in the v2 refactor. The server already sends server.heartbeat every 10s, so the data needed to drive this UI exists on the wire today.
Proposal
A small, persistent status affordance (e.g. header or sidebar footer) showing:
- Stream state:
connected/reconnecting (attempt n, retrying in Xs)/offline, driven by heartbeat age — e.g. degraded if no event (heartbeat counts) within ~3× the 10s heartbeat interval, and alastEventAttimestamp. - Reconnect progress: attempt count, next retry delay, last disconnect reason.
- Version health: the app knows the server version at bootstrap; if the embedded/proxied UI asset version differs from the server's (or the server version changes under an open tab — deploy mid-session), show "client outdated — reload" with a safe reload that preserves the draft prompt.
- Queue feedback: pending/queued prompts while offline, instead of silent loss or apparent hanging.
// state sketch driven by the existing stream
type StreamHealth = {
state: "connected" | "reconnecting" | "offline"
lastEventAt: number // updated on ANY event, incl. server.heartbeat
attempt: number
nextRetryAt?: number
serverVersion?: string // from server.connected or a /health endpoint
clientVersion: string // build-time constant
}Acceptance ideas
- Kill the network mid-session → indicator flips to
reconnecting, counts retries, and the session resyncs on recovery without a manual refresh (depends on the stall watchdog — see the regression report in Mobile browser tab does not reconnect SSE stream after returning from another app #39030 / PR fix(client): detect stalled event streams and resync on foreground #47571 context). - Deploy a new server version with a tab open → non-blocking "update available" affordance.
- No new server work required for v1: everything derives from
server.connected,server.heartbeat, and existing version/config endpoints.
Benefits
Users currently cannot distinguish "session is thinking" from "connection is dead" — which is why stale-UI bug reports keep recurring. An honest status surface turns a whole class of silent failures into observable, self-healing ones.
Related work
| Ref | State | What it reports / fixes |
|---|---|---|
| PR #47571 | merged (lost) | Already tracked connected | connecting | reconnecting internally — the status model this UI would surface. |
| #21716 | closed | SSE stale after laptop sleep/wake with no detection or recovery — the symptom this surface makes visible. |
| #36582 | open issue | TUI: make API failures explicit and actionable — same principle, TUI side. |
| #51291 | open issue | Provider stream can disappear while a tool call stays "running" forever — server-side analogue of invisible liveness. |
| #48622 | open issue | Background auto-update — pairs with the version-mismatch affordance. |
| #41280 | open issue | Concrete instance of bundled UI version mismatch this surface would catch. |
| #47563 | open issue | Heartbeat floods opencode.log at INFO (95GB/34d reported) — if health UI consumes heartbeats, consider demoting their log level too. |
| #51857 / #51858 | open issues | Companion fixes: stall watchdog (live-update staleness) and cache directives (deploy staleness). This surface is what lets users see both working. |
Triage note for maintainers
Recurring stale-UI reports (#39030, #47258, #45860, #21716, #46733) share one property: the failure is invisible. Even after the watchdog lands (#51857), users need to distinguish "thinking" from "disconnected". The data already exists on the wire (server.connected, 10s server.heartbeat) — this is a client-only feature with no server contract change, so it is cheap to ship alongside the watchdog work.
Activity
github-actions commentedon Sep 28, 2026
This issue doesn't fully meet our contributing guidelines.
What needs to be fixed:
Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
If you believe this was flagged incorrectly, please let a maintainer know.
github-actions commentedon Sep 28, 2026
Thanks for updating this feature request. It still needs the required verification checkbox from the Feature Request template confirming you checked for prior suggestions. Please add and check that box after verifying this request has not already been suggested.
afonsoft commentedon Sep 28, 2026
cc @adamdotdevin — feature ask, no server contract change needed.
Priority rationale: every stale-session bug report upstream shares the same invisible failure mode. With #51857's watchdog this surface becomes the difference between 'self-healing' and 'silently frozen' — and it also gives #51858's version pivot a UI to live in. Suggest scheduling right after the watchdog so the reconnect states it exposes are actually real.
afonsoft commentedon Sep 28, 2026
Original issue description (preserved before reformatting to the feature-request template)
Describe the enhancement you want to request
A visible connection-health surface in the web UI: stream status, reconnect progress, and client/server version mismatch.
Today, when the event stream is degraded, the UI gives no signal: the stream either works or the app silently goes stale (#39030 family). The client implementation that was merged in #47571 already tracked a
connected | connecting | reconnectingstatus internally — it was just never surfaced, and the code has since been lost in the v2 refactor. The server already sendsserver.heartbeatevery 10s, so the data needed to drive this UI exists on the wire today.Proposal
A small, persistent status affordance (e.g. header or sidebar footer) showing:
connected/reconnecting (attempt n, retrying in Xs)/offline, driven by heartbeat age — e.g. degraded if no event (heartbeat counts) within ~3× the 10s heartbeat interval, and alastEventAttimestamp.Acceptance ideas
reconnecting, counts retries, and the session resyncs on recovery without a manual refresh (depends on the stall watchdog — see the regression report in Mobile browser tab does not reconnect SSE stream after returning from another app #39030 / PR fix(client): detect stalled event streams and resync on foreground #47571 context).server.connected,server.heartbeat, and existing version/config endpoints.Benefits
Users currently cannot distinguish "session is thinking" from "connection is dead" — which is why stale-UI bug reports keep recurring. An honest status surface turns a whole class of silent failures into observable, self-healing ones.
Related work
connected | connecting | reconnectinginternally — the status model this UI would surface.opencode.logat INFO (95GB/34d reported) — if health UI consumes heartbeats, consider demoting their log level too.Triage note for maintainers
Recurring stale-UI reports (#39030, #47258, #45860, #21716, #46733) share one property: the failure is invisible. Even after the watchdog lands (#51857), users need to distinguish "thinking" from "disconnected". The data already exists on the wire (
server.connected, 10sserver.heartbeat) — this is a client-only feature with no server contract change, so it is cheap to ship alongside the watchdog work.github-actions commentedon Sep 28, 2026
Thanks for updating this issue to use the Feature Request template and include the required verification checkbox.
opencodejr commentedon Oct 28, 2026
Thanks for the detailed proposal! In short, you're asking for a persistent connection-health indicator in the web UI. It would show the stream state (connected / reconnecting with attempt count and retry delay / offline, based on heartbeat age), warn when the client and server versions don't match and offer a reload that keeps the draft prompt, and show prompts queued while offline. That way users can tell a session that's still thinking apart from a dropped connection.
Maintainers will consider it. Related issues you linked that are worth keeping together with this one: