@agen-ai/provider-acp 0.4.0 → 0.4.1

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 (64) hide show
  1. package/README.md +355 -12
  2. package/dist/capabilities.d.ts +3 -1
  3. package/dist/capabilities.js +5 -4
  4. package/dist/configuration/catalog.js +0 -2
  5. package/dist/configuration/errors.js +0 -1
  6. package/dist/connection/contracts.d.ts +21 -0
  7. package/dist/connection/errors.js +0 -1
  8. package/dist/connection/initialize.d.ts +7 -3
  9. package/dist/connection/initialize.js +46 -17
  10. package/dist/connection/negotiation.d.ts +2 -1
  11. package/dist/connection/negotiation.js +15 -1
  12. package/dist/contracts.d.ts +3 -0
  13. package/dist/driver.d.ts +1 -1
  14. package/dist/driver.js +6 -39
  15. package/dist/driverFactory.d.ts +8 -0
  16. package/dist/driverFactory.js +48 -0
  17. package/dist/host/interactions.js +0 -1
  18. package/dist/host/leases.js +0 -1
  19. package/dist/host/router.js +0 -1
  20. package/dist/host/terminals.js +0 -2
  21. package/dist/index.d.ts +1 -0
  22. package/dist/instance.d.ts +7 -2
  23. package/dist/instance.js +102 -27
  24. package/dist/node/contracts.d.ts +6 -0
  25. package/dist/node/execution/errors.d.ts +11 -0
  26. package/dist/node/execution/errors.js +17 -0
  27. package/dist/node/execution/owner.d.ts +34 -0
  28. package/dist/node/execution/owner.js +162 -0
  29. package/dist/node/execution/types.d.ts +20 -0
  30. package/dist/node/execution/types.js +0 -0
  31. package/dist/node/index.d.ts +3 -1
  32. package/dist/node/index.js +16 -6
  33. package/dist/node/launch.d.ts +5 -8
  34. package/dist/node/launch.js +13 -1
  35. package/dist/permissions/contracts.d.ts +22 -0
  36. package/dist/permissions/contracts.js +0 -0
  37. package/dist/permissions/mapping.d.ts +13 -0
  38. package/dist/permissions/mapping.js +99 -0
  39. package/dist/permissions/selection.d.ts +5 -0
  40. package/dist/permissions/selection.js +96 -0
  41. package/dist/session/create.d.ts +7 -1
  42. package/dist/session/create.js +3 -1
  43. package/dist/session/errors.js +0 -1
  44. package/dist/session/mapping.d.ts +6 -0
  45. package/dist/session/mapping.js +5 -26
  46. package/dist/session/opening.d.ts +1 -0
  47. package/dist/session/opening.js +3 -1
  48. package/dist/session/queue.js +0 -1
  49. package/dist/session/requests/forms.js +0 -2
  50. package/dist/session/requests/pending.js +0 -1
  51. package/dist/session/resources.js +5 -3
  52. package/dist/session/session.d.ts +4 -1
  53. package/dist/session/session.js +67 -25
  54. package/dist/sessionInteractions/broker.d.ts +42 -0
  55. package/dist/sessionInteractions/broker.js +171 -0
  56. package/dist/sessionInteractions/contracts.d.ts +3 -0
  57. package/dist/sessionInteractions/contracts.js +0 -0
  58. package/dist/sessionInteractions/extensions.d.ts +3 -0
  59. package/dist/sessionInteractions/extensions.js +17 -0
  60. package/dist/sessionInteractions/grokFolderTrust.d.ts +43 -0
  61. package/dist/sessionInteractions/grokFolderTrust.js +107 -0
  62. package/dist/sessionInteractions/request.d.ts +38 -0
  63. package/dist/sessionInteractions/request.js +145 -0
  64. package/package.json +4 -4
package/README.md CHANGED
@@ -1,17 +1,23 @@
1
1
  # @agen-ai/provider-acp
2
2
 
