@victor-software-house/pi-acp 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,32 +1,93 @@
1
1
  #!/usr/bin/env node
2
2
  import { a as socketPath, i as removeStaleSocketIfAny, n as ensureSocketParentDir, r as releaseLock, t as acquireLock } from "./socket-BUNWxnAN.mjs";
3
- import { t as serveAcp } from "./serve-DgZht0tv.mjs";
3
+ import { t as serveAcp } from "./serve-DLukbpF4.mjs";
4
4
  import { createServer } from "node:net";
5
- //#region src/daemon/context.ts
6
- function createStubSessionRegistry() {
5
+ //#region src/daemon/session-registry.ts
6
+ function createSessionRegistry() {
7
7
  const map = /* @__PURE__ */ new Map();
8
8
  return {
9
- register(entry) {
10
- map.set(entry.sessionId, entry);
9
+ register(input) {
10
+ const entry = {
11
+ sessionId: input.sessionId,
12
+ piSession: input.piSession,
13
+ ownerConnectionId: input.ownerConnectionId,
14
+ alsoHeldBy: /* @__PURE__ */ new Set(),
15
+ cwd: input.cwd,
16
+ sessionFile: input.sessionFile,
17
+ updatedAt: /* @__PURE__ */ new Date()
18
+ };
19
+ map.set(input.sessionId, entry);
20
+ },
21
+ attach(sessionId, connectionId) {
22
+ const entry = map.get(sessionId);
23
+ if (entry === void 0) return void 0;
24
+ if (entry.ownerConnectionId !== connectionId) {
25
+ entry.alsoHeldBy.add(connectionId);
26
+ entry.updatedAt = /* @__PURE__ */ new Date();
27
+ }
28
+ return entry;
11
29
  },
12
30
  release(sessionId, connectionId) {
13
31
  const entry = map.get(sessionId);
14
- if (!entry) return { unknown: true };
15
- entry.alsoHeldBy.delete(connectionId);
16
- if (entry.ownerConnectionId === connectionId && entry.alsoHeldBy.size === 0) {
32
+ if (entry === void 0) return { kind: "unknown" };
33
+ if (entry.alsoHeldBy.delete(connectionId)) {
34
+ entry.updatedAt = /* @__PURE__ */ new Date();
35
+ if (entry.ownerConnectionId === connectionId && entry.alsoHeldBy.size === 0) {
36
+ map.delete(sessionId);
37
+ return {
38
+ kind: "disposed",
39
+ entry
40
+ };
41
+ }
42
+ return {
43
+ kind: "still-held",
44
+ entry
45
+ };
46
+ }
47
+ if (entry.ownerConnectionId === connectionId) {
48
+ if (entry.alsoHeldBy.size > 0) {
49
+ const next = entry.alsoHeldBy.values().next().value;
50
+ if (next !== void 0) {
51
+ entry.alsoHeldBy.delete(next);
52
+ entry.ownerConnectionId = next;
53
+ entry.updatedAt = /* @__PURE__ */ new Date();
54
+ return {
55
+ kind: "still-held",
56
+ entry
57
+ };
58
+ }
59
+ }
17
60
  map.delete(sessionId);
18
- return { disposed: true };
61
+ return {
62
+ kind: "disposed",
63
+ entry
64
+ };
19
65
  }
20
- return { disposed: false };
66
+ return {
67
+ kind: "still-held",
68
+ entry
69
+ };
70
+ },
71
+ get(sessionId) {
72
+ return map.get(sessionId);
21
73
  },
22
74
  listAll() {
23
75
  return Array.from(map.values());
24
76
  },
25
- get(sessionId) {
26
- return map.get(sessionId);
77
+ listOwnedBy(connectionId) {
78
+ return Array.from(map.values()).filter((e) => e.ownerConnectionId === connectionId || e.alsoHeldBy.has(connectionId));
27
79
  }
28
80
  };
29
81
  }
82
+ //#endregion
83
+ //#region src/daemon/context.ts
84
+ /**
85
+ * Daemon-level shared state injected into per-connection PiAcpAgent instances.
86
+ *
87
+ * Phase 1 landed the interface + stub IdleTracker.
88
+ * Phase 2 wires the real SessionRegistry.
89
+ * Phase 3 will replace IdleTracker.
90
+ */
30
91
  function createNoopIdleTracker() {
31
92
  return {
32
93
  bump() {},
@@ -35,7 +96,7 @@ function createNoopIdleTracker() {
35
96
  }
36
97
  function createDaemonContext() {
37
98
  return {
38
- sessionRegistry: createStubSessionRegistry(),
99
+ sessionRegistry: createSessionRegistry(),
39
100
  idleTracker: createNoopIdleTracker()
40
101
  };
41
102
  }
@@ -125,4 +186,4 @@ async function runDaemon() {
125
186
  //#endregion
126
187
  export { runDaemon };
127
188
 
128
- //# sourceMappingURL=daemon-y7gCaXDq.mjs.map
189
+ //# sourceMappingURL=daemon-irIzm1zJ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"daemon-irIzm1zJ.mjs","names":[],"sources":["../src/daemon/session-registry.ts","../src/daemon/context.ts","../src/daemon/index.ts"],"sourcesContent":["/**\n * Daemon-level session registry. Maps sessionId -> live AgentSession plus\n * ownership refcount so that closing a session from one client does NOT\n * dispose the underlying pi runtime if another client also holds it.\n */\n\nimport type { AgentSession } from \"@earendil-works/pi-coding-agent\";\n\nexport interface SessionEntry {\n\tsessionId: string;\n\tpiSession: AgentSession;\n\townerConnectionId: string;\n\talsoHeldBy: Set<string>;\n\tcwd: string;\n\tsessionFile: string | undefined;\n\tupdatedAt: Date;\n}\n\nexport interface SessionRegistry {\n\tregister(entry: NewSessionEntry): void;\n\tattach(sessionId: string, connectionId: string): SessionEntry | undefined;\n\trelease(sessionId: string, connectionId: string): ReleaseResult;\n\tget(sessionId: string): SessionEntry | undefined;\n\tlistAll(): SessionEntry[];\n\tlistOwnedBy(connectionId: string): SessionEntry[];\n}\n\nexport interface NewSessionEntry {\n\tsessionId: string;\n\tpiSession: AgentSession;\n\townerConnectionId: string;\n\tcwd: string;\n\tsessionFile: string | undefined;\n}\n\nexport type ReleaseResult =\n\t| { kind: \"disposed\"; entry: SessionEntry }\n\t| { kind: \"still-held\"; entry: SessionEntry }\n\t| { kind: \"unknown\" };\n\nexport function createSessionRegistry(): SessionRegistry {\n\tconst map = new Map<string, SessionEntry>();\n\n\treturn {\n\t\tregister(input) {\n\t\t\tconst entry: SessionEntry = {\n\t\t\t\tsessionId: input.sessionId,\n\t\t\t\tpiSession: input.piSession,\n\t\t\t\townerConnectionId: input.ownerConnectionId,\n\t\t\t\talsoHeldBy: new Set<string>(),\n\t\t\t\tcwd: input.cwd,\n\t\t\t\tsessionFile: input.sessionFile,\n\t\t\t\tupdatedAt: new Date(),\n\t\t\t};\n\t\t\tmap.set(input.sessionId, entry);\n\t\t},\n\n\t\tattach(sessionId, connectionId) {\n\t\t\tconst entry = map.get(sessionId);\n\t\t\tif (entry === undefined) return undefined;\n\t\t\tif (entry.ownerConnectionId !== connectionId) {\n\t\t\t\tentry.alsoHeldBy.add(connectionId);\n\t\t\t\tentry.updatedAt = new Date();\n\t\t\t}\n\t\t\treturn entry;\n\t\t},\n\n\t\trelease(sessionId, connectionId) {\n\t\t\tconst entry = map.get(sessionId);\n\t\t\tif (entry === undefined) return { kind: \"unknown\" };\n\n\t\t\tif (entry.alsoHeldBy.delete(connectionId)) {\n\t\t\t\tentry.updatedAt = new Date();\n\t\t\t\tif (entry.ownerConnectionId === connectionId && entry.alsoHeldBy.size === 0) {\n\t\t\t\t\tmap.delete(sessionId);\n\t\t\t\t\treturn { kind: \"disposed\", entry };\n\t\t\t\t}\n\t\t\t\treturn { kind: \"still-held\", entry };\n\t\t\t}\n\n\t\t\tif (entry.ownerConnectionId === connectionId) {\n\t\t\t\tif (entry.alsoHeldBy.size > 0) {\n\t\t\t\t\t// Hand ownership to one of the still-holders so the entry\n\t\t\t\t\t// keeps a coherent owner record. Pick first by iteration.\n\t\t\t\t\tconst next = entry.alsoHeldBy.values().next().value;\n\t\t\t\t\tif (next !== undefined) {\n\t\t\t\t\t\tentry.alsoHeldBy.delete(next);\n\t\t\t\t\t\tentry.ownerConnectionId = next;\n\t\t\t\t\t\tentry.updatedAt = new Date();\n\t\t\t\t\t\treturn { kind: \"still-held\", entry };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tmap.delete(sessionId);\n\t\t\t\treturn { kind: \"disposed\", entry };\n\t\t\t}\n\n\t\t\treturn { kind: \"still-held\", entry };\n\t\t},\n\n\t\tget(sessionId) {\n\t\t\treturn map.get(sessionId);\n\t\t},\n\n\t\tlistAll() {\n\t\t\treturn Array.from(map.values());\n\t\t},\n\n\t\tlistOwnedBy(connectionId) {\n\t\t\treturn Array.from(map.values()).filter(\n\t\t\t\t(e) => e.ownerConnectionId === connectionId || e.alsoHeldBy.has(connectionId),\n\t\t\t);\n\t\t},\n\t};\n}\n","/**\n * Daemon-level shared state injected into per-connection PiAcpAgent instances.\n *\n * Phase 1 landed the interface + stub IdleTracker.\n * Phase 2 wires the real SessionRegistry.\n * Phase 3 will replace IdleTracker.\n */\n\nimport { createSessionRegistry, type SessionRegistry } from \"@pi-acp/daemon/session-registry\";\n\nexport interface DaemonContext {\n\t/** Cross-window session registry. PRD-003 FR-5. */\n\tsessionRegistry: SessionRegistry;\n\t/** Idle-shutdown tracker. Stub in Phase 1-2; real in Phase 3. */\n\tidleTracker: IdleTracker;\n}\n\n/** Phase-3 stub. Replaced when idle shutdown lands. */\nexport interface IdleTracker {\n\tbump(delta: 1 | -1): void;\n\tdispose(): void;\n}\n\nexport type { SessionEntry, SessionRegistry } from \"@pi-acp/daemon/session-registry\";\nexport { createSessionRegistry } from \"@pi-acp/daemon/session-registry\";\n\nexport function createNoopIdleTracker(): IdleTracker {\n\treturn {\n\t\tbump() {\n\t\t\t/* phase 3 wires this */\n\t\t},\n\t\tdispose() {\n\t\t\t/* phase 3 wires this */\n\t\t},\n\t};\n}\n\nexport function createDaemonContext(): DaemonContext {\n\treturn {\n\t\tsessionRegistry: createSessionRegistry(),\n\t\tidleTracker: createNoopIdleTracker(),\n\t};\n}\n","/**\n * Daemon entry point. Invoked when pi-acp is launched with `--daemon`.\n *\n * Lifecycle:\n * 1. Acquire per-UID lockfile (refuses if another daemon alive).\n * 2. Remove stale socket file if any (left by a dead prior daemon).\n * 3. Construct DaemonContext shared singletons (Phase 1: stubs).\n * 4. Bind socket; accept loop spawns a per-connection serveAcp instance.\n * 5. SIGINT / SIGTERM → graceful shutdown.\n */\n\nimport { createServer, type Server, type Socket } from \"node:net\";\nimport { createDaemonContext, type DaemonContext } from \"@pi-acp/daemon/context\";\nimport {\n\tacquireLock,\n\tensureSocketParentDir,\n\treleaseLock,\n\tremoveStaleSocketIfAny,\n\tsocketPath,\n} from \"@pi-acp/daemon/socket\";\nimport { type ServeHandle, serveAcp } from \"@pi-acp/runtime/serve\";\n\ninterface Connection {\n\tsocket: Socket;\n\thandle: ServeHandle;\n}\n\nexport async function runDaemon(): Promise<void> {\n\tconst lockResult = acquireLock();\n\tif (!lockResult.ok) {\n\t\tprocess.stderr.write(\n\t\t\t`pi-acp daemon: already running (pid ${lockResult.heldByPid ?? \"unknown\"})\\n`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tensureSocketParentDir();\n\tremoveStaleSocketIfAny();\n\n\tconst ctx: DaemonContext = createDaemonContext();\n\tconst connections = new Set<Connection>();\n\tlet shuttingDown = false;\n\n\tconst server: Server = createServer((socket) => {\n\t\tif (shuttingDown) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tconst handle = serveAcp({ input: socket, output: socket, daemonContext: ctx });\n\t\tconst entry: Connection = { socket, handle };\n\t\tconnections.add(entry);\n\t\tctx.idleTracker.bump(1);\n\n\t\tconst cleanup = (): void => {\n\t\t\tif (!connections.delete(entry)) return;\n\t\t\ttry {\n\t\t\t\thandle.dispose();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t\tctx.idleTracker.bump(-1);\n\t\t};\n\n\t\tsocket.on(\"close\", cleanup);\n\t\tsocket.on(\"error\", cleanup);\n\t});\n\n\tserver.on(\"error\", (err) => {\n\t\tprocess.stderr.write(`pi-acp daemon: server error: ${err.message}\\n`);\n\t});\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst path = socketPath();\n\t\tserver.listen(path, () => resolve());\n\t\tserver.once(\"error\", reject);\n\t});\n\n\tif (process.env[\"PI_ACP_DAEMON_DEBUG\"] === \"1\") {\n\t\tprocess.stderr.write(`pi-acp daemon: listening on ${socketPath()} (pid ${process.pid})\\n`);\n\t}\n\n\tconst shutdown = async (): Promise<void> => {\n\t\tif (shuttingDown) return;\n\t\tshuttingDown = true;\n\t\tserver.close();\n\t\tfor (const entry of connections) {\n\t\t\ttry {\n\t\t\t\tentry.handle.dispose();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tentry.socket.destroy();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tconnections.clear();\n\t\tctx.idleTracker.dispose();\n\t\tremoveStaleSocketIfAny();\n\t\treleaseLock();\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown();\n\t});\n}\n"],"mappings":";;;;;AAwCA,SAAgB,wBAAyC;CACxD,MAAM,sBAAM,IAAI,KAA2B;AAE3C,QAAO;EACN,SAAS,OAAO;GACf,MAAM,QAAsB;IAC3B,WAAW,MAAM;IACjB,WAAW,MAAM;IACjB,mBAAmB,MAAM;IACzB,4BAAY,IAAI,KAAa;IAC7B,KAAK,MAAM;IACX,aAAa,MAAM;IACnB,2BAAW,IAAI,MAAM;IACrB;AACD,OAAI,IAAI,MAAM,WAAW,MAAM;;EAGhC,OAAO,WAAW,cAAc;GAC/B,MAAM,QAAQ,IAAI,IAAI,UAAU;AAChC,OAAI,UAAU,KAAA,EAAW,QAAO,KAAA;AAChC,OAAI,MAAM,sBAAsB,cAAc;AAC7C,UAAM,WAAW,IAAI,aAAa;AAClC,UAAM,4BAAY,IAAI,MAAM;;AAE7B,UAAO;;EAGR,QAAQ,WAAW,cAAc;GAChC,MAAM,QAAQ,IAAI,IAAI,UAAU;AAChC,OAAI,UAAU,KAAA,EAAW,QAAO,EAAE,MAAM,WAAW;AAEnD,OAAI,MAAM,WAAW,OAAO,aAAa,EAAE;AAC1C,UAAM,4BAAY,IAAI,MAAM;AAC5B,QAAI,MAAM,sBAAsB,gBAAgB,MAAM,WAAW,SAAS,GAAG;AAC5E,SAAI,OAAO,UAAU;AACrB,YAAO;MAAE,MAAM;MAAY;MAAO;;AAEnC,WAAO;KAAE,MAAM;KAAc;KAAO;;AAGrC,OAAI,MAAM,sBAAsB,cAAc;AAC7C,QAAI,MAAM,WAAW,OAAO,GAAG;KAG9B,MAAM,OAAO,MAAM,WAAW,QAAQ,CAAC,MAAM,CAAC;AAC9C,SAAI,SAAS,KAAA,GAAW;AACvB,YAAM,WAAW,OAAO,KAAK;AAC7B,YAAM,oBAAoB;AAC1B,YAAM,4BAAY,IAAI,MAAM;AAC5B,aAAO;OAAE,MAAM;OAAc;OAAO;;;AAGtC,QAAI,OAAO,UAAU;AACrB,WAAO;KAAE,MAAM;KAAY;KAAO;;AAGnC,UAAO;IAAE,MAAM;IAAc;IAAO;;EAGrC,IAAI,WAAW;AACd,UAAO,IAAI,IAAI,UAAU;;EAG1B,UAAU;AACT,UAAO,MAAM,KAAK,IAAI,QAAQ,CAAC;;EAGhC,YAAY,cAAc;AACzB,UAAO,MAAM,KAAK,IAAI,QAAQ,CAAC,CAAC,QAC9B,MAAM,EAAE,sBAAsB,gBAAgB,EAAE,WAAW,IAAI,aAAa,CAC7E;;EAEF;;;;;;;;;;;ACtFF,SAAgB,wBAAqC;AACpD,QAAO;EACN,OAAO;EAGP,UAAU;EAGV;;AAGF,SAAgB,sBAAqC;AACpD,QAAO;EACN,iBAAiB,uBAAuB;EACxC,aAAa,uBAAuB;EACpC;;;;;;;;;;;;;;ACdF,eAAsB,YAA2B;CAChD,MAAM,aAAa,aAAa;AAChC,KAAI,CAAC,WAAW,IAAI;AACnB,UAAQ,OAAO,MACd,uCAAuC,WAAW,aAAa,UAAU,KACzE;AACD,UAAQ,KAAK,EAAE;;AAGhB,wBAAuB;AACvB,yBAAwB;CAExB,MAAM,MAAqB,qBAAqB;CAChD,MAAM,8BAAc,IAAI,KAAiB;CACzC,IAAI,eAAe;CAEnB,MAAM,SAAiB,cAAc,WAAW;AAC/C,MAAI,cAAc;AACjB,UAAO,SAAS;AAChB;;EAED,MAAM,SAAS,SAAS;GAAE,OAAO;GAAQ,QAAQ;GAAQ,eAAe;GAAK,CAAC;EAC9E,MAAM,QAAoB;GAAE;GAAQ;GAAQ;AAC5C,cAAY,IAAI,MAAM;AACtB,MAAI,YAAY,KAAK,EAAE;EAEvB,MAAM,gBAAsB;AAC3B,OAAI,CAAC,YAAY,OAAO,MAAM,CAAE;AAChC,OAAI;AACH,WAAO,SAAS;WACT;AAGR,OAAI,YAAY,KAAK,GAAG;;AAGzB,SAAO,GAAG,SAAS,QAAQ;AAC3B,SAAO,GAAG,SAAS,QAAQ;GAC1B;AAEF,QAAO,GAAG,UAAU,QAAQ;AAC3B,UAAQ,OAAO,MAAM,gCAAgC,IAAI,QAAQ,IAAI;GACpE;AAEF,OAAM,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,OAAO,YAAY;AACzB,SAAO,OAAO,YAAY,SAAS,CAAC;AACpC,SAAO,KAAK,SAAS,OAAO;GAC3B;AAEF,KAAI,QAAQ,IAAI,2BAA2B,IAC1C,SAAQ,OAAO,MAAM,+BAA+B,YAAY,CAAC,QAAQ,QAAQ,IAAI,KAAK;CAG3F,MAAM,WAAW,YAA2B;AAC3C,MAAI,aAAc;AAClB,iBAAe;AACf,SAAO,OAAO;AACd,OAAK,MAAM,SAAS,aAAa;AAChC,OAAI;AACH,UAAM,OAAO,SAAS;WACf;AAGR,OAAI;AACH,UAAM,OAAO,SAAS;WACf;;AAIT,cAAY,OAAO;AACnB,MAAI,YAAY,SAAS;AACzB,0BAAwB;AACxB,eAAa;AACb,UAAQ,KAAK,EAAE;;AAGhB,SAAQ,GAAG,gBAAgB;AACrB,YAAU;GACd;AACF,SAAQ,GAAG,iBAAiB;AACtB,YAAU;GACd"}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as serveAcp } from "./serve-DgZht0tv.mjs";
2
+ import { t as serveAcp } from "./serve-DLukbpF4.mjs";
3
3
  //#region src/runtime/in-process.ts
4
4
  /**
5
5
  * In-process ACP server. The v0.5 codepath, preserved as the `PI_ACP_NO_DAEMON`
@@ -28,4 +28,4 @@ function runInProcess() {
28
28
  //#endregion
29
29
  export { runInProcess };
30
30
 
31
- //# sourceMappingURL=in-process-DZBoxK5h.mjs.map
31
+ //# sourceMappingURL=in-process-DcAV6Sgx.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"in-process-DZBoxK5h.mjs","names":[],"sources":["../src/runtime/in-process.ts"],"sourcesContent":["/**\n * In-process ACP server. The v0.5 codepath, preserved as the `PI_ACP_NO_DAEMON`\n * escape hatch and reused by the daemon's own stdio-bridge fallback.\n *\n * Treats process.stdin/stdout as the ACP transport. Owns the shutdown\n * lifecycle (AgentSideConnection.closed + SIGINT/SIGTERM).\n */\n\nimport { serveAcp } from \"@pi-acp/runtime/serve\";\n\nexport function runInProcess(): void {\n\tconst handle = serveAcp({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t\t// No DaemonContext: behavior identical to v0.5.\n\t});\n\n\tlet shuttingDown = false;\n\tconst shutdown = (): void => {\n\t\tif (shuttingDown) return;\n\t\tshuttingDown = true;\n\t\thandle.dispose();\n\t\tprocess.exit(0);\n\t};\n\n\tvoid handle.connection.closed.then(shutdown);\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n\tprocess.stdout.on(\"error\", () => process.exit(0));\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,eAAqB;CACpC,MAAM,SAAS,SAAS;EACvB,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAEhB,CAAC;CAEF,IAAI,eAAe;CACnB,MAAM,iBAAuB;AAC5B,MAAI,aAAc;AAClB,iBAAe;AACf,SAAO,SAAS;AAChB,UAAQ,KAAK,EAAE;;AAGX,QAAO,WAAW,OAAO,KAAK,SAAS;AAE5C,SAAQ,GAAG,UAAU,SAAS;AAC9B,SAAQ,GAAG,WAAW,SAAS;AAC/B,SAAQ,OAAO,GAAG,eAAe,QAAQ,KAAK,EAAE,CAAC"}
1
+ {"version":3,"file":"in-process-DcAV6Sgx.mjs","names":[],"sources":["../src/runtime/in-process.ts"],"sourcesContent":["/**\n * In-process ACP server. The v0.5 codepath, preserved as the `PI_ACP_NO_DAEMON`\n * escape hatch and reused by the daemon's own stdio-bridge fallback.\n *\n * Treats process.stdin/stdout as the ACP transport. Owns the shutdown\n * lifecycle (AgentSideConnection.closed + SIGINT/SIGTERM).\n */\n\nimport { serveAcp } from \"@pi-acp/runtime/serve\";\n\nexport function runInProcess(): void {\n\tconst handle = serveAcp({\n\t\tinput: process.stdin,\n\t\toutput: process.stdout,\n\t\t// No DaemonContext: behavior identical to v0.5.\n\t});\n\n\tlet shuttingDown = false;\n\tconst shutdown = (): void => {\n\t\tif (shuttingDown) return;\n\t\tshuttingDown = true;\n\t\thandle.dispose();\n\t\tprocess.exit(0);\n\t};\n\n\tvoid handle.connection.closed.then(shutdown);\n\n\tprocess.on(\"SIGINT\", shutdown);\n\tprocess.on(\"SIGTERM\", shutdown);\n\tprocess.stdout.on(\"error\", () => process.exit(0));\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,eAAqB;CACpC,MAAM,SAAS,SAAS;EACvB,OAAO,QAAQ;EACf,QAAQ,QAAQ;EAEhB,CAAC;CAEF,IAAI,eAAe;CACnB,MAAM,iBAAuB;AAC5B,MAAI,aAAc;AAClB,iBAAe;AACf,SAAO,SAAS;AAChB,UAAQ,KAAK,EAAE;;AAGX,QAAO,WAAW,OAAO,KAAK,SAAS;AAE5C,SAAQ,GAAG,UAAU,SAAS;AAC9B,SAAQ,GAAG,WAAW,SAAS;AAC/B,SAAQ,OAAO,GAAG,eAAe,QAAQ,KAAK,EAAE,CAAC"}
package/dist/index.mjs CHANGED
@@ -25,10 +25,10 @@ import { platform } from "node:os";
25
25
  const argv = process.argv.slice(2);
26
26
  if (argv.includes("--terminal-login")) await runTerminalLogin();
27
27
  else if (argv.includes("--daemon")) {
28
- const { runDaemon } = await import("./daemon-y7gCaXDq.mjs");
28
+ const { runDaemon } = await import("./daemon-irIzm1zJ.mjs");
29
29
  await runDaemon();
30
30
  } else if (argv.includes("--no-daemon") || process.env["PI_ACP_NO_DAEMON"] === "1") {
31
- const { runInProcess } = await import("./in-process-DZBoxK5h.mjs");
31
+ const { runInProcess } = await import("./in-process-DcAV6Sgx.mjs");
32
32
  runInProcess();
33
33
  } else {
34
34
  const { runClient } = await import("./client-CTg5Oiz5.mjs");
@@ -4,6 +4,7 @@ import { spawnSync } from "node:child_process";
4
4
  import { existsSync, readFileSync, realpathSync } from "node:fs";
5
5
  import { dirname, isAbsolute, join, resolve } from "node:path";
6
6
  import { AgentSideConnection, RequestError, ndJsonStream } from "@agentclientprotocol/sdk";
7
+ import { randomUUID } from "node:crypto";
7
8
  import { SessionManager, createAgentSession } from "@earendil-works/pi-coding-agent";
8
9
  import * as z from "zod";
9
10
  //#region src/acp/auth.ts
@@ -627,6 +628,19 @@ var SessionManager$1 = class {
627
628
  } catch {}
628
629
  this.sessions.delete(sessionId);
629
630
  }
631
+ /**
632
+ * Drop this connection's PiAcpSession wrapper without disposing the
633
+ * underlying pi runtime. Used when the daemon SessionRegistry reports
634
+ * another client still holds the session.
635
+ */
636
+ detach(sessionId) {
637
+ const s = this.sessions.get(sessionId);
638
+ if (!s) return;
639
+ try {
640
+ s.unsubscribeOnly();
641
+ } catch {}
642
+ this.sessions.delete(sessionId);
643
+ }
630
644
  closeAllExcept(keepSessionId) {
631
645
  for (const id of this.sessions.keys()) if (id !== keepSessionId) this.close(id);
632
646
  }
@@ -671,6 +685,15 @@ var PiAcpSession = class {
671
685
  this.unsubscribe?.();
672
686
  this.piSession.dispose();
673
687
  }
688
+ /**
689
+ * Drop event subscription without disposing the underlying piSession.
690
+ * Used when the daemon registry transfers ownership to another connection
691
+ * that still holds this session.
692
+ */
693
+ unsubscribeOnly() {
694
+ this.unsubscribe?.();
695
+ this.unsubscribe = void 0;
696
+ }
674
697
  async prompt(message, images = []) {
675
698
  if (this.promptRunning) return new Promise((resolve, reject) => {
676
699
  this.pendingMessages.push({
@@ -1115,7 +1138,7 @@ function acpPromptToPiMessage(blocks) {
1115
1138
  //#endregion
1116
1139
  //#region package.json
1117
1140
  var name = "@victor-software-house/pi-acp";
1118
- var version = "0.6.0";
1141
+ var version = "0.7.0";
1119
1142
  //#endregion
1120
1143
  //#region src/acp/agent.ts
1121
1144
  /** Builtin ACP slash commands handled directly by the adapter. */
@@ -1206,15 +1229,36 @@ var PiAcpAgent = class {
1206
1229
  terminalAuth: false,
1207
1230
  gatewayAuth: false
1208
1231
  };
1232
+ daemonContext;
1233
+ /** Unique ID for this ACP connection. Used as the ownership key in the daemon SessionRegistry. */
1234
+ connectionId = randomUUID();
1209
1235
  dispose() {
1236
+ if (this.daemonContext !== void 0) {
1237
+ const registry = this.daemonContext.sessionRegistry;
1238
+ for (const entry of registry.listOwnedBy(this.connectionId)) if (registry.release(entry.sessionId, this.connectionId).kind === "disposed") try {
1239
+ entry.piSession.dispose();
1240
+ } catch {}
1241
+ }
1210
1242
  this.sessions.disposeAll();
1211
- this.daemonContext;
1212
1243
  }
1213
- daemonContext;
1214
1244
  constructor(conn, daemonContext) {
1215
1245
  this.conn = conn;
1216
1246
  this.daemonContext = daemonContext;
1217
1247
  }
1248
+ registerWithDaemon(input) {
1249
+ if (this.daemonContext === void 0) return;
1250
+ this.daemonContext.sessionRegistry.register({
1251
+ sessionId: input.sessionId,
1252
+ piSession: input.piSession,
1253
+ ownerConnectionId: this.connectionId,
1254
+ cwd: input.cwd,
1255
+ sessionFile: input.sessionFile
1256
+ });
1257
+ }
1258
+ releaseFromDaemon(sessionId) {
1259
+ if (this.daemonContext === void 0) return { disposed: true };
1260
+ return { disposed: this.daemonContext.sessionRegistry.release(sessionId, this.connectionId).kind === "disposed" };
1261
+ }
1218
1262
  async initialize(params) {
1219
1263
  const supportedVersion = 1;
1220
1264
  const requested = params.protocolVersion;
@@ -1275,6 +1319,12 @@ var PiAcpAgent = class {
1275
1319
  supportsTerminalOutput: this.clientCapabilities.terminalOutput
1276
1320
  });
1277
1321
  this.sessions.register(session);
1322
+ this.registerWithDaemon({
1323
+ sessionId,
1324
+ piSession,
1325
+ cwd: params.cwd,
1326
+ sessionFile
1327
+ });
1278
1328
  const modes = buildThinkingModes(piSession);
1279
1329
  const models = buildModelState(piSession);
1280
1330
  const configOptions = buildConfigOptions(modes, models);
@@ -1474,13 +1524,35 @@ var PiAcpAgent = class {
1474
1524
  }
1475
1525
  const start = params.cursor !== void 0 && params.cursor !== null ? Number.parseInt(params.cursor, 10) : 0;
1476
1526
  const PAGE_SIZE = 50;
1477
- return {
1478
- sessions: sessions.slice(start, start + PAGE_SIZE).map((s) => ({
1527
+ const page = sessions.slice(start, start + PAGE_SIZE);
1528
+ const liveSessions = this.daemonContext !== void 0 ? this.daemonContext.sessionRegistry.listAll() : [];
1529
+ const liveById = new Map(liveSessions.map((e) => [e.sessionId, e]));
1530
+ const acpSessions = page.map((s) => {
1531
+ const live = liveById.get(s.id);
1532
+ const isOwnedByThisConnection = live !== void 0 && (live.ownerConnectionId === this.connectionId || live.alsoHeldBy.has(this.connectionId));
1533
+ return {
1479
1534
  sessionId: s.id,
1480
1535
  cwd: s.cwd,
1481
1536
  title: (s.name !== void 0 && s.name !== "" ? s.name : null) ?? truncateSessionTitle(s.firstMessage) ?? null,
1482
- updatedAt: s.modified.toISOString()
1483
- })),
1537
+ updatedAt: s.modified.toISOString(),
1538
+ ...live !== void 0 ? { _meta: { piAcp: {
1539
+ live: true,
1540
+ ownedByThisConnection: isOwnedByThisConnection
1541
+ } } } : {}
1542
+ };
1543
+ });
1544
+ const seen = new Set(page.map((s) => s.id));
1545
+ return {
1546
+ sessions: [...liveSessions.filter((e) => !seen.has(e.sessionId)).map((e) => ({
1547
+ sessionId: e.sessionId,
1548
+ cwd: e.cwd,
1549
+ title: null,
1550
+ updatedAt: e.updatedAt.toISOString(),
1551
+ _meta: { piAcp: {
1552
+ live: true,
1553
+ ownedByThisConnection: e.ownerConnectionId === this.connectionId || e.alsoHeldBy.has(this.connectionId)
1554
+ } }
1555
+ })), ...acpSessions],
1484
1556
  nextCursor: start + PAGE_SIZE < sessions.length ? String(start + PAGE_SIZE) : null,
1485
1557
  _meta: {}
1486
1558
  };
@@ -1513,6 +1585,12 @@ var PiAcpAgent = class {
1513
1585
  supportsTerminalOutput: this.clientCapabilities.terminalOutput
1514
1586
  });
1515
1587
  this.sessions.register(session);
1588
+ this.registerWithDaemon({
1589
+ sessionId: params.sessionId,
1590
+ piSession,
1591
+ cwd: params.cwd,
1592
+ sessionFile
1593
+ });
1516
1594
  await this.replaySessionHistory(session, piSession.messages);
1517
1595
  const modes = buildThinkingModes(piSession);
1518
1596
  const models = buildModelState(piSession);
@@ -1539,8 +1617,11 @@ var PiAcpAgent = class {
1539
1617
  };
1540
1618
  }
1541
1619
  async closeSession(params) {
1542
- if (this.sessions.maybeGet(params.sessionId) === void 0) throw RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);
1543
- this.sessions.close(params.sessionId);
1620
+ const local = this.sessions.maybeGet(params.sessionId);
1621
+ const inRegistry = this.daemonContext?.sessionRegistry.get(params.sessionId);
1622
+ if (local === void 0 && inRegistry === void 0) throw RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);
1623
+ if (this.releaseFromDaemon(params.sessionId).disposed) this.sessions.close(params.sessionId);
1624
+ else if (local !== void 0) this.sessions.detach(params.sessionId);
1544
1625
  return {};
1545
1626
  }
1546
1627
  async resumeSession(params) {
@@ -1555,6 +1636,28 @@ var PiAcpAgent = class {
1555
1636
  models
1556
1637
  };
1557
1638
  }
1639
+ if (this.daemonContext !== void 0) {
1640
+ const attached = this.daemonContext.sessionRegistry.attach(params.sessionId, this.connectionId);
1641
+ if (attached !== void 0) {
1642
+ const session = new PiAcpSession({
1643
+ sessionId: params.sessionId,
1644
+ cwd: params.cwd,
1645
+ mcpServers: params.mcpServers ?? [],
1646
+ piSession: attached.piSession,
1647
+ conn: this.conn,
1648
+ supportsTerminalOutput: this.clientCapabilities.terminalOutput
1649
+ });
1650
+ this.sessions.register(session);
1651
+ if (attached.sessionFile !== void 0) this.sessionPaths.set(params.sessionId, attached.sessionFile);
1652
+ const modes = buildThinkingModes(attached.piSession);
1653
+ const models = buildModelState(attached.piSession);
1654
+ return {
1655
+ configOptions: buildConfigOptions(modes, models),
1656
+ modes,
1657
+ models
1658
+ };
1659
+ }
1660
+ }
1558
1661
  const sessionFile = await this.resolveSessionFile(params.sessionId);
1559
1662
  if (sessionFile === null) throw RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);
1560
1663
  let result;
@@ -1581,6 +1684,12 @@ var PiAcpAgent = class {
1581
1684
  });
1582
1685
  this.sessions.register(session);
1583
1686
  this.sessionPaths.set(params.sessionId, sessionFile);
1687
+ this.registerWithDaemon({
1688
+ sessionId: params.sessionId,
1689
+ piSession,
1690
+ cwd: params.cwd,
1691
+ sessionFile
1692
+ });
1584
1693
  const enableSkillCommands = skillCommandsEnabled(params.cwd);
1585
1694
  setTimeout(() => {
1586
1695
  (async () => {
@@ -1634,6 +1743,12 @@ var PiAcpAgent = class {
1634
1743
  supportsTerminalOutput: this.clientCapabilities.terminalOutput
1635
1744
  });
1636
1745
  this.sessions.register(session);
1746
+ this.registerWithDaemon({
1747
+ sessionId: newSessionId,
1748
+ piSession,
1749
+ cwd: params.cwd,
1750
+ sessionFile: newSessionFile
1751
+ });
1637
1752
  const enableSkillCommands = skillCommandsEnabled(params.cwd);
1638
1753
  setTimeout(() => {
1639
1754
  (async () => {
@@ -2145,4 +2260,4 @@ function toWebWritable(dst) {
2145
2260
  //#endregion
2146
2261
  export { serveAcp as t };
2147
2262
 
2148
- //# sourceMappingURL=serve-DgZht0tv.mjs.map
2263
+ //# sourceMappingURL=serve-DLukbpF4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"serve-DLukbpF4.mjs","names":["resolvePath","SessionManager","isTextBlock","SessionManager","pkgJson.name","pkgJson.version","PiSessionManager"],"sources":["../src/acp/auth.ts","../src/acp/auth-required.ts","../src/acp/client-capabilities.ts","../src/acp/model-alias.ts","../src/acp/pi-settings.ts","../src/acp/translate/tool-content.ts","../src/acp/unreachable.ts","../src/acp/session.ts","../src/acp/translate/pi-messages.ts","../src/acp/translate/prompt.ts","../package.json","../src/acp/agent.ts","../src/runtime/serve.ts"],"sourcesContent":["/**\n * Build ACP AuthMethod descriptors for terminal-based authentication.\n *\n * Supports both the registry-required \"type/args/env\" shape and Zed's\n * _meta[\"terminal-auth\"] extension for the Authenticate banner.\n */\n\nimport type { AuthMethod } from \"@agentclientprotocol/sdk\";\n\nexport const AUTH_METHOD_ID = \"pi_terminal_login\";\n\ninterface AuthMethodOptions {\n\tsupportsTerminalAuthMeta?: boolean;\n}\n\nexport function buildAuthMethods(opts?: AuthMethodOptions): AuthMethod[] {\n\tconst supportsTerminalAuthMeta = opts?.supportsTerminalAuthMeta ?? true;\n\n\tconst method: AuthMethod = {\n\t\tid: AUTH_METHOD_ID,\n\t\tname: \"Launch pi in the terminal\",\n\t\tdescription: \"Start pi in an interactive terminal to configure API keys or login\",\n\t\ttype: \"terminal\",\n\t\targs: [\"--terminal-login\"],\n\t\tenv: {},\n\t};\n\n\tif (supportsTerminalAuthMeta) {\n\t\tconst launch = resolveTerminalLaunchCommand();\n\t\tmethod._meta = {\n\t\t\t\"terminal-auth\": {\n\t\t\t\t...launch,\n\t\t\t\tlabel: \"Launch pi\",\n\t\t\t},\n\t\t};\n\t}\n\n\treturn [method];\n}\n\nfunction resolveTerminalLaunchCommand(): { command: string; args: string[] } {\n\tconst argv0 = process.argv[0] ?? \"node\";\n\tconst argv1 = process.argv[1];\n\n\tif (argv1 !== undefined && argv0.includes(\"node\") && argv1.endsWith(\".js\")) {\n\t\treturn { command: argv0, args: [argv1, \"--terminal-login\"] };\n\t}\n\n\treturn { command: \"pi-acp\", args: [\"--terminal-login\"] };\n}\n","/**\n * Detect common auth/credential errors from pi and surface them as ACP AUTH_REQUIRED.\n */\n\nimport { RequestError } from \"@agentclientprotocol/sdk\";\nimport { buildAuthMethods } from \"@pi-acp/acp/auth\";\n\nconst AUTH_ERROR_PATTERNS = [\n\t\"api key\",\n\t\"apikey\",\n\t\"missing key\",\n\t\"no key\",\n\t\"not configured\",\n\t\"unauthorized\",\n\t\"authentication\",\n\t\"permission denied\",\n\t\"forbidden\",\n\t\"401\",\n\t\"403\",\n];\n\nexport function detectAuthError(err: unknown): RequestError | null {\n\tconst text = err instanceof Error ? err.message : String(err ?? \"\");\n\tconst lower = text.toLowerCase();\n\n\tconst isAuthRelated = AUTH_ERROR_PATTERNS.some((p) => lower.includes(p));\n\tif (!isAuthRelated) return null;\n\n\treturn RequestError.authRequired(\n\t\t{ authMethods: buildAuthMethods() },\n\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t);\n}\n","/**\n * Parse and represent client capabilities from the ACP initialize request.\n *\n * Both reference implementations (claude-agent-acp, codex-acp) store and\n * use `clientCapabilities` for feature detection and auth method selection.\n */\n\nimport type { ClientCapabilities } from \"@agentclientprotocol/sdk\";\n\nexport interface ClientCapabilityFlags {\n\t/** Client supports terminal output metadata (info/output/exit lifecycle). */\n\tterminalOutput: boolean;\n\t/** Client supports terminal-based authentication with command metadata. */\n\tterminalAuth: boolean;\n\t/** Client supports gateway-based authentication. */\n\tgatewayAuth: boolean;\n}\n\n/**\n * Extract well-known capability flags from ACP `ClientCapabilities`.\n *\n * Reads from:\n * - `_meta.terminal_output` (terminal output rendering)\n * - `_meta.terminal-auth` (terminal auth with command metadata)\n * - `auth._meta.gateway` (gateway auth, future use)\n */\nexport function parseClientCapabilities(\n\tcaps: ClientCapabilities | undefined | null,\n): ClientCapabilityFlags {\n\tif (caps === undefined || caps === null) {\n\t\treturn { terminalOutput: false, terminalAuth: false, gatewayAuth: false };\n\t}\n\n\t// _meta is an optional declared property, safe to access with dot\n\tconst meta = caps._meta;\n\tconst terminalOutput =\n\t\ttypeof meta === \"object\" && meta !== null && meta[\"terminal_output\"] === true;\n\tconst terminalAuth = typeof meta === \"object\" && meta !== null && meta[\"terminal-auth\"] === true;\n\n\t// gateway auth lives under auth._meta.gateway (non-standard extension)\n\tlet gatewayAuth = false;\n\tif (\"auth\" in caps) {\n\t\tconst auth = caps.auth;\n\t\tif (typeof auth === \"object\" && auth !== null && \"_meta\" in auth) {\n\t\t\tconst authMeta = auth._meta;\n\t\t\tif (typeof authMeta === \"object\" && authMeta !== null && \"gateway\" in authMeta) {\n\t\t\t\tgatewayAuth = authMeta[\"gateway\"] === true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { terminalOutput, terminalAuth, gatewayAuth };\n}\n","/**\n * Model alias resolution for user-friendly model names.\n *\n * Lets users type \"opus\", \"sonnet\", \"opus[1m]\" instead of exact\n * \"provider/modelId\" strings. Uses tokenized matching and scoring\n * following the claude-agent-acp pattern.\n */\n\ninterface ModelEntry {\n\tprovider: string;\n\tid: string;\n\tname?: string | undefined;\n}\n\ninterface ResolvedModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Tokenize a string: split on non-alphanumeric, lowercase, strip \"claude\".\n */\nfunction tokenize(input: string): string[] {\n\treturn input\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((t) => t !== \"\" && t !== \"claude\");\n}\n\n/**\n * Extract a context hint in square brackets, e.g. \"opus[1m]\" -> { base: \"opus\", hint: \"1m\" }.\n */\nfunction extractContextHint(input: string): { base: string; hint: string | null } {\n\tconst match = /^(.+?)\\[([^\\]]+)\\]$/.exec(input);\n\tif (match !== null && match[1] !== undefined && match[2] !== undefined) {\n\t\treturn { base: match[1], hint: match[2] };\n\t}\n\treturn { base: input, hint: null };\n}\n\n/** Check if a string is purely numeric. */\nfunction isNumeric(s: string): boolean {\n\treturn /^\\d+$/.test(s);\n}\n\n/**\n * Score how well a model matches the given preference tokens.\n *\n * Returns a score >= 0 (higher is better), or -1 for no match.\n * Requires at least one non-numeric token to match to avoid false positives\n * from bare version numbers (e.g. \"4\" matching model version suffixes).\n */\nfunction scoreModel(model: ModelEntry, prefTokens: string[], hint: string | null): number {\n\tconst modelStr = `${model.provider}/${model.id}/${model.name ?? \"\"}`.toLowerCase();\n\tconst modelTokens = tokenize(modelStr);\n\n\tlet matched = 0;\n\tlet hasNonNumericMatch = false;\n\tfor (const pt of prefTokens) {\n\t\tif (modelTokens.some((mt) => mt.includes(pt) || pt.includes(mt))) {\n\t\t\tmatched++;\n\t\t\tif (!isNumeric(pt)) hasNonNumericMatch = true;\n\t\t}\n\t}\n\n\tif (matched === 0) return -1;\n\n\t// Require at least one non-numeric token to match -- prevents \"gpt-4\"\n\t// matching on the bare \"4\" version component.\n\tif (!hasNonNumericMatch) return -1;\n\n\tlet score = matched / prefTokens.length;\n\n\t// Bonus for hint match (e.g. \"1m\" context window hint)\n\tif (hint !== null && modelStr.includes(hint.toLowerCase())) {\n\t\tscore += 0.5;\n\t}\n\n\t// Bonus for exact substring match on model id\n\tconst pref = prefTokens.join(\"\");\n\tif (model.id.toLowerCase().includes(pref)) {\n\t\tscore += 0.25;\n\t}\n\n\treturn score;\n}\n\n/**\n * Resolve a user-friendly model preference to a concrete model.\n *\n * Matching strategy (in order):\n * 1. Exact match on \"provider/id\"\n * 2. Exact match on \"id\" alone\n * 3. Tokenized scored match with optional context hint\n *\n * Returns null if no model matches.\n */\nexport function resolveModelPreference(\n\tmodels: readonly ModelEntry[],\n\tpreference: string,\n): ResolvedModel | null {\n\tconst trimmed = preference.trim();\n\tif (trimmed === \"\") return null;\n\n\t// 1. Exact match on \"provider/id\"\n\tif (trimmed.includes(\"/\")) {\n\t\tconst [p, ...rest] = trimmed.split(\"/\");\n\t\tconst provider = p ?? \"\";\n\t\tconst id = rest.join(\"/\");\n\t\tconst exact = models.find(\n\t\t\t(m) =>\n\t\t\t\tm.provider.toLowerCase() === provider.toLowerCase() &&\n\t\t\t\tm.id.toLowerCase() === id.toLowerCase(),\n\t\t);\n\t\tif (exact !== undefined) return { provider: exact.provider, id: exact.id };\n\t}\n\n\t// 2. Exact match on id alone\n\tconst byId = models.find((m) => m.id.toLowerCase() === trimmed.toLowerCase());\n\tif (byId !== undefined) return { provider: byId.provider, id: byId.id };\n\n\t// 3. Tokenized scored match\n\tconst { base, hint } = extractContextHint(trimmed);\n\tconst prefTokens = tokenize(base);\n\tif (prefTokens.length === 0) return null;\n\n\tlet bestModel: ModelEntry | null = null;\n\tlet bestScore = -1;\n\n\tfor (const model of models) {\n\t\tconst s = scoreModel(model, prefTokens, hint);\n\t\tif (s > bestScore) {\n\t\t\tbestScore = s;\n\t\t\tbestModel = model;\n\t\t}\n\t}\n\n\t// Require at least 50% of preference tokens to match to avoid spurious hits\n\t// (e.g. \"gpt-4\" matching on the \"4\" token alone)\n\tif (bestModel === null || bestScore < 0.5) return null;\n\treturn { provider: bestModel.provider, id: bestModel.id };\n}\n","/**\n * Read pi settings from global and project config files.\n *\n * Settings are merged: project overrides global.\n * Paths follow pi-mono conventions:\n * Global: ~/.pi/agent/settings.json\n * Project: <cwd>/.pi/settings.json\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport * as z from \"zod\";\n\nconst piSettingsSchema = z.object({\n\tenableSkillCommands: z.boolean().optional(),\n\tquietStartup: z.boolean().optional(),\n\tquietStart: z.boolean().optional(),\n\tskills: z\n\t\t.object({\n\t\t\tenableSkillCommands: z.boolean().optional(),\n\t\t})\n\t\t.optional(),\n});\n\ntype PiSettings = z.infer<typeof piSettingsSchema>;\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n\treturn typeof x === \"object\" && x !== null && !Array.isArray(x);\n}\n\nfunction merge(\n\tbase: Record<string, unknown>,\n\toverride: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = { ...base };\n\tfor (const [key, val] of Object.entries(override)) {\n\t\tconst existing = result[key];\n\t\tif (isRecord(existing) && isRecord(val)) {\n\t\t\tresult[key] = merge(existing, val);\n\t\t} else {\n\t\t\tresult[key] = val;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction readJson(path: string): Record<string, unknown> {\n\ttry {\n\t\tif (!existsSync(path)) return {};\n\t\tconst data: unknown = JSON.parse(readFileSync(path, \"utf-8\"));\n\t\treturn isRecord(data) ? data : {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nexport function piAgentDir(): string {\n\treturn process.env.PI_CODING_AGENT_DIR !== undefined\n\t\t? resolve(process.env.PI_CODING_AGENT_DIR)\n\t\t: join(homedir(), \".pi\", \"agent\");\n}\n\nfunction resolvedSettings(cwd: string): PiSettings {\n\tconst globalPath = join(piAgentDir(), \"settings.json\");\n\tconst projectPath = resolve(cwd, \".pi\", \"settings.json\");\n\tconst merged = merge(readJson(globalPath), readJson(projectPath));\n\tconst result = piSettingsSchema.safeParse(merged);\n\treturn result.success ? result.data : {};\n}\n\nexport function skillCommandsEnabled(cwd: string): boolean {\n\tconst settings = resolvedSettings(cwd);\n\n\tif (typeof settings.enableSkillCommands === \"boolean\") {\n\t\treturn settings.enableSkillCommands;\n\t}\n\n\tif (typeof settings.skills?.enableSkillCommands === \"boolean\") {\n\t\treturn settings.skills.enableSkillCommands;\n\t}\n\n\treturn true;\n}\n","/**\n * Per-tool content formatting for ACP tool results.\n *\n * Dispatches formatting by tool name following the reference implementation\n * pattern (claude-agent-acp / codex-acp). Each tool type produces\n * `ToolCallContent[]` appropriate for its output shape.\n */\n\nimport type { ToolCallContent } from \"@agentclientprotocol/sdk\";\nimport * as z from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Zod schemas for pi tool result shapes\n// ---------------------------------------------------------------------------\n\nconst textBlockSchema = z.object({\n\ttype: z.literal(\"text\"),\n\ttext: z.string(),\n});\n\nconst imageBlockSchema = z.object({\n\ttype: z.literal(\"image\"),\n});\n\nconst contentBlockSchema = z.union([textBlockSchema, imageBlockSchema]);\n\nconst bashDetailsSchema = z.object({\n\tstdout: z.string().optional(),\n\tstderr: z.string().optional(),\n\toutput: z.string().optional(),\n\texitCode: z.number().optional(),\n\tcode: z.number().optional(),\n});\n\nconst bashResultSchema = z.object({\n\tcontent: z.array(z.unknown()).optional(),\n\tdetails: bashDetailsSchema.optional(),\n\tstdout: z.string().optional(),\n\tstderr: z.string().optional(),\n\toutput: z.string().optional(),\n\texitCode: z.number().optional(),\n\tcode: z.number().optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Extraction helpers\n// ---------------------------------------------------------------------------\n\nexport interface BashOutput {\n\toutput: string;\n\texitCode: number | undefined;\n}\n\n/**\n * Extract stdout/stderr and exit code from a pi bash/tmux result.\n */\nexport function extractBashOutput(result: unknown): BashOutput {\n\tif (result === null || result === undefined || typeof result !== \"object\") {\n\t\treturn { output: \"\", exitCode: undefined };\n\t}\n\n\tconst parsed = bashResultSchema.safeParse(result);\n\tif (!parsed.success) {\n\t\treturn { output: \"\", exitCode: undefined };\n\t}\n\n\tconst r = parsed.data;\n\tconst d = r.details;\n\n\t// Try content blocks first\n\tif (r.content !== undefined) {\n\t\tconst texts = r.content\n\t\t\t.map((block) => textBlockSchema.safeParse(block))\n\t\t\t.filter((res) => res.success)\n\t\t\t.map((res) => res.data.text);\n\t\tif (texts.length > 0) {\n\t\t\tconst exitCode = d?.exitCode ?? r.exitCode ?? d?.code ?? r.code;\n\t\t\treturn { output: texts.join(\"\"), exitCode };\n\t\t}\n\t}\n\n\tconst stdout = d?.stdout ?? r.stdout ?? d?.output ?? r.output;\n\tconst stderr = d?.stderr ?? r.stderr;\n\tconst exitCode = d?.exitCode ?? r.exitCode ?? d?.code ?? r.code;\n\n\tconst parts: string[] = [];\n\tif (stdout !== undefined && stdout.trim() !== \"\") parts.push(stdout);\n\tif (stderr !== undefined && stderr.trim() !== \"\") parts.push(stderr);\n\n\treturn { output: parts.join(\"\\n\"), exitCode };\n}\n\n/**\n * Extract text content from a pi tool result (generic).\n */\nexport function extractTextContent(result: unknown): string {\n\tif (result === null || result === undefined || typeof result !== \"object\") return \"\";\n\n\tif (\"content\" in result && Array.isArray(result.content)) {\n\t\tconst texts: string[] = [];\n\t\tfor (const block of result.content) {\n\t\t\tconst parsed = textBlockSchema.safeParse(block);\n\t\t\tif (parsed.success) texts.push(parsed.data.text);\n\t\t}\n\t\tif (texts.length > 0) return texts.join(\"\");\n\t}\n\n\ttry {\n\t\treturn JSON.stringify(result, null, 2);\n\t} catch {\n\t\treturn String(result);\n\t}\n}\n\n/**\n * Extract content blocks from a pi result, preserving type information.\n * Used for read results where images need to be preserved.\n */\nexport function extractContentBlocks(\n\tresult: unknown,\n): Array<{ type: \"text\"; text: string } | { type: \"image\" }> {\n\tif (result === null || result === undefined || typeof result !== \"object\") return [];\n\tif (!(\"content\" in result) || !Array.isArray(result.content)) return [];\n\n\tconst blocks: Array<{ type: \"text\"; text: string } | { type: \"image\" }> = [];\n\tfor (const raw of result.content) {\n\t\tconst parsed = contentBlockSchema.safeParse(raw);\n\t\tif (parsed.success) {\n\t\t\tblocks.push(parsed.data);\n\t\t}\n\t}\n\treturn blocks;\n}\n\n// ---------------------------------------------------------------------------\n// Markdown escaping via dynamic backtick fence wrapping\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest consecutive backtick sequence in a string.\n */\nfunction longestBacktickRun(text: string): number {\n\tlet max = 0;\n\tlet current = 0;\n\tfor (const ch of text) {\n\t\tif (ch === \"`\") {\n\t\t\tcurrent++;\n\t\t\tif (current > max) max = current;\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn max;\n}\n\n/**\n * Wrap text in a dynamically-sized backtick fence to prevent markdown rendering.\n *\n * Instead of character-level escaping (which fails on files containing backtick\n * sequences, indented code blocks, blockquotes, and list markers), this wraps\n * the entire text in a backtick fence whose length exceeds any backtick sequence\n * in the content. This approach is simpler and strictly more correct (following\n * the claude-agent-acp pattern).\n */\nexport function markdownEscape(text: string): string {\n\tif (text === \"\") return \"\";\n\n\tconst fenceLen = Math.max(3, longestBacktickRun(text) + 1);\n\tconst fence = \"`\".repeat(fenceLen);\n\n\t// Avoid a trailing double newline before the closing fence\n\tconst body = text.endsWith(\"\\n\") ? text.slice(0, -1) : text;\n\treturn `${fence}\\n${body}\\n${fence}`;\n}\n\n// ---------------------------------------------------------------------------\n// Per-tool content formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Format tool output into `ToolCallContent[]` by tool name.\n *\n * Returns the appropriate content shape for each tool type:\n * - bash/tmux: console code fences\n * - read: markdown-escaped text (images preserved)\n * - edit/write: empty (diff handled separately)\n * - lsp: code fences\n * - errors: code fences with failed status\n * - everything else: plain text\n */\nexport function formatToolContent(\n\ttoolName: string,\n\tresult: unknown,\n\tisError: boolean,\n): ToolCallContent[] {\n\t// Error path: wrap any error text in a code fence\n\tif (isError) {\n\t\tconst text = extractTextContent(result);\n\t\tif (text === \"\") return [];\n\t\treturn [{ type: \"content\", content: { type: \"text\", text: `\\`\\`\\`\\n${text}\\n\\`\\`\\`` } }];\n\t}\n\n\tswitch (toolName) {\n\t\tcase \"bash\":\n\t\tcase \"tmux\":\n\t\t\treturn formatBashContent(result);\n\n\t\tcase \"read\":\n\t\t\treturn formatReadContent(result);\n\n\t\tcase \"edit\":\n\t\tcase \"write\":\n\t\t\t// Diff content is handled separately in handleToolEnd.\n\t\t\t// Return empty so the diff path takes precedence.\n\t\t\treturn [];\n\n\t\tcase \"lsp\":\n\t\t\treturn formatLspContent(result);\n\n\t\tdefault:\n\t\t\treturn formatFallbackContent(result);\n\t}\n}\n\nfunction formatBashContent(result: unknown): ToolCallContent[] {\n\tconst { output, exitCode } = extractBashOutput(result);\n\tif (output === \"\" && exitCode === undefined) return [];\n\n\tconst parts: string[] = [];\n\tif (output !== \"\") {\n\t\tparts.push(`\\`\\`\\`console\\n${output}\\n\\`\\`\\``);\n\t}\n\tif (exitCode !== undefined && exitCode !== 0) {\n\t\tparts.push(`exit code: ${exitCode}`);\n\t}\n\n\tconst text = parts.join(\"\\n\\n\");\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text } }];\n}\n\nfunction formatReadContent(result: unknown): ToolCallContent[] {\n\tconst blocks = extractContentBlocks(result);\n\tif (blocks.length === 0) {\n\t\t// Check if the result explicitly has an empty content array\n\t\tif (\n\t\t\ttypeof result === \"object\" &&\n\t\t\tresult !== null &&\n\t\t\t\"content\" in result &&\n\t\t\tArray.isArray(result.content) &&\n\t\t\tresult.content.length === 0\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\t// Fallback to text extraction for results without content blocks\n\t\tconst text = extractTextContent(result);\n\t\tif (text === \"\") return [];\n\t\treturn [{ type: \"content\", content: { type: \"text\", text: markdownEscape(text) } }];\n\t}\n\n\tconst content: ToolCallContent[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\") {\n\t\t\tcontent.push({\n\t\t\t\ttype: \"content\",\n\t\t\t\tcontent: { type: \"text\", text: markdownEscape(block.text) },\n\t\t\t});\n\t\t}\n\t\t// Image blocks are preserved as-is (the ACP client handles rendering)\n\t\t// We skip them here since they need their original structure from the result\n\t}\n\n\t// If we only had image blocks and no text, return empty\n\treturn content;\n}\n\nfunction formatLspContent(result: unknown): ToolCallContent[] {\n\tconst text = extractTextContent(result);\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text: `\\`\\`\\`\\n${text}\\n\\`\\`\\`` } }];\n}\n\nfunction formatFallbackContent(result: unknown): ToolCallContent[] {\n\tconst text = extractTextContent(result);\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text } }];\n}\n\n/**\n * Wrap streaming output text in a console code fence for bash/tmux.\n *\n * Each streaming update is self-contained (full accumulated buffer),\n * following the codex-acp pattern.\n */\nexport function wrapStreamingBashOutput(text: string): string {\n\tif (text === \"\") return \"\";\n\treturn `\\`\\`\\`console\\n${text}\\n\\`\\`\\``;\n}\n","/**\n * Exhaustive switch/case helper.\n *\n * Writes unknown values to stderr instead of silently ignoring them, aiding\n * debugging when the pi SDK adds new event types. Never write to stdout: it\n * carries the ACP NDJSON stream and any other byte poisons the protocol.\n */\nexport function unreachable(value: never, context?: string): void {\n\tconst label = context !== undefined ? `[${context}] ` : \"\";\n\tprocess.stderr.write(`${label}Unhandled value: ${String(value)}\\n`);\n}\n","import { readFileSync } from \"node:fs\";\nimport { isAbsolute, resolve as resolvePath } from \"node:path\";\nimport {\n\ttype AgentSideConnection,\n\ttype ContentBlock,\n\ttype McpServer,\n\tRequestError,\n\ttype SessionUpdate,\n\ttype ToolCallContent,\n\ttype ToolCallLocation,\n\ttype ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport type { AgentEvent, AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessageEvent, ToolCall } from \"@earendil-works/pi-ai\";\nimport type { AgentSession, AgentSessionEvent } from \"@earendil-works/pi-coding-agent\";\nimport { formatToolContent, wrapStreamingBashOutput } from \"@pi-acp/acp/translate/tool-content\";\nimport { unreachable } from \"@pi-acp/acp/unreachable\";\nimport * as z from \"zod\";\n\nexport type StopReason = \"end_turn\" | \"cancelled\" | \"max_tokens\" | \"error\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction findUniqueLineNumber(text: string, needle: string): number | undefined {\n\tif (!needle) return undefined;\n\tconst first = text.indexOf(needle);\n\tif (first < 0) return undefined;\n\tif (text.indexOf(needle, first + needle.length) >= 0) return undefined;\n\n\tlet line = 1;\n\tfor (let i = 0; i < first; i++) {\n\t\tif (text.charCodeAt(i) === 10) line++;\n\t}\n\treturn line;\n}\n\nexport interface ToolArgs {\n\tpath?: string | undefined;\n\toldText?: string | undefined;\n\t[key: string]: unknown;\n}\n\nexport function resolveToolPath(\n\targs: ToolArgs,\n\tcwd: string,\n\tline?: number,\n): ToolCallLocation[] | undefined {\n\tconst p = args.path;\n\tif (p === undefined) return undefined;\n\n\tconst resolved = isAbsolute(p) ? p : resolvePath(cwd, p);\n\treturn [{ path: resolved, ...(typeof line === \"number\" ? { line } : {}) }];\n}\n\nexport function toToolKind(toolName: string): ToolKind {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn \"read\";\n\t\tcase \"write\":\n\t\tcase \"edit\":\n\t\t\treturn \"edit\";\n\t\tcase \"bash\":\n\t\tcase \"tmux\":\n\t\t\treturn \"execute\";\n\t\tcase \"lsp\":\n\t\t\treturn \"search\";\n\t\tdefault:\n\t\t\treturn \"other\";\n\t}\n}\n\nconst MAX_TITLE_LEN = 80;\n\nfunction truncateTitle(text: string): string {\n\tconst oneLine = text.replace(/\\n/g, \" \").trim();\n\tif (oneLine.length <= MAX_TITLE_LEN) return oneLine;\n\treturn `${oneLine.slice(0, MAX_TITLE_LEN - 1)}…`;\n}\n\nfunction capitalize(s: string): string {\n\tif (s.length === 0) return s;\n\treturn s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/**\n * Build a descriptive tool title from tool name and args.\n *\n * Returns a short human-readable label like \"Read src/index.ts\" or \"Run ls -la\".\n */\nexport function buildToolTitle(toolName: string, args: ToolArgs): string {\n\tconst p = args.path;\n\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn p !== undefined ? `Read ${p}` : \"Read\";\n\t\tcase \"write\":\n\t\t\treturn p !== undefined ? `Write ${p}` : \"Write\";\n\t\tcase \"edit\":\n\t\t\treturn p !== undefined ? `Edit ${p}` : \"Edit\";\n\t\tcase \"bash\": {\n\t\t\tconst command =\n\t\t\t\ttypeof args[\"command\"] === \"string\"\n\t\t\t\t\t? args[\"command\"]\n\t\t\t\t\t: typeof args[\"cmd\"] === \"string\"\n\t\t\t\t\t\t? args[\"cmd\"]\n\t\t\t\t\t\t: undefined;\n\t\t\treturn command !== undefined ? truncateTitle(`Run ${command}`) : \"bash\";\n\t\t}\n\t\tcase \"lsp\": {\n\t\t\tconst action = typeof args[\"action\"] === \"string\" ? args[\"action\"] : undefined;\n\t\t\tconst file = typeof args[\"file\"] === \"string\" ? args[\"file\"] : undefined;\n\t\t\tconst query = typeof args[\"query\"] === \"string\" ? args[\"query\"] : undefined;\n\t\t\tconst line = typeof args[\"line\"] === \"number\" ? args[\"line\"] : undefined;\n\t\t\tif (action !== undefined) {\n\t\t\t\tconst target = file !== undefined ? (line !== undefined ? `${file}:${line}` : file) : query;\n\t\t\t\treturn target !== undefined\n\t\t\t\t\t? truncateTitle(`${capitalize(action)} ${target}`)\n\t\t\t\t\t: capitalize(action);\n\t\t\t}\n\t\t\treturn \"LSP\";\n\t\t}\n\t\tcase \"tmux\": {\n\t\t\tconst action = typeof args[\"action\"] === \"string\" ? args[\"action\"] : undefined;\n\t\t\tconst command = typeof args[\"command\"] === \"string\" ? args[\"command\"] : undefined;\n\t\t\tconst name = typeof args[\"name\"] === \"string\" ? args[\"name\"] : undefined;\n\t\t\tif (action === \"run\" && command !== undefined) return truncateTitle(`Tmux: ${command}`);\n\t\t\tif (action !== undefined && name !== undefined)\n\t\t\t\treturn truncateTitle(`Tmux ${action} ${name}`);\n\t\t\tif (action !== undefined) return `Tmux ${action}`;\n\t\t\treturn \"Tmux\";\n\t\t}\n\t\tcase \"context_tag\": {\n\t\t\tconst name = typeof args[\"name\"] === \"string\" ? args[\"name\"] : undefined;\n\t\t\treturn name !== undefined ? `Tag ${name}` : \"Tag\";\n\t\t}\n\t\tcase \"context_log\":\n\t\t\treturn \"Context log\";\n\t\tcase \"context_checkout\": {\n\t\t\tconst target = typeof args[\"target\"] === \"string\" ? args[\"target\"] : undefined;\n\t\t\treturn target !== undefined ? truncateTitle(`Checkout ${target}`) : \"Checkout\";\n\t\t}\n\t\tcase \"claudemon\":\n\t\t\treturn \"Check quota\";\n\t\tdefault:\n\t\t\treturn toolName;\n\t}\n}\n\n/**\n * Map pi assistant stopReason to ACP StopReason.\n * pi: \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\"\n * ACP: \"end_turn\" | \"cancelled\" | \"max_tokens\" | \"error\"\n */\nfunction mapPiStopReason(piReason: string | null): StopReason {\n\tswitch (piReason) {\n\t\tcase \"stop\":\n\t\tcase \"toolUse\":\n\t\t\treturn \"end_turn\";\n\t\tcase \"length\":\n\t\t\treturn \"max_tokens\";\n\t\tcase \"aborted\":\n\t\t\treturn \"cancelled\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tdefault:\n\t\t\treturn \"end_turn\";\n\t}\n}\n\nfunction extractToolCallFromPartial(ame: AssistantMessageEvent): ToolCall | undefined {\n\tif (!(\"partial\" in ame)) return undefined;\n\tconst content = ame.partial.content;\n\tconst idx = \"contentIndex\" in ame ? ame.contentIndex : 0;\n\tconst block = content[idx];\n\tif (block && \"type\" in block && block.type === \"toolCall\") return block;\n\treturn undefined;\n}\n\nfunction parseToolInput(tc: ToolCall): ToolArgs {\n\treturn tc.arguments;\n}\n\nconst toolArgsSchema = z\n\t.object({\n\t\tpath: z.string().trim().optional(),\n\t\toldText: z.string().trim().optional(),\n\t})\n\t.loose();\n\nexport function toToolArgs(raw: unknown): ToolArgs {\n\tconst result = toolArgsSchema.safeParse(raw);\n\treturn result.success ? result.data : {};\n}\n\n// ---------------------------------------------------------------------------\n// _meta builder helpers\n// ---------------------------------------------------------------------------\n\ntype PiAcpMeta = Record<string, unknown>;\n\n/** Build the `_meta.piAcp` tool name metadata. */\nfunction buildToolMeta(toolName: string, extra?: PiAcpMeta): PiAcpMeta {\n\tconst base: PiAcpMeta = { piAcp: { toolName } };\n\tif (extra !== undefined) {\n\t\treturn { ...base, ...extra };\n\t}\n\treturn base;\n}\n\n// ---------------------------------------------------------------------------\n// Terminal tool classification\n// ---------------------------------------------------------------------------\n\n/** Tools that produce terminal-style output. */\nfunction isTerminalTool(toolName: string): boolean {\n\treturn toolName === \"bash\" || toolName === \"tmux\";\n}\n\n// ---------------------------------------------------------------------------\n// Session manager\n// ---------------------------------------------------------------------------\n\nexport class SessionManager {\n\tprivate sessions = new Map<string, PiAcpSession>();\n\n\tdisposeAll(): void {\n\t\tfor (const id of this.sessions.keys()) this.close(id);\n\t}\n\n\tmaybeGet(sessionId: string): PiAcpSession | undefined {\n\t\treturn this.sessions.get(sessionId);\n\t}\n\n\tclose(sessionId: string): void {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) return;\n\t\ttry {\n\t\t\ts.dispose();\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t\tthis.sessions.delete(sessionId);\n\t}\n\n\t/**\n\t * Drop this connection's PiAcpSession wrapper without disposing the\n\t * underlying pi runtime. Used when the daemon SessionRegistry reports\n\t * another client still holds the session.\n\t */\n\tdetach(sessionId: string): void {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) return;\n\t\ttry {\n\t\t\ts.unsubscribeOnly();\n\t\t} catch {\n\t\t\t// best-effort — fall back to full dispose if detach is unsupported\n\t\t}\n\t\tthis.sessions.delete(sessionId);\n\t}\n\n\tcloseAllExcept(keepSessionId: string): void {\n\t\tfor (const id of this.sessions.keys()) {\n\t\t\tif (id !== keepSessionId) this.close(id);\n\t\t}\n\t}\n\n\tregister(session: PiAcpSession): void {\n\t\tthis.sessions.set(session.sessionId, session);\n\t}\n\n\tget(sessionId: string): PiAcpSession {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) throw RequestError.invalidParams(`Unknown sessionId: ${sessionId}`);\n\t\treturn s;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// ACP session wrapping a pi AgentSession\n// ---------------------------------------------------------------------------\n\nexport interface PiAcpSessionOpts {\n\tsessionId: string;\n\tcwd: string;\n\tmcpServers: McpServer[];\n\tpiSession: AgentSession;\n\tconn: AgentSideConnection;\n\t/** Whether the client supports terminal output metadata. */\n\tsupportsTerminalOutput?: boolean | undefined;\n}\n\nexport class PiAcpSession {\n\treadonly sessionId: string;\n\treadonly cwd: string;\n\treadonly mcpServers: McpServer[];\n\treadonly piSession: AgentSession;\n\treadonly supportsTerminalOutput: boolean;\n\n\tprivate readonly conn: AgentSideConnection;\n\n\tprivate cancelRequested = false;\n\tprivate promptRunning = false;\n\tprivate pendingTurn: { resolve: (r: StopReason) => void; reject: (e: unknown) => void } | null =\n\t\tnull;\n\t/** Queued prompts waiting for the active turn to complete. */\n\tprivate pendingMessages: Array<{\n\t\tmessage: string;\n\t\timages: unknown[];\n\t\tresolve: (r: StopReason) => void;\n\t\treject: (e: unknown) => void;\n\t}> = [];\n\n\tprivate currentToolCalls = new Map<string, \"pending\" | \"in_progress\">();\n\t/** Map of toolCallId -> toolName for streaming updates (Phase 5). */\n\tprivate toolCallNames = new Map<string, string>();\n\tprivate editSnapshots = new Map<string, { path: string; oldText: string }>();\n\tprivate lastAssistantStopReason: string | null = null;\n\tprivate lastEmit: Promise<void> = Promise.resolve();\n\tprivate unsubscribe: (() => void) | undefined;\n\n\tconstructor(opts: PiAcpSessionOpts) {\n\t\tthis.sessionId = opts.sessionId;\n\t\tthis.cwd = opts.cwd;\n\t\tthis.mcpServers = opts.mcpServers;\n\t\tthis.piSession = opts.piSession;\n\t\tthis.conn = opts.conn;\n\t\tthis.supportsTerminalOutput = opts.supportsTerminalOutput ?? false;\n\t\tthis.unsubscribe = this.piSession.subscribe((ev: AgentSessionEvent) => this.handlePiEvent(ev));\n\t}\n\n\tdispose(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.piSession.dispose();\n\t}\n\n\t/**\n\t * Drop event subscription without disposing the underlying piSession.\n\t * Used when the daemon registry transfers ownership to another connection\n\t * that still holds this session.\n\t */\n\tunsubscribeOnly(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.unsubscribe = undefined;\n\t}\n\n\tasync prompt(message: string, images: unknown[] = []): Promise<StopReason> {\n\t\t// If a prompt is already running, queue this one and return a promise\n\t\t// that resolves when it eventually executes.\n\t\tif (this.promptRunning) {\n\t\t\treturn new Promise<StopReason>((resolve, reject) => {\n\t\t\t\tthis.pendingMessages.push({ message, images, resolve, reject });\n\t\t\t});\n\t\t}\n\n\t\treturn this.executePrompt(message, images);\n\t}\n\n\tasync cancel(): Promise<void> {\n\t\tthis.cancelRequested = true;\n\n\t\t// Resolve all queued prompts as cancelled\n\t\tfor (const pending of this.pendingMessages) {\n\t\t\tpending.resolve(\"cancelled\");\n\t\t}\n\t\tthis.pendingMessages = [];\n\n\t\tawait this.piSession.abort();\n\t}\n\n\tprivate executePrompt(message: string, images: unknown[]): Promise<StopReason> {\n\t\tthis.promptRunning = true;\n\n\t\tconst turnPromise = new Promise<StopReason>((resolve, reject) => {\n\t\t\tthis.cancelRequested = false;\n\t\t\tthis.pendingTurn = { resolve, reject };\n\t\t});\n\n\t\tconst imageContents = Array.isArray(images)\n\t\t\t? images.filter(\n\t\t\t\t\t(img): img is { type: \"image\"; data: string; mimeType: string } =>\n\t\t\t\t\t\ttypeof img === \"object\" && img !== null && \"type\" in img && img.type === \"image\",\n\t\t\t\t)\n\t\t\t: [];\n\n\t\tthis.piSession.prompt(message, { images: imageContents }).catch(() => {\n\t\t\tvoid this.flushEmits().finally(() => {\n\t\t\t\tconst reason: StopReason = this.cancelRequested ? \"cancelled\" : \"error\";\n\t\t\t\tthis.pendingTurn?.resolve(reason);\n\t\t\t\tthis.pendingTurn = null;\n\t\t\t});\n\t\t});\n\n\t\treturn turnPromise;\n\t}\n\n\t/**\n\t * Dequeue and execute the next pending prompt, if any.\n\t * Called after a turn completes.\n\t */\n\tprivate dequeueNextPrompt(): void {\n\t\tconst next = this.pendingMessages.shift();\n\t\tif (next === undefined) {\n\t\t\tthis.promptRunning = false;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.executePrompt(next.message, next.images).then(next.resolve, next.reject);\n\t}\n\n\twasCancelRequested(): boolean {\n\t\treturn this.cancelRequested;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Internal\n\t// -----------------------------------------------------------------------\n\n\tprivate emit(update: SessionUpdate): void {\n\t\tthis.lastEmit = this.lastEmit\n\t\t\t.then(() => this.conn.sessionUpdate({ sessionId: this.sessionId, update }))\n\t\t\t.catch(() => {});\n\t}\n\n\tprivate async flushEmits(): Promise<void> {\n\t\tawait this.lastEmit;\n\t}\n\n\tprivate handlePiEvent(ev: AgentSessionEvent): void {\n\t\tif (!isAgentEvent(ev)) return;\n\n\t\tswitch (ev.type) {\n\t\t\tcase \"message_update\":\n\t\t\t\tthis.handleMessageUpdate(ev.assistantMessageEvent);\n\t\t\t\tbreak;\n\t\t\tcase \"message_end\":\n\t\t\t\tthis.handleMessageEnd(ev.message);\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_start\":\n\t\t\t\tthis.handleToolStart(ev.toolCallId, ev.toolName, toToolArgs(ev.args));\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_update\":\n\t\t\t\tthis.handleToolUpdate(ev.toolCallId, ev.toolName, ev.partialResult);\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_end\":\n\t\t\t\tthis.handleToolEnd(ev.toolCallId, ev.toolName, ev.result, ev.isError);\n\t\t\t\tbreak;\n\t\t\tcase \"agent_end\":\n\t\t\t\tthis.handleAgentEnd();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachable(ev, \"handlePiEvent\");\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate handleMessageUpdate(ame: AssistantMessageEvent): void {\n\t\tif (ame.type === \"text_delta\") {\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\tcontent: { type: \"text\", text: ame.delta } satisfies ContentBlock,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (ame.type === \"thinking_delta\") {\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"agent_thought_chunk\",\n\t\t\t\tcontent: { type: \"text\", text: ame.delta } satisfies ContentBlock,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tame.type === \"toolcall_start\" ||\n\t\t\tame.type === \"toolcall_delta\" ||\n\t\t\tame.type === \"toolcall_end\"\n\t\t) {\n\t\t\tconst toolCall = ame.type === \"toolcall_end\" ? ame.toolCall : extractToolCallFromPartial(ame);\n\t\t\tif (!toolCall) return;\n\n\t\t\tconst rawInput = parseToolInput(toolCall);\n\t\t\tconst locations = resolveToolPath(rawInput, this.cwd);\n\t\t\tconst existingStatus = this.currentToolCalls.get(toolCall.id);\n\t\t\tconst status = existingStatus ?? \"pending\";\n\n\t\t\tif (!existingStatus) {\n\t\t\t\tthis.currentToolCalls.set(toolCall.id, \"pending\");\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\ttitle: buildToolTitle(toolCall.name, rawInput),\n\t\t\t\t\tkind: toToolKind(toolCall.name),\n\t\t\t\t\tstatus,\n\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\trawInput,\n\t\t\t\t\t_meta: buildToolMeta(toolCall.name),\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\tstatus,\n\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\trawInput,\n\t\t\t\t\t_meta: buildToolMeta(toolCall.name),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleMessageEnd(msg: AgentMessage): void {\n\t\tif (\"role\" in msg && msg.role === \"assistant\") {\n\t\t\tthis.lastAssistantStopReason = msg.stopReason;\n\t\t}\n\t}\n\n\tprivate handleToolStart(toolCallId: string, toolName: string, args: ToolArgs): void {\n\t\t// Track toolName for streaming updates (Phase 5)\n\t\tthis.toolCallNames.set(toolCallId, toolName);\n\n\t\tlet line: number | undefined;\n\n\t\tif ((toolName === \"edit\" || toolName === \"write\") && args.path !== undefined) {\n\t\t\ttry {\n\t\t\t\tconst abs = isAbsolute(args.path) ? args.path : resolvePath(this.cwd, args.path);\n\t\t\t\tlet oldText = \"\";\n\t\t\t\ttry {\n\t\t\t\t\toldText = readFileSync(abs, \"utf8\");\n\t\t\t\t} catch {\n\t\t\t\t\t// File may not exist yet for write -- treat as empty.\n\t\t\t\t}\n\t\t\t\tthis.editSnapshots.set(toolCallId, { path: abs, oldText });\n\t\t\t\tif (toolName === \"edit\") {\n\t\t\t\t\tline = findUniqueLineNumber(oldText, args.oldText ?? \"\");\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// snapshot failure is non-fatal\n\t\t\t}\n\t\t}\n\n\t\tconst locations = resolveToolPath(args, this.cwd, line);\n\n\t\t// Build terminal metadata for bash/tmux when client supports it\n\t\tconst terminalMeta =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? { terminal_info: { terminal_id: toolCallId, cwd: this.cwd } }\n\t\t\t\t: undefined;\n\t\tconst meta = buildToolMeta(toolName, terminalMeta);\n\n\t\t// Build content for terminal-aware clients\n\t\tconst terminalContent: ToolCallContent[] | undefined =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? [{ type: \"terminal\" as const, terminalId: toolCallId }]\n\t\t\t\t: undefined;\n\n\t\tif (!this.currentToolCalls.has(toolCallId)) {\n\t\t\tthis.currentToolCalls.set(toolCallId, \"in_progress\");\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\ttoolCallId,\n\t\t\t\ttitle: buildToolTitle(toolName, args),\n\t\t\t\tkind: toToolKind(toolName),\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t...(terminalContent !== undefined ? { content: terminalContent } : {}),\n\t\t\t\trawInput: args,\n\t\t\t\t_meta: meta,\n\t\t\t});\n\t\t} else {\n\t\t\tthis.currentToolCalls.set(toolCallId, \"in_progress\");\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\ttitle: buildToolTitle(toolName, args),\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t...(terminalContent !== undefined ? { content: terminalContent } : {}),\n\t\t\t\trawInput: args,\n\t\t\t\t_meta: meta,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleToolUpdate(toolCallId: string, toolName: string, partialResult: unknown): void {\n\t\t// Look up tool name from our map (Phase 5), fall back to event's toolName\n\t\tconst name = this.toolCallNames.get(toolCallId) ?? toolName;\n\n\t\tif (this.supportsTerminalOutput && isTerminalTool(name)) {\n\t\t\t// Terminal-aware path: emit only _meta.terminal_output, no content\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t_meta: buildToolMeta(name, {\n\t\t\t\t\tterminal_output: { terminal_id: toolCallId, data: text },\n\t\t\t\t}),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t} else if (isTerminalTool(name)) {\n\t\t\t// Non-terminal fallback: wrap in console code fence\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tconst wrapped = wrapStreamingBashOutput(text);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\tcontent: wrapped\n\t\t\t\t\t? ([\n\t\t\t\t\t\t\t{ type: \"content\", content: { type: \"text\", text: wrapped } },\n\t\t\t\t\t\t] satisfies ToolCallContent[])\n\t\t\t\t\t: null,\n\t\t\t\t_meta: buildToolMeta(name),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t} else {\n\t\t\t// Other tools: plain text content\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\tcontent: text\n\t\t\t\t\t? ([{ type: \"content\", content: { type: \"text\", text } }] satisfies ToolCallContent[])\n\t\t\t\t\t: null,\n\t\t\t\t_meta: buildToolMeta(name),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleToolEnd(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: unknown,\n\t\tisError: boolean,\n\t): void {\n\t\tconst snapshot = this.editSnapshots.get(toolCallId);\n\t\tlet content: ToolCallContent[] | null = null;\n\n\t\t// Diff path for edit/write\n\t\tif (!isError && snapshot) {\n\t\t\ttry {\n\t\t\t\tconst newText = readFileSync(snapshot.path, \"utf8\");\n\t\t\t\tif (newText !== snapshot.oldText) {\n\t\t\t\t\tconst formatted = formatToolContent(toolName, result, isError);\n\t\t\t\t\tcontent = [\n\t\t\t\t\t\t{ type: \"diff\", path: snapshot.path, oldText: snapshot.oldText, newText },\n\t\t\t\t\t\t...formatted,\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// fall back to formatted content\n\t\t\t}\n\t\t}\n\n\t\t// If no diff content, use formatted tool content\n\t\tif (content === null) {\n\t\t\tconst formatted = formatToolContent(toolName, result, isError);\n\t\t\tcontent = formatted.length > 0 ? formatted : null;\n\t\t}\n\n\t\t// Last resort: if formatToolContent returns empty and no diff, generate plain text\n\t\tif (content === null && !isError && toolName !== \"edit\" && toolName !== \"write\") {\n\t\t\tconst text = extractStreamingText(result);\n\t\t\tif (text) {\n\t\t\t\tcontent = [{ type: \"content\", content: { type: \"text\", text } }];\n\t\t\t}\n\t\t}\n\n\t\t// For terminal tools: emit a separate terminal_output update before terminal_exit.\n\t\t// This ensures Zed renders output before the exit status (following claude-agent-acp).\n\t\tif (this.supportsTerminalOutput && isTerminalTool(toolName)) {\n\t\t\tconst outputText = extractStreamingText(result);\n\t\t\tif (outputText !== \"\") {\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t\t_meta: buildToolMeta(toolName, {\n\t\t\t\t\t\tterminal_output: { terminal_id: toolCallId, data: outputText },\n\t\t\t\t\t}),\n\t\t\t\t\trawOutput: result,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Build terminal exit metadata for bash/tmux\n\t\tconst terminalExitMeta =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? {\n\t\t\t\t\t\tterminal_exit: {\n\t\t\t\t\t\t\tterminal_id: toolCallId,\n\t\t\t\t\t\t\texit_code: extractExitCode(result),\n\t\t\t\t\t\t\tsignal: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\tconst meta = buildToolMeta(toolName, terminalExitMeta);\n\n\t\tthis.emit({\n\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\ttoolCallId,\n\t\t\tstatus: isError ? \"failed\" : \"completed\",\n\t\t\tcontent,\n\t\t\t_meta: meta,\n\t\t\trawOutput: result,\n\t\t});\n\n\t\tthis.currentToolCalls.delete(toolCallId);\n\t\tthis.editSnapshots.delete(toolCallId);\n\t\tthis.toolCallNames.delete(toolCallId);\n\t}\n\n\tprivate handleAgentEnd(): void {\n\t\tthis.emitUsageUpdate();\n\t\tvoid this.flushEmits().finally(() => {\n\t\t\tconst reason: StopReason = this.cancelRequested\n\t\t\t\t? \"cancelled\"\n\t\t\t\t: mapPiStopReason(this.lastAssistantStopReason);\n\t\t\tthis.lastAssistantStopReason = null;\n\t\t\tthis.pendingTurn?.resolve(reason);\n\t\t\tthis.pendingTurn = null;\n\t\t\tthis.dequeueNextPrompt();\n\t\t});\n\t}\n\n\t/**\n\t * Emit a usage_update notification with current context and cost data.\n\t */\n\tprivate emitUsageUpdate(): void {\n\t\tconst contextUsage = this.piSession.getContextUsage?.();\n\t\tconst stats = this.piSession.getSessionStats();\n\n\t\tconst used = contextUsage?.tokens ?? 0;\n\t\tconst size = contextUsage?.contextWindow ?? 0;\n\n\t\tthis.emit({\n\t\t\tsessionUpdate: \"usage_update\",\n\t\t\tused,\n\t\t\tsize,\n\t\t\tcost: stats.cost > 0 ? { amount: stats.cost, currency: \"USD\" } : null,\n\t\t});\n\t}\n\n\t/**\n\t * Build ACP Usage data from pi session stats for prompt response.\n\t */\n\tgetUsage(): {\n\t\tinputTokens: number;\n\t\toutputTokens: number;\n\t\tcachedReadTokens: number;\n\t\tcachedWriteTokens: number;\n\t} {\n\t\tconst stats = this.piSession.getSessionStats();\n\t\treturn {\n\t\t\tinputTokens: stats.tokens.input,\n\t\t\toutputTokens: stats.tokens.output,\n\t\t\tcachedReadTokens: stats.tokens.cacheRead,\n\t\t\tcachedWriteTokens: stats.tokens.cacheWrite,\n\t\t};\n\t}\n\n\t/**\n\t * Get cumulative session cost.\n\t */\n\tgetCost(): number {\n\t\treturn this.piSession.getSessionStats().cost;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Streaming text extraction (lightweight, no formatting)\n// ---------------------------------------------------------------------------\n\nfunction isTextBlock(v: unknown): v is { type: \"text\"; text: string } {\n\treturn (\n\t\ttypeof v === \"object\" &&\n\t\tv !== null &&\n\t\t\"type\" in v &&\n\t\tv.type === \"text\" &&\n\t\t\"text\" in v &&\n\t\ttypeof v.text === \"string\"\n\t);\n}\n\nfunction extractStreamingText(result: unknown): string {\n\tif (result === null || result === undefined) return \"\";\n\tif (typeof result === \"string\") return result;\n\tif (typeof result !== \"object\") return String(result);\n\n\t// Content blocks\n\tif (\"content\" in result && Array.isArray(result.content)) {\n\t\tconst texts: string[] = [];\n\t\tfor (const raw of result.content) {\n\t\t\tif (isTextBlock(raw)) {\n\t\t\t\ttexts.push(raw.text);\n\t\t\t}\n\t\t}\n\t\tif (texts.length > 0) return texts.join(\"\");\n\t}\n\n\t// Details fields\n\tif (\"details\" in result) {\n\t\tconst details = result.details;\n\t\tif (typeof details === \"object\" && details !== null) {\n\t\t\tif (\"stdout\" in details && typeof details.stdout === \"string\" && details.stdout.trim() !== \"\")\n\t\t\t\treturn details.stdout;\n\t\t\tif (\"output\" in details && typeof details.output === \"string\" && details.output.trim() !== \"\")\n\t\t\t\treturn details.output;\n\t\t}\n\t}\n\n\t// Top-level output/stdout\n\tif (\"output\" in result && typeof result.output === \"string\" && result.output.trim() !== \"\")\n\t\treturn result.output;\n\tif (\"stdout\" in result && typeof result.stdout === \"string\" && result.stdout.trim() !== \"\")\n\t\treturn result.stdout;\n\n\treturn \"\";\n}\n\nfunction extractExitCode(result: unknown): number | null {\n\tif (result === null || result === undefined || typeof result !== \"object\") return null;\n\n\tif (\"details\" in result) {\n\t\tconst details = result.details;\n\t\tif (typeof details === \"object\" && details !== null) {\n\t\t\tif (\"exitCode\" in details && typeof details.exitCode === \"number\") return details.exitCode;\n\t\t\tif (\"code\" in details && typeof details.code === \"number\") return details.code;\n\t\t}\n\t}\n\n\tif (\"exitCode\" in result && typeof result.exitCode === \"number\") return result.exitCode;\n\tif (\"code\" in result && typeof result.code === \"number\") return result.code;\n\n\treturn null;\n}\n\n/**\n * Type guard to narrow AgentSessionEvent to the AgentEvent subset\n * (the variants we handle). Session-specific events like auto_compaction\n * are ignored.\n */\nfunction isAgentEvent(\n\tev: AgentSessionEvent,\n): ev is Extract<\n\tAgentEvent,\n\t| { type: \"message_update\" }\n\t| { type: \"message_end\" }\n\t| { type: \"tool_execution_start\" }\n\t| { type: \"tool_execution_update\" }\n\t| { type: \"tool_execution_end\" }\n\t| { type: \"agent_end\" }\n> {\n\treturn (\n\t\tev.type === \"message_update\" ||\n\t\tev.type === \"message_end\" ||\n\t\tev.type === \"tool_execution_start\" ||\n\t\tev.type === \"tool_execution_update\" ||\n\t\tev.type === \"tool_execution_end\" ||\n\t\tev.type === \"agent_end\"\n\t);\n}\n","/**\n * Extract plain text from pi message content.\n *\n * Pi messages store content as either a string or an array of typed blocks.\n * These helpers extract the text portions for ACP session replay.\n */\n\ninterface TextBlock {\n\ttype: \"text\";\n\ttext: string;\n}\n\nfunction isTextBlock(block: unknown): block is TextBlock {\n\tif (typeof block !== \"object\" || block === null) return false;\n\treturn (\n\t\t\"type\" in block && block.type === \"text\" && \"text\" in block && typeof block.text === \"string\"\n\t);\n}\n\nexport function extractUserMessageText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter(isTextBlock)\n\t\t.map((b) => b.text)\n\t\t.join(\"\");\n}\n\nexport function extractAssistantText(content: unknown): string {\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter(isTextBlock)\n\t\t.map((b) => b.text)\n\t\t.join(\"\");\n}\n","/**\n * Convert ACP prompt ContentBlocks to a pi-compatible message string and image array.\n */\n\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\n\nexport interface PiImage {\n\ttype: \"image\";\n\tmimeType: string;\n\tdata: string;\n}\n\nexport function acpPromptToPiMessage(blocks: ContentBlock[]): {\n\tmessage: string;\n\timages: PiImage[];\n} {\n\tlet message = \"\";\n\tconst images: PiImage[] = [];\n\n\tfor (const block of blocks) {\n\t\tswitch (block.type) {\n\t\t\tcase \"text\":\n\t\t\t\tmessage += block.text;\n\t\t\t\tbreak;\n\n\t\t\tcase \"resource_link\":\n\t\t\t\tmessage += `\\n[Context] ${block.uri}`;\n\t\t\t\tbreak;\n\n\t\t\tcase \"image\":\n\t\t\t\timages.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: block.mimeType,\n\t\t\t\t\tdata: block.data,\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"resource\": {\n\t\t\t\tconst resource = block.resource;\n\t\t\t\tconst uri = resource.uri;\n\t\t\t\tconst mime = resource.mimeType ?? null;\n\n\t\t\t\tif (\"text\" in resource) {\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri} (${mime ?? \"text/plain\"})\\n${resource.text}`;\n\t\t\t\t} else if (\"blob\" in resource) {\n\t\t\t\t\tconst bytes = Buffer.byteLength(resource.blob, \"base64\");\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri} (${mime ?? \"application/octet-stream\"}, ${bytes} bytes)`;\n\t\t\t\t} else {\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri}`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"audio\": {\n\t\t\t\tconst bytes = Buffer.byteLength(block.data, \"base64\");\n\t\t\t\tmessage += `\\n[Audio] (${block.mimeType}, ${bytes} bytes) not supported`;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { message, images };\n}\n","","import { spawnSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, join } from \"node:path\";\nimport {\n\ttype Agent as ACPAgent,\n\ttype AgentSideConnection,\n\ttype AuthenticateRequest,\n\ttype AvailableCommand,\n\ttype CancelNotification,\n\ttype CloseSessionRequest,\n\ttype CloseSessionResponse,\n\ttype ForkSessionRequest,\n\ttype ForkSessionResponse,\n\ttype InitializeRequest,\n\ttype InitializeResponse,\n\ttype ListSessionsRequest,\n\ttype ListSessionsResponse,\n\ttype LoadSessionRequest,\n\ttype LoadSessionResponse,\n\ttype ModelInfo,\n\ttype NewSessionRequest,\n\ttype PromptRequest,\n\ttype PromptResponse,\n\tRequestError,\n\ttype ResumeSessionRequest,\n\ttype ResumeSessionResponse,\n\ttype SessionConfigOption,\n\ttype SessionInfo,\n\ttype SessionModelState,\n\ttype SessionModeState,\n\ttype SetSessionConfigOptionRequest,\n\ttype SetSessionConfigOptionResponse,\n\ttype SetSessionModelRequest,\n\ttype SetSessionModelResponse,\n\ttype SetSessionModeRequest,\n\ttype SetSessionModeResponse,\n\ttype StopReason,\n} from \"@agentclientprotocol/sdk\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, ToolResultMessage, UserMessage } from \"@earendil-works/pi-ai\";\nimport {\n\ttype AgentSession,\n\ttype CreateAgentSessionResult,\n\tcreateAgentSession,\n\tSessionManager as PiSessionManager,\n} from \"@earendil-works/pi-coding-agent\";\nimport { buildAuthMethods } from \"@pi-acp/acp/auth\";\nimport { detectAuthError } from \"@pi-acp/acp/auth-required\";\nimport {\n\ttype ClientCapabilityFlags,\n\tparseClientCapabilities,\n} from \"@pi-acp/acp/client-capabilities\";\nimport { resolveModelPreference } from \"@pi-acp/acp/model-alias\";\nimport { skillCommandsEnabled } from \"@pi-acp/acp/pi-settings\";\nimport {\n\tbuildToolTitle,\n\tPiAcpSession,\n\tresolveToolPath,\n\tSessionManager,\n\ttype ToolArgs,\n\ttoToolArgs,\n\ttoToolKind,\n} from \"@pi-acp/acp/session\";\nimport { extractUserMessageText } from \"@pi-acp/acp/translate/pi-messages\";\nimport { acpPromptToPiMessage } from \"@pi-acp/acp/translate/prompt\";\nimport { formatToolContent } from \"@pi-acp/acp/translate/tool-content\";\n\nimport pkgJson from \"../../package.json\" with { type: \"json\" };\n\ntype ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\n/** Builtin ACP slash commands handled directly by the adapter. */\nconst BUILTIN_COMMANDS: readonly AvailableCommand[] = [\n\t{\n\t\tname: \"compact\",\n\t\tdescription: \"Manually compact the session context\",\n\t\tinput: { hint: \"optional custom instructions\" },\n\t},\n\t{\n\t\tname: \"autocompact\",\n\t\tdescription: \"Toggle automatic context compaction\",\n\t\tinput: { hint: \"on|off|toggle\" },\n\t},\n\t{ name: \"export\", description: \"Export session to an HTML file in the session cwd\" },\n\t{ name: \"session\", description: \"Show session stats (messages, tokens, cost, session file)\" },\n\t{ name: \"name\", description: \"Set session display name\", input: { hint: \"<name>\" } },\n\t{\n\t\tname: \"steering\",\n\t\tdescription: \"Get/set pi steering message delivery mode\",\n\t\tinput: { hint: \"(no args to show) all | one-at-a-time\" },\n\t},\n\t{\n\t\tname: \"follow-up\",\n\t\tdescription: \"Get/set pi follow-up message delivery mode\",\n\t\tinput: { hint: \"(no args to show) all | one-at-a-time\" },\n\t},\n\t{ name: \"changelog\", description: \"Show pi changelog\" },\n] as const;\n\n/**\n * Deduplicate commands by name. First occurrence wins.\n */\nfunction deduplicateCommands(commands: AvailableCommand[]): AvailableCommand[] {\n\tconst seen = new Set<string>();\n\tconst out: AvailableCommand[] = [];\n\tfor (const c of commands) {\n\t\tif (seen.has(c.name)) continue;\n\t\tseen.add(c.name);\n\t\tout.push(c);\n\t}\n\treturn out;\n}\n\nfunction parseArgs(input: string): string[] {\n\tconst args: string[] = [];\n\tlet current = \"\";\n\tlet quote: string | null = null;\n\n\tfor (const ch of input) {\n\t\tif (quote !== null) {\n\t\t\tif (ch === quote) quote = null;\n\t\t\telse current += ch;\n\t\t} else if (ch === '\"' || ch === \"'\") {\n\t\t\tquote = ch;\n\t\t} else if (ch === \" \" || ch === \"\\t\") {\n\t\t\tif (current !== \"\") {\n\t\t\t\targs.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\n\tif (current !== \"\") args.push(current);\n\treturn args;\n}\n\nconst SESSION_TITLE_MAX = 100;\n\nfunction truncateSessionTitle(text: string): string | null {\n\tconst trimmed = text.trim();\n\tif (trimmed === \"\") return null;\n\tconst oneLine = trimmed.replace(/\\n/g, \" \");\n\tif (oneLine.length <= SESSION_TITLE_MAX) return oneLine;\n\treturn `${oneLine.slice(0, SESSION_TITLE_MAX - 1)}…`;\n}\n\nexport class PiAcpAgent implements ACPAgent {\n\tprivate readonly conn: AgentSideConnection;\n\tprivate readonly sessions = new SessionManager();\n\t/** Cache of sessionId → file path, populated by listSessions and newSession. */\n\tprivate readonly sessionPaths = new Map<string, string>();\n\t/** Parsed client capability flags from initialize(). */\n\tprivate clientCapabilities: ClientCapabilityFlags = {\n\t\tterminalOutput: false,\n\t\tterminalAuth: false,\n\t\tgatewayAuth: false,\n\t};\n\n\tprivate readonly daemonContext: import(\"@pi-acp/daemon/context\").DaemonContext | undefined;\n\t/** Unique ID for this ACP connection. Used as the ownership key in the daemon SessionRegistry. */\n\tprivate readonly connectionId = randomUUID();\n\n\tdispose(): void {\n\t\t// On connection close, release every session this connection owned or\n\t\t// resumed from the daemon registry. Sessions another client still holds\n\t\t// stay live; sessions only this connection held get disposed by release().\n\t\tif (this.daemonContext !== undefined) {\n\t\t\tconst registry = this.daemonContext.sessionRegistry;\n\t\t\tfor (const entry of registry.listOwnedBy(this.connectionId)) {\n\t\t\t\tconst result = registry.release(entry.sessionId, this.connectionId);\n\t\t\t\tif (result.kind === \"disposed\") {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tentry.piSession.dispose();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t/* best-effort */\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.sessions.disposeAll();\n\t}\n\n\tconstructor(\n\t\tconn: AgentSideConnection,\n\t\tdaemonContext?: import(\"@pi-acp/daemon/context\").DaemonContext,\n\t) {\n\t\tthis.conn = conn;\n\t\tthis.daemonContext = daemonContext;\n\t}\n\n\tprivate registerWithDaemon(input: {\n\t\tsessionId: string;\n\t\tpiSession: AgentSession;\n\t\tcwd: string;\n\t\tsessionFile: string | undefined;\n\t}): void {\n\t\tif (this.daemonContext === undefined) return;\n\t\tthis.daemonContext.sessionRegistry.register({\n\t\t\tsessionId: input.sessionId,\n\t\t\tpiSession: input.piSession,\n\t\t\townerConnectionId: this.connectionId,\n\t\t\tcwd: input.cwd,\n\t\t\tsessionFile: input.sessionFile,\n\t\t});\n\t}\n\n\tprivate releaseFromDaemon(sessionId: string): { disposed: boolean } {\n\t\tif (this.daemonContext === undefined) return { disposed: true };\n\t\tconst result = this.daemonContext.sessionRegistry.release(sessionId, this.connectionId);\n\t\treturn { disposed: result.kind === \"disposed\" };\n\t}\n\n\tasync initialize(params: InitializeRequest): Promise<InitializeResponse> {\n\t\tconst supportedVersion = 1;\n\t\tconst requested = params.protocolVersion;\n\n\t\tthis.clientCapabilities = parseClientCapabilities(params.clientCapabilities);\n\n\t\treturn {\n\t\t\tprotocolVersion: requested === supportedVersion ? requested : supportedVersion,\n\t\t\tagentInfo: {\n\t\t\t\tname: pkgJson.name,\n\t\t\t\ttitle: \"pi ACP adapter\",\n\t\t\t\tversion: pkgJson.version,\n\t\t\t},\n\t\t\tauthMethods: buildAuthMethods({\n\t\t\t\tsupportsTerminalAuthMeta: this.clientCapabilities.terminalAuth,\n\t\t\t}),\n\t\t\tagentCapabilities: {\n\t\t\t\tloadSession: true,\n\t\t\t\tmcpCapabilities: { http: false, sse: false },\n\t\t\t\tpromptCapabilities: {\n\t\t\t\t\timage: true,\n\t\t\t\t\taudio: false,\n\t\t\t\t\tembeddedContext: true,\n\t\t\t\t},\n\t\t\t\tsessionCapabilities: {\n\t\t\t\t\tlist: {},\n\t\t\t\t\tclose: {},\n\t\t\t\t\tresume: {},\n\t\t\t\t\tfork: {},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync newSession(params: NewSessionRequest) {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tresult = await createAgentSession({ cwd: params.cwd });\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to create pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst availableModels = piSession.modelRegistry.getAvailable();\n\t\tif (availableModels.length === 0) {\n\t\t\tpiSession.dispose();\n\t\t\tthrow RequestError.authRequired(\n\t\t\t\t{ authMethods: buildAuthMethods() },\n\t\t\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t\t\t);\n\t\t}\n\n\t\tconst sessionId = piSession.sessionManager.getSessionId();\n\t\tconst sessionFile = piSession.sessionManager.getSessionFile();\n\t\tif (sessionFile !== undefined) {\n\t\t\tthis.sessionPaths.set(sessionId, sessionFile);\n\t\t}\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers,\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\t\tthis.registerWithDaemon({ sessionId, piSession, cwd: params.cwd, sessionFile });\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\treturn {\n\t\t\tsessionId: session.sessionId,\n\t\t\tconfigOptions,\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync authenticate(_params: AuthenticateRequest) {\n\t\treturn {};\n\t}\n\n\tasync prompt(params: PromptRequest): Promise<PromptResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst { message, images } = acpPromptToPiMessage(params.prompt);\n\n\t\tif (images.length === 0 && message.trimStart().startsWith(\"/\")) {\n\t\t\tconst trimmed = message.trim();\n\t\t\tconst space = trimmed.indexOf(\" \");\n\t\t\tconst cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);\n\t\t\tconst argsString = space === -1 ? \"\" : trimmed.slice(space + 1);\n\t\t\tconst args = parseArgs(argsString);\n\n\t\t\tconst handled = await this.handleBuiltinCommand(session, cmd, args);\n\t\t\tif (handled) return handled;\n\t\t}\n\n\t\tconst result = await session.prompt(message, images);\n\n\t\tconst stopReason: StopReason = result === \"error\" ? \"end_turn\" : result;\n\t\tconst usage = session.getUsage();\n\t\tconst cost = session.getCost();\n\n\t\treturn {\n\t\t\tstopReason,\n\t\t\tusage: {\n\t\t\t\tinputTokens: usage.inputTokens,\n\t\t\t\toutputTokens: usage.outputTokens,\n\t\t\t\tcachedReadTokens: usage.cachedReadTokens,\n\t\t\t\tcachedWriteTokens: usage.cachedWriteTokens,\n\t\t\t\ttotalTokens: usage.inputTokens + usage.outputTokens,\n\t\t\t},\n\t\t\t_meta: cost > 0 ? { cost: { amount: cost, currency: \"USD\" } } : {},\n\t\t};\n\t}\n\n\tasync cancel(params: CancelNotification): Promise<void> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tawait session.cancel();\n\t}\n\n\t/**\n\t * Resolve a session ID to a file path.\n\t * Checks the local cache first (populated by listSessions/newSession),\n\t * falls back to a full listAll() scan on cache miss.\n\t */\n\tprivate async resolveSessionFile(sessionId: string): Promise<string | null> {\n\t\tconst cached = this.sessionPaths.get(sessionId);\n\t\tif (cached !== undefined) return cached;\n\n\t\tconst all = await PiSessionManager.listAll();\n\t\tfor (const s of all) {\n\t\t\tthis.sessionPaths.set(s.id, s.path);\n\t\t}\n\n\t\treturn this.sessionPaths.get(sessionId) ?? null;\n\t}\n\n\t/**\n\t * Replay persisted session messages as ACP session updates.\n\t *\n\t * Iterates through the message history, emitting structured updates for each\n\t * content block type: text, thinking, tool calls, and tool results. A map of\n\t * tool call IDs to their invocation data (from assistant messages) is built\n\t * to enrich subsequent tool result updates with rawInput and locations.\n\t */\n\tprivate async replaySessionHistory(\n\t\tsession: PiAcpSession,\n\t\tmessages: AgentMessage[],\n\t): Promise<void> {\n\t\tconst toolCallMap = new Map<string, { name: string; args: ToolArgs }>();\n\n\t\tfor (const m of messages) {\n\t\t\tif (!(\"role\" in m)) continue;\n\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst text = extractUserMessageText((m satisfies UserMessage).content);\n\t\t\t\tif (text) {\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: { sessionUpdate: \"user_message_chunk\", content: { type: \"text\", text } },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (m.role === \"assistant\") {\n\t\t\t\tconst am = m satisfies AssistantMessage;\n\t\t\t\tfor (const block of am.content) {\n\t\t\t\t\tif (block.type === \"text\" && block.text) {\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\t\t\tcontent: { type: \"text\", text: block.text },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (block.type === \"thinking\" && block.thinking) {\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"agent_thought_chunk\",\n\t\t\t\t\t\t\t\tcontent: { type: \"text\", text: block.thinking },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\tconst args = toToolArgs(block.arguments);\n\t\t\t\t\t\ttoolCallMap.set(block.id, { name: block.name, args });\n\t\t\t\t\t\tconst locations = resolveToolPath(args, session.cwd);\n\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\t\t\ttoolCallId: block.id,\n\t\t\t\t\t\t\t\ttitle: buildToolTitle(block.name, args),\n\t\t\t\t\t\t\t\tkind: toToolKind(block.name),\n\t\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\t\trawInput: args,\n\t\t\t\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\t\t\t\t_meta: { piAcp: { toolName: block.name } },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (m.role === \"toolResult\") {\n\t\t\t\tconst tr = m satisfies ToolResultMessage;\n\t\t\t\tconst toolName = tr.toolName;\n\t\t\t\tconst toolCallId = tr.toolCallId;\n\t\t\t\tconst isError = tr.isError;\n\n\t\t\t\t// Enrich from the preceding assistant tool call if available.\n\t\t\t\tconst invocation = toolCallMap.get(toolCallId);\n\t\t\t\tconst args = invocation?.args;\n\t\t\t\tconst locations = args !== undefined ? resolveToolPath(args, session.cwd) : undefined;\n\n\t\t\t\t// If no tool_call was emitted from the assistant message (e.g. older\n\t\t\t\t// session format without structured assistant content), emit one now.\n\t\t\t\tif (invocation === undefined) {\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\t\ttitle: buildToolTitle(toolName, {}),\n\t\t\t\t\t\t\tkind: toToolKind(toolName),\n\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\trawInput: null,\n\t\t\t\t\t\t\trawOutput: m,\n\t\t\t\t\t\t\t_meta: { piAcp: { toolName } },\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst content = formatToolContent(toolName, m, isError);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\tstatus: isError ? \"failed\" : \"completed\",\n\t\t\t\t\t\tcontent: content.length > 0 ? content : null,\n\t\t\t\t\t\trawOutput: m,\n\t\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\t\t_meta: { piAcp: { toolName } },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tasync listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {\n\t\tconst cwd = params.cwd;\n\n\t\tconst raw =\n\t\t\tcwd !== undefined && cwd !== null\n\t\t\t\t? await PiSessionManager.list(cwd)\n\t\t\t\t: await PiSessionManager.listAll();\n\n\t\tfor (const s of raw) {\n\t\t\tthis.sessionPaths.set(s.id, s.path);\n\t\t}\n\n\t\tconst sessions = raw.map((s) => ({\n\t\t\tid: s.id,\n\t\t\tcwd: s.cwd,\n\t\t\tname: s.name,\n\t\t\tfirstMessage: s.firstMessage,\n\t\t\tmodified: s.modified,\n\t\t\tmessageCount: s.messageCount,\n\t\t}));\n\n\t\tif (params.cursor !== undefined && params.cursor !== null) {\n\t\t\tconst parsed = Number.parseInt(params.cursor, 10);\n\t\t\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\t\t\tthrow RequestError.invalidParams(`Invalid cursor: ${params.cursor}`);\n\t\t\t}\n\t\t}\n\n\t\tconst start =\n\t\t\tparams.cursor !== undefined && params.cursor !== null\n\t\t\t\t? Number.parseInt(params.cursor, 10)\n\t\t\t\t: 0;\n\n\t\tconst PAGE_SIZE = 50;\n\t\tconst page = sessions.slice(start, start + PAGE_SIZE);\n\n\t\tconst liveSessions =\n\t\t\tthis.daemonContext !== undefined ? this.daemonContext.sessionRegistry.listAll() : [];\n\t\tconst liveById = new Map(liveSessions.map((e) => [e.sessionId, e]));\n\n\t\tconst acpSessions: SessionInfo[] = page.map((s) => {\n\t\t\tconst live = liveById.get(s.id);\n\t\t\tconst isOwnedByThisConnection =\n\t\t\t\tlive !== undefined &&\n\t\t\t\t(live.ownerConnectionId === this.connectionId || live.alsoHeldBy.has(this.connectionId));\n\t\t\treturn {\n\t\t\t\tsessionId: s.id,\n\t\t\t\tcwd: s.cwd,\n\t\t\t\ttitle:\n\t\t\t\t\t(s.name !== undefined && s.name !== \"\" ? s.name : null) ??\n\t\t\t\t\ttruncateSessionTitle(s.firstMessage) ??\n\t\t\t\t\tnull,\n\t\t\t\tupdatedAt: s.modified.toISOString(),\n\t\t\t\t...(live !== undefined\n\t\t\t\t\t? {\n\t\t\t\t\t\t\t_meta: {\n\t\t\t\t\t\t\t\tpiAcp: {\n\t\t\t\t\t\t\t\t\tlive: true,\n\t\t\t\t\t\t\t\t\townedByThisConnection: isOwnedByThisConnection,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t}\n\t\t\t\t\t: {}),\n\t\t\t};\n\t\t});\n\n\t\t// Surface daemon-live sessions that are NOT on disk yet (e.g., newSession\n\t\t// called but not yet persisted by pi). Insert at the front so the most\n\t\t// recently-active live ones bubble up.\n\t\tconst seen = new Set(page.map((s) => s.id));\n\t\tconst liveOnly = liveSessions\n\t\t\t.filter((e) => !seen.has(e.sessionId))\n\t\t\t.map<SessionInfo>((e) => ({\n\t\t\t\tsessionId: e.sessionId,\n\t\t\t\tcwd: e.cwd,\n\t\t\t\ttitle: null,\n\t\t\t\tupdatedAt: e.updatedAt.toISOString(),\n\t\t\t\t_meta: {\n\t\t\t\t\tpiAcp: {\n\t\t\t\t\t\tlive: true,\n\t\t\t\t\t\townedByThisConnection:\n\t\t\t\t\t\t\te.ownerConnectionId === this.connectionId || e.alsoHeldBy.has(this.connectionId),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t}));\n\n\t\tconst merged = [...liveOnly, ...acpSessions];\n\t\tconst nextCursor = start + PAGE_SIZE < sessions.length ? String(start + PAGE_SIZE) : null;\n\n\t\treturn { sessions: merged, nextCursor, _meta: {} };\n\t}\n\n\tasync loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tthis.sessions.close(params.sessionId);\n\n\t\tconst sessionFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sessionFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.open(sessionFile);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to load pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: params.sessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers,\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\t\tthis.registerWithDaemon({\n\t\t\tsessionId: params.sessionId,\n\t\t\tpiSession,\n\t\t\tcwd: params.cwd,\n\t\t\tsessionFile,\n\t\t});\n\n\t\tawait this.replaySessionHistory(session, piSession.messages);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\treturn {\n\t\t\tconfigOptions,\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse> {\n\t\tconst local = this.sessions.maybeGet(params.sessionId);\n\t\t// Check daemon registry too: another client may have created the session\n\t\t// and this connection only resumed it; the local PiAcpSession wrapper\n\t\t// existed but the underlying piSession is shared.\n\t\tconst inRegistry = this.daemonContext?.sessionRegistry.get(params.sessionId);\n\t\tif (local === undefined && inRegistry === undefined) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\t// Release from registry first to decide whether to dispose pi runtime.\n\t\tconst release = this.releaseFromDaemon(params.sessionId);\n\t\tif (release.disposed) {\n\t\t\t// Last holder — full close including pi dispose via SessionManager.\n\t\t\tthis.sessions.close(params.sessionId);\n\t\t} else if (local !== undefined) {\n\t\t\t// Other clients still hold the session. Drop only this connection's\n\t\t\t// PiAcpSession wrapper (which holds our own event subscription).\n\t\t\t// SessionManager.detach removes the entry without disposing the\n\t\t\t// underlying piSession.\n\t\t\tthis.sessions.detach(params.sessionId);\n\t\t}\n\t\treturn {};\n\t}\n\n\tasync resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\t// If the session is already live in THIS connection, reuse it.\n\t\tconst existing = this.sessions.maybeGet(params.sessionId);\n\t\tif (existing !== undefined) {\n\t\t\tconst modes = buildThinkingModes(existing.piSession);\n\t\t\tconst models = buildModelState(existing.piSession);\n\t\t\treturn {\n\t\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\t\tmodes,\n\t\t\t\tmodels,\n\t\t\t};\n\t\t}\n\n\t\t// If another connection in the same daemon already holds the session,\n\t\t// attach to it and create a local PiAcpSession wrapping the shared\n\t\t// piSession with this connection's own event subscription + conn.\n\t\tif (this.daemonContext !== undefined) {\n\t\t\tconst registry = this.daemonContext.sessionRegistry;\n\t\t\tconst attached = registry.attach(params.sessionId, this.connectionId);\n\t\t\tif (attached !== undefined) {\n\t\t\t\tconst session = new PiAcpSession({\n\t\t\t\t\tsessionId: params.sessionId,\n\t\t\t\t\tcwd: params.cwd,\n\t\t\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\t\t\tpiSession: attached.piSession,\n\t\t\t\t\tconn: this.conn,\n\t\t\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t\t\t});\n\t\t\t\tthis.sessions.register(session);\n\t\t\t\tif (attached.sessionFile !== undefined) {\n\t\t\t\t\tthis.sessionPaths.set(params.sessionId, attached.sessionFile);\n\t\t\t\t}\n\t\t\t\tconst modes = buildThinkingModes(attached.piSession);\n\t\t\t\tconst models = buildModelState(attached.piSession);\n\t\t\t\treturn {\n\t\t\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\t\t\tmodes,\n\t\t\t\t\tmodels,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Otherwise, load from disk (same path as loadSession but without replay).\n\t\tconst sessionFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sessionFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.open(sessionFile);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to resume pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: params.sessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\t\tthis.sessionPaths.set(params.sessionId, sessionFile);\n\t\tthis.registerWithDaemon({\n\t\t\tsessionId: params.sessionId,\n\t\t\tpiSession,\n\t\t\tcwd: params.cwd,\n\t\t\tsessionFile,\n\t\t});\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\treturn {\n\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync unstable_forkSession(params: ForkSessionRequest): Promise<ForkSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tconst sourceFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sourceFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.forkFrom(sourceFile, params.cwd);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to fork pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst newSessionId = piSession.sessionManager.getSessionId();\n\t\tconst newSessionFile = piSession.sessionManager.getSessionFile();\n\t\tif (newSessionFile !== undefined) {\n\t\t\tthis.sessionPaths.set(newSessionId, newSessionFile);\n\t\t}\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: newSessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\t\tthis.registerWithDaemon({\n\t\t\tsessionId: newSessionId,\n\t\t\tpiSession,\n\t\t\tcwd: params.cwd,\n\t\t\tsessionFile: newSessionFile,\n\t\t});\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\treturn {\n\t\t\tsessionId: newSessionId,\n\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst mode = String(params.modeId);\n\t\tif (!isThinkingLevel(mode)) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modeId: ${mode}`);\n\t\t}\n\n\t\tsession.piSession.setThinkingLevel(mode);\n\n\t\tvoid this.conn.sessionUpdate({\n\t\t\tsessionId: session.sessionId,\n\t\t\tupdate: { sessionUpdate: \"current_mode_update\", currentModeId: mode },\n\t\t});\n\n\t\tthis.emitConfigOptionUpdate(session);\n\n\t\treturn {};\n\t}\n\n\tasync unstable_setSessionModel(\n\t\tparams: SetSessionModelRequest,\n\t): Promise<SetSessionModelResponse | void> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst available = session.piSession.modelRegistry.getAvailable();\n\n\t\tconst resolved = resolveModelPreference(available, params.modelId);\n\t\tif (resolved === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modelId: ${params.modelId}`);\n\t\t}\n\n\t\tconst model = available.find((m) => m.provider === resolved.provider && m.id === resolved.id);\n\t\tif (!model) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modelId: ${params.modelId}`);\n\t\t}\n\n\t\tawait session.piSession.setModel(model);\n\t\tthis.emitConfigOptionUpdate(session);\n\t}\n\n\tasync setSessionConfigOption(\n\t\tparams: SetSessionConfigOptionRequest,\n\t): Promise<SetSessionConfigOptionResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst configId = String(params.configId);\n\t\tconst value = String(params.value);\n\n\t\tif (configId === \"model\") {\n\t\t\tconst available = session.piSession.modelRegistry.getAvailable();\n\t\t\tconst resolved = resolveModelPreference(available, value);\n\t\t\tif (resolved === null) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t}\n\n\t\t\tconst model = available.find((m) => m.provider === resolved.provider && m.id === resolved.id);\n\t\t\tif (!model) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t}\n\n\t\t\tawait session.piSession.setModel(model);\n\t\t} else if (configId === \"thought_level\") {\n\t\t\tif (!isThinkingLevel(value)) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown thinking level: ${value}`);\n\t\t\t}\n\t\t\tsession.piSession.setThinkingLevel(value);\n\t\t} else {\n\t\t\tthrow RequestError.invalidParams(`Unknown config option: ${configId}`);\n\t\t}\n\n\t\tconst modes = buildThinkingModes(session.piSession);\n\t\tconst models = buildModelState(session.piSession);\n\t\treturn { configOptions: buildConfigOptions(modes, models) };\n\t}\n\n\tprivate emitConfigOptionUpdate(session: PiAcpSession): void {\n\t\tconst modes = buildThinkingModes(session.piSession);\n\t\tconst models = buildModelState(session.piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tvoid this.conn.sessionUpdate({\n\t\t\tsessionId: session.sessionId,\n\t\t\tupdate: {\n\t\t\t\tsessionUpdate: \"config_option_update\",\n\t\t\t\tconfigOptions,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async handleBuiltinCommand(\n\t\tsession: PiAcpSession,\n\t\tcmd: string,\n\t\targs: string[],\n\t): Promise<PromptResponse | null> {\n\t\tconst piSession = session.piSession;\n\n\t\tif (cmd === \"compact\") {\n\t\t\tconst customInstructions = args.join(\" \").trim() || undefined;\n\t\t\tconst res = await piSession.compact(customInstructions);\n\n\t\t\tconst headerLines = [\n\t\t\t\t`Compaction completed.${customInstructions !== undefined && customInstructions !== \"\" ? \" (custom instructions applied)\" : \"\"}`,\n\t\t\t\ttypeof res?.tokensBefore === \"number\" ? `Tokens before: ${res.tokensBefore}` : null,\n\t\t\t].filter(Boolean);\n\n\t\t\tconst text = headerLines.join(\"\\n\") + (res?.summary ? `\\n\\n${res.summary}` : \"\");\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"session\") {\n\t\t\tconst stats = piSession.getSessionStats();\n\t\t\tconst lines: string[] = [];\n\t\t\tif (stats.sessionId !== undefined && stats.sessionId !== \"\")\n\t\t\t\tlines.push(`Session: ${stats.sessionId}`);\n\t\t\tif (stats.sessionFile !== undefined && stats.sessionFile !== \"\")\n\t\t\t\tlines.push(`Session file: ${stats.sessionFile}`);\n\t\t\tlines.push(`Messages: ${stats.totalMessages}`);\n\t\t\tlines.push(`Cost: ${stats.cost}`);\n\t\t\tconst t = stats.tokens;\n\t\t\tconst parts: string[] = [];\n\t\t\tif (t.input) parts.push(`in ${t.input}`);\n\t\t\tif (t.output) parts.push(`out ${t.output}`);\n\t\t\tif (t.cacheRead) parts.push(`cache read ${t.cacheRead}`);\n\t\t\tif (t.cacheWrite) parts.push(`cache write ${t.cacheWrite}`);\n\t\t\tif (t.total) parts.push(`total ${t.total}`);\n\t\t\tif (parts.length > 0) lines.push(`Tokens: ${parts.join(\", \")}`);\n\n\t\t\tconst text = lines.join(\"\\n\");\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"name\") {\n\t\t\tconst name = args.join(\" \").trim();\n\t\t\tif (!name) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /name <name>\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tpiSession.setSessionName(name);\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"session_info_update\",\n\t\t\t\t\ttitle: name,\n\t\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Session name set: ${name}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"steering\") {\n\t\t\tconst modeRaw = String(args[0] ?? \"\").toLowerCase();\n\t\t\tif (!modeRaw) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Steering mode: ${piSession.steeringMode}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tif (modeRaw !== \"all\" && modeRaw !== \"one-at-a-time\") {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /steering all | /steering one-at-a-time\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tpiSession.setSteeringMode(modeRaw);\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Steering mode set to: ${modeRaw}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"follow-up\") {\n\t\t\tconst modeRaw = String(args[0] ?? \"\").toLowerCase();\n\t\t\tif (!modeRaw) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Follow-up mode: ${piSession.followUpMode}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tif (modeRaw !== \"all\" && modeRaw !== \"one-at-a-time\") {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /follow-up all | /follow-up one-at-a-time\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tpiSession.setFollowUpMode(modeRaw);\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Follow-up mode set to: ${modeRaw}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"autocompact\") {\n\t\t\tconst mode = (args[0] ?? \"toggle\").toLowerCase();\n\t\t\tlet enabled: boolean | null = null;\n\t\t\tif (mode === \"on\" || mode === \"true\" || mode === \"enable\") enabled = true;\n\t\t\telse if (mode === \"off\" || mode === \"false\" || mode === \"disable\") enabled = false;\n\n\t\t\tif (enabled === null) {\n\t\t\t\tenabled = !piSession.autoCompactionEnabled;\n\t\t\t}\n\n\t\t\tpiSession.setAutoCompactionEnabled(enabled);\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Auto-compaction ${enabled ? \"enabled\" : \"disabled\"}.` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"changelog\") {\n\t\t\tconst changelogPath = findChangelog();\n\t\t\tif (changelogPath === null) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Changelog not found.\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tlet text = \"\";\n\t\t\ttry {\n\t\t\t\ttext = readFileSync(changelogPath, \"utf-8\");\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Failed to read changelog: ${msg}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tconst maxChars = 20_000;\n\t\t\tif (text.length > maxChars) text = `${text.slice(0, maxChars)}\\n\\n...(truncated)...`;\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"export\") {\n\t\t\tconst messageCount = piSession.messages.length;\n\t\t\tif (messageCount === 0) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Nothing to export yet. Send a prompt first.\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst safeSessionId = session.sessionId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t\t\t\tconst outputPath = join(session.cwd, `pi-session-${safeSessionId}.html`);\n\t\t\t\tconst resultPath = await piSession.exportToHtml(outputPath);\n\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Session exported: \" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\ttype: \"resource_link\",\n\t\t\t\t\t\t\tname: `pi-session-${safeSessionId}.html`,\n\t\t\t\t\t\t\turi: `file://${resultPath}`,\n\t\t\t\t\t\t\tmimeType: \"text/html\",\n\t\t\t\t\t\t\ttitle: \"Session exported\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Export failed: ${msg}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\nfunction isThinkingLevel(x: string): x is ThinkingLevel {\n\treturn (\n\t\tx === \"off\" || x === \"minimal\" || x === \"low\" || x === \"medium\" || x === \"high\" || x === \"xhigh\"\n\t);\n}\n\nfunction buildThinkingModes(piSession: AgentSession): {\n\tavailableModes: Array<{ id: string; name: string; description?: string | null }>;\n\tcurrentModeId: string;\n} {\n\tconst levels = piSession.getAvailableThinkingLevels();\n\treturn {\n\t\tcurrentModeId: piSession.thinkingLevel,\n\t\tavailableModes: levels.map((id) => ({\n\t\t\tid,\n\t\t\tname: `Thinking: ${id}`,\n\t\t\tdescription: null,\n\t\t})),\n\t};\n}\n\nfunction buildModelState(piSession: AgentSession): SessionModelState {\n\tconst available = piSession.modelRegistry.getAvailable();\n\tconst current = piSession.model;\n\n\tconst availableModels: ModelInfo[] = available.map((m) => ({\n\t\tmodelId: `${m.provider}/${m.id}`,\n\t\tname: `${m.provider}/${m.name ?? m.id}`,\n\t\tdescription: null,\n\t}));\n\n\tlet currentModelId = \"default\";\n\tif (current !== undefined) {\n\t\tcurrentModelId = `${current.provider}/${current.id}`;\n\t} else if (availableModels.length > 0 && availableModels[0] !== undefined) {\n\t\tcurrentModelId = availableModels[0].modelId;\n\t}\n\n\treturn { availableModels, currentModelId };\n}\n\nfunction buildConfigOptions(\n\tmodes: SessionModeState,\n\tmodels: SessionModelState,\n): SessionConfigOption[] {\n\treturn [\n\t\t{\n\t\t\tid: \"model\",\n\t\t\tname: \"Model\",\n\t\t\tdescription: \"AI model to use\",\n\t\t\tcategory: \"model\",\n\t\t\ttype: \"select\" as const,\n\t\t\tcurrentValue: models.currentModelId,\n\t\t\toptions: models.availableModels.map((m) => ({\n\t\t\t\tvalue: m.modelId,\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description ?? null,\n\t\t\t})),\n\t\t},\n\t\t{\n\t\t\tid: \"thought_level\",\n\t\t\tname: \"Thinking Level\",\n\t\t\tdescription: \"Reasoning depth for models that support it\",\n\t\t\tcategory: \"thought_level\",\n\t\t\ttype: \"select\" as const,\n\t\t\tcurrentValue: modes.currentModeId,\n\t\t\toptions: modes.availableModes.map((m) => ({\n\t\t\t\tvalue: m.id,\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description ?? null,\n\t\t\t})),\n\t\t},\n\t];\n}\n\nfunction buildCommandList(\n\tpiSession: AgentSession,\n\tenableSkillCommands: boolean,\n): AvailableCommand[] {\n\tconst commands: AvailableCommand[] = [];\n\n\tfor (const template of piSession.promptTemplates) {\n\t\tcommands.push({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description ?? `(prompt)`,\n\t\t});\n\t}\n\n\tif (enableSkillCommands) {\n\t\tconst skills = piSession.resourceLoader.getSkills();\n\t\tfor (const skill of skills.skills) {\n\t\t\tcommands.push({\n\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\tdescription: skill.description ?? `(skill)`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const cmd of piSession.extensionRunner.getRegisteredCommands()) {\n\t\tcommands.push({\n\t\t\tname: cmd.name,\n\t\t\tdescription: cmd.description ?? \"(extension)\",\n\t\t});\n\t}\n\n\treturn commands;\n}\n\nfunction findChangelog(): string | null {\n\ttry {\n\t\tconst whichCmd = process.platform === \"win32\" ? \"where\" : \"which\";\n\t\tconst which = spawnSync(whichCmd, [\"pi\"], { encoding: \"utf-8\" });\n\t\tconst piPath = String(which.stdout ?? \"\")\n\t\t\t.split(/\\r?\\n/)[0]\n\t\t\t?.trim();\n\t\tif (piPath !== undefined && piPath !== \"\") {\n\t\t\tconst resolved = realpathSync(piPath);\n\t\t\tconst pkgRoot = dirname(dirname(resolved));\n\t\t\tconst p = join(pkgRoot, \"CHANGELOG.md\");\n\t\t\tif (existsSync(p)) return p;\n\t\t}\n\t} catch {}\n\n\ttry {\n\t\tconst npmRoot = spawnSync(\"npm\", [\"root\", \"-g\"], { encoding: \"utf-8\" });\n\t\tconst root = String(npmRoot.stdout ?? \"\").trim();\n\t\tif (root) {\n\t\t\tconst p = join(root, \"@mariozechner\", \"pi-coding-agent\", \"CHANGELOG.md\");\n\t\t\tif (existsSync(p)) return p;\n\t\t}\n\t} catch {}\n\n\treturn null;\n}\n","/**\n * Shared ACP-over-stream wiring used by both the in-process v0.5 fallback and\n * the daemon's per-connection accept path.\n *\n * Owns nothing global. Returns the constructed AgentSideConnection plus a\n * shutdown helper. Caller decides what process / signal handlers to attach.\n */\n\nimport type { Duplex } from \"node:stream\";\nimport { AgentSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\";\nimport { PiAcpAgent } from \"@pi-acp/acp/agent\";\nimport type { DaemonContext } from \"@pi-acp/daemon/context\";\n\nexport interface ServeOptions {\n\t/** Reads from the client. */\n\tinput: Duplex;\n\t/** Writes to the client. */\n\toutput: Duplex;\n\t/** Optional daemon context. Absent in `PI_ACP_NO_DAEMON=1` fallback path. */\n\tdaemonContext?: DaemonContext;\n}\n\nexport interface ServeHandle {\n\tconnection: AgentSideConnection;\n\t/** Best-effort dispose of the PiAcpAgent. */\n\tdispose: () => void;\n}\n\nexport function serveAcp(opts: ServeOptions): ServeHandle {\n\t// Build the NDJSON framing layer. `input` is the client-bound stream we\n\t// read FROM (client → agent). `output` is the stream we write TO\n\t// (agent → client). ndJsonStream(writable, readable): first arg is where\n\t// the agent writes responses, second is where it reads requests.\n\tconst stream = ndJsonStream(toWebWritable(opts.output), toWebReadable(opts.input));\n\tconst connection = new AgentSideConnection(\n\t\t(conn) => new PiAcpAgent(conn, opts.daemonContext),\n\t\tstream,\n\t);\n\treturn {\n\t\tconnection,\n\t\tdispose() {\n\t\t\ttry {\n\t\t\t\tconst inner = readUnknownProp(connection, \"agent\");\n\t\t\t\tconst dispose = readUnknownProp(inner, \"dispose\");\n\t\t\t\tif (typeof dispose === \"function\") {\n\t\t\t\t\tReflect.apply(dispose, inner, []);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction readUnknownProp(target: unknown, key: string): unknown {\n\tif (typeof target !== \"object\" || target === null) return undefined;\n\treturn Reflect.get(target, key);\n}\n\nfunction toWebReadable(src: Duplex): ReadableStream<Uint8Array> {\n\treturn new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tsrc.on(\"data\", (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)));\n\t\t\tsrc.on(\"end\", () => {\n\t\t\t\ttry {\n\t\t\t\t\tcontroller.close();\n\t\t\t\t} catch {\n\t\t\t\t\t/* already closed */\n\t\t\t\t}\n\t\t\t});\n\t\t\tsrc.on(\"error\", (err) => {\n\t\t\t\ttry {\n\t\t\t\t\tcontroller.error(err);\n\t\t\t\t} catch {\n\t\t\t\t\t/* already terminated */\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t});\n}\n\nfunction toWebWritable(dst: Duplex): WritableStream<Uint8Array> {\n\treturn new WritableStream<Uint8Array>({\n\t\twrite(chunk) {\n\t\t\treturn new Promise<void>((resolve) => {\n\t\t\t\tif (dst.destroyed || !dst.writable) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tdst.write(chunk, () => resolve());\n\t\t\t\t} catch {\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t});\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@victor-software-house/pi-acp",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "ACP adapter for pi coding agent",
5
5
  "license": "MIT",
6
6
  "author": "Victor Software House",
@@ -1 +0,0 @@
1
- {"version":3,"file":"daemon-y7gCaXDq.mjs","names":[],"sources":["../src/daemon/context.ts","../src/daemon/index.ts"],"sourcesContent":["/**\n * Daemon-level shared state injected into per-connection PiAcpAgent instances.\n *\n * Phase 1 lands the interface plus stub implementations. Future phases (PRD-002\n * backends, PRD-003 SessionRegistry / IdleTracker) replace stubs with real\n * implementations registered at daemon startup.\n */\n\nexport interface DaemonContext {\n\t/** Cross-window session registry. Phase 2 of PRD-003. */\n\tsessionRegistry: SessionRegistry;\n\t/** Idle-shutdown tracker. Phase 3 of PRD-003. */\n\tidleTracker: IdleTracker;\n}\n\n/** Phase-1 stub. Replaced in Phase 2 (cross-window session visibility). */\nexport interface SessionRegistry {\n\tregister(entry: SessionEntry): void;\n\trelease(sessionId: string, connectionId: string): { disposed: boolean } | { unknown: true };\n\tlistAll(): SessionEntry[];\n\tget(sessionId: string): SessionEntry | undefined;\n}\n\nexport interface SessionEntry {\n\tsessionId: string;\n\townerConnectionId: string;\n\talsoHeldBy: Set<string>;\n}\n\n/** Phase-1 stub. Replaced in Phase 3 (idle shutdown timer). */\nexport interface IdleTracker {\n\tbump(delta: 1 | -1): void;\n\tdispose(): void;\n}\n\nexport function createStubSessionRegistry(): SessionRegistry {\n\tconst map = new Map<string, SessionEntry>();\n\treturn {\n\t\tregister(entry) {\n\t\t\tmap.set(entry.sessionId, entry);\n\t\t},\n\t\trelease(sessionId, connectionId) {\n\t\t\tconst entry = map.get(sessionId);\n\t\t\tif (!entry) return { unknown: true };\n\t\t\tentry.alsoHeldBy.delete(connectionId);\n\t\t\tif (entry.ownerConnectionId === connectionId && entry.alsoHeldBy.size === 0) {\n\t\t\t\tmap.delete(sessionId);\n\t\t\t\treturn { disposed: true };\n\t\t\t}\n\t\t\treturn { disposed: false };\n\t\t},\n\t\tlistAll() {\n\t\t\treturn Array.from(map.values());\n\t\t},\n\t\tget(sessionId) {\n\t\t\treturn map.get(sessionId);\n\t\t},\n\t};\n}\n\nexport function createNoopIdleTracker(): IdleTracker {\n\treturn {\n\t\tbump() {\n\t\t\t/* phase 3 wires this */\n\t\t},\n\t\tdispose() {\n\t\t\t/* phase 3 wires this */\n\t\t},\n\t};\n}\n\nexport function createDaemonContext(): DaemonContext {\n\treturn {\n\t\tsessionRegistry: createStubSessionRegistry(),\n\t\tidleTracker: createNoopIdleTracker(),\n\t};\n}\n","/**\n * Daemon entry point. Invoked when pi-acp is launched with `--daemon`.\n *\n * Lifecycle:\n * 1. Acquire per-UID lockfile (refuses if another daemon alive).\n * 2. Remove stale socket file if any (left by a dead prior daemon).\n * 3. Construct DaemonContext shared singletons (Phase 1: stubs).\n * 4. Bind socket; accept loop spawns a per-connection serveAcp instance.\n * 5. SIGINT / SIGTERM → graceful shutdown.\n */\n\nimport { createServer, type Server, type Socket } from \"node:net\";\nimport { createDaemonContext, type DaemonContext } from \"@pi-acp/daemon/context\";\nimport {\n\tacquireLock,\n\tensureSocketParentDir,\n\treleaseLock,\n\tremoveStaleSocketIfAny,\n\tsocketPath,\n} from \"@pi-acp/daemon/socket\";\nimport { type ServeHandle, serveAcp } from \"@pi-acp/runtime/serve\";\n\ninterface Connection {\n\tsocket: Socket;\n\thandle: ServeHandle;\n}\n\nexport async function runDaemon(): Promise<void> {\n\tconst lockResult = acquireLock();\n\tif (!lockResult.ok) {\n\t\tprocess.stderr.write(\n\t\t\t`pi-acp daemon: already running (pid ${lockResult.heldByPid ?? \"unknown\"})\\n`,\n\t\t);\n\t\tprocess.exit(1);\n\t}\n\n\tensureSocketParentDir();\n\tremoveStaleSocketIfAny();\n\n\tconst ctx: DaemonContext = createDaemonContext();\n\tconst connections = new Set<Connection>();\n\tlet shuttingDown = false;\n\n\tconst server: Server = createServer((socket) => {\n\t\tif (shuttingDown) {\n\t\t\tsocket.destroy();\n\t\t\treturn;\n\t\t}\n\t\tconst handle = serveAcp({ input: socket, output: socket, daemonContext: ctx });\n\t\tconst entry: Connection = { socket, handle };\n\t\tconnections.add(entry);\n\t\tctx.idleTracker.bump(1);\n\n\t\tconst cleanup = (): void => {\n\t\t\tif (!connections.delete(entry)) return;\n\t\t\ttry {\n\t\t\t\thandle.dispose();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t\tctx.idleTracker.bump(-1);\n\t\t};\n\n\t\tsocket.on(\"close\", cleanup);\n\t\tsocket.on(\"error\", cleanup);\n\t});\n\n\tserver.on(\"error\", (err) => {\n\t\tprocess.stderr.write(`pi-acp daemon: server error: ${err.message}\\n`);\n\t});\n\n\tawait new Promise<void>((resolve, reject) => {\n\t\tconst path = socketPath();\n\t\tserver.listen(path, () => resolve());\n\t\tserver.once(\"error\", reject);\n\t});\n\n\tif (process.env[\"PI_ACP_DAEMON_DEBUG\"] === \"1\") {\n\t\tprocess.stderr.write(`pi-acp daemon: listening on ${socketPath()} (pid ${process.pid})\\n`);\n\t}\n\n\tconst shutdown = async (): Promise<void> => {\n\t\tif (shuttingDown) return;\n\t\tshuttingDown = true;\n\t\tserver.close();\n\t\tfor (const entry of connections) {\n\t\t\ttry {\n\t\t\t\tentry.handle.dispose();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tentry.socket.destroy();\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t}\n\t\tconnections.clear();\n\t\tctx.idleTracker.dispose();\n\t\tremoveStaleSocketIfAny();\n\t\treleaseLock();\n\t\tprocess.exit(0);\n\t};\n\n\tprocess.on(\"SIGINT\", () => {\n\t\tvoid shutdown();\n\t});\n\tprocess.on(\"SIGTERM\", () => {\n\t\tvoid shutdown();\n\t});\n}\n"],"mappings":";;;;;AAmCA,SAAgB,4BAA6C;CAC5D,MAAM,sBAAM,IAAI,KAA2B;AAC3C,QAAO;EACN,SAAS,OAAO;AACf,OAAI,IAAI,MAAM,WAAW,MAAM;;EAEhC,QAAQ,WAAW,cAAc;GAChC,MAAM,QAAQ,IAAI,IAAI,UAAU;AAChC,OAAI,CAAC,MAAO,QAAO,EAAE,SAAS,MAAM;AACpC,SAAM,WAAW,OAAO,aAAa;AACrC,OAAI,MAAM,sBAAsB,gBAAgB,MAAM,WAAW,SAAS,GAAG;AAC5E,QAAI,OAAO,UAAU;AACrB,WAAO,EAAE,UAAU,MAAM;;AAE1B,UAAO,EAAE,UAAU,OAAO;;EAE3B,UAAU;AACT,UAAO,MAAM,KAAK,IAAI,QAAQ,CAAC;;EAEhC,IAAI,WAAW;AACd,UAAO,IAAI,IAAI,UAAU;;EAE1B;;AAGF,SAAgB,wBAAqC;AACpD,QAAO;EACN,OAAO;EAGP,UAAU;EAGV;;AAGF,SAAgB,sBAAqC;AACpD,QAAO;EACN,iBAAiB,2BAA2B;EAC5C,aAAa,uBAAuB;EACpC;;;;;;;;;;;;;;AChDF,eAAsB,YAA2B;CAChD,MAAM,aAAa,aAAa;AAChC,KAAI,CAAC,WAAW,IAAI;AACnB,UAAQ,OAAO,MACd,uCAAuC,WAAW,aAAa,UAAU,KACzE;AACD,UAAQ,KAAK,EAAE;;AAGhB,wBAAuB;AACvB,yBAAwB;CAExB,MAAM,MAAqB,qBAAqB;CAChD,MAAM,8BAAc,IAAI,KAAiB;CACzC,IAAI,eAAe;CAEnB,MAAM,SAAiB,cAAc,WAAW;AAC/C,MAAI,cAAc;AACjB,UAAO,SAAS;AAChB;;EAED,MAAM,SAAS,SAAS;GAAE,OAAO;GAAQ,QAAQ;GAAQ,eAAe;GAAK,CAAC;EAC9E,MAAM,QAAoB;GAAE;GAAQ;GAAQ;AAC5C,cAAY,IAAI,MAAM;AACtB,MAAI,YAAY,KAAK,EAAE;EAEvB,MAAM,gBAAsB;AAC3B,OAAI,CAAC,YAAY,OAAO,MAAM,CAAE;AAChC,OAAI;AACH,WAAO,SAAS;WACT;AAGR,OAAI,YAAY,KAAK,GAAG;;AAGzB,SAAO,GAAG,SAAS,QAAQ;AAC3B,SAAO,GAAG,SAAS,QAAQ;GAC1B;AAEF,QAAO,GAAG,UAAU,QAAQ;AAC3B,UAAQ,OAAO,MAAM,gCAAgC,IAAI,QAAQ,IAAI;GACpE;AAEF,OAAM,IAAI,SAAe,SAAS,WAAW;EAC5C,MAAM,OAAO,YAAY;AACzB,SAAO,OAAO,YAAY,SAAS,CAAC;AACpC,SAAO,KAAK,SAAS,OAAO;GAC3B;AAEF,KAAI,QAAQ,IAAI,2BAA2B,IAC1C,SAAQ,OAAO,MAAM,+BAA+B,YAAY,CAAC,QAAQ,QAAQ,IAAI,KAAK;CAG3F,MAAM,WAAW,YAA2B;AAC3C,MAAI,aAAc;AAClB,iBAAe;AACf,SAAO,OAAO;AACd,OAAK,MAAM,SAAS,aAAa;AAChC,OAAI;AACH,UAAM,OAAO,SAAS;WACf;AAGR,OAAI;AACH,UAAM,OAAO,SAAS;WACf;;AAIT,cAAY,OAAO;AACnB,MAAI,YAAY,SAAS;AACzB,0BAAwB;AACxB,eAAa;AACb,UAAQ,KAAK,EAAE;;AAGhB,SAAQ,GAAG,gBAAgB;AACrB,YAAU;GACd;AACF,SAAQ,GAAG,iBAAiB;AACtB,YAAU;GACd"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"serve-DgZht0tv.mjs","names":["resolvePath","SessionManager","isTextBlock","SessionManager","pkgJson.name","pkgJson.version","PiSessionManager"],"sources":["../src/acp/auth.ts","../src/acp/auth-required.ts","../src/acp/client-capabilities.ts","../src/acp/model-alias.ts","../src/acp/pi-settings.ts","../src/acp/translate/tool-content.ts","../src/acp/unreachable.ts","../src/acp/session.ts","../src/acp/translate/pi-messages.ts","../src/acp/translate/prompt.ts","../package.json","../src/acp/agent.ts","../src/runtime/serve.ts"],"sourcesContent":["/**\n * Build ACP AuthMethod descriptors for terminal-based authentication.\n *\n * Supports both the registry-required \"type/args/env\" shape and Zed's\n * _meta[\"terminal-auth\"] extension for the Authenticate banner.\n */\n\nimport type { AuthMethod } from \"@agentclientprotocol/sdk\";\n\nexport const AUTH_METHOD_ID = \"pi_terminal_login\";\n\ninterface AuthMethodOptions {\n\tsupportsTerminalAuthMeta?: boolean;\n}\n\nexport function buildAuthMethods(opts?: AuthMethodOptions): AuthMethod[] {\n\tconst supportsTerminalAuthMeta = opts?.supportsTerminalAuthMeta ?? true;\n\n\tconst method: AuthMethod = {\n\t\tid: AUTH_METHOD_ID,\n\t\tname: \"Launch pi in the terminal\",\n\t\tdescription: \"Start pi in an interactive terminal to configure API keys or login\",\n\t\ttype: \"terminal\",\n\t\targs: [\"--terminal-login\"],\n\t\tenv: {},\n\t};\n\n\tif (supportsTerminalAuthMeta) {\n\t\tconst launch = resolveTerminalLaunchCommand();\n\t\tmethod._meta = {\n\t\t\t\"terminal-auth\": {\n\t\t\t\t...launch,\n\t\t\t\tlabel: \"Launch pi\",\n\t\t\t},\n\t\t};\n\t}\n\n\treturn [method];\n}\n\nfunction resolveTerminalLaunchCommand(): { command: string; args: string[] } {\n\tconst argv0 = process.argv[0] ?? \"node\";\n\tconst argv1 = process.argv[1];\n\n\tif (argv1 !== undefined && argv0.includes(\"node\") && argv1.endsWith(\".js\")) {\n\t\treturn { command: argv0, args: [argv1, \"--terminal-login\"] };\n\t}\n\n\treturn { command: \"pi-acp\", args: [\"--terminal-login\"] };\n}\n","/**\n * Detect common auth/credential errors from pi and surface them as ACP AUTH_REQUIRED.\n */\n\nimport { RequestError } from \"@agentclientprotocol/sdk\";\nimport { buildAuthMethods } from \"@pi-acp/acp/auth\";\n\nconst AUTH_ERROR_PATTERNS = [\n\t\"api key\",\n\t\"apikey\",\n\t\"missing key\",\n\t\"no key\",\n\t\"not configured\",\n\t\"unauthorized\",\n\t\"authentication\",\n\t\"permission denied\",\n\t\"forbidden\",\n\t\"401\",\n\t\"403\",\n];\n\nexport function detectAuthError(err: unknown): RequestError | null {\n\tconst text = err instanceof Error ? err.message : String(err ?? \"\");\n\tconst lower = text.toLowerCase();\n\n\tconst isAuthRelated = AUTH_ERROR_PATTERNS.some((p) => lower.includes(p));\n\tif (!isAuthRelated) return null;\n\n\treturn RequestError.authRequired(\n\t\t{ authMethods: buildAuthMethods() },\n\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t);\n}\n","/**\n * Parse and represent client capabilities from the ACP initialize request.\n *\n * Both reference implementations (claude-agent-acp, codex-acp) store and\n * use `clientCapabilities` for feature detection and auth method selection.\n */\n\nimport type { ClientCapabilities } from \"@agentclientprotocol/sdk\";\n\nexport interface ClientCapabilityFlags {\n\t/** Client supports terminal output metadata (info/output/exit lifecycle). */\n\tterminalOutput: boolean;\n\t/** Client supports terminal-based authentication with command metadata. */\n\tterminalAuth: boolean;\n\t/** Client supports gateway-based authentication. */\n\tgatewayAuth: boolean;\n}\n\n/**\n * Extract well-known capability flags from ACP `ClientCapabilities`.\n *\n * Reads from:\n * - `_meta.terminal_output` (terminal output rendering)\n * - `_meta.terminal-auth` (terminal auth with command metadata)\n * - `auth._meta.gateway` (gateway auth, future use)\n */\nexport function parseClientCapabilities(\n\tcaps: ClientCapabilities | undefined | null,\n): ClientCapabilityFlags {\n\tif (caps === undefined || caps === null) {\n\t\treturn { terminalOutput: false, terminalAuth: false, gatewayAuth: false };\n\t}\n\n\t// _meta is an optional declared property, safe to access with dot\n\tconst meta = caps._meta;\n\tconst terminalOutput =\n\t\ttypeof meta === \"object\" && meta !== null && meta[\"terminal_output\"] === true;\n\tconst terminalAuth = typeof meta === \"object\" && meta !== null && meta[\"terminal-auth\"] === true;\n\n\t// gateway auth lives under auth._meta.gateway (non-standard extension)\n\tlet gatewayAuth = false;\n\tif (\"auth\" in caps) {\n\t\tconst auth = caps.auth;\n\t\tif (typeof auth === \"object\" && auth !== null && \"_meta\" in auth) {\n\t\t\tconst authMeta = auth._meta;\n\t\t\tif (typeof authMeta === \"object\" && authMeta !== null && \"gateway\" in authMeta) {\n\t\t\t\tgatewayAuth = authMeta[\"gateway\"] === true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { terminalOutput, terminalAuth, gatewayAuth };\n}\n","/**\n * Model alias resolution for user-friendly model names.\n *\n * Lets users type \"opus\", \"sonnet\", \"opus[1m]\" instead of exact\n * \"provider/modelId\" strings. Uses tokenized matching and scoring\n * following the claude-agent-acp pattern.\n */\n\ninterface ModelEntry {\n\tprovider: string;\n\tid: string;\n\tname?: string | undefined;\n}\n\ninterface ResolvedModel {\n\tprovider: string;\n\tid: string;\n}\n\n/**\n * Tokenize a string: split on non-alphanumeric, lowercase, strip \"claude\".\n */\nfunction tokenize(input: string): string[] {\n\treturn input\n\t\t.toLowerCase()\n\t\t.split(/[^a-z0-9]+/)\n\t\t.filter((t) => t !== \"\" && t !== \"claude\");\n}\n\n/**\n * Extract a context hint in square brackets, e.g. \"opus[1m]\" -> { base: \"opus\", hint: \"1m\" }.\n */\nfunction extractContextHint(input: string): { base: string; hint: string | null } {\n\tconst match = /^(.+?)\\[([^\\]]+)\\]$/.exec(input);\n\tif (match !== null && match[1] !== undefined && match[2] !== undefined) {\n\t\treturn { base: match[1], hint: match[2] };\n\t}\n\treturn { base: input, hint: null };\n}\n\n/** Check if a string is purely numeric. */\nfunction isNumeric(s: string): boolean {\n\treturn /^\\d+$/.test(s);\n}\n\n/**\n * Score how well a model matches the given preference tokens.\n *\n * Returns a score >= 0 (higher is better), or -1 for no match.\n * Requires at least one non-numeric token to match to avoid false positives\n * from bare version numbers (e.g. \"4\" matching model version suffixes).\n */\nfunction scoreModel(model: ModelEntry, prefTokens: string[], hint: string | null): number {\n\tconst modelStr = `${model.provider}/${model.id}/${model.name ?? \"\"}`.toLowerCase();\n\tconst modelTokens = tokenize(modelStr);\n\n\tlet matched = 0;\n\tlet hasNonNumericMatch = false;\n\tfor (const pt of prefTokens) {\n\t\tif (modelTokens.some((mt) => mt.includes(pt) || pt.includes(mt))) {\n\t\t\tmatched++;\n\t\t\tif (!isNumeric(pt)) hasNonNumericMatch = true;\n\t\t}\n\t}\n\n\tif (matched === 0) return -1;\n\n\t// Require at least one non-numeric token to match -- prevents \"gpt-4\"\n\t// matching on the bare \"4\" version component.\n\tif (!hasNonNumericMatch) return -1;\n\n\tlet score = matched / prefTokens.length;\n\n\t// Bonus for hint match (e.g. \"1m\" context window hint)\n\tif (hint !== null && modelStr.includes(hint.toLowerCase())) {\n\t\tscore += 0.5;\n\t}\n\n\t// Bonus for exact substring match on model id\n\tconst pref = prefTokens.join(\"\");\n\tif (model.id.toLowerCase().includes(pref)) {\n\t\tscore += 0.25;\n\t}\n\n\treturn score;\n}\n\n/**\n * Resolve a user-friendly model preference to a concrete model.\n *\n * Matching strategy (in order):\n * 1. Exact match on \"provider/id\"\n * 2. Exact match on \"id\" alone\n * 3. Tokenized scored match with optional context hint\n *\n * Returns null if no model matches.\n */\nexport function resolveModelPreference(\n\tmodels: readonly ModelEntry[],\n\tpreference: string,\n): ResolvedModel | null {\n\tconst trimmed = preference.trim();\n\tif (trimmed === \"\") return null;\n\n\t// 1. Exact match on \"provider/id\"\n\tif (trimmed.includes(\"/\")) {\n\t\tconst [p, ...rest] = trimmed.split(\"/\");\n\t\tconst provider = p ?? \"\";\n\t\tconst id = rest.join(\"/\");\n\t\tconst exact = models.find(\n\t\t\t(m) =>\n\t\t\t\tm.provider.toLowerCase() === provider.toLowerCase() &&\n\t\t\t\tm.id.toLowerCase() === id.toLowerCase(),\n\t\t);\n\t\tif (exact !== undefined) return { provider: exact.provider, id: exact.id };\n\t}\n\n\t// 2. Exact match on id alone\n\tconst byId = models.find((m) => m.id.toLowerCase() === trimmed.toLowerCase());\n\tif (byId !== undefined) return { provider: byId.provider, id: byId.id };\n\n\t// 3. Tokenized scored match\n\tconst { base, hint } = extractContextHint(trimmed);\n\tconst prefTokens = tokenize(base);\n\tif (prefTokens.length === 0) return null;\n\n\tlet bestModel: ModelEntry | null = null;\n\tlet bestScore = -1;\n\n\tfor (const model of models) {\n\t\tconst s = scoreModel(model, prefTokens, hint);\n\t\tif (s > bestScore) {\n\t\t\tbestScore = s;\n\t\t\tbestModel = model;\n\t\t}\n\t}\n\n\t// Require at least 50% of preference tokens to match to avoid spurious hits\n\t// (e.g. \"gpt-4\" matching on the \"4\" token alone)\n\tif (bestModel === null || bestScore < 0.5) return null;\n\treturn { provider: bestModel.provider, id: bestModel.id };\n}\n","/**\n * Read pi settings from global and project config files.\n *\n * Settings are merged: project overrides global.\n * Paths follow pi-mono conventions:\n * Global: ~/.pi/agent/settings.json\n * Project: <cwd>/.pi/settings.json\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport * as z from \"zod\";\n\nconst piSettingsSchema = z.object({\n\tenableSkillCommands: z.boolean().optional(),\n\tquietStartup: z.boolean().optional(),\n\tquietStart: z.boolean().optional(),\n\tskills: z\n\t\t.object({\n\t\t\tenableSkillCommands: z.boolean().optional(),\n\t\t})\n\t\t.optional(),\n});\n\ntype PiSettings = z.infer<typeof piSettingsSchema>;\n\nfunction isRecord(x: unknown): x is Record<string, unknown> {\n\treturn typeof x === \"object\" && x !== null && !Array.isArray(x);\n}\n\nfunction merge(\n\tbase: Record<string, unknown>,\n\toverride: Record<string, unknown>,\n): Record<string, unknown> {\n\tconst result: Record<string, unknown> = { ...base };\n\tfor (const [key, val] of Object.entries(override)) {\n\t\tconst existing = result[key];\n\t\tif (isRecord(existing) && isRecord(val)) {\n\t\t\tresult[key] = merge(existing, val);\n\t\t} else {\n\t\t\tresult[key] = val;\n\t\t}\n\t}\n\treturn result;\n}\n\nfunction readJson(path: string): Record<string, unknown> {\n\ttry {\n\t\tif (!existsSync(path)) return {};\n\t\tconst data: unknown = JSON.parse(readFileSync(path, \"utf-8\"));\n\t\treturn isRecord(data) ? data : {};\n\t} catch {\n\t\treturn {};\n\t}\n}\n\nexport function piAgentDir(): string {\n\treturn process.env.PI_CODING_AGENT_DIR !== undefined\n\t\t? resolve(process.env.PI_CODING_AGENT_DIR)\n\t\t: join(homedir(), \".pi\", \"agent\");\n}\n\nfunction resolvedSettings(cwd: string): PiSettings {\n\tconst globalPath = join(piAgentDir(), \"settings.json\");\n\tconst projectPath = resolve(cwd, \".pi\", \"settings.json\");\n\tconst merged = merge(readJson(globalPath), readJson(projectPath));\n\tconst result = piSettingsSchema.safeParse(merged);\n\treturn result.success ? result.data : {};\n}\n\nexport function skillCommandsEnabled(cwd: string): boolean {\n\tconst settings = resolvedSettings(cwd);\n\n\tif (typeof settings.enableSkillCommands === \"boolean\") {\n\t\treturn settings.enableSkillCommands;\n\t}\n\n\tif (typeof settings.skills?.enableSkillCommands === \"boolean\") {\n\t\treturn settings.skills.enableSkillCommands;\n\t}\n\n\treturn true;\n}\n","/**\n * Per-tool content formatting for ACP tool results.\n *\n * Dispatches formatting by tool name following the reference implementation\n * pattern (claude-agent-acp / codex-acp). Each tool type produces\n * `ToolCallContent[]` appropriate for its output shape.\n */\n\nimport type { ToolCallContent } from \"@agentclientprotocol/sdk\";\nimport * as z from \"zod\";\n\n// ---------------------------------------------------------------------------\n// Zod schemas for pi tool result shapes\n// ---------------------------------------------------------------------------\n\nconst textBlockSchema = z.object({\n\ttype: z.literal(\"text\"),\n\ttext: z.string(),\n});\n\nconst imageBlockSchema = z.object({\n\ttype: z.literal(\"image\"),\n});\n\nconst contentBlockSchema = z.union([textBlockSchema, imageBlockSchema]);\n\nconst bashDetailsSchema = z.object({\n\tstdout: z.string().optional(),\n\tstderr: z.string().optional(),\n\toutput: z.string().optional(),\n\texitCode: z.number().optional(),\n\tcode: z.number().optional(),\n});\n\nconst bashResultSchema = z.object({\n\tcontent: z.array(z.unknown()).optional(),\n\tdetails: bashDetailsSchema.optional(),\n\tstdout: z.string().optional(),\n\tstderr: z.string().optional(),\n\toutput: z.string().optional(),\n\texitCode: z.number().optional(),\n\tcode: z.number().optional(),\n});\n\n// ---------------------------------------------------------------------------\n// Extraction helpers\n// ---------------------------------------------------------------------------\n\nexport interface BashOutput {\n\toutput: string;\n\texitCode: number | undefined;\n}\n\n/**\n * Extract stdout/stderr and exit code from a pi bash/tmux result.\n */\nexport function extractBashOutput(result: unknown): BashOutput {\n\tif (result === null || result === undefined || typeof result !== \"object\") {\n\t\treturn { output: \"\", exitCode: undefined };\n\t}\n\n\tconst parsed = bashResultSchema.safeParse(result);\n\tif (!parsed.success) {\n\t\treturn { output: \"\", exitCode: undefined };\n\t}\n\n\tconst r = parsed.data;\n\tconst d = r.details;\n\n\t// Try content blocks first\n\tif (r.content !== undefined) {\n\t\tconst texts = r.content\n\t\t\t.map((block) => textBlockSchema.safeParse(block))\n\t\t\t.filter((res) => res.success)\n\t\t\t.map((res) => res.data.text);\n\t\tif (texts.length > 0) {\n\t\t\tconst exitCode = d?.exitCode ?? r.exitCode ?? d?.code ?? r.code;\n\t\t\treturn { output: texts.join(\"\"), exitCode };\n\t\t}\n\t}\n\n\tconst stdout = d?.stdout ?? r.stdout ?? d?.output ?? r.output;\n\tconst stderr = d?.stderr ?? r.stderr;\n\tconst exitCode = d?.exitCode ?? r.exitCode ?? d?.code ?? r.code;\n\n\tconst parts: string[] = [];\n\tif (stdout !== undefined && stdout.trim() !== \"\") parts.push(stdout);\n\tif (stderr !== undefined && stderr.trim() !== \"\") parts.push(stderr);\n\n\treturn { output: parts.join(\"\\n\"), exitCode };\n}\n\n/**\n * Extract text content from a pi tool result (generic).\n */\nexport function extractTextContent(result: unknown): string {\n\tif (result === null || result === undefined || typeof result !== \"object\") return \"\";\n\n\tif (\"content\" in result && Array.isArray(result.content)) {\n\t\tconst texts: string[] = [];\n\t\tfor (const block of result.content) {\n\t\t\tconst parsed = textBlockSchema.safeParse(block);\n\t\t\tif (parsed.success) texts.push(parsed.data.text);\n\t\t}\n\t\tif (texts.length > 0) return texts.join(\"\");\n\t}\n\n\ttry {\n\t\treturn JSON.stringify(result, null, 2);\n\t} catch {\n\t\treturn String(result);\n\t}\n}\n\n/**\n * Extract content blocks from a pi result, preserving type information.\n * Used for read results where images need to be preserved.\n */\nexport function extractContentBlocks(\n\tresult: unknown,\n): Array<{ type: \"text\"; text: string } | { type: \"image\" }> {\n\tif (result === null || result === undefined || typeof result !== \"object\") return [];\n\tif (!(\"content\" in result) || !Array.isArray(result.content)) return [];\n\n\tconst blocks: Array<{ type: \"text\"; text: string } | { type: \"image\" }> = [];\n\tfor (const raw of result.content) {\n\t\tconst parsed = contentBlockSchema.safeParse(raw);\n\t\tif (parsed.success) {\n\t\t\tblocks.push(parsed.data);\n\t\t}\n\t}\n\treturn blocks;\n}\n\n// ---------------------------------------------------------------------------\n// Markdown escaping via dynamic backtick fence wrapping\n// ---------------------------------------------------------------------------\n\n/**\n * Find the longest consecutive backtick sequence in a string.\n */\nfunction longestBacktickRun(text: string): number {\n\tlet max = 0;\n\tlet current = 0;\n\tfor (const ch of text) {\n\t\tif (ch === \"`\") {\n\t\t\tcurrent++;\n\t\t\tif (current > max) max = current;\n\t\t} else {\n\t\t\tcurrent = 0;\n\t\t}\n\t}\n\treturn max;\n}\n\n/**\n * Wrap text in a dynamically-sized backtick fence to prevent markdown rendering.\n *\n * Instead of character-level escaping (which fails on files containing backtick\n * sequences, indented code blocks, blockquotes, and list markers), this wraps\n * the entire text in a backtick fence whose length exceeds any backtick sequence\n * in the content. This approach is simpler and strictly more correct (following\n * the claude-agent-acp pattern).\n */\nexport function markdownEscape(text: string): string {\n\tif (text === \"\") return \"\";\n\n\tconst fenceLen = Math.max(3, longestBacktickRun(text) + 1);\n\tconst fence = \"`\".repeat(fenceLen);\n\n\t// Avoid a trailing double newline before the closing fence\n\tconst body = text.endsWith(\"\\n\") ? text.slice(0, -1) : text;\n\treturn `${fence}\\n${body}\\n${fence}`;\n}\n\n// ---------------------------------------------------------------------------\n// Per-tool content formatting\n// ---------------------------------------------------------------------------\n\n/**\n * Format tool output into `ToolCallContent[]` by tool name.\n *\n * Returns the appropriate content shape for each tool type:\n * - bash/tmux: console code fences\n * - read: markdown-escaped text (images preserved)\n * - edit/write: empty (diff handled separately)\n * - lsp: code fences\n * - errors: code fences with failed status\n * - everything else: plain text\n */\nexport function formatToolContent(\n\ttoolName: string,\n\tresult: unknown,\n\tisError: boolean,\n): ToolCallContent[] {\n\t// Error path: wrap any error text in a code fence\n\tif (isError) {\n\t\tconst text = extractTextContent(result);\n\t\tif (text === \"\") return [];\n\t\treturn [{ type: \"content\", content: { type: \"text\", text: `\\`\\`\\`\\n${text}\\n\\`\\`\\`` } }];\n\t}\n\n\tswitch (toolName) {\n\t\tcase \"bash\":\n\t\tcase \"tmux\":\n\t\t\treturn formatBashContent(result);\n\n\t\tcase \"read\":\n\t\t\treturn formatReadContent(result);\n\n\t\tcase \"edit\":\n\t\tcase \"write\":\n\t\t\t// Diff content is handled separately in handleToolEnd.\n\t\t\t// Return empty so the diff path takes precedence.\n\t\t\treturn [];\n\n\t\tcase \"lsp\":\n\t\t\treturn formatLspContent(result);\n\n\t\tdefault:\n\t\t\treturn formatFallbackContent(result);\n\t}\n}\n\nfunction formatBashContent(result: unknown): ToolCallContent[] {\n\tconst { output, exitCode } = extractBashOutput(result);\n\tif (output === \"\" && exitCode === undefined) return [];\n\n\tconst parts: string[] = [];\n\tif (output !== \"\") {\n\t\tparts.push(`\\`\\`\\`console\\n${output}\\n\\`\\`\\``);\n\t}\n\tif (exitCode !== undefined && exitCode !== 0) {\n\t\tparts.push(`exit code: ${exitCode}`);\n\t}\n\n\tconst text = parts.join(\"\\n\\n\");\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text } }];\n}\n\nfunction formatReadContent(result: unknown): ToolCallContent[] {\n\tconst blocks = extractContentBlocks(result);\n\tif (blocks.length === 0) {\n\t\t// Check if the result explicitly has an empty content array\n\t\tif (\n\t\t\ttypeof result === \"object\" &&\n\t\t\tresult !== null &&\n\t\t\t\"content\" in result &&\n\t\t\tArray.isArray(result.content) &&\n\t\t\tresult.content.length === 0\n\t\t) {\n\t\t\treturn [];\n\t\t}\n\t\t// Fallback to text extraction for results without content blocks\n\t\tconst text = extractTextContent(result);\n\t\tif (text === \"\") return [];\n\t\treturn [{ type: \"content\", content: { type: \"text\", text: markdownEscape(text) } }];\n\t}\n\n\tconst content: ToolCallContent[] = [];\n\tfor (const block of blocks) {\n\t\tif (block.type === \"text\") {\n\t\t\tcontent.push({\n\t\t\t\ttype: \"content\",\n\t\t\t\tcontent: { type: \"text\", text: markdownEscape(block.text) },\n\t\t\t});\n\t\t}\n\t\t// Image blocks are preserved as-is (the ACP client handles rendering)\n\t\t// We skip them here since they need their original structure from the result\n\t}\n\n\t// If we only had image blocks and no text, return empty\n\treturn content;\n}\n\nfunction formatLspContent(result: unknown): ToolCallContent[] {\n\tconst text = extractTextContent(result);\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text: `\\`\\`\\`\\n${text}\\n\\`\\`\\`` } }];\n}\n\nfunction formatFallbackContent(result: unknown): ToolCallContent[] {\n\tconst text = extractTextContent(result);\n\tif (text === \"\") return [];\n\treturn [{ type: \"content\", content: { type: \"text\", text } }];\n}\n\n/**\n * Wrap streaming output text in a console code fence for bash/tmux.\n *\n * Each streaming update is self-contained (full accumulated buffer),\n * following the codex-acp pattern.\n */\nexport function wrapStreamingBashOutput(text: string): string {\n\tif (text === \"\") return \"\";\n\treturn `\\`\\`\\`console\\n${text}\\n\\`\\`\\``;\n}\n","/**\n * Exhaustive switch/case helper.\n *\n * Writes unknown values to stderr instead of silently ignoring them, aiding\n * debugging when the pi SDK adds new event types. Never write to stdout: it\n * carries the ACP NDJSON stream and any other byte poisons the protocol.\n */\nexport function unreachable(value: never, context?: string): void {\n\tconst label = context !== undefined ? `[${context}] ` : \"\";\n\tprocess.stderr.write(`${label}Unhandled value: ${String(value)}\\n`);\n}\n","import { readFileSync } from \"node:fs\";\nimport { isAbsolute, resolve as resolvePath } from \"node:path\";\nimport {\n\ttype AgentSideConnection,\n\ttype ContentBlock,\n\ttype McpServer,\n\tRequestError,\n\ttype SessionUpdate,\n\ttype ToolCallContent,\n\ttype ToolCallLocation,\n\ttype ToolKind,\n} from \"@agentclientprotocol/sdk\";\nimport type { AgentEvent, AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessageEvent, ToolCall } from \"@earendil-works/pi-ai\";\nimport type { AgentSession, AgentSessionEvent } from \"@earendil-works/pi-coding-agent\";\nimport { formatToolContent, wrapStreamingBashOutput } from \"@pi-acp/acp/translate/tool-content\";\nimport { unreachable } from \"@pi-acp/acp/unreachable\";\nimport * as z from \"zod\";\n\nexport type StopReason = \"end_turn\" | \"cancelled\" | \"max_tokens\" | \"error\";\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction findUniqueLineNumber(text: string, needle: string): number | undefined {\n\tif (!needle) return undefined;\n\tconst first = text.indexOf(needle);\n\tif (first < 0) return undefined;\n\tif (text.indexOf(needle, first + needle.length) >= 0) return undefined;\n\n\tlet line = 1;\n\tfor (let i = 0; i < first; i++) {\n\t\tif (text.charCodeAt(i) === 10) line++;\n\t}\n\treturn line;\n}\n\nexport interface ToolArgs {\n\tpath?: string | undefined;\n\toldText?: string | undefined;\n\t[key: string]: unknown;\n}\n\nexport function resolveToolPath(\n\targs: ToolArgs,\n\tcwd: string,\n\tline?: number,\n): ToolCallLocation[] | undefined {\n\tconst p = args.path;\n\tif (p === undefined) return undefined;\n\n\tconst resolved = isAbsolute(p) ? p : resolvePath(cwd, p);\n\treturn [{ path: resolved, ...(typeof line === \"number\" ? { line } : {}) }];\n}\n\nexport function toToolKind(toolName: string): ToolKind {\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn \"read\";\n\t\tcase \"write\":\n\t\tcase \"edit\":\n\t\t\treturn \"edit\";\n\t\tcase \"bash\":\n\t\tcase \"tmux\":\n\t\t\treturn \"execute\";\n\t\tcase \"lsp\":\n\t\t\treturn \"search\";\n\t\tdefault:\n\t\t\treturn \"other\";\n\t}\n}\n\nconst MAX_TITLE_LEN = 80;\n\nfunction truncateTitle(text: string): string {\n\tconst oneLine = text.replace(/\\n/g, \" \").trim();\n\tif (oneLine.length <= MAX_TITLE_LEN) return oneLine;\n\treturn `${oneLine.slice(0, MAX_TITLE_LEN - 1)}…`;\n}\n\nfunction capitalize(s: string): string {\n\tif (s.length === 0) return s;\n\treturn s.charAt(0).toUpperCase() + s.slice(1);\n}\n\n/**\n * Build a descriptive tool title from tool name and args.\n *\n * Returns a short human-readable label like \"Read src/index.ts\" or \"Run ls -la\".\n */\nexport function buildToolTitle(toolName: string, args: ToolArgs): string {\n\tconst p = args.path;\n\n\tswitch (toolName) {\n\t\tcase \"read\":\n\t\t\treturn p !== undefined ? `Read ${p}` : \"Read\";\n\t\tcase \"write\":\n\t\t\treturn p !== undefined ? `Write ${p}` : \"Write\";\n\t\tcase \"edit\":\n\t\t\treturn p !== undefined ? `Edit ${p}` : \"Edit\";\n\t\tcase \"bash\": {\n\t\t\tconst command =\n\t\t\t\ttypeof args[\"command\"] === \"string\"\n\t\t\t\t\t? args[\"command\"]\n\t\t\t\t\t: typeof args[\"cmd\"] === \"string\"\n\t\t\t\t\t\t? args[\"cmd\"]\n\t\t\t\t\t\t: undefined;\n\t\t\treturn command !== undefined ? truncateTitle(`Run ${command}`) : \"bash\";\n\t\t}\n\t\tcase \"lsp\": {\n\t\t\tconst action = typeof args[\"action\"] === \"string\" ? args[\"action\"] : undefined;\n\t\t\tconst file = typeof args[\"file\"] === \"string\" ? args[\"file\"] : undefined;\n\t\t\tconst query = typeof args[\"query\"] === \"string\" ? args[\"query\"] : undefined;\n\t\t\tconst line = typeof args[\"line\"] === \"number\" ? args[\"line\"] : undefined;\n\t\t\tif (action !== undefined) {\n\t\t\t\tconst target = file !== undefined ? (line !== undefined ? `${file}:${line}` : file) : query;\n\t\t\t\treturn target !== undefined\n\t\t\t\t\t? truncateTitle(`${capitalize(action)} ${target}`)\n\t\t\t\t\t: capitalize(action);\n\t\t\t}\n\t\t\treturn \"LSP\";\n\t\t}\n\t\tcase \"tmux\": {\n\t\t\tconst action = typeof args[\"action\"] === \"string\" ? args[\"action\"] : undefined;\n\t\t\tconst command = typeof args[\"command\"] === \"string\" ? args[\"command\"] : undefined;\n\t\t\tconst name = typeof args[\"name\"] === \"string\" ? args[\"name\"] : undefined;\n\t\t\tif (action === \"run\" && command !== undefined) return truncateTitle(`Tmux: ${command}`);\n\t\t\tif (action !== undefined && name !== undefined)\n\t\t\t\treturn truncateTitle(`Tmux ${action} ${name}`);\n\t\t\tif (action !== undefined) return `Tmux ${action}`;\n\t\t\treturn \"Tmux\";\n\t\t}\n\t\tcase \"context_tag\": {\n\t\t\tconst name = typeof args[\"name\"] === \"string\" ? args[\"name\"] : undefined;\n\t\t\treturn name !== undefined ? `Tag ${name}` : \"Tag\";\n\t\t}\n\t\tcase \"context_log\":\n\t\t\treturn \"Context log\";\n\t\tcase \"context_checkout\": {\n\t\t\tconst target = typeof args[\"target\"] === \"string\" ? args[\"target\"] : undefined;\n\t\t\treturn target !== undefined ? truncateTitle(`Checkout ${target}`) : \"Checkout\";\n\t\t}\n\t\tcase \"claudemon\":\n\t\t\treturn \"Check quota\";\n\t\tdefault:\n\t\t\treturn toolName;\n\t}\n}\n\n/**\n * Map pi assistant stopReason to ACP StopReason.\n * pi: \"stop\" | \"length\" | \"toolUse\" | \"error\" | \"aborted\"\n * ACP: \"end_turn\" | \"cancelled\" | \"max_tokens\" | \"error\"\n */\nfunction mapPiStopReason(piReason: string | null): StopReason {\n\tswitch (piReason) {\n\t\tcase \"stop\":\n\t\tcase \"toolUse\":\n\t\t\treturn \"end_turn\";\n\t\tcase \"length\":\n\t\t\treturn \"max_tokens\";\n\t\tcase \"aborted\":\n\t\t\treturn \"cancelled\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t\tdefault:\n\t\t\treturn \"end_turn\";\n\t}\n}\n\nfunction extractToolCallFromPartial(ame: AssistantMessageEvent): ToolCall | undefined {\n\tif (!(\"partial\" in ame)) return undefined;\n\tconst content = ame.partial.content;\n\tconst idx = \"contentIndex\" in ame ? ame.contentIndex : 0;\n\tconst block = content[idx];\n\tif (block && \"type\" in block && block.type === \"toolCall\") return block;\n\treturn undefined;\n}\n\nfunction parseToolInput(tc: ToolCall): ToolArgs {\n\treturn tc.arguments;\n}\n\nconst toolArgsSchema = z\n\t.object({\n\t\tpath: z.string().trim().optional(),\n\t\toldText: z.string().trim().optional(),\n\t})\n\t.loose();\n\nexport function toToolArgs(raw: unknown): ToolArgs {\n\tconst result = toolArgsSchema.safeParse(raw);\n\treturn result.success ? result.data : {};\n}\n\n// ---------------------------------------------------------------------------\n// _meta builder helpers\n// ---------------------------------------------------------------------------\n\ntype PiAcpMeta = Record<string, unknown>;\n\n/** Build the `_meta.piAcp` tool name metadata. */\nfunction buildToolMeta(toolName: string, extra?: PiAcpMeta): PiAcpMeta {\n\tconst base: PiAcpMeta = { piAcp: { toolName } };\n\tif (extra !== undefined) {\n\t\treturn { ...base, ...extra };\n\t}\n\treturn base;\n}\n\n// ---------------------------------------------------------------------------\n// Terminal tool classification\n// ---------------------------------------------------------------------------\n\n/** Tools that produce terminal-style output. */\nfunction isTerminalTool(toolName: string): boolean {\n\treturn toolName === \"bash\" || toolName === \"tmux\";\n}\n\n// ---------------------------------------------------------------------------\n// Session manager\n// ---------------------------------------------------------------------------\n\nexport class SessionManager {\n\tprivate sessions = new Map<string, PiAcpSession>();\n\n\tdisposeAll(): void {\n\t\tfor (const id of this.sessions.keys()) this.close(id);\n\t}\n\n\tmaybeGet(sessionId: string): PiAcpSession | undefined {\n\t\treturn this.sessions.get(sessionId);\n\t}\n\n\tclose(sessionId: string): void {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) return;\n\t\ttry {\n\t\t\ts.dispose();\n\t\t} catch {\n\t\t\t// best-effort\n\t\t}\n\t\tthis.sessions.delete(sessionId);\n\t}\n\n\tcloseAllExcept(keepSessionId: string): void {\n\t\tfor (const id of this.sessions.keys()) {\n\t\t\tif (id !== keepSessionId) this.close(id);\n\t\t}\n\t}\n\n\tregister(session: PiAcpSession): void {\n\t\tthis.sessions.set(session.sessionId, session);\n\t}\n\n\tget(sessionId: string): PiAcpSession {\n\t\tconst s = this.sessions.get(sessionId);\n\t\tif (!s) throw RequestError.invalidParams(`Unknown sessionId: ${sessionId}`);\n\t\treturn s;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// ACP session wrapping a pi AgentSession\n// ---------------------------------------------------------------------------\n\nexport interface PiAcpSessionOpts {\n\tsessionId: string;\n\tcwd: string;\n\tmcpServers: McpServer[];\n\tpiSession: AgentSession;\n\tconn: AgentSideConnection;\n\t/** Whether the client supports terminal output metadata. */\n\tsupportsTerminalOutput?: boolean | undefined;\n}\n\nexport class PiAcpSession {\n\treadonly sessionId: string;\n\treadonly cwd: string;\n\treadonly mcpServers: McpServer[];\n\treadonly piSession: AgentSession;\n\treadonly supportsTerminalOutput: boolean;\n\n\tprivate readonly conn: AgentSideConnection;\n\n\tprivate cancelRequested = false;\n\tprivate promptRunning = false;\n\tprivate pendingTurn: { resolve: (r: StopReason) => void; reject: (e: unknown) => void } | null =\n\t\tnull;\n\t/** Queued prompts waiting for the active turn to complete. */\n\tprivate pendingMessages: Array<{\n\t\tmessage: string;\n\t\timages: unknown[];\n\t\tresolve: (r: StopReason) => void;\n\t\treject: (e: unknown) => void;\n\t}> = [];\n\n\tprivate currentToolCalls = new Map<string, \"pending\" | \"in_progress\">();\n\t/** Map of toolCallId -> toolName for streaming updates (Phase 5). */\n\tprivate toolCallNames = new Map<string, string>();\n\tprivate editSnapshots = new Map<string, { path: string; oldText: string }>();\n\tprivate lastAssistantStopReason: string | null = null;\n\tprivate lastEmit: Promise<void> = Promise.resolve();\n\tprivate unsubscribe: (() => void) | undefined;\n\n\tconstructor(opts: PiAcpSessionOpts) {\n\t\tthis.sessionId = opts.sessionId;\n\t\tthis.cwd = opts.cwd;\n\t\tthis.mcpServers = opts.mcpServers;\n\t\tthis.piSession = opts.piSession;\n\t\tthis.conn = opts.conn;\n\t\tthis.supportsTerminalOutput = opts.supportsTerminalOutput ?? false;\n\t\tthis.unsubscribe = this.piSession.subscribe((ev: AgentSessionEvent) => this.handlePiEvent(ev));\n\t}\n\n\tdispose(): void {\n\t\tthis.unsubscribe?.();\n\t\tthis.piSession.dispose();\n\t}\n\n\tasync prompt(message: string, images: unknown[] = []): Promise<StopReason> {\n\t\t// If a prompt is already running, queue this one and return a promise\n\t\t// that resolves when it eventually executes.\n\t\tif (this.promptRunning) {\n\t\t\treturn new Promise<StopReason>((resolve, reject) => {\n\t\t\t\tthis.pendingMessages.push({ message, images, resolve, reject });\n\t\t\t});\n\t\t}\n\n\t\treturn this.executePrompt(message, images);\n\t}\n\n\tasync cancel(): Promise<void> {\n\t\tthis.cancelRequested = true;\n\n\t\t// Resolve all queued prompts as cancelled\n\t\tfor (const pending of this.pendingMessages) {\n\t\t\tpending.resolve(\"cancelled\");\n\t\t}\n\t\tthis.pendingMessages = [];\n\n\t\tawait this.piSession.abort();\n\t}\n\n\tprivate executePrompt(message: string, images: unknown[]): Promise<StopReason> {\n\t\tthis.promptRunning = true;\n\n\t\tconst turnPromise = new Promise<StopReason>((resolve, reject) => {\n\t\t\tthis.cancelRequested = false;\n\t\t\tthis.pendingTurn = { resolve, reject };\n\t\t});\n\n\t\tconst imageContents = Array.isArray(images)\n\t\t\t? images.filter(\n\t\t\t\t\t(img): img is { type: \"image\"; data: string; mimeType: string } =>\n\t\t\t\t\t\ttypeof img === \"object\" && img !== null && \"type\" in img && img.type === \"image\",\n\t\t\t\t)\n\t\t\t: [];\n\n\t\tthis.piSession.prompt(message, { images: imageContents }).catch(() => {\n\t\t\tvoid this.flushEmits().finally(() => {\n\t\t\t\tconst reason: StopReason = this.cancelRequested ? \"cancelled\" : \"error\";\n\t\t\t\tthis.pendingTurn?.resolve(reason);\n\t\t\t\tthis.pendingTurn = null;\n\t\t\t});\n\t\t});\n\n\t\treturn turnPromise;\n\t}\n\n\t/**\n\t * Dequeue and execute the next pending prompt, if any.\n\t * Called after a turn completes.\n\t */\n\tprivate dequeueNextPrompt(): void {\n\t\tconst next = this.pendingMessages.shift();\n\t\tif (next === undefined) {\n\t\t\tthis.promptRunning = false;\n\t\t\treturn;\n\t\t}\n\n\t\tthis.executePrompt(next.message, next.images).then(next.resolve, next.reject);\n\t}\n\n\twasCancelRequested(): boolean {\n\t\treturn this.cancelRequested;\n\t}\n\n\t// -----------------------------------------------------------------------\n\t// Internal\n\t// -----------------------------------------------------------------------\n\n\tprivate emit(update: SessionUpdate): void {\n\t\tthis.lastEmit = this.lastEmit\n\t\t\t.then(() => this.conn.sessionUpdate({ sessionId: this.sessionId, update }))\n\t\t\t.catch(() => {});\n\t}\n\n\tprivate async flushEmits(): Promise<void> {\n\t\tawait this.lastEmit;\n\t}\n\n\tprivate handlePiEvent(ev: AgentSessionEvent): void {\n\t\tif (!isAgentEvent(ev)) return;\n\n\t\tswitch (ev.type) {\n\t\t\tcase \"message_update\":\n\t\t\t\tthis.handleMessageUpdate(ev.assistantMessageEvent);\n\t\t\t\tbreak;\n\t\t\tcase \"message_end\":\n\t\t\t\tthis.handleMessageEnd(ev.message);\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_start\":\n\t\t\t\tthis.handleToolStart(ev.toolCallId, ev.toolName, toToolArgs(ev.args));\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_update\":\n\t\t\t\tthis.handleToolUpdate(ev.toolCallId, ev.toolName, ev.partialResult);\n\t\t\t\tbreak;\n\t\t\tcase \"tool_execution_end\":\n\t\t\t\tthis.handleToolEnd(ev.toolCallId, ev.toolName, ev.result, ev.isError);\n\t\t\t\tbreak;\n\t\t\tcase \"agent_end\":\n\t\t\t\tthis.handleAgentEnd();\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tunreachable(ev, \"handlePiEvent\");\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprivate handleMessageUpdate(ame: AssistantMessageEvent): void {\n\t\tif (ame.type === \"text_delta\") {\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\tcontent: { type: \"text\", text: ame.delta } satisfies ContentBlock,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (ame.type === \"thinking_delta\") {\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"agent_thought_chunk\",\n\t\t\t\tcontent: { type: \"text\", text: ame.delta } satisfies ContentBlock,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tif (\n\t\t\tame.type === \"toolcall_start\" ||\n\t\t\tame.type === \"toolcall_delta\" ||\n\t\t\tame.type === \"toolcall_end\"\n\t\t) {\n\t\t\tconst toolCall = ame.type === \"toolcall_end\" ? ame.toolCall : extractToolCallFromPartial(ame);\n\t\t\tif (!toolCall) return;\n\n\t\t\tconst rawInput = parseToolInput(toolCall);\n\t\t\tconst locations = resolveToolPath(rawInput, this.cwd);\n\t\t\tconst existingStatus = this.currentToolCalls.get(toolCall.id);\n\t\t\tconst status = existingStatus ?? \"pending\";\n\n\t\t\tif (!existingStatus) {\n\t\t\t\tthis.currentToolCalls.set(toolCall.id, \"pending\");\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\ttitle: buildToolTitle(toolCall.name, rawInput),\n\t\t\t\t\tkind: toToolKind(toolCall.name),\n\t\t\t\t\tstatus,\n\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\trawInput,\n\t\t\t\t\t_meta: buildToolMeta(toolCall.name),\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\ttoolCallId: toolCall.id,\n\t\t\t\t\tstatus,\n\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\trawInput,\n\t\t\t\t\t_meta: buildToolMeta(toolCall.name),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate handleMessageEnd(msg: AgentMessage): void {\n\t\tif (\"role\" in msg && msg.role === \"assistant\") {\n\t\t\tthis.lastAssistantStopReason = msg.stopReason;\n\t\t}\n\t}\n\n\tprivate handleToolStart(toolCallId: string, toolName: string, args: ToolArgs): void {\n\t\t// Track toolName for streaming updates (Phase 5)\n\t\tthis.toolCallNames.set(toolCallId, toolName);\n\n\t\tlet line: number | undefined;\n\n\t\tif ((toolName === \"edit\" || toolName === \"write\") && args.path !== undefined) {\n\t\t\ttry {\n\t\t\t\tconst abs = isAbsolute(args.path) ? args.path : resolvePath(this.cwd, args.path);\n\t\t\t\tlet oldText = \"\";\n\t\t\t\ttry {\n\t\t\t\t\toldText = readFileSync(abs, \"utf8\");\n\t\t\t\t} catch {\n\t\t\t\t\t// File may not exist yet for write -- treat as empty.\n\t\t\t\t}\n\t\t\t\tthis.editSnapshots.set(toolCallId, { path: abs, oldText });\n\t\t\t\tif (toolName === \"edit\") {\n\t\t\t\t\tline = findUniqueLineNumber(oldText, args.oldText ?? \"\");\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// snapshot failure is non-fatal\n\t\t\t}\n\t\t}\n\n\t\tconst locations = resolveToolPath(args, this.cwd, line);\n\n\t\t// Build terminal metadata for bash/tmux when client supports it\n\t\tconst terminalMeta =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? { terminal_info: { terminal_id: toolCallId, cwd: this.cwd } }\n\t\t\t\t: undefined;\n\t\tconst meta = buildToolMeta(toolName, terminalMeta);\n\n\t\t// Build content for terminal-aware clients\n\t\tconst terminalContent: ToolCallContent[] | undefined =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? [{ type: \"terminal\" as const, terminalId: toolCallId }]\n\t\t\t\t: undefined;\n\n\t\tif (!this.currentToolCalls.has(toolCallId)) {\n\t\t\tthis.currentToolCalls.set(toolCallId, \"in_progress\");\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\ttoolCallId,\n\t\t\t\ttitle: buildToolTitle(toolName, args),\n\t\t\t\tkind: toToolKind(toolName),\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t...(terminalContent !== undefined ? { content: terminalContent } : {}),\n\t\t\t\trawInput: args,\n\t\t\t\t_meta: meta,\n\t\t\t});\n\t\t} else {\n\t\t\tthis.currentToolCalls.set(toolCallId, \"in_progress\");\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\ttitle: buildToolTitle(toolName, args),\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t...(terminalContent !== undefined ? { content: terminalContent } : {}),\n\t\t\t\trawInput: args,\n\t\t\t\t_meta: meta,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleToolUpdate(toolCallId: string, toolName: string, partialResult: unknown): void {\n\t\t// Look up tool name from our map (Phase 5), fall back to event's toolName\n\t\tconst name = this.toolCallNames.get(toolCallId) ?? toolName;\n\n\t\tif (this.supportsTerminalOutput && isTerminalTool(name)) {\n\t\t\t// Terminal-aware path: emit only _meta.terminal_output, no content\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t_meta: buildToolMeta(name, {\n\t\t\t\t\tterminal_output: { terminal_id: toolCallId, data: text },\n\t\t\t\t}),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t} else if (isTerminalTool(name)) {\n\t\t\t// Non-terminal fallback: wrap in console code fence\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tconst wrapped = wrapStreamingBashOutput(text);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\tcontent: wrapped\n\t\t\t\t\t? ([\n\t\t\t\t\t\t\t{ type: \"content\", content: { type: \"text\", text: wrapped } },\n\t\t\t\t\t\t] satisfies ToolCallContent[])\n\t\t\t\t\t: null,\n\t\t\t\t_meta: buildToolMeta(name),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t} else {\n\t\t\t// Other tools: plain text content\n\t\t\tconst text = extractStreamingText(partialResult);\n\t\t\tthis.emit({\n\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\ttoolCallId,\n\t\t\t\tstatus: \"in_progress\",\n\t\t\t\tcontent: text\n\t\t\t\t\t? ([{ type: \"content\", content: { type: \"text\", text } }] satisfies ToolCallContent[])\n\t\t\t\t\t: null,\n\t\t\t\t_meta: buildToolMeta(name),\n\t\t\t\trawOutput: partialResult,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate handleToolEnd(\n\t\ttoolCallId: string,\n\t\ttoolName: string,\n\t\tresult: unknown,\n\t\tisError: boolean,\n\t): void {\n\t\tconst snapshot = this.editSnapshots.get(toolCallId);\n\t\tlet content: ToolCallContent[] | null = null;\n\n\t\t// Diff path for edit/write\n\t\tif (!isError && snapshot) {\n\t\t\ttry {\n\t\t\t\tconst newText = readFileSync(snapshot.path, \"utf8\");\n\t\t\t\tif (newText !== snapshot.oldText) {\n\t\t\t\t\tconst formatted = formatToolContent(toolName, result, isError);\n\t\t\t\t\tcontent = [\n\t\t\t\t\t\t{ type: \"diff\", path: snapshot.path, oldText: snapshot.oldText, newText },\n\t\t\t\t\t\t...formatted,\n\t\t\t\t\t];\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// fall back to formatted content\n\t\t\t}\n\t\t}\n\n\t\t// If no diff content, use formatted tool content\n\t\tif (content === null) {\n\t\t\tconst formatted = formatToolContent(toolName, result, isError);\n\t\t\tcontent = formatted.length > 0 ? formatted : null;\n\t\t}\n\n\t\t// Last resort: if formatToolContent returns empty and no diff, generate plain text\n\t\tif (content === null && !isError && toolName !== \"edit\" && toolName !== \"write\") {\n\t\t\tconst text = extractStreamingText(result);\n\t\t\tif (text) {\n\t\t\t\tcontent = [{ type: \"content\", content: { type: \"text\", text } }];\n\t\t\t}\n\t\t}\n\n\t\t// For terminal tools: emit a separate terminal_output update before terminal_exit.\n\t\t// This ensures Zed renders output before the exit status (following claude-agent-acp).\n\t\tif (this.supportsTerminalOutput && isTerminalTool(toolName)) {\n\t\t\tconst outputText = extractStreamingText(result);\n\t\t\tif (outputText !== \"\") {\n\t\t\t\tthis.emit({\n\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\ttoolCallId,\n\t\t\t\t\tstatus: \"in_progress\",\n\t\t\t\t\t_meta: buildToolMeta(toolName, {\n\t\t\t\t\t\tterminal_output: { terminal_id: toolCallId, data: outputText },\n\t\t\t\t\t}),\n\t\t\t\t\trawOutput: result,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// Build terminal exit metadata for bash/tmux\n\t\tconst terminalExitMeta =\n\t\t\tthis.supportsTerminalOutput && isTerminalTool(toolName)\n\t\t\t\t? {\n\t\t\t\t\t\tterminal_exit: {\n\t\t\t\t\t\t\tterminal_id: toolCallId,\n\t\t\t\t\t\t\texit_code: extractExitCode(result),\n\t\t\t\t\t\t\tsignal: null,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\tconst meta = buildToolMeta(toolName, terminalExitMeta);\n\n\t\tthis.emit({\n\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\ttoolCallId,\n\t\t\tstatus: isError ? \"failed\" : \"completed\",\n\t\t\tcontent,\n\t\t\t_meta: meta,\n\t\t\trawOutput: result,\n\t\t});\n\n\t\tthis.currentToolCalls.delete(toolCallId);\n\t\tthis.editSnapshots.delete(toolCallId);\n\t\tthis.toolCallNames.delete(toolCallId);\n\t}\n\n\tprivate handleAgentEnd(): void {\n\t\tthis.emitUsageUpdate();\n\t\tvoid this.flushEmits().finally(() => {\n\t\t\tconst reason: StopReason = this.cancelRequested\n\t\t\t\t? \"cancelled\"\n\t\t\t\t: mapPiStopReason(this.lastAssistantStopReason);\n\t\t\tthis.lastAssistantStopReason = null;\n\t\t\tthis.pendingTurn?.resolve(reason);\n\t\t\tthis.pendingTurn = null;\n\t\t\tthis.dequeueNextPrompt();\n\t\t});\n\t}\n\n\t/**\n\t * Emit a usage_update notification with current context and cost data.\n\t */\n\tprivate emitUsageUpdate(): void {\n\t\tconst contextUsage = this.piSession.getContextUsage?.();\n\t\tconst stats = this.piSession.getSessionStats();\n\n\t\tconst used = contextUsage?.tokens ?? 0;\n\t\tconst size = contextUsage?.contextWindow ?? 0;\n\n\t\tthis.emit({\n\t\t\tsessionUpdate: \"usage_update\",\n\t\t\tused,\n\t\t\tsize,\n\t\t\tcost: stats.cost > 0 ? { amount: stats.cost, currency: \"USD\" } : null,\n\t\t});\n\t}\n\n\t/**\n\t * Build ACP Usage data from pi session stats for prompt response.\n\t */\n\tgetUsage(): {\n\t\tinputTokens: number;\n\t\toutputTokens: number;\n\t\tcachedReadTokens: number;\n\t\tcachedWriteTokens: number;\n\t} {\n\t\tconst stats = this.piSession.getSessionStats();\n\t\treturn {\n\t\t\tinputTokens: stats.tokens.input,\n\t\t\toutputTokens: stats.tokens.output,\n\t\t\tcachedReadTokens: stats.tokens.cacheRead,\n\t\t\tcachedWriteTokens: stats.tokens.cacheWrite,\n\t\t};\n\t}\n\n\t/**\n\t * Get cumulative session cost.\n\t */\n\tgetCost(): number {\n\t\treturn this.piSession.getSessionStats().cost;\n\t}\n}\n\n// ---------------------------------------------------------------------------\n// Streaming text extraction (lightweight, no formatting)\n// ---------------------------------------------------------------------------\n\nfunction isTextBlock(v: unknown): v is { type: \"text\"; text: string } {\n\treturn (\n\t\ttypeof v === \"object\" &&\n\t\tv !== null &&\n\t\t\"type\" in v &&\n\t\tv.type === \"text\" &&\n\t\t\"text\" in v &&\n\t\ttypeof v.text === \"string\"\n\t);\n}\n\nfunction extractStreamingText(result: unknown): string {\n\tif (result === null || result === undefined) return \"\";\n\tif (typeof result === \"string\") return result;\n\tif (typeof result !== \"object\") return String(result);\n\n\t// Content blocks\n\tif (\"content\" in result && Array.isArray(result.content)) {\n\t\tconst texts: string[] = [];\n\t\tfor (const raw of result.content) {\n\t\t\tif (isTextBlock(raw)) {\n\t\t\t\ttexts.push(raw.text);\n\t\t\t}\n\t\t}\n\t\tif (texts.length > 0) return texts.join(\"\");\n\t}\n\n\t// Details fields\n\tif (\"details\" in result) {\n\t\tconst details = result.details;\n\t\tif (typeof details === \"object\" && details !== null) {\n\t\t\tif (\"stdout\" in details && typeof details.stdout === \"string\" && details.stdout.trim() !== \"\")\n\t\t\t\treturn details.stdout;\n\t\t\tif (\"output\" in details && typeof details.output === \"string\" && details.output.trim() !== \"\")\n\t\t\t\treturn details.output;\n\t\t}\n\t}\n\n\t// Top-level output/stdout\n\tif (\"output\" in result && typeof result.output === \"string\" && result.output.trim() !== \"\")\n\t\treturn result.output;\n\tif (\"stdout\" in result && typeof result.stdout === \"string\" && result.stdout.trim() !== \"\")\n\t\treturn result.stdout;\n\n\treturn \"\";\n}\n\nfunction extractExitCode(result: unknown): number | null {\n\tif (result === null || result === undefined || typeof result !== \"object\") return null;\n\n\tif (\"details\" in result) {\n\t\tconst details = result.details;\n\t\tif (typeof details === \"object\" && details !== null) {\n\t\t\tif (\"exitCode\" in details && typeof details.exitCode === \"number\") return details.exitCode;\n\t\t\tif (\"code\" in details && typeof details.code === \"number\") return details.code;\n\t\t}\n\t}\n\n\tif (\"exitCode\" in result && typeof result.exitCode === \"number\") return result.exitCode;\n\tif (\"code\" in result && typeof result.code === \"number\") return result.code;\n\n\treturn null;\n}\n\n/**\n * Type guard to narrow AgentSessionEvent to the AgentEvent subset\n * (the variants we handle). Session-specific events like auto_compaction\n * are ignored.\n */\nfunction isAgentEvent(\n\tev: AgentSessionEvent,\n): ev is Extract<\n\tAgentEvent,\n\t| { type: \"message_update\" }\n\t| { type: \"message_end\" }\n\t| { type: \"tool_execution_start\" }\n\t| { type: \"tool_execution_update\" }\n\t| { type: \"tool_execution_end\" }\n\t| { type: \"agent_end\" }\n> {\n\treturn (\n\t\tev.type === \"message_update\" ||\n\t\tev.type === \"message_end\" ||\n\t\tev.type === \"tool_execution_start\" ||\n\t\tev.type === \"tool_execution_update\" ||\n\t\tev.type === \"tool_execution_end\" ||\n\t\tev.type === \"agent_end\"\n\t);\n}\n","/**\n * Extract plain text from pi message content.\n *\n * Pi messages store content as either a string or an array of typed blocks.\n * These helpers extract the text portions for ACP session replay.\n */\n\ninterface TextBlock {\n\ttype: \"text\";\n\ttext: string;\n}\n\nfunction isTextBlock(block: unknown): block is TextBlock {\n\tif (typeof block !== \"object\" || block === null) return false;\n\treturn (\n\t\t\"type\" in block && block.type === \"text\" && \"text\" in block && typeof block.text === \"string\"\n\t);\n}\n\nexport function extractUserMessageText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter(isTextBlock)\n\t\t.map((b) => b.text)\n\t\t.join(\"\");\n}\n\nexport function extractAssistantText(content: unknown): string {\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.filter(isTextBlock)\n\t\t.map((b) => b.text)\n\t\t.join(\"\");\n}\n","/**\n * Convert ACP prompt ContentBlocks to a pi-compatible message string and image array.\n */\n\nimport type { ContentBlock } from \"@agentclientprotocol/sdk\";\n\nexport interface PiImage {\n\ttype: \"image\";\n\tmimeType: string;\n\tdata: string;\n}\n\nexport function acpPromptToPiMessage(blocks: ContentBlock[]): {\n\tmessage: string;\n\timages: PiImage[];\n} {\n\tlet message = \"\";\n\tconst images: PiImage[] = [];\n\n\tfor (const block of blocks) {\n\t\tswitch (block.type) {\n\t\t\tcase \"text\":\n\t\t\t\tmessage += block.text;\n\t\t\t\tbreak;\n\n\t\t\tcase \"resource_link\":\n\t\t\t\tmessage += `\\n[Context] ${block.uri}`;\n\t\t\t\tbreak;\n\n\t\t\tcase \"image\":\n\t\t\t\timages.push({\n\t\t\t\t\ttype: \"image\",\n\t\t\t\t\tmimeType: block.mimeType,\n\t\t\t\t\tdata: block.data,\n\t\t\t\t});\n\t\t\t\tbreak;\n\n\t\t\tcase \"resource\": {\n\t\t\t\tconst resource = block.resource;\n\t\t\t\tconst uri = resource.uri;\n\t\t\t\tconst mime = resource.mimeType ?? null;\n\n\t\t\t\tif (\"text\" in resource) {\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri} (${mime ?? \"text/plain\"})\\n${resource.text}`;\n\t\t\t\t} else if (\"blob\" in resource) {\n\t\t\t\t\tconst bytes = Buffer.byteLength(resource.blob, \"base64\");\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri} (${mime ?? \"application/octet-stream\"}, ${bytes} bytes)`;\n\t\t\t\t} else {\n\t\t\t\t\tmessage += `\\n[Embedded Context] ${uri}`;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tcase \"audio\": {\n\t\t\t\tconst bytes = Buffer.byteLength(block.data, \"base64\");\n\t\t\t\tmessage += `\\n[Audio] (${block.mimeType}, ${bytes} bytes) not supported`;\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn { message, images };\n}\n","","import { spawnSync } from \"node:child_process\";\nimport { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, isAbsolute, join } from \"node:path\";\nimport {\n\ttype Agent as ACPAgent,\n\ttype AgentSideConnection,\n\ttype AuthenticateRequest,\n\ttype AvailableCommand,\n\ttype CancelNotification,\n\ttype CloseSessionRequest,\n\ttype CloseSessionResponse,\n\ttype ForkSessionRequest,\n\ttype ForkSessionResponse,\n\ttype InitializeRequest,\n\ttype InitializeResponse,\n\ttype ListSessionsRequest,\n\ttype ListSessionsResponse,\n\ttype LoadSessionRequest,\n\ttype LoadSessionResponse,\n\ttype ModelInfo,\n\ttype NewSessionRequest,\n\ttype PromptRequest,\n\ttype PromptResponse,\n\tRequestError,\n\ttype ResumeSessionRequest,\n\ttype ResumeSessionResponse,\n\ttype SessionConfigOption,\n\ttype SessionInfo,\n\ttype SessionModelState,\n\ttype SessionModeState,\n\ttype SetSessionConfigOptionRequest,\n\ttype SetSessionConfigOptionResponse,\n\ttype SetSessionModelRequest,\n\ttype SetSessionModelResponse,\n\ttype SetSessionModeRequest,\n\ttype SetSessionModeResponse,\n\ttype StopReason,\n} from \"@agentclientprotocol/sdk\";\nimport type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport type { AssistantMessage, ToolResultMessage, UserMessage } from \"@earendil-works/pi-ai\";\nimport {\n\ttype AgentSession,\n\ttype CreateAgentSessionResult,\n\tcreateAgentSession,\n\tSessionManager as PiSessionManager,\n} from \"@earendil-works/pi-coding-agent\";\nimport { buildAuthMethods } from \"@pi-acp/acp/auth\";\nimport { detectAuthError } from \"@pi-acp/acp/auth-required\";\nimport {\n\ttype ClientCapabilityFlags,\n\tparseClientCapabilities,\n} from \"@pi-acp/acp/client-capabilities\";\nimport { resolveModelPreference } from \"@pi-acp/acp/model-alias\";\nimport { skillCommandsEnabled } from \"@pi-acp/acp/pi-settings\";\nimport {\n\tbuildToolTitle,\n\tPiAcpSession,\n\tresolveToolPath,\n\tSessionManager,\n\ttype ToolArgs,\n\ttoToolArgs,\n\ttoToolKind,\n} from \"@pi-acp/acp/session\";\nimport { extractUserMessageText } from \"@pi-acp/acp/translate/pi-messages\";\nimport { acpPromptToPiMessage } from \"@pi-acp/acp/translate/prompt\";\nimport { formatToolContent } from \"@pi-acp/acp/translate/tool-content\";\n\nimport pkgJson from \"../../package.json\" with { type: \"json\" };\n\ntype ThinkingLevel = \"off\" | \"minimal\" | \"low\" | \"medium\" | \"high\" | \"xhigh\";\n\n/** Builtin ACP slash commands handled directly by the adapter. */\nconst BUILTIN_COMMANDS: readonly AvailableCommand[] = [\n\t{\n\t\tname: \"compact\",\n\t\tdescription: \"Manually compact the session context\",\n\t\tinput: { hint: \"optional custom instructions\" },\n\t},\n\t{\n\t\tname: \"autocompact\",\n\t\tdescription: \"Toggle automatic context compaction\",\n\t\tinput: { hint: \"on|off|toggle\" },\n\t},\n\t{ name: \"export\", description: \"Export session to an HTML file in the session cwd\" },\n\t{ name: \"session\", description: \"Show session stats (messages, tokens, cost, session file)\" },\n\t{ name: \"name\", description: \"Set session display name\", input: { hint: \"<name>\" } },\n\t{\n\t\tname: \"steering\",\n\t\tdescription: \"Get/set pi steering message delivery mode\",\n\t\tinput: { hint: \"(no args to show) all | one-at-a-time\" },\n\t},\n\t{\n\t\tname: \"follow-up\",\n\t\tdescription: \"Get/set pi follow-up message delivery mode\",\n\t\tinput: { hint: \"(no args to show) all | one-at-a-time\" },\n\t},\n\t{ name: \"changelog\", description: \"Show pi changelog\" },\n] as const;\n\n/**\n * Deduplicate commands by name. First occurrence wins.\n */\nfunction deduplicateCommands(commands: AvailableCommand[]): AvailableCommand[] {\n\tconst seen = new Set<string>();\n\tconst out: AvailableCommand[] = [];\n\tfor (const c of commands) {\n\t\tif (seen.has(c.name)) continue;\n\t\tseen.add(c.name);\n\t\tout.push(c);\n\t}\n\treturn out;\n}\n\nfunction parseArgs(input: string): string[] {\n\tconst args: string[] = [];\n\tlet current = \"\";\n\tlet quote: string | null = null;\n\n\tfor (const ch of input) {\n\t\tif (quote !== null) {\n\t\t\tif (ch === quote) quote = null;\n\t\t\telse current += ch;\n\t\t} else if (ch === '\"' || ch === \"'\") {\n\t\t\tquote = ch;\n\t\t} else if (ch === \" \" || ch === \"\\t\") {\n\t\t\tif (current !== \"\") {\n\t\t\t\targs.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent += ch;\n\t\t}\n\t}\n\n\tif (current !== \"\") args.push(current);\n\treturn args;\n}\n\nconst SESSION_TITLE_MAX = 100;\n\nfunction truncateSessionTitle(text: string): string | null {\n\tconst trimmed = text.trim();\n\tif (trimmed === \"\") return null;\n\tconst oneLine = trimmed.replace(/\\n/g, \" \");\n\tif (oneLine.length <= SESSION_TITLE_MAX) return oneLine;\n\treturn `${oneLine.slice(0, SESSION_TITLE_MAX - 1)}…`;\n}\n\nexport class PiAcpAgent implements ACPAgent {\n\tprivate readonly conn: AgentSideConnection;\n\tprivate readonly sessions = new SessionManager();\n\t/** Cache of sessionId → file path, populated by listSessions and newSession. */\n\tprivate readonly sessionPaths = new Map<string, string>();\n\t/** Parsed client capability flags from initialize(). */\n\tprivate clientCapabilities: ClientCapabilityFlags = {\n\t\tterminalOutput: false,\n\t\tterminalAuth: false,\n\t\tgatewayAuth: false,\n\t};\n\n\tdispose(): void {\n\t\tthis.sessions.disposeAll();\n\t\tvoid this.daemonContext;\n\t}\n\n\tprivate readonly daemonContext: import(\"@pi-acp/daemon/context\").DaemonContext | undefined;\n\n\tconstructor(\n\t\tconn: AgentSideConnection,\n\t\tdaemonContext?: import(\"@pi-acp/daemon/context\").DaemonContext,\n\t) {\n\t\tthis.conn = conn;\n\t\tthis.daemonContext = daemonContext;\n\t}\n\n\tasync initialize(params: InitializeRequest): Promise<InitializeResponse> {\n\t\tconst supportedVersion = 1;\n\t\tconst requested = params.protocolVersion;\n\n\t\tthis.clientCapabilities = parseClientCapabilities(params.clientCapabilities);\n\n\t\treturn {\n\t\t\tprotocolVersion: requested === supportedVersion ? requested : supportedVersion,\n\t\t\tagentInfo: {\n\t\t\t\tname: pkgJson.name,\n\t\t\t\ttitle: \"pi ACP adapter\",\n\t\t\t\tversion: pkgJson.version,\n\t\t\t},\n\t\t\tauthMethods: buildAuthMethods({\n\t\t\t\tsupportsTerminalAuthMeta: this.clientCapabilities.terminalAuth,\n\t\t\t}),\n\t\t\tagentCapabilities: {\n\t\t\t\tloadSession: true,\n\t\t\t\tmcpCapabilities: { http: false, sse: false },\n\t\t\t\tpromptCapabilities: {\n\t\t\t\t\timage: true,\n\t\t\t\t\taudio: false,\n\t\t\t\t\tembeddedContext: true,\n\t\t\t\t},\n\t\t\t\tsessionCapabilities: {\n\t\t\t\t\tlist: {},\n\t\t\t\t\tclose: {},\n\t\t\t\t\tresume: {},\n\t\t\t\t\tfork: {},\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tasync newSession(params: NewSessionRequest) {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tresult = await createAgentSession({ cwd: params.cwd });\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to create pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst availableModels = piSession.modelRegistry.getAvailable();\n\t\tif (availableModels.length === 0) {\n\t\t\tpiSession.dispose();\n\t\t\tthrow RequestError.authRequired(\n\t\t\t\t{ authMethods: buildAuthMethods() },\n\t\t\t\t\"Configure an API key or log in with an OAuth provider.\",\n\t\t\t);\n\t\t}\n\n\t\tconst sessionId = piSession.sessionManager.getSessionId();\n\t\tconst sessionFile = piSession.sessionManager.getSessionFile();\n\t\tif (sessionFile !== undefined) {\n\t\t\tthis.sessionPaths.set(sessionId, sessionFile);\n\t\t}\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers,\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\treturn {\n\t\t\tsessionId: session.sessionId,\n\t\t\tconfigOptions,\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync authenticate(_params: AuthenticateRequest) {\n\t\treturn {};\n\t}\n\n\tasync prompt(params: PromptRequest): Promise<PromptResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst { message, images } = acpPromptToPiMessage(params.prompt);\n\n\t\tif (images.length === 0 && message.trimStart().startsWith(\"/\")) {\n\t\t\tconst trimmed = message.trim();\n\t\t\tconst space = trimmed.indexOf(\" \");\n\t\t\tconst cmd = space === -1 ? trimmed.slice(1) : trimmed.slice(1, space);\n\t\t\tconst argsString = space === -1 ? \"\" : trimmed.slice(space + 1);\n\t\t\tconst args = parseArgs(argsString);\n\n\t\t\tconst handled = await this.handleBuiltinCommand(session, cmd, args);\n\t\t\tif (handled) return handled;\n\t\t}\n\n\t\tconst result = await session.prompt(message, images);\n\n\t\tconst stopReason: StopReason = result === \"error\" ? \"end_turn\" : result;\n\t\tconst usage = session.getUsage();\n\t\tconst cost = session.getCost();\n\n\t\treturn {\n\t\t\tstopReason,\n\t\t\tusage: {\n\t\t\t\tinputTokens: usage.inputTokens,\n\t\t\t\toutputTokens: usage.outputTokens,\n\t\t\t\tcachedReadTokens: usage.cachedReadTokens,\n\t\t\t\tcachedWriteTokens: usage.cachedWriteTokens,\n\t\t\t\ttotalTokens: usage.inputTokens + usage.outputTokens,\n\t\t\t},\n\t\t\t_meta: cost > 0 ? { cost: { amount: cost, currency: \"USD\" } } : {},\n\t\t};\n\t}\n\n\tasync cancel(params: CancelNotification): Promise<void> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tawait session.cancel();\n\t}\n\n\t/**\n\t * Resolve a session ID to a file path.\n\t * Checks the local cache first (populated by listSessions/newSession),\n\t * falls back to a full listAll() scan on cache miss.\n\t */\n\tprivate async resolveSessionFile(sessionId: string): Promise<string | null> {\n\t\tconst cached = this.sessionPaths.get(sessionId);\n\t\tif (cached !== undefined) return cached;\n\n\t\tconst all = await PiSessionManager.listAll();\n\t\tfor (const s of all) {\n\t\t\tthis.sessionPaths.set(s.id, s.path);\n\t\t}\n\n\t\treturn this.sessionPaths.get(sessionId) ?? null;\n\t}\n\n\t/**\n\t * Replay persisted session messages as ACP session updates.\n\t *\n\t * Iterates through the message history, emitting structured updates for each\n\t * content block type: text, thinking, tool calls, and tool results. A map of\n\t * tool call IDs to their invocation data (from assistant messages) is built\n\t * to enrich subsequent tool result updates with rawInput and locations.\n\t */\n\tprivate async replaySessionHistory(\n\t\tsession: PiAcpSession,\n\t\tmessages: AgentMessage[],\n\t): Promise<void> {\n\t\tconst toolCallMap = new Map<string, { name: string; args: ToolArgs }>();\n\n\t\tfor (const m of messages) {\n\t\t\tif (!(\"role\" in m)) continue;\n\n\t\t\tif (m.role === \"user\") {\n\t\t\t\tconst text = extractUserMessageText((m satisfies UserMessage).content);\n\t\t\t\tif (text) {\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: { sessionUpdate: \"user_message_chunk\", content: { type: \"text\", text } },\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (m.role === \"assistant\") {\n\t\t\t\tconst am = m satisfies AssistantMessage;\n\t\t\t\tfor (const block of am.content) {\n\t\t\t\t\tif (block.type === \"text\" && block.text) {\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\t\t\tcontent: { type: \"text\", text: block.text },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (block.type === \"thinking\" && block.thinking) {\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"agent_thought_chunk\",\n\t\t\t\t\t\t\t\tcontent: { type: \"text\", text: block.thinking },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\t\tconst args = toToolArgs(block.arguments);\n\t\t\t\t\t\ttoolCallMap.set(block.id, { name: block.name, args });\n\t\t\t\t\t\tconst locations = resolveToolPath(args, session.cwd);\n\n\t\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\t\t\ttoolCallId: block.id,\n\t\t\t\t\t\t\t\ttitle: buildToolTitle(block.name, args),\n\t\t\t\t\t\t\t\tkind: toToolKind(block.name),\n\t\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\t\trawInput: args,\n\t\t\t\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\t\t\t\t_meta: { piAcp: { toolName: block.name } },\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (m.role === \"toolResult\") {\n\t\t\t\tconst tr = m satisfies ToolResultMessage;\n\t\t\t\tconst toolName = tr.toolName;\n\t\t\t\tconst toolCallId = tr.toolCallId;\n\t\t\t\tconst isError = tr.isError;\n\n\t\t\t\t// Enrich from the preceding assistant tool call if available.\n\t\t\t\tconst invocation = toolCallMap.get(toolCallId);\n\t\t\t\tconst args = invocation?.args;\n\t\t\t\tconst locations = args !== undefined ? resolveToolPath(args, session.cwd) : undefined;\n\n\t\t\t\t// If no tool_call was emitted from the assistant message (e.g. older\n\t\t\t\t// session format without structured assistant content), emit one now.\n\t\t\t\tif (invocation === undefined) {\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"tool_call\",\n\t\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\t\ttitle: buildToolTitle(toolName, {}),\n\t\t\t\t\t\t\tkind: toToolKind(toolName),\n\t\t\t\t\t\t\tstatus: \"completed\",\n\t\t\t\t\t\t\trawInput: null,\n\t\t\t\t\t\t\trawOutput: m,\n\t\t\t\t\t\t\t_meta: { piAcp: { toolName } },\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t}\n\n\t\t\t\tconst content = formatToolContent(toolName, m, isError);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"tool_call_update\",\n\t\t\t\t\t\ttoolCallId,\n\t\t\t\t\t\tstatus: isError ? \"failed\" : \"completed\",\n\t\t\t\t\t\tcontent: content.length > 0 ? content : null,\n\t\t\t\t\t\trawOutput: m,\n\t\t\t\t\t\t...(locations ? { locations } : {}),\n\t\t\t\t\t\t_meta: { piAcp: { toolName } },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\tasync listSessions(params: ListSessionsRequest): Promise<ListSessionsResponse> {\n\t\tconst cwd = params.cwd;\n\n\t\tconst raw =\n\t\t\tcwd !== undefined && cwd !== null\n\t\t\t\t? await PiSessionManager.list(cwd)\n\t\t\t\t: await PiSessionManager.listAll();\n\n\t\tfor (const s of raw) {\n\t\t\tthis.sessionPaths.set(s.id, s.path);\n\t\t}\n\n\t\tconst sessions = raw.map((s) => ({\n\t\t\tid: s.id,\n\t\t\tcwd: s.cwd,\n\t\t\tname: s.name,\n\t\t\tfirstMessage: s.firstMessage,\n\t\t\tmodified: s.modified,\n\t\t\tmessageCount: s.messageCount,\n\t\t}));\n\n\t\tif (params.cursor !== undefined && params.cursor !== null) {\n\t\t\tconst parsed = Number.parseInt(params.cursor, 10);\n\t\t\tif (!Number.isFinite(parsed) || parsed < 0) {\n\t\t\t\tthrow RequestError.invalidParams(`Invalid cursor: ${params.cursor}`);\n\t\t\t}\n\t\t}\n\n\t\tconst start =\n\t\t\tparams.cursor !== undefined && params.cursor !== null\n\t\t\t\t? Number.parseInt(params.cursor, 10)\n\t\t\t\t: 0;\n\n\t\tconst PAGE_SIZE = 50;\n\t\tconst page = sessions.slice(start, start + PAGE_SIZE);\n\n\t\tconst acpSessions: SessionInfo[] = page.map((s) => ({\n\t\t\tsessionId: s.id,\n\t\t\tcwd: s.cwd,\n\t\t\ttitle:\n\t\t\t\t(s.name !== undefined && s.name !== \"\" ? s.name : null) ??\n\t\t\t\ttruncateSessionTitle(s.firstMessage) ??\n\t\t\t\tnull,\n\t\t\tupdatedAt: s.modified.toISOString(),\n\t\t}));\n\n\t\tconst nextCursor = start + PAGE_SIZE < sessions.length ? String(start + PAGE_SIZE) : null;\n\n\t\treturn { sessions: acpSessions, nextCursor, _meta: {} };\n\t}\n\n\tasync loadSession(params: LoadSessionRequest): Promise<LoadSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tthis.sessions.close(params.sessionId);\n\n\t\tconst sessionFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sessionFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.open(sessionFile);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to load pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: params.sessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers,\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\n\t\tawait this.replaySessionHistory(session, piSession.messages);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\treturn {\n\t\t\tconfigOptions,\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync closeSession(params: CloseSessionRequest): Promise<CloseSessionResponse> {\n\t\tconst session = this.sessions.maybeGet(params.sessionId);\n\t\tif (session === undefined) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\t\tthis.sessions.close(params.sessionId);\n\t\treturn {};\n\t}\n\n\tasync resumeSession(params: ResumeSessionRequest): Promise<ResumeSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\t// If the session is already live, reuse it.\n\t\tconst existing = this.sessions.maybeGet(params.sessionId);\n\t\tif (existing !== undefined) {\n\t\t\tconst modes = buildThinkingModes(existing.piSession);\n\t\t\tconst models = buildModelState(existing.piSession);\n\t\t\treturn {\n\t\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\t\tmodes,\n\t\t\t\tmodels,\n\t\t\t};\n\t\t}\n\n\t\t// Otherwise, load from disk (same path as loadSession but without replay).\n\t\tconst sessionFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sessionFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.open(sessionFile);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to resume pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: params.sessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\t\tthis.sessionPaths.set(params.sessionId, sessionFile);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\treturn {\n\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync unstable_forkSession(params: ForkSessionRequest): Promise<ForkSessionResponse> {\n\t\tif (!isAbsolute(params.cwd)) {\n\t\t\tthrow RequestError.invalidParams(`cwd must be an absolute path: ${params.cwd}`);\n\t\t}\n\n\t\tconst sourceFile = await this.resolveSessionFile(params.sessionId);\n\t\tif (sourceFile === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown sessionId: ${params.sessionId}`);\n\t\t}\n\n\t\tlet result: CreateAgentSessionResult;\n\t\ttry {\n\t\t\tconst sm = PiSessionManager.forkFrom(sourceFile, params.cwd);\n\t\t\tresult = await createAgentSession({\n\t\t\t\tcwd: params.cwd,\n\t\t\t\tsessionManager: sm,\n\t\t\t});\n\t\t} catch (e: unknown) {\n\t\t\tconst authErr = detectAuthError(e);\n\t\t\tif (authErr !== null) throw authErr;\n\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\tthrow RequestError.internalError({}, `Failed to fork pi session: ${msg}`);\n\t\t}\n\n\t\tconst piSession = result.session;\n\n\t\tconst newSessionId = piSession.sessionManager.getSessionId();\n\t\tconst newSessionFile = piSession.sessionManager.getSessionFile();\n\t\tif (newSessionFile !== undefined) {\n\t\t\tthis.sessionPaths.set(newSessionId, newSessionFile);\n\t\t}\n\n\t\tconst session = new PiAcpSession({\n\t\t\tsessionId: newSessionId,\n\t\t\tcwd: params.cwd,\n\t\t\tmcpServers: params.mcpServers ?? [],\n\t\t\tpiSession,\n\t\t\tconn: this.conn,\n\t\t\tsupportsTerminalOutput: this.clientCapabilities.terminalOutput,\n\t\t});\n\n\t\tthis.sessions.register(session);\n\n\t\tconst enableSkillCommands = skillCommandsEnabled(params.cwd);\n\t\tsetTimeout(() => {\n\t\t\tvoid (async () => {\n\t\t\t\ttry {\n\t\t\t\t\tconst commands = buildCommandList(piSession, enableSkillCommands);\n\t\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tsessionUpdate: \"available_commands_update\",\n\t\t\t\t\t\t\tavailableCommands: deduplicateCommands([...commands, ...BUILTIN_COMMANDS]),\n\t\t\t\t\t\t},\n\t\t\t\t\t});\n\t\t\t\t} catch {}\n\t\t\t})();\n\t\t}, 0);\n\n\t\tconst modes = buildThinkingModes(piSession);\n\t\tconst models = buildModelState(piSession);\n\t\treturn {\n\t\t\tsessionId: newSessionId,\n\t\t\tconfigOptions: buildConfigOptions(modes, models),\n\t\t\tmodes,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\tasync setSessionMode(params: SetSessionModeRequest): Promise<SetSessionModeResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst mode = String(params.modeId);\n\t\tif (!isThinkingLevel(mode)) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modeId: ${mode}`);\n\t\t}\n\n\t\tsession.piSession.setThinkingLevel(mode);\n\n\t\tvoid this.conn.sessionUpdate({\n\t\t\tsessionId: session.sessionId,\n\t\t\tupdate: { sessionUpdate: \"current_mode_update\", currentModeId: mode },\n\t\t});\n\n\t\tthis.emitConfigOptionUpdate(session);\n\n\t\treturn {};\n\t}\n\n\tasync unstable_setSessionModel(\n\t\tparams: SetSessionModelRequest,\n\t): Promise<SetSessionModelResponse | void> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst available = session.piSession.modelRegistry.getAvailable();\n\n\t\tconst resolved = resolveModelPreference(available, params.modelId);\n\t\tif (resolved === null) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modelId: ${params.modelId}`);\n\t\t}\n\n\t\tconst model = available.find((m) => m.provider === resolved.provider && m.id === resolved.id);\n\t\tif (!model) {\n\t\t\tthrow RequestError.invalidParams(`Unknown modelId: ${params.modelId}`);\n\t\t}\n\n\t\tawait session.piSession.setModel(model);\n\t\tthis.emitConfigOptionUpdate(session);\n\t}\n\n\tasync setSessionConfigOption(\n\t\tparams: SetSessionConfigOptionRequest,\n\t): Promise<SetSessionConfigOptionResponse> {\n\t\tconst session = this.sessions.get(params.sessionId);\n\t\tconst configId = String(params.configId);\n\t\tconst value = String(params.value);\n\n\t\tif (configId === \"model\") {\n\t\t\tconst available = session.piSession.modelRegistry.getAvailable();\n\t\t\tconst resolved = resolveModelPreference(available, value);\n\t\t\tif (resolved === null) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t}\n\n\t\t\tconst model = available.find((m) => m.provider === resolved.provider && m.id === resolved.id);\n\t\t\tif (!model) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown model: ${value}`);\n\t\t\t}\n\n\t\t\tawait session.piSession.setModel(model);\n\t\t} else if (configId === \"thought_level\") {\n\t\t\tif (!isThinkingLevel(value)) {\n\t\t\t\tthrow RequestError.invalidParams(`Unknown thinking level: ${value}`);\n\t\t\t}\n\t\t\tsession.piSession.setThinkingLevel(value);\n\t\t} else {\n\t\t\tthrow RequestError.invalidParams(`Unknown config option: ${configId}`);\n\t\t}\n\n\t\tconst modes = buildThinkingModes(session.piSession);\n\t\tconst models = buildModelState(session.piSession);\n\t\treturn { configOptions: buildConfigOptions(modes, models) };\n\t}\n\n\tprivate emitConfigOptionUpdate(session: PiAcpSession): void {\n\t\tconst modes = buildThinkingModes(session.piSession);\n\t\tconst models = buildModelState(session.piSession);\n\t\tconst configOptions = buildConfigOptions(modes, models);\n\n\t\tvoid this.conn.sessionUpdate({\n\t\t\tsessionId: session.sessionId,\n\t\t\tupdate: {\n\t\t\t\tsessionUpdate: \"config_option_update\",\n\t\t\t\tconfigOptions,\n\t\t\t},\n\t\t});\n\t}\n\n\tprivate async handleBuiltinCommand(\n\t\tsession: PiAcpSession,\n\t\tcmd: string,\n\t\targs: string[],\n\t): Promise<PromptResponse | null> {\n\t\tconst piSession = session.piSession;\n\n\t\tif (cmd === \"compact\") {\n\t\t\tconst customInstructions = args.join(\" \").trim() || undefined;\n\t\t\tconst res = await piSession.compact(customInstructions);\n\n\t\t\tconst headerLines = [\n\t\t\t\t`Compaction completed.${customInstructions !== undefined && customInstructions !== \"\" ? \" (custom instructions applied)\" : \"\"}`,\n\t\t\t\ttypeof res?.tokensBefore === \"number\" ? `Tokens before: ${res.tokensBefore}` : null,\n\t\t\t].filter(Boolean);\n\n\t\t\tconst text = headerLines.join(\"\\n\") + (res?.summary ? `\\n\\n${res.summary}` : \"\");\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"session\") {\n\t\t\tconst stats = piSession.getSessionStats();\n\t\t\tconst lines: string[] = [];\n\t\t\tif (stats.sessionId !== undefined && stats.sessionId !== \"\")\n\t\t\t\tlines.push(`Session: ${stats.sessionId}`);\n\t\t\tif (stats.sessionFile !== undefined && stats.sessionFile !== \"\")\n\t\t\t\tlines.push(`Session file: ${stats.sessionFile}`);\n\t\t\tlines.push(`Messages: ${stats.totalMessages}`);\n\t\t\tlines.push(`Cost: ${stats.cost}`);\n\t\t\tconst t = stats.tokens;\n\t\t\tconst parts: string[] = [];\n\t\t\tif (t.input) parts.push(`in ${t.input}`);\n\t\t\tif (t.output) parts.push(`out ${t.output}`);\n\t\t\tif (t.cacheRead) parts.push(`cache read ${t.cacheRead}`);\n\t\t\tif (t.cacheWrite) parts.push(`cache write ${t.cacheWrite}`);\n\t\t\tif (t.total) parts.push(`total ${t.total}`);\n\t\t\tif (parts.length > 0) lines.push(`Tokens: ${parts.join(\", \")}`);\n\n\t\t\tconst text = lines.join(\"\\n\");\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"name\") {\n\t\t\tconst name = args.join(\" \").trim();\n\t\t\tif (!name) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /name <name>\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tpiSession.setSessionName(name);\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"session_info_update\",\n\t\t\t\t\ttitle: name,\n\t\t\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\t\t},\n\t\t\t});\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Session name set: ${name}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"steering\") {\n\t\t\tconst modeRaw = String(args[0] ?? \"\").toLowerCase();\n\t\t\tif (!modeRaw) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Steering mode: ${piSession.steeringMode}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tif (modeRaw !== \"all\" && modeRaw !== \"one-at-a-time\") {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /steering all | /steering one-at-a-time\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tpiSession.setSteeringMode(modeRaw);\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Steering mode set to: ${modeRaw}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"follow-up\") {\n\t\t\tconst modeRaw = String(args[0] ?? \"\").toLowerCase();\n\t\t\tif (!modeRaw) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Follow-up mode: ${piSession.followUpMode}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tif (modeRaw !== \"all\" && modeRaw !== \"one-at-a-time\") {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Usage: /follow-up all | /follow-up one-at-a-time\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\t\t\tpiSession.setFollowUpMode(modeRaw);\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Follow-up mode set to: ${modeRaw}` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"autocompact\") {\n\t\t\tconst mode = (args[0] ?? \"toggle\").toLowerCase();\n\t\t\tlet enabled: boolean | null = null;\n\t\t\tif (mode === \"on\" || mode === \"true\" || mode === \"enable\") enabled = true;\n\t\t\telse if (mode === \"off\" || mode === \"false\" || mode === \"disable\") enabled = false;\n\n\t\t\tif (enabled === null) {\n\t\t\t\tenabled = !piSession.autoCompactionEnabled;\n\t\t\t}\n\n\t\t\tpiSession.setAutoCompactionEnabled(enabled);\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: {\n\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\tcontent: { type: \"text\", text: `Auto-compaction ${enabled ? \"enabled\" : \"disabled\"}.` },\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"changelog\") {\n\t\t\tconst changelogPath = findChangelog();\n\t\t\tif (changelogPath === null) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Changelog not found.\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tlet text = \"\";\n\t\t\ttry {\n\t\t\t\ttext = readFileSync(changelogPath, \"utf-8\");\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Failed to read changelog: ${msg}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\tconst maxChars = 20_000;\n\t\t\tif (text.length > maxChars) text = `${text.slice(0, maxChars)}\\n\\n...(truncated)...`;\n\n\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\tsessionId: session.sessionId,\n\t\t\t\tupdate: { sessionUpdate: \"agent_message_chunk\", content: { type: \"text\", text } },\n\t\t\t});\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\tif (cmd === \"export\") {\n\t\t\tconst messageCount = piSession.messages.length;\n\t\t\tif (messageCount === 0) {\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Nothing to export yet. Send a prompt first.\" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\treturn { stopReason: \"end_turn\" };\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst safeSessionId = session.sessionId.replace(/[^a-zA-Z0-9_-]/g, \"_\");\n\t\t\t\tconst outputPath = join(session.cwd, `pi-session-${safeSessionId}.html`);\n\t\t\t\tconst resultPath = await piSession.exportToHtml(outputPath);\n\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: \"Session exported: \" },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: {\n\t\t\t\t\t\t\ttype: \"resource_link\",\n\t\t\t\t\t\t\tname: `pi-session-${safeSessionId}.html`,\n\t\t\t\t\t\t\turi: `file://${resultPath}`,\n\t\t\t\t\t\t\tmimeType: \"text/html\",\n\t\t\t\t\t\t\ttitle: \"Session exported\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t} catch (e: unknown) {\n\t\t\t\tconst msg = e instanceof Error ? e.message : String(e);\n\t\t\t\tawait this.conn.sessionUpdate({\n\t\t\t\t\tsessionId: session.sessionId,\n\t\t\t\t\tupdate: {\n\t\t\t\t\t\tsessionUpdate: \"agent_message_chunk\",\n\t\t\t\t\t\tcontent: { type: \"text\", text: `Export failed: ${msg}` },\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { stopReason: \"end_turn\" };\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\nfunction isThinkingLevel(x: string): x is ThinkingLevel {\n\treturn (\n\t\tx === \"off\" || x === \"minimal\" || x === \"low\" || x === \"medium\" || x === \"high\" || x === \"xhigh\"\n\t);\n}\n\nfunction buildThinkingModes(piSession: AgentSession): {\n\tavailableModes: Array<{ id: string; name: string; description?: string | null }>;\n\tcurrentModeId: string;\n} {\n\tconst levels = piSession.getAvailableThinkingLevels();\n\treturn {\n\t\tcurrentModeId: piSession.thinkingLevel,\n\t\tavailableModes: levels.map((id) => ({\n\t\t\tid,\n\t\t\tname: `Thinking: ${id}`,\n\t\t\tdescription: null,\n\t\t})),\n\t};\n}\n\nfunction buildModelState(piSession: AgentSession): SessionModelState {\n\tconst available = piSession.modelRegistry.getAvailable();\n\tconst current = piSession.model;\n\n\tconst availableModels: ModelInfo[] = available.map((m) => ({\n\t\tmodelId: `${m.provider}/${m.id}`,\n\t\tname: `${m.provider}/${m.name ?? m.id}`,\n\t\tdescription: null,\n\t}));\n\n\tlet currentModelId = \"default\";\n\tif (current !== undefined) {\n\t\tcurrentModelId = `${current.provider}/${current.id}`;\n\t} else if (availableModels.length > 0 && availableModels[0] !== undefined) {\n\t\tcurrentModelId = availableModels[0].modelId;\n\t}\n\n\treturn { availableModels, currentModelId };\n}\n\nfunction buildConfigOptions(\n\tmodes: SessionModeState,\n\tmodels: SessionModelState,\n): SessionConfigOption[] {\n\treturn [\n\t\t{\n\t\t\tid: \"model\",\n\t\t\tname: \"Model\",\n\t\t\tdescription: \"AI model to use\",\n\t\t\tcategory: \"model\",\n\t\t\ttype: \"select\" as const,\n\t\t\tcurrentValue: models.currentModelId,\n\t\t\toptions: models.availableModels.map((m) => ({\n\t\t\t\tvalue: m.modelId,\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description ?? null,\n\t\t\t})),\n\t\t},\n\t\t{\n\t\t\tid: \"thought_level\",\n\t\t\tname: \"Thinking Level\",\n\t\t\tdescription: \"Reasoning depth for models that support it\",\n\t\t\tcategory: \"thought_level\",\n\t\t\ttype: \"select\" as const,\n\t\t\tcurrentValue: modes.currentModeId,\n\t\t\toptions: modes.availableModes.map((m) => ({\n\t\t\t\tvalue: m.id,\n\t\t\t\tname: m.name,\n\t\t\t\tdescription: m.description ?? null,\n\t\t\t})),\n\t\t},\n\t];\n}\n\nfunction buildCommandList(\n\tpiSession: AgentSession,\n\tenableSkillCommands: boolean,\n): AvailableCommand[] {\n\tconst commands: AvailableCommand[] = [];\n\n\tfor (const template of piSession.promptTemplates) {\n\t\tcommands.push({\n\t\t\tname: template.name,\n\t\t\tdescription: template.description ?? `(prompt)`,\n\t\t});\n\t}\n\n\tif (enableSkillCommands) {\n\t\tconst skills = piSession.resourceLoader.getSkills();\n\t\tfor (const skill of skills.skills) {\n\t\t\tcommands.push({\n\t\t\t\tname: `skill:${skill.name}`,\n\t\t\t\tdescription: skill.description ?? `(skill)`,\n\t\t\t});\n\t\t}\n\t}\n\n\tfor (const cmd of piSession.extensionRunner.getRegisteredCommands()) {\n\t\tcommands.push({\n\t\t\tname: cmd.name,\n\t\t\tdescription: cmd.description ?? \"(extension)\",\n\t\t});\n\t}\n\n\treturn commands;\n}\n\nfunction findChangelog(): string | null {\n\ttry {\n\t\tconst whichCmd = process.platform === \"win32\" ? \"where\" : \"which\";\n\t\tconst which = spawnSync(whichCmd, [\"pi\"], { encoding: \"utf-8\" });\n\t\tconst piPath = String(which.stdout ?? \"\")\n\t\t\t.split(/\\r?\\n/)[0]\n\t\t\t?.trim();\n\t\tif (piPath !== undefined && piPath !== \"\") {\n\t\t\tconst resolved = realpathSync(piPath);\n\t\t\tconst pkgRoot = dirname(dirname(resolved));\n\t\t\tconst p = join(pkgRoot, \"CHANGELOG.md\");\n\t\t\tif (existsSync(p)) return p;\n\t\t}\n\t} catch {}\n\n\ttry {\n\t\tconst npmRoot = spawnSync(\"npm\", [\"root\", \"-g\"], { encoding: \"utf-8\" });\n\t\tconst root = String(npmRoot.stdout ?? \"\").trim();\n\t\tif (root) {\n\t\t\tconst p = join(root, \"@mariozechner\", \"pi-coding-agent\", \"CHANGELOG.md\");\n\t\t\tif (existsSync(p)) return p;\n\t\t}\n\t} catch {}\n\n\treturn null;\n}\n","/**\n * Shared ACP-over-stream wiring used by both the in-process v0.5 fallback and\n * the daemon's per-connection accept path.\n *\n * Owns nothing global. Returns the constructed AgentSideConnection plus a\n * shutdown helper. Caller decides what process / signal handlers to attach.\n */\n\nimport type { Duplex } from \"node:stream\";\nimport { AgentSideConnection, ndJsonStream } from \"@agentclientprotocol/sdk\";\nimport { PiAcpAgent } from \"@pi-acp/acp/agent\";\nimport type { DaemonContext } from \"@pi-acp/daemon/context\";\n\nexport interface ServeOptions {\n\t/** Reads from the client. */\n\tinput: Duplex;\n\t/** Writes to the client. */\n\toutput: Duplex;\n\t/** Optional daemon context. Absent in `PI_ACP_NO_DAEMON=1` fallback path. */\n\tdaemonContext?: DaemonContext;\n}\n\nexport interface ServeHandle {\n\tconnection: AgentSideConnection;\n\t/** Best-effort dispose of the PiAcpAgent. */\n\tdispose: () => void;\n}\n\nexport function serveAcp(opts: ServeOptions): ServeHandle {\n\t// Build the NDJSON framing layer. `input` is the client-bound stream we\n\t// read FROM (client → agent). `output` is the stream we write TO\n\t// (agent → client). ndJsonStream(writable, readable): first arg is where\n\t// the agent writes responses, second is where it reads requests.\n\tconst stream = ndJsonStream(toWebWritable(opts.output), toWebReadable(opts.input));\n\tconst connection = new AgentSideConnection(\n\t\t(conn) => new PiAcpAgent(conn, opts.daemonContext),\n\t\tstream,\n\t);\n\treturn {\n\t\tconnection,\n\t\tdispose() {\n\t\t\ttry {\n\t\t\t\tconst inner = readUnknownProp(connection, \"agent\");\n\t\t\t\tconst dispose = readUnknownProp(inner, \"dispose\");\n\t\t\t\tif (typeof dispose === \"function\") {\n\t\t\t\t\tReflect.apply(dispose, inner, []);\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t/* best-effort */\n\t\t\t}\n\t\t},\n\t};\n}\n\nfunction readUnknownProp(target: unknown, key: string): unknown {\n\tif (typeof target !== \"object\" || target === null) return undefined;\n\treturn Reflect.get(target, key);\n}\n\nfunction toWebReadable(src: Duplex): ReadableStream<Uint8Array> {\n\treturn new ReadableStream<Uint8Array>({\n\t\tstart(controller) {\n\t\t\tsrc.on(\"data\", (chunk: Buffer) => controller.enqueue(new Uint8Array(chunk)));\n\t\t\tsrc.on(\"end\", () => {\n\t\t\t\ttry {\n\t\t\t\t\tcontroller.close();\n\t\t\t\t} catch {\n\t\t\t\t\t/* already closed */\n\t\t\t\t}\n\t\t\t});\n\t\t\tsrc.on(\"error\", (err) => {\n\t\t\t\ttry {\n\t\t\t\t\tcontroller.error(err);\n\t\t\t\t} catch {\n\t\t\t\t\t/* already terminated */\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t});\n}\n\nfunction toWebWritable(dst: Duplex): WritableStream<Uint8Array> {\n\treturn new WritableStream<Uint8Array>({\n\t\twrite(chunk) {\n\t\t\treturn new Promise<void>((resolve) => {\n\t\t\t\tif (dst.destroyed || !dst.writable) {\n\t\t\t\t\tresolve();\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\ttry {\n\t\t\t\t\tdst.write(chunk, () => resolve());\n\t\t\t\t} catch {\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\t});\n}\n"],"mappings":"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"}