pi-acp 0.0.20 → 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 +2 -4
- package/dist/index.js +57 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ This is an MVP-style adapter intended to be useful today and easy to iterate on.
|
|
|
21
21
|
- Adds a small set of built-in commands for headless/editor usage
|
|
22
22
|
- Supports skill commands (if enabled in pi settings, they appear as `/skill:skill-name` in the ACP client)
|
|
23
23
|
- Skills are loaded by pi directly and are available in ACP sessions
|
|
24
|
-
- (Zed)
|
|
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.
|
|
25
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.
|
|
26
26
|
|
|
27
27
|
## Prerequisites
|
|
@@ -50,9 +50,7 @@ Add the following to your Zed `settngs.json`:
|
|
|
50
50
|
"type": "custom",
|
|
51
51
|
"command": "npx",
|
|
52
52
|
"args": ["-y", "pi-acp"],
|
|
53
|
-
"env": {
|
|
54
|
-
"PI_ACP_STARTUP_INFO": "true" // optional, "true" by default
|
|
55
|
-
}
|
|
53
|
+
"env": {}
|
|
56
54
|
}
|
|
57
55
|
}
|
|
58
56
|
```
|
package/dist/index.js
CHANGED
|
@@ -531,6 +531,19 @@ var SessionManager = class {
|
|
|
531
531
|
maybeGet(sessionId) {
|
|
532
532
|
return this.sessions.get(sessionId);
|
|
533
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
|
+
}
|
|
534
547
|
async create(params) {
|
|
535
548
|
let proc;
|
|
536
549
|
try {
|
|
@@ -1254,21 +1267,32 @@ function readJsonFile(path) {
|
|
|
1254
1267
|
return {};
|
|
1255
1268
|
}
|
|
1256
1269
|
}
|
|
1257
|
-
function
|
|
1258
|
-
return process.env.PI_CODING_AGENT_DIR ? resolve2(process.env.PI_CODING_AGENT_DIR) : join4(homedir4(), ".pi", "agent");
|
|
1259
|
-
}
|
|
1260
|
-
function getEnableSkillCommands(cwd) {
|
|
1270
|
+
function getMergedSettings(cwd) {
|
|
1261
1271
|
const globalSettingsPath = join4(getAgentDir(), "settings.json");
|
|
1262
1272
|
const projectSettingsPath = resolve2(cwd, ".pi", "settings.json");
|
|
1263
1273
|
const global = readJsonFile(globalSettingsPath);
|
|
1264
1274
|
const project = readJsonFile(projectSettingsPath);
|
|
1265
|
-
|
|
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);
|
|
1266
1282
|
const direct = merged.enableSkillCommands;
|
|
1267
1283
|
if (typeof direct === "boolean") return direct;
|
|
1268
1284
|
const nested = isObject(merged.skills) ? merged.skills.enableSkillCommands : void 0;
|
|
1269
1285
|
if (typeof nested === "boolean") return nested;
|
|
1270
1286
|
return true;
|
|
1271
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
|
+
}
|
|
1272
1296
|
|
|
1273
1297
|
// src/acp/pi-commands.ts
|
|
1274
1298
|
function describeFallback(c) {
|
|
@@ -1377,14 +1401,6 @@ function hasAnyPiAuthConfigured() {
|
|
|
1377
1401
|
|
|
1378
1402
|
// src/acp/agent.ts
|
|
1379
1403
|
import { fileURLToPath } from "url";
|
|
1380
|
-
function booleanEnv(name, defaultValue) {
|
|
1381
|
-
const raw = process.env[name];
|
|
1382
|
-
if (raw == null) return defaultValue;
|
|
1383
|
-
const v = String(raw).trim().toLowerCase();
|
|
1384
|
-
if (v === "true") return true;
|
|
1385
|
-
if (v === "false") return false;
|
|
1386
|
-
return defaultValue;
|
|
1387
|
-
}
|
|
1388
1404
|
function builtinAvailableCommands() {
|
|
1389
1405
|
return [
|
|
1390
1406
|
{
|
|
@@ -1516,8 +1532,13 @@ var PiAcpAgent = class {
|
|
|
1516
1532
|
}
|
|
1517
1533
|
const models = await getModelState(session.proc);
|
|
1518
1534
|
const thinking = await getThinkingState(session.proc);
|
|
1519
|
-
const
|
|
1520
|
-
const
|
|
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
|
+
});
|
|
1521
1542
|
if (preludeText) session.setStartupInfo(preludeText);
|
|
1522
1543
|
const response = {
|
|
1523
1544
|
sessionId: session.sessionId,
|
|
@@ -1529,7 +1550,7 @@ var PiAcpAgent = class {
|
|
|
1529
1550
|
}
|
|
1530
1551
|
}
|
|
1531
1552
|
};
|
|
1532
|
-
if (
|
|
1553
|
+
if (preludeText) setTimeout(() => session.sendStartupInfoIfPending(), 0);
|
|
1533
1554
|
setTimeout(() => {
|
|
1534
1555
|
void (async () => {
|
|
1535
1556
|
try {
|
|
@@ -1960,6 +1981,7 @@ ${JSON.stringify(stats, null, 2)}`;
|
|
|
1960
1981
|
if (!isAbsolute2(params.cwd)) {
|
|
1961
1982
|
throw RequestError3.invalidParams(`cwd must be an absolute path: ${params.cwd}`);
|
|
1962
1983
|
}
|
|
1984
|
+
this.sessions.close(params.sessionId);
|
|
1963
1985
|
this.lastSessionCwd = params.cwd;
|
|
1964
1986
|
const stored = this.store.get(params.sessionId);
|
|
1965
1987
|
const sessionFile = stored?.sessionFile ?? findPiSessionFile(params.sessionId);
|
|
@@ -2203,10 +2225,26 @@ function compareSemver(a, b) {
|
|
|
2203
2225
|
}
|
|
2204
2226
|
return 0;
|
|
2205
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
|
+
}
|
|
2206
2245
|
function buildStartupInfo(opts) {
|
|
2207
2246
|
void opts.fileCommands;
|
|
2208
2247
|
const md = [];
|
|
2209
|
-
let updateNotice = null;
|
|
2210
2248
|
try {
|
|
2211
2249
|
const piVersion = spawnSync("pi", ["--version"], { encoding: "utf-8" });
|
|
2212
2250
|
const installed = String(piVersion.stdout ?? "").trim().replace(/^v/i, "");
|
|
@@ -2214,17 +2252,6 @@ function buildStartupInfo(opts) {
|
|
|
2214
2252
|
md.push(`pi v${installed}`);
|
|
2215
2253
|
md.push("---");
|
|
2216
2254
|
md.push("");
|
|
2217
|
-
try {
|
|
2218
|
-
const latestRes = spawnSync("npm", ["view", "@mariozechner/pi-coding-agent", "version"], {
|
|
2219
|
-
encoding: "utf-8",
|
|
2220
|
-
timeout: 800
|
|
2221
|
-
});
|
|
2222
|
-
const latest = String(latestRes.stdout ?? "").trim().replace(/^v/i, "");
|
|
2223
|
-
if (latest && isSemver(latest) && isSemver(installed) && compareSemver(latest, installed) > 0) {
|
|
2224
|
-
updateNotice = `New version available: v${latest} (installed v${installed}). Run: \`npm i -g @mariozechner/pi-coding-agent\``;
|
|
2225
|
-
}
|
|
2226
|
-
} catch {
|
|
2227
|
-
}
|
|
2228
2255
|
}
|
|
2229
2256
|
} catch {
|
|
2230
2257
|
}
|
|
@@ -2318,9 +2345,9 @@ function buildStartupInfo(opts) {
|
|
|
2318
2345
|
} catch {
|
|
2319
2346
|
}
|
|
2320
2347
|
addSection("Extensions", extItems);
|
|
2321
|
-
if (updateNotice) {
|
|
2348
|
+
if (opts.updateNotice) {
|
|
2322
2349
|
md.push("---");
|
|
2323
|
-
md.push(updateNotice);
|
|
2350
|
+
md.push(opts.updateNotice);
|
|
2324
2351
|
md.push("");
|
|
2325
2352
|
}
|
|
2326
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: '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 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 === '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 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: '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\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"]}
|