{"version":3,"file":"async-resume.d.ts","sourceRoot":"","sources":["../../../../src/runs/background/async-resume.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAwB,KAAK,WAAW,EAAQ,KAAK,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEtH,OAAO,EAGN,KAAK,iCAAiC,EACtC,MAAM,iCAAiC,CAAC;AAKzC,MAAM,WAAW,iBAAiB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,eAAe;IAC/B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,OAAO,CAAC;IAC7D,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,kBAAkB;IAClC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC/B,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,0BAA0B,CAAC;IAChD,iBAAiB,CAAC,EAAE,iCAAiC,CAAC;IACtD,oBAAoB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AA4BF,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AA0JD,wBAAgB,yBAAyB,CACxC,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAoBnD;AAED,wBAAgB,uBAAuB,CACtC,MAAM,EAAE,iBAAiB,EACzB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAChB,gBAAgB,CAkClB;AAuED,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,0BAA0B,GAAG,SAAS,CA4OhH;AAUD,wBAAgB,wBAAwB,CACvC,MAAM,EAAE,iBAAiB,EACzB,IAAI,GAAE,eAAoB,EAC1B,OAAO,GAAE,kBAAuB,GAC9B,iBAAiB,CAuKnB;AAED,wBAAgB,gCAAgC,CAC/C,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,0BAA0B,GACpC,WAAW,CAuBb;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAexF","sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { AgentConfig } from \"../../agents/agents.ts\";\nimport { type AcceptanceInput, type AsyncStatus, DIRS, type SteeringRecoveryDescriptor } from \"../../shared/types.ts\";\nimport { validateAcceptanceInput } from \"../shared/acceptance.ts\";\nimport {\n\tintersectSubagentCapabilityCeilings,\n\tparseSubagentCapabilityCeiling,\n\ttype ResolvedSubagentCapabilityCeiling,\n} from \"../shared/capability-ceiling.ts\";\nimport { validateToolBudgetConfig } from \"../shared/tool-budget.ts\";\nimport { resolveTurnBudgetConfig } from \"../shared/turn-budget.ts\";\nimport { reconcileAsyncRun } from \"./stale-run-reconciler.ts\";\n\nexport interface AsyncResumeParams {\n\tid?: string;\n\trunId?: string;\n\tdir?: string;\n\tindex?: number;\n}\n\nexport interface AsyncResumeDeps {\n\tasyncDirRoot?: string;\n\tresultsDir?: string;\n\tkill?: (pid: number, signal?: NodeJS.Signals | 0) => boolean;\n\tnow?: () => number;\n}\n\nexport interface AsyncResumeOptions {\n\trequireSessionFile?: boolean;\n\tsessionId?: string;\n}\n\nexport type AsyncResumeTarget = {\n\tkind: \"live\" | \"revive\";\n\trunId: string;\n\tasyncDir?: string;\n\tstate: AsyncStatus[\"state\"];\n\tagent: string;\n\tindex: number;\n\tcwd?: string;\n\tsessionFile?: string;\n\tmodel?: string;\n\tthinking?: string;\n\trecoveryDescriptor?: SteeringRecoveryDescriptor;\n\tcapabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n\tlaunchContractDigest?: string;\n};\n\ninterface AsyncResultFile {\n\tid?: string;\n\trunId?: string;\n\tagent?: string;\n\tmode?: string;\n\tstate?: string;\n\tsuccess?: boolean;\n\tcwd?: string;\n\tsessionId?: string;\n\tsessionFile?: string;\n\tmodel?: string;\n\tthinking?: string;\n\tlaunchContractDigest?: string;\n\tcapabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n\tresults?: Array<{\n\t\tagent?: string;\n\t\tsuccess?: boolean;\n\t\tsessionFile?: string;\n\t\tintercomTarget?: string;\n\t\tmodel?: string;\n\t\tthinking?: string;\n\t\tlaunchContractDigest?: string;\n\t\tcapabilityCeiling?: ResolvedSubagentCapabilityCeiling;\n\t}>;\n}\n\nexport interface AsyncRunLocation {\n\tasyncDir: string | null;\n\tresultPath: string | null;\n\tresolvedId?: string;\n}\n\nfunction getErrorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction ensureObject(value: unknown, source: string): Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tthrow new Error(`Async result file '${source}' must contain a JSON object.`);\n\t}\n\treturn value as Record<string, unknown>;\n}\n\nfunction validateOptionalString(\n\tvalue: Record<string, unknown>,\n\tfield: string,\n\tsource: string,\n\tdisplayField = field,\n): string | undefined {\n\tconst fieldValue = value[field];\n\tif (fieldValue === undefined) return undefined;\n\tif (typeof fieldValue !== \"string\")\n\t\tthrow new Error(`Invalid async result file '${source}': ${displayField} must be a string.`);\n\treturn fieldValue;\n}\n\nfunction validateResultFile(value: unknown, resultPath: string): AsyncResultFile {\n\tconst data = ensureObject(value, resultPath);\n\tconst resultsValue = data.results;\n\tlet results: AsyncResultFile[\"results\"];\n\tif (resultsValue !== undefined) {\n\t\tif (!Array.isArray(resultsValue))\n\t\t\tthrow new Error(`Invalid async result file '${resultPath}': results must be an array.`);\n\t\tresults = resultsValue.map((entry, index) => {\n\t\t\tconst child = ensureObject(entry, `${resultPath} results[${index}]`);\n\t\t\tconst agent = validateOptionalString(child, \"agent\", resultPath, `results[${index}].agent`);\n\t\t\tconst sessionFile = validateOptionalString(child, \"sessionFile\", resultPath, `results[${index}].sessionFile`);\n\t\t\tconst intercomTarget = validateOptionalString(\n\t\t\t\tchild,\n\t\t\t\t\"intercomTarget\",\n\t\t\t\tresultPath,\n\t\t\t\t`results[${index}].intercomTarget`,\n\t\t\t);\n\t\t\tconst model = validateOptionalString(child, \"model\", resultPath, `results[${index}].model`);\n\t\t\tconst thinking = validateOptionalString(child, \"thinking\", resultPath, `results[${index}].thinking`);\n\t\t\tconst launchContractDigest = validateOptionalString(\n\t\t\t\tchild,\n\t\t\t\t\"launchContractDigest\",\n\t\t\t\tresultPath,\n\t\t\t\t`results[${index}].launchContractDigest`,\n\t\t\t);\n\t\t\tconst capabilityCeiling =\n\t\t\t\tchild.capabilityCeiling === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: parseSubagentCapabilityCeiling(\n\t\t\t\t\t\t\tchild.capabilityCeiling,\n\t\t\t\t\t\t\t`async result file '${resultPath}' results[${index}].capabilityCeiling`,\n\t\t\t\t\t\t);\n\t\t\tconst success = child.success;\n\t\t\tif (success !== undefined && typeof success !== \"boolean\")\n\t\t\t\tthrow new Error(`Invalid async result file '${resultPath}': results[${index}].success must be a boolean.`);\n\t\t\treturn {\n\t\t\t\tagent,\n\t\t\t\tsessionFile,\n\t\t\t\tintercomTarget,\n\t\t\t\tmodel,\n\t\t\t\tthinking,\n\t\t\t\tlaunchContractDigest,\n\t\t\t\t...(capabilityCeiling ? { capabilityCeiling } : {}),\n\t\t\t\t...(typeof success === \"boolean\" ? { success } : {}),\n\t\t\t};\n\t\t});\n\t}\n\tconst success = data.success;\n\tif (success !== undefined && typeof success !== \"boolean\")\n\t\tthrow new Error(`Invalid async result file '${resultPath}': success must be a boolean.`);\n\treturn {\n\t\tid: validateOptionalString(data, \"id\", resultPath),\n\t\trunId: validateOptionalString(data, \"runId\", resultPath),\n\t\tagent: validateOptionalString(data, \"agent\", resultPath),\n\t\tmode: validateOptionalString(data, \"mode\", resultPath),\n\t\tstate: validateOptionalString(data, \"state\", resultPath),\n\t\tcwd: validateOptionalString(data, \"cwd\", resultPath),\n\t\tsessionId: validateOptionalString(data, \"sessionId\", resultPath),\n\t\tsessionFile: validateOptionalString(data, \"sessionFile\", resultPath),\n\t\tmodel: validateOptionalString(data, \"model\", resultPath),\n\t\tthinking: validateOptionalString(data, \"thinking\", resultPath),\n\t\tlaunchContractDigest: validateOptionalString(data, \"launchContractDigest\", resultPath),\n\t\t...(data.capabilityCeiling === undefined\n\t\t\t? {}\n\t\t\t: {\n\t\t\t\t\tcapabilityCeiling: parseSubagentCapabilityCeiling(\n\t\t\t\t\t\tdata.capabilityCeiling,\n\t\t\t\t\t\t`async result file '${resultPath}' capabilityCeiling`,\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t...(typeof success === \"boolean\" ? { success } : {}),\n\t\t...(results ? { results } : {}),\n\t};\n}\n\nfunction readResultFile(resultPath: string): AsyncResultFile {\n\tlet raw: string;\n\ttry {\n\t\traw = fs.readFileSync(resultPath, \"utf-8\");\n\t} catch (error) {\n\t\tthrow new Error(`Failed to read async result file '${resultPath}': ${getErrorMessage(error)}`, {\n\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t});\n\t}\n\ttry {\n\t\treturn validateResultFile(JSON.parse(raw), resultPath);\n\t} catch (error) {\n\t\tif (error instanceof SyntaxError) {\n\t\t\tthrow new Error(`Failed to parse async result file '${resultPath}': ${getErrorMessage(error)}`, {\n\t\t\t\tcause: error,\n\t\t\t});\n\t\t}\n\t\tthrow error;\n\t}\n}\n\nfunction assertRunId(value: string | undefined, field: \"id\" | \"runId\"): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value.trim() === \"\") throw new Error(`${field} must not be empty.`);\n\tif (path.isAbsolute(value) || /[\\\\/]/.test(value) || value.includes(\"..\")) {\n\t\tthrow new Error(`${field} must be an async run id or prefix, not a path.`);\n\t}\n\treturn value;\n}\n\nfunction assertInsideRoot(root: string, target: string, label: string): void {\n\tconst rootPath = path.resolve(root);\n\tconst targetPath = path.resolve(target);\n\tconst relative = path.relative(rootPath, targetPath);\n\tif (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) return;\n\tthrow new Error(`${label} must be inside ${rootPath}.`);\n}\n\nfunction prefixedRunIds(dir: string, prefix: string, suffix = \"\"): string[] {\n\tif (!fs.existsSync(dir)) return [];\n\treturn fs\n\t\t.readdirSync(dir)\n\t\t.filter((entry) => entry.startsWith(prefix) && (!suffix || entry.endsWith(suffix)))\n\t\t.map((entry) => (suffix ? entry.slice(0, -suffix.length) : entry))\n\t\t.sort();\n}\n\nfunction exactResultPath(resultsDir: string, runId: string): string | null {\n\tconst resultPath = path.join(resultsDir, `${runId}.json`);\n\tassertInsideRoot(resultsDir, resultPath, \"Async result file\");\n\treturn fs.existsSync(resultPath) ? resultPath : null;\n}\n\nexport function findAsyncRunPrefixMatches(\n\tprefix: string,\n\tasyncDirRoot: string,\n\tresultsDir: string,\n): Array<{ id: string; location: AsyncRunLocation }> {\n\tconst requestedId = assertRunId(prefix, \"id\");\n\tif (!requestedId) return [];\n\tconst asyncRoot = path.resolve(asyncDirRoot);\n\tconst resultRoot = path.resolve(resultsDir);\n\tconst matchingIds = [\n\t\t...new Set([...prefixedRunIds(asyncRoot, requestedId), ...prefixedRunIds(resultRoot, requestedId, \".json\")]),\n\t].sort();\n\treturn matchingIds.map((id) => {\n\t\tconst asyncDir = path.join(asyncRoot, id);\n\t\tassertInsideRoot(asyncRoot, asyncDir, \"Async run directory\");\n\t\treturn {\n\t\t\tid,\n\t\t\tlocation: {\n\t\t\t\tasyncDir: fs.existsSync(asyncDir) ? asyncDir : null,\n\t\t\t\tresultPath: exactResultPath(resultRoot, id),\n\t\t\t\tresolvedId: id,\n\t\t\t},\n\t\t};\n\t});\n}\n\nexport function resolveAsyncRunLocation(\n\tparams: AsyncResumeParams,\n\tasyncDirRoot: string,\n\tresultsDir: string,\n): AsyncRunLocation {\n\tconst asyncRoot = path.resolve(asyncDirRoot);\n\tconst resultRoot = path.resolve(resultsDir);\n\tconst requestedId = assertRunId(params.id, \"id\") ?? assertRunId(params.runId, \"runId\");\n\tif (params.dir) {\n\t\tconst asyncDir = path.resolve(params.dir);\n\t\tassertInsideRoot(asyncRoot, asyncDir, \"Async run directory\");\n\t\tconst resolvedId = requestedId ?? path.basename(asyncDir);\n\t\tif (requestedId && requestedId !== path.basename(asyncDir)) {\n\t\t\tthrow new Error(`Async run id '${requestedId}' does not match directory '${path.basename(asyncDir)}'.`);\n\t\t}\n\t\treturn { asyncDir, resultPath: exactResultPath(resultRoot, resolvedId), resolvedId };\n\t}\n\tif (!requestedId) return { asyncDir: null, resultPath: null };\n\n\tconst directAsyncDir = path.join(asyncRoot, requestedId);\n\tassertInsideRoot(asyncRoot, directAsyncDir, \"Async run directory\");\n\tconst directResultPath = exactResultPath(resultRoot, requestedId);\n\tif (fs.existsSync(directAsyncDir) || directResultPath) {\n\t\treturn {\n\t\t\tasyncDir: fs.existsSync(directAsyncDir) ? directAsyncDir : null,\n\t\t\tresultPath: directResultPath,\n\t\t\tresolvedId: requestedId,\n\t\t};\n\t}\n\n\tconst matching = findAsyncRunPrefixMatches(requestedId, asyncRoot, resultRoot);\n\tif (matching.length === 0) return { asyncDir: null, resultPath: null, resolvedId: requestedId };\n\tif (matching.length > 1) {\n\t\tthrow new Error(\n\t\t\t`Ambiguous async run id prefix '${requestedId}' matched: ${matching.map((match) => match.id).join(\", \")}. Provide a longer id.`,\n\t\t);\n\t}\n\treturn matching[0]!.location;\n}\n\nfunction resultState(result: AsyncResultFile): AsyncStatus[\"state\"] {\n\tif (\n\t\tresult.state === \"complete\" ||\n\t\tresult.state === \"failed\" ||\n\t\tresult.state === \"paused\" ||\n\t\tresult.state === \"stopped\" ||\n\t\tresult.state === \"running\" ||\n\t\tresult.state === \"queued\"\n\t) {\n\t\treturn result.state;\n\t}\n\treturn result.success ? \"complete\" : \"failed\";\n}\n\nfunction validateStatusForResume(status: AsyncStatus | null, source: string): void {\n\tif (!status) return;\n\tif (typeof status.runId !== \"string\") throw new Error(`Invalid async status '${source}': runId must be a string.`);\n\tif (status.sessionId !== undefined && typeof status.sessionId !== \"string\")\n\t\tthrow new Error(`Invalid async status '${source}': sessionId must be a string.`);\n\tif (status.cwd !== undefined && typeof status.cwd !== \"string\")\n\t\tthrow new Error(`Invalid async status '${source}': cwd must be a string.`);\n\tif (status.sessionFile !== undefined && typeof status.sessionFile !== \"string\")\n\t\tthrow new Error(`Invalid async status '${source}': sessionFile must be a string.`);\n\tif (status.capabilityCeiling !== undefined)\n\t\tstatus.capabilityCeiling = parseSubagentCapabilityCeiling(\n\t\t\tstatus.capabilityCeiling,\n\t\t\t`async status '${source}' capabilityCeiling`,\n\t\t);\n\tif (status.steps !== undefined) {\n\t\tif (!Array.isArray(status.steps)) throw new Error(`Invalid async status '${source}': steps must be an array.`);\n\t\tstatus.steps.forEach((step, index) => {\n\t\t\tif (!step || typeof step !== \"object\" || Array.isArray(step))\n\t\t\t\tthrow new Error(`Invalid async status '${source}': steps[${index}] must be an object.`);\n\t\t\tconst stepRecord = step as Record<string, unknown>;\n\t\t\tif (typeof stepRecord.agent !== \"string\")\n\t\t\t\tthrow new Error(`Invalid async status '${source}': steps[${index}].agent must be a string.`);\n\t\t\tif (stepRecord.sessionFile !== undefined && typeof stepRecord.sessionFile !== \"string\")\n\t\t\t\tthrow new Error(`Invalid async status '${source}': steps[${index}].sessionFile must be a string.`);\n\t\t\tif (stepRecord.model !== undefined && typeof stepRecord.model !== \"string\")\n\t\t\t\tthrow new Error(`Invalid async status '${source}': steps[${index}].model must be a string.`);\n\t\t\tif (stepRecord.thinking !== undefined && typeof stepRecord.thinking !== \"string\")\n\t\t\t\tthrow new Error(`Invalid async status '${source}': steps[${index}].thinking must be a string.`);\n\t\t\tif (stepRecord.launchContractDigest !== undefined && typeof stepRecord.launchContractDigest !== \"string\")\n\t\t\t\tthrow new Error(`Invalid async status '${source}': steps[${index}].launchContractDigest must be a string.`);\n\t\t\tif (stepRecord.capabilityCeiling !== undefined)\n\t\t\t\tstepRecord.capabilityCeiling = parseSubagentCapabilityCeiling(\n\t\t\t\t\tstepRecord.capabilityCeiling,\n\t\t\t\t\t`async status '${source}' steps[${index}].capabilityCeiling`,\n\t\t\t\t);\n\t\t});\n\t}\n}\n\nfunction normalizeRecoveryAcceptance(value: unknown, descriptorPath: string): AcceptanceInput | undefined {\n\tif (\n\t\tvalue &&\n\t\ttypeof value === \"object\" &&\n\t\t!Array.isArray(value) &&\n\t\t(\"explicit\" in value || \"inferredReason\" in value)\n\t) {\n\t\tconst { explicit, inferredReason: _inferredReason, ...publicAcceptance } = value as Record<string, unknown>;\n\t\tif (explicit === false) return undefined;\n\t\tvalue = publicAcceptance;\n\t}\n\tconst errors = validateAcceptanceInput(value, \"recoveryDescriptor.acceptance\");\n\tif (errors.length) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${errors.join(\" \")}`);\n\treturn value as AcceptanceInput;\n}\n\nexport function readAsyncRecoveryDescriptor(asyncDir: string | undefined): SteeringRecoveryDescriptor | undefined {\n\tif (!asyncDir) return undefined;\n\tconst descriptorPath = path.join(asyncDir, \"recovery-descriptor.json\");\n\tif (!fs.existsSync(descriptorPath)) return undefined;\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(fs.readFileSync(descriptorPath, \"utf-8\"));\n\t} catch (error) {\n\t\tthrow new Error(`Failed to parse async recovery descriptor '${descriptorPath}': ${getErrorMessage(error)}`, {\n\t\t\tcause: error instanceof Error ? error : undefined,\n\t\t});\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value))\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': expected an object.`);\n\tconst parsed = value as Record<string, unknown>;\n\tconst allowedFields = new Set([\n\t\t\"version\",\n\t\t\"launchContractDigest\",\n\t\t\"sourceRunId\",\n\t\t\"agentContract\",\n\t\t\"agent\",\n\t\t\"sessionFile\",\n\t\t\"cwd\",\n\t\t\"model\",\n\t\t\"fallbackModels\",\n\t\t\"thinking\",\n\t\t\"tools\",\n\t\t\"extensions\",\n\t\t\"subagentOnlyExtensions\",\n\t\t\"mcpDirectTools\",\n\t\t\"systemPrompt\",\n\t\t\"systemPromptMode\",\n\t\t\"inheritProjectContext\",\n\t\t\"inheritSkills\",\n\t\t\"skills\",\n\t\t\"skillPath\",\n\t\t\"agentFilePath\",\n\t\t\"completionGuard\",\n\t\t\"memory\",\n\t\t\"outputPath\",\n\t\t\"outputMode\",\n\t\t\"structuredOutputSchema\",\n\t\t\"acceptance\",\n\t\t\"sessionDir\",\n\t\t\"artifactConfig\",\n\t\t\"artifactsDir\",\n\t\t\"maxOutput\",\n\t\t\"controlConfig\",\n\t\t\"absoluteDeadlineAt\",\n\t\t\"initialTurnBudget\",\n\t\t\"initialToolBudget\",\n\t\t\"maxSubagentDepth\",\n\t\t\"share\",\n\t\t\"capabilityCeiling\",\n\t\t\"launchResolvedExtensions\",\n\t]);\n\tfor (const field of Object.keys(parsed)) {\n\t\tif (!allowedFields.has(field))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': unknown field '${field}'.`);\n\t}\n\tconst requiredStrings = [\"sourceRunId\", \"agent\", \"cwd\", \"systemPromptMode\", \"outputMode\"] as const;\n\tfor (const field of requiredStrings) {\n\t\tif (typeof parsed[field] !== \"string\" || !(parsed[field] as string).trim())\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);\n\t}\n\tif (parsed.version !== 1)\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': version must be 1.`);\n\tif (parsed.capabilityCeiling !== undefined)\n\t\tparsed.capabilityCeiling = parseSubagentCapabilityCeiling(\n\t\t\tparsed.capabilityCeiling,\n\t\t\t`async recovery descriptor '${descriptorPath}' capabilityCeiling`,\n\t\t);\n\tif (parsed.agentContract !== undefined) {\n\t\tif (!parsed.agentContract || typeof parsed.agentContract !== \"object\" || Array.isArray(parsed.agentContract))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': agentContract must be an object.`);\n\t\tconst contract = parsed.agentContract as Record<string, unknown>;\n\t\tif (contract.version !== 1 || Object.keys(contract).some((key) => key !== \"version\"))\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': agentContract must be { version: 1 }.`,\n\t\t\t);\n\t}\n\tif (parsed.systemPromptMode !== \"append\" && parsed.systemPromptMode !== \"replace\")\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': systemPromptMode is invalid.`);\n\tif (parsed.outputMode !== \"inline\" && parsed.outputMode !== \"file-only\")\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': outputMode is invalid.`);\n\tfor (const field of [\"inheritProjectContext\", \"inheritSkills\", \"share\"] as const) {\n\t\tif (typeof parsed[field] !== \"boolean\")\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a boolean.`);\n\t}\n\tif (!Number.isInteger(parsed.maxSubagentDepth) || (parsed.maxSubagentDepth as number) < 0)\n\t\tthrow new Error(\n\t\t\t`Invalid async recovery descriptor '${descriptorPath}': maxSubagentDepth must be a non-negative integer.`,\n\t\t);\n\tfor (const field of [\n\t\t\"fallbackModels\",\n\t\t\"tools\",\n\t\t\"extensions\",\n\t\t\"subagentOnlyExtensions\",\n\t\t\"mcpDirectTools\",\n\t\t\"skills\",\n\t\t\"skillPath\",\n\t] as const) {\n\t\tconst item = parsed[field];\n\t\tif (\n\t\t\titem !== undefined &&\n\t\t\t(!Array.isArray(item) || item.some((entry) => typeof entry !== \"string\" || !entry.trim()))\n\t\t)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': ${field} must contain non-empty strings.`,\n\t\t\t);\n\t}\n\tif (parsed.systemPrompt !== undefined && typeof parsed.systemPrompt !== \"string\")\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': systemPrompt must be a string.`);\n\tfor (const field of [\n\t\t\"launchContractDigest\",\n\t\t\"sessionFile\",\n\t\t\"model\",\n\t\t\"thinking\",\n\t\t\"agentFilePath\",\n\t\t\"outputPath\",\n\t\t\"sessionDir\",\n\t\t\"artifactsDir\",\n\t] as const) {\n\t\tif (parsed[field] !== undefined && (typeof parsed[field] !== \"string\" || !(parsed[field] as string).trim()))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': ${field} must be a non-empty string.`);\n\t}\n\tif (parsed.completionGuard !== undefined && typeof parsed.completionGuard !== \"boolean\")\n\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': completionGuard must be a boolean.`);\n\tif (\n\t\tparsed.structuredOutputSchema !== undefined &&\n\t\t(!parsed.structuredOutputSchema ||\n\t\t\ttypeof parsed.structuredOutputSchema !== \"object\" ||\n\t\t\tArray.isArray(parsed.structuredOutputSchema))\n\t)\n\t\tthrow new Error(\n\t\t\t`Invalid async recovery descriptor '${descriptorPath}': structuredOutputSchema must be an object.`,\n\t\t);\n\tif (parsed.memory !== undefined) {\n\t\tif (!parsed.memory || typeof parsed.memory !== \"object\" || Array.isArray(parsed.memory))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': memory must be an object.`);\n\t\tconst memory = parsed.memory as Record<string, unknown>;\n\t\tif (\n\t\t\t(memory.scope !== \"project\" && memory.scope !== \"user\") ||\n\t\t\ttypeof memory.path !== \"string\" ||\n\t\t\t!memory.path.trim()\n\t\t)\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': memory is invalid.`);\n\t}\n\tif (\n\t\tparsed.absoluteDeadlineAt !== undefined &&\n\t\t(!Number.isFinite(parsed.absoluteDeadlineAt) || (parsed.absoluteDeadlineAt as number) <= 0)\n\t)\n\t\tthrow new Error(\n\t\t\t`Invalid async recovery descriptor '${descriptorPath}': absoluteDeadlineAt must be a positive timestamp.`,\n\t\t);\n\tif (parsed.initialTurnBudget !== undefined) {\n\t\tconst result = resolveTurnBudgetConfig(parsed.initialTurnBudget, \"recoveryDescriptor.initialTurnBudget\");\n\t\tif (result.error) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${result.error}`);\n\t}\n\tif (parsed.initialToolBudget !== undefined) {\n\t\tconst result = validateToolBudgetConfig(parsed.initialToolBudget, \"recoveryDescriptor.initialToolBudget\");\n\t\tif (result.error) throw new Error(`Invalid async recovery descriptor '${descriptorPath}': ${result.error}`);\n\t}\n\tif (parsed.maxOutput !== undefined) {\n\t\tif (!parsed.maxOutput || typeof parsed.maxOutput !== \"object\" || Array.isArray(parsed.maxOutput))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': maxOutput must be an object.`);\n\t\tfor (const field of [\"bytes\", \"lines\"] as const) {\n\t\t\tconst item = (parsed.maxOutput as Record<string, unknown>)[field];\n\t\t\tif (item !== undefined && (!Number.isInteger(item) || (item as number) < 1))\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': maxOutput.${field} must be a positive integer.`,\n\t\t\t\t);\n\t\t}\n\t}\n\tif (parsed.artifactConfig !== undefined) {\n\t\tif (!parsed.artifactConfig || typeof parsed.artifactConfig !== \"object\" || Array.isArray(parsed.artifactConfig))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': artifactConfig must be an object.`);\n\t\tconst artifact = parsed.artifactConfig as Record<string, unknown>;\n\t\tfor (const field of [\"enabled\", \"includeInput\", \"includeOutput\", \"includeJsonl\", \"includeMetadata\"] as const) {\n\t\t\tif (typeof artifact[field] !== \"boolean\")\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.${field} must be a boolean.`,\n\t\t\t\t);\n\t\t}\n\t\tif (artifact.includeTranscript !== undefined && typeof artifact.includeTranscript !== \"boolean\")\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.includeTranscript must be a boolean.`,\n\t\t\t);\n\t\tif (!Number.isInteger(artifact.cleanupDays) || (artifact.cleanupDays as number) < 0)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': artifactConfig.cleanupDays must be a non-negative integer.`,\n\t\t\t);\n\t}\n\tif (parsed.controlConfig !== undefined) {\n\t\tif (!parsed.controlConfig || typeof parsed.controlConfig !== \"object\" || Array.isArray(parsed.controlConfig))\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig must be an object.`);\n\t\tconst control = parsed.controlConfig as Record<string, unknown>;\n\t\tif (typeof control.enabled !== \"boolean\")\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': controlConfig.enabled must be a boolean.`,\n\t\t\t);\n\t\tfor (const field of [\n\t\t\t\"needsAttentionAfterMs\",\n\t\t\t\"activeNoticeAfterMs\",\n\t\t\t\"failedToolAttemptsBeforeAttention\",\n\t\t] as const) {\n\t\t\tif (!Number.isInteger(control[field]) || (control[field] as number) < 1)\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': controlConfig.${field} must be a positive integer.`,\n\t\t\t\t);\n\t\t}\n\t\tfor (const field of [\"activeNoticeAfterTurns\", \"activeNoticeAfterTokens\"] as const) {\n\t\t\tif (control[field] !== undefined && (!Number.isInteger(control[field]) || (control[field] as number) < 1))\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': controlConfig.${field} must be a positive integer.`,\n\t\t\t\t);\n\t\t}\n\t\tif (\n\t\t\t!Array.isArray(control.notifyOn) ||\n\t\t\tcontrol.notifyOn.some((item) => item !== \"active_long_running\" && item !== \"needs_attention\")\n\t\t)\n\t\t\tthrow new Error(`Invalid async recovery descriptor '${descriptorPath}': controlConfig.notifyOn is invalid.`);\n\t\tif (\n\t\t\t!Array.isArray(control.notifyChannels) ||\n\t\t\tcontrol.notifyChannels.some((item) => item !== \"event\" && item !== \"async\" && item !== \"intercom\")\n\t\t)\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid async recovery descriptor '${descriptorPath}': controlConfig.notifyChannels is invalid.`,\n\t\t\t);\n\t}\n\tif (parsed.acceptance !== undefined) {\n\t\tconst acceptance = normalizeRecoveryAcceptance(parsed.acceptance, descriptorPath);\n\t\tif (acceptance === undefined) delete parsed.acceptance;\n\t\telse parsed.acceptance = acceptance;\n\t}\n\treturn parsed as unknown as SteeringRecoveryDescriptor;\n}\n\nfunction validateResumeSessionFile(runId: string, sessionFile: string): string {\n\tif (path.extname(sessionFile) !== \".jsonl\")\n\t\tthrow new Error(`Async run '${runId}' session file must be a .jsonl file: ${sessionFile}`);\n\tconst resolved = path.resolve(sessionFile);\n\tif (!fs.existsSync(resolved)) throw new Error(`Async run '${runId}' session file does not exist: ${sessionFile}`);\n\treturn resolved;\n}\n\nexport function resolveAsyncResumeTarget(\n\tparams: AsyncResumeParams,\n\tdeps: AsyncResumeDeps = {},\n\toptions: AsyncResumeOptions = {},\n): AsyncResumeTarget {\n\tconst asyncDirRoot = deps.asyncDirRoot ?? DIRS.async;\n\tconst resultsDir = deps.resultsDir ?? DIRS.results;\n\tconst requireSessionFile = options.requireSessionFile ?? true;\n\tconst location = resolveAsyncRunLocation(params, asyncDirRoot, resultsDir);\n\tif (!location.asyncDir && !location.resultPath) {\n\t\tthrow new Error(\"Async run not found. Provide id or dir.\");\n\t}\n\n\tconst reconciliation = location.asyncDir\n\t\t? reconcileAsyncRun(location.asyncDir, { resultsDir, kill: deps.kill, now: deps.now })\n\t\t: undefined;\n\tconst status = reconciliation?.status ?? null;\n\tvalidateStatusForResume(status, location.asyncDir ? path.join(location.asyncDir, \"status.json\") : \"status.json\");\n\tconst recoveryDescriptor = readAsyncRecoveryDescriptor(location.asyncDir ?? undefined);\n\tconst result = location.resultPath ? readResultFile(location.resultPath) : undefined;\n\tconst runId =\n\t\tstatus?.runId ??\n\t\tresult?.runId ??\n\t\tresult?.id ??\n\t\tlocation.resolvedId ??\n\t\t(location.asyncDir ? path.basename(location.asyncDir) : \"unknown\");\n\tif (\n\t\toptions.sessionId &&\n\t\t((status && status.sessionId !== options.sessionId) || (result && result.sessionId !== options.sessionId))\n\t) {\n\t\tthrow new Error(`Async run '${runId}' was not found in the active session.`);\n\t}\n\tif (recoveryDescriptor && recoveryDescriptor.sourceRunId !== runId)\n\t\tthrow new Error(`Async run '${runId}' has a recovery descriptor for a different source run.`);\n\tconst state = status?.state ?? (result ? resultState(result) : undefined);\n\tif (!state) throw new Error(`Status file not found for async run '${runId}'.`);\n\tif (state === \"stopped\")\n\t\tthrow new Error(`Async run '${runId}' was stopped and cannot be resumed. Start a new run instead.`);\n\n\tconst statusSteps = status?.steps ?? [];\n\tconst resultSteps = result?.results ?? [];\n\tconst stepCount = statusSteps.length || resultSteps.length || (result?.agent ? 1 : 0);\n\tconst requestedIndex = params.index;\n\tif (requestedIndex !== undefined && !Number.isInteger(requestedIndex))\n\t\tthrow new Error(`Async run '${runId}' index must be an integer.`);\n\tconst terminalStepStatuses = new Set([\"complete\", \"completed\", \"failed\", \"paused\"]);\n\n\tif (state === \"running\") {\n\t\tif (requestedIndex !== undefined) {\n\t\t\tif (requestedIndex < 0 || requestedIndex >= stepCount)\n\t\t\t\tthrow new Error(`Async run '${runId}' has ${stepCount} children. Index ${requestedIndex} is out of range.`);\n\t\t\tconst selectedStep = statusSteps[requestedIndex];\n\t\t\tif (selectedStep?.status === \"running\") {\n\t\t\t\tconst capabilityCeiling = intersectSubagentCapabilityCeilings(\n\t\t\t\t\tstatus?.capabilityCeiling,\n\t\t\t\t\tselectedStep.capabilityCeiling,\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tkind: \"live\",\n\t\t\t\t\trunId,\n\t\t\t\t\tasyncDir: location.asyncDir ?? undefined,\n\t\t\t\t\tstate,\n\t\t\t\t\tagent: selectedStep.agent,\n\t\t\t\t\tindex: requestedIndex,\n\t\t\t\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t\t\t\tsessionFile: selectedStep.sessionFile ?? status?.sessionFile ?? result?.sessionFile,\n\t\t\t\t\tmodel: selectedStep.model,\n\t\t\t\t\tthinking: selectedStep.thinking,\n\t\t\t\t\tlaunchContractDigest:\n\t\t\t\t\t\tselectedStep.launchContractDigest ??\n\t\t\t\t\t\tresult?.results?.[requestedIndex]?.launchContractDigest ??\n\t\t\t\t\t\tresult?.launchContractDigest ??\n\t\t\t\t\t\trecoveryDescriptor?.launchContractDigest,\n\t\t\t\t\t...(capabilityCeiling ? { capabilityCeiling } : {}),\n\t\t\t\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t\t\t\t};\n\t\t\t}\n\t\t\tif (selectedStep?.status === \"pending\")\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Async run '${runId}' child ${requestedIndex} is pending and has not started yet. Wait for it to run or complete before resuming.`,\n\t\t\t\t);\n\t\t\tif (selectedStep && !terminalStepStatuses.has(selectedStep.status))\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Async run '${runId}' child ${requestedIndex} is ${selectedStep.status} and cannot be revived yet.`,\n\t\t\t\t);\n\t\t} else {\n\t\t\tconst running = statusSteps\n\t\t\t\t.map((step, index) => ({ step, index }))\n\t\t\t\t.filter(({ step }) => step.status === \"running\");\n\t\t\tconst selected = running.length === 1 ? running[0] : undefined;\n\t\t\tif (!selected) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Async run '${runId}' has ${running.length} running children. Provide index to choose one.`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst capabilityCeiling = intersectSubagentCapabilityCeilings(\n\t\t\t\tstatus?.capabilityCeiling,\n\t\t\t\tselected.step.capabilityCeiling,\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tkind: \"live\",\n\t\t\t\trunId,\n\t\t\t\tasyncDir: location.asyncDir ?? undefined,\n\t\t\t\tstate,\n\t\t\t\tagent: selected.step.agent,\n\t\t\t\tindex: selected.index,\n\t\t\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t\t\tsessionFile: selected.step.sessionFile ?? status?.sessionFile ?? result?.sessionFile,\n\t\t\t\tmodel: selected.step.model,\n\t\t\t\tthinking: selected.step.thinking,\n\t\t\t\tlaunchContractDigest:\n\t\t\t\t\tselected.step.launchContractDigest ??\n\t\t\t\t\tresult?.results?.[selected.index]?.launchContractDigest ??\n\t\t\t\t\tresult?.launchContractDigest ??\n\t\t\t\t\trecoveryDescriptor?.launchContractDigest,\n\t\t\t\t...(capabilityCeiling ? { capabilityCeiling } : {}),\n\t\t\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t\t\t};\n\t\t}\n\t}\n\n\tif (stepCount > 1 && requestedIndex === undefined) {\n\t\tthrow new Error(`Async run '${runId}' has ${stepCount} children. Provide index to choose one.`);\n\t}\n\tconst index = requestedIndex ?? 0;\n\tif (!Number.isInteger(index)) throw new Error(`Async run '${runId}' index must be an integer.`);\n\tif (index < 0 || index >= stepCount)\n\t\tthrow new Error(`Async run '${runId}' has ${stepCount} children. Index ${index} is out of range.`);\n\tconst agent = statusSteps[index]?.agent ?? resultSteps[index]?.agent ?? result?.agent;\n\tif (!agent) throw new Error(`Could not determine child agent for async run '${runId}'.`);\n\tif (recoveryDescriptor && recoveryDescriptor.agent !== agent)\n\t\tthrow new Error(\n\t\t\t`Async run '${runId}' has a recovery descriptor for '${recoveryDescriptor.agent}', not '${agent}'.`,\n\t\t);\n\tconst sessionFile =\n\t\tstatusSteps[index]?.sessionFile ??\n\t\tresultSteps[index]?.sessionFile ??\n\t\t(stepCount === 1 ? (status?.sessionFile ?? result?.sessionFile) : undefined);\n\tif (!sessionFile && requireSessionFile)\n\t\tthrow new Error(`Async run '${runId}' child ${index} does not have a persisted session file to resume from.`);\n\tconst resolvedSessionFile = sessionFile ? validateResumeSessionFile(runId, sessionFile) : undefined;\n\tconst stepModel =\n\t\tstatusSteps[index]?.model ?? resultSteps[index]?.model ?? (stepCount === 1 ? result?.model : undefined);\n\tconst stepThinking =\n\t\tstatusSteps[index]?.thinking ?? resultSteps[index]?.thinking ?? (stepCount === 1 ? result?.thinking : undefined);\n\tconst capabilityCeiling = intersectSubagentCapabilityCeilings(\n\t\tstatus?.capabilityCeiling,\n\t\tstatusSteps[index]?.capabilityCeiling,\n\t\tresult?.capabilityCeiling,\n\t\tresultSteps[index]?.capabilityCeiling,\n\t);\n\n\treturn {\n\t\tkind: \"revive\",\n\t\trunId,\n\t\tasyncDir: location.asyncDir ?? undefined,\n\t\tstate,\n\t\tagent,\n\t\tindex,\n\t\tcwd: status?.cwd ?? result?.cwd,\n\t\t...(resolvedSessionFile ? { sessionFile: resolvedSessionFile } : {}),\n\t\t...(stepModel ? { model: stepModel } : {}),\n\t\t...(stepThinking ? { thinking: stepThinking } : {}),\n\t\tlaunchContractDigest:\n\t\t\tstatusSteps[index]?.launchContractDigest ??\n\t\t\tresultSteps[index]?.launchContractDigest ??\n\t\t\tresult?.launchContractDigest ??\n\t\t\trecoveryDescriptor?.launchContractDigest,\n\t\t...(capabilityCeiling ? { capabilityCeiling } : {}),\n\t\t...(recoveryDescriptor ? { recoveryDescriptor } : {}),\n\t};\n}\n\nexport function applySteeringRecoveryAgentConfig(\n\tagentConfig: AgentConfig,\n\tdescriptor: SteeringRecoveryDescriptor,\n): AgentConfig {\n\treturn {\n\t\t...agentConfig,\n\t\tmodel: descriptor.model,\n\t\tfallbackModels: descriptor.fallbackModels ? [...descriptor.fallbackModels] : undefined,\n\t\tthinking: descriptor.thinking,\n\t\ttools: descriptor.tools ? [...descriptor.tools] : undefined,\n\t\textensions: descriptor.extensions ? [...descriptor.extensions] : undefined,\n\t\tsubagentOnlyExtensions: descriptor.subagentOnlyExtensions ? [...descriptor.subagentOnlyExtensions] : undefined,\n\t\tmcpDirectTools: descriptor.mcpDirectTools ? [...descriptor.mcpDirectTools] : undefined,\n\t\tsystemPrompt: descriptor.systemPrompt ?? agentConfig.systemPrompt,\n\t\tsystemPromptMode: descriptor.systemPromptMode,\n\t\tinheritProjectContext: descriptor.inheritProjectContext,\n\t\tinheritSkills: descriptor.inheritSkills,\n\t\tskills: descriptor.skills ? [...descriptor.skills] : undefined,\n\t\tskillPath: descriptor.skillPath ? [...descriptor.skillPath] : undefined,\n\t\tfilePath: descriptor.agentFilePath as string,\n\t\tcompletionGuard: descriptor.completionGuard,\n\t\tmemory: descriptor.memory ? { ...descriptor.memory } : undefined,\n\t\toutput: descriptor.outputPath,\n\t\ttoolBudget: descriptor.initialToolBudget,\n\t\tmaxSubagentDepth: descriptor.maxSubagentDepth,\n\t};\n}\n\nexport function buildRevivedAsyncTask(target: AsyncResumeTarget, message: string): string {\n\treturn [\n\t\t\"You are reviving a previous subagent conversation.\",\n\t\t\"\",\n\t\t`Original run: ${target.runId}`,\n\t\t`Original agent: ${target.agent}`,\n\t\ttarget.sessionFile ? `Original session file: ${target.sessionFile}` : undefined,\n\t\t\"\",\n\t\t\"Use the stored session context as background. Answer the orchestrator's follow-up below. Do not assume the original child process is still alive.\",\n\t\t\"\",\n\t\t\"Follow-up:\",\n\t\tmessage,\n\t]\n\t\t.filter((line): line is string => line !== undefined)\n\t\t.join(\"\\n\");\n}\n"]}