[Hermes][Desktop][hermes-desktop-crash-survivable-turn-progress][2/n] fix(desktop): recover in-flight turn progress after restart - #44339
Conversation
|
Current state after merge-gate sweep:
I attempted the actual merge through |
0aa167b to
4557e8c
Compare
…urn progress after restart Re-authored onto current upstream/main (c9a150d). Persist each session's in-flight turn tail to a localStorage journal and, on resume, fold it back onto the restored transcript so a mid-turn app/renderer crash no longer drops the streaming assistant. - New apps/desktop/src/lib/inflight-turn-journal.ts (+ unit tests): bounded, best-effort journal (persist / read / recover / merge-backend-inflight). - use-session-state-cache: persist the active tail on every state update; clear it on session switch / turn settle. - types/hermes: SessionResumeResponse.inflight/.running + SessionInFlightTurn. - use-session-actions resume: recover local journal + backend inflight AFTER preferredMessages resolves, so recovery COEXISTS with upstream's prefetch-hit lazy-IIFE fast path (no forced always-reconcile). Re-arm busy/streamId/turnStartedAt/sawAssistantPayload only when a tail is recovered; the empty-transcript fail-latch checks pre-recovery messages so an orphan journal entry can't mask a lost transcript. Recovery wiring covered by new headless tests in use-session-actions.test.tsx. Full crash-restart flow still warrants manual QA. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
4557e8c to
bb26e09
Compare
|
Refreshed onto current main as a single-commit re-authoring (the desktop session hooks were refactored since this opened, so the recovery wiring was rebuilt onto Verified headlessly: Verification boundary (manual QA): the true end-to-end packaged-app crash → restart → localStorage-survives → view-repaint can only be exercised in a real Electron run; the wiring and journal logic are unit-verified, but that final layer isn't headlessly testable. |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for rebuilding this onto the refactored desktop session hooks. The recovery gap is real on current main: tui_gateway/server.py:6049-6080 returns live inflight state, while apps/desktop/src/app/session/hooks/use-session-actions/index.ts:549-594 currently ignores it.
Problems
apps/desktop/src/app/session/hooks/use-session-actions/index.ts:92-93applies backend recovery before local recovery, despite the comment at:82-85saying the local journal wins. A backend assistant snapshot causesmergeInFlightMessages()to mark the local tail caught up (apps/desktop/src/lib/inflight-turn-journal.ts:270-280) and clear it. That can drop locally recorded tool progress because the backend snapshot carries only text (tui_gateway/server.py:5156-5169).
Suggested changes
- Resolve an applicable local journal tail before using backend recovery, or use backend recovery only as the fallback when no local tail applies.
- Add a combined-source regression test: local tool tail plus backend assistant text for the same prompt.
The branch is currently conflicting with main, so salvage should also retain current session-switch protections. This is an automated hermes-sweeper review.
| backendInFlight: BackendInFlightTurn | null | undefined, | ||
| keepPending: boolean | ||
| ): InFlightRecoveryResult { | ||
| const backend = mergeBackendInFlightTurn(baseMessages, backendInFlight, { keepPending }) |
There was a problem hiding this comment.
This ordering makes the backend win, not the local journal described above. mergeBackendInFlightTurn() appends an assistant for the matching user; then local recovery sees that assistant after its user, returns caughtUp, and clears the journal. Since the backend snapshot is text-only while the journal can retain tool parts, resolve the local journal first (or use backend only as its fallback) and add a combined-source test.
|
Superseded by #71184, which rebuilds this onto the current split session hooks with the review defects fixed (local-journal-first merge ordering so backend text snapshots can't drop journaled tool progress, plus throttled persistence off the delta-flush hot path). Your journal design carried over largely intact — thanks @OmarB97, credited via Co-authored-by. |
Why
Hermes Desktop can lose visible in-flight turn progress if the app process dies mid-turn. On restart, the persisted session transcript may only contain the initiating user prompt, which makes streamed assistant text and tool progress appear lost even when the turn was actively producing useful output before the crash.
What Changed
inflightresume payloads when present.How To Review
Start with
apps/desktop/src/lib/inflight-turn-journal.ts, then check the resume integration inapps/desktop/src/app/session/hooks/use-session-actions.tsand the central persistence hook inapps/desktop/src/app/session/hooks/use-session-state-cache.ts.Evidence
git diff --check upstream/main...HEADexited rc=0.Verification
npm run test:ui -- src/lib/inflight-turn-journal.test.ts src/app/session/hooks/use-session-state-cache.test.tsx src/app/session/hooks/use-message-stream.test.tsxexited rc=0: 2 files, 10 tests passed.npx eslint src/lib/inflight-turn-journal.ts src/lib/inflight-turn-journal.test.ts src/app/session/hooks/use-session-state-cache.ts src/app/session/hooks/use-session-actions.ts src/types/hermes.tsexited rc=0.npm run typecheckexited rc=0.git diff --check upstream/main...HEADexited rc=0.Risks / Gaps
Accepted no-follow-up rationale: the journal is intentionally local to the desktop renderer and tail-limited, restoring the visible transcript after renderer/app death without mutating model conversation history. Installed-app swap/relaunch verification stays on MeshBoard task
hermes-desktop-crash-survivable-turn-progress-20260611because it requires a safe restart window for active sessions.Collaborators
hermes-desktop-crash-survivable-turn-progress-20260611, implemented and verified the upstream branch on 2026-06-11.