[orchestrator-v2] fix(orchestrator): Resume persisted Claude sessions after provider session recycle#3750
Draft
mwolson wants to merge 1 commit into
Draft
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Claude threads that sit idle for more than 30 minutes fail instantly on the
next message with
transport_error "Claude Agent SDK query failed."(the CLIreports
Session ID ... is already in use). This PR makes the adapter resumethe persisted native session instead of trying to recreate it.
One commit on
fix/claude-session-resume:ClaudeAdapterV2.ts(the fix) andClaudeAdapterV2.test.ts(two new tests). Everything else comes from the basebranch.
Problem and Fix
ProviderSessionManageridle-releases a provider session (30 min default), the adapter's in-memoryopenedNativeThreadsset is lost. The next turn'sopenQuerytherefore opens the native thread with{sessionId}(create semantics,--session-id) instead of{resume}, and the Claude CLI fails fast because the session id already exists on disk.openQuery, treat a persisted provider turn as proof the native session exists:providerTurnOrdinal > 1(computed byProviderTurnStartServiceas max persisted turn ordinal for the provider thread plus 1) forces{resume}alongside the existing in-memory and rollback signals.Edge cases checked: run attempt retries (session created on first attempt),
steering (
steerTurnnever callsopenQuery),thread_startrollback (newprovider thread id resets the ordinal to 1, so create is used for the fresh
native session), mid-thread rollback (
resumeSessionAtalready forcesresume), forks in the same session instance (covered by
openedWithResume),and first-run failures before CLI spawn (no turn persisted, ordinal stays 1).
Validation
vp check: passvp run typecheck: passvp test apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts:14/14 pass, including two new tests (
ClaudeAdapterV2 native session identity) asserting ordinal 1 opens withsessionIdand ordinal 2 openswith
resumestashing the fix and rerunning)
OrchestratorReplayFixtures.integration.test.ts(claude fixtures): passKnown limitations
the native session (or the reverse: session created, persistence failed),
the identity choice can still be wrong on retry. Both traps pre-date this
change (the in-memory set had the same blind spots within a session
instance); this PR keeps the fix minimal and does not add auto-retry
identity flipping.
persisted for the forked thread. If the process restarts between the fork
and the forked thread's first turn, the ordinal is still 1 and
openQuerysends
{sessionId}for an existing native session. The ordinal signaldoes not engage there, so behavior is identical to before this change
(pre-existing hole, found by review; a
forkedFrom-based signal wasrejected because
thread_startrollback preservesforkedFromwhileminting a fresh, uncreated native session id).
Note
Resume persisted Claude sessions on subsequent provider turns in
ClaudeAdapterV2When a provider session is recycled (idle release), the adapter previously opened a new native Claude session on the next turn instead of resuming the existing one.
openSessionnow checksproviderTurnOrdinal > 1as an additional condition to setshouldResume, ensuring the query opens in resume mode for any turn after the first. Tests are added to assert new-session behavior on the first provider turn and resume behavior on subsequent turns.Macroscope summarized 3c8b95b.