@automatalabs/acp-agents 0.22.1 → 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.
Files changed (2) hide show
  1. package/README.md +35 -8
  2. 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 Codex backends that implement the `AgentRunner` seam from `@automatalabs/shared-types`. It spawns `claude-agent-acp` / `codex-acp` as child processes, drives one subagent turn to completion over ACP, and returns structured output or text.
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** Claude/Codex agent over ACP yourself.
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 backend (Claude vs Codex) 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.
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-codex",
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 two built-in backend strategies (spawn config + per-backend schema wiring).
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.1",
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.2",
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"