fix: preserve session state on session expiration, abort, and compaction (Fixes #1054) - #1055
Conversation
|
Thanks for the detailed root-cause writeup — this is a well-documented PR and the instinct (sync
Overall the direction is right but this needs a regression test demonstrating the fixed behavior, and ideally splitting the prompt-text change into its own PR. |
…erruption and compaction
87d92b8 to
f1418c3
Compare
|
Thanks for the thoughtful review and constructive feedback. I've addressed all four points in the latest commit ( 1. Regression Tests (
|
Fixes #1054
Summary
Fixes an issue where sending a message (such as "continue") after a free session expires or after interrupting with
Esccauses the assistant to lose all conversation memory and restart exploration from scratch.Root Cause
Missing in-memory state update on errors / session expiration (
use-send-message.ts):When a free session ends or fails with a gate error, the
catch (error)block inuse-send-message.tscallssaveChatStateto persist the snapshot to disk, but does not updatepreviousRunStateRef.currentin React memory. When the user sends a follow-up prompt in the same running session,sendMessagereads the un-syncedpreviousRunStateRef.current, causingsdk/src/run.tsto instantiate a blankinitialSessionState(messageHistory = []).Abort race condition (
use-send-message.ts):When a user interrupts with
Esc, the UI input lock was released beforeclient.run()finished resolving without synchronously assigningpreviousRunStateRef.current = latestRunStateSnapshot.Compaction continuation guidance (
compact-history.ts,context-pruner.ts):When deterministic compaction runs, the history is collapsed into a synthetic summary. Because the system prompt retains
# Initial Git Changes, models seeing 0 assistant turns occasionally re-ran exploratory git diff and tree commands.Changes
cli/src/hooks/use-send-message.ts:previousRunStateRef.current = latestRunStateSnapshotandsetRunState(latestRunStateSnapshot)insideregisterActiveRunupon abort.previousRunStateRef.current = latestRunStateSnapshotandsetRunState(latestRunStateSnapshot)in thecatch (error)block alongsidesaveChatState.cli/src/hooks/helpers/send-message.ts:packages/agent-runtime/src/compact-history.ts&agents/context-pruner.ts:CONTINUATION_TEXT(in 100% parity) to instruct models that initial repository exploration is already recorded in<historical_memory>.Verification
bun test sdk/src/__tests__/run-cancellation.test.ts(16 passed)bun test cli/src/utils/__tests__/run-state-storage.test.ts(37 passed)bun test packages/agent-runtime/src/__tests__/compact-history.test.ts(31 passed)packages/agent-runtime/src/__tests__/context-pruner-parity.test.ts(13 passed)agents/__tests__/context-pruner.test.ts(69 passed)bun run build:sdkandbun run build:freebuffboth compile with exit code 0.