@earendil-works/pi-coding-agent 0.85.0 → 0.85.1

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 (271) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +0 -2
  3. package/dist/bun/cli.d.ts +3 -1
  4. package/dist/bun/cli.d.ts.map +1 -1
  5. package/dist/bun/cli.js +3 -12
  6. package/dist/bun/cli.js.map +1 -1
  7. package/dist/bun/sandbox-env-setup.d.ts +2 -0
  8. package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
  9. package/dist/bun/sandbox-env-setup.js +4 -0
  10. package/dist/bun/sandbox-env-setup.js.map +1 -0
  11. package/dist/bundle/chunks/{anthropic-messages-QAQLEQIY.js → anthropic-messages-VWZZOSJQ.js} +1 -1
  12. package/dist/bundle/chunks/{azure-openai-responses-Q7MJBRE6.js → azure-openai-responses-BJLAM6CD.js} +1 -1
  13. package/dist/bundle/chunks/{chunk-R7UUJ4C2.js → chunk-CLNPYIDP.js} +1 -1
  14. package/dist/bundle/chunks/chunk-JVUZSMYM.js +1547 -0
  15. package/dist/bundle/chunks/{chunk-2KVJKXS2.js → chunk-U6ZMQKGD.js} +1 -1
  16. package/dist/bundle/chunks/github-copilot.js +1 -1
  17. package/dist/bundle/chunks/{google-generative-ai-BSMTYDAM.js → google-generative-ai-Q2K7FBDI.js} +1 -1
  18. package/dist/bundle/chunks/{google-vertex-5C3HASOJ.js → google-vertex-7UJBF4S7.js} +1 -1
  19. package/dist/bundle/chunks/{node-EM5FIVUN.js → node-KG362ECQ.js} +1 -1
  20. package/dist/bundle/chunks/{openai-codex-responses-YJOO52RW.js → openai-codex-responses-R6VYZTVY.js} +1 -1
  21. package/dist/bundle/chunks/{openai-completions-QOT3QX7D.js → openai-completions-EKZT2IH2.js} +1 -1
  22. package/dist/bundle/chunks/openai-responses-TFDINO6W.js +2 -0
  23. package/dist/bundle/chunks/{pi-messages-EGZIFQGG.js → pi-messages-PML4SPVJ.js} +1 -1
  24. package/dist/bundle/cli.js +1 -1
  25. package/dist/bundle/index.js +1 -1
  26. package/dist/bundle/rpc-entry.js +1 -1
  27. package/dist/cli/args.d.ts.map +1 -1
  28. package/dist/cli/args.js +0 -2
  29. package/dist/cli/args.js.map +1 -1
  30. package/dist/cli/setup.d.ts +2 -0
  31. package/dist/cli/setup.d.ts.map +1 -0
  32. package/dist/cli/setup.js +12 -0
  33. package/dist/cli/setup.js.map +1 -0
  34. package/dist/cli.d.ts.map +1 -1
  35. package/dist/cli.js +3 -25
  36. package/dist/cli.js.map +1 -1
  37. package/dist/core/keybindings.d.ts +5 -0
  38. package/dist/core/keybindings.d.ts.map +1 -1
  39. package/dist/core/keybindings.js +4 -0
  40. package/dist/core/keybindings.js.map +1 -1
  41. package/dist/main.d.ts.map +1 -1
  42. package/dist/main.js +0 -122
  43. package/dist/main.js.map +1 -1
  44. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  45. package/dist/modes/interactive/components/model-selector.js +5 -5
  46. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  47. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  48. package/dist/modes/interactive/components/scoped-models-selector.js +8 -8
  49. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  50. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  51. package/dist/modes/interactive/components/thinking-selector.js +4 -4
  52. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  53. package/docs/containerization.md +45 -0
  54. package/docs/development.md +19 -0
  55. package/docs/environment-variables.md +2 -2
  56. package/docs/keybindings.md +2 -1
  57. package/docs/models.md +1 -1
  58. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  59. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  60. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  61. package/examples/extensions/gondolin/package-lock.json +2 -2
  62. package/examples/extensions/gondolin/package.json +1 -1
  63. package/examples/extensions/sandbox/package-lock.json +2 -2
  64. package/examples/extensions/sandbox/package.json +1 -1
  65. package/examples/extensions/with-deps/package-lock.json +2 -2
  66. package/examples/extensions/with-deps/package.json +1 -1
  67. package/npm-shrinkwrap.json +20 -46
  68. package/package.json +13 -12
  69. package/dist/bundle/chunks/chunk-EQ6DR6XK.js +0 -5
  70. package/dist/bundle/chunks/chunk-LZKJTKCT.js +0 -2
  71. package/dist/bundle/chunks/chunk-WBE4J4AU.js +0 -9
  72. package/dist/bundle/chunks/chunk-WZB2R5YO.js +0 -1558
  73. package/dist/bundle/chunks/openai-responses-U7LNPQN4.js +0 -2
  74. package/dist/bundle/client.js +0 -2
  75. package/dist/bundle/coordinator.js +0 -3
  76. package/dist/cli/experimental/cli.d.ts +0 -10
  77. package/dist/cli/experimental/cli.d.ts.map +0 -1
  78. package/dist/cli/experimental/cli.js +0 -9
  79. package/dist/cli/experimental/cli.js.map +0 -1
  80. package/dist/cli/experimental/command-options.d.ts +0 -28
  81. package/dist/cli/experimental/command-options.d.ts.map +0 -1
  82. package/dist/cli/experimental/command-options.js +0 -84
  83. package/dist/cli/experimental/command-options.js.map +0 -1
  84. package/dist/cli/experimental/command.d.ts +0 -70
  85. package/dist/cli/experimental/command.d.ts.map +0 -1
  86. package/dist/cli/experimental/command.js +0 -144
  87. package/dist/cli/experimental/command.js.map +0 -1
  88. package/dist/cli/experimental/commands/client.d.ts +0 -19
  89. package/dist/cli/experimental/commands/client.d.ts.map +0 -1
  90. package/dist/cli/experimental/commands/client.js +0 -63
  91. package/dist/cli/experimental/commands/client.js.map +0 -1
  92. package/dist/cli/experimental/commands/server.d.ts +0 -17
  93. package/dist/cli/experimental/commands/server.d.ts.map +0 -1
  94. package/dist/cli/experimental/commands/server.js +0 -44
  95. package/dist/cli/experimental/commands/server.js.map +0 -1
  96. package/dist/client/index.d.ts +0 -2
  97. package/dist/client/index.d.ts.map +0 -1
  98. package/dist/client/index.js +0 -2
  99. package/dist/client/index.js.map +0 -1
  100. package/dist/experimental/client-runtime.d.ts +0 -43
  101. package/dist/experimental/client-runtime.d.ts.map +0 -1
  102. package/dist/experimental/client-runtime.js +0 -183
  103. package/dist/experimental/client-runtime.js.map +0 -1
  104. package/dist/experimental/client-tui-chat.d.ts +0 -14
  105. package/dist/experimental/client-tui-chat.d.ts.map +0 -1
  106. package/dist/experimental/client-tui-chat.js +0 -171
  107. package/dist/experimental/client-tui-chat.js.map +0 -1
  108. package/dist/experimental/client-tui.d.ts +0 -37
  109. package/dist/experimental/client-tui.d.ts.map +0 -1
  110. package/dist/experimental/client-tui.js +0 -702
  111. package/dist/experimental/client-tui.js.map +0 -1
  112. package/dist/experimental/client.d.ts +0 -25
  113. package/dist/experimental/client.d.ts.map +0 -1
  114. package/dist/experimental/client.js +0 -99
  115. package/dist/experimental/client.js.map +0 -1
  116. package/dist/experimental/coordinator-entry.d.ts +0 -3
  117. package/dist/experimental/coordinator-entry.d.ts.map +0 -1
  118. package/dist/experimental/coordinator-entry.js +0 -11
  119. package/dist/experimental/coordinator-entry.js.map +0 -1
  120. package/dist/experimental/coordinator.d.ts +0 -38
  121. package/dist/experimental/coordinator.d.ts.map +0 -1
  122. package/dist/experimental/coordinator.js +0 -570
  123. package/dist/experimental/coordinator.js.map +0 -1
  124. package/dist/experimental/mini/main.d.ts +0 -7
  125. package/dist/experimental/mini/main.d.ts.map +0 -1
  126. package/dist/experimental/mini/main.js +0 -21
  127. package/dist/experimental/mini/main.js.map +0 -1
  128. package/dist/experimental/mini/server/entry.d.ts +0 -3
  129. package/dist/experimental/mini/server/entry.d.ts.map +0 -1
  130. package/dist/experimental/mini/server/entry.js +0 -11
  131. package/dist/experimental/mini/server/entry.js.map +0 -1
  132. package/dist/experimental/mini/server/run.d.ts +0 -13
  133. package/dist/experimental/mini/server/run.d.ts.map +0 -1
  134. package/dist/experimental/mini/server/run.js +0 -150
  135. package/dist/experimental/mini/server/run.js.map +0 -1
  136. package/dist/experimental/mini/shared/protocol.d.ts +0 -127
  137. package/dist/experimental/mini/shared/protocol.d.ts.map +0 -1
  138. package/dist/experimental/mini/shared/protocol.js +0 -13
  139. package/dist/experimental/mini/shared/protocol.js.map +0 -1
  140. package/dist/experimental/mini/shared/rpc.d.ts +0 -49
  141. package/dist/experimental/mini/shared/rpc.d.ts.map +0 -1
  142. package/dist/experimental/mini/shared/rpc.js +0 -171
  143. package/dist/experimental/mini/shared/rpc.js.map +0 -1
  144. package/dist/experimental/mini/shared/transport.d.ts +0 -35
  145. package/dist/experimental/mini/shared/transport.d.ts.map +0 -1
  146. package/dist/experimental/mini/shared/transport.js +0 -94
  147. package/dist/experimental/mini/shared/transport.js.map +0 -1
  148. package/dist/experimental/mini/tui/run.d.ts +0 -9
  149. package/dist/experimental/mini/tui/run.d.ts.map +0 -1
  150. package/dist/experimental/mini/tui/run.js +0 -62
  151. package/dist/experimental/mini/tui/run.js.map +0 -1
  152. package/dist/experimental/mini/tui/session.d.ts +0 -26
  153. package/dist/experimental/mini/tui/session.d.ts.map +0 -1
  154. package/dist/experimental/mini/tui/session.js +0 -94
  155. package/dist/experimental/mini/tui/session.js.map +0 -1
  156. package/dist/experimental/mini/tui/view.d.ts +0 -10
  157. package/dist/experimental/mini/tui/view.d.ts.map +0 -1
  158. package/dist/experimental/mini/tui/view.js +0 -459
  159. package/dist/experimental/mini/tui/view.js.map +0 -1
  160. package/dist/experimental/mini/worker/entry.d.ts +0 -3
  161. package/dist/experimental/mini/worker/entry.d.ts.map +0 -1
  162. package/dist/experimental/mini/worker/entry.js +0 -10
  163. package/dist/experimental/mini/worker/entry.js.map +0 -1
  164. package/dist/experimental/mini/worker/lane-service.d.ts +0 -44
  165. package/dist/experimental/mini/worker/lane-service.d.ts.map +0 -1
  166. package/dist/experimental/mini/worker/lane-service.js +0 -97
  167. package/dist/experimental/mini/worker/lane-service.js.map +0 -1
  168. package/dist/experimental/mini/worker/models-service.d.ts +0 -19
  169. package/dist/experimental/mini/worker/models-service.d.ts.map +0 -1
  170. package/dist/experimental/mini/worker/models-service.js +0 -136
  171. package/dist/experimental/mini/worker/models-service.js.map +0 -1
  172. package/dist/experimental/mini/worker/run.d.ts +0 -14
  173. package/dist/experimental/mini/worker/run.d.ts.map +0 -1
  174. package/dist/experimental/mini/worker/run.js +0 -88
  175. package/dist/experimental/mini/worker/run.js.map +0 -1
  176. package/dist/experimental/plugin.d.ts +0 -4
  177. package/dist/experimental/plugin.d.ts.map +0 -1
  178. package/dist/experimental/plugin.js +0 -4
  179. package/dist/experimental/plugin.js.map +0 -1
  180. package/dist/experimental/plugins/bundled.d.ts +0 -7
  181. package/dist/experimental/plugins/bundled.d.ts.map +0 -1
  182. package/dist/experimental/plugins/bundled.js +0 -48
  183. package/dist/experimental/plugins/bundled.js.map +0 -1
  184. package/dist/experimental/plugins/package.d.ts +0 -18
  185. package/dist/experimental/plugins/package.d.ts.map +0 -1
  186. package/dist/experimental/plugins/package.js +0 -113
  187. package/dist/experimental/plugins/package.js.map +0 -1
  188. package/dist/experimental/process.d.ts +0 -20
  189. package/dist/experimental/process.d.ts.map +0 -1
  190. package/dist/experimental/process.js +0 -85
  191. package/dist/experimental/process.js.map +0 -1
  192. package/dist/experimental/radius-auth.d.ts +0 -17
  193. package/dist/experimental/radius-auth.d.ts.map +0 -1
  194. package/dist/experimental/radius-auth.js +0 -52
  195. package/dist/experimental/radius-auth.js.map +0 -1
  196. package/dist/experimental/radius-relay.d.ts +0 -90
  197. package/dist/experimental/radius-relay.d.ts.map +0 -1
  198. package/dist/experimental/radius-relay.js +0 -582
  199. package/dist/experimental/radius-relay.js.map +0 -1
  200. package/dist/experimental/server.d.ts +0 -75
  201. package/dist/experimental/server.d.ts.map +0 -1
  202. package/dist/experimental/server.js +0 -682
  203. package/dist/experimental/server.js.map +0 -1
  204. package/dist/experimental/services/agent-controller-provider.d.ts +0 -4
  205. package/dist/experimental/services/agent-controller-provider.d.ts.map +0 -1
  206. package/dist/experimental/services/agent-controller-provider.js +0 -84
  207. package/dist/experimental/services/agent-controller-provider.js.map +0 -1
  208. package/dist/experimental/services/agent-controller.d.ts +0 -57
  209. package/dist/experimental/services/agent-controller.d.ts.map +0 -1
  210. package/dist/experimental/services/agent-controller.js +0 -3
  211. package/dist/experimental/services/agent-controller.js.map +0 -1
  212. package/dist/experimental/services/connection.d.ts +0 -40
  213. package/dist/experimental/services/connection.d.ts.map +0 -1
  214. package/dist/experimental/services/connection.js +0 -300
  215. package/dist/experimental/services/connection.js.map +0 -1
  216. package/dist/experimental/services/models-provider.d.ts +0 -16
  217. package/dist/experimental/services/models-provider.d.ts.map +0 -1
  218. package/dist/experimental/services/models-provider.js +0 -116
  219. package/dist/experimental/services/models-provider.js.map +0 -1
  220. package/dist/experimental/services/models.d.ts +0 -36
  221. package/dist/experimental/services/models.d.ts.map +0 -1
  222. package/dist/experimental/services/models.js +0 -3
  223. package/dist/experimental/services/models.js.map +0 -1
  224. package/dist/experimental/services/plugins.d.ts +0 -16
  225. package/dist/experimental/services/plugins.d.ts.map +0 -1
  226. package/dist/experimental/services/plugins.js +0 -4
  227. package/dist/experimental/services/plugins.js.map +0 -1
  228. package/dist/experimental/services/presentation-ui.d.ts +0 -13
  229. package/dist/experimental/services/presentation-ui.d.ts.map +0 -1
  230. package/dist/experimental/services/presentation-ui.js +0 -3
  231. package/dist/experimental/services/presentation-ui.js.map +0 -1
  232. package/dist/experimental/services/server.d.ts +0 -19
  233. package/dist/experimental/services/server.d.ts.map +0 -1
  234. package/dist/experimental/services/server.js +0 -104
  235. package/dist/experimental/services/server.js.map +0 -1
  236. package/dist/experimental/services/sessions.d.ts +0 -28
  237. package/dist/experimental/services/sessions.d.ts.map +0 -1
  238. package/dist/experimental/services/sessions.js +0 -4
  239. package/dist/experimental/services/sessions.js.map +0 -1
  240. package/dist/experimental/services/slash-commands-provider.d.ts +0 -14
  241. package/dist/experimental/services/slash-commands-provider.d.ts.map +0 -1
  242. package/dist/experimental/services/slash-commands-provider.js +0 -200
  243. package/dist/experimental/services/slash-commands-provider.js.map +0 -1
  244. package/dist/experimental/services/slash-commands.d.ts +0 -24
  245. package/dist/experimental/services/slash-commands.d.ts.map +0 -1
  246. package/dist/experimental/services/slash-commands.js +0 -3
  247. package/dist/experimental/services/slash-commands.js.map +0 -1
  248. package/dist/experimental/services/transcript-provider.d.ts +0 -12
  249. package/dist/experimental/services/transcript-provider.d.ts.map +0 -1
  250. package/dist/experimental/services/transcript-provider.js +0 -109
  251. package/dist/experimental/services/transcript-provider.js.map +0 -1
  252. package/dist/experimental/services/transcript.d.ts +0 -13
  253. package/dist/experimental/services/transcript.d.ts.map +0 -1
  254. package/dist/experimental/services/transcript.js +0 -3
  255. package/dist/experimental/services/transcript.js.map +0 -1
  256. package/dist/experimental/services/worker.d.ts +0 -28
  257. package/dist/experimental/services/worker.d.ts.map +0 -1
  258. package/dist/experimental/services/worker.js +0 -107
  259. package/dist/experimental/services/worker.js.map +0 -1
  260. package/dist/experimental/session-worker-manager.d.ts +0 -24
  261. package/dist/experimental/session-worker-manager.d.ts.map +0 -1
  262. package/dist/experimental/session-worker-manager.js +0 -691
  263. package/dist/experimental/session-worker-manager.js.map +0 -1
  264. package/dist/experimental/session-worker.d.ts +0 -188
  265. package/dist/experimental/session-worker.d.ts.map +0 -1
  266. package/dist/experimental/session-worker.js +0 -785
  267. package/dist/experimental/session-worker.js.map +0 -1
  268. package/dist/experimental/source-resolver.d.ts +0 -2
  269. package/dist/experimental/source-resolver.d.ts.map +0 -1
  270. package/dist/experimental/source-resolver.js +0 -71
  271. package/dist/experimental/source-resolver.js.map +0 -1
