@agen-ai/agent-runtime 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -71
- package/dist/adapterValidation.d.ts +4 -2
- package/dist/adapterValidation.js +108 -59
- package/dist/contractErrors.d.ts +1 -1
- package/dist/contractErrors.js +7 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/nativeContinuations/admission.d.ts +17 -0
- package/dist/nativeContinuations/admission.js +250 -0
- package/dist/nativeContinuations/index.d.ts +2 -0
- package/dist/nativeContinuations/index.js +1 -0
- package/dist/nativeContinuations/types.d.ts +52 -0
- package/dist/nativeContinuations/types.js +0 -0
- package/dist/outputValidation.js +1 -0
- package/dist/providerCatalog.d.ts +1 -1
- package/dist/providerDriver.d.ts +4 -1
- package/dist/providerInstanceRegistry.d.ts +4 -4
- package/dist/sessionAdmission.d.ts +12 -0
- package/dist/sessionAdmission.js +54 -0
- package/dist/sessionInteractions/lifetime.d.ts +32 -3
- package/dist/sessionInteractions/lifetime.js +145 -13
- package/dist/sessionInteractions/request.d.ts +3 -2
- package/dist/sessionInteractions/request.js +98 -25
- package/dist/sessionInteractions/types.d.ts +68 -12
- package/dist/sessionInteractions/validation.d.ts +13 -9
- package/dist/sessionInteractions/validation.js +121 -60
- package/dist/sessionValidation.d.ts +78 -2
- package/dist/sessionValidation.js +213 -162
- package/dist/sessions.d.ts +33 -2
- package/dist/testing/conformance.d.ts +3 -1
- package/dist/testing/conformance.js +180 -85
- package/dist/testing/fakeProvider.js +2 -2
- package/dist/turnExecution/execution.d.ts +23 -6
- package/dist/turnExecution/execution.js +136 -32
- package/dist/turnExecution/requests.d.ts +15 -3
- package/dist/turnExecution/requests.js +93 -28
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -9,10 +9,14 @@ 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
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
This unpublished source candidate implements Agent Protocol V12 at coordinated SDK version `0.4.2`,
|
|
13
|
+
including tagged decision responses and exact turn request unavailability. Published `0.4.1`
|
|
14
|
+
retains V11 and its qualification evidence; the earlier `0.4.0` release retains V10.
|
|
15
|
+
The runtime also provides neutral session forms, plan reviews, staged native continuations and
|
|
16
|
+
explicit human-wait policies. Provider mappings require their own support and qualification.
|
|
17
|
+
Keep all installed SDK packages at the same version; the [0.4.2 migration
|
|
18
|
+
guide](../../MIGRATING-TO-0.4.2.md) covers tagged responses, continuous request output and store
|
|
19
|
+
contract changes. Generic contract proof and exact native qualification are separate boundaries.
|
|
16
20
|
The SDK contract version is independent of private transport and product persistence versions. This
|
|
17
21
|
is intentionally one coordinated tuple rather than a deployable mixed-version graph.
|
|
18
22
|
|
|
@@ -199,28 +203,35 @@ same correlation and lifecycle validation at their respective ports.
|
|
|
199
203
|
|
|
200
204
|
## Session-lifetime interactions
|
|
201
205
|
|
|
202
|
-
An adapter can offer a decision outside
|
|
203
|
-
|
|
204
|
-
`{ kind: 'unsupported' }
|
|
205
|
-
`
|
|
206
|
-
`
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
`
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
206
|
+
An adapter can offer a decision, form or plan review outside a model turn through
|
|
207
|
+
`sessionInteractions`. Support is separate from portable turn capabilities: absence means
|
|
208
|
+
`{ kind: 'unsupported' }`. Supported adapters declare exact
|
|
209
|
+
`{ openingOperation, requestKind }` mappings, `producerOwnership: 'exclusive'` and supported
|
|
210
|
+
`humanWait` modes. Create support does not imply resume or branch support. Supplying a handler
|
|
211
|
+
or policy for an unsupported mapping rejects before candidate opening.
|
|
212
|
+
|
|
213
|
+
Driver authors implement `AgentProviderAdapter` with candidate opening inputs
|
|
214
|
+
`AgentProviderCreateSessionInput`, `AgentProviderResumeSessionInput` and
|
|
215
|
+
`AgentProviderBranchSessionInput`. The runtime installs their producer facade before entering
|
|
216
|
+
that opening. Registry consumers receive `AgentValidatedProviderAdapter` in a
|
|
217
|
+
`ValidatedMaterializedAgentProviderInstance`; they use `AgentCreateSessionInput`,
|
|
218
|
+
`AgentResumeSessionInput` and `AgentBranchSessionInput`. These types separate provider offers
|
|
219
|
+
from application handlers. Revalidating an adapter retains its original candidate ownership.
|
|
220
|
+
|
|
221
|
+
Install `interactions.onRequest` before opening. The application callback receives a bound
|
|
222
|
+
`AgentSessionInteraction` containing its immutable portable request, observed deadline,
|
|
223
|
+
eligibility signal, terminal promise and `respond` capability. Narrow `request.kind` before
|
|
224
|
+
reading workspace targets, form fields or the exact plan snapshot. Responses are tagged by
|
|
225
|
+
kind and validate the offered choice and action; forms validate field answers, and plan
|
|
226
|
+
responses validate plan ID and revision. Only revision accepts required nonblank feedback.
|
|
227
|
+
|
|
228
|
+
For an already selected validated `adapter`, host-owned `openingInput` and UI-owned map:
|
|
218
229
|
|
|
219
230
|
```ts
|
|
220
|
-
import type {
|
|
231
|
+
import type { AgentCreateSessionInput, AgentSessionInteraction } from '@agen-ai/agent-runtime';
|
|
221
232
|
|
|
222
233
|
const pending = new Map<string, AgentSessionInteraction>();
|
|
223
|
-
const input:
|
|
234
|
+
const input: AgentCreateSessionInput = {
|
|
224
235
|
...openingInput,
|
|
225
236
|
interactions: {
|
|
226
237
|
onRequest(interaction) {
|
|
@@ -229,67 +240,124 @@ const input: AgentProviderCreateSessionInput = {
|
|
|
229
240
|
},
|
|
230
241
|
};
|
|
231
242
|
const session = await adapter.createSession(input);
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
//
|
|
243
|
+
// Narrow request.kind and present the actual offered choices before answering.
|
|
244
|
+
// A workspace decision uses respond({ kind: 'decision', choiceId }).
|
|
245
|
+
// Retire the UI entry when interaction.signal aborts; keep entered receipt ownership.
|
|
235
246
|
```
|
|
236
247
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
248
|
+
A handler can return after handing the capability to an owned UI, or return a promise whose
|
|
249
|
+
actual work remains tracked. Opening may return while a request remains pending. Session
|
|
250
|
+
requests do not become `AgentEvent` request outputs or execution `resolveRequest` calls.
|
|
251
|
+
The complete public [lifecycle example](../../examples/lifecycle-interactions.ts) opens with a
|
|
252
|
+
pending decision, selects a synthetic decline and joins cleanup without a model turn. It needs
|
|
253
|
+
only the core protocol/runtime dependency closure. An ordinary noninteractive opening omits
|
|
254
|
+
`interactions`; no automatic answer policy is installed. A provider requiring a handler must
|
|
255
|
+
reject that opening. Authentication retains its separate bounded owner.
|
|
243
256
|
|
|
244
|
-
`respond`
|
|
257
|
+
`respond` allows one unsettled response attempt per request:
|
|
245
258
|
|
|
246
259
|
| Receipt | Meaning |
|
|
247
260
|
| --- | --- |
|
|
248
|
-
| `delivered` | The provider-owned handler accepted the exact
|
|
249
|
-
| `rejected` with `requestState: 'pending'` | Definitive refusal
|
|
250
|
-
| `rejected` with `requestState: 'unavailable'` | The request
|
|
251
|
-
| `delivery_uncertain` | Entered delivery did not establish acceptance or refusal.
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
261
|
+
| `delivered` | The provider-owned handler accepted the exact response. This does not prove model consumption, continuation start, successful effects or persistence. |
|
|
262
|
+
| `rejected` with `requestState: 'pending'` | Definitive refusal permits a later attempt only if the request remains live. A concurrent response also receives pending refusal without entering overlapping delivery. |
|
|
263
|
+
| `rejected` with `requestState: 'unavailable'` | The request cannot be answered again. |
|
|
264
|
+
| `delivery_uncertain` | Entered delivery did not establish acceptance or refusal. Mutation is fenced; retain cleanup and do not replay the response. |
|
|
265
|
+
|
|
266
|
+
Terminals are `answered`, `rejected`, `delivery_uncertain`, `withdrawn`, `expired`,
|
|
267
|
+
`session_closed` and `failed`. `answered.response` retains accepted kind, choice and action,
|
|
268
|
+
plus plan ID/revision where applicable; it does not duplicate form values or revision feedback.
|
|
269
|
+
`expired.source` distinguishes provider expiry from host policy. A terminal ends answer
|
|
270
|
+
eligibility, independently of an entered attempt's receipt. A delivered or rejected/pending
|
|
271
|
+
receipt racing withdrawal remains unchanged and cannot restore the retired request.
|
|
272
|
+
|
|
273
|
+
Local parse and pre-abort errors remain precise before provider entry. Entered response
|
|
274
|
+
exceptions or observation timeout return uncertainty. Successful cleanup cannot establish
|
|
275
|
+
whether an uncertain answer was accepted or authorize replay. Eligibility abortion, terminal
|
|
276
|
+
settlement and promise observation are not proof that producers or callbacks have joined.
|
|
277
|
+
|
|
278
|
+
### Human waiting and retention
|
|
279
|
+
|
|
280
|
+
Omitting `humanWait`, or selecting `{ kind: 'bounded' }`, retains the finite default.
|
|
281
|
+
The only numeric human timeout is `limits.requestTimeoutMs`. An explicitly supported
|
|
282
|
+
`humanWait: { kind: 'until_withdrawn_or_closed' }` installs no SDK human timer. Supplying a
|
|
283
|
+
`requestTimeoutMs` property in that mode rejects before opening, even when it equals the
|
|
284
|
+
default. The producer facade omits that property in unbounded mode.
|
|
285
|
+
|
|
286
|
+
The descriptor's optional `expiresAt` means actual provider expiry. At validated offer time,
|
|
287
|
+
the runtime fixes `interaction.deadline` to the earlier provider expiry or bounded host policy;
|
|
288
|
+
provider expiry wins a tie. No provider expiry and no host timer yields `{ kind: 'no_deadline' }`.
|
|
289
|
+
Presentation delay and queue residence do not restart this deadline. Expiry never fabricates an
|
|
290
|
+
answer. Without independently qualified provider-local survival semantics, expiry initiates
|
|
291
|
+
owned shutdown. Exact withdrawal remains distinct from expiry or general transport failure.
|
|
267
292
|
|
|
268
293
|
| Limit | Default | Allowed override |
|
|
269
294
|
| --- | --- | --- |
|
|
270
295
|
| `maxRetainedRequests` | 8 | 1 to 32 |
|
|
271
296
|
| `maxRetainedBytes` | 524,288 bytes | 65,536 to 2,097,152 bytes |
|
|
272
|
-
| `requestTimeoutMs` | 300,000 ms | 1,000 to 1,800,000 ms |
|
|
297
|
+
| `requestTimeoutMs` in bounded mode | 300,000 ms | 1,000 to 1,800,000 ms |
|
|
273
298
|
| `responseTimeoutMs` | 30,000 ms | 1,000 to 120,000 ms |
|
|
274
299
|
| `cleanupTimeoutMs` | 30,000 ms | 1,000 to 120,000 ms |
|
|
275
300
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
301
|
+
Retained descriptor bytes include each immutable plan snapshot once. Separately bounded
|
|
302
|
+
response material remains charged to its single unsettled attempt. Terminal requests stay
|
|
303
|
+
retained until actual native terminal, response and presentation callback work drain.
|
|
304
|
+
Unknown fields, fractional values and out-of-range overrides reject. Human-wait policy does
|
|
305
|
+
not remove response, preparation, cleanup, authentication, transport or capacity bounds.
|
|
306
|
+
All turn and session request IDs share the fixed session-generation census of 4,096 IDs and
|
|
307
|
+
1 MiB of UTF-8 identity bytes; tombstones are not evicted to grant reuse.
|
|
308
|
+
|
|
309
|
+
### Native continuations
|
|
310
|
+
|
|
311
|
+
A response that can start native work uses a provider `prepared` interaction. Effect-free
|
|
312
|
+
`prepareResponse` receives the exact parsed response and runtime-owned attempt identity.
|
|
313
|
+
It returns either `no_continuation` or `native_continuation`, with once-only `dispatch` and
|
|
314
|
+
idempotent predispatch `cancel` operations. Direct interactions may only deliver responses
|
|
315
|
+
that cannot start execution. A known no-work action does not reserve an execution.
|
|
316
|
+
|
|
317
|
+
The application installs `nativeContinuations.onExecution` before opening. Exact support
|
|
318
|
+
includes the opening operation, request kind and timing; it does not imply other combinations.
|
|
319
|
+
When preparation selects a continuation, the runtime synchronously reserves the same slot
|
|
320
|
+
used by caller `startTurn`, allocates a turn identity and adopts the candidate through ordinary
|
|
321
|
+
output validation. It never creates a synthetic caller prompt or calls candidate `startTurn`.
|
|
322
|
+
|
|
323
|
+
The host must actually call `next()` on the supplied execution's sole output iterator. Merely
|
|
324
|
+
retaining the handle or acquiring an iterator is insufficient. The parked wrapper pull proves
|
|
325
|
+
reader readiness without touching the candidate iterator before dispatch. A handler may await
|
|
326
|
+
that first output: dispatch does not wait for callback fulfillment. After readiness, runtime
|
|
327
|
+
rechecks exact request, attempt, opening, deadline and slot ownership before entering dispatch.
|
|
328
|
+
Output produced during dispatch stays on that original reader.
|
|
329
|
+
|
|
330
|
+
One fixed 30-second window covers preparation and reader readiness from response claim.
|
|
331
|
+
Predispatch failure cancels and joins allocated source/callback ownership before releasing the
|
|
332
|
+
slot. Failed cleanup retains the stopped owner and its retry handle. A started execution uses
|
|
333
|
+
normal session quiescence and output cleanup. The independent continuation `outcome` reports
|
|
334
|
+
`started` or `not_started`; a delivery receipt proves neither. Missing outcome cannot free a
|
|
335
|
+
slot or rewrite a delivered receipt. One dispatch-anchored response deadline observes both
|
|
336
|
+
receipt and outcome; uncertainty fences mutation without dropping either owner.
|
|
337
|
+
|
|
338
|
+
Opening timing is explicit: `after_open_return`, `before_open_return`, or `before_binding`.
|
|
339
|
+
The opening owner exists before candidate entry and transfers atomically after exact binding
|
|
340
|
+
validation. Exceptional data awaiting binding is limited to 16 envelopes, 1 MiB and 30 seconds.
|
|
341
|
+
It cannot invent a binding or route output by working directory. Core timing support does not
|
|
342
|
+
qualify a native provider mapping; select only that provider's explicitly supported tuple.
|
|
343
|
+
|
|
344
|
+
### Close and retained cleanup
|
|
345
|
+
|
|
346
|
+
Close fences opening/session admission and starts native quiescence before joining preparation,
|
|
347
|
+
responses, output and callbacks. A callback ignoring abort remains owned. Host binding and
|
|
348
|
+
installation resources are released only after actual native cleanup and joins succeed.
|
|
349
|
+
The opening signal applies until adoption; later cancellation belongs to the returned session
|
|
350
|
+
or response owner.
|
|
351
|
+
|
|
352
|
+
If opening fails with incomplete cleanup, call
|
|
353
|
+
`isAgentProviderSessionCleanupErrorFor(error, openingInput)` with the exact original object.
|
|
354
|
+
Retain the matching `AgentProviderSessionCleanupError` and its bound `retryCleanup()`; keep
|
|
355
|
+
registry, instance, host resources and installation references until it succeeds. A returned
|
|
356
|
+
session with failed close likewise retains cleanup through that session and its cleanup error.
|
|
357
|
+
An observation timeout cannot detach actual work. Retry joins the same owner without opening
|
|
358
|
+
another session or resending a response. Serialized errors and request IDs cannot restore
|
|
359
|
+
callable cleanup or response authority. Adapter authors preserve failed opening ownership with
|
|
360
|
+
`createAgentProviderSessionCleanupError({ openingInput, providerKey, errors, retryCleanup })`.
|
|
293
361
|
|
|
294
362
|
## Session-local host tools and instructions
|
|
295
363
|
|
|
@@ -450,8 +518,23 @@ turn/request ordering, request resolution, steering, interruption, configuration
|
|
|
450
518
|
close, and idempotent disposal. Unsupported operations must remain explicit discriminants and
|
|
451
519
|
must not expose handlers.
|
|
452
520
|
|
|
453
|
-
|
|
454
|
-
|
|
521
|
+
`resolutionFor(request, { signal })` accepts the existing synchronous resolution callback,
|
|
522
|
+
an asynchronous callback, or `undefined` to deliberately leave a request unanswered. Its
|
|
523
|
+
request-scoped signal aborts when the original output stream reports that exact request
|
|
524
|
+
unavailable, when the turn completes, or when conformance cleanup begins. Honor the signal
|
|
525
|
+
to dismiss pending human input; do not fabricate a denial or retry an answer after retirement.
|
|
526
|
+
The runner continuously reads the same execution while callbacks and delivery receipts are
|
|
527
|
+
pending. A returned answer is checked against the exact offered request before delivery.
|
|
528
|
+
`request_resolution` appears in the report only after a delivered receipt;
|
|
529
|
+
`request_unavailability` records consumption of a native retirement event. Opening a request
|
|
530
|
+
alone proves neither. The runner checks session controls before its main turn and inspects
|
|
531
|
+
turn-produced resources after terminal output while the session remains open. It then starts session
|
|
532
|
+
close before joining its reader and actual callback tasks; failure also starts close before joins. Original
|
|
533
|
+
failures and cleanup failures remain observable. A callback that ignores cancellation
|
|
534
|
+
remains owned until its actual promise settles.
|
|
535
|
+
|
|
536
|
+
The coordinated SDK release is `0.4.1` and implements Agent Protocol V11.
|
|
537
|
+
The earlier `0.4.0` release retains V10.
|
|
455
538
|
The earlier public `0.3.0` and `0.3.1` releases implemented V9 and remain historical.
|
|
456
539
|
Keep installed packages in the seven-package SDK release family on the coordinated version; the
|
|
457
540
|
orchestration and ACP packages remain optional. Every materialized instance requires `environment` and
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type AgentCapabilities } from "@agen-ai/agent-protocol";
|
|
2
|
-
import type { AgentProviderAdapter } from "./sessions.js";
|
|
3
|
-
export declare function validateAgentProviderAdapter(
|
|
2
|
+
import type { AgentProviderAdapter, AgentValidatedProviderAdapter } from "./sessions.js";
|
|
3
|
+
export declare function validateAgentProviderAdapter(capabilities: AgentCapabilities, candidate: AgentProviderAdapter): AgentValidatedProviderAdapter;
|
|
4
|
+
export declare function validateAgentProviderAdapter(capabilities: AgentCapabilities, candidate: AgentValidatedProviderAdapter): AgentValidatedProviderAdapter;
|
|
5
|
+
export declare function validateAgentProviderAdapter(capabilities: AgentCapabilities, candidate: AgentProviderAdapter | AgentValidatedProviderAdapter): AgentValidatedProviderAdapter;
|
|
4
6
|
//# sourceMappingURL=adapterValidation.d.ts.map
|
|
@@ -17,7 +17,7 @@ import { withAgentSessionHostBinding } from "./hostBindings/lifetime.js";
|
|
|
17
17
|
import { invokeAgentSessionOpening } from "./hostBindings/opening.js";
|
|
18
18
|
import { validateAgentSessionHostBindingSupport } from "./hostBindings/validation.js";
|
|
19
19
|
import { createSessionInteractionOwner } from "./sessionInteractions/lifetime.js";
|
|
20
|
-
import { validateSessionInteractionSupport } from "./sessionInteractions/validation.js";
|
|
20
|
+
import { validateSessionInteractionSupport, validateNativeContinuationSupport } from "./sessionInteractions/validation.js";
|
|
21
21
|
import {
|
|
22
22
|
validateAgentProviderOperationResult,
|
|
23
23
|
validateAgentProviderOutputForContext
|
|
@@ -25,9 +25,13 @@ import {
|
|
|
25
25
|
import {
|
|
26
26
|
closeRejectedAgentProviderSession,
|
|
27
27
|
openIdentityCreatingAgentProviderSession,
|
|
28
|
-
validateAgentProviderSession
|
|
28
|
+
validateAgentProviderSession,
|
|
29
|
+
createAgentSessionValidationOwner
|
|
29
30
|
} from "./sessionValidation.js";
|
|
30
31
|
const validatedAdapters = /* @__PURE__ */ new WeakMap();
|
|
32
|
+
function isCandidateAdapter(adapter) {
|
|
33
|
+
return !validatedAdapters.has(adapter);
|
|
34
|
+
}
|
|
31
35
|
function parseWorkingDirectory(value) {
|
|
32
36
|
if (value.length < 1 || value.length > 4096 || !path.isAbsolute(value) || path.normalize(value) !== value || containsAgentControlCharacter(value)) {
|
|
33
37
|
throw new TypeError(
|
|
@@ -48,7 +52,15 @@ function assertAuthenticationOutputKind(providerKey, output) {
|
|
|
48
52
|
}
|
|
49
53
|
function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
50
54
|
const capabilities = parseAgentCapabilities(capabilityInput);
|
|
51
|
-
|
|
55
|
+
if (!isCandidateAdapter(adapterInput)) return validateAgentProviderAdapter(capabilities, validatedAdapters.get(adapterInput));
|
|
56
|
+
const adapter = adapterInput;
|
|
57
|
+
const returnedOpening = (promise, opening) => {
|
|
58
|
+
void promise.then(() => {
|
|
59
|
+
queueMicrotask(() => opening.owner?.markReturned());
|
|
60
|
+
}, () => {
|
|
61
|
+
});
|
|
62
|
+
return promise;
|
|
63
|
+
};
|
|
52
64
|
if (adapter === null || typeof adapter !== "object" || typeof adapter.createSession !== "function" || adapter.resumption === null || typeof adapter.resumption !== "object" || !["supported", "unsupported"].includes(adapter.resumption.kind) || adapter.resumption.kind === "supported" && typeof adapter.resumption.resumeSession !== "function" || adapter.branching === null || typeof adapter.branching !== "object" || !["through_turn", "unsupported"].includes(adapter.branching.kind) || adapter.branching.kind === "through_turn" && typeof adapter.branching.branchSession !== "function" || adapter.authentication === null || typeof adapter.authentication !== "object" || !["supported", "unsupported"].includes(adapter.authentication.kind) || adapter.authentication.kind === "supported" && (typeof adapter.authentication.start !== "function" || typeof adapter.authentication.cancel !== "function")) {
|
|
53
65
|
throwAgentProviderContractError(
|
|
54
66
|
capabilities.providerKey,
|
|
@@ -65,6 +77,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
65
77
|
}
|
|
66
78
|
const declaredResumption = adapter.resumption;
|
|
67
79
|
const sessionInteractions = validateSessionInteractionSupport(capabilities, adapter);
|
|
80
|
+
const nativeContinuations = validateNativeContinuationSupport(capabilities, adapter, sessionInteractions);
|
|
68
81
|
let hostBinding;
|
|
69
82
|
try {
|
|
70
83
|
hostBinding = validateAgentSessionHostBindingSupport(adapter.hostBinding);
|
|
@@ -77,7 +90,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
77
90
|
}
|
|
78
91
|
const resumption = declaredResumption.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
79
92
|
kind: "supported",
|
|
80
|
-
resumeSession: async (resumeInput) => withAgentSessionHostBinding({
|
|
93
|
+
resumeSession: async (resumeInput, invocation = {}) => withAgentSessionHostBinding({
|
|
81
94
|
providerKey: capabilities.providerKey,
|
|
82
95
|
binding: resumeInput.hostBinding,
|
|
83
96
|
openingInput: resumeInput,
|
|
@@ -101,14 +114,20 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
101
114
|
resumeInput.workingDirectory
|
|
102
115
|
);
|
|
103
116
|
const binding = parsed.binding;
|
|
117
|
+
const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId);
|
|
104
118
|
const interactions = createSessionInteractionOwner({
|
|
105
119
|
providerKey: capabilities.providerKey,
|
|
106
120
|
sessionId: parsed.sessionId,
|
|
107
121
|
operation: "resume",
|
|
108
122
|
support: sessionInteractions,
|
|
123
|
+
nativeSupport: nativeContinuations,
|
|
124
|
+
validationOwner,
|
|
125
|
+
...resumeInput.nativeContinuations === void 0 ? {} : { continuations: resumeInput.nativeContinuations },
|
|
109
126
|
...resumeInput.interactions === void 0 ? {} : { context: resumeInput.interactions },
|
|
110
127
|
...resumeInput.signal === void 0 ? {} : { signal: resumeInput.signal }
|
|
111
128
|
});
|
|
129
|
+
if (interactions) invocation.owner = interactions;
|
|
130
|
+
interactions?.bind();
|
|
112
131
|
const candidate = await invokeAgentSessionOpening({
|
|
113
132
|
providerKey: capabilities.providerKey,
|
|
114
133
|
openingInput: resumeInput,
|
|
@@ -128,6 +147,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
128
147
|
try {
|
|
129
148
|
const session = validateAgentProviderSession({
|
|
130
149
|
capabilities,
|
|
150
|
+
validationOwner,
|
|
131
151
|
sessionId: parsed.sessionId,
|
|
132
152
|
candidate,
|
|
133
153
|
expectedBinding: binding,
|
|
@@ -151,7 +171,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
151
171
|
const declaredBranching = adapter.branching;
|
|
152
172
|
const branching = declaredBranching.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
153
173
|
kind: "through_turn",
|
|
154
|
-
branchSession: async (branchInput) => withAgentSessionHostBinding({
|
|
174
|
+
branchSession: async (branchInput, invocation = {}) => withAgentSessionHostBinding({
|
|
155
175
|
providerKey: capabilities.providerKey,
|
|
156
176
|
binding: branchInput.hostBinding,
|
|
157
177
|
openingInput: branchInput,
|
|
@@ -175,16 +195,22 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
175
195
|
branchInput.workingDirectory
|
|
176
196
|
);
|
|
177
197
|
const sourceBinding = parsed.source.binding;
|
|
198
|
+
const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId);
|
|
178
199
|
const interactions = createSessionInteractionOwner({
|
|
179
200
|
providerKey: capabilities.providerKey,
|
|
180
201
|
sessionId: parsed.sessionId,
|
|
181
202
|
operation: "branch",
|
|
182
203
|
support: sessionInteractions,
|
|
204
|
+
nativeSupport: nativeContinuations,
|
|
205
|
+
validationOwner,
|
|
206
|
+
...branchInput.nativeContinuations === void 0 ? {} : { continuations: branchInput.nativeContinuations },
|
|
183
207
|
...branchInput.interactions === void 0 ? {} : { context: branchInput.interactions },
|
|
184
208
|
...branchInput.signal === void 0 ? {} : { signal: branchInput.signal }
|
|
185
209
|
});
|
|
210
|
+
if (interactions) invocation.owner = interactions;
|
|
186
211
|
return openIdentityCreatingAgentProviderSession({
|
|
187
212
|
capabilities,
|
|
213
|
+
validationOwner,
|
|
188
214
|
sessionId: parsed.sessionId,
|
|
189
215
|
observer: branchInput.onBindingCreated,
|
|
190
216
|
sourceBinding,
|
|
@@ -281,66 +307,89 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
|
|
|
281
307
|
return result;
|
|
282
308
|
}
|
|
283
309
|
});
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
310
|
+
const createSession = async (createInput, invocation = {}) => withAgentSessionHostBinding({
|
|
311
|
+
providerKey: capabilities.providerKey,
|
|
312
|
+
binding: createInput.hostBinding,
|
|
313
|
+
openingInput: createInput,
|
|
314
|
+
support: hostBinding,
|
|
315
|
+
open: async (lease) => {
|
|
316
|
+
throwIfAgentOperationAborted(createInput.signal);
|
|
317
|
+
const parsed = parseAgentSessionOpenInput({
|
|
318
|
+
operation: "create",
|
|
319
|
+
sessionId: createInput.sessionId,
|
|
320
|
+
configuration: createInput.configuration
|
|
321
|
+
});
|
|
322
|
+
assertAgentSessionConfigurationSupported(
|
|
323
|
+
capabilities,
|
|
324
|
+
parsed.configuration
|
|
325
|
+
);
|
|
326
|
+
const workingDirectory = parseWorkingDirectory(
|
|
327
|
+
createInput.workingDirectory
|
|
328
|
+
);
|
|
329
|
+
const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId);
|
|
330
|
+
const interactions = createSessionInteractionOwner({
|
|
331
|
+
providerKey: capabilities.providerKey,
|
|
332
|
+
sessionId: parsed.sessionId,
|
|
333
|
+
operation: "create",
|
|
334
|
+
support: sessionInteractions,
|
|
335
|
+
nativeSupport: nativeContinuations,
|
|
336
|
+
validationOwner,
|
|
337
|
+
...createInput.nativeContinuations === void 0 ? {} : { continuations: createInput.nativeContinuations },
|
|
338
|
+
...createInput.interactions === void 0 ? {} : { context: createInput.interactions },
|
|
339
|
+
...createInput.signal === void 0 ? {} : { signal: createInput.signal }
|
|
340
|
+
});
|
|
341
|
+
if (interactions) invocation.owner = interactions;
|
|
342
|
+
return openIdentityCreatingAgentProviderSession({
|
|
343
|
+
capabilities,
|
|
344
|
+
validationOwner,
|
|
345
|
+
sessionId: parsed.sessionId,
|
|
346
|
+
observer: createInput.onBindingCreated,
|
|
347
|
+
openingInput: createInput,
|
|
348
|
+
...interactions === void 0 ? {} : { sessionInteractionOwner: interactions },
|
|
349
|
+
...lease === void 0 ? {} : { hostBindingLease: lease },
|
|
350
|
+
open: (observer) => invokeAgentSessionOpening({
|
|
307
351
|
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
|
-
});
|
|
314
|
-
return openIdentityCreatingAgentProviderSession({
|
|
315
|
-
capabilities,
|
|
316
|
-
sessionId: parsed.sessionId,
|
|
317
|
-
observer: createInput.onBindingCreated,
|
|
318
352
|
openingInput: createInput,
|
|
319
|
-
|
|
320
|
-
...
|
|
321
|
-
open: (
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
353
|
+
lease,
|
|
354
|
+
...interactions === void 0 ? {} : { interactions },
|
|
355
|
+
open: (context) => adapter.createSession(context),
|
|
356
|
+
candidateInput: {
|
|
357
|
+
sessionId: parsed.sessionId,
|
|
358
|
+
workingDirectory,
|
|
359
|
+
configuration: parsed.configuration,
|
|
360
|
+
onBindingCreated: observer,
|
|
361
|
+
...lease === void 0 ? {} : { hostBinding: lease.binding },
|
|
362
|
+
...interactions === void 0 ? {} : { interactions: interactions.facade },
|
|
363
|
+
...(interactions?.openingSignal ?? createInput.signal) === void 0 ? {} : { signal: interactions?.openingSignal ?? createInput.signal }
|
|
364
|
+
}
|
|
365
|
+
})
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
const openingAdapter = Object.freeze({
|
|
370
|
+
hostBinding,
|
|
371
|
+
sessionInteractions,
|
|
372
|
+
nativeContinuations,
|
|
373
|
+
createSession,
|
|
340
374
|
resumption,
|
|
341
375
|
branching,
|
|
342
376
|
authentication
|
|
343
377
|
});
|
|
378
|
+
const validated = Object.freeze({
|
|
379
|
+
...openingAdapter,
|
|
380
|
+
createSession: (input) => {
|
|
381
|
+
const invocation = {};
|
|
382
|
+
return returnedOpening(createSession(input, invocation), invocation);
|
|
383
|
+
},
|
|
384
|
+
resumption: resumption.kind === "unsupported" ? resumption : Object.freeze({ kind: "supported", resumeSession: (input) => {
|
|
385
|
+
const invocation = {};
|
|
386
|
+
return returnedOpening(resumption.resumeSession(input, invocation), invocation);
|
|
387
|
+
} }),
|
|
388
|
+
branching: branching.kind === "unsupported" ? branching : Object.freeze({ kind: "through_turn", branchSession: (input) => {
|
|
389
|
+
const invocation = {};
|
|
390
|
+
return returnedOpening(branching.branchSession(input, invocation), invocation);
|
|
391
|
+
} })
|
|
392
|
+
});
|
|
344
393
|
validatedAdapters.set(validated, adapter);
|
|
345
394
|
return validated;
|
|
346
395
|
}
|
package/dist/contractErrors.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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", "invalid_session_interaction", "session_interactions_unsupported"];
|
|
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", "request_identity_limit_exceeded", "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", "native_continuations_unsupported", "native_continuation_preparation_failed", "native_continuation_reader_not_ready", "native_continuation_limit_exceeded", "invalid_native_continuation"];
|
|
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 {
|
package/dist/contractErrors.js
CHANGED
|
@@ -26,6 +26,7 @@ const AGENT_PROVIDER_CONTRACT_ERROR_CODES = [
|
|
|
26
26
|
"input_capability_mismatch",
|
|
27
27
|
"invalid_turn_sequence",
|
|
28
28
|
"request_resolution_mismatch",
|
|
29
|
+
"request_identity_limit_exceeded",
|
|
29
30
|
"configuration_key_unsupported",
|
|
30
31
|
"configuration_value_unsupported",
|
|
31
32
|
"request_pending",
|
|
@@ -38,7 +39,12 @@ const AGENT_PROVIDER_CONTRACT_ERROR_CODES = [
|
|
|
38
39
|
"host_tool_result_invalid",
|
|
39
40
|
"host_tool_capacity_exhausted",
|
|
40
41
|
"invalid_session_interaction",
|
|
41
|
-
"session_interactions_unsupported"
|
|
42
|
+
"session_interactions_unsupported",
|
|
43
|
+
"native_continuations_unsupported",
|
|
44
|
+
"native_continuation_preparation_failed",
|
|
45
|
+
"native_continuation_reader_not_ready",
|
|
46
|
+
"native_continuation_limit_exceeded",
|
|
47
|
+
"invalid_native_continuation"
|
|
42
48
|
];
|
|
43
49
|
class AgentProviderContractError extends Error {
|
|
44
50
|
constructor(providerKey, code, message, options) {
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./providerInstanceRegistry.js";
|
|
|
14
14
|
export * from "./readiness.js";
|
|
15
15
|
export * from "./sessions.js";
|
|
16
16
|
export * from "./sessionInteractions/index.js";
|
|
17
|
+
export * from "./nativeContinuations/index.js";
|
|
17
18
|
export { createAgentProviderSessionCleanupError, isAgentProviderSessionCleanupErrorFor } from "./sessionCleanup.js";
|
|
18
19
|
export * from "./text.js";
|
|
19
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./providerInstanceRegistry.js";
|
|
|
14
14
|
export * from "./readiness.js";
|
|
15
15
|
export * from "./sessions.js";
|
|
16
16
|
export * from "./sessionInteractions/index.js";
|
|
17
|
+
export * from "./nativeContinuations/index.js";
|
|
17
18
|
import { createAgentProviderSessionCleanupError, isAgentProviderSessionCleanupErrorFor } from "./sessionCleanup.js";
|
|
18
19
|
export * from "./text.js";
|
|
19
20
|
export {
|