@agen-ai/provider-acp 0.4.3 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -15
- package/dist/capabilities.d.ts +2 -1
- package/dist/capabilities.js +4 -3
- package/dist/connection/contracts.d.ts +1 -1
- package/dist/connection/initialize.d.ts +2 -0
- package/dist/connection/initialize.js +1 -1
- package/dist/connection/negotiation.d.ts +2 -1
- package/dist/connection/negotiation.js +4 -1
- package/dist/contracts.d.ts +3 -0
- package/dist/driverFactory.js +3 -0
- package/dist/host/router.d.ts +10 -0
- package/dist/host/router.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/instance.d.ts +2 -0
- package/dist/instance.js +15 -1
- package/dist/limits.d.ts +1 -1
- package/dist/limits.js +2 -2
- package/dist/node/index.js +1 -0
- package/dist/session/completion.js +6 -5
- package/dist/session/deadline.d.ts +2 -0
- package/dist/session/deadline.js +18 -0
- package/dist/session/mapping.js +1 -1
- package/dist/session/session.js +22 -12
- package/dist/session/turn.d.ts +2 -1
- package/dist/structuredOutput/completion.d.ts +4 -0
- package/dist/structuredOutput/completion.js +55 -0
- package/dist/structuredOutput/mapping.d.ts +10 -0
- package/dist/structuredOutput/mapping.js +45 -0
- package/dist/structuredOutput/request.d.ts +7 -0
- package/dist/structuredOutput/request.js +19 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
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
|
|
5
|
-
|
|
6
|
-
historical evidence for its exact V11 artifacts.
|
|
4
|
+
Agent Client Protocol wire version 1 into the Agent Protocol V13 session API. Current source is
|
|
5
|
+
the unpublished coordinated eight-package `0.4.4` candidate. Published `0.4.3` is the seven-package
|
|
6
|
+
V12 release; published `0.4.1` qualification remains historical evidence for its exact V11 artifacts.
|
|
7
7
|
The package is ESM, MIT licensed, side-effect-free on import and requires Node.js
|
|
8
8
|
22 or newer. It depends only on the public transport, runtime and protocol packages;
|
|
9
9
|
the core packages remain independent of ACP.
|
|
10
10
|
|
|
11
11
|
The provider pins the transport's `schema-v1.23.0` stable profile. It translates
|
|
12
|
-
ACP into current
|
|
12
|
+
ACP into current V13 capabilities and rejects unsupported semantics explicitly.
|
|
13
13
|
Connection negotiation, configured host facilities, and mapping policy fix one
|
|
14
14
|
capability envelope per instance; every later connection must match it.
|
|
15
|
+
The [0.4.4 upgrade guide](../../UPGRADING-TO-0.4.4.md) describes the coordinated candidate.
|
|
16
|
+
Optional `@agen-ai/agent-history` browsing remains independent of this execution provider; native
|
|
17
|
+
transcript JSON and ACP metadata alone establish no structured-generation capability.
|
|
15
18
|
|
|
16
19
|
Tool approvals default to once-only scoped consequences. Both constructors accept an explicit
|
|
17
20
|
`permissionMapping` selection for completely described provider-managed remembered choices.
|
|
@@ -53,9 +56,11 @@ under a different policy.
|
|
|
53
56
|
| Surface | Supported behavior and requirements |
|
|
54
57
|
| --- | --- |
|
|
55
58
|
| 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. |
|
|
59
|
+
| Execution input | Unsupported for every public ACP/Grok composition. There is no input mapping selection or native interjection dispatch; peer labels, metadata and extension advertisements cannot enable it. |
|
|
60
|
+
| Structured final output | Unsupported for generic ACP. Explicit `grok-build-1.0.62-structured-output-v1` mapping supports native turn-scoped `agenai.output-schema.v1` requests and independently validated terminal objects, within the bounds below. |
|
|
56
61
|
| 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. |
|
|
57
62
|
| 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. |
|
|
58
|
-
| Forms | Canonical boolean/single-select/multi-select forms that fit
|
|
63
|
+
| Forms | Canonical boolean/single-select/multi-select forms that fit V13 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. |
|
|
59
64
|
| 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. |
|
|
60
65
|
| Plans | Complete replacements of observed turn plans. A mode called “plan” does not establish enforced planning behavior or approval authority. |
|
|
61
66
|
| 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. |
|
|
@@ -69,7 +74,7 @@ Through-turn branching, same-turn steering, enforced plan mode, persistent
|
|
|
69
74
|
SDK-owned tool-approval grants, context usage/compaction, account quota, effective skill/rule
|
|
70
75
|
inventory, collaboration, generated resources and artifact publication remain
|
|
71
76
|
unsupported. ACP usage counters can decrease without confirmed compaction and
|
|
72
|
-
cannot satisfy
|
|
77
|
+
cannot satisfy V13's context continuity contract. Unsupported media output fails
|
|
73
78
|
explicitly rather than disappearing from an otherwise successful transcript.
|
|
74
79
|
Embedded terminal references also fail explicitly: a mutable, possibly truncated
|
|
75
80
|
terminal snapshot does not provide an ordered append-only transcript. Agents can
|
|
@@ -80,9 +85,121 @@ this release. Host-owned integrations may use the transport directly with their
|
|
|
80
85
|
own authorization and native lifecycle policy. No capability grants authority
|
|
81
86
|
over other conversations or account state.
|
|
82
87
|
|
|
88
|
+
## Input during an execution
|
|
89
|
+
|
|
90
|
+
The optional runtime `execution.input` contract is available in the unpublished `0.4.4`
|
|
91
|
+
candidate, but this provider exposes no supported execution-input port. Consumers must narrow
|
|
92
|
+
`execution.input?.kind === 'supported'` before sending. Absence and `{ kind: 'unsupported' }`
|
|
93
|
+
both mean unsupported; use ordinary `startTurn()` for new work when idle. Strict `turns.steer`
|
|
94
|
+
semantics are unchanged and remain unsupported here. The
|
|
95
|
+
[runtime README](../agent-runtime/README.md) explains receipt, consumption and output ownership.
|
|
96
|
+
|
|
97
|
+
Stable ACP `schema-v1.23.0` negotiation and standard unknown-extension handling do not grant
|
|
98
|
+
native input support. Grok Build `1.0.67` has native interjection facilities, but the inspected
|
|
99
|
+
behavior did not establish an authoritative input-to-command link, ownership of autonomous wake
|
|
100
|
+
work, or reusable-session producer quiescence. Queued acknowledgements, matching text and empty
|
|
101
|
+
queue snapshots cannot establish those guarantees. No Grok input mapping is shipped. The
|
|
102
|
+
independent Grok `1.0.62` structured-output mapping and history qualification retain their own
|
|
103
|
+
versions and scope.
|
|
104
|
+
|
|
105
|
+
Installed public-package proof exercises six unsupported cases: generic ACP, Grok labels and
|
|
106
|
+
input advertisements, and the selected Grok `1.0.62` structured-output mapping, each with borrowed
|
|
107
|
+
and owned connections. The actual packed provider constructors use a synthetic serialized peer;
|
|
108
|
+
all six retain one original turn and reader, dispatch zero native input requests, and join cleanup.
|
|
109
|
+
An unsolicited input extension request receives `-32601`. This is public unsupported-boundary
|
|
110
|
+
proof, separate from private controlled Claude qualification; no public Claude execution constructor ships.
|
|
111
|
+
|
|
112
|
+
## Structured final output
|
|
113
|
+
|
|
114
|
+
ACP schema `1.23.0` does not define a portable final-output-schema capability. Generic provider
|
|
115
|
+
instances declare `turns.structuredOutput: { kind: 'unsupported' }`. Standard unknown-extension
|
|
116
|
+
handling, a peer accepting metadata, or JSON-looking assistant text cannot enable it.
|
|
117
|
+
|
|
118
|
+
Both constructors accept one exact opt-in native mapping:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { parseAgentProviderKey } from '@agen-ai/agent-protocol';
|
|
122
|
+
import { createNodeAcpProviderDriver } from '@agen-ai/provider-acp/node';
|
|
123
|
+
|
|
124
|
+
const driver = createNodeAcpProviderDriver({
|
|
125
|
+
providerKey: parseAgentProviderKey('grok-build'),
|
|
126
|
+
structuredOutputMapping: { mapping: 'grok-build-1.0.62-structured-output-v1' },
|
|
127
|
+
launch: {
|
|
128
|
+
executable: approvedExecutable,
|
|
129
|
+
args: ['agent', '--no-leader', 'stdio'],
|
|
130
|
+
cwd: workingDirectory,
|
|
131
|
+
env: explicitNativeEnvironment,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The host supplies and verifies the executable, environment, credentials and confinement policy.
|
|
137
|
+
For injected connections, pass the same `structuredOutputMapping` to `createAcpProviderDriver`.
|
|
138
|
+
The selection is captured at construction; each connection must negotiate the pinned stable ACP
|
|
139
|
+
profile and initialize with Grok's exact `grokShell: true` / `agentVersion: '1.0.62'` identity.
|
|
140
|
+
Initialization identity is an admission check, not executable provenance or inference proof.
|
|
141
|
+
Changing a mapping needs a new driver/materialization; it is absent from serialized empty
|
|
142
|
+
`driverConfiguration`.
|
|
143
|
+
|
|
144
|
+
The supported declaration has `mechanism: 'native'`,
|
|
145
|
+
`schemaProfile: 'agenai.output-schema.v1'`, `scope: 'turn'`, `maxSchemaBytes: 16_384`,
|
|
146
|
+
`maxOutputBytes: 16_384`, `resume: false`, and `branch: false`. Supply the schema on `startTurn`,
|
|
147
|
+
or use [`generateObject`](../agent-runtime/README.md#generate-a-typed-object), which borrows the
|
|
148
|
+
selected instance and owns a fresh session through cleanup. Session-opening output is rejected.
|
|
149
|
+
A later ordinary turn omits `output` and sends no schema. Ordinary exact-binding resume remains
|
|
150
|
+
separate; structured requests cannot restore schema state through resume or branch.
|
|
151
|
+
|
|
152
|
+
The mapping sends the admitted schema through prompt `_meta.outputSchema` and reads only the
|
|
153
|
+
correlated authoritative prompt response's `_meta.structuredOutput`. A successful `end_turn`
|
|
154
|
+
and a complete schema-valid object are both required for terminal `structuredOutput.kind: 'json'`.
|
|
155
|
+
Text deltas are not parsed as output, and the SDK never extracts a JSON substring or repairs it.
|
|
156
|
+
The shared runtime validates the candidate independently against the exact admitted schema.
|
|
157
|
+
|
|
158
|
+
| Native observation | Portable structured result |
|
|
159
|
+
| --- | --- |
|
|
160
|
+
| `refusal` | `unavailable/refused`, preserving native completed outcome |
|
|
161
|
+
| Non-`end_turn` stop, including token/request limit or cancellation | `unavailable/incomplete`, preserving native outcome |
|
|
162
|
+
| Successful `end_turn` without structured metadata | `unavailable/missing_output` |
|
|
163
|
+
| Bounded native `structuredOutputError` | `unavailable/provider_error`; Grok's free text cannot distinguish exhausted retries from other native validation errors |
|
|
164
|
+
| Oversized metadata/value | `unavailable/output_limit_exceeded` |
|
|
165
|
+
| Complete object that fails the admitted schema | `unavailable/schema_mismatch` with bounded issues |
|
|
166
|
+
|
|
167
|
+
Native structured metadata is capped at 32,768 UTF-8 bytes and its error string at 4,096 bytes.
|
|
168
|
+
The canonical schema/value ceilings are each 16,384 serialized bytes, with the additional
|
|
169
|
+
[portable shape limits](../agent-protocol/README.md#the-agenaioutput-schemav1-profile). Ambiguous
|
|
170
|
+
value-plus-error metadata, a wrong native session identity, or malformed error metadata is a
|
|
171
|
+
contract failure. Ordinary turns report `structuredOutput: { kind: 'not_requested' }`.
|
|
172
|
+
Only `outcome: 'completed'` can carry `json`; a native finished turn does not guarantee generation
|
|
173
|
+
success. There is no SDK generation retry, fallback model or tool replay. Native validation/fallback
|
|
174
|
+
attempts may occur inside the provider's one prompt and are not described as SDK retries.
|
|
175
|
+
|
|
176
|
+
Selecting this mapping does not disable native tools or alter host permission policy. A generation
|
|
177
|
+
that requires a human response needs an explicit handler; the helper fails with
|
|
178
|
+
`interaction_required` when one is absent. Retain cleanup errors and their callable retry owners
|
|
179
|
+
as described by the [runtime generation lifecycle](../agent-runtime/README.md#deadlines-requests-and-cleanup).
|
|
180
|
+
|
|
181
|
+
### Qualified installed native scope
|
|
182
|
+
|
|
183
|
+
The 2026-10-22 qualification used all eight installed public `0.4.4` candidate tarballs, only public
|
|
184
|
+
entrypoints, stable ACP schema `1.23.0`, Linux x86_64 / Node `24.18.0`, Grok Build `1.0.62`
|
|
185
|
+
(`1474f9cbdd91`), `grok-4.3`, low reasoning and explicit xAI API-key authentication. The executable
|
|
186
|
+
SHA-256 was `2a46d9e4d7ebd7a9cff7f95716714b19dad5f21dd2a497822400b1fb128969aa`.
|
|
187
|
+
The shipped title example returned a typed title and saved it after session/reader closure. Further
|
|
188
|
+
native turns produced an independently validated rich nested object, a changed `{ count: 7 }`
|
|
189
|
+
schema, and ordinary `Ready` text with no schema. Sessions/readers closed, both observed native
|
|
190
|
+
process groups were absent, the caller-owned registry was disposed and owned scratch removed.
|
|
191
|
+
|
|
192
|
+
This exact local tuple establishes the public mapping's installed native behavior. It does not
|
|
193
|
+
qualify generic ACP, other Grok releases/models/authentication modes, OpenCode, Cursor or arbitrary
|
|
194
|
+
harnesses. Process-group evidence does not establish escaped-descendant or cgroup containment;
|
|
195
|
+
the Node launcher grants no production execution authority or backend billing guarantee. The
|
|
196
|
+
separate private Codex and Claude diagnostic mappings are not public provider packages and cannot
|
|
197
|
+
be imported through this package. Existing history/delegation/approval qualifications below keep
|
|
198
|
+
their original version-specific scope. The `0.4.4` candidate remains unpublished.
|
|
199
|
+
|
|
83
200
|
## Operational failures and uncertainty
|
|
84
201
|
|
|
85
|
-
The provider maps supported standard `schema-v1.23.0` prompt errors into
|
|
202
|
+
The provider maps supported standard `schema-v1.23.0` prompt errors into V13 `AgentError` values.
|
|
86
203
|
Standard `-32000` reports `authentication` with an `authenticate` user-action hint; `-32602` reports
|
|
87
204
|
`invalid_request`; `-32603` reports `provider`; standard parse/request/method errors report `protocol`.
|
|
88
205
|
Other remote codes remain `unknown` with unknown recovery. Mapping uses the standard error code,
|
|
@@ -414,7 +531,7 @@ unknown-extension handling never enables it implicitly.
|
|
|
414
531
|
The selected launch arguments are exactly `['agent', '--no-leader', 'stdio']`.
|
|
415
532
|
The adapter exposes the exact `sessionInteractions.mappings` tuple
|
|
416
533
|
`{ openingOperation: 'create', requestKind: 'decision' }`, exclusive producer
|
|
417
|
-
ownership and, in current
|
|
534
|
+
ownership and, in current source, `humanWait: ['bounded', 'until_withdrawn_or_closed']`. The handler receives a neutral workspace
|
|
418
535
|
decision and can keep its response capability after opening returns, before
|
|
419
536
|
any model turn. Use the generic
|
|
420
537
|
[runtime lifecycle](../agent-runtime/README.md#session-lifetime-interactions)
|
|
@@ -479,7 +596,7 @@ other builds/platforms, browser login, native durable recovery, SDK-managed
|
|
|
479
596
|
remembered permissions or private execution support. The earlier failed native
|
|
480
597
|
ownership attempt remains unqualified.
|
|
481
598
|
|
|
482
|
-
The current
|
|
599
|
+
The current V13 decision descriptor omits `expiresAt` because this native mapping reports no
|
|
483
600
|
provider-owned expiry. The bounded host timer remains a separate policy boundary;
|
|
484
601
|
`humanWait: { kind: 'until_withdrawn_or_closed' }` omits that human timer and
|
|
485
602
|
rejects an explicitly supplied `limits.requestTimeoutMs`. Initialization,
|
|
@@ -494,7 +611,7 @@ validated consumer facade. Session forms, plan reviews and native continuations
|
|
|
494
611
|
remain unsupported by `grok-folder-trust-v1`. The retained SDK02 native evidence
|
|
495
612
|
above remains specific to its original finite waiting configuration.
|
|
496
613
|
|
|
497
|
-
## Restored plan requests
|
|
614
|
+
## Restored plan requests
|
|
498
615
|
|
|
499
616
|
The Node constructor accepts a separate explicit selection:
|
|
500
617
|
`sessionInteractions: { mapping: 'grok-build-1.0.60-session-requests-v1' }`.
|
|
@@ -921,8 +1038,8 @@ close ends that handle's ownership. The host retains control over its process po
|
|
|
921
1038
|
Canonical forms preflight the whole schema before presenting a request. They
|
|
922
1039
|
support at most 16 ordinary fields and 100 choices per selection. Free-text fields,
|
|
923
1040
|
nested objects, numeric fields, defaults, patterns/formats, and constraints without
|
|
924
|
-
a
|
|
925
|
-
and measures length in Unicode code points;
|
|
1041
|
+
a V13 representation are rejected. Native free text permits blank/whitespace values
|
|
1042
|
+
and measures length in Unicode code points; V13 text answers use nonblank/UTF-16
|
|
926
1043
|
bounds. The provider does not narrow those native semantics silently. Enumerated
|
|
927
1044
|
string values can map through opaque canonical selection IDs.
|
|
928
1045
|
A required multi-select must require exactly one minimum selection; an optional
|
|
@@ -943,7 +1060,7 @@ binding grants no interaction authority. Their host callbacks receive a turn
|
|
|
943
1060
|
lifetime signal that ends on cancellation, settlement or close.
|
|
944
1061
|
|
|
945
1062
|
Image input allows at most 16 images, 375,000 decoded bytes per image and 750,000
|
|
946
|
-
decoded bytes total, subject to the stricter 1 MiB
|
|
1063
|
+
decoded bytes total, subject to the stricter 1 MiB V13 turn-content bound. Declared
|
|
947
1064
|
media type, dimensions, base64 encoding and byte counts are validated. The provider
|
|
948
1065
|
does not decode pixels or publish generated bytes; hosts needing image-content
|
|
949
1066
|
inspection must perform it before submitting input.
|
|
@@ -952,18 +1069,40 @@ inspection must perform it before submitting input.
|
|
|
952
1069
|
|
|
953
1070
|
`limits` can override `maxQueuedMessages`, `maxQueuedBytes`,
|
|
954
1071
|
`maxPendingRequests`, `maxHostTerminals`, `hostOperationTimeoutMs`,
|
|
955
|
-
`authenticationTimeoutMs`, `initializationTimeoutMs`, `
|
|
1072
|
+
`authenticationTimeoutMs`, `initializationTimeoutMs`, `terminalWaitTimeoutMs`, and
|
|
956
1073
|
`cancellationTimeoutMs`. Defaults share a 128-entry, 8 MiB budget across queued
|
|
957
1074
|
sources and retained current-turn item state, with output/control headroom
|
|
958
1075
|
reserved inside that budget. Large bursts and turns with many retained items
|
|
959
1076
|
can exhaust the same budget. Defaults allow 16 pending requests, 16 host terminals,
|
|
960
1077
|
30 seconds for initialization or a host operation, 15 minutes for authentication,
|
|
961
|
-
30 minutes for
|
|
1078
|
+
30 minutes for an individual host-terminal exit wait, and 5 seconds for cancellation. Admission
|
|
962
1079
|
reserves finite source capacity synchronously. Response and cancellation
|
|
963
1080
|
processing remain independent of slow output consumers. Overflow, malformed
|
|
964
1081
|
messages, process loss, or unconfirmed cancellation fail closed and require
|
|
965
1082
|
closing the unusable session before rematerialization.
|
|
966
1083
|
|
|
1084
|
+
Ordinary prompts have no implicit execution deadline. Omit turn `deadlineAt` to
|
|
1085
|
+
retain the original prompt, sole output reader and connection until native
|
|
1086
|
+
completion, explicit cancellation or close. Startup, authentication, host APIs,
|
|
1087
|
+
human-decision policies, output capacity and cleanup keep their independent bounds.
|
|
1088
|
+
Selected native continuations also retain their original execution and reader;
|
|
1089
|
+
their preparation, promotion and response observations remain separately bounded.
|
|
1090
|
+
|
|
1091
|
+
Set `deadlineAt` on each `startTurn` for a caller-selected finite execution budget,
|
|
1092
|
+
for example `new Date(Date.now() + 86_400_000).toISOString()` for one day. Distant
|
|
1093
|
+
dates use timer slices without an SDK business-duration ceiling or premature Node
|
|
1094
|
+
timer overflow. Expiry sends native `session/cancel` while retaining the original
|
|
1095
|
+
prompt RPC until its native terminal. A confirmed canceled response produces
|
|
1096
|
+
`expired`; an unconfirmed cancellation fails the session and starts owned cleanup.
|
|
1097
|
+
Neither expiry nor a cancellation request invents a completed native receipt.
|
|
1098
|
+
|
|
1099
|
+
The former provider `limits.promptTimeoutMs` is rejected. Migrate its numeric
|
|
1100
|
+
budget to each turn's `deadlineAt`; use `terminalWaitTimeoutMs` only for host-terminal
|
|
1101
|
+
exit observation. That setting preserves the prior finite 30-minute default and
|
|
1102
|
+
maximum. A host-terminal wait timeout leaves its terminal lease owned for explicit
|
|
1103
|
+
kill/release or connection cleanup. Applications retain live owners and close them;
|
|
1104
|
+
unbounded prompt waiting does not provide controller-crash survival.
|
|
1105
|
+
|
|
967
1106
|
Readiness reports completed initialization and the reported agent version when
|
|
968
1107
|
available. It does not prove authentication or inference. The Node launcher
|
|
969
1108
|
does not install agents, load credentials, apply a sandbox, or grant production
|
package/dist/capabilities.d.ts
CHANGED
|
@@ -2,5 +2,6 @@ import { type AgentAuthenticationFlow, type AgentCapabilities, type AgentProvide
|
|
|
2
2
|
import type { AcpNegotiatedAgent } from './connection/contracts.js';
|
|
3
3
|
import type { AcpSessionInteractionSelection } from './sessionInteractions/contracts.js';
|
|
4
4
|
import type { AcpPermissionMappingSelection } from './permissions/contracts.js';
|
|
5
|
-
|
|
5
|
+
import { type AcpStructuredOutputMappingSelection } from './structuredOutput/mapping.js';
|
|
6
|
+
export declare function acpProviderCapabilities(providerKey: AgentProviderKey, negotiated: AcpNegotiatedAgent, configuration?: 'managed' | 'selectable', authenticationFlows?: readonly AgentAuthenticationFlow[], sessionInteractions?: AcpSessionInteractionSelection, permissionMapping?: AcpPermissionMappingSelection, structuredOutputMapping?: AcpStructuredOutputMappingSelection): AgentCapabilities;
|
|
6
7
|
//# sourceMappingURL=capabilities.d.ts.map
|
package/dist/capabilities.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { parseAgentCapabilities } from "@agen-ai/agent-protocol";
|
|
2
2
|
import { acpPermissionCapability } from "./permissions/selection.js";
|
|
3
|
+
import { acpStructuredOutputCapability } from "./structuredOutput/mapping.js";
|
|
3
4
|
function freezeCapabilities(value) {
|
|
4
5
|
if (value && typeof value === "object") {
|
|
5
6
|
for (const child of Object.values(value)) freezeCapabilities(child);
|
|
@@ -7,12 +8,12 @@ function freezeCapabilities(value) {
|
|
|
7
8
|
}
|
|
8
9
|
return value;
|
|
9
10
|
}
|
|
10
|
-
function acpProviderCapabilities(providerKey, negotiated, configuration = "managed", authenticationFlows = [], sessionInteractions, permissionMapping = { mapping: "once-only-v1" }) {
|
|
11
|
+
function acpProviderCapabilities(providerKey, negotiated, configuration = "managed", authenticationFlows = [], sessionInteractions, permissionMapping = { mapping: "once-only-v1" }, structuredOutputMapping) {
|
|
11
12
|
return freezeCapabilities(parseAgentCapabilities({
|
|
12
|
-
protocolVersion:
|
|
13
|
+
protocolVersion: 13,
|
|
13
14
|
providerKey,
|
|
14
15
|
sessions: { create: true, resume: sessionInteractions?.mapping !== "grok-folder-trust-v1" && (negotiated.agentCapabilities.loadSession === true || negotiated.agentCapabilities.sessionCapabilities?.resume != null), branch: { kind: "unsupported" } },
|
|
15
|
-
turns: { interactionModes: ["default"], interrupt: true, steer: { kind: "unsupported" } },
|
|
16
|
+
turns: { structuredOutput: acpStructuredOutputCapability(structuredOutputMapping), interactionModes: ["default"], interrupt: true, steer: { kind: "unsupported" } },
|
|
16
17
|
requests: {
|
|
17
18
|
approval: acpPermissionCapability(permissionMapping),
|
|
18
19
|
elicitation: { kind: "supported", fieldKinds: ["single_select", "multi_select", "boolean"], maxFields: 16, sensitiveFields: false }
|
|
@@ -24,7 +24,7 @@ export interface AcpNegotiatedAgent {
|
|
|
24
24
|
name: string;
|
|
25
25
|
version: string;
|
|
26
26
|
}>;
|
|
27
|
-
/** Bounded
|
|
27
|
+
/** Bounded native version observation retained by explicitly selected Grok mappings. */
|
|
28
28
|
readonly agentVersion?: string;
|
|
29
29
|
readonly agentCapabilities: AcpJsonObject;
|
|
30
30
|
readonly authMethods: readonly AcpJsonValue[];
|
|
@@ -5,6 +5,7 @@ import type { AcpConnectionAcquisition, AcpInitializedConnection } from './contr
|
|
|
5
5
|
import type { AcpAuthenticationMethods, AcpHostFacilities } from '../host/contracts.js';
|
|
6
6
|
import type { AcpSessionInteractionSelection } from '../sessionInteractions/contracts.js';
|
|
7
7
|
import type { AcpPermissionMappingSelection } from '../permissions/contracts.js';
|
|
8
|
+
import type { AcpStructuredOutputMappingSelection } from '../structuredOutput/mapping.js';
|
|
8
9
|
export declare function initializeAcpConnection(input: {
|
|
9
10
|
readonly source: AcpConnectionAcquisition;
|
|
10
11
|
readonly unknownExtensionPolicy: AcpUnknownExtensionPolicy;
|
|
@@ -16,5 +17,6 @@ export declare function initializeAcpConnection(input: {
|
|
|
16
17
|
readonly configuration?: 'managed' | 'selectable';
|
|
17
18
|
readonly sessionInteractions?: AcpSessionInteractionSelection;
|
|
18
19
|
readonly permissionMapping?: AcpPermissionMappingSelection;
|
|
20
|
+
readonly structuredOutputMapping?: AcpStructuredOutputMappingSelection;
|
|
19
21
|
}): Promise<AcpInitializedConnection>;
|
|
20
22
|
//# sourceMappingURL=initialize.d.ts.map
|
|
@@ -208,7 +208,7 @@ async function initializeAcpConnection(input) {
|
|
|
208
208
|
signal: initialization.signal
|
|
209
209
|
});
|
|
210
210
|
if (stopped.signal.aborted) throw stopped.signal.reason;
|
|
211
|
-
const negotiated = readNegotiatedAgent(response, input.permissionMapping, input.sessionInteractions);
|
|
211
|
+
const negotiated = readNegotiatedAgent(response, input.permissionMapping, input.sessionInteractions, input.structuredOutputMapping);
|
|
212
212
|
initialization.signal.removeEventListener("abort", onAbort);
|
|
213
213
|
return Object.freeze({
|
|
214
214
|
client,
|
|
@@ -2,7 +2,8 @@ import type { AcpJsonValue } from '@agen-ai/acp-transport';
|
|
|
2
2
|
import type { AcpNegotiatedAgent } from './contracts.js';
|
|
3
3
|
import type { AcpPermissionMappingSelection } from '../permissions/contracts.js';
|
|
4
4
|
import type { AcpSessionInteractionSelection } from '../sessionInteractions/contracts.js';
|
|
5
|
+
import { type AcpStructuredOutputMappingSelection } from '../structuredOutput/mapping.js';
|
|
5
6
|
/** The transport has already validated the complete pinned initialize response. */
|
|
6
|
-
export declare function readNegotiatedAgent(response: AcpJsonValue, permissionMapping?: AcpPermissionMappingSelection, sessionInteractions?: AcpSessionInteractionSelection): AcpNegotiatedAgent;
|
|
7
|
+
export declare function readNegotiatedAgent(response: AcpJsonValue, permissionMapping?: AcpPermissionMappingSelection, sessionInteractions?: AcpSessionInteractionSelection, structuredOutputMapping?: AcpStructuredOutputMappingSelection): AcpNegotiatedAgent;
|
|
7
8
|
export declare function negotiatedEnvelope(negotiated: AcpNegotiatedAgent): string;
|
|
8
9
|
//# sourceMappingURL=negotiation.d.ts.map
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AcpProviderConnectionError } from "./errors.js";
|
|
2
|
+
import { assertAcpStructuredOutputIdentity } from "../structuredOutput/mapping.js";
|
|
2
3
|
function immutableProtocolData(value) {
|
|
3
4
|
if (Array.isArray(value)) {
|
|
4
5
|
const items = value.map(immutableProtocolData);
|
|
@@ -11,7 +12,7 @@ function immutableProtocolData(value) {
|
|
|
11
12
|
}
|
|
12
13
|
return value;
|
|
13
14
|
}
|
|
14
|
-
function readNegotiatedAgent(response, permissionMapping = { mapping: "once-only-v1" }, sessionInteractions) {
|
|
15
|
+
function readNegotiatedAgent(response, permissionMapping = { mapping: "once-only-v1" }, sessionInteractions, structuredOutputMapping) {
|
|
15
16
|
const value = response;
|
|
16
17
|
if (value.protocolVersion !== 1) {
|
|
17
18
|
throw new AcpProviderConnectionError("acp_provider_version_unsupported", "ACP wire version 1 is required.");
|
|
@@ -28,6 +29,8 @@ function readNegotiatedAgent(response, permissionMapping = { mapping: "once-only
|
|
|
28
29
|
agentInfo = Object.freeze({ name: info.name, version: info.version });
|
|
29
30
|
}
|
|
30
31
|
let agentVersion;
|
|
32
|
+
assertAcpStructuredOutputIdentity(value, structuredOutputMapping);
|
|
33
|
+
if (structuredOutputMapping) agentVersion = "1.0.62";
|
|
31
34
|
if (sessionInteractions?.mapping === "grok-build-1.0.60-session-requests-v1") {
|
|
32
35
|
const meta = value._meta;
|
|
33
36
|
if (meta === null || typeof meta !== "object" || Array.isArray(meta) || meta.agentVersion !== "1.0.60") {
|
package/dist/contracts.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { AcpProviderLimits } from './limits.js';
|
|
|
5
5
|
import type { AcpStandardMcpServer, AcpUnknownExtensionPolicy } from '@agen-ai/acp-transport';
|
|
6
6
|
import type { AcpAuthenticationMethods, AcpHostFacilities } from './host/contracts.js';
|
|
7
7
|
import type { AcpPermissionMappingSelection } from './permissions/contracts.js';
|
|
8
|
+
import type { AcpStructuredOutputMappingSelection } from './structuredOutput/mapping.js';
|
|
8
9
|
export type { AcpProviderLimits } from './limits.js';
|
|
9
10
|
export interface AcpConnectionStreams {
|
|
10
11
|
readonly stdout: Readable;
|
|
@@ -54,6 +55,8 @@ export interface CreateAcpProviderDriverOptions {
|
|
|
54
55
|
readonly unknownExtensionPolicy?: AcpUnknownExtensionPolicy;
|
|
55
56
|
/** Defaults to once-only choices; complete profiles require independently qualified native semantics. */
|
|
56
57
|
readonly permissionMapping?: AcpPermissionMappingSelection;
|
|
58
|
+
/** Opts into the exact qualified native schema contract; absent means unsupported. */
|
|
59
|
+
readonly structuredOutputMapping?: AcpStructuredOutputMappingSelection;
|
|
57
60
|
readonly limits?: Partial<AcpProviderLimits>;
|
|
58
61
|
readonly configuration?: 'managed' | 'selectable';
|
|
59
62
|
readonly authentication?: AcpAuthenticationMethods;
|
package/dist/driverFactory.js
CHANGED
|
@@ -7,6 +7,7 @@ import { resolveAuthenticationMapping } from "./auth/methods.js";
|
|
|
7
7
|
import { resolveHostFacilities } from "./host/validation.js";
|
|
8
8
|
import { resolveAcpMcpServers, resolveAcpSessionMcpBinding } from "./mcp.js";
|
|
9
9
|
import { resolveAcpPermissionMapping } from "./permissions/selection.js";
|
|
10
|
+
import { resolveAcpStructuredOutputMapping } from "./structuredOutput/mapping.js";
|
|
10
11
|
function createAcpProviderDriverInternal(options, sessionInteractions) {
|
|
11
12
|
const providerKey = parseAgentProviderKey(options.providerKey);
|
|
12
13
|
const connectionSource = options.connectionSource;
|
|
@@ -21,6 +22,7 @@ function createAcpProviderDriverInternal(options, sessionInteractions) {
|
|
|
21
22
|
const mcpServers = resolveAcpMcpServers(options.mcpServers);
|
|
22
23
|
const sessionMcpBinding = resolveAcpSessionMcpBinding(options.sessionMcpBinding);
|
|
23
24
|
const permissionMapping = resolveAcpPermissionMapping(options.permissionMapping);
|
|
25
|
+
const structuredOutputMapping = resolveAcpStructuredOutputMapping(options.structuredOutputMapping);
|
|
24
26
|
const usedStreams = /* @__PURE__ */ new WeakSet();
|
|
25
27
|
return defineAgentProviderDriver({
|
|
26
28
|
providerKey,
|
|
@@ -38,6 +40,7 @@ function createAcpProviderDriverInternal(options, sessionInteractions) {
|
|
|
38
40
|
host,
|
|
39
41
|
mcpServers,
|
|
40
42
|
permissionMapping,
|
|
43
|
+
...structuredOutputMapping ? { structuredOutputMapping } : {},
|
|
41
44
|
...sessionMcpBinding ? { sessionMcpBinding } : {},
|
|
42
45
|
...sessionInteractions ? { sessionInteractions } : {}
|
|
43
46
|
})
|
package/dist/host/router.d.ts
CHANGED
|
@@ -31,9 +31,19 @@ export declare class AcpHostRouter {
|
|
|
31
31
|
readonly requestId: AcpRequestId;
|
|
32
32
|
}) => void;
|
|
33
33
|
onResponseReceived: (response: import("@agen-ai/acp-transport").AcpResponseReceived) => void;
|
|
34
|
+
signal?: AbortSignal;
|
|
35
|
+
lifetime?: "bounded";
|
|
34
36
|
timeoutMs?: number;
|
|
35
37
|
deadlineAt?: number | Date;
|
|
38
|
+
} | {
|
|
39
|
+
onRequestDispatch: (context: {
|
|
40
|
+
readonly requestId: AcpRequestId;
|
|
41
|
+
}) => void;
|
|
42
|
+
onResponseReceived: (response: import("@agen-ai/acp-transport").AcpResponseReceived) => void;
|
|
36
43
|
signal?: AbortSignal;
|
|
44
|
+
lifetime: "until_settled";
|
|
45
|
+
timeoutMs?: never;
|
|
46
|
+
deadlineAt?: never;
|
|
37
47
|
};
|
|
38
48
|
close: () => Promise<void>;
|
|
39
49
|
};
|
package/dist/host/router.js
CHANGED
|
@@ -95,7 +95,7 @@ class AcpHostRouter {
|
|
|
95
95
|
if (!ingress) throw invalidHostRequest();
|
|
96
96
|
return ingress.onPermissionRequest(context);
|
|
97
97
|
}
|
|
98
|
-
const timeout = context.method === "terminal/wait_for_exit" ? this.input.limits.
|
|
98
|
+
const timeout = context.method === "terminal/wait_for_exit" ? this.input.limits.terminalWaitTimeoutMs : this.input.limits.hostOperationTimeoutMs;
|
|
99
99
|
const deadline = hostDeadline(session.signal, timeout);
|
|
100
100
|
return this.hostRequest(context.method, params, { ...session, signal: deadline.signal }).finally(() => deadline.close());
|
|
101
101
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export { createAcpProviderDriver } from './driver.js';
|
|
|
2
2
|
export { DEFAULT_ACP_PROVIDER_LIMITS, type AcpProviderLimits } from './limits.js';
|
|
3
3
|
export { AcpProviderConnectionError } from './connection/errors.js';
|
|
4
4
|
export { AcpProviderSessionError } from './session/errors.js';
|
|
5
|
+
export type { AcpStructuredOutputMappingSelection } from './structuredOutput/mapping.js';
|
|
5
6
|
export type { AcpPermissionOptionSignature, AcpPermissionMenuSignature, AcpPermissionMappingSelection, } from './permissions/contracts.js';
|
|
6
7
|
export type { AcpConnectionStreams, AcpConnectionLease, AcpConnectionFactoryContext, AcpConnectionFactory, AcpSessionMcpBindingContext, AcpSessionMcpBindingLease, AcpSessionMcpBindingFactory, AcpSessionMcpBindingOptions, CreateAcpProviderDriverOptions, } from './contracts.js';
|
|
7
8
|
export type { AcpAuthenticationMethods, AcpHostFacilities, AcpHostInteractionScope, AcpHostInteractionInput, AcpHostFormInput, AcpHostFormResponse, AcpHostUrlInput, AcpHostUrlDecision, AcpHostUrlInteractionLease, AcpHostSessionInput, AcpHostFileReadInput, AcpHostFileWriteInput, AcpHostTerminalCreateInput, AcpHostTerminalLease, AcpHostTerminalOutput, AcpHostTerminalExitStatus, AcpHostAuthenticationTerminalInput, AcpHostAuthenticationTerminalLease, } from './host/contracts.js';
|
package/dist/instance.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import type { AcpProviderLimits } from './limits.js';
|
|
|
7
7
|
import type { AcpConnectionSource } from './connection/contracts.js';
|
|
8
8
|
import type { AcpSessionInteractionSelection } from './sessionInteractions/contracts.js';
|
|
9
9
|
import type { AcpPermissionMappingSelection } from './permissions/contracts.js';
|
|
10
|
+
import type { AcpStructuredOutputMappingSelection } from './structuredOutput/mapping.js';
|
|
10
11
|
export declare function createAcpProviderInstance(input: {
|
|
11
12
|
readonly providerKey: AgentProviderKey;
|
|
12
13
|
readonly instanceId: AgentInstanceId;
|
|
@@ -19,6 +20,7 @@ export declare function createAcpProviderInstance(input: {
|
|
|
19
20
|
readonly host: AcpHostFacilities;
|
|
20
21
|
readonly mcpServers: readonly AcpStandardMcpServer[];
|
|
21
22
|
readonly permissionMapping: AcpPermissionMappingSelection;
|
|
23
|
+
readonly structuredOutputMapping?: AcpStructuredOutputMappingSelection;
|
|
22
24
|
readonly sessionMcpBinding?: AcpSessionMcpBindingOptions;
|
|
23
25
|
readonly sessionInteractions?: AcpSessionInteractionSelection;
|
|
24
26
|
}): Promise<MaterializedAgentProviderInstance>;
|
package/dist/instance.js
CHANGED
|
@@ -43,6 +43,7 @@ async function createAcpProviderInstance(input) {
|
|
|
43
43
|
authentication: input.authentication,
|
|
44
44
|
host: input.host,
|
|
45
45
|
permissionMapping: input.permissionMapping,
|
|
46
|
+
...input.structuredOutputMapping ? { structuredOutputMapping: input.structuredOutputMapping } : {},
|
|
46
47
|
...input.sessionInteractions ? { sessionInteractions: input.sessionInteractions } : {}
|
|
47
48
|
});
|
|
48
49
|
};
|
|
@@ -53,7 +54,15 @@ async function createAcpProviderInstance(input) {
|
|
|
53
54
|
try {
|
|
54
55
|
assertAcpMcpSupport(input.mcpServers, negotiated);
|
|
55
56
|
methods = selectedAuthenticationMethods(negotiated, input.authentication, input.host);
|
|
56
|
-
capabilities = acpProviderCapabilities(
|
|
57
|
+
capabilities = acpProviderCapabilities(
|
|
58
|
+
input.providerKey,
|
|
59
|
+
negotiated,
|
|
60
|
+
input.configuration,
|
|
61
|
+
[...methods.keys()],
|
|
62
|
+
input.sessionInteractions,
|
|
63
|
+
input.permissionMapping,
|
|
64
|
+
input.structuredOutputMapping
|
|
65
|
+
);
|
|
57
66
|
} catch (cause) {
|
|
58
67
|
if (eager.execution?.cleanupFailure) throw eager.execution.retainedError(cause, eager.execution.cleanupFailure.error);
|
|
59
68
|
try {
|
|
@@ -133,6 +142,11 @@ async function createAcpProviderInstance(input) {
|
|
|
133
142
|
const open = async (context, resume) => {
|
|
134
143
|
throwIfAgentOperationAborted(context.signal);
|
|
135
144
|
throwIfAgentOperationAborted(lifetime.signal);
|
|
145
|
+
if ("output" in context && context.output !== void 0) throw new AgentProviderContractError(
|
|
146
|
+
input.providerKey,
|
|
147
|
+
capabilities.turns.structuredOutput.kind === "unsupported" ? "structured_output_unsupported" : "structured_output_scope_mismatch",
|
|
148
|
+
"ACP structured output is accepted only when starting a turn."
|
|
149
|
+
);
|
|
136
150
|
if (input.sessionInteractions?.mapping === "grok-folder-trust-v1" && resume) throw new AgentProviderContractError(
|
|
137
151
|
input.providerKey,
|
|
138
152
|
"session_interactions_unsupported",
|
package/dist/limits.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ export interface AcpProviderLimits {
|
|
|
7
7
|
readonly authenticationTimeoutMs: number;
|
|
8
8
|
readonly cancellationTimeoutMs: number;
|
|
9
9
|
readonly initializationTimeoutMs: number;
|
|
10
|
-
readonly
|
|
10
|
+
readonly terminalWaitTimeoutMs: number;
|
|
11
11
|
}
|
|
12
12
|
export declare const DEFAULT_ACP_PROVIDER_LIMITS: AcpProviderLimits;
|
|
13
13
|
export declare function resolveAcpProviderLimits(overrides?: Partial<AcpProviderLimits>): AcpProviderLimits;
|
package/dist/limits.js
CHANGED
|
@@ -7,7 +7,7 @@ const DEFAULT_ACP_PROVIDER_LIMITS = Object.freeze({
|
|
|
7
7
|
authenticationTimeoutMs: 15 * 6e4,
|
|
8
8
|
cancellationTimeoutMs: 5e3,
|
|
9
9
|
initializationTimeoutMs: 3e4,
|
|
10
|
-
|
|
10
|
+
terminalWaitTimeoutMs: 30 * 6e4
|
|
11
11
|
});
|
|
12
12
|
const BOUNDS = {
|
|
13
13
|
maxQueuedMessages: [4, 1024],
|
|
@@ -18,7 +18,7 @@ const BOUNDS = {
|
|
|
18
18
|
authenticationTimeoutMs: [10, 30 * 6e4],
|
|
19
19
|
cancellationTimeoutMs: [10, 6e4],
|
|
20
20
|
initializationTimeoutMs: [10, 30 * 6e4],
|
|
21
|
-
|
|
21
|
+
terminalWaitTimeoutMs: [10, 30 * 6e4]
|
|
22
22
|
};
|
|
23
23
|
function resolveAcpProviderLimits(overrides = {}) {
|
|
24
24
|
if (Object.keys(overrides).some((key) => !Object.hasOwn(BOUNDS, key))) {
|
package/dist/node/index.js
CHANGED
|
@@ -15,6 +15,7 @@ function createNodeAcpProviderDriver(options) {
|
|
|
15
15
|
connectionSource: reserve ? { kind: "reserved", reserve } : { kind: "factory", create: (context) => spawnAcpProcess(launch, context) },
|
|
16
16
|
...options.unknownExtensionPolicy !== void 0 ? { unknownExtensionPolicy: options.unknownExtensionPolicy } : {},
|
|
17
17
|
...options.permissionMapping !== void 0 ? { permissionMapping: options.permissionMapping } : {},
|
|
18
|
+
...options.structuredOutputMapping !== void 0 ? { structuredOutputMapping: options.structuredOutputMapping } : {},
|
|
18
19
|
...options.limits ? { limits: options.limits } : {},
|
|
19
20
|
...options.configuration ? { configuration: options.configuration } : {},
|
|
20
21
|
...options.authentication ? { authentication: options.authentication } : {},
|
|
@@ -2,15 +2,16 @@ import { AcpProviderSessionError } from "./errors.js";
|
|
|
2
2
|
import { nativeObject, nativeString } from "./native.js";
|
|
3
3
|
function acpTurnCompletion(response, cancelReason) {
|
|
4
4
|
if (response.kind === "error") return {
|
|
5
|
+
structuredOutput: { kind: "not_requested" },
|
|
5
6
|
outcome: "failed",
|
|
6
7
|
error: promptFailure(response.error.code)
|
|
7
8
|
};
|
|
8
9
|
const reason = nativeString(nativeObject(response.result, "prompt response").stopReason, "prompt stop reason");
|
|
9
|
-
if (reason === "cancelled") return { outcome: cancelReason === "timeout" ? "expired" : "canceled" };
|
|
10
|
-
if (reason === "end_turn") return { outcome: "completed" };
|
|
11
|
-
if (reason === "max_tokens") return { outcome: "completed", reason: "The agent reached its token limit." };
|
|
12
|
-
if (reason === "max_turn_requests") return { outcome: "completed", reason: "The agent reached its request limit." };
|
|
13
|
-
if (reason === "refusal") return { outcome: "completed", reason: "The agent declined the request." };
|
|
10
|
+
if (reason === "cancelled") return { structuredOutput: { kind: "not_requested" }, outcome: cancelReason === "timeout" ? "expired" : "canceled" };
|
|
11
|
+
if (reason === "end_turn") return { structuredOutput: { kind: "not_requested" }, outcome: "completed" };
|
|
12
|
+
if (reason === "max_tokens") return { structuredOutput: { kind: "not_requested" }, outcome: "completed", reason: "The agent reached its token limit." };
|
|
13
|
+
if (reason === "max_turn_requests") return { structuredOutput: { kind: "not_requested" }, outcome: "completed", reason: "The agent reached its request limit." };
|
|
14
|
+
if (reason === "refusal") return { structuredOutput: { kind: "not_requested" }, outcome: "completed", reason: "The agent declined the request." };
|
|
14
15
|
throw new AcpProviderSessionError("acp_stop_reason_invalid", "ACP returned an unsupported prompt stop reason.");
|
|
15
16
|
}
|
|
16
17
|
function promptFailure(code) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const MAX_TIMER_DELAY_MS = 2147483647;
|
|
2
|
+
function scheduleTurnDeadline(deadlineAt, expire) {
|
|
3
|
+
const expiresAt = Date.parse(deadlineAt);
|
|
4
|
+
let timer;
|
|
5
|
+
const check = () => {
|
|
6
|
+
const remaining = expiresAt - Date.now();
|
|
7
|
+
if (remaining <= 0) {
|
|
8
|
+
expire();
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
timer = setTimeout(check, Math.min(remaining, MAX_TIMER_DELAY_MS));
|
|
12
|
+
};
|
|
13
|
+
timer = setTimeout(check, Math.min(Math.max(0, expiresAt - Date.now()), MAX_TIMER_DELAY_MS));
|
|
14
|
+
return () => clearTimeout(timer);
|
|
15
|
+
}
|
|
16
|
+
export {
|
|
17
|
+
scheduleTurnDeadline
|
|
18
|
+
};
|
package/dist/session/mapping.js
CHANGED
package/dist/session/session.js
CHANGED
|
@@ -25,6 +25,9 @@ import { prepareAcpSessionElicitation } from "./requests/elicitation.js";
|
|
|
25
25
|
import { canceledRequestReply, PendingSessionRequests } from "./requests/pending.js";
|
|
26
26
|
import { nativeBytes, nativeObject, nativeString, SESSION_METADATA_UPDATES } from "./native.js";
|
|
27
27
|
import { deferred, SessionQueue } from "./queue.js";
|
|
28
|
+
import { prepareAcpStructuredOutput } from "../structuredOutput/request.js";
|
|
29
|
+
import { acpStructuredOutputCompletion } from "../structuredOutput/completion.js";
|
|
30
|
+
import { scheduleTurnDeadline } from "./deadline.js";
|
|
28
31
|
class SessionState {
|
|
29
32
|
constructor(input) {
|
|
30
33
|
this.input = input;
|
|
@@ -286,16 +289,18 @@ class SessionState {
|
|
|
286
289
|
throw new AcpProviderSessionError("acp_input_unsupported", "ACP supports only the default interaction mode.");
|
|
287
290
|
}
|
|
288
291
|
const prompt = prepareAcpPrompt(input.parts, this.input.capabilities);
|
|
289
|
-
const
|
|
290
|
-
|
|
292
|
+
const output = prepareAcpStructuredOutput(input.output, this.input.capabilities);
|
|
293
|
+
const turn = this.createNativeTurn(input.turnId, output?.schema);
|
|
294
|
+
return this.execution(turn, () => this.streamTurn(turn, input, prompt, output?.promptMeta));
|
|
291
295
|
}
|
|
292
|
-
createNativeTurn(turnId) {
|
|
296
|
+
createNativeTurn(turnId, outputSchema) {
|
|
293
297
|
this.requireUsable();
|
|
294
298
|
if (this.turn && !this.turn.sourceSettled) throw new AcpProviderSessionError("acp_turn_active", "The ACP session already has an active or waiting turn.");
|
|
295
299
|
const settled = deferred();
|
|
296
300
|
void settled.promise.catch(() => void 0);
|
|
297
301
|
const turn = {
|
|
298
302
|
turnId,
|
|
303
|
+
...outputSchema ? { outputSchema } : {},
|
|
299
304
|
mapping: new TurnMapping({
|
|
300
305
|
sessionId: this.input.context.sessionId,
|
|
301
306
|
turnId,
|
|
@@ -348,7 +353,7 @@ class SessionState {
|
|
|
348
353
|
this.queue.admit({ kind: "terminal", payload }, nativeBytes(payload), true);
|
|
349
354
|
turn.settled.resolve(payload);
|
|
350
355
|
}
|
|
351
|
-
launchTurn(turn, input, prompt) {
|
|
356
|
+
launchTurn(turn, input, prompt, promptMeta) {
|
|
352
357
|
this.requireUsable();
|
|
353
358
|
throwIfAgentOperationAborted(input.signal);
|
|
354
359
|
if (turn.nativeSettled) return;
|
|
@@ -356,11 +361,17 @@ class SessionState {
|
|
|
356
361
|
turn.nativeStarted = true;
|
|
357
362
|
turn.prompt = this.operations.prompt({
|
|
358
363
|
sessionId: this.nativeSessionId,
|
|
359
|
-
prompt
|
|
364
|
+
prompt,
|
|
365
|
+
...promptMeta ? { _meta: promptMeta } : {}
|
|
360
366
|
}, {
|
|
361
|
-
|
|
367
|
+
lifetime: "until_settled",
|
|
362
368
|
onResponseReceived: (response) => {
|
|
363
|
-
const payload =
|
|
369
|
+
const payload = acpStructuredOutputCompletion(
|
|
370
|
+
acpTurnCompletion(response, turn.cancelReason),
|
|
371
|
+
response,
|
|
372
|
+
turn.outputSchema,
|
|
373
|
+
this.nativeSessionId
|
|
374
|
+
);
|
|
364
375
|
this.completeNativeTurn(turn, payload);
|
|
365
376
|
}
|
|
366
377
|
}).then(() => void 0, (error) => {
|
|
@@ -376,8 +387,7 @@ class SessionState {
|
|
|
376
387
|
if (input.signal.aborted) abort();
|
|
377
388
|
}
|
|
378
389
|
if (input.deadlineAt !== void 0) {
|
|
379
|
-
|
|
380
|
-
turn.cleanup.push(() => clearTimeout(timer));
|
|
390
|
+
turn.cleanup.push(scheduleTurnDeadline(input.deadlineAt, () => cancel("timeout")));
|
|
381
391
|
}
|
|
382
392
|
}
|
|
383
393
|
async *emit(output) {
|
|
@@ -499,10 +509,10 @@ class SessionState {
|
|
|
499
509
|
if (turn.terminal) return;
|
|
500
510
|
yield* this.emit(turn.mapping.event("turn.state_changed", { state: "waiting_for_request", requestId: canonical.requestId }));
|
|
501
511
|
}
|
|
502
|
-
async *streamTurn(turn, input, prompt) {
|
|
512
|
+
async *streamTurn(turn, input, prompt, promptMeta) {
|
|
503
513
|
let stable = false;
|
|
504
514
|
try {
|
|
505
|
-
this.launchTurn(turn, input, prompt);
|
|
515
|
+
this.launchTurn(turn, input, prompt, promptMeta);
|
|
506
516
|
yield* this.emit(turn.mapping.event("turn.started", {}));
|
|
507
517
|
yield* this.drain(turn);
|
|
508
518
|
await this.requests.join();
|
|
@@ -534,7 +544,7 @@ class SessionState {
|
|
|
534
544
|
this.requests.cancelAll();
|
|
535
545
|
turn.hostInteractions.abort(new DOMException("The ACP turn was canceled.", "AbortError"));
|
|
536
546
|
if (!turn.nativeStarted) {
|
|
537
|
-
const payload = { outcome: reason === "timeout" ? "expired" : "canceled" };
|
|
547
|
+
const payload = { structuredOutput: turn.outputSchema ? { kind: "unavailable", reason: "incomplete" } : { kind: "not_requested" }, outcome: reason === "timeout" ? "expired" : "canceled" };
|
|
538
548
|
turn.nativeSettled = true;
|
|
539
549
|
this.queue.admit({ kind: "terminal", payload }, nativeBytes(payload), true);
|
|
540
550
|
turn.settled.resolve(payload);
|
package/dist/session/turn.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AcpJsonObject } from '@agen-ai/acp-transport';
|
|
2
|
-
import type { AgentRequestId, AgentTurnCompletedPayload, AgentTurnId } from '@agen-ai/agent-protocol';
|
|
2
|
+
import type { AgentOutputSchema, AgentRequestId, AgentTurnCompletedPayload, AgentTurnId } from '@agen-ai/agent-protocol';
|
|
3
3
|
import type { TurnMapping } from './mapping.js';
|
|
4
4
|
import type { deferred } from './queue.js';
|
|
5
5
|
import type { PendingSessionRequest } from './requests/pending.js';
|
|
@@ -19,6 +19,7 @@ export type SessionMessage = Readonly<{
|
|
|
19
19
|
}>;
|
|
20
20
|
export interface NativeTurn {
|
|
21
21
|
readonly turnId: AgentTurnId;
|
|
22
|
+
readonly outputSchema?: AgentOutputSchema;
|
|
22
23
|
readonly mapping: TurnMapping;
|
|
23
24
|
readonly settled: ReturnType<typeof deferred<AgentTurnCompletedPayload>>;
|
|
24
25
|
readonly cleanup: (() => void)[];
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AcpResponseReceived } from '@agen-ai/acp-transport';
|
|
2
|
+
import type { AgentOutputSchema, AgentTurnCompletedPayload } from '@agen-ai/agent-protocol';
|
|
3
|
+
export declare function acpStructuredOutputCompletion(completion: AgentTurnCompletedPayload, response: AcpResponseReceived, schema: AgentOutputSchema | undefined, nativeSessionId: string): AgentTurnCompletedPayload;
|
|
4
|
+
//# sourceMappingURL=completion.d.ts.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { createAgentStructuredOutputCandidate } from "@agen-ai/agent-runtime";
|
|
2
|
+
import { AcpProviderSessionError } from "../session/errors.js";
|
|
3
|
+
import { nativeBytes, nativeObject } from "../session/native.js";
|
|
4
|
+
const GROK_STRUCTURED_METADATA_BYTES_LIMIT = 32768;
|
|
5
|
+
const GROK_STRUCTURED_ERROR_BYTES_LIMIT = 4096;
|
|
6
|
+
function structuredOutputResult(response, schema, nativeSessionId) {
|
|
7
|
+
if (!schema) return { kind: "not_requested" };
|
|
8
|
+
const unavailable = (reason) => createAgentStructuredOutputCandidate({
|
|
9
|
+
schema,
|
|
10
|
+
candidate: { kind: "unavailable", reason }
|
|
11
|
+
});
|
|
12
|
+
if (response.kind === "error") return unavailable("provider_error");
|
|
13
|
+
const result = nativeObject(response.result, "structured prompt response");
|
|
14
|
+
const meta = result._meta === void 0 ? void 0 : nativeObject(result._meta, "structured response metadata");
|
|
15
|
+
if (meta && nativeBytes(meta) > GROK_STRUCTURED_METADATA_BYTES_LIMIT) return unavailable("output_limit_exceeded");
|
|
16
|
+
if (meta?.sessionId !== void 0 && meta.sessionId !== nativeSessionId) {
|
|
17
|
+
throw new AcpProviderSessionError(
|
|
18
|
+
"acp_structured_output_identity_mismatch",
|
|
19
|
+
"Structured output metadata identifies a different native session."
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
const hasOutput = meta !== void 0 && Object.hasOwn(meta, "structuredOutput");
|
|
23
|
+
const hasError = meta !== void 0 && Object.hasOwn(meta, "structuredOutputError");
|
|
24
|
+
if (hasOutput && hasError) {
|
|
25
|
+
throw new AcpProviderSessionError(
|
|
26
|
+
"acp_structured_output_ambiguous",
|
|
27
|
+
"Structured output response contains both a value and an error."
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
if (hasError && (typeof meta?.structuredOutputError !== "string" || !meta.structuredOutputError.trim() || Buffer.byteLength(meta.structuredOutputError, "utf8") > GROK_STRUCTURED_ERROR_BYTES_LIMIT)) {
|
|
31
|
+
throw new AcpProviderSessionError(
|
|
32
|
+
"acp_structured_output_error_invalid",
|
|
33
|
+
"Structured output error must be a bounded nonempty native error string."
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
if (result.stopReason === "refusal") return unavailable("refused");
|
|
37
|
+
if (result.stopReason !== "end_turn") return unavailable("incomplete");
|
|
38
|
+
if (hasError) return unavailable("provider_error");
|
|
39
|
+
if (!hasOutput) return unavailable("missing_output");
|
|
40
|
+
return createAgentStructuredOutputCandidate({ schema, candidate: { kind: "json_value", value: meta?.structuredOutput } });
|
|
41
|
+
}
|
|
42
|
+
function acpStructuredOutputCompletion(completion, response, schema, nativeSessionId) {
|
|
43
|
+
const structuredOutput = structuredOutputResult(response, schema, nativeSessionId);
|
|
44
|
+
if (completion.outcome === "completed") return { ...completion, structuredOutput };
|
|
45
|
+
if (structuredOutput.kind === "json") {
|
|
46
|
+
throw new AcpProviderSessionError(
|
|
47
|
+
"acp_structured_output_terminal_invalid",
|
|
48
|
+
"A structured output value requires successful native completion."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return { ...completion, structuredOutput };
|
|
52
|
+
}
|
|
53
|
+
export {
|
|
54
|
+
acpStructuredOutputCompletion
|
|
55
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type AgentStructuredOutputCapability } from '@agen-ai/agent-protocol';
|
|
2
|
+
import type { AcpJsonObject } from '@agen-ai/acp-transport';
|
|
3
|
+
/** Explicit native contract; generic ACP metadata support does not imply this feature. */
|
|
4
|
+
export interface AcpStructuredOutputMappingSelection {
|
|
5
|
+
readonly mapping: 'grok-build-1.0.62-structured-output-v1';
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveAcpStructuredOutputMapping(input: unknown): AcpStructuredOutputMappingSelection | undefined;
|
|
8
|
+
export declare function assertAcpStructuredOutputIdentity(initialized: AcpJsonObject, selected: AcpStructuredOutputMappingSelection | undefined): void;
|
|
9
|
+
export declare function acpStructuredOutputCapability(selected: AcpStructuredOutputMappingSelection | undefined): AgentStructuredOutputCapability;
|
|
10
|
+
//# sourceMappingURL=mapping.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AGENT_OUTPUT_SCHEMA_BYTES_LIMIT,
|
|
3
|
+
AGENT_OUTPUT_SCHEMA_PROFILE,
|
|
4
|
+
AGENT_OUTPUT_VALUE_BYTES_LIMIT
|
|
5
|
+
} from "@agen-ai/agent-protocol";
|
|
6
|
+
import { AcpProviderConnectionError } from "../connection/errors.js";
|
|
7
|
+
function resolveAcpStructuredOutputMapping(input) {
|
|
8
|
+
if (input === void 0) return void 0;
|
|
9
|
+
if (input === null || typeof input !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(input))) {
|
|
10
|
+
throw new TypeError("ACP structured output mapping must be an explicit selection.");
|
|
11
|
+
}
|
|
12
|
+
const keys = Reflect.ownKeys(input);
|
|
13
|
+
const descriptor = Object.getOwnPropertyDescriptor(input, "mapping");
|
|
14
|
+
if (keys.length !== 1 || keys[0] !== "mapping" || !descriptor || !("value" in descriptor) || !descriptor.enumerable || descriptor.value !== "grok-build-1.0.62-structured-output-v1") {
|
|
15
|
+
throw new TypeError("ACP structured output mapping is unsupported.");
|
|
16
|
+
}
|
|
17
|
+
return Object.freeze({ mapping: "grok-build-1.0.62-structured-output-v1" });
|
|
18
|
+
}
|
|
19
|
+
function assertAcpStructuredOutputIdentity(initialized, selected) {
|
|
20
|
+
if (!selected) return;
|
|
21
|
+
const meta = initialized._meta;
|
|
22
|
+
if (meta === null || typeof meta !== "object" || Array.isArray(meta) || meta.grokShell !== true || meta.agentVersion !== "1.0.62") {
|
|
23
|
+
throw new AcpProviderConnectionError(
|
|
24
|
+
"acp_structured_output_profile_mismatch",
|
|
25
|
+
"The selected structured output mapping requires exact Grok Build agentVersion 1.0.62."
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function acpStructuredOutputCapability(selected) {
|
|
30
|
+
return selected ? {
|
|
31
|
+
kind: "supported",
|
|
32
|
+
mechanism: "native",
|
|
33
|
+
schemaProfile: AGENT_OUTPUT_SCHEMA_PROFILE,
|
|
34
|
+
scope: "turn",
|
|
35
|
+
maxSchemaBytes: AGENT_OUTPUT_SCHEMA_BYTES_LIMIT,
|
|
36
|
+
maxOutputBytes: AGENT_OUTPUT_VALUE_BYTES_LIMIT,
|
|
37
|
+
resume: false,
|
|
38
|
+
branch: false
|
|
39
|
+
} : { kind: "unsupported" };
|
|
40
|
+
}
|
|
41
|
+
export {
|
|
42
|
+
acpStructuredOutputCapability,
|
|
43
|
+
assertAcpStructuredOutputIdentity,
|
|
44
|
+
resolveAcpStructuredOutputMapping
|
|
45
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type AcpJsonObject } from '@agen-ai/acp-transport';
|
|
2
|
+
import { type AgentCapabilities, type AgentOutputSchema, type AgentStructuredOutputRequest } from '@agen-ai/agent-protocol';
|
|
3
|
+
export declare function prepareAcpStructuredOutput(request: AgentStructuredOutputRequest | undefined, capabilities: AgentCapabilities): Readonly<{
|
|
4
|
+
schema: AgentOutputSchema;
|
|
5
|
+
promptMeta: AcpJsonObject;
|
|
6
|
+
}> | undefined;
|
|
7
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { assertBoundedAcpJson, DEFAULT_ACP_PROTOCOL_LIMITS } from "@agen-ai/acp-transport";
|
|
2
|
+
import { parseAgentOutputSchema } from "@agen-ai/agent-protocol";
|
|
3
|
+
import { AgentProviderContractError } from "@agen-ai/agent-runtime";
|
|
4
|
+
function prepareAcpStructuredOutput(request, capabilities) {
|
|
5
|
+
if (request === void 0) return void 0;
|
|
6
|
+
if (capabilities.turns.structuredOutput.kind === "unsupported") {
|
|
7
|
+
throw new AgentProviderContractError(
|
|
8
|
+
capabilities.providerKey,
|
|
9
|
+
"structured_output_unsupported",
|
|
10
|
+
"The ACP provider has no selected native structured output mapping."
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
const schema = parseAgentOutputSchema(request.schema);
|
|
14
|
+
assertBoundedAcpJson(schema, DEFAULT_ACP_PROTOCOL_LIMITS);
|
|
15
|
+
return { schema, promptMeta: { outputSchema: schema } };
|
|
16
|
+
}
|
|
17
|
+
export {
|
|
18
|
+
prepareAcpStructuredOutput
|
|
19
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agen-ai/provider-acp",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Optional Agent Client Protocol provider for the AgenAI coding-agent runtime.",
|
|
6
6
|
"type": "module",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"./package.json": "./package.json"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@agen-ai/acp-transport": "^0.4.
|
|
31
|
-
"@agen-ai/agent-
|
|
32
|
-
"@agen-ai/agent-
|
|
30
|
+
"@agen-ai/acp-transport": "^0.4.5",
|
|
31
|
+
"@agen-ai/agent-runtime": "^0.4.5",
|
|
32
|
+
"@agen-ai/agent-protocol": "^0.4.5"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"tsup": "^8.5.0"
|