@automatalabs/acp-agents 0.22.0 → 0.22.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 +35 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
# @automatalabs/acp-agents
|
|
2
2
|
|
|
3
|
-
Low-level building block: the [Agent Client Protocol](https://agentclientprotocol.com) (ACP) client plus Claude and
|
|
3
|
+
Low-level building block: the [Agent Client Protocol](https://agentclientprotocol.com) (ACP) client plus Claude, Codex, OpenCode, and custom backends that implement the `AgentRunner` seam from `@automatalabs/shared-types`. It spawns an ACP server as a child process, drives one subagent turn to completion, and returns structured output or text.
|
|
4
4
|
|
|
5
5
|
This is the layer `@automatalabs/workflows` and `@automatalabs/mcp-server` are built on.
|
|
6
6
|
|
|
7
7
|
## Most users want `@automatalabs/workflows`
|
|
8
8
|
|
|
9
|
-
If you are orchestrating a workflow, use [`@automatalabs/workflows`](../workflows) instead — it re-exports `createAcpRunner` and wires it into the engine for you. Reach for this package directly only when you want to drive a **single**
|
|
9
|
+
If you are orchestrating a workflow, use [`@automatalabs/workflows`](../workflows) instead — it re-exports `createAcpRunner` and wires it into the engine for you. Reach for this package directly only when you want to drive a **single** ACP agent yourself or need the low-level auth/session lifecycle APIs.
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
12
|
npm install @automatalabs/acp-agents
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
Claude and Codex adapters are dependencies of this package. OpenCode is resolved from an
|
|
16
|
+
`opencode-ai` installation or an `opencode` executable on `PATH` only when selected.
|
|
17
|
+
|
|
15
18
|
## Standalone use: drive one agent
|
|
16
19
|
|
|
17
|
-
`createAcpRunner().run(prompt, options)` runs a single agent to completion. Pass a [typebox](https://github.com/sinclairzx81/typebox) `schema` to get a validated object back (typed as `Static<typeof schema>`); omit it to get the final assistant text as a `string`. The
|
|
20
|
+
`createAcpRunner().run(prompt, options)` runs a single agent to completion. Pass a [typebox](https://github.com/sinclairzx81/typebox) `schema` to get a validated object back (typed as `Static<typeof schema>`); omit it to get the final assistant text as a `string`. The Claude, Codex, OpenCode, or registered custom backend is selected from `model` / `tier`. Whoever constructs the runner owns it: call `dispose()` (or use `await using`) when you're done to tear down the pooled child processes.
|
|
18
21
|
|
|
19
22
|
```ts
|
|
20
23
|
import { createAcpRunner } from "@automatalabs/acp-agents";
|
|
@@ -45,7 +48,7 @@ try {
|
|
|
45
48
|
}
|
|
46
49
|
```
|
|
47
50
|
|
|
48
|
-
`run()` accepts the full `RunOptions` seam: `schema`, `model`, `tier`, `cwd`, `instructions`, `label`, `signal` (cancellation), `toolNames` / `disallowedToolNames`, `mcpServers`, `images` (see below), `runId`, `baseInstructions` / `developerInstructions` (Codex-only, see below), `onUsage`, `onModelResolved`, `onModelFallback`, and `onHistory`. See `@automatalabs/shared-types` for the field-by-field contract.
|
|
51
|
+
`run()` accepts the full `RunOptions` seam: `schema`, `model`, `mode`, `tier`, `cwd`, `instructions`, `label`, `signal` (cancellation), `toolNames` / `disallowedToolNames`, `maxSchemaRetries`, `mcpServers`, `images` (see below), `runId`, `backends`, `meta` / `promptMeta`, `baseInstructions` / `developerInstructions` (Codex-only, see below), `keepSession`, `onSessionOpen`, `onUsage`, `onModelResolved`, `onModelFallback`, and `onHistory`. See `@automatalabs/shared-types` for the field-by-field contract.
|
|
49
52
|
|
|
50
53
|
### Image attachments (`images`)
|
|
51
54
|
|
|
@@ -69,7 +72,7 @@ They ride ACP `session/new` `_meta` as bare keys and are threaded into the Codex
|
|
|
69
72
|
|
|
70
73
|
```ts
|
|
71
74
|
await runner.run("Cut the release.", {
|
|
72
|
-
model: "openai/gpt-5
|
|
75
|
+
model: "openai/gpt-5.5",
|
|
73
76
|
cwd: "/abs/path/to/worktree",
|
|
74
77
|
baseInstructions: "You are a release bot. Only touch CHANGELOG.md.",
|
|
75
78
|
developerInstructions: "Prefer conventional-commit summaries.",
|
|
@@ -131,6 +134,28 @@ try {
|
|
|
131
134
|
}
|
|
132
135
|
```
|
|
133
136
|
|
|
137
|
+
## Authentication lifecycle
|
|
138
|
+
|
|
139
|
+
The built-in runner is auth-capable without widening the minimal `AgentRunner` interface.
|
|
140
|
+
`describeAuthMethods()` returns normalized `agent` / `terminal` / `env_var` descriptors;
|
|
141
|
+
`completeAuth()` applies a host resolution; and `runner.auth.status()`, `.authenticate()`, and
|
|
142
|
+
`.logout()` provide the controller form. Construct the runner with `authCapabilities` to advertise
|
|
143
|
+
what the host can complete and `onAuth` to resolve an `AuthContext` inline.
|
|
144
|
+
|
|
145
|
+
Without an inline resolver, an ACP `-32000` signal becomes a non-recoverable
|
|
146
|
+
`WorkflowError { code: "AUTH_REQUIRED", authContext }`. The workflow manager recognizes that code
|
|
147
|
+
and pauses managed runs, but a direct `runner.run()` caller receives the error and decides how to
|
|
148
|
+
authenticate/retry. Credential env/meta payloads remain in the in-memory `AuthStore`, are redacted
|
|
149
|
+
from errors and events, and are zeroized on logout.
|
|
150
|
+
|
|
151
|
+
## Session handoff
|
|
152
|
+
|
|
153
|
+
Use `onSessionOpen` to capture the backend/session/cwd re-attach handle. Set `keepSession: true`
|
|
154
|
+
when the backend supports persistence and the host intends to call `loadSession()` or
|
|
155
|
+
`resumeSession()` later; this skips the release-time best-effort `session/close`. The runner also
|
|
156
|
+
exposes `listSessions()` and `deleteSession()` where advertised. Re-attach support is capability
|
|
157
|
+
gated, so inspect the handle's `reopen` flags rather than assuming every ACP agent persists state.
|
|
158
|
+
|
|
134
159
|
## Listening in: live ACP events
|
|
135
160
|
|
|
136
161
|
`AcpAgentRunner` is also a typed event bus — `runner.on(name, listener)` bubbles up the live ACP stream of every run (streaming text, tool calls, usage, permissions, elicitations). Event names are the ACP `sessionUpdate` discriminants (`agent_message_chunk`, `tool_call`, `usage_update`, …) plus the cross-cutting `session_update` (catch-all), `permission_pending`, `permission_request`, `elicitation_pending`, `elicitation_request`, `elicitation_complete`, `raw_message`, `session_open` / `session_close`, and `backend_error`. Each payload carries a `{ sessionId, backendId, label?, runId? }` context envelope (a pooled runner multiplexes many runs at once). `permission_pending` / `elicitation_pending` are resolver-only and carry `{ request }` before the host resolver is invoked; `permission_request` / `elicitation_request` fire exactly once with the final `{ request, outcome }` returned to the agent; `elicitation_complete` carries `{ notification }` for URL completions. `on()` / `once()` return an unsubscribe thunk; `off()` and `removeAllListeners()` round it out. Listeners are best-effort observers — a throwing listener never affects the run.
|
|
@@ -152,13 +177,14 @@ From [`src/index.ts`](./src/index.ts):
|
|
|
152
177
|
|
|
153
178
|
- **`createAcpRunner(options?)`** — factory returning an `AcpAgentRunner` (this is what `@automatalabs/workflows` injects into the engine).
|
|
154
179
|
- **`AcpAgentRunner`** — the `AgentRunner` implementation; `run(prompt, options)`, `openSession(options)`, `dispose()`, and `[Symbol.asyncDispose]()` for `await using`. The caller that constructs a runner owns its lifecycle.
|
|
155
|
-
- **Auth/provider lifecycle methods** — `authMethods()`, `authenticate()`, `listProviders()`, `setProvider()`, `disableProvider()`, and `logout()`; see [docs/api.md](../../docs/api.md) for capability gating and installed adapter support.
|
|
180
|
+
- **Auth/provider lifecycle methods** — `describeAuthMethods()`, `completeAuth()`, `runner.auth`, `authMethods()`, `authenticate()`, `listProviders()`, `setProvider()`, `disableProvider()`, and `logout()`; see [docs/api.md](../../docs/api.md) for capability gating and installed adapter support.
|
|
156
181
|
- **Session lifecycle methods** — `listSessions()`, `deleteSession()`, `loadSession()`, and `resumeSession()` for backends that advertise session persistence; see [docs/api.md](../../docs/api.md).
|
|
157
182
|
- **`InteractiveSession` / `InteractiveSessionOptions` / `InteractiveTurn`** — the held-open multi-turn session surface returned by `openSession()`.
|
|
158
183
|
- **`AcpRunnerOptions.onElicitation`** — runner-wide ACP elicitation responder; sessions can override with `InteractiveSessionOptions.onElicitation`.
|
|
159
184
|
- **`selectBackend({ model, tier }, registry?)`** — the cross-provider routing rule: which backend a spec maps to (registered custom names match first, exact or `name/<inner-model>`).
|
|
160
|
-
- **`ClaudeBackend` / `CodexBackend`** — the
|
|
161
|
-
- **`CustomAcpBackend` / `resolveBackendRegistry` / `BACKENDS_ENV`** — the custom-backend registry: run **any** ACP agent as a named backend via `createAcpRunner({ backends: { name: { command, args?, env?, sessionMeta?, customCapabilities? } } })` or the `AGENTPRISM_BACKENDS` env var (JSON, same shape; the option wins per name; `claude`/`codex` reserved). Custom backends carry a `schema` as turn-level `_meta.outputSchema` and read the result off the final message as JSON. `customCapabilities: { namespace, gatedKeys }` declares the agent's `agentCapabilities._meta` negotiation contract: once the agent advertises that namespace, each declared bare `_meta` key is sent only when its same-named flag is `true` (no declaration = never gated).
|
|
185
|
+
- **`ClaudeBackend` / `CodexBackend` / `OpenCodeBackend`** — the three built-in backend strategies (spawn config + per-backend schema/auth wiring). OpenCode is host-resolved rather than bundled.
|
|
186
|
+
- **`CustomAcpBackend` / `resolveBackendRegistry` / `BACKENDS_ENV`** — the custom-backend registry: run **any** ACP agent as a named backend via `createAcpRunner({ backends: { name: { command, args?, env?, sessionMeta?, customCapabilities? } } })` or the `AGENTPRISM_BACKENDS` env var (JSON, same shape; the option wins per name; `claude`/`codex`/`opencode` reserved). Custom backends carry a `schema` as turn-level `_meta.outputSchema` and read the result off the final message as JSON. `customCapabilities: { namespace, gatedKeys }` declares the agent's `agentCapabilities._meta` negotiation contract: once the agent advertises that namespace, each declared bare `_meta` key is sent only when its same-named flag is `true` (no declaration = never gated).
|
|
187
|
+
- **Auth contracts and lifecycle** — `AuthStore`, `BackendAuthMachine`, `buildAuthDescriptors`, the built-in auth profiles, and the `AuthContext` / `AuthResolution` / `AuthMethodDescriptor` / `AuthCapableRunner` types.
|
|
162
188
|
- **`PermissionResolver`** — async human-in-the-loop permission resolution for runner-wide or interactive sessions.
|
|
163
189
|
- **`clientCapabilitiesFor` + the `ClientHandlers` / `FsHandlers` / `TerminalHandlers` / `AcpSessionContext` types** — the client-side fs/terminal interposition surface (see above).
|
|
164
190
|
- **`negotiateCapabilities` / `adaptPromptContent` / `gateCustomMeta` / `unsupportedMcpServer` + `NegotiatedCapabilities`** — the `initialize` capability-negotiation primitives; the negotiated record for a live connection is exposed on `PooledConnection.capabilities`.
|
|
@@ -178,6 +204,7 @@ Also exported: `AcpAgentPool` / `resolvePoolSize`, `PooledConnection` / `Session
|
|
|
178
204
|
| `AGENTPRISM_CLAUDE_ACP_CMD` / `AGENTPRISM_CLAUDE_ACP_ARGS` | Override the command (and args) used to spawn the Claude ACP server. |
|
|
179
205
|
| `AGENTPRISM_CODEX_ACP_CMD` / `AGENTPRISM_CODEX_ACP_ARGS` | Override the command (and args) used to spawn the Codex ACP server. |
|
|
180
206
|
| `AGENTPRISM_CODEX_ACP_BIN` | Override only the resolved Codex ACP bin path (keeps the default node launcher). |
|
|
207
|
+
| `AGENTPRISM_OPENCODE_ACP_CMD` / `AGENTPRISM_OPENCODE_ACP_ARGS` | Override the command (and args) used to spawn the OpenCode ACP server. |
|
|
181
208
|
|
|
182
209
|
## License
|
|
183
210
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@automatalabs/acp-agents",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": ">=22"
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@agentclientprotocol/claude-agent-acp": "0.57.0",
|
|
31
31
|
"@agentclientprotocol/sdk": "^1.2.1",
|
|
32
|
-
"@automatalabs/codex-acp": "1.5.
|
|
32
|
+
"@automatalabs/codex-acp": "1.5.3",
|
|
33
33
|
"@modelcontextprotocol/sdk": "^1.29",
|
|
34
34
|
"typebox": "1.3.2",
|
|
35
35
|
"@automatalabs/shared-types": "0.14.0"
|