uxnan-bridge 0.0.1-alpha.20260621

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.
Files changed (255) hide show
  1. package/README.md +150 -0
  2. package/dist/src/account-status.d.ts +13 -0
  3. package/dist/src/account-status.js +78 -0
  4. package/dist/src/account-status.js.map +1 -0
  5. package/dist/src/adapters/base-adapter.d.ts +18 -0
  6. package/dist/src/adapters/base-adapter.js +15 -0
  7. package/dist/src/adapters/base-adapter.js.map +1 -0
  8. package/dist/src/adapters/claude-adapter.d.ts +102 -0
  9. package/dist/src/adapters/claude-adapter.js +486 -0
  10. package/dist/src/adapters/claude-adapter.js.map +1 -0
  11. package/dist/src/adapters/claude-tools.d.ts +25 -0
  12. package/dist/src/adapters/claude-tools.js +146 -0
  13. package/dist/src/adapters/claude-tools.js.map +1 -0
  14. package/dist/src/adapters/codex-adapter.d.ts +116 -0
  15. package/dist/src/adapters/codex-adapter.js +912 -0
  16. package/dist/src/adapters/codex-adapter.js.map +1 -0
  17. package/dist/src/adapters/codex-app-server.d.ts +74 -0
  18. package/dist/src/adapters/codex-app-server.js +225 -0
  19. package/dist/src/adapters/codex-app-server.js.map +1 -0
  20. package/dist/src/adapters/codex-approval.d.ts +88 -0
  21. package/dist/src/adapters/codex-approval.js +160 -0
  22. package/dist/src/adapters/codex-approval.js.map +1 -0
  23. package/dist/src/adapters/codex-tools.d.ts +18 -0
  24. package/dist/src/adapters/codex-tools.js +106 -0
  25. package/dist/src/adapters/codex-tools.js.map +1 -0
  26. package/dist/src/adapters/content-blocks.d.ts +68 -0
  27. package/dist/src/adapters/content-blocks.js +205 -0
  28. package/dist/src/adapters/content-blocks.js.map +1 -0
  29. package/dist/src/adapters/echo-agent-adapter.d.ts +23 -0
  30. package/dist/src/adapters/echo-agent-adapter.js +72 -0
  31. package/dist/src/adapters/echo-agent-adapter.js.map +1 -0
  32. package/dist/src/adapters/gemini-adapter.d.ts +87 -0
  33. package/dist/src/adapters/gemini-adapter.js +594 -0
  34. package/dist/src/adapters/gemini-adapter.js.map +1 -0
  35. package/dist/src/adapters/gemini-tools.d.ts +4 -0
  36. package/dist/src/adapters/gemini-tools.js +48 -0
  37. package/dist/src/adapters/gemini-tools.js.map +1 -0
  38. package/dist/src/adapters/opencode-adapter.d.ts +74 -0
  39. package/dist/src/adapters/opencode-adapter.js +418 -0
  40. package/dist/src/adapters/opencode-adapter.js.map +1 -0
  41. package/dist/src/adapters/opencode-tools.d.ts +2 -0
  42. package/dist/src/adapters/opencode-tools.js +41 -0
  43. package/dist/src/adapters/opencode-tools.js.map +1 -0
  44. package/dist/src/adapters/pi-adapter.d.ts +92 -0
  45. package/dist/src/adapters/pi-adapter.js +467 -0
  46. package/dist/src/adapters/pi-adapter.js.map +1 -0
  47. package/dist/src/adapters/pi-tools.d.ts +10 -0
  48. package/dist/src/adapters/pi-tools.js +72 -0
  49. package/dist/src/adapters/pi-tools.js.map +1 -0
  50. package/dist/src/adapters/process-agent-adapter.d.ts +24 -0
  51. package/dist/src/adapters/process-agent-adapter.js +111 -0
  52. package/dist/src/adapters/process-agent-adapter.js.map +1 -0
  53. package/dist/src/adapters/resolve-claude.d.ts +13 -0
  54. package/dist/src/adapters/resolve-claude.js +57 -0
  55. package/dist/src/adapters/resolve-claude.js.map +1 -0
  56. package/dist/src/adapters/resolve-codex.d.ts +13 -0
  57. package/dist/src/adapters/resolve-codex.js +48 -0
  58. package/dist/src/adapters/resolve-codex.js.map +1 -0
  59. package/dist/src/adapters/resolve-gemini.d.ts +13 -0
  60. package/dist/src/adapters/resolve-gemini.js +47 -0
  61. package/dist/src/adapters/resolve-gemini.js.map +1 -0
  62. package/dist/src/adapters/resolve-opencode.d.ts +11 -0
  63. package/dist/src/adapters/resolve-opencode.js +49 -0
  64. package/dist/src/adapters/resolve-opencode.js.map +1 -0
  65. package/dist/src/adapters/resolve-pi.d.ts +13 -0
  66. package/dist/src/adapters/resolve-pi.js +46 -0
  67. package/dist/src/adapters/resolve-pi.js.map +1 -0
  68. package/dist/src/adapters/run-options.d.ts +22 -0
  69. package/dist/src/adapters/run-options.js +48 -0
  70. package/dist/src/adapters/run-options.js.map +1 -0
  71. package/dist/src/adapters/spawn.d.ts +20 -0
  72. package/dist/src/adapters/spawn.js +16 -0
  73. package/dist/src/adapters/spawn.js.map +1 -0
  74. package/dist/src/agents/agent-manager.d.ts +98 -0
  75. package/dist/src/agents/agent-manager.js +433 -0
  76. package/dist/src/agents/agent-manager.js.map +1 -0
  77. package/dist/src/agents/attachments.d.ts +28 -0
  78. package/dist/src/agents/attachments.js +121 -0
  79. package/dist/src/agents/attachments.js.map +1 -0
  80. package/dist/src/bridge-context.d.ts +45 -0
  81. package/dist/src/bridge-context.js +2 -0
  82. package/dist/src/bridge-context.js.map +1 -0
  83. package/dist/src/bridge-status.d.ts +12 -0
  84. package/dist/src/bridge-status.js +17 -0
  85. package/dist/src/bridge-status.js.map +1 -0
  86. package/dist/src/bridge.d.ts +37 -0
  87. package/dist/src/bridge.js +446 -0
  88. package/dist/src/bridge.js.map +1 -0
  89. package/dist/src/cli.d.ts +2 -0
  90. package/dist/src/cli.js +194 -0
  91. package/dist/src/cli.js.map +1 -0
  92. package/dist/src/conversation/session-history.d.ts +27 -0
  93. package/dist/src/conversation/session-history.js +1082 -0
  94. package/dist/src/conversation/session-history.js.map +1 -0
  95. package/dist/src/conversation/thread-store.d.ts +74 -0
  96. package/dist/src/conversation/thread-store.js +366 -0
  97. package/dist/src/conversation/thread-store.js.map +1 -0
  98. package/dist/src/daemon-config.d.ts +123 -0
  99. package/dist/src/daemon-config.js +64 -0
  100. package/dist/src/daemon-config.js.map +1 -0
  101. package/dist/src/daemon-state.d.ts +27 -0
  102. package/dist/src/daemon-state.js +76 -0
  103. package/dist/src/daemon-state.js.map +1 -0
  104. package/dist/src/git/git-runner.d.ts +24 -0
  105. package/dist/src/git/git-runner.js +63 -0
  106. package/dist/src/git/git-runner.js.map +1 -0
  107. package/dist/src/git/git-service.d.ts +76 -0
  108. package/dist/src/git/git-service.js +435 -0
  109. package/dist/src/git/git-service.js.map +1 -0
  110. package/dist/src/handler-router.d.ts +34 -0
  111. package/dist/src/handler-router.js +67 -0
  112. package/dist/src/handler-router.js.map +1 -0
  113. package/dist/src/handlers/account-handler.d.ts +4 -0
  114. package/dist/src/handlers/account-handler.js +27 -0
  115. package/dist/src/handlers/account-handler.js.map +1 -0
  116. package/dist/src/handlers/agent-handler.d.ts +2 -0
  117. package/dist/src/handlers/agent-handler.js +8 -0
  118. package/dist/src/handlers/agent-handler.js.map +1 -0
  119. package/dist/src/handlers/bridge-control-handler.d.ts +2 -0
  120. package/dist/src/handlers/bridge-control-handler.js +64 -0
  121. package/dist/src/handlers/bridge-control-handler.js.map +1 -0
  122. package/dist/src/handlers/desktop-handler.d.ts +12 -0
  123. package/dist/src/handlers/desktop-handler.js +5 -0
  124. package/dist/src/handlers/desktop-handler.js.map +1 -0
  125. package/dist/src/handlers/git-handler.d.ts +2 -0
  126. package/dist/src/handlers/git-handler.js +82 -0
  127. package/dist/src/handlers/git-handler.js.map +1 -0
  128. package/dist/src/handlers/index.d.ts +8 -0
  129. package/dist/src/handlers/index.js +22 -0
  130. package/dist/src/handlers/index.js.map +1 -0
  131. package/dist/src/handlers/not-implemented.d.ts +10 -0
  132. package/dist/src/handlers/not-implemented.js +21 -0
  133. package/dist/src/handlers/not-implemented.js.map +1 -0
  134. package/dist/src/handlers/notifications-handler.d.ts +2 -0
  135. package/dist/src/handlers/notifications-handler.js +62 -0
  136. package/dist/src/handlers/notifications-handler.js.map +1 -0
  137. package/dist/src/handlers/params.d.ts +11 -0
  138. package/dist/src/handlers/params.js +72 -0
  139. package/dist/src/handlers/params.js.map +1 -0
  140. package/dist/src/handlers/project-handler.d.ts +2 -0
  141. package/dist/src/handlers/project-handler.js +6 -0
  142. package/dist/src/handlers/project-handler.js.map +1 -0
  143. package/dist/src/handlers/thread-context-handler.d.ts +2 -0
  144. package/dist/src/handlers/thread-context-handler.js +211 -0
  145. package/dist/src/handlers/thread-context-handler.js.map +1 -0
  146. package/dist/src/handlers/workspace-handler.d.ts +2 -0
  147. package/dist/src/handlers/workspace-handler.js +101 -0
  148. package/dist/src/handlers/workspace-handler.js.map +1 -0
  149. package/dist/src/hooks/claude-approval-hook.d.ts +7 -0
  150. package/dist/src/hooks/claude-approval-hook.js +95 -0
  151. package/dist/src/hooks/claude-approval-hook.js.map +1 -0
  152. package/dist/src/hooks/gemini-approval-hook.d.ts +7 -0
  153. package/dist/src/hooks/gemini-approval-hook.js +113 -0
  154. package/dist/src/hooks/gemini-approval-hook.js.map +1 -0
  155. package/dist/src/index.d.ts +62 -0
  156. package/dist/src/index.js +65 -0
  157. package/dist/src/index.js.map +1 -0
  158. package/dist/src/keyring-secret-store.d.ts +36 -0
  159. package/dist/src/keyring-secret-store.js +70 -0
  160. package/dist/src/keyring-secret-store.js.map +1 -0
  161. package/dist/src/lock-file.d.ts +18 -0
  162. package/dist/src/lock-file.js +60 -0
  163. package/dist/src/lock-file.js.map +1 -0
  164. package/dist/src/logger.d.ts +28 -0
  165. package/dist/src/logger.js +99 -0
  166. package/dist/src/logger.js.map +1 -0
  167. package/dist/src/pairing/pairing-code-service.d.ts +45 -0
  168. package/dist/src/pairing/pairing-code-service.js +183 -0
  169. package/dist/src/pairing/pairing-code-service.js.map +1 -0
  170. package/dist/src/projects/project-registry.d.ts +14 -0
  171. package/dist/src/projects/project-registry.js +60 -0
  172. package/dist/src/projects/project-registry.js.map +1 -0
  173. package/dist/src/push/push-sender.d.ts +21 -0
  174. package/dist/src/push/push-sender.js +96 -0
  175. package/dist/src/push/push-sender.js.map +1 -0
  176. package/dist/src/push/push-service.d.ts +122 -0
  177. package/dist/src/push/push-service.js +260 -0
  178. package/dist/src/push/push-service.js.map +1 -0
  179. package/dist/src/qr.d.ts +17 -0
  180. package/dist/src/qr.js +31 -0
  181. package/dist/src/qr.js.map +1 -0
  182. package/dist/src/secret-store.d.ts +23 -0
  183. package/dist/src/secret-store.js +27 -0
  184. package/dist/src/secret-store.js.map +1 -0
  185. package/dist/src/secure-device-state.d.ts +16 -0
  186. package/dist/src/secure-device-state.js +63 -0
  187. package/dist/src/secure-device-state.js.map +1 -0
  188. package/dist/src/service-installer.d.ts +57 -0
  189. package/dist/src/service-installer.js +254 -0
  190. package/dist/src/service-installer.js.map +1 -0
  191. package/dist/src/session-state.d.ts +14 -0
  192. package/dist/src/session-state.js +19 -0
  193. package/dist/src/session-state.js.map +1 -0
  194. package/dist/src/transport/crypto.d.ts +43 -0
  195. package/dist/src/transport/crypto.js +78 -0
  196. package/dist/src/transport/crypto.js.map +1 -0
  197. package/dist/src/transport/lan-server.d.ts +33 -0
  198. package/dist/src/transport/lan-server.js +105 -0
  199. package/dist/src/transport/lan-server.js.map +1 -0
  200. package/dist/src/transport/local-hosts.d.ts +17 -0
  201. package/dist/src/transport/local-hosts.js +30 -0
  202. package/dist/src/transport/local-hosts.js.map +1 -0
  203. package/dist/src/transport/mdns-advertiser.d.ts +83 -0
  204. package/dist/src/transport/mdns-advertiser.js +282 -0
  205. package/dist/src/transport/mdns-advertiser.js.map +1 -0
  206. package/dist/src/transport/message-io.d.ts +33 -0
  207. package/dist/src/transport/message-io.js +87 -0
  208. package/dist/src/transport/message-io.js.map +1 -0
  209. package/dist/src/transport/outbound-log.d.ts +24 -0
  210. package/dist/src/transport/outbound-log.js +78 -0
  211. package/dist/src/transport/outbound-log.js.map +1 -0
  212. package/dist/src/transport/relay-client.d.ts +19 -0
  213. package/dist/src/transport/relay-client.js +27 -0
  214. package/dist/src/transport/relay-client.js.map +1 -0
  215. package/dist/src/transport/secure-channel.d.ts +33 -0
  216. package/dist/src/transport/secure-channel.js +81 -0
  217. package/dist/src/transport/secure-channel.js.map +1 -0
  218. package/dist/src/transport/server-handshake.d.ts +49 -0
  219. package/dist/src/transport/server-handshake.js +137 -0
  220. package/dist/src/transport/server-handshake.js.map +1 -0
  221. package/dist/src/transport/session-handler.d.ts +19 -0
  222. package/dist/src/transport/session-handler.js +134 -0
  223. package/dist/src/transport/session-handler.js.map +1 -0
  224. package/dist/src/transport/session-registry.d.ts +58 -0
  225. package/dist/src/transport/session-registry.js +91 -0
  226. package/dist/src/transport/session-registry.js.map +1 -0
  227. package/dist/src/transport/trust-store.d.ts +23 -0
  228. package/dist/src/transport/trust-store.js +33 -0
  229. package/dist/src/transport/trust-store.js.map +1 -0
  230. package/dist/src/transport/ws-adapter.d.ts +7 -0
  231. package/dist/src/transport/ws-adapter.js +16 -0
  232. package/dist/src/transport/ws-adapter.js.map +1 -0
  233. package/dist/src/version.d.ts +1 -0
  234. package/dist/src/version.js +13 -0
  235. package/dist/src/version.js.map +1 -0
  236. package/dist/src/workspace/browse-service.d.ts +10 -0
  237. package/dist/src/workspace/browse-service.js +97 -0
  238. package/dist/src/workspace/browse-service.js.map +1 -0
  239. package/dist/src/workspace/checkpoint-service.d.ts +21 -0
  240. package/dist/src/workspace/checkpoint-service.js +219 -0
  241. package/dist/src/workspace/checkpoint-service.js.map +1 -0
  242. package/dist/src/workspace/path-guard.d.ts +7 -0
  243. package/dist/src/workspace/path-guard.js +51 -0
  244. package/dist/src/workspace/path-guard.js.map +1 -0
  245. package/dist/src/workspace/workspace-service.d.ts +8 -0
  246. package/dist/src/workspace/workspace-service.js +111 -0
  247. package/dist/src/workspace/workspace-service.js.map +1 -0
  248. package/package.json +46 -0
  249. package/scripts/extract-gemini-hook.mjs +16 -0
  250. package/scripts/fake-approval-bridge.mjs +23 -0
  251. package/scripts/install-service-linux.sh +38 -0
  252. package/scripts/install-service-macos.sh +38 -0
  253. package/scripts/install-service-windows.ps1 +26 -0
  254. package/scripts/test-gemini-hook-e2e.mjs +168 -0
  255. package/scripts/write-gemini-settings.mjs +31 -0
