acpx 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/{acp-jsonrpc-CGT_1Mel.js → acp-jsonrpc-BNHXq7qK.js} +2 -2
- package/dist/{acp-jsonrpc-CGT_1Mel.js.map → acp-jsonrpc-BNHXq7qK.js.map} +1 -1
- package/dist/cli.js +43 -35
- package/dist/cli.js.map +1 -1
- package/dist/{output-BgMdEq3x.js → output-BmkPP7qE.js} +3 -6
- package/dist/{output-BgMdEq3x.js.map → output-BmkPP7qE.js.map} +1 -1
- package/dist/{output-render-Cvz0eKSb.js → output-render-DEAaMxg8.js} +5 -6
- package/dist/{output-render-Cvz0eKSb.js.map → output-render-DEAaMxg8.js.map} +1 -1
- package/dist/{queue-ipc-C8StWiZt.js → queue-ipc-EQLpBMKv.js} +133 -98
- package/dist/queue-ipc-EQLpBMKv.js.map +1 -0
- package/dist/rolldown-runtime-CiIaOW0V.js +13 -0
- package/dist/{runtime-session-id-B03l5p1Q.js → runtime-session-id-C544sPPL.js} +2 -3
- package/dist/{runtime-session-id-B03l5p1Q.js.map → runtime-session-id-C544sPPL.js.map} +1 -1
- package/dist/{session-C6nyqSfk.js → session-C2Q8ktsN.js} +244 -80
- package/dist/session-C2Q8ktsN.js.map +1 -0
- package/package.json +4 -3
- package/skills/acpx/SKILL.md +7 -4
- package/dist/queue-ipc-C8StWiZt.js.map +0 -1
- package/dist/rolldown-runtime-CjeV3_4I.js +0 -18
- package/dist/session-C6nyqSfk.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-C2Q8ktsN.js","names":["nowIso","canPromptForPermission","fs","canPromptForPermission","waitForSpawn","isoNow","asRecord","isoNow","hasOwn","isUserMessage","isAgentMessage","asRecord","ensureAcpxState","sessionBaseDir","asRecord","fs","ensureSessionDir","fs","fs","sessionBaseDir","segmentEventPath","activeEventPath","eventsLockPath","recordConversationSessionUpdate","recordConversationClientOperation","waitMs","fs"],"sources":["../src/permission-prompt.ts","../src/filesystem.ts","../src/permissions.ts","../src/session-runtime-helpers.ts","../src/terminal.ts","../src/client.ts","../src/perf-metrics-capture.ts","../src/session-conversation-model.ts","../src/session-event-log.ts","../src/session-persistence/serialize.ts","../src/persisted-key-policy.ts","../src/session-persistence/parse.ts","../src/session-persistence/index.ts","../src/session-persistence/repository.ts","../src/session-events.ts","../src/queue-owner-turn-controller.ts","../src/session-mode-preference.ts","../src/session-runtime/lifecycle.ts","../src/session-runtime/connect-load.ts","../src/session-runtime/prompt-runner.ts","../src/session-runtime/queue-owner-process.ts","../src/session-runtime.ts","../src/session.ts"],"sourcesContent":["import readline from \"node:readline/promises\";\n\nexport type PermissionPromptOptions = {\n prompt: string;\n header?: string;\n details?: string;\n};\n\nexport async function promptForPermission(options: PermissionPromptOptions): Promise<boolean> {\n if (!process.stdin.isTTY || !process.stderr.isTTY) {\n return false;\n }\n\n if (options.header) {\n process.stderr.write(`\\n${options.header}\\n`);\n }\n if (options.details && options.details.trim().length > 0) {\n process.stderr.write(`${options.details}\\n`);\n }\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stderr,\n });\n\n try {\n const answer = await rl.question(options.prompt);\n const normalized = answer.trim().toLowerCase();\n return normalized === \"y\" || normalized === \"yes\";\n } finally {\n rl.close();\n }\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type {\n ReadTextFileRequest,\n ReadTextFileResponse,\n WriteTextFileRequest,\n WriteTextFileResponse,\n} from \"@agentclientprotocol/sdk\";\nimport { PermissionDeniedError, PermissionPromptUnavailableError } from \"./errors.js\";\nimport { promptForPermission } from \"./permission-prompt.js\";\nimport type { ClientOperation, NonInteractivePermissionPolicy, PermissionMode } from \"./types.js\";\n\nconst WRITE_PREVIEW_MAX_LINES = 16;\nconst WRITE_PREVIEW_MAX_CHARS = 1_200;\n\nexport type FileSystemHandlersOptions = {\n cwd: string;\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n onOperation?: (operation: ClientOperation) => void;\n confirmWrite?: (filePath: string, preview: string) => Promise<boolean>;\n};\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction isWithinRoot(rootDir: string, targetPath: string): boolean {\n const relative = path.relative(rootDir, targetPath);\n return relative.length === 0 || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nfunction toWritePreview(content: string): string {\n const normalized = content.replace(/\\r\\n/g, \"\\n\");\n const lines = normalized.split(\"\\n\");\n const visibleLines = lines.slice(0, WRITE_PREVIEW_MAX_LINES);\n let preview = visibleLines.join(\"\\n\");\n\n if (lines.length > visibleLines.length) {\n preview += `\\n... (${lines.length - visibleLines.length} more lines)`;\n }\n\n if (preview.length > WRITE_PREVIEW_MAX_CHARS) {\n preview = `${preview.slice(0, WRITE_PREVIEW_MAX_CHARS - 3)}...`;\n }\n\n return preview;\n}\n\nasync function defaultConfirmWrite(filePath: string, preview: string): Promise<boolean> {\n return await promptForPermission({\n header: `[permission] Allow write to ${filePath}?`,\n details: preview,\n prompt: \"Allow write? (y/N) \",\n });\n}\n\nfunction canPromptForPermission(): boolean {\n return Boolean(process.stdin.isTTY && process.stderr.isTTY);\n}\n\nexport class FileSystemHandlers {\n private readonly rootDir: string;\n private permissionMode: PermissionMode;\n private nonInteractivePermissions: NonInteractivePermissionPolicy;\n private readonly onOperation?: (operation: ClientOperation) => void;\n private readonly usesDefaultConfirmWrite: boolean;\n private readonly confirmWrite: (filePath: string, preview: string) => Promise<boolean>;\n\n constructor(options: FileSystemHandlersOptions) {\n this.rootDir = path.resolve(options.cwd);\n this.permissionMode = options.permissionMode;\n this.nonInteractivePermissions = options.nonInteractivePermissions ?? \"deny\";\n this.onOperation = options.onOperation;\n this.usesDefaultConfirmWrite = options.confirmWrite == null;\n this.confirmWrite = options.confirmWrite ?? defaultConfirmWrite;\n }\n\n updatePermissionPolicy(\n permissionMode: PermissionMode,\n nonInteractivePermissions?: NonInteractivePermissionPolicy,\n ): void {\n this.permissionMode = permissionMode;\n this.nonInteractivePermissions = nonInteractivePermissions ?? \"deny\";\n }\n\n async readTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse> {\n const filePath = this.resolvePathWithinRoot(params.path);\n const summary = `read_text_file: ${filePath}`;\n this.emitOperation({\n method: \"fs/read_text_file\",\n status: \"running\",\n summary,\n details: this.readWindowDetails(params.line, params.limit),\n timestamp: nowIso(),\n });\n\n try {\n if (this.permissionMode === \"deny-all\") {\n throw new PermissionDeniedError(\"Permission denied for fs/read_text_file (--deny-all)\");\n }\n\n const content = await fs.readFile(filePath, \"utf8\");\n const sliced = this.sliceContent(content, params.line, params.limit);\n\n this.emitOperation({\n method: \"fs/read_text_file\",\n status: \"completed\",\n summary,\n details: this.readWindowDetails(params.line, params.limit),\n timestamp: nowIso(),\n });\n return { content: sliced };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.emitOperation({\n method: \"fs/read_text_file\",\n status: \"failed\",\n summary,\n details: message,\n timestamp: nowIso(),\n });\n throw error;\n }\n }\n\n async writeTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse> {\n const filePath = this.resolvePathWithinRoot(params.path);\n const preview = toWritePreview(params.content);\n const summary = `write_text_file: ${filePath}`;\n\n this.emitOperation({\n method: \"fs/write_text_file\",\n status: \"running\",\n summary,\n details: preview,\n timestamp: nowIso(),\n });\n\n try {\n if (!(await this.isWriteApproved(filePath, preview))) {\n throw new PermissionDeniedError(\"Permission denied for fs/write_text_file\");\n }\n\n await fs.mkdir(path.dirname(filePath), { recursive: true });\n await fs.writeFile(filePath, params.content, \"utf8\");\n\n this.emitOperation({\n method: \"fs/write_text_file\",\n status: \"completed\",\n summary,\n details: preview,\n timestamp: nowIso(),\n });\n return {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.emitOperation({\n method: \"fs/write_text_file\",\n status: \"failed\",\n summary,\n details: message,\n timestamp: nowIso(),\n });\n throw error;\n }\n }\n\n private async isWriteApproved(filePath: string, preview: string): Promise<boolean> {\n if (this.permissionMode === \"approve-all\") {\n return true;\n }\n if (this.permissionMode === \"deny-all\") {\n return false;\n }\n if (\n this.usesDefaultConfirmWrite &&\n this.nonInteractivePermissions === \"fail\" &&\n !canPromptForPermission()\n ) {\n throw new PermissionPromptUnavailableError();\n }\n return await this.confirmWrite(filePath, preview);\n }\n\n private resolvePathWithinRoot(rawPath: string): string {\n if (!path.isAbsolute(rawPath)) {\n throw new Error(`Path must be absolute: ${rawPath}`);\n }\n const resolved = path.resolve(rawPath);\n if (!isWithinRoot(this.rootDir, resolved)) {\n throw new Error(`Path is outside allowed cwd subtree: ${resolved}`);\n }\n return resolved;\n }\n\n private sliceContent(\n content: string,\n line: number | null | undefined,\n limit: number | null | undefined,\n ): string {\n if (line == null && limit == null) {\n return content;\n }\n\n const lines = content.split(\"\\n\");\n const startLine = line == null ? 1 : Math.max(1, Math.trunc(line));\n const startIndex = Math.max(0, startLine - 1);\n const maxLines = limit == null ? undefined : Math.max(0, Math.trunc(limit));\n\n if (maxLines === 0) {\n return \"\";\n }\n\n const endIndex =\n maxLines == null ? lines.length : Math.min(lines.length, startIndex + maxLines);\n\n return lines.slice(startIndex, endIndex).join(\"\\n\");\n }\n\n private readWindowDetails(\n line: number | null | undefined,\n limit: number | null | undefined,\n ): string | undefined {\n if (line == null && limit == null) {\n return undefined;\n }\n const start = line == null ? 1 : Math.max(1, Math.trunc(line));\n const max = limit == null ? \"all\" : Math.max(0, Math.trunc(limit));\n return `line=${start}, limit=${max}`;\n }\n\n private emitOperation(operation: ClientOperation): void {\n this.onOperation?.(operation);\n }\n}\n","import {\n type PermissionOption,\n type RequestPermissionRequest,\n type RequestPermissionResponse,\n type ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport { PermissionPromptUnavailableError } from \"./errors.js\";\nimport { promptForPermission } from \"./permission-prompt.js\";\nimport type { NonInteractivePermissionPolicy, PermissionMode } from \"./types.js\";\n\ntype PermissionDecision = \"approved\" | \"denied\" | \"cancelled\";\n\nfunction selected(optionId: string): RequestPermissionResponse {\n return { outcome: { outcome: \"selected\", optionId } };\n}\n\nfunction cancelled(): RequestPermissionResponse {\n return { outcome: { outcome: \"cancelled\" } };\n}\n\nfunction pickOption(\n options: PermissionOption[],\n kinds: PermissionOption[\"kind\"][],\n): PermissionOption | undefined {\n for (const kind of kinds) {\n const match = options.find((option) => option.kind === kind);\n if (match) {\n return match;\n }\n }\n return undefined;\n}\n\nfunction inferToolKind(params: RequestPermissionRequest): ToolKind | undefined {\n if (params.toolCall.kind) {\n return params.toolCall.kind;\n }\n\n const title = params.toolCall.title?.trim().toLowerCase();\n if (!title) {\n return undefined;\n }\n\n const head = title.split(\":\", 1)[0]?.trim();\n if (!head) {\n return undefined;\n }\n\n if (head.includes(\"read\") || head.includes(\"cat\")) {\n return \"read\";\n }\n if (head.includes(\"search\") || head.includes(\"find\") || head.includes(\"grep\")) {\n return \"search\";\n }\n if (head.includes(\"write\") || head.includes(\"edit\") || head.includes(\"patch\")) {\n return \"edit\";\n }\n if (head.includes(\"delete\") || head.includes(\"remove\")) {\n return \"delete\";\n }\n if (head.includes(\"move\") || head.includes(\"rename\")) {\n return \"move\";\n }\n if (head.includes(\"run\") || head.includes(\"execute\") || head.includes(\"bash\")) {\n return \"execute\";\n }\n if (head.includes(\"fetch\") || head.includes(\"http\") || head.includes(\"url\")) {\n return \"fetch\";\n }\n if (head.includes(\"think\")) {\n return \"think\";\n }\n\n return \"other\";\n}\n\nfunction isAutoApprovedReadKind(kind: ToolKind | undefined): boolean {\n return kind === \"read\" || kind === \"search\";\n}\n\nasync function promptForToolPermission(params: RequestPermissionRequest): Promise<boolean> {\n const toolName = params.toolCall.title ?? \"tool\";\n const toolKind = inferToolKind(params) ?? \"other\";\n return await promptForPermission({\n prompt: `\\n[permission] Allow ${toolName} [${toolKind}]? (y/N) `,\n });\n}\n\nfunction canPromptForPermission(): boolean {\n return Boolean(process.stdin.isTTY && process.stderr.isTTY);\n}\n\nexport async function resolvePermissionRequest(\n params: RequestPermissionRequest,\n mode: PermissionMode,\n nonInteractivePolicy: NonInteractivePermissionPolicy = \"deny\",\n): Promise<RequestPermissionResponse> {\n const options = params.options ?? [];\n if (options.length === 0) {\n return cancelled();\n }\n\n const allowOption = pickOption(options, [\"allow_once\", \"allow_always\"]);\n const rejectOption = pickOption(options, [\"reject_once\", \"reject_always\"]);\n\n if (mode === \"approve-all\") {\n if (allowOption) {\n return selected(allowOption.optionId);\n }\n return selected(options[0].optionId);\n }\n\n if (mode === \"deny-all\") {\n if (rejectOption) {\n return selected(rejectOption.optionId);\n }\n return cancelled();\n }\n\n const kind = inferToolKind(params);\n if (isAutoApprovedReadKind(kind) && allowOption) {\n return selected(allowOption.optionId);\n }\n\n if (!canPromptForPermission()) {\n if (nonInteractivePolicy === \"fail\") {\n throw new PermissionPromptUnavailableError();\n }\n if (rejectOption) {\n return selected(rejectOption.optionId);\n }\n return cancelled();\n }\n\n const approved = await promptForToolPermission(params);\n if (approved && allowOption) {\n return selected(allowOption.optionId);\n }\n if (!approved && rejectOption) {\n return selected(rejectOption.optionId);\n }\n return cancelled();\n}\n\nexport function classifyPermissionDecision(\n params: RequestPermissionRequest,\n response: RequestPermissionResponse,\n): PermissionDecision {\n if (response.outcome.outcome !== \"selected\") {\n return \"cancelled\";\n }\n\n const selectedOptionId = response.outcome.optionId;\n const selectedOption = params.options.find((option) => option.optionId === selectedOptionId);\n\n if (!selectedOption) {\n return \"cancelled\";\n }\n\n if (selectedOption.kind === \"allow_once\" || selectedOption.kind === \"allow_always\") {\n return \"approved\";\n }\n\n return \"denied\";\n}\n","export class TimeoutError extends Error {\n constructor(timeoutMs: number) {\n super(`Timed out after ${timeoutMs}ms`);\n this.name = \"TimeoutError\";\n }\n}\n\nexport class InterruptedError extends Error {\n constructor() {\n super(\"Interrupted\");\n this.name = \"InterruptedError\";\n }\n}\n\nexport async function withTimeout<T>(promise: Promise<T>, timeoutMs?: number): Promise<T> {\n if (timeoutMs == null || timeoutMs <= 0) {\n return await promise;\n }\n\n let timer: NodeJS.Timeout | undefined;\n const timeoutPromise = new Promise<T>((_resolve, reject) => {\n timer = setTimeout(() => {\n reject(new TimeoutError(timeoutMs));\n }, timeoutMs);\n });\n\n try {\n return await Promise.race([promise, timeoutPromise]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n}\n\nexport async function withInterrupt<T>(\n run: () => Promise<T>,\n onInterrupt: () => Promise<void>,\n): Promise<T> {\n return await new Promise<T>((resolve, reject) => {\n let settled = false;\n\n const finish = (cb: () => void) => {\n if (settled) {\n return;\n }\n settled = true;\n process.off(\"SIGINT\", onSigint);\n process.off(\"SIGTERM\", onSigterm);\n cb();\n };\n\n const onSigint = () => {\n void onInterrupt().finally(() => {\n finish(() => reject(new InterruptedError()));\n });\n };\n\n const onSigterm = () => {\n void onInterrupt().finally(() => {\n finish(() => reject(new InterruptedError()));\n });\n };\n\n process.once(\"SIGINT\", onSigint);\n process.once(\"SIGTERM\", onSigterm);\n\n void run().then(\n (result) => finish(() => resolve(result)),\n (error) => finish(() => reject(error)),\n );\n });\n}\n","import { spawn, type ChildProcessByStdio } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport type { Readable } from \"node:stream\";\nimport type {\n CreateTerminalRequest,\n CreateTerminalResponse,\n KillTerminalRequest,\n KillTerminalResponse,\n ReleaseTerminalRequest,\n ReleaseTerminalResponse,\n TerminalOutputRequest,\n TerminalOutputResponse,\n WaitForTerminalExitRequest,\n WaitForTerminalExitResponse,\n} from \"@agentclientprotocol/sdk\";\nimport { PermissionDeniedError, PermissionPromptUnavailableError } from \"./errors.js\";\nimport { promptForPermission } from \"./permission-prompt.js\";\nimport type { ClientOperation, NonInteractivePermissionPolicy, PermissionMode } from \"./types.js\";\n\nconst DEFAULT_TERMINAL_OUTPUT_LIMIT_BYTES = 64 * 1024;\nconst DEFAULT_KILL_GRACE_MS = 1_500;\n\ntype ManagedTerminal = {\n process: ChildProcessByStdio<null, Readable, Readable>;\n output: Buffer;\n truncated: boolean;\n outputByteLimit: number;\n exitCode: number | null | undefined;\n signal: NodeJS.Signals | null | undefined;\n exitPromise: Promise<WaitForTerminalExitResponse>;\n resolveExit: (response: WaitForTerminalExitResponse) => void;\n};\n\nexport type TerminalManagerOptions = {\n cwd: string;\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n onOperation?: (operation: ClientOperation) => void;\n confirmExecute?: (commandLine: string) => Promise<boolean>;\n killGraceMs?: number;\n};\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nfunction toCommandLine(command: string, args: string[] | undefined): string {\n const renderedArgs = (args ?? []).map((arg) => JSON.stringify(arg)).join(\" \");\n return renderedArgs.length > 0 ? `${command} ${renderedArgs}` : command;\n}\n\nfunction toEnvObject(env: CreateTerminalRequest[\"env\"]): NodeJS.ProcessEnv | undefined {\n if (!env || env.length === 0) {\n return undefined;\n }\n\n const merged: NodeJS.ProcessEnv = { ...process.env };\n for (const entry of env) {\n merged[entry.name] = entry.value;\n }\n return merged;\n}\n\nexport function buildTerminalSpawnOptions(\n cwd: string,\n env: CreateTerminalRequest[\"env\"],\n): {\n cwd: string;\n env: NodeJS.ProcessEnv | undefined;\n stdio: [\"ignore\", \"pipe\", \"pipe\"];\n windowsHide: true;\n} {\n return {\n cwd,\n env: toEnvObject(env),\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n };\n}\n\nfunction trimToUtf8Boundary(buffer: Buffer, limit: number): Buffer {\n if (limit <= 0) {\n return Buffer.alloc(0);\n }\n if (buffer.length <= limit) {\n return buffer;\n }\n\n let start = buffer.length - limit;\n while (start < buffer.length && (buffer[start] & 0b1100_0000) === 0b1000_0000) {\n start += 1;\n }\n\n if (start >= buffer.length) {\n start = buffer.length - limit;\n }\n return buffer.subarray(start);\n}\n\nfunction waitForSpawn(process: ChildProcessByStdio<null, Readable, Readable>): Promise<void> {\n return new Promise((resolve, reject) => {\n const onSpawn = () => {\n process.off(\"error\", onError);\n resolve();\n };\n const onError = (error: Error) => {\n process.off(\"spawn\", onSpawn);\n reject(error);\n };\n\n process.once(\"spawn\", onSpawn);\n process.once(\"error\", onError);\n });\n}\n\nasync function defaultConfirmExecute(commandLine: string): Promise<boolean> {\n return await promptForPermission({\n prompt: `\\n[permission] Allow terminal command \"${commandLine}\"? (y/N) `,\n });\n}\n\nfunction canPromptForPermission(): boolean {\n return Boolean(process.stdin.isTTY && process.stderr.isTTY);\n}\n\nfunction waitMs(ms: number): Promise<void> {\n return new Promise<void>((resolve) => {\n setTimeout(resolve, Math.max(0, ms));\n });\n}\n\nexport class TerminalManager {\n private readonly cwd: string;\n private permissionMode: PermissionMode;\n private nonInteractivePermissions: NonInteractivePermissionPolicy;\n private readonly onOperation?: (operation: ClientOperation) => void;\n private readonly usesDefaultConfirmExecute: boolean;\n private readonly confirmExecute: (commandLine: string) => Promise<boolean>;\n private readonly killGraceMs: number;\n private readonly terminals = new Map<string, ManagedTerminal>();\n\n constructor(options: TerminalManagerOptions) {\n this.cwd = options.cwd;\n this.permissionMode = options.permissionMode;\n this.nonInteractivePermissions = options.nonInteractivePermissions ?? \"deny\";\n this.onOperation = options.onOperation;\n this.usesDefaultConfirmExecute = options.confirmExecute == null;\n this.confirmExecute = options.confirmExecute ?? defaultConfirmExecute;\n this.killGraceMs = Math.max(0, Math.round(options.killGraceMs ?? DEFAULT_KILL_GRACE_MS));\n }\n\n updatePermissionPolicy(\n permissionMode: PermissionMode,\n nonInteractivePermissions?: NonInteractivePermissionPolicy,\n ): void {\n this.permissionMode = permissionMode;\n this.nonInteractivePermissions = nonInteractivePermissions ?? \"deny\";\n }\n\n async createTerminal(params: CreateTerminalRequest): Promise<CreateTerminalResponse> {\n const commandLine = toCommandLine(params.command, params.args);\n const summary = `terminal/create: ${commandLine}`;\n\n this.emitOperation({\n method: \"terminal/create\",\n status: \"running\",\n summary,\n timestamp: nowIso(),\n });\n\n try {\n if (!(await this.isExecuteApproved(commandLine))) {\n throw new PermissionDeniedError(\"Permission denied for terminal/create\");\n }\n\n const outputByteLimit = Math.max(\n 0,\n Math.round(params.outputByteLimit ?? DEFAULT_TERMINAL_OUTPUT_LIMIT_BYTES),\n );\n const proc = spawn(\n params.command,\n params.args ?? [],\n buildTerminalSpawnOptions(params.cwd ?? this.cwd, params.env),\n );\n await waitForSpawn(proc);\n\n let resolveExit: (response: WaitForTerminalExitResponse) => void = () => {};\n const exitPromise = new Promise<WaitForTerminalExitResponse>((resolve) => {\n resolveExit = resolve;\n });\n\n const terminal: ManagedTerminal = {\n process: proc,\n output: Buffer.alloc(0),\n truncated: false,\n outputByteLimit,\n exitCode: undefined,\n signal: undefined,\n exitPromise,\n resolveExit,\n };\n\n const appendOutput = (chunk: Buffer | string): void => {\n const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);\n if (bytes.length === 0) {\n return;\n }\n\n terminal.output = Buffer.concat([terminal.output, bytes]);\n if (terminal.output.length > terminal.outputByteLimit) {\n terminal.output = trimToUtf8Boundary(terminal.output, terminal.outputByteLimit);\n terminal.truncated = true;\n }\n };\n\n proc.stdout.on(\"data\", appendOutput);\n proc.stderr.on(\"data\", appendOutput);\n proc.once(\"exit\", (exitCode, signal) => {\n terminal.exitCode = exitCode;\n terminal.signal = signal;\n terminal.resolveExit({\n exitCode: exitCode ?? null,\n signal: signal ?? null,\n });\n });\n\n const terminalId = randomUUID();\n this.terminals.set(terminalId, terminal);\n\n this.emitOperation({\n method: \"terminal/create\",\n status: \"completed\",\n summary,\n details: `terminalId=${terminalId}`,\n timestamp: nowIso(),\n });\n return { terminalId };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.emitOperation({\n method: \"terminal/create\",\n status: \"failed\",\n summary,\n details: message,\n timestamp: nowIso(),\n });\n throw error;\n }\n }\n\n async terminalOutput(params: TerminalOutputRequest): Promise<TerminalOutputResponse> {\n const terminal = this.getTerminal(params.terminalId);\n if (!terminal) {\n throw new Error(`Unknown terminal: ${params.terminalId}`);\n }\n\n const hasExitStatus = terminal.exitCode !== undefined || terminal.signal !== undefined;\n\n this.emitOperation({\n method: \"terminal/output\",\n status: \"completed\",\n summary: `terminal/output: ${params.terminalId}`,\n timestamp: nowIso(),\n });\n\n return {\n output: terminal.output.toString(\"utf8\"),\n truncated: terminal.truncated,\n exitStatus: hasExitStatus\n ? {\n exitCode: terminal.exitCode ?? null,\n signal: terminal.signal ?? null,\n }\n : undefined,\n };\n }\n\n async waitForTerminalExit(\n params: WaitForTerminalExitRequest,\n ): Promise<WaitForTerminalExitResponse> {\n const terminal = this.getTerminal(params.terminalId);\n if (!terminal) {\n throw new Error(`Unknown terminal: ${params.terminalId}`);\n }\n\n const response = await terminal.exitPromise;\n this.emitOperation({\n method: \"terminal/wait_for_exit\",\n status: \"completed\",\n summary: `terminal/wait_for_exit: ${params.terminalId}`,\n details: `exitCode=${response.exitCode ?? \"null\"}, signal=${response.signal ?? \"null\"}`,\n timestamp: nowIso(),\n });\n return response;\n }\n\n async killTerminal(params: KillTerminalRequest): Promise<KillTerminalResponse> {\n const terminal = this.getTerminal(params.terminalId);\n if (!terminal) {\n throw new Error(`Unknown terminal: ${params.terminalId}`);\n }\n\n const summary = `terminal/kill: ${params.terminalId}`;\n this.emitOperation({\n method: \"terminal/kill\",\n status: \"running\",\n summary,\n timestamp: nowIso(),\n });\n\n try {\n await this.killProcess(terminal);\n this.emitOperation({\n method: \"terminal/kill\",\n status: \"completed\",\n summary,\n timestamp: nowIso(),\n });\n return {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.emitOperation({\n method: \"terminal/kill\",\n status: \"failed\",\n summary,\n details: message,\n timestamp: nowIso(),\n });\n throw error;\n }\n }\n\n async releaseTerminal(params: ReleaseTerminalRequest): Promise<ReleaseTerminalResponse> {\n const summary = `terminal/release: ${params.terminalId}`;\n this.emitOperation({\n method: \"terminal/release\",\n status: \"running\",\n summary,\n timestamp: nowIso(),\n });\n\n const terminal = this.getTerminal(params.terminalId);\n if (!terminal) {\n this.emitOperation({\n method: \"terminal/release\",\n status: \"completed\",\n summary,\n details: \"already released\",\n timestamp: nowIso(),\n });\n return {};\n }\n\n try {\n await this.killProcess(terminal);\n await terminal.exitPromise.catch(() => {\n // ignore best-effort wait failures\n });\n terminal.output = Buffer.alloc(0);\n this.terminals.delete(params.terminalId);\n\n this.emitOperation({\n method: \"terminal/release\",\n status: \"completed\",\n summary,\n timestamp: nowIso(),\n });\n return {};\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.emitOperation({\n method: \"terminal/release\",\n status: \"failed\",\n summary,\n details: message,\n timestamp: nowIso(),\n });\n throw error;\n }\n }\n\n async shutdown(): Promise<void> {\n for (const terminalId of Array.from(this.terminals.keys())) {\n await this.releaseTerminal({ terminalId, sessionId: \"shutdown\" });\n }\n }\n\n private getTerminal(terminalId: string): ManagedTerminal | undefined {\n return this.terminals.get(terminalId);\n }\n\n private emitOperation(operation: ClientOperation): void {\n this.onOperation?.(operation);\n }\n\n private async isExecuteApproved(commandLine: string): Promise<boolean> {\n if (this.permissionMode === \"approve-all\") {\n return true;\n }\n if (this.permissionMode === \"deny-all\") {\n return false;\n }\n if (\n this.usesDefaultConfirmExecute &&\n this.nonInteractivePermissions === \"fail\" &&\n !canPromptForPermission()\n ) {\n throw new PermissionPromptUnavailableError();\n }\n return await this.confirmExecute(commandLine);\n }\n\n private isRunning(terminal: ManagedTerminal): boolean {\n return terminal.exitCode === undefined && terminal.signal === undefined;\n }\n\n private async killProcess(terminal: ManagedTerminal): Promise<void> {\n if (!this.isRunning(terminal)) {\n return;\n }\n\n try {\n terminal.process.kill(\"SIGTERM\");\n } catch {\n return;\n }\n\n const exitedAfterTerm = await Promise.race([\n terminal.exitPromise.then(() => true),\n waitMs(this.killGraceMs).then(() => false),\n ]);\n\n if (exitedAfterTerm || !this.isRunning(terminal)) {\n return;\n }\n\n try {\n terminal.process.kill(\"SIGKILL\");\n } catch {\n return;\n }\n\n await Promise.race([terminal.exitPromise.then(() => undefined), waitMs(this.killGraceMs)]);\n }\n}\n","import { spawn, type ChildProcess, type ChildProcessByStdio } from \"node:child_process\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { Readable, Writable } from \"node:stream\";\nimport {\n ClientSideConnection,\n PROTOCOL_VERSION,\n ndJsonStream,\n type AnyMessage,\n type AuthMethod,\n type CreateTerminalRequest,\n type CreateTerminalResponse,\n type InitializeResponse,\n type KillTerminalRequest,\n type KillTerminalResponse,\n type LoadSessionResponse,\n type PromptResponse,\n type ReadTextFileRequest,\n type ReadTextFileResponse,\n type ReleaseTerminalRequest,\n type ReleaseTerminalResponse,\n type RequestPermissionRequest,\n type RequestPermissionResponse,\n type SessionNotification,\n type SetSessionConfigOptionResponse,\n type TerminalOutputRequest,\n type TerminalOutputResponse,\n type WaitForTerminalExitRequest,\n type WaitForTerminalExitResponse,\n type WriteTextFileRequest,\n type WriteTextFileResponse,\n} from \"@agentclientprotocol/sdk\";\nimport { extractAcpError } from \"./acp-error-shapes.js\";\nimport { isSessionUpdateNotification } from \"./acp-jsonrpc.js\";\nimport {\n AgentSpawnError,\n AuthPolicyError,\n ClaudeAcpSessionCreateTimeoutError,\n CopilotAcpUnsupportedError,\n GeminiAcpStartupTimeoutError,\n PermissionDeniedError,\n PermissionPromptUnavailableError,\n} from \"./errors.js\";\nimport { FileSystemHandlers } from \"./filesystem.js\";\nimport { classifyPermissionDecision, resolvePermissionRequest } from \"./permissions.js\";\nimport { textPrompt } from \"./prompt-content.js\";\nimport { extractRuntimeSessionId } from \"./runtime-session-id.js\";\nimport { TimeoutError, withTimeout } from \"./session-runtime-helpers.js\";\nimport { TerminalManager } from \"./terminal.js\";\nimport type {\n AcpClientOptions,\n NonInteractivePermissionPolicy,\n PermissionMode,\n PermissionStats,\n PromptInput,\n} from \"./types.js\";\n\ntype CommandParts = {\n command: string;\n args: string[];\n};\n\nconst REPLAY_IDLE_MS = 80;\nconst REPLAY_DRAIN_TIMEOUT_MS = 5_000;\nconst DRAIN_POLL_INTERVAL_MS = 20;\nconst AGENT_CLOSE_AFTER_STDIN_END_MS = 100;\nconst AGENT_CLOSE_TERM_GRACE_MS = 1_500;\nconst AGENT_CLOSE_KILL_GRACE_MS = 1_000;\nconst GEMINI_ACP_STARTUP_TIMEOUT_MS = 15_000;\nconst CLAUDE_ACP_SESSION_CREATE_TIMEOUT_MS = 60_000;\nconst GEMINI_VERSION_TIMEOUT_MS = 2_000;\nconst GEMINI_ACP_FLAG_VERSION = [0, 33, 0] as const;\nconst COPILOT_HELP_TIMEOUT_MS = 2_000;\nconst SESSION_CONTROL_UNSUPPORTED_ACP_CODES = new Set([-32601, -32602]);\n\ntype LoadSessionOptions = {\n suppressReplayUpdates?: boolean;\n replayIdleMs?: number;\n replayDrainTimeoutMs?: number;\n};\n\nexport type SessionCreateResult = {\n sessionId: string;\n agentSessionId?: string;\n};\n\nexport type SessionLoadResult = {\n agentSessionId?: string;\n};\n\ntype AgentDisconnectReason = \"process_exit\" | \"process_close\" | \"pipe_close\" | \"connection_close\";\n\ntype AuthSelection = {\n methodId: string;\n credential: string;\n source: \"env\" | \"config\";\n};\n\ntype GeminiVersion = {\n raw: string;\n parts: [number, number, number];\n};\n\nexport type AgentExitInfo = {\n exitCode: number | null;\n signal: NodeJS.Signals | null;\n exitedAt: string;\n reason: AgentDisconnectReason;\n unexpectedDuringPrompt: boolean;\n};\n\nexport type AgentLifecycleSnapshot = {\n pid?: number;\n startedAt?: string;\n running: boolean;\n lastExit?: AgentExitInfo;\n};\n\ntype ConsoleErrorMethod = typeof console.error;\n\nfunction shouldSuppressSdkConsoleError(args: unknown[]): boolean {\n if (args.length === 0) {\n return false;\n }\n return typeof args[0] === \"string\" && args[0] === \"Error handling request\";\n}\n\nfunction installSdkConsoleErrorSuppression(): () => void {\n const originalConsoleError: ConsoleErrorMethod = console.error;\n console.error = (...args: unknown[]) => {\n if (shouldSuppressSdkConsoleError(args)) {\n return;\n }\n originalConsoleError(...args);\n };\n return () => {\n console.error = originalConsoleError;\n };\n}\n\nfunction isoNow(): string {\n return new Date().toISOString();\n}\n\nfunction waitForSpawn(child: ChildProcess): Promise<void> {\n return new Promise((resolve, reject) => {\n const onSpawn = () => {\n child.off(\"error\", onError);\n resolve();\n };\n const onError = (error: Error) => {\n child.off(\"spawn\", onSpawn);\n reject(error);\n };\n\n child.once(\"spawn\", onSpawn);\n child.once(\"error\", onError);\n });\n}\n\nfunction isChildProcessRunning(child: ChildProcess): boolean {\n return child.exitCode == null && child.signalCode == null;\n}\n\nfunction requireAgentStdio(child: ChildProcess): ChildProcessByStdio<Writable, Readable, Readable> {\n if (!child.stdin || !child.stdout || !child.stderr) {\n throw new Error(\"ACP agent must be spawned with piped stdin/stdout/stderr\");\n }\n return child as ChildProcessByStdio<Writable, Readable, Readable>;\n}\n\nfunction waitForChildExit(\n child: ChildProcessByStdio<Writable, Readable, Readable>,\n timeoutMs: number,\n): Promise<boolean> {\n if (!isChildProcessRunning(child)) {\n return Promise.resolve(true);\n }\n\n return new Promise<boolean>((resolve) => {\n let settled = false;\n const timer = setTimeout(\n () => {\n finish(false);\n },\n Math.max(0, timeoutMs),\n );\n\n const finish = (value: boolean) => {\n if (settled) {\n return;\n }\n settled = true;\n child.off(\"close\", onExitLike);\n child.off(\"exit\", onExitLike);\n clearTimeout(timer);\n resolve(value);\n };\n\n const onExitLike = () => {\n finish(true);\n };\n\n child.once(\"close\", onExitLike);\n child.once(\"exit\", onExitLike);\n });\n}\n\nfunction splitCommandLine(value: string): CommandParts {\n const parts: string[] = [];\n let current = \"\";\n let quote: \"'\" | '\"' | null = null;\n let escaping = false;\n\n for (const ch of value) {\n if (escaping) {\n current += ch;\n escaping = false;\n continue;\n }\n\n if (ch === \"\\\\\" && quote !== \"'\") {\n escaping = true;\n continue;\n }\n\n if (quote) {\n if (ch === quote) {\n quote = null;\n } else {\n current += ch;\n }\n continue;\n }\n\n if (ch === \"'\" || ch === '\"') {\n quote = ch;\n continue;\n }\n\n if (/\\s/.test(ch)) {\n if (current.length > 0) {\n parts.push(current);\n current = \"\";\n }\n continue;\n }\n\n current += ch;\n }\n\n if (escaping) {\n current += \"\\\\\";\n }\n\n if (quote) {\n throw new Error(\"Invalid --agent command: unterminated quote\");\n }\n\n if (current.length > 0) {\n parts.push(current);\n }\n\n if (parts.length === 0) {\n throw new Error(\"Invalid --agent command: empty command\");\n }\n\n return {\n command: parts[0],\n args: parts.slice(1),\n };\n}\n\nfunction asAbsoluteCwd(cwd: string): string {\n return path.resolve(cwd);\n}\n\nfunction basenameToken(value: string): string {\n return path\n .basename(value)\n .toLowerCase()\n .replace(/\\.(cmd|exe|bat)$/u, \"\");\n}\n\nfunction isGeminiAcpCommand(command: string, args: readonly string[]): boolean {\n return (\n basenameToken(command) === \"gemini\" &&\n (args.includes(\"--acp\") || args.includes(\"--experimental-acp\"))\n );\n}\n\nfunction isClaudeAcpCommand(command: string, args: readonly string[]): boolean {\n const commandToken = basenameToken(command);\n if (commandToken === \"claude-agent-acp\") {\n return true;\n }\n return args.some((arg) => arg.includes(\"claude-agent-acp\"));\n}\n\nfunction isCopilotAcpCommand(command: string, args: readonly string[]): boolean {\n return basenameToken(command) === \"copilot\" && args.includes(\"--acp\");\n}\n\nfunction readWindowsEnvValue(env: NodeJS.ProcessEnv, key: string): string | undefined {\n const matchedKey = Object.keys(env).find((entry) => entry.toUpperCase() === key);\n return matchedKey ? env[matchedKey] : undefined;\n}\n\nfunction resolveWindowsCommand(\n command: string,\n env: NodeJS.ProcessEnv = process.env,\n): string | undefined {\n const extensions = (readWindowsEnvValue(env, \"PATHEXT\") ?? \".COM;.EXE;.BAT;.CMD\")\n .split(\";\")\n .map((value) => value.trim().toLowerCase())\n .filter((value) => value.length > 0);\n const commandExtension = path.extname(command);\n const candidates =\n commandExtension.length > 0\n ? [command]\n : extensions.map((extension) => `${command}${extension}`);\n const hasPath = command.includes(\"/\") || command.includes(\"\\\\\") || path.isAbsolute(command);\n\n if (hasPath) {\n return candidates.find((candidate) => fs.existsSync(candidate));\n }\n\n const pathValue = readWindowsEnvValue(env, \"PATH\");\n if (!pathValue) {\n return undefined;\n }\n\n for (const directory of pathValue.split(\";\")) {\n const trimmedDirectory = directory.trim();\n if (trimmedDirectory.length === 0) {\n continue;\n }\n for (const candidate of candidates) {\n const resolved = path.join(trimmedDirectory, candidate);\n if (fs.existsSync(resolved)) {\n return resolved;\n }\n }\n }\n\n return undefined;\n}\n\nfunction shouldUseWindowsBatchShell(\n command: string,\n platform: NodeJS.Platform = process.platform,\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n if (platform !== \"win32\") {\n return false;\n }\n const resolvedCommand = resolveWindowsCommand(command, env) ?? command;\n const ext = path.extname(resolvedCommand).toLowerCase();\n return ext === \".cmd\" || ext === \".bat\";\n}\n\nexport function buildSpawnCommandOptions(\n command: string,\n options: Parameters<typeof spawn>[2],\n platform: NodeJS.Platform = process.platform,\n env: NodeJS.ProcessEnv = process.env,\n): Parameters<typeof spawn>[2] {\n if (!shouldUseWindowsBatchShell(command, platform, env)) {\n return options;\n }\n return {\n ...options,\n shell: true,\n };\n}\n\nfunction resolveGeminiAcpStartupTimeoutMs(): number {\n const raw = process.env.ACPX_GEMINI_ACP_STARTUP_TIMEOUT_MS;\n if (typeof raw === \"string\" && raw.trim().length > 0) {\n const parsed = Number(raw);\n if (Number.isFinite(parsed) && parsed > 0) {\n return Math.round(parsed);\n }\n }\n return GEMINI_ACP_STARTUP_TIMEOUT_MS;\n}\n\nfunction resolveClaudeAcpSessionCreateTimeoutMs(): number {\n const raw = process.env.ACPX_CLAUDE_ACP_SESSION_CREATE_TIMEOUT_MS;\n if (typeof raw === \"string\" && raw.trim().length > 0) {\n const parsed = Number(raw);\n if (Number.isFinite(parsed) && parsed > 0) {\n return Math.round(parsed);\n }\n }\n return CLAUDE_ACP_SESSION_CREATE_TIMEOUT_MS;\n}\n\nfunction parseGeminiVersion(value: string | undefined): GeminiVersion | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n\n const normalized = value.trim();\n const match = normalized.match(/(\\d+)\\.(\\d+)\\.(\\d+)/);\n if (!match) {\n return undefined;\n }\n\n return {\n raw: normalized,\n parts: [Number(match[1]), Number(match[2]), Number(match[3])],\n };\n}\n\nfunction compareVersionParts(left: readonly number[], right: readonly number[]): number {\n for (let index = 0; index < Math.max(left.length, right.length); index += 1) {\n const leftPart = left[index] ?? 0;\n const rightPart = right[index] ?? 0;\n if (leftPart !== rightPart) {\n return leftPart - rightPart;\n }\n }\n return 0;\n}\n\nasync function detectGeminiVersion(command: string): Promise<GeminiVersion | undefined> {\n return await new Promise<GeminiVersion | undefined>((resolve) => {\n const child = spawn(\n command,\n [\"--version\"],\n buildSpawnCommandOptions(command, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n }),\n );\n\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n const finish = (value: GeminiVersion | undefined) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timer);\n child.removeAllListeners();\n child.stdout?.removeAllListeners();\n child.stderr?.removeAllListeners();\n resolve(value);\n };\n const timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n finish(undefined);\n }, GEMINI_VERSION_TIMEOUT_MS);\n\n child.stdout?.setEncoding(\"utf8\");\n child.stderr?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (chunk: string) => {\n stdout += chunk;\n });\n child.stderr?.on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n child.once(\"error\", () => {\n finish(undefined);\n });\n child.once(\"close\", () => {\n const versionLine = `${stdout}\\n${stderr}`\n .split(/\\r?\\n/)\n .map((line) => line.trim())\n .find((line) => /\\d+\\.\\d+\\.\\d+/.test(line));\n finish(parseGeminiVersion(versionLine));\n });\n });\n}\n\nasync function resolveGeminiCommandArgs(\n command: string,\n args: readonly string[],\n): Promise<string[]> {\n if (basenameToken(command) !== \"gemini\" || !args.includes(\"--acp\")) {\n return [...args];\n }\n\n const version = await detectGeminiVersion(command);\n if (version && compareVersionParts(version.parts, GEMINI_ACP_FLAG_VERSION) < 0) {\n return args.map((arg) => (arg === \"--acp\" ? \"--experimental-acp\" : arg));\n }\n\n return [...args];\n}\n\nasync function readCommandOutput(\n command: string,\n args: readonly string[],\n timeoutMs: number,\n): Promise<string | undefined> {\n return await new Promise<string | undefined>((resolve) => {\n const child = spawn(\n command,\n [...args],\n buildSpawnCommandOptions(command, {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n windowsHide: true,\n }),\n );\n\n let stdout = \"\";\n let stderr = \"\";\n let settled = false;\n const finish = (value: string | undefined) => {\n if (settled) {\n return;\n }\n settled = true;\n clearTimeout(timer);\n child.removeAllListeners();\n child.stdout?.removeAllListeners();\n child.stderr?.removeAllListeners();\n resolve(value);\n };\n const timer = setTimeout(() => {\n child.kill(\"SIGKILL\");\n finish(undefined);\n }, timeoutMs);\n\n child.stdout?.setEncoding(\"utf8\");\n child.stderr?.setEncoding(\"utf8\");\n child.stdout?.on(\"data\", (chunk: string) => {\n stdout += chunk;\n });\n child.stderr?.on(\"data\", (chunk: string) => {\n stderr += chunk;\n });\n child.once(\"error\", () => {\n finish(undefined);\n });\n child.once(\"close\", () => {\n finish(`${stdout}\\n${stderr}`);\n });\n });\n}\n\nasync function buildGeminiAcpStartupTimeoutMessage(command: string): Promise<string> {\n const parts = [\n \"Gemini CLI ACP startup timed out before initialize completed.\",\n \"This usually means the local Gemini CLI is waiting on interactive OAuth or has incompatible ACP subprocess behavior.\",\n ];\n\n const version = await detectGeminiVersion(command);\n if (version) {\n parts.push(`Detected Gemini CLI version: ${version.raw}.`);\n }\n\n if (!process.env.GEMINI_API_KEY && !process.env.GOOGLE_API_KEY) {\n parts.push(\"No GEMINI_API_KEY or GOOGLE_API_KEY was set for non-interactive auth.\");\n }\n\n parts.push(\"Try upgrading Gemini CLI and using API-key-based auth for non-interactive ACP runs.\");\n return parts.join(\" \");\n}\n\nfunction buildClaudeAcpSessionCreateTimeoutMessage(): string {\n return [\n \"Claude ACP session creation timed out before session/new completed.\",\n \"This matches the known persistent-session stall seen with some Claude Code and @zed-industries/claude-agent-acp combinations.\",\n \"In harnessed or non-interactive runs, prefer --approve-all with nonInteractivePermissions=deny, upgrade Claude Code and the Claude ACP adapter, or use acpx claude exec as a one-shot fallback.\",\n ].join(\" \");\n}\n\nasync function buildCopilotAcpUnsupportedMessage(command: string): Promise<string> {\n const parts = [\n \"GitHub Copilot CLI ACP stdio mode is not available in the installed copilot binary.\",\n \"acpx copilot expects a Copilot CLI release that supports --acp --stdio.\",\n ];\n\n const helpOutput = await readCommandOutput(command, [\"--help\"], COPILOT_HELP_TIMEOUT_MS);\n if (typeof helpOutput === \"string\" && !helpOutput.includes(\"--acp\")) {\n parts.push(\"Detected copilot --help output without --acp support.\");\n }\n\n parts.push(\n \"Upgrade GitHub Copilot CLI to a release with ACP stdio support, or use --agent with another ACP-compatible adapter in the meantime.\",\n );\n return parts.join(\" \");\n}\n\nasync function ensureCopilotAcpSupport(command: string): Promise<void> {\n const helpOutput = await readCommandOutput(command, [\"--help\"], COPILOT_HELP_TIMEOUT_MS);\n if (typeof helpOutput === \"string\" && !helpOutput.includes(\"--acp\")) {\n throw new CopilotAcpUnsupportedError(await buildCopilotAcpUnsupportedMessage(command), {\n retryable: false,\n });\n }\n}\n\nfunction toEnvToken(value: string): string {\n return value\n .trim()\n .replace(/[^a-zA-Z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .toUpperCase();\n}\n\nfunction authEnvKeys(methodId: string): string[] {\n const token = toEnvToken(methodId);\n const keys = new Set<string>([methodId]);\n if (token) {\n keys.add(token);\n keys.add(`ACPX_AUTH_${token}`);\n }\n return [...keys];\n}\n\nfunction readEnvCredential(methodId: string): string | undefined {\n for (const key of authEnvKeys(methodId)) {\n const value = process.env[key];\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value;\n }\n }\n return undefined;\n}\n\nfunction buildClaudeCodeOptionsMeta(\n options: AcpClientOptions[\"sessionOptions\"],\n): Record<string, unknown> | undefined {\n if (!options) {\n return undefined;\n }\n\n const claudeCodeOptions: Record<string, unknown> = {};\n if (typeof options.model === \"string\" && options.model.trim().length > 0) {\n claudeCodeOptions.model = options.model;\n }\n if (Array.isArray(options.allowedTools)) {\n claudeCodeOptions.allowedTools = [...options.allowedTools];\n }\n if (typeof options.maxTurns === \"number\") {\n claudeCodeOptions.maxTurns = options.maxTurns;\n }\n\n if (Object.keys(claudeCodeOptions).length === 0) {\n return undefined;\n }\n\n return {\n claudeCode: {\n options: claudeCodeOptions,\n },\n };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction isLikelySessionControlUnsupportedError(acp: {\n code: number;\n message: string;\n data?: unknown;\n}): boolean {\n if (SESSION_CONTROL_UNSUPPORTED_ACP_CODES.has(acp.code)) {\n return true;\n }\n\n if (acp.code !== -32603) {\n return false;\n }\n\n const details = asRecord(acp.data)?.details;\n return typeof details === \"string\" && details.toLowerCase().includes(\"invalid params\");\n}\n\nfunction formatSessionControlAcpSummary(acp: {\n code: number;\n message: string;\n data?: unknown;\n}): string {\n const details = asRecord(acp.data)?.details;\n if (typeof details === \"string\" && details.trim().length > 0) {\n return `${details.trim()} (ACP ${acp.code}, adapter reported \"${acp.message}\")`;\n }\n return `${acp.message} (ACP ${acp.code})`;\n}\n\nfunction maybeWrapSessionControlError(\n method: \"session/set_mode\" | \"session/set_config_option\",\n error: unknown,\n context?: string,\n): unknown {\n const acp = extractAcpError(error);\n if (!acp || !isLikelySessionControlUnsupportedError(acp)) {\n return error;\n }\n\n const acpSummary = formatSessionControlAcpSummary(acp);\n const contextSuffix = context ? ` ${context}` : \"\";\n const message =\n `Agent rejected ${method}${contextSuffix}: ${acpSummary}. ` +\n `The adapter may not implement ${method}, or the requested value is not supported.`;\n const wrapped = new Error(message, {\n cause: error instanceof Error ? error : undefined,\n }) as Error & {\n acp?: typeof acp;\n };\n wrapped.acp = acp;\n return wrapped;\n}\n\nfunction buildAgentEnvironment(\n authCredentials: Record<string, string> | undefined,\n): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env };\n if (!authCredentials) {\n return env;\n }\n\n for (const [methodId, credential] of Object.entries(authCredentials)) {\n if (typeof credential !== \"string\" || credential.trim().length === 0) {\n continue;\n }\n\n if (!methodId.includes(\"=\") && !methodId.includes(\"\\u0000\") && env[methodId] == null) {\n env[methodId] = credential;\n }\n\n const normalized = toEnvToken(methodId);\n if (normalized) {\n const prefixed = `ACPX_AUTH_${normalized}`;\n if (env[prefixed] == null) {\n env[prefixed] = credential;\n }\n if (env[normalized] == null) {\n env[normalized] = credential;\n }\n }\n }\n\n return env;\n}\n\nexport function buildAgentSpawnOptions(\n cwd: string,\n authCredentials: Record<string, string> | undefined,\n): {\n cwd: string;\n env: NodeJS.ProcessEnv;\n stdio: [\"pipe\", \"pipe\", \"pipe\"];\n windowsHide: true;\n} {\n return {\n cwd,\n env: buildAgentEnvironment(authCredentials),\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n windowsHide: true,\n };\n}\n\nexport class AcpClient {\n private options: AcpClientOptions;\n private connection?: ClientSideConnection;\n private agent?: ChildProcessByStdio<Writable, Readable, Readable>;\n private initResult?: InitializeResponse;\n private loadedSessionId?: string;\n private eventHandlers: Pick<\n AcpClientOptions,\n \"onAcpMessage\" | \"onAcpOutputMessage\" | \"onSessionUpdate\" | \"onClientOperation\"\n >;\n private readonly permissionStats: PermissionStats = {\n requested: 0,\n approved: 0,\n denied: 0,\n cancelled: 0,\n };\n private readonly filesystem: FileSystemHandlers;\n private readonly terminalManager: TerminalManager;\n private sessionUpdateChain: Promise<void> = Promise.resolve();\n private observedSessionUpdates = 0;\n private processedSessionUpdates = 0;\n private suppressSessionUpdates = false;\n private suppressReplaySessionUpdateMessages = false;\n private activePrompt?: {\n sessionId: string;\n promise: Promise<PromptResponse>;\n };\n private readonly cancellingSessionIds = new Set<string>();\n private closing = false;\n private agentStartedAt?: string;\n private lastAgentExit?: AgentExitInfo;\n private lastKnownPid?: number;\n private readonly promptPermissionFailures = new Map<string, PermissionPromptUnavailableError>();\n\n constructor(options: AcpClientOptions) {\n this.options = {\n ...options,\n cwd: asAbsoluteCwd(options.cwd),\n authPolicy: options.authPolicy ?? \"skip\",\n };\n this.eventHandlers = {\n onAcpMessage: this.options.onAcpMessage,\n onAcpOutputMessage: this.options.onAcpOutputMessage,\n onSessionUpdate: this.options.onSessionUpdate,\n onClientOperation: this.options.onClientOperation,\n };\n\n this.filesystem = new FileSystemHandlers({\n cwd: this.options.cwd,\n permissionMode: this.options.permissionMode,\n nonInteractivePermissions: this.options.nonInteractivePermissions,\n onOperation: (operation) => {\n this.eventHandlers.onClientOperation?.(operation);\n },\n });\n this.terminalManager = new TerminalManager({\n cwd: this.options.cwd,\n permissionMode: this.options.permissionMode,\n nonInteractivePermissions: this.options.nonInteractivePermissions,\n onOperation: (operation) => {\n this.eventHandlers.onClientOperation?.(operation);\n },\n });\n }\n\n get initializeResult(): InitializeResponse | undefined {\n return this.initResult;\n }\n\n getAgentPid(): number | undefined {\n return this.agent?.pid ?? this.lastKnownPid;\n }\n\n getPermissionStats(): PermissionStats {\n return { ...this.permissionStats };\n }\n\n getAgentLifecycleSnapshot(): AgentLifecycleSnapshot {\n const pid = this.agent?.pid ?? this.lastKnownPid;\n const running =\n Boolean(this.agent) &&\n this.agent?.exitCode == null &&\n this.agent?.signalCode == null &&\n !this.agent?.killed;\n return {\n pid,\n startedAt: this.agentStartedAt,\n running,\n lastExit: this.lastAgentExit ? { ...this.lastAgentExit } : undefined,\n };\n }\n\n supportsLoadSession(): boolean {\n return Boolean(this.initResult?.agentCapabilities?.loadSession);\n }\n\n setEventHandlers(\n handlers: Pick<\n AcpClientOptions,\n \"onAcpMessage\" | \"onAcpOutputMessage\" | \"onSessionUpdate\" | \"onClientOperation\"\n >,\n ): void {\n this.eventHandlers = { ...handlers };\n }\n\n clearEventHandlers(): void {\n this.eventHandlers = {};\n }\n\n updateRuntimeOptions(options: {\n permissionMode?: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n suppressSdkConsoleErrors?: boolean;\n verbose?: boolean;\n }): void {\n if (options.permissionMode) {\n this.options.permissionMode = options.permissionMode;\n }\n if (options.nonInteractivePermissions !== undefined) {\n this.options.nonInteractivePermissions = options.nonInteractivePermissions;\n }\n if (options.permissionMode || options.nonInteractivePermissions !== undefined) {\n this.filesystem.updatePermissionPolicy(\n this.options.permissionMode,\n this.options.nonInteractivePermissions,\n );\n this.terminalManager.updatePermissionPolicy(\n this.options.permissionMode,\n this.options.nonInteractivePermissions,\n );\n }\n if (options.suppressSdkConsoleErrors !== undefined) {\n this.options.suppressSdkConsoleErrors = options.suppressSdkConsoleErrors;\n }\n if (options.verbose !== undefined) {\n this.options.verbose = options.verbose;\n }\n }\n\n hasReusableSession(sessionId: string): boolean {\n return (\n this.connection != null &&\n this.agent != null &&\n isChildProcessRunning(this.agent) &&\n this.loadedSessionId === sessionId\n );\n }\n\n hasActivePrompt(sessionId?: string): boolean {\n if (!this.activePrompt) {\n return false;\n }\n if (sessionId == null) {\n return true;\n }\n return this.activePrompt.sessionId === sessionId;\n }\n\n async start(): Promise<void> {\n if (this.connection && this.agent && isChildProcessRunning(this.agent)) {\n return;\n }\n if (this.connection || this.agent) {\n await this.close();\n }\n\n const { command, args: initialArgs } = splitCommandLine(this.options.agentCommand);\n const args = await resolveGeminiCommandArgs(command, initialArgs);\n this.log(`spawning agent: ${command} ${args.join(\" \")}`);\n const geminiAcp = isGeminiAcpCommand(command, args);\n const copilotAcp = isCopilotAcpCommand(command, args);\n\n if (copilotAcp) {\n await ensureCopilotAcpSupport(command);\n }\n\n const spawnedChild = spawn(\n command,\n args,\n buildSpawnCommandOptions(\n command,\n buildAgentSpawnOptions(this.options.cwd, this.options.authCredentials),\n ),\n ) as ChildProcessByStdio<Writable, Readable, Readable>;\n\n try {\n await waitForSpawn(spawnedChild);\n } catch (error) {\n throw new AgentSpawnError(this.options.agentCommand, error);\n }\n const child = requireAgentStdio(spawnedChild);\n this.closing = false;\n this.agentStartedAt = isoNow();\n this.lastAgentExit = undefined;\n this.lastKnownPid = child.pid ?? undefined;\n this.attachAgentLifecycleObservers(child);\n\n child.stderr.on(\"data\", (chunk: Buffer | string) => {\n if (!this.options.verbose) {\n return;\n }\n process.stderr.write(chunk);\n });\n\n const input = Writable.toWeb(child.stdin);\n const output = Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>;\n const stream = this.createTappedStream(ndJsonStream(input, output));\n\n const connection = new ClientSideConnection(\n () => ({\n sessionUpdate: async (params: SessionNotification) => {\n await this.handleSessionUpdate(params);\n },\n requestPermission: async (\n params: RequestPermissionRequest,\n ): Promise<RequestPermissionResponse> => {\n return this.handlePermissionRequest(params);\n },\n readTextFile: async (params: ReadTextFileRequest): Promise<ReadTextFileResponse> => {\n return this.handleReadTextFile(params);\n },\n writeTextFile: async (params: WriteTextFileRequest): Promise<WriteTextFileResponse> => {\n return this.handleWriteTextFile(params);\n },\n createTerminal: async (params: CreateTerminalRequest): Promise<CreateTerminalResponse> => {\n return this.handleCreateTerminal(params);\n },\n terminalOutput: async (params: TerminalOutputRequest): Promise<TerminalOutputResponse> => {\n return this.handleTerminalOutput(params);\n },\n waitForTerminalExit: async (\n params: WaitForTerminalExitRequest,\n ): Promise<WaitForTerminalExitResponse> => {\n return this.handleWaitForTerminalExit(params);\n },\n killTerminal: async (params: KillTerminalRequest): Promise<KillTerminalResponse> => {\n return this.handleKillTerminal(params);\n },\n releaseTerminal: async (\n params: ReleaseTerminalRequest,\n ): Promise<ReleaseTerminalResponse> => {\n return this.handleReleaseTerminal(params);\n },\n }),\n stream,\n );\n connection.signal.addEventListener(\n \"abort\",\n () => {\n this.recordAgentExit(\"connection_close\", child.exitCode ?? null, child.signalCode ?? null);\n },\n { once: true },\n );\n\n try {\n const initializePromise = connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {\n fs: {\n readTextFile: true,\n writeTextFile: true,\n },\n terminal: true,\n },\n clientInfo: {\n name: \"acpx\",\n version: \"0.1.0\",\n },\n });\n const initResult = geminiAcp\n ? await withTimeout(initializePromise, resolveGeminiAcpStartupTimeoutMs())\n : await initializePromise;\n\n await this.authenticateIfRequired(connection, initResult.authMethods ?? []);\n\n this.connection = connection;\n this.agent = child;\n this.initResult = initResult;\n this.log(`initialized protocol version ${initResult.protocolVersion}`);\n } catch (error) {\n child.kill();\n if (geminiAcp && error instanceof TimeoutError) {\n throw new GeminiAcpStartupTimeoutError(await buildGeminiAcpStartupTimeoutMessage(command), {\n cause: error,\n retryable: true,\n });\n }\n throw error;\n }\n }\n\n private createTappedStream(base: {\n readable: ReadableStream<AnyMessage>;\n writable: WritableStream<AnyMessage>;\n }): {\n readable: ReadableStream<AnyMessage>;\n writable: WritableStream<AnyMessage>;\n } {\n const onAcpMessage = () => this.eventHandlers.onAcpMessage;\n const onAcpOutputMessage = () => this.eventHandlers.onAcpOutputMessage;\n\n const shouldSuppressInboundReplaySessionUpdate = (message: AnyMessage): boolean => {\n return this.suppressReplaySessionUpdateMessages && isSessionUpdateNotification(message);\n };\n\n const readable = new ReadableStream<AnyMessage>({\n async start(controller) {\n const reader = base.readable.getReader();\n try {\n while (true) {\n const { value, done } = await reader.read();\n if (done) {\n break;\n }\n if (!value) {\n continue;\n }\n if (!shouldSuppressInboundReplaySessionUpdate(value)) {\n onAcpOutputMessage()?.(\"inbound\", value);\n onAcpMessage()?.(\"inbound\", value);\n }\n controller.enqueue(value);\n }\n } finally {\n reader.releaseLock();\n controller.close();\n }\n },\n });\n\n const writable = new WritableStream<AnyMessage>({\n async write(message) {\n onAcpOutputMessage()?.(\"outbound\", message);\n onAcpMessage()?.(\"outbound\", message);\n const writer = base.writable.getWriter();\n try {\n await writer.write(message);\n } finally {\n writer.releaseLock();\n }\n },\n });\n\n return { readable, writable };\n }\n\n async createSession(cwd = this.options.cwd): Promise<SessionCreateResult> {\n const connection = this.getConnection();\n const { command, args } = splitCommandLine(this.options.agentCommand);\n const claudeAcp = isClaudeAcpCommand(command, args);\n\n let result: Awaited<ReturnType<typeof connection.newSession>>;\n try {\n const createPromise = connection.newSession({\n cwd: asAbsoluteCwd(cwd),\n mcpServers: this.options.mcpServers ?? [],\n _meta: buildClaudeCodeOptionsMeta(this.options.sessionOptions),\n });\n result = claudeAcp\n ? await withTimeout(createPromise, resolveClaudeAcpSessionCreateTimeoutMs())\n : await createPromise;\n } catch (error) {\n if (claudeAcp && error instanceof TimeoutError) {\n throw new ClaudeAcpSessionCreateTimeoutError(buildClaudeAcpSessionCreateTimeoutMessage(), {\n cause: error,\n retryable: true,\n });\n }\n throw error;\n }\n\n this.loadedSessionId = result.sessionId;\n return {\n sessionId: result.sessionId,\n agentSessionId: extractRuntimeSessionId(result._meta),\n };\n }\n\n async loadSession(sessionId: string, cwd = this.options.cwd): Promise<SessionLoadResult> {\n this.getConnection();\n return await this.loadSessionWithOptions(sessionId, cwd, {});\n }\n\n async loadSessionWithOptions(\n sessionId: string,\n cwd = this.options.cwd,\n options: LoadSessionOptions = {},\n ): Promise<SessionLoadResult> {\n const connection = this.getConnection();\n const previousSuppression = this.suppressSessionUpdates;\n const previousReplaySuppression = this.suppressReplaySessionUpdateMessages;\n this.suppressSessionUpdates = previousSuppression || Boolean(options.suppressReplayUpdates);\n this.suppressReplaySessionUpdateMessages =\n previousReplaySuppression || Boolean(options.suppressReplayUpdates);\n\n let response: LoadSessionResponse | undefined;\n\n try {\n response = await connection.loadSession({\n sessionId,\n cwd: asAbsoluteCwd(cwd),\n mcpServers: this.options.mcpServers ?? [],\n });\n\n await this.waitForSessionUpdateDrain(\n options.replayIdleMs ?? REPLAY_IDLE_MS,\n options.replayDrainTimeoutMs ?? REPLAY_DRAIN_TIMEOUT_MS,\n );\n } finally {\n this.suppressSessionUpdates = previousSuppression;\n this.suppressReplaySessionUpdateMessages = previousReplaySuppression;\n }\n\n this.loadedSessionId = sessionId;\n return {\n agentSessionId: extractRuntimeSessionId(response?._meta),\n };\n }\n\n async prompt(sessionId: string, prompt: PromptInput | string): Promise<PromptResponse> {\n const connection = this.getConnection();\n const restoreConsoleError = this.options.suppressSdkConsoleErrors\n ? installSdkConsoleErrorSuppression()\n : undefined;\n\n let promptPromise: Promise<PromptResponse>;\n try {\n promptPromise = connection.prompt({\n sessionId,\n prompt: typeof prompt === \"string\" ? textPrompt(prompt) : prompt,\n });\n } catch (error) {\n restoreConsoleError?.();\n throw error;\n }\n\n this.activePrompt = {\n sessionId,\n promise: promptPromise,\n };\n\n try {\n const response = await promptPromise;\n const permissionFailure = this.consumePromptPermissionFailure(sessionId);\n if (permissionFailure) {\n throw permissionFailure;\n }\n return response;\n } catch (error) {\n const permissionFailure = this.consumePromptPermissionFailure(sessionId);\n if (permissionFailure) {\n throw permissionFailure;\n }\n throw error;\n } finally {\n restoreConsoleError?.();\n if (this.activePrompt?.promise === promptPromise) {\n this.activePrompt = undefined;\n }\n this.cancellingSessionIds.delete(sessionId);\n this.promptPermissionFailures.delete(sessionId);\n }\n }\n\n async setSessionMode(sessionId: string, modeId: string): Promise<void> {\n const connection = this.getConnection();\n try {\n await connection.setSessionMode({\n sessionId,\n modeId,\n });\n } catch (error) {\n throw maybeWrapSessionControlError(\"session/set_mode\", error, `for mode \"${modeId}\"`);\n }\n }\n\n async setSessionConfigOption(\n sessionId: string,\n configId: string,\n value: string,\n ): Promise<SetSessionConfigOptionResponse> {\n const connection = this.getConnection();\n try {\n return await connection.setSessionConfigOption({\n sessionId,\n configId,\n value,\n });\n } catch (error) {\n throw maybeWrapSessionControlError(\n \"session/set_config_option\",\n error,\n `for \"${configId}\"=\"${value}\"`,\n );\n }\n }\n\n async cancel(sessionId: string): Promise<void> {\n const connection = this.getConnection();\n this.cancellingSessionIds.add(sessionId);\n await connection.cancel({\n sessionId,\n });\n }\n\n async requestCancelActivePrompt(): Promise<boolean> {\n const active = this.activePrompt;\n if (!active) {\n return false;\n }\n await this.cancel(active.sessionId);\n return true;\n }\n\n async cancelActivePrompt(waitMs = 2_500): Promise<PromptResponse | undefined> {\n const active = this.activePrompt;\n if (!active) {\n return undefined;\n }\n\n try {\n await this.cancel(active.sessionId);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.log(`failed to send session/cancel: ${message}`);\n }\n\n if (waitMs <= 0) {\n return undefined;\n }\n\n let timer: NodeJS.Timeout | number | undefined;\n const timeoutPromise = new Promise<undefined>((resolve) => {\n timer = setTimeout(resolve, waitMs);\n });\n\n try {\n return await Promise.race([\n active.promise.then(\n (response) => response,\n () => undefined,\n ),\n timeoutPromise,\n ]);\n } finally {\n if (timer) {\n clearTimeout(timer);\n }\n }\n }\n\n async close(): Promise<void> {\n this.closing = true;\n\n await this.terminalManager.shutdown();\n\n const agent = this.agent;\n if (agent) {\n await this.terminateAgentProcess(agent);\n }\n\n this.sessionUpdateChain = Promise.resolve();\n this.observedSessionUpdates = 0;\n this.processedSessionUpdates = 0;\n this.suppressSessionUpdates = false;\n this.suppressReplaySessionUpdateMessages = false;\n this.activePrompt = undefined;\n this.cancellingSessionIds.clear();\n this.promptPermissionFailures.clear();\n this.loadedSessionId = undefined;\n this.initResult = undefined;\n this.connection = undefined;\n this.agent = undefined;\n }\n\n private async terminateAgentProcess(\n child: ChildProcessByStdio<Writable, Readable, Readable>,\n ): Promise<void> {\n // Closing stdin is the most graceful shutdown signal for stdio-based ACP agents.\n if (!child.stdin.destroyed) {\n try {\n child.stdin.end();\n } catch {\n // best effort\n }\n }\n\n let exited = await waitForChildExit(child, AGENT_CLOSE_AFTER_STDIN_END_MS);\n if (!exited && isChildProcessRunning(child)) {\n try {\n child.kill(\"SIGTERM\");\n } catch {\n // best effort\n }\n exited = await waitForChildExit(child, AGENT_CLOSE_TERM_GRACE_MS);\n }\n\n if (!exited && isChildProcessRunning(child)) {\n this.log(`agent did not exit after ${AGENT_CLOSE_TERM_GRACE_MS}ms; forcing SIGKILL`);\n try {\n child.kill(\"SIGKILL\");\n } catch {\n // best effort\n }\n exited = await waitForChildExit(child, AGENT_CLOSE_KILL_GRACE_MS);\n }\n\n // Ensure stdio handles don't keep this process alive after close() returns.\n this.detachAgentHandles(child, !exited);\n }\n\n private detachAgentHandles(agent: ChildProcess, unref: boolean): void {\n const stdin = agent.stdin;\n const stdout = agent.stdout;\n const stderr = agent.stderr;\n\n stdin?.destroy();\n stdout?.destroy();\n stderr?.destroy();\n\n if (unref) {\n try {\n agent.unref();\n } catch {\n // best effort\n }\n }\n }\n\n private getConnection(): ClientSideConnection {\n if (!this.connection) {\n throw new Error(\"ACP client not started\");\n }\n return this.connection;\n }\n\n private log(message: string): void {\n if (!this.options.verbose) {\n return;\n }\n process.stderr.write(`[acpx] ${message}\\n`);\n }\n\n private selectAuthMethod(methods: AuthMethod[]): AuthSelection | undefined {\n const configCredentials = this.options.authCredentials ?? {};\n\n for (const method of methods) {\n const envCredential = readEnvCredential(method.id);\n if (envCredential) {\n return {\n methodId: method.id,\n credential: envCredential,\n source: \"env\",\n };\n }\n\n const configCredential =\n configCredentials[method.id] ?? configCredentials[toEnvToken(method.id)];\n if (typeof configCredential === \"string\" && configCredential.trim().length > 0) {\n return {\n methodId: method.id,\n credential: configCredential,\n source: \"config\",\n };\n }\n }\n\n return undefined;\n }\n\n private async authenticateIfRequired(\n connection: ClientSideConnection,\n methods: AuthMethod[],\n ): Promise<void> {\n if (methods.length === 0) {\n return;\n }\n\n const selected = this.selectAuthMethod(methods);\n if (!selected) {\n if (this.options.authPolicy === \"fail\") {\n throw new AuthPolicyError(\n `agent advertised auth methods [${methods.map((m) => m.id).join(\", \")}] but no matching credentials found`,\n );\n }\n\n this.log(\n `agent advertised auth methods [${methods.map((m) => m.id).join(\", \")}] but no matching credentials found — skipping (agent may handle auth internally)`,\n );\n return;\n }\n\n await connection.authenticate({\n methodId: selected.methodId,\n });\n\n this.log(`authenticated with method ${selected.methodId} (${selected.source})`);\n }\n\n private async handlePermissionRequest(\n params: RequestPermissionRequest,\n ): Promise<RequestPermissionResponse> {\n if (this.cancellingSessionIds.has(params.sessionId)) {\n return {\n outcome: {\n outcome: \"cancelled\",\n },\n };\n }\n\n let response: RequestPermissionResponse;\n try {\n response = await resolvePermissionRequest(\n params,\n this.options.permissionMode,\n this.options.nonInteractivePermissions ?? \"deny\",\n );\n } catch (error) {\n if (error instanceof PermissionPromptUnavailableError) {\n this.notePromptPermissionFailure(params.sessionId, error);\n this.recordPermissionDecision(\"cancelled\");\n return {\n outcome: {\n outcome: \"cancelled\",\n },\n };\n }\n throw error;\n }\n\n const decision = classifyPermissionDecision(params, response);\n this.recordPermissionDecision(decision);\n\n return response;\n }\n\n private attachAgentLifecycleObservers(\n child: ChildProcessByStdio<Writable, Readable, Readable>,\n ): void {\n child.once(\"exit\", (exitCode, signal) => {\n this.recordAgentExit(\"process_exit\", exitCode, signal);\n });\n\n child.once(\"close\", (exitCode, signal) => {\n this.recordAgentExit(\"process_close\", exitCode, signal);\n });\n\n child.stdout.once(\"close\", () => {\n this.recordAgentExit(\"pipe_close\", child.exitCode ?? null, child.signalCode ?? null);\n });\n }\n\n private recordAgentExit(\n reason: AgentDisconnectReason,\n exitCode: number | null,\n signal: NodeJS.Signals | null,\n ): void {\n if (this.lastAgentExit) {\n return;\n }\n\n this.lastAgentExit = {\n exitCode,\n signal,\n exitedAt: isoNow(),\n reason,\n unexpectedDuringPrompt: !this.closing && Boolean(this.activePrompt),\n };\n }\n\n private notePromptPermissionFailure(\n sessionId: string,\n error: PermissionPromptUnavailableError,\n ): void {\n if (!this.promptPermissionFailures.has(sessionId)) {\n this.promptPermissionFailures.set(sessionId, error);\n }\n }\n\n private consumePromptPermissionFailure(\n sessionId: string,\n ): PermissionPromptUnavailableError | undefined {\n const error = this.promptPermissionFailures.get(sessionId);\n if (error) {\n this.promptPermissionFailures.delete(sessionId);\n }\n return error;\n }\n\n private async handleReadTextFile(params: ReadTextFileRequest): Promise<ReadTextFileResponse> {\n try {\n return await this.filesystem.readTextFile(params);\n } catch (error) {\n this.recordPermissionError(params.sessionId, error);\n throw error;\n }\n }\n\n private async handleWriteTextFile(params: WriteTextFileRequest): Promise<WriteTextFileResponse> {\n try {\n return await this.filesystem.writeTextFile(params);\n } catch (error) {\n this.recordPermissionError(params.sessionId, error);\n throw error;\n }\n }\n\n private async handleCreateTerminal(\n params: CreateTerminalRequest,\n ): Promise<CreateTerminalResponse> {\n try {\n return await this.terminalManager.createTerminal(params);\n } catch (error) {\n this.recordPermissionError(params.sessionId, error);\n throw error;\n }\n }\n\n private async handleTerminalOutput(\n params: TerminalOutputRequest,\n ): Promise<TerminalOutputResponse> {\n return await this.terminalManager.terminalOutput(params);\n }\n\n private async handleWaitForTerminalExit(\n params: WaitForTerminalExitRequest,\n ): Promise<WaitForTerminalExitResponse> {\n return await this.terminalManager.waitForTerminalExit(params);\n }\n\n private async handleKillTerminal(params: KillTerminalRequest): Promise<KillTerminalResponse> {\n return await this.terminalManager.killTerminal(params);\n }\n\n private async handleReleaseTerminal(\n params: ReleaseTerminalRequest,\n ): Promise<ReleaseTerminalResponse> {\n return await this.terminalManager.releaseTerminal(params);\n }\n\n private recordPermissionDecision(decision: \"approved\" | \"denied\" | \"cancelled\"): void {\n this.permissionStats.requested += 1;\n if (decision === \"approved\") {\n this.permissionStats.approved += 1;\n return;\n }\n if (decision === \"denied\") {\n this.permissionStats.denied += 1;\n return;\n }\n this.permissionStats.cancelled += 1;\n }\n\n private recordPermissionError(sessionId: string, error: unknown): void {\n if (error instanceof PermissionPromptUnavailableError) {\n this.notePromptPermissionFailure(sessionId, error);\n this.recordPermissionDecision(\"cancelled\");\n return;\n }\n if (error instanceof PermissionDeniedError) {\n this.recordPermissionDecision(\"denied\");\n }\n }\n\n private async handleSessionUpdate(notification: SessionNotification): Promise<void> {\n const sequence = ++this.observedSessionUpdates;\n this.sessionUpdateChain = this.sessionUpdateChain.then(async () => {\n try {\n if (!this.suppressSessionUpdates) {\n this.eventHandlers.onSessionUpdate?.(notification);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n this.log(`session update handler failed: ${message}`);\n } finally {\n this.processedSessionUpdates = sequence;\n }\n });\n\n await this.sessionUpdateChain;\n }\n\n private async waitForSessionUpdateDrain(idleMs: number, timeoutMs: number): Promise<void> {\n const normalizedIdleMs = Math.max(0, idleMs);\n const normalizedTimeoutMs = Math.max(normalizedIdleMs, timeoutMs);\n const deadline = Date.now() + normalizedTimeoutMs;\n let lastObserved = this.observedSessionUpdates;\n let idleSince = Date.now();\n\n while (Date.now() <= deadline) {\n const observed = this.observedSessionUpdates;\n if (observed !== lastObserved) {\n lastObserved = observed;\n idleSince = Date.now();\n }\n\n if (\n this.processedSessionUpdates === this.observedSessionUpdates &&\n Date.now() - idleSince >= normalizedIdleMs\n ) {\n await this.sessionUpdateChain;\n if (this.processedSessionUpdates === this.observedSessionUpdates) {\n return;\n }\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, DRAIN_POLL_INTERVAL_MS);\n });\n }\n\n throw new Error(`Timed out waiting for session replay drain after ${normalizedTimeoutMs}ms`);\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getPerfMetricsSnapshot, resetPerfMetrics } from \"./perf-metrics.js\";\n\nconst PERF_METRICS_FILE_ENV = \"ACPX_PERF_METRICS_FILE\";\n\nlet installed = false;\nlet flushed = false;\nlet captureFilePath: string | undefined;\nlet captureRole = \"cli\";\nlet captureArgv: string[] = [];\nlet captureSequence = 0;\n\ntype CaptureReason = \"checkpoint\" | \"exit\" | \"signal\";\n\nfunction shouldCapture(): boolean {\n return typeof captureFilePath === \"string\" && captureFilePath.trim().length > 0;\n}\n\nfunction buildPayload(reason: CaptureReason): Record<string, unknown> {\n return {\n timestamp: new Date().toISOString(),\n pid: process.pid,\n ppid: process.ppid,\n role: captureRole,\n argv: captureArgv,\n cwd: process.cwd(),\n sequence: captureSequence,\n reason,\n metrics: getPerfMetricsSnapshot(),\n };\n}\n\nfunction writePerfMetricsCapture(reason: CaptureReason, resetAfterWrite: boolean): boolean {\n if (!shouldCapture()) {\n return false;\n }\n\n const payload = buildPayload(reason);\n const metrics = payload.metrics as {\n counters?: Record<string, number>;\n gauges?: Record<string, number>;\n timings?: Record<string, unknown>;\n };\n const hasData =\n Object.keys(metrics.counters ?? {}).length > 0 ||\n Object.keys(metrics.gauges ?? {}).length > 0 ||\n Object.keys(metrics.timings ?? {}).length > 0;\n if (!hasData) {\n return false;\n }\n\n try {\n fs.mkdirSync(path.dirname(captureFilePath!), { recursive: true });\n fs.appendFileSync(captureFilePath!, `${JSON.stringify(payload)}\\n`, \"utf8\");\n captureSequence += 1;\n if (resetAfterWrite) {\n resetPerfMetrics();\n }\n return true;\n } catch {\n // metrics capture is best-effort only\n return false;\n }\n}\n\nexport function checkpointPerfMetricsCapture(): void {\n flushed = false;\n writePerfMetricsCapture(\"checkpoint\", true);\n}\n\nexport function flushPerfMetricsCapture(reason: CaptureReason = \"exit\"): void {\n if (flushed || !shouldCapture()) {\n return;\n }\n flushed = true;\n writePerfMetricsCapture(reason, false);\n}\n\nexport function installPerfMetricsCapture(\n options: {\n argv?: string[];\n role?: string;\n filePath?: string;\n } = {},\n): void {\n captureFilePath = options.filePath ?? process.env[PERF_METRICS_FILE_ENV];\n if (!shouldCapture()) {\n return;\n }\n\n resetPerfMetrics();\n captureRole = options.role ?? captureRole;\n captureArgv = options.argv ?? [];\n captureSequence = 0;\n flushed = false;\n\n if (installed) {\n return;\n }\n installed = true;\n\n process.once(\"exit\", () => {\n flushPerfMetricsCapture(\"exit\");\n });\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) {\n const handler = () => {\n flushPerfMetricsCapture(\"signal\");\n process.removeListener(signal, handler);\n process.kill(process.pid, signal);\n };\n process.once(signal, handler);\n }\n}\n\nexport function perfMetricsCaptureFileFromEnv(\n env: NodeJS.ProcessEnv = process.env,\n): string | undefined {\n const value = env[PERF_METRICS_FILE_ENV];\n if (typeof value !== \"string\" || value.trim().length === 0) {\n return undefined;\n }\n return value;\n}\n","import { randomUUID } from \"node:crypto\";\nimport type {\n ContentBlock,\n SessionNotification,\n SessionUpdate,\n ToolCall,\n ToolCallUpdate,\n UsageUpdate,\n} from \"@agentclientprotocol/sdk\";\nimport { textPrompt } from \"./prompt-content.js\";\nimport type {\n ClientOperation,\n PromptInput,\n SessionAcpxState,\n SessionConversation,\n SessionAgentContent,\n SessionAgentMessage,\n SessionMessage,\n SessionTokenUsage,\n SessionToolResult,\n SessionToolResultContent,\n SessionToolUse,\n SessionUserContent,\n} from \"./types.js\";\n\nexport type LegacyHistoryEntry = {\n role: \"user\" | \"assistant\";\n timestamp: string;\n textPreview: string;\n};\n\nconst MAX_RUNTIME_MESSAGES = 200;\nconst MAX_RUNTIME_AGENT_TEXT_CHARS = 8_000;\nconst MAX_RUNTIME_THINKING_CHARS = 4_000;\nconst MAX_RUNTIME_TOOL_IO_CHARS = 4_000;\nconst MAX_RUNTIME_REQUEST_TOKEN_USAGE = 100;\n\nfunction isoNow(): string {\n return new Date().toISOString();\n}\n\nfunction deepClone<T>(value: T): T {\n try {\n return structuredClone(value);\n } catch {\n return value;\n }\n}\n\nfunction hasOwn(source: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(source, key);\n}\n\nfunction normalizeAgentName(value: unknown): string | undefined {\n if (typeof value !== \"string\") {\n return undefined;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction extractText(content: ContentBlock): string | undefined {\n if (content.type === \"text\") {\n return content.text;\n }\n\n if (content.type === \"resource_link\") {\n return content.title ?? content.name ?? content.uri;\n }\n\n if (content.type === \"resource\") {\n if (\"text\" in content.resource && typeof content.resource.text === \"string\") {\n return content.resource.text;\n }\n return content.resource.uri;\n }\n\n return undefined;\n}\n\nfunction contentToUserContent(content: ContentBlock): SessionUserContent | undefined {\n if (content.type === \"text\") {\n return {\n Text: content.text,\n };\n }\n\n if (content.type === \"resource_link\") {\n const value = content.title ?? content.name ?? content.uri;\n return {\n Mention: {\n uri: content.uri,\n content: value,\n },\n };\n }\n\n if (content.type === \"resource\") {\n if (\"text\" in content.resource && typeof content.resource.text === \"string\") {\n return {\n Text: content.resource.text,\n };\n }\n\n return {\n Mention: {\n uri: content.resource.uri,\n content: content.resource.uri,\n },\n };\n }\n\n if (content.type === \"image\") {\n return {\n Image: {\n source: content.data,\n size: null,\n },\n };\n }\n\n return undefined;\n}\n\nfunction nextUserMessageId(): string {\n return randomUUID();\n}\n\nfunction isUserMessage(message: SessionMessage): message is {\n User: SessionConversation[\"messages\"][number] extends infer T\n ? T extends { User: infer U }\n ? U\n : never\n : never;\n} {\n return typeof message === \"object\" && message !== null && hasOwn(message, \"User\");\n}\n\nfunction isAgentMessage(message: SessionMessage): message is { Agent: SessionAgentMessage } {\n return typeof message === \"object\" && message !== null && hasOwn(message, \"Agent\");\n}\n\nfunction isAgentTextContent(content: SessionAgentContent): content is { Text: string } {\n return hasOwn(content, \"Text\");\n}\n\nfunction isAgentThinkingContent(\n content: SessionAgentContent,\n): content is { Thinking: { text: string; signature?: string | null } } {\n return hasOwn(content, \"Thinking\");\n}\n\nfunction isAgentToolUseContent(\n content: SessionAgentContent,\n): content is { ToolUse: SessionToolUse } {\n return hasOwn(content, \"ToolUse\");\n}\n\nfunction updateConversationTimestamp(conversation: SessionConversation, timestamp: string): void {\n conversation.updated_at = timestamp;\n}\n\nfunction ensureAgentMessage(conversation: SessionConversation): SessionAgentMessage {\n const last = conversation.messages.at(-1);\n if (last && isAgentMessage(last)) {\n return last.Agent;\n }\n\n const created: SessionAgentMessage = {\n content: [],\n tool_results: {},\n };\n conversation.messages.push({ Agent: created });\n return created;\n}\n\nfunction appendAgentText(agent: SessionAgentMessage, text: string): void {\n if (!text.trim()) {\n return;\n }\n\n const last = agent.content.at(-1);\n if (last && isAgentTextContent(last)) {\n last.Text = trimRuntimeText(`${last.Text}${text}`, MAX_RUNTIME_AGENT_TEXT_CHARS);\n return;\n }\n\n const next: SessionAgentContent = {\n Text: text,\n };\n agent.content.push(next);\n}\n\nfunction appendAgentThinking(agent: SessionAgentMessage, text: string): void {\n if (!text.trim()) {\n return;\n }\n\n const last = agent.content.at(-1);\n if (last && isAgentThinkingContent(last)) {\n last.Thinking.text = trimRuntimeText(\n `${last.Thinking.text}${text}`,\n MAX_RUNTIME_THINKING_CHARS,\n );\n return;\n }\n\n const next: SessionAgentContent = {\n Thinking: {\n text,\n signature: null,\n },\n };\n agent.content.push(next);\n}\n\nfunction trimRuntimeText(value: string, maxChars: number): string {\n if (value.length <= maxChars) {\n return value;\n }\n return `${value.slice(0, Math.max(0, maxChars - 3))}...`;\n}\n\nfunction statusIndicatesComplete(status: unknown): boolean {\n if (typeof status !== \"string\") {\n return false;\n }\n const normalized = status.toLowerCase();\n return (\n normalized.includes(\"complete\") ||\n normalized.includes(\"done\") ||\n normalized.includes(\"success\") ||\n normalized.includes(\"failed\") ||\n normalized.includes(\"error\") ||\n normalized.includes(\"cancel\")\n );\n}\n\nfunction statusIndicatesError(status: unknown): boolean {\n if (typeof status !== \"string\") {\n return false;\n }\n const normalized = status.toLowerCase();\n return normalized.includes(\"fail\") || normalized.includes(\"error\");\n}\n\nfunction toToolResultContent(value: unknown): SessionToolResultContent {\n if (typeof value === \"string\") {\n return { Text: trimRuntimeText(value, MAX_RUNTIME_TOOL_IO_CHARS) };\n }\n\n if (value != null) {\n try {\n return { Text: trimRuntimeText(JSON.stringify(value), MAX_RUNTIME_TOOL_IO_CHARS) };\n } catch {\n return { Text: \"[Unserializable value]\" };\n }\n }\n\n return { Text: \"\" };\n}\n\nfunction toRawInput(value: unknown): string {\n if (typeof value === \"string\") {\n return trimRuntimeText(value, MAX_RUNTIME_TOOL_IO_CHARS);\n }\n\n try {\n return trimRuntimeText(JSON.stringify(value ?? {}), MAX_RUNTIME_TOOL_IO_CHARS);\n } catch {\n return value == null ? \"\" : \"[Unserializable input]\";\n }\n}\n\nfunction ensureToolUseContent(agent: SessionAgentMessage, toolCallId: string): SessionToolUse {\n for (const content of agent.content) {\n if (isAgentToolUseContent(content) && content.ToolUse.id === toolCallId) {\n return content.ToolUse;\n }\n }\n\n const created: SessionToolUse = {\n id: toolCallId,\n name: \"tool_call\",\n raw_input: \"{}\",\n input: {},\n is_input_complete: false,\n thought_signature: null,\n };\n agent.content.push({ ToolUse: created });\n return created;\n}\n\nfunction upsertToolResult(\n agent: SessionAgentMessage,\n toolCallId: string,\n patch: Partial<SessionToolResult>,\n): void {\n const existing = agent.tool_results[toolCallId];\n const next: SessionToolResult = {\n tool_use_id: toolCallId,\n tool_name: patch.tool_name ?? existing?.tool_name ?? \"tool_call\",\n is_error: patch.is_error ?? existing?.is_error ?? false,\n content: patch.content ?? existing?.content ?? { Text: \"\" },\n output: patch.output ?? existing?.output,\n };\n agent.tool_results[toolCallId] = next;\n}\n\nfunction applyToolCallUpdate(agent: SessionAgentMessage, update: ToolCall | ToolCallUpdate): void {\n const tool = ensureToolUseContent(agent, update.toolCallId);\n\n if (hasOwn(update, \"title\")) {\n tool.name =\n normalizeAgentName((update as { title?: unknown }).title) ?? tool.name ?? \"tool_call\";\n }\n\n if (hasOwn(update, \"kind\")) {\n const kindName = normalizeAgentName((update as { kind?: unknown }).kind);\n if (!tool.name || tool.name === \"tool_call\") {\n tool.name = kindName ?? tool.name;\n }\n }\n\n if (hasOwn(update, \"rawInput\")) {\n const rawInput = deepClone((update as { rawInput?: unknown }).rawInput);\n tool.input = rawInput ?? {};\n tool.raw_input = toRawInput(rawInput);\n }\n\n if (hasOwn(update, \"status\")) {\n tool.is_input_complete = statusIndicatesComplete((update as { status?: unknown }).status);\n }\n\n if (\n hasOwn(update, \"rawOutput\") ||\n hasOwn(update, \"status\") ||\n hasOwn(update, \"title\") ||\n hasOwn(update, \"kind\")\n ) {\n const status = (update as { status?: unknown }).status;\n const output = hasOwn(update, \"rawOutput\")\n ? deepClone((update as { rawOutput?: unknown }).rawOutput)\n : undefined;\n\n upsertToolResult(agent, update.toolCallId, {\n tool_name: tool.name,\n is_error: statusIndicatesError(status),\n content: output === undefined ? undefined : toToolResultContent(output),\n output,\n });\n }\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction numberField(source: Record<string, unknown>, keys: readonly string[]): number | undefined {\n for (const key of keys) {\n const value = source[key];\n if (typeof value === \"number\" && Number.isFinite(value) && value >= 0) {\n return value;\n }\n }\n return undefined;\n}\n\nfunction usageToTokenUsage(update: UsageUpdate): SessionTokenUsage | undefined {\n const updateRecord = asRecord(update);\n const usageMeta = asRecord(updateRecord?._meta)?.usage;\n const source = asRecord(usageMeta) ?? updateRecord;\n if (!source) {\n return undefined;\n }\n\n const normalized: SessionTokenUsage = {\n input_tokens: numberField(source, [\"input_tokens\", \"inputTokens\"]),\n output_tokens: numberField(source, [\"output_tokens\", \"outputTokens\"]),\n cache_creation_input_tokens: numberField(source, [\n \"cache_creation_input_tokens\",\n \"cacheCreationInputTokens\",\n \"cachedWriteTokens\",\n ]),\n cache_read_input_tokens: numberField(source, [\n \"cache_read_input_tokens\",\n \"cacheReadInputTokens\",\n \"cachedReadTokens\",\n ]),\n };\n\n if (\n normalized.input_tokens === undefined &&\n normalized.output_tokens === undefined &&\n normalized.cache_creation_input_tokens === undefined &&\n normalized.cache_read_input_tokens === undefined\n ) {\n return undefined;\n }\n\n return normalized;\n}\n\nfunction ensureAcpxState(state: SessionAcpxState | undefined): SessionAcpxState {\n return state ?? {};\n}\n\nfunction lastUserMessageId(conversation: SessionConversation): string | undefined {\n for (let index = conversation.messages.length - 1; index >= 0; index -= 1) {\n const message = conversation.messages[index];\n if (message && isUserMessage(message)) {\n return message.User.id;\n }\n }\n return undefined;\n}\n\nexport function createSessionConversation(timestamp = isoNow()): SessionConversation {\n return {\n title: null,\n messages: [],\n updated_at: timestamp,\n cumulative_token_usage: {},\n request_token_usage: {},\n };\n}\n\nexport function cloneSessionConversation(\n conversation: SessionConversation | undefined,\n): SessionConversation {\n if (!conversation) {\n return createSessionConversation();\n }\n\n return {\n title: conversation.title,\n messages: deepClone(conversation.messages ?? []),\n updated_at: conversation.updated_at,\n cumulative_token_usage: deepClone(conversation.cumulative_token_usage ?? {}),\n request_token_usage: deepClone(conversation.request_token_usage ?? {}),\n };\n}\n\nexport function cloneSessionAcpxState(\n state: SessionAcpxState | undefined,\n): SessionAcpxState | undefined {\n if (!state) {\n return undefined;\n }\n\n return {\n current_mode_id: state.current_mode_id,\n desired_mode_id: state.desired_mode_id,\n available_commands: state.available_commands ? [...state.available_commands] : undefined,\n config_options: state.config_options ? deepClone(state.config_options) : undefined,\n };\n}\n\nexport function appendLegacyHistory(\n conversation: SessionConversation,\n entries: LegacyHistoryEntry[],\n): void {\n for (const entry of entries) {\n const text = entry.textPreview?.trim();\n if (!text) {\n continue;\n }\n\n if (entry.role === \"user\") {\n conversation.messages.push({\n User: {\n id: nextUserMessageId(),\n content: [{ Text: text }],\n },\n });\n } else {\n conversation.messages.push({\n Agent: {\n content: [{ Text: text }],\n tool_results: {},\n },\n });\n }\n\n updateConversationTimestamp(conversation, entry.timestamp || conversation.updated_at);\n }\n}\n\nexport function recordPromptSubmission(\n conversation: SessionConversation,\n prompt: PromptInput | string,\n timestamp = isoNow(),\n): void {\n const normalizedPrompt = typeof prompt === \"string\" ? textPrompt(prompt) : prompt;\n const userContent = normalizedPrompt\n .map((content) => contentToUserContent(content))\n .filter((content) => content !== undefined);\n if (userContent.length === 0) {\n return;\n }\n\n conversation.messages.push({\n User: {\n id: nextUserMessageId(),\n content: userContent.map((content) => {\n if (\"Text\" in content) {\n return {\n Text: trimRuntimeText(content.Text, MAX_RUNTIME_AGENT_TEXT_CHARS),\n };\n }\n return content;\n }),\n },\n });\n updateConversationTimestamp(conversation, timestamp);\n trimConversationForRuntime(conversation);\n}\n\nexport function recordSessionUpdate(\n conversation: SessionConversation,\n state: SessionAcpxState | undefined,\n notification: SessionNotification,\n timestamp = isoNow(),\n): SessionAcpxState {\n const acpx = ensureAcpxState(state);\n\n const update: SessionUpdate = notification.update;\n switch (update.sessionUpdate) {\n case \"user_message_chunk\": {\n const userContent = contentToUserContent(update.content);\n if (userContent) {\n conversation.messages.push({\n User: {\n id: nextUserMessageId(),\n content: [userContent],\n },\n });\n }\n break;\n }\n case \"agent_message_chunk\": {\n const text = extractText(update.content);\n if (text) {\n const agent = ensureAgentMessage(conversation);\n appendAgentText(agent, text);\n }\n break;\n }\n case \"agent_thought_chunk\": {\n const text = extractText(update.content);\n if (text) {\n const agent = ensureAgentMessage(conversation);\n appendAgentThinking(agent, text);\n }\n break;\n }\n case \"tool_call\":\n case \"tool_call_update\": {\n const agent = ensureAgentMessage(conversation);\n applyToolCallUpdate(agent, update);\n break;\n }\n case \"usage_update\": {\n const usage = usageToTokenUsage(update);\n if (usage) {\n conversation.cumulative_token_usage = usage;\n const userId = lastUserMessageId(conversation);\n if (userId) {\n conversation.request_token_usage[userId] = usage;\n }\n }\n break;\n }\n case \"session_info_update\": {\n if (hasOwn(update, \"title\")) {\n conversation.title = update.title ?? null;\n }\n if (hasOwn(update, \"updatedAt\")) {\n conversation.updated_at = update.updatedAt ?? conversation.updated_at;\n }\n break;\n }\n case \"available_commands_update\": {\n acpx.available_commands = update.availableCommands\n .map((entry) => entry.name)\n .filter((entry) => typeof entry === \"string\" && entry.trim().length > 0);\n break;\n }\n case \"current_mode_update\": {\n acpx.current_mode_id = update.currentModeId;\n break;\n }\n case \"config_option_update\": {\n acpx.config_options = deepClone(update.configOptions);\n break;\n }\n default:\n break;\n }\n\n updateConversationTimestamp(conversation, timestamp);\n trimConversationForRuntime(conversation);\n return acpx;\n}\n\nexport function recordClientOperation(\n conversation: SessionConversation,\n state: SessionAcpxState | undefined,\n operation: ClientOperation,\n timestamp = isoNow(),\n): SessionAcpxState {\n const acpx = ensureAcpxState(state);\n updateConversationTimestamp(conversation, timestamp);\n trimConversationForRuntime(conversation);\n return acpx;\n}\n\nexport function trimConversationForRuntime(conversation: SessionConversation): void {\n if (conversation.messages.length > MAX_RUNTIME_MESSAGES) {\n conversation.messages = conversation.messages.slice(-MAX_RUNTIME_MESSAGES);\n }\n\n for (const message of conversation.messages) {\n if (!isAgentMessage(message)) {\n if (isUserMessage(message)) {\n message.User.content = message.User.content.map((content) => {\n if (\"Text\" in content) {\n return {\n Text: trimRuntimeText(content.Text, MAX_RUNTIME_AGENT_TEXT_CHARS),\n };\n }\n return content;\n });\n }\n continue;\n }\n\n for (const content of message.Agent.content) {\n if (\"Text\" in content) {\n content.Text = trimRuntimeText(content.Text, MAX_RUNTIME_AGENT_TEXT_CHARS);\n } else if (\"Thinking\" in content) {\n content.Thinking.text = trimRuntimeText(content.Thinking.text, MAX_RUNTIME_THINKING_CHARS);\n } else if (\"ToolUse\" in content) {\n content.ToolUse.raw_input = trimRuntimeText(\n content.ToolUse.raw_input,\n MAX_RUNTIME_TOOL_IO_CHARS,\n );\n }\n }\n\n for (const result of Object.values(message.Agent.tool_results)) {\n if (\"Text\" in result.content) {\n result.content.Text = trimRuntimeText(result.content.Text, MAX_RUNTIME_TOOL_IO_CHARS);\n }\n if (typeof result.output === \"string\") {\n result.output = trimRuntimeText(result.output, MAX_RUNTIME_TOOL_IO_CHARS);\n }\n }\n }\n\n const requestUsageEntries = Object.entries(conversation.request_token_usage);\n if (requestUsageEntries.length > MAX_RUNTIME_REQUEST_TOKEN_USAGE) {\n conversation.request_token_usage = Object.fromEntries(\n requestUsageEntries.slice(-MAX_RUNTIME_REQUEST_TOKEN_USAGE),\n );\n }\n}\n","import os from \"node:os\";\nimport path from \"node:path\";\nimport type { SessionEventLog } from \"./types.js\";\n\nexport const DEFAULT_EVENT_SEGMENT_MAX_BYTES = 64 * 1024 * 1024;\nexport const DEFAULT_EVENT_MAX_SEGMENTS = 5;\n\nexport function sessionBaseDir(): string {\n return path.join(os.homedir(), \".acpx\", \"sessions\");\n}\n\nexport function safeSessionId(sessionId: string): string {\n return encodeURIComponent(sessionId);\n}\n\nexport function sessionEventActivePath(sessionId: string): string {\n return path.join(sessionBaseDir(), `${safeSessionId(sessionId)}.stream.ndjson`);\n}\n\nexport function sessionEventSegmentPath(sessionId: string, segment: number): string {\n return path.join(sessionBaseDir(), `${safeSessionId(sessionId)}.stream.${segment}.ndjson`);\n}\n\nexport function sessionEventLockPath(sessionId: string): string {\n return path.join(sessionBaseDir(), `${safeSessionId(sessionId)}.stream.lock`);\n}\n\nexport function defaultSessionEventLog(sessionId: string): SessionEventLog {\n return {\n active_path: sessionEventActivePath(sessionId),\n segment_count: DEFAULT_EVENT_MAX_SEGMENTS,\n max_segment_bytes: DEFAULT_EVENT_SEGMENT_MAX_BYTES,\n max_segments: DEFAULT_EVENT_MAX_SEGMENTS,\n last_write_at: undefined,\n last_write_error: null,\n };\n}\n","import { normalizeRuntimeSessionId } from \"../runtime-session-id.js\";\nimport type { SessionRecord } from \"../types.js\";\nimport { SESSION_RECORD_SCHEMA } from \"../types.js\";\n\nexport function serializeSessionRecordForDisk(record: SessionRecord): Record<string, unknown> {\n const canonical: SessionRecord = {\n ...record,\n schema: SESSION_RECORD_SCHEMA,\n };\n\n return {\n schema: canonical.schema,\n acpx_record_id: canonical.acpxRecordId,\n acp_session_id: canonical.acpSessionId,\n agent_session_id: normalizeRuntimeSessionId(canonical.agentSessionId),\n agent_command: canonical.agentCommand,\n cwd: canonical.cwd,\n name: canonical.name,\n created_at: canonical.createdAt,\n last_used_at: canonical.lastUsedAt,\n last_seq: canonical.lastSeq,\n last_request_id: canonical.lastRequestId,\n event_log: canonical.eventLog,\n closed: canonical.closed,\n closed_at: canonical.closedAt,\n pid: canonical.pid,\n agent_started_at: canonical.agentStartedAt,\n last_prompt_at: canonical.lastPromptAt,\n last_agent_exit_code: canonical.lastAgentExitCode,\n last_agent_exit_signal: canonical.lastAgentExitSignal,\n last_agent_exit_at: canonical.lastAgentExitAt,\n last_agent_disconnect_reason: canonical.lastAgentDisconnectReason,\n protocol_version: canonical.protocolVersion,\n agent_capabilities: canonical.agentCapabilities,\n title: canonical.title,\n messages: canonical.messages,\n updated_at: canonical.updated_at,\n cumulative_token_usage: canonical.cumulative_token_usage,\n request_token_usage: canonical.request_token_usage,\n acpx: canonical.acpx,\n };\n}\n","const SNAKE_CASE_KEY = /^[a-z][a-z0-9_]*$/;\n\nconst ZED_TAG_KEYS = new Set([\n \"User\",\n \"Agent\",\n \"Resume\",\n \"Text\",\n \"Mention\",\n \"Image\",\n \"Thinking\",\n \"RedactedThinking\",\n \"ToolUse\",\n]);\n\nconst MAP_OBJECT_PATHS = new Set([\"request_token_usage\", \"messages.Agent.tool_results\"]);\n\nconst OPAQUE_VALUE_PATHS = new Set([\n \"agent_capabilities\",\n \"messages.Agent.content.ToolUse.input\",\n \"acpx.config_options\",\n]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction joinPath(path: string[]): string {\n return path.join(\".\");\n}\n\nfunction isAllowedKey(path: string[], key: string): boolean {\n if (ZED_TAG_KEYS.has(key)) {\n return true;\n }\n\n return false;\n}\n\nfunction shouldSkipKeyRule(path: string[]): boolean {\n return MAP_OBJECT_PATHS.has(joinPath(path));\n}\n\nfunction shouldSkipDescend(path: string[]): boolean {\n return OPAQUE_VALUE_PATHS.has(joinPath(path)) || isToolResultOutputPath(path);\n}\n\nfunction isToolResultOutputPath(path: string[]): boolean {\n if (path.length < 5 || path[path.length - 1] !== \"output\") {\n return false;\n }\n\n const toolResultsIndex = path.lastIndexOf(\"tool_results\");\n if (toolResultsIndex === -1 || toolResultsIndex + 2 !== path.length - 1) {\n return false;\n }\n\n const parentPath = path.slice(0, toolResultsIndex + 1).join(\".\");\n return parentPath === \"messages.Agent.tool_results\";\n}\n\nfunction collectViolations(value: unknown, path: string[], violations: string[]): void {\n if (Array.isArray(value)) {\n for (const entry of value) {\n collectViolations(entry, path, violations);\n }\n return;\n }\n\n if (!isRecord(value)) {\n return;\n }\n\n const skipKeyRule = shouldSkipKeyRule(path);\n for (const [key, child] of Object.entries(value)) {\n if (!skipKeyRule && !SNAKE_CASE_KEY.test(key) && !isAllowedKey(path, key)) {\n violations.push(`${joinPath(path)}.${key}`.replace(/^\\./, \"\"));\n }\n\n const childPath = [...path, key];\n if (shouldSkipDescend(childPath)) {\n continue;\n }\n\n collectViolations(child, childPath, violations);\n }\n}\n\nexport function findPersistedKeyPolicyViolations(value: unknown): string[] {\n const violations: string[] = [];\n collectViolations(value, [], violations);\n return violations;\n}\n\nexport function assertPersistedKeyPolicy(value: unknown): void {\n const violations = findPersistedKeyPolicyViolations(value);\n if (violations.length === 0) {\n return;\n }\n\n throw new Error(\n `Persisted key policy violation (expected snake_case keys): ${violations.join(\", \")}`,\n );\n}\n","import { normalizeRuntimeSessionId } from \"../runtime-session-id.js\";\nimport { defaultSessionEventLog } from \"../session-event-log.js\";\nimport type {\n SessionAcpxState,\n SessionEventLog,\n SessionRecord,\n SessionConversation,\n} from \"../types.js\";\nimport { SESSION_RECORD_SCHEMA } from \"../types.js\";\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction hasOwn(source: object, key: string): boolean {\n return Object.prototype.hasOwnProperty.call(source, key);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction parseTokenUsage(\n raw: unknown,\n): SessionConversation[\"cumulative_token_usage\"] | null | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n\n const record = asRecord(raw);\n if (!record) {\n return null;\n }\n\n const usage: SessionConversation[\"cumulative_token_usage\"] = {};\n const fields: Array<keyof SessionConversation[\"cumulative_token_usage\"]> = [\n \"input_tokens\",\n \"output_tokens\",\n \"cache_creation_input_tokens\",\n \"cache_read_input_tokens\",\n ];\n\n for (const field of fields) {\n const value = record[field];\n if (value === undefined) {\n continue;\n }\n if (typeof value !== \"number\" || !Number.isFinite(value) || value < 0) {\n return null;\n }\n usage[field] = value;\n }\n\n return usage;\n}\n\nfunction parseRequestTokenUsage(\n raw: unknown,\n): SessionConversation[\"request_token_usage\"] | null | undefined {\n if (raw === undefined || raw === null) {\n return undefined;\n }\n\n const record = asRecord(raw);\n if (!record) {\n return null;\n }\n\n const usage: SessionConversation[\"request_token_usage\"] = {};\n for (const [key, value] of Object.entries(record)) {\n const parsed = parseTokenUsage(value);\n if (parsed == null) {\n return null;\n }\n usage[key] = parsed;\n }\n\n return usage;\n}\n\nfunction isSessionMessageImage(raw: unknown): boolean {\n const record = asRecord(raw);\n if (!record || typeof record.source !== \"string\") {\n return false;\n }\n\n if (record.size === undefined || record.size === null) {\n return true;\n }\n\n const size = asRecord(record.size);\n return (\n !!size &&\n typeof size.width === \"number\" &&\n Number.isFinite(size.width) &&\n typeof size.height === \"number\" &&\n Number.isFinite(size.height)\n );\n}\n\nfunction isUserContent(raw: unknown): boolean {\n const record = asRecord(raw);\n if (!record) {\n return false;\n }\n\n if (typeof record.Text === \"string\") {\n return true;\n }\n\n if (record.Mention !== undefined) {\n const mention = asRecord(record.Mention);\n return !!mention && typeof mention.uri === \"string\" && typeof mention.content === \"string\";\n }\n\n if (record.Image !== undefined) {\n return isSessionMessageImage(record.Image);\n }\n\n return false;\n}\n\nfunction isToolUse(raw: unknown): boolean {\n const record = asRecord(raw);\n return (\n !!record &&\n typeof record.id === \"string\" &&\n typeof record.name === \"string\" &&\n typeof record.raw_input === \"string\" &&\n hasOwn(record, \"input\") &&\n typeof record.is_input_complete === \"boolean\" &&\n (record.thought_signature === undefined ||\n record.thought_signature === null ||\n typeof record.thought_signature === \"string\")\n );\n}\n\nfunction isToolResultContent(raw: unknown): boolean {\n const record = asRecord(raw);\n if (!record) {\n return false;\n }\n\n if (typeof record.Text === \"string\") {\n return true;\n }\n\n if (record.Image !== undefined) {\n return isSessionMessageImage(record.Image);\n }\n\n return false;\n}\n\nfunction isToolResult(raw: unknown): boolean {\n const record = asRecord(raw);\n return (\n !!record &&\n typeof record.tool_use_id === \"string\" &&\n typeof record.tool_name === \"string\" &&\n typeof record.is_error === \"boolean\" &&\n isToolResultContent(record.content)\n );\n}\n\nfunction isAgentContent(raw: unknown): boolean {\n const record = asRecord(raw);\n if (!record) {\n return false;\n }\n\n if (typeof record.Text === \"string\") {\n return true;\n }\n\n if (record.Thinking !== undefined) {\n const thinking = asRecord(record.Thinking);\n return (\n !!thinking &&\n typeof thinking.text === \"string\" &&\n (thinking.signature === undefined ||\n thinking.signature === null ||\n typeof thinking.signature === \"string\")\n );\n }\n\n if (typeof record.RedactedThinking === \"string\") {\n return true;\n }\n\n if (record.ToolUse !== undefined) {\n return isToolUse(record.ToolUse);\n }\n\n return false;\n}\n\nfunction isUserMessage(raw: unknown): boolean {\n const record = asRecord(raw);\n if (!record || record.User === undefined) {\n return false;\n }\n\n const user = asRecord(record.User);\n return (\n !!user &&\n typeof user.id === \"string\" &&\n Array.isArray(user.content) &&\n user.content.every((entry) => isUserContent(entry))\n );\n}\n\nfunction isAgentMessage(raw: unknown): boolean {\n const record = asRecord(raw);\n if (!record || record.Agent === undefined) {\n return false;\n }\n\n const agent = asRecord(record.Agent);\n if (!agent || !Array.isArray(agent.content) || !agent.content.every(isAgentContent)) {\n return false;\n }\n\n const toolResults = asRecord(agent.tool_results);\n if (!toolResults) {\n return false;\n }\n\n return Object.values(toolResults).every(isToolResult);\n}\n\nfunction isConversationMessage(raw: unknown): boolean {\n return raw === \"Resume\" || isUserMessage(raw) || isAgentMessage(raw);\n}\n\nfunction parseConversationRecord(record: Record<string, unknown>): SessionConversation | undefined {\n if (\n !Array.isArray(record.messages) ||\n !record.messages.every(isConversationMessage) ||\n typeof record.updated_at !== \"string\"\n ) {\n return undefined;\n }\n\n if (record.title !== undefined && record.title !== null && typeof record.title !== \"string\") {\n return undefined;\n }\n\n const cumulativeTokenUsage = parseTokenUsage(record.cumulative_token_usage);\n const requestTokenUsage = parseRequestTokenUsage(record.request_token_usage);\n if (cumulativeTokenUsage === null || requestTokenUsage === null) {\n return undefined;\n }\n\n return {\n title:\n record.title === undefined || record.title === null || typeof record.title === \"string\"\n ? record.title\n : null,\n messages: record.messages as SessionConversation[\"messages\"],\n updated_at: record.updated_at,\n cumulative_token_usage: cumulativeTokenUsage ?? {},\n request_token_usage: requestTokenUsage ?? {},\n };\n}\n\nfunction parseAcpxState(raw: unknown): SessionAcpxState | undefined {\n const record = asRecord(raw);\n if (!record) {\n return undefined;\n }\n\n const state: SessionAcpxState = {};\n\n if (typeof record.current_mode_id === \"string\") {\n state.current_mode_id = record.current_mode_id;\n }\n\n if (typeof record.desired_mode_id === \"string\") {\n state.desired_mode_id = record.desired_mode_id;\n }\n\n if (isStringArray(record.available_commands)) {\n state.available_commands = [...record.available_commands];\n }\n\n if (Array.isArray(record.config_options)) {\n state.config_options = record.config_options as SessionAcpxState[\"config_options\"];\n }\n\n return state;\n}\n\nfunction parseEventLog(raw: unknown, sessionId: string): SessionEventLog {\n const record = asRecord(raw);\n if (!record) {\n return defaultSessionEventLog(sessionId);\n }\n\n if (\n typeof record.active_path !== \"string\" ||\n typeof record.segment_count !== \"number\" ||\n !Number.isInteger(record.segment_count) ||\n record.segment_count < 1 ||\n typeof record.max_segment_bytes !== \"number\" ||\n !Number.isInteger(record.max_segment_bytes) ||\n record.max_segment_bytes < 1 ||\n typeof record.max_segments !== \"number\" ||\n !Number.isInteger(record.max_segments) ||\n record.max_segments < 1\n ) {\n return defaultSessionEventLog(sessionId);\n }\n\n return {\n active_path: record.active_path,\n segment_count: record.segment_count,\n max_segment_bytes: record.max_segment_bytes,\n max_segments: record.max_segments,\n last_write_at: typeof record.last_write_at === \"string\" ? record.last_write_at : undefined,\n last_write_error:\n record.last_write_error == null || typeof record.last_write_error === \"string\"\n ? record.last_write_error\n : null,\n };\n}\n\nfunction normalizeOptionalName(value: unknown): string | undefined | null {\n if (value == null) {\n return undefined;\n }\n\n if (typeof value !== \"string\") {\n return null;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nfunction normalizeOptionalPid(value: unknown): number | undefined | null {\n if (value == null) {\n return undefined;\n }\n\n if (!Number.isInteger(value) || (value as number) <= 0) {\n return null;\n }\n\n return value as number;\n}\n\nfunction normalizeOptionalBoolean(value: unknown, fallback = false): boolean | null {\n if (value == null) {\n return fallback;\n }\n return typeof value === \"boolean\" ? value : null;\n}\n\nfunction normalizeOptionalString(value: unknown): string | undefined | null {\n if (value == null) {\n return undefined;\n }\n return typeof value === \"string\" ? value : null;\n}\n\nfunction normalizeOptionalExitCode(value: unknown): number | null | undefined | symbol {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return null;\n }\n if (Number.isInteger(value)) {\n return value as number;\n }\n return Symbol(\"invalid\");\n}\n\nfunction normalizeOptionalSignal(value: unknown): NodeJS.Signals | null | undefined | symbol {\n if (value === undefined) {\n return undefined;\n }\n if (value === null) {\n return null;\n }\n if (typeof value === \"string\") {\n return value as NodeJS.Signals;\n }\n return Symbol(\"invalid\");\n}\n\nexport function parseSessionRecord(raw: unknown): SessionRecord | null {\n const record = asRecord(raw);\n if (!record) {\n return null;\n }\n\n if (record.schema !== SESSION_RECORD_SCHEMA) {\n return null;\n }\n\n const name = normalizeOptionalName(record.name);\n const pid = normalizeOptionalPid(record.pid);\n const closed = normalizeOptionalBoolean(record.closed, false);\n const closedAt = normalizeOptionalString(record.closed_at);\n const agentStartedAt = normalizeOptionalString(record.agent_started_at);\n const lastPromptAt = normalizeOptionalString(record.last_prompt_at);\n const lastAgentExitCode = normalizeOptionalExitCode(record.last_agent_exit_code);\n const lastAgentExitSignal = normalizeOptionalSignal(record.last_agent_exit_signal);\n const lastAgentExitAt = normalizeOptionalString(record.last_agent_exit_at);\n const lastAgentDisconnectReason = normalizeOptionalString(record.last_agent_disconnect_reason);\n\n if (\n typeof record.acpx_record_id !== \"string\" ||\n typeof record.acp_session_id !== \"string\" ||\n typeof record.agent_command !== \"string\" ||\n typeof record.cwd !== \"string\" ||\n typeof record.created_at !== \"string\" ||\n typeof record.last_used_at !== \"string\" ||\n typeof record.last_seq !== \"number\" ||\n !Number.isInteger(record.last_seq) ||\n record.last_seq < 0 ||\n name === null ||\n pid === null ||\n closed === null ||\n closedAt === null ||\n agentStartedAt === null ||\n lastPromptAt === null ||\n typeof lastAgentExitCode === \"symbol\" ||\n typeof lastAgentExitSignal === \"symbol\" ||\n lastAgentExitAt === null ||\n lastAgentDisconnectReason === null\n ) {\n return null;\n }\n\n const conversation = parseConversationRecord(record);\n if (!conversation) {\n return null;\n }\n\n const eventLog = parseEventLog(record.event_log, record.acpx_record_id);\n const lastRequestId = normalizeOptionalString(record.last_request_id);\n if (lastRequestId === null) {\n return null;\n }\n\n return {\n schema: SESSION_RECORD_SCHEMA,\n acpxRecordId: record.acpx_record_id,\n acpSessionId: record.acp_session_id,\n agentSessionId: normalizeRuntimeSessionId(record.agent_session_id),\n agentCommand: record.agent_command,\n cwd: record.cwd,\n name,\n createdAt: record.created_at,\n lastUsedAt: record.last_used_at,\n lastSeq: record.last_seq,\n lastRequestId,\n eventLog,\n closed,\n closedAt,\n pid,\n agentStartedAt,\n lastPromptAt,\n lastAgentExitCode,\n lastAgentExitSignal: lastAgentExitSignal,\n lastAgentExitAt,\n lastAgentDisconnectReason,\n protocolVersion:\n typeof record.protocol_version === \"number\" ? record.protocol_version : undefined,\n agentCapabilities: asRecord(record.agent_capabilities) as SessionRecord[\"agentCapabilities\"],\n title: conversation.title,\n messages: conversation.messages,\n updated_at: conversation.updated_at,\n cumulative_token_usage: conversation.cumulative_token_usage,\n request_token_usage: conversation.request_token_usage,\n acpx: parseAcpxState(record.acpx),\n };\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { SessionRecord } from \"../types.js\";\nimport { parseSessionRecord } from \"./parse.js\";\n\nconst SESSION_INDEX_SCHEMA = \"acpx.session-index.v1\";\n\nexport type SessionIndexEntry = {\n file: string;\n acpxRecordId: string;\n acpSessionId: string;\n agentCommand: string;\n cwd: string;\n name?: string;\n closed: boolean;\n lastUsedAt: string;\n};\n\ntype SessionIndex = {\n schema: typeof SESSION_INDEX_SCHEMA;\n files: string[];\n entries: SessionIndexEntry[];\n};\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n return undefined;\n }\n return value as Record<string, unknown>;\n}\n\nfunction parseIndexEntry(raw: unknown): SessionIndexEntry | undefined {\n const record = asRecord(raw);\n if (!record) {\n return undefined;\n }\n if (\n typeof record.file !== \"string\" ||\n typeof record.acpxRecordId !== \"string\" ||\n typeof record.acpSessionId !== \"string\" ||\n typeof record.agentCommand !== \"string\" ||\n typeof record.cwd !== \"string\" ||\n typeof record.lastUsedAt !== \"string\" ||\n typeof record.closed !== \"boolean\"\n ) {\n return undefined;\n }\n if (record.name !== undefined && typeof record.name !== \"string\") {\n return undefined;\n }\n return {\n file: record.file,\n acpxRecordId: record.acpxRecordId,\n acpSessionId: record.acpSessionId,\n agentCommand: record.agentCommand,\n cwd: record.cwd,\n name: record.name,\n closed: record.closed,\n lastUsedAt: record.lastUsedAt,\n };\n}\n\nexport function sessionIndexPath(sessionDir: string): string {\n return path.join(sessionDir, \"index.json\");\n}\n\nexport function toSessionIndexEntry(record: SessionRecord, fileName: string): SessionIndexEntry {\n return {\n file: fileName,\n acpxRecordId: record.acpxRecordId,\n acpSessionId: record.acpSessionId,\n agentCommand: record.agentCommand,\n cwd: record.cwd,\n name: record.name,\n closed: record.closed === true,\n lastUsedAt: record.lastUsedAt,\n };\n}\n\nexport async function readSessionIndex(sessionDir: string): Promise<SessionIndex | undefined> {\n const filePath = sessionIndexPath(sessionDir);\n try {\n const payload = await fs.readFile(filePath, \"utf8\");\n const parsed = JSON.parse(payload) as unknown;\n const record = asRecord(parsed);\n if (!record || record.schema !== SESSION_INDEX_SCHEMA || !Array.isArray(record.files)) {\n return undefined;\n }\n const files = record.files.filter((entry): entry is string => typeof entry === \"string\");\n if (files.length !== record.files.length || !Array.isArray(record.entries)) {\n return undefined;\n }\n const entries = record.entries\n .map((entry) => parseIndexEntry(entry))\n .filter((entry): entry is SessionIndexEntry => Boolean(entry));\n if (entries.length !== record.entries.length) {\n return undefined;\n }\n return {\n schema: SESSION_INDEX_SCHEMA,\n files,\n entries,\n };\n } catch {\n return undefined;\n }\n}\n\nexport async function writeSessionIndex(\n sessionDir: string,\n index: {\n files: string[];\n entries: SessionIndexEntry[];\n },\n): Promise<void> {\n const filePath = sessionIndexPath(sessionDir);\n const tempFile = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n const payload = JSON.stringify(\n {\n schema: SESSION_INDEX_SCHEMA,\n files: [...index.files].toSorted(),\n entries: [...index.entries].toSorted((a, b) => b.lastUsedAt.localeCompare(a.lastUsedAt)),\n },\n null,\n 2,\n );\n await fs.writeFile(tempFile, `${payload}\\n`, \"utf8\");\n await fs.rename(tempFile, filePath);\n}\n\nexport async function rebuildSessionIndex(sessionDir: string): Promise<SessionIndex> {\n const entries = await fs.readdir(sessionDir, { withFileTypes: true });\n const files = entries\n .filter(\n (entry) => entry.isFile() && entry.name.endsWith(\".json\") && entry.name !== \"index.json\",\n )\n .map((entry) => entry.name)\n .toSorted();\n\n const indexEntries: SessionIndexEntry[] = [];\n for (const file of files) {\n try {\n const payload = await fs.readFile(path.join(sessionDir, file), \"utf8\");\n const parsed = parseSessionRecord(JSON.parse(payload));\n if (!parsed) {\n continue;\n }\n indexEntries.push(toSessionIndexEntry(parsed, file));\n } catch {\n // ignore corrupt session files while rebuilding the cache index\n }\n }\n\n const index: SessionIndex = {\n schema: SESSION_INDEX_SCHEMA,\n files,\n entries: indexEntries,\n };\n await writeSessionIndex(sessionDir, index);\n return index;\n}\n\nexport async function loadOrRebuildSessionIndex(sessionDir: string): Promise<SessionIndex> {\n const files = (await fs.readdir(sessionDir, { withFileTypes: true }))\n .filter(\n (entry) => entry.isFile() && entry.name.endsWith(\".json\") && entry.name !== \"index.json\",\n )\n .map((entry) => entry.name)\n .toSorted();\n const existing = await readSessionIndex(sessionDir);\n if (\n existing &&\n existing.files.length === files.length &&\n existing.files.every((file, index) => file === files[index])\n ) {\n return existing;\n }\n return await rebuildSessionIndex(sessionDir);\n}\n","import { statSync } from \"node:fs\";\nimport fs from \"node:fs/promises\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { SessionNotFoundError, SessionResolutionError } from \"../errors.js\";\nimport { incrementPerfCounter, measurePerf } from \"../perf-metrics.js\";\nimport { assertPersistedKeyPolicy } from \"../persisted-key-policy.js\";\nimport type { SessionRecord } from \"../types.js\";\nimport {\n loadOrRebuildSessionIndex,\n rebuildSessionIndex,\n toSessionIndexEntry,\n writeSessionIndex,\n type SessionIndexEntry,\n} from \"./index.js\";\nimport { parseSessionRecord } from \"./parse.js\";\nimport { serializeSessionRecordForDisk } from \"./serialize.js\";\n\nexport const DEFAULT_HISTORY_LIMIT = 20;\n\ntype FindSessionOptions = {\n agentCommand: string;\n cwd: string;\n name?: string;\n includeClosed?: boolean;\n};\n\ntype FindSessionByDirectoryWalkOptions = {\n agentCommand: string;\n cwd: string;\n name?: string;\n boundary?: string;\n};\n\nfunction sessionFilePath(acpxRecordId: string): string {\n const safeId = encodeURIComponent(acpxRecordId);\n return path.join(sessionBaseDir(), `${safeId}.json`);\n}\n\nfunction sessionBaseDir(): string {\n return path.join(os.homedir(), \".acpx\", \"sessions\");\n}\n\nasync function ensureSessionDir(): Promise<void> {\n await fs.mkdir(sessionBaseDir(), { recursive: true });\n}\n\nasync function loadRecordFromIndexEntry(\n entry: SessionIndexEntry,\n): Promise<SessionRecord | undefined> {\n try {\n const payload = await fs.readFile(path.join(sessionBaseDir(), entry.file), \"utf8\");\n return parseSessionRecord(JSON.parse(payload)) ?? undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function loadSessionIndexEntries(): Promise<SessionIndexEntry[]> {\n await ensureSessionDir();\n const index = await measurePerf(\"session.index_load\", async () => {\n return await loadOrRebuildSessionIndex(sessionBaseDir());\n });\n return index.entries;\n}\n\nfunction matchesSessionEntry(\n session: SessionIndexEntry,\n normalizedCwd: string,\n normalizedName: string | undefined,\n includeClosed = false,\n): boolean {\n if (session.cwd !== normalizedCwd) {\n return false;\n }\n if (!includeClosed && session.closed) {\n return false;\n }\n if (normalizedName == null) {\n return session.name == null;\n }\n return session.name === normalizedName;\n}\n\nexport async function writeSessionRecord(record: SessionRecord): Promise<void> {\n await measurePerf(\"session.write_record\", async () => {\n await ensureSessionDir();\n\n const persisted = serializeSessionRecordForDisk(record);\n assertPersistedKeyPolicy(persisted);\n\n const file = sessionFilePath(record.acpxRecordId);\n const tempFile = `${file}.${process.pid}.${Date.now()}.tmp`;\n const payload = JSON.stringify(persisted, null, 2);\n await fs.writeFile(tempFile, `${payload}\\n`, \"utf8\");\n await fs.rename(tempFile, file);\n\n const sessionDir = sessionBaseDir();\n const index = await loadOrRebuildSessionIndex(sessionDir);\n const fileName = path.basename(file);\n const entries = index.entries.filter((entry) => entry.file !== fileName);\n entries.push(toSessionIndexEntry(record, fileName));\n const files = [...new Set([...index.files.filter((entry) => entry !== fileName), fileName])];\n await writeSessionIndex(sessionDir, { files, entries });\n });\n}\n\nexport async function resolveSessionRecord(sessionId: string): Promise<SessionRecord> {\n await ensureSessionDir();\n\n const directPath = sessionFilePath(sessionId);\n try {\n const directPayload = await measurePerf(\"session.resolve_direct\", async () => {\n return await fs.readFile(directPath, \"utf8\");\n });\n const directRecord = parseSessionRecord(JSON.parse(directPayload));\n if (directRecord) {\n return directRecord;\n }\n } catch {\n // fallback to indexed search\n }\n\n const entries = await loadSessionIndexEntries();\n const exactEntries = entries.filter(\n (entry) => entry.acpxRecordId === sessionId || entry.acpSessionId === sessionId,\n );\n const exactRecords = (\n await Promise.all(exactEntries.map((entry) => loadRecordFromIndexEntry(entry)))\n ).filter((entry): entry is SessionRecord => Boolean(entry));\n if (exactRecords.length === 1) {\n return exactRecords[0];\n }\n if (exactRecords.length > 1) {\n throw new SessionResolutionError(`Multiple sessions match id: ${sessionId}`);\n }\n\n const suffixEntries = entries.filter(\n (entry) => entry.acpxRecordId.endsWith(sessionId) || entry.acpSessionId.endsWith(sessionId),\n );\n const suffixRecords = (\n await Promise.all(suffixEntries.map((entry) => loadRecordFromIndexEntry(entry)))\n ).filter((entry): entry is SessionRecord => Boolean(entry));\n if (suffixRecords.length === 1) {\n return suffixRecords[0];\n }\n if (suffixRecords.length > 1) {\n throw new SessionResolutionError(`Session id is ambiguous: ${sessionId}`);\n }\n\n incrementPerfCounter(\"session.resolve_miss\");\n throw new SessionNotFoundError(sessionId);\n}\n\nfunction hasGitDirectory(dir: string): boolean {\n const gitPath = path.join(dir, \".git\");\n try {\n return statSync(gitPath).isDirectory();\n } catch {\n return false;\n }\n}\n\nfunction isWithinBoundary(boundary: string, target: string): boolean {\n const relative = path.relative(boundary, target);\n return relative.length === 0 || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nexport function absolutePath(value: string): string {\n return path.resolve(value);\n}\n\nexport function findGitRepositoryRoot(startDir: string): string | undefined {\n let current = absolutePath(startDir);\n const root = path.parse(current).root;\n\n for (;;) {\n if (hasGitDirectory(current)) {\n return current;\n }\n\n if (current === root) {\n return undefined;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n current = parent;\n }\n}\n\nexport function normalizeName(value: string | undefined): string | undefined {\n if (value == null) {\n return undefined;\n }\n\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function isoNow(): string {\n return new Date().toISOString();\n}\n\nexport async function listSessions(): Promise<SessionRecord[]> {\n await ensureSessionDir();\n const entries = await loadSessionIndexEntries();\n const records: SessionRecord[] = [];\n\n for (const entry of entries) {\n const parsed = await loadRecordFromIndexEntry(entry);\n if (parsed) {\n records.push(parsed);\n }\n }\n\n records.sort((a, b) => b.lastUsedAt.localeCompare(a.lastUsedAt));\n return records;\n}\n\nexport async function listSessionsForAgent(agentCommand: string): Promise<SessionRecord[]> {\n const entries = (await loadSessionIndexEntries()).filter(\n (session) => session.agentCommand === agentCommand,\n );\n const records = await Promise.all(entries.map((entry) => loadRecordFromIndexEntry(entry)));\n return records\n .filter((entry): entry is SessionRecord => Boolean(entry))\n .toSorted((a, b) => b.lastUsedAt.localeCompare(a.lastUsedAt));\n}\n\nexport async function findSession(options: FindSessionOptions): Promise<SessionRecord | undefined> {\n const normalizedCwd = absolutePath(options.cwd);\n const normalizedName = normalizeName(options.name);\n const entries = await loadSessionIndexEntries();\n const match = entries.find(\n (session) =>\n session.agentCommand === options.agentCommand &&\n matchesSessionEntry(session, normalizedCwd, normalizedName, options.includeClosed),\n );\n if (!match) {\n return undefined;\n }\n return await loadRecordFromIndexEntry(match);\n}\n\nexport async function findSessionByDirectoryWalk(\n options: FindSessionByDirectoryWalkOptions,\n): Promise<SessionRecord | undefined> {\n const normalizedName = normalizeName(options.name);\n const normalizedStart = absolutePath(options.cwd);\n const normalizedBoundary = absolutePath(options.boundary ?? normalizedStart);\n const walkBoundary = isWithinBoundary(normalizedBoundary, normalizedStart)\n ? normalizedBoundary\n : normalizedStart;\n const sessions = (await loadSessionIndexEntries()).filter(\n (session) => session.agentCommand === options.agentCommand,\n );\n\n let current = normalizedStart;\n const walkRoot = path.parse(current).root;\n\n for (;;) {\n const match = sessions.find((session) => matchesSessionEntry(session, current, normalizedName));\n if (match) {\n return await loadRecordFromIndexEntry(match);\n }\n\n if (current === walkBoundary || current === walkRoot) {\n return undefined;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n\n current = parent;\n\n if (!isWithinBoundary(walkBoundary, current)) {\n return undefined;\n }\n }\n}\n\nfunction killSignalCandidates(signal: NodeJS.Signals | undefined): NodeJS.Signals[] {\n if (!signal) {\n return [\"SIGTERM\", \"SIGKILL\"];\n }\n\n const normalized = signal.toUpperCase() as NodeJS.Signals;\n if (normalized === \"SIGKILL\") {\n return [\"SIGKILL\"];\n }\n\n return [normalized, \"SIGKILL\"];\n}\n\nexport async function closeSession(id: string): Promise<SessionRecord> {\n const record = await resolveSessionRecord(id);\n const now = isoNow();\n\n if (record.pid) {\n for (const signal of killSignalCandidates(record.lastAgentExitSignal ?? undefined)) {\n try {\n process.kill(record.pid, signal);\n } catch {\n // ignore\n }\n }\n }\n\n record.closed = true;\n record.closedAt = now;\n record.pid = undefined;\n record.lastUsedAt = now;\n record.lastPromptAt = record.lastPromptAt ?? now;\n\n await writeSessionRecord(record);\n await rebuildSessionIndex(sessionBaseDir()).catch(() => {\n // best effort cache rebuild\n });\n return record;\n}\n","import fs from \"node:fs/promises\";\nimport { isAcpJsonRpcMessage } from \"./acp-jsonrpc.js\";\nimport { incrementPerfCounter, measurePerf } from \"./perf-metrics.js\";\nimport { isProcessAlive } from \"./queue-lease-store.js\";\nimport {\n DEFAULT_EVENT_MAX_SEGMENTS,\n DEFAULT_EVENT_SEGMENT_MAX_BYTES,\n sessionBaseDir,\n sessionEventActivePath as activeEventPath,\n sessionEventLockPath as eventsLockPath,\n sessionEventSegmentPath as segmentEventPath,\n} from \"./session-event-log.js\";\nimport { resolveSessionRecord, writeSessionRecord } from \"./session-persistence.js\";\nimport type { AcpJsonRpcMessage, SessionRecord } from \"./types.js\";\n\nconst LOCK_RETRY_MS = 15;\nconst EVENT_LOCK_STALE_MS = 15_000;\n\nasync function ensureSessionDir(): Promise<void> {\n await fs.mkdir(sessionBaseDir(), { recursive: true });\n}\n\nasync function pathExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nasync function statSize(filePath: string): Promise<number> {\n try {\n const stats = await fs.stat(filePath);\n return stats.size;\n } catch {\n return 0;\n }\n}\n\nasync function countExistingSegments(sessionId: string, maxSegments: number): Promise<number> {\n let count = 0;\n\n for (let segment = 1; segment <= maxSegments; segment += 1) {\n if (await pathExists(segmentEventPath(sessionId, segment))) {\n count += 1;\n }\n }\n\n if (await pathExists(activeEventPath(sessionId))) {\n count += 1;\n }\n\n return count;\n}\n\nasync function resolveSessionMaxSegments(sessionId: string): Promise<number> {\n try {\n const record = await resolveSessionRecord(sessionId);\n const configured = record.eventLog.max_segments;\n if (Number.isInteger(configured) && configured > 0) {\n return configured;\n }\n } catch {\n // Fall back to defaults when metadata is unavailable.\n }\n\n return DEFAULT_EVENT_MAX_SEGMENTS;\n}\n\nasync function rotateSegments(sessionId: string, maxSegments: number): Promise<void> {\n const active = activeEventPath(sessionId);\n\n const overflow = segmentEventPath(sessionId, maxSegments);\n await fs.unlink(overflow).catch((error) => {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n });\n\n for (let segment = maxSegments - 1; segment >= 1; segment -= 1) {\n const from = segmentEventPath(sessionId, segment);\n const to = segmentEventPath(sessionId, segment + 1);\n if (!(await pathExists(from))) {\n continue;\n }\n await fs.rename(from, to);\n }\n\n if (await pathExists(active)) {\n await fs.rename(active, segmentEventPath(sessionId, 1));\n }\n}\n\ntype LockHandle = {\n filePath: string;\n};\n\ntype EventLockPayload = {\n pid?: number;\n created_at?: string;\n};\n\nfunction parseEventLockPayload(raw: string): EventLockPayload {\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n return {};\n }\n const record = parsed as Record<string, unknown>;\n return {\n pid: typeof record.pid === \"number\" ? record.pid : undefined,\n created_at: typeof record.created_at === \"string\" ? record.created_at : undefined,\n };\n } catch {\n return {};\n }\n}\n\nasync function removeStaleEventLock(lockPath: string): Promise<boolean> {\n try {\n const payload = await fs.readFile(lockPath, \"utf8\");\n const parsed = parseEventLockPayload(payload);\n const createdAtMs = parsed.created_at ? Date.parse(parsed.created_at) : Number.NaN;\n const lockAgeMs = Number.isFinite(createdAtMs)\n ? Date.now() - createdAtMs\n : Number.POSITIVE_INFINITY;\n const pidAlive = isProcessAlive(parsed.pid);\n if (pidAlive && lockAgeMs <= EVENT_LOCK_STALE_MS) {\n return false;\n }\n await fs.unlink(lockPath);\n incrementPerfCounter(\"session.events.stale_lock_recovered\");\n return true;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return true;\n }\n return false;\n }\n}\n\nasync function acquireEventsLock(sessionId: string): Promise<LockHandle> {\n await ensureSessionDir();\n const lockPath = eventsLockPath(sessionId);\n const payload = JSON.stringify(\n {\n pid: process.pid,\n created_at: new Date().toISOString(),\n },\n null,\n 2,\n );\n\n for (;;) {\n try {\n await fs.writeFile(lockPath, `${payload}\\n`, {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n return { filePath: lockPath };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n const recovered = await removeStaleEventLock(lockPath);\n if (recovered) {\n continue;\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, LOCK_RETRY_MS);\n });\n }\n }\n}\n\nasync function releaseEventsLock(lock: LockHandle): Promise<void> {\n await fs.unlink(lock.filePath).catch((error) => {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n });\n}\n\ntype SessionEventWriterOptions = {\n maxSegmentBytes?: number;\n maxSegments?: number;\n};\n\ntype AppendOptions = {\n checkpoint?: boolean;\n};\n\nexport class SessionEventWriter {\n private readonly record: SessionRecord;\n private readonly lock: LockHandle;\n private readonly maxSegmentBytes: number;\n private readonly maxSegments: number;\n private activePath: string;\n private activeSizeBytes: number;\n private segmentCount: number;\n private closed = false;\n\n private constructor(\n record: SessionRecord,\n lock: LockHandle,\n options: Required<SessionEventWriterOptions>,\n state: {\n activePath: string;\n activeSizeBytes: number;\n segmentCount: number;\n },\n ) {\n this.record = record;\n this.lock = lock;\n this.maxSegmentBytes = options.maxSegmentBytes;\n this.maxSegments = options.maxSegments;\n this.activePath = state.activePath;\n this.activeSizeBytes = state.activeSizeBytes;\n this.segmentCount = state.segmentCount;\n }\n\n static async open(\n record: SessionRecord,\n options: SessionEventWriterOptions = {},\n ): Promise<SessionEventWriter> {\n const lock = await acquireEventsLock(record.acpxRecordId);\n const maxSegmentBytes =\n options.maxSegmentBytes ??\n record.eventLog.max_segment_bytes ??\n DEFAULT_EVENT_SEGMENT_MAX_BYTES;\n const maxSegments =\n options.maxSegments ?? record.eventLog.max_segments ?? DEFAULT_EVENT_MAX_SEGMENTS;\n const activePath = activeEventPath(record.acpxRecordId);\n const activeSizeBytes = await statSize(activePath);\n const segmentCount =\n Number.isInteger(record.eventLog.segment_count) && record.eventLog.segment_count > 0\n ? record.eventLog.segment_count\n : (await countExistingSegments(record.acpxRecordId, maxSegments)) || 1;\n return new SessionEventWriter(\n record,\n lock,\n {\n maxSegmentBytes,\n maxSegments,\n },\n {\n activePath,\n activeSizeBytes,\n segmentCount,\n },\n );\n }\n\n getRecord(): SessionRecord {\n return this.record;\n }\n\n async appendMessage(message: AcpJsonRpcMessage, options: AppendOptions = {}): Promise<void> {\n await this.appendMessages([message], options);\n }\n\n async appendMessages(messages: AcpJsonRpcMessage[], options: AppendOptions = {}): Promise<void> {\n if (this.closed) {\n throw new Error(\"SessionEventWriter is closed\");\n }\n\n if (messages.length === 0) {\n return;\n }\n\n await ensureSessionDir();\n\n await measurePerf(\"session.events.append_batch\", async () => {\n for (const message of messages) {\n if (!isAcpJsonRpcMessage(message)) {\n throw new Error(\"Attempted to persist invalid ACP JSON-RPC payload\");\n }\n\n const line = `${JSON.stringify(message)}\\n`;\n const lineBytes = Buffer.byteLength(line);\n if (this.activeSizeBytes > 0 && this.activeSizeBytes + lineBytes > this.maxSegmentBytes) {\n await rotateSegments(this.record.acpxRecordId, this.maxSegments);\n this.activePath = activeEventPath(this.record.acpxRecordId);\n this.activeSizeBytes = 0;\n this.segmentCount = Math.min(this.segmentCount + 1, this.maxSegments);\n incrementPerfCounter(\"session.events.rotate\");\n }\n\n await fs.appendFile(this.activePath, line, \"utf8\");\n this.activeSizeBytes += lineBytes;\n\n this.record.lastSeq += 1;\n if (Object.hasOwn(message, \"id\")) {\n const id = (message as { id?: unknown }).id;\n if (typeof id === \"string\" || typeof id === \"number\") {\n this.record.lastRequestId = String(id);\n }\n }\n const writeTs = new Date().toISOString();\n this.record.lastUsedAt = writeTs;\n this.record.eventLog = {\n active_path: this.activePath,\n segment_count: this.segmentCount,\n max_segment_bytes: this.maxSegmentBytes,\n max_segments: this.maxSegments,\n last_write_at: writeTs,\n last_write_error: null,\n };\n }\n });\n\n if (options.checkpoint === true) {\n await writeSessionRecord(this.record);\n }\n }\n\n async checkpoint(): Promise<void> {\n if (this.closed) {\n throw new Error(\"SessionEventWriter is closed\");\n }\n await writeSessionRecord(this.record);\n }\n\n async close(options: AppendOptions = {}): Promise<void> {\n if (this.closed) {\n return;\n }\n\n try {\n if (options.checkpoint !== false) {\n await writeSessionRecord(this.record);\n }\n } finally {\n this.closed = true;\n await releaseEventsLock(this.lock);\n }\n }\n}\n\nexport async function listSessionEvents(sessionId: string): Promise<AcpJsonRpcMessage[]> {\n const maxSegments = await resolveSessionMaxSegments(sessionId);\n const files: string[] = [];\n\n for (let segment = maxSegments; segment >= 1; segment -= 1) {\n const filePath = segmentEventPath(sessionId, segment);\n if (await pathExists(filePath)) {\n files.push(filePath);\n }\n }\n\n const active = activeEventPath(sessionId);\n if (await pathExists(active)) {\n files.push(active);\n }\n\n const events: AcpJsonRpcMessage[] = [];\n for (const filePath of files) {\n const payload = await fs.readFile(filePath, \"utf8\");\n const lines = payload.split(\"\\n\").filter((line) => line.trim().length > 0);\n for (const line of lines) {\n try {\n const parsed = JSON.parse(line);\n if (isAcpJsonRpcMessage(parsed)) {\n events.push(parsed);\n }\n } catch {\n // Skip malformed lines to keep event listing resilient.\n }\n }\n }\n\n return events;\n}\n","import type { SetSessionConfigOptionResponse } from \"@agentclientprotocol/sdk\";\nimport { QueueConnectionError } from \"./errors.js\";\n\nexport type QueueOwnerTurnState = \"idle\" | \"starting\" | \"active\" | \"closing\";\n\nexport type QueueOwnerActiveSessionController = {\n hasActivePrompt: () => boolean;\n requestCancelActivePrompt: () => Promise<boolean>;\n setSessionMode: (modeId: string) => Promise<void>;\n setSessionConfigOption: (\n configId: string,\n value: string,\n ) => Promise<SetSessionConfigOptionResponse>;\n};\n\ntype QueueOwnerTurnControllerOptions = {\n withTimeout: <T>(run: () => Promise<T>, timeoutMs?: number) => Promise<T>;\n setSessionModeFallback: (modeId: string, timeoutMs?: number) => Promise<void>;\n setSessionConfigOptionFallback: (\n configId: string,\n value: string,\n timeoutMs?: number,\n ) => Promise<SetSessionConfigOptionResponse>;\n};\n\nexport class QueueOwnerTurnController {\n private readonly options: QueueOwnerTurnControllerOptions;\n private state: QueueOwnerTurnState = \"idle\";\n private pendingCancel = false;\n private activeController?: QueueOwnerActiveSessionController;\n\n constructor(options: QueueOwnerTurnControllerOptions) {\n this.options = options;\n }\n\n get lifecycleState(): QueueOwnerTurnState {\n return this.state;\n }\n\n get hasPendingCancel(): boolean {\n return this.pendingCancel;\n }\n\n beginTurn(): void {\n this.state = \"starting\";\n this.pendingCancel = false;\n }\n\n markPromptActive(): void {\n if (this.state === \"starting\" || this.state === \"active\") {\n this.state = \"active\";\n }\n }\n\n endTurn(): void {\n this.state = \"idle\";\n this.pendingCancel = false;\n }\n\n beginClosing(): void {\n this.state = \"closing\";\n this.pendingCancel = false;\n this.activeController = undefined;\n }\n\n setActiveController(controller: QueueOwnerActiveSessionController): void {\n this.activeController = controller;\n }\n\n clearActiveController(): void {\n this.activeController = undefined;\n }\n\n private assertCanHandleControlRequest(): void {\n if (this.state === \"closing\") {\n throw new QueueConnectionError(\"Queue owner is closing\", {\n detailCode: \"QUEUE_OWNER_SHUTTING_DOWN\",\n origin: \"queue\",\n retryable: true,\n });\n }\n }\n\n async requestCancel(): Promise<boolean> {\n const activeController = this.activeController;\n if (activeController?.hasActivePrompt()) {\n const cancelled = await activeController.requestCancelActivePrompt();\n if (cancelled) {\n this.pendingCancel = false;\n }\n return cancelled;\n }\n\n if (this.state === \"starting\" || this.state === \"active\") {\n this.pendingCancel = true;\n return true;\n }\n\n return false;\n }\n\n async applyPendingCancel(): Promise<boolean> {\n const activeController = this.activeController;\n if (!this.pendingCancel || !activeController || !activeController.hasActivePrompt()) {\n return false;\n }\n\n const cancelled = await activeController.requestCancelActivePrompt();\n if (cancelled) {\n this.pendingCancel = false;\n }\n return cancelled;\n }\n\n async setSessionMode(modeId: string, timeoutMs?: number): Promise<void> {\n this.assertCanHandleControlRequest();\n const activeController = this.activeController;\n if (activeController) {\n await this.options.withTimeout(\n async () => await activeController.setSessionMode(modeId),\n timeoutMs,\n );\n return;\n }\n\n await this.options.setSessionModeFallback(modeId, timeoutMs);\n }\n\n async setSessionConfigOption(\n configId: string,\n value: string,\n timeoutMs?: number,\n ): Promise<SetSessionConfigOptionResponse> {\n this.assertCanHandleControlRequest();\n const activeController = this.activeController;\n if (activeController) {\n return await this.options.withTimeout(\n async () => await activeController.setSessionConfigOption(configId, value),\n timeoutMs,\n );\n }\n\n return await this.options.setSessionConfigOptionFallback(configId, value, timeoutMs);\n }\n}\n","import type { SessionAcpxState, SessionRecord } from \"./types.js\";\n\nfunction ensureAcpxState(state: SessionAcpxState | undefined): SessionAcpxState {\n return state ?? {};\n}\n\nexport function normalizeModeId(modeId: string | undefined): string | undefined {\n if (typeof modeId !== \"string\") {\n return undefined;\n }\n const trimmed = modeId.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n}\n\nexport function getDesiredModeId(state: SessionAcpxState | undefined): string | undefined {\n return normalizeModeId(state?.desired_mode_id);\n}\n\nexport function setDesiredModeId(record: SessionRecord, modeId: string | undefined): void {\n const acpx = ensureAcpxState(record.acpx);\n const normalized = normalizeModeId(modeId);\n\n if (normalized) {\n acpx.desired_mode_id = normalized;\n } else {\n delete acpx.desired_mode_id;\n }\n\n record.acpx = acpx;\n}\n","import type { AgentLifecycleSnapshot } from \"../client.js\";\nimport { normalizeRuntimeSessionId } from \"../runtime-session-id.js\";\nimport type { SessionConversation, SessionRecord } from \"../types.js\";\n\nexport function applyLifecycleSnapshotToRecord(\n record: SessionRecord,\n snapshot: AgentLifecycleSnapshot,\n): void {\n record.pid = snapshot.pid;\n record.agentStartedAt = snapshot.startedAt;\n\n if (snapshot.lastExit) {\n record.lastAgentExitCode = snapshot.lastExit.exitCode;\n record.lastAgentExitSignal = snapshot.lastExit.signal;\n record.lastAgentExitAt = snapshot.lastExit.exitedAt;\n record.lastAgentDisconnectReason = snapshot.lastExit.reason;\n return;\n }\n\n record.lastAgentExitCode = undefined;\n record.lastAgentExitSignal = undefined;\n record.lastAgentExitAt = undefined;\n record.lastAgentDisconnectReason = undefined;\n}\n\nexport function reconcileAgentSessionId(\n record: SessionRecord,\n agentSessionId: string | undefined,\n): void {\n const normalized = normalizeRuntimeSessionId(agentSessionId);\n if (!normalized) {\n return;\n }\n\n record.agentSessionId = normalized;\n}\n\nexport function sessionHasAgentMessages(record: SessionRecord): boolean {\n return record.messages.some(\n (message) => typeof message === \"object\" && message !== null && \"Agent\" in message,\n );\n}\n\nexport function applyConversation(record: SessionRecord, conversation: SessionConversation): void {\n record.title = conversation.title;\n record.messages = conversation.messages;\n record.updated_at = conversation.updated_at;\n record.cumulative_token_usage = conversation.cumulative_token_usage;\n record.request_token_usage = conversation.request_token_usage;\n}\n","import type { AcpClient } from \"../client.js\";\nimport {\n extractAcpError,\n formatErrorMessage,\n isAcpQueryClosedBeforeResponseError,\n isAcpResourceNotFoundError,\n} from \"../error-normalization.js\";\nimport { SessionModeReplayError } from \"../errors.js\";\nimport { incrementPerfCounter } from \"../perf-metrics.js\";\nimport { isProcessAlive } from \"../queue-ipc.js\";\nimport type { QueueOwnerActiveSessionController } from \"../queue-owner-turn-controller.js\";\nimport { getDesiredModeId } from \"../session-mode-preference.js\";\nimport { InterruptedError, TimeoutError, withTimeout } from \"../session-runtime-helpers.js\";\nimport type { SessionRecord } from \"../types.js\";\nimport {\n applyLifecycleSnapshotToRecord,\n reconcileAgentSessionId,\n sessionHasAgentMessages,\n} from \"./lifecycle.js\";\n\nexport type ConnectAndLoadSessionOptions = {\n client: AcpClient;\n record: SessionRecord;\n timeoutMs?: number;\n verbose?: boolean;\n activeController: QueueOwnerActiveSessionController;\n onClientAvailable?: (controller: QueueOwnerActiveSessionController) => void;\n onConnectedRecord?: (record: SessionRecord) => void;\n onSessionIdResolved?: (sessionId: string) => void;\n};\n\nexport type ConnectAndLoadSessionResult = {\n sessionId: string;\n agentSessionId?: string;\n resumed: boolean;\n loadError?: string;\n};\n\nfunction shouldFallbackToNewSession(error: unknown, record: SessionRecord): boolean {\n if (error instanceof TimeoutError || error instanceof InterruptedError) {\n return false;\n }\n\n if (isAcpResourceNotFoundError(error)) {\n return true;\n }\n\n // Some adapters return JSON-RPC internal errors when trying to\n // load sessions that have never produced an agent turn yet.\n if (!sessionHasAgentMessages(record)) {\n if (isAcpQueryClosedBeforeResponseError(error)) {\n return true;\n }\n\n const acp = extractAcpError(error);\n if (acp?.code === -32603) {\n return true;\n }\n }\n\n return false;\n}\n\nexport async function connectAndLoadSession(\n options: ConnectAndLoadSessionOptions,\n): Promise<ConnectAndLoadSessionResult> {\n const record = options.record;\n const client = options.client;\n const originalSessionId = record.acpSessionId;\n const originalAgentSessionId = record.agentSessionId;\n const desiredModeId = getDesiredModeId(record.acpx);\n const storedProcessAlive = isProcessAlive(record.pid);\n const shouldReconnect = Boolean(record.pid) && !storedProcessAlive;\n\n if (options.verbose) {\n if (storedProcessAlive) {\n process.stderr.write(\n `[acpx] saved session pid ${record.pid} is running; reconnecting with loadSession\\n`,\n );\n } else if (shouldReconnect) {\n process.stderr.write(\n `[acpx] saved session pid ${record.pid} is dead; respawning agent and attempting session/load\\n`,\n );\n }\n }\n\n const reusingLoadedSession = client.hasReusableSession(record.acpSessionId);\n if (reusingLoadedSession) {\n incrementPerfCounter(\"runtime.connect_and_load.reused_session\");\n } else {\n await withTimeout(client.start(), options.timeoutMs);\n }\n options.onClientAvailable?.(options.activeController);\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n record.closed = false;\n record.closedAt = undefined;\n options.onConnectedRecord?.(record);\n\n let resumed = false;\n let loadError: string | undefined;\n let sessionId = record.acpSessionId;\n let createdFreshSession = false;\n let pendingAgentSessionId = record.agentSessionId;\n\n if (reusingLoadedSession) {\n resumed = true;\n } else if (client.supportsLoadSession()) {\n try {\n const loadResult = await withTimeout(\n client.loadSessionWithOptions(record.acpSessionId, record.cwd, {\n suppressReplayUpdates: true,\n }),\n options.timeoutMs,\n );\n reconcileAgentSessionId(record, loadResult.agentSessionId);\n resumed = true;\n } catch (error) {\n loadError = formatErrorMessage(error);\n if (!shouldFallbackToNewSession(error, record)) {\n throw error;\n }\n const createdSession = await withTimeout(client.createSession(record.cwd), options.timeoutMs);\n sessionId = createdSession.sessionId;\n createdFreshSession = true;\n pendingAgentSessionId = createdSession.agentSessionId;\n }\n } else {\n const createdSession = await withTimeout(client.createSession(record.cwd), options.timeoutMs);\n sessionId = createdSession.sessionId;\n createdFreshSession = true;\n pendingAgentSessionId = createdSession.agentSessionId;\n }\n\n if (createdFreshSession && desiredModeId) {\n try {\n await withTimeout(client.setSessionMode(sessionId, desiredModeId), options.timeoutMs);\n if (options.verbose) {\n process.stderr.write(\n `[acpx] replayed desired mode ${desiredModeId} on fresh ACP session ${sessionId} (previous ${originalSessionId})\\n`,\n );\n }\n } catch (error) {\n const message =\n `Failed to replay saved session mode ${desiredModeId} on fresh ACP session ${sessionId}: ` +\n formatErrorMessage(error);\n record.acpSessionId = originalSessionId;\n record.agentSessionId = originalAgentSessionId;\n if (options.verbose) {\n process.stderr.write(`[acpx] ${message}\\n`);\n }\n throw new SessionModeReplayError(message, {\n cause: error instanceof Error ? error : undefined,\n retryable: true,\n });\n }\n }\n\n if (createdFreshSession) {\n record.acpSessionId = sessionId;\n reconcileAgentSessionId(record, pendingAgentSessionId);\n }\n\n options.onSessionIdResolved?.(sessionId);\n\n return {\n sessionId,\n agentSessionId: record.agentSessionId,\n resumed,\n loadError,\n };\n}\n","import { AcpClient } from \"../client.js\";\nimport type { QueueOwnerActiveSessionController } from \"../queue-owner-turn-controller.js\";\nimport { setDesiredModeId } from \"../session-mode-preference.js\";\nimport {\n absolutePath,\n isoNow,\n resolveSessionRecord,\n writeSessionRecord,\n} from \"../session-persistence.js\";\nimport { withInterrupt, withTimeout } from \"../session-runtime-helpers.js\";\nimport type {\n AuthPolicy,\n McpServer,\n NonInteractivePermissionPolicy,\n PermissionMode,\n SessionRecord,\n SessionSetConfigOptionResult,\n SessionSetModeResult,\n} from \"../types.js\";\nimport { connectAndLoadSession } from \"./connect-load.js\";\nimport { applyLifecycleSnapshotToRecord } from \"./lifecycle.js\";\n\nexport type ActiveSessionController = QueueOwnerActiveSessionController;\n\ntype WithConnectedSessionOptions<T> = {\n sessionRecordId: string;\n mcpServers?: McpServer[];\n permissionMode?: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n timeoutMs?: number;\n verbose?: boolean;\n onClientAvailable?: (controller: ActiveSessionController) => void;\n onClientClosed?: () => void;\n run: (client: AcpClient, sessionId: string, record: SessionRecord) => Promise<T>;\n};\n\ntype WithConnectedSessionResult<T> = {\n value: T;\n record: SessionRecord;\n resumed: boolean;\n loadError?: string;\n};\n\nasync function withConnectedSession<T>(\n options: WithConnectedSessionOptions<T>,\n): Promise<WithConnectedSessionResult<T>> {\n const record = await resolveSessionRecord(options.sessionRecordId);\n const client = new AcpClient({\n agentCommand: record.agentCommand,\n cwd: absolutePath(record.cwd),\n mcpServers: options.mcpServers,\n permissionMode: options.permissionMode ?? \"approve-reads\",\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n verbose: options.verbose,\n });\n let activeSessionIdForControl = record.acpSessionId;\n let notifiedClientAvailable = false;\n const activeController: ActiveSessionController = {\n hasActivePrompt: () => client.hasActivePrompt(),\n requestCancelActivePrompt: async () => await client.requestCancelActivePrompt(),\n setSessionMode: async (modeId: string) => {\n await client.setSessionMode(activeSessionIdForControl, modeId);\n },\n setSessionConfigOption: async (configId: string, value: string) => {\n return await client.setSessionConfigOption(activeSessionIdForControl, configId, value);\n },\n };\n\n try {\n return await withInterrupt(\n async () => {\n const {\n sessionId: activeSessionId,\n resumed,\n loadError,\n } = await connectAndLoadSession({\n client,\n record,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n activeController,\n onClientAvailable: (controller) => {\n options.onClientAvailable?.(controller);\n notifiedClientAvailable = true;\n },\n onSessionIdResolved: (sessionId) => {\n activeSessionIdForControl = sessionId;\n },\n });\n\n const value = await options.run(client, activeSessionId, record);\n\n const now = isoNow();\n record.lastUsedAt = now;\n record.closed = false;\n record.closedAt = undefined;\n record.protocolVersion = client.initializeResult?.protocolVersion;\n record.agentCapabilities = client.initializeResult?.agentCapabilities;\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n await writeSessionRecord(record);\n\n return {\n value,\n record,\n resumed,\n loadError,\n };\n },\n async () => {\n await client.cancelActivePrompt(2_500);\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n record.lastUsedAt = isoNow();\n await writeSessionRecord(record).catch(() => {\n // best effort while process is being interrupted\n });\n await client.close();\n },\n );\n } finally {\n if (notifiedClientAvailable) {\n options.onClientClosed?.();\n }\n await client.close();\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n await writeSessionRecord(record).catch(() => {\n // best effort on close\n });\n }\n}\n\nexport type RunSessionSetModeDirectOptions = {\n sessionRecordId: string;\n modeId: string;\n mcpServers?: McpServer[];\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n timeoutMs?: number;\n verbose?: boolean;\n onClientAvailable?: (controller: ActiveSessionController) => void;\n onClientClosed?: () => void;\n};\n\nexport type RunSessionSetConfigOptionDirectOptions = {\n sessionRecordId: string;\n configId: string;\n value: string;\n mcpServers?: McpServer[];\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n timeoutMs?: number;\n verbose?: boolean;\n onClientAvailable?: (controller: ActiveSessionController) => void;\n onClientClosed?: () => void;\n};\n\nexport async function runSessionSetModeDirect(\n options: RunSessionSetModeDirectOptions,\n): Promise<SessionSetModeResult> {\n const result = await withConnectedSession({\n sessionRecordId: options.sessionRecordId,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n onClientAvailable: options.onClientAvailable,\n onClientClosed: options.onClientClosed,\n run: async (client, sessionId, record) => {\n await withTimeout(client.setSessionMode(sessionId, options.modeId), options.timeoutMs);\n setDesiredModeId(record, options.modeId);\n },\n });\n\n return {\n record: result.record,\n resumed: result.resumed,\n loadError: result.loadError,\n };\n}\n\nexport async function runSessionSetConfigOptionDirect(\n options: RunSessionSetConfigOptionDirectOptions,\n): Promise<SessionSetConfigOptionResult> {\n const result = await withConnectedSession({\n sessionRecordId: options.sessionRecordId,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n onClientAvailable: options.onClientAvailable,\n onClientClosed: options.onClientClosed,\n run: async (client, sessionId, record) => {\n const response = await withTimeout(\n client.setSessionConfigOption(sessionId, options.configId, options.value),\n options.timeoutMs,\n );\n if (options.configId === \"mode\") {\n setDesiredModeId(record, options.value);\n }\n return response;\n },\n });\n\n return {\n record: result.record,\n response: result.value,\n resumed: result.resumed,\n loadError: result.loadError,\n };\n}\n","import { spawn } from \"node:child_process\";\nimport { realpathSync } from \"node:fs\";\nimport type {\n AuthPolicy,\n McpServer,\n NonInteractivePermissionPolicy,\n PermissionMode,\n} from \"../types.js\";\n\nexport type QueueOwnerRuntimeOptions = {\n sessionId: string;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n suppressSdkConsoleErrors?: boolean;\n verbose?: boolean;\n ttlMs?: number;\n maxQueueDepth?: number;\n};\n\ntype SessionSendLike = {\n sessionId: string;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n suppressSdkConsoleErrors?: boolean;\n verbose?: boolean;\n ttlMs?: number;\n maxQueueDepth?: number;\n};\n\nexport function resolveQueueOwnerSpawnArgs(argv: readonly string[] = process.argv): string[] {\n const entry = argv[1];\n if (!entry || entry.trim().length === 0) {\n throw new Error(\"acpx self-spawn failed: missing CLI entry path\");\n }\n const resolvedEntry = realpathSync(entry);\n return [resolvedEntry, \"__queue-owner\"];\n}\n\nexport function queueOwnerRuntimeOptionsFromSend(\n options: SessionSendLike,\n): QueueOwnerRuntimeOptions {\n return {\n sessionId: options.sessionId,\n mcpServers: options.mcpServers,\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n verbose: options.verbose,\n ttlMs: options.ttlMs,\n maxQueueDepth: options.maxQueueDepth,\n };\n}\n\nexport function buildQueueOwnerSpawnOptions(payload: string): {\n detached: true;\n stdio: \"ignore\";\n env: NodeJS.ProcessEnv;\n windowsHide: true;\n} {\n return {\n detached: true,\n stdio: \"ignore\",\n env: {\n ...process.env,\n ACPX_QUEUE_OWNER_PAYLOAD: payload,\n },\n windowsHide: true,\n };\n}\n\nexport function spawnQueueOwnerProcess(options: QueueOwnerRuntimeOptions): void {\n const payload = JSON.stringify(options);\n const child = spawn(\n process.execPath,\n resolveQueueOwnerSpawnArgs(),\n buildQueueOwnerSpawnOptions(payload),\n );\n child.unref();\n}\n","import fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { AcpClient } from \"./client.js\";\nimport { formatErrorMessage, normalizeOutputError } from \"./error-normalization.js\";\nimport { checkpointPerfMetricsCapture } from \"./perf-metrics-capture.js\";\nimport { formatPerfMetric, measurePerf, setPerfGauge, startPerfTimer } from \"./perf-metrics.js\";\nimport { refreshQueueOwnerLease } from \"./queue-lease-store.js\";\nimport {\n cloneSessionAcpxState,\n cloneSessionConversation,\n createSessionConversation,\n recordClientOperation as recordConversationClientOperation,\n recordPromptSubmission,\n recordSessionUpdate as recordConversationSessionUpdate,\n trimConversationForRuntime,\n} from \"./session-conversation-model.js\";\nimport { defaultSessionEventLog } from \"./session-event-log.js\";\nimport { SessionEventWriter } from \"./session-events.js\";\nimport { InterruptedError, withInterrupt, withTimeout } from \"./session-runtime-helpers.js\";\nexport { InterruptedError, TimeoutError } from \"./session-runtime-helpers.js\";\nimport {\n type QueueOwnerMessage,\n type QueueTask,\n QUEUE_CONNECT_RETRY_MS,\n SessionQueueOwner,\n isProcessAlive,\n releaseQueueOwnerLease,\n terminateProcess,\n terminateQueueOwnerForSession,\n tryAcquireQueueOwnerLease,\n tryCancelOnRunningOwner,\n trySetConfigOptionOnRunningOwner,\n trySetModeOnRunningOwner,\n trySubmitToRunningOwner,\n waitMs,\n} from \"./queue-ipc.js\";\nimport {\n QueueOwnerTurnController,\n type QueueOwnerActiveSessionController,\n} from \"./queue-owner-turn-controller.js\";\nimport { normalizeRuntimeSessionId } from \"./runtime-session-id.js\";\nimport { setDesiredModeId } from \"./session-mode-preference.js\";\nimport { connectAndLoadSession } from \"./session-runtime/connect-load.js\";\nimport { applyConversation, applyLifecycleSnapshotToRecord } from \"./session-runtime/lifecycle.js\";\nimport {\n runSessionSetConfigOptionDirect,\n runSessionSetModeDirect,\n} from \"./session-runtime/prompt-runner.js\";\nimport {\n queueOwnerRuntimeOptionsFromSend,\n spawnQueueOwnerProcess,\n type QueueOwnerRuntimeOptions,\n} from \"./session-runtime/queue-owner-process.js\";\nexport type { QueueOwnerRuntimeOptions } from \"./session-runtime/queue-owner-process.js\";\nimport { promptToDisplayText, textPrompt } from \"./prompt-content.js\";\nimport {\n DEFAULT_HISTORY_LIMIT,\n absolutePath,\n findGitRepositoryRoot,\n findSession,\n findSessionByDirectoryWalk,\n isoNow,\n listSessions,\n listSessionsForAgent,\n normalizeName,\n resolveSessionRecord,\n writeSessionRecord,\n} from \"./session-persistence.js\";\nimport {\n SESSION_RECORD_SCHEMA,\n type AcpJsonRpcMessage,\n type AuthPolicy,\n type McpServer,\n type NonInteractivePermissionPolicy,\n type OutputErrorEmissionPolicy,\n type OutputErrorAcpPayload,\n type OutputErrorCode,\n type OutputErrorOrigin,\n type OutputFormatter,\n type PermissionMode,\n type PromptInput,\n type RunPromptResult,\n type SessionEnsureResult,\n type SessionRecord,\n type SessionSetConfigOptionResult,\n type SessionSetModeResult,\n type SessionSendOutcome,\n type SessionSendResult,\n} from \"./types.js\";\n\nexport const DEFAULT_QUEUE_OWNER_TTL_MS = 300_000;\nconst INTERRUPT_CANCEL_WAIT_MS = 2_500;\nconst QUEUE_OWNER_STARTUP_MAX_ATTEMPTS = 120;\nconst QUEUE_OWNER_HEARTBEAT_INTERVAL_MS = 5_000;\n\ntype TimedRunOptions = {\n timeoutMs?: number;\n};\n\nexport type SessionAgentOptions = {\n model?: string;\n allowedTools?: string[];\n maxTurns?: number;\n};\n\nexport type RunOnceOptions = {\n agentCommand: string;\n cwd: string;\n prompt: PromptInput;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n outputFormatter: OutputFormatter;\n suppressSdkConsoleErrors?: boolean;\n verbose?: boolean;\n sessionOptions?: SessionAgentOptions;\n} & TimedRunOptions;\n\nexport type SessionCreateOptions = {\n agentCommand: string;\n cwd: string;\n name?: string;\n resumeSessionId?: string;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n verbose?: boolean;\n sessionOptions?: SessionAgentOptions;\n} & TimedRunOptions;\n\nexport type SessionSendOptions = {\n sessionId: string;\n prompt: PromptInput;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n outputFormatter: OutputFormatter;\n errorEmissionPolicy?: OutputErrorEmissionPolicy;\n suppressSdkConsoleErrors?: boolean;\n verbose?: boolean;\n waitForCompletion?: boolean;\n ttlMs?: number;\n maxQueueDepth?: number;\n} & TimedRunOptions;\n\nexport type SessionEnsureOptions = {\n agentCommand: string;\n cwd: string;\n name?: string;\n resumeSessionId?: string;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n verbose?: boolean;\n walkBoundary?: string;\n sessionOptions?: SessionAgentOptions;\n} & TimedRunOptions;\n\nexport type SessionCancelOptions = {\n sessionId: string;\n verbose?: boolean;\n};\n\nexport type SessionCancelResult = {\n sessionId: string;\n cancelled: boolean;\n};\n\nexport type SessionSetModeOptions = {\n sessionId: string;\n modeId: string;\n mcpServers?: McpServer[];\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n verbose?: boolean;\n} & TimedRunOptions;\n\nexport type SessionSetConfigOptionOptions = {\n sessionId: string;\n configId: string;\n value: string;\n mcpServers?: McpServer[];\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n verbose?: boolean;\n} & TimedRunOptions;\n\nfunction toPromptResult(\n stopReason: RunPromptResult[\"stopReason\"],\n sessionId: string,\n client: AcpClient,\n): RunPromptResult {\n return {\n stopReason,\n sessionId,\n permissionStats: client.getPermissionStats(),\n };\n}\n\ntype RunSessionPromptOptions = {\n sessionRecordId: string;\n prompt: PromptInput;\n mcpServers?: McpServer[];\n permissionMode: PermissionMode;\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n outputFormatter: OutputFormatter;\n timeoutMs?: number;\n suppressSdkConsoleErrors?: boolean;\n verbose?: boolean;\n onClientAvailable?: (controller: ActiveSessionController) => void;\n onClientClosed?: () => void;\n onPromptActive?: () => Promise<void> | void;\n client?: AcpClient;\n};\n\ntype ActiveSessionController = QueueOwnerActiveSessionController;\n\nclass QueueTaskOutputFormatter implements OutputFormatter {\n private readonly requestId: string;\n private readonly send: (message: QueueOwnerMessage) => void;\n\n constructor(task: QueueTask) {\n this.requestId = task.requestId;\n this.send = task.send;\n }\n\n setContext(_context: { sessionId: string }): void {\n // queue formatter context is fixed by task request id\n }\n\n onAcpMessage(message: AcpJsonRpcMessage): void {\n this.send({\n type: \"event\",\n requestId: this.requestId,\n message,\n });\n }\n\n onError(params: {\n code: OutputErrorCode;\n detailCode?: string;\n origin?: OutputErrorOrigin;\n message: string;\n retryable?: boolean;\n acp?: OutputErrorAcpPayload;\n timestamp?: string;\n }): void {\n this.send({\n type: \"error\",\n requestId: this.requestId,\n code: params.code,\n detailCode: params.detailCode,\n origin: params.origin,\n message: params.message,\n retryable: params.retryable,\n acp: params.acp,\n });\n }\n\n flush(): void {\n // no-op for stream forwarding\n }\n}\n\nconst DISCARD_OUTPUT_FORMATTER: OutputFormatter = {\n setContext(_context) {\n // no-op\n },\n onAcpMessage() {\n // no-op\n },\n onError() {\n // no-op\n },\n flush() {\n // no-op\n },\n};\n\nfunction jsonRpcIdKey(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n return `s:${value}`;\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return `n:${value}`;\n }\n return undefined;\n}\n\nfunction extractJsonRpcRequestInfo(\n message: AcpJsonRpcMessage,\n): { idKey: string; method: string } | undefined {\n const candidate = message as { method?: unknown; id?: unknown };\n if (typeof candidate.method !== \"string\") {\n return undefined;\n }\n const idKey = jsonRpcIdKey(candidate.id);\n if (!idKey) {\n return undefined;\n }\n return {\n idKey,\n method: candidate.method,\n };\n}\n\nfunction extractJsonRpcResponseInfo(\n message: AcpJsonRpcMessage,\n): { idKey: string; hasError: boolean } | undefined {\n const candidate = message as { id?: unknown; error?: unknown; result?: unknown };\n const idKey = jsonRpcIdKey(candidate.id);\n if (!idKey) {\n return undefined;\n }\n const hasError = Object.hasOwn(candidate, \"error\");\n const hasResult = Object.hasOwn(candidate, \"result\");\n if (!hasError && !hasResult) {\n return undefined;\n }\n return {\n idKey,\n hasError,\n };\n}\n\nfunction filterRecoverableLoadFallbackOutput(messages: AcpJsonRpcMessage[]): AcpJsonRpcMessage[] {\n const requestMethodById = new Map<string, string>();\n const failedLoadRequestIds = new Set<string>();\n\n for (const message of messages) {\n const request = extractJsonRpcRequestInfo(message);\n if (request) {\n requestMethodById.set(request.idKey, request.method);\n continue;\n }\n\n const response = extractJsonRpcResponseInfo(message);\n if (!response || !response.hasError) {\n continue;\n }\n\n if (requestMethodById.get(response.idKey) === \"session/load\") {\n failedLoadRequestIds.add(response.idKey);\n }\n }\n\n if (failedLoadRequestIds.size === 0) {\n return messages;\n }\n\n return messages.filter((message) => {\n const request = extractJsonRpcRequestInfo(message);\n if (request && request.method === \"session/load\" && failedLoadRequestIds.has(request.idKey)) {\n return false;\n }\n\n const response = extractJsonRpcResponseInfo(message);\n if (response && failedLoadRequestIds.has(response.idKey)) {\n return false;\n }\n\n return true;\n });\n}\n\nexport function normalizeQueueOwnerTtlMs(ttlMs: number | undefined): number {\n if (ttlMs == null) {\n return DEFAULT_QUEUE_OWNER_TTL_MS;\n }\n\n if (!Number.isFinite(ttlMs) || ttlMs < 0) {\n return DEFAULT_QUEUE_OWNER_TTL_MS;\n }\n\n // 0 means keep alive forever (no TTL)\n return Math.round(ttlMs);\n}\n\nasync function runQueuedTask(\n sessionRecordId: string,\n task: QueueTask,\n options: {\n sharedClient?: AcpClient;\n verbose?: boolean;\n mcpServers?: McpServer[];\n nonInteractivePermissions?: NonInteractivePermissionPolicy;\n authCredentials?: Record<string, string>;\n authPolicy?: AuthPolicy;\n suppressSdkConsoleErrors?: boolean;\n onClientAvailable?: (controller: ActiveSessionController) => void;\n onClientClosed?: () => void;\n onPromptActive?: () => Promise<void> | void;\n },\n): Promise<void> {\n const outputFormatter = task.waitForCompletion\n ? new QueueTaskOutputFormatter(task)\n : DISCARD_OUTPUT_FORMATTER;\n\n try {\n const result = await runSessionPrompt({\n sessionRecordId,\n mcpServers: options.mcpServers,\n prompt: task.prompt ?? textPrompt(task.message),\n permissionMode: task.permissionMode,\n nonInteractivePermissions:\n task.nonInteractivePermissions ?? options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n outputFormatter,\n timeoutMs: task.timeoutMs,\n suppressSdkConsoleErrors: task.suppressSdkConsoleErrors ?? options.suppressSdkConsoleErrors,\n verbose: options.verbose,\n onClientAvailable: options.onClientAvailable,\n onClientClosed: options.onClientClosed,\n onPromptActive: options.onPromptActive,\n client: options.sharedClient,\n });\n\n if (task.waitForCompletion) {\n task.send({\n type: \"result\",\n requestId: task.requestId,\n result,\n });\n }\n } catch (error) {\n const normalizedError = normalizeOutputError(error, {\n origin: \"runtime\",\n detailCode: \"QUEUE_RUNTIME_PROMPT_FAILED\",\n });\n const alreadyEmitted =\n (error as { outputAlreadyEmitted?: unknown }).outputAlreadyEmitted === true;\n if (task.waitForCompletion) {\n task.send({\n type: \"error\",\n requestId: task.requestId,\n code: normalizedError.code,\n detailCode: normalizedError.detailCode,\n origin: normalizedError.origin,\n message: normalizedError.message,\n retryable: normalizedError.retryable,\n acp: normalizedError.acp,\n outputAlreadyEmitted: alreadyEmitted,\n });\n }\n\n if (error instanceof InterruptedError) {\n throw error;\n }\n } finally {\n task.close();\n }\n}\n\nasync function runSessionPrompt(options: RunSessionPromptOptions): Promise<SessionSendResult> {\n const stopTotalTimer = startPerfTimer(\"runtime.prompt.total\");\n const output = options.outputFormatter;\n const record = await measurePerf(\"session.resolve_prompt_record\", async () => {\n return await resolveSessionRecord(options.sessionRecordId);\n });\n const conversation = cloneSessionConversation(record);\n let acpxState = cloneSessionAcpxState(record.acpx);\n recordPromptSubmission(conversation, options.prompt, isoNow());\n\n output.setContext({\n sessionId: record.acpxRecordId,\n });\n\n const eventWriter = await measurePerf(\"session.events.open\", async () => {\n return await SessionEventWriter.open(record);\n });\n const pendingMessages: AcpJsonRpcMessage[] = [];\n const pendingConnectOutputMessages: AcpJsonRpcMessage[] = [];\n let bufferingConnectOutput = true;\n let sawAcpMessage = false;\n let eventWriterClosed = false;\n\n const closeEventWriter = async (checkpoint: boolean): Promise<void> => {\n if (eventWriterClosed) {\n return;\n }\n eventWriterClosed = true;\n await eventWriter.close({ checkpoint });\n };\n\n const flushPendingMessages = async (checkpoint = false): Promise<void> => {\n if (pendingMessages.length === 0) {\n return;\n }\n\n const batch = pendingMessages.splice(0, pendingMessages.length);\n await measurePerf(\"session.events.flush_pending\", async () => {\n await eventWriter.appendMessages(batch, { checkpoint });\n });\n };\n\n const ownClient = options.client == null;\n const client =\n options.client ??\n new AcpClient({\n agentCommand: record.agentCommand,\n cwd: absolutePath(record.cwd),\n mcpServers: options.mcpServers,\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n verbose: options.verbose,\n });\n client.updateRuntimeOptions({\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n verbose: options.verbose,\n });\n client.setEventHandlers({\n onAcpMessage: (_direction, message) => {\n sawAcpMessage = true;\n pendingMessages.push(message);\n },\n onAcpOutputMessage: (_direction, message) => {\n if (bufferingConnectOutput) {\n pendingConnectOutputMessages.push(message);\n return;\n }\n output.onAcpMessage(message);\n },\n onSessionUpdate: (notification) => {\n acpxState = recordConversationSessionUpdate(conversation, acpxState, notification);\n trimConversationForRuntime(conversation);\n },\n onClientOperation: (operation) => {\n acpxState = recordConversationClientOperation(conversation, acpxState, operation);\n trimConversationForRuntime(conversation);\n },\n });\n let activeSessionIdForControl = record.acpSessionId;\n let notifiedClientAvailable = false;\n const activeController: ActiveSessionController = {\n hasActivePrompt: () => client.hasActivePrompt(),\n requestCancelActivePrompt: async () => await client.requestCancelActivePrompt(),\n setSessionMode: async (modeId: string) => {\n await client.setSessionMode(activeSessionIdForControl, modeId);\n },\n setSessionConfigOption: async (configId: string, value: string) => {\n return await client.setSessionConfigOption(activeSessionIdForControl, configId, value);\n },\n };\n\n try {\n return await withInterrupt(\n async () => {\n const connectStartedAt = Date.now();\n const {\n sessionId: activeSessionId,\n resumed,\n loadError,\n } = await measurePerf(\"runtime.connect_and_load\", async () => {\n try {\n return await connectAndLoadSession({\n client,\n record,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n activeController,\n onClientAvailable: (controller) => {\n options.onClientAvailable?.(controller);\n notifiedClientAvailable = true;\n },\n onConnectedRecord: (connectedRecord) => {\n connectedRecord.lastPromptAt = isoNow();\n },\n onSessionIdResolved: (sessionId) => {\n activeSessionIdForControl = sessionId;\n },\n });\n } catch (error) {\n bufferingConnectOutput = false;\n for (const message of pendingConnectOutputMessages) {\n output.onAcpMessage(message);\n }\n pendingConnectOutputMessages.length = 0;\n throw error;\n }\n });\n bufferingConnectOutput = false;\n const connectOutputMessages =\n loadError == null\n ? pendingConnectOutputMessages\n : filterRecoverableLoadFallbackOutput(pendingConnectOutputMessages);\n for (const message of connectOutputMessages) {\n output.onAcpMessage(message);\n }\n pendingConnectOutputMessages.length = 0;\n if (options.verbose) {\n process.stderr.write(\n `[acpx] ${formatPerfMetric(\"prompt.connect_and_load\", Date.now() - connectStartedAt)}\\n`,\n );\n }\n\n output.setContext({\n sessionId: record.acpxRecordId,\n });\n await flushPendingMessages(false);\n\n let response;\n try {\n const promptStartedAt = Date.now();\n const promptPromise = client.prompt(activeSessionId, options.prompt);\n if (options.onPromptActive) {\n try {\n await options.onPromptActive();\n } catch (error) {\n if (options.verbose) {\n process.stderr.write(\n \"[acpx] onPromptActive hook failed: \" + formatErrorMessage(error) + \"\\n\",\n );\n }\n }\n }\n response = await measurePerf(\"runtime.prompt.agent_turn\", async () => {\n return await withTimeout(promptPromise, options.timeoutMs);\n });\n if (options.verbose) {\n process.stderr.write(\n `[acpx] ${formatPerfMetric(\"prompt.agent_turn\", Date.now() - promptStartedAt)}\\n`,\n );\n }\n } catch (error) {\n const snapshot = client.getAgentLifecycleSnapshot();\n applyLifecycleSnapshotToRecord(record, snapshot);\n if (snapshot.lastExit?.unexpectedDuringPrompt && options.verbose) {\n process.stderr.write(\n \"[acpx] agent disconnected during prompt (\" +\n snapshot.lastExit.reason +\n \", exit=\" +\n snapshot.lastExit.exitCode +\n \", signal=\" +\n (snapshot.lastExit.signal ?? \"none\") +\n \")\\n\",\n );\n }\n\n const normalizedError = normalizeOutputError(error, {\n origin: \"runtime\",\n });\n\n await flushPendingMessages(false).catch(() => {\n // best effort while bubbling prompt failure\n });\n\n output.flush();\n\n record.lastUsedAt = isoNow();\n applyConversation(record, conversation);\n record.acpx = acpxState;\n\n const propagated = error instanceof Error ? error : new Error(formatErrorMessage(error));\n (propagated as { outputAlreadyEmitted?: boolean }).outputAlreadyEmitted = sawAcpMessage;\n (propagated as { normalizedOutputError?: unknown }).normalizedOutputError =\n normalizedError;\n throw propagated;\n }\n\n await flushPendingMessages(false);\n output.flush();\n\n const now = isoNow();\n record.lastUsedAt = now;\n record.closed = false;\n record.closedAt = undefined;\n record.protocolVersion = client.initializeResult?.protocolVersion;\n record.agentCapabilities = client.initializeResult?.agentCapabilities;\n applyConversation(record, conversation);\n record.acpx = acpxState;\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n stopTotalTimer();\n\n return {\n ...toPromptResult(response.stopReason, record.acpxRecordId, client),\n record,\n resumed,\n loadError,\n };\n },\n async () => {\n await client.cancelActivePrompt(INTERRUPT_CANCEL_WAIT_MS);\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n record.lastUsedAt = isoNow();\n applyConversation(record, conversation);\n record.acpx = acpxState;\n await flushPendingMessages(false).catch(() => {\n // best effort while process is being interrupted\n });\n if (ownClient) {\n await client.close();\n }\n },\n );\n } finally {\n if (options.verbose) {\n process.stderr.write(`[acpx] ${formatPerfMetric(\"prompt.total\", stopTotalTimer())}\\n`);\n } else {\n stopTotalTimer();\n }\n if (notifiedClientAvailable) {\n options.onClientClosed?.();\n }\n client.clearEventHandlers();\n if (ownClient) {\n await client.close();\n }\n applyLifecycleSnapshotToRecord(record, client.getAgentLifecycleSnapshot());\n applyConversation(record, conversation);\n record.acpx = acpxState;\n await flushPendingMessages(false).catch(() => {\n // best effort on close\n });\n await closeEventWriter(true).catch(() => {\n // best effort on close\n });\n }\n}\n\nexport async function runOnce(options: RunOnceOptions): Promise<RunPromptResult> {\n const output = options.outputFormatter;\n const client = new AcpClient({\n agentCommand: options.agentCommand,\n cwd: absolutePath(options.cwd),\n mcpServers: options.mcpServers,\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n verbose: options.verbose,\n onAcpOutputMessage: (_direction, message) => output.onAcpMessage(message),\n sessionOptions: options.sessionOptions,\n });\n\n try {\n return await withInterrupt(\n async () => {\n await measurePerf(\"runtime.exec.start\", async () => {\n await withTimeout(client.start(), options.timeoutMs);\n });\n const createdSession = await measurePerf(\"runtime.exec.create_session\", async () => {\n return await withTimeout(\n client.createSession(absolutePath(options.cwd)),\n options.timeoutMs,\n );\n });\n const sessionId = createdSession.sessionId;\n\n output.setContext({\n sessionId,\n });\n\n const response = await measurePerf(\"runtime.exec.prompt\", async () => {\n return await withTimeout(client.prompt(sessionId, options.prompt), options.timeoutMs);\n });\n output.flush();\n return toPromptResult(response.stopReason, sessionId, client);\n },\n async () => {\n await client.cancelActivePrompt(INTERRUPT_CANCEL_WAIT_MS);\n await client.close();\n },\n );\n } finally {\n await client.close();\n }\n}\n\nexport async function createSession(options: SessionCreateOptions): Promise<SessionRecord> {\n const client = new AcpClient({\n agentCommand: options.agentCommand,\n cwd: absolutePath(options.cwd),\n mcpServers: options.mcpServers,\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n verbose: options.verbose,\n sessionOptions: options.sessionOptions,\n });\n\n try {\n return await withInterrupt(\n async () => {\n const cwd = absolutePath(options.cwd);\n await measurePerf(\"runtime.session_create.start\", async () => {\n await withTimeout(client.start(), options.timeoutMs);\n });\n let sessionId: string;\n let agentSessionId: string | undefined;\n\n if (options.resumeSessionId) {\n if (!client.supportsLoadSession()) {\n throw new Error(\n `Agent command \"${options.agentCommand}\" does not support session/load; cannot resume session ${options.resumeSessionId}`,\n );\n }\n\n try {\n const loadedSession = await withTimeout(\n client.loadSession(options.resumeSessionId, cwd),\n options.timeoutMs,\n );\n sessionId = options.resumeSessionId;\n agentSessionId = normalizeRuntimeSessionId(loadedSession.agentSessionId);\n } catch (error) {\n throw new Error(\n `Failed to resume ACP session ${options.resumeSessionId}: ${formatErrorMessage(error)}`,\n {\n cause: error,\n },\n );\n }\n } else {\n const createdSession = await measurePerf(\n \"runtime.session_create.create_session\",\n async () => await withTimeout(client.createSession(cwd), options.timeoutMs),\n );\n sessionId = createdSession.sessionId;\n agentSessionId = normalizeRuntimeSessionId(createdSession.agentSessionId);\n }\n const lifecycle = client.getAgentLifecycleSnapshot();\n\n const now = isoNow();\n const record: SessionRecord = {\n schema: SESSION_RECORD_SCHEMA,\n acpxRecordId: sessionId,\n acpSessionId: sessionId,\n agentSessionId,\n agentCommand: options.agentCommand,\n cwd,\n name: normalizeName(options.name),\n createdAt: now,\n lastUsedAt: now,\n lastSeq: 0,\n lastRequestId: undefined,\n eventLog: defaultSessionEventLog(sessionId),\n closed: false,\n closedAt: undefined,\n pid: lifecycle.pid,\n agentStartedAt: lifecycle.startedAt,\n protocolVersion: client.initializeResult?.protocolVersion,\n agentCapabilities: client.initializeResult?.agentCapabilities,\n ...createSessionConversation(now),\n acpx: {},\n };\n\n await writeSessionRecord(record);\n return record;\n },\n async () => {\n await client.close();\n },\n );\n } finally {\n await client.close();\n }\n}\n\nexport async function ensureSession(options: SessionEnsureOptions): Promise<SessionEnsureResult> {\n const cwd = absolutePath(options.cwd);\n const gitRoot = findGitRepositoryRoot(cwd);\n const walkBoundary = options.walkBoundary ?? gitRoot ?? cwd;\n const existing = await findSessionByDirectoryWalk({\n agentCommand: options.agentCommand,\n cwd,\n name: options.name,\n boundary: walkBoundary,\n });\n if (existing) {\n return {\n record: existing,\n created: false,\n };\n }\n\n const record = await createSession({\n agentCommand: options.agentCommand,\n cwd,\n name: options.name,\n resumeSessionId: options.resumeSessionId,\n mcpServers: options.mcpServers,\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n sessionOptions: options.sessionOptions,\n });\n\n return {\n record,\n created: true,\n };\n}\n\nasync function submitToRunningOwner(\n options: SessionSendOptions,\n waitForCompletion: boolean,\n): Promise<SessionSendOutcome | undefined> {\n return await trySubmitToRunningOwner({\n sessionId: options.sessionId,\n message: promptToDisplayText(options.prompt),\n prompt: options.prompt,\n permissionMode: options.permissionMode,\n nonInteractivePermissions: options.nonInteractivePermissions,\n outputFormatter: options.outputFormatter,\n errorEmissionPolicy: options.errorEmissionPolicy,\n timeoutMs: options.timeoutMs,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n waitForCompletion,\n verbose: options.verbose,\n });\n}\n\nexport async function runSessionQueueOwner(options: QueueOwnerRuntimeOptions): Promise<void> {\n const lease = await tryAcquireQueueOwnerLease(options.sessionId);\n if (!lease) {\n return;\n }\n\n const sessionRecord = await resolveSessionRecord(options.sessionId);\n let owner: SessionQueueOwner | undefined;\n let heartbeatTimer: NodeJS.Timeout | undefined;\n const sharedClient = new AcpClient({\n agentCommand: sessionRecord.agentCommand,\n cwd: absolutePath(sessionRecord.cwd),\n mcpServers: options.mcpServers,\n permissionMode: \"approve-reads\",\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n verbose: options.verbose,\n });\n const ttlMs = normalizeQueueOwnerTtlMs(options.ttlMs);\n const maxQueueDepth = Math.max(1, Math.round(options.maxQueueDepth ?? 16));\n const taskPollTimeoutMs = ttlMs === 0 ? undefined : ttlMs;\n const initialTaskPollTimeoutMs =\n taskPollTimeoutMs == null ? undefined : Math.max(taskPollTimeoutMs, 1_000);\n const turnController = new QueueOwnerTurnController({\n withTimeout: async (run, timeoutMs) => await withTimeout(run(), timeoutMs),\n setSessionModeFallback: async (modeId: string, timeoutMs?: number) => {\n await runSessionSetModeDirect({\n sessionRecordId: options.sessionId,\n modeId,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs,\n verbose: options.verbose,\n });\n },\n setSessionConfigOptionFallback: async (configId: string, value: string, timeoutMs?: number) => {\n const result = await runSessionSetConfigOptionDirect({\n sessionRecordId: options.sessionId,\n configId,\n value,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs,\n verbose: options.verbose,\n });\n return result.response;\n },\n });\n\n const applyPendingCancel = async (): Promise<boolean> => {\n return await turnController.applyPendingCancel();\n };\n\n const scheduleApplyPendingCancel = (): void => {\n void applyPendingCancel().catch((error) => {\n if (options.verbose) {\n process.stderr.write(\n `[acpx] failed to apply deferred cancel: ${formatErrorMessage(error)}\\n`,\n );\n }\n });\n };\n\n const setActiveController = (controller: ActiveSessionController) => {\n turnController.setActiveController(controller);\n scheduleApplyPendingCancel();\n };\n\n const clearActiveController = () => {\n turnController.clearActiveController();\n };\n\n const runPromptTurn = async <T>(run: () => Promise<T>): Promise<T> => {\n turnController.beginTurn();\n try {\n return await run();\n } finally {\n turnController.endTurn();\n }\n };\n\n try {\n owner = await SessionQueueOwner.start(\n lease,\n {\n cancelPrompt: async () => {\n const accepted = await turnController.requestCancel();\n if (!accepted) {\n return false;\n }\n await applyPendingCancel();\n return true;\n },\n setSessionMode: async (modeId: string, timeoutMs?: number) => {\n await turnController.setSessionMode(modeId, timeoutMs);\n },\n setSessionConfigOption: async (configId: string, value: string, timeoutMs?: number) => {\n return await turnController.setSessionConfigOption(configId, value, timeoutMs);\n },\n },\n {\n maxQueueDepth,\n onQueueDepthChanged: (queueDepth) => {\n setPerfGauge(\"queue.owner.depth\", queueDepth);\n void refreshQueueOwnerLease(lease, { queueDepth }).catch(() => {\n // best effort heartbeat refresh while owner is live\n });\n },\n },\n );\n\n if (options.verbose) {\n process.stderr.write(\n `[acpx] queue owner ready for session ${options.sessionId} (ttlMs=${ttlMs}, maxQueueDepth=${maxQueueDepth})\\n`,\n );\n }\n await refreshQueueOwnerLease(lease, { queueDepth: owner.queueDepth() }).catch(() => {\n // best effort initial heartbeat\n });\n heartbeatTimer = setInterval(() => {\n void refreshQueueOwnerLease(lease, { queueDepth: owner?.queueDepth() ?? 0 }).catch(() => {\n // best effort heartbeat\n });\n }, QUEUE_OWNER_HEARTBEAT_INTERVAL_MS);\n\n let isFirstTask = true;\n while (true) {\n const pollTimeoutMs = isFirstTask ? initialTaskPollTimeoutMs : taskPollTimeoutMs;\n const task = await owner.nextTask(pollTimeoutMs);\n if (!task) {\n break;\n }\n isFirstTask = false;\n\n await runPromptTurn(async () => {\n try {\n await runQueuedTask(options.sessionId, task, {\n sharedClient,\n verbose: options.verbose,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n suppressSdkConsoleErrors: options.suppressSdkConsoleErrors,\n onClientAvailable: setActiveController,\n onClientClosed: clearActiveController,\n onPromptActive: async () => {\n turnController.markPromptActive();\n await applyPendingCancel();\n },\n });\n } finally {\n checkpointPerfMetricsCapture();\n }\n });\n }\n } finally {\n if (heartbeatTimer) {\n clearInterval(heartbeatTimer);\n }\n turnController.beginClosing();\n if (owner) {\n await owner.close();\n }\n await sharedClient.close().catch(() => {\n // best effort while queue owner is shutting down\n });\n try {\n const record = await resolveSessionRecord(options.sessionId);\n applyLifecycleSnapshotToRecord(record, sharedClient.getAgentLifecycleSnapshot());\n await writeSessionRecord(record);\n } catch {\n // best effort — session may already be cleaned up\n }\n await releaseQueueOwnerLease(lease);\n\n if (options.verbose) {\n process.stderr.write(`[acpx] queue owner stopped for session ${options.sessionId}\\n`);\n }\n }\n}\n\nexport async function sendSession(options: SessionSendOptions): Promise<SessionSendOutcome> {\n const waitForCompletion = options.waitForCompletion !== false;\n\n const queuedToOwner = await submitToRunningOwner(options, waitForCompletion);\n if (queuedToOwner) {\n return queuedToOwner;\n }\n\n spawnQueueOwnerProcess(queueOwnerRuntimeOptionsFromSend(options));\n\n for (let attempt = 0; attempt < QUEUE_OWNER_STARTUP_MAX_ATTEMPTS; attempt += 1) {\n const queued = await submitToRunningOwner(options, waitForCompletion);\n if (queued) {\n return queued;\n }\n await waitMs(QUEUE_CONNECT_RETRY_MS);\n }\n\n throw new Error(`Session queue owner failed to start for session ${options.sessionId}`);\n}\n\nexport async function cancelSessionPrompt(\n options: SessionCancelOptions,\n): Promise<SessionCancelResult> {\n const cancelled = await tryCancelOnRunningOwner(options);\n return {\n sessionId: options.sessionId,\n cancelled: cancelled === true,\n };\n}\n\nexport async function setSessionMode(\n options: SessionSetModeOptions,\n): Promise<SessionSetModeResult> {\n const submittedToOwner = await trySetModeOnRunningOwner(\n options.sessionId,\n options.modeId,\n options.timeoutMs,\n options.verbose,\n );\n if (submittedToOwner) {\n const record = await resolveSessionRecord(options.sessionId);\n setDesiredModeId(record, options.modeId);\n await writeSessionRecord(record);\n return {\n record,\n resumed: false,\n };\n }\n\n return await runSessionSetModeDirect({\n sessionRecordId: options.sessionId,\n modeId: options.modeId,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n });\n}\n\nexport async function setSessionConfigOption(\n options: SessionSetConfigOptionOptions,\n): Promise<SessionSetConfigOptionResult> {\n const ownerResponse = await trySetConfigOptionOnRunningOwner(\n options.sessionId,\n options.configId,\n options.value,\n options.timeoutMs,\n options.verbose,\n );\n if (ownerResponse) {\n const record = await resolveSessionRecord(options.sessionId);\n if (options.configId === \"mode\") {\n setDesiredModeId(record, options.value);\n await writeSessionRecord(record);\n }\n return {\n record,\n response: ownerResponse,\n resumed: false,\n };\n }\n\n return await runSessionSetConfigOptionDirect({\n sessionRecordId: options.sessionId,\n configId: options.configId,\n value: options.value,\n mcpServers: options.mcpServers,\n nonInteractivePermissions: options.nonInteractivePermissions,\n authCredentials: options.authCredentials,\n authPolicy: options.authPolicy,\n timeoutMs: options.timeoutMs,\n verbose: options.verbose,\n });\n}\n\nfunction firstAgentCommandToken(command: string): string | undefined {\n const trimmed = command.trim();\n if (!trimmed) {\n return undefined;\n }\n const token = trimmed.split(/\\s+/, 1)[0];\n return token.length > 0 ? token : undefined;\n}\n\nasync function isLikelyMatchingProcess(pid: number, agentCommand: string): Promise<boolean> {\n const expectedToken = firstAgentCommandToken(agentCommand);\n if (!expectedToken) {\n return false;\n }\n\n const procCmdline = `/proc/${pid}/cmdline`;\n try {\n const payload = await fs.readFile(procCmdline, \"utf8\");\n const argv = payload\n .split(\"\\u0000\")\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0);\n if (argv.length === 0) {\n return false;\n }\n\n const executableBase = path.basename(argv[0]);\n const expectedBase = path.basename(expectedToken);\n return (\n executableBase === expectedBase || argv.some((entry) => path.basename(entry) === expectedBase)\n );\n } catch {\n // If /proc is unavailable, fall back to PID liveness checks only.\n return true;\n }\n}\n\nexport async function closeSession(sessionId: string): Promise<SessionRecord> {\n const record = await resolveSessionRecord(sessionId);\n await terminateQueueOwnerForSession(record.acpxRecordId);\n\n if (\n record.pid != null &&\n isProcessAlive(record.pid) &&\n (await isLikelyMatchingProcess(record.pid, record.agentCommand))\n ) {\n await terminateProcess(record.pid);\n }\n\n record.pid = undefined;\n record.closed = true;\n record.closedAt = isoNow();\n await writeSessionRecord(record);\n\n return record;\n}\n\nexport {\n DEFAULT_HISTORY_LIMIT,\n findGitRepositoryRoot,\n findSession,\n findSessionByDirectoryWalk,\n isProcessAlive,\n listSessions,\n listSessionsForAgent,\n};\n","export * from \"./session-runtime.js\";\n"],"mappings":"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"}
|