pi-acp 0.0.19 → 0.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,19 +6,7 @@ ACP ([Agent Client Protocol](https://agentclientprotocol.com/overview/introducti
6
6
 
7
7
  ## Status
8
8
 
9
- This is an MVP-style adapter intended to be useful today and easy to iterate on. Some ACP features may be not implemented or are not supported (see [Limitations](#limitations)). Development is centered around Zed editor support, other clients may have varying levels of compatibility.
10
-
11
- ## How it works
12
-
13
- - **ACP side:** JSON-RPC 2.0 over stdio using `@agentclientprotocol/sdk`
14
- - **Pi side:** spawns `pi --mode rpc` and communicates via newline-delimited JSON on stdio
15
- - **Session model:** 1 ACP session ↔ 1 `pi` subprocess
16
-
17
- High-level mapping:
18
-
19
- - `session/new` → spawn `pi --mode rpc` (working directory = `cwd`)
20
- - `session/prompt` → send `{ type: "prompt", message, images }` to pi and stream events back as `session/update`
21
- - `session/cancel` → send `{ type: "abort" }`
9
+ This is an MVP-style adapter intended to be useful today and easy to iterate on. Some ACP features may be not implemented or are not supported (see [Limitations](#limitations)). Development is centered around [Zed](https://zed.dev) editor support, other clients may have varying levels of compatibility.
22
10
 
23
11
  ## Features
24
12
 
@@ -31,9 +19,9 @@ High-level mapping:
31
19
  - Slash commands
32
20
  - Loads file-based slash commands compatible with pi’s conventions
33
21
  - Adds a small set of built-in commands for headless/editor usage
22
+ - Supports skill commands (if enabled in pi settings, they appear as `/skill:skill-name` in the ACP client)
34
23
  - Skills are loaded by pi directly and are available in ACP sessions
35
- - (Zed) On session start, `pi-acp` posts a markdown “startup info” block (pi version, context file, skills, prompts, extensions)
36
- - (Zed) By default, `pi-acp` emits a short markdown “startup info” block into the session (pi version, context, skills, prompts, extensions - similar to `pi` in the terminal). You can disable it by setting: `PI_ACP_STARTUP_INFO=false` (see below)
24
+ - (Zed) `pi-acp` emits a short markdown “startup info” block into the session (pi version, context, skills, prompts, extensions - similar to `pi` in the terminal). You can disable it by setting `quietStartup: true` in pi settings (`~/.pi/agent/settings.json` or `<project>/.pi/settings.json`). When `quietStartup` is enabled, `pi-acp` will still emit a 'New version available' message if the installed pi version is outdated.
37
25
  - (Zed) Session history is supported in Zed starting with [`v0.225.0`](https://zed.dev/releases/preview/0.225.0). Session loading / history maps to pi's session files. Sessions can be resumed both in `pi` and in the ACP client.
38
26
 
39
27
  ## Prerequisites
@@ -62,9 +50,7 @@ Add the following to your Zed `settngs.json`:
62
50
  "type": "custom",
63
51
  "command": "npx",
64
52
  "args": ["-y", "pi-acp"],
65
- "env": {
66
- "PI_ACP_STARTUP_INFO": "true" // optional, "true" by default
67
- }
53
+ "env": {}
68
54
  }
69
55
  }
70
56
  ```
@@ -125,6 +111,7 @@ These are expanded adapter-side (pi RPC mode doesn’t expand them).
125
111
  - `/autocompact on|off|toggle` – toggle automatic compaction
126
112
  - `/export` – export the current session to HTML in the session `cwd`
127
113
  - `/session` – show session stats (tokens/messages/cost/session file)
114
+ - `/name <name>` – set session display name
128
115
  - `/queue all|one-at-a-time` – set pi queue mode (unstable feature)
129
116
  - `/changelog` – print the installed pi changelog (best-effort)
130
117
  - `/steering` - maps to `pi` Steering Mode, get/set
@@ -138,16 +125,14 @@ Other built-in commands:
138
125
 
139
126
  #### 3) Skill commands
140
127
 
141
- - Skill commands can be enabled in pi settings and will appear in the slash command list in ACP host as `/skill:skill-name`.
128
+ - Skill commands can be enabled in pi settings and will appear in the slash command list in ACP client as `/skill:skill-name`.
142
129
 
143
130
  **Note**: Slash commands provided by pi extensions are not currently supported.
144
131
 
145
- ## Authentication / Setup (ACP Registry)
146
-
147
- This agent supports **Terminal Auth** for the ACP Registry.
132
+ ## Authentication (ACP Registry support)
148
133
 
134
+ This agent supports **Terminal Auth** for the [ACP Registry](https://agentclientprotocol.com/get-started/registry).
149
135
  In Zed, this will show an **Authenticate** banner that launches pi in a terminal.
150
-
151
136
  Launch pi in a terminal for interactive login/setup:
152
137
 
153
138
  ```bash
@@ -163,7 +148,7 @@ npm install
163
148
  npm run dev # run from src via tsx
164
149
  npm run build
165
150
  npm run lint
166
- npm test
151
+ npm run test
167
152
  ```
168
153
 
169
154
  Project layout:
@@ -174,7 +159,7 @@ Project layout:
174
159
  ## Limitations
175
160
 
176
161
  - No ACP filesystem delegation (`fs/*`) and no ACP terminal delegation (`terminal/*`). pi reads/writes and executes locally.
177
- - MCP servers are accepted in ACP params and stored in session state, but not wired through to pi.
162
+ - MCP servers are accepted in ACP params and stored in session state, but not wired through to pi (see [why](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/)). If you use [pi MCP adapter](https://github.com/nicobailon/pi-mcp-adapter) it will be available in the ACP client.
178
163
  - Assistant streaming is currently sent as `agent_message_chunk` (no separate thought stream).
179
164
  - Queue is implemented client-side and should work like pi's `one-at-a-time`
180
165
  - ~~ACP clients don't yet suport session history, but ACP sessions from `pi-acp` can be `/resume`d in pi directly~~
package/dist/index.js CHANGED
@@ -268,6 +268,10 @@ var PiRpcProcess = class _PiRpcProcess {
268
268
  if (!res.success) throw new Error(`pi get_session_stats failed: ${res.error ?? JSON.stringify(res.data)}`);
269
269
  return res.data;
270
270
  }
271
+ async setSessionName(name) {
272
+ const res = await this.request({ type: "set_session_name", name });
273
+ if (!res.success) throw new Error(`pi set_session_name failed: ${res.error ?? JSON.stringify(res.data)}`);
274
+ }
271
275
  async exportHtml(outputPath) {
272
276
  const res = await this.request({ type: "export_html", outputPath });
273
277
  if (!res.success) throw new Error(`pi export_html failed: ${res.error ?? JSON.stringify(res.data)}`);
@@ -527,6 +531,19 @@ var SessionManager = class {
527
531
  maybeGet(sessionId) {
528
532
  return this.sessions.get(sessionId);
529
533
  }
534
+ /**
535
+ * Dispose a session's underlying pi process and remove it from the manager.
536
+ * Used when clients explicitly reload a session and we want a fresh pi subprocess.
537
+ */
538
+ close(sessionId) {
539
+ const s = this.sessions.get(sessionId);
540
+ if (!s) return;
541
+ try {
542
+ s.proc.dispose?.();
543
+ } catch {
544
+ }
545
+ this.sessions.delete(sessionId);
546
+ }
530
547
  async create(params) {
531
548
  let proc;
532
549
  try {
@@ -1250,21 +1267,32 @@ function readJsonFile(path) {
1250
1267
  return {};
1251
1268
  }
1252
1269
  }
1253
- function getAgentDir() {
1254
- return process.env.PI_CODING_AGENT_DIR ? resolve2(process.env.PI_CODING_AGENT_DIR) : join4(homedir4(), ".pi", "agent");
1255
- }
1256
- function getEnableSkillCommands(cwd) {
1270
+ function getMergedSettings(cwd) {
1257
1271
  const globalSettingsPath = join4(getAgentDir(), "settings.json");
1258
1272
  const projectSettingsPath = resolve2(cwd, ".pi", "settings.json");
1259
1273
  const global = readJsonFile(globalSettingsPath);
1260
1274
  const project = readJsonFile(projectSettingsPath);
1261
- const merged = deepMerge(global, project);
1275
+ return deepMerge(global, project);
1276
+ }
1277
+ function getAgentDir() {
1278
+ return process.env.PI_CODING_AGENT_DIR ? resolve2(process.env.PI_CODING_AGENT_DIR) : join4(homedir4(), ".pi", "agent");
1279
+ }
1280
+ function getEnableSkillCommands(cwd) {
1281
+ const merged = getMergedSettings(cwd);
1262
1282
  const direct = merged.enableSkillCommands;
1263
1283
  if (typeof direct === "boolean") return direct;
1264
1284
  const nested = isObject(merged.skills) ? merged.skills.enableSkillCommands : void 0;
1265
1285
  if (typeof nested === "boolean") return nested;
1266
1286
  return true;
1267
1287
  }
1288
+ function getQuietStartup(cwd) {
1289
+ const merged = getMergedSettings(cwd);
1290
+ const direct = merged.quietStartup;
1291
+ if (typeof direct === "boolean") return direct;
1292
+ const legacy = merged.quietStart;
1293
+ if (typeof legacy === "boolean") return legacy;
1294
+ return false;
1295
+ }
1268
1296
 
1269
1297
  // src/acp/pi-commands.ts
1270
1298
  function describeFallback(c) {
@@ -1373,14 +1401,6 @@ function hasAnyPiAuthConfigured() {
1373
1401
 
1374
1402
  // src/acp/agent.ts
1375
1403
  import { fileURLToPath } from "url";
1376
- function booleanEnv(name, defaultValue) {
1377
- const raw = process.env[name];
1378
- if (raw == null) return defaultValue;
1379
- const v = String(raw).trim().toLowerCase();
1380
- if (v === "true") return true;
1381
- if (v === "false") return false;
1382
- return defaultValue;
1383
- }
1384
1404
  function builtinAvailableCommands() {
1385
1405
  return [
1386
1406
  {
@@ -1401,6 +1421,11 @@ function builtinAvailableCommands() {
1401
1421
  name: "session",
1402
1422
  description: "Show session stats (messages, tokens, cost, session file)"
1403
1423
  },
1424
+ {
1425
+ name: "name",
1426
+ description: "Set session display name",
1427
+ input: { hint: "<name>" }
1428
+ },
1404
1429
  {
1405
1430
  name: "steering",
1406
1431
  description: "Get/set pi steering message delivery mode (how queued steering messages are delivered)",
@@ -1507,8 +1532,13 @@ var PiAcpAgent = class {
1507
1532
  }
1508
1533
  const models = await getModelState(session.proc);
1509
1534
  const thinking = await getThinkingState(session.proc);
1510
- const showStartupInfo = booleanEnv("PI_ACP_STARTUP_INFO", true);
1511
- const preludeText = showStartupInfo ? buildStartupInfo({ cwd: params.cwd, fileCommands }) : "";
1535
+ const quietStartup = getQuietStartup(params.cwd);
1536
+ const updateNotice = buildUpdateNotice();
1537
+ const preludeText = quietStartup ? updateNotice ? updateNotice + "\n" : "" : buildStartupInfo({
1538
+ cwd: params.cwd,
1539
+ fileCommands,
1540
+ updateNotice
1541
+ });
1512
1542
  if (preludeText) session.setStartupInfo(preludeText);
1513
1543
  const response = {
1514
1544
  sessionId: session.sessionId,
@@ -1520,7 +1550,7 @@ var PiAcpAgent = class {
1520
1550
  }
1521
1551
  }
1522
1552
  };
1523
- if (showStartupInfo) setTimeout(() => session.sendStartupInfoIfPending(), 0);
1553
+ if (preludeText) setTimeout(() => session.sendStartupInfoIfPending(), 0);
1524
1554
  setTimeout(() => {
1525
1555
  void (async () => {
1526
1556
  try {
@@ -1612,6 +1642,49 @@ ${JSON.stringify(stats, null, 2)}`;
1612
1642
  });
1613
1643
  return { stopReason: "end_turn" };
1614
1644
  }
1645
+ if (cmd === "name") {
1646
+ const name = args.join(" ").trim();
1647
+ if (!name) {
1648
+ await this.conn.sessionUpdate({
1649
+ sessionId: session.sessionId,
1650
+ update: {
1651
+ sessionUpdate: "agent_message_chunk",
1652
+ content: { type: "text", text: "Usage: /name <name>" }
1653
+ }
1654
+ });
1655
+ return { stopReason: "end_turn" };
1656
+ }
1657
+ try {
1658
+ await session.proc.setSessionName(name);
1659
+ } catch (e) {
1660
+ const msg = String(e?.message ?? e);
1661
+ const hint = /set_session_name/i.test(msg) ? " This requires a newer pi version that supports `set_session_name` in RPC mode." : "";
1662
+ await this.conn.sessionUpdate({
1663
+ sessionId: session.sessionId,
1664
+ update: {
1665
+ sessionUpdate: "agent_message_chunk",
1666
+ content: { type: "text", text: `Failed to set session name: ${msg}${hint}` }
1667
+ }
1668
+ });
1669
+ return { stopReason: "end_turn" };
1670
+ }
1671
+ await this.conn.sessionUpdate({
1672
+ sessionId: session.sessionId,
1673
+ update: {
1674
+ sessionUpdate: "session_info_update",
1675
+ title: name,
1676
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1677
+ }
1678
+ });
1679
+ await this.conn.sessionUpdate({
1680
+ sessionId: session.sessionId,
1681
+ update: {
1682
+ sessionUpdate: "agent_message_chunk",
1683
+ content: { type: "text", text: `Session name set: ${name}` }
1684
+ }
1685
+ });
1686
+ return { stopReason: "end_turn" };
1687
+ }
1615
1688
  if (cmd === "steering") {
1616
1689
  const modeRaw = String(args[0] ?? "").toLowerCase();
1617
1690
  const state = await session.proc.getState();
@@ -1908,6 +1981,7 @@ ${JSON.stringify(stats, null, 2)}`;
1908
1981
  if (!isAbsolute2(params.cwd)) {
1909
1982
  throw RequestError3.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
1910
1983
  }
1984
+ this.sessions.close(params.sessionId);
1911
1985
  this.lastSessionCwd = params.cwd;
1912
1986
  const stored = this.store.get(params.sessionId);
1913
1987
  const sessionFile = stored?.sessionFile ?? findPiSessionFile(params.sessionId);
@@ -2151,10 +2225,26 @@ function compareSemver(a, b) {
2151
2225
  }
2152
2226
  return 0;
2153
2227
  }
2228
+ function buildUpdateNotice() {
2229
+ try {
2230
+ const piVersion = spawnSync("pi", ["--version"], { encoding: "utf-8" });
2231
+ const installed = String(piVersion.stdout ?? "").trim().replace(/^v/i, "");
2232
+ if (!installed || !isSemver(installed)) return null;
2233
+ const latestRes = spawnSync("npm", ["view", "@mariozechner/pi-coding-agent", "version"], {
2234
+ encoding: "utf-8",
2235
+ timeout: 800
2236
+ });
2237
+ const latest = String(latestRes.stdout ?? "").trim().replace(/^v/i, "");
2238
+ if (!latest || !isSemver(latest)) return null;
2239
+ if (compareSemver(latest, installed) <= 0) return null;
2240
+ return `New version available: v${latest} (installed v${installed}). Run: \`npm i -g @mariozechner/pi-coding-agent\``;
2241
+ } catch {
2242
+ return null;
2243
+ }
2244
+ }
2154
2245
  function buildStartupInfo(opts) {
2155
2246
  void opts.fileCommands;
2156
2247
  const md = [];
2157
- let updateNotice = null;
2158
2248
  try {
2159
2249
  const piVersion = spawnSync("pi", ["--version"], { encoding: "utf-8" });
2160
2250
  const installed = String(piVersion.stdout ?? "").trim().replace(/^v/i, "");
@@ -2162,17 +2252,6 @@ function buildStartupInfo(opts) {
2162
2252
  md.push(`pi v${installed}`);
2163
2253
  md.push("---");
2164
2254
  md.push("");
2165
- try {
2166
- const latestRes = spawnSync("npm", ["view", "@mariozechner/pi-coding-agent", "version"], {
2167
- encoding: "utf-8",
2168
- timeout: 800
2169
- });
2170
- const latest = String(latestRes.stdout ?? "").trim().replace(/^v/i, "");
2171
- if (latest && isSemver(latest) && isSemver(installed) && compareSemver(latest, installed) > 0) {
2172
- updateNotice = `New version available: v${latest} (installed v${installed}). Run: \`npm i -g @mariozechner/pi-coding-agent\``;
2173
- }
2174
- } catch {
2175
- }
2176
2255
  }
2177
2256
  } catch {
2178
2257
  }
@@ -2266,9 +2345,9 @@ function buildStartupInfo(opts) {
2266
2345
  } catch {
2267
2346
  }
2268
2347
  addSection("Extensions", extItems);
2269
- if (updateNotice) {
2348
+ if (opts.updateNotice) {
2270
2349
  md.push("---");
2271
- md.push(updateNotice);
2350
+ md.push(opts.updateNotice);
2272
2351
  md.push("");
2273
2352
  }
2274
2353
  return md.join("\n").trim() + "\n";
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'\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 = process.env.PI_ACP_PI_COMMAND ?? '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\nnew AgentSideConnection(conn => new PiAcpAgent(conn), stream)\n\nprocess.stdin.resume()\nprocess.on('SIGINT', () => process.exit(0))\nprocess.on('SIGTERM', () => process.exit(0))\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 } 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 booleanEnv(name: string, defaultValue: boolean): boolean {\n const raw = process.env[name]\n if (raw == null) return defaultValue\n const v = String(raw).trim().toLowerCase()\n if (v === 'true') return true\n if (v === 'false') return false\n return defaultValue\n}\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: '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 // 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 // Proactive auth gate: if pi has no models available, it's effectively unauthenticated.\n let rawModelsCount = 0\n try {\n const data = (await session.proc.getAvailableModels()) as any\n rawModelsCount = Array.isArray(data?.models) ? data.models.length : 0\n } catch {\n // ignore\n }\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)\n const thinking = await getThinkingState(session.proc)\n\n const showStartupInfo = booleanEnv('PI_ACP_STARTUP_INFO', true)\n\n // In pi --mode rpc there typically is no human-readable prelude on stdout.\n // So we synthesize a similar \"startup info\" block from local data and emit it.\n const preludeText = showStartupInfo ? buildStartupInfo({ cwd: params.cwd, fileCommands }) : ''\n if (preludeText) session.setStartupInfo(preludeText)\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 (showStartupInfo) 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 === '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 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 // (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(proc: PiRpcProcess): 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 try {\n const state = (await proc.getState()) as any\n const tl = typeof state?.thinkingLevel === 'string' ? state.thinkingLevel : null\n if (tl && isThinkingLevel(tl)) current = tl\n } catch {\n // ignore\n }\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(proc: PiRpcProcess): Promise<{\n availableModels: ModelInfo[]\n currentModelId: string\n} | null> {\n // Ask pi for available models.\n let availableModels: ModelInfo[] = []\n try {\n const data = (await proc.getAvailableModels()) as any\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 } catch {\n // ignore\n }\n\n // Ask pi what model is currently active.\n let currentModelId: string | null = null\n try {\n const state = (await proc.getState()) as any\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 } catch {\n // ignore\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 buildStartupInfo(opts: { cwd: string; fileCommands: ReturnType<typeof loadSlashCommands> }): string {\n void opts.fileCommands\n\n const md: string[] = []\n\n let updateNotice: string | null = null\n\n // pi version header + update notice (best-effort, matches what users see in terminal startup)\n try {\n // No timeout here; in some environments process startup can be slow and we'd rather show the version.\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 // Best-effort update check against npm registry.\n // Important: keep it fast to not slow down session/new.\n try {\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) && isSemver(installed) && compareSemver(latest, installed) > 0) {\n updateNotice = `New version available: v${latest} (installed v${installed}). Run: \\`npm i -g @mariozechner/pi-coding-agent\\``\n }\n } catch {\n // ignore\n }\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 (updateNotice) {\n md.push('---')\n md.push(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 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\nexport class SessionManager {\n private sessions = new Map<string, PiAcpSession>()\n private readonly store = new SessionStore()\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 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 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 // If we have startup info pending, emit it as the first chunk of the first turn.\n // This is more reliable than sending a standalone sessionUpdate right after session/new,\n // because some clients won't render agent messages until a prompt occurs.\n if (!this.startupInfoSent && this.startupInfo) {\n this.startupInfoSent = true\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: this.startupInfo }\n })\n }\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 // 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 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 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 rawInput\n })\n }\n }\n\n break\n }\n\n // (MVP) ignore other delta types (thinking, etc.) 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\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 } catch {\n // Ignore snapshot failures; we'll fall back to plain text output.\n }\n }\n }\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 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 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'\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: '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 cmd = params.piCommand ?? 'pi'\n\n const args = ['--mode', 'rpc']\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 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\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 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 const merged = deepMerge(global, project)\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","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"]}
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'\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 = process.env.PI_ACP_PI_COMMAND ?? '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\nnew AgentSideConnection(conn => new PiAcpAgent(conn), stream)\n\nprocess.stdin.resume()\nprocess.on('SIGINT', () => process.exit(0))\nprocess.on('SIGTERM', () => process.exit(0))\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\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 // 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 // Proactive auth gate: if pi has no models available, it's effectively unauthenticated.\n let rawModelsCount = 0\n try {\n const data = (await session.proc.getAvailableModels()) as any\n rawModelsCount = Array.isArray(data?.models) ? data.models.length : 0\n } catch {\n // ignore\n }\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)\n const thinking = await getThinkingState(session.proc)\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 ? (updateNotice ? updateNotice + '\\n' : '') : buildStartupInfo({\n cwd: params.cwd,\n fileCommands,\n updateNotice\n })\n\n if (preludeText) session.setStartupInfo(preludeText)\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 // (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(proc: PiRpcProcess): 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 try {\n const state = (await proc.getState()) as any\n const tl = typeof state?.thinkingLevel === 'string' ? state.thinkingLevel : null\n if (tl && isThinkingLevel(tl)) current = tl\n } catch {\n // ignore\n }\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(proc: PiRpcProcess): Promise<{\n availableModels: ModelInfo[]\n currentModelId: string\n} | null> {\n // Ask pi for available models.\n let availableModels: ModelInfo[] = []\n try {\n const data = (await proc.getAvailableModels()) as any\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 } catch {\n // ignore\n }\n\n // Ask pi what model is currently active.\n let currentModelId: string | null = null\n try {\n const state = (await proc.getState()) as any\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 } catch {\n // ignore\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 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\nexport class SessionManager {\n private sessions = new Map<string, PiAcpSession>()\n private readonly store = new SessionStore()\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 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 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 // If we have startup info pending, emit it as the first chunk of the first turn.\n // This is more reliable than sending a standalone sessionUpdate right after session/new,\n // because some clients won't render agent messages until a prompt occurs.\n if (!this.startupInfoSent && this.startupInfo) {\n this.startupInfoSent = true\n this.emit({\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: this.startupInfo }\n })\n }\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 // 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 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 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 rawInput\n })\n }\n }\n\n break\n }\n\n // (MVP) ignore other delta types (thinking, etc.) 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\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 } catch {\n // Ignore snapshot failures; we'll fall back to plain text output.\n }\n }\n }\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 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 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'\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 cmd = params.piCommand ?? 'pi'\n\n const args = ['--mode', 'rpc']\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","spawnSync","resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-acp",
3
- "version": "0.0.19",
3
+ "version": "0.0.21",
4
4
  "description": "ACP adapter for pi coding agent",
5
5
  "license": "MIT",
6
6
  "author": "Sergii Kozak <svkozak@gmail.com>",