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.
- package/README.md +29 -0
- package/dist/adapters/agents/backends/acp-cli-probe.d.ts +1 -1
- package/dist/adapters/agents/backends/acp-cli-probe.d.ts.map +1 -1
- package/dist/adapters/agents/backends/acp-cli-probe.js +7 -7
- package/dist/adapters/agents/backends/acp-cli-probe.js.map +2 -2
- package/dist/adapters/agents/backends/acp-cli.d.ts.map +1 -1
- package/dist/adapters/agents/backends/acp-cli.js +12 -12
- package/dist/adapters/agents/backends/acp-cli.js.map +2 -2
- package/dist/adapters/agents/backends/anthropic-api.d.ts.map +1 -1
- package/dist/adapters/agents/backends/anthropic-api.js +76 -94
- package/dist/adapters/agents/backends/anthropic-api.js.map +2 -2
- package/dist/adapters/agents/backends/api-shared.d.ts +9 -0
- package/dist/adapters/agents/backends/api-shared.d.ts.map +1 -1
- package/dist/adapters/agents/backends/api-shared.js +13 -0
- package/dist/adapters/agents/backends/api-shared.js.map +2 -2
- package/dist/adapters/agents/backends/catalog.d.ts +4 -4
- package/dist/adapters/agents/backends/catalog.d.ts.map +1 -1
- package/dist/adapters/agents/backends/catalog.js +22 -31
- package/dist/adapters/agents/backends/catalog.js.map +2 -2
- package/dist/adapters/agents/backends/claude-code-cli.d.ts.map +1 -1
- package/dist/adapters/agents/backends/claude-code-cli.js +4 -6
- package/dist/adapters/agents/backends/claude-code-cli.js.map +2 -2
- package/dist/adapters/agents/backends/cli-helpers.d.ts +7 -0
- package/dist/adapters/agents/backends/cli-helpers.d.ts.map +1 -1
- package/dist/adapters/agents/backends/cli-helpers.js +7 -0
- package/dist/adapters/agents/backends/cli-helpers.js.map +2 -2
- package/dist/adapters/agents/backends/codex-cli.d.ts.map +1 -1
- package/dist/adapters/agents/backends/codex-cli.js +4 -6
- package/dist/adapters/agents/backends/codex-cli.js.map +2 -2
- package/dist/adapters/agents/backends/cursor-cli.d.ts.map +1 -1
- package/dist/adapters/agents/backends/cursor-cli.js +4 -6
- package/dist/adapters/agents/backends/cursor-cli.js.map +2 -2
- package/dist/adapters/agents/backends/descriptors.d.ts +31 -0
- package/dist/adapters/agents/backends/descriptors.d.ts.map +1 -0
- package/dist/adapters/agents/backends/descriptors.js +57 -0
- package/dist/adapters/agents/backends/descriptors.js.map +7 -0
- package/dist/adapters/agents/backends/gemini-api.d.ts.map +1 -1
- package/dist/adapters/agents/backends/gemini-api.js +35 -56
- package/dist/adapters/agents/backends/gemini-api.js.map +2 -2
- package/dist/adapters/agents/backends/gemini-cli.d.ts.map +1 -1
- package/dist/adapters/agents/backends/gemini-cli.js +4 -6
- package/dist/adapters/agents/backends/gemini-cli.js.map +2 -2
- package/dist/adapters/agents/backends/index.d.ts.map +1 -1
- package/dist/adapters/agents/backends/index.js +23 -42
- package/dist/adapters/agents/backends/index.js.map +2 -2
- package/dist/adapters/agents/backends/native-messages/anthropic.d.ts.map +1 -1
- package/dist/adapters/agents/backends/native-messages/anthropic.js +2 -1
- package/dist/adapters/agents/backends/native-messages/anthropic.js.map +2 -2
- package/dist/adapters/agents/backends/native-messages/gemini.d.ts.map +1 -1
- package/dist/adapters/agents/backends/native-messages/gemini.js +2 -1
- package/dist/adapters/agents/backends/native-messages/gemini.js.map +2 -2
- package/dist/adapters/agents/backends/native-messages/index.d.ts +2 -2
- package/dist/adapters/agents/backends/native-messages/index.js.map +1 -1
- package/dist/adapters/agents/backends/native-messages/ollama.d.ts +2 -0
- package/dist/adapters/agents/backends/native-messages/ollama.d.ts.map +1 -1
- package/dist/adapters/agents/backends/native-messages/ollama.js +19 -17
- package/dist/adapters/agents/backends/native-messages/ollama.js.map +2 -2
- package/dist/adapters/agents/backends/native-messages/openai.d.ts +13 -1
- package/dist/adapters/agents/backends/native-messages/openai.d.ts.map +1 -1
- package/dist/adapters/agents/backends/native-messages/openai.js +34 -12
- package/dist/adapters/agents/backends/native-messages/openai.js.map +2 -2
- package/dist/adapters/agents/backends/native-messages/shared.d.ts +24 -0
- package/dist/adapters/agents/backends/native-messages/shared.d.ts.map +1 -1
- package/dist/adapters/agents/backends/native-messages/shared.js +32 -0
- package/dist/adapters/agents/backends/native-messages/shared.js.map +2 -2
- package/dist/adapters/agents/backends/native-messages/vercel.d.ts.map +1 -1
- package/dist/adapters/agents/backends/native-messages/vercel.js +5 -3
- package/dist/adapters/agents/backends/native-messages/vercel.js.map +2 -2
- package/dist/adapters/agents/backends/openai-api.d.ts.map +1 -1
- package/dist/adapters/agents/backends/openai-api.js +41 -55
- package/dist/adapters/agents/backends/openai-api.js.map +2 -2
- package/dist/adapters/agents/backends/protocol-codecs.d.ts +32 -0
- package/dist/adapters/agents/backends/protocol-codecs.d.ts.map +1 -0
- package/dist/adapters/agents/backends/protocol-codecs.js +46 -0
- package/dist/adapters/agents/backends/protocol-codecs.js.map +7 -0
- package/dist/adapters/agents/discover.d.ts.map +1 -1
- package/dist/adapters/agents/discover.js +12 -10
- package/dist/adapters/agents/discover.js.map +2 -2
- package/dist/adapters/agents/ollama/backend.d.ts.map +1 -1
- package/dist/adapters/agents/ollama/backend.js +7 -3
- package/dist/adapters/agents/ollama/backend.js.map +2 -2
- package/dist/adapters/agents/ollama/client.d.ts.map +1 -1
- package/dist/adapters/agents/ollama/client.js +7 -2
- package/dist/adapters/agents/ollama/client.js.map +2 -2
- package/dist/adapters/agents/ollama/errors.d.ts.map +1 -1
- package/dist/adapters/agents/ollama/errors.js +4 -0
- package/dist/adapters/agents/ollama/errors.js.map +2 -2
- package/dist/adapters/agents/runtime/ssh-runner-internal.d.ts +1 -2
- package/dist/adapters/agents/runtime/ssh-runner-internal.d.ts.map +1 -1
- package/dist/adapters/agents/runtime/ssh-runner-internal.js +2 -2
- package/dist/adapters/agents/runtime/ssh-runner-internal.js.map +2 -2
- package/dist/adapters/agents/selection.d.ts.map +1 -1
- package/dist/adapters/agents/selection.js +7 -7
- package/dist/adapters/agents/selection.js.map +2 -2
- package/dist/cli/index.cjs +3100 -3120
- package/dist/cli/index.cjs.map +4 -4
- package/dist/domain/errors/domain.d.ts +2 -0
- package/dist/domain/errors/domain.d.ts.map +1 -1
- package/dist/domain/errors/domain.js +5 -1
- package/dist/domain/errors/domain.js.map +2 -2
- package/dist/domain/errors/index.d.ts +1 -1
- package/dist/domain/errors/index.d.ts.map +1 -1
- package/dist/domain/errors/index.js +5 -1
- package/dist/domain/errors/index.js.map +2 -2
- package/dist/domain/errors/media.d.ts +15 -0
- package/dist/domain/errors/media.d.ts.map +1 -0
- package/dist/domain/errors/media.js +25 -0
- package/dist/domain/errors/media.js.map +7 -0
- package/dist/domain/errors/model.d.ts +12 -0
- package/dist/domain/errors/model.d.ts.map +1 -0
- package/dist/domain/errors/model.js +21 -0
- package/dist/domain/errors/model.js.map +7 -0
- package/dist/environments/local.js +3 -2
- package/dist/environments/local.js.map +2 -2
- package/dist/exports/index-orchestration.d.ts +1 -0
- package/dist/exports/index-orchestration.d.ts.map +1 -1
- package/dist/exports/index-orchestration.js +2 -0
- package/dist/exports/index-orchestration.js.map +2 -2
- package/dist/index.cjs +3548 -3366
- package/dist/index.cjs.map +4 -4
- package/dist/runtime/bridge/agent-handle-types.d.ts +1 -1
- package/dist/runtime/bridge/agent-handle-types.d.ts.map +1 -1
- package/dist/runtime/bridge/agent-handle.d.ts +1 -1
- package/dist/runtime/bridge/agent-handle.d.ts.map +1 -1
- package/dist/runtime/bridge/agent-handle.js.map +1 -1
- package/dist/runtime/bridge/agent-info-types.d.ts +1 -1
- package/dist/runtime/bridge/agent-info-types.d.ts.map +1 -1
- package/dist/runtime/bridge/agent-route-types.d.ts +1 -1
- package/dist/runtime/bridge/agent-route-types.d.ts.map +1 -1
- package/dist/runtime/bridge/anthropic-gateway-converters.d.ts.map +1 -1
- package/dist/runtime/bridge/anthropic-gateway-converters.js +4 -6
- package/dist/runtime/bridge/anthropic-gateway-converters.js.map +2 -2
- package/dist/runtime/bridge/anthropic-gateway.d.ts.map +1 -1
- package/dist/runtime/bridge/anthropic-gateway.js +2 -1
- package/dist/runtime/bridge/anthropic-gateway.js.map +2 -2
- package/dist/runtime/bridge/brain-contract.d.ts +1 -1
- package/dist/runtime/bridge/brain-contract.d.ts.map +1 -1
- package/dist/runtime/bridge/brain-contract.js.map +1 -1
- package/dist/runtime/bridge/brain-plugin.js.map +1 -1
- package/dist/runtime/bridge/bridge-class.d.ts.map +1 -1
- package/dist/runtime/bridge/bridge-class.js +3 -0
- package/dist/runtime/bridge/bridge-class.js.map +2 -2
- package/dist/runtime/bridge/create-bridge.d.ts +1 -1
- package/dist/runtime/bridge/create-bridge.d.ts.map +1 -1
- package/dist/runtime/bridge/create-bridge.js +1 -1
- package/dist/runtime/bridge/create-bridge.js.map +1 -1
- package/dist/runtime/bridge/fabric-bridge-types.d.ts +1 -1
- package/dist/runtime/bridge/fabric-bridge-types.d.ts.map +1 -1
- package/dist/runtime/bridge/fabric-plugin.js.map +1 -1
- package/dist/runtime/bridge/gateway-converter-utils.d.ts +12 -0
- package/dist/runtime/bridge/gateway-converter-utils.d.ts.map +1 -0
- package/dist/runtime/bridge/gateway-converter-utils.js +15 -0
- package/dist/runtime/bridge/gateway-converter-utils.js.map +7 -0
- package/dist/runtime/bridge/gateway-requests/anthropic.d.ts +3 -0
- package/dist/runtime/bridge/gateway-requests/anthropic.d.ts.map +1 -0
- package/dist/runtime/bridge/gateway-requests/anthropic.js +69 -0
- package/dist/runtime/bridge/gateway-requests/anthropic.js.map +7 -0
- package/dist/runtime/bridge/gateway-requests/openai.d.ts +5 -0
- package/dist/runtime/bridge/gateway-requests/openai.d.ts.map +1 -0
- package/dist/runtime/bridge/gateway-requests/openai.js +136 -0
- package/dist/runtime/bridge/gateway-requests/openai.js.map +7 -0
- package/dist/runtime/bridge/memory-plugin.d.ts +1 -1
- package/dist/runtime/bridge/memory-plugin.d.ts.map +1 -1
- package/dist/runtime/bridge/memory-plugin.js.map +1 -1
- package/dist/runtime/bridge/named-agents.js.map +1 -1
- package/dist/runtime/bridge/openai-gateway-converters.d.ts.map +1 -1
- package/dist/runtime/bridge/openai-gateway-converters.js +5 -9
- package/dist/runtime/bridge/openai-gateway-converters.js.map +2 -2
- package/dist/runtime/bridge/openai-gateway.d.ts.map +1 -1
- package/dist/runtime/bridge/openai-gateway.js +9 -4
- package/dist/runtime/bridge/openai-gateway.js.map +2 -2
- package/dist/runtime/bridge/plugins.d.ts +1 -1
- package/dist/runtime/bridge/plugins.d.ts.map +1 -1
- package/dist/runtime/bridge/plugins.js.map +1 -1
- package/dist/runtime/bridge/quickstart.d.ts +1 -1
- package/dist/runtime/bridge/quickstart.d.ts.map +1 -1
- package/dist/runtime/bridge/quickstart.js.map +1 -1
- package/dist/runtime/bridge/runtime-plugin-support.d.ts +1 -1
- package/dist/runtime/bridge/runtime-plugin-support.d.ts.map +1 -1
- package/dist/runtime/bridge/runtime-plugin-support.js.map +1 -1
- package/dist/runtime/bridge/session.d.ts +1 -1
- package/dist/runtime/bridge/session.d.ts.map +1 -1
- package/dist/runtime/bridge/session.js.map +1 -1
- package/dist/runtime/bridge/task-runner-execution-helpers.d.ts +50 -0
- package/dist/runtime/bridge/task-runner-execution-helpers.d.ts.map +1 -0
- package/dist/runtime/bridge/task-runner-execution-helpers.js +90 -0
- package/dist/runtime/bridge/task-runner-execution-helpers.js.map +7 -0
- package/dist/runtime/bridge/task-runner-execution.d.ts.map +1 -1
- package/dist/runtime/bridge/task-runner-execution.js +4 -83
- package/dist/runtime/bridge/task-runner-execution.js.map +2 -2
- package/dist/runtime/bridge/validate-send-params.d.ts +9 -0
- package/dist/runtime/bridge/validate-send-params.d.ts.map +1 -0
- package/dist/runtime/bridge/validate-send-params.js +11 -0
- package/dist/runtime/bridge/validate-send-params.js.map +7 -0
- package/dist/runtime/orchestration/pack/dispatch-worker.d.ts +1 -1
- package/dist/runtime/orchestration/pack/dispatch-worker.d.ts.map +1 -1
- package/dist/runtime/orchestration/pack/dispatch-worker.js +1 -1
- package/dist/runtime/orchestration/pack/dispatch-worker.js.map +2 -2
- package/dist/runtime/orchestration/pack/helpers.d.ts +1 -1
- package/dist/runtime/orchestration/pack/helpers.d.ts.map +1 -1
- package/dist/runtime/orchestration/pack/helpers.js.map +1 -1
- package/dist/runtime/orchestration/pack/pack-workers.d.ts +1 -1
- package/dist/runtime/orchestration/pack/pack-workers.d.ts.map +1 -1
- package/dist/runtime/orchestration/pack/pack-workers.js +1 -1
- package/dist/runtime/orchestration/pack/pack-workers.js.map +1 -1
- package/dist/runtime/orchestration/pack/pack.d.ts +3 -2
- package/dist/runtime/orchestration/pack/pack.d.ts.map +1 -1
- package/dist/runtime/orchestration/pack/pack.js +1 -1
- package/dist/runtime/orchestration/pack/pack.js.map +2 -2
- package/dist/runtime/orchestration/pack/types.d.ts +1 -1
- package/dist/runtime/orchestration/pack/types.d.ts.map +1 -1
- package/dist/runtime/orchestration/pack/types.js.map +1 -1
- package/dist/runtime/orchestration/pack.cjs +3203 -3223
- package/dist/runtime/orchestration/pack.cjs.map +4 -4
- package/dist/runtime/orchestration/run/extract-run-text.d.ts +9 -0
- package/dist/runtime/orchestration/run/extract-run-text.d.ts.map +1 -0
- package/dist/runtime/orchestration/run/extract-run-text.js +17 -0
- package/dist/runtime/orchestration/run/extract-run-text.js.map +7 -0
- package/dist/subpath-a2a.cjs +3153 -3172
- package/dist/subpath-a2a.cjs.map +4 -4
- package/dist/subpath-environments.cjs +3 -2
- package/dist/subpath-environments.cjs.map +2 -2
- package/dist/subpath-ssh.cjs +3 -3
- package/dist/subpath-ssh.cjs.map +2 -2
- package/dist/testing.cjs.map +2 -2
- 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":"
|
|
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
|
-
|
|
5
|
-
|
|
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
|
|
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
|
|
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\
|
|
5
|
-
"mappings": "AAAA,SAAS,aAAa;AACtB,SAAS,UAAU,gBAAgB;
|
|
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": "AAAA,SAAS,aAAa;AACtB,SAAS,UAAU,gBAAgB;AAUnC,MAAM,eAAe,MAAM,OAAO,0BAA0B;AAC5D,IAAI,gBAAwD;AAC5D,MAAM,aAAa,MAChB,kBAAkB,aAAa;AAElC;AAAA,EAKE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAYP,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AAMA,eAAsB,4BACpB,YACA,WACA,MAC2B;AAQ3B,QAAM,YAAa,WAAyB;AAC5C,MAAI,CAAC,UAAW,OAAM,IAAI,MAAM,6CAA6C;AAC7E,QAAM,OAAO,MAAM,UAAU,KAAK,YAAY;AAAA,IAC5C;AAAA,IACA,KAAK,MAAM,OAAO,QAAQ,IAAI;AAAA,IAC9B,GAAI,MAAM,aAAa,EAAE,YAAY,KAAK,WAAW,IAAI,CAAC;AAAA,EAC5D,CAAC;AACD,QAAM,QAAQ,SAAS,IAAI,KAAK,OAAO,KAAK,WAAW,MAAM,WAAW,KAAK,WAAW,IAAI;AAC5F,QAAM,gBAAgB,sBAAsB,IAAI;AAChD,SAAO;AAAA,IACL,WAAW;AAAA,IACX,GAAI,cAAc,SAAS,IAAI,EAAE,cAAc,IAAI,CAAC;AAAA,EACtD;AACF;AAuBA,SAAS,eAAe,QAAiE;AACvF,MAAI,OAAO,QAAS,QAAO,EAAE,KAAK,OAAO,SAAS,SAAS,OAAO,QAAQ,CAAC,EAAE;AAC7E,QAAM,QAAQ,OAAO,SAAS,QAAQ,IAAI,aAAa;AACvD,QAAM,EAAE,SAAS,KAAK,MAAM,QAAQ,IAAI,uBAAuB,OAAO,OAAO,cAAc;AAC3F,SAAO,EAAE,KAAK,QAAQ;AACxB;AAEA,SAAS,iBAAiB;AACxB,SAAO;AAAA,IACL,eAAe,MAAM,QAAQ,QAAQ;AAAA,IACrC,mBAAmB,MACjB,QAAQ,QAAQ,EAAE,SAAS,EAAE,SAAS,YAAqB,EAAE,CAAC;AAAA,EAClE;AACF;AASA,eAAsB,qBACpB,SAA8B,CAAC,GAC/B,MAC8B;AAC9B,QAAM,EAAE,cAAc,sBAAsB,0BAA0B,iBAAiB,IACrF,MAAM,WAAW;AACnB,QAAM,EAAE,KAAK,QAAQ,IAAI,eAAe,MAAM;AAC9C,QAAM,YAAY,MAAM,aAAa;AACrC,QAAM,aAAa,MAAM,OAAO,QAAQ,IAAI;AAE5C,QAAM,QAAQ,MAAM,KAAK,SAAS;AAAA,IAChC,OAAO,CAAC,QAAQ,QAAQ,SAAS;AAAA,IACjC,KAAK,QAAQ;AAAA,EACf,CAAC;AAED,MAAI;AACF,UAAM,SAAS;AAAA,MACb,SAAS,MAAM,MAAM,KAAK;AAAA,MAC1B,SAAS,MAAM,MAAM,MAAM;AAAA,IAC7B;AACA,UAAM,aAAa,IAAI,yBAAyB,gBAAgB,MAAM;AAEtE,UAAM,aAAsB,MAAM;AAAA,MAChC,WAAW,WAAW;AAAA,QACpB,iBAAiB;AAAA,QACjB,oBAAoB,CAAC;AAAA,QACrB,YAAY,EAAE,MAAM,iBAAiB,OAAO,YAAY,SAAS,QAAQ;AAAA,MAC3E,CAAC;AAAA,MACD;AAAA,IACF;AAEA,UAAM,OAAO,4BAA4B,UAAU;AAEnD,UAAM,SAA8B;AAAA,MAClC,iBAAiB,KAAK;AAAA,MACtB,aAAa,KAAK,kBAAkB,cAAc;AAAA,MAClD,cAAc,KAAK,kBAAkB,cAAc;AAAA,MACnD,eAAe,KAAK,mBAAmB,cAAc;AAAA,MACrD,aAAa,KAAK,iBAAiB,cAAc;AAAA,MACjD,eAAe;AAAA,MACf,SAAS,KAAK,kBAAkB,cAAc;AAAA,MAC9C,QAAQ,KAAK,iBAAiB,cAAc;AAAA,IAC9C;AAEA,QAAI,KAAK,iBAAiB;AACxB,YAAM,SAAS,MAAM;AAAA,QACnB,6BAA6B,YAAY,EAAE,KAAK,WAAW,CAAC;AAAA,QAC5D;AAAA,MACF,EAAE,MAAM,MAAM,IAAI;AAClB,UAAI,QAAQ;AACV,eAAO,WAAW,OAAO;AACzB,YAAI,OAAO,WAAY,QAAO,oBAAoB,OAAO;AAAA,MAC3D;AAAA,IACF;AAEA,UAAM,cAAuB,MAAM;AAAA,MACjC,WAAW,WAAW,EAAE,KAAK,YAAY,YAAY,CAAC,EAAE,CAAC;AAAA,MACzD;AAAA,IACF,EAAE,MAAM,MAAM,IAAI;AAElB,QAAI,aAAa;AACf,YAAM,YAAa,YAAmC,aAAa;AACnE,YAAM,aAAa,sBAAsB,WAAW;AACpD,UAAI,WAAW,SAAS,GAAG;AACzB,eAAO,gBAAgB;AACvB,eAAO,UAAU;AAAA,MACnB;AAEA,UAAI,KAAK,mBAAmB,WAAW;AACrC,cAAM;AAAA,UACJ,2BAA2B,YAAY,WAAW,IAAI;AAAA,UACtD;AAAA,QACF,EAAE,MAAM,MAAM,MAAS;AAAA,MACzB;AAAA,IACF;AAEA,WAAO;AAAA,EACT,UAAE;AACA,QAAI,CAAC,MAAM,OAAQ,OAAM,KAAK;AAAA,EAChC;AACF;AASA,eAAsB,gBACpB,SAA8B,CAAC,GAC/B,MACkF;AAClF,QAAM,EAAE,cAAc,sBAAsB,0BAA0B,iBAAiB,IACrF,MAAM,WAAW;AACnB,QAAM,EAAE,KAAK,QAAQ,IAAI,eAAe,MAAM;AAC9C,QAAM,YAAY,MAAM,aAAa;AAErC,QAAM,QAAQ,MAAM,KAAK,SAAS;AAAA,IAChC,OAAO,CAAC,QAAQ,QAAQ,SAAS;AAAA,IACjC,KAAK,QAAQ;AAAA,EACf,CAAC;AAED,MAAI;AACF,UAAM,SAAS;AAAA,MACb,SAAS,MAAM,MAAM,KAAK;AAAA,MAC1B,SAAS,MAAM,MAAM,MAAM;AAAA,IAC7B;AACA,UAAM,aAAa,IAAI,yBAAyB,gBAAgB,MAAM;AAEtE,UAAM,aAAsB,MAAM;AAAA,MAChC,WAAW,WAAW;AAAA,QACpB,iBAAiB;AAAA,QACjB,oBAAoB,CAAC;AAAA,QACrB,YAAY,EAAE,MAAM,iBAAiB,OAAO,YAAY,SAAS,QAAQ;AAAA,MAC3E,CAAC;AAAA,MACD;AAAA,IACF;AAEA,UAAM,OAAO,4BAA4B,UAAU;AACnD,QAAI,CAAC,KAAK,gBAAiB,QAAO,EAAE,UAAU,CAAC,GAAG,WAAW,MAAM;AAEnE,UAAM,SAAS,MAAM;AAAA,MACnB,6BAA6B,YAAY,EAAE,KAAK,MAAM,KAAK,QAAQ,MAAM,OAAO,CAAC;AAAA,MACjF;AAAA,IACF;AACA,WAAO,EAAE,GAAG,QAAQ,WAAW,KAAK;AAAA,EACtC,UAAE;AACA,QAAI,CAAC,MAAM,OAAQ,OAAM,KAAK;AAAA,EAChC;AACF;",
|
|
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":"
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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": "AAAA,SAAS,aAAa;AACtB,OAAO,YAAY;AACnB,SAAS,UAAU,gBAAgB;
|
|
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,
|
|
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
|
-
|
|
26
|
-
|
|
27
|
-
} from "./
|
|
28
|
-
|
|
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
|
|
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
|
-
|
|
198
|
-
const
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
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
|
-
|
|
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
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
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
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
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
|
-
|
|
231
|
+
} else if (deltaType === "thinking_delta" && chunk.delta?.thinking) {
|
|
232
|
+
yield { type: "thinking", text: chunk.delta.thinking };
|
|
269
233
|
}
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
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
|
-
|
|
279
|
-
|
|
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 {
|