octoflow-core 1.0.0 → 1.0.2

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 (226) hide show
  1. package/README.md +29 -0
  2. package/dist/adapters/agents/backends/acp-cli-probe.d.ts +1 -1
  3. package/dist/adapters/agents/backends/acp-cli-probe.d.ts.map +1 -1
  4. package/dist/adapters/agents/backends/acp-cli-probe.js +7 -7
  5. package/dist/adapters/agents/backends/acp-cli-probe.js.map +2 -2
  6. package/dist/adapters/agents/backends/acp-cli.d.ts.map +1 -1
  7. package/dist/adapters/agents/backends/acp-cli.js +12 -12
  8. package/dist/adapters/agents/backends/acp-cli.js.map +2 -2
  9. package/dist/adapters/agents/backends/anthropic-api.d.ts.map +1 -1
  10. package/dist/adapters/agents/backends/anthropic-api.js +76 -94
  11. package/dist/adapters/agents/backends/anthropic-api.js.map +2 -2
  12. package/dist/adapters/agents/backends/api-shared.d.ts +9 -0
  13. package/dist/adapters/agents/backends/api-shared.d.ts.map +1 -1
  14. package/dist/adapters/agents/backends/api-shared.js +13 -0
  15. package/dist/adapters/agents/backends/api-shared.js.map +2 -2
  16. package/dist/adapters/agents/backends/catalog.d.ts +4 -4
  17. package/dist/adapters/agents/backends/catalog.d.ts.map +1 -1
  18. package/dist/adapters/agents/backends/catalog.js +22 -31
  19. package/dist/adapters/agents/backends/catalog.js.map +2 -2
  20. package/dist/adapters/agents/backends/claude-code-cli.d.ts.map +1 -1
  21. package/dist/adapters/agents/backends/claude-code-cli.js +4 -6
  22. package/dist/adapters/agents/backends/claude-code-cli.js.map +2 -2
  23. package/dist/adapters/agents/backends/cli-helpers.d.ts +7 -0
  24. package/dist/adapters/agents/backends/cli-helpers.d.ts.map +1 -1
  25. package/dist/adapters/agents/backends/cli-helpers.js +7 -0
  26. package/dist/adapters/agents/backends/cli-helpers.js.map +2 -2
  27. package/dist/adapters/agents/backends/codex-cli.d.ts.map +1 -1
  28. package/dist/adapters/agents/backends/codex-cli.js +4 -6
  29. package/dist/adapters/agents/backends/codex-cli.js.map +2 -2
  30. package/dist/adapters/agents/backends/cursor-cli.d.ts.map +1 -1
  31. package/dist/adapters/agents/backends/cursor-cli.js +4 -6
  32. package/dist/adapters/agents/backends/cursor-cli.js.map +2 -2
  33. package/dist/adapters/agents/backends/descriptors.d.ts +31 -0
  34. package/dist/adapters/agents/backends/descriptors.d.ts.map +1 -0
  35. package/dist/adapters/agents/backends/descriptors.js +57 -0
  36. package/dist/adapters/agents/backends/descriptors.js.map +7 -0
  37. package/dist/adapters/agents/backends/gemini-api.d.ts.map +1 -1
  38. package/dist/adapters/agents/backends/gemini-api.js +35 -56
  39. package/dist/adapters/agents/backends/gemini-api.js.map +2 -2
  40. package/dist/adapters/agents/backends/gemini-cli.d.ts.map +1 -1
  41. package/dist/adapters/agents/backends/gemini-cli.js +4 -6
  42. package/dist/adapters/agents/backends/gemini-cli.js.map +2 -2
  43. package/dist/adapters/agents/backends/index.d.ts.map +1 -1
  44. package/dist/adapters/agents/backends/index.js +23 -42
  45. package/dist/adapters/agents/backends/index.js.map +2 -2
  46. package/dist/adapters/agents/backends/native-messages/anthropic.d.ts.map +1 -1
  47. package/dist/adapters/agents/backends/native-messages/anthropic.js +2 -1
  48. package/dist/adapters/agents/backends/native-messages/anthropic.js.map +2 -2
  49. package/dist/adapters/agents/backends/native-messages/gemini.d.ts.map +1 -1
  50. package/dist/adapters/agents/backends/native-messages/gemini.js +2 -1
  51. package/dist/adapters/agents/backends/native-messages/gemini.js.map +2 -2
  52. package/dist/adapters/agents/backends/native-messages/index.d.ts +2 -2
  53. package/dist/adapters/agents/backends/native-messages/index.js.map +1 -1
  54. package/dist/adapters/agents/backends/native-messages/ollama.d.ts +2 -0
  55. package/dist/adapters/agents/backends/native-messages/ollama.d.ts.map +1 -1
  56. package/dist/adapters/agents/backends/native-messages/ollama.js +19 -17
  57. package/dist/adapters/agents/backends/native-messages/ollama.js.map +2 -2
  58. package/dist/adapters/agents/backends/native-messages/openai.d.ts +13 -1
  59. package/dist/adapters/agents/backends/native-messages/openai.d.ts.map +1 -1
  60. package/dist/adapters/agents/backends/native-messages/openai.js +34 -12
  61. package/dist/adapters/agents/backends/native-messages/openai.js.map +2 -2
  62. package/dist/adapters/agents/backends/native-messages/shared.d.ts +24 -0
  63. package/dist/adapters/agents/backends/native-messages/shared.d.ts.map +1 -1
  64. package/dist/adapters/agents/backends/native-messages/shared.js +32 -0
  65. package/dist/adapters/agents/backends/native-messages/shared.js.map +2 -2
  66. package/dist/adapters/agents/backends/native-messages/vercel.d.ts.map +1 -1
  67. package/dist/adapters/agents/backends/native-messages/vercel.js +5 -3
  68. package/dist/adapters/agents/backends/native-messages/vercel.js.map +2 -2
  69. package/dist/adapters/agents/backends/openai-api.d.ts.map +1 -1
  70. package/dist/adapters/agents/backends/openai-api.js +41 -55
  71. package/dist/adapters/agents/backends/openai-api.js.map +2 -2
  72. package/dist/adapters/agents/backends/protocol-codecs.d.ts +32 -0
  73. package/dist/adapters/agents/backends/protocol-codecs.d.ts.map +1 -0
  74. package/dist/adapters/agents/backends/protocol-codecs.js +46 -0
  75. package/dist/adapters/agents/backends/protocol-codecs.js.map +7 -0
  76. package/dist/adapters/agents/discover.d.ts.map +1 -1
  77. package/dist/adapters/agents/discover.js +12 -10
  78. package/dist/adapters/agents/discover.js.map +2 -2
  79. package/dist/adapters/agents/ollama/backend.d.ts.map +1 -1
  80. package/dist/adapters/agents/ollama/backend.js +7 -3
  81. package/dist/adapters/agents/ollama/backend.js.map +2 -2
  82. package/dist/adapters/agents/ollama/client.d.ts.map +1 -1
  83. package/dist/adapters/agents/ollama/client.js +7 -2
  84. package/dist/adapters/agents/ollama/client.js.map +2 -2
  85. package/dist/adapters/agents/ollama/errors.d.ts.map +1 -1
  86. package/dist/adapters/agents/ollama/errors.js +4 -0
  87. package/dist/adapters/agents/ollama/errors.js.map +2 -2
  88. package/dist/adapters/agents/runtime/ssh-runner-internal.d.ts +1 -2
  89. package/dist/adapters/agents/runtime/ssh-runner-internal.d.ts.map +1 -1
  90. package/dist/adapters/agents/runtime/ssh-runner-internal.js +2 -2
  91. package/dist/adapters/agents/runtime/ssh-runner-internal.js.map +2 -2
  92. package/dist/adapters/agents/selection.d.ts.map +1 -1
  93. package/dist/adapters/agents/selection.js +7 -7
  94. package/dist/adapters/agents/selection.js.map +2 -2
  95. package/dist/cli/index.cjs +3100 -3120
  96. package/dist/cli/index.cjs.map +4 -4
  97. package/dist/domain/errors/domain.d.ts +2 -0
  98. package/dist/domain/errors/domain.d.ts.map +1 -1
  99. package/dist/domain/errors/domain.js +5 -1
  100. package/dist/domain/errors/domain.js.map +2 -2
  101. package/dist/domain/errors/index.d.ts +1 -1
  102. package/dist/domain/errors/index.d.ts.map +1 -1
  103. package/dist/domain/errors/index.js +5 -1
  104. package/dist/domain/errors/index.js.map +2 -2
  105. package/dist/domain/errors/media.d.ts +15 -0
  106. package/dist/domain/errors/media.d.ts.map +1 -0
  107. package/dist/domain/errors/media.js +25 -0
  108. package/dist/domain/errors/media.js.map +7 -0
  109. package/dist/domain/errors/model.d.ts +12 -0
  110. package/dist/domain/errors/model.d.ts.map +1 -0
  111. package/dist/domain/errors/model.js +21 -0
  112. package/dist/domain/errors/model.js.map +7 -0
  113. package/dist/environments/local.js +3 -2
  114. package/dist/environments/local.js.map +2 -2
  115. package/dist/exports/index-orchestration.d.ts +1 -0
  116. package/dist/exports/index-orchestration.d.ts.map +1 -1
  117. package/dist/exports/index-orchestration.js +2 -0
  118. package/dist/exports/index-orchestration.js.map +2 -2
  119. package/dist/index.cjs +3548 -3366
  120. package/dist/index.cjs.map +4 -4
  121. package/dist/runtime/bridge/agent-handle-types.d.ts +1 -1
  122. package/dist/runtime/bridge/agent-handle-types.d.ts.map +1 -1
  123. package/dist/runtime/bridge/agent-handle.d.ts +1 -1
  124. package/dist/runtime/bridge/agent-handle.d.ts.map +1 -1
  125. package/dist/runtime/bridge/agent-handle.js.map +1 -1
  126. package/dist/runtime/bridge/agent-info-types.d.ts +1 -1
  127. package/dist/runtime/bridge/agent-info-types.d.ts.map +1 -1
  128. package/dist/runtime/bridge/agent-route-types.d.ts +1 -1
  129. package/dist/runtime/bridge/agent-route-types.d.ts.map +1 -1
  130. package/dist/runtime/bridge/anthropic-gateway-converters.d.ts.map +1 -1
  131. package/dist/runtime/bridge/anthropic-gateway-converters.js +4 -6
  132. package/dist/runtime/bridge/anthropic-gateway-converters.js.map +2 -2
  133. package/dist/runtime/bridge/anthropic-gateway.d.ts.map +1 -1
  134. package/dist/runtime/bridge/anthropic-gateway.js +2 -1
  135. package/dist/runtime/bridge/anthropic-gateway.js.map +2 -2
  136. package/dist/runtime/bridge/brain-contract.d.ts +1 -1
  137. package/dist/runtime/bridge/brain-contract.d.ts.map +1 -1
  138. package/dist/runtime/bridge/brain-contract.js.map +1 -1
  139. package/dist/runtime/bridge/brain-plugin.js.map +1 -1
  140. package/dist/runtime/bridge/bridge-class.d.ts.map +1 -1
  141. package/dist/runtime/bridge/bridge-class.js +3 -0
  142. package/dist/runtime/bridge/bridge-class.js.map +2 -2
  143. package/dist/runtime/bridge/create-bridge.d.ts +1 -1
  144. package/dist/runtime/bridge/create-bridge.d.ts.map +1 -1
  145. package/dist/runtime/bridge/create-bridge.js +1 -1
  146. package/dist/runtime/bridge/create-bridge.js.map +1 -1
  147. package/dist/runtime/bridge/fabric-bridge-types.d.ts +1 -1
  148. package/dist/runtime/bridge/fabric-bridge-types.d.ts.map +1 -1
  149. package/dist/runtime/bridge/fabric-plugin.js.map +1 -1
  150. package/dist/runtime/bridge/gateway-converter-utils.d.ts +12 -0
  151. package/dist/runtime/bridge/gateway-converter-utils.d.ts.map +1 -0
  152. package/dist/runtime/bridge/gateway-converter-utils.js +15 -0
  153. package/dist/runtime/bridge/gateway-converter-utils.js.map +7 -0
  154. package/dist/runtime/bridge/gateway-requests/anthropic.d.ts +3 -0
  155. package/dist/runtime/bridge/gateway-requests/anthropic.d.ts.map +1 -0
  156. package/dist/runtime/bridge/gateway-requests/anthropic.js +69 -0
  157. package/dist/runtime/bridge/gateway-requests/anthropic.js.map +7 -0
  158. package/dist/runtime/bridge/gateway-requests/openai.d.ts +5 -0
  159. package/dist/runtime/bridge/gateway-requests/openai.d.ts.map +1 -0
  160. package/dist/runtime/bridge/gateway-requests/openai.js +136 -0
  161. package/dist/runtime/bridge/gateway-requests/openai.js.map +7 -0
  162. package/dist/runtime/bridge/memory-plugin.d.ts +1 -1
  163. package/dist/runtime/bridge/memory-plugin.d.ts.map +1 -1
  164. package/dist/runtime/bridge/memory-plugin.js.map +1 -1
  165. package/dist/runtime/bridge/named-agents.js.map +1 -1
  166. package/dist/runtime/bridge/openai-gateway-converters.d.ts.map +1 -1
  167. package/dist/runtime/bridge/openai-gateway-converters.js +5 -9
  168. package/dist/runtime/bridge/openai-gateway-converters.js.map +2 -2
  169. package/dist/runtime/bridge/openai-gateway.d.ts.map +1 -1
  170. package/dist/runtime/bridge/openai-gateway.js +9 -4
  171. package/dist/runtime/bridge/openai-gateway.js.map +2 -2
  172. package/dist/runtime/bridge/plugins.d.ts +1 -1
  173. package/dist/runtime/bridge/plugins.d.ts.map +1 -1
  174. package/dist/runtime/bridge/plugins.js.map +1 -1
  175. package/dist/runtime/bridge/quickstart.d.ts +1 -1
  176. package/dist/runtime/bridge/quickstart.d.ts.map +1 -1
  177. package/dist/runtime/bridge/quickstart.js.map +1 -1
  178. package/dist/runtime/bridge/runtime-plugin-support.d.ts +1 -1
  179. package/dist/runtime/bridge/runtime-plugin-support.d.ts.map +1 -1
  180. package/dist/runtime/bridge/runtime-plugin-support.js.map +1 -1
  181. package/dist/runtime/bridge/session.d.ts +1 -1
  182. package/dist/runtime/bridge/session.d.ts.map +1 -1
  183. package/dist/runtime/bridge/session.js.map +1 -1
  184. package/dist/runtime/bridge/task-runner-execution-helpers.d.ts +50 -0
  185. package/dist/runtime/bridge/task-runner-execution-helpers.d.ts.map +1 -0
  186. package/dist/runtime/bridge/task-runner-execution-helpers.js +90 -0
  187. package/dist/runtime/bridge/task-runner-execution-helpers.js.map +7 -0
  188. package/dist/runtime/bridge/task-runner-execution.d.ts.map +1 -1
  189. package/dist/runtime/bridge/task-runner-execution.js +4 -83
  190. package/dist/runtime/bridge/task-runner-execution.js.map +2 -2
  191. package/dist/runtime/bridge/validate-send-params.d.ts +9 -0
  192. package/dist/runtime/bridge/validate-send-params.d.ts.map +1 -0
  193. package/dist/runtime/bridge/validate-send-params.js +11 -0
  194. package/dist/runtime/bridge/validate-send-params.js.map +7 -0
  195. package/dist/runtime/orchestration/pack/dispatch-worker.d.ts +1 -1
  196. package/dist/runtime/orchestration/pack/dispatch-worker.d.ts.map +1 -1
  197. package/dist/runtime/orchestration/pack/dispatch-worker.js +1 -1
  198. package/dist/runtime/orchestration/pack/dispatch-worker.js.map +2 -2
  199. package/dist/runtime/orchestration/pack/helpers.d.ts +1 -1
  200. package/dist/runtime/orchestration/pack/helpers.d.ts.map +1 -1
  201. package/dist/runtime/orchestration/pack/helpers.js.map +1 -1
  202. package/dist/runtime/orchestration/pack/pack-workers.d.ts +1 -1
  203. package/dist/runtime/orchestration/pack/pack-workers.d.ts.map +1 -1
  204. package/dist/runtime/orchestration/pack/pack-workers.js +1 -1
  205. package/dist/runtime/orchestration/pack/pack-workers.js.map +1 -1
  206. package/dist/runtime/orchestration/pack/pack.d.ts +3 -2
  207. package/dist/runtime/orchestration/pack/pack.d.ts.map +1 -1
  208. package/dist/runtime/orchestration/pack/pack.js +1 -1
  209. package/dist/runtime/orchestration/pack/pack.js.map +2 -2
  210. package/dist/runtime/orchestration/pack/types.d.ts +1 -1
  211. package/dist/runtime/orchestration/pack/types.d.ts.map +1 -1
  212. package/dist/runtime/orchestration/pack/types.js.map +1 -1
  213. package/dist/runtime/orchestration/pack.cjs +3203 -3223
  214. package/dist/runtime/orchestration/pack.cjs.map +4 -4
  215. package/dist/runtime/orchestration/run/extract-run-text.d.ts +9 -0
  216. package/dist/runtime/orchestration/run/extract-run-text.d.ts.map +1 -0
  217. package/dist/runtime/orchestration/run/extract-run-text.js +17 -0
  218. package/dist/runtime/orchestration/run/extract-run-text.js.map +7 -0
  219. package/dist/subpath-a2a.cjs +3153 -3172
  220. package/dist/subpath-a2a.cjs.map +4 -4
  221. package/dist/subpath-environments.cjs +3 -2
  222. package/dist/subpath-environments.cjs.map +2 -2
  223. package/dist/subpath-ssh.cjs +3 -3
  224. package/dist/subpath-ssh.cjs.map +2 -2
  225. package/dist/testing.cjs.map +2 -2
  226. package/package.json +5 -5
