@agen-ai/provider-acp 0.0.0-stage → 0.4.0

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 (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +480 -2
  3. package/dist/auth/controller.d.ts +23 -0
  4. package/dist/auth/controller.js +170 -0
  5. package/dist/auth/methods.d.ts +12 -0
  6. package/dist/auth/methods.js +51 -0
  7. package/dist/capabilities.d.ts +4 -0
  8. package/dist/capabilities.js +46 -0
  9. package/dist/configuration/catalog.d.ts +35 -0
  10. package/dist/configuration/catalog.js +222 -0
  11. package/dist/configuration/control.d.ts +19 -0
  12. package/dist/configuration/control.js +109 -0
  13. package/dist/configuration/errors.d.ts +6 -0
  14. package/dist/configuration/errors.js +15 -0
  15. package/dist/configuration.d.ts +3 -0
  16. package/dist/configuration.js +9 -0
  17. package/dist/connection/acquire.d.ts +6 -0
  18. package/dist/connection/acquire.js +30 -0
  19. package/dist/connection/contracts.d.ts +28 -0
  20. package/dist/connection/contracts.js +0 -0
  21. package/dist/connection/errors.d.ts +5 -0
  22. package/dist/connection/errors.js +11 -0
  23. package/dist/connection/initialize.d.ts +16 -0
  24. package/dist/connection/initialize.js +225 -0
  25. package/dist/connection/negotiation.d.ts +6 -0
  26. package/dist/connection/negotiation.js +43 -0
  27. package/dist/contracts.d.ts +62 -0
  28. package/dist/contracts.js +0 -0
  29. package/dist/driver.d.ts +4 -0
  30. package/dist/driver.js +44 -0
  31. package/dist/environment/commands.d.ts +17 -0
  32. package/dist/environment/commands.js +104 -0
  33. package/dist/host/contracts.d.ts +108 -0
  34. package/dist/host/contracts.js +0 -0
  35. package/dist/host/interactions.d.ts +22 -0
  36. package/dist/host/interactions.js +146 -0
  37. package/dist/host/leases.d.ts +18 -0
  38. package/dist/host/leases.js +69 -0
  39. package/dist/host/lifecycle.d.ts +9 -0
  40. package/dist/host/lifecycle.js +56 -0
  41. package/dist/host/router.d.ts +47 -0
  42. package/dist/host/router.js +165 -0
  43. package/dist/host/terminals.d.ts +15 -0
  44. package/dist/host/terminals.js +94 -0
  45. package/dist/host/validation.d.ts +13 -0
  46. package/dist/host/validation.js +69 -0
  47. package/dist/index.d.ts +7 -0
  48. package/dist/index.js +10 -0
  49. package/dist/instance.d.ts +20 -0
  50. package/dist/instance.js +248 -0
  51. package/dist/limits.d.ts +14 -0
  52. package/dist/limits.js +42 -0
  53. package/dist/mcp.d.ts +9 -0
  54. package/dist/mcp.js +62 -0
  55. package/dist/node/contracts.d.ts +15 -0
  56. package/dist/node/contracts.js +0 -0
  57. package/dist/node/index.d.ts +6 -0
  58. package/dist/node/index.js +20 -0
  59. package/dist/node/launch.d.ts +10 -0
  60. package/dist/node/launch.js +36 -0
  61. package/dist/node/process.d.ts +4 -0
  62. package/dist/node/process.js +98 -0
  63. package/dist/session/completion.d.ts +4 -0
  64. package/dist/session/completion.js +59 -0
  65. package/dist/session/create.d.ts +21 -0
  66. package/dist/session/create.js +27 -0
  67. package/dist/session/errors.d.ts +6 -0
  68. package/dist/session/errors.js +15 -0
  69. package/dist/session/files.d.ts +8 -0
  70. package/dist/session/files.js +35 -0
  71. package/dist/session/mapping.d.ts +36 -0
  72. package/dist/session/mapping.js +231 -0
  73. package/dist/session/media.d.ts +5 -0
  74. package/dist/session/media.js +22 -0
  75. package/dist/session/native.d.ts +7 -0
  76. package/dist/session/native.js +34 -0
  77. package/dist/session/opening.d.ts +22 -0
  78. package/dist/session/opening.js +67 -0
  79. package/dist/session/plans.d.ts +5 -0
  80. package/dist/session/plans.js +20 -0
  81. package/dist/session/queue.d.ts +32 -0
  82. package/dist/session/queue.js +105 -0
  83. package/dist/session/requests/elicitation.d.ts +14 -0
  84. package/dist/session/requests/elicitation.js +24 -0
  85. package/dist/session/requests/forms.d.ts +31 -0
  86. package/dist/session/requests/forms.js +241 -0
  87. package/dist/session/requests/pending.d.ts +46 -0
  88. package/dist/session/requests/pending.js +79 -0
  89. package/dist/session/requests/resolution.d.ts +5 -0
  90. package/dist/session/requests/resolution.js +32 -0
  91. package/dist/session/resources.d.ts +30 -0
  92. package/dist/session/resources.js +99 -0
  93. package/dist/session/session.d.ts +43 -0
  94. package/dist/session/session.js +479 -0
  95. package/dist/session/turn.d.ts +33 -0
  96. package/dist/session/turn.js +0 -0
  97. package/package.json +58 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Trevor Nichols
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,481 @@
1
- # Temporary Holding Version
1
+ # @agen-ai/provider-acp
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ An optional provider for the AgenAI coding-agent runtime. It translates the stable
4
+ Agent Client Protocol wire version 1 into the existing Agent Protocol V10 session
5
+ API at coordinated SDK version `0.4.0`.
6
+ The package is ESM, MIT licensed, side-effect-free on import and requires Node.js
7
+ 22 or newer. It depends only on the public transport, runtime and protocol packages;
8
+ the core packages remain independent of ACP.
9
+
10
+ The provider pins the transport's `schema-v1.23.0` stable profile. It translates
11
+ ACP into existing V10 capabilities and rejects unsupported semantics explicitly.
12
+ Connection negotiation, configured host facilities, and mapping policy fix one
13
+ capability envelope per instance; every later connection must match it.
14
+
15
+ ## Unknown extensions
16
+
17
+ Both `createAcpProviderDriver` and `createNodeAcpProviderDriver` default to
18
+ `unknownExtensionPolicy: 'standard'`. This deliberately changes the public
19
+ provider default in `0.4.0`. Direct transport clients
20
+ continue to default to `'reject'`. AgenAI's controlled private Hostd composition
21
+ explicitly selects `'reject'`; public interoperability does not change that policy.
22
+
23
+ Standard handling discards otherwise unregistered underscore notifications after
24
+ the transport's envelope, size and notification-rate checks. An unsupported
25
+ underscore request receives a correlated `-32601` response without invoking a
26
+ host callback. Core methods, exact registered extensions and protocol controls
27
+ keep their existing validation; malformed registered payloads and unknown `$/`
28
+ controls still fail the connection. Ignoring an optional message such as
29
+ `_x.ai/mcp/servers_updated` establishes no MCP tool exposure or feature support.
30
+ Discarded notifications produce no neutral event or effect authority. Request
31
+ errors remain within the existing outbound byte/backpressure budget and retain
32
+ their IDs until writing finishes; all other transport/provider bounds remain
33
+ unchanged. Required vendor features still need an explicit supported mapping.
34
+
35
+ Set `unknownExtensionPolicy: 'reject'` on either provider constructor to retain
36
+ strict handling on every connection, including authentication reconnects and
37
+ native resume. Only `undefined` selects the default; other values outside
38
+ `'standard'` and `'reject'` throw `TypeError` before connection acquisition or
39
+ process launch. The constructor captures the resolved policy, so later mutation
40
+ of its options cannot change it. The policy is host composition and is absent
41
+ from the closed, empty serialized `driverConfiguration`. Changing policy needs
42
+ a fresh driver and materialization; uncertain native work must not be retried
43
+ under a different policy.
44
+
45
+ ## Capability matrix
46
+
47
+ | Surface | Supported behavior and requirements |
48
+ | --- | --- |
49
+ | Turns and requests | Default text turns, streamed assistant/reasoning text, tool progress, cancellation and once-only exact-action permissions. One execution retains the original native prompt across request waits and answers. |
50
+ | Resume | Exact persisted binding using advertised `session/resume`, otherwise advertised `session/load`. Load history is bounded and suppressed from new-turn output. No automatic recreation after failure. |
51
+ | Configuration | Managed by default. Explicit `configuration: 'selectable'` maps observed boolean/select catalogs, with a session-mode fallback when config options are absent. Unknown metadata differs from observed empty metadata. |
52
+ | Forms | Canonical boolean/single-select/multi-select forms that fit V10 constraints. An intent stage preserves decline separately from cancel, followed by answers on the same native waiter. Explicit host form facilities can handle broader native forms. |
53
+ | Images | Inline base64 PNG/JPEG/WebP only when the peer advertises image input, within image and total turn budgets. No implicit local-file read or URL fetch. |
54
+ | Plans | Complete replacements of observed turn plans. A mode called “plan” does not establish enforced planning behavior or approval authority. |
55
+ | File changes | Partial structured observations from native tool diffs. Canonical paths contained by the working directory become sorted relative display paths without filesystem reads. Unfinished tools remain unknown at ordinary turn completion. No final workspace diff or Review artifact is inferred. |
56
+ | Commands | Session catalogs and invalidations from `available_commands_update`. Missing metadata remains uninitialized; an observed empty list is available and empty. |
57
+ | Authentication | Explicit method-to-flow selection and host interaction facilities. Agent methods retain the authenticated connection; terminal methods require a host facility and fresh verified initialization afterward. |
58
+ | Files and terminals | Explicit host callbacks, correlated to the bound native session. Terminal support requires the complete output/wait/kill/release lifecycle; embedded terminal transcript references remain unsupported. |
59
+ | MCP setup | Static host-approved `mcpServers` and optional owned `sessionMcpBinding` factory for creation/resume. HTTP/SSE require advertised peer support. Configuration is not observed tool exposure. |
60
+
61
+ Through-turn branching, same-turn steering, enforced plan mode, persistent
62
+ permission grants, context usage/compaction, account quota, effective skill/rule
63
+ inventory, collaboration, generated resources and artifact publication remain
64
+ unsupported. ACP usage counters can decrease without confirmed compaction and
65
+ cannot satisfy V10's context continuity contract. Unsupported media output fails
66
+ explicitly rather than disappearing from an otherwise successful transcript.
67
+ Embedded terminal references also fail explicitly: a mutable, possibly truncated
68
+ terminal snapshot does not provide an ordered append-only transcript. Agents can
69
+ use terminal RPCs and emit their observed output as ordinary text/tool content.
70
+
71
+ ACP administration (list/delete/logout/import) has no portable provider API in
72
+ this release. Host-owned integrations may use the transport directly with their
73
+ own authorization and native lifecycle policy. No capability grants authority
74
+ over other conversations or account state.
75
+
76
+ ## Operational failures and uncertainty
77
+
78
+ The provider maps supported standard `schema-v1.23.0` prompt errors into V10 `AgentError` values.
79
+ Standard `-32000` reports `authentication` with an `authenticate` user-action hint; `-32602` reports
80
+ `invalid_request`; `-32603` reports `provider`; standard parse/request/method errors report `protocol`.
81
+ Other remote codes remain `unknown` with unknown recovery. Mapping uses the standard error code,
82
+ without copying remote messages, arbitrary data or xAI-specific meanings into a canonical failure.
83
+ Generic ACP does not infer rate limits or exhausted allowance from vendor code `-32003`, and its
84
+ account-quota capability remains unsupported.
85
+
86
+ A validated prompt error response establishes a failed terminal result. A lost response, process loss,
87
+ or unconfirmed cancellation after dispatch does not establish that result; preserve uncertainty and
88
+ close the unusable session without replaying its prompt. Operational classification cannot override
89
+ native settlement or cleanup ownership. The provider does not infer `runtime.retrying` from an RPC
90
+ failure, add a retry loop or enable a vendor retry extension. A future faithful mapping still needs
91
+ explicit native evidence and turn correlation.
92
+
93
+ ## Explicit Node process launch
94
+
95
+ Import process construction through the exact `/node` entrypoint. Supply an
96
+ absolute executable and working directory. Arguments are literal strings and
97
+ spawning always uses `shell: false`. Only the supplied environment is passed to
98
+ the child; the current process environment is never inherited.
99
+
100
+ ```ts
101
+ import {
102
+ parseAgentConfigurationRevisionId,
103
+ parseAgentInstanceId,
104
+ parseAgentProviderKey,
105
+ parseAgentSessionId,
106
+ parseAgentTurnId,
107
+ } from '@agen-ai/agent-protocol';
108
+ import {
109
+ createAgentProviderRegistry,
110
+ isAgentProviderSessionCleanupErrorFor,
111
+ type AgentProviderCreateSessionInput,
112
+ type AgentProviderSession,
113
+ } from '@agen-ai/agent-runtime';
114
+ import { createNodeAcpProviderDriver } from '@agen-ai/provider-acp/node';
115
+
116
+ const providerKey = parseAgentProviderKey('my-acp-agent');
117
+ const instanceId = parseAgentInstanceId('my-agent:primary');
118
+ const driver = createNodeAcpProviderDriver({
119
+ providerKey,
120
+ launch: {
121
+ executable: '/opt/my-agent/bin/agent',
122
+ args: ['--acp'],
123
+ cwd: '/work/project',
124
+ env: { HOME: '/work/agent-home', PATH: '/usr/bin:/bin' },
125
+ },
126
+ });
127
+ const registry = await createAgentProviderRegistry({
128
+ drivers: [driver],
129
+ definitions: [{ providerKey, instanceId, driverConfiguration: {} }],
130
+ });
131
+ const instance = registry.requireInstance(instanceId);
132
+ const openingInput: AgentProviderCreateSessionInput = {
133
+ sessionId: parseAgentSessionId('session:example'),
134
+ workingDirectory: '/work/project',
135
+ configuration: {
136
+ kind: 'managed',
137
+ revision: parseAgentConfigurationRevisionId('configuration:1'),
138
+ },
139
+ onBindingCreated(binding) {
140
+ // Persist this exact opaque binding before proceeding with application work.
141
+ console.log(binding);
142
+ },
143
+ };
144
+ let session: AgentProviderSession | undefined;
145
+ let retainedOpeningCleanup = false;
146
+ try {
147
+ try {
148
+ session = await instance.adapter.createSession(openingInput);
149
+ } catch (error) {
150
+ retainedOpeningCleanup = isAgentProviderSessionCleanupErrorFor(error, openingInput);
151
+ throw error;
152
+ }
153
+ const execution = session.startTurn({
154
+ turnId: parseAgentTurnId('turn:example'),
155
+ interactionMode: 'default',
156
+ parts: [{ type: 'text', text: 'Explain this project.' }],
157
+ });
158
+ for await (const output of execution.outputs) {
159
+ console.log(output);
160
+ }
161
+ } finally {
162
+ if (!retainedOpeningCleanup) {
163
+ await session?.close({ reason: 'shutdown' });
164
+ await registry.dispose();
165
+ }
166
+ }
167
+ ```
168
+
169
+ An exact failed-opening cleanup receipt keeps the registry owned. Retain the receipt and call its
170
+ `retryCleanup()` before disposing the registry. A failed session close likewise skips registry
171
+ disposal; retain that session and retry its cleanup before releasing dependent owners.
172
+
173
+ The registry validates instance, adapter, capability, and canonical output
174
+ contracts. `startTurn` reserves one execution; its native prompt starts lazily
175
+ when `execution.outputs` is first consumed. Keep one output consumer through
176
+ actual terminal settlement. Requests are installed before `request.opened`, so
177
+ an answer can be sent immediately from that event with
178
+ `await execution.resolveRequest({ resolution })`, independently of the next
179
+ output pull. One canonical request is offered at a time; additional bounded
180
+ native callbacks retain FIFO order while unrelated output continues.
181
+ The immediate `await` above is appropriate once the answer is already available. If a person must
182
+ choose it, enqueue the exact request to a separately owned, signal-aware handler and keep pulling
183
+ outputs; join that handler after initiating cancellation and close. The public
184
+ [live-output example](../../examples/live-request-output.ts) demonstrates the ownership without
185
+ native launch or credentials, and the [migration guide](../../MIGRATING-TO-0.4.md) shows before/after code.
186
+
187
+ The response Promise reports `delivered`, `rejected` with `requestState` of
188
+ `pending` or `unavailable`, or `delivery_uncertain`. For ACP, `delivered` means the
189
+ exact still-live local callback accepted the answer, or the canonical form flow
190
+ accepted its intent step. An intent receipt does not await the fields answer.
191
+ The later JSON-RPC write has no peer acknowledgment; delivery does not establish
192
+ wire receipt or model consumption. A later transport failure belongs to the
193
+ original execution's output and cannot revoke an accepted response or authorize
194
+ its replay. Local input/correlation and pre-abort failures reject with their
195
+ precise errors. Do not retry an uncertain response or prompt.
196
+ Only `rejected/pending` preserves the exact response's eligibility for a fresh valid answer.
197
+ `rejected/unavailable` removes it without completing the original execution. Request expiry,
198
+ accepted interruption and observed terminality fence later answers; an older waiting observation
199
+ never restores that eligibility. Close starts native cancellation before joining response work.
200
+ If cleanup fails, retain the session or exact opening-cleanup receipt and its dependent registry/MCP
201
+ resources until the owned retry succeeds.
202
+
203
+ The `startTurn` signal and deadline govern the entire native prompt, including
204
+ time spent waiting for permission or a form answer. Keep them valid through
205
+ terminal settlement. `execution.resolveRequest` has its own operation signal,
206
+ which does not replace the original prompt lifetime. Await each output
207
+ destination's acknowledgement before advancing the iterator. Persist the exact
208
+ opaque binding before application work; a display log is not durable session
209
+ storage.
210
+
211
+ To launch a registry installation, first acquire an exact installation reference
212
+ and resolve its verified recipe through `@agen-ai/acp-registry/node`. Pass the
213
+ absolute executable, literal arguments and approved environment to this same
214
+ constructor. Retain that reference until every session and owned process has
215
+ successfully closed. Startup or disposal failure does not authorize releasing it;
216
+ the host must retain ownership and establish native-process quiescence.
217
+
218
+ ## Injected connections and ownership
219
+
220
+ The root entrypoint exports `createAcpProviderDriver`. Its constructor accepts
221
+ `providerKey`, `createConnection`, and optional `limits`, `configuration`,
222
+ `authentication`, `host`, `mcpServers`, and `sessionMcpBinding`. The connection factory receives the public
223
+ `instanceId` and an initialization `signal`. Return fresh, exclusive Node
224
+ `stdout`, `stdin`, and optional `stderr` streams for every invocation, with one of:
225
+
226
+ - `{ ownership: 'owned', stdout, stdin, stderr?, release }`: the provider invokes
227
+ the lease's idempotent release callback when it closes the connection.
228
+ Concurrent cleanup is coalesced, successful release is retained, and failed
229
+ cleanup can be explicitly retried through session or registry disposal.
230
+ - `{ ownership: 'borrowed', stdout, stdin, stderr? }`: the provider removes its
231
+ stream listeners on close and leaves stream destruction to the caller.
232
+
233
+ The factory owns acquisition work until it returns a lease and must honor its
234
+ abort signal. Initialization has one deadline covering acquisition and the
235
+ initialize request. If an uncooperative factory delivers an owned lease after
236
+ that deadline, the provider invokes its release callback asynchronously; callers
237
+ remain responsible for factory work that never returns a lease. A release
238
+ callback owns only the resources of its own lease.
239
+
240
+ Materialization eagerly initializes one connection and reserves it for the
241
+ first session. Later sessions acquire fresh connections, verify the same frozen
242
+ initialization envelope, then create their own native session. Driver
243
+ configuration is strictly `{}`; launch and connection authority belong to the
244
+ driver constructor. The built-in `/node` launcher supports POSIX systems and creates
245
+ a separate process group for each connection. Closing a session or instance sends
246
+ `SIGTERM` to that group, then escalates to `SIGKILL` if necessary. Each phase waits
247
+ up to `shutdownTimeoutMs`; successful cleanup requires both group disappearance and
248
+ closed child streams, including when the leader exited first or descendants closed
249
+ their streams. Failed cleanup remains available for explicit retry.
250
+
251
+ This process-group ownership is not a sandbox: descendants that deliberately leave
252
+ the group require host-provided OS containment. The host must reap exited children.
253
+ The built-in launcher rejects Windows before spawning with
254
+ `acp_provider_process_platform_unsupported`. Windows hosts can use
255
+ `createAcpProviderDriver` with an owned connection factory backed by their own process
256
+ supervisor, such as a Windows Job Object; the SDK does not supply a native Windows
257
+ process-tree launcher in `0.4.0`.
258
+
259
+ ## Session-scoped MCP bindings
260
+
261
+ `sessionMcpBinding: { transport, create }` pairs a host-certified `http` or `sse` transport
262
+ with an owned factory. The provider declares runtime host-binding support only when that transport
263
+ was negotiated with the peer. The factory runs only when an opening carries a `hostBinding`, after
264
+ connection initialization and before native session creation or resume. Its trusted context carries
265
+ the instance/session IDs, working directory, opening operation, validated binding facade and an
266
+ acquisition signal. Parent identity never comes from a model tool argument.
267
+
268
+ An application using the optional orchestration package can compose its explicit bridge:
269
+
270
+ ```ts
271
+ import { startDelegationMcpBridge } from "@agen-ai/agent-orchestration/mcp";
272
+
273
+ const sessionMcpBinding = {
274
+ transport: "http" as const,
275
+ async create({ hostBinding, signal }: import("@agen-ai/provider-acp").AcpSessionMcpBindingContext) {
276
+ const bridge = await startDelegationMcpBridge({ binding: hostBinding, signal });
277
+ return {
278
+ mcpServers: [{ type: "http" as const, name: bridge.server.name, url: bridge.server.url,
279
+ headers: Object.entries(bridge.server.headers).map(([name, value]) => ({ name, value })) }],
280
+ release: bridge.release,
281
+ };
282
+ },
283
+ };
284
+ // Supply sessionMcpBinding to either ACP driver constructor.
285
+ ```
286
+
287
+ Each opening needs a fresh binding and lease, including native resume. Dynamic entries must use the
288
+ declared transport and merge with static entries under the existing combined 32-server/512-KiB
289
+ limits. Duplicate names are rejected. The factory installs the binding's actual tools and
290
+ `tool_context` instructions; ACP does not claim a trusted system/developer instruction channel.
291
+ Neither the factory nor its transport may call the facade's `release`: the validated runtime owns
292
+ the original binding.
293
+
294
+ Factory rejection must leave no factory-owned producers. A partially acquired resource must remain
295
+ represented by an owned lease, including a lease delivered after cancellation. Closing quiesces
296
+ the native connection before releasing the MCP lease, then runtime closes the original binding.
297
+ `hostOperationTimeoutMs` bounds acquisition and cleanup waits without discarding the actual pending
298
+ factory or release promise. Pending or failed opening cleanup blocks new openings and authentication
299
+ changes until its retained responsibility is settled.
300
+ Failed opening cleanup retains an explicit retry receipt; failed or pending cleanup cannot be
301
+ treated as successful disposal. Ending a parent turn does not close its session binding or cancel
302
+ independently admitted children.
303
+
304
+ Advertising a transport and accepting a server list are configuration evidence. Qualify each real
305
+ agent/version separately with MCP initialization, tool discovery and an actual invocation. A peer
306
+ that accepts but never exposes tools is not qualified by this adapter. Configuration labels likewise
307
+ do not certify model, reasoning or fast-mode semantics: hosts must map exact selectable session
308
+ configuration, verify it before the first child prompt, and reject shared/global-only changes.
309
+
310
+ From the public SDK repository root, `pnpm examples:delegation:acp` runs a credentialless peer that
311
+ actually discovers and invokes the managed tools. It applies synthetic Standard/Max configuration
312
+ before the child prompt, lets the parent turn finish while the child waits for approval, and later
313
+ delivers the completion through another authorized parent turn. See `examples/delegation/README.md`
314
+ for the shared direct and qualified durable workflows. These fixtures do not qualify a real native
315
+ agent/version. Required vendor features still need an exact supported mapping, and explicit reject
316
+ policy can prevent session opening after successful initialization when the peer emits an
317
+ unregistered vendor extension. AgenAI Workspaces preferences and Hostd production rollout remain
318
+ separate product work.
319
+
320
+ In the standalone repository, the separate opt-in
321
+ [native qualification example](../../examples/delegation/native/README.md) documents the exact
322
+ Grok Build `1.0.50` (`c58f321264ba`) Linux x86_64 pairing qualified on 2026-10-11 with explicit API-key
323
+ authentication, `grok-4.3`, `Low` reasoning and verified request-default standard mapping. Final MS003
324
+ r6 direct and retained-installation reports record actual managed callbacks and once-only approvals,
325
+ real child-result consumption in a later parent turn, cancellation after provider start and closed
326
+ cleanup. Retained mode observes installer exit before a fresh worker reopens the verified store.
327
+ Those immutable version-1 reports use the prior continuation API; the current version-2 execution
328
+ reports require fresh installed qualification. Current hermetic checks establish synthetic behavior.
329
+ The review-applicability record preserves those reports and separately qualifies later preflight,
330
+ deadline and diagnostic-cleanup repairs. The locally authored catalog and transformed binary prove
331
+ exact artifact/launch identity, without authenticating a publisher or certifying backend billing.
332
+ This scope does not qualify browser login, durable native recovery, private Hostd/fleet execution,
333
+ other native pairings, releases or platforms. The qualified SQLite reference remains separate.
334
+
335
+ The 2026-10-10 Grok Build `1.0.34` session-opening failure on `_x.ai/mcp/servers_updated` remains
336
+ historical evidence under the then-strict policy; it involved no model prompt or paid inference.
337
+ The public standard default does not retroactively qualify that binary.
338
+
339
+ ## Configuration and resume
340
+
341
+ Choose `configuration: 'selectable'` at driver construction to expose the existing
342
+ runtime configuration port. Preserve native defaults with this bootstrap input:
343
+
344
+ ```ts
345
+ const configuration = {
346
+ kind: 'selected' as const,
347
+ revision: parseAgentConfigurationRevisionId('configuration:1'),
348
+ catalogRevision: 1,
349
+ selections: [],
350
+ };
351
+ ```
352
+
353
+ This reserved input is not evidence of an empty catalog. Read `listConfiguration`, present its offered
354
+ fields/options, and submit its exact catalog and field revisions through
355
+ `applyConfigurationSelection`.
356
+
357
+ Native field/option IDs remain behind opaque public IDs. Group labels preserve
358
+ their context. Empty optional descriptions normalize to an omitted description;
359
+ identifiers, labels and metadata bounds remain validated. Changed mapped catalogs advance revisions;
360
+ duplicate observations do not. The provider checks the offered revision immediately before local
361
+ dispatch and requires an acknowledged result. ACP supplies no peer-side
362
+ compare-and-set, so this is not an atomic remote-state guarantee. A dispatched
363
+ selection with a failed, lost or unconfirmed result makes the session unusable;
364
+ close and rematerialize without automatically replaying the selection.
365
+
366
+ Persist the exact binding supplied by `onBindingCreated` and pass it to the
367
+ runtime's normal `resumeSession`. Resume restores that conversation, not a
368
+ requested history anchor or fabricated branch. Load replay has total byte/message
369
+ bounds and an opening deadline. Historical permission requests are rejected.
370
+
371
+ ## Host facilities and authentication
372
+
373
+ The typed `host` object supplies optional `form`, `url`, `readTextFile`,
374
+ `writeTextFile`, `createTerminal`, and `authenticateInTerminal` callbacks. There
375
+ are no ambient filesystem, terminal, browser, credential or environment fallbacks.
376
+ Callbacks receive the instance, authorized interaction/session scope and abort
377
+ signal. The application must enforce workspace, network, executable and user
378
+ policy before performing the requested operation. Paths and commands are requests,
379
+ not authorization; these callbacks do not create a sandbox.
380
+
381
+ A URL facility presents consent before opening a URL and never prefetches it. Its
382
+ lease supplies the user's accept/decline/cancel decision, optional completion,
383
+ and idempotent release. Publishing a URL does not count as acceptance. Out-of-turn
384
+ form/URL interactions must match an exact active session-control or authentication
385
+ RPC ID. Unknown/completed IDs are rejected; prompts do not acquire this authority.
386
+
387
+ Enable authentication with an exact selection such as
388
+ `authentication: { browser: { methodId: 'advertised-method-id' } }` and the host
389
+ interactions required by that agent. Browser/device-code flows require an
390
+ agent-managed method. Terminal flows require an advertised terminal method and
391
+ `host.authenticateInTerminal`, which reproduces the host-configured invocation
392
+ with the method's arguments/environment under host policy. Terminal login does
393
+ not send `authenticate` RPC. Native method labels are not used to guess flows.
394
+
395
+ The provider does not copy credentials between connections. A confirmed
396
+ agent-managed login retains that exact idle connection for the next session.
397
+ Authentication changes are rejected while sessions are active. An interrupted
398
+ attempt after dispatch may leave external account state uncertain; the provider
399
+ retires the connection and does not retry login automatically.
400
+
401
+ File callbacks are independently advertised. Terminal support requires a complete
402
+ facility. Handles are scoped to their connection/session; unknown or cross-session
403
+ handles never reach host callbacks. Leases own their resources even when ACP
404
+ streams are borrowed. Idempotent `release` must terminate a running owned process.
405
+ Hosts must honor abort signals; late-acquired leases are released after cancellation.
406
+ Pending terminal, URL and authentication lease acquisitions remain owned and count
407
+ against facility capacity. Disposal waits within the host-operation deadline and
408
+ fails if acquisition or release is still unresolved. Failed releases remain owned
409
+ for an explicit disposal retry; a successful disposal never hides pending cleanup.
410
+ File reads receive an explicit `maxBytes` bound so the host can reject oversized
411
+ content before allocating it; the provider never silently truncates a file response.
412
+ Terminal handles belong to the session and may span turns. Interrupting a prompt
413
+ does not prove that every terminal exited; native release or session/connection
414
+ close ends that handle's ownership. The host retains control over its process policy.
415
+
416
+ ## Form and media limits
417
+
418
+ Canonical forms preflight the whole schema before presenting a request. They
419
+ support at most 16 ordinary fields and 100 choices per selection. Free-text fields,
420
+ nested objects, numeric fields, defaults, patterns/formats, and constraints without
421
+ a V10 representation are rejected. Native free text permits blank/whitespace values
422
+ and measures length in Unicode code points; V10 text answers use nonblank/UTF-16
423
+ bounds. The provider does not narrow those native semantics silently. Enumerated
424
+ string values can map through opaque canonical selection IDs.
425
+ A required multi-select must require exactly one minimum selection; an optional
426
+ multi-select must allow zero. Unsupported shapes never produce a partial form.
427
+
428
+ The first stage offers “Provide answers” (or “Accept” for an empty form) and
429
+ “Decline”. Canceling either stage returns native cancel; decline returns native
430
+ decline. Submitting the answer stage returns native accept with validated content.
431
+ Both stages hold one native request, adding a user step without prompt replay.
432
+ Active session forms use canonical requests when they fit the supported subset.
433
+ An explicit `host.form` callback handles valid broader forms directly, including
434
+ blank text, Unicode code-point bounds, numeric bounds and defaults without
435
+ canonical conversion. Exactly correlated control/auth forms also use that host
436
+ facility. The provider validates the entire native schema and the host's returned
437
+ content; patterns/formats remain unsupported before any callback. Session forms
438
+ and URL interactions require an active prompt; historical replay or an idle
439
+ binding grants no interaction authority. Their host callbacks receive a turn
440
+ lifetime signal that ends on cancellation, settlement or close.
441
+
442
+ Image input allows at most 16 images, 375,000 decoded bytes per image and 750,000
443
+ decoded bytes total, subject to the stricter 1 MiB V10 turn-content bound. Declared
444
+ media type, dimensions, base64 encoding and byte counts are validated. The provider
445
+ does not decode pixels or publish generated bytes; hosts needing image-content
446
+ inspection must perform it before submitting input.
447
+
448
+ ## Bounds and evidence
449
+
450
+ `limits` can override `maxQueuedMessages`, `maxQueuedBytes`,
451
+ `maxPendingRequests`, `maxHostTerminals`, `hostOperationTimeoutMs`,
452
+ `authenticationTimeoutMs`, `initializationTimeoutMs`, `promptTimeoutMs`, and
453
+ `cancellationTimeoutMs`. Defaults share a 128-entry, 8 MiB budget across queued
454
+ sources and retained current-turn item state, with output/control headroom
455
+ reserved inside that budget. Large bursts and turns with many retained items
456
+ can exhaust the same budget. Defaults allow 16 pending requests, 16 host terminals,
457
+ 30 seconds for initialization or a host operation, 15 minutes for authentication,
458
+ 30 minutes for a prompt, and 5 seconds for cancellation. Admission
459
+ reserves finite source capacity synchronously. Response and cancellation
460
+ processing remain independent of slow output consumers. Overflow, malformed
461
+ messages, process loss, or unconfirmed cancellation fail closed and require
462
+ closing the unusable session before rematerialization.
463
+
464
+ Readiness reports completed initialization and the reported agent version when
465
+ available. It does not prove authentication or inference. The Node launcher
466
+ does not install agents, load credentials, apply a sandbox, or grant production
467
+ execution authority. Those responsibilities belong to the application. Tests
468
+ use synthetic processes and streams; they do not qualify a native agent,
469
+ authenticated account, paid inference, or a production host.
470
+
471
+ The selected schema is stable `schema-v1.23.0` at upstream commit
472
+ `6d08f412a7a1370d3cc9a124e3be3d6acf92641e`, using ACP wire version 1.
473
+ The package version, schema release and native agent version are separate identities.
474
+ Qualify the exact native release, target, credentials, toolchain and confinement
475
+ policy before relying on native behavior; initialization alone is a narrower claim.
476
+
477
+ ```sh
478
+ pnpm --filter @agen-ai/provider-acp build
479
+ pnpm --filter @agen-ai/provider-acp typecheck
480
+ pnpm --filter @agen-ai/provider-acp test
481
+ ```
@@ -0,0 +1,23 @@
1
+ import type { AgentAuthenticationFlow, AgentInstanceId } from '@agen-ai/agent-protocol';
2
+ import { type AgentProviderAuthentication } from '@agen-ai/agent-runtime';
3
+ import type { AcpInitializedConnection } from '../connection/contracts.js';
4
+ import type { AcpHostFacilities } from '../host/contracts.js';
5
+ import type { AcpProviderLimits } from '../limits.js';
6
+ import type { AcpAuthenticationMethod } from './methods.js';
7
+ export declare function createAcpAuthentication(input: {
8
+ readonly instanceId: AgentInstanceId;
9
+ readonly methods: ReadonlyMap<AgentAuthenticationFlow, AcpAuthenticationMethod>;
10
+ readonly host: AcpHostFacilities;
11
+ readonly limits: AcpProviderLimits;
12
+ readonly lifetime: AbortSignal;
13
+ readonly now: () => string;
14
+ readonly acquire: (signal: AbortSignal) => Promise<AcpInitializedConnection>;
15
+ readonly retain: (connection: AcpInitializedConnection) => void;
16
+ readonly retire: (connection: AcpInitializedConnection) => Promise<void>;
17
+ }): {
18
+ port: AgentProviderAuthentication;
19
+ readonly active: boolean;
20
+ readonly cleanupPending: boolean;
21
+ close(): Promise<void>;
22
+ };
23
+ //# sourceMappingURL=controller.d.ts.map