({
agentId,
prompt,
toolUseContext,
canUseTool,
invokingRequestId,
}: {
agentId: string
prompt: string
toolUseContext: ToolUseContext
canUseTool: CanUseToolFn
invokingRequestId?: string
})
| 40 | outputFile: string |
| 41 | } |
| 42 | export async function resumeAgentBackground({ |
| 43 | agentId, |
| 44 | prompt, |
| 45 | toolUseContext, |
| 46 | canUseTool, |
| 47 | invokingRequestId, |
| 48 | }: { |
| 49 | agentId: string |
| 50 | prompt: string |
| 51 | toolUseContext: ToolUseContext |
| 52 | canUseTool: CanUseToolFn |
| 53 | invokingRequestId?: string |
| 54 | }): Promise<ResumeAgentResult> { |
| 55 | const startTime = Date.now() |
| 56 | const appState = toolUseContext.getAppState() |
| 57 | // In-process teammates get a no-op setAppState; setAppStateForTasks |
| 58 | // reaches the root store so task registration/progress/kill stay visible. |
| 59 | const rootSetAppState = |
| 60 | toolUseContext.setAppStateForTasks ?? toolUseContext.setAppState |
| 61 | const permissionMode = appState.toolPermissionContext.mode |
| 62 | |
| 63 | const [transcript, meta] = await Promise.all([ |
| 64 | getAgentTranscript(asAgentId(agentId)), |
| 65 | readAgentMetadata(asAgentId(agentId)), |
| 66 | ]) |
| 67 | if (!transcript) { |
| 68 | throw new Error(`No transcript found for agent ID: ${agentId}`) |
| 69 | } |
| 70 | const resumedMessages = filterWhitespaceOnlyAssistantMessages( |
| 71 | filterOrphanedThinkingOnlyMessages( |
| 72 | filterUnresolvedToolUses(transcript.messages), |
| 73 | ), |
| 74 | ) |
| 75 | const resumedReplacementState = reconstructForSubagentResume( |
| 76 | toolUseContext.contentReplacementState, |
| 77 | resumedMessages, |
| 78 | transcript.contentReplacements, |
| 79 | ) |
| 80 | // Best-effort: if the original worktree was removed externally, fall back |
| 81 | // to parent cwd rather than crashing on chdir later. |
| 82 | const resumedWorktreePath = meta?.worktreePath |
| 83 | ? await fsp.stat(meta.worktreePath).then( |
| 84 | s => (s.isDirectory() ? meta.worktreePath : undefined), |
| 85 | () => { |
| 86 | logForDebugging( |
| 87 | `Resumed worktree ${meta.worktreePath} no longer exists; falling back to parent cwd`, |
| 88 | ) |
| 89 | return undefined |
| 90 | }, |
| 91 | ) |
| 92 | : undefined |
| 93 | if (resumedWorktreePath) { |
| 94 | // Bump mtime so stale-worktree cleanup doesn't delete a just-resumed worktree (#22355) |
| 95 | const now = new Date() |
| 96 | await fsp.utimes(resumedWorktreePath, now, now) |
| 97 | } |
| 98 | |
| 99 | // Skip filterDeniedAgents re-gating — original spawn already passed permission checks |
no test coverage detected