@@ -19,6 +19,19 @@ Run from source:
19
19
 
20
20
  The script can be run from any directory. Pi keeps the caller's current working directory.
21
21
 
22
+ ### Experimental remote harness
23
+
24
+ The remote harness server/client integration is development-only. Run it from the repository with:
25
+
26
+ ```bash
27
+ PI_EXPERIMENTAL=1 ./pi-test.sh server
28
+ PI_EXPERIMENTAL=1 ./pi-test.sh client
29
+ ```
30
+
31
+ `PI_SERVER_DIR` overrides the server profile and socket directory (default: `~/.pi/server`). `PI_SERVER_ID` selects the logical server ID when `--server-id` is omitted.
32
+
33
+ The `client` and `experimental/plugin` package subpaths resolve only under the `source` condition in a checkout. Their implementations and the server/client commands are excluded from npm packages and standalone binaries. `pi-client`, `pi-protocol`, and `pi-server` are development dependencies of coding-agent, not runtime dependencies. The local SDK and stdio RPC API are unchanged.
34
+
22
35
  ## Forking / Rebranding
23
36
 
24
37
  Configure via `package.json`:
@@ -60,6 +73,12 @@ npm test # Run all tests
60
73
  npm test -- test/specific.test.ts # Run specific test
61
74
  ```
62
75
 
76
+ ### Published package smoke test
77
+
78
+ After building, run `npm run check:package-install`. It packs the public packages and installs only coding-agent as a direct dependency in a temporary directory outside the repository. Local tarball overrides select declared transitive dependencies without installing development-only packages. The check verifies SDK imports and CLI startup without credentials or model requests.
79
+
80
+ `npm run check` also checks runtime dependency declarations and rejects excluded development sources pulled into a package's build through imports.
81
+
63
82
  ## Project Structure
64
83
 
65
84
  ```
@@ -81,8 +81,6 @@ These variables are read by Pi itself:
81
81
  | `PI_CODING_AGENT_DIR` | Override the config directory; default is `~/.pi/agent` |
82
82
  | `PI_CODING_AGENT_SESSION_DIR` | Override session storage; overridden by `--session-dir` |
83
83
  | `PI_PACKAGE_DIR` | Override the package directory, useful for Nix/Guix store paths |
84
- | `PI_SERVER_DIR` | Override the experimental server profile and socket directory; default is `~/.pi/server` |
85
- | `PI_SERVER_ID` | Select the logical experimental server ID when `--server-id` is omitted |
86
84
  | `PI_OFFLINE` | Disable startup network operations, including update checks, package updates, and install/update telemetry |
87
85
  | `PI_SKIP_VERSION_CHECK` | Disable the `pi.dev` latest-version request |
88
86
  | `PI_TELEMETRY` | Override install/update telemetry and provider attribution headers: `1`/`true`/`yes` or `0`/`false`/`no` |
@@ -97,3 +95,5 @@ These variables are read by Pi itself:
97
95
  | `HTTP_PROXY`, `HTTPS_PROXY` | Proxy outbound HTTP requests |
98
96
 
