feat(chat): surface failed turns and add error diagnostics to the status report

A turn that OpenCode stopped could end with nothing on screen: the
session.error event was only turned into a sidebar badge, its message was
dropped (the notification expected a different shape than OpenCode sends),
and a send that was accepted but never answered looked the same as success.

- The chat shows what OpenCode reported under the last message while that
  turn is the latest one, and names a user message an idle session has left
  unanswered for five seconds.
- The last 20 session errors are kept in memory and listed in the status
  report (Ctrl/Cmd+Shift+L, also `__opencodeDebug.statusReport()`), next to
  rejected sends, the managed OpenCode process's last error and stderr
  tail, and the OpenCode and desktop log file locations.
- The OpenCode health probe hits /global/health instead of a route that
  does not exist, and probe URLs resolve against the page for web runtimes.
This commit is contained in:
Bohdan Triapitsyn
2026-08-29 23:22:27 +03:00
parent d8e223bf49
commit b18933f19c
21 changed files with 390 additions and 7 deletions
+16
View File
@@ -202,6 +202,22 @@ Rules:
Initial loads use smaller pages on constrained VS Code/mobile surfaces. Prefetch resolves only the initial renderable page; it does not eagerly download older history. The mounted chat timeline requests older pages when its viewport is underfilled or the user scrolls toward history, while mobile uses its explicit load-older action. Timeline caches, pending work, prepend snapshots, and stale checks use runtime + directory + session identity so equal session IDs in different worktrees cannot share lifecycle state. Older pages are fetched through the same loader and merged with optimistic records before publication. The same chronology contract applies in the VS Code webview because it consumes this shared loader and sync store; the extension bridge must transport OpenCode records without introducing its own ID-based ordering.
## Failed-turn diagnostics
A `session.error` event is the only account of a turn OpenCode stopped, and
it can arrive with no assistant message to attach to. `session-error-log.ts`
keeps the last 20 of them in memory (`recordSessionError`, fed from the
event pipeline next to the error notification) and `summarizeOpenCodeError`
reads the `{ name, data: { message } }` payload. The chat shows the newest
error for the open session under its last message while that turn is the
latest one (`SessionErrorNotice`), and also names a user message that an idle
session has left unanswered for five seconds, since an accepted send that
produced neither a message nor an error would otherwise look like nothing
happened. Both buffers — session errors and rejected sends — appear in the
status report (`buildOpenCodeStatusReport`, Ctrl/Cmd+Shift+L or
`__opencodeDebug.statusReport()`) together with the managed OpenCode
process's last error and stderr tail and the expected log file locations.
## Loading diagnostics
Session loading instrumentation is disabled by default. Set `localStorage.openchamber_session_load_perf` to `"1"`, reproduce the interaction, then inspect `window.__openchamberSessionLoadPerformance.events`.