Skip to content

[FEATURE]: web: connection health surface — stream status, reconnect progress, client/server version mismatch #51860

Open

Description

@afonsoft

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 a lastEventAt timestamp.
  • 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

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

  1. github-actions commented on Sep 28, 2026

    @github-actions
    Contributor

    This issue doesn't fully meet our contributing guidelines.

    What needs to be fixed:

    • The Feature Request template's required verification checkbox confirming that you checked for prior suggestions is missing. Please verify this feature hasn't already been suggested and include the checkbox.

    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.

  2. github-actions commented on Sep 28, 2026

    @github-actions
    Contributor

    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.

  3. afonsoft commented on Sep 28, 2026

    @afonsoft
    Author

    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.

  4. afonsoft commented on Sep 28, 2026

    @afonsoft
    Author
    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 | 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 a lastEventAt timestamp.
    • 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

    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.

  5. github-actions commented on Sep 28, 2026

    @github-actions
    Contributor

    Thanks for updating this issue to use the Feature Request template and include the required verification checkbox.

  6. opencodejr commented on Oct 28, 2026

    @opencodejr
    Contributor

    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:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions