mirror of
https://github.com/alphaXiv/OpenResearch.git
synced 2026-11-11 09:59:34 +08:00
* Surface silently-dropped chat turns (v0.1.86) A sent message could vanish with no response and no error. Evidence from the live DB: user messages persisted with no assistant reply at all — the claude turn loop waits on child events with no watchdog, so a wedged resident child (seen: expired-OAuth refresh hang) spins forever; the user's only recourse, Stop/Escape, aborted the turn task without leaving any trace; and a failed send POST was swallowed by the UI catch. - claude adapter: watchdog the event wait (120s to first event, 30min between events, matching the codex TURN_WATCHDOG), exempting turns held on a pending mcp-gate approval; on trip, kill the child and surface a visible error (next message resumes via --resume). - ChatHost::interrupt_by_user: the Stop/Escape path now persists an 'Interrupted' marker row, so a stopped turn no longer reads as 'orx did nothing'. Internal interrupts (plan resume, deletes) stay silent. - UI: a failed send now renders a local error row instead of silently clearing busy; chat SSE reconnects re-seed sessions/busy and the active transcript (chat frames are edge-only, gap frames are lost). * Address review: verified send-failure surfacing, watchdog guard arm, shared consts - send() catch: restore draft/attachments even when session creation failed; an explicit 'session is busy' rejection always surfaces (that busy is someone else's turn); a network failure probes server-side busy first and undoes the restore when the turn is real. - claude watchdog: permission re-arm is a guard arm that no longer promotes the first-event deadline; error reports minutes on the mid-turn path and the login hint only on the first-event path. - TURN_WATCHDOG hoisted to harness/mod.rs, shared with codex. - interrupt_by_user: timestamp captured before the abort; WirePart::tool constructor (also used by push_error). - Reconnect repair: shared syncSessionList (deletedIds tombstones, contextUsage merge, seenTitles baseline), seedBusy scoped by known ids, transcript reseed retries once via msgGen when a flush raced it. * Guard claude turns against --resume replay output (echo boundary) Folds in (and supersedes) the unmerged daniel/fix-swallowed-messages branch: a --resume respawn can replay prior-session/startup output before touching the new message — fatally a stale result event, which ended the turn instantly with zero parts while the real reply streamed into a dropped channel. --replay-user-messages makes the child echo the submitted message; the turn loop now skips everything before the echo. Review round (2x empirical against claude 2.1.212): echo is byte-exact and stdin-scoped (no history replay, so no same-text false positive); pre-echo lines count as watchdog proof-of-life (API backoff after boot must not be killed at 120s; only total silence keeps the fast wedge budget + login hint); pre-echo system/init harvests the session id for first-turn interrupts; module docs pin the echo contract. * Reconcile deleted sessions on SSE reconnect; repair after a failed first connect Addresses review findings 2 and 3 on PR #139: - A session deleted while SSE was down lost its chat.session.deleted frame for good: syncSessionList removed the sidebar row but left the cached transcript, loadedSessions, activeId, and — via the known- scoped seedBusy merge — a stale busy flag. Now the pre-fetch snapshot of shown sessions is diffed against the authoritative list and every missing id gets the full forgetSession cleanup, before seedBusy so the ghost's flag can't be carried forward. The snapshot is taken before the fetch (a session created mid-flight can't be tombstoned), and the project-change reset clears the snapshot ref synchronously (the old project's rows must not read as deleted under the new one). - 'reconnected' now also fires when the first successful EventSource open follows a FAILED first connect (page loaded while the backend was briefly down) — the initial fetches likely failed too, so the panel repaired itself only on later drops, never on that first recovery. A clean first open still emits nothing. Verified live on the slot-8 dev stack: session row deleted from the DB while the backend was down; on reconnect (same page, no reload) the row, ghost transcript, active selection, and busy flag all clear.