pi-acp 0.0.23 → 0.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -84,7 +84,22 @@ import { isAbsolute, resolve as resolvePath } from "path";
84
84
  // src/pi-rpc/process.ts
85
85
  import { spawn } from "child_process";
86
86
  import * as readline from "readline";
87
+
88
+ // src/pi-rpc/command.ts
87
89
  import { platform } from "os";
90
+ function defaultPiCommand() {
91
+ return platform() === "win32" ? "pi.cmd" : "pi";
92
+ }
93
+ function getPiCommand(override) {
94
+ return override ?? defaultPiCommand();
95
+ }
96
+ function shouldUseShellForPiCommand(cmd) {
97
+ if (platform() !== "win32") return false;
98
+ const normalized = cmd.trim().toLowerCase();
99
+ return normalized.endsWith(".cmd") || normalized.endsWith(".bat");
100
+ }
101
+
102
+ // src/pi-rpc/process.ts
88
103
  var PiRpcSpawnError = class extends Error {
89
104
  /** Underlying spawn error code, e.g. ENOENT, EACCES */
90
105
  code;
@@ -146,14 +161,14 @@ var PiRpcProcess = class _PiRpcProcess {
146
161
  });
147
162
  }
148
163
  static async spawn(params) {
149
- const isWindows = platform() === "win32";
150
- const cmd = params.piCommand ?? (isWindows ? "pi.cmd" : "pi");
164
+ const cmd = getPiCommand(params.piCommand);
151
165
  const args = ["--mode", "rpc", "--no-themes"];
152
166
  if (params.sessionPath) args.push("--session", params.sessionPath);
153
167
  const child = spawn(cmd, args, {
154
168
  cwd: params.cwd,
155
169
  stdio: "pipe",
156
- env: process.env
170
+ env: process.env,
171
+ shell: shouldUseShellForPiCommand(cmd)
157
172
  });
158
173
  try {
159
174
  await new Promise((resolve3, reject) => {
@@ -930,6 +945,37 @@ var PiAcpSession = class {
930
945
  this.editSnapshots.delete(toolCallId);
931
946
  break;
932
947
  }
948
+ case "auto_retry_start": {
949
+ this.emit({
950
+ sessionUpdate: "agent_message_chunk",
951
+ content: { type: "text", text: formatAutoRetryMessage(ev) }
952
+ });
953
+ break;
954
+ }
955
+ case "auto_retry_end": {
956
+ this.emit({
957
+ sessionUpdate: "agent_message_chunk",
958
+ content: { type: "text", text: "Retry finished, resuming." }
959
+ });
960
+ break;
961
+ }
962
+ case "auto_compaction_start": {
963
+ this.emit({
964
+ sessionUpdate: "agent_message_chunk",
965
+ content: { type: "text", text: "Context nearing limit, running automatic compaction..." }
966
+ });
967
+ break;
968
+ }
969
+ case "auto_compaction_end": {
970
+ this.emit({
971
+ sessionUpdate: "agent_message_chunk",
972
+ content: {
973
+ type: "text",
974
+ text: "Automatic compaction finished; context was summarized to continue the session."
975
+ }
976
+ });
977
+ break;
978
+ }
933
979
  case "agent_start": {
934
980
  this.inAgentLoop = true;
935
981
  break;
@@ -964,6 +1010,17 @@ var PiAcpSession = class {
964
1010
  }
965
1011
  }
966
1012
  };
1013
+ function formatAutoRetryMessage(ev) {
1014
+ const attempt = Number(ev.attempt);
1015
+ const maxAttempts = Number(ev.maxAttempts);
1016
+ const delayMs = Number(ev.delayMs);
1017
+ if (!Number.isFinite(attempt) || !Number.isFinite(maxAttempts) || !Number.isFinite(delayMs)) {
1018
+ return "Retrying...";
1019
+ }
1020
+ let delaySeconds = Math.round(delayMs / 1e3);
1021
+ if (delayMs > 0 && delaySeconds === 0) delaySeconds = 1;
1022
+ return `Retrying (attempt ${attempt}/${maxAttempts}, waiting ${delaySeconds}s)...`;
1023
+ }
967
1024
  function toToolKind(toolName) {
968
1025
  switch (toolName) {
969
1026
  case "read":
@@ -2292,7 +2349,7 @@ function compareSemver(a, b) {
2292
2349
  function buildUpdateNotice() {
2293
2350
  try {
2294
2351
  const piVersion = spawnSync("pi", ["--version"], { encoding: "utf-8" });
2295
- const installed = String(piVersion.stdout ?? "").trim().replace(/^v/i, "");
2352
+ const installed = (String(piVersion.stdout ?? "").trim() || String(piVersion.stderr ?? "").trim()).replace(/^v/i, "");
2296
2353
  if (!installed || !isSemver(installed)) return null;
2297
2354
  const latestRes = spawnSync("npm", ["view", "@mariozechner/pi-coding-agent", "version"], {
2298
2355
  encoding: "utf-8",
@@ -2311,7 +2368,7 @@ function buildStartupInfo(opts) {
2311
2368
  const md = [];
2312
2369
  try {
2313
2370
  const piVersion = spawnSync("pi", ["--version"], { encoding: "utf-8" });
2314
- const installed = String(piVersion.stdout ?? "").trim().replace(/^v/i, "");
2371
+ const installed = (String(piVersion.stdout ?? "").trim() || String(piVersion.stderr ?? "").trim()).replace(/^v/i, "");
2315
2372
  if (installed) {
2316
2373
  md.push(`pi v${installed}`);
2317
2374
  md.push("---");
@@ -2433,12 +2490,14 @@ function readNearestPackageJson(metaUrl) {
2433
2490
  }
2434
2491
 
2435
2492
  // src/index.ts
2436
- import { platform as platform2 } from "os";
2437
2493
  if (process.argv.includes("--terminal-login")) {
2438
2494
  const { spawnSync: spawnSync2 } = await import("child_process");
2439
- const isWindows = platform2() === "win32";
2440
- const cmd = process.env.PI_ACP_PI_COMMAND ?? (isWindows ? "pi.cmd" : "pi");
2441
- const res = spawnSync2(cmd, [], { stdio: "inherit", env: process.env });
2495
+ const cmd = getPiCommand(process.env.PI_ACP_PI_COMMAND);
2496
+ const res = spawnSync2(cmd, [], {
2497
+ stdio: "inherit",
2498
+ env: process.env,
2499
+ shell: shouldUseShellForPiCommand(cmd)
2500
+ });
2442
2501
  if (res.error && res.error.code === "ENOENT") {
2443
2502
  process.stderr.write(
2444
2503
  `pi-acp: could not start pi (command not found: ${cmd}). Install it via \`npm install -g @mariozechner/pi-coding-agent\` or ensure \`pi\` is on your PATH.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/acp/agent.ts","../src/acp/auth.ts","../src/acp/session.ts","../src/acp/auth-required.ts","../src/pi-rpc/process.ts","../src/acp/session-store.ts","../src/acp/paths.ts","../src/acp/translate/pi-tools.ts","../src/acp/slash-commands.ts","../src/acp/pi-sessions.ts","../src/acp/translate/pi-messages.ts","../src/acp/translate/prompt.ts","../src/acp/pi-settings.ts","../src/acp/pi-commands.ts","../src/pi-auth/status.ts"],"sourcesContent":["import { AgentSideConnection, ndJsonStream } from '@agentclientprotocol/sdk'\nimport { PiAcpAgent } from './acp/agent.js'\nimport { platform } from 'node:os'\n// Terminal Auth entrypoint. The ACP client launches the agent with `--terminal-login`.\nif (process.argv.includes('--terminal-login')) {\n const { spawnSync } = await import('node:child_process')\n const isWindows = platform() === 'win32'\n const cmd = process.env.PI_ACP_PI_COMMAND ?? (isWindows ? 'pi.cmd' : 'pi')\n const res = spawnSync(cmd, [], { stdio: 'inherit', env: process.env })\n\n if ((res as any).error && (res as any).error.code === 'ENOENT') {\n process.stderr.write(\n `pi-acp: could not start pi (command not found: ${cmd}). Install it via \\`npm install -g @mariozechner/pi-coding-agent\\` or ensure \\`pi\\` is on your PATH.\\n`\n )\n process.exit(1)\n }\n\n process.exit(typeof res.status === 'number' ? res.status : 1)\n}\n\nconst input = new WritableStream<Uint8Array>({\n write(chunk) {\n return new Promise<void>(resolve => {\n if ((process.stdout as any).destroyed || !process.stdout.writable) return resolve()\n\n try {\n process.stdout.write(chunk, err => {\n void err\n resolve()\n })\n } catch {\n // Common: ERR_STREAM_DESTROYED (\"Cannot call write after a stream was destroyed\").\n resolve()\n }\n })\n }\n})\n\nconst output = new ReadableStream<Uint8Array>({\n start(controller) {\n process.stdin.on('data', (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)))\n process.stdin.on('end', () => controller.close())\n process.stdin.on('error', err => controller.error(err))\n }\n})\n\nconst stream = ndJsonStream(input, output)\n\nconst agent = new AgentSideConnection(conn => new PiAcpAgent(conn), stream)\n\nfunction shutdown() {\n try {\n // Best-effort: dispose session subprocesses when the client disconnects.\n ;(agent as any)?.agent?.dispose?.()\n } catch {\n // ignore\n }\n try {\n process.exit(0)\n } catch {\n // ignore\n }\n}\n\nprocess.stdin.on('end', shutdown)\nprocess.stdin.on('close', shutdown)\n\nprocess.stdin.resume()\nprocess.on('SIGINT', shutdown)\nprocess.on('SIGTERM', shutdown)\n\n// Avoid crashing if the client closes stdout early.\nprocess.stdout.on('error', () => {\n try {\n process.exit(0)\n } catch {\n // ignore\n }\n})\n","import {\n RequestError,\n type Agent as ACPAgent,\n type AgentSideConnection,\n type AuthenticateRequest,\n type CancelNotification,\n type InitializeRequest,\n type InitializeResponse,\n type ListSessionsRequest,\n type ListSessionsResponse,\n type LoadSessionRequest,\n type LoadSessionResponse,\n type ModelInfo,\n type NewSessionRequest,\n type PromptRequest,\n type PromptResponse,\n type SessionInfo,\n type SetSessionModeRequest,\n type SetSessionModeResponse,\n type StopReason\n} from '@agentclientprotocol/sdk'\nimport { getAuthMethods } from './auth.js'\nimport { SessionManager } from './session.js'\nimport { SessionStore } from './session-store.js'\nimport { PiRpcProcess } from '../pi-rpc/process.js'\nimport { listPiSessions, findPiSessionFile } from './pi-sessions.js'\nimport { normalizePiAssistantText, normalizePiMessageText } from './translate/pi-messages.js'\nimport { toolResultToText } from './translate/pi-tools.js'\nimport { promptToPiMessage } from './translate/prompt.js'\nimport { loadSlashCommands, parseCommandArgs, toAvailableCommands } from './slash-commands.js'\nimport { getAgentDir, getEnableSkillCommands, getQuietStartup } from './pi-settings.js'\nimport { toAvailableCommandsFromPiGetCommands } from './pi-commands.js'\nimport { isAbsolute } from 'node:path'\nimport { existsSync, readFileSync, realpathSync, readdirSync, statSync } from 'node:fs'\nimport type { AvailableCommand } from '@agentclientprotocol/sdk'\nimport { join, dirname, basename } from 'node:path'\nimport { spawnSync } from 'node:child_process'\nimport { hasAnyPiAuthConfigured } from '../pi-auth/status.js'\n\ntype ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'\n\nfunction builtinAvailableCommands(): AvailableCommand[] {\n return [\n {\n name: 'compact',\n description: 'Manually compact the session context',\n input: { hint: 'optional custom instructions' }\n },\n {\n name: 'autocompact',\n description: 'Toggle automatic context compaction',\n input: { hint: 'on|off|toggle' }\n },\n {\n name: 'export',\n description: 'Export session to an HTML file in the session cwd'\n },\n {\n name: 'session',\n description: 'Show session stats (messages, tokens, cost, session file)'\n },\n {\n name: 'name',\n description: 'Set session display name',\n input: { hint: '<name>' }\n },\n {\n name: 'steering',\n description: 'Get/set pi steering message delivery mode (how queued steering messages are delivered)',\n input: { hint: '(no args to show) all | one-at-a-time' }\n },\n {\n name: 'follow-up',\n description: 'Get/set pi follow-up message delivery mode (how queued follow-up messages are delivered)',\n input: { hint: '(no args to show) all | one-at-a-time' }\n },\n {\n name: 'changelog',\n description: 'Show pi changelog'\n }\n ]\n}\n\nfunction mergeCommands(a: AvailableCommand[], b: AvailableCommand[]): AvailableCommand[] {\n // Preserve order, de-dupe by name (first wins).\n const out: AvailableCommand[] = []\n const seen = new Set<string>()\n\n for (const c of [...a, ...b]) {\n if (seen.has(c.name)) continue\n seen.add(c.name)\n out.push(c)\n }\n\n return out\n}\nimport { fileURLToPath } from 'node:url'\n\nconst pkg = readNearestPackageJson(import.meta.url)\n\nexport class PiAcpAgent implements ACPAgent {\n private readonly conn: AgentSideConnection\n private readonly sessions = new SessionManager()\n private readonly store = new SessionStore()\n\n dispose(): void {\n this.sessions.disposeAll()\n }\n\n // Remember recent session cwd and use it as the default filter.\n private lastSessionCwd: string | null = null\n\n constructor(conn: AgentSideConnection, _config?: unknown) {\n this.conn = conn\n void _config\n }\n\n async initialize(params: InitializeRequest): Promise<InitializeResponse> {\n // We currently only support ACP protocol version 1.\n const supportedVersion = 1\n const requested = params.protocolVersion\n\n return {\n protocolVersion: requested === supportedVersion ? requested : supportedVersion,\n agentInfo: {\n name: pkg.name ?? 'pi-acp',\n title: 'pi ACP adapter',\n version: pkg.version ?? '0.0.0'\n },\n // Zed currently uses ClientCapabilities._meta[\"terminal-auth\"] to decide whether to show\n // the \"Authenticate\" banner/button. If not supported, we still return the method for the registry.\n authMethods: getAuthMethods({\n supportsTerminalAuthMeta: (params as any)?.clientCapabilities?._meta?.['terminal-auth'] === true\n }),\n agentCapabilities: {\n loadSession: true,\n mcpCapabilities: { http: false, sse: false },\n promptCapabilities: {\n image: true,\n audio: false,\n embeddedContext: false\n },\n sessionCapabilities: {\n // **UNSTABLE** ACP capability used by Zed's codex-acp adapter.\n // Enables a native session picker in clients that support it.\n list: {}\n }\n }\n }\n }\n\n async newSession(params: NewSessionRequest) {\n if (!isAbsolute(params.cwd)) {\n throw RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`)\n }\n\n this.lastSessionCwd = params.cwd\n\n // IMPORTANT: pi exits immediately in --mode rpc if no model is available (no auth configured).\n // So we must detect that situation without spawning pi, and return AUTH_REQUIRED so clients\n // (e.g. Zed) can show the Authenticate banner and launch a terminal login.\n if (!hasAnyPiAuthConfigured()) {\n throw RequestError.authRequired(\n { authMethods: getAuthMethods() },\n 'Configure an API key or log in with an OAuth provider.'\n )\n }\n\n const fileCommands = loadSlashCommands(params.cwd)\n const enableSkillCommands = getEnableSkillCommands(params.cwd)\n\n // Pi doesn't support mcpServers, but we accept and store.\n const session = await this.sessions.create({\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n conn: this.conn,\n fileCommands,\n piCommand: process.env.PI_ACP_PI_COMMAND\n })\n\n // Fetch state + models once (parallel) to reduce startup latency.\n let state: any = null\n let availableModels: any = null\n\n await Promise.all([\n session.proc\n .getState()\n .then(s => {\n state = s as any\n })\n .catch(() => {\n state = null\n }),\n session.proc\n .getAvailableModels()\n .then(m => {\n availableModels = m as any\n })\n .catch(() => {\n availableModels = null\n })\n ])\n\n // Proactive auth gate: if pi has no models available, it's effectively unauthenticated.\n const rawModelsCount = Array.isArray(availableModels?.models) ? availableModels.models.length : 0\n\n if (rawModelsCount === 0) {\n try {\n session.proc.dispose?.()\n } catch {\n // ignore\n }\n throw RequestError.authRequired(\n { authMethods: getAuthMethods() },\n 'Configure an API key or log in with an OAuth provider.'\n )\n }\n\n const models = await getModelState(session.proc, { state, availableModels })\n const thinking = await getThinkingState(session.proc, { state })\n\n const quietStartup = getQuietStartup(params.cwd)\n const updateNotice = buildUpdateNotice()\n\n // If quietStartup is enabled, suppress the full \"startup info\" prelude, but still surface\n // the \"New version available\" notice (if any) since it's high-signal and actionable.\n const preludeText = quietStartup\n ? updateNotice\n ? updateNotice + '\\n'\n : ''\n : buildStartupInfo({\n cwd: params.cwd,\n fileCommands,\n updateNotice\n })\n\n if (preludeText)\n session.setStartupInfo(preludeText)\n\n // Policy: within a single ACP connection (one client window), keep only one live pi subprocess.\n // This avoids leaking subprocesses when clients start new sessions but don't explicitly close old ones.\n // It does NOT affect other client windows because they run in separate agent processes.\n //\n // (Tests sometimes stub out `this.sessions`, so guard the call.)\n ;(this.sessions as any).closeAllExcept?.(session.sessionId)\n\n const response = {\n sessionId: session.sessionId,\n models,\n modes: thinking,\n _meta: {\n piAcp: {\n startupInfo: preludeText || null\n }\n }\n }\n\n // Try to send it immediately after session/new returns; if the client ignores it,\n // it will still be emitted as the first chunk of the first prompt.\n if (preludeText) setTimeout(() => session.sendStartupInfoIfPending(), 0)\n\n // Advertise slash commands (ACP: available_commands_update)\n // Important: some clients (e.g. Zed) will ignore notifications for an unknown sessionId.\n // So we must send this *after* the session/new response has been delivered.\n setTimeout(() => {\n void (async () => {\n try {\n const pi = (await session.proc.getCommands()) as any\n const { commands } = toAvailableCommandsFromPiGetCommands(pi, {\n enableSkillCommands,\n includeExtensionCommands: false\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(commands, builtinAvailableCommands())\n }\n })\n return\n } catch {\n // Fall back to file-based prompt templates (legacy behavior).\n }\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(toAvailableCommands(fileCommands), builtinAvailableCommands())\n }\n })\n })()\n }, 0)\n\n return response\n }\n\n async authenticate(_params: AuthenticateRequest) {\n // Terminal Auth is handled out-of-band by re-launching the binary with `--terminal-login`.\n // If the client calls `authenticate` anyway, we can no-op successfully.\n return\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.sessions.get(params.sessionId)\n\n const { message, images } = promptToPiMessage(params.prompt)\n\n // Built-in ACP slash command handling (headless-friendly subset).\n // Note: file-based slash commands are expanded inside session.prompt().\n if (images.length === 0 && message.trimStart().startsWith('/')) {\n const trimmed = message.trim()\n const space = trimmed.indexOf(' ')\n const cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space)\n const argsString = space === -1 ? '' : trimmed.slice(space + 1)\n const args = parseCommandArgs(argsString)\n\n if (cmd === 'compact') {\n const customInstructions = args.join(' ').trim() || undefined\n const res = await session.proc.compact(customInstructions)\n\n const r: any = res && typeof res === 'object' ? (res as any) : null\n const tokensBefore = typeof r?.tokensBefore === 'number' ? r.tokensBefore : null\n const summary = typeof r?.summary === 'string' ? r.summary : null\n\n const headerLines = [\n `Compaction completed.${customInstructions ? ' (custom instructions applied)' : ''}`,\n tokensBefore !== null ? `Tokens before: ${tokensBefore}` : null\n ].filter(Boolean)\n\n const text = headerLines.join('\\n') + (summary ? `\\n\\n${summary}` : '')\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'session') {\n const stats = (await session.proc.getSessionStats()) as any\n\n const lines: string[] = []\n if (stats?.sessionId) lines.push(`Session: ${stats.sessionId}`)\n if (stats?.sessionFile) lines.push(`Session file: ${stats.sessionFile}`)\n if (typeof stats?.totalMessages === 'number') lines.push(`Messages: ${stats.totalMessages}`)\n\n if (typeof stats?.cost === 'number') lines.push(`Cost: ${stats.cost}`)\n\n const t = stats?.tokens\n if (t && typeof t === 'object') {\n const parts: string[] = []\n if (typeof t.input === 'number') parts.push(`in ${t.input}`)\n if (typeof t.output === 'number') parts.push(`out ${t.output}`)\n if (typeof t.cacheRead === 'number') parts.push(`cache read ${t.cacheRead}`)\n if (typeof t.cacheWrite === 'number') parts.push(`cache write ${t.cacheWrite}`)\n if (typeof t.total === 'number') parts.push(`total ${t.total}`)\n if (parts.length) lines.push(`Tokens: ${parts.join(', ')}`)\n }\n\n // Fallback if stats shape changes.\n const text = lines.length ? lines.join('\\n') : `Session stats:\\n${JSON.stringify(stats, null, 2)}`\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'name') {\n const name = args.join(' ').trim()\n if (!name) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: 'Usage: /name <name>' }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n try {\n await session.proc.setSessionName(name)\n } catch (e: any) {\n const msg = String(e?.message ?? e)\n const hint = /set_session_name/i.test(msg)\n ? ' This requires a newer pi version that supports `set_session_name` in RPC mode.'\n : ''\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Failed to set session name: ${msg}${hint}` }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'session_info_update',\n title: name,\n updatedAt: new Date().toISOString()\n }\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Session name set: ${name}` }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'steering') {\n const modeRaw = String(args[0] ?? '').toLowerCase()\n const state = (await session.proc.getState()) as any\n const current = String(state?.steeringMode ?? '')\n\n // If no arg, just report current.\n if (!modeRaw) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Steering mode: ${current || 'unknown'}`\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n if (modeRaw !== 'all' && modeRaw !== 'one-at-a-time') {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Usage: /steering all | /steering one-at-a-time'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n await session.proc.setSteeringMode(modeRaw as 'all' | 'one-at-a-time')\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Steering mode set to: ${modeRaw}` }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'follow-up') {\n const modeRaw = String(args[0] ?? '').toLowerCase()\n const state = (await session.proc.getState()) as any\n const current = String(state?.followUpMode ?? '')\n\n // If no arg, just report current.\n if (!modeRaw) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Follow-up mode: ${current || 'unknown'}`\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n if (modeRaw !== 'all' && modeRaw !== 'one-at-a-time') {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Usage: /follow-up all | /follow-up one-at-a-time'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n await session.proc.setFollowUpMode(modeRaw as 'all' | 'one-at-a-time')\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Follow-up mode set to: ${modeRaw}` }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'changelog') {\n // Read pi's installed CHANGELOG.md. Adapter-side, no model call.\n const findChangelog = (): string | null => {\n // 1) Locate the installed pi package by resolving the `pi` executable.\n // On Node installs, `pi` typically resolves to .../@mariozechner/pi-coding-agent/dist/cli.js\n try {\n const whichCmd = process.platform === 'win32' ? 'where' : 'which'\n const which = spawnSync(whichCmd, ['pi'], { encoding: 'utf-8' })\n const piPath = String(which.stdout ?? '')\n .split(/\\r?\\n/)[0]\n ?.trim()\n\n if (piPath) {\n const resolved = realpathSync(piPath)\n const pkgRoot = dirname(dirname(resolved))\n const p = join(pkgRoot, 'CHANGELOG.md')\n if (existsSync(p)) return p\n }\n } catch {\n // ignore\n }\n\n // 2) Fallback: ask npm where global modules live.\n try {\n const npmRoot = spawnSync('npm', ['root', '-g'], { encoding: 'utf-8' })\n const root = String(npmRoot.stdout ?? '').trim()\n if (root) {\n const p = join(root, '@mariozechner', 'pi-coding-agent', 'CHANGELOG.md')\n if (existsSync(p)) return p\n }\n } catch {\n // ignore\n }\n\n return null\n }\n\n const changelogPath = findChangelog()\n if (!changelogPath) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: \"Changelog not found (couldn't locate pi installation).\" }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n let text = ''\n try {\n text = readFileSync(changelogPath, 'utf-8')\n } catch (e: any) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Failed to read changelog: ${String(e?.message ?? e)}` }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n // Keep it reasonably sized in chat.\n const maxChars = 20_000\n if (text.length > maxChars) text = text.slice(0, maxChars) + '\\n\\n...(truncated)...'\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'export') {\n // For now we always export into the session cwd and do not accept a user-provided path.\n // IMPORTANT: pi's export_html reads the session JSONL file. If it doesn't exist yet\n // (no messages) or is empty, pi throws and RPC mode emits an uncorrelated parse error\n // (no id), which would otherwise hang our request. So we guard here.\n const state = (await session.proc.getState()) as any\n const sessionFile = typeof state?.sessionFile === 'string' ? state.sessionFile : null\n const messageCount = typeof state?.messageCount === 'number' ? state.messageCount : 0\n\n if (!sessionFile || messageCount === 0 || !existsSync(sessionFile)) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Nothing to export yet (no session messages). Send a prompt first.'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n try {\n const raw = readFileSync(sessionFile, 'utf-8')\n if (raw.trim().length === 0) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Nothing to export yet (empty session file). Send a prompt first.'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n } catch {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: \"Couldn't read session file for export. Try sending a prompt first.\"\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n const safeSessionId = session.sessionId.replace(/[^a-zA-Z0-9_-]/g, '_')\n const outputPath = join(session.cwd, `pi-session-${safeSessionId}.html`)\n\n let resultPath = ''\n try {\n const result = await session.proc.exportHtml(outputPath)\n resultPath = result.path\n } catch (e: any) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Export failed: ${String(e?.message ?? e)}`\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n if (!resultPath) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Export failed: no output path returned by pi.'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n const uri = `file://${resultPath}`\n\n // Emit a short prefix + a resource link. Many clients concatenate chunks into a single\n // assistant message, so this avoids the \"link + duplicate plain text\" look.\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Session exported: '\n }\n }\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'resource_link',\n name: `pi-session-${safeSessionId}.html`,\n uri,\n mimeType: 'text/html',\n title: 'Session exported'\n }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'autocompact') {\n const mode = (args[0] ?? 'toggle').toLowerCase()\n let enabled: boolean | null = null\n if (mode === 'on' || mode === 'true' || mode === 'enable' || mode === 'enabled') enabled = true\n else if (mode === 'off' || mode === 'false' || mode === 'disable' || mode === 'disabled') enabled = false\n\n if (enabled === null) {\n // toggle: read current state and invert.\n const state = (await session.proc.getState()) as any\n const current = Boolean(state?.autoCompactionEnabled)\n enabled = !current\n }\n\n await session.proc.setAutoCompaction(enabled)\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Auto-compaction ${enabled ? 'enabled' : 'disabled'}.`\n }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n }\n\n const result = await session.prompt(message, images)\n\n // ACP StopReason does not include \"error\"; if pi fails we map to end_turn for now,\n // unless we know this was a cancellation.\n const stopReason: StopReason =\n result === 'error' ? (session.wasCancelRequested() ? 'cancelled' : 'end_turn') : result\n\n return { stopReason }\n }\n\n async cancel(params: CancelNotification): Promise<void> {\n const session = this.sessions.get(params.sessionId)\n await session.cancel()\n }\n\n async unstable_listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {\n // ACP: filter by cwd if provided.\n // Zed currently sends `{}` (no cwd), so we default to the last session cwd to\n // emulate pi's `/resume` picker (project-scoped).\n const all = listPiSessions()\n\n const effectiveCwd = (params as any).cwd ?? this.lastSessionCwd\n const filtered = effectiveCwd ? all.filter(s => s.cwd === effectiveCwd) : all\n\n // Cursor-based pagination (opaque cursor). For MVP, we use a simple numeric offset.\n // If cursor is invalid, treat as 0.\n const offset = params.cursor ? Number.parseInt(params.cursor, 10) : 0\n const start = Number.isFinite(offset) && offset > 0 ? offset : 0\n\n const PAGE_SIZE = 50\n const page = filtered.slice(start, start + PAGE_SIZE)\n\n const sessions: SessionInfo[] = page.map(s => ({\n sessionId: s.sessionId,\n cwd: s.cwd,\n title: s.title,\n updatedAt: s.updatedAt\n }))\n\n const nextCursor = start + PAGE_SIZE < filtered.length ? String(start + PAGE_SIZE) : null\n\n return { sessions, nextCursor, _meta: {} }\n }\n\n async loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {\n if (!isAbsolute(params.cwd)) {\n throw RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`)\n }\n\n // If the client is re-loading a session that is already active, tear down the existing\n // pi subprocess so we can start fresh and re-advertise commands reliably.\n // (Some clients may call session/load when restoring from history.)\n this.sessions.close(params.sessionId)\n\n this.lastSessionCwd = params.cwd\n\n // MVP: ignore mcpServers.\n // Prefer ACP-created mapping first (fast path), otherwise scan pi sessions dir.\n const stored = this.store.get(params.sessionId)\n const sessionFile = stored?.sessionFile ?? findPiSessionFile(params.sessionId)\n\n if (!sessionFile) {\n throw RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`)\n }\n\n // Spawn pi and point it directly at the session file.\n let proc: PiRpcProcess\n try {\n proc = await PiRpcProcess.spawn({\n cwd: params.cwd,\n sessionPath: sessionFile,\n piCommand: process.env.PI_ACP_PI_COMMAND\n })\n } catch (e: any) {\n if (e?.name === 'PiRpcSpawnError') {\n throw RequestError.internalError({ code: e?.code }, String(e?.message ?? e))\n }\n throw e\n }\n\n const fileCommands = loadSlashCommands(params.cwd)\n const enableSkillCommands = getEnableSkillCommands(params.cwd)\n\n const session = this.sessions.getOrCreate(params.sessionId, {\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n conn: this.conn,\n proc,\n fileCommands\n })\n\n // Policy: within a single ACP connection (one Zed window), keep only one live pi subprocess.\n // (Tests sometimes stub out `this.sessions`, so guard the call.)\n ;(this.sessions as any).closeAllExcept?.(session.sessionId)\n\n // (Optional) ensure mapping stays fresh.\n this.store.upsert({\n sessionId: params.sessionId,\n cwd: params.cwd,\n sessionFile\n })\n\n // Replay full conversation history.\n const data = (await proc.getMessages()) as any\n const messages = Array.isArray(data?.messages) ? data.messages : []\n\n for (const m of messages) {\n const role = String(m?.role ?? '')\n\n if (role === 'user') {\n const text = normalizePiMessageText(m?.content)\n if (text) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'user_message_chunk',\n content: { type: 'text', text }\n }\n })\n }\n }\n\n if (role === 'assistant') {\n const text = normalizePiAssistantText(m?.content)\n if (text) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n }\n }\n\n if (role === 'toolResult') {\n const toolName = String((m as any)?.toolName ?? 'tool')\n const toolCallId = String((m as any)?.toolCallId ?? crypto.randomUUID())\n const isError = Boolean((m as any)?.isError)\n\n // Create a synthetic ACP tool call to render historic tool usage.\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'tool_call',\n toolCallId,\n title: toolName,\n kind: toolName === 'read' ? 'read' : toolName === 'write' || toolName === 'edit' ? 'edit' : 'other',\n status: 'completed',\n rawInput: null,\n rawOutput: m\n }\n })\n\n const text = toolResultToText(m)\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: isError ? 'failed' : 'completed',\n content: text ? [{ type: 'content', content: { type: 'text', text } }] : null,\n rawOutput: m\n }\n })\n }\n }\n\n const models = await getModelState(proc)\n const thinking = await getThinkingState(proc)\n\n const response = {\n models,\n modes: thinking,\n _meta: {\n piAcp: {\n startupInfo: null\n }\n }\n }\n\n // Advertise slash commands after the response so the client knows the session exists.\n setTimeout(() => {\n void (async () => {\n try {\n const pi = (await proc.getCommands()) as any\n const { commands } = toAvailableCommandsFromPiGetCommands(pi, {\n enableSkillCommands,\n includeExtensionCommands: false\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(commands, builtinAvailableCommands())\n }\n })\n return\n } catch {\n // fall back\n }\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(toAvailableCommands(fileCommands), builtinAvailableCommands())\n }\n })\n })()\n }, 0)\n\n return response\n }\n\n async unstable_setSessionModel(params: { sessionId: string; modelId: string }): Promise<void> {\n const session = this.sessions.get(params.sessionId)\n\n // Accept either:\n // - \"provider/model\" (preferred, matches how we advertise)\n // - \"model\" (fallback, we try to resolve via available models)\n let provider: string | null = null\n let modelId: string | null = null\n\n if (params.modelId.includes('/')) {\n const [p, ...rest] = params.modelId.split('/')\n provider = p\n modelId = rest.join('/')\n } else {\n modelId = params.modelId\n }\n\n if (!provider) {\n const data = (await session.proc.getAvailableModels()) as any\n const models: any[] = Array.isArray(data?.models) ? data.models : []\n const found = models.find(m => String(m?.id) === modelId)\n if (found) {\n provider = String(found.provider)\n modelId = String(found.id)\n }\n }\n\n if (!provider || !modelId) {\n throw RequestError.invalidParams(`Unknown modelId: ${params.modelId}`)\n }\n\n await session.proc.setModel(provider, modelId)\n }\n\n async setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse> {\n const session = this.sessions.get(params.sessionId)\n\n const mode = String(params.modeId)\n if (!isThinkingLevel(mode)) {\n throw RequestError.invalidParams(`Unknown modeId: ${mode}`)\n }\n\n await session.proc.setThinkingLevel(mode)\n\n // Let the client know the current mode changed (keeps the dropdown in sync).\n void this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'current_mode_update',\n currentModeId: mode\n }\n })\n\n return {}\n }\n}\n\nfunction isThinkingLevel(x: string): x is ThinkingLevel {\n return x === 'off' || x === 'minimal' || x === 'low' || x === 'medium' || x === 'high' || x === 'xhigh'\n}\n\nasync function getThinkingState(\n proc: PiRpcProcess,\n pre?: { state?: any | null }\n): Promise<{\n availableModes: Array<{\n id: string\n name: string\n description?: string | null\n }>\n currentModeId: string\n}> {\n // Ask pi for current thinking level.\n let current: ThinkingLevel = 'medium'\n\n const state = pre?.state ?? (await (async () => {\n try {\n return (await proc.getState()) as any\n } catch {\n return null\n }\n })())\n\n const tl = typeof state?.thinkingLevel === 'string' ? state.thinkingLevel : null\n if (tl && isThinkingLevel(tl)) current = tl\n\n const available: ThinkingLevel[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh']\n\n return {\n currentModeId: current,\n availableModes: available.map(id => ({\n id,\n name: `Thinking: ${id}`,\n description: null\n }))\n }\n}\n\nasync function getModelState(\n proc: PiRpcProcess,\n pre?: { state?: any | null; availableModels?: any | null }\n): Promise<{\n availableModels: ModelInfo[]\n currentModelId: string\n} | null> {\n // Ask pi for available models.\n let availableModels: ModelInfo[] = []\n\n const data = pre?.availableModels ?? (await (async () => {\n try {\n return (await proc.getAvailableModels()) as any\n } catch {\n return null\n }\n })())\n\n const models: any[] = Array.isArray(data?.models) ? data.models : []\n availableModels = models\n .map(m => {\n const provider = String(m?.provider ?? '').trim()\n const id = String(m?.id ?? '').trim()\n if (!provider || !id) return null\n\n const name = String(m?.name ?? id)\n return {\n modelId: `${provider}/${id}`,\n name: `${provider}/${name}`,\n description: null\n } satisfies ModelInfo\n })\n .filter(Boolean) as ModelInfo[]\n\n // Ask pi what model is currently active.\n let currentModelId: string | null = null\n\n const state = pre?.state ?? (await (async () => {\n try {\n return (await proc.getState()) as any\n } catch {\n return null\n }\n })())\n\n const model = state?.model\n if (model && typeof model === 'object') {\n const provider = String((model as any).provider ?? '').trim()\n const id = String((model as any).id ?? '').trim()\n if (provider && id) currentModelId = `${provider}/${id}`\n }\n\n if (!availableModels.length && !currentModelId) return null\n\n // Fallback if current model is unknown: use first in list.\n if (!currentModelId) currentModelId = availableModels[0]?.modelId ?? 'default'\n\n return {\n availableModels,\n currentModelId\n }\n}\n\nfunction isSemver(v: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(?:[-+].+)?$/.test(v)\n}\n\nfunction compareSemver(a: string, b: string): number {\n // Very small comparator for x.y.z (ignores pre-release/build beyond making them \"not greater\" unless base differs)\n const pa = a\n .split(/[.-]/)\n .slice(0, 3)\n .map(n => Number(n))\n const pb = b\n .split(/[.-]/)\n .slice(0, 3)\n .map(n => Number(n))\n for (let i = 0; i < 3; i++) {\n const da = pa[i] ?? 0\n const db = pb[i] ?? 0\n if (da > db) return 1\n if (da < db) return -1\n }\n return 0\n}\n\nfunction buildUpdateNotice(): string | null {\n // Best-effort update check against npm registry.\n // Important: keep it fast to not slow down session/new.\n try {\n const piVersion = spawnSync('pi', ['--version'], { encoding: 'utf-8' })\n const installed = String(piVersion.stdout ?? '')\n .trim()\n .replace(/^v/i, '')\n\n if (!installed || !isSemver(installed)) return null\n\n const latestRes = spawnSync('npm', ['view', '@mariozechner/pi-coding-agent', 'version'], {\n encoding: 'utf-8',\n timeout: 800\n })\n const latest = String(latestRes.stdout ?? '')\n .trim()\n .replace(/^v/i, '')\n\n if (!latest || !isSemver(latest)) return null\n if (compareSemver(latest, installed) <= 0) return null\n\n return `New version available: v${latest} (installed v${installed}). Run: \\`npm i -g @mariozechner/pi-coding-agent\\``\n } catch {\n return null\n }\n}\n\nfunction buildStartupInfo(opts: {\n cwd: string\n fileCommands: ReturnType<typeof loadSlashCommands>\n updateNotice: string | null\n}): string {\n void opts.fileCommands\n\n const md: string[] = []\n\n // pi version header\n try {\n const piVersion = spawnSync('pi', ['--version'], { encoding: 'utf-8' })\n const installed = String(piVersion.stdout ?? '')\n .trim()\n .replace(/^v/i, '')\n if (installed) {\n md.push(`pi v${installed}`)\n md.push('---')\n md.push('')\n }\n } catch {\n // ignore\n }\n\n const addSection = (title: string, items: string[]) => {\n const cleaned = items.map(s => s.trim()).filter(Boolean)\n if (!cleaned.length) return\n\n md.push(`## ${title}`)\n for (const item of cleaned) md.push(`- ${item}`)\n md.push('')\n }\n\n // Context\n const contextItems: string[] = []\n const contextPath = join(opts.cwd, 'AGENTS.md')\n if (existsSync(contextPath)) contextItems.push(contextPath)\n addSection('Context', contextItems)\n\n // Skills\n const skillsItems: string[] = []\n\n const pushSkillFromRoot = (root: string) => {\n try {\n // Direct .md files in root\n for (const e of readdirSync(root)) {\n const p = join(root, e)\n try {\n const st = statSync(p)\n if (st.isFile() && e.toLowerCase().endsWith('.md')) {\n skillsItems.push(p)\n }\n } catch {\n // ignore\n }\n }\n\n // Recursive SKILL.md under subdirectories\n const stack: string[] = [root]\n while (stack.length) {\n const dir = stack.pop()!\n let entries: string[] = []\n try {\n entries = readdirSync(dir)\n } catch {\n continue\n }\n\n for (const name of entries) {\n // Skip obvious noise\n if (name === 'node_modules' || name === '.git') continue\n const p = join(dir, name)\n let st\n try {\n st = statSync(p)\n } catch {\n continue\n }\n if (st.isDirectory()) {\n stack.push(p)\n } else if (st.isFile() && name === 'SKILL.md') {\n skillsItems.push(p)\n }\n }\n }\n } catch {\n // ignore\n }\n }\n\n // Global skills\n // Use getAgentDir() so this respects PI_CODING_AGENT_DIR overrides.\n const globalSkillsDir = join(getAgentDir(), 'skills')\n pushSkillFromRoot(globalSkillsDir)\n\n // Also support ~/.agents/skills (pi skill discovery)\n const legacyAgentsSkillsDir = join(process.env.HOME ?? '', '.agents', 'skills')\n pushSkillFromRoot(legacyAgentsSkillsDir)\n\n // Project skills (.pi/skills)\n const projectSkillsDir = join(opts.cwd, '.pi', 'skills')\n pushSkillFromRoot(projectSkillsDir)\n\n addSection('Skills', skillsItems)\n\n // Prompts\n const promptsItems: string[] = []\n const promptsDir = join(process.env.HOME ?? '', '.pi', 'agent', 'prompts')\n try {\n const prompts = readdirSync(promptsDir).filter(f => f.endsWith('.md'))\n for (const f of prompts) promptsItems.push(`/${basename(f, '.md')}`)\n } catch {\n // ignore\n }\n addSection('Prompts', promptsItems)\n\n // Extensions\n const extItems: string[] = []\n const extDir = join(process.env.HOME ?? '', '.pi', 'agent', 'extensions')\n try {\n const exts = readdirSync(extDir).filter(f => f.endsWith('.ts') || f.endsWith('.js'))\n for (const f of exts) extItems.push(join(extDir, f))\n } catch {\n // ignore\n }\n\n // Also show npm packages from pi settings (best-effort)\n try {\n const settingsPath = join(process.env.HOME ?? '', '.pi', 'agent', 'settings.json')\n const settings = JSON.parse(readFileSync(settingsPath, 'utf-8')) as any\n const pkgs: string[] = Array.isArray(settings?.packages) ? settings.packages : []\n for (const pkg of pkgs) {\n const s = String(pkg)\n if (s.startsWith('npm:')) {\n // Render a two-line bullet structure using markdown indentation.\n extItems.push(`${s}\\n - index.ts`)\n } else {\n extItems.push(s)\n }\n }\n } catch {\n // ignore\n }\n\n addSection('Extensions', extItems)\n\n if (opts.updateNotice) {\n md.push('---')\n md.push(opts.updateNotice)\n md.push('')\n }\n\n // Do NOT include themes (per request).\n return md.join('\\n').trim() + '\\n'\n}\n\nfunction readNearestPackageJson(metaUrl: string): {\n name?: string\n version?: string\n} {\n try {\n let dir = dirname(fileURLToPath(metaUrl))\n\n // Walk upwards a few levels to find the nearest package.json\n for (let i = 0; i < 6; i++) {\n const p = join(dir, 'package.json')\n if (existsSync(p)) {\n const json = JSON.parse(readFileSync(p, 'utf-8')) as any\n return { name: json?.name, version: json?.version }\n }\n dir = dirname(dir)\n }\n } catch {\n // ignore\n }\n return { name: 'pi-acp', version: '0.0.0' }\n}\n","import type { AuthMethod } from '@agentclientprotocol/sdk'\n\nexport const PI_SETUP_METHOD_ID = 'pi_terminal_login'\n\n/**\n * Zed (and some other clients) currently support \"Terminal Auth\" via an extension field\n * in AuthMethod._meta, rather than the RFD \"type/args/env\" shape.\n *\n * We include BOTH for maximum compatibility:\n * - `_meta[\"terminal-auth\"]`: used by Zed to render the \"Authenticate\" banner + button.\n * - `type/args/env`: registry-required shape.\n */\nexport function getAuthMethods(opts?: { supportsTerminalAuthMeta?: boolean }): AuthMethod[] {\n const supportsTerminalAuthMeta = opts?.supportsTerminalAuthMeta ?? true\n\n const method: any = {\n id: PI_SETUP_METHOD_ID,\n name: 'Launch pi in the terminal',\n description: 'Start pi in an interactive terminal to configure API keys or login',\n\n // Registry-required fields\n type: 'terminal',\n args: ['--terminal-login'],\n env: {}\n }\n\n if (supportsTerminalAuthMeta) {\n // Best-effort launch spec for Zed's terminal-auth banner.\n // Zed expects a full command+args (see mistral-vibe implementation).\n const launch = terminalAuthLaunchSpec()\n\n method._meta = {\n ...(method._meta ?? {}),\n 'terminal-auth': {\n ...launch,\n label: 'Launch pi'\n }\n }\n }\n\n return [method as AuthMethod]\n}\n\nfunction terminalAuthLaunchSpec(): { command: string; args: string[] } {\n // If we were launched as `node /path/to/dist/index.js`, reuse that.\n // This is the most reliable in local dev and custom Zed configurations.\n const argv0 = process.argv[0] || 'node'\n const argv1 = process.argv[1]\n if (argv1 && argv0) {\n const isNode = argv0.includes('node')\n const isJs = argv1.endsWith('.js')\n if (isNode && isJs) {\n return { command: argv0, args: [argv1, '--terminal-login'] }\n }\n }\n\n // Fallback: assume `pi-acp` is on PATH.\n return { command: 'pi-acp', args: ['--terminal-login'] }\n}\n","import type {\n AgentSideConnection,\n ContentBlock,\n McpServer,\n SessionUpdate,\n ToolCallContent,\n ToolCallLocation,\n ToolKind\n} from '@agentclientprotocol/sdk'\nimport { RequestError } from '@agentclientprotocol/sdk'\nimport { maybeAuthRequiredError } from './auth-required.js'\nimport { readFileSync } from 'node:fs'\nimport { isAbsolute, resolve as resolvePath } from 'node:path'\nimport { PiRpcProcess, PiRpcSpawnError, type PiRpcEvent } from '../pi-rpc/process.js'\nimport { SessionStore } from './session-store.js'\nimport { toolResultToText } from './translate/pi-tools.js'\nimport { expandSlashCommand, type FileSlashCommand } from './slash-commands.js'\n\ntype SessionCreateParams = {\n cwd: string\n mcpServers: McpServer[]\n conn: AgentSideConnection\n fileCommands?: import('./slash-commands.js').FileSlashCommand[]\n piCommand?: string\n}\n\nexport type StopReason = 'end_turn' | 'cancelled' | 'error'\n\ntype PendingTurn = {\n resolve: (reason: StopReason) => void\n reject: (err: unknown) => void\n}\n\ntype QueuedTurn = {\n message: string\n images: unknown[]\n resolve: (reason: StopReason) => void\n reject: (err: unknown) => void\n}\n\nfunction findUniqueLineNumber(text: string, needle: string): number | undefined {\n if (!needle) return undefined\n\n const first = text.indexOf(needle)\n if (first < 0) return undefined\n\n const second = text.indexOf(needle, first + needle.length)\n if (second >= 0) return undefined\n\n let line = 1\n for (let i = 0; i < first; i += 1) {\n if (text.charCodeAt(i) === 10) line += 1\n }\n return line\n}\n\nfunction toToolCallLocations(args: unknown, cwd: string, line?: number): ToolCallLocation[] | undefined {\n const path = typeof (args as { path?: unknown } | null | undefined)?.path === 'string' ? (args as { path: string }).path : undefined\n if (!path) return undefined\n\n const resolvedPath = isAbsolute(path) ? path : resolvePath(cwd, path)\n return [{ path: resolvedPath, ...(typeof line === 'number' ? { line } : {}) }]\n}\n\nexport class SessionManager {\n private sessions = new Map<string, PiAcpSession>()\n private readonly store = new SessionStore()\n\n /** Dispose all sessions and their underlying pi subprocesses. */\n disposeAll(): void {\n for (const [id] of this.sessions) this.close(id)\n }\n\n /** Get a registered session if it exists (no throw). */\n maybeGet(sessionId: string): PiAcpSession | undefined {\n return this.sessions.get(sessionId)\n }\n\n /**\n * Dispose a session's underlying pi process and remove it from the manager.\n * Used when clients explicitly reload a session and we want a fresh pi subprocess.\n */\n close(sessionId: string): void {\n const s = this.sessions.get(sessionId)\n if (!s) return\n try {\n s.proc.dispose?.()\n } catch {\n // ignore\n }\n this.sessions.delete(sessionId)\n }\n\n /** Close all sessions except the one with `keepSessionId`. */\n closeAllExcept(keepSessionId: string): void {\n for (const [id] of this.sessions) {\n if (id === keepSessionId) continue\n this.close(id)\n }\n }\n\n async create(params: SessionCreateParams): Promise<PiAcpSession> {\n // Let pi manage session persistence in its default location (~/.pi/agent/sessions/...)\n // so sessions are visible to the regular `pi` CLI.\n let proc: PiRpcProcess\n try {\n proc = await PiRpcProcess.spawn({\n cwd: params.cwd,\n piCommand: params.piCommand\n })\n } catch (e) {\n if (e instanceof PiRpcSpawnError) {\n throw RequestError.internalError({ code: e.code }, e.message)\n }\n throw e\n }\n\n let state: any = null\n try {\n state = (await proc.getState()) as any\n } catch {\n state = null\n }\n\n const sessionId = typeof state?.sessionId === 'string' ? state.sessionId : crypto.randomUUID()\n const sessionFile = typeof state?.sessionFile === 'string' ? state.sessionFile : null\n\n if (sessionFile) {\n this.store.upsert({ sessionId, cwd: params.cwd, sessionFile })\n }\n\n const session = new PiAcpSession({\n sessionId,\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n proc,\n conn: params.conn,\n fileCommands: params.fileCommands ?? []\n })\n\n this.sessions.set(sessionId, session)\n return session\n }\n\n get(sessionId: string): PiAcpSession {\n const s = this.sessions.get(sessionId)\n if (!s) throw RequestError.invalidParams(`Unknown sessionId: ${sessionId}`)\n return s\n }\n\n /**\n * Used by session/load: create a session object bound to an existing sessionId/proc\n * if it isn't already registered.\n */\n getOrCreate(sessionId: string, params: SessionCreateParams & { proc: PiRpcProcess }): PiAcpSession {\n const existing = this.sessions.get(sessionId)\n if (existing) return existing\n\n const session = new PiAcpSession({\n sessionId,\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n proc: params.proc,\n conn: params.conn,\n fileCommands: params.fileCommands ?? []\n })\n\n this.sessions.set(sessionId, session)\n return session\n }\n}\n\nexport class PiAcpSession {\n readonly sessionId: string\n readonly cwd: string\n readonly mcpServers: McpServer[]\n\n private startupInfo: string | null = null\n private startupInfoSent = false\n\n readonly proc: PiRpcProcess\n private readonly conn: AgentSideConnection\n private readonly fileCommands: FileSlashCommand[]\n\n // Used to map abort semantics to ACP stopReason.\n // Applies to the currently running turn.\n private cancelRequested = false\n\n // Current in-flight turn (if any). Additional prompts are queued.\n private pendingTurn: PendingTurn | null = null\n private readonly turnQueue: QueuedTurn[] = []\n // Track tool call statuses and ensure they are monotonic (pending -> in_progress -> completed).\n // Some pi events can arrive out of order (e.g. late toolcall_* deltas after execution starts),\n // and clients may hide progress if we ever downgrade back to `pending`.\n private currentToolCalls = new Map<string, 'pending' | 'in_progress'>()\n\n // pi can emit multiple `turn_end` events for a single user prompt (e.g. after tool_use).\n // The overall agent loop completes when `agent_end` is emitted.\n private inAgentLoop = false\n\n // For ACP diff support: capture file contents before edits, then emit ToolCallContent {type:\"diff\"}.\n // This is due to pi sending diff as a string as opposed to ACP expected diff format.\n // Compatible format may need to be implemented in pi in the future.\n private editSnapshots = new Map<string, { path: string; oldText: string }>()\n\n // Ensure `session/update` notifications are sent in order and can be awaited\n // before completing a `session/prompt` request.\n private lastEmit: Promise<void> = Promise.resolve()\n\n constructor(opts: {\n sessionId: string\n cwd: string\n mcpServers: McpServer[]\n proc: PiRpcProcess\n conn: AgentSideConnection\n fileCommands?: FileSlashCommand[]\n }) {\n this.sessionId = opts.sessionId\n this.cwd = opts.cwd\n this.mcpServers = opts.mcpServers\n this.proc = opts.proc\n this.conn = opts.conn\n this.fileCommands = opts.fileCommands ?? []\n\n this.proc.onEvent(ev => this.handlePiEvent(ev))\n }\n\n setStartupInfo(text: string) {\n this.startupInfo = text\n }\n\n /**\n * Best-effort attempt to send startup info outside of a prompt turn.\n * Some clients (e.g. Zed) may only render agent messages once the UI is ready;\n * callers can invoke this shortly after session/new returns.\n */\n sendStartupInfoIfPending(): void {\n if (this.startupInfoSent || !this.startupInfo) return\n this.startupInfoSent = true\n\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: this.startupInfo }\n })\n }\n\n async prompt(message: string, images: unknown[] = []): Promise<StopReason> {\n\n // pi RPC mode disables slash command expansion, so we do it here.\n const expandedMessage = expandSlashCommand(message, this.fileCommands)\n\n const turnPromise = new Promise<StopReason>((resolve, reject) => {\n const queued: QueuedTurn = { message: expandedMessage, images, resolve, reject }\n\n // If a turn is already running, enqueue.\n if (this.pendingTurn) {\n this.turnQueue.push(queued)\n\n // Best-effort: notify client that a prompt was queued.\n // This doesn't work in Zed yet, needs to be revisited\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Queued message (position ${this.turnQueue.length}).`\n }\n })\n\n // Also publish queue depth via session info metadata.\n // This also not visible in the client\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: this.turnQueue.length, running: true } }\n })\n\n return\n }\n\n // No turn is running; start immediately.\n this.startTurn(queued)\n })\n\n return turnPromise\n }\n\n async cancel(): Promise<void> {\n // Cancel current and clear any queued prompts.\n this.cancelRequested = true\n\n if (this.turnQueue.length) {\n const queued = this.turnQueue.splice(0, this.turnQueue.length)\n for (const t of queued) t.resolve('cancelled')\n\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: 'Cleared queued prompts.' }\n })\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: 0, running: Boolean(this.pendingTurn) } }\n })\n }\n\n // Abort the currently running turn (if any). If nothing is running, this is a no-op.\n await this.proc.abort()\n }\n\n wasCancelRequested(): boolean {\n return this.cancelRequested\n }\n\n private emit(update: SessionUpdate): void {\n // Serialize update delivery.\n this.lastEmit = this.lastEmit\n .then(() =>\n this.conn.sessionUpdate({\n sessionId: this.sessionId,\n update\n })\n )\n .catch(() => {\n // Ignore notification errors (client may have gone away). We still want\n // prompt completion.\n })\n }\n\n private async flushEmits(): Promise<void> {\n await this.lastEmit\n }\n\n private startTurn(t: QueuedTurn): void {\n this.cancelRequested = false\n this.inAgentLoop = false\n\n this.pendingTurn = { resolve: t.resolve, reject: t.reject }\n\n // Publish queue depth (0 because we're starting the turn now).\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: this.turnQueue.length, running: true } }\n })\n\n // Kick off pi, but completion is determined by pi events, not the RPC response.\n // Important: pi may emit multiple `turn_end` events (e.g. when the model requests tools).\n // The full prompt is finished when we see `agent_end`.\n this.proc.prompt(t.message, t.images).catch(err => {\n // If the subprocess errors before we get an `agent_end`, treat as error unless cancelled.\n // Also ensure we flush any already-enqueued updates first.\n void this.flushEmits().finally(() => {\n // If this looks like an auth/config issue, surface AUTH_REQUIRED so clients can offer terminal login.\n const authErr = maybeAuthRequiredError(err)\n if (authErr) {\n this.pendingTurn?.reject(authErr)\n } else {\n const reason: StopReason = this.cancelRequested ? 'cancelled' : 'error'\n this.pendingTurn?.resolve(reason)\n }\n\n this.pendingTurn = null\n this.inAgentLoop = false\n\n // If the prompt failed, do not automatically proceed—pi may be unhealthy.\n // But we still clear the queueDepth metadata.\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: this.turnQueue.length, running: false } }\n })\n })\n void err\n })\n }\n\n private handlePiEvent(ev: PiRpcEvent) {\n const type = String((ev as any).type ?? '')\n\n switch (type) {\n case 'message_update': {\n const ame = (ev as any).assistantMessageEvent\n\n // Stream assistant text.\n if (ame?.type === 'text_delta' && typeof ame.delta === 'string') {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: ame.delta } satisfies ContentBlock\n })\n break\n }\n\n if (ame?.type === 'thinking_delta' && typeof ame.delta === 'string') {\n this.emit({\n sessionUpdate: 'agent_thought_chunk',\n content: { type: 'text', text: ame.delta } satisfies ContentBlock\n })\n break\n }\n\n // Surface tool calls ASAP so clients (e.g. Zed) can show a tool-in-use/loading UI\n // while the model is still streaming tool call args.\n if (ame?.type === 'toolcall_start' || ame?.type === 'toolcall_delta' || ame?.type === 'toolcall_end') {\n const toolCall =\n // pi sometimes includes the tool call directly on the event\n (ame as any)?.toolCall ??\n // ...and always includes it in the partial assistant message at contentIndex\n (ame as any)?.partial?.content?.[(ame as any)?.contentIndex ?? 0]\n\n const toolCallId = String((toolCall as any)?.id ?? '')\n const toolName = String((toolCall as any)?.name ?? 'tool')\n\n if (toolCallId) {\n const rawInput =\n (toolCall as any)?.arguments && typeof (toolCall as any).arguments === 'object'\n ? (toolCall as any).arguments\n : (() => {\n const s = String((toolCall as any)?.partialArgs ?? '')\n if (!s) return undefined\n try {\n return JSON.parse(s)\n } catch {\n return { partialArgs: s }\n }\n })()\n\n const locations = toToolCallLocations(rawInput, this.cwd)\n const existingStatus = this.currentToolCalls.get(toolCallId)\n // IMPORTANT: never downgrade status (e.g. if we already marked in_progress via tool_execution_start).\n const status = existingStatus ?? 'pending'\n\n if (!existingStatus) {\n this.currentToolCalls.set(toolCallId, 'pending')\n this.emit({\n sessionUpdate: 'tool_call',\n toolCallId,\n title: toolName,\n kind: toToolKind(toolName),\n status,\n locations,\n rawInput\n })\n } else {\n // Best-effort: keep rawInput updated while args are streaming.\n // Keep the existing status (pending or in_progress).\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status,\n locations,\n rawInput\n })\n }\n }\n\n break\n }\n\n // Ignore other delta/event types for now.\n break\n }\n\n case 'tool_execution_start': {\n const toolCallId = String((ev as any).toolCallId ?? crypto.randomUUID())\n const toolName = String((ev as any).toolName ?? 'tool')\n const args = (ev as any).args\n let line: number | undefined\n\n // Capture pre-edit file contents so we can emit a structured ACP diff on completion.\n if (toolName === 'edit') {\n const p = typeof args?.path === 'string' ? args.path : undefined\n if (p) {\n try {\n const abs = isAbsolute(p) ? p : resolvePath(this.cwd, p)\n const oldText = readFileSync(abs, 'utf8')\n this.editSnapshots.set(toolCallId, { path: p, oldText })\n\n const needle = typeof args?.oldText === 'string' ? args.oldText : ''\n line = findUniqueLineNumber(oldText, needle)\n } catch {\n // Ignore snapshot failures; we'll fall back to plain text output.\n }\n }\n }\n\n const locations = toToolCallLocations(args, this.cwd, line)\n\n // If we already surfaced the tool call while the model streamed it, just transition.\n if (!this.currentToolCalls.has(toolCallId)) {\n this.currentToolCalls.set(toolCallId, 'in_progress')\n this.emit({\n sessionUpdate: 'tool_call',\n toolCallId,\n title: toolName,\n kind: toToolKind(toolName),\n status: 'in_progress',\n locations,\n rawInput: args\n })\n } else {\n this.currentToolCalls.set(toolCallId, 'in_progress')\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: 'in_progress',\n locations,\n rawInput: args\n })\n }\n\n break\n }\n\n case 'tool_execution_update': {\n const toolCallId = String((ev as any).toolCallId ?? '')\n if (!toolCallId) break\n\n const partial = (ev as any).partialResult\n const text = toolResultToText(partial)\n\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: 'in_progress',\n content: text\n ? ([{ type: 'content', content: { type: 'text', text } }] satisfies ToolCallContent[])\n : undefined,\n rawOutput: partial\n })\n break\n }\n\n case 'tool_execution_end': {\n const toolCallId = String((ev as any).toolCallId ?? '')\n if (!toolCallId) break\n\n const result = (ev as any).result\n const isError = Boolean((ev as any).isError)\n const text = toolResultToText(result)\n\n // If this was an edit and we captured a snapshot, emit a structured ACP diff.\n // This enables clients like Zed to render an actual diff UI.\n const snapshot = this.editSnapshots.get(toolCallId)\n let content: ToolCallContent[] | undefined\n\n if (!isError && snapshot) {\n try {\n const abs = isAbsolute(snapshot.path) ? snapshot.path : resolvePath(this.cwd, snapshot.path)\n const newText = readFileSync(abs, 'utf8')\n if (newText !== snapshot.oldText) {\n content = [\n {\n type: 'diff',\n path: snapshot.path,\n oldText: snapshot.oldText,\n newText\n },\n ...(text ? ([{ type: 'content', content: { type: 'text', text } }] as ToolCallContent[]) : [])\n ]\n }\n } catch {\n // ignore; fall back to text only\n }\n }\n\n // Fallback: just text content.\n if (!content && text) {\n content = [{ type: 'content', content: { type: 'text', text } }] satisfies ToolCallContent[]\n }\n\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: isError ? 'failed' : 'completed',\n content,\n rawOutput: result\n })\n\n this.currentToolCalls.delete(toolCallId)\n this.editSnapshots.delete(toolCallId)\n break\n }\n\n case 'agent_start': {\n this.inAgentLoop = true\n break\n }\n\n case 'turn_end': {\n // pi uses `turn_end` for sub-steps (e.g. tool_use) and will often start another turn.\n // Do NOT resolve the ACP `session/prompt` here; wait for `agent_end`.\n break\n }\n\n case 'agent_end': {\n // Ensure all updates derived from pi events are delivered before we resolve\n // the ACP `session/prompt` request.\n void this.flushEmits().finally(() => {\n const reason: StopReason = this.cancelRequested ? 'cancelled' : 'end_turn'\n this.pendingTurn?.resolve(reason)\n this.pendingTurn = null\n this.inAgentLoop = false\n\n // Start next queued prompt, if any.\n const next = this.turnQueue.shift()\n if (next) {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Starting queued message. (${this.turnQueue.length} remaining)` }\n })\n this.startTurn(next)\n } else {\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: 0, running: false } }\n })\n }\n })\n break\n }\n\n default:\n break\n }\n }\n}\n\nfunction toToolKind(toolName: string): ToolKind {\n switch (toolName) {\n case 'read':\n return 'read'\n case 'write':\n case 'edit':\n return 'edit'\n case 'bash':\n // Many ACP clients render `execute` tool calls only via the terminal APIs.\n // Since this adapter lets pi execute locally (no client terminal delegation),\n // we report bash as `other` so clients show inline text output blocks.\n return 'other'\n default:\n return 'other'\n }\n}\n","import { RequestError } from '@agentclientprotocol/sdk'\nimport { getAuthMethods } from './auth.js'\n\n/**\n * Best-effort detection of missing credentials / not-configured errors from pi/providers.\n *\n * We can't do a full provider-specific check here, so we look for common substrings.\n */\nexport function maybeAuthRequiredError(err: unknown): RequestError | null {\n const msg = String((err as any)?.message ?? err ?? '')\n const s = msg.toLowerCase()\n\n const patterns = [\n 'api key',\n 'apikey',\n 'missing key',\n 'no key',\n 'not configured',\n 'unauthorized',\n 'authentication',\n 'permission denied',\n 'forbidden',\n '401',\n '403'\n ]\n\n const hit = patterns.some(p => s.includes(p))\n if (!hit) return null\n\n // Include terminal auth method options in error data.\n return RequestError.authRequired(\n {\n authMethods: getAuthMethods()\n },\n 'Configure an API key or log in with an OAuth provider.'\n )\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport * as readline from 'node:readline'\nimport { platform } from 'node:os'\n\nexport class PiRpcSpawnError extends Error {\n /** Underlying spawn error code, e.g. ENOENT, EACCES */\n code?: string\n\n constructor(message: string, opts?: { code?: string; cause?: unknown }) {\n super(message)\n this.name = 'PiRpcSpawnError'\n this.code = opts?.code\n ;(this as any).cause = opts?.cause\n }\n}\n\nconst ESC = String.fromCharCode(0x1b)\nconst CSI = String.fromCharCode(0x9b)\n\nconst ANSI_ESCAPE_REGEX = new RegExp(\n `[${ESC}${CSI}][[\\\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]`,\n 'g'\n)\n\nfunction stripAnsi(s: string): string {\n // Basic ANSI escape stripping (colors, cursor movement, etc.)\n return s.replace(ANSI_ESCAPE_REGEX, '')\n}\n\ntype PiRpcCommand =\n | { type: 'prompt'; id?: string; message: string; images?: unknown[] }\n | { type: 'abort'; id?: string }\n | { type: 'get_state'; id?: string }\n // Model\n | { type: 'get_available_models'; id?: string }\n | { type: 'set_model'; id?: string; provider: string; modelId: string }\n // Thinking\n | { type: 'set_thinking_level'; id?: string; level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' }\n // Modes\n | { type: 'set_follow_up_mode'; id?: string; mode: 'all' | 'one-at-a-time' }\n | { type: 'set_steering_mode'; id?: string; mode: 'all' | 'one-at-a-time' }\n // Compaction\n | { type: 'compact'; id?: string; customInstructions?: string }\n | { type: 'set_auto_compaction'; id?: string; enabled: boolean }\n // Session\n | { type: 'get_session_stats'; id?: string }\n | { type: 'set_session_name'; id?: string; name: string }\n | { type: 'export_html'; id?: string; outputPath?: string }\n | { type: 'switch_session'; id?: string; sessionPath: string }\n // Messages\n | { type: 'get_messages'; id?: string }\n // Commands\n | { type: 'get_commands'; id?: string }\n\ntype PiRpcResponse = {\n type: 'response'\n id?: string\n command: string\n success: boolean\n data?: unknown\n error?: string\n}\n\nexport type PiRpcEvent = Record<string, unknown>\n\ntype SpawnParams = {\n cwd: string\n /** Optional override for `pi` executable name/path */\n piCommand?: string\n /** If set, pi will persist the session to this exact file (via `--session <path>`). */\n sessionPath?: string\n}\n\nexport class PiRpcProcess {\n private readonly child: ChildProcessWithoutNullStreams\n private readonly pending = new Map<string, { resolve: (v: PiRpcResponse) => void; reject: (e: unknown) => void }>()\n private eventHandlers: Array<(ev: PiRpcEvent) => void> = []\n private readonly preludeLines: string[] = []\n\n private constructor(child: ChildProcessWithoutNullStreams) {\n this.child = child\n\n const rl = readline.createInterface({ input: child.stdout })\n rl.on('line', line => {\n if (!line.trim()) return\n let msg: any\n try {\n msg = JSON.parse(line)\n } catch {\n // pi may emit a human-readable prelude on stdout before NDJSON starts.\n // Capture it so the ACP adapter can surface it on session start.\n const cleaned = stripAnsi(String(line)).trimEnd()\n if (cleaned) this.preludeLines.push(cleaned)\n return\n }\n\n if (msg?.type === 'response') {\n const id = typeof msg.id === 'string' ? msg.id : undefined\n if (id) {\n const pending = this.pending.get(id)\n if (pending) {\n this.pending.delete(id)\n pending.resolve(msg as PiRpcResponse)\n return\n }\n }\n }\n\n for (const h of this.eventHandlers) h(msg as PiRpcEvent)\n })\n\n child.on('exit', (code, signal) => {\n const err = new Error(`pi process exited (code=${code}, signal=${signal})`)\n for (const [, p] of this.pending) p.reject(err)\n this.pending.clear()\n })\n\n child.on('error', err => {\n for (const [, p] of this.pending) p.reject(err)\n this.pending.clear()\n })\n }\n\n static async spawn(params: SpawnParams): Promise<PiRpcProcess> {\n const isWindows = platform() === 'win32'\n // On Windows, npm creates pi.cmd; use explicit extension to avoid ENOENT\n const cmd = params.piCommand ?? (isWindows ? 'pi.cmd' : 'pi')\n\n // Speed/robustness for ACP:\n // - themes are irrelevant in rpc mode and can be noisy/slow to load.\n // Keep extensions + prompt templates enabled because ACP users may rely on them\n // (e.g. MCP extensions, prompt templates for workflows).\n const args = ['--mode', 'rpc', '--no-themes']\n if (params.sessionPath) args.push('--session', params.sessionPath)\n\n const child = spawn(cmd, args, {\n cwd: params.cwd,\n stdio: 'pipe',\n env: process.env\n })\n\n // Ensure spawn failures (e.g. ENOENT when pi isn't installed) are surfaced as a\n // deterministic error instead of later EPIPE/internal-error noise.\n try {\n await new Promise<void>((resolve, reject) => {\n const onSpawn = () => {\n cleanup()\n resolve()\n }\n const onError = (err: any) => {\n cleanup()\n reject(err)\n }\n const cleanup = () => {\n child.off('spawn', onSpawn)\n child.off('error', onError)\n }\n\n child.once('spawn', onSpawn)\n child.once('error', onError)\n })\n } catch (e: any) {\n const code = typeof e?.code === 'string' ? e.code : undefined\n if (code === 'ENOENT') {\n throw new PiRpcSpawnError(\n `Could not start pi: executable not found (command: ${cmd}). Pi needs to be installed before it can run in ACP clients. Install it via \\`npm install -g @mariozechner/pi-coding-agent\\` or ensure \\`pi\\` is on your PATH. Then try again.`,\n { code, cause: e }\n )\n }\n\n if (code === 'EACCES') {\n throw new PiRpcSpawnError(`Could not start pi: permission denied (command: ${cmd}).`, { code, cause: e })\n }\n\n throw new PiRpcSpawnError(`Could not start pi (command: ${cmd}).`, { code, cause: e })\n }\n\n child.stderr.on('data', () => {\n // leave stderr untouched; ACP clients may capture it.\n })\n\n const proc = new PiRpcProcess(child)\n\n // Best-effort handshake.\n // Important: pi may emit a get_state response pointing at a sessionFile in a directory\n // that is created lazily. Create the parent dir up-front to avoid later parse errors\n // when we call commands like export_html.\n try {\n const state = (await proc.getState()) as any\n const sessionFile = typeof state?.sessionFile === 'string' ? state.sessionFile : null\n if (sessionFile) {\n const { mkdirSync } = await import('node:fs')\n const { dirname } = await import('node:path')\n mkdirSync(dirname(sessionFile), { recursive: true })\n }\n } catch {\n // ignore for now\n }\n\n return proc\n }\n\n onEvent(handler: (ev: PiRpcEvent) => void): () => void {\n this.eventHandlers.push(handler)\n return () => {\n this.eventHandlers = this.eventHandlers.filter(h => h !== handler)\n }\n }\n\n dispose(signal: NodeJS.Signals | number = 'SIGTERM'): void {\n if (this.child.killed) return\n try {\n this.child.kill(signal as any)\n } catch {\n // ignore\n }\n }\n\n /**\n * Human-readable stdout lines emitted before RPC NDJSON begins (e.g. Context/Skills/Extensions info).\n * Themes are typically noisy/less useful for ACP, so callers can filter as needed.\n */\n consumePreludeLines(): string[] {\n const lines = this.preludeLines.splice(0, this.preludeLines.length)\n return lines\n }\n\n async prompt(message: string, images: unknown[] = []): Promise<void> {\n const res = await this.request({ type: 'prompt', message, images })\n if (!res.success) throw new Error(`pi prompt failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async abort(): Promise<void> {\n const res = await this.request({ type: 'abort' })\n if (!res.success) throw new Error(`pi abort failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async getState(): Promise<unknown> {\n const res = await this.request({ type: 'get_state' })\n if (!res.success) throw new Error(`pi get_state failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async getAvailableModels(): Promise<unknown> {\n const res = await this.request({ type: 'get_available_models' })\n if (!res.success) throw new Error(`pi get_available_models failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setModel(provider: string, modelId: string): Promise<unknown> {\n const res = await this.request({ type: 'set_model', provider, modelId })\n if (!res.success) throw new Error(`pi set_model failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setThinkingLevel(level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'): Promise<void> {\n const res = await this.request({ type: 'set_thinking_level', level })\n if (!res.success) throw new Error(`pi set_thinking_level failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async setFollowUpMode(mode: 'all' | 'one-at-a-time'): Promise<void> {\n const res = await this.request({ type: 'set_follow_up_mode', mode })\n if (!res.success) throw new Error(`pi set_follow_up_mode failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async setSteeringMode(mode: 'all' | 'one-at-a-time'): Promise<void> {\n const res = await this.request({ type: 'set_steering_mode', mode })\n if (!res.success) throw new Error(`pi set_steering_mode failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async compact(customInstructions?: string): Promise<unknown> {\n const res = await this.request({ type: 'compact', customInstructions })\n if (!res.success) throw new Error(`pi compact failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setAutoCompaction(enabled: boolean): Promise<void> {\n const res = await this.request({ type: 'set_auto_compaction', enabled })\n if (!res.success) throw new Error(`pi set_auto_compaction failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async getSessionStats(): Promise<unknown> {\n const res = await this.request({ type: 'get_session_stats' })\n if (!res.success) throw new Error(`pi get_session_stats failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setSessionName(name: string): Promise<void> {\n const res = await this.request({ type: 'set_session_name', name })\n if (!res.success) throw new Error(`pi set_session_name failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async exportHtml(outputPath?: string): Promise<{ path: string }> {\n const res = await this.request({ type: 'export_html', outputPath })\n if (!res.success) throw new Error(`pi export_html failed: ${res.error ?? JSON.stringify(res.data)}`)\n const data: any = res.data\n return { path: String(data?.path ?? '') }\n }\n\n async switchSession(sessionPath: string): Promise<void> {\n const res = await this.request({ type: 'switch_session', sessionPath })\n if (!res.success) throw new Error(`pi switch_session failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async getMessages(): Promise<unknown> {\n const res = await this.request({ type: 'get_messages' })\n if (!res.success) throw new Error(`pi get_messages failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async getCommands(): Promise<unknown> {\n const res = await this.request({ type: 'get_commands' })\n if (!res.success) throw new Error(`pi get_commands failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n private request(cmd: PiRpcCommand): Promise<PiRpcResponse> {\n const id = crypto.randomUUID()\n const withId = { ...cmd, id }\n\n const line = JSON.stringify(withId) + '\\n'\n\n return new Promise<PiRpcResponse>((resolve, reject) => {\n this.pending.set(id, { resolve, reject })\n\n try {\n this.child.stdin.write(line, err => {\n if (err) {\n this.pending.delete(id)\n reject(err)\n }\n })\n } catch (e) {\n this.pending.delete(id)\n reject(e)\n }\n })\n }\n}\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { getPiAcpSessionMapPath } from './paths.js'\n\nexport type StoredSession = {\n sessionId: string\n cwd: string\n sessionFile: string\n updatedAt: string\n}\n\ntype SessionMapFile = {\n version: 1\n sessions: Record<string, StoredSession>\n}\n\nfunction ensureParentDir(path: string) {\n mkdirSync(dirname(path), { recursive: true })\n}\n\nfunction loadFile(path: string): SessionMapFile {\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as SessionMapFile\n if (parsed?.version !== 1 || typeof parsed.sessions !== 'object' || !parsed.sessions) {\n return { version: 1, sessions: {} }\n }\n return parsed\n } catch {\n return { version: 1, sessions: {} }\n }\n}\n\nfunction saveFile(path: string, data: SessionMapFile): void {\n ensureParentDir(path)\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf-8')\n}\n\nexport class SessionStore {\n private readonly path: string\n\n constructor(path = getPiAcpSessionMapPath()) {\n this.path = path\n }\n\n get(sessionId: string): StoredSession | null {\n const db = loadFile(this.path)\n return db.sessions[sessionId] ?? null\n }\n\n upsert(entry: { sessionId: string; cwd: string; sessionFile: string }): void {\n const db = loadFile(this.path)\n db.sessions[entry.sessionId] = {\n sessionId: entry.sessionId,\n cwd: entry.cwd,\n sessionFile: entry.sessionFile,\n updatedAt: new Date().toISOString()\n }\n saveFile(this.path, db)\n }\n}\n","import { homedir } from 'node:os'\nimport { join } from 'node:path'\n\n/**\n * Storage owned by the ACP adapter.\n *\n * We intentionally keep this separate from pi's own ~/.pi/agent/* directory.\n */\nexport function getPiAcpDir(): string {\n return join(homedir(), '.pi', 'pi-acp')\n}\n\nexport function getPiAcpSessionMapPath(): string {\n return join(getPiAcpDir(), 'session-map.json')\n}\n","export function toolResultToText(result: unknown): string {\n if (!result) return ''\n\n // pi tool results generally look like: { content: [{type:\"text\", text:\"...\"}], details: {...} }\n const content = (result as any).content\n if (Array.isArray(content)) {\n const texts = content\n .map((c: any) => (c?.type === 'text' && typeof c.text === 'string' ? c.text : ''))\n .filter(Boolean)\n if (texts.length) return texts.join('')\n }\n\n const details = (result as any)?.details\n\n // Some pi tools return a unified diff in `details.diff`.\n const diff = details?.diff\n if (typeof diff === 'string' && diff.trim()) {\n return diff\n }\n\n // The bash tool frequently returns stdout/stderr in `details` rather than content blocks.\n const stdout =\n (typeof details?.stdout === 'string' ? details.stdout : undefined) ??\n (typeof (result as any)?.stdout === 'string' ? (result as any).stdout : undefined) ??\n (typeof details?.output === 'string' ? details.output : undefined) ??\n (typeof (result as any)?.output === 'string' ? (result as any).output : undefined)\n\n const stderr =\n (typeof details?.stderr === 'string' ? details.stderr : undefined) ??\n (typeof (result as any)?.stderr === 'string' ? (result as any).stderr : undefined)\n\n const exitCode =\n (typeof details?.exitCode === 'number' ? details.exitCode : undefined) ??\n (typeof (result as any)?.exitCode === 'number' ? (result as any).exitCode : undefined) ??\n (typeof details?.code === 'number' ? details.code : undefined) ??\n (typeof (result as any)?.code === 'number' ? (result as any).code : undefined)\n\n if ((typeof stdout === 'string' && stdout.trim()) || (typeof stderr === 'string' && stderr.trim())) {\n const parts: string[] = []\n if (typeof stdout === 'string' && stdout.trim()) parts.push(stdout)\n if (typeof stderr === 'string' && stderr.trim()) parts.push(`stderr:\\n${stderr}`)\n if (typeof exitCode === 'number') parts.push(`exit code: ${exitCode}`)\n return parts.join('\\n\\n').trimEnd()\n }\n\n try {\n return JSON.stringify(result, null, 2)\n } catch {\n return String(result)\n }\n}\n","import { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport type { AvailableCommand } from '@agentclientprotocol/sdk'\n\n/**\n * File-based slash command (mirrors pi-coding-agent semantics).\n */\nexport type FileSlashCommand = {\n name: string\n description: string\n content: string\n source: string // e.g. \"(user)\", \"(project)\", \"(project:frontend)\"\n}\n\nfunction parseFrontmatter(content: string): {\n frontmatter: Record<string, string>\n content: string\n} {\n const frontmatter: Record<string, string> = {}\n\n if (!content.startsWith('---')) return { frontmatter, content }\n\n const endIndex = content.indexOf('\\n---', 3)\n if (endIndex === -1) return { frontmatter, content }\n\n const frontmatterBlock = content.slice(4, endIndex)\n const remaining = content.slice(endIndex + 4).trim()\n\n for (const line of frontmatterBlock.split('\\n')) {\n const match = line.match(/^(\\w+):\\s*(.*)$/)\n if (match) frontmatter[match[1]] = match[2].trim()\n }\n\n return { frontmatter, content: remaining }\n}\n\nfunction loadCommandsFromDir(dir: string, source: 'user' | 'project', subdir = ''): FileSlashCommand[] {\n const commands: FileSlashCommand[] = []\n if (!existsSync(dir)) return commands\n\n try {\n const entries = readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n\n if (entry.isDirectory()) {\n const newSubdir = subdir ? `${subdir}:${entry.name}` : entry.name\n commands.push(...loadCommandsFromDir(fullPath, source, newSubdir))\n continue\n }\n\n if (!entry.isFile() || !entry.name.endsWith('.md')) continue\n\n try {\n const rawContent = readFileSync(fullPath, 'utf-8')\n const { frontmatter, content } = parseFrontmatter(rawContent)\n\n const name = entry.name.slice(0, -3)\n\n const sourceStr =\n source === 'user' ? (subdir ? `(user:${subdir})` : '(user)') : subdir ? `(project:${subdir})` : '(project)'\n\n let description = frontmatter.description || ''\n if (!description) {\n const firstLine = content.split('\\n').find(l => l.trim())\n if (firstLine) {\n description = firstLine.slice(0, 60)\n if (firstLine.length > 60) description += '...'\n }\n }\n\n description = description ? `${description} ${sourceStr}` : sourceStr\n\n commands.push({\n name,\n description,\n content,\n source: sourceStr\n })\n } catch {\n // Silently skip unreadable files.\n }\n }\n } catch {\n // Silently skip unreadable dirs.\n }\n\n return commands\n}\n\n/**\n * Load prompt templates from pi's prompt directories (formerly \"commands\").\n * - user: ~/.pi/agent/prompts/**\\/*.md\n * - project: <cwd>/.pi/prompts/**\\/*.md\n */\nexport function loadSlashCommands(cwd: string): FileSlashCommand[] {\n const commands: FileSlashCommand[] = []\n\n const userDir = join(homedir(), '.pi', 'agent', 'prompts')\n const projectDir = resolve(cwd, '.pi', 'prompts')\n\n // Match pi ordering: user first, then project.\n commands.push(...loadCommandsFromDir(userDir, 'user'))\n commands.push(...loadCommandsFromDir(projectDir, 'project'))\n\n return commands\n}\n\n/**\n * Convert file-based commands to ACP AvailableCommand objects.\n * De-dupes by name (first wins).\n */\nexport function toAvailableCommands(fileCommands: FileSlashCommand[]): AvailableCommand[] {\n const seen = new Set<string>()\n const out: AvailableCommand[] = []\n\n for (const c of fileCommands) {\n if (seen.has(c.name)) continue\n seen.add(c.name)\n\n out.push({\n name: c.name,\n description: c.description\n // input: omitted for now (pi commands don't specify this)\n })\n }\n\n return out\n}\n\n/**\n * Parse command args (bash-style quotes).\n */\nexport function parseCommandArgs(argsString: string): string[] {\n const args: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (let i = 0; i < argsString.length; i++) {\n const ch = argsString[i]\n\n if (inQuote) {\n if (ch === inQuote) inQuote = null\n else current += ch\n continue\n }\n\n if (ch === '\"' || ch === \"'\") {\n inQuote = ch\n } else if (ch === ' ' || ch === '\\t') {\n if (current) {\n args.push(current)\n current = ''\n }\n } else {\n current += ch\n }\n }\n\n if (current) args.push(current)\n return args\n}\n\n/**\n * Substitute $1, $2, ... and $@.\n */\nexport function substituteArgs(content: string, args: string[]): string {\n let result = content\n\n result = result.replace(/\\$@/g, args.join(' '))\n result = result.replace(/\\$(\\d+)/g, (_m, num) => {\n const idx = Number.parseInt(String(num), 10) - 1\n return args[idx] ?? ''\n })\n\n return result\n}\n\n/**\n * Expand a leading /command using the loaded file commands.\n * Returns original text if it's not a known slash command.\n */\nexport function expandSlashCommand(text: string, fileCommands: FileSlashCommand[]): string {\n if (!text.startsWith('/')) return text\n\n const spaceIndex = text.indexOf(' ')\n const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex)\n const argsString = spaceIndex === -1 ? '' : text.slice(spaceIndex + 1)\n\n const cmd = fileCommands.find(c => c.name === commandName)\n if (!cmd) return text\n\n const args = parseCommandArgs(argsString)\n return substituteArgs(cmd.content, args)\n}\n","import { readdirSync, readFileSync, statSync, openSync, readSync, closeSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type PiSessionListItem = {\n sessionId: string\n cwd: string\n title: string | null\n updatedAt: string | null\n sessionFile: string\n}\n\nconst DEFAULT_TAIL_BYTES = 256 * 1024\nconst DEFAULT_HEAD_BYTES = 64 * 1024\n\nfunction getPiAgentDir(): string {\n // pi supports overriding config dir via PI_CODING_AGENT_DIR.\n // See pi README.\n return process.env.PI_CODING_AGENT_DIR ?? join(homedir(), '.pi', 'agent')\n}\n\nexport function getPiSessionsDir(): string {\n return join(getPiAgentDir(), 'sessions')\n}\n\nfunction walkJsonlFiles(dir: string, out: string[]) {\n let entries: import('node:fs').Dirent[]\n try {\n // Force string names.\n entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' }) as unknown as import('node:fs').Dirent[]\n } catch {\n return\n }\n\n for (const e of entries) {\n const name = typeof (e as any).name === 'string' ? (e as any).name : String((e as any).name)\n const p = join(dir, name)\n if (e.isDirectory()) walkJsonlFiles(p, out)\n else if (e.isFile() && name.endsWith('.jsonl')) out.push(p)\n }\n}\n\nfunction readFirstLine(path: string): string | null {\n // Avoid reading the whole file.\n const fd = openSync(path, 'r')\n try {\n const buf = Buffer.alloc(DEFAULT_HEAD_BYTES)\n const n = readSync(fd, buf, 0, buf.length, 0)\n if (n <= 0) return null\n const s = buf.subarray(0, n).toString('utf-8')\n const idx = s.indexOf('\\n')\n return idx === -1 ? s.trim() : s.slice(0, idx).trim()\n } catch {\n return null\n } finally {\n try {\n closeSync(fd)\n } catch {\n // ignore\n }\n }\n}\n\nfunction readTail(path: string, tailBytes = DEFAULT_TAIL_BYTES): string {\n const st = statSync(path)\n const start = Math.max(0, st.size - tailBytes)\n const len = st.size - start\n\n const fd = openSync(path, 'r')\n try {\n const buf = Buffer.alloc(len)\n const n = readSync(fd, buf, 0, buf.length, start)\n return buf.subarray(0, n).toString('utf-8')\n } finally {\n try {\n closeSync(fd)\n } catch {\n // ignore\n }\n }\n}\n\nfunction parseSessionHeader(firstLine: string): { sessionId: string; cwd: string } | null {\n try {\n const obj = JSON.parse(firstLine) as any\n if (obj?.type !== 'session') return null\n const sessionId = typeof obj?.id === 'string' ? obj.id : null\n const cwd = typeof obj?.cwd === 'string' ? obj.cwd : null\n if (!sessionId || !cwd) return null\n return { sessionId, cwd }\n } catch {\n return null\n }\n}\n\nfunction pickTitleFromTail(tail: string): string | null {\n // Try to find the *latest* session_info entry (stores the user-provided name).\n // We scan backwards line-by-line.\n const lines = tail.split(/\\r?\\n/)\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type === 'session_info' && typeof obj?.name === 'string' && obj.name.trim()) {\n return obj.name.trim()\n }\n } catch {\n // ignore\n }\n }\n return null\n}\n\nfunction scanSessionInfoNameFromFile(path: string): string | null {\n // Fallback when the session_info entry is older than our tail window.\n // Scan the whole file line-by-line and remember the last session_info.name.\n const fd = openSync(path, 'r')\n try {\n const buf = Buffer.alloc(256 * 1024)\n let leftover = ''\n let offset = 0\n let lastName: string | null = null\n\n while (true) {\n const n = readSync(fd, buf, 0, buf.length, offset)\n if (n <= 0) break\n offset += n\n\n const chunk = leftover + buf.subarray(0, n).toString('utf8')\n const lines = chunk.split(/\\r?\\n/)\n leftover = lines.pop() ?? ''\n\n for (const line0 of lines) {\n const line = line0.trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type === 'session_info' && typeof obj?.name === 'string' && obj.name.trim()) {\n lastName = obj.name.trim()\n }\n } catch {\n // ignore\n }\n }\n }\n\n // Best-effort: parse leftover if it was a full line without trailing newline.\n const tailLine = leftover.trim()\n if (tailLine) {\n try {\n const obj = JSON.parse(tailLine) as any\n if (obj?.type === 'session_info' && typeof obj?.name === 'string' && obj.name.trim()) {\n lastName = obj.name.trim()\n }\n } catch {\n // ignore\n }\n }\n\n return lastName\n } catch {\n return null\n } finally {\n try {\n closeSync(fd)\n } catch {\n // ignore\n }\n }\n}\n\nfunction pickUpdatedAtFromTail(tail: string): string | null {\n // pi's `/resume` effectively orders sessions by last *message* activity.\n // We scan backwards and pick the timestamp of the most recent entry with type === \"message\".\n const lines = tail.split(/\\r?\\n/)\n\n // 1) Prefer the most recent message entry.\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type !== 'message') continue\n const ts = typeof obj?.timestamp === 'string' ? obj.timestamp : null\n if (!ts) continue\n const d = new Date(ts)\n if (Number.isFinite(d.getTime())) return d.toISOString()\n } catch {\n // ignore\n }\n }\n\n // 2) Fallback: any valid timestamp (covers sessions that somehow have no messages).\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n const ts = typeof obj?.timestamp === 'string' ? obj.timestamp : null\n if (!ts) continue\n const d = new Date(ts)\n if (Number.isFinite(d.getTime())) return d.toISOString()\n } catch {\n // ignore\n }\n }\n\n return null\n}\n\nfunction pickFallbackTitleFromHead(path: string): string | null {\n // Fallback to first user message.\n // NOTE: we keep this simple: read a small head chunk and parse line-by-line.\n try {\n const raw = readFileSync(path, { encoding: 'utf8' })\n const lines = raw.split(/\\r?\\n/)\n for (const line0 of lines) {\n const line = line0.trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type === 'message' && obj?.message?.role === 'user') {\n const content = obj?.message?.content\n if (typeof content === 'string') return content.slice(0, 80)\n if (Array.isArray(content)) {\n const t = content.find((c: any) => c?.type === 'text' && typeof c?.text === 'string')\n if (t?.text) return String(t.text).slice(0, 80)\n }\n }\n } catch {\n // ignore\n }\n\n // Avoid scanning extremely large files fully.\n // If we didn't find a user message in the first ~2000 lines, give up.\n // (Most sessions have it early.)\n if (lines.length > 2000) break\n }\n } catch {\n // ignore\n }\n\n return null\n}\n\nexport function listPiSessions(): PiSessionListItem[] {\n const sessionsDir = getPiSessionsDir()\n const files: string[] = []\n walkJsonlFiles(sessionsDir, files)\n\n const items: PiSessionListItem[] = []\n\n for (const file of files) {\n const first = readFirstLine(file)\n if (!first) continue\n const header = parseSessionHeader(first)\n if (!header) continue\n\n let updatedAt: string | null = null\n\n let title: string | null = null\n try {\n const tail = readTail(file)\n title = pickTitleFromTail(tail)\n updatedAt = pickUpdatedAtFromTail(tail)\n } catch {\n // ignore\n }\n\n // If the session was named early and grew large, it may fall outside of the tail window.\n if (!title) {\n title = scanSessionInfoNameFromFile(file)\n }\n\n // Fallback for updatedAt when we couldn't parse timestamps from tail.\n if (!updatedAt) {\n try {\n updatedAt = statSync(file).mtime.toISOString()\n } catch {\n updatedAt = null\n }\n }\n\n if (!title) {\n title = pickFallbackTitleFromHead(file)\n }\n\n items.push({\n sessionId: header.sessionId,\n cwd: header.cwd,\n title,\n updatedAt,\n sessionFile: file\n })\n }\n\n // Sort most recent first.\n items.sort((a, b) => {\n const aa = a.updatedAt ?? ''\n const bb = b.updatedAt ?? ''\n return bb.localeCompare(aa)\n })\n\n return items\n}\n\nexport function findPiSessionFile(sessionId: string): string | null {\n const all = listPiSessions()\n const found = all.find(s => s.sessionId === sessionId)\n return found?.sessionFile ?? null\n}\n","export function normalizePiMessageText(content: unknown): string {\n if (typeof content === 'string') return content\n if (!Array.isArray(content)) return ''\n return content\n .map((c: any) => (c?.type === 'text' && typeof c.text === 'string' ? c.text : ''))\n .filter(Boolean)\n .join('')\n}\n\nexport function normalizePiAssistantText(content: unknown): string {\n // Assistant content is typically an array of blocks; only replay text blocks for MVP.\n if (!Array.isArray(content)) return ''\n return content\n .map((c: any) => (c?.type === 'text' && typeof c.text === 'string' ? c.text : ''))\n .filter(Boolean)\n .join('')\n}\n","import type { ContentBlock } from '@agentclientprotocol/sdk'\n\nexport type PiImage = {\n type: 'image'\n mimeType: string\n data: string\n}\n\nexport function promptToPiMessage(blocks: ContentBlock[]): {\n message: string\n images: PiImage[]\n} {\n let message = ''\n const images: PiImage[] = []\n\n for (const b of blocks) {\n switch (b.type) {\n case 'text':\n message += b.text\n break\n\n case 'resource_link':\n // A lightweight, human-readable hint for the LLM.\n message += `\\n[Context] ${b.uri}`\n break\n\n case 'image': {\n // pi expects base64 image bytes in `data` without a data-url prefix.\n images.push({\n type: 'image',\n mimeType: b.mimeType,\n data: b.data\n })\n break\n }\n\n case 'resource': {\n // Clients should not send this if embeddedContext=false, but be resilient.\n const r: any = (b as any).resource\n const uri = typeof r?.uri === 'string' ? r.uri : '(unknown)'\n\n if (typeof r?.text === 'string') {\n // TextResourceContents\n const mime = typeof r?.mimeType === 'string' ? r.mimeType : 'text/plain'\n message += `\\n[Embedded Context] ${uri} (${mime})\\n${r.text}`\n } else if (typeof r?.blob === 'string') {\n // BlobResourceContents\n const mime = typeof r?.mimeType === 'string' ? r.mimeType : 'application/octet-stream'\n const bytes = Buffer.byteLength(r.blob, 'base64')\n message += `\\n[Embedded Context] ${uri} (${mime}, ${bytes} bytes)`\n } else {\n message += `\\n[Embedded Context] ${uri}`\n }\n break\n }\n\n case 'audio': {\n // Not supported by pi. Provide a marker so we don't silently drop context.\n const bytes = Buffer.byteLength(b.data, 'base64')\n message += `\\n[Audio] (${b.mimeType}, ${bytes} bytes) not supported by pi-acp`\n break\n }\n\n default:\n // Ignore unknown block types for now.\n break\n }\n }\n\n return { message, images }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\n\nfunction isObject(x: unknown): x is Record<string, unknown> {\n return Boolean(x) && typeof x === 'object' && !Array.isArray(x)\n}\n\nfunction deepMerge(a: Record<string, unknown>, b: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...a }\n for (const [k, v] of Object.entries(b)) {\n const av = out[k]\n if (isObject(av) && isObject(v)) out[k] = deepMerge(av, v)\n else out[k] = v\n }\n return out\n}\n\nfunction readJsonFile(path: string): Record<string, unknown> {\n try {\n if (!existsSync(path)) return {}\n const raw = readFileSync(path, 'utf-8')\n const data = JSON.parse(raw)\n return isObject(data) ? data : {}\n } catch {\n return {}\n }\n}\n\nfunction getMergedSettings(cwd: string): Record<string, unknown> {\n const globalSettingsPath = join(getAgentDir(), 'settings.json')\n const projectSettingsPath = resolve(cwd, '.pi', 'settings.json')\n\n const global = readJsonFile(globalSettingsPath)\n const project = readJsonFile(projectSettingsPath)\n return deepMerge(global, project)\n}\n\nexport function getAgentDir(): string {\n return process.env.PI_CODING_AGENT_DIR ? resolve(process.env.PI_CODING_AGENT_DIR) : join(homedir(), '.pi', 'agent')\n}\n\n/**\n * Mirror pi settings semantics (global + project merge, project overrides global).\n * Only returns the bits we currently need.\n */\nexport function getEnableSkillCommands(cwd: string): boolean {\n const merged = getMergedSettings(cwd)\n\n const direct = merged.enableSkillCommands\n if (typeof direct === 'boolean') return direct\n\n // Back-compat: some versions used skills.enableSkillCommands\n const nested = isObject(merged.skills) ? merged.skills.enableSkillCommands : undefined\n if (typeof nested === 'boolean') return nested\n\n return true\n}\n\n/**\n * Mirror pi's quietStartup setting: if true, pi suppresses the verbose startup prelude.\n * We use it to decide whether to synthesize + emit our own \"startup info\" message.\n */\nexport function getQuietStartup(cwd: string): boolean {\n const merged = getMergedSettings(cwd)\n\n const direct = merged.quietStartup\n if (typeof direct === 'boolean') return direct\n\n // Back-compat: some versions used quietStart\n const legacy = (merged as any).quietStart\n if (typeof legacy === 'boolean') return legacy\n\n return false\n}\n","import type { AvailableCommand } from '@agentclientprotocol/sdk'\n\nexport type PiRpcCommandInfo = {\n name?: unknown\n description?: unknown\n source?: unknown\n location?: unknown\n path?: unknown\n}\n\nfunction describeFallback(c: PiRpcCommandInfo): string {\n const source = typeof c.source === 'string' ? c.source : ''\n const location = typeof c.location === 'string' ? c.location : ''\n\n const parts: string[] = []\n if (source) parts.push(source)\n if (location) parts.push(location)\n\n return parts.length ? `(${parts.join(':')})` : '(command)'\n}\n\nexport function toAvailableCommandsFromPiGetCommands(\n data: unknown,\n opts?: { enableSkillCommands?: boolean; includeExtensionCommands?: boolean }\n): {\n commands: AvailableCommand[]\n raw: PiRpcCommandInfo[]\n} {\n const enableSkillCommands = opts?.enableSkillCommands ?? true\n const includeExtensionCommands = opts?.includeExtensionCommands ?? false\n\n const root: any = data\n const commandsRaw: PiRpcCommandInfo[] = Array.isArray(root?.commands) ? root.commands : Array.isArray(root?.data?.commands) ? root.data.commands : []\n\n const out: AvailableCommand[] = []\n\n for (const c of commandsRaw) {\n const name = typeof c?.name === 'string' ? c.name.trim() : ''\n if (!name) continue\n\n const source = typeof c?.source === 'string' ? c.source : ''\n if (!includeExtensionCommands && source === 'extension') continue\n\n if (!enableSkillCommands && name.startsWith('skill:')) continue\n\n const desc = typeof c?.description === 'string' ? c.description.trim() : ''\n\n out.push({\n name,\n description: desc || describeFallback(c)\n })\n }\n\n return { commands: out, raw: commandsRaw }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nfunction safeReadJson(path: string): any | null {\n try {\n if (!existsSync(path)) return null\n const raw = readFileSync(path, 'utf-8')\n if (!raw.trim()) return null\n return JSON.parse(raw)\n } catch {\n return null\n }\n}\n\nexport function getPiAgentDir(): string {\n // pi-mono uses ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`.\n // Default APP_NAME is \"pi\".\n const envDir = process.env.PI_CODING_AGENT_DIR\n if (envDir) {\n if (envDir === '~') return homedir()\n if (envDir.startsWith('~/')) return homedir() + envDir.slice(1)\n return envDir\n }\n return join(homedir(), '.pi', 'agent')\n}\n\nexport function hasAnyPiAuthConfigured(): boolean {\n // 1) auth.json present and non-empty (api keys or oauth creds)\n const agentDir = getPiAgentDir()\n const authPath = join(agentDir, 'auth.json')\n const auth = safeReadJson(authPath)\n if (auth && typeof auth === 'object' && Object.keys(auth).length > 0) return true\n\n // 2) models.json with custom provider apiKey configured\n const modelsPath = join(agentDir, 'models.json')\n const models = safeReadJson(modelsPath)\n const providers = models?.providers\n if (providers && typeof providers === 'object') {\n for (const p of Object.values(providers as Record<string, any>)) {\n if (p && typeof p === 'object' && typeof (p as any).apiKey === 'string' && (p as any).apiKey.trim()) {\n // Note: pi treats a non-empty string as either env-var name OR literal secret.\n // So presence of apiKey config is enough to be considered \"auth configured\".\n return true\n }\n }\n }\n\n // 3) Known provider env vars (mirrors pi-ai getEnvApiKey mapping)\n const envVars = [\n 'OPENAI_API_KEY',\n 'AZURE_OPENAI_API_KEY',\n 'GEMINI_API_KEY',\n 'GROQ_API_KEY',\n 'CEREBRAS_API_KEY',\n 'XAI_API_KEY',\n 'OPENROUTER_API_KEY',\n 'AI_GATEWAY_API_KEY',\n 'ZAI_API_KEY',\n 'MISTRAL_API_KEY',\n 'MINIMAX_API_KEY',\n 'MINIMAX_CN_API_KEY',\n 'HF_TOKEN',\n 'OPENCODE_API_KEY',\n 'KIMI_API_KEY',\n // Copilot/github\n 'COPILOT_GITHUB_TOKEN',\n 'GH_TOKEN',\n 'GITHUB_TOKEN',\n // Anthropic oauth\n 'ANTHROPIC_OAUTH_TOKEN',\n 'ANTHROPIC_API_KEY'\n ]\n\n for (const k of envVars) {\n const v = process.env[k]\n if (typeof v === 'string' && v.trim()) return true\n }\n\n return false\n}\n"],"mappings":"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","names":["RequestError","RequestError","readFileSync","resolve","mkdirSync","dirname","readFileSync","homedir","join","RequestError","resolve","readFileSync","readdirSync","readFileSync","homedir","join","existsSync","readFileSync","homedir","join","resolve","isAbsolute","existsSync","readFileSync","readdirSync","statSync","join","dirname","existsSync","readFileSync","homedir","join","getPiAgentDir","isAbsolute","RequestError","dirname","join","existsSync","readFileSync","result","readdirSync","statSync","pkg","platform","spawnSync","resolve"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/acp/agent.ts","../src/acp/auth.ts","../src/acp/session.ts","../src/acp/auth-required.ts","../src/pi-rpc/process.ts","../src/pi-rpc/command.ts","../src/acp/session-store.ts","../src/acp/paths.ts","../src/acp/translate/pi-tools.ts","../src/acp/slash-commands.ts","../src/acp/pi-sessions.ts","../src/acp/translate/pi-messages.ts","../src/acp/translate/prompt.ts","../src/acp/pi-settings.ts","../src/acp/pi-commands.ts","../src/pi-auth/status.ts"],"sourcesContent":["import { AgentSideConnection, ndJsonStream } from '@agentclientprotocol/sdk'\nimport { PiAcpAgent } from './acp/agent.js'\nimport { getPiCommand, shouldUseShellForPiCommand } from './pi-rpc/command.js'\n// Terminal Auth entrypoint. The ACP client launches the agent with `--terminal-login`.\nif (process.argv.includes('--terminal-login')) {\n const { spawnSync } = await import('node:child_process')\n const cmd = getPiCommand(process.env.PI_ACP_PI_COMMAND)\n const res = spawnSync(cmd, [], {\n stdio: 'inherit',\n env: process.env,\n shell: shouldUseShellForPiCommand(cmd)\n })\n\n if ((res as any).error && (res as any).error.code === 'ENOENT') {\n process.stderr.write(\n `pi-acp: could not start pi (command not found: ${cmd}). Install it via \\`npm install -g @mariozechner/pi-coding-agent\\` or ensure \\`pi\\` is on your PATH.\\n`\n )\n process.exit(1)\n }\n\n process.exit(typeof res.status === 'number' ? res.status : 1)\n}\n\nconst input = new WritableStream<Uint8Array>({\n write(chunk) {\n return new Promise<void>(resolve => {\n if ((process.stdout as any).destroyed || !process.stdout.writable) return resolve()\n\n try {\n process.stdout.write(chunk, err => {\n void err\n resolve()\n })\n } catch {\n // Common: ERR_STREAM_DESTROYED (\"Cannot call write after a stream was destroyed\").\n resolve()\n }\n })\n }\n})\n\nconst output = new ReadableStream<Uint8Array>({\n start(controller) {\n process.stdin.on('data', (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)))\n process.stdin.on('end', () => controller.close())\n process.stdin.on('error', err => controller.error(err))\n }\n})\n\nconst stream = ndJsonStream(input, output)\n\nconst agent = new AgentSideConnection(conn => new PiAcpAgent(conn), stream)\n\nfunction shutdown() {\n try {\n // Best-effort: dispose session subprocesses when the client disconnects.\n ;(agent as any)?.agent?.dispose?.()\n } catch {\n // ignore\n }\n try {\n process.exit(0)\n } catch {\n // ignore\n }\n}\n\nprocess.stdin.on('end', shutdown)\nprocess.stdin.on('close', shutdown)\n\nprocess.stdin.resume()\nprocess.on('SIGINT', shutdown)\nprocess.on('SIGTERM', shutdown)\n\n// Avoid crashing if the client closes stdout early.\nprocess.stdout.on('error', () => {\n try {\n process.exit(0)\n } catch {\n // ignore\n }\n})\n","import {\n RequestError,\n type Agent as ACPAgent,\n type AgentSideConnection,\n type AuthenticateRequest,\n type CancelNotification,\n type InitializeRequest,\n type InitializeResponse,\n type ListSessionsRequest,\n type ListSessionsResponse,\n type LoadSessionRequest,\n type LoadSessionResponse,\n type ModelInfo,\n type NewSessionRequest,\n type PromptRequest,\n type PromptResponse,\n type SessionInfo,\n type SetSessionModeRequest,\n type SetSessionModeResponse,\n type StopReason\n} from '@agentclientprotocol/sdk'\nimport { getAuthMethods } from './auth.js'\nimport { SessionManager } from './session.js'\nimport { SessionStore } from './session-store.js'\nimport { PiRpcProcess } from '../pi-rpc/process.js'\nimport { listPiSessions, findPiSessionFile } from './pi-sessions.js'\nimport { normalizePiAssistantText, normalizePiMessageText } from './translate/pi-messages.js'\nimport { toolResultToText } from './translate/pi-tools.js'\nimport { promptToPiMessage } from './translate/prompt.js'\nimport { loadSlashCommands, parseCommandArgs, toAvailableCommands } from './slash-commands.js'\nimport { getAgentDir, getEnableSkillCommands, getQuietStartup } from './pi-settings.js'\nimport { toAvailableCommandsFromPiGetCommands } from './pi-commands.js'\nimport { isAbsolute } from 'node:path'\nimport { existsSync, readFileSync, realpathSync, readdirSync, statSync } from 'node:fs'\nimport type { AvailableCommand } from '@agentclientprotocol/sdk'\nimport { join, dirname, basename } from 'node:path'\nimport { spawnSync } from 'node:child_process'\nimport { hasAnyPiAuthConfigured } from '../pi-auth/status.js'\n\ntype ThinkingLevel = 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'\n\nfunction builtinAvailableCommands(): AvailableCommand[] {\n return [\n {\n name: 'compact',\n description: 'Manually compact the session context',\n input: { hint: 'optional custom instructions' }\n },\n {\n name: 'autocompact',\n description: 'Toggle automatic context compaction',\n input: { hint: 'on|off|toggle' }\n },\n {\n name: 'export',\n description: 'Export session to an HTML file in the session cwd'\n },\n {\n name: 'session',\n description: 'Show session stats (messages, tokens, cost, session file)'\n },\n {\n name: 'name',\n description: 'Set session display name',\n input: { hint: '<name>' }\n },\n {\n name: 'steering',\n description: 'Get/set pi steering message delivery mode (how queued steering messages are delivered)',\n input: { hint: '(no args to show) all | one-at-a-time' }\n },\n {\n name: 'follow-up',\n description: 'Get/set pi follow-up message delivery mode (how queued follow-up messages are delivered)',\n input: { hint: '(no args to show) all | one-at-a-time' }\n },\n {\n name: 'changelog',\n description: 'Show pi changelog'\n }\n ]\n}\n\nfunction mergeCommands(a: AvailableCommand[], b: AvailableCommand[]): AvailableCommand[] {\n // Preserve order, de-dupe by name (first wins).\n const out: AvailableCommand[] = []\n const seen = new Set<string>()\n\n for (const c of [...a, ...b]) {\n if (seen.has(c.name)) continue\n seen.add(c.name)\n out.push(c)\n }\n\n return out\n}\nimport { fileURLToPath } from 'node:url'\n\nconst pkg = readNearestPackageJson(import.meta.url)\n\nexport class PiAcpAgent implements ACPAgent {\n private readonly conn: AgentSideConnection\n private readonly sessions = new SessionManager()\n private readonly store = new SessionStore()\n\n dispose(): void {\n this.sessions.disposeAll()\n }\n\n // Remember recent session cwd and use it as the default filter.\n private lastSessionCwd: string | null = null\n\n constructor(conn: AgentSideConnection, _config?: unknown) {\n this.conn = conn\n void _config\n }\n\n async initialize(params: InitializeRequest): Promise<InitializeResponse> {\n // We currently only support ACP protocol version 1.\n const supportedVersion = 1\n const requested = params.protocolVersion\n\n return {\n protocolVersion: requested === supportedVersion ? requested : supportedVersion,\n agentInfo: {\n name: pkg.name ?? 'pi-acp',\n title: 'pi ACP adapter',\n version: pkg.version ?? '0.0.0'\n },\n // Zed currently uses ClientCapabilities._meta[\"terminal-auth\"] to decide whether to show\n // the \"Authenticate\" banner/button. If not supported, we still return the method for the registry.\n authMethods: getAuthMethods({\n supportsTerminalAuthMeta: (params as any)?.clientCapabilities?._meta?.['terminal-auth'] === true\n }),\n agentCapabilities: {\n loadSession: true,\n mcpCapabilities: { http: false, sse: false },\n promptCapabilities: {\n image: true,\n audio: false,\n embeddedContext: false\n },\n sessionCapabilities: {\n // **UNSTABLE** ACP capability used by Zed's codex-acp adapter.\n // Enables a native session picker in clients that support it.\n list: {}\n }\n }\n }\n }\n\n async newSession(params: NewSessionRequest) {\n if (!isAbsolute(params.cwd)) {\n throw RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`)\n }\n\n this.lastSessionCwd = params.cwd\n\n // IMPORTANT: pi exits immediately in --mode rpc if no model is available (no auth configured).\n // So we must detect that situation without spawning pi, and return AUTH_REQUIRED so clients\n // (e.g. Zed) can show the Authenticate banner and launch a terminal login.\n if (!hasAnyPiAuthConfigured()) {\n throw RequestError.authRequired(\n { authMethods: getAuthMethods() },\n 'Configure an API key or log in with an OAuth provider.'\n )\n }\n\n const fileCommands = loadSlashCommands(params.cwd)\n const enableSkillCommands = getEnableSkillCommands(params.cwd)\n\n // Pi doesn't support mcpServers, but we accept and store.\n const session = await this.sessions.create({\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n conn: this.conn,\n fileCommands,\n piCommand: process.env.PI_ACP_PI_COMMAND\n })\n\n // Fetch state + models once (parallel) to reduce startup latency.\n let state: any = null\n let availableModels: any = null\n\n await Promise.all([\n session.proc\n .getState()\n .then(s => {\n state = s as any\n })\n .catch(() => {\n state = null\n }),\n session.proc\n .getAvailableModels()\n .then(m => {\n availableModels = m as any\n })\n .catch(() => {\n availableModels = null\n })\n ])\n\n // Proactive auth gate: if pi has no models available, it's effectively unauthenticated.\n const rawModelsCount = Array.isArray(availableModels?.models) ? availableModels.models.length : 0\n\n if (rawModelsCount === 0) {\n try {\n session.proc.dispose?.()\n } catch {\n // ignore\n }\n throw RequestError.authRequired(\n { authMethods: getAuthMethods() },\n 'Configure an API key or log in with an OAuth provider.'\n )\n }\n\n const models = await getModelState(session.proc, { state, availableModels })\n const thinking = await getThinkingState(session.proc, { state })\n\n const quietStartup = getQuietStartup(params.cwd)\n const updateNotice = buildUpdateNotice()\n\n // If quietStartup is enabled, suppress the full \"startup info\" prelude, but still surface\n // the \"New version available\" notice (if any) since it's high-signal and actionable.\n const preludeText = quietStartup\n ? updateNotice\n ? updateNotice + '\\n'\n : ''\n : buildStartupInfo({\n cwd: params.cwd,\n fileCommands,\n updateNotice\n })\n\n if (preludeText)\n session.setStartupInfo(preludeText)\n\n // Policy: within a single ACP connection (one client window), keep only one live pi subprocess.\n // This avoids leaking subprocesses when clients start new sessions but don't explicitly close old ones.\n // It does NOT affect other client windows because they run in separate agent processes.\n //\n // (Tests sometimes stub out `this.sessions`, so guard the call.)\n ;(this.sessions as any).closeAllExcept?.(session.sessionId)\n\n const response = {\n sessionId: session.sessionId,\n models,\n modes: thinking,\n _meta: {\n piAcp: {\n startupInfo: preludeText || null\n }\n }\n }\n\n // Try to send it immediately after session/new returns; if the client ignores it,\n // it will still be emitted as the first chunk of the first prompt.\n if (preludeText) setTimeout(() => session.sendStartupInfoIfPending(), 0)\n\n // Advertise slash commands (ACP: available_commands_update)\n // Important: some clients (e.g. Zed) will ignore notifications for an unknown sessionId.\n // So we must send this *after* the session/new response has been delivered.\n setTimeout(() => {\n void (async () => {\n try {\n const pi = (await session.proc.getCommands()) as any\n const { commands } = toAvailableCommandsFromPiGetCommands(pi, {\n enableSkillCommands,\n includeExtensionCommands: false\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(commands, builtinAvailableCommands())\n }\n })\n return\n } catch {\n // Fall back to file-based prompt templates (legacy behavior).\n }\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(toAvailableCommands(fileCommands), builtinAvailableCommands())\n }\n })\n })()\n }, 0)\n\n return response\n }\n\n async authenticate(_params: AuthenticateRequest) {\n // Terminal Auth is handled out-of-band by re-launching the binary with `--terminal-login`.\n // If the client calls `authenticate` anyway, we can no-op successfully.\n return\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.sessions.get(params.sessionId)\n\n const { message, images } = promptToPiMessage(params.prompt)\n\n // Built-in ACP slash command handling (headless-friendly subset).\n // Note: file-based slash commands are expanded inside session.prompt().\n if (images.length === 0 && message.trimStart().startsWith('/')) {\n const trimmed = message.trim()\n const space = trimmed.indexOf(' ')\n const cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space)\n const argsString = space === -1 ? '' : trimmed.slice(space + 1)\n const args = parseCommandArgs(argsString)\n\n if (cmd === 'compact') {\n const customInstructions = args.join(' ').trim() || undefined\n const res = await session.proc.compact(customInstructions)\n\n const r: any = res && typeof res === 'object' ? (res as any) : null\n const tokensBefore = typeof r?.tokensBefore === 'number' ? r.tokensBefore : null\n const summary = typeof r?.summary === 'string' ? r.summary : null\n\n const headerLines = [\n `Compaction completed.${customInstructions ? ' (custom instructions applied)' : ''}`,\n tokensBefore !== null ? `Tokens before: ${tokensBefore}` : null\n ].filter(Boolean)\n\n const text = headerLines.join('\\n') + (summary ? `\\n\\n${summary}` : '')\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'session') {\n const stats = (await session.proc.getSessionStats()) as any\n\n const lines: string[] = []\n if (stats?.sessionId) lines.push(`Session: ${stats.sessionId}`)\n if (stats?.sessionFile) lines.push(`Session file: ${stats.sessionFile}`)\n if (typeof stats?.totalMessages === 'number') lines.push(`Messages: ${stats.totalMessages}`)\n\n if (typeof stats?.cost === 'number') lines.push(`Cost: ${stats.cost}`)\n\n const t = stats?.tokens\n if (t && typeof t === 'object') {\n const parts: string[] = []\n if (typeof t.input === 'number') parts.push(`in ${t.input}`)\n if (typeof t.output === 'number') parts.push(`out ${t.output}`)\n if (typeof t.cacheRead === 'number') parts.push(`cache read ${t.cacheRead}`)\n if (typeof t.cacheWrite === 'number') parts.push(`cache write ${t.cacheWrite}`)\n if (typeof t.total === 'number') parts.push(`total ${t.total}`)\n if (parts.length) lines.push(`Tokens: ${parts.join(', ')}`)\n }\n\n // Fallback if stats shape changes.\n const text = lines.length ? lines.join('\\n') : `Session stats:\\n${JSON.stringify(stats, null, 2)}`\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'name') {\n const name = args.join(' ').trim()\n if (!name) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: 'Usage: /name <name>' }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n try {\n await session.proc.setSessionName(name)\n } catch (e: any) {\n const msg = String(e?.message ?? e)\n const hint = /set_session_name/i.test(msg)\n ? ' This requires a newer pi version that supports `set_session_name` in RPC mode.'\n : ''\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Failed to set session name: ${msg}${hint}` }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'session_info_update',\n title: name,\n updatedAt: new Date().toISOString()\n }\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Session name set: ${name}` }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'steering') {\n const modeRaw = String(args[0] ?? '').toLowerCase()\n const state = (await session.proc.getState()) as any\n const current = String(state?.steeringMode ?? '')\n\n // If no arg, just report current.\n if (!modeRaw) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Steering mode: ${current || 'unknown'}`\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n if (modeRaw !== 'all' && modeRaw !== 'one-at-a-time') {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Usage: /steering all | /steering one-at-a-time'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n await session.proc.setSteeringMode(modeRaw as 'all' | 'one-at-a-time')\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Steering mode set to: ${modeRaw}` }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'follow-up') {\n const modeRaw = String(args[0] ?? '').toLowerCase()\n const state = (await session.proc.getState()) as any\n const current = String(state?.followUpMode ?? '')\n\n // If no arg, just report current.\n if (!modeRaw) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Follow-up mode: ${current || 'unknown'}`\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n if (modeRaw !== 'all' && modeRaw !== 'one-at-a-time') {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Usage: /follow-up all | /follow-up one-at-a-time'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n await session.proc.setFollowUpMode(modeRaw as 'all' | 'one-at-a-time')\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Follow-up mode set to: ${modeRaw}` }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'changelog') {\n // Read pi's installed CHANGELOG.md. Adapter-side, no model call.\n const findChangelog = (): string | null => {\n // 1) Locate the installed pi package by resolving the `pi` executable.\n // On Node installs, `pi` typically resolves to .../@mariozechner/pi-coding-agent/dist/cli.js\n try {\n const whichCmd = process.platform === 'win32' ? 'where' : 'which'\n const which = spawnSync(whichCmd, ['pi'], { encoding: 'utf-8' })\n const piPath = String(which.stdout ?? '')\n .split(/\\r?\\n/)[0]\n ?.trim()\n\n if (piPath) {\n const resolved = realpathSync(piPath)\n const pkgRoot = dirname(dirname(resolved))\n const p = join(pkgRoot, 'CHANGELOG.md')\n if (existsSync(p)) return p\n }\n } catch {\n // ignore\n }\n\n // 2) Fallback: ask npm where global modules live.\n try {\n const npmRoot = spawnSync('npm', ['root', '-g'], { encoding: 'utf-8' })\n const root = String(npmRoot.stdout ?? '').trim()\n if (root) {\n const p = join(root, '@mariozechner', 'pi-coding-agent', 'CHANGELOG.md')\n if (existsSync(p)) return p\n }\n } catch {\n // ignore\n }\n\n return null\n }\n\n const changelogPath = findChangelog()\n if (!changelogPath) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: \"Changelog not found (couldn't locate pi installation).\" }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n let text = ''\n try {\n text = readFileSync(changelogPath, 'utf-8')\n } catch (e: any) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Failed to read changelog: ${String(e?.message ?? e)}` }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n // Keep it reasonably sized in chat.\n const maxChars = 20_000\n if (text.length > maxChars) text = text.slice(0, maxChars) + '\\n\\n...(truncated)...'\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'export') {\n // For now we always export into the session cwd and do not accept a user-provided path.\n // IMPORTANT: pi's export_html reads the session JSONL file. If it doesn't exist yet\n // (no messages) or is empty, pi throws and RPC mode emits an uncorrelated parse error\n // (no id), which would otherwise hang our request. So we guard here.\n const state = (await session.proc.getState()) as any\n const sessionFile = typeof state?.sessionFile === 'string' ? state.sessionFile : null\n const messageCount = typeof state?.messageCount === 'number' ? state.messageCount : 0\n\n if (!sessionFile || messageCount === 0 || !existsSync(sessionFile)) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Nothing to export yet (no session messages). Send a prompt first.'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n try {\n const raw = readFileSync(sessionFile, 'utf-8')\n if (raw.trim().length === 0) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Nothing to export yet (empty session file). Send a prompt first.'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n } catch {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: \"Couldn't read session file for export. Try sending a prompt first.\"\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n const safeSessionId = session.sessionId.replace(/[^a-zA-Z0-9_-]/g, '_')\n const outputPath = join(session.cwd, `pi-session-${safeSessionId}.html`)\n\n let resultPath = ''\n try {\n const result = await session.proc.exportHtml(outputPath)\n resultPath = result.path\n } catch (e: any) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Export failed: ${String(e?.message ?? e)}`\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n if (!resultPath) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Export failed: no output path returned by pi.'\n }\n }\n })\n return { stopReason: 'end_turn' }\n }\n\n const uri = `file://${resultPath}`\n\n // Emit a short prefix + a resource link. Many clients concatenate chunks into a single\n // assistant message, so this avoids the \"link + duplicate plain text\" look.\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Session exported: '\n }\n }\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'resource_link',\n name: `pi-session-${safeSessionId}.html`,\n uri,\n mimeType: 'text/html',\n title: 'Session exported'\n }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n\n if (cmd === 'autocompact') {\n const mode = (args[0] ?? 'toggle').toLowerCase()\n let enabled: boolean | null = null\n if (mode === 'on' || mode === 'true' || mode === 'enable' || mode === 'enabled') enabled = true\n else if (mode === 'off' || mode === 'false' || mode === 'disable' || mode === 'disabled') enabled = false\n\n if (enabled === null) {\n // toggle: read current state and invert.\n const state = (await session.proc.getState()) as any\n const current = Boolean(state?.autoCompactionEnabled)\n enabled = !current\n }\n\n await session.proc.setAutoCompaction(enabled)\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Auto-compaction ${enabled ? 'enabled' : 'disabled'}.`\n }\n }\n })\n\n return { stopReason: 'end_turn' }\n }\n }\n\n const result = await session.prompt(message, images)\n\n // ACP StopReason does not include \"error\"; if pi fails we map to end_turn for now,\n // unless we know this was a cancellation.\n const stopReason: StopReason =\n result === 'error' ? (session.wasCancelRequested() ? 'cancelled' : 'end_turn') : result\n\n return { stopReason }\n }\n\n async cancel(params: CancelNotification): Promise<void> {\n const session = this.sessions.get(params.sessionId)\n await session.cancel()\n }\n\n async unstable_listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {\n // ACP: filter by cwd if provided.\n // Zed currently sends `{}` (no cwd), so we default to the last session cwd to\n // emulate pi's `/resume` picker (project-scoped).\n const all = listPiSessions()\n\n const effectiveCwd = (params as any).cwd ?? this.lastSessionCwd\n const filtered = effectiveCwd ? all.filter(s => s.cwd === effectiveCwd) : all\n\n // Cursor-based pagination (opaque cursor). For MVP, we use a simple numeric offset.\n // If cursor is invalid, treat as 0.\n const offset = params.cursor ? Number.parseInt(params.cursor, 10) : 0\n const start = Number.isFinite(offset) && offset > 0 ? offset : 0\n\n const PAGE_SIZE = 50\n const page = filtered.slice(start, start + PAGE_SIZE)\n\n const sessions: SessionInfo[] = page.map(s => ({\n sessionId: s.sessionId,\n cwd: s.cwd,\n title: s.title,\n updatedAt: s.updatedAt\n }))\n\n const nextCursor = start + PAGE_SIZE < filtered.length ? String(start + PAGE_SIZE) : null\n\n return { sessions, nextCursor, _meta: {} }\n }\n\n async loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {\n if (!isAbsolute(params.cwd)) {\n throw RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`)\n }\n\n // If the client is re-loading a session that is already active, tear down the existing\n // pi subprocess so we can start fresh and re-advertise commands reliably.\n // (Some clients may call session/load when restoring from history.)\n this.sessions.close(params.sessionId)\n\n this.lastSessionCwd = params.cwd\n\n // MVP: ignore mcpServers.\n // Prefer ACP-created mapping first (fast path), otherwise scan pi sessions dir.\n const stored = this.store.get(params.sessionId)\n const sessionFile = stored?.sessionFile ?? findPiSessionFile(params.sessionId)\n\n if (!sessionFile) {\n throw RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`)\n }\n\n // Spawn pi and point it directly at the session file.\n let proc: PiRpcProcess\n try {\n proc = await PiRpcProcess.spawn({\n cwd: params.cwd,\n sessionPath: sessionFile,\n piCommand: process.env.PI_ACP_PI_COMMAND\n })\n } catch (e: any) {\n if (e?.name === 'PiRpcSpawnError') {\n throw RequestError.internalError({ code: e?.code }, String(e?.message ?? e))\n }\n throw e\n }\n\n const fileCommands = loadSlashCommands(params.cwd)\n const enableSkillCommands = getEnableSkillCommands(params.cwd)\n\n const session = this.sessions.getOrCreate(params.sessionId, {\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n conn: this.conn,\n proc,\n fileCommands\n })\n\n // Policy: within a single ACP connection (one Zed window), keep only one live pi subprocess.\n // (Tests sometimes stub out `this.sessions`, so guard the call.)\n ;(this.sessions as any).closeAllExcept?.(session.sessionId)\n\n // (Optional) ensure mapping stays fresh.\n this.store.upsert({\n sessionId: params.sessionId,\n cwd: params.cwd,\n sessionFile\n })\n\n // Replay full conversation history.\n const data = (await proc.getMessages()) as any\n const messages = Array.isArray(data?.messages) ? data.messages : []\n\n for (const m of messages) {\n const role = String(m?.role ?? '')\n\n if (role === 'user') {\n const text = normalizePiMessageText(m?.content)\n if (text) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'user_message_chunk',\n content: { type: 'text', text }\n }\n })\n }\n }\n\n if (role === 'assistant') {\n const text = normalizePiAssistantText(m?.content)\n if (text) {\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text }\n }\n })\n }\n }\n\n if (role === 'toolResult') {\n const toolName = String((m as any)?.toolName ?? 'tool')\n const toolCallId = String((m as any)?.toolCallId ?? crypto.randomUUID())\n const isError = Boolean((m as any)?.isError)\n\n // Create a synthetic ACP tool call to render historic tool usage.\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'tool_call',\n toolCallId,\n title: toolName,\n kind: toolName === 'read' ? 'read' : toolName === 'write' || toolName === 'edit' ? 'edit' : 'other',\n status: 'completed',\n rawInput: null,\n rawOutput: m\n }\n })\n\n const text = toolResultToText(m)\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: isError ? 'failed' : 'completed',\n content: text ? [{ type: 'content', content: { type: 'text', text } }] : null,\n rawOutput: m\n }\n })\n }\n }\n\n const models = await getModelState(proc)\n const thinking = await getThinkingState(proc)\n\n const response = {\n models,\n modes: thinking,\n _meta: {\n piAcp: {\n startupInfo: null\n }\n }\n }\n\n // Advertise slash commands after the response so the client knows the session exists.\n setTimeout(() => {\n void (async () => {\n try {\n const pi = (await proc.getCommands()) as any\n const { commands } = toAvailableCommandsFromPiGetCommands(pi, {\n enableSkillCommands,\n includeExtensionCommands: false\n })\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(commands, builtinAvailableCommands())\n }\n })\n return\n } catch {\n // fall back\n }\n\n await this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'available_commands_update',\n availableCommands: mergeCommands(toAvailableCommands(fileCommands), builtinAvailableCommands())\n }\n })\n })()\n }, 0)\n\n return response\n }\n\n async unstable_setSessionModel(params: { sessionId: string; modelId: string }): Promise<void> {\n const session = this.sessions.get(params.sessionId)\n\n // Accept either:\n // - \"provider/model\" (preferred, matches how we advertise)\n // - \"model\" (fallback, we try to resolve via available models)\n let provider: string | null = null\n let modelId: string | null = null\n\n if (params.modelId.includes('/')) {\n const [p, ...rest] = params.modelId.split('/')\n provider = p\n modelId = rest.join('/')\n } else {\n modelId = params.modelId\n }\n\n if (!provider) {\n const data = (await session.proc.getAvailableModels()) as any\n const models: any[] = Array.isArray(data?.models) ? data.models : []\n const found = models.find(m => String(m?.id) === modelId)\n if (found) {\n provider = String(found.provider)\n modelId = String(found.id)\n }\n }\n\n if (!provider || !modelId) {\n throw RequestError.invalidParams(`Unknown modelId: ${params.modelId}`)\n }\n\n await session.proc.setModel(provider, modelId)\n }\n\n async setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse> {\n const session = this.sessions.get(params.sessionId)\n\n const mode = String(params.modeId)\n if (!isThinkingLevel(mode)) {\n throw RequestError.invalidParams(`Unknown modeId: ${mode}`)\n }\n\n await session.proc.setThinkingLevel(mode)\n\n // Let the client know the current mode changed (keeps the dropdown in sync).\n void this.conn.sessionUpdate({\n sessionId: session.sessionId,\n update: {\n sessionUpdate: 'current_mode_update',\n currentModeId: mode\n }\n })\n\n return {}\n }\n}\n\nfunction isThinkingLevel(x: string): x is ThinkingLevel {\n return x === 'off' || x === 'minimal' || x === 'low' || x === 'medium' || x === 'high' || x === 'xhigh'\n}\n\nasync function getThinkingState(\n proc: PiRpcProcess,\n pre?: { state?: any | null }\n): Promise<{\n availableModes: Array<{\n id: string\n name: string\n description?: string | null\n }>\n currentModeId: string\n}> {\n // Ask pi for current thinking level.\n let current: ThinkingLevel = 'medium'\n\n const state = pre?.state ?? (await (async () => {\n try {\n return (await proc.getState()) as any\n } catch {\n return null\n }\n })())\n\n const tl = typeof state?.thinkingLevel === 'string' ? state.thinkingLevel : null\n if (tl && isThinkingLevel(tl)) current = tl\n\n const available: ThinkingLevel[] = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh']\n\n return {\n currentModeId: current,\n availableModes: available.map(id => ({\n id,\n name: `Thinking: ${id}`,\n description: null\n }))\n }\n}\n\nasync function getModelState(\n proc: PiRpcProcess,\n pre?: { state?: any | null; availableModels?: any | null }\n): Promise<{\n availableModels: ModelInfo[]\n currentModelId: string\n} | null> {\n // Ask pi for available models.\n let availableModels: ModelInfo[] = []\n\n const data = pre?.availableModels ?? (await (async () => {\n try {\n return (await proc.getAvailableModels()) as any\n } catch {\n return null\n }\n })())\n\n const models: any[] = Array.isArray(data?.models) ? data.models : []\n availableModels = models\n .map(m => {\n const provider = String(m?.provider ?? '').trim()\n const id = String(m?.id ?? '').trim()\n if (!provider || !id) return null\n\n const name = String(m?.name ?? id)\n return {\n modelId: `${provider}/${id}`,\n name: `${provider}/${name}`,\n description: null\n } satisfies ModelInfo\n })\n .filter(Boolean) as ModelInfo[]\n\n // Ask pi what model is currently active.\n let currentModelId: string | null = null\n\n const state = pre?.state ?? (await (async () => {\n try {\n return (await proc.getState()) as any\n } catch {\n return null\n }\n })())\n\n const model = state?.model\n if (model && typeof model === 'object') {\n const provider = String((model as any).provider ?? '').trim()\n const id = String((model as any).id ?? '').trim()\n if (provider && id) currentModelId = `${provider}/${id}`\n }\n\n if (!availableModels.length && !currentModelId) return null\n\n // Fallback if current model is unknown: use first in list.\n if (!currentModelId) currentModelId = availableModels[0]?.modelId ?? 'default'\n\n return {\n availableModels,\n currentModelId\n }\n}\n\nfunction isSemver(v: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(?:[-+].+)?$/.test(v)\n}\n\nfunction compareSemver(a: string, b: string): number {\n // Very small comparator for x.y.z (ignores pre-release/build beyond making them \"not greater\" unless base differs)\n const pa = a\n .split(/[.-]/)\n .slice(0, 3)\n .map(n => Number(n))\n const pb = b\n .split(/[.-]/)\n .slice(0, 3)\n .map(n => Number(n))\n for (let i = 0; i < 3; i++) {\n const da = pa[i] ?? 0\n const db = pb[i] ?? 0\n if (da > db) return 1\n if (da < db) return -1\n }\n return 0\n}\n\nfunction buildUpdateNotice(): string | null {\n // Best-effort update check against npm registry.\n // Important: keep it fast to not slow down session/new.\n try {\n const piVersion = spawnSync('pi', ['--version'], { encoding: 'utf-8' })\n const installed = (String(piVersion.stdout ?? '').trim() || String(piVersion.stderr ?? '').trim())\n .replace(/^v/i, '')\n\n if (!installed || !isSemver(installed)) return null\n\n const latestRes = spawnSync('npm', ['view', '@mariozechner/pi-coding-agent', 'version'], {\n encoding: 'utf-8',\n timeout: 800\n })\n const latest = String(latestRes.stdout ?? '')\n .trim()\n .replace(/^v/i, '')\n\n if (!latest || !isSemver(latest)) return null\n if (compareSemver(latest, installed) <= 0) return null\n\n return `New version available: v${latest} (installed v${installed}). Run: \\`npm i -g @mariozechner/pi-coding-agent\\``\n } catch {\n return null\n }\n}\n\nfunction buildStartupInfo(opts: {\n cwd: string\n fileCommands: ReturnType<typeof loadSlashCommands>\n updateNotice: string | null\n}): string {\n void opts.fileCommands\n\n const md: string[] = []\n\n // pi version header\n try {\n const piVersion = spawnSync('pi', ['--version'], { encoding: 'utf-8' })\n const installed = (String(piVersion.stdout ?? '').trim() || String(piVersion.stderr ?? '').trim())\n .replace(/^v/i, '')\n if (installed) {\n md.push(`pi v${installed}`)\n md.push('---')\n md.push('')\n }\n } catch {\n // ignore\n }\n\n const addSection = (title: string, items: string[]) => {\n const cleaned = items.map(s => s.trim()).filter(Boolean)\n if (!cleaned.length) return\n\n md.push(`## ${title}`)\n for (const item of cleaned) md.push(`- ${item}`)\n md.push('')\n }\n\n // Context\n const contextItems: string[] = []\n const contextPath = join(opts.cwd, 'AGENTS.md')\n if (existsSync(contextPath)) contextItems.push(contextPath)\n addSection('Context', contextItems)\n\n // Skills\n const skillsItems: string[] = []\n\n const pushSkillFromRoot = (root: string) => {\n try {\n // Direct .md files in root\n for (const e of readdirSync(root)) {\n const p = join(root, e)\n try {\n const st = statSync(p)\n if (st.isFile() && e.toLowerCase().endsWith('.md')) {\n skillsItems.push(p)\n }\n } catch {\n // ignore\n }\n }\n\n // Recursive SKILL.md under subdirectories\n const stack: string[] = [root]\n while (stack.length) {\n const dir = stack.pop()!\n let entries: string[] = []\n try {\n entries = readdirSync(dir)\n } catch {\n continue\n }\n\n for (const name of entries) {\n // Skip obvious noise\n if (name === 'node_modules' || name === '.git') continue\n const p = join(dir, name)\n let st\n try {\n st = statSync(p)\n } catch {\n continue\n }\n if (st.isDirectory()) {\n stack.push(p)\n } else if (st.isFile() && name === 'SKILL.md') {\n skillsItems.push(p)\n }\n }\n }\n } catch {\n // ignore\n }\n }\n\n // Global skills\n // Use getAgentDir() so this respects PI_CODING_AGENT_DIR overrides.\n const globalSkillsDir = join(getAgentDir(), 'skills')\n pushSkillFromRoot(globalSkillsDir)\n\n // Also support ~/.agents/skills (pi skill discovery)\n const legacyAgentsSkillsDir = join(process.env.HOME ?? '', '.agents', 'skills')\n pushSkillFromRoot(legacyAgentsSkillsDir)\n\n // Project skills (.pi/skills)\n const projectSkillsDir = join(opts.cwd, '.pi', 'skills')\n pushSkillFromRoot(projectSkillsDir)\n\n addSection('Skills', skillsItems)\n\n // Prompts\n const promptsItems: string[] = []\n const promptsDir = join(process.env.HOME ?? '', '.pi', 'agent', 'prompts')\n try {\n const prompts = readdirSync(promptsDir).filter(f => f.endsWith('.md'))\n for (const f of prompts) promptsItems.push(`/${basename(f, '.md')}`)\n } catch {\n // ignore\n }\n addSection('Prompts', promptsItems)\n\n // Extensions\n const extItems: string[] = []\n const extDir = join(process.env.HOME ?? '', '.pi', 'agent', 'extensions')\n try {\n const exts = readdirSync(extDir).filter(f => f.endsWith('.ts') || f.endsWith('.js'))\n for (const f of exts) extItems.push(join(extDir, f))\n } catch {\n // ignore\n }\n\n // Also show npm packages from pi settings (best-effort)\n try {\n const settingsPath = join(process.env.HOME ?? '', '.pi', 'agent', 'settings.json')\n const settings = JSON.parse(readFileSync(settingsPath, 'utf-8')) as any\n const pkgs: string[] = Array.isArray(settings?.packages) ? settings.packages : []\n for (const pkg of pkgs) {\n const s = String(pkg)\n if (s.startsWith('npm:')) {\n // Render a two-line bullet structure using markdown indentation.\n extItems.push(`${s}\\n - index.ts`)\n } else {\n extItems.push(s)\n }\n }\n } catch {\n // ignore\n }\n\n addSection('Extensions', extItems)\n\n if (opts.updateNotice) {\n md.push('---')\n md.push(opts.updateNotice)\n md.push('')\n }\n\n // Do NOT include themes (per request).\n return md.join('\\n').trim() + '\\n'\n}\n\nfunction readNearestPackageJson(metaUrl: string): {\n name?: string\n version?: string\n} {\n try {\n let dir = dirname(fileURLToPath(metaUrl))\n\n // Walk upwards a few levels to find the nearest package.json\n for (let i = 0; i < 6; i++) {\n const p = join(dir, 'package.json')\n if (existsSync(p)) {\n const json = JSON.parse(readFileSync(p, 'utf-8')) as any\n return { name: json?.name, version: json?.version }\n }\n dir = dirname(dir)\n }\n } catch {\n // ignore\n }\n return { name: 'pi-acp', version: '0.0.0' }\n}\n","import type { AuthMethod } from '@agentclientprotocol/sdk'\n\nexport const PI_SETUP_METHOD_ID = 'pi_terminal_login'\n\n/**\n * Zed (and some other clients) currently support \"Terminal Auth\" via an extension field\n * in AuthMethod._meta, rather than the RFD \"type/args/env\" shape.\n *\n * We include BOTH for maximum compatibility:\n * - `_meta[\"terminal-auth\"]`: used by Zed to render the \"Authenticate\" banner + button.\n * - `type/args/env`: registry-required shape.\n */\nexport function getAuthMethods(opts?: { supportsTerminalAuthMeta?: boolean }): AuthMethod[] {\n const supportsTerminalAuthMeta = opts?.supportsTerminalAuthMeta ?? true\n\n const method: any = {\n id: PI_SETUP_METHOD_ID,\n name: 'Launch pi in the terminal',\n description: 'Start pi in an interactive terminal to configure API keys or login',\n\n // Registry-required fields\n type: 'terminal',\n args: ['--terminal-login'],\n env: {}\n }\n\n if (supportsTerminalAuthMeta) {\n // Best-effort launch spec for Zed's terminal-auth banner.\n // Zed expects a full command+args (see mistral-vibe implementation).\n const launch = terminalAuthLaunchSpec()\n\n method._meta = {\n ...(method._meta ?? {}),\n 'terminal-auth': {\n ...launch,\n label: 'Launch pi'\n }\n }\n }\n\n return [method as AuthMethod]\n}\n\nfunction terminalAuthLaunchSpec(): { command: string; args: string[] } {\n // If we were launched as `node /path/to/dist/index.js`, reuse that.\n // This is the most reliable in local dev and custom Zed configurations.\n const argv0 = process.argv[0] || 'node'\n const argv1 = process.argv[1]\n if (argv1 && argv0) {\n const isNode = argv0.includes('node')\n const isJs = argv1.endsWith('.js')\n if (isNode && isJs) {\n return { command: argv0, args: [argv1, '--terminal-login'] }\n }\n }\n\n // Fallback: assume `pi-acp` is on PATH.\n return { command: 'pi-acp', args: ['--terminal-login'] }\n}\n","import type {\n AgentSideConnection,\n ContentBlock,\n McpServer,\n SessionUpdate,\n ToolCallContent,\n ToolCallLocation,\n ToolKind\n} from '@agentclientprotocol/sdk'\nimport { RequestError } from '@agentclientprotocol/sdk'\nimport { maybeAuthRequiredError } from './auth-required.js'\nimport { readFileSync } from 'node:fs'\nimport { isAbsolute, resolve as resolvePath } from 'node:path'\nimport { PiRpcProcess, PiRpcSpawnError, type PiRpcEvent } from '../pi-rpc/process.js'\nimport { SessionStore } from './session-store.js'\nimport { toolResultToText } from './translate/pi-tools.js'\nimport { expandSlashCommand, type FileSlashCommand } from './slash-commands.js'\n\ntype SessionCreateParams = {\n cwd: string\n mcpServers: McpServer[]\n conn: AgentSideConnection\n fileCommands?: import('./slash-commands.js').FileSlashCommand[]\n piCommand?: string\n}\n\nexport type StopReason = 'end_turn' | 'cancelled' | 'error'\n\ntype PendingTurn = {\n resolve: (reason: StopReason) => void\n reject: (err: unknown) => void\n}\n\ntype QueuedTurn = {\n message: string\n images: unknown[]\n resolve: (reason: StopReason) => void\n reject: (err: unknown) => void\n}\n\nfunction findUniqueLineNumber(text: string, needle: string): number | undefined {\n if (!needle) return undefined\n\n const first = text.indexOf(needle)\n if (first < 0) return undefined\n\n const second = text.indexOf(needle, first + needle.length)\n if (second >= 0) return undefined\n\n let line = 1\n for (let i = 0; i < first; i += 1) {\n if (text.charCodeAt(i) === 10) line += 1\n }\n return line\n}\n\nfunction toToolCallLocations(args: unknown, cwd: string, line?: number): ToolCallLocation[] | undefined {\n const path = typeof (args as { path?: unknown } | null | undefined)?.path === 'string' ? (args as { path: string }).path : undefined\n if (!path) return undefined\n\n const resolvedPath = isAbsolute(path) ? path : resolvePath(cwd, path)\n return [{ path: resolvedPath, ...(typeof line === 'number' ? { line } : {}) }]\n}\n\nexport class SessionManager {\n private sessions = new Map<string, PiAcpSession>()\n private readonly store = new SessionStore()\n\n /** Dispose all sessions and their underlying pi subprocesses. */\n disposeAll(): void {\n for (const [id] of this.sessions) this.close(id)\n }\n\n /** Get a registered session if it exists (no throw). */\n maybeGet(sessionId: string): PiAcpSession | undefined {\n return this.sessions.get(sessionId)\n }\n\n /**\n * Dispose a session's underlying pi process and remove it from the manager.\n * Used when clients explicitly reload a session and we want a fresh pi subprocess.\n */\n close(sessionId: string): void {\n const s = this.sessions.get(sessionId)\n if (!s) return\n try {\n s.proc.dispose?.()\n } catch {\n // ignore\n }\n this.sessions.delete(sessionId)\n }\n\n /** Close all sessions except the one with `keepSessionId`. */\n closeAllExcept(keepSessionId: string): void {\n for (const [id] of this.sessions) {\n if (id === keepSessionId) continue\n this.close(id)\n }\n }\n\n async create(params: SessionCreateParams): Promise<PiAcpSession> {\n // Let pi manage session persistence in its default location (~/.pi/agent/sessions/...)\n // so sessions are visible to the regular `pi` CLI.\n let proc: PiRpcProcess\n try {\n proc = await PiRpcProcess.spawn({\n cwd: params.cwd,\n piCommand: params.piCommand\n })\n } catch (e) {\n if (e instanceof PiRpcSpawnError) {\n throw RequestError.internalError({ code: e.code }, e.message)\n }\n throw e\n }\n\n let state: any = null\n try {\n state = (await proc.getState()) as any\n } catch {\n state = null\n }\n\n const sessionId = typeof state?.sessionId === 'string' ? state.sessionId : crypto.randomUUID()\n const sessionFile = typeof state?.sessionFile === 'string' ? state.sessionFile : null\n\n if (sessionFile) {\n this.store.upsert({ sessionId, cwd: params.cwd, sessionFile })\n }\n\n const session = new PiAcpSession({\n sessionId,\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n proc,\n conn: params.conn,\n fileCommands: params.fileCommands ?? []\n })\n\n this.sessions.set(sessionId, session)\n return session\n }\n\n get(sessionId: string): PiAcpSession {\n const s = this.sessions.get(sessionId)\n if (!s) throw RequestError.invalidParams(`Unknown sessionId: ${sessionId}`)\n return s\n }\n\n /**\n * Used by session/load: create a session object bound to an existing sessionId/proc\n * if it isn't already registered.\n */\n getOrCreate(sessionId: string, params: SessionCreateParams & { proc: PiRpcProcess }): PiAcpSession {\n const existing = this.sessions.get(sessionId)\n if (existing) return existing\n\n const session = new PiAcpSession({\n sessionId,\n cwd: params.cwd,\n mcpServers: params.mcpServers,\n proc: params.proc,\n conn: params.conn,\n fileCommands: params.fileCommands ?? []\n })\n\n this.sessions.set(sessionId, session)\n return session\n }\n}\n\nexport class PiAcpSession {\n readonly sessionId: string\n readonly cwd: string\n readonly mcpServers: McpServer[]\n\n private startupInfo: string | null = null\n private startupInfoSent = false\n\n readonly proc: PiRpcProcess\n private readonly conn: AgentSideConnection\n private readonly fileCommands: FileSlashCommand[]\n\n // Used to map abort semantics to ACP stopReason.\n // Applies to the currently running turn.\n private cancelRequested = false\n\n // Current in-flight turn (if any). Additional prompts are queued.\n private pendingTurn: PendingTurn | null = null\n private readonly turnQueue: QueuedTurn[] = []\n // Track tool call statuses and ensure they are monotonic (pending -> in_progress -> completed).\n // Some pi events can arrive out of order (e.g. late toolcall_* deltas after execution starts),\n // and clients may hide progress if we ever downgrade back to `pending`.\n private currentToolCalls = new Map<string, 'pending' | 'in_progress'>()\n\n // pi can emit multiple `turn_end` events for a single user prompt (e.g. after tool_use).\n // The overall agent loop completes when `agent_end` is emitted.\n private inAgentLoop = false\n\n // For ACP diff support: capture file contents before edits, then emit ToolCallContent {type:\"diff\"}.\n // This is due to pi sending diff as a string as opposed to ACP expected diff format.\n // Compatible format may need to be implemented in pi in the future.\n private editSnapshots = new Map<string, { path: string; oldText: string }>()\n\n // Ensure `session/update` notifications are sent in order and can be awaited\n // before completing a `session/prompt` request.\n private lastEmit: Promise<void> = Promise.resolve()\n\n constructor(opts: {\n sessionId: string\n cwd: string\n mcpServers: McpServer[]\n proc: PiRpcProcess\n conn: AgentSideConnection\n fileCommands?: FileSlashCommand[]\n }) {\n this.sessionId = opts.sessionId\n this.cwd = opts.cwd\n this.mcpServers = opts.mcpServers\n this.proc = opts.proc\n this.conn = opts.conn\n this.fileCommands = opts.fileCommands ?? []\n\n this.proc.onEvent(ev => this.handlePiEvent(ev))\n }\n\n setStartupInfo(text: string) {\n this.startupInfo = text\n }\n\n /**\n * Best-effort attempt to send startup info outside of a prompt turn.\n * Some clients (e.g. Zed) may only render agent messages once the UI is ready;\n * callers can invoke this shortly after session/new returns.\n */\n sendStartupInfoIfPending(): void {\n if (this.startupInfoSent || !this.startupInfo) return\n this.startupInfoSent = true\n\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: this.startupInfo }\n })\n }\n\n async prompt(message: string, images: unknown[] = []): Promise<StopReason> {\n\n // pi RPC mode disables slash command expansion, so we do it here.\n const expandedMessage = expandSlashCommand(message, this.fileCommands)\n\n const turnPromise = new Promise<StopReason>((resolve, reject) => {\n const queued: QueuedTurn = { message: expandedMessage, images, resolve, reject }\n\n // If a turn is already running, enqueue.\n if (this.pendingTurn) {\n this.turnQueue.push(queued)\n\n // Best-effort: notify client that a prompt was queued.\n // This doesn't work in Zed yet, needs to be revisited\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: `Queued message (position ${this.turnQueue.length}).`\n }\n })\n\n // Also publish queue depth via session info metadata.\n // This also not visible in the client\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: this.turnQueue.length, running: true } }\n })\n\n return\n }\n\n // No turn is running; start immediately.\n this.startTurn(queued)\n })\n\n return turnPromise\n }\n\n async cancel(): Promise<void> {\n // Cancel current and clear any queued prompts.\n this.cancelRequested = true\n\n if (this.turnQueue.length) {\n const queued = this.turnQueue.splice(0, this.turnQueue.length)\n for (const t of queued) t.resolve('cancelled')\n\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: 'Cleared queued prompts.' }\n })\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: 0, running: Boolean(this.pendingTurn) } }\n })\n }\n\n // Abort the currently running turn (if any). If nothing is running, this is a no-op.\n await this.proc.abort()\n }\n\n wasCancelRequested(): boolean {\n return this.cancelRequested\n }\n\n private emit(update: SessionUpdate): void {\n // Serialize update delivery.\n this.lastEmit = this.lastEmit\n .then(() =>\n this.conn.sessionUpdate({\n sessionId: this.sessionId,\n update\n })\n )\n .catch(() => {\n // Ignore notification errors (client may have gone away). We still want\n // prompt completion.\n })\n }\n\n private async flushEmits(): Promise<void> {\n await this.lastEmit\n }\n\n private startTurn(t: QueuedTurn): void {\n this.cancelRequested = false\n this.inAgentLoop = false\n\n this.pendingTurn = { resolve: t.resolve, reject: t.reject }\n\n // Publish queue depth (0 because we're starting the turn now).\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: this.turnQueue.length, running: true } }\n })\n\n // Kick off pi, but completion is determined by pi events, not the RPC response.\n // Important: pi may emit multiple `turn_end` events (e.g. when the model requests tools).\n // The full prompt is finished when we see `agent_end`.\n this.proc.prompt(t.message, t.images).catch(err => {\n // If the subprocess errors before we get an `agent_end`, treat as error unless cancelled.\n // Also ensure we flush any already-enqueued updates first.\n void this.flushEmits().finally(() => {\n // If this looks like an auth/config issue, surface AUTH_REQUIRED so clients can offer terminal login.\n const authErr = maybeAuthRequiredError(err)\n if (authErr) {\n this.pendingTurn?.reject(authErr)\n } else {\n const reason: StopReason = this.cancelRequested ? 'cancelled' : 'error'\n this.pendingTurn?.resolve(reason)\n }\n\n this.pendingTurn = null\n this.inAgentLoop = false\n\n // If the prompt failed, do not automatically proceed—pi may be unhealthy.\n // But we still clear the queueDepth metadata.\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: this.turnQueue.length, running: false } }\n })\n })\n void err\n })\n }\n\n private handlePiEvent(ev: PiRpcEvent) {\n const type = String((ev as any).type ?? '')\n\n switch (type) {\n case 'message_update': {\n const ame = (ev as any).assistantMessageEvent\n\n // Stream assistant text.\n if (ame?.type === 'text_delta' && typeof ame.delta === 'string') {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: ame.delta } satisfies ContentBlock\n })\n break\n }\n\n if (ame?.type === 'thinking_delta' && typeof ame.delta === 'string') {\n this.emit({\n sessionUpdate: 'agent_thought_chunk',\n content: { type: 'text', text: ame.delta } satisfies ContentBlock\n })\n break\n }\n\n // Surface tool calls ASAP so clients (e.g. Zed) can show a tool-in-use/loading UI\n // while the model is still streaming tool call args.\n if (ame?.type === 'toolcall_start' || ame?.type === 'toolcall_delta' || ame?.type === 'toolcall_end') {\n const toolCall =\n // pi sometimes includes the tool call directly on the event\n (ame as any)?.toolCall ??\n // ...and always includes it in the partial assistant message at contentIndex\n (ame as any)?.partial?.content?.[(ame as any)?.contentIndex ?? 0]\n\n const toolCallId = String((toolCall as any)?.id ?? '')\n const toolName = String((toolCall as any)?.name ?? 'tool')\n\n if (toolCallId) {\n const rawInput =\n (toolCall as any)?.arguments && typeof (toolCall as any).arguments === 'object'\n ? (toolCall as any).arguments\n : (() => {\n const s = String((toolCall as any)?.partialArgs ?? '')\n if (!s) return undefined\n try {\n return JSON.parse(s)\n } catch {\n return { partialArgs: s }\n }\n })()\n\n const locations = toToolCallLocations(rawInput, this.cwd)\n const existingStatus = this.currentToolCalls.get(toolCallId)\n // IMPORTANT: never downgrade status (e.g. if we already marked in_progress via tool_execution_start).\n const status = existingStatus ?? 'pending'\n\n if (!existingStatus) {\n this.currentToolCalls.set(toolCallId, 'pending')\n this.emit({\n sessionUpdate: 'tool_call',\n toolCallId,\n title: toolName,\n kind: toToolKind(toolName),\n status,\n locations,\n rawInput\n })\n } else {\n // Best-effort: keep rawInput updated while args are streaming.\n // Keep the existing status (pending or in_progress).\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status,\n locations,\n rawInput\n })\n }\n }\n\n break\n }\n\n // Ignore other delta/event types for now.\n break\n }\n\n case 'tool_execution_start': {\n const toolCallId = String((ev as any).toolCallId ?? crypto.randomUUID())\n const toolName = String((ev as any).toolName ?? 'tool')\n const args = (ev as any).args\n let line: number | undefined\n\n // Capture pre-edit file contents so we can emit a structured ACP diff on completion.\n if (toolName === 'edit') {\n const p = typeof args?.path === 'string' ? args.path : undefined\n if (p) {\n try {\n const abs = isAbsolute(p) ? p : resolvePath(this.cwd, p)\n const oldText = readFileSync(abs, 'utf8')\n this.editSnapshots.set(toolCallId, { path: p, oldText })\n\n const needle = typeof args?.oldText === 'string' ? args.oldText : ''\n line = findUniqueLineNumber(oldText, needle)\n } catch {\n // Ignore snapshot failures; we'll fall back to plain text output.\n }\n }\n }\n\n const locations = toToolCallLocations(args, this.cwd, line)\n\n // If we already surfaced the tool call while the model streamed it, just transition.\n if (!this.currentToolCalls.has(toolCallId)) {\n this.currentToolCalls.set(toolCallId, 'in_progress')\n this.emit({\n sessionUpdate: 'tool_call',\n toolCallId,\n title: toolName,\n kind: toToolKind(toolName),\n status: 'in_progress',\n locations,\n rawInput: args\n })\n } else {\n this.currentToolCalls.set(toolCallId, 'in_progress')\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: 'in_progress',\n locations,\n rawInput: args\n })\n }\n\n break\n }\n\n case 'tool_execution_update': {\n const toolCallId = String((ev as any).toolCallId ?? '')\n if (!toolCallId) break\n\n const partial = (ev as any).partialResult\n const text = toolResultToText(partial)\n\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: 'in_progress',\n content: text\n ? ([{ type: 'content', content: { type: 'text', text } }] satisfies ToolCallContent[])\n : undefined,\n rawOutput: partial\n })\n break\n }\n\n case 'tool_execution_end': {\n const toolCallId = String((ev as any).toolCallId ?? '')\n if (!toolCallId) break\n\n const result = (ev as any).result\n const isError = Boolean((ev as any).isError)\n const text = toolResultToText(result)\n\n // If this was an edit and we captured a snapshot, emit a structured ACP diff.\n // This enables clients like Zed to render an actual diff UI.\n const snapshot = this.editSnapshots.get(toolCallId)\n let content: ToolCallContent[] | undefined\n\n if (!isError && snapshot) {\n try {\n const abs = isAbsolute(snapshot.path) ? snapshot.path : resolvePath(this.cwd, snapshot.path)\n const newText = readFileSync(abs, 'utf8')\n if (newText !== snapshot.oldText) {\n content = [\n {\n type: 'diff',\n path: snapshot.path,\n oldText: snapshot.oldText,\n newText\n },\n ...(text ? ([{ type: 'content', content: { type: 'text', text } }] as ToolCallContent[]) : [])\n ]\n }\n } catch {\n // ignore; fall back to text only\n }\n }\n\n // Fallback: just text content.\n if (!content && text) {\n content = [{ type: 'content', content: { type: 'text', text } }] satisfies ToolCallContent[]\n }\n\n this.emit({\n sessionUpdate: 'tool_call_update',\n toolCallId,\n status: isError ? 'failed' : 'completed',\n content,\n rawOutput: result\n })\n\n this.currentToolCalls.delete(toolCallId)\n this.editSnapshots.delete(toolCallId)\n break\n }\n\n case 'auto_retry_start': {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: formatAutoRetryMessage(ev) } satisfies ContentBlock\n })\n break\n }\n\n case 'auto_retry_end': {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: 'Retry finished, resuming.' } satisfies ContentBlock\n })\n break\n }\n\n case 'auto_compaction_start': {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: 'Context nearing limit, running automatic compaction...' } satisfies ContentBlock\n })\n break\n }\n\n case 'auto_compaction_end': {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: {\n type: 'text',\n text: 'Automatic compaction finished; context was summarized to continue the session.'\n } satisfies ContentBlock\n })\n break\n }\n\n case 'agent_start': {\n this.inAgentLoop = true\n break\n }\n\n case 'turn_end': {\n // pi uses `turn_end` for sub-steps (e.g. tool_use) and will often start another turn.\n // Do NOT resolve the ACP `session/prompt` here; wait for `agent_end`.\n break\n }\n\n case 'agent_end': {\n // Ensure all updates derived from pi events are delivered before we resolve\n // the ACP `session/prompt` request.\n void this.flushEmits().finally(() => {\n const reason: StopReason = this.cancelRequested ? 'cancelled' : 'end_turn'\n this.pendingTurn?.resolve(reason)\n this.pendingTurn = null\n this.inAgentLoop = false\n\n // Start next queued prompt, if any.\n const next = this.turnQueue.shift()\n if (next) {\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: `Starting queued message. (${this.turnQueue.length} remaining)` }\n })\n this.startTurn(next)\n } else {\n this.emit({\n sessionUpdate: 'session_info_update',\n _meta: { piAcp: { queueDepth: 0, running: false } }\n })\n }\n })\n break\n }\n\n default:\n break\n }\n }\n}\n\nfunction formatAutoRetryMessage(ev: PiRpcEvent): string {\n const attempt = Number((ev as any).attempt)\n const maxAttempts = Number((ev as any).maxAttempts)\n const delayMs = Number((ev as any).delayMs)\n\n if (!Number.isFinite(attempt) || !Number.isFinite(maxAttempts) || !Number.isFinite(delayMs)) {\n return 'Retrying...'\n }\n\n let delaySeconds = Math.round(delayMs / 1000)\n if (delayMs > 0 && delaySeconds === 0) delaySeconds = 1\n\n return `Retrying (attempt ${attempt}/${maxAttempts}, waiting ${delaySeconds}s)...`\n}\n\nfunction toToolKind(toolName: string): ToolKind {\n switch (toolName) {\n case 'read':\n return 'read'\n case 'write':\n case 'edit':\n return 'edit'\n case 'bash':\n // Many ACP clients render `execute` tool calls only via the terminal APIs.\n // Since this adapter lets pi execute locally (no client terminal delegation),\n // we report bash as `other` so clients show inline text output blocks.\n return 'other'\n default:\n return 'other'\n }\n}\n","import { RequestError } from '@agentclientprotocol/sdk'\nimport { getAuthMethods } from './auth.js'\n\n/**\n * Best-effort detection of missing credentials / not-configured errors from pi/providers.\n *\n * We can't do a full provider-specific check here, so we look for common substrings.\n */\nexport function maybeAuthRequiredError(err: unknown): RequestError | null {\n const msg = String((err as any)?.message ?? err ?? '')\n const s = msg.toLowerCase()\n\n const patterns = [\n 'api key',\n 'apikey',\n 'missing key',\n 'no key',\n 'not configured',\n 'unauthorized',\n 'authentication',\n 'permission denied',\n 'forbidden',\n '401',\n '403'\n ]\n\n const hit = patterns.some(p => s.includes(p))\n if (!hit) return null\n\n // Include terminal auth method options in error data.\n return RequestError.authRequired(\n {\n authMethods: getAuthMethods()\n },\n 'Configure an API key or log in with an OAuth provider.'\n )\n}\n","import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process'\nimport * as readline from 'node:readline'\nimport { getPiCommand, shouldUseShellForPiCommand } from './command.js'\n\nexport class PiRpcSpawnError extends Error {\n /** Underlying spawn error code, e.g. ENOENT, EACCES */\n code?: string\n\n constructor(message: string, opts?: { code?: string; cause?: unknown }) {\n super(message)\n this.name = 'PiRpcSpawnError'\n this.code = opts?.code\n ;(this as any).cause = opts?.cause\n }\n}\n\nconst ESC = String.fromCharCode(0x1b)\nconst CSI = String.fromCharCode(0x9b)\n\nconst ANSI_ESCAPE_REGEX = new RegExp(\n `[${ESC}${CSI}][[\\\\]()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]`,\n 'g'\n)\n\nfunction stripAnsi(s: string): string {\n // Basic ANSI escape stripping (colors, cursor movement, etc.)\n return s.replace(ANSI_ESCAPE_REGEX, '')\n}\n\ntype PiRpcCommand =\n | { type: 'prompt'; id?: string; message: string; images?: unknown[] }\n | { type: 'abort'; id?: string }\n | { type: 'get_state'; id?: string }\n // Model\n | { type: 'get_available_models'; id?: string }\n | { type: 'set_model'; id?: string; provider: string; modelId: string }\n // Thinking\n | { type: 'set_thinking_level'; id?: string; level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' }\n // Modes\n | { type: 'set_follow_up_mode'; id?: string; mode: 'all' | 'one-at-a-time' }\n | { type: 'set_steering_mode'; id?: string; mode: 'all' | 'one-at-a-time' }\n // Compaction\n | { type: 'compact'; id?: string; customInstructions?: string }\n | { type: 'set_auto_compaction'; id?: string; enabled: boolean }\n // Session\n | { type: 'get_session_stats'; id?: string }\n | { type: 'set_session_name'; id?: string; name: string }\n | { type: 'export_html'; id?: string; outputPath?: string }\n | { type: 'switch_session'; id?: string; sessionPath: string }\n // Messages\n | { type: 'get_messages'; id?: string }\n // Commands\n | { type: 'get_commands'; id?: string }\n\ntype PiRpcResponse = {\n type: 'response'\n id?: string\n command: string\n success: boolean\n data?: unknown\n error?: string\n}\n\nexport type PiRpcEvent = Record<string, unknown>\n\ntype SpawnParams = {\n cwd: string\n /** Optional override for `pi` executable name/path */\n piCommand?: string\n /** If set, pi will persist the session to this exact file (via `--session <path>`). */\n sessionPath?: string\n}\n\nexport class PiRpcProcess {\n private readonly child: ChildProcessWithoutNullStreams\n private readonly pending = new Map<string, { resolve: (v: PiRpcResponse) => void; reject: (e: unknown) => void }>()\n private eventHandlers: Array<(ev: PiRpcEvent) => void> = []\n private readonly preludeLines: string[] = []\n\n private constructor(child: ChildProcessWithoutNullStreams) {\n this.child = child\n\n const rl = readline.createInterface({ input: child.stdout })\n rl.on('line', line => {\n if (!line.trim()) return\n let msg: any\n try {\n msg = JSON.parse(line)\n } catch {\n // pi may emit a human-readable prelude on stdout before NDJSON starts.\n // Capture it so the ACP adapter can surface it on session start.\n const cleaned = stripAnsi(String(line)).trimEnd()\n if (cleaned) this.preludeLines.push(cleaned)\n return\n }\n\n if (msg?.type === 'response') {\n const id = typeof msg.id === 'string' ? msg.id : undefined\n if (id) {\n const pending = this.pending.get(id)\n if (pending) {\n this.pending.delete(id)\n pending.resolve(msg as PiRpcResponse)\n return\n }\n }\n }\n\n for (const h of this.eventHandlers) h(msg as PiRpcEvent)\n })\n\n child.on('exit', (code, signal) => {\n const err = new Error(`pi process exited (code=${code}, signal=${signal})`)\n for (const [, p] of this.pending) p.reject(err)\n this.pending.clear()\n })\n\n child.on('error', err => {\n for (const [, p] of this.pending) p.reject(err)\n this.pending.clear()\n })\n }\n\n static async spawn(params: SpawnParams): Promise<PiRpcProcess> {\n // On Windows, npm commonly creates pi.cmd / pi.bat launcher scripts.\n const cmd = getPiCommand(params.piCommand)\n\n // Speed/robustness for ACP:\n // - themes are irrelevant in rpc mode and can be noisy/slow to load.\n // Keep extensions + prompt templates enabled because ACP users may rely on them\n // (e.g. MCP extensions, prompt templates for workflows).\n const args = ['--mode', 'rpc', '--no-themes']\n if (params.sessionPath) args.push('--session', params.sessionPath)\n\n const child = spawn(cmd, args, {\n cwd: params.cwd,\n stdio: 'pipe',\n env: process.env,\n shell: shouldUseShellForPiCommand(cmd)\n })\n\n // Ensure spawn failures (e.g. ENOENT when pi isn't installed) are surfaced as a\n // deterministic error instead of later EPIPE/internal-error noise.\n try {\n await new Promise<void>((resolve, reject) => {\n const onSpawn = () => {\n cleanup()\n resolve()\n }\n const onError = (err: any) => {\n cleanup()\n reject(err)\n }\n const cleanup = () => {\n child.off('spawn', onSpawn)\n child.off('error', onError)\n }\n\n child.once('spawn', onSpawn)\n child.once('error', onError)\n })\n } catch (e: any) {\n const code = typeof e?.code === 'string' ? e.code : undefined\n if (code === 'ENOENT') {\n throw new PiRpcSpawnError(\n `Could not start pi: executable not found (command: ${cmd}). Pi needs to be installed before it can run in ACP clients. Install it via \\`npm install -g @mariozechner/pi-coding-agent\\` or ensure \\`pi\\` is on your PATH. Then try again.`,\n { code, cause: e }\n )\n }\n\n if (code === 'EACCES') {\n throw new PiRpcSpawnError(`Could not start pi: permission denied (command: ${cmd}).`, { code, cause: e })\n }\n\n throw new PiRpcSpawnError(`Could not start pi (command: ${cmd}).`, { code, cause: e })\n }\n\n child.stderr.on('data', () => {\n // leave stderr untouched; ACP clients may capture it.\n })\n\n const proc = new PiRpcProcess(child)\n\n // Best-effort handshake.\n // Important: pi may emit a get_state response pointing at a sessionFile in a directory\n // that is created lazily. Create the parent dir up-front to avoid later parse errors\n // when we call commands like export_html.\n try {\n const state = (await proc.getState()) as any\n const sessionFile = typeof state?.sessionFile === 'string' ? state.sessionFile : null\n if (sessionFile) {\n const { mkdirSync } = await import('node:fs')\n const { dirname } = await import('node:path')\n mkdirSync(dirname(sessionFile), { recursive: true })\n }\n } catch {\n // ignore for now\n }\n\n return proc\n }\n\n onEvent(handler: (ev: PiRpcEvent) => void): () => void {\n this.eventHandlers.push(handler)\n return () => {\n this.eventHandlers = this.eventHandlers.filter(h => h !== handler)\n }\n }\n\n dispose(signal: NodeJS.Signals | number = 'SIGTERM'): void {\n if (this.child.killed) return\n try {\n this.child.kill(signal as any)\n } catch {\n // ignore\n }\n }\n\n /**\n * Human-readable stdout lines emitted before RPC NDJSON begins (e.g. Context/Skills/Extensions info).\n * Themes are typically noisy/less useful for ACP, so callers can filter as needed.\n */\n consumePreludeLines(): string[] {\n const lines = this.preludeLines.splice(0, this.preludeLines.length)\n return lines\n }\n\n async prompt(message: string, images: unknown[] = []): Promise<void> {\n const res = await this.request({ type: 'prompt', message, images })\n if (!res.success) throw new Error(`pi prompt failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async abort(): Promise<void> {\n const res = await this.request({ type: 'abort' })\n if (!res.success) throw new Error(`pi abort failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async getState(): Promise<unknown> {\n const res = await this.request({ type: 'get_state' })\n if (!res.success) throw new Error(`pi get_state failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async getAvailableModels(): Promise<unknown> {\n const res = await this.request({ type: 'get_available_models' })\n if (!res.success) throw new Error(`pi get_available_models failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setModel(provider: string, modelId: string): Promise<unknown> {\n const res = await this.request({ type: 'set_model', provider, modelId })\n if (!res.success) throw new Error(`pi set_model failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setThinkingLevel(level: 'off' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh'): Promise<void> {\n const res = await this.request({ type: 'set_thinking_level', level })\n if (!res.success) throw new Error(`pi set_thinking_level failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async setFollowUpMode(mode: 'all' | 'one-at-a-time'): Promise<void> {\n const res = await this.request({ type: 'set_follow_up_mode', mode })\n if (!res.success) throw new Error(`pi set_follow_up_mode failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async setSteeringMode(mode: 'all' | 'one-at-a-time'): Promise<void> {\n const res = await this.request({ type: 'set_steering_mode', mode })\n if (!res.success) throw new Error(`pi set_steering_mode failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async compact(customInstructions?: string): Promise<unknown> {\n const res = await this.request({ type: 'compact', customInstructions })\n if (!res.success) throw new Error(`pi compact failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setAutoCompaction(enabled: boolean): Promise<void> {\n const res = await this.request({ type: 'set_auto_compaction', enabled })\n if (!res.success) throw new Error(`pi set_auto_compaction failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async getSessionStats(): Promise<unknown> {\n const res = await this.request({ type: 'get_session_stats' })\n if (!res.success) throw new Error(`pi get_session_stats failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async setSessionName(name: string): Promise<void> {\n const res = await this.request({ type: 'set_session_name', name })\n if (!res.success) throw new Error(`pi set_session_name failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async exportHtml(outputPath?: string): Promise<{ path: string }> {\n const res = await this.request({ type: 'export_html', outputPath })\n if (!res.success) throw new Error(`pi export_html failed: ${res.error ?? JSON.stringify(res.data)}`)\n const data: any = res.data\n return { path: String(data?.path ?? '') }\n }\n\n async switchSession(sessionPath: string): Promise<void> {\n const res = await this.request({ type: 'switch_session', sessionPath })\n if (!res.success) throw new Error(`pi switch_session failed: ${res.error ?? JSON.stringify(res.data)}`)\n }\n\n async getMessages(): Promise<unknown> {\n const res = await this.request({ type: 'get_messages' })\n if (!res.success) throw new Error(`pi get_messages failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n async getCommands(): Promise<unknown> {\n const res = await this.request({ type: 'get_commands' })\n if (!res.success) throw new Error(`pi get_commands failed: ${res.error ?? JSON.stringify(res.data)}`)\n return res.data\n }\n\n private request(cmd: PiRpcCommand): Promise<PiRpcResponse> {\n const id = crypto.randomUUID()\n const withId = { ...cmd, id }\n\n const line = JSON.stringify(withId) + '\\n'\n\n return new Promise<PiRpcResponse>((resolve, reject) => {\n this.pending.set(id, { resolve, reject })\n\n try {\n this.child.stdin.write(line, err => {\n if (err) {\n this.pending.delete(id)\n reject(err)\n }\n })\n } catch (e) {\n this.pending.delete(id)\n reject(e)\n }\n })\n }\n}\n","import { platform } from 'node:os'\n\nexport function defaultPiCommand(): string {\n return platform() === 'win32' ? 'pi.cmd' : 'pi'\n}\n\nexport function getPiCommand(override?: string): string {\n return override ?? defaultPiCommand()\n}\n\nexport function shouldUseShellForPiCommand(cmd: string): boolean {\n if (platform() !== 'win32') return false\n\n const normalized = cmd.trim().toLowerCase()\n return normalized.endsWith('.cmd') || normalized.endsWith('.bat')\n}\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport { getPiAcpSessionMapPath } from './paths.js'\n\nexport type StoredSession = {\n sessionId: string\n cwd: string\n sessionFile: string\n updatedAt: string\n}\n\ntype SessionMapFile = {\n version: 1\n sessions: Record<string, StoredSession>\n}\n\nfunction ensureParentDir(path: string) {\n mkdirSync(dirname(path), { recursive: true })\n}\n\nfunction loadFile(path: string): SessionMapFile {\n try {\n const raw = readFileSync(path, 'utf-8')\n const parsed = JSON.parse(raw) as SessionMapFile\n if (parsed?.version !== 1 || typeof parsed.sessions !== 'object' || !parsed.sessions) {\n return { version: 1, sessions: {} }\n }\n return parsed\n } catch {\n return { version: 1, sessions: {} }\n }\n}\n\nfunction saveFile(path: string, data: SessionMapFile): void {\n ensureParentDir(path)\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf-8')\n}\n\nexport class SessionStore {\n private readonly path: string\n\n constructor(path = getPiAcpSessionMapPath()) {\n this.path = path\n }\n\n get(sessionId: string): StoredSession | null {\n const db = loadFile(this.path)\n return db.sessions[sessionId] ?? null\n }\n\n upsert(entry: { sessionId: string; cwd: string; sessionFile: string }): void {\n const db = loadFile(this.path)\n db.sessions[entry.sessionId] = {\n sessionId: entry.sessionId,\n cwd: entry.cwd,\n sessionFile: entry.sessionFile,\n updatedAt: new Date().toISOString()\n }\n saveFile(this.path, db)\n }\n}\n","import { homedir } from 'node:os'\nimport { join } from 'node:path'\n\n/**\n * Storage owned by the ACP adapter.\n *\n * We intentionally keep this separate from pi's own ~/.pi/agent/* directory.\n */\nexport function getPiAcpDir(): string {\n return join(homedir(), '.pi', 'pi-acp')\n}\n\nexport function getPiAcpSessionMapPath(): string {\n return join(getPiAcpDir(), 'session-map.json')\n}\n","export function toolResultToText(result: unknown): string {\n if (!result) return ''\n\n // pi tool results generally look like: { content: [{type:\"text\", text:\"...\"}], details: {...} }\n const content = (result as any).content\n if (Array.isArray(content)) {\n const texts = content\n .map((c: any) => (c?.type === 'text' && typeof c.text === 'string' ? c.text : ''))\n .filter(Boolean)\n if (texts.length) return texts.join('')\n }\n\n const details = (result as any)?.details\n\n // Some pi tools return a unified diff in `details.diff`.\n const diff = details?.diff\n if (typeof diff === 'string' && diff.trim()) {\n return diff\n }\n\n // The bash tool frequently returns stdout/stderr in `details` rather than content blocks.\n const stdout =\n (typeof details?.stdout === 'string' ? details.stdout : undefined) ??\n (typeof (result as any)?.stdout === 'string' ? (result as any).stdout : undefined) ??\n (typeof details?.output === 'string' ? details.output : undefined) ??\n (typeof (result as any)?.output === 'string' ? (result as any).output : undefined)\n\n const stderr =\n (typeof details?.stderr === 'string' ? details.stderr : undefined) ??\n (typeof (result as any)?.stderr === 'string' ? (result as any).stderr : undefined)\n\n const exitCode =\n (typeof details?.exitCode === 'number' ? details.exitCode : undefined) ??\n (typeof (result as any)?.exitCode === 'number' ? (result as any).exitCode : undefined) ??\n (typeof details?.code === 'number' ? details.code : undefined) ??\n (typeof (result as any)?.code === 'number' ? (result as any).code : undefined)\n\n if ((typeof stdout === 'string' && stdout.trim()) || (typeof stderr === 'string' && stderr.trim())) {\n const parts: string[] = []\n if (typeof stdout === 'string' && stdout.trim()) parts.push(stdout)\n if (typeof stderr === 'string' && stderr.trim()) parts.push(`stderr:\\n${stderr}`)\n if (typeof exitCode === 'number') parts.push(`exit code: ${exitCode}`)\n return parts.join('\\n\\n').trimEnd()\n }\n\n try {\n return JSON.stringify(result, null, 2)\n } catch {\n return String(result)\n }\n}\n","import { existsSync, readdirSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport type { AvailableCommand } from '@agentclientprotocol/sdk'\n\n/**\n * File-based slash command (mirrors pi-coding-agent semantics).\n */\nexport type FileSlashCommand = {\n name: string\n description: string\n content: string\n source: string // e.g. \"(user)\", \"(project)\", \"(project:frontend)\"\n}\n\nfunction parseFrontmatter(content: string): {\n frontmatter: Record<string, string>\n content: string\n} {\n const frontmatter: Record<string, string> = {}\n\n if (!content.startsWith('---')) return { frontmatter, content }\n\n const endIndex = content.indexOf('\\n---', 3)\n if (endIndex === -1) return { frontmatter, content }\n\n const frontmatterBlock = content.slice(4, endIndex)\n const remaining = content.slice(endIndex + 4).trim()\n\n for (const line of frontmatterBlock.split('\\n')) {\n const match = line.match(/^(\\w+):\\s*(.*)$/)\n if (match) frontmatter[match[1]] = match[2].trim()\n }\n\n return { frontmatter, content: remaining }\n}\n\nfunction loadCommandsFromDir(dir: string, source: 'user' | 'project', subdir = ''): FileSlashCommand[] {\n const commands: FileSlashCommand[] = []\n if (!existsSync(dir)) return commands\n\n try {\n const entries = readdirSync(dir, { withFileTypes: true })\n\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n\n if (entry.isDirectory()) {\n const newSubdir = subdir ? `${subdir}:${entry.name}` : entry.name\n commands.push(...loadCommandsFromDir(fullPath, source, newSubdir))\n continue\n }\n\n if (!entry.isFile() || !entry.name.endsWith('.md')) continue\n\n try {\n const rawContent = readFileSync(fullPath, 'utf-8')\n const { frontmatter, content } = parseFrontmatter(rawContent)\n\n const name = entry.name.slice(0, -3)\n\n const sourceStr =\n source === 'user' ? (subdir ? `(user:${subdir})` : '(user)') : subdir ? `(project:${subdir})` : '(project)'\n\n let description = frontmatter.description || ''\n if (!description) {\n const firstLine = content.split('\\n').find(l => l.trim())\n if (firstLine) {\n description = firstLine.slice(0, 60)\n if (firstLine.length > 60) description += '...'\n }\n }\n\n description = description ? `${description} ${sourceStr}` : sourceStr\n\n commands.push({\n name,\n description,\n content,\n source: sourceStr\n })\n } catch {\n // Silently skip unreadable files.\n }\n }\n } catch {\n // Silently skip unreadable dirs.\n }\n\n return commands\n}\n\n/**\n * Load prompt templates from pi's prompt directories (formerly \"commands\").\n * - user: ~/.pi/agent/prompts/**\\/*.md\n * - project: <cwd>/.pi/prompts/**\\/*.md\n */\nexport function loadSlashCommands(cwd: string): FileSlashCommand[] {\n const commands: FileSlashCommand[] = []\n\n const userDir = join(homedir(), '.pi', 'agent', 'prompts')\n const projectDir = resolve(cwd, '.pi', 'prompts')\n\n // Match pi ordering: user first, then project.\n commands.push(...loadCommandsFromDir(userDir, 'user'))\n commands.push(...loadCommandsFromDir(projectDir, 'project'))\n\n return commands\n}\n\n/**\n * Convert file-based commands to ACP AvailableCommand objects.\n * De-dupes by name (first wins).\n */\nexport function toAvailableCommands(fileCommands: FileSlashCommand[]): AvailableCommand[] {\n const seen = new Set<string>()\n const out: AvailableCommand[] = []\n\n for (const c of fileCommands) {\n if (seen.has(c.name)) continue\n seen.add(c.name)\n\n out.push({\n name: c.name,\n description: c.description\n // input: omitted for now (pi commands don't specify this)\n })\n }\n\n return out\n}\n\n/**\n * Parse command args (bash-style quotes).\n */\nexport function parseCommandArgs(argsString: string): string[] {\n const args: string[] = []\n let current = ''\n let inQuote: string | null = null\n\n for (let i = 0; i < argsString.length; i++) {\n const ch = argsString[i]\n\n if (inQuote) {\n if (ch === inQuote) inQuote = null\n else current += ch\n continue\n }\n\n if (ch === '\"' || ch === \"'\") {\n inQuote = ch\n } else if (ch === ' ' || ch === '\\t') {\n if (current) {\n args.push(current)\n current = ''\n }\n } else {\n current += ch\n }\n }\n\n if (current) args.push(current)\n return args\n}\n\n/**\n * Substitute $1, $2, ... and $@.\n */\nexport function substituteArgs(content: string, args: string[]): string {\n let result = content\n\n result = result.replace(/\\$@/g, args.join(' '))\n result = result.replace(/\\$(\\d+)/g, (_m, num) => {\n const idx = Number.parseInt(String(num), 10) - 1\n return args[idx] ?? ''\n })\n\n return result\n}\n\n/**\n * Expand a leading /command using the loaded file commands.\n * Returns original text if it's not a known slash command.\n */\nexport function expandSlashCommand(text: string, fileCommands: FileSlashCommand[]): string {\n if (!text.startsWith('/')) return text\n\n const spaceIndex = text.indexOf(' ')\n const commandName = spaceIndex === -1 ? text.slice(1) : text.slice(1, spaceIndex)\n const argsString = spaceIndex === -1 ? '' : text.slice(spaceIndex + 1)\n\n const cmd = fileCommands.find(c => c.name === commandName)\n if (!cmd) return text\n\n const args = parseCommandArgs(argsString)\n return substituteArgs(cmd.content, args)\n}\n","import { readdirSync, readFileSync, statSync, openSync, readSync, closeSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nexport type PiSessionListItem = {\n sessionId: string\n cwd: string\n title: string | null\n updatedAt: string | null\n sessionFile: string\n}\n\nconst DEFAULT_TAIL_BYTES = 256 * 1024\nconst DEFAULT_HEAD_BYTES = 64 * 1024\n\nfunction getPiAgentDir(): string {\n // pi supports overriding config dir via PI_CODING_AGENT_DIR.\n // See pi README.\n return process.env.PI_CODING_AGENT_DIR ?? join(homedir(), '.pi', 'agent')\n}\n\nexport function getPiSessionsDir(): string {\n return join(getPiAgentDir(), 'sessions')\n}\n\nfunction walkJsonlFiles(dir: string, out: string[]) {\n let entries: import('node:fs').Dirent[]\n try {\n // Force string names.\n entries = readdirSync(dir, { withFileTypes: true, encoding: 'utf8' }) as unknown as import('node:fs').Dirent[]\n } catch {\n return\n }\n\n for (const e of entries) {\n const name = typeof (e as any).name === 'string' ? (e as any).name : String((e as any).name)\n const p = join(dir, name)\n if (e.isDirectory()) walkJsonlFiles(p, out)\n else if (e.isFile() && name.endsWith('.jsonl')) out.push(p)\n }\n}\n\nfunction readFirstLine(path: string): string | null {\n // Avoid reading the whole file.\n const fd = openSync(path, 'r')\n try {\n const buf = Buffer.alloc(DEFAULT_HEAD_BYTES)\n const n = readSync(fd, buf, 0, buf.length, 0)\n if (n <= 0) return null\n const s = buf.subarray(0, n).toString('utf-8')\n const idx = s.indexOf('\\n')\n return idx === -1 ? s.trim() : s.slice(0, idx).trim()\n } catch {\n return null\n } finally {\n try {\n closeSync(fd)\n } catch {\n // ignore\n }\n }\n}\n\nfunction readTail(path: string, tailBytes = DEFAULT_TAIL_BYTES): string {\n const st = statSync(path)\n const start = Math.max(0, st.size - tailBytes)\n const len = st.size - start\n\n const fd = openSync(path, 'r')\n try {\n const buf = Buffer.alloc(len)\n const n = readSync(fd, buf, 0, buf.length, start)\n return buf.subarray(0, n).toString('utf-8')\n } finally {\n try {\n closeSync(fd)\n } catch {\n // ignore\n }\n }\n}\n\nfunction parseSessionHeader(firstLine: string): { sessionId: string; cwd: string } | null {\n try {\n const obj = JSON.parse(firstLine) as any\n if (obj?.type !== 'session') return null\n const sessionId = typeof obj?.id === 'string' ? obj.id : null\n const cwd = typeof obj?.cwd === 'string' ? obj.cwd : null\n if (!sessionId || !cwd) return null\n return { sessionId, cwd }\n } catch {\n return null\n }\n}\n\nfunction pickTitleFromTail(tail: string): string | null {\n // Try to find the *latest* session_info entry (stores the user-provided name).\n // We scan backwards line-by-line.\n const lines = tail.split(/\\r?\\n/)\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type === 'session_info' && typeof obj?.name === 'string' && obj.name.trim()) {\n return obj.name.trim()\n }\n } catch {\n // ignore\n }\n }\n return null\n}\n\nfunction scanSessionInfoNameFromFile(path: string): string | null {\n // Fallback when the session_info entry is older than our tail window.\n // Scan the whole file line-by-line and remember the last session_info.name.\n const fd = openSync(path, 'r')\n try {\n const buf = Buffer.alloc(256 * 1024)\n let leftover = ''\n let offset = 0\n let lastName: string | null = null\n\n while (true) {\n const n = readSync(fd, buf, 0, buf.length, offset)\n if (n <= 0) break\n offset += n\n\n const chunk = leftover + buf.subarray(0, n).toString('utf8')\n const lines = chunk.split(/\\r?\\n/)\n leftover = lines.pop() ?? ''\n\n for (const line0 of lines) {\n const line = line0.trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type === 'session_info' && typeof obj?.name === 'string' && obj.name.trim()) {\n lastName = obj.name.trim()\n }\n } catch {\n // ignore\n }\n }\n }\n\n // Best-effort: parse leftover if it was a full line without trailing newline.\n const tailLine = leftover.trim()\n if (tailLine) {\n try {\n const obj = JSON.parse(tailLine) as any\n if (obj?.type === 'session_info' && typeof obj?.name === 'string' && obj.name.trim()) {\n lastName = obj.name.trim()\n }\n } catch {\n // ignore\n }\n }\n\n return lastName\n } catch {\n return null\n } finally {\n try {\n closeSync(fd)\n } catch {\n // ignore\n }\n }\n}\n\nfunction pickUpdatedAtFromTail(tail: string): string | null {\n // pi's `/resume` effectively orders sessions by last *message* activity.\n // We scan backwards and pick the timestamp of the most recent entry with type === \"message\".\n const lines = tail.split(/\\r?\\n/)\n\n // 1) Prefer the most recent message entry.\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type !== 'message') continue\n const ts = typeof obj?.timestamp === 'string' ? obj.timestamp : null\n if (!ts) continue\n const d = new Date(ts)\n if (Number.isFinite(d.getTime())) return d.toISOString()\n } catch {\n // ignore\n }\n }\n\n // 2) Fallback: any valid timestamp (covers sessions that somehow have no messages).\n for (let i = lines.length - 1; i >= 0; i--) {\n const line = lines[i].trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n const ts = typeof obj?.timestamp === 'string' ? obj.timestamp : null\n if (!ts) continue\n const d = new Date(ts)\n if (Number.isFinite(d.getTime())) return d.toISOString()\n } catch {\n // ignore\n }\n }\n\n return null\n}\n\nfunction pickFallbackTitleFromHead(path: string): string | null {\n // Fallback to first user message.\n // NOTE: we keep this simple: read a small head chunk and parse line-by-line.\n try {\n const raw = readFileSync(path, { encoding: 'utf8' })\n const lines = raw.split(/\\r?\\n/)\n for (const line0 of lines) {\n const line = line0.trim()\n if (!line) continue\n try {\n const obj = JSON.parse(line) as any\n if (obj?.type === 'message' && obj?.message?.role === 'user') {\n const content = obj?.message?.content\n if (typeof content === 'string') return content.slice(0, 80)\n if (Array.isArray(content)) {\n const t = content.find((c: any) => c?.type === 'text' && typeof c?.text === 'string')\n if (t?.text) return String(t.text).slice(0, 80)\n }\n }\n } catch {\n // ignore\n }\n\n // Avoid scanning extremely large files fully.\n // If we didn't find a user message in the first ~2000 lines, give up.\n // (Most sessions have it early.)\n if (lines.length > 2000) break\n }\n } catch {\n // ignore\n }\n\n return null\n}\n\nexport function listPiSessions(): PiSessionListItem[] {\n const sessionsDir = getPiSessionsDir()\n const files: string[] = []\n walkJsonlFiles(sessionsDir, files)\n\n const items: PiSessionListItem[] = []\n\n for (const file of files) {\n const first = readFirstLine(file)\n if (!first) continue\n const header = parseSessionHeader(first)\n if (!header) continue\n\n let updatedAt: string | null = null\n\n let title: string | null = null\n try {\n const tail = readTail(file)\n title = pickTitleFromTail(tail)\n updatedAt = pickUpdatedAtFromTail(tail)\n } catch {\n // ignore\n }\n\n // If the session was named early and grew large, it may fall outside of the tail window.\n if (!title) {\n title = scanSessionInfoNameFromFile(file)\n }\n\n // Fallback for updatedAt when we couldn't parse timestamps from tail.\n if (!updatedAt) {\n try {\n updatedAt = statSync(file).mtime.toISOString()\n } catch {\n updatedAt = null\n }\n }\n\n if (!title) {\n title = pickFallbackTitleFromHead(file)\n }\n\n items.push({\n sessionId: header.sessionId,\n cwd: header.cwd,\n title,\n updatedAt,\n sessionFile: file\n })\n }\n\n // Sort most recent first.\n items.sort((a, b) => {\n const aa = a.updatedAt ?? ''\n const bb = b.updatedAt ?? ''\n return bb.localeCompare(aa)\n })\n\n return items\n}\n\nexport function findPiSessionFile(sessionId: string): string | null {\n const all = listPiSessions()\n const found = all.find(s => s.sessionId === sessionId)\n return found?.sessionFile ?? null\n}\n","export function normalizePiMessageText(content: unknown): string {\n if (typeof content === 'string') return content\n if (!Array.isArray(content)) return ''\n return content\n .map((c: any) => (c?.type === 'text' && typeof c.text === 'string' ? c.text : ''))\n .filter(Boolean)\n .join('')\n}\n\nexport function normalizePiAssistantText(content: unknown): string {\n // Assistant content is typically an array of blocks; only replay text blocks for MVP.\n if (!Array.isArray(content)) return ''\n return content\n .map((c: any) => (c?.type === 'text' && typeof c.text === 'string' ? c.text : ''))\n .filter(Boolean)\n .join('')\n}\n","import type { ContentBlock } from '@agentclientprotocol/sdk'\n\nexport type PiImage = {\n type: 'image'\n mimeType: string\n data: string\n}\n\nexport function promptToPiMessage(blocks: ContentBlock[]): {\n message: string\n images: PiImage[]\n} {\n let message = ''\n const images: PiImage[] = []\n\n for (const b of blocks) {\n switch (b.type) {\n case 'text':\n message += b.text\n break\n\n case 'resource_link':\n // A lightweight, human-readable hint for the LLM.\n message += `\\n[Context] ${b.uri}`\n break\n\n case 'image': {\n // pi expects base64 image bytes in `data` without a data-url prefix.\n images.push({\n type: 'image',\n mimeType: b.mimeType,\n data: b.data\n })\n break\n }\n\n case 'resource': {\n // Clients should not send this if embeddedContext=false, but be resilient.\n const r: any = (b as any).resource\n const uri = typeof r?.uri === 'string' ? r.uri : '(unknown)'\n\n if (typeof r?.text === 'string') {\n // TextResourceContents\n const mime = typeof r?.mimeType === 'string' ? r.mimeType : 'text/plain'\n message += `\\n[Embedded Context] ${uri} (${mime})\\n${r.text}`\n } else if (typeof r?.blob === 'string') {\n // BlobResourceContents\n const mime = typeof r?.mimeType === 'string' ? r.mimeType : 'application/octet-stream'\n const bytes = Buffer.byteLength(r.blob, 'base64')\n message += `\\n[Embedded Context] ${uri} (${mime}, ${bytes} bytes)`\n } else {\n message += `\\n[Embedded Context] ${uri}`\n }\n break\n }\n\n case 'audio': {\n // Not supported by pi. Provide a marker so we don't silently drop context.\n const bytes = Buffer.byteLength(b.data, 'base64')\n message += `\\n[Audio] (${b.mimeType}, ${bytes} bytes) not supported by pi-acp`\n break\n }\n\n default:\n // Ignore unknown block types for now.\n break\n }\n }\n\n return { message, images }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join, resolve } from 'node:path'\n\nfunction isObject(x: unknown): x is Record<string, unknown> {\n return Boolean(x) && typeof x === 'object' && !Array.isArray(x)\n}\n\nfunction deepMerge(a: Record<string, unknown>, b: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = { ...a }\n for (const [k, v] of Object.entries(b)) {\n const av = out[k]\n if (isObject(av) && isObject(v)) out[k] = deepMerge(av, v)\n else out[k] = v\n }\n return out\n}\n\nfunction readJsonFile(path: string): Record<string, unknown> {\n try {\n if (!existsSync(path)) return {}\n const raw = readFileSync(path, 'utf-8')\n const data = JSON.parse(raw)\n return isObject(data) ? data : {}\n } catch {\n return {}\n }\n}\n\nfunction getMergedSettings(cwd: string): Record<string, unknown> {\n const globalSettingsPath = join(getAgentDir(), 'settings.json')\n const projectSettingsPath = resolve(cwd, '.pi', 'settings.json')\n\n const global = readJsonFile(globalSettingsPath)\n const project = readJsonFile(projectSettingsPath)\n return deepMerge(global, project)\n}\n\nexport function getAgentDir(): string {\n return process.env.PI_CODING_AGENT_DIR ? resolve(process.env.PI_CODING_AGENT_DIR) : join(homedir(), '.pi', 'agent')\n}\n\n/**\n * Mirror pi settings semantics (global + project merge, project overrides global).\n * Only returns the bits we currently need.\n */\nexport function getEnableSkillCommands(cwd: string): boolean {\n const merged = getMergedSettings(cwd)\n\n const direct = merged.enableSkillCommands\n if (typeof direct === 'boolean') return direct\n\n // Back-compat: some versions used skills.enableSkillCommands\n const nested = isObject(merged.skills) ? merged.skills.enableSkillCommands : undefined\n if (typeof nested === 'boolean') return nested\n\n return true\n}\n\n/**\n * Mirror pi's quietStartup setting: if true, pi suppresses the verbose startup prelude.\n * We use it to decide whether to synthesize + emit our own \"startup info\" message.\n */\nexport function getQuietStartup(cwd: string): boolean {\n const merged = getMergedSettings(cwd)\n\n const direct = merged.quietStartup\n if (typeof direct === 'boolean') return direct\n\n // Back-compat: some versions used quietStart\n const legacy = (merged as any).quietStart\n if (typeof legacy === 'boolean') return legacy\n\n return false\n}\n","import type { AvailableCommand } from '@agentclientprotocol/sdk'\n\nexport type PiRpcCommandInfo = {\n name?: unknown\n description?: unknown\n source?: unknown\n location?: unknown\n path?: unknown\n}\n\nfunction describeFallback(c: PiRpcCommandInfo): string {\n const source = typeof c.source === 'string' ? c.source : ''\n const location = typeof c.location === 'string' ? c.location : ''\n\n const parts: string[] = []\n if (source) parts.push(source)\n if (location) parts.push(location)\n\n return parts.length ? `(${parts.join(':')})` : '(command)'\n}\n\nexport function toAvailableCommandsFromPiGetCommands(\n data: unknown,\n opts?: { enableSkillCommands?: boolean; includeExtensionCommands?: boolean }\n): {\n commands: AvailableCommand[]\n raw: PiRpcCommandInfo[]\n} {\n const enableSkillCommands = opts?.enableSkillCommands ?? true\n const includeExtensionCommands = opts?.includeExtensionCommands ?? false\n\n const root: any = data\n const commandsRaw: PiRpcCommandInfo[] = Array.isArray(root?.commands) ? root.commands : Array.isArray(root?.data?.commands) ? root.data.commands : []\n\n const out: AvailableCommand[] = []\n\n for (const c of commandsRaw) {\n const name = typeof c?.name === 'string' ? c.name.trim() : ''\n if (!name) continue\n\n const source = typeof c?.source === 'string' ? c.source : ''\n if (!includeExtensionCommands && source === 'extension') continue\n\n if (!enableSkillCommands && name.startsWith('skill:')) continue\n\n const desc = typeof c?.description === 'string' ? c.description.trim() : ''\n\n out.push({\n name,\n description: desc || describeFallback(c)\n })\n }\n\n return { commands: out, raw: commandsRaw }\n}\n","import { existsSync, readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\n\nfunction safeReadJson(path: string): any | null {\n try {\n if (!existsSync(path)) return null\n const raw = readFileSync(path, 'utf-8')\n if (!raw.trim()) return null\n return JSON.parse(raw)\n } catch {\n return null\n }\n}\n\nexport function getPiAgentDir(): string {\n // pi-mono uses ENV_AGENT_DIR = `${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`.\n // Default APP_NAME is \"pi\".\n const envDir = process.env.PI_CODING_AGENT_DIR\n if (envDir) {\n if (envDir === '~') return homedir()\n if (envDir.startsWith('~/')) return homedir() + envDir.slice(1)\n return envDir\n }\n return join(homedir(), '.pi', 'agent')\n}\n\nexport function hasAnyPiAuthConfigured(): boolean {\n // 1) auth.json present and non-empty (api keys or oauth creds)\n const agentDir = getPiAgentDir()\n const authPath = join(agentDir, 'auth.json')\n const auth = safeReadJson(authPath)\n if (auth && typeof auth === 'object' && Object.keys(auth).length > 0) return true\n\n // 2) models.json with custom provider apiKey configured\n const modelsPath = join(agentDir, 'models.json')\n const models = safeReadJson(modelsPath)\n const providers = models?.providers\n if (providers && typeof providers === 'object') {\n for (const p of Object.values(providers as Record<string, any>)) {\n if (p && typeof p === 'object' && typeof (p as any).apiKey === 'string' && (p as any).apiKey.trim()) {\n // Note: pi treats a non-empty string as either env-var name OR literal secret.\n // So presence of apiKey config is enough to be considered \"auth configured\".\n return true\n }\n }\n }\n\n // 3) Known provider env vars (mirrors pi-ai getEnvApiKey mapping)\n const envVars = [\n 'OPENAI_API_KEY',\n 'AZURE_OPENAI_API_KEY',\n 'GEMINI_API_KEY',\n 'GROQ_API_KEY',\n 'CEREBRAS_API_KEY',\n 'XAI_API_KEY',\n 'OPENROUTER_API_KEY',\n 'AI_GATEWAY_API_KEY',\n 'ZAI_API_KEY',\n 'MISTRAL_API_KEY',\n 'MINIMAX_API_KEY',\n 'MINIMAX_CN_API_KEY',\n 'HF_TOKEN',\n 'OPENCODE_API_KEY',\n 'KIMI_API_KEY',\n // Copilot/github\n 'COPILOT_GITHUB_TOKEN',\n 'GH_TOKEN',\n 'GITHUB_TOKEN',\n // Anthropic oauth\n 'ANTHROPIC_OAUTH_TOKEN',\n 'ANTHROPIC_API_KEY'\n ]\n\n for (const k of envVars) {\n const v = process.env[k]\n if (typeof v === 'string' && v.trim()) return true\n }\n\n return false\n}\n"],"mappings":"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","names":["RequestError","RequestError","readFileSync","resolve","mkdirSync","dirname","readFileSync","homedir","join","RequestError","resolve","readFileSync","readdirSync","readFileSync","homedir","join","existsSync","readFileSync","homedir","join","resolve","isAbsolute","existsSync","readFileSync","readdirSync","statSync","join","dirname","existsSync","readFileSync","homedir","join","getPiAgentDir","isAbsolute","RequestError","dirname","join","existsSync","readFileSync","result","readdirSync","statSync","pkg","spawnSync","resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-acp",
3
- "version": "0.0.23",
3
+ "version": "0.0.25",
4
4
  "description": "ACP adapter for pi coding agent",
5
5
  "license": "MIT",
6
6
  "author": "Sergii Kozak <svkozak@gmail.com>",