@agen-ai/agent-runtime 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.
Files changed (56) hide show
  1. package/README.md +297 -10
  2. package/dist/adapterValidation.js +38 -4
  3. package/dist/contractErrors.d.ts +2 -2
  4. package/dist/contractErrors.js +8 -1
  5. package/dist/executionInput/index.d.ts +3 -0
  6. package/dist/executionInput/index.js +4 -0
  7. package/dist/executionInput/lifetime.d.ts +47 -0
  8. package/dist/executionInput/lifetime.js +241 -0
  9. package/dist/executionInput/types.d.ts +61 -0
  10. package/dist/executionInput/types.js +0 -0
  11. package/dist/executionInput/validation.d.ts +25 -0
  12. package/dist/executionInput/validation.js +178 -0
  13. package/dist/generation/cleanup.d.ts +15 -0
  14. package/dist/generation/cleanup.js +108 -0
  15. package/dist/generation/deadline.d.ts +16 -0
  16. package/dist/generation/deadline.js +81 -0
  17. package/dist/generation/decoding.d.ts +4 -0
  18. package/dist/generation/decoding.js +59 -0
  19. package/dist/generation/errors.d.ts +29 -0
  20. package/dist/generation/errors.js +39 -0
  21. package/dist/generation/generateObject.d.ts +3 -0
  22. package/dist/generation/generateObject.js +148 -0
  23. package/dist/generation/index.d.ts +5 -0
  24. package/dist/generation/index.js +8 -0
  25. package/dist/generation/preflight.d.ts +25 -0
  26. package/dist/generation/preflight.js +48 -0
  27. package/dist/generation/requests.d.ts +17 -0
  28. package/dist/generation/requests.js +117 -0
  29. package/dist/generation/types.d.ts +22 -0
  30. package/dist/generation/types.js +0 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.js +7 -1
  33. package/dist/nativeContinuations/admission.js +1 -0
  34. package/dist/outputValidation.d.ts +2 -0
  35. package/dist/outputValidation.js +29 -1
  36. package/dist/sessionInteractions/lifetime.d.ts +1 -0
  37. package/dist/sessionInteractions/lifetime.js +4 -0
  38. package/dist/sessionInteractions/request.d.ts +1 -0
  39. package/dist/sessionInteractions/request.js +3 -0
  40. package/dist/sessionValidation.d.ts +13 -3
  41. package/dist/sessionValidation.js +80 -6
  42. package/dist/sessions.d.ts +7 -1
  43. package/dist/structuredOutput/admission.d.ts +16 -0
  44. package/dist/structuredOutput/admission.js +89 -0
  45. package/dist/structuredOutput/candidate.d.ts +22 -0
  46. package/dist/structuredOutput/candidate.js +64 -0
  47. package/dist/structuredOutput/validation.d.ts +8 -0
  48. package/dist/structuredOutput/validation.js +26 -0
  49. package/dist/testing/conformance.d.ts +20 -1
  50. package/dist/testing/conformance.js +103 -3
  51. package/dist/testing/fakeProvider.js +5 -4
  52. package/dist/turnExecution/execution.d.ts +9 -1
  53. package/dist/turnExecution/execution.js +88 -7
  54. package/dist/turnExecution/terminalBuffer.d.ts +9 -0
  55. package/dist/turnExecution/terminalBuffer.js +38 -0
  56. package/package.json +6 -2
package/README.md CHANGED
@@ -9,14 +9,20 @@ 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 package implements Agent Protocol V12 at coordinated SDK version `0.4.3`,
12
+ Current source implements Agent Protocol V13 in the unpublished coordinated eight-package `0.4.4`
13
+ candidate, including structured final output. Published `0.4.3` is the seven-package V12 release,
13
14
  including tagged decision responses and exact turn request unavailability. Published `0.4.1`
14
15
  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.
16
+ The runtime also provides neutral session forms, plan reviews, staged native continuations,
17
+ explicit human-wait policies and optional input during an owned execution. Provider mappings
18
+ require their own support and qualification. The candidate ships no public native provider with
19
+ execution-input support; the separately controlled private Claude diagnostic mapping does not
20
+ introduce a public Claude constructor.
17
21
  Keep all installed SDK packages at the same version; the [0.4.2 migration
18
22
  guide](../../MIGRATING-TO-0.4.2.md) covers tagged responses, continuous request output and store
19
23
  contract changes. Generic contract proof and exact native qualification are separate boundaries.
24
+ The [0.4.4 upgrade guide](../../UPGRADING-TO-0.4.4.md) covers V13 and the optional
25
+ `@agen-ai/agent-history` package, whose native conversation browsing remains independent of execution.
20
26
  The SDK contract version is independent of private transport and product persistence versions. This