3
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`.
4
+ Agent Client Protocol wire version 1 into the existing Agent Protocol V11 session
5
+ API. The coordinated source SDK version is `0.4.1` and remains unpublished;
6
+ the published release is `0.4.0`.
6
7
  The package is ESM, MIT licensed, side-effect-free on import and requires Node.js
7
8
  22 or newer. It depends only on the public transport, runtime and protocol packages;
8
9
  the core packages remain independent of ACP.
9
10
 
10
11
  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
+ ACP into current V11 capabilities and rejects unsupported semantics explicitly.
12
13
  Connection negotiation, configured host facilities, and mapping policy fix one
13
14
  capability envelope per instance; every later connection must match it.
14
15
 
16
+ Tool approvals default to once-only scoped consequences. Both constructors accept an explicit
17
+ `permissionMapping` selection for completely described provider-managed remembered choices.
18
+ Native option labels or kinds alone never establish their consequences. See
19
+ [Remembered tool approvals](#remembered-tool-approvals) for mapping admission and qualification limits.
20
+
15
21
  ## Unknown extensions
16
22
 
17
23
  Both `createAcpProviderDriver` and `createNodeAcpProviderDriver` default to
@@ -46,10 +52,10 @@ under a different policy.
46
52
 
47
53
  | Surface | Supported behavior and requirements |
48
54
  | --- | --- |
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. |
55
+ | Turns and requests | Default text turns, streamed assistant/reasoning text, tool progress, cancellation and once-only exact-action permissions by default, with opt-in complete remembered-choice mappings. One execution retains the original native prompt across request waits and answers. |
50
56
  | 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
57
  | 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. |
58
+ | Forms | Canonical boolean/single-select/multi-select forms that fit V11 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
59
  | 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
60
  | Plans | Complete replacements of observed turn plans. A mode called “plan” does not establish enforced planning behavior or approval authority. |
55
61
  | 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. |
@@ -57,12 +63,13 @@ under a different policy.
57
63
  | 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
64
  | 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
65
  | 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. |
66
+ | Session decisions | Opt-in `grok-folder-trust-v1` on the Node constructor, with a required host execution boundary and handler registered before create. This outside-turn mapping has its own exact support and qualification scope below. |
60
67
 
61
68
  Through-turn branching, same-turn steering, enforced plan mode, persistent
62
- permission grants, context usage/compaction, account quota, effective skill/rule
69
+ SDK-owned tool-approval grants, context usage/compaction, account quota, effective skill/rule
63
70
  inventory, collaboration, generated resources and artifact publication remain
64
71
  unsupported. ACP usage counters can decrease without confirmed compaction and
65
- cannot satisfy V10's context continuity contract. Unsupported media output fails
72
+ cannot satisfy V11's context continuity contract. Unsupported media output fails
66
73
  explicitly rather than disappearing from an otherwise successful transcript.
67
74
  Embedded terminal references also fail explicitly: a mutable, possibly truncated
68
75
  terminal snapshot does not provide an ordered append-only transcript. Agents can
@@ -75,7 +82,7 @@ over other conversations or account state.
75
82
 
76
83
  ## Operational failures and uncertainty
77
84
 
78
- The provider maps supported standard `schema-v1.23.0` prompt errors into V10 `AgentError` values.
85
+ The provider maps supported standard `schema-v1.23.0` prompt errors into V11 `AgentError` values.
79
86
  Standard `-32000` reports `authentication` with an `authenticate` user-action hint; `-32602` reports
80
87
  `invalid_request`; `-32603` reports `provider`; standard parse/request/method errors report `protocol`.
81
88
  Other remote codes remain `unknown` with unknown recovery. Mapping uses the standard error code,
@@ -219,7 +226,7 @@ the host must retain ownership and establish native-process quiescence.
219
226
 
220
227
  The root entrypoint exports `createAcpProviderDriver`. Its constructor accepts
221
228
  `providerKey`, `createConnection`, and optional `limits`, `configuration`,
222
- `authentication`, `host`, `mcpServers`, and `sessionMcpBinding`. The connection factory receives the public
229
+ `authentication`, `host`, `mcpServers`, `sessionMcpBinding`, and `permissionMapping`. The connection factory receives the public
223
230
  `instanceId` and an initialization `signal`. Return fresh, exclusive Node
224
231
  `stdout`, `stdin`, and optional `stderr` streams for every invocation, with one of:
225
232
 
@@ -256,6 +263,342 @@ The built-in launcher rejects Windows before spawning with
256
263
  supervisor, such as a Windows Job Object; the SDK does not supply a native Windows
257
264
  process-tree launcher in `0.4.0`.
258
265
 
266
+ ## Remembered tool approvals
267
+
268
+ `permissionMapping` is constructor configuration on both `createAcpProviderDriver` and
269
+ `createNodeAcpProviderDriver`. It is captured when the driver is created and is absent from the
270
+ empty serialized `driverConfiguration`. Omission or `{ mapping: 'once-only-v1' }` retains the
271
+ conservative once-only subset of each menu and advertises `providerManagedRemembrance: false`.
272
+ A remembered-only native menu is unsupported under that default.
273
+
274
+ For a peer whose complete permission behavior you have inspected and qualified, declare its exact
275
+ initialized identity and complete ordered menus:
276
+
277
+ ```ts
278
+ import type { AcpPermissionMappingSelection } from '@agen-ai/provider-acp';
279
+
280
+ const permissionMapping = {
281
+ mapping: 'declared-complete-consequences-v1',
282
+ agentInfo: { name: 'example-agent', version: '1.2.3' },
283
+ menus: [{
284
+ toolKind: 'edit',
285
+ options: [
286
+ { optionId: 'allow-once', kind: 'allow_once' },
287
+ { optionId: 'remember-allow', kind: 'allow_always' },
288
+ { optionId: 'deny-once', kind: 'reject_once' },
289
+ { optionId: 'remember-deny', kind: 'reject_always' },
290
+ ],
291
+ }],
292
+ } as const satisfies AcpPermissionMappingSelection;
293
+ ```
294
+
295
+ Pass that value with your ordinary connection or Node launch options. The example identities are
296
+ illustrative. Selecting this mapping is your attestation that every listed option has only its
297
+ current allow/deny decision and once-only or provider-managed remembered consequence. A choice
298
+ that also changes mode, clears context or grants another authority needs a different complete
299
+ mapping; this API cannot discover hidden effects or authenticate the implementation from its name.
300
+
301
+ Declarations contain 1–16 menus, each with 1–16 options. Native IDs must be canonical strings of
302
+ 1–256 characters and unique within each menu. Menu signatures must be unique. Peer names are
303
+ bounded to 256 characters and versions to 160; edge whitespace and control/format characters are
304
+ rejected. Tool kinds use the pinned ACP standard vocabulary. Selection uses exact identity, tool
305
+ kind and the complete ordered ID/kind list; native labels are display data. There are no predicates,
306
+ regular expressions, native payload bags or custom mapping callbacks.
307
+
308
+ The capability reflects the selected declarations. Remembered-only menus advertise no precise
309
+ modes and `providerManagedRemembrance: true`; combined menus advertise once/exact-action as well.
310
+ A remembered option has the neutral label “Allow and remember” or “Deny and remember” and an
311
+ explanation that duration and future matching are unspecified. Native wording is omitted from its
312
+ optional description. An offered choice never promises that a provider actually saved a rule.
313
+
314
+ The SDK keeps distinct offered IDs, including several options with the same immediate decision.
315
+ Resolve one exact public option ID on the original execution. The live callback returns its exact
316
+ original native ID once. Deny-once, deny-and-remember and cancellation remain distinct. Continue
317
+ reading the original execution outputs through terminal settlement; a delivery receipt establishes
318
+ local callback acceptance, not native persistence, later matching or successful tool execution.
319
+
320
+ Malformed constructor selection throws `TypeError` before acquisition. A selected peer identity
321
+ mismatch fails initialization with `acp_permission_profile_mismatch`; retain any failed cleanup
322
+ owner as usual. Declared menu mismatches or unqualified option/request metadata fail with
323
+ `acp_permission_consequence_unsupported`. Duplicate IDs are rejected across the entire native menu
324
+ before any filtering. Invalid menu size fails with `acp_permission_options_invalid`. The default's
325
+ remembered-only refusal remains `acp_permission_persistence_unsupported`.
326
+
327
+ The built-in `{ mapping: 'grok-build-1.0.50-edit-remembrance-v1' }` selects the narrowly inspected
328
+ Grok Build 1.0.50 edit behavior. Its peer must report `_meta.agentVersion: '1.0.50'`. It recognizes
329
+ only the inspected `SearchReplace` edit input with `replace_all: false` and the ordered native menu
330
+ `allow-edits-session`/`allow_always`, `allow-once`/`allow_once`, `reject-once`/`reject_once`.
331
+ Other action categories retain the once-only subset with an explicit warning on the original
332
+ output stream; unsupported remembered-only menus fail. Native terminal remembrance and remembered
333
+ denial are not qualified by this edit profile. Duration and applicability remain unknown despite
334
+ native wording or observed same-session behavior.
335
+
336
+ The selected constructor and your host-owned installation/launch attest to the exact inspected
337
+ native executable; the reported version does not authenticate its bytes. The inspected candidate
338
+ is Linux x86_64 Grok Build 1.0.50 (`c58f321264ba`), SHA-256
339
+ `c80de0155706ff2d995623887b102f2d0abd2c62b2643dea3a0cebaf7dd724d5`, launched with
340
+ `agent --no-leader stdio`. Controlled mapping tests prove exact reply behavior; the installed
341
+ native fixture proof below separately establishes the selected edits' actual effects and cleanup.
342
+
343
+ This turn-level selection is independent of session-lifetime folder trust, host filesystem/terminal
344
+ facilities and unknown-extension policy. It creates no SDK permission database, automatic answer
345
+ cache, revoke operation or private Workspaces execution authority.
346
+
347
+ ### Qualified remembered-edit scope (SDK03)
348
+
349
+ Two final native fixture attempts used the genuine executable above, the selected
350
+ `grok-build-1.0.50-edit-remembrance-v1` mapping, modern stable `schema-v1.23.0` and a matching
351
+ installed seven-package `0.4.1`/Agent Protocol V11 set. The recorded tuple is Linux x86_64 kernel
352
+ `7.0.0-38-generic`, Node `24.18.0`, pnpm `11.7.0`, systemd `259.5`, Bubblewrap `0.11.1` and owned
353
+ tmpfs state. An isolated loopback model fixture drove actual native tool calls without real account
354
+ credentials or paid/backend inference. The SDK owned the only ACP reader and responder; a passive
355
+ observer independently checked exact native choices and actual fixture effects.
356
+
357
+ The first attempt used one public/native session and six turns:
358
+
359
+ | Turn | Observed request and effect |
360
+ | --- | --- |
361
+ | Once-only edit | One request; exact once-only native choice delivered once; edit performed. |
362
+ | Repeat after once-only | Asked again; exact once-only choice delivered once; edit performed. |
363
+ | Remembered edit | One request; exact remembered native choice delivered once; edit performed. |
364
+ | Exact repeat after remembrance | No new request; edit performed. |
365
+ | Neighboring owned file | No new request; edit performed. |
366
+ | Uncovered terminal action | Asked again; effect occurred after its exact once-only approval. |
367
+
368
+ The second attempt reopened the verified retained owned state with both a fresh native process
369
+ and a distinct native session. Its first edit asked again and performed the expected edit after
370
+ one exact once-only answer. This combined restart/new-session observation does not isolate the
371
+ effect of either change or define a general expiry or storage contract. Same-process second-session
372
+ behavior was observed only in separate native discovery, outside this installed Node composition.
373
+
374
+ For both attempts, successful public `session.close()` preceded an independent empty checkpoint
375
+ of the same physical workload cgroup while the controller remained alive, before registry or host
376
+ disposal. No earlier external cleanup intervention or OOM kill occurred. Native effects, answer
377
+ correlation and SDK cleanup were checked independently.
378
+
379
+ The exact retained report SHA-256 identities are
380
+ `4ea3ea5b9fac16761b32919ac476ec9b4621f2e99434c441d9eefadb469c5a6b` (six-turn attempt) and
381
+ `bd93b95c3fdba51b0f7f03eaea0393e796a4626298eaedb2a9ebf1ce9bb36730` (retained-state restart).
382
+ The native-used package archives have these SHA-256 identities:
383
+
384
+ | Package at `0.4.1` | Native-used archive SHA-256 |
385
+ | --- | --- |
386
+ | `@agen-ai/validation` | `84d97191d2175be1c7d83e86a007157b80c303088b94be0c05ec6961e2a41729` |
387
+ | `@agen-ai/agent-protocol` | `5a647b2fa504ec3175d58075f503f5e9e435186ec0e8c0758e74ea37741ad192` |
388
+ | `@agen-ai/agent-runtime` | `81dc5ed8940d96bc5f3ae3f0fdb2ad862af87a087e57032db41995a29dacf4b4` |
389
+ | `@agen-ai/agent-orchestration` | `914ad78cdac3ee6af1fe6a7d8522e5c216a3de670816462a082f5c0bde0988fa` |
390
+ | `@agen-ai/acp-transport` | `81314926f24fa428e910c0256671add61f525cac036d5b2841185a7c3e953894` |
391
+ | `@agen-ai/provider-acp` | `2a68df821134fc0af48ab850c1a48ad33be74b8e42e64a6d916bfe2eb84acf6a` |
392
+ | `@agen-ai/acp-registry` | `ab317cc347bf53dcd0045aff4a6d74cb429fc6781c336ea6ed128ced13bdaa07` |
393
+
394
+ Later documentation or packing can change archive bytes; the same version is not an identity
395
+ check. Reuse of this evidence requires comparison of the exact installed dependency closure,
396
+ runtime/declaration members, mapping and host composition. The earlier SDK02 folder-trust proof
397
+ below used different `0.4.1`/V10 artifacts and establishes a separate session-lifetime behavior.
398
+
399
+ Duration and applicability remain unknown. This fixture proof does not qualify arbitrary path
400
+ matching, separate projects/profiles, remembered denial, terminal remembrance, revocation,
401
+ worktree/account/distributed behavior, real-model inference or other native/runtime pairings.
402
+ It does not publish packages, integrate a consumer application or enable private execution.
403
+
404
+ ## Session-lifetime folder decisions
405
+
406
+ The unpublished `0.4.1` source includes the opt-in mapping on
407
+ `createNodeAcpProviderDriver`:
408
+ `sessionInteractions: { mapping: 'grok-folder-trust-v1' }`. Supply an explicit
409
+ `executionBoundary` at construction and the generic `interactions.onRequest`
410
+ handler on each `createSession` input before opening. Materialization itself
411
+ remains noninteractive. The mapping is absent by default, and ordinary standard
412
+ unknown-extension handling never enables it implicitly.
413
+
414
+ The selected launch arguments are exactly `['agent', '--no-leader', 'stdio']`.
415
+ The adapter exposes create-only `sessionInteractions` support with an exclusive
416
+ producer and decision requests. The handler receives a neutral workspace
417
+ decision and can keep its response capability after opening returns, before
418
+ any model turn. Use the generic
419
+ [runtime lifecycle](../agent-runtime/README.md#session-lifetime-interactions)
420
+ for presentation, exact offered choices, receipt handling and cleanup. The core
421
+ [runnable example](../../examples/lifecycle-interactions.ts) requires no ACP
422
+ dependency, native account or network.
423
+
424
+ | Phase or surface | Selected mapping support |
425
+ | --- | --- |
426
+ | Create a session with an early handler | Workspace decision may remain pending after opening returns. |
427
+ | Grant or decline the offered decision | One bound response, with a local delivery receipt separate from native effect. |
428
+ | Close while unanswered | Retires eligibility, joins the native producer and callback, and refuses a late response. |
429
+ | Interactive materialization | Unsupported; no materialization handler is added. |
430
+ | Resume or branch in this selected profile | Unsupported. Generic ACP resume remains a separate unselected capability. |
431
+ | Injected/shared root connections | Unsupported for this mapping; the Node-only execution boundary is required. |
432
+ | Session forms or authentication questions | Unsupported by this outside-turn decision mapping. Existing turn/form and adapter authentication APIs remain separate. |
433
+
434
+ The grant consequence covers current and future configuration for the workspace
435
+ and is provider-managed persistent trust that can affect other sessions using
436
+ that profile. Detected configuration categories do not narrow it. Decline leaves
437
+ configuration gated without revoking old grants or proving a persisted denial.
438
+ Do not expose native request IDs or use a parallel transport responder. Only
439
+ the offered neutral response capability may answer the request.
440
+
441
+ `delivered` establishes acceptance by the local provider handler. It does not
442
+ universally prove native receipt, loaded configuration or stored trust. An
443
+ entered delivery failure or timeout is uncertain and fences further mutation;
444
+ close without resending the choice. A request's terminal promise or aborted
445
+ presentation signal cannot replace full producer/callback cleanup. Retain the
446
+ session, opening cleanup receipt and dependent host/installation owners when
447
+ cleanup fails.
448
+
449
+ ### Qualified session-lifetime scope (SDK02)
450
+
451
+ The earlier SDK02 native qualification covers Grok Build `1.0.50` (`c58f321264ba`),
452
+ executable SHA-256 `c80de0155706ff2d995623887b102f2d0abd2c62b2643dea3a0cebaf7dd724d5`,
453
+ direct no-leader stdio, this selected mapping, modern stable `schema-v1.23.0`,
454
+ its retained installed public SDK `0.4.1`/Agent Protocol V10 artifacts, API-key authentication,
455
+ Linux x86_64 kernel
456
+ `7.0.0-38-generic`, Node `24.18.0`, and the exact retained reference,
457
+ toolchain, network and dependency inputs. It is local qualification, with no
458
+ package publication or consumer-repository integration implied. These exact earlier artifacts
459
+ are distinct from the SDK03 V11 remembered-edit artifacts above despite sharing version `0.4.1`.
460
+
461
+ Three separate native runs established grant, decline and pending close. Grant
462
+ additionally observed the vendor-written isolated workspace trust file. Decline
463
+ established local acceptance and absence of a grant; no further hidden native
464
+ acknowledgment was attested. Pending close sent no choice before close, joined
465
+ the handler and rejected the stale grant as unavailable. Each run independently
466
+ enrolled the genuine target and observed the same stable cgroup empty after SDK
467
+ close with the consumer alive, before registry or host disposal, without external
468
+ intervention. The trusted host was retired afterward.
469
+
470
+ Native wire reply correlation and prompt-frame counts remain unobserved. Zero
471
+ SDK turn invocations is a frozen-consumer-source claim. Separate installed
472
+ controlled peers prove exact wire correlation, no prompts and failure ownership;
473
+ the real Linux controlled lane proves descendant containment and negative
474
+ close-checkpoint behavior. Neither substitutes for native effect evidence.
475
+ The bounded native runs fit the reference's 64-task/512 MiB/180-second limits
476
+ for these setup scenarios only. They establish no general model-turn sizing,
477
+ other builds/platforms, browser login, native durable recovery, SDK-managed
478
+ remembered permissions or private execution support. The earlier failed native
479
+ ownership attempt remains unqualified.
480
+
481
+ ## Reserved execution ownership
482
+
483
+ This surface is included in the unpublished `0.4.1` source candidate.
484
+
485
+ The Node constructor also accepts an explicit `executionBoundary`. This host-owned
486
+ port is useful when native descendants can create their own sessions or process
487
+ groups. It is required when selecting
488
+ `sessionInteractions: { mapping: 'grok-folder-trust-v1' }`; omission fails at
489
+ constructor admission before materialization. The root injected constructor does
490
+ not accept this Node-only option. Ordinary unselected Node drivers keep the
491
+ process-group launcher described above.
492
+
493
+ Import the types from `@agen-ai/provider-acp/node`. A boundary synchronously
494
+ reserves one fresh, inert owner for each immutable launch recipe:
495
+
496
+ ```ts
497
+ interface NodeAcpExecutionBoundary {
498
+ reserve(input: NodeAcpExecutionInput): NodeAcpExecutionReservation;
499
+ }
500
+ ```
501
+
502
+ The recipe contains the exact absolute executable, literal arguments, working
503
+ directory, explicit environment and `shutdownTimeoutMs`. `reserve` must acquire
504
+ no resources and start no asynchronous work. The SDK retains its bound `start`
505
+ and `release` methods before entering startup. `start(context)` establishes the
506
+ operating-system boundary before executing native code and returns ACP streams;
507
+ it receives the current initialization signal. `release()` must synchronously
508
+ fence further startup, initiate termination, and join entered startup, streams
509
+ and the complete descendant workload. It must work before, during and after
510
+ startup. Late startup results remain owned by that same reservation.
511
+
512
+ A supplied object is an ownership contract, not containment proof. The host must
513
+ prevent the workload from leaving its boundary or controlling its supervisor.
514
+ A changing PID list or killing one process group cannot establish that guarantee.
515
+ The standalone [Linux reference](../../examples/execution/linux/README.md) uses
516
+ explicit cgroup delegation and isolated supervisor controls. Its platform and
517
+ host prerequisites are separate from the portable SDK API; there is no automatic
518
+ privilege escalation or fallback to weaker ownership for the selected mapping.
519
+
520
+ For the qualified Linux composition, retain the external host before starting
521
+ it, then give its boundary to the Node driver. The host supplies the physical
522
+ installation, workspace and each writable profile/runtime/temp mount plus an
523
+ explicit native environment:
524
+
525
+ ```ts
526
+ import { createNodeAcpProviderDriver } from '@agen-ai/provider-acp/node';
527
+ import { createLinuxExecutionHost } from '../../examples/execution/linux/boundary.mjs';
528
+
529
+ const host = createLinuxExecutionHost({
530
+ network: 'host',
531
+ networkInputs: {
532
+ resolver: '/etc/resolv.conf',
533
+ hosts: '/etc/hosts',
534
+ certificates: '/etc/ssl/certs',
535
+ },
536
+ mounts: [
537
+ { path: installationRoot, writable: false },
538
+ { path: workspaceRoot, writable: true },
539
+ ...ownedProfileMounts,
540
+ ],
541
+ });
542
+ await host.start();
543
+ const driver = createNodeAcpProviderDriver({
544
+ providerKey,
545
+ sessionInteractions: { mapping: 'grok-folder-trust-v1' },
546
+ executionBoundary: host.executionBoundary,
547
+ launch: { executable: approvedExecutable, args: ['agent', '--no-leader', 'stdio'],
548
+ cwd: workspaceRoot, env: explicitNativeEnvironment, shutdownTimeoutMs: 2_000 },
549
+ });
550
+ ```
551
+
552
+ Construct a registry with that driver and register the generic handler on
553
+ session opening. On success, close the session, dispose the registry, then
554
+ dispose the host. Retain the host if `start()` rejects. When qualifying cleanup,
555
+ keep the exact empty boundary for an independent checkpoint after SDK close
556
+ and before registry/host disposal. Networking and confinement remain explicit
557
+ host authority; the SDK does not create this Linux host automatically.
558
+
559
+ If initial materialization fails and cleanup remains incomplete, the `/node`
560
+ entrypoint exposes `NodeAcpExecutionCleanupError` and
561
+ `isNodeAcpExecutionCleanupError`. Through `createAgentProviderRegistry`, this
562
+ error remains the registry error's `cause`. Keep that original object and its
563
+ bound `retryCleanup()` callback until cleanup succeeds. Its `cause` preserves the
564
+ original startup failure and `cleanupError` records the failed cleanup attempt.
565
+ The callback retains the full acquired resource lifetime, including native work,
566
+ streams and entered provider callbacks. Serializing the error cannot preserve
567
+ this cleanup authority.
568
+
569
+ For example, a failed registry construction can be inspected without replacing
570
+ the callable owner:
571
+
572
+ ```ts
573
+ import { AgentProviderRegistryError } from '@agen-ai/agent-runtime';
574
+ import { isNodeAcpExecutionCleanupError } from '@agen-ai/provider-acp/node';
575
+
576
+ if (error instanceof AgentProviderRegistryError && isNodeAcpExecutionCleanupError(error.cause)) {
577
+ const retained = error.cause;
578
+ await retained.retryCleanup();
579
+ // Only now may the host release resources that depended on this native owner.
580
+ }
581
+ ```
582
+
583
+ If this retry rejects, keep `retained` and the external host owned for explicit
584
+ recovery. A late cleanup success cannot change the original opening failure or
585
+ authorize another native action. Host intervention during qualification keeps
586
+ the original verdict failed even if recovery eventually succeeds.
587
+
588
+ Each cleanup attempt has one observation window of `2 * shutdownTimeoutMs`
589
+ (default four seconds, maximum sixty seconds). A timeout preserves actual pending
590
+ work. A retry gets a fresh observation window and joins the same work; it never
591
+ starts a second process or overlaps an unfinished release. Only a release that
592
+ actually settled with failure may be called again. A shorter runtime deadline
593
+ can return first while the same cleanup remains owned.
594
+
595
+ Once an instance exists, an unsuccessful session opening uses the existing exact
596
+ `AgentProviderSessionCleanupError` receipt. A returned session keeps its normal
597
+ `close` retry path. Retain the corresponding instance, registry and host supervisor
598
+ until all dependent cleanup succeeds. A successful session close establishes
599
+ native quiescence under the supplied owner's contract; independent qualification
600
+ must verify that the concrete owner fulfills it.
601
+
259
602
  ## Session-scoped MCP bindings
260
603
 
261
604
  `sessionMcpBinding: { transport, create }` pairs a host-certified `http` or `sse` transport
@@ -418,8 +761,8 @@ close ends that handle's ownership. The host retains control over its process po
418
761
  Canonical forms preflight the whole schema before presenting a request. They
419
762
  support at most 16 ordinary fields and 100 choices per selection. Free-text fields,
420
763
  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
764
+ a V11 representation are rejected. Native free text permits blank/whitespace values
765
+ and measures length in Unicode code points; V11 text answers use nonblank/UTF-16
423
766
  bounds. The provider does not narrow those native semantics silently. Enumerated
424
767
  string values can map through opaque canonical selection IDs.
425
768
  A required multi-select must require exactly one minimum selection; an optional
@@ -440,7 +783,7 @@ binding grants no interaction authority. Their host callbacks receive a turn
440
783
  lifetime signal that ends on cancellation, settlement or close.
441
784
 
442
785
  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
786
+ decoded bytes total, subject to the stricter 1 MiB V11 turn-content bound. Declared
444
787
  media type, dimensions, base64 encoding and byte counts are validated. The provider
445
788
  does not decode pixels or publish generated bytes; hosts needing image-content
446
789
  inspection must perform it before submitting input.
@@ -1,4 +1,6 @@
1
1
  import { type AgentAuthenticationFlow, type AgentCapabilities, type AgentProviderKey } from '@agen-ai/agent-protocol';
2
2
  import type { AcpNegotiatedAgent } from './connection/contracts.js';
3
- export declare function acpProviderCapabilities(providerKey: AgentProviderKey, negotiated: AcpNegotiatedAgent, configuration?: 'managed' | 'selectable', authenticationFlows?: readonly AgentAuthenticationFlow[]): AgentCapabilities;
3
+ import type { AcpSessionInteractionSelection } from './sessionInteractions/contracts.js';
4
+ import type { AcpPermissionMappingSelection } from './permissions/contracts.js';
5
+ export declare function acpProviderCapabilities(providerKey: AgentProviderKey, negotiated: AcpNegotiatedAgent, configuration?: 'managed' | 'selectable', authenticationFlows?: readonly AgentAuthenticationFlow[], sessionInteractions?: AcpSessionInteractionSelection, permissionMapping?: AcpPermissionMappingSelection): AgentCapabilities;
4
6
  //# sourceMappingURL=capabilities.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import { parseAgentCapabilities } from "@agen-ai/agent-protocol";
2
+ import { acpPermissionCapability } from "./permissions/selection.js";
2
3
  function freezeCapabilities(value) {
3
4
  if (value && typeof value === "object") {
4
5
  for (const child of Object.values(value)) freezeCapabilities(child);
@@ -6,14 +7,14 @@ function freezeCapabilities(value) {
6
7
  }
7
8
  return value;
8
9
  }
9
- function acpProviderCapabilities(providerKey, negotiated, configuration = "managed", authenticationFlows = []) {
10
+ function acpProviderCapabilities(providerKey, negotiated, configuration = "managed", authenticationFlows = [], sessionInteractions, permissionMapping = { mapping: "once-only-v1" }) {
10
11
  return freezeCapabilities(parseAgentCapabilities({
11
- protocolVersion: 10,
12
+ protocolVersion: 11,
12
13
  providerKey,
13
- sessions: { create: true, resume: negotiated.agentCapabilities.loadSession === true || negotiated.agentCapabilities.sessionCapabilities?.resume != null, branch: { kind: "unsupported" } },
14
+ sessions: { create: true, resume: sessionInteractions === void 0 && (negotiated.agentCapabilities.loadSession === true || negotiated.agentCapabilities.sessionCapabilities?.resume != null), branch: { kind: "unsupported" } },
14
15
  turns: { interactionModes: ["default"], interrupt: true, steer: { kind: "unsupported" } },
15
16
  requests: {
16
- approval: { kind: "supported", modes: [{ persistence: "once", scopeKinds: ["exact_action"] }] },
17
+ approval: acpPermissionCapability(permissionMapping),
17
18
  elicitation: { kind: "supported", fieldKinds: ["single_select", "multi_select", "boolean"], maxFields: 16, sensitiveFields: false }
18
19
  },
19
20
  context: { usage: { kind: "unsupported" }, compaction: { kind: "unsupported" } },
@@ -127,8 +127,6 @@ class AcpConfigurationCatalogState {
127
127
  this.maxSnapshotBytes = maxSnapshotBytes;
128
128
  this.capability = capability;
129
129
  }
130
- maxSnapshotBytes;
131
- capability;
132
130
  snapshot;
133
131
  bindings = /* @__PURE__ */ new Map();
134
132
  fingerprint;
@@ -4,7 +4,6 @@ class AcpConfigurationError extends Error {
4
4
  this.reasonCode = reasonCode;
5
5
  this.name = "AcpConfigurationError";
6
6
  }
7
- reasonCode;
8
7
  }
9
8
  function invalidConfigurationCatalog() {
10
9
  throw new AcpConfigurationError("acp_configuration_catalog_invalid", "ACP configuration cannot be represented faithfully within the declared bounds.");
@@ -1,12 +1,31 @@
1
1
  import type { AcpClient, AcpJsonObject, AcpJsonValue, AcpNotificationContext, AcpReverseRequestContext, AcpRequestOptions } from '@agen-ai/acp-transport';
2
2
  import type { AcpHostInteractionScope } from '../host/contracts.js';
3
3
  import type { AcpBoundSession } from '../host/router.js';
4
+ import type { SessionInteractionBroker } from '../sessionInteractions/broker.js';
5
+ import type { AcpConnectionFactory } from '../contracts.js';
6
+ import type { NodeAcpExecutionOwner } from '../node/execution/owner.js';
7
+ export type AcpConnectionSource = Readonly<{
8
+ kind: 'factory';
9
+ create: AcpConnectionFactory;
10
+ }> | Readonly<{
11
+ kind: 'reserved';
12
+ reserve: () => NodeAcpExecutionOwner;
13
+ }>;
14
+ export type AcpConnectionAcquisition = Readonly<{
15
+ kind: 'factory';
16
+ create: AcpConnectionFactory;
17
+ }> | Readonly<{
18
+ kind: 'reserved';
19
+ owner: NodeAcpExecutionOwner;
20
+ }>;
4
21
  export interface AcpNegotiatedAgent {
5
22
  readonly protocolVersion: 1;
6
23
  readonly agentInfo?: Readonly<{
7
24
  name: string;
8
25
  version: string;
9
26
  }>;
27
+ /** Bounded compatibility observation retained only by the selected Grok permission profile. */
28
+ readonly agentVersion?: string;
10
29
  readonly agentCapabilities: AcpJsonObject;
11
30
  readonly authMethods: readonly AcpJsonValue[];
12
31
  }
@@ -19,6 +38,8 @@ export interface AcpInitializedConnection {
19
38
  readonly client: AcpClient;
20
39
  readonly negotiated: AcpNegotiatedAgent;
21
40
  readonly stopped: AbortSignal;
41
+ readonly execution?: NodeAcpExecutionOwner;
42
+ readonly sessionInteractions?: SessionInteractionBroker;
22
43
  readonly attachSession: (ingress: AcpSessionIngress) => () => void;
23
44
  readonly bindSession: (binding: AcpBoundSession) => void;
24
45
  readonly requestWithScope: (method: string, params: AcpJsonValue, scope: AcpHostInteractionScope, options?: AcpRequestOptions) => Promise<AcpJsonValue>;
@@ -4,7 +4,6 @@ class AcpProviderConnectionError extends Error {
4
4
  this.reasonCode = reasonCode;
5
5
  this.name = "AcpProviderConnectionError";
6
6
  }
7
- reasonCode;
8
7
  }
9
8
  export {
10
9
  AcpProviderConnectionError
@@ -1,10 +1,12 @@
1
1
  import { type AcpUnknownExtensionPolicy } from '@agen-ai/acp-transport';
2
- import type { AcpConnectionFactory, AcpConnectionFactoryContext } from '../contracts.js';
2
+ import type { AcpConnectionFactoryContext } from '../contracts.js';
3
3
  import type { AcpProviderLimits } from '../limits.js';
4
- import type { AcpInitializedConnection } from './contracts.js';
4
+ import type { AcpConnectionAcquisition, AcpInitializedConnection } from './contracts.js';
5
5
  import type { AcpAuthenticationMethods, AcpHostFacilities } from '../host/contracts.js';
6
+ import type { AcpSessionInteractionSelection } from '../sessionInteractions/contracts.js';
7
+ import type { AcpPermissionMappingSelection } from '../permissions/contracts.js';
6
8
  export declare function initializeAcpConnection(input: {
7
- readonly createConnection: AcpConnectionFactory;
9
+ readonly source: AcpConnectionAcquisition;
8
10
  readonly unknownExtensionPolicy: AcpUnknownExtensionPolicy;
9
11
  readonly context: AcpConnectionFactoryContext;
10
12
  readonly limits: AcpProviderLimits;
@@ -12,5 +14,7 @@ export declare function initializeAcpConnection(input: {
12
14
  readonly host?: AcpHostFacilities;
13
15
  readonly authentication?: AcpAuthenticationMethods;
14
16
  readonly configuration?: 'managed' | 'selectable';
17
+ readonly sessionInteractions?: AcpSessionInteractionSelection;
18
+ readonly permissionMapping?: AcpPermissionMappingSelection;
15
19
  }): Promise<AcpInitializedConnection>;
16
20
  //# sourceMappingURL=initialize.d.ts.map