package/README.md CHANGED
@@ -238,6 +238,35 @@ const agent = await createAgent({
238
238
  // to `env.exec(...)`, so shell calls run inside the container.
239
239
  ```
240
240
 
241
+ ## Bundling & CJS / Electron consumers
242
+
243
+ `octoflow-core` ships both ESM (`dist/index.js`) and CommonJS (`dist/index.cjs`)
244
+ entries and works in Node, Electron, and bundled apps. A few notes for bundlers
245
+ (Vite, esbuild/tsup, webpack), especially Electron main processes:
246
+
247
+ - **Externalize native deps.** Some backends pull native modules
248
+ (`better-sqlite3`, and — only when you use the SSH runner — `ssh2` /
249
+ `cpu-features`). Bundlers can't inline `.node` binaries. Mark them external so
250
+ they're required from `node_modules` at runtime:
251
+
252
+ ```ts
253
+ // vite main config / tsup config
254
+ external: ['octoflow-core', 'ssh2', 'cpu-features', 'better-sqlite3', /^node:/]
255
+ ```
256
+
257
+ `ssh2`/`cpu-features` are loaded lazily (only when an SSH runner connects), so
258
+ if you never use SSH they're never required — but listing them as external is
259
+ still the safe default for bundlers that eagerly resolve.
260
+
261
+ - **ESM-only optional deps are lazy.** The ACP CLI backend depends on the
262
+ ESM-only `@agentclientprotocol/sdk`; it is imported via dynamic `import()` at
263
+ connect time, so loading `octoflow-core` (including its CJS entry) never
264
+ `require()`s an ESM module. No special handling needed.
265
+
266
+ - **Electron main is CommonJS-friendly.** `require('octoflow-core')` works out of
267
+ the box. If you prefer the ESM build from a CJS bundle, load it with a dynamic
268
+ `import()` the bundler won't downlevel (e.g. `new Function('m','return import(m)')`).
269
+
241
270
  ## Learn More
242
271
 
243
272
  - [`../../docs/api.md`](../../docs/api.md) - public API guide.
@@ -1,4 +1,4 @@
1
- import { ClientSideConnection } from '@agentclientprotocol/sdk';
1
+ import type { ClientSideConnection } from '@agentclientprotocol/sdk';
2
2
  import { type AcpCliBackendConfig, type AcpConfigOption, type AcpMcpServerSpec, type AcpSessionInfo } from './acp-cli-helpers.js';
3
3
  export type { AcpConfigOption, AcpSessionInfo };
4
4
  /** Result of a successful `session/fork` operation. */
@@ -1 +1 @@
1
- {"version":3,"file":"acp-cli-probe.d.ts","sourceRoot":"","sources":["../../../../src/adapters/agents/backends/acp-cli-probe.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,oBAAoB,EAGrB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EAQpB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;AAEhD,uDAAuD;AACvD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,eAAe,EAAE,CAAC;CACnC,CAAC;AAMF;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,oBAAoB,EAChC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAAE,GACvD,OAAO,CAAC,gBAAgB,CAAC,CAqB3B;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,GAAG,aAAa,CAAC;IACzC,YAAY,EAAE,WAAW,GAAG,aAAa,CAAC;IAC1C,aAAa,EAAE,WAAW,GAAG,aAAa,CAAC;IAC3C,4DAA4D;IAC5D,WAAW,EAAE,WAAW,GAAG,aAAa,CAAC;IACzC,aAAa,EAAE,WAAW,GAAG,aAAa,CAAC;IAC3C,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC;IACrC,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC;IACpC,qFAAqF;IACrF,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAiBF;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,GAAE,mBAAwB,EAChC,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,mBAAmB,CAAC,CA2E9B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,GAAE,mBAAwB,EAChC,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3D,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAoClF"}
1
+ {"version":3,"file":"acp-cli-probe.d.ts","sourceRoot":"","sources":["../../../../src/adapters/agents/backends/acp-cli-probe.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,oBAAoB,EAErB,MAAM,0BAA0B,CAAC;AAOlC,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,cAAc,EAQpB,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;AAEhD,uDAAuD;AACvD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,sCAAsC;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,eAAe,EAAE,CAAC;CACnC,CAAC;AAMF;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,UAAU,EAAE,oBAAoB,EAChC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAAE,GACvD,OAAO,CAAC,gBAAgB,CAAC,CAqB3B;AAED;;;GAGG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,WAAW,EAAE,WAAW,GAAG,aAAa,CAAC;IACzC,YAAY,EAAE,WAAW,GAAG,aAAa,CAAC;IAC1C,aAAa,EAAE,WAAW,GAAG,aAAa,CAAC;IAC3C,4DAA4D;IAC5D,WAAW,EAAE,WAAW,GAAG,aAAa,CAAC;IACzC,aAAa,EAAE,WAAW,GAAG,aAAa,CAAC;IAC3C,OAAO,EAAE,WAAW,GAAG,aAAa,CAAC;IACrC,MAAM,EAAE,WAAW,GAAG,aAAa,CAAC;IACpC,qFAAqF;IACrF,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAiBF;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,GAAE,mBAAwB,EAChC,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,mBAAmB,CAAC,CA6E9B;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,GAAE,mBAAwB,EAChC,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3D,OAAO,CAAC;IAAE,QAAQ,EAAE,cAAc,EAAE,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAsClF"}
@@ -1,10 +1,8 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { Readable, Writable } from "node:stream";
3
- import {
4
- ClientSideConnection,
5
- ndJsonStream,
6
- PROTOCOL_VERSION
7
- } from "@agentclientprotocol/sdk";
3
+ const importAcpSdk = () => import("@agentclientprotocol/sdk");
4
+ let acpSdkPromise = null;
5
+ const loadAcpSdk = () => acpSdkPromise ??= importAcpSdk();
8
6
  import {
9
7
  closeAcpSessionIfSupported,
10
8
  HANDSHAKE_TIMEOUT_MS,
@@ -45,6 +43,7 @@ function makeNullClient() {
45
43
  };
46
44
  }
47
45
  async function probeAcpCapabilities(config = {}, opts) {
46
+ const { ndJsonStream, ClientSideConnection: ClientSideConnectionCtor, PROTOCOL_VERSION } = await loadAcpSdk();
48
47
  const { cmd, cmdArgs } = resolveCommand(config);
49
48
  const timeoutMs = opts?.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;
50
49
  const sessionCwd = opts?.cwd ?? process.cwd();
@@ -57,7 +56,7 @@ async function probeAcpCapabilities(config = {}, opts) {
57
56
  Writable.toWeb(child.stdin),
58
57
  Readable.toWeb(child.stdout)
59
58
  );
60
- const connection = new ClientSideConnection(makeNullClient, stream);
59
+ const connection = new ClientSideConnectionCtor(makeNullClient, stream);
61
60
  const initResult = await withAcpTimeout(
62
61
  connection.initialize({
63
62
  protocolVersion: PROTOCOL_VERSION,
@@ -111,6 +110,7 @@ async function probeAcpCapabilities(config = {}, opts) {
111
110
  }
112
111
  }
113
112
  async function listAcpSessions(config = {}, opts) {
113
+ const { ndJsonStream, ClientSideConnection: ClientSideConnectionCtor, PROTOCOL_VERSION } = await loadAcpSdk();
114
114
  const { cmd, cmdArgs } = resolveCommand(config);
115
115
  const timeoutMs = opts?.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;
116
116
  const child = spawn(cmd, cmdArgs, {
@@ -122,7 +122,7 @@ async function listAcpSessions(config = {}, opts) {
122
122
  Writable.toWeb(child.stdin),
123
123
  Readable.toWeb(child.stdout)
124
124
  );
125
- const connection = new ClientSideConnection(makeNullClient, stream);
125
+ const connection = new ClientSideConnectionCtor(makeNullClient, stream);
126
126
  const initResult = await withAcpTimeout(
127
127
  connection.initialize({
128
128
  protocolVersion: PROTOCOL_VERSION,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/adapters/agents/backends/acp-cli-probe.ts"],
4
- "sourcesContent": ["import { spawn } from 'node:child_process';\nimport { Readable, Writable } from 'node:stream';\n\nimport type { NewSessionResponse } from '@agentclientprotocol/sdk';\nimport {\n ClientSideConnection,\n ndJsonStream,\n PROTOCOL_VERSION,\n} from '@agentclientprotocol/sdk';\n\nimport {\n type AcpCliBackendConfig,\n type AcpConfigOption,\n type AcpMcpServerSpec,\n type AcpSessionInfo,\n closeAcpSessionIfSupported,\n HANDSHAKE_TIMEOUT_MS,\n listAcpSessionsViaConnection,\n parseAcpConfigOptions,\n resolveAcpAgentCapabilities,\n resolveAcpAgentCommand,\n withAcpTimeout,\n} from './acp-cli-helpers.js';\n\nexport type { AcpConfigOption, AcpSessionInfo };\n\n/** Result of a successful `session/fork` operation. */\nexport type AcpForkedSession = {\n /** ID of the newly forked session. */\n sessionId: string;\n /** Config options reported by the agent for the forked session, if any. */\n configOptions?: AcpConfigOption[];\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Calls the unstable `session/fork` on an already-initialized connection.\n * Throws if the agent does not implement `unstable_forkSession`.\n */\nexport async function forkAcpSessionViaConnection(\n connection: ClientSideConnection,\n sessionId: string,\n opts?: { cwd?: string; mcpServers?: AcpMcpServerSpec[] }\n): Promise<AcpForkedSession> {\n type MaybeFork = ClientSideConnection & {\n unstable_forkSession?: (params: {\n sessionId: string;\n cwd: string;\n mcpServers?: AcpMcpServerSpec[];\n }) => Promise<unknown>;\n };\n const maybeFork = (connection as MaybeFork).unstable_forkSession;\n if (!maybeFork) throw new Error('session/fork is not supported by this agent');\n const resp = await maybeFork.call(connection, {\n sessionId,\n cwd: opts?.cwd ?? process.cwd(),\n ...(opts?.mcpServers ? { mcpServers: opts.mcpServers } : {}),\n });\n const rawId = isRecord(resp) && typeof resp['sessionId'] === 'string' ? resp['sessionId'] : '';\n const configOptions = parseAcpConfigOptions(resp);\n return {\n sessionId: rawId,\n ...(configOptions.length > 0 ? { configOptions } : {}),\n };\n}\n\n/**\n * Result of a full ACP capability probe against a running agent.\n * Each surface is either `'supported'` or `'unsupported'`.\n */\nexport type AcpCapabilityMatrix = {\n protocolVersion: number | null;\n sessionList: 'supported' | 'unsupported';\n sessionClose: 'supported' | 'unsupported';\n sessionResume: 'supported' | 'unsupported';\n /** Whether the agent supports `session/fork` (unstable). */\n sessionFork: 'supported' | 'unsupported';\n configOptions: 'supported' | 'unsupported';\n mcpHttp: 'supported' | 'unsupported';\n mcpSse: 'supported' | 'unsupported';\n /** Sessions returned by `session/list` (only when `sessionList === 'supported'`). */\n sessions?: AcpSessionInfo[];\n sessionNextCursor?: string;\n /** Config options returned by `session/new` (only when `configOptions === 'supported'`). */\n options?: AcpConfigOption[];\n};\n\nfunction resolveCommand(config: AcpCliBackendConfig): { cmd: string; cmdArgs: string[] } {\n if (config.command) return { cmd: config.command, cmdArgs: config.args ?? [] };\n const agent = config.agent ?? process.env.ACP_AGENT ?? 'claude';\n const { command: cmd, args: cmdArgs } = resolveAcpAgentCommand(agent, config.agentOverrides);\n return { cmd, cmdArgs };\n}\n\nfunction makeNullClient() {\n return {\n sessionUpdate: () => Promise.resolve(),\n requestPermission: () =>\n Promise.resolve({ outcome: { outcome: 'cancelled' as const } }),\n };\n}\n\n/**\n * Spawns the ACP agent, runs a full capability probe, and returns a\n * {@link AcpCapabilityMatrix} describing which optional protocol surfaces\n * the agent supports. No prompts are sent; the probe only calls\n * `initialize`, optionally `session/list`, `session/new` (to read\n * `configOptions`), and `session/close`.\n */\nexport async function probeAcpCapabilities(\n config: AcpCliBackendConfig = {},\n opts?: { cwd?: string; timeoutMs?: number }\n): Promise<AcpCapabilityMatrix> {\n const { cmd, cmdArgs } = resolveCommand(config);\n const timeoutMs = opts?.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;\n const sessionCwd = opts?.cwd ?? process.cwd();\n\n const child = spawn(cmd, cmdArgs, {\n stdio: ['pipe', 'pipe', 'inherit'],\n env: process.env,\n });\n\n try {\n const stream = ndJsonStream(\n Writable.toWeb(child.stdin) as WritableStream<Uint8Array>,\n Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>\n );\n const connection = new ClientSideConnection(makeNullClient, stream);\n\n const initResult: unknown = await withAcpTimeout<unknown>(\n connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {},\n clientInfo: { name: 'octoflow-core', title: 'OctoFlow', version: '1.0.0' },\n }),\n timeoutMs\n );\n\n const caps = resolveAcpAgentCapabilities(initResult);\n\n const matrix: AcpCapabilityMatrix = {\n protocolVersion: caps.protocolVersion,\n sessionList: caps.canListSessions ? 'supported' : 'unsupported',\n sessionClose: caps.canCloseSession ? 'supported' : 'unsupported',\n sessionResume: caps.canResumeSession ? 'supported' : 'unsupported',\n sessionFork: caps.canForkSession ? 'supported' : 'unsupported',\n configOptions: 'unsupported',\n mcpHttp: caps.supportsMcpHttp ? 'supported' : 'unsupported',\n mcpSse: caps.supportsMcpSse ? 'supported' : 'unsupported',\n };\n\n if (caps.canListSessions) {\n const listed = await withAcpTimeout(\n listAcpSessionsViaConnection(connection, { cwd: sessionCwd }),\n timeoutMs\n ).catch(() => null);\n if (listed) {\n matrix.sessions = listed.sessions;\n if (listed.nextCursor) matrix.sessionNextCursor = listed.nextCursor;\n }\n }\n\n const sessionResp: unknown = await withAcpTimeout<unknown>(\n connection.newSession({ cwd: sessionCwd, mcpServers: [] }),\n timeoutMs\n ).catch(() => null);\n\n if (sessionResp) {\n const sessionId = (sessionResp as NewSessionResponse).sessionId ?? '';\n const rawOptions = parseAcpConfigOptions(sessionResp);\n if (rawOptions.length > 0) {\n matrix.configOptions = 'supported';\n matrix.options = rawOptions;\n }\n\n if (caps.canCloseSession && sessionId) {\n await withAcpTimeout(\n closeAcpSessionIfSupported(connection, sessionId, true),\n 2_000\n ).catch(() => undefined);\n }\n }\n\n return matrix;\n } finally {\n if (!child.killed) child.kill();\n }\n}\n\n/**\n * Lists sessions known to the ACP agent. Spawns a fresh process, calls\n * `initialize` + `session/list`, then terminates it.\n *\n * Returns `{ supported: false }` when the agent does not advertise the\n * `session/list` capability.\n */\nexport async function listAcpSessions(\n config: AcpCliBackendConfig = {},\n opts?: { cwd?: string; cursor?: string; timeoutMs?: number }\n): Promise<{ sessions: AcpSessionInfo[]; nextCursor?: string; supported: boolean }> {\n const { cmd, cmdArgs } = resolveCommand(config);\n const timeoutMs = opts?.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;\n\n const child = spawn(cmd, cmdArgs, {\n stdio: ['pipe', 'pipe', 'inherit'],\n env: process.env,\n });\n\n try {\n const stream = ndJsonStream(\n Writable.toWeb(child.stdin) as WritableStream<Uint8Array>,\n Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>\n );\n const connection = new ClientSideConnection(makeNullClient, stream);\n\n const initResult: unknown = await withAcpTimeout<unknown>(\n connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {},\n clientInfo: { name: 'octoflow-core', title: 'OctoFlow', version: '1.0.0' },\n }),\n timeoutMs\n );\n\n const caps = resolveAcpAgentCapabilities(initResult);\n if (!caps.canListSessions) return { sessions: [], supported: false };\n\n const result = await withAcpTimeout(\n listAcpSessionsViaConnection(connection, { cwd: opts?.cwd, cursor: opts?.cursor }),\n timeoutMs\n );\n return { ...result, supported: true };\n } finally {\n if (!child.killed) child.kill();\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { spawn } from 'node:child_process';\nimport { Readable, Writable } from 'node:stream';\n\n// Type-only import: `@agentclientprotocol/sdk` is ESM-only and loaded lazily at\n// runtime (see `loadAcpSdk`) so octoflow-core's CommonJS entry never `require()`s\n// an ESM module at load time.\nimport type {\n ClientSideConnection,\n NewSessionResponse,\n} from '@agentclientprotocol/sdk';\n\nconst importAcpSdk = () => import('@agentclientprotocol/sdk');\nlet acpSdkPromise: ReturnType<typeof importAcpSdk> | null = null;\nconst loadAcpSdk = (): ReturnType<typeof importAcpSdk> =>\n (acpSdkPromise ??= importAcpSdk());\n\nimport {\n type AcpCliBackendConfig,\n type AcpConfigOption,\n type AcpMcpServerSpec,\n type AcpSessionInfo,\n closeAcpSessionIfSupported,\n HANDSHAKE_TIMEOUT_MS,\n listAcpSessionsViaConnection,\n parseAcpConfigOptions,\n resolveAcpAgentCapabilities,\n resolveAcpAgentCommand,\n withAcpTimeout,\n} from './acp-cli-helpers.js';\n\nexport type { AcpConfigOption, AcpSessionInfo };\n\n/** Result of a successful `session/fork` operation. */\nexport type AcpForkedSession = {\n /** ID of the newly forked session. */\n sessionId: string;\n /** Config options reported by the agent for the forked session, if any. */\n configOptions?: AcpConfigOption[];\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Calls the unstable `session/fork` on an already-initialized connection.\n * Throws if the agent does not implement `unstable_forkSession`.\n */\nexport async function forkAcpSessionViaConnection(\n connection: ClientSideConnection,\n sessionId: string,\n opts?: { cwd?: string; mcpServers?: AcpMcpServerSpec[] }\n): Promise<AcpForkedSession> {\n type MaybeFork = ClientSideConnection & {\n unstable_forkSession?: (params: {\n sessionId: string;\n cwd: string;\n mcpServers?: AcpMcpServerSpec[];\n }) => Promise<unknown>;\n };\n const maybeFork = (connection as MaybeFork).unstable_forkSession;\n if (!maybeFork) throw new Error('session/fork is not supported by this agent');\n const resp = await maybeFork.call(connection, {\n sessionId,\n cwd: opts?.cwd ?? process.cwd(),\n ...(opts?.mcpServers ? { mcpServers: opts.mcpServers } : {}),\n });\n const rawId = isRecord(resp) && typeof resp['sessionId'] === 'string' ? resp['sessionId'] : '';\n const configOptions = parseAcpConfigOptions(resp);\n return {\n sessionId: rawId,\n ...(configOptions.length > 0 ? { configOptions } : {}),\n };\n}\n\n/**\n * Result of a full ACP capability probe against a running agent.\n * Each surface is either `'supported'` or `'unsupported'`.\n */\nexport type AcpCapabilityMatrix = {\n protocolVersion: number | null;\n sessionList: 'supported' | 'unsupported';\n sessionClose: 'supported' | 'unsupported';\n sessionResume: 'supported' | 'unsupported';\n /** Whether the agent supports `session/fork` (unstable). */\n sessionFork: 'supported' | 'unsupported';\n configOptions: 'supported' | 'unsupported';\n mcpHttp: 'supported' | 'unsupported';\n mcpSse: 'supported' | 'unsupported';\n /** Sessions returned by `session/list` (only when `sessionList === 'supported'`). */\n sessions?: AcpSessionInfo[];\n sessionNextCursor?: string;\n /** Config options returned by `session/new` (only when `configOptions === 'supported'`). */\n options?: AcpConfigOption[];\n};\n\nfunction resolveCommand(config: AcpCliBackendConfig): { cmd: string; cmdArgs: string[] } {\n if (config.command) return { cmd: config.command, cmdArgs: config.args ?? [] };\n const agent = config.agent ?? process.env.ACP_AGENT ?? 'claude';\n const { command: cmd, args: cmdArgs } = resolveAcpAgentCommand(agent, config.agentOverrides);\n return { cmd, cmdArgs };\n}\n\nfunction makeNullClient() {\n return {\n sessionUpdate: () => Promise.resolve(),\n requestPermission: () =>\n Promise.resolve({ outcome: { outcome: 'cancelled' as const } }),\n };\n}\n\n/**\n * Spawns the ACP agent, runs a full capability probe, and returns a\n * {@link AcpCapabilityMatrix} describing which optional protocol surfaces\n * the agent supports. No prompts are sent; the probe only calls\n * `initialize`, optionally `session/list`, `session/new` (to read\n * `configOptions`), and `session/close`.\n */\nexport async function probeAcpCapabilities(\n config: AcpCliBackendConfig = {},\n opts?: { cwd?: string; timeoutMs?: number }\n): Promise<AcpCapabilityMatrix> {\n const { ndJsonStream, ClientSideConnection: ClientSideConnectionCtor, PROTOCOL_VERSION } =\n await loadAcpSdk();\n const { cmd, cmdArgs } = resolveCommand(config);\n const timeoutMs = opts?.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;\n const sessionCwd = opts?.cwd ?? process.cwd();\n\n const child = spawn(cmd, cmdArgs, {\n stdio: ['pipe', 'pipe', 'inherit'],\n env: process.env,\n });\n\n try {\n const stream = ndJsonStream(\n Writable.toWeb(child.stdin) as WritableStream<Uint8Array>,\n Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>\n );\n const connection = new ClientSideConnectionCtor(makeNullClient, stream);\n\n const initResult: unknown = await withAcpTimeout<unknown>(\n connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {},\n clientInfo: { name: 'octoflow-core', title: 'OctoFlow', version: '1.0.0' },\n }),\n timeoutMs\n );\n\n const caps = resolveAcpAgentCapabilities(initResult);\n\n const matrix: AcpCapabilityMatrix = {\n protocolVersion: caps.protocolVersion,\n sessionList: caps.canListSessions ? 'supported' : 'unsupported',\n sessionClose: caps.canCloseSession ? 'supported' : 'unsupported',\n sessionResume: caps.canResumeSession ? 'supported' : 'unsupported',\n sessionFork: caps.canForkSession ? 'supported' : 'unsupported',\n configOptions: 'unsupported',\n mcpHttp: caps.supportsMcpHttp ? 'supported' : 'unsupported',\n mcpSse: caps.supportsMcpSse ? 'supported' : 'unsupported',\n };\n\n if (caps.canListSessions) {\n const listed = await withAcpTimeout(\n listAcpSessionsViaConnection(connection, { cwd: sessionCwd }),\n timeoutMs\n ).catch(() => null);\n if (listed) {\n matrix.sessions = listed.sessions;\n if (listed.nextCursor) matrix.sessionNextCursor = listed.nextCursor;\n }\n }\n\n const sessionResp: unknown = await withAcpTimeout<unknown>(\n connection.newSession({ cwd: sessionCwd, mcpServers: [] }),\n timeoutMs\n ).catch(() => null);\n\n if (sessionResp) {\n const sessionId = (sessionResp as NewSessionResponse).sessionId ?? '';\n const rawOptions = parseAcpConfigOptions(sessionResp);\n if (rawOptions.length > 0) {\n matrix.configOptions = 'supported';\n matrix.options = rawOptions;\n }\n\n if (caps.canCloseSession && sessionId) {\n await withAcpTimeout(\n closeAcpSessionIfSupported(connection, sessionId, true),\n 2_000\n ).catch(() => undefined);\n }\n }\n\n return matrix;\n } finally {\n if (!child.killed) child.kill();\n }\n}\n\n/**\n * Lists sessions known to the ACP agent. Spawns a fresh process, calls\n * `initialize` + `session/list`, then terminates it.\n *\n * Returns `{ supported: false }` when the agent does not advertise the\n * `session/list` capability.\n */\nexport async function listAcpSessions(\n config: AcpCliBackendConfig = {},\n opts?: { cwd?: string; cursor?: string; timeoutMs?: number }\n): Promise<{ sessions: AcpSessionInfo[]; nextCursor?: string; supported: boolean }> {\n const { ndJsonStream, ClientSideConnection: ClientSideConnectionCtor, PROTOCOL_VERSION } =\n await loadAcpSdk();\n const { cmd, cmdArgs } = resolveCommand(config);\n const timeoutMs = opts?.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;\n\n const child = spawn(cmd, cmdArgs, {\n stdio: ['pipe', 'pipe', 'inherit'],\n env: process.env,\n });\n\n try {\n const stream = ndJsonStream(\n Writable.toWeb(child.stdin) as WritableStream<Uint8Array>,\n Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>\n );\n const connection = new ClientSideConnectionCtor(makeNullClient, stream);\n\n const initResult: unknown = await withAcpTimeout<unknown>(\n connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {},\n clientInfo: { name: 'octoflow-core', title: 'OctoFlow', version: '1.0.0' },\n }),\n timeoutMs\n );\n\n const caps = resolveAcpAgentCapabilities(initResult);\n if (!caps.canListSessions) return { sessions: [], supported: false };\n\n const result = await withAcpTimeout(\n listAcpSessionsViaConnection(connection, { cwd: opts?.cwd, cursor: opts?.cursor }),\n timeoutMs\n );\n return { ...result, supported: true };\n } finally {\n if (!child.killed) child.kill();\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"acp-cli.d.ts","sourceRoot":"","sources":["../../../../src/adapters/agents/backends/acp-cli.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EACV,OAAO,EAKR,MAAM,uCAAuC,CAAC;AAS/C,OAAO,EACL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAEpB,KAAK,cAAc,EAKnB,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EAGrB,sBAAsB,EACtB,+BAA+B,EAC/B,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAO9B,YAAY,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACnH,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,+BAA+B,EAC/B,kBAAkB,GACnB,CAAC;AACF,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAkPxG,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,mBAAwB,GAAG,OAAO,CAiE7E"}
1
+ {"version":3,"file":"acp-cli.d.ts","sourceRoot":"","sources":["../../../../src/adapters/agents/backends/acp-cli.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,OAAO,EAKR,MAAM,uCAAuC,CAAC;AAS/C,OAAO,EACL,kBAAkB,EAClB,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAEpB,KAAK,cAAc,EAKnB,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EAGrB,sBAAsB,EACtB,+BAA+B,EAC/B,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAI9B,YAAY,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AACnH,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAChF,YAAY,EAAE,mBAAmB,EAAE,eAAe,EAAE,cAAc,EAAE,CAAC;AACrE,OAAO,EACL,kBAAkB,EAClB,4BAA4B,EAC5B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,+BAA+B,EAC/B,kBAAkB,GACnB,CAAC;AACF,OAAO,EAAE,2BAA2B,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AA6PxG,wBAAgB,mBAAmB,CAAC,MAAM,GAAE,mBAAwB,GAAG,OAAO,CAiE7E"}
@@ -1,11 +1,6 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import crypto from "node:crypto";
3
3
  import { Readable, Writable } from "node:stream";
4
- import {
5
- ClientSideConnection,
6
- ndJsonStream,
7
- PROTOCOL_VERSION
8
- } from "@agentclientprotocol/sdk";
9
4
  import { APPROVAL_POSTURE_ACP_CLI } from "../approval-posture.js";
10
5
  import {
11
6
  buildElicitationCapabilities,
@@ -27,11 +22,8 @@ import {
27
22
  toAcpToolLocations,
28
23
  withAcpTimeout
29
24
  } from "./acp-cli-helpers.js";
30
- import {
31
- BACKEND_METADATA,
32
- createCliBackendBase,
33
- isCliInstalledAsync
34
- } from "./shared.js";
25
+ import { getBackendDescriptor } from "./descriptors.js";
26
+ import { createCliBackendBase, isCliInstalledAsync } from "./shared.js";
35
27
  import { forkAcpSessionViaConnection, listAcpSessions, probeAcpCapabilities } from "./acp-cli-probe.js";
36
28
  const AGENT_MODELS = {
37
29
  claude: ["opus", "sonnet", "haiku"],
@@ -49,7 +41,15 @@ function wrapAcpAgentError(err, agentCommand) {
49
41
  }
50
42
  return err instanceof Error ? err : new Error(msg);
51
43
  }
44
+ const importAcpSdk = () => import("@agentclientprotocol/sdk");
45
+ let acpSdkPromise = null;
46
+ const loadAcpSdk = () => acpSdkPromise ??= importAcpSdk();
52
47
  async function* runAcpSession(command, spawnArgs, request, options, onElicitation) {
48
+ const {
49
+ ndJsonStream,
50
+ ClientSideConnection: ClientSideConnectionCtor,
51
+ PROTOCOL_VERSION
52
+ } = await loadAcpSdk();
53
53
  const sessionCwd = options.cwd ?? process.cwd();
54
54
  const mcpServers = readAcpMcpServers(request.mcpConfigPath, sessionCwd);
55
55
  const child = spawn(command, spawnArgs, {
@@ -90,7 +90,7 @@ async function* runAcpSession(command, spawnArgs, request, options, onElicitatio
90
90
  },
91
91
  unstable_createElicitation: (params) => dispatchElicitation(params, onElicitation, push)
92
92
  };
93
- const connection = new ClientSideConnection(() => client, stream);
93
+ const connection = new ClientSideConnectionCtor(() => client, stream);
94
94
  const onAbort = () => {
95
95
  if (currentSessionId) {
96
96
  void connection.cancel({ sessionId: currentSessionId }).catch(() => void 0);
@@ -215,7 +215,7 @@ async function* runAcpSession(command, spawnArgs, request, options, onElicitatio
215
215
  if (!child.killed) child.kill();
216
216
  }
217
217
  }
218
- const META = BACKEND_METADATA["acp-cli"];
218
+ const META = getBackendDescriptor("acp-cli").meta;
219
219
  const CAPABILITIES = {
220
220
  streaming: true,
221
221
  sessionPersistence: true,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/adapters/agents/backends/acp-cli.ts"],
4
- "sourcesContent": ["import { spawn } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport { Readable, Writable } from 'node:stream';\n\nimport {\n type Client,\n ClientSideConnection,\n type CreateElicitationRequest,\n type CreateElicitationResponse,\n ndJsonStream,\n type NewSessionResponse,\n type PromptResponse,\n PROTOCOL_VERSION,\n type RequestPermissionRequest,\n type RequestPermissionResponse,\n type SessionNotification,\n} from '@agentclientprotocol/sdk';\n\nimport type {\n Backend,\n BackendCapabilities,\n BackendExecuteOptions,\n BackendExecutionPlan,\n BackendRunRequest,\n} from '../../../domain/contracts/backends.js';\nimport type { ParsedEvent } from '../../../domain/contracts/messages.js';\nimport { APPROVAL_POSTURE_ACP_CLI } from '../approval-posture.js';\nimport {\n type AcpElicitationRequest,\n type AcpElicitationResponse,\n buildElicitationCapabilities,\n dispatchElicitation,\n} from './acp-cli-elicitation.js';\nimport {\n ACP_AGENT_REGISTRY,\n type AcpCliBackendConfig,\n type AcpConfigOption,\n type AcpMcpServerSpec,\n type AcpSessionInfo,\n assertAcpProtocolCompatible,\n closeAcpSessionIfSupported,\n filterMcpServersByCapabilities,\n HANDSHAKE_TIMEOUT_MS,\n listAcpSessionsViaConnection,\n mapAcpSessionUpdate,\n parseAcpConfigOptions,\n readAcpMcpServers,\n resolveAcpAgentCapabilities,\n resolveAcpAgentCommand,\n setAcpConfigOptionViaConnection,\n toAcpToolLocations,\n withAcpTimeout,\n} from './acp-cli-helpers.js';\nimport {\n BACKEND_METADATA,\n createCliBackendBase,\n isCliInstalledAsync,\n} from './shared.js';\n\nexport type { AcpElicitationField, AcpElicitationRequest, AcpElicitationResponse } from './acp-cli-elicitation.js';\nexport type { AcpCapabilityMatrix, AcpForkedSession } from './acp-cli-probe.js';\nexport type { AcpCliBackendConfig, AcpConfigOption, AcpSessionInfo };\nexport {\n ACP_AGENT_REGISTRY,\n listAcpSessionsViaConnection,\n mapAcpSessionUpdate,\n parseAcpConfigOptions,\n resolveAcpAgentCommand,\n setAcpConfigOptionViaConnection,\n toAcpToolLocations,\n};\nexport { forkAcpSessionViaConnection, listAcpSessions, probeAcpCapabilities } from './acp-cli-probe.js';\n\nconst AGENT_MODELS: Record<string, string[]> = {\n claude: ['opus', 'sonnet', 'haiku'],\n codex: ['gpt-5-codex', 'o3', 'o4-mini'],\n gemini: ['gemini-2.5-pro', 'gemini-2.5-flash'],\n cursor: ['auto', 'sonnet-4.6', 'gpt-5.3-codex'],\n};\n\n/**\n * Re-wraps errors returned by an ACP agent binary that look like raw internal\n * JS crashes (e.g. \"Cannot read properties of undefined (reading 'connection')\").\n * These come back as JSON-RPC error messages from the agent process and would\n * otherwise surface as confusing implementation details to callers.\n */\nfunction wrapAcpAgentError(err: unknown, agentCommand: string): Error {\n const msg = err instanceof Error ? err.message : String(err);\n const isRawJsError =\n msg.startsWith('Cannot read properties') ||\n msg.startsWith('TypeError:') ||\n msg.includes('is not a function') ||\n msg.includes('is not defined');\n if (isRawJsError) {\n return new Error(\n `ACP agent crashed during initialization (${agentCommand}): ${msg}`\n );\n }\n return err instanceof Error ? err : new Error(msg);\n}\n\nasync function* runAcpSession(\n command: string,\n spawnArgs: string[],\n request: BackendRunRequest,\n options: BackendExecuteOptions,\n onElicitation?: (req: AcpElicitationRequest) => Promise<AcpElicitationResponse>\n): AsyncGenerator<ParsedEvent> {\n const sessionCwd = options.cwd ?? process.cwd();\n const mcpServers = readAcpMcpServers(request.mcpConfigPath, sessionCwd);\n const child = spawn(command, spawnArgs, {\n stdio: ['pipe', 'pipe', 'inherit'],\n env: { ...process.env, ...options.env },\n cwd: options.cwd,\n });\n\n const stream = ndJsonStream(\n Writable.toWeb(child.stdin) as WritableStream<Uint8Array>,\n Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>\n );\n\n const pending: ParsedEvent[] = [];\n let waiter: (() => void) | null = null;\n let sessionDone = false;\n let sessionError: unknown = null;\n let currentSessionId = '';\n let canCloseSession = false;\n\n const push = (event: ParsedEvent): void => {\n pending.push(event);\n waiter?.();\n waiter = null;\n };\n\n const waitForNext = (): Promise<void> =>\n new Promise<void>((resolve) => { waiter = resolve; });\n\n const client: Client & {\n unstable_createElicitation?: (params: CreateElicitationRequest) => Promise<CreateElicitationResponse>;\n } = {\n sessionUpdate({ update }: SessionNotification): Promise<void> {\n mapAcpSessionUpdate(update, push);\n return Promise.resolve();\n },\n requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse> {\n const first = params.options[0];\n if (!first) {\n return Promise.resolve({ outcome: { outcome: 'cancelled' } });\n }\n push({ type: 'tool', name: params.toolCall.title ?? 'permission' });\n return Promise.resolve({ outcome: { outcome: 'selected', optionId: first.optionId } });\n },\n unstable_createElicitation: (params: CreateElicitationRequest) =>\n dispatchElicitation(params, onElicitation, push),\n };\n\n const connection = new ClientSideConnection(() => client, stream);\n\n const onAbort = (): void => {\n if (currentSessionId) {\n void connection.cancel({ sessionId: currentSessionId }).catch(() => undefined);\n }\n sessionDone = true;\n waiter?.();\n waiter = null;\n if (!child.killed) child.kill();\n };\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const sessionTimeoutMs = request.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;\n\n const sessionPromise = (async () => {\n const elicitationCaps = buildElicitationCapabilities(!!onElicitation);\n let initializeResult: unknown;\n try {\n initializeResult = await withAcpTimeout<unknown>(\n connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {\n fs: { readTextFile: true, writeTextFile: true },\n ...(elicitationCaps ? { elicitation: elicitationCaps } : {}),\n },\n clientInfo: {\n name: 'octoflow-core',\n title: 'OctoFlow',\n version: '1.0.0',\n },\n }),\n sessionTimeoutMs\n );\n } catch (err) {\n throw wrapAcpAgentError(err, command);\n }\n const capabilities = resolveAcpAgentCapabilities(initializeResult);\n canCloseSession = capabilities.canCloseSession;\n const effectiveMcpServers = filterMcpServersByCapabilities(\n mcpServers,\n capabilities\n );\n assertAcpProtocolCompatible(capabilities, PROTOCOL_VERSION);\n\n let sessionId: string;\n if (request.isResume && request.sessionId) {\n if (capabilities.canResumeSession) {\n await withAcpTimeout(\n connection.resumeSession({\n sessionId: request.sessionId,\n cwd: sessionCwd,\n mcpServers: effectiveMcpServers,\n }),\n sessionTimeoutMs\n );\n sessionId = request.sessionId;\n } else if (capabilities.canLoadSession) {\n type MaybeLoadSession = ClientSideConnection & {\n loadSession?: (params: {\n sessionId: string;\n cwd: string;\n mcpServers: AcpMcpServerSpec[];\n }) => Promise<unknown>;\n };\n const maybeLoad = (connection as MaybeLoadSession).loadSession;\n if (!maybeLoad) {\n throw new Error('ACP agent advertises loadSession but SDK client has no loadSession method');\n }\n await withAcpTimeout(\n maybeLoad({\n sessionId: request.sessionId,\n cwd: sessionCwd,\n mcpServers: effectiveMcpServers,\n }),\n sessionTimeoutMs\n );\n sessionId = request.sessionId;\n } else {\n throw new Error(\n 'ACP agent does not advertise resume/load session capabilities; cannot resume session.'\n );\n }\n } else {\n const resp = (await withAcpTimeout(\n connection.newSession({ cwd: sessionCwd, mcpServers: effectiveMcpServers }),\n sessionTimeoutMs\n )) as NewSessionResponse;\n ({ sessionId } = resp);\n }\n\n currentSessionId = sessionId;\n push({ type: 'init', sessionId });\n\n if (request.model && request.model !== 'default' && !request.isResume && !(request.model in ACP_AGENT_REGISTRY)) {\n void connection.unstable_setSessionModel?.({ sessionId, modelId: request.model });\n }\n\n const promptParts = [\n ...(request.systemPrompt && !request.isResume\n ? [{ type: 'text' as const, text: `[System]: ${request.systemPrompt}\\n\\n` }]\n : []),\n { type: 'text' as const, text: request.prompt },\n ];\n\n const promptResult = (await withAcpTimeout(\n connection.prompt({\n sessionId,\n prompt: promptParts,\n _meta: request.isOrchestration ? { mode: 'steer' } : undefined,\n }),\n sessionTimeoutMs\n )) as PromptResponse;\n\n push({ type: 'result', stopReason: promptResult.stopReason });\n })()\n .catch((err: unknown) => { sessionError = err; })\n .finally(() => {\n sessionDone = true;\n waiter?.();\n waiter = null;\n });\n\n try {\n while (!sessionDone || pending.length > 0) {\n if (pending.length > 0) {\n yield pending.shift() as ParsedEvent;\n } else if (!sessionDone) {\n await waitForNext();\n }\n }\n await sessionPromise;\n if (sessionError) throw sessionError as Error;\n } finally {\n await withAcpTimeout(\n closeAcpSessionIfSupported(connection, currentSessionId, canCloseSession),\n 2_000\n );\n options.signal?.removeEventListener('abort', onAbort);\n if (!child.killed) child.kill();\n }\n}\n\nconst META = BACKEND_METADATA['acp-cli'];\n\nconst CAPABILITIES: BackendCapabilities = {\n streaming: true,\n sessionPersistence: true,\n workingDirectory: true,\n forceMode: false,\n systemPrompt: true,\n planning: false,\n tools: true,\n mcp: false,\n approvalCallback: APPROVAL_POSTURE_ACP_CLI,\n};\n\nexport function createAcpCliBackend(config: AcpCliBackendConfig = {}): Backend {\n let resolvedCommand: string;\n let resolvedArgs: string[];\n\n if (config.command) {\n resolvedCommand = config.command;\n resolvedArgs = config.args ?? [];\n } else {\n const agent = config.agent ?? process.env.ACP_AGENT ?? 'claude';\n ({ command: resolvedCommand, args: resolvedArgs } = resolveAcpAgentCommand(\n agent,\n config.agentOverrides\n ));\n }\n\n const agentName = config.command ? null : (config.agent ?? process.env.ACP_AGENT ?? 'claude');\n const effectiveModels = config.models ?? (agentName ? AGENT_MODELS[agentName] : null) ?? META.models;\n const effectiveMeta = {\n ...META,\n models: effectiveModels,\n defaultModel: effectiveModels[0] ?? META.defaultModel,\n };\n\n const base = createCliBackendBase(effectiveMeta, CAPABILITIES, 'acp', {\n resolveInstalled: () => isCliInstalledAsync(resolvedCommand),\n resolveVersion: () => null,\n });\n\n return {\n ...base,\n\n validateModel(model: string): boolean {\n return effectiveModels.includes(model) || model === 'default' || model in ACP_AGENT_REGISTRY;\n },\n\n generateSessionId(): string {\n return crypto.randomUUID();\n },\n\n buildExecutionPlan(request: BackendRunRequest): BackendExecutionPlan {\n let cmd = resolvedCommand;\n let cmdArgs = resolvedArgs;\n if (!config.command && request.model && request.model in ACP_AGENT_REGISTRY) {\n ({ command: cmd, args: cmdArgs } = resolveAcpAgentCommand(\n request.model,\n config.agentOverrides\n ));\n }\n\n return {\n env: request.env ?? {},\n stdin: '',\n cwd: request.cwd ?? undefined,\n parser: 'acp',\n timeoutMs: request.timeoutMs,\n sessionId: request.sessionId ?? undefined,\n execute: (execOptions: BackendExecuteOptions) =>\n runAcpSession(cmd, cmdArgs, request, execOptions, config.onElicitation),\n };\n },\n\n extractSessionId(_output: string): string | null {\n return null;\n },\n };\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { spawn } from 'node:child_process';\nimport crypto from 'node:crypto';\nimport { Readable, Writable } from 'node:stream';\n\n// Type-only import: `@agentclientprotocol/sdk` is ESM-only, so its runtime\n// values are loaded lazily (see `loadAcpSdk`) to keep octoflow-core's CommonJS\n// entry from `require()`-ing an ESM module at load time.\nimport type {\n Client,\n ClientSideConnection,\n CreateElicitationRequest,\n CreateElicitationResponse,\n NewSessionResponse,\n PromptResponse,\n RequestPermissionRequest,\n RequestPermissionResponse,\n SessionNotification,\n} from '@agentclientprotocol/sdk';\n\nimport type {\n Backend,\n BackendCapabilities,\n BackendExecuteOptions,\n BackendExecutionPlan,\n BackendRunRequest,\n} from '../../../domain/contracts/backends.js';\nimport type { ParsedEvent } from '../../../domain/contracts/messages.js';\nimport { APPROVAL_POSTURE_ACP_CLI } from '../approval-posture.js';\nimport {\n type AcpElicitationRequest,\n type AcpElicitationResponse,\n buildElicitationCapabilities,\n dispatchElicitation,\n} from './acp-cli-elicitation.js';\nimport {\n ACP_AGENT_REGISTRY,\n type AcpCliBackendConfig,\n type AcpConfigOption,\n type AcpMcpServerSpec,\n type AcpSessionInfo,\n assertAcpProtocolCompatible,\n closeAcpSessionIfSupported,\n filterMcpServersByCapabilities,\n HANDSHAKE_TIMEOUT_MS,\n listAcpSessionsViaConnection,\n mapAcpSessionUpdate,\n parseAcpConfigOptions,\n readAcpMcpServers,\n resolveAcpAgentCapabilities,\n resolveAcpAgentCommand,\n setAcpConfigOptionViaConnection,\n toAcpToolLocations,\n withAcpTimeout,\n} from './acp-cli-helpers.js';\nimport { getBackendDescriptor } from './descriptors.js';\nimport { createCliBackendBase, isCliInstalledAsync } from './shared.js';\n\nexport type { AcpElicitationField, AcpElicitationRequest, AcpElicitationResponse } from './acp-cli-elicitation.js';\nexport type { AcpCapabilityMatrix, AcpForkedSession } from './acp-cli-probe.js';\nexport type { AcpCliBackendConfig, AcpConfigOption, AcpSessionInfo };\nexport {\n ACP_AGENT_REGISTRY,\n listAcpSessionsViaConnection,\n mapAcpSessionUpdate,\n parseAcpConfigOptions,\n resolveAcpAgentCommand,\n setAcpConfigOptionViaConnection,\n toAcpToolLocations,\n};\nexport { forkAcpSessionViaConnection, listAcpSessions, probeAcpCapabilities } from './acp-cli-probe.js';\n\nconst AGENT_MODELS: Record<string, string[]> = {\n claude: ['opus', 'sonnet', 'haiku'],\n codex: ['gpt-5-codex', 'o3', 'o4-mini'],\n gemini: ['gemini-2.5-pro', 'gemini-2.5-flash'],\n cursor: ['auto', 'sonnet-4.6', 'gpt-5.3-codex'],\n};\n\n/**\n * Re-wraps errors returned by an ACP agent binary that look like raw internal\n * JS crashes (e.g. \"Cannot read properties of undefined (reading 'connection')\").\n * These come back as JSON-RPC error messages from the agent process and would\n * otherwise surface as confusing implementation details to callers.\n */\nfunction wrapAcpAgentError(err: unknown, agentCommand: string): Error {\n const msg = err instanceof Error ? err.message : String(err);\n const isRawJsError =\n msg.startsWith('Cannot read properties') ||\n msg.startsWith('TypeError:') ||\n msg.includes('is not a function') ||\n msg.includes('is not defined');\n if (isRawJsError) {\n return new Error(\n `ACP agent crashed during initialization (${agentCommand}): ${msg}`\n );\n }\n return err instanceof Error ? err : new Error(msg);\n}\n\n// Lazy ESM loader for the ACP SDK \u2014 see the type-only import note above.\nconst importAcpSdk = () => import('@agentclientprotocol/sdk');\nlet acpSdkPromise: ReturnType<typeof importAcpSdk> | null = null;\nconst loadAcpSdk = (): ReturnType<typeof importAcpSdk> =>\n (acpSdkPromise ??= importAcpSdk());\n\nasync function* runAcpSession(\n command: string,\n spawnArgs: string[],\n request: BackendRunRequest,\n options: BackendExecuteOptions,\n onElicitation?: (req: AcpElicitationRequest) => Promise<AcpElicitationResponse>\n): AsyncGenerator<ParsedEvent> {\n const {\n ndJsonStream,\n ClientSideConnection: ClientSideConnectionCtor,\n PROTOCOL_VERSION,\n } = await loadAcpSdk();\n const sessionCwd = options.cwd ?? process.cwd();\n const mcpServers = readAcpMcpServers(request.mcpConfigPath, sessionCwd);\n const child = spawn(command, spawnArgs, {\n stdio: ['pipe', 'pipe', 'inherit'],\n env: { ...process.env, ...options.env },\n cwd: options.cwd,\n });\n\n const stream = ndJsonStream(\n Writable.toWeb(child.stdin) as WritableStream<Uint8Array>,\n Readable.toWeb(child.stdout) as ReadableStream<Uint8Array>\n );\n\n const pending: ParsedEvent[] = [];\n let waiter: (() => void) | null = null;\n let sessionDone = false;\n let sessionError: unknown = null;\n let currentSessionId = '';\n let canCloseSession = false;\n\n const push = (event: ParsedEvent): void => {\n pending.push(event);\n waiter?.();\n waiter = null;\n };\n\n const waitForNext = (): Promise<void> =>\n new Promise<void>((resolve) => { waiter = resolve; });\n\n const client: Client & {\n unstable_createElicitation?: (params: CreateElicitationRequest) => Promise<CreateElicitationResponse>;\n } = {\n sessionUpdate({ update }: SessionNotification): Promise<void> {\n mapAcpSessionUpdate(update, push);\n return Promise.resolve();\n },\n requestPermission(params: RequestPermissionRequest): Promise<RequestPermissionResponse> {\n const first = params.options[0];\n if (!first) {\n return Promise.resolve({ outcome: { outcome: 'cancelled' } });\n }\n push({ type: 'tool', name: params.toolCall.title ?? 'permission' });\n return Promise.resolve({ outcome: { outcome: 'selected', optionId: first.optionId } });\n },\n unstable_createElicitation: (params: CreateElicitationRequest) =>\n dispatchElicitation(params, onElicitation, push),\n };\n\n const connection = new ClientSideConnectionCtor(() => client, stream);\n\n const onAbort = (): void => {\n if (currentSessionId) {\n void connection.cancel({ sessionId: currentSessionId }).catch(() => undefined);\n }\n sessionDone = true;\n waiter?.();\n waiter = null;\n if (!child.killed) child.kill();\n };\n options.signal?.addEventListener('abort', onAbort, { once: true });\n\n const sessionTimeoutMs = request.timeoutMs ?? HANDSHAKE_TIMEOUT_MS;\n\n const sessionPromise = (async () => {\n const elicitationCaps = buildElicitationCapabilities(!!onElicitation);\n let initializeResult: unknown;\n try {\n initializeResult = await withAcpTimeout<unknown>(\n connection.initialize({\n protocolVersion: PROTOCOL_VERSION,\n clientCapabilities: {\n fs: { readTextFile: true, writeTextFile: true },\n ...(elicitationCaps ? { elicitation: elicitationCaps } : {}),\n },\n clientInfo: {\n name: 'octoflow-core',\n title: 'OctoFlow',\n version: '1.0.0',\n },\n }),\n sessionTimeoutMs\n );\n } catch (err) {\n throw wrapAcpAgentError(err, command);\n }\n const capabilities = resolveAcpAgentCapabilities(initializeResult);\n canCloseSession = capabilities.canCloseSession;\n const effectiveMcpServers = filterMcpServersByCapabilities(\n mcpServers,\n capabilities\n );\n assertAcpProtocolCompatible(capabilities, PROTOCOL_VERSION);\n\n let sessionId: string;\n if (request.isResume && request.sessionId) {\n if (capabilities.canResumeSession) {\n await withAcpTimeout(\n connection.resumeSession({\n sessionId: request.sessionId,\n cwd: sessionCwd,\n mcpServers: effectiveMcpServers,\n }),\n sessionTimeoutMs\n );\n sessionId = request.sessionId;\n } else if (capabilities.canLoadSession) {\n type MaybeLoadSession = ClientSideConnection & {\n loadSession?: (params: {\n sessionId: string;\n cwd: string;\n mcpServers: AcpMcpServerSpec[];\n }) => Promise<unknown>;\n };\n const maybeLoad = (connection as MaybeLoadSession).loadSession;\n if (!maybeLoad) {\n throw new Error('ACP agent advertises loadSession but SDK client has no loadSession method');\n }\n await withAcpTimeout(\n maybeLoad({\n sessionId: request.sessionId,\n cwd: sessionCwd,\n mcpServers: effectiveMcpServers,\n }),\n sessionTimeoutMs\n );\n sessionId = request.sessionId;\n } else {\n throw new Error(\n 'ACP agent does not advertise resume/load session capabilities; cannot resume session.'\n );\n }\n } else {\n const resp = (await withAcpTimeout(\n connection.newSession({ cwd: sessionCwd, mcpServers: effectiveMcpServers }),\n sessionTimeoutMs\n )) as NewSessionResponse;\n ({ sessionId } = resp);\n }\n\n currentSessionId = sessionId;\n push({ type: 'init', sessionId });\n\n if (request.model && request.model !== 'default' && !request.isResume && !(request.model in ACP_AGENT_REGISTRY)) {\n void connection.unstable_setSessionModel?.({ sessionId, modelId: request.model });\n }\n\n const promptParts = [\n ...(request.systemPrompt && !request.isResume\n ? [{ type: 'text' as const, text: `[System]: ${request.systemPrompt}\\n\\n` }]\n : []),\n { type: 'text' as const, text: request.prompt },\n ];\n\n const promptResult = (await withAcpTimeout(\n connection.prompt({\n sessionId,\n prompt: promptParts,\n _meta: request.isOrchestration ? { mode: 'steer' } : undefined,\n }),\n sessionTimeoutMs\n )) as PromptResponse;\n\n push({ type: 'result', stopReason: promptResult.stopReason });\n })()\n .catch((err: unknown) => { sessionError = err; })\n .finally(() => {\n sessionDone = true;\n waiter?.();\n waiter = null;\n });\n\n try {\n while (!sessionDone || pending.length > 0) {\n if (pending.length > 0) {\n yield pending.shift() as ParsedEvent;\n } else if (!sessionDone) {\n await waitForNext();\n }\n }\n await sessionPromise;\n if (sessionError) throw sessionError as Error;\n } finally {\n await withAcpTimeout(\n closeAcpSessionIfSupported(connection, currentSessionId, canCloseSession),\n 2_000\n );\n options.signal?.removeEventListener('abort', onAbort);\n if (!child.killed) child.kill();\n }\n}\n\nconst META = getBackendDescriptor('acp-cli').meta;\n\nconst CAPABILITIES: BackendCapabilities = {\n streaming: true,\n sessionPersistence: true,\n workingDirectory: true,\n forceMode: false,\n systemPrompt: true,\n planning: false,\n tools: true,\n mcp: false,\n approvalCallback: APPROVAL_POSTURE_ACP_CLI,\n};\n\nexport function createAcpCliBackend(config: AcpCliBackendConfig = {}): Backend {\n let resolvedCommand: string;\n let resolvedArgs: string[];\n\n if (config.command) {\n resolvedCommand = config.command;\n resolvedArgs = config.args ?? [];\n } else {\n const agent = config.agent ?? process.env.ACP_AGENT ?? 'claude';\n ({ command: resolvedCommand, args: resolvedArgs } = resolveAcpAgentCommand(\n agent,\n config.agentOverrides\n ));\n }\n\n const agentName = config.command ? null : (config.agent ?? process.env.ACP_AGENT ?? 'claude');\n const effectiveModels = config.models ?? (agentName ? AGENT_MODELS[agentName] : null) ?? META.models;\n const effectiveMeta = {\n ...META,\n models: effectiveModels,\n defaultModel: effectiveModels[0] ?? META.defaultModel,\n };\n\n const base = createCliBackendBase(effectiveMeta, CAPABILITIES, 'acp', {\n resolveInstalled: () => isCliInstalledAsync(resolvedCommand),\n resolveVersion: () => null,\n });\n\n return {\n ...base,\n\n validateModel(model: string): boolean {\n return effectiveModels.includes(model) || model === 'default' || model in ACP_AGENT_REGISTRY;\n },\n\n generateSessionId(): string {\n return crypto.randomUUID();\n },\n\n buildExecutionPlan(request: BackendRunRequest): BackendExecutionPlan {\n let cmd = resolvedCommand;\n let cmdArgs = resolvedArgs;\n if (!config.command && request.model && request.model in ACP_AGENT_REGISTRY) {\n ({ command: cmd, args: cmdArgs } = resolveAcpAgentCommand(\n request.model,\n config.agentOverrides\n ));\n }\n\n return {\n env: request.env ?? {},\n stdin: '',\n cwd: request.cwd ?? undefined,\n parser: 'acp',\n timeoutMs: request.timeoutMs,\n sessionId: request.sessionId ?? undefined,\n execute: (execOptions: BackendExecuteOptions) =>\n runAcpSession(cmd, cmdArgs, request, execOptions, config.onElicitation),\n };\n },\n\n extractSessionId(_output: string): string | null {\n return null;\n },\n };\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"anthropic-api.d.ts","sourceRoot":"","sources":["../../../../src/adapters/agents/backends/anthropic-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACb,OAAO,EAIP,cAAc,EACf,MAAM,uCAAuC,CAAC;AAiF/C,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,aAAa,CAAC;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,gBAAgB,EAAE,CAO5E;AACD,wBAAgB,yBAAyB,CACvC,MAAM,GAAE,yBAA8B,GACrC,OAAO,CAsTT"}
1
+ {"version":3,"file":"anthropic-api.d.ts","sourceRoot":"","sources":["../../../../src/adapters/agents/backends/anthropic-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACb,OAAO,EAIP,cAAc,EACf,MAAM,uCAAuC,CAAC;AAiF/C,UAAU,gBAAgB;IACxB,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,aAAa,CAAC;CAC7B;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,gBAAgB,EAAE,CAO5E;AACD,wBAAgB,yBAAyB,CACvC,MAAM,GAAE,yBAA8B,GACrC,OAAO,CA+RT"}
@@ -19,14 +19,14 @@ import {
19
19
  isCustomApiBaseUrl,
20
20
  normalizeToolSchema,
21
21
  parseSseDataLine,
22
+ readSseLines,
22
23
  resolveApiBaseUrl
23
24
  } from "./api-shared.js";
24
- import {
25
- buildAnthropicPayload,
26
- structuredHistoryToMessages
27
- } from "./native-messages/index.js";
28
- import { BACKEND_METADATA, createInfoFields } from "./shared.js";
29
- const META = BACKEND_METADATA["anthropic-api"];
25
+ import { getBackendDescriptor } from "./descriptors.js";
26
+ import { buildAnthropicPayload } from "./native-messages/index.js";
27
+ import { backendRequestMessagesWithPrompt } from "./protocol-codecs.js";
28
+ import { createInfoFields } from "./shared.js";
29
+ const META = getBackendDescriptor("anthropic-api").meta;
30
30
  const DEFAULT_BASE_URL = "https://api.anthropic.com";
31
31
  const DEFAULT_MAX_TOKENS = 8192;
32
32
  const BASE_URL_ENV_KEY = "ANTHROPIC_BASE_URL";
@@ -119,16 +119,7 @@ function createAnthropicApiBackend(config = {}) {
119
119
  options.timeoutMs ?? request.timeoutMs,
120
120
  options.signal ?? request.signal
121
121
  );
122
- const historyMessages = request.messages ?? structuredHistoryToMessages(request.structuredHistory);
123
- const allMessages = [
124
- ...historyMessages,
125
- {
126
- kind: "message",
127
- messageId: "_prompt",
128
- role: "user",
129
- parts: [{ kind: "text", text: request.prompt }]
130
- }
131
- ];
122
+ const allMessages = backendRequestMessagesWithPrompt(request);
132
123
  const cacheEnabled = request.cache?.enabled !== false;
133
124
  const cacheTtl = request.cache?.ttl;
134
125
  const systemOverride = request.cacheControl?.system;
@@ -188,96 +179,87 @@ function createAnthropicApiBackend(config = {}) {
188
179
  "response body is not readable"
189
180
  );
190
181
  }
191
- const decoder = new TextDecoder();
192
- let buffer = "";
193
182
  let fullText = "";
194
183
  let usage = null;
195
184
  const toolCallAccumulators = /* @__PURE__ */ new Map();
196
185
  try {
197
- while (true) {
198
- const { done, value } = await reader.read();
199
- if (done) break;
200
- buffer += decoder.decode(value, { stream: true });
201
- const lines = buffer.split("\n");
202
- buffer = lines.pop() ?? "";
203
- for (const rawLine of lines) {
204
- const chunk = parseSSELine(rawLine.trim());
205
- if (!chunk || !chunk.type) continue;
206
- switch (chunk.type) {
207
- case "message_start": {
208
- const msgUsage = chunk.message?.usage;
209
- if (msgUsage) {
210
- const cache = hasAnthropicCacheUsage(msgUsage) ? anthropicCacheUsage(msgUsage) : void 0;
211
- usage = createUsage(
212
- msgUsage.input_tokens ?? 0,
213
- msgUsage.output_tokens ?? 0,
214
- {
215
- cachedInputTokens: msgUsage.cache_read_input_tokens,
216
- cacheWriteTokens: msgUsage.cache_creation_input_tokens,
217
- ...cache ? { cache } : {}
218
- }
219
- );
220
- }
221
- break;
222
- }
223
- case "content_block_start": {
224
- const blockType = chunk.content_block?.type ?? "text";
225
- if (blockType === "tool_use") {
226
- const idx = chunk.index ?? 0;
227
- const acc = createToolCallAccumulator(
228
- chunk.content_block?.id ?? `tool_${idx}`
229
- );
230
- acc.name = chunk.content_block?.name ?? "";
231
- toolCallAccumulators.set(idx, acc);
232
- } else if (blockType === "thinking") {
233
- yield { type: "thinking_start" };
234
- }
235
- break;
186
+ for await (const rawLine of readSseLines(reader)) {
187
+ const chunk = parseSSELine(rawLine.trim());
188
+ if (!chunk || !chunk.type) continue;
189
+ switch (chunk.type) {
190
+ case "message_start": {
191
+ const msgUsage = chunk.message?.usage;
192
+ if (msgUsage) {
193
+ const cache = hasAnthropicCacheUsage(msgUsage) ? anthropicCacheUsage(msgUsage) : void 0;
194
+ usage = createUsage(
195
+ msgUsage.input_tokens ?? 0,
196
+ msgUsage.output_tokens ?? 0,
197
+ {
198
+ cachedInputTokens: msgUsage.cache_read_input_tokens,
199
+ cacheWriteTokens: msgUsage.cache_creation_input_tokens,
200
+ ...cache ? { cache } : {}
201
+ }
202
+ );
236
203
  }
237
- case "content_block_delta": {
204
+ break;
205
+ }
206
+ case "content_block_start": {
207
+ const blockType = chunk.content_block?.type ?? "text";
208
+ if (blockType === "tool_use") {
238
209
  const idx = chunk.index ?? 0;
239
- const deltaType = chunk.delta?.type;
240
- if (deltaType === "text_delta" && chunk.delta?.text) {
241
- fullText += chunk.delta.text;
242
- yield { type: "text", text: chunk.delta.text };
243
- } else if (deltaType === "input_json_delta" && chunk.delta?.partial_json !== void 0) {
244
- const acc = toolCallAccumulators.get(idx);
245
- if (acc) {
246
- acc.arguments += chunk.delta.partial_json;
247
- }
248
- } else if (deltaType === "thinking_delta" && chunk.delta?.thinking) {
249
- yield { type: "thinking", text: chunk.delta.thinking };
250
- }
251
- break;
210
+ const acc = createToolCallAccumulator(
211
+ chunk.content_block?.id ?? `tool_${idx}`
212
+ );
213
+ acc.name = chunk.content_block?.name ?? "";
214
+ toolCallAccumulators.set(idx, acc);
215
+ } else if (blockType === "thinking") {
216
+ yield { type: "thinking_start" };
252
217
  }
253
- case "content_block_stop":
254
- break;
255
- case "message_delta": {
256
- const deltaUsage = chunk.usage;
257
- if (deltaUsage) {
258
- usage = createUsage(
259
- usage?.inputTokens ?? deltaUsage.input_tokens ?? 0,
260
- deltaUsage.output_tokens ?? usage?.outputTokens ?? 0,
261
- {
262
- cachedInputTokens: usage?.cachedInputTokens,
263
- cacheWriteTokens: usage?.cacheWriteTokens,
264
- ...usage?.cache ? { cache: usage.cache } : {}
265
- }
266
- );
218
+ break;
219
+ }
220
+ case "content_block_delta": {
221
+ const idx = chunk.index ?? 0;
222
+ const deltaType = chunk.delta?.type;
223
+ if (deltaType === "text_delta" && chunk.delta?.text) {
224
+ fullText += chunk.delta.text;
225
+ yield { type: "text", text: chunk.delta.text };
226
+ } else if (deltaType === "input_json_delta" && chunk.delta?.partial_json !== void 0) {
227
+ const acc = toolCallAccumulators.get(idx);
228
+ if (acc) {
229
+ acc.arguments += chunk.delta.partial_json;
267
230
  }
268
- break;
231
+ } else if (deltaType === "thinking_delta" && chunk.delta?.thinking) {
232
+ yield { type: "thinking", text: chunk.delta.thinking };
269
233
  }
270
- case "error": {
271
- const errType = chunk.error?.type ?? "unknown_error";
272
- const errMsg = chunk.error?.message ?? "Unknown stream error";
273
- throw new ApiStreamError(
274
- "anthropic-api",
275
- `${errType}: ${errMsg}`
234
+ break;
235
+ }
236
+ case "content_block_stop":
237
+ break;
238
+ case "message_delta": {
239
+ const deltaUsage = chunk.usage;
240
+ if (deltaUsage) {
241
+ usage = createUsage(
242
+ usage?.inputTokens ?? deltaUsage.input_tokens ?? 0,
243
+ deltaUsage.output_tokens ?? usage?.outputTokens ?? 0,
244
+ {
245
+ cachedInputTokens: usage?.cachedInputTokens,
246
+ cacheWriteTokens: usage?.cacheWriteTokens,
247
+ ...usage?.cache ? { cache: usage.cache } : {}
248
+ }
276
249
  );
277
250
  }
278
- default:
279
- break;
251
+ break;
252
+ }
253
+ case "error": {
254
+ const errType = chunk.error?.type ?? "unknown_error";
255
+ const errMsg = chunk.error?.message ?? "Unknown stream error";
256
+ throw new ApiStreamError(
257
+ "anthropic-api",
258
+ `${errType}: ${errMsg}`
259
+ );
280
260
  }
261
+ default:
262
+ break;
281
263
  }
282
264
  }
283
265
  } finally {