99
97
  Provider credentials such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and cloud-provider configuration are listed in [Providers](providers.md#environment-variables-or-auth-file).
98
+
99
+ `PI_SERVER_DIR` and `PI_SERVER_ID` apply only to the source-only [experimental remote harness](development.md#experimental-remote-harness), not distributed builds.
@@ -151,7 +151,9 @@ This routing remains configurable through the ordinary action bindings. For exam
151
151
  | `app.model.select` | `ctrl+l` | Open model selector |
152
152
  | `app.model.cycleForward` | `ctrl+p` | Cycle to next model |
153
153
  | `app.model.cycleBackward` | `shift+ctrl+p` (`alt+p` on Windows and WSL) | Cycle to previous model |
154
+ | `app.models.save` | `ctrl+s` | Save the selected default model or scoped model configuration to settings |
154
155
  | `app.thinking.cycle` | `shift+tab` | Cycle thinking level |
156
+ | `app.thinking.save` | `ctrl+s` | Save current thinking level to settings |
155
157
  | `app.thinking.toggle` | `ctrl+t` | Collapse or expand thinking blocks |
156
158
 
157
159
  ### Display and Message Queue
@@ -185,7 +187,6 @@ Used inside the scoped models selector (opened via `/scoped-models`).
185
187
 
186
188
  | Keybinding id | Default | Description |
187
189
  |--------|---------|-------------|
188
- | `app.models.save` | `ctrl+s` | Save current model selection to settings |
189
190
  | `app.models.enableAll` | `ctrl+a` | Enable all models (or all matching the current search) |
190
191
  | `app.models.clearAll` | `ctrl+x` | Clear all models (or all matching the current search) |
191
192
  | `app.models.toggleProvider` | `ctrl+p` | Toggle all models for the current provider |
package/docs/models.md CHANGED
@@ -482,7 +482,7 @@ For providers with partial OpenAI compatibility, use the `compat` field.
482
482
  | `supportsStrictMode` | Whether the provider accepts strict JSON-schema function tool definitions. Defaults depend on the API; built-in OpenAI models carry explicit capability metadata. |
483
483
  | `supportsOpenAIGrammarTools` | Whether OpenAI-compatible APIs emit custom Lark/regex grammar tools. When `false`, grammar-constrained tools fall back to normal function tools. Default: `false`; the built-in model catalog enables it for GPT-5+ models on OpenAI, OpenAI Codex, Azure OpenAI, GitHub Copilot, opencode, and Cloudflare AI Gateway. |
484
484
  | `deferredToolsMode` | Use provider-specific deferred tool serialization. Currently only `"kimi"` is supported for Kimi's OpenAI-compatible Chat Completions format. |
485
- | `supportsLongCacheRetention` | Whether the provider accepts long cache retention when cache retention is `long`: `prompt_cache_retention: "24h"` for OpenAI prompt caching, or `cache_control.ttl: "1h"` when `cacheControlFormat` is `anthropic`. Default: `true`. |
485
+ | `supportsLongCacheRetention` | Whether the provider accepts long cache retention when cache retention is `long`: `prompt_cache_options.ttl: "30m"` for GPT-5.6+ Responses models, `prompt_cache_retention: "24h"` for earlier OpenAI models, or `cache_control.ttl: "1h"` when `cacheControlFormat` is `anthropic`. Default: `true`. |
486
486
  | `openRouterRouting` | OpenRouter provider routing preferences. This object is sent as-is in the `provider` field of the [OpenRouter API request](https://openrouter.ai/docs/guides/routing/provider-selection). |
487
487
  | `vercelGatewayRouting` | Vercel AI Gateway routing config for provider selection (`only`, `order`) |
488
488
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider",
3
- "version": "0.85.0",
3
+ "version": "0.85.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-custom-provider",
9
- "version": "0.85.0",
9
+ "version": "0.85.1",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sdk": "^0.52.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-anthropic",
3
3
  "private": true,
4
- "version": "0.85.0",
4
+ "version": "0.85.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-custom-provider-gitlab-duo",
3
3
  "private": true,
4
- "version": "0.85.0",
4
+ "version": "0.85.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
- "version": "0.85.0",
3
+ "version": "0.85.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-gondolin",
9
- "version": "0.85.0",
9
+ "version": "0.85.1",
10
10
  "dependencies": {
11
11
  "@earendil-works/gondolin": "0.12.0"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-gondolin",
3
3
  "private": true,
4
- "version": "0.85.0",
4
+ "version": "0.85.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
- "version": "1.15.0",
3
+ "version": "1.15.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-sandbox",
9
- "version": "1.15.0",
9
+ "version": "1.15.1",
10
10
  "dependencies": {
11
11
  "@anthropic-ai/sandbox-runtime": "^0.0.26"
12
12
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-sandbox",
3
3
  "private": true,
4
- "version": "1.15.0",
4
+ "version": "1.15.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
- "version": "0.85.0",
3
+ "version": "0.85.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "pi-extension-with-deps",
9
- "version": "0.85.0",
9
+ "version": "0.85.1",
10
10
  "dependencies": {
11
11
  "ms": "^2.1.3"
12
12
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-extension-with-deps",
3
3
  "private": true,
4
- "version": "0.85.0",
4
+ "version": "0.85.1",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "clean": "echo 'nothing to clean'",
@@ -1,20 +1,18 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.85.0",
3
+ "version": "0.85.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@earendil-works/pi-coding-agent",
9
- "version": "0.85.0",
9
+ "version": "0.85.1",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
- "@earendil-works/chord": "^0.85.0",
13
- "@earendil-works/pi-agent-core": "^0.85.0",
14
- "@earendil-works/pi-ai": "^0.85.0",
15
- "@earendil-works/pi-client": "^0.85.0",
16
- "@earendil-works/pi-protocol": "^0.85.0",
17
- "@earendil-works/pi-tui": "^0.85.0",
12
+ "@earendil-works/chord": "^0.85.1",
13
+ "@earendil-works/pi-agent-core": "^0.85.1",
14
+ "@earendil-works/pi-ai": "^0.85.1",
15
+ "@earendil-works/pi-tui": "^0.85.1",
18
16
  "@silvia-odwyer/photon-node": "0.3.4",
19
17
  "chalk": "5.6.2",
20
18
  "cross-spawn": "7.0.6",
@@ -478,8 +476,8 @@
478
476
  }
479
477
  },
480
478
  "node_modules/@earendil-works/chord": {
481
- "version": "0.85.0",
482
- "resolved": "https://registry.npmjs.org/@earendil-works/chord/-/chord-0.85.0.tgz",
479
+ "version": "0.85.1",
480
+ "resolved": "https://registry.npmjs.org/@earendil-works/chord/-/chord-0.85.1.tgz",
483
481
  "license": "MIT",
484
482
  "dependencies": {
485
483
  "esbuild": "0.28.1"
@@ -489,13 +487,13 @@
489
487
  }
490
488
  },
491
489
  "node_modules/@earendil-works/pi-agent-core": {
492
- "version": "0.85.0",
493
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.85.0.tgz",
490
+ "version": "0.85.1",
491
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-agent-core/-/pi-agent-core-0.85.1.tgz",
494
492
  "license": "MIT",
495
493
  "dependencies": {
496
- "@earendil-works/chord": "^0.85.0",
497
- "@earendil-works/pi-ai": "^0.85.0",
498
- "@earendil-works/pi-telemetry": "^0.85.0",
494
+ "@earendil-works/chord": "^0.85.1",
495
+ "@earendil-works/pi-ai": "^0.85.1",
496
+ "@earendil-works/pi-telemetry": "^0.85.1",
499
497
  "diff": "8.0.4",
500
498
  "ignore": "7.0.5",
501
499
  "typebox": "1.3.7",
@@ -506,13 +504,13 @@
506
504
  }
507
505
  },
508
506
  "node_modules/@earendil-works/pi-ai": {
509
- "version": "0.85.0",
510
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.85.0.tgz",
507
+ "version": "0.85.1",
508
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-ai/-/pi-ai-0.85.1.tgz",
511
509
  "license": "MIT",
512
510
  "dependencies": {
513
511
  "@anthropic-ai/sdk": "0.123.0",
514
512
  "@aws-sdk/client-bedrock-runtime": "3.1048.0",
515
- "@earendil-works/pi-telemetry": "^0.85.0",
513
+ "@earendil-works/pi-telemetry": "^0.85.1",
516
514
  "@google/genai": "1.52.0",
517
515
  "@smithy/node-http-handler": "4.7.3",
518
516
  "http-proxy-agent": "7.0.2",
@@ -528,41 +526,17 @@
528
526
  "node": ">=22.19.0"
529
527
  }
530
528
  },
531
- "node_modules/@earendil-works/pi-client": {
532
- "version": "0.85.0",
533
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-client/-/pi-client-0.85.0.tgz",
534
- "license": "MIT",
535
- "dependencies": {
536
- "@earendil-works/chord": "^0.85.0",
537
- "@earendil-works/pi-protocol": "^0.85.0"
538
- },
539
- "engines": {
540
- "node": ">=22.19.0"
541
- }
542
- },
543
- "node_modules/@earendil-works/pi-protocol": {
544
- "version": "0.85.0",
545
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-protocol/-/pi-protocol-0.85.0.tgz",
546
- "license": "MIT",
547
- "dependencies": {
548
- "@earendil-works/chord": "^0.85.0",
549
- "typebox": "1.3.7"
550
- },
551
- "engines": {
552
- "node": ">=22.19.0"
553
- }
554
- },
555
529
  "node_modules/@earendil-works/pi-telemetry": {
556
- "version": "0.85.0",
557
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-telemetry/-/pi-telemetry-0.85.0.tgz",
530
+ "version": "0.85.1",
531
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-telemetry/-/pi-telemetry-0.85.1.tgz",
558
532
  "license": "MIT",
559
533
  "engines": {
560
534
  "node": ">=22.19.0"
561
535
  }
562
536
  },
563
537
  "node_modules/@earendil-works/pi-tui": {
564
- "version": "0.85.0",
565
- "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.85.0.tgz",
538
+ "version": "0.85.1",
539
+ "resolved": "https://registry.npmjs.org/@earendil-works/pi-tui/-/pi-tui-0.85.1.tgz",
566
540
  "license": "MIT",
567
541
  "dependencies": {
568
542
  "get-east-asian-width": "1.6.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@earendil-works/pi-coding-agent",
3
- "version": "0.85.0",
3
+ "version": "0.85.1",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "piConfig": {
@@ -20,17 +20,17 @@
20
20
  "import": "./dist/bundle/rpc-entry.js"
21
21
  },
22
22
  "./client": {
23
- "types": "./dist/client/index.d.ts",
24
- "import": "./dist/client/index.js"
23
+ "source": "./src/client/index.ts"
25
24
  },
26
25
  "./experimental/plugin": {
27
- "source": "./src/experimental/plugin.ts",
28
- "types": "./dist/experimental/plugin.d.ts",
29
- "import": "./dist/experimental/plugin.js"
26
+ "source": "./src/experimental/plugin.ts"
30
27
  }
31
28
  },
32
29
  "files": [
33
30
  "dist",
31
+ "!dist/client",
32
+ "!dist/experimental",
33
+ "!dist/cli/experimental",
34
34
  "docs",
35
35
  "examples",
36
36
  "containerization.md",
@@ -49,12 +49,10 @@
49
49
  "prepublishOnly": "npm run clean && npm run build && npm run shrinkwrap"
50
50
  },
51
51
  "dependencies": {
52
- "@earendil-works/chord": "^0.85.0",
53
- "@earendil-works/pi-agent-core": "^0.85.0",
54
- "@earendil-works/pi-ai": "^0.85.0",
55
- "@earendil-works/pi-client": "^0.85.0",
56
- "@earendil-works/pi-protocol": "^0.85.0",
57
- "@earendil-works/pi-tui": "^0.85.0",
52
+ "@earendil-works/chord": "^0.85.1",
53
+ "@earendil-works/pi-agent-core": "^0.85.1",
54
+ "@earendil-works/pi-ai": "^0.85.1",
55
+ "@earendil-works/pi-tui": "^0.85.1",
58
56
  "@silvia-odwyer/photon-node": "0.3.4",
59
57
  "chalk": "5.6.2",
60
58
  "cross-spawn": "7.0.6",
@@ -82,6 +80,9 @@
82
80
  "@mariozechner/clipboard": "0.3.9"
83
81
  },
84
82
  "devDependencies": {
83
+ "@earendil-works/pi-client": "^0.85.1",
84
+ "@earendil-works/pi-protocol": "^0.85.1",
85
+ "@earendil-works/pi-server": "^0.85.1",
85
86
  "@types/cross-spawn": "6.0.6",
86
87
  "@types/hosted-git-info": "3.0.5",
87
88
  "@types/node": "22.19.19",
@@ -1,5 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{Check,build_default}from"./chunk-WBE4J4AU.js";import{__commonJS,__require,__toESM}from"./chunk-4L3WN2XY.js";var require_windows=__commonJS({"node_modules/isexe/windows.js"(exports,module){module.exports=isexe;isexe.sync=sync;var fs=__require("fs");function checkPathExt(path,options){var pathext=options.pathExt!==void 0?options.pathExt:process.env.PATHEXT;if(!pathext||(pathext=pathext.split(";"),pathext.indexOf("")!==-1))return!0;for(var i=0;i<pathext.length;i++){var p=pathext[i].toLowerCase();if(p&&path.substr(-p.length).toLowerCase()===p)return!0}return!1}function checkStat(stat,path,options){return!stat.isSymbolicLink()&&!stat.isFile()?!1:checkPathExt(path,options)}function isexe(path,options,cb){fs.stat(path,function(er,stat){cb(er,er?!1:checkStat(stat,path,options))})}function sync(path,options){return checkStat(fs.statSync(path),path,options)}}});var require_mode=__commonJS({"node_modules/isexe/mode.js"(exports,module){module.exports=isexe;isexe.sync=sync;var fs=__require("fs");function isexe(path,options,cb){fs.stat(path,function(er,stat){cb(er,er?!1:checkStat(stat,options))})}function sync(path,options){return checkStat(fs.statSync(path),options)}function checkStat(stat,options){return stat.isFile()&&checkMode(stat,options)}function checkMode(stat,options){var mod=stat.mode,uid=stat.uid,gid=stat.gid,myUid=options.uid!==void 0?options.uid:process.getuid&&process.getuid(),myGid=options.gid!==void 0?options.gid:process.getgid&&process.getgid(),u=parseInt("100",8),g=parseInt("010",8),o=parseInt("001",8),ug=u|g,ret=mod&o||mod&g&&gid===myGid||mod&u&&uid===myUid||mod&ug&&myUid===0;return ret}}});var require_isexe=__commonJS({"node_modules/isexe/index.js"(exports,module){var fs=__require("fs"),core;process.platform==="win32"||global.TESTING_WINDOWS?core=require_windows():core=require_mode();module.exports=isexe;isexe.sync=sync;function isexe(path,options,cb){if(typeof options=="function"&&(cb=options,options={}),!cb){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(resolve3,reject){isexe(path,options||{},function(er,is){er?reject(er):resolve3(is)})})}core(path,options||{},function(er,is){er&&(er.code==="EACCES"||options&&options.ignoreErrors)&&(er=null,is=!1),cb(er,is)})}function sync(path,options){try{return core.sync(path,options||{})}catch(er){if(options&&options.ignoreErrors||er.code==="EACCES")return!1;throw er}}}});var require_which=__commonJS({"node_modules/which/which.js"(exports,module){var isWindows=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",path=__require("path"),COLON=isWindows?";":":",isexe=require_isexe(),getNotFoundError=cmd=>Object.assign(new Error(`not found: ${cmd}`),{code:"ENOENT"}),getPathInfo=(cmd,opt)=>{let colon=opt.colon||COLON,pathEnv=cmd.match(/\//)||isWindows&&cmd.match(/\\/)?[""]:[...isWindows?[process.cwd()]:[],...(opt.path||process.env.PATH||"").split(colon)],pathExtExe=isWindows?opt.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",pathExt=isWindows?pathExtExe.split(colon):[""];return isWindows&&cmd.indexOf(".")!==-1&&pathExt[0]!==""&&pathExt.unshift(""),{pathEnv,pathExt,pathExtExe}},which=(cmd,opt,cb)=>{typeof opt=="function"&&(cb=opt,opt={}),opt||(opt={});let{pathEnv,pathExt,pathExtExe}=getPathInfo(cmd,opt),found=[],step=i=>new Promise((resolve3,reject)=>{if(i===pathEnv.length)return opt.all&&found.length?resolve3(found):reject(getNotFoundError(cmd));let ppRaw=pathEnv[i],pathPart=/^".*"$/.test(ppRaw)?ppRaw.slice(1,-1):ppRaw,pCmd=path.join(pathPart,cmd),p=!pathPart&&/^\.[\\\/]/.test(cmd)?cmd.slice(0,2)+pCmd:pCmd;resolve3(subStep(p,i,0))}),subStep=(p,i,ii)=>new Promise((resolve3,reject)=>{if(ii===pathExt.length)return resolve3(step(i+1));let ext=pathExt[ii];isexe(p+ext,{pathExt:pathExtExe},(er,is)=>{if(!er&&is)if(opt.all)found.push(p+ext);else return resolve3(p+ext);return resolve3(subStep(p,i,ii+1))})});return cb?step(0).then(res=>cb(null,res),cb):step(0)},whichSync=(cmd,opt)=>{opt=opt||{};let{pathEnv,pathExt,pathExtExe}=getPathInfo(cmd,opt),found=[];for(let i=0;i<pathEnv.length;i++){let ppRaw=pathEnv[i],pathPart=/^".*"$/.test(ppRaw)?ppRaw.slice(1,-1):ppRaw,pCmd=path.join(pathPart,cmd),p=!pathPart&&/^\.[\\\/]/.test(cmd)?cmd.slice(0,2)+pCmd:pCmd;for(let j=0;j<pathExt.length;j++){let cur=p+pathExt[j];try{if(isexe.sync(cur,{pathExt:pathExtExe}))if(opt.all)found.push(cur);else return cur}catch{}}}if(opt.all&&found.length)return found;if(opt.nothrow)return null;throw getNotFoundError(cmd)};module.exports=which;which.sync=whichSync}});var require_path_key=__commonJS({"node_modules/path-key/index.js"(exports,module){"use strict";var pathKey=(options={})=>{let environment=options.env||process.env;return(options.platform||process.platform)!=="win32"?"PATH":Object.keys(environment).reverse().find(key=>key.toUpperCase()==="PATH")||"Path"};module.exports=pathKey;module.exports.default=pathKey}});var require_resolveCommand=__commonJS({"node_modules/cross-spawn/lib/util/resolveCommand.js"(exports,module){"use strict";var path=__require("path"),which=require_which(),getPathKey=require_path_key();function resolveCommandAttempt(parsed,withoutPathExt){let env=parsed.options.env||process.env,cwd=process.cwd(),hasCustomCwd=parsed.options.cwd!=null,shouldSwitchCwd=hasCustomCwd&&process.chdir!==void 0&&!process.chdir.disabled;if(shouldSwitchCwd)try{process.chdir(parsed.options.cwd)}catch{}let resolved;try{resolved=which.sync(parsed.command,{path:env[getPathKey({env})],pathExt:withoutPathExt?path.delimiter:void 0})}catch{}finally{shouldSwitchCwd&&process.chdir(cwd)}return resolved&&(resolved=path.resolve(hasCustomCwd?parsed.options.cwd:"",resolved)),resolved}function resolveCommand(parsed){return resolveCommandAttempt(parsed)||resolveCommandAttempt(parsed,!0)}module.exports=resolveCommand}});var require_escape=__commonJS({"node_modules/cross-spawn/lib/util/escape.js"(exports,module){"use strict";var metaCharsRegExp=/([()\][%!^"`<>&|;, *?])/g;function escapeCommand(arg){return arg=arg.replace(metaCharsRegExp,"^$1"),arg}function escapeArgument(arg,doubleEscapeMetaChars){return arg=`${arg}`,arg=arg.replace(/(?=(\\+?)?)\1"/g,'$1$1\\"'),arg=arg.replace(/(?=(\\+?)?)\1$/,"$1$1"),arg=`"${arg}"`,arg=arg.replace(metaCharsRegExp,"^$1"),doubleEscapeMetaChars&&(arg=arg.replace(metaCharsRegExp,"^$1")),arg}module.exports.command=escapeCommand;module.exports.argument=escapeArgument}});var require_shebang_regex=__commonJS({"node_modules/shebang-regex/index.js"(exports,module){"use strict";module.exports=/^#!(.*)/}});var require_shebang_command=__commonJS({"node_modules/shebang-command/index.js"(exports,module){"use strict";var shebangRegex=require_shebang_regex();module.exports=(string="")=>{let match=string.match(shebangRegex);if(!match)return null;let[path,argument]=match[0].replace(/#! ?/,"").split(" "),binary=path.split("/").pop();return binary==="env"?argument:argument?`${binary} ${argument}`:binary}}});var require_readShebang=__commonJS({"node_modules/cross-spawn/lib/util/readShebang.js"(exports,module){"use strict";var fs=__require("fs"),shebangCommand=require_shebang_command();function readShebang(command){let buffer=Buffer.alloc(150),fd;try{fd=fs.openSync(command,"r"),fs.readSync(fd,buffer,0,150,0),fs.closeSync(fd)}catch{}return shebangCommand(buffer.toString())}module.exports=readShebang}});var require_parse=__commonJS({"node_modules/cross-spawn/lib/parse.js"(exports,module){"use strict";var path=__require("path"),resolveCommand=require_resolveCommand(),escape=require_escape(),readShebang=require_readShebang(),isWin=process.platform==="win32",isExecutableRegExp=/\.(?:com|exe)$/i,isCmdShimRegExp=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function detectShebang(parsed){parsed.file=resolveCommand(parsed);let shebang=parsed.file&&readShebang(parsed.file);return shebang?(parsed.args.unshift(parsed.file),parsed.command=shebang,resolveCommand(parsed)):parsed.file}function parseNonShell(parsed){if(!isWin)return parsed;let commandFile=detectShebang(parsed),needsShell=!isExecutableRegExp.test(commandFile);if(parsed.options.forceShell||needsShell){let needsDoubleEscapeMetaChars=isCmdShimRegExp.test(commandFile);parsed.command=path.normalize(parsed.command),parsed.command=escape.command(parsed.command),parsed.args=parsed.args.map(arg=>escape.argument(arg,needsDoubleEscapeMetaChars));let shellCommand=[parsed.command].concat(parsed.args).join(" ");parsed.args=["/d","/s","/c",`"${shellCommand}"`],parsed.command=process.env.comspec||"cmd.exe",parsed.options.windowsVerbatimArguments=!0}return parsed}function parse(command,args,options){args&&!Array.isArray(args)&&(options=args,args=null),args=args?args.slice(0):[],options=Object.assign({},options);let parsed={command,args,options,file:void 0,original:{command,args}};return options.shell?parsed:parseNonShell(parsed)}module.exports=parse}});var require_enoent=__commonJS({"node_modules/cross-spawn/lib/enoent.js"(exports,module){"use strict";var isWin=process.platform==="win32";function notFoundError(original,syscall){return Object.assign(new Error(`${syscall} ${original.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${syscall} ${original.command}`,path:original.command,spawnargs:original.args})}function hookChildProcess(cp,parsed){if(!isWin)return;let originalEmit=cp.emit;cp.emit=function(name,arg1){if(name==="exit"){let err=verifyENOENT(arg1,parsed);if(err)return originalEmit.call(cp,"error",err)}return originalEmit.apply(cp,arguments)}}function verifyENOENT(status,parsed){return isWin&&status===1&&!parsed.file?notFoundError(parsed.original,"spawn"):null}function verifyENOENTSync(status,parsed){return isWin&&status===1&&!parsed.file?notFoundError(parsed.original,"spawnSync"):null}module.exports={hookChildProcess,verifyENOENT,verifyENOENTSync,notFoundError}}});var require_cross_spawn=__commonJS({"node_modules/cross-spawn/index.js"(exports,module){"use strict";var cp=__require("child_process"),parse=require_parse(),enoent=require_enoent();function spawn2(command,args,options){let parsed=parse(command,args,options),spawned=cp.spawn(parsed.command,parsed.args,parsed.options);return enoent.hookChildProcess(spawned,parsed),spawned}function spawnSync(command,args,options){let parsed=parse(command,args,options),result=cp.spawnSync(parsed.command,parsed.args,parsed.options);return result.error=result.error||enoent.verifyENOENTSync(result.status,parsed),result}module.exports=spawn2;module.exports.spawn=spawn2;module.exports.sync=spawnSync;module.exports._parse=parse;module.exports._enoent=enoent}});import{accessSync,constants,existsSync,readFileSync,realpathSync as realpathSync2}from"fs";import{homedir as homedir2}from"os";import{basename,dirname,join as join2,resolve,sep as sep2,win32}from"path";import{fileURLToPath as fileURLToPath2}from"url";var import_cross_spawn=__toESM(require_cross_spawn(),1);import{spawn as nodeSpawn,spawnSync as nodeSpawnSync}from"node:child_process";var EXIT_STDIO_GRACE_MS=100;function spawnProcess(command,args,options){return process.platform==="win32"?(0,import_cross_spawn.default)(command,args,options):nodeSpawn(command,args,options)}function spawnProcessSync(command,args,options){return process.platform==="win32"?import_cross_spawn.default.sync(command,args,options):nodeSpawnSync(command,args,options)}function waitForChildProcess(child){return new Promise((resolve3,reject)=>{let settled=!1,exited=!1,exitCode=null,postExitTimer,stdoutEnded=child.stdout===null,stderrEnded=child.stderr===null,cleanup=()=>{postExitTimer&&(clearTimeout(postExitTimer),postExitTimer=void 0),child.removeListener("error",onError),child.removeListener("exit",onExit),child.removeListener("close",onClose),child.stdout?.removeListener("end",onStdoutEnd),child.stderr?.removeListener("end",onStderrEnd),child.stdout?.removeListener("data",onData),child.stderr?.removeListener("data",onData)},finalize=code=>{settled||(settled=!0,cleanup(),child.stdout?.destroy(),child.stderr?.destroy(),resolve3(code))},maybeFinalizeAfterExit=()=>{!exited||settled||stdoutEnded&&stderrEnded&&finalize(exitCode)},armIdleTimer=()=>{postExitTimer&&clearTimeout(postExitTimer),postExitTimer=setTimeout(()=>finalize(exitCode),EXIT_STDIO_GRACE_MS)},onData=()=>{exited&&!settled&&armIdleTimer()},onStdoutEnd=()=>{stdoutEnded=!0,maybeFinalizeAfterExit()},onStderrEnd=()=>{stderrEnded=!0,maybeFinalizeAfterExit()},onError=err=>{settled||(settled=!0,cleanup(),reject(err))},onExit=code=>{exited=!0,exitCode=code,maybeFinalizeAfterExit(),settled||armIdleTimer()},onClose=code=>{finalize(code)};child.stdout?.once("end",onStdoutEnd),child.stderr?.once("end",onStderrEnd),child.stdout?.on("data",onData),child.stderr?.on("data",onData),child.once("error",onError),child.once("exit",onExit),child.once("close",onClose)})}import{realpathSync,statSync}from"node:fs";import{homedir}from"node:os";import{isAbsolute,join,resolve as nodeResolvePath,relative,sep}from"node:path";import{fileURLToPath}from"node:url";var UNICODE_SPACES=/[\u00A0\u2000-\u200A\u202F\u205F\u3000]/g;function canonicalizePath(path){try{return realpathSync(path)}catch{return path}}function getFileRevision(path){try{let stats=statSync(path,{bigint:!0});return`${stats.dev}:${stats.ino}:${stats.size}:${stats.mtimeNs}:${stats.ctimeNs}`}catch{return}}function isLocalPath(value){let trimmed=value.trim();return!(trimmed.startsWith("npm:")||trimmed.startsWith("git:")||trimmed.startsWith("github:")||trimmed.startsWith("http:")||trimmed.startsWith("https:")||trimmed.startsWith("ssh:"))}function normalizeWindowsShellPath(filePath){if(!filePath.startsWith("/")||filePath.startsWith("//")||filePath.includes("\\"))return filePath;let match=filePath.match(/^\/(?:mnt\/|cygdrive\/)?([a-z])(?:\/(.*))?$/i);if(!match)return filePath;let suffix=match[2]?.replaceAll("/","\\");return`${match[1].toUpperCase()}:\\${suffix??""}`}function normalizePath(input,options={}){let normalized=options.trim?input.trim():input;if(options.normalizeUnicodeSpaces&&(normalized=normalized.replace(UNICODE_SPACES," ")),options.stripAtPrefix&&normalized.startsWith("@")&&(normalized=normalized.slice(1)),process.platform==="win32"&&(normalized=normalizeWindowsShellPath(normalized)),options.expandTilde??!0){let home=options.homeDir??homedir();if(normalized==="~")return home;if(normalized.startsWith("~/")||process.platform==="win32"&&normalized.startsWith("~\\"))return join(home,normalized.slice(2))}return/^file:\/\//.test(normalized)?fileURLToPath(normalized):normalized}function resolvePath(input,baseDir=process.cwd(),options={}){let normalized=normalizePath(input,options),normalizedBaseDir=normalizePath(baseDir);return isAbsolute(normalized)?nodeResolvePath(normalized):nodeResolvePath(normalizedBaseDir,normalized)}function getCwdRelativePath(filePath,cwd){let resolvedCwd=resolvePath(cwd),resolvedPath=resolvePath(filePath,resolvedCwd),relativePath=relative(resolvedCwd,resolvedPath);return relativePath===""||relativePath!==".."&&!relativePath.startsWith(`..${sep}`)&&!isAbsolute(relativePath)?relativePath||".":void 0}function formatPathRelativeToCwdOrAbsolute(filePath,cwd){let absolutePath=resolvePath(filePath,cwd);return(getCwdRelativePath(absolutePath,cwd)??absolutePath).split(sep).join("/")}function markPathIgnoredByCloudSync(path){let attrs=process.platform==="darwin"?["com.dropbox.ignored","com.apple.fileprovider.ignore#P"]:process.platform==="linux"?["user.com.dropbox.ignored"]:[];for(let attr of attrs)process.platform==="darwin"?spawnProcessSync("xattr",["-w",attr,"1",path],{encoding:"utf-8",stdio:"ignore"}):spawnProcessSync("setfattr",["-n",attr,"-v","1",path],{encoding:"utf-8",stdio:"ignore"})}function splitBom(content){return content.startsWith("\uFEFF")?{bom:"\uFEFF",text:content.slice(1)}:{bom:"",text:content}}function stripBom(content){return splitBom(content).text}var __filename=fileURLToPath2(import.meta.url),__dirname=dirname(__filename),isBunBinary=import.meta.url.includes("$bunfs")||import.meta.url.includes("~BUN")||import.meta.url.includes("%7EBUN"),isBunRuntime=!!process.versions.bun,isBundledNode=!0;function normalizeSelfUpdatePackageTarget(target){return typeof target=="string"?{packageName:target,installSpec:target}:{packageName:target.packageName,installSpec:target.installSpec??target.packageName}}function makeSelfUpdateCommand(installStep,uninstallStep){return uninstallStep?{...installStep,display:`${uninstallStep.display} && ${installStep.display}`,steps:[uninstallStep,installStep]}:installStep}function makeSelfUpdateCommandStep(command,args){return{command,args,display:[command,...args].map(arg=>/\s/.test(arg)?`"${arg}"`:arg).join(" ")}}function detectInstallMethod(){if(isBunBinary)return"bun-binary";let resolvedPath=`${__dirname}\0${process.execPath||""}`.toLowerCase().replace(/\\/g,"/");return resolvedPath.includes("/pnpm/")||resolvedPath.includes("/.pnpm/")?"pnpm":resolvedPath.includes("/yarn/")||resolvedPath.includes("/.yarn/")?"yarn":isBunRuntime||resolvedPath.includes("/install/global/node_modules/")?"bun":resolvedPath.includes("/npm/")||resolvedPath.includes("/node_modules/")?"npm":"unknown"}function getInferredNpmInstall(){let packageDir=getPackageDir(),path=process.platform==="win32"||packageDir.includes("\\")?win32:{basename,dirname},parent=path.dirname(packageDir),root;if(path.basename(parent).startsWith("@")&&path.basename(path.dirname(parent))==="node_modules"?root=path.dirname(parent):path.basename(parent)==="node_modules"&&(root=parent),!root)return;let rootParent=path.dirname(root);if(path.basename(rootParent)==="lib")return{root,prefix:path.dirname(rootParent)}}function getSelfUpdateCommandForMethod(method,installedPackageName,updatePackageTarget=installedPackageName,npmCommand){let target=normalizeSelfUpdatePackageTarget(updatePackageTarget);switch(method){case"bun-binary":return;case"pnpm":{let match=readCommandOutput("pnpm",["root","-g"])?void 0:/^(.*[\\/]global[\\/][^\\/]+)[\\/]\.pnpm[\\/]/.exec(getPackageDir()),binDirArgs=match?[`--config.global-bin-dir=${process.env.PNPM_HOME||dirname(dirname(match[1]))}`]:[];return makeSelfUpdateCommand(makeSelfUpdateCommandStep("pnpm",["install","-g","--ignore-scripts","--config.minimumReleaseAge=0",...binDirArgs,target.installSpec]),target.packageName===installedPackageName?void 0:makeSelfUpdateCommandStep("pnpm",["remove","-g",...binDirArgs,installedPackageName]))}case"yarn":return makeSelfUpdateCommand(makeSelfUpdateCommandStep("yarn",["global","add","--ignore-scripts",target.installSpec]),target.packageName===installedPackageName?void 0:makeSelfUpdateCommandStep("yarn",["global","remove",installedPackageName]));case"bun":return makeSelfUpdateCommand(makeSelfUpdateCommandStep("bun",["install","-g","--ignore-scripts","--minimum-release-age=0",target.installSpec]),target.packageName===installedPackageName?void 0:makeSelfUpdateCommandStep("bun",["uninstall","-g",installedPackageName]));case"npm":{let[command="npm",...npmArgs]=npmCommand??[],inferred=npmCommand?.length?void 0:getInferredNpmInstall(),prefixArgs=[...npmArgs,...inferred?["--prefix",inferred.prefix]:[]],installStep=makeSelfUpdateCommandStep(command,[...prefixArgs,"install","-g","--ignore-scripts","--min-release-age=0",target.installSpec]),uninstallStep=target.packageName===installedPackageName?void 0:makeSelfUpdateCommandStep(command,[...prefixArgs,"uninstall","-g",installedPackageName]);return makeSelfUpdateCommand(installStep,uninstallStep)}case"unknown":return}}function readCommandOutput(command,args,options={}){let result=spawnProcessSync(command,args,{encoding:"utf-8",stdio:["ignore","pipe","pipe"]});if(result.status===0)return result.stdout.trim()||void 0;if(options.requireSuccess){let reason=result.error?.message||result.stderr.trim()||`exit code ${result.status??"unknown"}`;throw new Error(`Failed to run ${[command,...args].join(" ")}: ${reason}`)}}function getGlobalPackageRoots(method,_packageName,npmCommand){switch(method){case"npm":{let configured=!!npmCommand?.length,[command="npm",...npmArgs]=npmCommand??[];if(configured&&command==="bun"){let bunBin=readCommandOutput(command,[...npmArgs,"pm","bin","-g"],{requireSuccess:!0}),roots=[join2(homedir2(),".bun","install","global","node_modules")];return bunBin&&roots.push(join2(dirname(bunBin),"install","global","node_modules")),roots}let root=readCommandOutput(command,[...npmArgs,"root","-g"],{requireSuccess:configured}),inferred=configured?void 0:getInferredNpmInstall();return[root,inferred?.root].filter(x=>!!x)}case"pnpm":{let root=readCommandOutput("pnpm",["root","-g"]);if(root)return[root,dirname(root)];let match=/^(.*[\\/]global[\\/][^\\/]+)[\\/]\.pnpm[\\/]/.exec(getPackageDir());return match?[match[1]]:[]}case"yarn":{let dir=readCommandOutput("yarn",["global","dir"]);return dir?[dir,join2(dir,"node_modules")]:[]}case"bun":{let bunBin=readCommandOutput("bun",["pm","bin","-g"]),roots=[join2(homedir2(),".bun","install","global","node_modules")];return bunBin&&roots.push(join2(dirname(bunBin),"install","global","node_modules")),roots}case"bun-binary":case"unknown":return[]}}function normalizeExistingPathForComparison(path,resolveSymlinks){let resolvedPath=resolve(path);if(!existsSync(resolvedPath))return;let normalizedPath=resolvedPath;if(resolveSymlinks)try{normalizedPath=realpathSync2(resolvedPath)}catch{return}return process.platform==="win32"&&(normalizedPath=normalizedPath.toLowerCase()),normalizedPath}function getPathComparisonCandidates(path){return Array.from(new Set([normalizeExistingPathForComparison(path,!1),normalizeExistingPathForComparison(path,!0)].filter(candidate=>!!candidate)))}function getEntrypointPackageDir(){let entrypoint=process.argv[1];if(!entrypoint)return;let dir=dirname(entrypoint);for(;dir!==dirname(dir);){if(existsSync(join2(dir,"package.json")))return dir;dir=dirname(dir)}}function isSelfUpdatePathWritable(){let packageDir=getPackageDir();try{return accessSync(packageDir,constants.W_OK),accessSync(dirname(packageDir),constants.W_OK),!0}catch{return!1}}function isManagedByGlobalPackageManager(method,packageName,npmCommand){let packageDirCandidates=[getPackageDir(),getEntrypointPackageDir()].filter(dir=>!!dir).flatMap(dir=>getPathComparisonCandidates(dir));return getGlobalPackageRoots(method,packageName,npmCommand).some(root=>getPathComparisonCandidates(root).some(normalizedRoot=>{let rootPrefix=normalizedRoot.endsWith(sep2)?normalizedRoot:`${normalizedRoot}${sep2}`;return packageDirCandidates.some(packageDir=>packageDir.startsWith(rootPrefix))}))}function getSelfUpdateCommand(packageName,npmCommand,updatePackageTarget=packageName){let method=detectInstallMethod(),command=getSelfUpdateCommandForMethod(method,packageName,updatePackageTarget,npmCommand);if(!(!command||!isManagedByGlobalPackageManager(method,packageName,npmCommand)||!isSelfUpdatePathWritable()))return command}function getSelfUpdateUnavailableInstruction(packageName,npmCommand,updatePackageTarget=packageName){let method=detectInstallMethod(),target=normalizeSelfUpdatePackageTarget(updatePackageTarget);if(method==="bun-binary")return"Download from: https://github.com/earendil-works/pi-mono/releases/latest";let command=getSelfUpdateCommandForMethod(method,packageName,target,npmCommand);return command?isManagedByGlobalPackageManager(method,packageName,npmCommand)&&!isSelfUpdatePathWritable()?`This installation is managed by a global ${method} install, but the install path is not writable. Update it yourself with: ${command.display}`:`This installation is not managed by a global ${method} install. Update it with the package manager, wrapper, or source checkout that provides it.`:`Update ${target.installSpec} using the package manager, wrapper, or source checkout that provides this installation.`}function findNodePackageDir(startDir){let dir=startDir;for(;dir!==dirname(dir);){if(existsSync(join2(dir,"package.json"))){let parent=dirname(dir);return basename(dir)==="dist"&&existsSync(join2(parent,"package.json"))?parent:dir}dir=dirname(dir)}return startDir}function getPackageDir(){let envDir=process.env.PI_PACKAGE_DIR;return envDir?normalizePath(envDir):isBunBinary?dirname(process.execPath):findNodePackageDir(__dirname)}function getThemesDir(){if(isBunBinary)return join2(getPackageDir(),"theme");let packageDir=getPackageDir(),srcOrDist=existsSync(join2(packageDir,"src"))?"src":"dist";return join2(packageDir,srcOrDist,"modes","interactive","theme")}function getExportTemplateDir(){if(isBunBinary)return join2(getPackageDir(),"export-html");let packageDir=getPackageDir(),srcOrDist=existsSync(join2(packageDir,"src"))?"src":"dist";return join2(packageDir,srcOrDist,"core","export-html")}function getPackageJsonPath(){return join2(getPackageDir(),"package.json")}function getReadmePath(){return resolve(join2(getPackageDir(),"README.md"))}function getDocsPath(){return resolve(join2(getPackageDir(),"docs"))}function getExamplesPath(){return resolve(join2(getPackageDir(),"examples"))}function getChangelogPath(){return resolve(join2(getPackageDir(),"CHANGELOG.md"))}function getInteractiveAssetsDir(){if(isBunBinary)return join2(getPackageDir(),"assets");let packageDir=getPackageDir(),srcOrDist=existsSync(join2(packageDir,"src"))?"src":"dist";return join2(packageDir,srcOrDist,"modes","interactive","assets")}function getBundledInteractiveAssetPath(name){return join2(getInteractiveAssetsDir(),name)}var pkg={};try{pkg=JSON.parse(stripBom(readFileSync(getPackageJsonPath(),"utf-8")))}catch(e){if(e.code!=="ENOENT")throw e}var piConfigName=pkg.piConfig?.name,PACKAGE_NAME=pkg.name||"@earendil-works/pi-coding-agent",APP_NAME=piConfigName||"pi",APP_TITLE=piConfigName?APP_NAME:"\u03C0",CONFIG_DIR_NAME=pkg.piConfig?.configDir||".pi",VERSION=pkg.version||"0.0.0",ENV_AGENT_DIR=`${APP_NAME.toUpperCase()}_CODING_AGENT_DIR`,ENV_SESSION_DIR=`${APP_NAME.toUpperCase()}_CODING_AGENT_SESSION_DIR`;function expandTildePath(path){return normalizePath(path)}var DEFAULT_SHARE_VIEWER_URL="https://pi.dev/session/";function getShareViewerUrl(gistId){return`${process.env.PI_SHARE_VIEWER_URL||DEFAULT_SHARE_VIEWER_URL}#${gistId}`}function getAgentDir(){let envDir=process.env[ENV_AGENT_DIR];return envDir?expandTildePath(envDir):join2(homedir2(),CONFIG_DIR_NAME,"agent")}function getCustomThemesDir(){return join2(getAgentDir(),"themes")}function getAuthPath(){return join2(getAgentDir(),"auth.json")}function getSettingsPath(){return join2(getAgentDir(),"settings.json")}function getBinDir(){return join2(getAgentDir(),"bin")}function getSessionsDir(){return join2(getAgentDir(),"sessions")}function getDebugLogPath(){return join2(getAgentDir(),`${APP_NAME}-debug.log`)}import{spawn}from"node:child_process";import{join as join3,resolve as resolve2}from"node:path";import{fileURLToPath as fileURLToPath3,pathToFileURL}from"node:url";var INTERNAL_PROCESS_ENV="__PI_INTERNAL_SPAWN";function isDirectInternalProcessEntry(moduleUrl){return!isBunBinary&&!isBundledNode&&process.argv[1]!==void 0&&resolve2(process.argv[1])===fileURLToPath3(moduleUrl)}function getInternalProcessRole(){let role=process.env[INTERNAL_PROCESS_ENV];if(role!==void 0){if(role==="coordinator"||role==="server"||role==="session-worker")return role;throw new Error(`Unsupported internal process role: ${role}`)}}function consumeInternalProcessRole(){let role=getInternalProcessRole();return delete process.env[INTERNAL_PROCESS_ENV],role}function spawnInternalProcess(role,args,options={}){if(isBunBinary&&options.entryUrl)throw new Error("A compiled Bun executable cannot launch an external internal-process entrypoint");let entryUrl=defaultEntryUrl(role,options.entryUrl),sourceRuntimeArgs=import.meta.url.endsWith(".ts")?["--import",fileURLToPath3(new URL("source-resolver.ts",import.meta.url))]:[],child=spawn(process.execPath,isBunBinary?[...args]:[...sourceRuntimeArgs,fileURLToPath3(entryUrl),...args],{cwd:process.cwd(),detached:!0,env:{...process.env,...options.env,[INTERNAL_PROCESS_ENV]:role},stdio:"ignore",windowsHide:!0});return child.unref(),child}async function terminateInternalProcess(child){if(child.pid===void 0||child.exitCode!==null||child.signalCode!==null)return;let terminated=new Promise(resolve3=>{child.once("exit",()=>resolve3()),child.once("error",()=>resolve3())});child.kill("SIGKILL"),await terminated}function defaultEntryUrl(role,override){if(override)return override;if(isBundledNode){let entry=role==="coordinator"?"coordinator.js":"cli.js";return pathToFileURL(join3(getPackageDir(),"dist","bundle",entry))}let javaScript=import.meta.url.endsWith(".js");return role==="coordinator"?new URL(javaScript?"coordinator.js":"coordinator.ts",import.meta.url):role==="server"?new URL(javaScript?"server.js":"server.ts",import.meta.url):new URL(javaScript?"session-worker.js":"session-worker.ts",import.meta.url)}var MAX_CONTROL_LINE_BYTES=128*1024*1024;function encodeControlLine(message){let line=`${JSON.stringify(message)}
3
- `;if(Buffer.byteLength(line)>MAX_CONTROL_LINE_BYTES)throw new Error("Internal control message is too large");return line}import{randomUUID}from"node:crypto";import{chmod,lstat,unlink}from"node:fs/promises";import{createConnection,createServer}from"node:net";var COORDINATOR_PROTOCOL_VERSION=3,COORDINATOR_START_TIMEOUT_MS=1e4,COORDINATOR_RETRY_MS=10,CoordinatorMessageSchema=build_default.Union([build_default.Object({type:build_default.Literal("server_registered"),serverConnectionId:build_default.String(),peers:build_default.Array(build_default.String())}),build_default.Object({type:build_default.Literal("server_replaced")}),build_default.Object({type:build_default.Literal("peer_connected"),peerId:build_default.String()}),build_default.Object({type:build_default.Literal("peer_disconnected"),peerId:build_default.String()}),build_default.Object({type:build_default.Literal("message"),from:build_default.String(),payload:build_default.Unknown()})]),CoordinatorConnection=class{serverConnectionId;replaced;peerIds=new Set;#controlPath;#endpoint;#listeners=new Set;#socket;#registered=!1;#closed=!1;#replacedValue=!1;#resolveRegistered;#rejectRegistered;#resolveReplaced;constructor(options){this.serverConnectionId=options.serverConnectionId??randomUUID(),this.#controlPath=options.controlPath,this.#endpoint=options.endpoint,this.replaced=new Promise(resolve3=>{this.#resolveReplaced=resolve3})}get controlPath(){return this.#controlPath}get wasReplaced(){return this.#replacedValue}onEvent(listener){return this.#listeners.add(listener),()=>this.#listeners.delete(listener)}async connect(){if(this.#socket)throw new Error("Coordinator server is already connected");let socket=await connectSocket(this.#controlPath);this.#socket=socket,attachJsonLineReader(socket,message=>this.#handleMessage(message));let registered=new Promise((resolve3,reject)=>{this.#resolveRegistered=resolve3,this.#rejectRegistered=reject});socket.once("close",()=>this.#disconnected(new Error("Coordinator connection closed"))),socket.once("error",error=>this.#disconnected(error)),await writeJsonLine(socket,{type:"register_server",protocol:COORDINATOR_PROTOCOL_VERSION,serverConnectionId:this.serverConnectionId,endpoint:this.#endpoint}),await registered}send(peerId,payload){return this.#write({type:"send",to:peerId,payload})}broadcast(payload){return this.#write({type:"broadcast",payload})}close(){this.#closed||(this.#closed=!0,this.#socket?.destroy(),this.#socket=void 0,this.peerIds.clear(),this.#rejectRegistered?.(new Error("Coordinator server closed")),this.#resolveRegistered=void 0,this.#rejectRegistered=void 0)}async#write(message){if(!this.#registered||!this.#socket||this.#closed)throw new Error("Coordinator server is not connected");await writeJsonLine(this.#socket,message)}#handleMessage(value){if(!Check(CoordinatorMessageSchema,value)){this.#socket?.destroy(new Error("Coordinator sent an invalid message"));return}let message=value;if(message.type==="server_registered"){if(message.serverConnectionId!==this.serverConnectionId){this.#socket?.destroy(new Error("Coordinator returned an invalid server registration"));return}for(let peerId of message.peers)this.peerIds.add(peerId);this.#registered=!0,this.#resolveRegistered?.(),this.#resolveRegistered=void 0,this.#rejectRegistered=void 0;return}if(message.type==="server_replaced"){this.#markReplaced();return}if(message.type==="peer_connected"){this.peerIds.add(message.peerId),this.#emit({type:"peer_connected",peerId:message.peerId});return}if(message.type==="peer_disconnected"){this.peerIds.delete(message.peerId),this.#emit({type:"peer_disconnected",peerId:message.peerId});return}if(message.type==="message"){this.#emit({type:"message",from:message.from,payload:message.payload});return}this.#socket?.destroy(new Error("Coordinator sent an unsupported message"))}#emit(event){for(let listener of this.#listeners)listener(event)}#disconnected(error){this.#socket=void 0,!this.#closed&&(this.#rejectRegistered?.(error),this.#resolveRegistered=void 0,this.#rejectRegistered=void 0,this.#markReplaced())}#markReplaced(){this.#replacedValue||(this.#replacedValue=!0,this.#resolveReplaced())}};async function ensureCoordinator(publicPath2,controlPath2){let existing=await tryConnect(controlPath2);if(existing)return{close:()=>existing.destroy()};let child=spawnInternalProcess("coordinator",[publicPath2,controlPath2]),deadline=Date.now()+COORDINATOR_START_TIMEOUT_MS;for(;;){let socket=await tryConnect(controlPath2);if(socket)return{close:()=>socket.destroy()};if(child.exitCode!==null||child.signalCode!==null)throw new Error("Coordinator exited during startup");if(Date.now()>=deadline)throw new Error("Timed out waiting for coordinator startup");await new Promise(resolve3=>setTimeout(resolve3,COORDINATOR_RETRY_MS))}}function connectSocket(path){return new Promise((resolve3,reject)=>{let socket=createConnection(path),onConnect=()=>{socket.off("error",onError),resolve3(socket)},onError=error=>{socket.off("connect",onConnect),reject(error)};socket.once("connect",onConnect),socket.once("error",onError)})}async function tryConnect(path){try{return await connectSocket(path)}catch(error){let code=error instanceof Error&&"code"in error?error.code:void 0;if(code==="ENOENT"||code==="ECONNREFUSED")return;throw error}}function attachJsonLineReader(socket,onMessage){let buffered="";socket.setEncoding("utf8"),socket.on("data",chunk=>{if(buffered+=chunk,Buffer.byteLength(buffered)>MAX_CONTROL_LINE_BYTES){socket.destroy(new Error("Coordinator message is too large"));return}for(;;){let newline=buffered.indexOf(`
4
- `);if(newline===-1)return;let line=buffered.slice(0,newline);buffered=buffered.slice(newline+1);try{onMessage(JSON.parse(line))}catch{socket.destroy(new Error("Coordinator sent invalid JSON"));return}}})}function writeJsonLine(socket,message){return new Promise((resolve3,reject)=>{socket.write(encodeControlLine(message),error=>{error?reject(error):resolve3()})})}var EMPTY_STARTUP_GRACE_MS=3e4,EMPTY_SHUTDOWN_GRACE_MS=250,publicPath,controlPath,running=!1,peers=new Map,controlConnections=new Set,publicConnections=new Map,currentServer,shuttingDown=!1,emptyTimer,publicServer=createServer(socket=>acceptPublicConnection(socket)),controlServer=createServer(socket=>acceptControlConnection(socket));async function runCoordinatorProcess(args){if(running)throw new Error("Coordinator process is already running");let[requestedPublicPath,requestedControlPath]=args;if(!requestedPublicPath||!requestedControlPath)throw new Error("Coordinator requires public and control socket paths");publicPath=requestedPublicPath,controlPath=requestedControlPath,running=!0,process.once("SIGINT",()=>{shutdownCoordinator()}),process.once("SIGTERM",()=>{shutdownCoordinator()}),await main()}async function main(){await removeStaleSocket(controlPath),await removeStaleSocket(publicPath);try{await listen(controlServer,controlPath),await restrictSocket(controlPath),await listen(publicServer,publicPath),await restrictSocket(publicPath)}catch(error){throw await Promise.all([cleanupSocket(controlPath),cleanupSocket(publicPath)]),error}scheduleEmptyShutdown(EMPTY_STARTUP_GRACE_MS)}function acceptControlConnection(socket){if(shuttingDown){socket.destroy();return}controlConnections.add(socket);let server,peer;attachRoutedLineReader(socket,message=>{if(!server&&!peer){if(message.type==="register_server"){server=registerServer(socket,message);return}if(message.type==="register_peer"){peer=registerPeer(socket,message);return}throw new Error("Coordinator connection did not register a role")}if(server){server===currentServer&&handleRoutedMessage("server",message);return}handleRoutedMessage(peer.peerId,message)});let disconnect=()=>{controlConnections.delete(socket),server&&currentServer===server&&(currentServer=void 0,notifyPeers({type:"server_disconnected",serverConnectionId:server.serverConnectionId})),peer&&peers.get(peer.peerId)===peer&&(peers.delete(peer.peerId),currentServer&&writeRoutedLine(currentServer.socket,{type:"peer_disconnected",peerId:peer.peerId})),checkEmpty()};socket.once("close",disconnect),socket.once("error",()=>socket.destroy())}function registerServer(socket,message){if(message.protocol!==COORDINATOR_PROTOCOL_VERSION)throw new Error("Unsupported coordinator protocol");if(typeof message.serverConnectionId!="string"||message.serverConnectionId.length===0)throw new Error("Coordinator serverConnectionId must be a string");if(typeof message.endpoint!="string"||message.endpoint.length===0)throw new Error("Coordinator endpoint must be a string");let{serverConnectionId,endpoint}=message,server={serverConnectionId,endpoint,socket},previous=currentServer;return currentServer=server,cancelEmptyShutdown(),writeRoutedLine(socket,{type:"server_registered",serverConnectionId,peers:[...peers.keys()]}),previous&&previous!==server&&(closePublicConnections(),notifyPeers({type:"server_disconnected",serverConnectionId:previous.serverConnectionId}),writeRoutedLine(previous.socket,{type:"server_replaced"})),notifyPeers({type:"server_connected",serverConnectionId}),server}function registerPeer(socket,message){if(message.protocol!==COORDINATOR_PROTOCOL_VERSION)throw new Error("Unsupported coordinator protocol");if(typeof message.peerId!="string"||message.peerId.length===0)throw new Error("Coordinator peerId must be a string");let{peerId}=message;if(peerId==="server"||peers.has(peerId))throw new Error(`Coordinator peer is already connected: ${peerId}`);let peer={peerId,socket};return peers.set(peerId,peer),cancelEmptyShutdown(),writeRoutedLine(socket,{type:"peer_registered",peerId,...currentServer===void 0?{}:{serverConnectionId:currentServer.serverConnectionId}}),currentServer&&writeRoutedLine(currentServer.socket,{type:"peer_connected",peerId}),peer}function notifyPeers(message){for(let peer of peers.values())writeRoutedLine(peer.socket,message)}function handleRoutedMessage(from,message){if(message.type==="send"){if(typeof message.to!="string"||message.to.length===0)throw new Error("Coordinator message target must be a string");let{to}=message,target=to==="server"?currentServer?.socket:peers.get(to)?.socket;target&&writeRoutedLine(target,{type:"message",from,payload:message.payload});return}if(message.type==="broadcast"){if(from!=="server")throw new Error("Only the current server may broadcast");for(let peer of peers.values())writeRoutedLine(peer.socket,{type:"message",from,payload:message.payload});return}throw new Error(`Unknown coordinator routing message: ${message.type}`)}function acceptPublicConnection(client){if(shuttingDown||!currentServer){client.destroy();return}cancelEmptyShutdown();let upstream=createConnection(currentServer.endpoint);publicConnections.set(client,upstream);let finalized=!1,finalize=()=>{finalized||(finalized=!0,publicConnections.delete(client),checkEmpty())};upstream.once("connect",()=>{client.pipe(upstream),upstream.pipe(client)}),upstream.once("error",()=>client.destroy()),upstream.once("close",()=>{client.destroy(),finalize()}),client.once("error",()=>upstream.destroy()),client.once("close",()=>{upstream.destroy(),finalize()})}function closePublicConnections(){for(let[client,upstream]of publicConnections)client.destroy(),upstream.destroy();publicConnections.clear()}function checkEmpty(){if(shuttingDown||currentServer||peers.size>0||publicConnections.size>0||controlConnections.size>0){cancelEmptyShutdown();return}scheduleEmptyShutdown(EMPTY_SHUTDOWN_GRACE_MS)}function scheduleEmptyShutdown(delayMs){emptyTimer||shuttingDown||(emptyTimer=setTimeout(()=>{emptyTimer=void 0,!currentServer&&peers.size===0&&publicConnections.size===0&&controlConnections.size===0&&shutdownCoordinator()},delayMs),emptyTimer.unref())}function cancelEmptyShutdown(){emptyTimer&&(clearTimeout(emptyTimer),emptyTimer=void 0)}async function shutdownCoordinator(){if(!shuttingDown){shuttingDown=!0,cancelEmptyShutdown(),closePublicConnections();for(let connection of controlConnections)connection.destroy();await Promise.all([closeServer(publicServer),closeServer(controlServer)]),await Promise.all([cleanupSocket(publicPath),cleanupSocket(controlPath)]),process.exit(0)}}function writeRoutedLine(socket,message){socket.destroyed||socket.write(encodeControlLine(message))}function attachRoutedLineReader(socket,onMessage){let buffered="";socket.setEncoding("utf8"),socket.on("data",chunk=>{if(buffered+=chunk,Buffer.byteLength(buffered)>MAX_CONTROL_LINE_BYTES){socket.destroy(new Error("Coordinator message is too large"));return}for(;;){let newline=buffered.indexOf(`
5
- `);if(newline===-1)return;let line=buffered.slice(0,newline);buffered=buffered.slice(newline+1);try{let message=JSON.parse(line);if(typeof message?.type!="string")throw new Error("Coordinator message must have a type");onMessage(message)}catch(error){socket.destroy(error instanceof Error?error:new Error(String(error)));return}}})}function listen(server,path){return new Promise((resolve3,reject)=>{let onError=error=>{server.off("listening",onListening),reject(error)},onListening=()=>{server.off("error",onError),resolve3()};server.once("error",onError),server.once("listening",onListening),server.listen(path)})}function closeServer(server){return server.listening?new Promise(resolve3=>server.close(()=>resolve3())):Promise.resolve()}async function restrictSocket(path){process.platform!=="win32"&&await chmod(path,384)}async function removeStaleSocket(path){try{if(!(await lstat(path)).isSocket())throw new Error(`Coordinator path is not a socket: ${path}`)}catch(error){if(error instanceof Error&&"code"in error&&error.code==="ENOENT")return;throw error}if(await new Promise((resolve3,reject)=>{let socket=createConnection(path);socket.once("connect",()=>{socket.destroy(),resolve3(!0)}),socket.once("error",error=>{socket.destroy(),error.code==="ECONNREFUSED"||error.code==="ENOENT"?resolve3(!1):reject(error)})}))throw new Error(`Coordinator socket is already active: ${path}`);await cleanupSocket(path)}async function cleanupSocket(path){process.platform!=="win32"&&await unlink(path).catch(error=>{if(!(error instanceof Error&&"code"in error&&error.code==="ENOENT"))throw error})}if(isDirectInternalProcessEntry(import.meta.url)){if(consumeInternalProcessRole()!=="coordinator")throw new Error("Coordinator entrypoint requires an internal coordinator invocation");runCoordinatorProcess(process.argv.slice(2)).catch(error=>{console.error(error),process.exit(1)})}export{spawnProcess,spawnProcessSync,waitForChildProcess,canonicalizePath,getFileRevision,isLocalPath,normalizePath,resolvePath,getCwdRelativePath,formatPathRelativeToCwdOrAbsolute,markPathIgnoredByCloudSync,splitBom,stripBom,isBunBinary,isBundledNode,detectInstallMethod,getSelfUpdateCommand,getSelfUpdateUnavailableInstruction,getPackageDir,getThemesDir,getExportTemplateDir,getReadmePath,getDocsPath,getExamplesPath,getChangelogPath,getBundledInteractiveAssetPath,PACKAGE_NAME,APP_NAME,APP_TITLE,CONFIG_DIR_NAME,VERSION,ENV_AGENT_DIR,ENV_SESSION_DIR,expandTildePath,getShareViewerUrl,getAgentDir,getCustomThemesDir,getAuthPath,getSettingsPath,getBinDir,getSessionsDir,getDebugLogPath,isDirectInternalProcessEntry,consumeInternalProcessRole,spawnInternalProcess,terminateInternalProcess,MAX_CONTROL_LINE_BYTES,encodeControlLine,COORDINATOR_PROTOCOL_VERSION,CoordinatorConnection,ensureCoordinator,runCoordinatorProcess};
@@ -1,2 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{Check,build_default}from"./chunk-WBE4J4AU.js";var ServerError=class extends Error{code;constructor(error){super(error.message),this.name="ServerError",this.code=error.code}},DisconnectedError=class extends Error{constructor(message="Client is disconnected",cause){super(message,cause===void 0?void 0:{cause}),this.name="DisconnectedError"}},ClientDisposedError=class extends Error{constructor(){super("Client is disposed"),this.name="ClientDisposedError"}};function toError(error){return error instanceof Error?error:new Error(String(error))}function toDisconnectedError(error){let cause=toError(error);return cause instanceof DisconnectedError?cause:new DisconnectedError(cause.message,cause)}import{createServiceCatalogueCall,createServiceStateDecoder,createServiceSubscribeCall,createServiceUnsubscribeCall,parseServiceCall,parseServiceCatalogue,parseWireServiceProviderUpdate,parseWireServiceSubscriptionSnapshot}from"@earendil-works/chord";import{BACKGROUND_CONTEXT}from"@earendil-works/chord/context";var CborError=class extends Error{constructor(message){super(message),this.name="CborError"}},textEncoder=new TextEncoder,textDecoder=new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0});function resolveLimit(name,value,maximum){if(!Number.isSafeInteger(value)||value<0||value>maximum)throw new RangeError(`${name} must be an integer between 0 and ${maximum}`);return value}function resolveOptions(options){return{maxByteLength:resolveLimit("maxByteLength",options?.maxByteLength??16777216,4294967295),maxContainerLength:resolveLimit("maxContainerLength",options?.maxContainerLength??1e6,4294967295),maxDepth:resolveLimit("maxDepth",options?.maxDepth??64,512)}}var CborReader=class{bytes;offset=0;options;constructor(bytes,options){this.bytes=bytes,this.options=options}decode(){let value=this.readItem(0);if(this.offset!==this.bytes.byteLength)throw new CborError("CBOR payload contains trailing data");return value}readItem(depth){if(depth>this.options.maxDepth)throw new CborError(`CBOR nesting depth exceeds configured limit of ${this.options.maxDepth}`);let initial=this.readByte(),majorType=initial>>>5,additionalInformation=initial&31;switch(majorType){case 0:return this.readArgument(additionalInformation);case 1:{let value=-1-this.readArgument(additionalInformation);if(!Number.isSafeInteger(value))throw new CborError("Decoded CBOR integer is outside the safe range");return value}case 2:{let length=this.readLength(additionalInformation,"byte string",this.options.maxByteLength);return new Uint8Array(this.readBytes(length))}case 3:{let length=this.readLength(additionalInformation,"text string",this.options.maxByteLength),bytes=this.readBytes(length);try{return textDecoder.decode(bytes)}catch{throw new CborError("CBOR text string contains invalid UTF-8")}}case 4:{let length=this.readLength(additionalInformation,"array",this.options.maxContainerLength),result=[];for(let index=0;index<length;index++)result.push(this.readItem(depth+1));return result}case 5:{let length=this.readLength(additionalInformation,"map",this.options.maxContainerLength),result={},keys=new Set;for(let index=0;index<length;index++){let key=this.readItem(depth+1);if(typeof key!="string")throw new CborError("CBOR map keys must be strings");if(keys.has(key))throw new CborError("CBOR map contains a duplicate key");keys.add(key),Object.defineProperty(result,key,{configurable:!0,enumerable:!0,value:this.readItem(depth+1),writable:!0})}return result}case 6:throw new CborError("CBOR tags are not supported");case 7:return this.readSimple(additionalInformation);default:throw new CborError("Malformed CBOR major type")}}readSimple(additionalInformation){switch(additionalInformation){case 20:return!1;case 21:return!0;case 22:return null;case 27:{let bytes=this.readBytes(8),value=new DataView(bytes.buffer,bytes.byteOffset,bytes.byteLength).getFloat64(0,!1);if(!Number.isFinite(value))throw new CborError("Decoded CBOR number must be finite");if(Number.isInteger(value)&&!Number.isSafeInteger(value))throw new CborError("Decoded CBOR integer is outside the safe range");return value}case 31:throw new CborError("CBOR break marker is not supported");default:throw new CborError("Unsupported CBOR simple value or floating-point width")}}readLength(additionalInformation,kind,limit){if(additionalInformation===31)throw new CborError(`Indefinite-length CBOR ${kind}s are not supported`);let length=this.readArgument(additionalInformation);if(length>limit)throw new CborError(`CBOR ${kind} length exceeds configured limit of ${limit}`);return length}readArgument(additionalInformation){if(additionalInformation<24)return additionalInformation;switch(additionalInformation){case 24:return this.readByte();case 25:{let bytes=this.readBytes(2);return bytes[0]*256+bytes[1]}case 26:{let bytes=this.readBytes(4);return bytes[0]*16777216+bytes[1]*65536+bytes[2]*256+bytes[3]}case 27:{let high=this.readArgument(26),low=this.readArgument(26);if(high>2097151)throw new CborError("Decoded CBOR integer or length is outside the safe range");return high*4294967296+low}case 31:throw new CborError("Indefinite-length CBOR items are not supported");default:throw new CborError("Malformed CBOR additional information")}}readByte(){if(this.offset>=this.bytes.byteLength)throw new CborError("Truncated CBOR payload");let value=this.bytes[this.offset];return this.offset++,value}readBytes(length){if(length>this.bytes.byteLength-this.offset)throw new CborError("Truncated CBOR payload");let value=this.bytes.subarray(this.offset,this.offset+length);return this.offset+=length,value}};function decodeCbor(bytes,options){if(!(bytes instanceof Uint8Array))throw new TypeError("CBOR input must be a Uint8Array");let resolved=resolveOptions(options);if(bytes.byteLength>resolved.maxByteLength)throw new CborError(`CBOR byte length exceeds configured limit of ${resolved.maxByteLength}`);return new CborReader(bytes,resolved).decode()}var CborWriter=class{buffer;offset=0;maxByteLength;constructor(maxByteLength){this.maxByteLength=maxByteLength,this.buffer=new Uint8Array(Math.min(256,maxByteLength))}writeByte(value){this.ensureCapacity(1),this.buffer[this.offset]=value,this.offset++}writeBytes(bytes){this.ensureCapacity(bytes.byteLength),this.buffer.set(bytes,this.offset),this.offset+=bytes.byteLength}writeUint16(value){this.ensureCapacity(2),this.buffer[this.offset]=value>>>8,this.buffer[this.offset+1]=value,this.offset+=2}writeUint32(value){this.ensureCapacity(4),this.buffer[this.offset]=value>>>24,this.buffer[this.offset+1]=value>>>16,this.buffer[this.offset+2]=value>>>8,this.buffer[this.offset+3]=value,this.offset+=4}writeUint64(value){let high=Math.floor(value/4294967296),low=value-high*4294967296;this.writeUint32(high),this.writeUint32(low)}writeFloat64(value){this.ensureCapacity(9),this.buffer[this.offset]=251,new DataView(this.buffer.buffer).setFloat64(this.offset+1,value,!1),this.offset+=9}finish(){return this.buffer.slice(0,this.offset)}ensureCapacity(additionalBytes){let required=this.offset+additionalBytes;if(required>this.maxByteLength)throw new CborError(`CBOR byte length exceeds configured limit of ${this.maxByteLength}`);if(required<=this.buffer.byteLength)return;let capacity=Math.max(1,this.buffer.byteLength);for(;capacity<required;)capacity=Math.min(this.maxByteLength,Math.max(required,capacity*2));let expanded=new Uint8Array(capacity);expanded.set(this.buffer),this.buffer=expanded}};function writeArgument(writer,majorType,value){let prefix=majorType<<5;value<24?writer.writeByte(prefix|value):value<=255?(writer.writeByte(prefix|24),writer.writeByte(value)):value<=65535?(writer.writeByte(prefix|25),writer.writeUint16(value)):value<=4294967295?(writer.writeByte(prefix|26),writer.writeUint32(value)):(writer.writeByte(prefix|27),writer.writeUint64(value))}function isPlainObject(value){if(typeof value!="object"||value===null)return!1;let prototype=Object.getPrototypeOf(value);return prototype===Object.prototype||prototype===null}function encodeText(writer,value,options){let bytes=textEncoder.encode(value);if(bytes.byteLength>options.maxByteLength)throw new CborError(`CBOR text string length exceeds configured limit of ${options.maxByteLength}`);if(textDecoder.decode(bytes)!==value)throw new CborError("CBOR text strings must contain valid Unicode scalar values");writeArgument(writer,3,bytes.byteLength),writer.writeBytes(bytes)}function encodeValue(writer,value,options,depth,ancestors){if(depth>options.maxDepth)throw new CborError(`CBOR nesting depth exceeds configured limit of ${options.maxDepth}`);if(value===null){writer.writeByte(246);return}if(typeof value=="boolean"){writer.writeByte(value?245:244);return}if(typeof value=="number"){if(!Number.isFinite(value))throw new CborError("CBOR numbers must be finite");if(Number.isInteger(value)&&!Object.is(value,-0)){if(!Number.isSafeInteger(value))throw new CborError("CBOR integers must be safe JavaScript integers");value>=0?writeArgument(writer,0,value):writeArgument(writer,1,-1-value)}else writer.writeFloat64(value);return}if(typeof value=="string"){encodeText(writer,value,options);return}if(value instanceof Uint8Array){if(value.byteLength>options.maxByteLength)throw new CborError(`CBOR byte string length exceeds configured limit of ${options.maxByteLength}`);writeArgument(writer,2,value.byteLength),writer.writeBytes(value);return}if(Array.isArray(value)){if(ancestors.has(value))throw new CborError("CBOR values must not contain cycles");if(value.length>options.maxContainerLength)throw new CborError(`CBOR array length exceeds configured limit of ${options.maxContainerLength}`);ancestors.add(value);try{writeArgument(writer,4,value.length);for(let index=0;index<value.length;index++){if(!Object.hasOwn(value,index)||value[index]===void 0)throw new CborError("CBOR arrays must not contain holes or undefined values");encodeValue(writer,value[index],options,depth+1,ancestors)}}finally{ancestors.delete(value)}return}if(isPlainObject(value)){if(ancestors.has(value))throw new CborError("CBOR values must not contain cycles");for(let symbol of Object.getOwnPropertySymbols(value))if(Object.prototype.propertyIsEnumerable.call(value,symbol))throw new CborError("CBOR map keys must be strings");let entries=[];for(let key of Object.keys(value)){let entryValue=value[key];entryValue!==void 0&&entries.push([key,entryValue])}if(entries.length>options.maxContainerLength)throw new CborError(`CBOR map length exceeds configured limit of ${options.maxContainerLength}`);ancestors.add(value);try{writeArgument(writer,5,entries.length);for(let[key,entryValue]of entries)encodeText(writer,key,options),encodeValue(writer,entryValue,options,depth+1,ancestors)}finally{ancestors.delete(value)}return}throw new CborError(`Unsupported CBOR value type: ${typeof value}`)}function encodeCbor(value,options){let resolved=resolveOptions(options),writer=new CborWriter(resolved.maxByteLength);return encodeValue(writer,value,resolved,0,new Set),writer.finish()}import{isJsonValue}from"@earendil-works/chord";var FrameError=class extends Error{constructor(message){super(message),this.name="FrameError"}};function resolveMaxFrameLength(options){let value=options?.maxFrameLength??16777216;if(!Number.isSafeInteger(value)||value<0||value>4294967295)throw new RangeError(`maxFrameLength must be an integer between 0 and ${4294967295}`);return value}function encodeFrame(payload){if(!(payload instanceof Uint8Array))throw new TypeError("Frame payload must be a Uint8Array");if(payload.byteLength>4294967295)throw new RangeError("Frame payload exceeds the unsigned 32-bit length limit");let frame=new Uint8Array(4+payload.byteLength),length=payload.byteLength;return frame[0]=length>>>24,frame[1]=length>>>16,frame[2]=length>>>8,frame[3]=length,frame.set(payload,4),frame}var FrameDecoder=class{header=new Uint8Array(4);headerLength=0;maxFrameLength;payloadBlocks=[];currentPayloadBlock;currentPayloadBlockLength=0;expectedPayloadLength;payloadLength=0;state="open";constructor(options){this.maxFrameLength=resolveMaxFrameLength(options)}push(chunk){if(this.state==="ended")throw new FrameError("Frame decoder has ended");if(this.state==="failed")throw new FrameError("Frame decoder has failed");if(!(chunk instanceof Uint8Array))throw new TypeError("Frame chunk must be a Uint8Array");let frames=[],chunkOffset=0;for(;chunkOffset<chunk.byteLength;){if(this.expectedPayloadLength===void 0){let headerBytes=Math.min(4-this.headerLength,chunk.byteLength-chunkOffset);if(this.header.set(chunk.subarray(chunkOffset,chunkOffset+headerBytes),this.headerLength),this.headerLength+=headerBytes,chunkOffset+=headerBytes,this.headerLength<4)continue;let frameLength=this.header[0]*16777216+this.header[1]*65536+this.header[2]*256+this.header[3];if(this.headerLength=0,frameLength>this.maxFrameLength&&this.fail(`Frame length ${frameLength} exceeds configured limit of ${this.maxFrameLength}`),frameLength===0){frames.push(new Uint8Array);continue}this.expectedPayloadLength=frameLength,this.payloadBlocks=[],this.currentPayloadBlock=void 0,this.currentPayloadBlockLength=0,this.payloadLength=0}let expectedPayloadLength=this.expectedPayloadLength;if(expectedPayloadLength!==void 0){for(;chunkOffset<chunk.byteLength&&this.payloadLength<expectedPayloadLength;){let block=this.currentPayloadBlock;(!block||this.currentPayloadBlockLength===block.byteLength)&&(block=new Uint8Array(Math.min(65536,expectedPayloadLength-this.payloadLength)),this.payloadBlocks.push(block),this.currentPayloadBlock=block,this.currentPayloadBlockLength=0);let payloadBytes=Math.min(block.byteLength-this.currentPayloadBlockLength,chunk.byteLength-chunkOffset);block.set(chunk.subarray(chunkOffset,chunkOffset+payloadBytes),this.currentPayloadBlockLength),this.currentPayloadBlockLength+=payloadBytes,this.payloadLength+=payloadBytes,chunkOffset+=payloadBytes}if(this.payloadLength===expectedPayloadLength){if(this.payloadBlocks.length===1)frames.push(this.payloadBlocks[0]);else{let payload=new Uint8Array(expectedPayloadLength),offset=0;for(let payloadBlock of this.payloadBlocks)payload.set(payloadBlock,offset),offset+=payloadBlock.byteLength;frames.push(payload)}this.payloadBlocks=[],this.currentPayloadBlock=void 0,this.currentPayloadBlockLength=0,this.expectedPayloadLength=void 0,this.payloadLength=0}}}return frames}end(){if(this.state==="ended")throw new FrameError("Frame decoder has ended");if(this.state==="failed")throw new FrameError("Frame decoder has failed");(this.headerLength!==0||this.expectedPayloadLength!==void 0)&&this.fail("Truncated frame at end of stream"),this.state="ended"}fail(message){throw this.state="failed",this.headerLength=0,this.payloadBlocks=[],this.currentPayloadBlock=void 0,this.currentPayloadBlockLength=0,this.expectedPayloadLength=void 0,this.payloadLength=0,new FrameError(message)}};var PROTOCOL_VERSION=8,IdSchema=build_default.String({minLength:1}),OpaqueJsonValueSchema=build_default.Unsafe(build_default.Unknown()),StrictObject=properties=>build_default.Object(properties,{additionalProperties:!1}),ServerIdSchema=build_default.String({pattern:"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"});function isServerId(value){return Check(ServerIdSchema,value)}var ProtocolErrorSchema=StrictObject({code:IdSchema,message:build_default.String()}),ClientHelloSchema=StrictObject({type:build_default.Literal("hello"),version:build_default.Integer({minimum:0})}),ServerTargetSchema=StrictObject({serverId:ServerIdSchema}),SessionTargetSchema=StrictObject({serverId:ServerIdSchema,sessionId:IdSchema,attachmentId:IdSchema}),RpcTargetSchema=build_default.Union([ServerTargetSchema,SessionTargetSchema]),RequestEnvelopeSchema=StrictObject({type:build_default.Literal("request"),id:IdSchema,target:RpcTargetSchema,call:OpaqueJsonValueSchema}),CancelEnvelopeSchema=StrictObject({type:build_default.Literal("cancel"),id:IdSchema,target:RpcTargetSchema}),ClientMessageSchema=build_default.Union([ClientHelloSchema,RequestEnvelopeSchema,CancelEnvelopeSchema]),ServerHelloSchema=StrictObject({type:build_default.Literal("hello"),version:build_default.Literal(PROTOCOL_VERSION),serverId:ServerIdSchema}),ServerHelloErrorSchema=StrictObject({type:build_default.Literal("hello_error"),error:ProtocolErrorSchema}),ResponseEnvelopeSchema=build_default.Union([StrictObject({type:build_default.Literal("response"),id:IdSchema,ok:build_default.Literal(!0),result:build_default.Optional(OpaqueJsonValueSchema)}),StrictObject({type:build_default.Literal("response"),id:IdSchema,ok:build_default.Literal(!1),error:ProtocolErrorSchema})]),ServiceEventEnvelopeSchema=StrictObject({type:build_default.Literal("service_update"),subscriptionId:IdSchema,update:OpaqueJsonValueSchema}),AttachmentEnvelopeSchema=StrictObject({type:build_default.Literal("attachment"),attachment:build_default.Union([SessionTargetSchema,build_default.Null()])}),ServerMessageSchema=build_default.Union([ServerHelloSchema,ServerHelloErrorSchema,ResponseEnvelopeSchema,ServiceEventEnvelopeSchema,AttachmentEnvelopeSchema]);var ProtocolValidationError=class extends Error{constructor(message){super(message),this.name="ProtocolValidationError"}};function parseClientMessage(value){if(!Check(ClientMessageSchema,value)||!isJsonValue(value))throw new ProtocolValidationError("Invalid client protocol message");return value}function parseServerMessage(value){if(!Check(ServerMessageSchema,value)||!isJsonValue(value))throw new ProtocolValidationError("Invalid server protocol message");return value}function boundedErrorMessage(error){return error instanceof Error?error.message.length<=500?error.message:`${error.message.slice(0,497)}...`:"Unknown codec error"}function encodeProtocolMessage(value,parse,kind,options){let validated=parse(value);try{let maxFrameLength=options?.maxFrameLength??16777216;return encodeFrame(encodeCbor(validated,{maxByteLength:maxFrameLength}))}catch(error){throw error instanceof ProtocolValidationError?error:new ProtocolValidationError(`Unable to encode ${kind} protocol message: ${boundedErrorMessage(error)}`)}}function encodeClientMessage(message,options){return encodeProtocolMessage(message,parseClientMessage,"client",options)}function encodeServerMessage(message,options){return encodeProtocolMessage(message,parseServerMessage,"server",options)}var ValidatedMessageDecoder=class{failed=!1;frames;kind;maxFrameLength;parse;constructor(kind,parse,options){this.frames=new FrameDecoder(options),this.kind=kind,this.maxFrameLength=options?.maxFrameLength??16777216,this.parse=parse}push(chunk){if(this.failed)throw new ProtocolValidationError(`${this.kind} message decoder has failed`);try{let messages=[];for(let frame of this.frames.push(chunk))messages.push(this.parse(decodeCbor(frame,{maxByteLength:this.maxFrameLength})));return messages}catch(error){throw this.failed=!0,error instanceof ProtocolValidationError?error:new ProtocolValidationError(`Invalid ${this.kind} protocol frame: ${boundedErrorMessage(error)}`)}}end(){if(this.failed)throw new ProtocolValidationError(`${this.kind} message decoder has failed`);try{this.frames.end()}catch(error){throw this.failed=!0,new ProtocolValidationError(`Invalid ${this.kind} protocol framing: ${boundedErrorMessage(error)}`)}}},ClientMessageDecoder=class{decoder;constructor(options){this.decoder=new ValidatedMessageDecoder("client",parseClientMessage,options)}push(chunk){return this.decoder.push(chunk)}end(){this.decoder.end()}},ServerMessageDecoder=class{decoder;constructor(options){this.decoder=new ValidatedMessageDecoder("server",parseServerMessage,options)}push(chunk){return this.decoder.push(chunk)}end(){this.decoder.end()}};function isSupportedProtocolVersion(version){return Number.isInteger(version)&&version===PROTOCOL_VERSION}function createPromiseResolvers(){let resolve,reject;return{promise:new Promise((resolvePromise,rejectPromise)=>{resolve=resolvePromise,reject=rejectPromise}),resolve,reject}}var MAX_UINT322=4294967295,Connection=class{#options;#maxFrameLength;#lifecycle={state:"disconnected"};#sequence=0;constructor(options){if(this.#options=options,this.#maxFrameLength=options.maxFrameLength??16777216,!Number.isSafeInteger(this.#maxFrameLength)||this.#maxFrameLength<=0||this.#maxFrameLength>MAX_UINT322)throw new TypeError(`Client maxFrameLength must be an integer between 1 and ${MAX_UINT322}`)}get state(){return this.#lifecycle.state}get maxFrameLength(){return this.#maxFrameLength}connect(){if(this.#lifecycle.state!=="disconnected")return Promise.reject(new DisconnectedError(`Client is already ${this.#lifecycle.state}`));let id=++this.#sequence,handshake=createPromiseResolvers();this.#lifecycle={state:"connecting",id,decoder:new ServerMessageDecoder({maxFrameLength:this.#maxFrameLength}),handshake},this.#options.onStateChange({state:"connecting"});let handlers={onData:chunk=>this.#handleData(id,chunk),onClose:()=>{this.#isCurrent(id)&&this.#handleClose()},onError:error=>{this.#isCurrent(id)&&this.#failAndClose(toDisconnectedError(error))}};return this.#openTransport(id,handlers),handshake.promise}disconnect(reason="Client disconnected"){this.#lifecycle.state!=="disconnected"&&this.#failAndClose(typeof reason=="string"?new DisconnectedError(reason):reason)}fail(error){this.#failAndClose(error)}send(frame){let lifecycle=this.#lifecycle;if(lifecycle.state!=="connected")throw new DisconnectedError;let sending;try{sending=lifecycle.transport.send(frame)}catch(error){this.#failAndClose(toDisconnectedError(error));return}sending.catch(error=>{let current=this.#lifecycle;current.state!=="disconnected"&&current.transport===lifecycle.transport&&this.#failAndClose(toDisconnectedError(error))})}async#openTransport(id,handlers){let transport;try{transport=await this.#options.transportFactory(handlers)}catch(error){this.#isCurrent(id)&&this.#fail(toDisconnectedError(error));return}let lifecycle=this.#lifecycle;if(lifecycle.state!=="connecting"||lifecycle.id!==id){transport.close();return}this.#lifecycle={...lifecycle,transport};try{await transport.send(encodeClientMessage({type:"hello",version:PROTOCOL_VERSION},{maxFrameLength:this.#maxFrameLength}))}catch(error){this.#isCurrent(id)&&this.#failAndClose(toDisconnectedError(error))}}#handleData(id,chunk){let lifecycle=this.#lifecycle;if(lifecycle.state==="disconnected"||lifecycle.id!==id)return;if(lifecycle.state==="connecting"&&!lifecycle.transport){this.#failAndClose(new ProtocolValidationError("Received server data before the client hello was sent"));return}let messages;try{messages=lifecycle.decoder.push(chunk)}catch(error){this.#failAndClose(toError(error));return}for(let message of messages){if(this.#lifecycle.state==="disconnected")return;this.#handleMessage(message)}}#handleMessage(message){let lifecycle=this.#lifecycle;if(lifecycle.state==="connecting"){if(message.type==="hello_error"){this.#failAndClose(new ServerError(message.error));return}if(message.type!=="hello"){this.#failAndClose(new ProtocolValidationError("Expected server hello as first message"));return}if(message.serverId!==this.#options.serverId){this.#failAndClose(new ProtocolValidationError(`Connected server ${JSON.stringify(message.serverId)} does not match ${JSON.stringify(this.#options.serverId)}`));return}if(!lifecycle.transport){this.#failAndClose(new ProtocolValidationError("Received server hello before the client hello was sent"));return}let connected={state:"connected",id:lifecycle.id,decoder:lifecycle.decoder,transport:lifecycle.transport,handshake:lifecycle.handshake};this.#lifecycle=connected;try{this.#options.onHandshake(message)}catch(error){this.#lifecycle===connected&&this.#failAndClose(toError(error));return}if(this.#lifecycle!==connected||(this.#options.onStateChange({state:"connected"}),this.#lifecycle!==connected))return;this.#lifecycle={...connected,handshake:void 0},lifecycle.handshake.resolve(message);return}if(lifecycle.state==="connected"){if(message.type==="hello"||message.type==="hello_error"){this.#failAndClose(new ProtocolValidationError("Unexpected handshake message"));return}this.#options.onMessage(message)}}#handleClose(){let lifecycle=this.#lifecycle;if(lifecycle.state==="disconnected")return;let error=new DisconnectedError("Byte transport closed");try{lifecycle.decoder.end()}catch(decoderError){error=toError(decoderError)}this.#fail(error)}#failAndClose(error){let lifecycle=this.#lifecycle,transport=lifecycle.state==="disconnected"?void 0:lifecycle.transport;this.#fail(error),transport?.close()}#fail(error){let lifecycle=this.#lifecycle;lifecycle.state!=="disconnected"&&(this.#lifecycle={state:"disconnected"},lifecycle.handshake?.reject(error),this.#options.onStateChange({state:"disconnected",error}))}#isCurrent(id){return this.#lifecycle.state!=="disconnected"&&this.#lifecycle.id===id}};var Client=class _Client{#options;#connection;#pendingRequests=new Map;#connectionStateListeners=new Set;#attachmentListeners=new Set;#serviceListeners=new Map;#requestSequence=0;#serviceSubscriptionSequence=0;#hello;#attachment;#disposed=!1;#disposePromise;constructor(options){if(!isServerId(options.serverId))throw new TypeError("serverId must be a canonical lowercase UUIDv4");this.#options=options,this.#connection=new Connection({transportFactory:options.transportFactory,serverId:options.serverId,maxFrameLength:options.maxFrameLength,onHandshake:hello=>{this.#hello=hello},onMessage:message=>this.#handleMessage(message),onStateChange:change=>this.#handleConnectionStateChange(change)})}get disposed(){return this.#disposed}get connectionState(){return this.#connection.state}get connected(){return this.#connection.state==="connected"}get serverId(){return this.#options.serverId}get hello(){return this.#hello}get attachment(){return this.#attachment}static async connect(options){let client=new _Client(options);try{return await client.connect(),client}catch(error){throw await client.dispose(),error}}connect(){return this.#disposed?Promise.reject(new ClientDisposedError):(this.#hello=void 0,this.#connection.connect())}reconnect(){return this.connect()}disconnect(reason="Client disconnected"){this.#connection.disconnect(reason)}onConnectionStateChange(listener){return this.#assertNotDisposed(),this.#connectionStateListeners.add(listener),()=>this.#connectionStateListeners.delete(listener)}onAttachmentChange(listener){return this.#assertNotDisposed(),this.#attachmentListeners.add(listener),()=>this.#attachmentListeners.delete(listener)}request(target,call,signal){return this.#request(target,call,signal)}async serviceCatalogue(target,signal){let result=await this.#request(target,createServiceCatalogueCall(),signal);try{return parseServiceCatalogue(result)}catch(error){let validationError=new ProtocolValidationError(error instanceof Error?error.message:"Invalid service catalogue");throw this.#connection.fail(validationError),validationError}}async subscribeService(target,serviceId,mode,listener,signal){let subscriptionId=`service-${++this.#serviceSubscriptionSequence}`,active={target,listener,decoder:createServiceStateDecoder(),queuedWireUpdates:[],queued:[],deliveryTail:Promise.resolve(),hydrated:!1,ready:!1};this.#serviceListeners.set(subscriptionId,active);let snapshot;try{snapshot=await this.#request(target,createServiceSubscribeCall(subscriptionId,serviceId,mode),signal,result=>{let decoded=active.decoder.decodeSnapshot(parseWireServiceSubscriptionSnapshot(result));active.hydrated=!0;for(let update of active.queuedWireUpdates.splice(0))active.queued.push(active.decoder.decodeUpdate(parseWireServiceProviderUpdate(update)));return decoded})}catch(error){throw this.#serviceListeners.get(subscriptionId)===active&&this.#serviceListeners.delete(subscriptionId),error}if(this.#serviceListeners.get(subscriptionId)!==active)throw new DisconnectedError;let disposed=!1;return{id:subscriptionId,target,snapshot,start:()=>{if(!(disposed||active.ready)){active.ready=!0;for(let update of active.queued.splice(0))this.#deliverServiceUpdate(active,update)}},dispose:async()=>{if(!disposed){disposed=!0,this.#serviceListeners.get(subscriptionId)===active&&this.#serviceListeners.delete(subscriptionId);try{this.connected&&this.#targetIsCurrent(target)&&await this.#request(target,createServiceUnsubscribeCall(subscriptionId)),await active.deliveryTail}finally{active.queuedWireUpdates.length=0,active.queued.length=0}}}}}#request(target,call,signal,transform){if(this.#disposed)return Promise.reject(new ClientDisposedError);if(!this.connected)return Promise.reject(new DisconnectedError);if(signal?.aborted)return Promise.reject(abortError(signal));let id=`request-${++this.#requestSequence}`,{promise,resolve,reject}=createPromiseResolvers(),sent=!1,aborted=!1,onAbort,sendCancel=()=>{if(!(!sent||!this.connected))try{this.#connection.send(encodeClientMessage({type:"cancel",id,target},{maxFrameLength:this.#connection.maxFrameLength}))}catch(error){this.#connection.fail(toError(error))}};signal!==void 0&&(onAbort=()=>{aborted||(aborted=!0,reject(abortError(signal)),sendCancel())},signal.addEventListener("abort",onAbort,{once:!0})),this.#pendingRequests.set(id,{resolve:result=>{try{resolve(transform===void 0?result:transform(result))}catch(error){let validationError=new ProtocolValidationError(error instanceof Error?error.message:"Invalid service operation stream");this.#connection.fail(validationError),reject(validationError)}},reject,cleanup:()=>{signal!==void 0&&onAbort!==void 0&&signal.removeEventListener("abort",onAbort)}});let frame;try{frame=encodeClientMessage({type:"request",id,target,call:parseServiceCall(call)},{maxFrameLength:this.#connection.maxFrameLength})}catch(error){return this.#takePendingRequest(id)?.reject(toError(error)),promise}return this.#connection.send(frame),sent=!0,aborted&&sendCancel(),promise}#handleMessage(message){if(message.type==="attachment"){if(message.attachment!==null&&message.attachment.serverId!==this.#options.serverId){this.#connection.fail(new ProtocolValidationError("Attachment update belongs to another server"));return}this.#setAttachment(message.attachment??void 0);return}if(message.type==="service_update"){let active=this.#serviceListeners.get(message.subscriptionId);if(active===void 0)return;if(!active.hydrated){active.queuedWireUpdates.push(message.update);return}let update;try{update=active.decoder.decodeUpdate(parseWireServiceProviderUpdate(message.update))}catch(error){this.#connection.fail(new ProtocolValidationError(error instanceof Error?error.message:"Invalid service operation stream"));return}active.ready?this.#deliverServiceUpdate(active,update):active.queued.push(update);return}let pending=this.#takePendingRequest(message.id);if(!pending){this.#connection.fail(new ProtocolValidationError("Response has no matching request"));return}if(!message.ok){pending.reject(new ServerError(message.error));return}pending.resolve(message.result)}#handleConnectionStateChange(change){change.state==="disconnected"&&(this.#hello=void 0,this.#setAttachment(void 0),this.#rejectPendingRequests(change.error??new DisconnectedError),this.#serviceListeners.clear());for(let listener of this.#connectionStateListeners)try{listener(change)}catch(error){this.#reportListenerError(error)}}#takePendingRequest(id){let request=this.#pendingRequests.get(id);return request&&(this.#pendingRequests.delete(id),request.cleanup()),request}#rejectPendingRequests(error){let requests=[...this.#pendingRequests.values()];this.#pendingRequests.clear();for(let request of requests)request.cleanup(),request.reject(error)}dispose(){if(this.#disposePromise)return this.#disposePromise;this.#disposed=!0,this.#disposePromise=Promise.resolve();let error=new ClientDisposedError;return this.#rejectPendingRequests(error),this.#connection.disconnect(error),this.#hello=void 0,this.#setAttachment(void 0),this.#connectionStateListeners.clear(),this.#attachmentListeners.clear(),this.#serviceListeners.clear(),this.#disposePromise}[Symbol.asyncDispose](){return this.dispose()}#setAttachment(attachment){let previous=this.#attachment;if(!(previous?.serverId===attachment?.serverId&&previous?.sessionId===attachment?.sessionId&&previous?.attachmentId===attachment?.attachmentId)){this.#attachment=attachment;for(let listener of this.#attachmentListeners)try{listener(attachment)}catch(error){this.#reportListenerError(error)}}}#deliverServiceUpdate(active,update){active.deliveryTail=active.deliveryTail.then(()=>active.listener(update)).catch(error=>this.#reportListenerError(error))}#targetIsCurrent(target){if(!("sessionId"in target))return this.#hello?.serverId===target.serverId;let attachment=this.#attachment;return attachment?.serverId===target.serverId&&attachment.sessionId===target.sessionId&&attachment.attachmentId===target.attachmentId}#assertNotDisposed(){if(this.#disposed)throw new ClientDisposedError}#reportListenerError(error){if(this.#options.onListenerError)try{this.#options.onListenerError(toError(error))}catch{}}};function createClientServiceTransport(client,getTarget){let target=()=>{let resolved=getTarget();if(resolved===void 0)throw new Error("Remote service target is unavailable");return resolved};return{invoke:async(call,context)=>client.request(target(),call,context.abortSignal),async subscribe(serviceId,mode,listener,context){let subscription=await client.subscribeService(target(),serviceId,mode,update=>listener(update,BACKGROUND_CONTEXT),context.abortSignal);return{snapshot:subscription.snapshot,activate:()=>subscription.start(),close:()=>subscription.dispose()}}}}function abortError(signal){let reason=signal.reason;return reason instanceof Error?reason:new DOMException("The operation was aborted","AbortError")}export{PROTOCOL_VERSION,isServerId,ProtocolValidationError,encodeServerMessage,ClientMessageDecoder,isSupportedProtocolVersion,ServerError,DisconnectedError,ClientDisposedError,Client,createClientServiceTransport};