@agen-ai/agent-runtime 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.
- package/README.md +116 -8
- package/dist/adapterValidation.js +45 -5
- package/dist/artifacts.js +0 -1
- package/dist/contractErrors.d.ts +2 -2
- package/dist/contractErrors.js +5 -7
- package/dist/hostBindings/opening.d.ts +2 -0
- package/dist/hostBindings/opening.js +58 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/outputValidation.js +2 -2
- package/dist/providerDriver.js +0 -1
- package/dist/providerInstanceRegistry.js +2 -1
- package/dist/sessionInteractions/index.d.ts +2 -0
- package/dist/sessionInteractions/index.js +1 -0
- package/dist/sessionInteractions/lifetime.d.ts +52 -0
- package/dist/sessionInteractions/lifetime.js +251 -0
- package/dist/sessionInteractions/request.d.ts +42 -0
- package/dist/sessionInteractions/request.js +308 -0
- package/dist/sessionInteractions/types.d.ts +54 -0
- package/dist/sessionInteractions/types.js +10 -0
- package/dist/sessionInteractions/validation.d.ts +21 -0
- package/dist/sessionInteractions/validation.js +119 -0
- package/dist/sessionValidation.d.ts +4 -1
- package/dist/sessionValidation.js +29 -21
- package/dist/sessions.d.ts +3 -0
- package/dist/testing/conformance.js +0 -1
- package/dist/testing/fakeProvider.js +5 -6
- package/dist/turnExecution/requests.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,8 +9,9 @@ sessions; each returned session owns its binding and conversation-local operatio
|
|
|
9
9
|
The runtime depends only on `@agen-ai/agent-protocol`. It has no concept of tenants, SaaS
|
|
10
10
|
workspaces, assigned users, database rows, persistence sequence, visibility, billing, host boots,
|
|
11
11
|
distributed leases, or storage policy. A host must authorize and select an instance before calling this SPI.
|
|
12
|
-
This source package implements Agent Protocol
|
|
13
|
-
`0.4.0`
|
|
12
|
+
This source package implements Agent Protocol V11 at coordinated SDK version `0.4.1`,
|
|
13
|
+
which remains unpublished. The published release remains `0.4.0` with V10. The source candidate
|
|
14
|
+
also includes the additive session-interaction API.
|
|
14
15
|
Upgrade consumers from `0.3.1` using the coordinated release and its migration guide.
|
|
15
16
|
The SDK contract version is independent of private transport and product persistence versions. This
|
|
16
17
|
is intentionally one coordinated tuple rather than a deployable mixed-version graph.
|
|
@@ -19,7 +20,7 @@ is intentionally one coordinated tuple rather than a deployable mixed-version gr
|
|
|
19
20
|
|
|
20
21
|
- `@agen-ai/agent-runtime` exports the public driver, instance, adapter, session, output,
|
|
21
22
|
readiness, account-quota port validation, bounded-evidence, artifact-candidate,
|
|
22
|
-
capability-bound interaction validation, and registry APIs.
|
|
23
|
+
capability-bound interaction validation, session-lifetime interaction and cleanup APIs, and registry APIs.
|
|
23
24
|
- `@agen-ai/agent-runtime/environment` exports the instance discovery and session observation ports.
|
|
24
25
|
- `@agen-ai/agent-runtime/testing` exports the deterministic fake provider and reusable
|
|
25
26
|
conformance runner.
|
|
@@ -29,7 +30,8 @@ is intentionally one coordinated tuple rather than a deployable mixed-version gr
|
|
|
29
30
|
1. Define an `AgentProviderDriver` with `defineAgentProviderDriver`.
|
|
30
31
|
2. Give caller-owned instance definitions to `createAgentProviderRegistry`.
|
|
31
32
|
3. Select a materialized instance by opaque `instanceId`.
|
|
32
|
-
4. Create, resume, or branch a provider session through its adapter.
|
|
33
|
+
4. Create, resume, or branch a provider session through its adapter. If supported and needed,
|
|
34
|
+
supply the session-interaction handler on that opening input before calling the adapter.
|
|
33
35
|
5. Call `startTurn` and consume its single `outputs` stream incrementally. Submit human answers with
|
|
34
36
|
the same execution's `resolveRequest`, which returns an independent delivery receipt. Neutral `AgentEvent`
|
|
35
37
|
output carries bounded provider source evidence atomically. A `request.opened` output may also
|
|
@@ -73,8 +75,19 @@ Explicit iterator return and normal end join native cleanup for at most 1,000 ms
|
|
|
73
75
|
Approval continuations are refusal-first. Before delegating to the candidate adapter, the
|
|
74
76
|
validated session proves that the request is still pending and unexpired and that a selected
|
|
75
77
|
`optionId` was offered by that exact request. Provider-emitted approval requests must correlate to
|
|
76
|
-
a live item or exact proposed-plan artifact
|
|
77
|
-
persistence/scope mode
|
|
78
|
+
a live item or exact proposed-plan artifact. A scoped consequence must fit an exact advertised
|
|
79
|
+
persistence/scope mode; a provider-managed remembrance consequence requires
|
|
80
|
+
`providerManagedRemembrance: true` and retains explicit unknown duration and applicability.
|
|
81
|
+
A delivered answer does not prove that a provider wrote a remembered rule. Exact offered IDs,
|
|
82
|
+
once-only response entry, and uncertain-delivery fencing remain unchanged.
|
|
83
|
+
Present every offered option's decision and consequence, then return the exact option chosen by
|
|
84
|
+
the caller; options with the same immediate decision can have different consequences. A human
|
|
85
|
+
handler should run independently while the original `execution.outputs` reader keeps consuming
|
|
86
|
+
progress. Resolve on that same execution, inspect its receipt, and retain its output and cleanup
|
|
87
|
+
owners through terminal settlement. A remembered answer creates no SDK rule or future automatic
|
|
88
|
+
answer; later requests still need their own offered choice. An uncertain answer must not be replayed.
|
|
89
|
+
|
|
90
|
+
Item identities are monotonic throughout a turn, including every request
|
|
78
91
|
continuation: an adapter cannot restart an observed identity, change its kind, erase prior progress
|
|
79
92
|
through an unknown-status update, regress it from in-progress to pending, or revive it after a
|
|
80
93
|
terminal event or status. An `item.completed` event must carry `completed`, `failed`, or `canceled`
|
|
@@ -184,6 +197,100 @@ identity, declared bounds, forward-only lifecycle transitions, and per-output ba
|
|
|
184
197
|
the operation result may settle. Collaboration and generated-resource observations retain the
|
|
185
198
|
same correlation and lifecycle validation at their respective ports.
|
|
186
199
|
|
|
200
|
+
## Session-lifetime interactions
|
|
201
|
+
|
|
202
|
+
An adapter can offer a decision outside any model turn through `sessionInteractions`.
|
|
203
|
+
Its support declaration is separate from V11 turn capabilities: absence means
|
|
204
|
+
`{ kind: 'unsupported' }`; supported adapters name exact `openingOperations`, declare
|
|
205
|
+
`requestKinds: ['decision']` and require `producerOwnership: 'exclusive'`. Supplying
|
|
206
|
+
`interactions` for an unsupported opening raises `session_interactions_unsupported` before
|
|
207
|
+
delegating that opening. An adapter's create support does not imply resume or branch support.
|
|
208
|
+
|
|
209
|
+
Install `interactions.onRequest` before opening. The callback receives a bound
|
|
210
|
+
`AgentSessionInteraction` containing the portable request, an eligibility signal, a
|
|
211
|
+
terminal promise and `respond({ choiceId, signal? })`. The handler can return immediately
|
|
212
|
+
after handing the capability to an owned UI, or return the promise for its work. Opening
|
|
213
|
+
may return while the decision remains pending; questions can also arrive after return.
|
|
214
|
+
Do not block session creation waiting for every human decision or route these decisions
|
|
215
|
+
through `startTurn`, `AgentEvent`, or an execution's `resolveRequest`.
|
|
216
|
+
|
|
217
|
+
For an already selected `adapter`, host-owned `openingInput` and UI-owned map, register early:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import type { AgentProviderCreateSessionInput, AgentSessionInteraction } from '@agen-ai/agent-runtime';
|
|
221
|
+
|
|
222
|
+
const pending = new Map<string, AgentSessionInteraction>();
|
|
223
|
+
const input: AgentProviderCreateSessionInput = {
|
|
224
|
+
...openingInput,
|
|
225
|
+
interactions: {
|
|
226
|
+
onRequest(interaction) {
|
|
227
|
+
pending.set(interaction.request.requestId, interaction);
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
const session = await adapter.createSession(input);
|
|
232
|
+
// Present the request target and every choice consequence before selecting a choice.
|
|
233
|
+
// Answer using that retained interaction's respond({ choiceId }) capability.
|
|
234
|
+
// The UI retires terminal entries and observes interaction.signal.
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
The complete public [lifecycle example](../../examples/lifecycle-interactions.ts) uses a
|
|
238
|
+
consumer-owned adapter, opens with a pending decision, selects a synthetic decline and joins
|
|
239
|
+
cleanup without a model turn. It needs only the core protocol/runtime dependency closure.
|
|
240
|
+
For an ordinary noninteractive opening, omit `interactions` from the input. The runtime
|
|
241
|
+
does not install an automatic answer policy; a provider requiring a handler must reject that
|
|
242
|
+
opening. Keep authentication and interactive materialization in their existing owners.
|
|
243
|
+
|
|
244
|
+
`respond` validates the choice against this exact request and allows one active response:
|
|
245
|
+
|
|
246
|
+
| Receipt | Meaning |
|
|
247
|
+
| --- | --- |
|
|
248
|
+
| `delivered` | The provider-owned handler accepted the exact choice. The interaction becomes `answered`; this does not prove a wire write, native consumption, effect completion or persistent storage. |
|
|
249
|
+
| `rejected` with `requestState: 'pending'` | Definitive refusal preserves this request's eligibility. A second response while one is active also receives pending refusal; it cannot start overlapping native delivery. |
|
|
250
|
+
| `rejected` with `requestState: 'unavailable'` | The request has retired and the capability cannot answer it again. |
|
|
251
|
+
| `delivery_uncertain` | Entered delivery did not establish acceptance or refusal. The session is fenced against further mutation; close it without replaying the choice. |
|
|
252
|
+
|
|
253
|
+
Malformed choices and pre-aborted response inputs preserve their original errors before provider
|
|
254
|
+
entry. An entered response that throws or exceeds its response deadline returns uncertainty,
|
|
255
|
+
even if the provider later settles. Closing or aborting does not make an entered answer safe
|
|
256
|
+
to repeat. Successful cleanup never resolves that uncertainty or authorizes replay.
|
|
257
|
+
|
|
258
|
+
Terminal variants are `answered`, `rejected`, `delivery_uncertain`, `withdrawn`, `expired`,
|
|
259
|
+
`session_closed`, and `failed`. `interaction.signal` controls answer eligibility and UI
|
|
260
|
+
presentation; terminal settlement records the decision lifecycle. Neither means the native
|
|
261
|
+
producer, entered response or callback has stopped. Close first fences admission and starts
|
|
262
|
+
native shutdown, then joins the actual response, terminal and callback work. A callback that
|
|
263
|
+
ignores abort remains owned. Request expiry or handler failure fails the interaction owner;
|
|
264
|
+
cleanup and its original failure remain observable through the owning session.
|
|
265
|
+
|
|
266
|
+
The runtime validates integer overrides once on the opening context:
|
|
267
|
+
|
|
268
|
+
| Limit | Default | Allowed override |
|
|
269
|
+
| --- | --- | --- |
|
|
270
|
+
| `maxRetainedRequests` | 8 | 1 to 32 |
|
|
271
|
+
| `maxRetainedBytes` | 524,288 bytes | 65,536 to 2,097,152 bytes |
|
|
272
|
+
| `requestTimeoutMs` | 300,000 ms | 1,000 to 1,800,000 ms |
|
|
273
|
+
| `responseTimeoutMs` | 30,000 ms | 1,000 to 120,000 ms |
|
|
274
|
+
| `cleanupTimeoutMs` | 30,000 ms | 1,000 to 120,000 ms |
|
|
275
|
+
|
|
276
|
+
Request eligibility uses the earlier provider expiry or runtime request deadline. Retained
|
|
277
|
+
capacity includes terminal requests whose native terminal, response or callback has not drained.
|
|
278
|
+
Unknown fields, fractional values and values outside the bounds reject the opening context.
|
|
279
|
+
The opening signal applies until the session is adopted; later cancellation belongs to the
|
|
280
|
+
returned session or a specific response rather than the completed opening call.
|
|
281
|
+
|
|
282
|
+
If an opening fails with incomplete cleanup, use
|
|
283
|
+
`isAgentProviderSessionCleanupErrorFor(error, openingInput)` with the exact input object
|
|
284
|
+
passed to the adapter, such as `input` above.
|
|
285
|
+
Retain that `AgentProviderSessionCleanupError` and its bound `retryCleanup()`; keep the
|
|
286
|
+
registry, instance, host resources and installation references owned until it succeeds.
|
|
287
|
+
A returned session with failed close likewise retains cleanup through the session and any
|
|
288
|
+
returned cleanup error. An observation timeout does not detach the actual work. Retry joins
|
|
289
|
+
the same owner and never opens another session or resends a choice. Serialized errors and
|
|
290
|
+
request IDs cannot restore callable cleanup or response authority. Adapter authors use
|
|
291
|
+
`createAgentProviderSessionCleanupError({ openingInput, providerKey, errors, retryCleanup })`
|
|
292
|
+
to preserve a failed opening's exact cleanup owner.
|
|
293
|
+
|
|
187
294
|
## Session-local host tools and instructions
|
|
188
295
|
|
|
189
296
|
A host can pass an optional `AgentSessionHostBinding` when creating, resuming or branching a
|
|
@@ -343,12 +450,13 @@ turn/request ordering, request resolution, steering, interruption, configuration
|
|
|
343
450
|
close, and idempotent disposal. Unsupported operations must remain explicit discriminants and
|
|
344
451
|
must not expose handlers.
|
|
345
452
|
|
|
346
|
-
The coordinated SDK version is `0.4.
|
|
453
|
+
The coordinated source SDK version is `0.4.1`, remains unpublished and implements Agent Protocol V11.
|
|
454
|
+
The published coordinated release remains `0.4.0` with V10.
|
|
347
455
|
The earlier public `0.3.0` and `0.3.1` releases implemented V9 and remain historical.
|
|
348
456
|
Keep installed packages in the seven-package SDK release family on the coordinated version; the
|
|
349
457
|
orchestration and ACP packages remain optional. Every materialized instance requires `environment` and
|
|
350
458
|
`accountQuota`; every session requires `environment`. The former standalone `integrations`
|
|
351
|
-
observation port is removed. The public runtime implements Agent Protocol
|
|
459
|
+
observation port is removed. The public runtime implements Agent Protocol V11 with one current
|
|
352
460
|
adapter/session surface. Package versions remain independent of private transport and product
|
|
353
461
|
persistence versions.
|
|
354
462
|
|
|
@@ -16,6 +16,8 @@ import { containsAgentControlCharacter } from "./internal/controlCharacters.js";
|
|
|
16
16
|
import { withAgentSessionHostBinding } from "./hostBindings/lifetime.js";
|
|
17
17
|
import { invokeAgentSessionOpening } from "./hostBindings/opening.js";
|
|
18
18
|
import { validateAgentSessionHostBindingSupport } from "./hostBindings/validation.js";
|
|
19
|
+
import { createSessionInteractionOwner } from "./sessionInteractions/lifetime.js";
|
|
20
|
+
import { validateSessionInteractionSupport } from "./sessionInteractions/validation.js";
|
|
19
21
|
import {
|
|
20
22
|
validateAgentProviderOperationResult,
|
|
21
23
|
validateAgentProviderOutputForContext
|
|
@@ -62,6 +64,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
62
64
|
);
|
|
63
65
|
}
|
|
64
66
|
const declaredResumption = adapter.resumption;
|
|
67
|
+
const sessionInteractions = validateSessionInteractionSupport(capabilities, adapter);
|
|
65
68
|
let hostBinding;
|
|
66
69
|
try {
|
|
67
70
|
hostBinding = validateAgentSessionHostBindingSupport(adapter.hostBinding);
|
|
@@ -98,10 +101,19 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
98
101
|
resumeInput.workingDirectory
|
|
99
102
|
);
|
|
100
103
|
const binding = parsed.binding;
|
|
104
|
+
const interactions = createSessionInteractionOwner({
|
|
105
|
+
providerKey: capabilities.providerKey,
|
|
106
|
+
sessionId: parsed.sessionId,
|
|
107
|
+
operation: "resume",
|
|
108
|
+
support: sessionInteractions,
|
|
109
|
+
...resumeInput.interactions === void 0 ? {} : { context: resumeInput.interactions },
|
|
110
|
+
...resumeInput.signal === void 0 ? {} : { signal: resumeInput.signal }
|
|
111
|
+
});
|
|
101
112
|
const candidate = await invokeAgentSessionOpening({
|
|
102
113
|
providerKey: capabilities.providerKey,
|
|
103
114
|
openingInput: resumeInput,
|
|
104
115
|
lease,
|
|
116
|
+
...interactions === void 0 ? {} : { interactions },
|
|
105
117
|
open: (context) => declaredResumption.resumeSession(context),
|
|
106
118
|
candidateInput: {
|
|
107
119
|
sessionId: parsed.sessionId,
|
|
@@ -109,23 +121,28 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
109
121
|
binding,
|
|
110
122
|
configuration: parsed.configuration,
|
|
111
123
|
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
112
|
-
...
|
|
124
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
125
|
+
...(interactions?.openingSignal ?? resumeInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? resumeInput.signal }
|
|
113
126
|
}
|
|
114
127
|
});
|
|
115
128
|
try {
|
|
116
|
-
|
|
129
|
+
const session = validateAgentProviderSession({
|
|
117
130
|
capabilities,
|
|
118
131
|
sessionId: parsed.sessionId,
|
|
119
132
|
candidate,
|
|
120
133
|
expectedBinding: binding,
|
|
134
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
121
135
|
...lease === void 0 ? {} : { hostBindingLease: lease }
|
|
122
136
|
});
|
|
137
|
+
interactions?.adopt();
|
|
138
|
+
return session;
|
|
123
139
|
} catch (error) {
|
|
124
140
|
return closeRejectedAgentProviderSession(
|
|
125
141
|
candidate,
|
|
126
142
|
error,
|
|
127
143
|
lease === void 0 ? void 0 : { providerKey: capabilities.providerKey, lease },
|
|
128
|
-
{ providerKey: capabilities.providerKey, input: resumeInput }
|
|
144
|
+
{ providerKey: capabilities.providerKey, input: resumeInput },
|
|
145
|
+
interactions
|
|
129
146
|
);
|
|
130
147
|
}
|
|
131
148
|
}
|
|
@@ -158,17 +175,27 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
158
175
|
branchInput.workingDirectory
|
|
159
176
|
);
|
|
160
177
|
const sourceBinding = parsed.source.binding;
|
|
178
|
+
const interactions = createSessionInteractionOwner({
|
|
179
|
+
providerKey: capabilities.providerKey,
|
|
180
|
+
sessionId: parsed.sessionId,
|
|
181
|
+
operation: "branch",
|
|
182
|
+
support: sessionInteractions,
|
|
183
|
+
...branchInput.interactions === void 0 ? {} : { context: branchInput.interactions },
|
|
184
|
+
...branchInput.signal === void 0 ? {} : { signal: branchInput.signal }
|
|
185
|
+
});
|
|
161
186
|
return openIdentityCreatingAgentProviderSession({
|
|
162
187
|
capabilities,
|
|
163
188
|
sessionId: parsed.sessionId,
|
|
164
189
|
observer: branchInput.onBindingCreated,
|
|
165
190
|
sourceBinding,
|
|
166
191
|
openingInput: branchInput,
|
|
192
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
167
193
|
...lease === void 0 ? {} : { hostBindingLease: lease },
|
|
168
194
|
open: (observer) => invokeAgentSessionOpening({
|
|
169
195
|
providerKey: capabilities.providerKey,
|
|
170
196
|
openingInput: branchInput,
|
|
171
197
|
lease,
|
|
198
|
+
...interactions === void 0 ? {} : { interactions },
|
|
172
199
|
open: (context) => declaredBranching.branchSession(context),
|
|
173
200
|
candidateInput: {
|
|
174
201
|
sessionId: parsed.sessionId,
|
|
@@ -177,7 +204,8 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
177
204
|
configuration: parsed.configuration,
|
|
178
205
|
onBindingCreated: observer,
|
|
179
206
|
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
180
|
-
...
|
|
207
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
208
|
+
...(interactions?.openingSignal ?? branchInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? branchInput.signal }
|
|
181
209
|
}
|
|
182
210
|
})
|
|
183
211
|
});
|
|
@@ -255,6 +283,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
255
283
|
});
|
|
256
284
|
const validated = Object.freeze({
|
|
257
285
|
hostBinding,
|
|
286
|
+
sessionInteractions,
|
|
258
287
|
createSession: async (createInput) => withAgentSessionHostBinding({
|
|
259
288
|
providerKey: capabilities.providerKey,
|
|
260
289
|
binding: createInput.hostBinding,
|
|
@@ -274,16 +303,26 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
274
303
|
const workingDirectory = parseWorkingDirectory(
|
|
275
304
|
createInput.workingDirectory
|
|
276
305
|
);
|
|
306
|
+
const interactions = createSessionInteractionOwner({
|
|
307
|
+
providerKey: capabilities.providerKey,
|
|
308
|
+
sessionId: parsed.sessionId,
|
|
309
|
+
operation: "create",
|
|
310
|
+
support: sessionInteractions,
|
|
311
|
+
...createInput.interactions === void 0 ? {} : { context: createInput.interactions },
|
|
312
|
+
...createInput.signal === void 0 ? {} : { signal: createInput.signal }
|
|
313
|
+
});
|
|
277
314
|
return openIdentityCreatingAgentProviderSession({
|
|
278
315
|
capabilities,
|
|
279
316
|
sessionId: parsed.sessionId,
|
|
280
317
|
observer: createInput.onBindingCreated,
|
|
281
318
|
openingInput: createInput,
|
|
319
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
282
320
|
...lease === void 0 ? {} : { hostBindingLease: lease },
|
|
283
321
|
open: (observer) => invokeAgentSessionOpening({
|
|
284
322
|
providerKey: capabilities.providerKey,
|
|
285
323
|
openingInput: createInput,
|
|
286
324
|
lease,
|
|
325
|
+
...interactions === void 0 ? {} : { interactions },
|
|
287
326
|
open: (context) => adapter.createSession(context),
|
|
288
327
|
candidateInput: {
|
|
289
328
|
sessionId: parsed.sessionId,
|
|
@@ -291,7 +330,8 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
291
330
|
configuration: parsed.configuration,
|
|
292
331
|
onBindingCreated: observer,
|
|
293
332
|
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
294
|
-
...
|
|
333
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
334
|
+
...(interactions?.openingSignal ?? createInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? createInput.signal }
|
|
295
335
|
}
|
|
296
336
|
})
|
|
297
337
|
});
|
package/dist/artifacts.js
CHANGED
package/dist/contractErrors.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { AgentProviderKey } from "@agen-ai/agent-protocol";
|
|
2
2
|
import type { MaybePromise } from "./foundation.js";
|
|
3
|
-
export declare const AGENT_PROVIDER_CONTRACT_ERROR_CODES: readonly ["capability_port_mismatch", "invalid_adapter", "invalid_session", "invalid_binding", "binding_callback_missing", "binding_callback_repeated", "binding_callback_mismatch", "resume_binding_mismatch", "branch_binding_reused", "session_closed", "session_unusable", "concurrent_turn", "active_turn_mismatch", "invalid_operation_result", "invalid_inventory", "invalid_collaboration_transition", "input_operation_mismatch", "output_session_mismatch", "output_turn_mismatch", "output_authentication_attempt_mismatch", "output_operation_mismatch", "output_collaboration_mismatch", "output_resource_mismatch", "output_capability_mismatch", "input_capability_mismatch", "invalid_turn_sequence", "request_resolution_mismatch", "configuration_key_unsupported", "configuration_value_unsupported", "request_pending", "invalid_host_binding", "host_binding_unsupported", "host_binding_reused", "host_binding_closed", "host_tool_name_conflict", "host_tool_input_invalid", "host_tool_result_invalid", "host_tool_capacity_exhausted"];
|
|
3
|
+
export declare const AGENT_PROVIDER_CONTRACT_ERROR_CODES: readonly ["capability_port_mismatch", "invalid_adapter", "invalid_session", "invalid_binding", "binding_callback_missing", "binding_callback_repeated", "binding_callback_mismatch", "resume_binding_mismatch", "branch_binding_reused", "session_closed", "session_unusable", "concurrent_turn", "active_turn_mismatch", "invalid_operation_result", "invalid_inventory", "invalid_collaboration_transition", "input_operation_mismatch", "output_session_mismatch", "output_turn_mismatch", "output_authentication_attempt_mismatch", "output_operation_mismatch", "output_collaboration_mismatch", "output_resource_mismatch", "output_capability_mismatch", "input_capability_mismatch", "invalid_turn_sequence", "request_resolution_mismatch", "configuration_key_unsupported", "configuration_value_unsupported", "request_pending", "invalid_host_binding", "host_binding_unsupported", "host_binding_reused", "host_binding_closed", "host_tool_name_conflict", "host_tool_input_invalid", "host_tool_result_invalid", "host_tool_capacity_exhausted", "invalid_session_interaction", "session_interactions_unsupported"];
|
|
4
4
|
export type AgentProviderContractErrorCode = (typeof AGENT_PROVIDER_CONTRACT_ERROR_CODES)[number];
|
|
5
5
|
export type AgentProviderDelegatedOperation = "resolve_request" | "steer_turn" | "invoke_operation" | "apply_configuration" | "spawn_collaboration" | "control_collaboration";
|
|
6
6
|
export declare class AgentProviderContractError extends Error {
|
|
7
7
|
readonly providerKey: AgentProviderKey;
|
|
8
8
|
readonly code: AgentProviderContractErrorCode;
|
|
9
|
-
constructor(providerKey: AgentProviderKey, code: AgentProviderContractErrorCode, message: string);
|
|
9
|
+
constructor(providerKey: AgentProviderKey, code: AgentProviderContractErrorCode, message: string, options?: ErrorOptions);
|
|
10
10
|
}
|
|
11
11
|
export declare class AgentProviderSessionCleanupError extends AggregateError {
|
|
12
12
|
readonly providerKey: AgentProviderKey;
|
package/dist/contractErrors.js
CHANGED
|
@@ -36,17 +36,17 @@ const AGENT_PROVIDER_CONTRACT_ERROR_CODES = [
|
|
|
36
36
|
"host_tool_name_conflict",
|
|
37
37
|
"host_tool_input_invalid",
|
|
38
38
|
"host_tool_result_invalid",
|
|
39
|
-
"host_tool_capacity_exhausted"
|
|
39
|
+
"host_tool_capacity_exhausted",
|
|
40
|
+
"invalid_session_interaction",
|
|
41
|
+
"session_interactions_unsupported"
|
|
40
42
|
];
|
|
41
43
|
class AgentProviderContractError extends Error {
|
|
42
|
-
constructor(providerKey, code, message) {
|
|
43
|
-
super(message);
|
|
44
|
+
constructor(providerKey, code, message, options) {
|
|
45
|
+
super(message, options);
|
|
44
46
|
this.providerKey = providerKey;
|
|
45
47
|
this.code = code;
|
|
46
48
|
this.name = "AgentProviderContractError";
|
|
47
49
|
}
|
|
48
|
-
providerKey;
|
|
49
|
-
code;
|
|
50
50
|
}
|
|
51
51
|
class AgentProviderSessionCleanupError extends AggregateError {
|
|
52
52
|
providerKey;
|
|
@@ -86,8 +86,6 @@ class AgentProviderDelegatedOperationError extends Error {
|
|
|
86
86
|
this.operation = operation;
|
|
87
87
|
this.name = "AgentProviderDelegatedOperationError";
|
|
88
88
|
}
|
|
89
|
-
providerKey;
|
|
90
|
-
operation;
|
|
91
89
|
providerExecution = "started";
|
|
92
90
|
}
|
|
93
91
|
function throwAgentProviderContractError(providerKey, code, message) {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { AgentProviderKey } from "@agen-ai/agent-protocol";
|
|
2
2
|
import type { MaybePromise } from "../foundation.js";
|
|
3
3
|
import type { AgentProviderSession, AgentProviderSessionContext } from "../sessions.js";
|
|
4
|
+
import type { SessionInteractionOwner } from "../sessionInteractions/lifetime.js";
|
|
4
5
|
import { type AgentHostBindingLease } from "./lifetime.js";
|
|
5
6
|
export declare function invokeAgentSessionOpening<Input extends AgentProviderSessionContext>(input: Readonly<{
|
|
6
7
|
providerKey: AgentProviderKey;
|
|
7
8
|
openingInput: object;
|
|
8
9
|
candidateInput: Input;
|
|
9
10
|
lease: AgentHostBindingLease | undefined;
|
|
11
|
+
interactions?: SessionInteractionOwner;
|
|
10
12
|
open: (context: Input) => MaybePromise<AgentProviderSession>;
|
|
11
13
|
}>): Promise<AgentProviderSession>;
|
|
12
14
|
//# sourceMappingURL=opening.d.ts.map
|
|
@@ -2,6 +2,7 @@ import { AgentProviderSessionCleanupError } from "../contractErrors.js";
|
|
|
2
2
|
import { associateAgentSessionCleanupError, isAgentProviderSessionCleanupErrorFor } from "../sessionCleanup.js";
|
|
3
3
|
import { createAgentHostBindingCleanupError } from "./lifetime.js";
|
|
4
4
|
async function invokeAgentSessionOpening(input) {
|
|
5
|
+
if (input.interactions) return invokeInteractiveSessionOpening({ ...input, interactions: input.interactions });
|
|
5
6
|
try {
|
|
6
7
|
return await input.open(input.candidateInput);
|
|
7
8
|
} catch (error) {
|
|
@@ -19,6 +20,63 @@ async function invokeAgentSessionOpening(input) {
|
|
|
19
20
|
throw associateAgentSessionCleanupError(retained, input.openingInput);
|
|
20
21
|
}
|
|
21
22
|
}
|
|
23
|
+
async function invokeInteractiveSessionOpening(input) {
|
|
24
|
+
let actual;
|
|
25
|
+
try {
|
|
26
|
+
input.interactions.requireUsable();
|
|
27
|
+
actual = Promise.resolve(input.open(input.candidateInput));
|
|
28
|
+
} catch (cause) {
|
|
29
|
+
actual = Promise.reject(cause);
|
|
30
|
+
}
|
|
31
|
+
void actual.catch(() => {
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
const candidate = await Promise.race([actual, input.interactions.failure.then((cause) => {
|
|
35
|
+
throw cause;
|
|
36
|
+
})]);
|
|
37
|
+
input.interactions.requireUsable();
|
|
38
|
+
return candidate;
|
|
39
|
+
} catch (error) {
|
|
40
|
+
input.interactions.stop();
|
|
41
|
+
input.lease?.stop();
|
|
42
|
+
let providerClosed = false;
|
|
43
|
+
let nativeCleanup;
|
|
44
|
+
let nativeCleanupRetained = false;
|
|
45
|
+
const cleanup = async () => {
|
|
46
|
+
let candidate;
|
|
47
|
+
try {
|
|
48
|
+
candidate = await actual;
|
|
49
|
+
} catch (cause) {
|
|
50
|
+
if (isAgentProviderSessionCleanupErrorFor(cause, input.candidateInput) && cause.providerKey === input.providerKey) {
|
|
51
|
+
nativeCleanup = cause;
|
|
52
|
+
if (!nativeCleanupRetained) {
|
|
53
|
+
nativeCleanupRetained = true;
|
|
54
|
+
throw cause;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (!providerClosed) {
|
|
59
|
+
if (nativeCleanup) await nativeCleanup.retryCleanup();
|
|
60
|
+
else if (candidate) await candidate.close({ reason: "contract_rejected" });
|
|
61
|
+
providerClosed = true;
|
|
62
|
+
}
|
|
63
|
+
await input.interactions.join();
|
|
64
|
+
await input.lease?.release();
|
|
65
|
+
};
|
|
66
|
+
try {
|
|
67
|
+
await input.interactions.close(cleanup, false);
|
|
68
|
+
} catch (cleanupError) {
|
|
69
|
+
const ownership = {
|
|
70
|
+
providerKey: input.providerKey,
|
|
71
|
+
errors: [error, cleanupError],
|
|
72
|
+
retryCleanup: () => input.interactions.close(cleanup, false)
|
|
73
|
+
};
|
|
74
|
+
const retained = input.lease ? createAgentHostBindingCleanupError({ ...ownership, lease: input.lease }) : new AgentProviderSessionCleanupError(ownership);
|
|
75
|
+
throw associateAgentSessionCleanupError(retained, input.openingInput);
|
|
76
|
+
}
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
22
80
|
export {
|
|
23
81
|
invokeAgentSessionOpening
|
|
24
82
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./providerDriver.js";
|
|
|
13
13
|
export * from "./providerInstanceRegistry.js";
|
|
14
14
|
export * from "./readiness.js";
|
|
15
15
|
export * from "./sessions.js";
|
|
16
|
+
export * from "./sessionInteractions/index.js";
|
|
16
17
|
export { createAgentProviderSessionCleanupError, isAgentProviderSessionCleanupErrorFor } from "./sessionCleanup.js";
|
|
17
18
|
export * from "./text.js";
|
|
18
19
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./providerDriver.js";
|
|
|
13
13
|
export * from "./providerInstanceRegistry.js";
|
|
14
14
|
export * from "./readiness.js";
|
|
15
15
|
export * from "./sessions.js";
|
|
16
|
+
export * from "./sessionInteractions/index.js";
|
|
16
17
|
import { createAgentProviderSessionCleanupError, isAgentProviderSessionCleanupErrorFor } from "./sessionCleanup.js";
|
|
17
18
|
export * from "./text.js";
|
|
18
19
|
export {
|
package/dist/outputValidation.js
CHANGED
|
@@ -56,8 +56,8 @@ function isApprovalRequestCapabilitySupported(capabilities, event) {
|
|
|
56
56
|
if (request.requestKind !== "approval") return false;
|
|
57
57
|
const capability = capabilities.requests.approval;
|
|
58
58
|
return capability.kind === "supported" && request.options.every(
|
|
59
|
-
(
|
|
60
|
-
(mode) => mode.persistence ===
|
|
59
|
+
({ consequence }) => consequence.kind === "provider_managed_remembrance" ? capability.providerManagedRemembrance : capability.modes.some(
|
|
60
|
+
(mode) => mode.persistence === consequence.persistence && mode.scopeKinds.includes(consequence.scope.kind)
|
|
61
61
|
)
|
|
62
62
|
);
|
|
63
63
|
}
|
package/dist/providerDriver.js
CHANGED
|
@@ -11,7 +11,6 @@ class AgentProviderConfigurationError extends Error {
|
|
|
11
11
|
this.providerKey = providerKey;
|
|
12
12
|
this.name = "AgentProviderConfigurationError";
|
|
13
13
|
}
|
|
14
|
-
providerKey;
|
|
15
14
|
}
|
|
16
15
|
function defineAgentProviderDriver(definition) {
|
|
17
16
|
const providerKey = parseAgentProviderKey(definition.providerKey);
|
|
@@ -213,7 +213,8 @@ async function materializeInstances(input) {
|
|
|
213
213
|
providerKey: definition.providerKey,
|
|
214
214
|
instanceId: definition.instanceId,
|
|
215
215
|
cleanupFailureInstanceIds,
|
|
216
|
-
message: error instanceof AgentProviderConfigurationError ? `Agent provider configuration is invalid for ${definition.instanceId}.` : `Agent provider instance ${definition.instanceId} could not be materialized
|
|
216
|
+
message: error instanceof AgentProviderConfigurationError ? `Agent provider configuration is invalid for ${definition.instanceId}.` : `Agent provider instance ${definition.instanceId} could not be materialized.`,
|
|
217
|
+
cause: error
|
|
217
218
|
});
|
|
218
219
|
}
|
|
219
220
|
let managed;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./types.js";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { AgentError, AgentProviderKey, AgentSessionId } from "@agen-ai/agent-protocol";
|
|
2
|
+
import type { MaybePromise } from "../foundation.js";
|
|
3
|
+
import type { AgentSessionInteractionContext, AgentSessionInteractionOpeningOperation, AgentSessionInteractionSupport, AgentSessionInteractionTerminal } from "./types.js";
|
|
4
|
+
import { SessionInteractionRequest } from "./request.js";
|
|
5
|
+
import { type ValidatedSessionInteractionContext } from "./validation.js";
|
|
6
|
+
export declare function sessionInteractionError(code: string, message: string, uncertain?: boolean): AgentError;
|
|
7
|
+
export declare function waitForInteractionWork<Result>(work: Promise<Result>, timeoutMs: number): Promise<Result>;
|
|
8
|
+
export declare class SessionInteractionOwner {
|
|
9
|
+
readonly providerKey: AgentProviderKey;
|
|
10
|
+
readonly sessionId: AgentSessionId;
|
|
11
|
+
readonly facade: AgentSessionInteractionContext;
|
|
12
|
+
readonly openingSignal: AbortSignal;
|
|
13
|
+
readonly limits: ValidatedSessionInteractionContext["limits"];
|
|
14
|
+
readonly failure: Promise<unknown>;
|
|
15
|
+
private readonly controller;
|
|
16
|
+
private readonly requests;
|
|
17
|
+
private readonly work;
|
|
18
|
+
private state;
|
|
19
|
+
private retainedBytes;
|
|
20
|
+
private fatal;
|
|
21
|
+
private fenceCause;
|
|
22
|
+
private resolveFailure;
|
|
23
|
+
private removeOpeningAbort;
|
|
24
|
+
private automaticClose;
|
|
25
|
+
private cleanupAttempt;
|
|
26
|
+
private cleanupDeadline;
|
|
27
|
+
private cleanupComplete;
|
|
28
|
+
private cleanupFailure;
|
|
29
|
+
private adopted;
|
|
30
|
+
private readonly context;
|
|
31
|
+
constructor(providerKey: AgentProviderKey, sessionId: AgentSessionId, context: AgentSessionInteractionContext, signal?: AbortSignal);
|
|
32
|
+
track<Result>(promise: Promise<Result>): Promise<Result>;
|
|
33
|
+
get accepting(): boolean;
|
|
34
|
+
requireUsable(): void;
|
|
35
|
+
private offer;
|
|
36
|
+
installClose(close: () => Promise<void>): void;
|
|
37
|
+
adopt(): void;
|
|
38
|
+
fence(cause: unknown, source: SessionInteractionRequest): void;
|
|
39
|
+
fail(cause: unknown): void;
|
|
40
|
+
stop(terminal?: AgentSessionInteractionTerminal): void;
|
|
41
|
+
join(): Promise<void>;
|
|
42
|
+
close(cleanup: () => MaybePromise<void>, explicit: boolean): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
export declare function createSessionInteractionOwner(input: Readonly<{
|
|
45
|
+
providerKey: AgentProviderKey;
|
|
46
|
+
sessionId: AgentSessionId;
|
|
47
|
+
operation: AgentSessionInteractionOpeningOperation;
|
|
48
|
+
support: AgentSessionInteractionSupport;
|
|
49
|
+
context?: AgentSessionInteractionContext;
|
|
50
|
+
signal?: AbortSignal;
|
|
51
|
+
}>): SessionInteractionOwner | undefined;
|
|
52
|
+
//# sourceMappingURL=lifetime.d.ts.map
|