21
27
  is intentionally one coordinated tuple rather than a deployable mixed-version graph.
22
28
 
@@ -25,10 +31,177 @@ is intentionally one coordinated tuple rather than a deployable mixed-version gr
25
31
  - `@agen-ai/agent-runtime` exports the public driver, instance, adapter, session, output,
26
32
  readiness, account-quota port validation, bounded-evidence, artifact-candidate,
27
33
  capability-bound interaction validation, session-lifetime interaction and cleanup APIs, and registry APIs.
34
+ It also exports `parseAgentExecutionInputMessageId` and the execution-input support, message,
35
+ port, receipt and outcome types; execution input has no separate package or entrypoint.
28
36
  - `@agen-ai/agent-runtime/environment` exports the instance discovery and session observation ports.
37
+ - `@agen-ai/agent-runtime/generation` exports `generateObject`, `AgentGenerationError`,
38
+ `AgentGenerationCleanupError`, and their input/result/error types. Generation is an explicit
39
+ entrypoint; importing the ordinary runtime does not select a provider or start work.
29
40
  - `@agen-ai/agent-runtime/testing` exports the deterministic fake provider and reusable
30
41
  conformance runner.
31
42
 
43
+ ## Generate a typed object
44
+
45
+ `generateObject` borrows an explicitly selected `ValidatedMaterializedAgentProviderInstance`,
46
+ opens a fresh native session, owns one continuous output reader and request delivery, validates
47
+ the terminal object, runs a value-preserving decoder, and closes that session before returning.
48
+ The caller retains the instance and its registry; generation never disposes them. It does not
49
+ accept an existing session or resume/branch a prior conversation. Its result contains the inferred
50
+ `value` and the caller's `sessionId` and `turnId`.
51
+
52
+ ```ts
53
+ import {
54
+ createAgentOutputDefinition,
55
+ parseAgentConfigurationRevisionId,
56
+ parseAgentSessionId,
57
+ parseAgentTurnId,
58
+ } from '@agen-ai/agent-protocol';
59
+ import type { ValidatedMaterializedAgentProviderInstance } from '@agen-ai/agent-runtime';
60
+ import { generateObject } from '@agen-ai/agent-runtime/generation';
61
+
62
+ const titleOutput = createAgentOutputDefinition({
63
+ type: 'object',
64
+ properties: { title: { type: 'string', minLength: 1, maxLength: 80 } },
65
+ required: ['title'],
66
+ additionalProperties: false,
67
+ }, (value) => typeof value.title === 'string'
68
+ ? { success: true, data: { title: value.title } }
69
+ : { success: false, issues: [{ code: 'title_required', path: ['title'], message: 'A title is required.' }] });
70
+
71
+ async function generateTitle(instance: ValidatedMaterializedAgentProviderInstance, workingDirectory: string) {
72
+ const result = await generateObject({
73
+ instance,
74
+ session: {
75
+ sessionId: parseAgentSessionId('title:conversation:42'),
76
+ workingDirectory,
77
+ configuration: { kind: 'managed', revision: parseAgentConfigurationRevisionId('title:configuration:1') },
78
+ },
79
+ turn: {
80
+ turnId: parseAgentTurnId('title:conversation:42:1'),
81
+ interactionMode: 'default',
82
+ parts: [{ type: 'text', text: 'Create a short title for a conversation about investigating payment failures.' }],
83
+ },
84
+ output: titleOutput,
85
+ timeoutMs: 30_000,
86
+ });
87
+ // The generation session and its reader are closed before this value is returned.
88
+ return result.value.title; // string, inferred from the decoder
89
+ }
90
+ ```
91
+
92
+ Choose configuration that fits the selected instance; the example uses a managed instance.
93
+ Use fresh caller-owned correlation IDs for each generation. The shipped public
94
+ [`examples/generate-title.ts`](../../examples/generate-title.ts) additionally saves the title after
95
+ successful cleanup. The application selects credentials, working-directory access and native
96
+ tool/sandbox policy. A title prompt and an output schema do not disable tools or grant permission.
97
+
98
+ For Zod authoring, use the explicit protocol adapter:
99
+
100
+ ```ts
101
+ import { z } from 'zod/v4';
102
+ import { zodOutput } from '@agen-ai/agent-protocol/zod';
103
+
104
+ const titleOutput = zodOutput(z.strictObject({ title: z.string() }));
105
+ // generateObject({ ..., output: titleOutput }) infers result.value as { title: string }.
106
+ ```
107
+
108
+ A schema-only `createAgentOutputDefinition(schema)` returns `AgentJsonObject`. A typed value needs
109
+ a real decoder or `zodOutput`; there is no unchecked `generateObject<MyType>` shortcut that omits
110
+ that evidence. Decoders validate synchronously and must preserve the generated JSON exactly. The
111
+ runtime rejects transformed/coerced values, freezes the successful JSON value, and leaves later
112
+ presentation transforms to the application. See the
113
+ [protocol profile and authoring limits](../agent-protocol/README.md#structured-final-output),
114
+ including the distinct unsupported Zod string/array length checks and their neutral-schema path.
115
+
116
+ ### Capability and schema lifetime
117
+
118
+ Generation preflights `instance.capabilities.turns.structuredOutput`. Unsupported support, wrong
119
+ scope, unsupported schema, configuration/input mismatch or excessive schema bytes fail before
120
+ native opening. A supported declaration has `mechanism: 'native'`,
121
+ `schemaProfile: 'agenai.output-schema.v1'`, `scope: 'turn' | 'session'`, bounded
122
+ `maxSchemaBytes`/`maxOutputBytes`, and `resume: false`, `branch: false`. `generateObject` supplies
123
+ the schema at the declared boundary: opening for session scope, start-turn for turn scope.
124
+ It owns `output`, `signal`, binding/start callbacks and native continuation control in those
125
+ inputs; supplying even an explicitly `undefined` reserved property is rejected.
126
+
127
+ With the lower-level API, a turn-scoped request applies only to that turn; omit `output` on the
128
+ next turn for ordinary text. A session-scoped request is an immutable opening binding inherited
129
+ by every turn. Supplying any turn `output` property, including the same schema or `undefined`,
130
+ cannot override or remove it. Steering cannot carry an `output` property. Requests to resume or
131
+ branch with structured output fail before native calls; ordinary resume/branch remain available
132
+ when separately supported. Schema-bound native continuations are not admitted. Admitted schemas
133
+ are detached frozen snapshots, so mutating the original object cannot alter running work.
134
+
135
+ Every `turn.completed` carries `payload.structuredOutput`: `not_requested`, `json` with a complete
136
+ object, or `unavailable` with a reason. Only a native `completed` outcome can contain `json`.
137
+ Native completion can still be `unavailable`, for example when output is missing or fails schema
138
+ validation. The validated runtime independently checks the terminal candidate against its exact
139
+ admitted schema and converts a well-formed mismatch into `unavailable/schema_mismatch` while
140
+ preserving the native outcome. Malformed envelopes, unsolicited output, duplicate terminals and
141
+ wrong identities remain contract failures. A stream ending without a terminal never manufactures
142
+ success. No partial JSON is exposed as a validated object, and there is no prose extraction,
143
+ model repair, automatic generation retry or provider/tool replay.
144
+
145
+ ### Deadlines, requests and cleanup
146
+
147
+ `onOutput` observes the same reader owned by the helper and applies backpressure; it must not
148
+ acquire another reader. An optional `onRequest(request, { signal })` returns an exact
149
+ `AgentRequestResolution`; the helper validates/delivers it while continuing output. Honor its
150
+ signal when a request is retired or generation stops. Without a handler, a turn request fails as
151
+ `interaction_required`; the helper never fabricates approval, denial or an answer. Any opening
152
+ session-interaction handler remains an explicit `session.interactions` choice. A generation
153
+ helper supplies no new effect authority.
154
+
155
+ | Generation bound | Value |
156
+ | --- | --- |
157
+ | Overall timeout | Five minutes by default; `timeoutMs` is a positive integer up to one hour |
158
+ | Effective execution deadline | Earlier of the overall timeout and `turn.deadlineAt`; caller abort also stops generation |
159
+ | Output observer / request handler / response delivery | 30 seconds / five minutes / 30 seconds, each still bounded by the generation deadline |
160
+ | Active request handlers | 8 retained request records; a record remains owned while its callback/delivery is pending |
161
+ | Cleanup attempt | 30 seconds, retaining actual pending work for retry |
162
+
163
+ The schema/value profile caps each at 16,384 serialized UTF-8 bytes; the provider can advertise
164
+ smaller byte limits. Other shape and raw-candidate limits belong to the
165
+ [protocol profile](../agent-protocol/README.md#the-agenaioutput-schemav1-profile).
166
+ Successful return means stream settlement, local decoding and session cleanup all succeeded.
167
+ On abort or failure, the helper initiates native interruption when applicable and session close
168
+ before joining entered reader/observer/request work. An uncooperative callback remains owned;
169
+ its timeout is not proof it stopped.
170
+
171
+ | Error | Application handling |
172
+ | --- | --- |
173
+ | `AgentGenerationError` | Inspect `code`: `unsupported`, `interaction_required`, `generation_failed`, `decoding_failed`, `observer_failed`, `request_failed`, or `timeout`. A generation failure may carry the unavailable `reason` and bounded `issues`; request failure may carry the exact delivery `receipt`. |
174
+ | `AgentProtocolValidationError` / `AgentProviderContractError` | Correct input or adapter contract faults; they retain their existing public semantics. |
175
+ | Caller cancellation | Retains the runtime's operation-abort semantics after cleanup. |
176
+ | `AgentGenerationCleanupError` | Retain the original object and borrowed instance/registry; its `retryCleanup()` owns remaining work. It may carry `primaryError` and a validated `result`, but the original call has not succeeded. |
177
+ | `AgentProviderSessionCleanupError` during opening | Retain the exact original opening receipt and its retry callback. |
178
+
179
+ ```ts
180
+ import { AgentGenerationCleanupError, AgentGenerationError } from '@agen-ai/agent-runtime/generation';
181
+ import { AgentProviderSessionCleanupError } from '@agen-ai/agent-runtime';
182
+
183
+ try {
184
+ const title = await generateTitle(instance, workingDirectory);
185
+ await saveTitle(title);
186
+ } catch (error) {
187
+ if (error instanceof AgentGenerationCleanupError || error instanceof AgentProviderSessionCleanupError) {
188
+ await error.retryCleanup(); // If it rejects, retain this same callable owner for recovery.
189
+ throw error; // Cleanup recovery does not replay generation or change the original verdict.
190
+ }
191
+ if (error instanceof AgentGenerationError && error.code === 'unsupported') {
192
+ showStructuredOutputUnavailable();
193
+ } else {
194
+ throw error;
195
+ }
196
+ }
197
+ ```
198
+
199
+ Do not serialize the error in place of retaining its callable cleanup owner or dispose dependent
200
+ resources while cleanup remains incomplete. A later application retry is a separate explicitly
201
+ chosen generation with its own effect and cost assessment. Generic ACP declares unsupported;
202
+ the public provider's exact opt-in Grok mapping and installed native qualification are described
203
+ in [`@agen-ai/provider-acp`](../provider-acp/README.md#structured-final-output).
204
+
32
205
  ## Lifecycle and ownership
33
206
 
34
207
  1. Define an `AgentProviderDriver` with `defineAgentProviderDriver`.
@@ -107,7 +280,7 @@ provider that replaces that process emits a `process.started` lifecycle output a
107
280
  boundary before reporting usage from the replacement. Validation then clears only the
108
281
  `materialization` occupancy, cumulative counters, and compaction allowance; logical `session`
109
282
  measurements remain continuous.
110
- `startTurn(input)` returns `{ turnId, outputs, resolveRequest }`. `outputs` preserves per-output
283
+ `startTurn(input)` returns `{ turnId, outputs, resolveRequest, input? }`. `outputs` preserves per-output
111
284
  backpressure and stays open during `waiting_for_request`; the consumer can call
112
285
  `execution.resolveRequest({ resolution })` as soon as it receives `request.opened`, before its next
113
286
  pull. A later queued waiting observation cannot revive an already answered request. No response
@@ -194,8 +367,8 @@ descriptor validation, through native settlement and awaited output acceptance.
194
367
  native continuations cannot overlap that reservation. Exact cached idempotent results are returned
195
368
  before reserving another execution. Close stops admission and initiates native quiescence before
196
369
  joining entered operation work; failed cleanup retains its stopped owner for retry. This lifecycle
197
- correction and operation retry observations are included in `0.4.3`, using the existing
198
- Agent Protocol V12 and operation SPI.
370
+ correction and operation retry observations were included in published `0.4.3`, using its
371
+ Agent Protocol V12 and operation SPI; current V13 source retains that behavior.
199
372
 
200
373
  Discover the operation through `session.operations` and its offered descriptor, using an exact
201
374
  application-configured ID. Pass the descriptor revision as `expectedRevision`, its exact fields,
@@ -219,6 +392,118 @@ identity, declared bounds, forward-only lifecycle transitions, and per-output ba
219
392
  the operation result may settle. Collaboration and generated-resource observations retain the
220
393
  same correlation and lifecycle validation at their respective ports.
221
394
 
395
+ ## Input during an owned execution
396
+
397
+ The unpublished `0.4.4` candidate adds optional provider-neutral input on a caller-started
398
+ execution. **No public native provider ships with support for this domain.** Public ACP,
399
+ including Grok compositions, remains unsupported. Positive native qualification belongs only to
400
+ a separately controlled private Claude SDK `0.3.309` / Code `2.1.309` diagnostic composition on
401
+ Linux x86_64 / Node `24.18.0`; there is no public Claude execution constructor. That evidence does
402
+ not qualify production/fleet execution, subscription authentication or billing. Other features'
403
+ provider selections and qualification remain independent.
404
+
405
+ An adapter optionally declares `executionInput?: AgentExecutionInputSupport`. An execution
406
+ optionally exposes `input?: AgentExecutionInput`; absence and `{ kind: 'unsupported' }` both mean
407
+ unsupported. Check `execution.input?.kind === 'supported'` before calling `sendMessage`. A supported
408
+ port must match the adapter's delivery, consumption reporting, input and limit declaration.
409
+ Legacy adapters can continue omitting the domain. Executions adopted from session human-response
410
+ native continuations expose input as unsupported even when caller-started executions support it.
411
+
412
+ The runtime root exports `parseAgentExecutionInputMessageId` and all six execution-input types:
413
+ `AgentExecutionInputMessageId`, `AgentExecutionInputMessage`, `AgentExecutionInputSupport`,
414
+ `AgentExecutionInput`, `AgentExecutionInputReceipt` and `AgentExecutionInputOutcome`.
415
+
416
+ ```ts
417
+ import {
418
+ parseAgentExecutionInputMessageId,
419
+ type AgentExecutionInputMessage,
420
+ } from '@agen-ai/agent-runtime';
421
+
422
+ const message: AgentExecutionInputMessage = {
423
+ messageId: parseAgentExecutionInputMessageId('conversation:42:requirement:2'),
424
+ parts: [{ type: 'text', text: 'Include the corrected requirement in the owned task.' }],
425
+ };
426
+ ```
427
+
428
+ Message IDs are branded separately from turn and human-request IDs. The parser accepts canonical
429
+ nonempty text up to 256 characters, without outer whitespace or control characters. Use a fresh ID
430
+ for every submission; parsing does not make the provider idempotent.
431
+
432
+ The delivery contract is `current_or_owned_continuation`: the message can be consumed in the
433
+ original native command or an additional native command owned by the same SDK execution. It keeps
434
+ one turn ID, output reader and cleanup owner. Existing `capabilities.turns.steer` /
435
+ `session.steering.steerTurn` retains strict running-native-command semantics. Do not substitute
436
+ input for steering or manufacture a fallback turn when input is unsupported.
437
+
438
+ `sendMessage({ messageId, parts, summary?, signal? })` accepts text only and returns one of:
439
+
440
+ | Receipt | Meaning |
441
+ | --- | --- |
442
+ | `accepted` | The native handler authoritatively acknowledged the exact submission. Includes `settled: Promise<AgentExecutionInputOutcome>`; does not establish consumption, compliance or completion. |
443
+ | `rejected` | Definite refusal to admit the message, with a bounded `AgentError` and no settlement promise. The original execution remains owned. |
444
+ | `delivery_uncertain` | Delivery may have started without an authoritative acknowledgement, with a bounded `AgentError`. The runtime fences further mutation while the original output reader can still drain. Never replay the message. |
445
+
446
+ An accepted receipt settles to `consumed` with its `messageId`, original SDK `turnId` and
447
+ `placement: 'original_native_command' | 'owned_native_continuation'`, or to `unconfirmed` with its
448
+ `messageId` and reason. The unconfirmed reasons are `provider_does_not_report_consumption`,
449
+ `closed`, `interrupted`, `native_failed` and `correlation_lost`; that variant has no turn ID or
450
+ placement. Only support declaring `consumptionReporting: 'message_ids'` can report `consumed`.
451
+ Support declaring `'unavailable'` may report `provider_does_not_report_consumption` instead.
452
+ An unconfirmed outcome preserves acceptance and does not prove non-consumption. Attributed
453
+ consumption still does not prove the model obeyed the instruction. These in-process receipts and
454
+ promise handles are not wire or persistence formats and grant no permission or tool authority.
455
+
456
+ Start the sole `outputs` reader before sending, then keep it running during both the receipt and
457
+ settlement waits. `startTurn` reserves the existing execution slot synchronously, but provider
458
+ entry is lazy until the first output pull. A retained handle or acquired iterator is insufficient.
459
+ Input on a reserved, idle, stale, completed or closed execution rejects before provider entry.
460
+ There is no idle-session input method; use ordinary `startTurn` when idle. A structured-output
461
+ turn or schema-bound session, a pending turn human request or its unsettled response, and a live
462
+ session interaction also reject input before native entry. Admitted continuations remain in the
463
+ same execution slot through settlement; native result frames cannot end ownership prematurely.
464
+
465
+ | Bound | SDK ceiling; a provider may declare a smaller positive limit |
466
+ | --- | --- |
467
+ | Outstanding entered/accepted messages awaiting actual settlement | 2 per execution |
468
+ | Entered messages, including definite provider rejections | 16 per execution |
469
+ | Buffered messages | 1,048,576 serialized UTF-8 bytes across message IDs, parts and summaries, excluding signals |
470
+ | Message identity retention | 4,096 IDs and 1,048,576 UTF-8 ID bytes per session generation |
471
+ | Receipt observation / input drain | 30 seconds / 30 seconds; actual entered work remains owned |
472
+
473
+ Existing turn-content validation also applies, including its 1 MiB plus 16 KiB serialized content
474
+ envelope. Execution input additionally rejects images/content references and must fit its stricter
475
+ buffered-envelope limit. After candidate entry, rejected and settled IDs stay reserved for the
476
+ session generation. Local duplicate, capacity and census failures use
477
+ `execution_input_identity_reused`, `execution_input_capacity_exhausted` and
478
+ `execution_input_identity_limit_exceeded`; census exhaustion initiates owned cleanup. Malformed
479
+ input and pre-abort failures preserve their pre-entry errors. Provider-invoked failures can throw
480
+ `AgentProviderDelegatedOperationError` with `operation: 'send_execution_input'` and started-execution
481
+ evidence. Post-entry abort or a lost receipt can mean uncertain delivery.
482
+
483
+ For a complete runnable caller flow, use
484
+ [`examples/execution-input`](../../examples/execution-input/README.md) in the public SDK checkout:
485
+
486
+ ```sh
487
+ pnpm exec tsx examples/execution-input/main.ts
488
+ ```
489
+
490
+ Its caller-owned teaching provider uses the actual runtime validator and no native process,
491
+ model, credentials, network, tools or storage. Five synthetic scenarios cover consumed,
492
+ unconfirmed, rejected, uncertain and unsupported input. `application.ts` waits for `turn.started`,
493
+ checks support and keeps the original reader progressing through both waits. Its result and
494
+ reader-join handles preserve ownership on failure. `main.ts` starts session close before joining
495
+ the reader, then disposes the instance; cleanup failure retains its callable retry owner. The same
496
+ source is compiled and run from the installed tarballs. Synthetic success qualifies no native
497
+ provider mapping.
498
+
499
+ On uncertainty, stop mutation, retain the reader and close the unusable session when needed.
500
+ Do not resend, steer, interrupt or start another turn to simulate delivery. Close starts native
501
+ quiescence before joining entered input, output and callbacks; elapsed observation time does not
502
+ prove they stopped. Keep the session or exact opening cleanup error and dependent instance,
503
+ registry and host resources until cleanup succeeds. Retry joins that same cleanup owner without
504
+ replaying input; rematerializing does not authorize an uncertain message's replay. This optional
505
+ runtime domain adds no Agent Protocol V13 change, private wire change or persistence migration.
506
+
222
507
  ## Session-lifetime interactions
223
508
 
224
509
  An adapter can offer a decision, form or plan review outside a model turn through
@@ -551,14 +836,16 @@ close before joining its reader and actual callback tasks; failure also starts c
551
836
  failures and cleanup failures remain observable. A callback that ignores cancellation
552
837
  remains owned until its actual promise settles.
553
838
 
554
- The coordinated SDK release is `0.4.3` and implements Agent Protocol V12.
839
+ The coordinated eight-package `0.4.4` source candidate implements Agent Protocol V13 and remains
840
+ unpublished. Published `0.4.3` is the seven-package V12 release.
555
841
  The earlier `0.4.1` release retains V11.
556
842
  The earlier `0.4.0` release retains V10.
557
843
  The earlier public `0.3.0` and `0.3.1` releases implemented V9 and remain historical.
558
- Keep installed packages in the seven-package SDK release family on the coordinated version; the
559
- orchestration and ACP packages remain optional. Every materialized instance requires `environment` and
844
+ Keep installed packages in a release family on its coordinated version; orchestration, ACP and
845
+ history packages remain optional. History browsing owns no execution turn and does not establish
846
+ structured-output support. Every materialized instance requires `environment` and
560
847
  `accountQuota`; every session requires `environment`. The former standalone `integrations`
561
- observation port is removed. The public runtime implements Agent Protocol V12 with one current
848
+ observation port is removed. The public runtime implements Agent Protocol V13 with one current
562
849
  adapter/session surface. Package versions remain independent of private transport and product
563
850
  persistence versions.
564
851
 
@@ -16,8 +16,10 @@ 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 { validateAgentExecutionInputSupport } from "./executionInput/validation.js";
19
20
  import { createSessionInteractionOwner } from "./sessionInteractions/lifetime.js";
20
21
  import { validateSessionInteractionSupport, validateNativeContinuationSupport } from "./sessionInteractions/validation.js";
22
+ import { admitAgentStructuredOutputOpening } from "./structuredOutput/admission.js";
21
23
  import {
22
24
  validateAgentProviderOperationResult,
23
25
  validateAgentProviderOutputForContext
@@ -78,6 +80,16 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
78
80
  const declaredResumption = adapter.resumption;
79
81
  const sessionInteractions = validateSessionInteractionSupport(capabilities, adapter);
80
82
  const nativeContinuations = validateNativeContinuationSupport(capabilities, adapter, sessionInteractions);
83
+ let executionInput;
84
+ try {
85
+ executionInput = validateAgentExecutionInputSupport(adapter.executionInput);
86
+ } catch {
87
+ return throwAgentProviderContractError(
88
+ capabilities.providerKey,
89
+ "invalid_adapter",
90
+ "Provider declared invalid execution-input support."
91
+ );
92
+ }
81
93
  let hostBinding;
82
94
  try {
83
95
  hostBinding = validateAgentSessionHostBindingSupport(adapter.hostBinding);
@@ -97,6 +109,13 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
97
109
  support: hostBinding,
98
110
  open: async (lease) => {
99
111
  throwIfAgentOperationAborted(resumeInput.signal);
112
+ if (Reflect.has(resumeInput, "output")) {
113
+ throwAgentProviderContractError(
114
+ capabilities.providerKey,
115
+ "structured_output_unsupported",
116
+ "Structured-output requests are unsupported when resuming a session."
117
+ );
118
+ }
100
119
  const parsed = parseAgentSessionOpenInput({
101
120
  operation: "resume",
102
121
  sessionId: resumeInput.sessionId,
@@ -114,7 +133,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
114
133
  resumeInput.workingDirectory
115
134
  );
116
135
  const binding = parsed.binding;
117
- const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId);
136
+ const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId, void 0, executionInput);
118
137
  const interactions = createSessionInteractionOwner({
119
138
  providerKey: capabilities.providerKey,
120
139
  sessionId: parsed.sessionId,
@@ -178,6 +197,13 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
178
197
  support: hostBinding,
179
198
  open: async (lease) => {
180
199
  throwIfAgentOperationAborted(branchInput.signal);
200
+ if (Reflect.has(branchInput, "output")) {
201
+ throwAgentProviderContractError(
202
+ capabilities.providerKey,
203
+ "structured_output_unsupported",
204
+ "Structured-output requests are unsupported when branching a session."
205
+ );
206
+ }
181
207
  const parsed = parseAgentSessionOpenInput({
182
208
  operation: "branch",
183
209
  sessionId: branchInput.sessionId,
@@ -195,7 +221,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
195
221
  branchInput.workingDirectory
196
222
  );
197
223
  const sourceBinding = parsed.source.binding;
198
- const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId);
224
+ const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId, void 0, executionInput);
199
225
  const interactions = createSessionInteractionOwner({
200
226
  providerKey: capabilities.providerKey,
201
227
  sessionId: parsed.sessionId,
@@ -317,7 +343,8 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
317
343
  const parsed = parseAgentSessionOpenInput({
318
344
  operation: "create",
319
345
  sessionId: createInput.sessionId,
320
- configuration: createInput.configuration
346
+ configuration: createInput.configuration,
347
+ ...createInput.output === void 0 ? {} : { output: createInput.output }
321
348
  });
322
349
  assertAgentSessionConfigurationSupported(
323
350
  capabilities,
@@ -326,7 +353,12 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
326
353
  const workingDirectory = parseWorkingDirectory(
327
354
  createInput.workingDirectory
328
355
  );
329
- const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId);
356
+ const structuredOutputBinding = admitAgentStructuredOutputOpening({
357
+ capabilities,
358
+ operation: "create",
359
+ output: parsed.operation === "create" ? parsed.output : void 0
360
+ });
361
+ const validationOwner = createAgentSessionValidationOwner(capabilities, parsed.sessionId, structuredOutputBinding, executionInput);
330
362
  const interactions = createSessionInteractionOwner({
331
363
  providerKey: capabilities.providerKey,
332
364
  sessionId: parsed.sessionId,
@@ -357,6 +389,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
357
389
  sessionId: parsed.sessionId,
358
390
  workingDirectory,
359
391
  configuration: parsed.configuration,
392
+ ...structuredOutputBinding === void 0 ? {} : { output: structuredOutputBinding.request },
360
393
  onBindingCreated: observer,
361
394
  ...lease === void 0 ? {} : { hostBinding: lease.binding },
362
395
  ...interactions === void 0 ? {} : { interactions: interactions.facade },
@@ -367,6 +400,7 @@ function validateAgentProviderAdapter(capabilityInput, adapterInput) {
367
400
  }
368
401
  });
369
402
  const openingAdapter = Object.freeze({
403
+ ...executionInput === void 0 ? {} : { executionInput },
370
404
  hostBinding,
371
405
  sessionInteractions,
372
406
  nativeContinuations,
@@ -1,8 +1,8 @@
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", "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"];
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", "structured_output_unsupported", "structured_output_scope_mismatch", "invalid_structured_output", "execution_input_capacity_exhausted", "execution_input_identity_reused", "execution_input_identity_limit_exceeded", "execution_input_correlation_lost"];
4
4
  export type AgentProviderContractErrorCode = (typeof AGENT_PROVIDER_CONTRACT_ERROR_CODES)[number];
5
- export type AgentProviderDelegatedOperation = "resolve_request" | "steer_turn" | "invoke_operation" | "apply_configuration" | "spawn_collaboration" | "control_collaboration";
5
+ export type AgentProviderDelegatedOperation = "resolve_request" | "steer_turn" | "send_execution_input" | "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;
@@ -44,7 +44,14 @@ const AGENT_PROVIDER_CONTRACT_ERROR_CODES = [
44
44
  "native_continuation_preparation_failed",
45
45
  "native_continuation_reader_not_ready",
46
46
  "native_continuation_limit_exceeded",
47
- "invalid_native_continuation"
47
+ "invalid_native_continuation",
48
+ "structured_output_unsupported",
49
+ "structured_output_scope_mismatch",
50
+ "invalid_structured_output",
51
+ "execution_input_capacity_exhausted",
52
+ "execution_input_identity_reused",
53
+ "execution_input_identity_limit_exceeded",
54
+ "execution_input_correlation_lost"
48
55
  ];
49
56
  class AgentProviderContractError extends Error {
50
57
  constructor(providerKey, code, message, options) {
@@ -0,0 +1,3 @@
1
+ export type { AgentExecutionInput, AgentExecutionInputMessage, AgentExecutionInputMessageId, AgentExecutionInputOutcome, AgentExecutionInputReceipt, AgentExecutionInputSupport, } from "./types.js";
2
+ export { parseAgentExecutionInputMessageId } from "./validation.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,4 @@
1
+ import { parseAgentExecutionInputMessageId } from "./validation.js";
2
+ export {
3
+ parseAgentExecutionInputMessageId
4
+ };
@@ -0,0 +1,47 @@
1
+ import type { AgentProviderKey, AgentTurnId } from "@agen-ai/agent-protocol";
2
+ import type { AgentExecutionInput, AgentExecutionInputMessage, AgentExecutionInputMessageId, AgentExecutionInputOutcome, AgentExecutionInputReceipt, AgentExecutionInputSupport } from "./types.js";
3
+ export declare function createExecutionInputCensus(providerKey: AgentProviderKey, exhausted: () => void): {
4
+ claim(messageId: AgentExecutionInputMessageId): void;
5
+ };
6
+ type UnconfirmedReason = Extract<AgentExecutionInputOutcome, {
7
+ status: "unconfirmed";
8
+ }>["reason"];
9
+ type SupportedInput = Extract<AgentExecutionInput, {
10
+ kind: "supported";
11
+ }>;
12
+ /** One execution's admission and observations; the existing execution owns its native output reader. */
13
+ export declare function createExecutionInputOwner(input: Readonly<{
14
+ providerKey: AgentProviderKey;
15
+ turnId: AgentTurnId;
16
+ support: Extract<AgentExecutionInputSupport, {
17
+ kind: "supported";
18
+ }>;
19
+ census: ReturnType<typeof createExecutionInputCensus>;
20
+ signal: AbortSignal;
21
+ requireAdmission: () => void;
22
+ fence: () => void;
23
+ }>): {
24
+ port: Readonly<{
25
+ kind: "supported";
26
+ support: Readonly<{
27
+ kind: "supported";
28
+ delivery: "current_or_owned_continuation";
29
+ consumptionReporting: "message_ids" | "unavailable";
30
+ input: import("@agen-ai/agent-protocol").AgentOperationInputCapability;
31
+ limits: Readonly<{
32
+ maxOutstandingMessages: number;
33
+ maxMessagesPerExecution: number;
34
+ maxBufferedBytes: number;
35
+ }>;
36
+ }>;
37
+ sendMessage: (candidate: AgentExecutionInputMessage) => Promise<AgentExecutionInputReceipt>;
38
+ }>;
39
+ attach(port: SupportedInput): void;
40
+ closeAdmission: (reason?: UnconfirmedReason) => void;
41
+ drain(producer?: Promise<void>): Promise<void>;
42
+ join: (producer?: Promise<void>) => Promise<void>;
43
+ readonly failed: boolean;
44
+ readonly retainsOwnership: boolean;
45
+ };
46
+ export {};
47
+ //# sourceMappingURL=lifetime.d.ts.map