| ... | ... | @@ -88,6 +88,7 @@ interface ClaudeSessionContext { |
| 88 | 88 | readonly promptQueue: Queue.Queue<PromptQueueItem>; |
| 89 | 89 | readonly query: ClaudeQueryRuntime; |
| 90 | 90 | readonly startedAt: string; |
| 91 | resumeSessionId: string | undefined; |
| 91 | 92 | readonly pendingApprovals: Map<ApprovalRequestId, PendingApproval>; |
| 92 | 93 | readonly turns: Array<{ |
| 93 | 94 | id: ReturnType<typeof ProviderTurnId.makeUnsafe>; |
| ... | ... | @@ -115,6 +116,12 @@ export interface ClaudeCodeAdapterLiveOptions { |
| 115 | 116 | }) => ClaudeQueryRuntime; |
| 116 | 117 | } |
| 117 | 118 | |
| 119 | function isUuid(value: string): boolean { |
| 120 | return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test( |
| 121 | value, |
| 122 | ); |
| 123 | } |
| 124 | |
| 118 | 125 | function toMessage(cause: unknown, fallback: string): string { |
| 119 | 126 | if (cause instanceof Error && cause.message.length > 0) { |
| 120 | 127 | return cause.message; |
| ... | ... | @@ -148,12 +155,13 @@ function readClaudeResumeState(resumeCursor: unknown): ClaudeResumeState | undef |
| 148 | 155 | }; |
| 149 | 156 | |
| 150 | 157 | const threadId = typeof cursor.threadId === "string" ? cursor.threadId : undefined; |
| 151 | | const resume = |
| 158 | const resumeCandidate = |
| 152 | 159 | typeof cursor.resume === "string" |
| 153 | 160 | ? cursor.resume |
| 154 | 161 | : typeof cursor.sessionId === "string" |
| 155 | 162 | ? cursor.sessionId |
| 156 | 163 | : undefined; |
| 164 | const resume = resumeCandidate && isUuid(resumeCandidate) ? resumeCandidate : undefined; |
| 157 | 165 | const resumeSessionAt = |
| 158 | 166 | typeof cursor.resumeSessionAt === "string" ? cursor.resumeSessionAt : undefined; |
| 159 | 167 | const turnCountValue = typeof cursor.turnCount === "number" ? cursor.turnCount : undefined; |
| ... | ... | @@ -351,7 +359,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { |
| 351 | 359 | |
| 352 | 360 | const resumeCursor = { |
| 353 | 361 | threadId, |
| 354 | | resume: threadId, |
| 362 | ...(context.resumeSessionId ? { resume: context.resumeSessionId } : {}), |
| 355 | 363 | ...(context.lastAssistantUuid ? { resumeSessionAt: context.lastAssistantUuid } : {}), |
| 356 | 364 | turnCount: context.turns.length, |
| 357 | 365 | }; |
| ... | ... | @@ -369,6 +377,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { |
| 369 | 377 | ): Effect.Effect<void> => |
| 370 | 378 | Effect.gen(function* () { |
| 371 | 379 | const nextThreadId = ProviderThreadId.makeUnsafe(message.session_id); |
| 380 | context.resumeSessionId = message.session_id; |
| 372 | 381 | const changed = context.session.threadId !== nextThreadId; |
| 373 | 382 | |
| 374 | 383 | if (changed) { |
| ... | ... | @@ -935,7 +944,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { |
| 935 | 944 | threadId, |
| 936 | 945 | resumeCursor: { |
| 937 | 946 | threadId, |
| 938 | | resume: resumeState?.resume ?? threadId, |
| 947 | ...(resumeState?.resume ? { resume: resumeState.resume } : {}), |
| 939 | 948 | ...(resumeState?.resumeSessionAt |
| 940 | 949 | ? { resumeSessionAt: resumeState.resumeSessionAt } |
| 941 | 950 | : {}), |
| ... | ... | @@ -950,6 +959,7 @@ function makeClaudeCodeAdapter(options?: ClaudeCodeAdapterLiveOptions) { |
| 950 | 959 | promptQueue, |
| 951 | 960 | query: queryRuntime, |
| 952 | 961 | startedAt, |
| 962 | resumeSessionId: resumeState?.resume, |
| 953 | 963 | pendingApprovals, |
| 954 | 964 | turns: [], |
| 955 | 965 | inFlightTools, |