Files
agent-desk-ng/docs/fixes/chat-realtime-recovery.md
mono 299ea50fb5 fix: recover chat replies and organize setup navigation [skip ci]
Targeted source-only patch from reviewed local e370485. Adds bounded realtime/catch-up recovery and moves the setup wizard under System. Static checks only; regression tests, full build and runtime verification have not been run. No deployment. Separate hardening-review branch is not merged. Expected tree: 6235478b9a.
2026-10-16 13:43:41 +00:00

3.5 KiB

Support chat realtime recovery

This targeted change is based on canonical Gitea main snapshot e57610a27c556e005b9b3b68115477ba1fdd3f1b (tree 9cf938c2498ce6b63faaad7cf8b286c1cfe7a5ef). It does not import the separate hardening-review branch.

Report and source findings

The reported scenario is opening a new chat from a previous one: sending works, but replies appear only after a page reload. Source inspection does not prove why the deployed WebSocket fails. The deployed version, reverse proxy, browser handshake and network have not been observed or tested for this report.

The source does establish these recovery gaps:

  • A socket in CONNECTING has no deadline; subsequent create/select/send paths see it and return without starting a replacement.
  • HTTP fallback checks end after 1.5, 3.5 and 7 seconds, so a later reply is not retrieved while realtime remains unavailable.
  • Reusing an open socket on create/select bypasses the shared status repair path.
  • Initial history failure prevents bootstrap/retry from starting realtime.
  • A replaced socket's late close can clear the current heartbeat/subscription bookkeeping. A late close-conversation response can affect a newer selection.

Changes

  • Bound connection/authentication attempts to 15 seconds, invalidate abandoned attempts, and retry using the existing exponential reconnect policy.
  • Ignore close events from replaced sockets before touching current state.
  • Route new/selected chats through the existing subscription/connection helper.
  • Fetch late replies every 5 seconds only while the chat is open, visible, has an active nonclosed conversation, and realtime is not connected. Never label HTTP fallback as an online WebSocket.
  • Keep latest-message refresh single-flight with a 15-second abort deadline. Cancel previous-view requests and fence their completion before starting a new one. Ignore stale identity/view results, stop recovery on connection, hiding, close or teardown, and recover on focus, visibility or network return. Background recovery failures remain quiet. The optional API AbortSignal is backward-compatible with existing history/pagination callers.
  • Connect independently of initial HTTP history success and merge history so it cannot remove a reply already delivered by realtime.
  • Restrict a close response to the conversation it actually closed.

No backend, SDK bundle, credentials, database, deployment configuration or production data is changed.

Validation status

Completed static checks only:

  • git diff --check.
  • Isolated strict TypeScript compile of web/lib/realtime-connection.ts using an already installed TypeScript 6.0.3 compiler.
  • TypeScript syntax/transpile diagnostics for the four changed production files.
  • JavaScript syntax checks for the two focused regression files.

Added offline mock regressions for delayed replies beyond seven seconds, moving from a previous chat, resubscription, stuck handshakes, late authentication and socket close events, hidden/unmounted lifecycle, single-flight fallback, identity/view changes, abort deadlines, stalled previous-view fetches, history failures and late close responses.

The regression tests have not been executed. Full project typecheck, lint, build and browser/runtime validation have not been run; permission for tests, installation and runtime verification remains pending. No services were started, real support messages sent, or deployment performed. Do not describe this source patch as a verified production fix.