@@ -0,0 +1,92 @@
1
+ import type { AgentCapabilities, AgentConfig, AgentId, AgentModel, SendTurnOptions } from '@uxnan/shared';
2
+ import { BaseAgentAdapter } from './base-adapter.js';
3
+ import { type PiToolUse } from './pi-tools.js';
4
+ import { type SpawnFn } from './spawn.js';
5
+ /**
6
+ * Tool posture passed to pi:
7
+ * - `default` → `--tools read,grep,find,ls` (read-only; no bash/edit/write);
8
+ * - `acceptEdits` → pi's default built-in tools (read/bash/edit/write);
9
+ * - `bypassPermissions` → default tools + `--approve` (trust project-local files).
10
+ */
11
+ export type PiPermissionMode = 'default' | 'acceptEdits' | 'bypassPermissions';
12
+ export interface PiAdapterOptions {
13
+ /** Executable to spawn (resolved path; see resolve-pi.ts). */
14
+ binaryPath?: string;
15
+ /** Args prepended before the adapter args (e.g. `[cli.js]` when running via node). */
16
+ prependArgs?: string[];
17
+ /** Default model (`provider/model`) when the thread/turn doesn't pick one. */
18
+ defaultModel?: string;
19
+ /** Tool posture (default `acceptEdits`). */
20
+ permissionMode?: PiPermissionMode;
21
+ /** Injected spawn function (tests). */
22
+ spawnFn?: SpawnFn;
23
+ }
24
+ /** A normalized pi event extracted from one `--mode json` line. */
25
+ export interface PiEvent {
26
+ kind: 'session' | 'delta' | 'thinking' | 'tool_start' | 'tool_end' | 'final' | 'end' | 'other';
27
+ /** Only set for `session`: the session id (for `--session-id` continuity). */
28
+ sessionId?: string;
29
+ /**
30
+ * `delta`: the streamed text chunk. `thinking`: a reasoning chunk. `final`:
31
+ * the assistant message's full text.
32
+ */
33
+ text?: string;
34
+ /** Only set for `final`: context-occupying token count, if reported. */
35
+ tokens?: number;
36
+ /** Only set for `final`: whether the assistant message ended in error. */
37
+ isError?: boolean;
38
+ /** Only set for `final`: the error message, when present. */
39
+ errorText?: string;
40
+ /** `tool_start`/`tool_end`: the tool call's id (for pairing args ↔ result). */
41
+ toolCallId?: string;
42
+ /** Only set for `tool_start`: the tool name + its arguments. */
43
+ tool?: PiToolUse;
44
+ /** Only set for `tool_end`: the tool's output text. */
45
+ toolOutput?: string;
46
+ /** Only set for `tool_end`: whether the tool failed. */
47
+ toolIsError?: boolean;
48
+ }
49
+ /**
50
+ * Sum the context-occupying tokens from a pi `usage` object
51
+ * (`{ input, output, cacheRead, cacheWrite, totalTokens, cost }`). Prefers the
52
+ * reported `totalTokens`, falling back to `input + output`.
53
+ */
54
+ export declare function parsePiUsageTokens(usage: unknown): number | undefined;
55
+ /**
56
+ * Parse a pi `--list-models` `context` cell into a token count: `"1.0M"` →
57
+ * 1_000_000, `"384K"` → 384_000, a bare `"200000"` → 200000. Returns undefined
58
+ * for an unparseable / non-positive cell (so the model just omits its window).
59
+ */
60
+ export declare function parsePiContextWindow(cell: string | undefined): number | undefined;
61
+ /** Parse one `pi -p --mode json` line, or null if it isn't JSON. */
62
+ export declare function parsePiLine(line: string): PiEvent | null;
63
+ /**
64
+ * Parse the `pi --list-models` table into {@link AgentModel}s. Each row is
65
+ * `provider model context max-out thinking images` (whitespace-separated, no
66
+ * field contains spaces). `id` is `provider/model` (the `--model` routing key);
67
+ * models whose `thinking` column is `yes` advertise the reasoning knob.
68
+ */
69
+ export declare function parsePiModelList(output: string, defaultModel?: string): AgentModel[];
70
+ export declare class PiAdapter extends BaseAgentAdapter {
71
+ #private;
72
+ readonly agentId: AgentId;
73
+ readonly capabilities: AgentCapabilities;
74
+ /** Native pi session id for a thread (on-disk history-fallback locator). */
75
+ nativeSessionId(threadId: string): string | undefined;
76
+ constructor(options?: PiAdapterOptions);
77
+ get defaultModel(): string | undefined;
78
+ start(config: AgentConfig): Promise<void>;
79
+ stop(): Promise<void>;
80
+ sendTurn(options: SendTurnOptions): Promise<void>;
81
+ cancelTurn(threadId: string, turnId: string): Promise<void>;
82
+ /**
83
+ * List the models pi reports via `pi --list-models` (account-aware: only
84
+ * providers the user has configured appear). The output is a table, parsed by
85
+ * {@link parsePiModelList}. Resolves to `[]` if the spawn fails or times out.
86
+ *
87
+ * Note: pi prints the `--list-models` table to STDERR, not stdout (verified
88
+ * against pi 0.79.1), so we accumulate BOTH streams. Without this the phone's
89
+ * model picker shows no models for the pi agent.
90
+ */
91
+ listModels(): Promise<AgentModel[]>;
92
+ }
@@ -0,0 +1,467 @@
1
+ /**
2
+ * pi adapter (`@earendil-works/pi-coding-agent`, the `pi` CLI — real agent).
3
+ *
4
+ * pi does NOT speak the generic bridge agent IPC. Each turn spawns
5
+ * `pi -p --mode json …` as a one-shot process and maps its newline-JSON event
6
+ * stream onto the bridge's agent events (same one-shot pattern as the OpenCode,
7
+ * Claude Code and Codex adapters). Session continuity is preserved by capturing
8
+ * the session `id` from the `session` event and passing `--session-id <id>` on
9
+ * the next turn — validated live against `pi` 0.79.1.
10
+ *
11
+ * Critical detail: `pi -p` blocks reading stdin when stdin is an open pipe, so we
12
+ * spawn with stdin IGNORED (the shared `defaultSpawn`). The prompt is passed as
13
+ * an argv element with `shell:false`, so it is never interpolated into a shell.
14
+ *
15
+ * Captured `--mode json` event shapes (one JSON object per line):
16
+ * { "type":"session", "id":"019…", "cwd":"…" }
17
+ * { "type":"message_update", "assistantMessageEvent":{ "type":"text_delta", "delta":"…" } }
18
+ * { "type":"message_end", "message":{ "role":"assistant", "content":[{ "type":"text","text":"…" }],
19
+ * "usage":{ "input":…, "output":…, "totalTokens":… }, "stopReason":"stop"|"error", "errorMessage"?:"…" } }
20
+ * { "type":"agent_end", "messages":[…], "willRetry":false }
21
+ * (`thinking_*` assistant events carry the model's reasoning and are NOT emitted
22
+ * as answer text.) A startup failure (e.g. a provider with no API key) prints a
23
+ * plain-text line instead of JSON; we surface that as the turn error.
24
+ *
25
+ * See bridge/FOR-DEV.md (agent adapters) and bridge/docs/testing.md.
26
+ */
27
+ import { createInterface } from 'node:readline';
28
+ import { BaseAgentAdapter } from './base-adapter.js';
29
+ import { piResultText, piToolBlock } from './pi-tools.js';
30
+ import { effortValues, reasoningOption, reasoningValue } from './run-options.js';
31
+ import { defaultSpawn } from './spawn.js';
32
+ /** Hard cap on the `--list-models` spawn before giving up. */
33
+ const MODEL_LIST_TIMEOUT_MS = 8000;
34
+ const PI_CAPABILITIES = {
35
+ // Plan mode is a pi extension, not core, so it's not advertised here.
36
+ planMode: false,
37
+ streaming: true,
38
+ // pi runs its tools autonomously in `-p` mode (no per-turn approval RPC).
39
+ approvals: false,
40
+ forking: true,
41
+ images: true,
42
+ reportsContextUsage: true,
43
+ };
44
+ /** Reasoning-effort levels pi's `--thinking` flag accepts (verified via `pi --help`). */
45
+ const PI_THINKING_LEVELS = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh'];
46
+ /** The `reasoning` knob advertised on pi models that support thinking. */
47
+ const PI_REASONING_OPTION = reasoningOption(effortValues(PI_THINKING_LEVELS));
48
+ /**
49
+ * Sum the context-occupying tokens from a pi `usage` object
50
+ * (`{ input, output, cacheRead, cacheWrite, totalTokens, cost }`). Prefers the
51
+ * reported `totalTokens`, falling back to `input + output`.
52
+ */
53
+ export function parsePiUsageTokens(usage) {
54
+ if (!isRecord(usage))
55
+ return undefined;
56
+ const num = (key) => typeof usage[key] === 'number' ? usage[key] : 0;
57
+ const total = num('totalTokens') > 0 ? num('totalTokens') : num('input') + num('output');
58
+ return total > 0 ? total : undefined;
59
+ }
60
+ /**
61
+ * Parse a pi `--list-models` `context` cell into a token count: `"1.0M"` →
62
+ * 1_000_000, `"384K"` → 384_000, a bare `"200000"` → 200000. Returns undefined
63
+ * for an unparseable / non-positive cell (so the model just omits its window).
64
+ */
65
+ export function parsePiContextWindow(cell) {
66
+ if (!cell)
67
+ return undefined;
68
+ const match = cell.trim().match(/^([\d.]+)\s*([KMkm]?)$/);
69
+ if (!match)
70
+ return undefined;
71
+ const value = Number(match[1]);
72
+ if (!Number.isFinite(value) || value <= 0)
73
+ return undefined;
74
+ const unit = match[2]?.toUpperCase();
75
+ const multiplier = unit === 'M' ? 1_000_000 : unit === 'K' ? 1_000 : 1;
76
+ return Math.round(value * multiplier);
77
+ }
78
+ /** Parse one `pi -p --mode json` line, or null if it isn't JSON. */
79
+ export function parsePiLine(line) {
80
+ const trimmed = line.trim();
81
+ if (!trimmed)
82
+ return null;
83
+ let parsed;
84
+ try {
85
+ parsed = JSON.parse(trimmed);
86
+ }
87
+ catch {
88
+ return null;
89
+ }
90
+ switch (parsed['type']) {
91
+ case 'session': {
92
+ const id = typeof parsed['id'] === 'string' ? parsed['id'] : undefined;
93
+ return { kind: 'session', ...(id !== undefined ? { sessionId: id } : {}) };
94
+ }
95
+ case 'message_update': {
96
+ const event = isRecord(parsed['assistantMessageEvent'])
97
+ ? parsed['assistantMessageEvent']
98
+ : undefined;
99
+ if (event && event['type'] === 'text_delta' && typeof event['delta'] === 'string') {
100
+ return { kind: 'delta', text: event['delta'] };
101
+ }
102
+ // Reasoning streams as `thinking_delta` updates (verified: pi emits
103
+ // `thinking_*` assistant events for the model's reasoning).
104
+ if (event && event['type'] === 'thinking_delta' && typeof event['delta'] === 'string') {
105
+ return { kind: 'thinking', text: event['delta'] };
106
+ }
107
+ // text_start/end and other updates carry no answer text.
108
+ return { kind: 'other' };
109
+ }
110
+ case 'message_end': {
111
+ const message = isRecord(parsed['message']) ? parsed['message'] : undefined;
112
+ if (!message || message['role'] !== 'assistant')
113
+ return { kind: 'other' };
114
+ const text = extractAssistantText(message['content']);
115
+ const tokens = parsePiUsageTokens(message['usage']);
116
+ const errorMessage = typeof message['errorMessage'] === 'string' ? message['errorMessage'] : undefined;
117
+ const isError = message['stopReason'] === 'error' || errorMessage !== undefined;
118
+ return {
119
+ kind: 'final',
120
+ ...(text.length > 0 ? { text } : {}),
121
+ ...(tokens !== undefined ? { tokens } : {}),
122
+ isError,
123
+ ...(errorMessage !== undefined ? { errorText: errorMessage } : {}),
124
+ };
125
+ }
126
+ case 'tool_execution_start': {
127
+ const id = typeof parsed['toolCallId'] === 'string' ? parsed['toolCallId'] : '';
128
+ const name = typeof parsed['toolName'] === 'string' ? parsed['toolName'] : '';
129
+ const args = isRecord(parsed['args']) ? parsed['args'] : {};
130
+ return { kind: 'tool_start', toolCallId: id, tool: { id, name, input: args } };
131
+ }
132
+ case 'tool_execution_end': {
133
+ const id = typeof parsed['toolCallId'] === 'string' ? parsed['toolCallId'] : '';
134
+ return {
135
+ kind: 'tool_end',
136
+ toolCallId: id,
137
+ toolOutput: piResultText(parsed['result']),
138
+ toolIsError: parsed['isError'] === true,
139
+ };
140
+ }
141
+ case 'agent_end':
142
+ return { kind: 'end' };
143
+ default:
144
+ return { kind: 'other' };
145
+ }
146
+ }
147
+ /**
148
+ * Parse the `pi --list-models` table into {@link AgentModel}s. Each row is
149
+ * `provider model context max-out thinking images` (whitespace-separated, no
150
+ * field contains spaces). `id` is `provider/model` (the `--model` routing key);
151
+ * models whose `thinking` column is `yes` advertise the reasoning knob.
152
+ */
153
+ export function parsePiModelList(output, defaultModel) {
154
+ const out = [];
155
+ const seen = new Set();
156
+ for (const raw of output.split(/\r?\n/)) {
157
+ const line = raw.trim();
158
+ if (!line)
159
+ continue;
160
+ const cols = line.split(/\s+/);
161
+ if (cols.length < 6)
162
+ continue;
163
+ const provider = cols[0];
164
+ const model = cols[1];
165
+ const context = cols[2];
166
+ const thinking = cols[4];
167
+ if (provider === 'provider')
168
+ continue; // header row
169
+ const id = `${provider}/${model}`;
170
+ if (seen.has(id))
171
+ continue;
172
+ seen.add(id);
173
+ const contextWindow = parsePiContextWindow(context);
174
+ out.push({
175
+ id,
176
+ displayName: model,
177
+ description: provider,
178
+ isDefault: id === defaultModel,
179
+ ...(thinking === 'yes' ? { options: [PI_REASONING_OPTION] } : {}),
180
+ ...(contextWindow !== undefined ? { contextWindow } : {}),
181
+ });
182
+ }
183
+ return out;
184
+ }
185
+ export class PiAdapter extends BaseAgentAdapter {
186
+ agentId = 'pi-agent';
187
+ capabilities = PI_CAPABILITIES;
188
+ #binaryPath;
189
+ #prependArgs;
190
+ #defaultModel;
191
+ #permissionMode;
192
+ #spawn;
193
+ /** threadId → pi session id, for `--session-id` continuity. */
194
+ #sessionByThread = new Map();
195
+ /** turnId → in-flight run, for cancellation. */
196
+ #active = new Map();
197
+ /** model id → context-window tokens, cached from `--list-models` for `usage`. */
198
+ #contextWindowByModel = new Map();
199
+ #defaultCwd = process.cwd();
200
+ /** Native pi session id for a thread (on-disk history-fallback locator). */
201
+ nativeSessionId(threadId) {
202
+ return this.#sessionByThread.get(threadId);
203
+ }
204
+ constructor(options = {}) {
205
+ super();
206
+ this.#binaryPath = options.binaryPath ?? 'pi';
207
+ this.#prependArgs = options.prependArgs ?? [];
208
+ this.#defaultModel = options.defaultModel;
209
+ this.#permissionMode = options.permissionMode ?? 'acceptEdits';
210
+ this.#spawn = options.spawnFn ?? defaultSpawn;
211
+ }
212
+ get defaultModel() {
213
+ return this.#defaultModel;
214
+ }
215
+ start(config) {
216
+ if (config.cwd)
217
+ this.#defaultCwd = config.cwd;
218
+ return Promise.resolve();
219
+ }
220
+ stop() {
221
+ for (const run of this.#active.values()) {
222
+ run.child.kill();
223
+ }
224
+ this.#active.clear();
225
+ return Promise.resolve();
226
+ }
227
+ sendTurn(options) {
228
+ const { threadId, turnId, text } = options;
229
+ const cwd = options.cwd ?? this.#defaultCwd;
230
+ const model = options.service ?? this.#defaultModel;
231
+ const effort = reasoningValue(options);
232
+ const sessionId = this.#sessionByThread.get(threadId);
233
+ const args = ['-p', '--mode', 'json'];
234
+ if (this.#permissionMode === 'default')
235
+ args.push('--tools', 'read,grep,find,ls');
236
+ else if (this.#permissionMode === 'bypassPermissions')
237
+ args.push('--approve');
238
+ if (model)
239
+ args.push('--model', model);
240
+ // Reasoning effort → pi's `--thinking <off|minimal|low|medium|high|xhigh>`.
241
+ if (effort)
242
+ args.push('--thinking', effort);
243
+ // Resume the thread's session (created on the first turn); the prompt is the
244
+ // final positional, never shell-interpolated.
245
+ if (sessionId)
246
+ args.push('--session-id', sessionId);
247
+ args.push(text);
248
+ let child;
249
+ try {
250
+ child = this.#spawn(this.#binaryPath, [...this.#prependArgs, ...args], cwd);
251
+ }
252
+ catch (err) {
253
+ this.emit({
254
+ type: 'turn_error',
255
+ threadId,
256
+ turnId,
257
+ data: { text: `failed to launch pi: ${errorMessage(err)}` },
258
+ });
259
+ return Promise.resolve();
260
+ }
261
+ this.#active.set(turnId, { child, threadId });
262
+ this.emit({ type: 'turn_started', threadId, turnId });
263
+ let full = '';
264
+ let finalText = '';
265
+ let tokens;
266
+ let errored = false;
267
+ let errorMsg;
268
+ // toolCallId → its invocation (args), until the matching execution_end pairs.
269
+ const pendingTools = new Map();
270
+ // Non-JSON output (e.g. a startup "No API key found" error) — surfaced if the
271
+ // turn produces no content.
272
+ const plainLines = [];
273
+ let completed = false;
274
+ const finish = () => {
275
+ if (completed)
276
+ return;
277
+ completed = true;
278
+ const body = full.length > 0 ? full : finalText;
279
+ if (errored && body.length === 0) {
280
+ this.emit({
281
+ type: 'turn_error',
282
+ threadId,
283
+ turnId,
284
+ data: { text: errorMsg ?? plainText(plainLines) ?? 'pi error' },
285
+ });
286
+ return;
287
+ }
288
+ if (body.length === 0 && plainLines.length > 0 && !errored) {
289
+ // No JSON content and no terminal event: surface the plain output.
290
+ this.emit({
291
+ type: 'turn_error',
292
+ threadId,
293
+ turnId,
294
+ data: { text: plainText(plainLines) ?? 'pi produced no output' },
295
+ });
296
+ return;
297
+ }
298
+ const contextWindow = model !== undefined ? this.#contextWindowByModel.get(model) : undefined;
299
+ const usage = tokens !== undefined
300
+ ? { tokens, ...(contextWindow !== undefined ? { contextWindow } : {}) }
301
+ : undefined;
302
+ this.emit({
303
+ type: 'turn_completed',
304
+ threadId,
305
+ turnId,
306
+ data: { text: body, ...(usage !== undefined ? { usage } : {}) },
307
+ });
308
+ };
309
+ const reader = createInterface({ input: child.stdout });
310
+ reader.on('line', (line) => {
311
+ const event = parsePiLine(line);
312
+ if (!event) {
313
+ const trimmed = line.trim();
314
+ if (trimmed.length > 0)
315
+ plainLines.push(trimmed);
316
+ return;
317
+ }
318
+ if (event.kind === 'session' && event.sessionId) {
319
+ this.#sessionByThread.set(threadId, event.sessionId);
320
+ }
321
+ else if (event.kind === 'delta' && event.text) {
322
+ full += event.text;
323
+ this.emit({ type: 'delta', threadId, turnId, data: { text: event.text } });
324
+ }
325
+ else if (event.kind === 'thinking' && event.text) {
326
+ this.emit({ type: 'thinking', threadId, turnId, data: { text: event.text } });
327
+ }
328
+ else if (event.kind === 'tool_start' && event.tool) {
329
+ pendingTools.set(event.toolCallId ?? '', event.tool);
330
+ }
331
+ else if (event.kind === 'tool_end') {
332
+ const tool = pendingTools.get(event.toolCallId ?? '');
333
+ if (tool) {
334
+ pendingTools.delete(event.toolCallId ?? '');
335
+ this.emit({
336
+ type: 'block',
337
+ threadId,
338
+ turnId,
339
+ data: {
340
+ content: piToolBlock(tool, event.toolOutput ?? '', event.toolIsError === true),
341
+ },
342
+ });
343
+ }
344
+ }
345
+ else if (event.kind === 'final') {
346
+ if (event.text)
347
+ finalText = event.text;
348
+ if (event.tokens !== undefined)
349
+ tokens = event.tokens;
350
+ if (event.isError) {
351
+ errored = true;
352
+ if (event.errorText)
353
+ errorMsg = event.errorText;
354
+ }
355
+ }
356
+ else if (event.kind === 'end') {
357
+ finish();
358
+ }
359
+ });
360
+ child.on('error', (err) => {
361
+ reader.close();
362
+ this.#active.delete(turnId);
363
+ if (!completed) {
364
+ completed = true;
365
+ this.emit({
366
+ type: 'turn_error',
367
+ threadId,
368
+ turnId,
369
+ data: { text: `pi process error: ${err.message}` },
370
+ });
371
+ }
372
+ });
373
+ child.on('close', () => {
374
+ reader.close();
375
+ this.#active.delete(turnId);
376
+ finish();
377
+ });
378
+ return Promise.resolve();
379
+ }
380
+ cancelTurn(threadId, turnId) {
381
+ const run = this.#active.get(turnId);
382
+ if (run) {
383
+ run.child.kill();
384
+ this.#active.delete(turnId);
385
+ this.emit({ type: 'turn_aborted', threadId, turnId });
386
+ }
387
+ return Promise.resolve();
388
+ }
389
+ /**
390
+ * List the models pi reports via `pi --list-models` (account-aware: only
391
+ * providers the user has configured appear). The output is a table, parsed by
392
+ * {@link parsePiModelList}. Resolves to `[]` if the spawn fails or times out.
393
+ *
394
+ * Note: pi prints the `--list-models` table to STDERR, not stdout (verified
395
+ * against pi 0.79.1), so we accumulate BOTH streams. Without this the phone's
396
+ * model picker shows no models for the pi agent.
397
+ */
398
+ listModels() {
399
+ return new Promise((resolve) => {
400
+ let settled = false;
401
+ let output = '';
402
+ let child;
403
+ const finish = (models) => {
404
+ if (settled)
405
+ return;
406
+ settled = true;
407
+ clearTimeout(timer);
408
+ try {
409
+ child.kill();
410
+ }
411
+ catch {
412
+ /* already gone */
413
+ }
414
+ resolve(models);
415
+ };
416
+ try {
417
+ child = this.#spawn(this.#binaryPath, [...this.#prependArgs, '--list-models'], this.#defaultCwd);
418
+ }
419
+ catch {
420
+ resolve([]);
421
+ return;
422
+ }
423
+ const timer = setTimeout(() => finish([]), MODEL_LIST_TIMEOUT_MS);
424
+ // pi emits the table on stderr; read stdout too so we stay correct if a
425
+ // future version moves it. Parse the combined output on close.
426
+ const collect = (chunk) => {
427
+ output += String(chunk);
428
+ };
429
+ child.stdout.on('data', collect);
430
+ child.stderr?.on('data', collect);
431
+ child.on('error', () => finish([]));
432
+ child.on('close', () => {
433
+ const models = parsePiModelList(output, this.#defaultModel);
434
+ // Cache each model's context window so `sendTurn` can emit `usage`
435
+ // with a window (→ percentage on the phone) without re-listing.
436
+ for (const m of models) {
437
+ if (m.contextWindow !== undefined) {
438
+ this.#contextWindowByModel.set(m.id, m.contextWindow);
439
+ }
440
+ }
441
+ finish(models);
442
+ });
443
+ });
444
+ }
445
+ }
446
+ function extractAssistantText(content) {
447
+ if (!Array.isArray(content))
448
+ return '';
449
+ let text = '';
450
+ for (const block of content) {
451
+ if (isRecord(block) && block['type'] === 'text' && typeof block['text'] === 'string') {
452
+ text += block['text'];
453
+ }
454
+ }
455
+ return text;
456
+ }
457
+ function plainText(lines) {
458
+ const joined = lines.join('\n').trim();
459
+ return joined.length > 0 ? joined : undefined;
460
+ }
461
+ function isRecord(value) {
462
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
463
+ }
464
+ function errorMessage(err) {
465
+ return err instanceof Error ? err.message : String(err);
466
+ }
467
+ //# sourceMappingURL=pi-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pi-adapter.js","sourceRoot":"","sources":["../../../src/adapters/pi-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /** A pi tool invocation (paired `tool_execution_start` args + `_end` result). */
2
+ export interface PiToolUse {
3
+ id: string;
4
+ name: string;
5
+ input: Record<string, unknown>;
6
+ }
7
+ /** Extracts the text of a pi tool `result` (`{ content:[{type:'text',text}] }`). */
8
+ export declare function piResultText(result: unknown): string;
9
+ /** Builds the MessageContent JSON for a paired pi tool execution. */
10
+ export declare function piToolBlock(tool: PiToolUse, output: string, isError: boolean): Record<string, unknown>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Maps pi tool executions onto structured MessageContent blocks.
3
+ *
4
+ * pi (`-p --mode json`) reports tools as top-level `tool_execution_start`
5
+ * (`{ toolCallId, toolName, args }`) and `tool_execution_end`
6
+ * (`{ toolCallId, toolName, result:{ content:[{type:'text',text}] }, isError }`)
7
+ * events; the adapter pairs them by `toolCallId`. Tool/arg names verified live
8
+ * against pi 0.79.1: `bash`→`command`, `write`→`path`+`content`, `read`→`path`.
9
+ */
10
+ import { commandBlock, editDiffBlock, extractPlanSteps, multiEditDiffBlock, planBlock, toolBlock, writeDiffBlock, } from './content-blocks.js';
11
+ function isRecord(value) {
12
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
13
+ }
14
+ function str(value) {
15
+ return typeof value === 'string' ? value : '';
16
+ }
17
+ /** Extracts the text of a pi tool `result` (`{ content:[{type:'text',text}] }`). */
18
+ export function piResultText(result) {
19
+ if (typeof result === 'string')
20
+ return result;
21
+ if (isRecord(result) && Array.isArray(result['content'])) {
22
+ let text = '';
23
+ for (const block of result['content']) {
24
+ if (isRecord(block) && block['type'] === 'text' && typeof block['text'] === 'string') {
25
+ text += block['text'];
26
+ }
27
+ }
28
+ return text;
29
+ }
30
+ return '';
31
+ }
32
+ /** Builds the MessageContent JSON for a paired pi tool execution. */
33
+ export function piToolBlock(tool, output, isError) {
34
+ const path = str(tool.input['path']) || str(tool.input['file_path']);
35
+ switch (tool.name) {
36
+ case 'bash':
37
+ return commandBlock(str(tool.input['command']), output, isError);
38
+ case 'edit':
39
+ case 'str_replace': {
40
+ // pi's edit tool: `{ path, edits: [{ oldText, newText }] }` (verified live
41
+ // against pi 0.79.1); tolerant of single old/new string shapes too.
42
+ const raw = tool.input['edits'];
43
+ if (Array.isArray(raw)) {
44
+ const edits = raw.filter(isRecord).map((e) => ({
45
+ old: str(e['oldText']) || str(e['old_string']) || str(e['old_str']),
46
+ new: str(e['newText']) || str(e['new_string']) || str(e['new_str']),
47
+ }));
48
+ return multiEditDiffBlock(path, edits);
49
+ }
50
+ return editDiffBlock(path, str(tool.input['oldText']) || str(tool.input['old_string']) || str(tool.input['old_str']), str(tool.input['newText']) || str(tool.input['new_string']) || str(tool.input['new_str']));
51
+ }
52
+ case 'write':
53
+ case 'create':
54
+ return writeDiffBlock(path, str(tool.input['content']));
55
+ // pi's plan/to-do tool. FOR-DEV: tool name + input shape ASSUMED
56
+ // (`todo`/`update_plan`/`plan`) — verify against a real pi plan turn; a
57
+ // mismatch yields no steps → falls back to a generic tool block.
58
+ case 'todo':
59
+ case 'todowrite':
60
+ case 'update_plan':
61
+ case 'plan': {
62
+ const steps = extractPlanSteps(tool.input);
63
+ if (steps.length > 0) {
64
+ return planBlock(steps, str(tool.input['explanation']) || str(tool.input['title']));
65
+ }
66
+ return toolBlock(tool.name, tool.id, tool.input, output, isError);
67
+ }
68
+ default:
69
+ return toolBlock(tool.name, tool.id, tool.input, output, isError);
70
+ }
71
+ }
72
+ //# sourceMappingURL=pi-tools.js.map