@@ -370,15 +370,22 @@ export async function prepareCliRunContext(
|
370 | 370 | bundleMcpEnabled && mcpLoopbackRuntime |
371 | 371 | ? hashCliSessionText(JSON.stringify(promptTools.map((tool) => tool.name).toSorted())) |
372 | 372 | : undefined; |
373 | | -// Pre-flight: if a saved Claude CLI sessionId points at a transcript that no |
374 | | -// longer exists on disk (e.g. update.run aborted mid-swap, Claude CLI was |
375 | | -// reinstalled, or the projects tree was manually pruned), `claude --resume` |
376 | | -// hangs or fails outside the cli-runner session_expired path. The persisted |
377 | | -// binding then never gets refreshed, causing every subsequent turn to retry |
378 | | -// the same dead sessionId. Drop the binding here so this turn starts fresh |
379 | | -// and the post-run flow writes the new sessionId back via setCliSessionBinding. |
380 | | -const candidateClaudeCliSessionId = |
381 | | -params.cliSessionBinding?.sessionId?.trim() || params.cliSessionId?.trim() || undefined; |
| 373 | +const reusableCliSessionCandidate: CliReusableSession = params.cliSessionBinding |
| 374 | + ? resolveCliSessionReuse({ |
| 375 | +binding: params.cliSessionBinding, |
| 376 | +authProfileId: effectiveAuthProfileId, |
| 377 | + authEpoch, |
| 378 | +authEpochVersion: CLI_AUTH_EPOCH_VERSION, |
| 379 | + extraSystemPromptHash, |
| 380 | + promptToolNamesHash, |
| 381 | + cwdHash, |
| 382 | +mcpConfigHash: preparedBackendFinal.mcpConfigHash, |
| 383 | +mcpResumeHash: preparedBackendFinal.mcpResumeHash, |
| 384 | +}) |
| 385 | + : params.cliSessionId |
| 386 | + ? { sessionId: params.cliSessionId } |
| 387 | + : {}; |
| 388 | +const candidateClaudeCliSessionId = reusableCliSessionCandidate.sessionId?.trim() || undefined; |
382 | 389 | const hasClaudeCliCandidate = |
383 | 390 | candidateClaudeCliSessionId !== undefined && isClaudeCliProvider(params.provider); |
384 | 391 | const claudeCliTranscriptMissing = |
@@ -402,21 +409,7 @@ export async function prepareCliRunContext(
|
402 | 409 | : undefined; |
403 | 410 | const reusableCliSession: CliReusableSession = claudeCliInvalidatedReason |
404 | 411 | ? { invalidatedReason: claudeCliInvalidatedReason } |
405 | | - : params.cliSessionBinding |
406 | | - ? resolveCliSessionReuse({ |
407 | | -binding: params.cliSessionBinding, |
408 | | -authProfileId: effectiveAuthProfileId, |
409 | | - authEpoch, |
410 | | -authEpochVersion: CLI_AUTH_EPOCH_VERSION, |
411 | | - extraSystemPromptHash, |
412 | | - promptToolNamesHash, |
413 | | - cwdHash, |
414 | | -mcpConfigHash: preparedBackendFinal.mcpConfigHash, |
415 | | -mcpResumeHash: preparedBackendFinal.mcpResumeHash, |
416 | | -}) |
417 | | - : params.cliSessionId |
418 | | - ? { sessionId: params.cliSessionId } |
419 | | - : {}; |
| 412 | + : reusableCliSessionCandidate; |
420 | 413 | if (reusableCliSession.invalidatedReason) { |
421 | 414 | cliBackendLog.info( |
422 | 415 | `cli session reset: provider=${params.provider} reason=${reusableCliSession.invalidatedReason}`, |
|