@victor-software-house/pi-acp 0.4.0 → 0.6.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.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["resolvePath","SessionManager","isTextBlock","SessionManager","pkgJson.name","pkgJson.version","PiSessionManager"],"sources":["../src/acp/auth.ts","../src/acp/auth-required.ts","../src/acp/client-capabilities.ts","../src/acp/model-alias.ts","../src/acp/pi-settings.ts","../src/acp/translate/tool-content.ts","../src/acp/unreachable.ts","../src/acp/session.ts","../src/acp/translate/pi-messages.ts","../src/acp/translate/prompt.ts","../src/pi-auth/status.ts","../package.json","../src/acp/agent.ts","../src/index.ts"],"sourcesContent":["/**\n * Build ACP AuthMethod descriptors for terminal-based authentication.\n *\n * Supports both the registry-required \"type/args/env\" shape and Zed's\n * _meta[\"terminal-auth\"] extension for the Authenticate banner.\n */\n\nimport type { AuthMethod } from \"@agentclientprotocol/sdk\";\n\nexport const AUTH_METHOD_ID = \"pi_terminal_login\";\n\ninterface AuthMethodOptions {\n\tsupportsTerminalAuthMeta?: boolean;\n}\n\nexport function buildAuthMethods(opts?: AuthMethodOptions): AuthMethod[] {\n\tconst supportsTerminalAuthMeta = opts?.supportsTerminalAuthMeta ?? true;\n\n\tconst method: AuthMethod = {\n\t\tid: AUTH_METHOD_ID,\n\t\tname: \"Launch pi in the terminal\",\n\t\tdescription: \"Start pi in an interactive terminal to configure API keys or login\",\n\t\ttype: \"terminal\",\n\t\targs: [\"--terminal-login\"],\n\t\tenv: {},\n\t};\n\n\tif (supportsTerminalAuthMeta) {\n\t\tconst launch = resolveTerminalLaunchCommand();\n\t\tmethod._meta = {\n\t\t\t\"terminal-auth\": {\n\t\t\t\t...launch,\n\t\t\t\tlabel: \"Launch pi\",\n\t\t\t},\n\t\t};\n\t}\n\n\treturn [method];\n}\n\nfunction resolveTerminalLaunchCommand(): { command: string; args: string[] } {\n\tconst argv0 = process.argv[0] ?? \"node\";\n\tconst argv1 = process.argv[1];\n\n\tif (argv1 !== undefined && argv0.includes(\"node\") && argv1.endsWith(\".js\")) {\n\t\treturn { command: argv0, args: [argv1, \"--terminal-login\"] };\n\t}\n\n\treturn { command: \"pi-acp\", args: [\"--terminal-login\"] };\n}\n","/**\n * Detect common auth/credential errors from pi and surface them as ACP AUTH_REQUIRED.\n */\n\nimport { RequestError } from \"@agentclientprotocol/sdk\";\nimport { buildAuthMethods } from \"@pi-acp/acp/auth\";\n\nconst AUTH_ERROR_PATTERNS = [\n\t\"api key\",\n\t\"apikey\",\n\t\"missing key\",\n\t\"no key\",\n\t\"not configured\",\n\t\"unauthorized\",\n\t\"authentication\",\n\t\"permission denied\",\n\t\"forbidden\",\n\t\"401\",\n\t\"403\",\n];\n\nexport function detectAuthError(err: unknown): RequestError | null {\n\tconst text = err instanceof Error ? err.message : String(err ?? \"\");\n\tconst lower = text.toLowerCase();\n\n\tconst isAuthRelated = AUTH_ERROR_PATTERNS.some((p) => lower.includes(p));\n\tif (!isAuthRelated) return null;\n\n\treturn RequestError.authRequired(\n\t\t{ authMethods: buildAuthMethods() },\n\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t);\n}\n","/**\n * Parse and represent client capabilities from the ACP initialize request.\n *\n * Both reference implementations (claude-agent-acp, codex-acp) store and\n * use `clientCapabilities` for feature detection and auth method selection.\n */\n\nimport type { ClientCapabilities } from \"@agentclientprotocol/sdk\";\n\nexport interface ClientCapabilityFlags {\n\t/** Client supports terminal output metadata (info/output/exit lifecycle). */\n\tterminalOutput: boolean;\n\t/** Client supports terminal-based authentication with command metadata. */\n\tterminalAuth: boolean;\n\t/** Client supports gateway-based authentication. */\n\tgatewayAuth: boolean;\n}\n\n/**\n * Extract well-known capability flags from ACP `ClientCapabilities`.\n *\n * Reads from:\n * - `_meta.terminal_output` (terminal output rendering)\n * - `_meta.terminal-auth` (terminal auth with command metadata)\n * - `auth._meta.gateway` (gateway auth, future use)\n */\nexport function parseClientCapabilities(\n\tcaps: ClientCapabilities | undefined | null,\n): ClientCapabilityFlags {\n\tif (caps === undefined || caps === null) {\n\t\treturn { terminalOutput: false, terminalAuth: false, gatewayAuth: false };\n\t}\n\n\t// _meta is an optional declared property, safe to access with dot\n\tconst meta = caps._meta;\n\tconst terminalOutput =\n\t\ttypeof meta === \"object\" && meta !== null && meta[\"terminal_output\"] === true;\n\tconst terminalAuth = typeof meta === \"object\" && meta !== null && meta[\"terminal-auth\"] === true;\n\n\t// gateway auth lives under auth._meta.gateway (non-standard extension)\n\tlet gatewayAuth = false;\n\tif (\"auth\" in caps) {\n\t\tconst auth = caps.auth;\n\t\tif (typeof auth === \"object\" && auth !== null && \"_meta\" in auth) {\n\t\t\tconst authMeta = auth._meta;\n\t\t\tif (typeof authMeta === \"object\" && authMeta !== null && \"gateway\" in authMeta) {\n\t\t\t\tgatewayAuth = authMeta[\"gateway\"] === true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { terminalOutput, terminalAuth, gatewayAuth };\n}\n","/**\n * Model alias resolution for user-friendly model names.\n *\n * Lets users type \"opus\", \"sonnet\", \"opus[1m]\" instead of exact\n * \"provider/modelId\" strings. Uses tokenized matching and scoring\n * following the claude-agent-acp pattern.\n */\n\ninterface ModelEntry {\n\tprovider: string;\n\tid: string;\n\tname?: string | undefined;\n}\n\ninterface ResolvedModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Tokenize a string: split on non-alphanumeric, lowercase, strip \"claude\".\n */\nfunction tokenize(input: string): string[] {\n\treturn input\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((t) => t !== \"\" && t !== \"claude\");\n}\n\n/**\n * Extract a context hint in square brackets, e.g. \"opus[1m]\" -> { base: \"opus\", hint: \"1m\" }.\n */\nfunction extractContextHint(input: string): { base: string; hint: string | null } {\n\tconst match = /^(.+?)\\[([^\\]]+)\\]$/.exec(input);\n\tif (match !== null && match[1] !== undefined && match[2] !== undefined) {\n\t\treturn { base: match[1], hint: match[2] };\n\t}\n\treturn { base: input, hint: null };\n}\n\n/** Check if a string is purely numeric. */\nfunction isNumeric(s: string): boolean {\n\treturn /^\\d+$/.test(s);\n}\n\n/**\n * Score how well a model matches the given preference tokens.\n *\n * Returns a score >= 0 (higher is better), or -1 for no match.\n * Requires at least one non-numeric token to match to avoid false positives\n * from bare version numbers (e.g. \"4\" matching model version suffixes).\n */\nfunction scoreModel(model: ModelEntry, prefTokens: string[], hint: string | null): number {\n\tconst modelStr = `${model.provider}/${model.id}/${model.name ?? \"\"}`.toLowerCase();\n\tconst modelTokens = tokenize(modelStr);\n\n\tlet matched = 0;\n\tlet hasNonNumericMatch = false;\n\tfor (const pt of prefTokens) {\n\t\tif (modelTokens.some((mt) => mt.includes(pt) || pt.includes(mt))) {\n\t\t\tmatched++;\n\t\t\tif (!isNumeric(pt)) hasNonNumericMatch = true;\n\t\t}\n\t}\n\n\tif (matched === 0) return -1;\n\n\t// Require at least one non-numeric token to match -- prevents \"gpt-4\"\n\t// matching on the bare \"4\" version component.\n\tif (!hasNonNumericMatch) return -1;\n\n\tlet score = matched / prefTokens.length;\n\n\t// Bonus for hint match (e.g. \"1m\" context window hint)\n\tif (hint !== null && modelStr.includes(hint.toLowerCase())) {\n\t\tscore += 0.5;\n\t}\n\n\t// Bonus for exact substring match on model id\n\tconst pref = prefTokens.join(\"\");\n\tif (model.id.toLowerCase().includes(pref)) {\n\t\tscore += 0.25;\n\t}\n\n\treturn score;\n}\n\n/**\n * Resolve a user-friendly model preference to a concrete model.\n *\n * Matching strategy (in order):\n * 1. Exact match on \"provider/id\"\n * 2. Exact match on \"id\" alone\n * 3. Tokenized scored match with optional context hint\n *\n * Returns null if no model matches.\n */\nexport function resolveModelPreference(\n\tmodels: readonly ModelEntry[],\n\tpreference: string,\n): ResolvedModel | null {\n\tconst trimmed = preference.trim();\n\tif (trimmed === \"\") return null;\n\n\t// 1. Exact match on \"provider/id\"\n\tif (trimmed.includes(\"/\")) {\n\t\tconst [p, ...rest] = trimmed.split(\"/\");\n\t\tconst provider = p ?? \"\";\n\t\tconst id = rest.join(\"/\");\n\t\tconst exact = models.find(\n\t\t\t(m) =>\n\t\t\t\tm.provider.toLowerCase() === provider.toLowerCase() &&\n\t\t\t\tm.id.toLowerCase() === id.toLowerCase(),\n\t\t);\n\t\tif (exact !== undefined) return { provider: exact.provider, id: exact.id };\n\t}\n\n\t// 2. Exact match on id alone\n\tconst byId = models.find((m) => m.id.toLowerCase() === trimmed.toLowerCase());\n\tif (byId !== undefined) return { provider: byId.provider, id: byId.id };\n\n\t// 3. Tokenized scored match\n\tconst { base, hint } = extractContextHint(trimmed);\n\tconst prefTokens = tokenize(base);\n\tif (prefTokens.length === 0) return null;\n\n\tlet bestModel: ModelEntry | null = null;\n\tlet bestScore = -1;\n\n\tfor (const model of models) {\n\t\tconst s = scoreModel(model, prefTokens, hint);\n\t\tif (s > bestScore) {\n\t\t\tbestScore = s;\n\t\t\tbestModel = model;\n\t\t}\n\t}\n\n\t// Require at least 50% of preference tokens to match to avoid spurious hits\n\t// (e.g. \"gpt-4\" matching on the \"4\" token alone)\n\tif (bestModel === null || bestScore < 0.5) return null;\n\treturn { provider: bestModel.provider, id: bestModel.id };\n}\n","/**\n * Read pi settings from global and project config files.\n *\n * Settings are merged: project overrides global.\n * Paths follow pi-mono conventions:\n * Global: ~/.pi/agent/settings.json\n * Project: <cwd>/.pi/settings.json\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport * as z from \"zod\";\n\nconst piSettingsSchema = z.object({\n\tenableSkillCommands: z.boolean().optional(),\n\tquietStartup: z.boolean().optional(),\n\tquietStart: z.boolean().optional(),\n\tskills: z\n\t\t.object({\n\t\t\tenableSkillCommands: z.boolean().optional(),\n\t\t})\n\t\t.optional(),\n});\n\ntype PiSettings = z.infer<typeof piSettingsSchema>;\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n\treturn typeof x === \"object\" && x !== null && !Array.isArray(x);\n}\n\nfunction merge(\n\tbase: Record<string, unknown>,\n\toverride: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = { ...base };\n\tfor (const [key, val] of Object.entries(override)) {\n\t\tconst existing = result[key];\n\t\tif (isRecord(existing) && isRecord(val)) {\n\t\t\tresult[key] = merge(existing, val);\n\t\t} else {\n\t\t\tresult[key] = val;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction readJson(path: string): Record<string, unknown> {\n\ttry {\n\t\tif (!existsSync(path)) return {};\n\t\tconst data: unknown = JSON.parse(readFileSync(path, \"utf-8\"));\n\t\treturn isRecord(data) ? data : {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nexport function piAgentDir(): string {\n\treturn process.env.PI_CODING_AGENT_DIR !== undefined\n\t\t? resolve(process.env.PI_CODING_AGENT_DIR)\n\t\t: join(homedir(), \".pi\", \"agent\");\n}\n\nfunction resolvedSettings(cwd: string): PiSettings {\n\tconst globalPath = join(piAgentDir(), \"settings.json\");\n\tconst projectPath = resolve(cwd, \".pi\", \"settings.json\");\n\tconst merged = merge(readJson(globalPath), readJson(projectPath));\n\tconst result = piSettingsSchema.safeParse(merged);\n\treturn result.success ? result.data : {};\n}\n\nexport function skillCommandsEnabled(cwd: string): boolean {\n\tconst settings = resolvedSettings(cwd);\n\n\tif (typeof settings.enableSkillCommands === \"boolean\") {\n\t\treturn settings.enableSkillCommands;\n\t}\n\n\tif (typeof settings.skills?.enableSkillCommands === \"boolean\") {\n\t\treturn settings.skills.enableSkillCommands;\n\t}\n\n\treturn true;\n}\n","/**\n * Per-tool content formatting for ACP tool results.\n *\n * Dispatches formatting by tool name following the reference implementation\n * pattern (claude-agent-acp / codex-acp). Each tool type produces\n * `ToolCallContent[]` appropriate for its output shape.\n */\n\nimport type { ToolCallContent } from \"@agentclientprotocol/sdk\";\nimport * as z from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Zod schemas for pi tool result shapes\n// ---------------------------------------------------------------------------\n\nconst textBlockSchema = z.object({\n\ttype: z.literal(\"text\"),\n\ttext: z.string(),\n});\n\nconst imageBlockSchema = z.object({\n\ttype: z.literal(\"image\"),\n});\n\nconst contentBlockSchema = z.union([textBlockSchema, imageBlockSchema]);\n\nconst bashDetailsSchema = z.object({\n\tstdout: z.string().optional(),\n\tstderr: z.string().optional(),\n\toutput: z.string().optional(),\n\texitCode: z.number().optional(),\n\tcode: z.number().optional(),\n});\n\nconst bashResultSchema = z.object({\n\tcontent: z.array(z.unknown()).optional(),\n\tdetails: bashDetailsSchema.optional(),\n\tstdout: z.string().optional(),\n\tstderr: z.string().optional(),\n\toutput: z.string().optional(),\n\texitCode: z.number().optional(),\n\tcode: z.number().optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Extraction helpers\n// ---------------------------------------------------------------------------\n\nexport interface BashOutput {\n\toutput: string;\n\texitCode: number | undefined;\n}\n\n/**\n * Extract stdout/stderr and exit code from a pi bash/tmux result.\n */\nexport function extractBashOutput(result: unknown): BashOutput {\n\tif (result === null || result === undefined || typeof result !== \"object\") {\n\t\treturn { output: \"\", exitCode: undefined };\n\t}\n\n\tconst parsed = bashResultSchema.safeParse(result);\n\tif (!parsed.success) {\n\t\treturn { output: \"\", exitCode: undefined };\n\t}\n\n\tconst r = parsed.data;\n\tconst d = r.details;\n\n\t// Try content blocks first\n\tif (r.content !== undefined) {\n\t\tconst texts = r.content\n\t\t\t.map((block) => textBlockSchema.safeParse(block))\n\t\t\t.filter((res) => res.success)\n\t\t\t.map((res) => res.data.text);\n\t\tif (texts.length > 0) {\n\t\t\tconst exitCode = d?.exitCode ?? r.exitCode ?? d?.code ?? r.code;\n\t\t\treturn { output: texts.join(\"\"), exitCode };\n\t\t}\n\t}\n\n\tconst stdout = d?.stdout ?? r.stdout ?? d?.output ?? r.output;\n\tconst stderr = d?.stderr ?? r.stderr;\n\tconst exitCode = d?.exitCode ?? r.exitCode ?? d?.code ?? r.code;\n\n\tconst parts: string[] = [];\n\tif (stdout !== undefined && stdout.trim() !== \"\") parts.push(stdout);\n\tif (stderr !== undefined && stderr.trim() !== \"\") parts.push(stderr);\n\n\treturn { output: parts.join(\"\\n\"), exitCode };\n}\n\n/**\n * Extract text content from a pi tool result (generic).\n */\nexport function extractTextContent(result: unknown): string {\n\tif (result === null || result === undefined || typeof result !== \"object\") return \"\";\n\n\tif (\"content\" in result && Array.isArray(result.content)) {\n\t\tconst texts: string[] = [];\n\t\tfor (const block of result.content) {\n\t\t\tconst parsed = textBlockSchema.safeParse(block);\n\t\t\tif (parsed.success) texts.push(parsed.data.text);\n\t\t}\n\t\tif (texts.length > 0) return texts.join(\"\");\n\t}\n\n\ttry {\n\t\treturn JSON.stringify(result, null, 2);\n\t} catch {\n\t\treturn String(result);\n\t}\n}\n\n/**\n * Extract content blocks from a pi result, preserving type information.\n * Used for read results where images need to be preserved.\n */\nexport function extractContentBlocks(\n\tresult: unknown,\n): Array<{ type: \"text\"; text: string } | { type: \"image\" }> {\n\tif (result === null || result === undefined || typeof result !== \"object\") return [];\n\tif (!(\"content\" in result) || !Array.isArray(result.content)) return [];\n\n\tconst blocks: Array<{ type: \"text\"; text: string } | { type: \"image\" }> = [];\n\tfor (const raw of result.content) {\n\t\tconst parsed = contentBlockSchema.safeParse(raw);\n\t\tif (parsed.success) {\n\t\t\tblocks.push(parsed.data);\n\t\t}\n\t}\n\treturn blocks;\n}\n\n// ---------------------------------------------------------------------------\n// Markdown escaping via dynamic backtick fence wrapping\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest consecutive backtick sequence in a string.\n */\nfunction longestBacktickRun(text: string): number {\n\tlet max = 0;\n\tlet current = 0;\n\tfor (const ch of text) {\n\t\tif (ch === \"`\") {\n\t\t\tcurrent++;\n\t\t\tif (current > max) max = current;\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn max;\n}\n\n/**\n * Wrap text in a dynamically-sized backtick fence to prevent markdown rendering.\n *\n * Instead of character-level escaping (which fails on files containing backtick\n * sequences, indented code blocks, blockquotes, and list markers), this wraps\n * the entire text in a backtick fence whose length exceeds any backtick sequence\n * in the content. This approach is simpler and strictly more correct (following\n * the claude-agent-acp pattern).\n */\nexport function markdownEscape(text: string): string {\n\tif (text === \"\") return \"\";\n\n\tconst fenceLen = Math.max(3, longestBacktickRun(text) + 1);\n\tconst fence = \"`\".repeat(fenceLen);\n\n\t// Avoid a trailing double newline before the closing fence\n\tconst body = text.endsWith(\"\\n\") ? text.slice(0, -1) : text;\n\treturn `${fence}\\n${body}\\n${fence}`;\n}\n\n// ---------------------------------------------------------------------------\n// Per-tool content formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Format tool output into `ToolCallContent[]` by tool name.\n *\n * Returns the appropriate content shape for each tool type:\n * - bash/tmux: console code fences\n * - read: markdown-escaped text (images preserved)\n * - edit/write: empty (diff handled separately)\n * - lsp: code fences\n * - errors: code fences with failed status\n * - everything else: plain text\n */\nexport function formatToolContent(\n\ttoolName: string,\n\tresult: unknown,\n\tisError: boolean,\n): ToolCallContent[] {\n\t// Error path: wrap any error text in a code fence\n\tif (isError) {\n\t\tconst text = extractTextContent(result);\n\t\tif (text === \"\") return [];\n\t\treturn [{ type: \"content\", content: { type: \"text\", text: `\\`\\`\\`\\n${text}\\n\\`\\`\\`` } }];\n\t}\n\n\tswitch (toolName) {\n\t\tcase \"bash\":\n\t\tcase \"tmux\":\n\t\t\treturn formatBashContent(result);\n\n\t\tcase \"read\":\n\t\t\treturn formatReadContent(result);\n\n\t\tcase \"edit\":\n\t\tcase \"write\":\n\t\t\t// Diff content is handled separately in handleToolEnd.\n\t\t\t// Return empty so the diff path takes precedence.\n\t\t\treturn [];\n\n\t\tcase \"lsp\":\n\t\t\treturn formatLspContent(result);\n\n\t\tdefault:\n\t\t\treturn formatFallbackContent(result);\n\t}\n}\n\nfunction formatBashContent(result: unknown): ToolCallContent[] {\n\tconst { output, exitCode } = extractBashOutput(result);\n\tif (output === \"\" && exitCode === undefined) return [];\n\n\tconst parts: string[] = [];\n\tif (output !== \"\") {\n\t\tparts.push(`\\`\\`\\`console\\n${output}\\n\\`\\`\\``);\n\t}\n\tif (exitCode !== undefined && exitCode !== 0) {\n\t\tparts.push(`exit code: ${exitCode}`);\n\t}\n\n\tconst text = parts.join(\"\\n\\n\");\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text } }];\n}\n\nfunction formatReadContent(result: unknown): ToolCallContent[] {\n\tconst blocks = extractContentBlocks(result);\n\tif (blocks.length === 0) {\n\t\t// Check if the result explicitly has an empty content array\n\t\tif (\n\t\t\ttypeof result === \"object\" &&\n\t\t\tresult !== null &&\n\t\t\t\"content\" in result &&\n\t\t\tArray.isArray(result.content) &&\n\t\t\tresult.content.length === 0\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\t// Fallback to text extraction for results without content blocks\n\t\tconst text = extractTextContent(result);\n\t\tif (text === \"\") return [];\n\t\treturn [{ type: \"content\", content: { type: \"text\", text: markdownEscape(text) } }];\n\t}\n\n\tconst content: ToolCallContent[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\") {\n\t\t\tcontent.push({\n\t\t\t\ttype: \"content\",\n\t\t\t\tcontent: { type: \"text\", text: markdownEscape(block.text) },\n\t\t\t});\n\t\t}\n\t\t// Image blocks are preserved as-is (the ACP client handles rendering)\n\t\t// We skip them here since they need their original structure from the result\n\t}\n\n\t// If we only had image blocks and no text, return empty\n\treturn content;\n}\n\nfunction formatLspContent(result: unknown): ToolCallContent[] {\n\tconst text = extractTextContent(result);\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text: `\\`\\`\\`\\n${text}\\n\\`\\`\\`` } }];\n}\n\nfunction formatFallbackContent(result: unknown): ToolCallContent[] {\n\tconst text = extractTextContent(result);\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text } }];\n}\n\n/**\n * Wrap streaming output text in a console code fence for bash/tmux.\n *\n * Each streaming update is self-contained (full accumulated buffer),\n * following the codex-acp pattern.\n */\nexport function wrapStreamingBashOutput(text: string): string {\n\tif (text === \"\") return \"\";\n\treturn `\\`\\`\\`console\\n${text}\\n\\`\\`\\``;\n}\n","/**\n * Exhaustive switch/case helper.\n *\n * Logs unknown values instead of silently ignoring them, aiding debugging\n * when the pi SDK adds new event types.\n */\nexport function unreachable(value: never, context?: string): void {\n\tconst label = context !== undefined ? `[${context}] ` : \"\";\n\tconsole.warn(`${label}Unhandled value: ${String(value)}`);\n}\n","import { readFileSync } from \"node:fs\";\nimport { isAbsolute, resolve as resolvePath } from \"node:path\";\nimport {\n\ttype AgentSideConnection,\n\ttype ContentBlock,\n\ttype McpServer,\n\tRequestError,\n\ttype SessionUpdate,\n\ttype ToolCallContent,\n\ttype ToolCallLocation,\n\ttype ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport type { AgentEvent, AgentMessage } from \"@mariozechner/pi-agent-core\";\nimport type { AssistantMessageEvent, ToolCall } from \"@mariozechner/pi-ai\";\nimport type { AgentSession, AgentSessionEvent } from \"@mariozechner/pi-coding-agent\";\nimport { formatToolContent, wrapStreamingBashOutput } from \"@pi-acp/acp/translate/tool-content\";\nimport { unreachable } from \"@pi-acp/acp/unreachable\";\nimport * as z from \"zod\";\n\nexport type StopReason = \"end_turn\" | \"cancelled\" | \"max_tokens\" | \"error\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction findUniqueLineNumber(text: string, needle: string): number | undefined {\n\tif (!needle) return undefined;\n\tconst first = text.indexOf(needle);\n\tif (first < 0) return undefined;\n\tif (text.indexOf(needle, first + needle.length) >= 0) return undefined;\n\n\tlet line = 1;\n\tfor (let i = 0; i < first; i++) {\n\t\tif (text.charCodeAt(i) === 10) line++;\n\t}\n\treturn line;\n}\n\nexport interface ToolArgs {\n\tpath?: string | undefined;\n\toldText?: string | undefined;\n\t[key: string]: unknown;\n}\n\nexport function resolveToolPath(\n\targs: ToolArgs,\n\tcwd: string,\n\tline?: number,\n): ToolCallLocation[] | undefined {\n\tconst p = args.path;\n\tif (p === undefined) return undefined;\n\n\tconst resolved = isAbsolute(p) ? p : resolvePath(cwd, p);\n\treturn [{ path: resolved, ...(typeof line === \"number\" ? { line } : {}) }];\n}\n\nexport function toToolKind(toolName: string): ToolKind {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn \"read\";\n\t\tcase \"write\":\n\t\tcase \"edit\":\n\t\t\treturn \"edit\";\n\t\tcase \"bash\":\n\t\tcase \"tmux\":\n\t\t\treturn \"execute\";\n\t\tcase \"lsp\":\n\t\t\treturn \"search\";\n\t\tdefault:\n\t\t\treturn \"other\";\n\t}\n}\n\nconst MAX_TITLE_LEN = 80;\n\nfunction truncateTitle(text: string): string {\n\tconst oneLine = text.replace(/\\n/g, \" \").trim();\n\tif (oneLine.length <= MAX_TITLE_LEN) return oneLine;\n\treturn `${oneLine.slice(0, MAX_TITLE_LEN - 1)}…`;\n}\n\nfunction capitalize(s: string): string {\n\tif (s.length === 0) return s;\n\treturn s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/**\n * Build a descriptive tool title from tool name and args.\n *\n * Returns a short human-readable label like \"Read src/index.ts\" or \"Run ls -la\".\n */\nexport function buildToolTitle(toolName: string, args: ToolArgs): string {\n\tconst p = args.path;\n\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn p !== undefined ? `Read ${p}` : \"Read\";\n\t\tcase \"write\":\n\t\t\treturn p !== undefined ? `Write ${p}` : \"Write\";\n\t\tcase \"edit\":\n\t\t\treturn p !== undefined ? `Edit ${p}` : \"Edit\";\n\t\tcase \"bash\": {\n\t\t\tconst command =\n\t\t\t\ttypeof args[\"command\"] === \"string\"\n\t\t\t\t\t? args[\"command\"]\n\t\t\t\t\t: typeof args[\"cmd\"] === \"string\"\n\t\t\t\t\t\t? args[\"cmd\"]\n\t\t\t\t\t\t: undefined;\n\t\t\treturn command !== undefined ? truncateTitle(`Run ${command}`) : \"bash\";\n\t\t}\n\t\tcase \"lsp\": {\n\t\t\tconst action = typeof args[\"action\"] === \"string\" ? args[\"action\"] : undefined;\n\t\t\tconst file = typeof args[\"file\"] === \"string\" ? args[\"file\"] : undefined;\n\t\t\tconst query = typeof args[\"query\"] === \"string\" ? args[\"query\"] : undefined;\n\t\t\tconst line = typeof args[\"line\"] === \"number\" ? args[\"line\"] : undefined;\n\t\t\tif (action !== undefined) {\n\t\t\t\tconst target = file !== undefined ? (line !== undefined ? `${file}:${line}` : file) : query;\n\t\t\t\treturn target !== undefined\n\t\t\t\t\t? truncateTitle(`${capitalize(action)} ${target}`)\n\t\t\t\t\t: capitalize(action);\n\t\t\t}\n\t\t\treturn \"LSP\";\n\t\t}\n\t\tcase \"tmux\": {\n\t\t\tconst action = typeof args[\"action\"] === \"string\" ? args[\"action\"] : undefined;\n\t\t\tconst command = typeof args[\"command\"] === \"string\" ? args[\"command\"] : undefined;\n\t\t\tconst name = typeof args[\"name\"] === \"string\" ? args[\"name\"] : undefined;\n\t\t\tif (action === \"run\" && command !== undefined) return truncateTitle(`Tmux: ${command}`);\n\t\t\tif (action !== undefined && name !== undefined)\n\t\t\t\treturn truncateTitle(`Tmux ${action} ${name}`);\n\t\t\tif (action !== undefined) return `Tmux ${action}`;\n\t\t\treturn \"Tmux\";\n\t\t}\n\t\tcase \"context_tag\": {\n\t\t\tconst name = typeof args[\"name\"] === \"string\" ? args[\"name\"] : undefined;\n\t\t\treturn name !== undefined ? `Tag ${name}` : \"Tag\";\n\t\t}\n\t\tcase \"context_log\":\n\t\t\treturn \"Context log\";\n\t\tcase \"context_checkout\": {\n\t\t\tconst target = typeof args[\"target\"] === \"string\" ? args[\"target\"] : undefined;\n\t\t\treturn target !== undefined ? truncateTitle(`Checkout ${target}`) : \"Checkout\";\n\t\t}\n\t\tcase \"claudemon\":\n\t\t\treturn \"Check quota\";\n\t\tdefault:\n\t\t\treturn toolName;\n\t}\n}\n\n/**\n * Map pi assistant stopReason to ACP StopReason.\n * pi: \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\"\n * ACP: \"end_turn\" | \"cancelled\" | \"max_tokens\" | \"error\"\n */\nfunction mapPiStopReason(piReason: string | null): StopReason {\n\tswitch (piReason) {\n\t\tcase \"stop\":\n\t\tcase \"toolUse\":\n\t\t\treturn \"end_turn\";\n\t\tcase \"length\":\n\t\t\treturn \"max_tokens\";\n\t\tcase \"aborted\":\n\t\t\treturn \"cancelled\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tdefault:\n\t\t\treturn \"end_turn\";\n\t}\n}\n\nfunction extractToolCallFromPartial(ame: AssistantMessageEvent): ToolCall | undefined {\n\tif (!(\"partial\" in ame)) return undefined;\n\tconst content = ame.partial.content;\n\tconst idx = \"contentIndex\" in ame ? ame.contentIndex : 0;\n\tconst block = content[idx];\n\tif (block && \"type\" in block && block.type === \"toolCall\") return block;\n\treturn undefined;\n}\n\nfunction parseToolInput(tc: ToolCall): ToolArgs {\n\treturn tc.arguments;\n}\n\nconst toolArgsSchema = z\n\t.object({\n\t\tpath: z.string().trim().optional(),\n\t\toldText: z.string().trim().optional(),\n\t})\n\t.loose();\n\nexport function toToolArgs(raw: unknown): ToolArgs {\n\tconst result = toolArgsSchema.safeParse(raw);\n\treturn result.success ? result.data : {};\n}\n\n// ---------------------------------------------------------------------------\n// _meta builder helpers\n// ---------------------------------------------------------------------------\n\ntype PiAcpMeta = Record<string, unknown>;\n\n/** Build the `_meta.piAcp` tool name metadata. */\nfunction buildToolMeta(toolName: string, extra?: PiAcpMeta): PiAcpMeta {\n\tconst base: PiAcpMeta = { piAcp: { toolName } };\n\tif (extra !== undefined) {\n\t\treturn { ...base, ...extra };\n\t}\n\treturn base;\n}\n\n// ---------------------------------------------------------------------------\n// Terminal tool classification\n// ---------------------------------------------------------------------------\n\n/** Tools that produce terminal-style output. */\nfunction isTerminalTool(toolName: string): boolean {\n\treturn toolName === \"bash\" || toolName === \"tmux\";\n}\n\n// ---------------------------------------------------------------------------\n// Session manager\n// ---------------------------------------------------------------------------\n\nexport class SessionManager {\n\tprivate sessions = new Map<string, PiAcpSession>();\n\n\tdisposeAll(): void {\n\t\tfor (const id of this.sessions.keys()) this.close(id);\n\t}\n\n\tmaybeGet(sessionId: string): PiAcpSession | undefined {\n\t\treturn this.sessions.get(sessionId);\n\t}\n\n\tclose(sessionId: string): void {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) return;\n\t\ttry {\n\t\t\ts.dispose();\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t\tthis.sessions.delete(sessionId);\n\t}\n\n\tcloseAllExcept(keepSessionId: string): void {\n\t\tfor (const id of this.sessions.keys()) {\n\t\t\tif (id !== keepSessionId) this.close(id);\n\t\t}\n\t}\n\n\tregister(session: PiAcpSession): void {\n\t\tthis.sessions.set(session.sessionId, session);\n\t}\n\n\tget(sessionId: string): PiAcpSession {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) throw RequestError.invalidParams(`Unknown sessionId: ${sessionId}`);\n\t\treturn s;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// ACP session wrapping a pi AgentSession\n// ---------------------------------------------------------------------------\n\nexport interface PiAcpSessionOpts {\n\tsessionId: string;\n\tcwd: string;\n\tmcpServers: McpServer[];\n\tpiSession: AgentSession;\n\tconn: AgentSideConnection;\n\t/** Whether the client supports terminal output metadata. */\n\tsupportsTerminalOutput?: boolean | undefined;\n}\n\nexport class PiAcpSession {\n\treadonly sessionId: string;\n\treadonly cwd: string;\n\treadonly mcpServers: McpServer[];\n\treadonly piSession: AgentSession;\n\treadonly supportsTerminalOutput: boolean;\n\n\tprivate readonly conn: AgentSideConnection;\n\n\tprivate cancelRequested = false;\n\tprivate promptRunning = false;\n\tprivate pendingTurn: { resolve: (r: StopReason) => void; reject: (e: unknown) => void } | null =\n\t\tnull;\n\t/** Queued prompts waiting for the active turn to complete. */\n\tprivate pendingMessages: Array<{\n\t\tmessage: string;\n\t\timages: unknown[];\n\t\tresolve: (r: StopReason) => void;\n\t\treject: (e: unknown) => void;\n\t}> = [];\n\n\tprivate currentToolCalls = new Map<string, \"pending\" | \"in_progress\">();\n\t/** Map of toolCallId -> toolName for streaming updates (Phase 5). */\n\tprivate toolCallNames = new Map<string, string>();\n\tprivate editSnapshots = new Map<string, { path: string; oldText: string }>();\n\tprivate lastAssistantStopReason: string | null = null;\n\tprivate lastEmit: Promise<void> = Promise.resolve();\n\tprivate unsubscribe: (() => void) | undefined;\n\n\tconstructor(opts: PiAcpSessionOpts) {\n\t\tthis.sessionId = opts.sessionId;\n\t\tthis.cwd = opts.cwd;\n\t\tthis.mcpServers = opts.mcpServers;\n\t\tthis.piSession = opts.piSession;\n\t\tthis.conn = opts.conn;\n\t\tthis.supportsTerminalOutput = opts.supportsTerminalOutput ?? false;\n\t\tthis.unsubscribe = this.piSession.subscribe((ev: AgentSessionEvent) => this.handlePiEvent(ev));\n\t}\n\n\tdispose(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.piSession.dispose();\n\t}\n\n\tasync prompt(message: string, images: unknown[] = []): Promise<StopReason> {\n\t\t// If a prompt is already running, queue this one and return a promise\n\t\t// that resolves when it eventually executes.\n\t\tif (this.promptRunning) {\n\t\t\treturn new Promise<StopReason>((resolve, reject) => {\n\t\t\t\tthis.pendingMessages.push({ message, images, resolve, reject });\n\t\t\t});\n\t\t}\n\n\t\treturn this.executePrompt(message, images);\n\t}\n\n\tasync cancel(): Promise<void> {\n\t\tthis.cancelRequested = true;\n\n\t\t// Resolve all queued prompts as cancelled\n\t\tfor (const pending of this.pendingMessages) {\n\t\t\tpending.resolve(\"cancelled\");\n\t\t}\n\t\tthis.pendingMessages = [];\n\n\t\tawait this.piSession.abort();\n\t}\n\n\tprivate executePrompt(message: string, images: unknown[]): Promise<StopReason> {\n\t\tthis.promptRunning = true;\n\n\t\tconst turnPromise = new Promise<StopReason>((resolve, reject) => {\n\t\t\tthis.cancelRequested = false;\n\t\t\tthis.pendingTurn = { resolve, reject };\n\t\t});\n\n\t\tconst imageContents = Array.isArray(images)\n\t\t\t? images.filter(\n\t\t\t\t\t(img): img is { type: \"image\"; data: string; mimeType: string } =>\n\t\t\t\t\t\ttypeof img === \"object\" && img !== null && \"type\" in img && img.type === \"image\",\n\t\t\t\t)\n\t\t\t: [];\n\n\t\tthis.piSession.prompt(message, { images: imageContents }).catch(() => {\n\t\t\tvoid this.flushEmits().finally(() => {\n\t\t\t\tconst reason: StopReason = this.cancelRequested ? \"cancelled\" : \"error\";\n\t\t\t\tthis.pendingTurn?.resolve(reason);\n\t\t\t\tthis.pendingTurn = null;\n\t\t\t});\n\t\t});\n\n\t\treturn turnPromise;\n\t}\n\n\t/**\n\t * Dequeue and execute the next pending prompt, if any.\n\t * Called after a turn completes.\n\t */\n\tprivate dequeueNextPrompt(): void {\n\t\tconst next = this.pendingMessages.shift();\n\t\tif (next === undefined) {\n\t\t\tthis.promptRunning = false;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.executePrompt(next.message, next.images).then(next.resolve, next.reject);\n\t}\n\n\twasCancelRequested(): boolean {\n\t\treturn this.cancelRequested;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Internal\n\t// -----------------------------------------------------------------------\n\n\tprivate emit(update: SessionUpdate): void {\n\t\tthis.lastEmit = this.lastEmit\n\t\t\t.then(() => this.conn.sessionUpdate({ sessionId: this.sessionId, update }))\n\t\t\t.catch(() => {});\n\t}\n\n\tprivate async flushEmits(): Promise<void> {\n\t\tawait this.lastEmit;\n\t}\n\n\tprivate handlePiEvent(ev: AgentSessionEvent): void {\n\t\tif (!isAgentEvent(ev)) return;\n\n\t\tswitch (ev.type) {\n\t\t\tcase \"message_update\":\n\t\t\t\tthis.handleMessageUpdate(ev.assistantMessageEvent);\n\t\t\t\tbreak;\n\t\t\tcase \"message_end\":\n\t\t\t\tthis.handleMessageEnd(ev.message);\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_start\":\n\t\t\t\tthis.handleToolStart(ev.toolCallId, ev.toolName, toToolArgs(ev.args));\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_update\":\n\t\t\t\tthis.handleToolUpdate(ev.toolCallId, ev.toolName, ev.partialResult);\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_end\":\n\t\t\t\tthis.handleToolEnd(ev.toolCallId, ev.toolName, ev.result, ev.isError);\n\t\t\t\tbreak;\n\t\t\tcase \"agent_end\":\n\t\t\t\tthis.handleAgentEnd();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachable(ev, \"handlePiEvent\");\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate handleMessageUpdate(ame: AssistantMessageEvent): void {\n\t\tif (ame.type === \"text_delta\") {\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\tcontent: { type: \"text\", text: ame.delta } satisfies ContentBlock,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (ame.type === \"thinking_delta\") {\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"agent_thought_chunk\",\n\t\t\t\tcontent: { type: \"text\", text: ame.delta } satisfies ContentBlock,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tame.type === \"toolcall_start\" ||\n\t\t\tame.type === \"toolcall_delta\" ||\n\t\t\tame.type === \"toolcall_end\"\n\t\t) {\n\t\t\tconst toolCall = ame.type === \"toolcall_end\" ? ame.toolCall : extractToolCallFromPartial(ame);\n\t\t\tif (!toolCall) return;\n\n\t\t\tconst rawInput = parseToolInput(toolCall);\n\t\t\tconst locations = resolveToolPath(rawInput, this.cwd);\n\t\t\tconst existingStatus = this.currentToolCalls.get(toolCall.id);\n\t\t\tconst status = existingStatus ?? \"pending\";\n\n\t\t\tif (!existingStatus) {\n\t\t\t\tthis.currentToolCalls.set(toolCall.id, \"pending\");\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\ttitle: buildToolTitle(toolCall.name, rawInput),\n\t\t\t\t\tkind: toToolKind(toolCall.name),\n\t\t\t\t\tstatus,\n\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\trawInput,\n\t\t\t\t\t_meta: buildToolMeta(toolCall.name),\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\tstatus,\n\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\trawInput,\n\t\t\t\t\t_meta: buildToolMeta(toolCall.name),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleMessageEnd(msg: AgentMessage): void {\n\t\tif (\"role\" in msg && msg.role === \"assistant\") {\n\t\t\tthis.lastAssistantStopReason = msg.stopReason;\n\t\t}\n\t}\n\n\tprivate handleToolStart(toolCallId: string, toolName: string, args: ToolArgs): void {\n\t\t// Track toolName for streaming updates (Phase 5)\n\t\tthis.toolCallNames.set(toolCallId, toolName);\n\n\t\tlet line: number | undefined;\n\n\t\tif ((toolName === \"edit\" || toolName === \"write\") && args.path !== undefined) {\n\t\t\ttry {\n\t\t\t\tconst abs = isAbsolute(args.path) ? args.path : resolvePath(this.cwd, args.path);\n\t\t\t\tlet oldText = \"\";\n\t\t\t\ttry {\n\t\t\t\t\toldText = readFileSync(abs, \"utf8\");\n\t\t\t\t} catch {\n\t\t\t\t\t// File may not exist yet for write -- treat as empty.\n\t\t\t\t}\n\t\t\t\tthis.editSnapshots.set(toolCallId, { path: abs, oldText });\n\t\t\t\tif (toolName === \"edit\") {\n\t\t\t\t\tline = findUniqueLineNumber(oldText, args.oldText ?? \"\");\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// snapshot failure is non-fatal\n\t\t\t}\n\t\t}\n\n\t\tconst locations = resolveToolPath(args, this.cwd, line);\n\n\t\t// Build terminal metadata for bash/tmux when client supports it\n\t\tconst terminalMeta =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? { terminal_info: { terminal_id: toolCallId, cwd: this.cwd } }\n\t\t\t\t: undefined;\n\t\tconst meta = buildToolMeta(toolName, terminalMeta);\n\n\t\t// Build content for terminal-aware clients\n\t\tconst terminalContent: ToolCallContent[] | undefined =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? [{ type: \"terminal\" as const, terminalId: toolCallId }]\n\t\t\t\t: undefined;\n\n\t\tif (!this.currentToolCalls.has(toolCallId)) {\n\t\t\tthis.currentToolCalls.set(toolCallId, \"in_progress\");\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\ttoolCallId,\n\t\t\t\ttitle: buildToolTitle(toolName, args),\n\t\t\t\tkind: toToolKind(toolName),\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t...(terminalContent !== undefined ? { content: terminalContent } : {}),\n\t\t\t\trawInput: args,\n\t\t\t\t_meta: meta,\n\t\t\t});\n\t\t} else {\n\t\t\tthis.currentToolCalls.set(toolCallId, \"in_progress\");\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\ttitle: buildToolTitle(toolName, args),\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t...(terminalContent !== undefined ? { content: terminalContent } : {}),\n\t\t\t\trawInput: args,\n\t\t\t\t_meta: meta,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleToolUpdate(toolCallId: string, toolName: string, partialResult: unknown): void {\n\t\t// Look up tool name from our map (Phase 5), fall back to event's toolName\n\t\tconst name = this.toolCallNames.get(toolCallId) ?? toolName;\n\n\t\tif (this.supportsTerminalOutput && isTerminalTool(name)) {\n\t\t\t// Terminal-aware path: emit only _meta.terminal_output, no content\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t_meta: buildToolMeta(name, {\n\t\t\t\t\tterminal_output: { terminal_id: toolCallId, data: text },\n\t\t\t\t}),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t} else if (isTerminalTool(name)) {\n\t\t\t// Non-terminal fallback: wrap in console code fence\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tconst wrapped = wrapStreamingBashOutput(text);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\tcontent: wrapped\n\t\t\t\t\t? ([\n\t\t\t\t\t\t\t{ type: \"content\", content: { type: \"text\", text: wrapped } },\n\t\t\t\t\t\t] satisfies ToolCallContent[])\n\t\t\t\t\t: null,\n\t\t\t\t_meta: buildToolMeta(name),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t} else {\n\t\t\t// Other tools: plain text content\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\tcontent: text\n\t\t\t\t\t? ([{ type: \"content\", content: { type: \"text\", text } }] satisfies ToolCallContent[])\n\t\t\t\t\t: null,\n\t\t\t\t_meta: buildToolMeta(name),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleToolEnd(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: unknown,\n\t\tisError: boolean,\n\t): void {\n\t\tconst snapshot = this.editSnapshots.get(toolCallId);\n\t\tlet content: ToolCallContent[] | null = null;\n\n\t\t// Diff path for edit/write\n\t\tif (!isError && snapshot) {\n\t\t\ttry {\n\t\t\t\tconst newText = readFileSync(snapshot.path, \"utf8\");\n\t\t\t\tif (newText !== snapshot.oldText) {\n\t\t\t\t\tconst formatted = formatToolContent(toolName, result, isError);\n\t\t\t\t\tcontent = [\n\t\t\t\t\t\t{ type: \"diff\", path: snapshot.path, oldText: snapshot.oldText, newText },\n\t\t\t\t\t\t...formatted,\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// fall back to formatted content\n\t\t\t}\n\t\t}\n\n\t\t// If no diff content, use formatted tool content\n\t\tif (content === null) {\n\t\t\tconst formatted = formatToolContent(toolName, result, isError);\n\t\t\tcontent = formatted.length > 0 ? formatted : null;\n\t\t}\n\n\t\t// Last resort: if formatToolContent returns empty and no diff, generate plain text\n\t\tif (content === null && !isError && toolName !== \"edit\" && toolName !== \"write\") {\n\t\t\tconst text = extractStreamingText(result);\n\t\t\tif (text) {\n\t\t\t\tcontent = [{ type: \"content\", content: { type: \"text\", text } }];\n\t\t\t}\n\t\t}\n\n\t\t// For terminal tools: emit a separate terminal_output update before terminal_exit.\n\t\t// This ensures Zed renders output before the exit status (following claude-agent-acp).\n\t\tif (this.supportsTerminalOutput && isTerminalTool(toolName)) {\n\t\t\tconst outputText = extractStreamingText(result);\n\t\t\tif (outputText !== \"\") {\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t\t_meta: buildToolMeta(toolName, {\n\t\t\t\t\t\tterminal_output: { terminal_id: toolCallId, data: outputText },\n\t\t\t\t\t}),\n\t\t\t\t\trawOutput: result,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Build terminal exit metadata for bash/tmux\n\t\tconst terminalExitMeta =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? {\n\t\t\t\t\t\tterminal_exit: {\n\t\t\t\t\t\t\tterminal_id: toolCallId,\n\t\t\t\t\t\t\texit_code: extractExitCode(result),\n\t\t\t\t\t\t\tsignal: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\tconst meta = buildToolMeta(toolName, terminalExitMeta);\n\n\t\tthis.emit({\n\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\ttoolCallId,\n\t\t\tstatus: isError ? \"failed\" : \"completed\",\n\t\t\tcontent,\n\t\t\t_meta: meta,\n\t\t\trawOutput: result,\n\t\t});\n\n\t\tthis.currentToolCalls.delete(toolCallId);\n\t\tthis.editSnapshots.delete(toolCallId);\n\t\tthis.toolCallNames.delete(toolCallId);\n\t}\n\n\tprivate handleAgentEnd(): void {\n\t\tthis.emitUsageUpdate();\n\t\tvoid this.flushEmits().finally(() => {\n\t\t\tconst reason: StopReason = this.cancelRequested\n\t\t\t\t? \"cancelled\"\n\t\t\t\t: mapPiStopReason(this.lastAssistantStopReason);\n\t\t\tthis.lastAssistantStopReason = null;\n\t\t\tthis.pendingTurn?.resolve(reason);\n\t\t\tthis.pendingTurn = null;\n\t\t\tthis.dequeueNextPrompt();\n\t\t});\n\t}\n\n\t/**\n\t * Emit a usage_update notification with current context and cost data.\n\t */\n\tprivate emitUsageUpdate(): void {\n\t\tconst contextUsage = this.piSession.getContextUsage?.();\n\t\tconst stats = this.piSession.getSessionStats();\n\n\t\tconst used = contextUsage?.tokens ?? 0;\n\t\tconst size = contextUsage?.contextWindow ?? 0;\n\n\t\tthis.emit({\n\t\t\tsessionUpdate: \"usage_update\",\n\t\t\tused,\n\t\t\tsize,\n\t\t\tcost: stats.cost > 0 ? { amount: stats.cost, currency: \"USD\" } : null,\n\t\t});\n\t}\n\n\t/**\n\t * Build ACP Usage data from pi session stats for prompt response.\n\t */\n\tgetUsage(): {\n\t\tinputTokens: number;\n\t\toutputTokens: number;\n\t\tcachedReadTokens: number;\n\t\tcachedWriteTokens: number;\n\t} {\n\t\tconst stats = this.piSession.getSessionStats();\n\t\treturn {\n\t\t\tinputTokens: stats.tokens.input,\n\t\t\toutputTokens: stats.tokens.output,\n\t\t\tcachedReadTokens: stats.tokens.cacheRead,\n\t\t\tcachedWriteTokens: stats.tokens.cacheWrite,\n\t\t};\n\t}\n\n\t/**\n\t * Get cumulative session cost.\n\t */\n\tgetCost(): number {\n\t\treturn this.piSession.getSessionStats().cost;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Streaming text extraction (lightweight, no formatting)\n// ---------------------------------------------------------------------------\n\nfunction isTextBlock(v: unknown): v is { type: \"text\"; text: string } {\n\treturn (\n\t\ttypeof v === \"object\" &&\n\t\tv !== null &&\n\t\t\"type\" in v &&\n\t\tv.type === \"text\" &&\n\t\t\"text\" in v &&\n\t\ttypeof v.text === \"string\"\n\t);\n}\n\nfunction extractStreamingText(result: unknown): string {\n\tif (result === null || result === undefined) return \"\";\n\tif (typeof result === \"string\") return result;\n\tif (typeof result !== \"object\") return String(result);\n\n\t// Content blocks\n\tif (\"content\" in result && Array.isArray(result.content)) {\n\t\tconst texts: string[] = [];\n\t\tfor (const raw of result.content) {\n\t\t\tif (isTextBlock(raw)) {\n\t\t\t\ttexts.push(raw.text);\n\t\t\t}\n\t\t}\n\t\tif (texts.length > 0) return texts.join(\"\");\n\t}\n\n\t// Details fields\n\tif (\"details\" in result) {\n\t\tconst details = result.details;\n\t\tif (typeof details === \"object\" && details !== null) {\n\t\t\tif (\"stdout\" in details && typeof details.stdout === \"string\" && details.stdout.trim() !== \"\")\n\t\t\t\treturn details.stdout;\n\t\t\tif (\"output\" in details && typeof details.output === \"string\" && details.output.trim() !== \"\")\n\t\t\t\treturn details.output;\n\t\t}\n\t}\n\n\t// Top-level output/stdout\n\tif (\"output\" in result && typeof result.output === \"string\" && result.output.trim() !== \"\")\n\t\treturn result.output;\n\tif (\"stdout\" in result && typeof result.stdout === \"string\" && result.stdout.trim() !== \"\")\n\t\treturn result.stdout;\n\n\treturn \"\";\n}\n\nfunction extractExitCode(result: unknown): number | null {\n\tif (result === null || result === undefined || typeof result !== \"object\") return null;\n\n\tif (\"details\" in result) {\n\t\tconst details = result.details;\n\t\tif (typeof details === \"object\" && details !== null) {\n\t\t\tif (\"exitCode\" in details && typeof details.exitCode === \"number\") return details.exitCode;\n\t\t\tif (\"code\" in details && typeof details.code === \"number\") return details.code;\n\t\t}\n\t}\n\n\tif (\"exitCode\" in result && typeof result.exitCode === \"number\") return result.exitCode;\n\tif (\"code\" in result && typeof result.code === \"number\") return result.code;\n\n\treturn null;\n}\n\n/**\n * Type guard to narrow AgentSessionEvent to the AgentEvent subset\n * (the variants we handle). Session-specific events like auto_compaction\n * are ignored.\n */\nfunction isAgentEvent(\n\tev: AgentSessionEvent,\n): ev is Extract<\n\tAgentEvent,\n\t| { type: \"message_update\" }\n\t| { type: \"message_end\" }\n\t| { type: \"tool_execution_start\" }\n\t| { type: \"tool_execution_update\" }\n\t| { type: \"tool_execution_end\" }\n\t| { type: \"agent_end\" }\n> {\n\treturn (\n\t\tev.type === \"message_update\" ||\n\t\tev.type === \"message_end\" ||\n\t\tev.type === \"tool_execution_start\" ||\n\t\tev.type === \"tool_execution_update\" ||\n\t\tev.type === \"tool_execution_end\" ||\n\t\tev.type === \"agent_end\"\n\t);\n}\n","/**\n * Extract plain text from pi message content.\n *\n * Pi messages store content as either a string or an array of typed blocks.\n * These helpers extract the text portions for ACP session replay.\n */\n\ninterface TextBlock {\n\ttype: \"text\";\n\ttext: string;\n}\n\nfunction isTextBlock(block: unknown): block is TextBlock {\n\tif (typeof block !== \"object\" || block === null) return false;\n\treturn (\n\t\t\"type\" in block && block.type === \"text\" && \"text\" in block && typeof block.text === \"string\"\n\t);\n}\n\nexport function extractUserMessageText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter(isTextBlock)\n\t\t.map((b) => b.text)\n\t\t.join(\"\");\n}\n\nexport function extractAssistantText(content: unknown): string {\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter(isTextBlock)\n\t\t.map((b) => b.text)\n\t\t.join(\"\");\n}\n","/**\n * Convert ACP prompt ContentBlocks to a pi-compatible message string and image array.\n */\n\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\n\nexport interface PiImage {\n\ttype: \"image\";\n\tmimeType: string;\n\tdata: string;\n}\n\nexport function acpPromptToPiMessage(blocks: ContentBlock[]): {\n\tmessage: string;\n\timages: PiImage[];\n} {\n\tlet message = \"\";\n\tconst images: PiImage[] = [];\n\n\tfor (const block of blocks) {\n\t\tswitch (block.type) {\n\t\t\tcase \"text\":\n\t\t\t\tmessage += block.text;\n\t\t\t\tbreak;\n\n\t\t\tcase \"resource_link\":\n\t\t\t\tmessage += `\\n[Context] ${block.uri}`;\n\t\t\t\tbreak;\n\n\t\t\tcase \"image\":\n\t\t\t\timages.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: block.mimeType,\n\t\t\t\t\tdata: block.data,\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"resource\": {\n\t\t\t\tconst resource = block.resource;\n\t\t\t\tconst uri = resource.uri;\n\t\t\t\tconst mime = resource.mimeType ?? null;\n\n\t\t\t\tif (\"text\" in resource) {\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri} (${mime ?? \"text/plain\"})\\n${resource.text}`;\n\t\t\t\t} else if (\"blob\" in resource) {\n\t\t\t\t\tconst bytes = Buffer.byteLength(resource.blob, \"base64\");\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri} (${mime ?? \"application/octet-stream\"}, ${bytes} bytes)`;\n\t\t\t\t} else {\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri}`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"audio\": {\n\t\t\t\tconst bytes = Buffer.byteLength(block.data, \"base64\");\n\t\t\t\tmessage += `\\n[Audio] (${block.mimeType}, ${bytes} bytes) not supported`;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { message, images };\n}\n","/**\n * Detect whether the user has any pi authentication configured.\n *\n * Checks three sources:\n * 1. auth.json (API keys, OAuth credentials)\n * 2. models.json custom provider apiKey entries\n * 3. Known provider environment variables\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport * as z from \"zod\";\n\nconst modelsConfigSchema = z.object({\n\tproviders: z\n\t\t.record(\n\t\t\tz.string().trim(),\n\t\t\tz.object({\n\t\t\t\tapiKey: z.string().trim().optional(),\n\t\t\t}),\n\t\t)\n\t\t.optional(),\n});\n\nfunction agentDir(): string {\n\tconst env = process.env.PI_CODING_AGENT_DIR;\n\tif (env === undefined) return join(homedir(), \".pi\", \"agent\");\n\tif (env === \"~\") return homedir();\n\tif (env.startsWith(\"~/\")) return homedir() + env.slice(1);\n\treturn env;\n}\n\nfunction readJsonFile(path: string): unknown {\n\ttry {\n\t\tif (!existsSync(path)) return null;\n\t\tconst raw = readFileSync(path, \"utf-8\").trim();\n\t\tif (!raw) return null;\n\t\treturn JSON.parse(raw);\n\t} catch {\n\t\treturn null;\n\t}\n}\n\nfunction hasAuthJson(): boolean {\n\tconst data = readJsonFile(join(agentDir(), \"auth.json\"));\n\treturn typeof data === \"object\" && data !== null && Object.keys(data).length > 0;\n}\n\nfunction hasCustomProviderKey(): boolean {\n\tconst raw = readJsonFile(join(agentDir(), \"models.json\"));\n\tconst result = modelsConfigSchema.safeParse(raw);\n\tif (!result.success || !result.data.providers) return false;\n\n\treturn Object.values(result.data.providers).some(\n\t\t(provider) => typeof provider.apiKey === \"string\" && provider.apiKey.trim().length > 0,\n\t);\n}\n\n/** Environment variables that indicate a configured provider API key. */\nconst PROVIDER_ENV_VARS = [\n\t\"ANTHROPIC_API_KEY\",\n\t\"ANTHROPIC_OAUTH_TOKEN\",\n\t\"OPENAI_API_KEY\",\n\t\"AZURE_OPENAI_API_KEY\",\n\t\"GEMINI_API_KEY\",\n\t\"GROQ_API_KEY\",\n\t\"CEREBRAS_API_KEY\",\n\t\"XAI_API_KEY\",\n\t\"OPENROUTER_API_KEY\",\n\t\"AI_GATEWAY_API_KEY\",\n\t\"ZAI_API_KEY\",\n\t\"MISTRAL_API_KEY\",\n\t\"MINIMAX_API_KEY\",\n\t\"MINIMAX_CN_API_KEY\",\n\t\"HF_TOKEN\",\n\t\"OPENCODE_API_KEY\",\n\t\"KIMI_API_KEY\",\n\t\"COPILOT_GITHUB_TOKEN\",\n\t\"GH_TOKEN\",\n\t\"GITHUB_TOKEN\",\n];\n\nfunction hasProviderEnvVar(): boolean {\n\treturn PROVIDER_ENV_VARS.some((key) => {\n\t\tconst val = process.env[key];\n\t\treturn typeof val === \"string\" && val.trim().length > 0;\n\t});\n}\n\nexport function hasPiAuthConfigured(): boolean {\n\treturn hasAuthJson() || hasCustomProviderKey() || hasProviderEnvVar();\n}\n","","import { spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, join } from \"node:path\";\nimport {\n\ttype Agent as ACPAgent,\n\ttype AgentSideConnection,\n\ttype AuthenticateRequest,\n\ttype AvailableCommand,\n\ttype CancelNotification,\n\ttype CloseSessionRequest,\n\ttype CloseSessionResponse,\n\ttype ForkSessionRequest,\n\ttype ForkSessionResponse,\n\ttype InitializeRequest,\n\ttype InitializeResponse,\n\ttype ListSessionsRequest,\n\ttype ListSessionsResponse,\n\ttype LoadSessionRequest,\n\ttype LoadSessionResponse,\n\ttype ModelInfo,\n\ttype NewSessionRequest,\n\ttype PromptRequest,\n\ttype PromptResponse,\n\tRequestError,\n\ttype ResumeSessionRequest,\n\ttype ResumeSessionResponse,\n\ttype SessionConfigOption,\n\ttype SessionInfo,\n\ttype SessionModelState,\n\ttype SessionModeState,\n\ttype SetSessionConfigOptionRequest,\n\ttype SetSessionConfigOptionResponse,\n\ttype SetSessionModelRequest,\n\ttype SetSessionModelResponse,\n\ttype SetSessionModeRequest,\n\ttype SetSessionModeResponse,\n\ttype StopReason,\n} from \"@agentclientprotocol/sdk\";\nimport type { AgentMessage } from \"@mariozechner/pi-agent-core\";\nimport type { AssistantMessage, ToolResultMessage, UserMessage } from \"@mariozechner/pi-ai\";\nimport {\n\ttype AgentSession,\n\ttype CreateAgentSessionResult,\n\tcreateAgentSession,\n\tSessionManager as PiSessionManager,\n} from \"@mariozechner/pi-coding-agent\";\nimport { buildAuthMethods } from \"@pi-acp/acp/auth\";\nimport { detectAuthError } from \"@pi-acp/acp/auth-required\";\nimport {\n\ttype ClientCapabilityFlags,\n\tparseClientCapabilities,\n} from \"@pi-acp/acp/client-capabilities\";\nimport { resolveModelPreference } from \"@pi-acp/acp/model-alias\";\nimport { skillCommandsEnabled } from \"@pi-acp/acp/pi-settings\";\nimport {\n\tbuildToolTitle,\n\tPiAcpSession,\n\tresolveToolPath,\n\tSessionManager,\n\ttype ToolArgs,\n\ttoToolArgs,\n\ttoToolKind,\n} from \"@pi-acp/acp/session\";\nimport { extractUserMessageText } from \"@pi-acp/acp/translate/pi-messages\";\nimport { acpPromptToPiMessage } from \"@pi-acp/acp/translate/prompt\";\nimport { formatToolContent } from \"@pi-acp/acp/translate/tool-content\";\nimport { hasPiAuthConfigured } from \"@pi-acp/pi-auth/status\";\n\nimport pkgJson from \"../../package.json\" with { type: \"json\" };\n\ntype ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\n/** Builtin ACP slash commands handled directly by the adapter. */\nconst BUILTIN_COMMANDS: readonly AvailableCommand[] = [\n\t{\n\t\tname: \"compact\",\n\t\tdescription: \"Manually compact the session context\",\n\t\tinput: { hint: \"optional custom instructions\" },\n\t},\n\t{\n\t\tname: \"autocompact\",\n\t\tdescription: \"Toggle automatic context compaction\",\n\t\tinput: { hint: \"on|off|toggle\" },\n\t},\n\t{ name: \"export\", description: \"Export session to an HTML file in the session cwd\" },\n\t{ name: \"session\", description: \"Show session stats (messages, tokens, cost, session file)\" },\n\t{ name: \"name\", description: \"Set session display name\", input: { hint: \"<name>\" } },\n\t{\n\t\tname: \"steering\",\n\t\tdescription: \"Get/set pi steering message delivery mode\",\n\t\tinput: { hint: \"(no args to show) all | one-at-a-time\" },\n\t},\n\t{\n\t\tname: \"follow-up\",\n\t\tdescription: \"Get/set pi follow-up message delivery mode\",\n\t\tinput: { hint: \"(no args to show) all | one-at-a-time\" },\n\t},\n\t{ name: \"changelog\", description: \"Show pi changelog\" },\n] as const;\n\n/**\n * Deduplicate commands by name. First occurrence wins.\n */\nfunction deduplicateCommands(commands: AvailableCommand[]): AvailableCommand[] {\n\tconst seen = new Set<string>();\n\tconst out: AvailableCommand[] = [];\n\tfor (const c of commands) {\n\t\tif (seen.has(c.name)) continue;\n\t\tseen.add(c.name);\n\t\tout.push(c);\n\t}\n\treturn out;\n}\n\nfunction parseArgs(input: string): string[] {\n\tconst args: string[] = [];\n\tlet current = \"\";\n\tlet quote: string | null = null;\n\n\tfor (const ch of input) {\n\t\tif (quote !== null) {\n\t\t\tif (ch === quote) quote = null;\n\t\t\telse current += ch;\n\t\t} else if (ch === '\"' || ch === \"'\") {\n\t\t\tquote = ch;\n\t\t} else if (ch === \" \" || ch === \"\\t\") {\n\t\t\tif (current !== \"\") {\n\t\t\t\targs.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\n\tif (current !== \"\") args.push(current);\n\treturn args;\n}\n\nconst SESSION_TITLE_MAX = 100;\n\nfunction truncateSessionTitle(text: string): string | null {\n\tconst trimmed = text.trim();\n\tif (trimmed === \"\") return null;\n\tconst oneLine = trimmed.replace(/\\n/g, \" \");\n\tif (oneLine.length <= SESSION_TITLE_MAX) return oneLine;\n\treturn `${oneLine.slice(0, SESSION_TITLE_MAX - 1)}…`;\n}\n\nexport class PiAcpAgent implements ACPAgent {\n\tprivate readonly conn: AgentSideConnection;\n\tprivate readonly sessions = new SessionManager();\n\t/** Cache of sessionId → file path, populated by listSessions and newSession. */\n\tprivate readonly sessionPaths = new Map<string, string>();\n\t/** Parsed client capability flags from initialize(). */\n\tprivate clientCapabilities: ClientCapabilityFlags = {\n\t\tterminalOutput: false,\n\t\tterminalAuth: false,\n\t\tgatewayAuth: false,\n\t};\n\n\tdispose(): void {\n\t\tthis.sessions.disposeAll();\n\t}\n\n\tconstructor(conn: AgentSideConnection, _config?: unknown) {\n\t\tthis.conn = conn;\n\t\tvoid _config;\n\t}\n\n\tasync initialize(params: InitializeRequest): Promise<InitializeResponse> {\n\t\tconst supportedVersion = 1;\n\t\tconst requested = params.protocolVersion;\n\n\t\tthis.clientCapabilities = parseClientCapabilities(params.clientCapabilities);\n\n\t\treturn {\n\t\t\tprotocolVersion: requested === supportedVersion ? requested : supportedVersion,\n\t\t\tagentInfo: {\n\t\t\t\tname: pkgJson.name,\n\t\t\t\ttitle: \"pi ACP adapter\",\n\t\t\t\tversion: pkgJson.version,\n\t\t\t},\n\t\t\tauthMethods: buildAuthMethods({\n\t\t\t\tsupportsTerminalAuthMeta: this.clientCapabilities.terminalAuth,\n\t\t\t}),\n\t\t\tagentCapabilities: {\n\t\t\t\tloadSession: true,\n\t\t\t\tmcpCapabilities: { http: false, sse: false },\n\t\t\t\tpromptCapabilities: {\n\t\t\t\t\timage: true,\n\t\t\t\t\taudio: false,\n\t\t\t\t\tembeddedContext: true,\n\t\t\t\t},\n\t\t\t\tsessionCapabilities: {\n\t\t\t\t\tlist: {},\n\t\t\t\t\tclose: {},\n\t\t\t\t\tresume: {},\n\t\t\t\t\tfork: {},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync newSession(params: NewSessionRequest) {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tif (!hasPiAuthConfigured()) {\n\t\t\tthrow RequestError.authRequired(\n\t\t\t\t{ authMethods: buildAuthMethods() },\n\t\t\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t\t\t);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tresult = await createAgentSession({ cwd: params.cwd });\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to create pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst availableModels = piSession.modelRegistry.getAvailable();\n\t\tif (availableModels.length === 0) {\n\t\t\tpiSession.dispose();\n\t\t\tthrow RequestError.authRequired(\n\t\t\t\t{ authMethods: buildAuthMethods() },\n\t\t\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t\t\t);\n\t\t}\n\n\t\tconst sessionId = piSession.sessionManager.getSessionId();\n\t\tconst sessionFile = piSession.sessionManager.getSessionFile();\n\t\tif (sessionFile !== undefined) {\n\t\t\tthis.sessionPaths.set(sessionId, sessionFile);\n\t\t}\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers,\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\treturn {\n\t\t\tsessionId: session.sessionId,\n\t\t\tconfigOptions,\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync authenticate(_params: AuthenticateRequest) {\n\t\treturn {};\n\t}\n\n\tasync prompt(params: PromptRequest): Promise<PromptResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst { message, images } = acpPromptToPiMessage(params.prompt);\n\n\t\tif (images.length === 0 && message.trimStart().startsWith(\"/\")) {\n\t\t\tconst trimmed = message.trim();\n\t\t\tconst space = trimmed.indexOf(\" \");\n\t\t\tconst cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);\n\t\t\tconst argsString = space === -1 ? \"\" : trimmed.slice(space + 1);\n\t\t\tconst args = parseArgs(argsString);\n\n\t\t\tconst handled = await this.handleBuiltinCommand(session, cmd, args);\n\t\t\tif (handled) return handled;\n\t\t}\n\n\t\tconst result = await session.prompt(message, images);\n\n\t\tconst stopReason: StopReason = result === \"error\" ? \"end_turn\" : result;\n\t\tconst usage = session.getUsage();\n\t\tconst cost = session.getCost();\n\n\t\treturn {\n\t\t\tstopReason,\n\t\t\tusage: {\n\t\t\t\tinputTokens: usage.inputTokens,\n\t\t\t\toutputTokens: usage.outputTokens,\n\t\t\t\tcachedReadTokens: usage.cachedReadTokens,\n\t\t\t\tcachedWriteTokens: usage.cachedWriteTokens,\n\t\t\t\ttotalTokens: usage.inputTokens + usage.outputTokens,\n\t\t\t},\n\t\t\t_meta: cost > 0 ? { cost: { amount: cost, currency: \"USD\" } } : {},\n\t\t};\n\t}\n\n\tasync cancel(params: CancelNotification): Promise<void> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tawait session.cancel();\n\t}\n\n\t/**\n\t * Resolve a session ID to a file path.\n\t * Checks the local cache first (populated by listSessions/newSession),\n\t * falls back to a full listAll() scan on cache miss.\n\t */\n\tprivate async resolveSessionFile(sessionId: string): Promise<string | null> {\n\t\tconst cached = this.sessionPaths.get(sessionId);\n\t\tif (cached !== undefined) return cached;\n\n\t\tconst all = await PiSessionManager.listAll();\n\t\tfor (const s of all) {\n\t\t\tthis.sessionPaths.set(s.id, s.path);\n\t\t}\n\n\t\treturn this.sessionPaths.get(sessionId) ?? null;\n\t}\n\n\t/**\n\t * Replay persisted session messages as ACP session updates.\n\t *\n\t * Iterates through the message history, emitting structured updates for each\n\t * content block type: text, thinking, tool calls, and tool results. A map of\n\t * tool call IDs to their invocation data (from assistant messages) is built\n\t * to enrich subsequent tool result updates with rawInput and locations.\n\t */\n\tprivate async replaySessionHistory(\n\t\tsession: PiAcpSession,\n\t\tmessages: AgentMessage[],\n\t): Promise<void> {\n\t\tconst toolCallMap = new Map<string, { name: string; args: ToolArgs }>();\n\n\t\tfor (const m of messages) {\n\t\t\tif (!(\"role\" in m)) continue;\n\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst text = extractUserMessageText((m satisfies UserMessage).content);\n\t\t\t\tif (text) {\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: { sessionUpdate: \"user_message_chunk\", content: { type: \"text\", text } },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (m.role === \"assistant\") {\n\t\t\t\tconst am = m satisfies AssistantMessage;\n\t\t\t\tfor (const block of am.content) {\n\t\t\t\t\tif (block.type === \"text\" && block.text) {\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\t\t\tcontent: { type: \"text\", text: block.text },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (block.type === \"thinking\" && block.thinking) {\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"agent_thought_chunk\",\n\t\t\t\t\t\t\t\tcontent: { type: \"text\", text: block.thinking },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\tconst args = toToolArgs(block.arguments);\n\t\t\t\t\t\ttoolCallMap.set(block.id, { name: block.name, args });\n\t\t\t\t\t\tconst locations = resolveToolPath(args, session.cwd);\n\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\t\t\ttoolCallId: block.id,\n\t\t\t\t\t\t\t\ttitle: buildToolTitle(block.name, args),\n\t\t\t\t\t\t\t\tkind: toToolKind(block.name),\n\t\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\t\trawInput: args,\n\t\t\t\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\t\t\t\t_meta: { piAcp: { toolName: block.name } },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (m.role === \"toolResult\") {\n\t\t\t\tconst tr = m satisfies ToolResultMessage;\n\t\t\t\tconst toolName = tr.toolName;\n\t\t\t\tconst toolCallId = tr.toolCallId;\n\t\t\t\tconst isError = tr.isError;\n\n\t\t\t\t// Enrich from the preceding assistant tool call if available.\n\t\t\t\tconst invocation = toolCallMap.get(toolCallId);\n\t\t\t\tconst args = invocation?.args;\n\t\t\t\tconst locations = args !== undefined ? resolveToolPath(args, session.cwd) : undefined;\n\n\t\t\t\t// If no tool_call was emitted from the assistant message (e.g. older\n\t\t\t\t// session format without structured assistant content), emit one now.\n\t\t\t\tif (invocation === undefined) {\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\t\ttitle: buildToolTitle(toolName, {}),\n\t\t\t\t\t\t\tkind: toToolKind(toolName),\n\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\trawInput: null,\n\t\t\t\t\t\t\trawOutput: m,\n\t\t\t\t\t\t\t_meta: { piAcp: { toolName } },\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst content = formatToolContent(toolName, m, isError);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\tstatus: isError ? \"failed\" : \"completed\",\n\t\t\t\t\t\tcontent: content.length > 0 ? content : null,\n\t\t\t\t\t\trawOutput: m,\n\t\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\t\t_meta: { piAcp: { toolName } },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tasync listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {\n\t\tconst cwd = params.cwd;\n\n\t\tconst raw =\n\t\t\tcwd !== undefined && cwd !== null\n\t\t\t\t? await PiSessionManager.list(cwd)\n\t\t\t\t: await PiSessionManager.listAll();\n\n\t\tfor (const s of raw) {\n\t\t\tthis.sessionPaths.set(s.id, s.path);\n\t\t}\n\n\t\tconst sessions = raw.map((s) => ({\n\t\t\tid: s.id,\n\t\t\tcwd: s.cwd,\n\t\t\tname: s.name,\n\t\t\tfirstMessage: s.firstMessage,\n\t\t\tmodified: s.modified,\n\t\t\tmessageCount: s.messageCount,\n\t\t}));\n\n\t\tif (params.cursor !== undefined && params.cursor !== null) {\n\t\t\tconst parsed = Number.parseInt(params.cursor, 10);\n\t\t\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\t\t\tthrow RequestError.invalidParams(`Invalid cursor: ${params.cursor}`);\n\t\t\t}\n\t\t}\n\n\t\tconst start =\n\t\t\tparams.cursor !== undefined && params.cursor !== null\n\t\t\t\t? Number.parseInt(params.cursor, 10)\n\t\t\t\t: 0;\n\n\t\tconst PAGE_SIZE = 50;\n\t\tconst page = sessions.slice(start, start + PAGE_SIZE);\n\n\t\tconst acpSessions: SessionInfo[] = page.map((s) => ({\n\t\t\tsessionId: s.id,\n\t\t\tcwd: s.cwd,\n\t\t\ttitle:\n\t\t\t\t(s.name !== undefined && s.name !== \"\" ? s.name : null) ??\n\t\t\t\ttruncateSessionTitle(s.firstMessage) ??\n\t\t\t\tnull,\n\t\t\tupdatedAt: s.modified.toISOString(),\n\t\t}));\n\n\t\tconst nextCursor = start + PAGE_SIZE < sessions.length ? String(start + PAGE_SIZE) : null;\n\n\t\treturn { sessions: acpSessions, nextCursor, _meta: {} };\n\t}\n\n\tasync loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tthis.sessions.close(params.sessionId);\n\n\t\tconst sessionFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sessionFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.open(sessionFile);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to load pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: params.sessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers,\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\n\t\tawait this.replaySessionHistory(session, piSession.messages);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\treturn {\n\t\t\tconfigOptions,\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync unstable_closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse> {\n\t\tconst session = this.sessions.maybeGet(params.sessionId);\n\t\tif (session === undefined) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\t\tthis.sessions.close(params.sessionId);\n\t\treturn {};\n\t}\n\n\tasync unstable_resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\t// If the session is already live, reuse it.\n\t\tconst existing = this.sessions.maybeGet(params.sessionId);\n\t\tif (existing !== undefined) {\n\t\t\tconst modes = buildThinkingModes(existing.piSession);\n\t\t\tconst models = buildModelState(existing.piSession);\n\t\t\treturn {\n\t\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\t\tmodes,\n\t\t\t\tmodels,\n\t\t\t};\n\t\t}\n\n\t\t// Otherwise, load from disk (same path as loadSession but without replay).\n\t\tconst sessionFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sessionFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.open(sessionFile);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to resume pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: params.sessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\t\tthis.sessionPaths.set(params.sessionId, sessionFile);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\treturn {\n\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync unstable_forkSession(params: ForkSessionRequest): Promise<ForkSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tconst sourceFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sourceFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.forkFrom(sourceFile, params.cwd);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to fork pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst newSessionId = piSession.sessionManager.getSessionId();\n\t\tconst newSessionFile = piSession.sessionManager.getSessionFile();\n\t\tif (newSessionFile !== undefined) {\n\t\t\tthis.sessionPaths.set(newSessionId, newSessionFile);\n\t\t}\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: newSessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\treturn {\n\t\t\tsessionId: newSessionId,\n\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst mode = String(params.modeId);\n\t\tif (!isThinkingLevel(mode)) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modeId: ${mode}`);\n\t\t}\n\n\t\tsession.piSession.setThinkingLevel(mode);\n\n\t\tvoid this.conn.sessionUpdate({\n\t\t\tsessionId: session.sessionId,\n\t\t\tupdate: { sessionUpdate: \"current_mode_update\", currentModeId: mode },\n\t\t});\n\n\t\tthis.emitConfigOptionUpdate(session);\n\n\t\treturn {};\n\t}\n\n\tasync unstable_setSessionModel(\n\t\tparams: SetSessionModelRequest,\n\t): Promise<SetSessionModelResponse | void> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst available = session.piSession.modelRegistry.getAvailable();\n\n\t\tconst resolved = resolveModelPreference(available, params.modelId);\n\t\tif (resolved === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modelId: ${params.modelId}`);\n\t\t}\n\n\t\tconst model = available.find((m) => m.provider === resolved.provider && m.id === resolved.id);\n\t\tif (!model) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modelId: ${params.modelId}`);\n\t\t}\n\n\t\tawait session.piSession.setModel(model);\n\t\tthis.emitConfigOptionUpdate(session);\n\t}\n\n\tasync setSessionConfigOption(\n\t\tparams: SetSessionConfigOptionRequest,\n\t): Promise<SetSessionConfigOptionResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst configId = String(params.configId);\n\t\tconst value = String(params.value);\n\n\t\tif (configId === \"model\") {\n\t\t\tconst available = session.piSession.modelRegistry.getAvailable();\n\t\t\tconst resolved = resolveModelPreference(available, value);\n\t\t\tif (resolved === null) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t}\n\n\t\t\tconst model = available.find((m) => m.provider === resolved.provider && m.id === resolved.id);\n\t\t\tif (!model) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t}\n\n\t\t\tawait session.piSession.setModel(model);\n\t\t} else if (configId === \"thought_level\") {\n\t\t\tif (!isThinkingLevel(value)) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown thinking level: ${value}`);\n\t\t\t}\n\t\t\tsession.piSession.setThinkingLevel(value);\n\t\t} else {\n\t\t\tthrow RequestError.invalidParams(`Unknown config option: ${configId}`);\n\t\t}\n\n\t\tconst modes = buildThinkingModes(session.piSession);\n\t\tconst models = buildModelState(session.piSession);\n\t\treturn { configOptions: buildConfigOptions(modes, models) };\n\t}\n\n\tprivate emitConfigOptionUpdate(session: PiAcpSession): void {\n\t\tconst modes = buildThinkingModes(session.piSession);\n\t\tconst models = buildModelState(session.piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tvoid this.conn.sessionUpdate({\n\t\t\tsessionId: session.sessionId,\n\t\t\tupdate: {\n\t\t\t\tsessionUpdate: \"config_option_update\",\n\t\t\t\tconfigOptions,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async handleBuiltinCommand(\n\t\tsession: PiAcpSession,\n\t\tcmd: string,\n\t\targs: string[],\n\t): Promise<PromptResponse | null> {\n\t\tconst piSession = session.piSession;\n\n\t\tif (cmd === \"compact\") {\n\t\t\tconst customInstructions = args.join(\" \").trim() || undefined;\n\t\t\tconst res = await piSession.compact(customInstructions);\n\n\t\t\tconst headerLines = [\n\t\t\t\t`Compaction completed.${customInstructions !== undefined && customInstructions !== \"\" ? \" (custom instructions applied)\" : \"\"}`,\n\t\t\t\ttypeof res?.tokensBefore === \"number\" ? `Tokens before: ${res.tokensBefore}` : null,\n\t\t\t].filter(Boolean);\n\n\t\t\tconst text = headerLines.join(\"\\n\") + (res?.summary ? `\\n\\n${res.summary}` : \"\");\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"session\") {\n\t\t\tconst stats = piSession.getSessionStats();\n\t\t\tconst lines: string[] = [];\n\t\t\tif (stats.sessionId !== undefined && stats.sessionId !== \"\")\n\t\t\t\tlines.push(`Session: ${stats.sessionId}`);\n\t\t\tif (stats.sessionFile !== undefined && stats.sessionFile !== \"\")\n\t\t\t\tlines.push(`Session file: ${stats.sessionFile}`);\n\t\t\tlines.push(`Messages: ${stats.totalMessages}`);\n\t\t\tlines.push(`Cost: ${stats.cost}`);\n\t\t\tconst t = stats.tokens;\n\t\t\tconst parts: string[] = [];\n\t\t\tif (t.input) parts.push(`in ${t.input}`);\n\t\t\tif (t.output) parts.push(`out ${t.output}`);\n\t\t\tif (t.cacheRead) parts.push(`cache read ${t.cacheRead}`);\n\t\t\tif (t.cacheWrite) parts.push(`cache write ${t.cacheWrite}`);\n\t\t\tif (t.total) parts.push(`total ${t.total}`);\n\t\t\tif (parts.length > 0) lines.push(`Tokens: ${parts.join(\", \")}`);\n\n\t\t\tconst text = lines.join(\"\\n\");\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"name\") {\n\t\t\tconst name = args.join(\" \").trim();\n\t\t\tif (!name) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /name <name>\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tpiSession.setSessionName(name);\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"session_info_update\",\n\t\t\t\t\ttitle: name,\n\t\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Session name set: ${name}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"steering\") {\n\t\t\tconst modeRaw = String(args[0] ?? \"\").toLowerCase();\n\t\t\tif (!modeRaw) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Steering mode: ${piSession.steeringMode}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tif (modeRaw !== \"all\" && modeRaw !== \"one-at-a-time\") {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /steering all | /steering one-at-a-time\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tpiSession.setSteeringMode(modeRaw);\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Steering mode set to: ${modeRaw}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"follow-up\") {\n\t\t\tconst modeRaw = String(args[0] ?? \"\").toLowerCase();\n\t\t\tif (!modeRaw) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Follow-up mode: ${piSession.followUpMode}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tif (modeRaw !== \"all\" && modeRaw !== \"one-at-a-time\") {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /follow-up all | /follow-up one-at-a-time\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tpiSession.setFollowUpMode(modeRaw);\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Follow-up mode set to: ${modeRaw}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"autocompact\") {\n\t\t\tconst mode = (args[0] ?? \"toggle\").toLowerCase();\n\t\t\tlet enabled: boolean | null = null;\n\t\t\tif (mode === \"on\" || mode === \"true\" || mode === \"enable\") enabled = true;\n\t\t\telse if (mode === \"off\" || mode === \"false\" || mode === \"disable\") enabled = false;\n\n\t\t\tif (enabled === null) {\n\t\t\t\tenabled = !piSession.autoCompactionEnabled;\n\t\t\t}\n\n\t\t\tpiSession.setAutoCompactionEnabled(enabled);\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Auto-compaction ${enabled ? \"enabled\" : \"disabled\"}.` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"changelog\") {\n\t\t\tconst changelogPath = findChangelog();\n\t\t\tif (changelogPath === null) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Changelog not found.\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tlet text = \"\";\n\t\t\ttry {\n\t\t\t\ttext = readFileSync(changelogPath, \"utf-8\");\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Failed to read changelog: ${msg}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tconst maxChars = 20_000;\n\t\t\tif (text.length > maxChars) text = `${text.slice(0, maxChars)}\\n\\n...(truncated)...`;\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"export\") {\n\t\t\tconst messageCount = piSession.messages.length;\n\t\t\tif (messageCount === 0) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Nothing to export yet. Send a prompt first.\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst safeSessionId = session.sessionId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t\t\t\tconst outputPath = join(session.cwd, `pi-session-${safeSessionId}.html`);\n\t\t\t\tconst resultPath = await piSession.exportToHtml(outputPath);\n\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Session exported: \" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\ttype: \"resource_link\",\n\t\t\t\t\t\t\tname: `pi-session-${safeSessionId}.html`,\n\t\t\t\t\t\t\turi: `file://${resultPath}`,\n\t\t\t\t\t\t\tmimeType: \"text/html\",\n\t\t\t\t\t\t\ttitle: \"Session exported\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Export failed: ${msg}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\nfunction isThinkingLevel(x: string): x is ThinkingLevel {\n\treturn (\n\t\tx === \"off\" || x === \"minimal\" || x === \"low\" || x === \"medium\" || x === \"high\" || x === \"xhigh\"\n\t);\n}\n\nfunction buildThinkingModes(piSession: AgentSession): {\n\tavailableModes: Array<{ id: string; name: string; description?: string | null }>;\n\tcurrentModeId: string;\n} {\n\tconst levels = piSession.getAvailableThinkingLevels();\n\treturn {\n\t\tcurrentModeId: piSession.thinkingLevel,\n\t\tavailableModes: levels.map((id) => ({\n\t\t\tid,\n\t\t\tname: `Thinking: ${id}`,\n\t\t\tdescription: null,\n\t\t})),\n\t};\n}\n\nfunction buildModelState(piSession: AgentSession): SessionModelState {\n\tconst available = piSession.modelRegistry.getAvailable();\n\tconst current = piSession.model;\n\n\tconst availableModels: ModelInfo[] = available.map((m) => ({\n\t\tmodelId: `${m.provider}/${m.id}`,\n\t\tname: `${m.provider}/${m.name ?? m.id}`,\n\t\tdescription: null,\n\t}));\n\n\tlet currentModelId = \"default\";\n\tif (current !== undefined) {\n\t\tcurrentModelId = `${current.provider}/${current.id}`;\n\t} else if (availableModels.length > 0 && availableModels[0] !== undefined) {\n\t\tcurrentModelId = availableModels[0].modelId;\n\t}\n\n\treturn { availableModels, currentModelId };\n}\n\nfunction buildConfigOptions(\n\tmodes: SessionModeState,\n\tmodels: SessionModelState,\n): SessionConfigOption[] {\n\treturn [\n\t\t{\n\t\t\tid: \"model\",\n\t\t\tname: \"Model\",\n\t\t\tdescription: \"AI model to use\",\n\t\t\tcategory: \"model\",\n\t\t\ttype: \"select\" as const,\n\t\t\tcurrentValue: models.currentModelId,\n\t\t\toptions: models.availableModels.map((m) => ({\n\t\t\t\tvalue: m.modelId,\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description ?? null,\n\t\t\t})),\n\t\t},\n\t\t{\n\t\t\tid: \"thought_level\",\n\t\t\tname: \"Thinking Level\",\n\t\t\tdescription: \"Reasoning depth for models that support it\",\n\t\t\tcategory: \"thought_level\",\n\t\t\ttype: \"select\" as const,\n\t\t\tcurrentValue: modes.currentModeId,\n\t\t\toptions: modes.availableModes.map((m) => ({\n\t\t\t\tvalue: m.id,\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description ?? null,\n\t\t\t})),\n\t\t},\n\t];\n}\n\nfunction buildCommandList(\n\tpiSession: AgentSession,\n\tenableSkillCommands: boolean,\n): AvailableCommand[] {\n\tconst commands: AvailableCommand[] = [];\n\n\tfor (const template of piSession.promptTemplates) {\n\t\tcommands.push({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description ?? `(prompt)`,\n\t\t});\n\t}\n\n\tif (enableSkillCommands) {\n\t\tconst skills = piSession.resourceLoader.getSkills();\n\t\tfor (const skill of skills.skills) {\n\t\t\tcommands.push({\n\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\tdescription: skill.description ?? `(skill)`,\n\t\t\t});\n\t\t}\n\t}\n\n\tconst runner = piSession.extensionRunner;\n\tif (runner) {\n\t\tfor (const cmd of runner.getRegisteredCommands()) {\n\t\t\tcommands.push({\n\t\t\t\tname: cmd.name,\n\t\t\t\tdescription: cmd.description ?? \"(extension)\",\n\t\t\t});\n\t\t}\n\t}\n\n\treturn commands;\n}\n\nfunction findChangelog(): string | null {\n\ttry {\n\t\tconst whichCmd = process.platform === \"win32\" ? \"where\" : \"which\";\n\t\tconst which = spawnSync(whichCmd, [\"pi\"], { encoding: \"utf-8\" });\n\t\tconst piPath = String(which.stdout ?? \"\")\n\t\t\t.split(/\\r?\\n/)[0]\n\t\t\t?.trim();\n\t\tif (piPath !== undefined && piPath !== \"\") {\n\t\t\tconst resolved = realpathSync(piPath);\n\t\t\tconst pkgRoot = dirname(dirname(resolved));\n\t\t\tconst p = join(pkgRoot, \"CHANGELOG.md\");\n\t\t\tif (existsSync(p)) return p;\n\t\t}\n\t} catch {}\n\n\ttry {\n\t\tconst npmRoot = spawnSync(\"npm\", [\"root\", \"-g\"], { encoding: \"utf-8\" });\n\t\tconst root = String(npmRoot.stdout ?? \"\").trim();\n\t\tif (root) {\n\t\t\tconst p = join(root, \"@mariozechner\", \"pi-coding-agent\", \"CHANGELOG.md\");\n\t\t\tif (existsSync(p)) return p;\n\t\t}\n\t} catch {}\n\n\treturn null;\n}\n","import { platform } from \"node:os\";\nimport { AgentSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\";\nimport { PiAcpAgent } from \"@pi-acp/acp/agent\";\n\n// Terminal Auth entrypoint: ACP client launches with `--terminal-login`.\nif (process.argv.includes(\"--terminal-login\")) {\n\tconst { spawnSync } = await import(\"node:child_process\");\n\tconst isWindows = platform() === \"win32\";\n\tconst cmd = process.env.PI_ACP_PI_COMMAND ?? (isWindows ? \"pi.cmd\" : \"pi\");\n\tconst res = spawnSync(cmd, [], { stdio: \"inherit\", env: process.env });\n\n\tif (res.error && \"code\" in res.error && res.error.code === \"ENOENT\") {\n\t\tprocess.stderr.write(\n\t\t\t`pi-acp: could not start pi (command not found: ${cmd}). ` +\n\t\t\t\t\"Install via `npm install -g @mariozechner/pi-coding-agent` \" +\n\t\t\t\t\"or ensure `pi` is on your PATH.\\n\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tprocess.exit(typeof res.status === \"number\" ? res.status : 1);\n}\n\nconst input = new WritableStream<Uint8Array>({\n\twrite(chunk) {\n\t\treturn new Promise<void>((resolve) => {\n\t\t\tif (process.stdout.destroyed || !process.stdout.writable) {\n\t\t\t\tresolve();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tprocess.stdout.write(chunk, () => resolve());\n\t\t\t} catch {\n\t\t\t\tresolve();\n\t\t\t}\n\t\t});\n\t},\n});\n\nconst output = new ReadableStream<Uint8Array>({\n\tstart(controller) {\n\t\tprocess.stdin.on(\"data\", (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)));\n\t\tprocess.stdin.on(\"end\", () => controller.close());\n\t\tprocess.stdin.on(\"error\", (err) => controller.error(err));\n\t},\n});\n\nconst stream = ndJsonStream(input, output);\nconst agent = new AgentSideConnection((conn) => new PiAcpAgent(conn), stream);\n\nfunction shutdown() {\n\ttry {\n\t\t// AgentSideConnection stores the agent instance internally;\n\t\t// call dispose() on it if available for clean shutdown.\n\t\tif (\"agent\" in agent) {\n\t\t\tconst inner: unknown = agent.agent;\n\t\t\tif (\n\t\t\t\ttypeof inner === \"object\" &&\n\t\t\t\tinner !== null &&\n\t\t\t\t\"dispose\" in inner &&\n\t\t\t\ttypeof inner.dispose === \"function\"\n\t\t\t) {\n\t\t\t\t// eslint-disable-next-line typescript-eslint/no-unsafe-call -- runtime-guarded\n\t\t\t\tinner.dispose();\n\t\t\t}\n\t\t}\n\t} catch {\n\t\t// best-effort cleanup\n\t}\n\tprocess.exit(0);\n}\n\nprocess.stdin.on(\"end\", shutdown);\nprocess.stdin.on(\"close\", shutdown);\nprocess.stdin.resume();\nprocess.on(\"SIGINT\", shutdown);\nprocess.on(\"SIGTERM\", shutdown);\nprocess.stdout.on(\"error\", () => process.exit(0));\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * pi-acp entry point. Dispatches between four modes:\n *\n * --terminal-login → foreground pi for interactive auth (v0.5 flow)\n * --daemon → long-running orchestrator (PRD-003)\n * --no-daemon | PI_ACP_NO_DAEMON=1 → v0.5 in-process server (escape hatch)\n * (default) → thin client; auto-spawns daemon\n *\n * ACP transports JSON-RPC NDJSON over stdout. Any stray byte poisons the\n * protocol stream. Redirect console.{log,info,warn,debug} to stderr at boot\n * so transitive deps (or our own debug prints) can't corrupt it.\n */\n\nimport { platform } from \"node:os\";\n\n{\n\tconst toStderr = (...args: unknown[]): void => {\n\t\tprocess.stderr.write(\n\t\t\t`${args.map((a) => (typeof a === \"string\" ? a : JSON.stringify(a))).join(\" \")}\\n`,\n\t\t);\n\t};\n\tconsole.log = toStderr;\n\tconsole.info = toStderr;\n\tconsole.warn = toStderr;\n\tconsole.debug = toStderr;\n}\n\nconst argv = process.argv.slice(2);\n\nif (argv.includes(\"--terminal-login\")) {\n\tawait runTerminalLogin();\n} else if (argv.includes(\"--daemon\")) {\n\tconst { runDaemon } = await import(\"@pi-acp/daemon/index\");\n\tawait runDaemon();\n} else if (argv.includes(\"--no-daemon\") || process.env[\"PI_ACP_NO_DAEMON\"] === \"1\") {\n\tconst { runInProcess } = await import(\"@pi-acp/runtime/in-process\");\n\trunInProcess();\n} else {\n\tconst { runClient } = await import(\"@pi-acp/client/index\");\n\tawait runClient();\n}\n\nasync function runTerminalLogin(): Promise<void> {\n\tconst { spawnSync } = await import(\"node:child_process\");\n\tconst isWindows = platform() === \"win32\";\n\tconst cmd = process.env[\"PI_ACP_PI_COMMAND\"] ?? (isWindows ? \"pi.cmd\" : \"pi\");\n\tconst res = spawnSync(cmd, [], { stdio: \"inherit\", env: process.env });\n\n\tif (res.error && \"code\" in res.error && res.error.code === \"ENOENT\") {\n\t\tprocess.stderr.write(\n\t\t\t`pi-acp: could not start pi (command not found: ${cmd}). ` +\n\t\t\t\t\"Install via `npm install -g @earendil-works/pi-coding-agent` \" +\n\t\t\t\t\"or ensure `pi` is on your PATH.\\n\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tprocess.exit(typeof res.status === \"number\" ? res.status : 1);\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA;CACC,MAAM,YAAY,GAAG,SAA0B;AAC9C,UAAQ,OAAO,MACd,GAAG,KAAK,KAAK,MAAO,OAAO,MAAM,WAAW,IAAI,KAAK,UAAU,EAAE,CAAE,CAAC,KAAK,IAAI,CAAC,IAC9E;;AAEF,SAAQ,MAAM;AACd,SAAQ,OAAO;AACf,SAAQ,OAAO;AACf,SAAQ,QAAQ;;AAGjB,MAAM,OAAO,QAAQ,KAAK,MAAM,EAAE;AAElC,IAAI,KAAK,SAAS,mBAAmB,CACpC,OAAM,kBAAkB;SACd,KAAK,SAAS,WAAW,EAAE;CACrC,MAAM,EAAE,cAAc,MAAM,OAAO;AACnC,OAAM,WAAW;WACP,KAAK,SAAS,cAAc,IAAI,QAAQ,IAAI,wBAAwB,KAAK;CACnF,MAAM,EAAE,iBAAiB,MAAM,OAAO;AACtC,eAAc;OACR;CACN,MAAM,EAAE,cAAc,MAAM,OAAO;AACnC,OAAM,WAAW;;AAGlB,eAAe,mBAAkC;CAChD,MAAM,EAAE,cAAc,MAAM,OAAO;CACnC,MAAM,YAAY,UAAU,KAAK;CACjC,MAAM,MAAM,QAAQ,IAAI,yBAAyB,YAAY,WAAW;CACxE,MAAM,MAAM,UAAU,KAAK,EAAE,EAAE;EAAE,OAAO;EAAW,KAAK,QAAQ;EAAK,CAAC;AAEtE,KAAI,IAAI,SAAS,UAAU,IAAI,SAAS,IAAI,MAAM,SAAS,UAAU;AACpE,UAAQ,OAAO,MACd,kDAAkD,IAAI;EAGtD;AACD,UAAQ,KAAK,EAAE;;AAGhB,SAAQ,KAAK,OAAO,IAAI,WAAW,WAAW,IAAI,SAAS,EAAE"}