@agen-ai/agent-runtime 0.4.0 → 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.
Files changed (45) hide show
  1. package/README.md +200 -9
  2. package/dist/adapterValidation.d.ts +4 -2
  3. package/dist/adapterValidation.js +140 -51
  4. package/dist/artifacts.js +0 -1
  5. package/dist/contractErrors.d.ts +2 -2
  6. package/dist/contractErrors.js +11 -7
  7. package/dist/hostBindings/opening.d.ts +2 -0
  8. package/dist/hostBindings/opening.js +58 -0
  9. package/dist/index.d.ts +2 -0
  10. package/dist/index.js +2 -0
  11. package/dist/nativeContinuations/admission.d.ts +17 -0
  12. package/dist/nativeContinuations/admission.js +250 -0
  13. package/dist/nativeContinuations/index.d.ts +2 -0
  14. package/dist/nativeContinuations/index.js +1 -0
  15. package/dist/nativeContinuations/types.d.ts +52 -0
  16. package/dist/nativeContinuations/types.js +0 -0
  17. package/dist/outputValidation.js +3 -2
  18. package/dist/providerCatalog.d.ts +1 -1
  19. package/dist/providerDriver.d.ts +4 -1
  20. package/dist/providerDriver.js +0 -1
  21. package/dist/providerInstanceRegistry.d.ts +4 -4
  22. package/dist/providerInstanceRegistry.js +2 -1
  23. package/dist/sessionAdmission.d.ts +12 -0
  24. package/dist/sessionAdmission.js +54 -0
  25. package/dist/sessionInteractions/index.d.ts +2 -0
  26. package/dist/sessionInteractions/index.js +1 -0
  27. package/dist/sessionInteractions/lifetime.d.ts +81 -0
  28. package/dist/sessionInteractions/lifetime.js +383 -0
  29. package/dist/sessionInteractions/request.d.ts +43 -0
  30. package/dist/sessionInteractions/request.js +381 -0
  31. package/dist/sessionInteractions/types.d.ts +110 -0
  32. package/dist/sessionInteractions/types.js +10 -0
  33. package/dist/sessionInteractions/validation.d.ts +25 -0
  34. package/dist/sessionInteractions/validation.js +180 -0
  35. package/dist/sessionValidation.d.ts +82 -3
  36. package/dist/sessionValidation.js +240 -181
  37. package/dist/sessions.d.ts +34 -0
  38. package/dist/testing/conformance.d.ts +3 -1
  39. package/dist/testing/conformance.js +180 -86
  40. package/dist/testing/fakeProvider.js +5 -6
  41. package/dist/turnExecution/execution.d.ts +23 -6
  42. package/dist/turnExecution/execution.js +136 -32
  43. package/dist/turnExecution/requests.d.ts +15 -3
  44. package/dist/turnExecution/requests.js +93 -28
  45. package/package.json +2 -2
@@ -0,0 +1,381 @@
1
+ import { parseAgentSessionResponseFor } from "@agen-ai/agent-protocol";
2
+ import { throwIfAgentOperationAborted } from "../foundation.js";
3
+ import { AgentProviderContractError } from "../contractErrors.js";
4
+ import { validateAgentRequestResolutionResult } from "../turnExecution/receipts.js";
5
+ import { sessionInteractionError } from "./lifetime.js";
6
+ import { dispatchPreparedSessionResponse, mintSessionResponseAttemptId } from "../nativeContinuations/admission.js";
7
+ import { interactionContractError, validateSessionInteractionTerminal } from "./validation.js";
8
+ const MAX_EXPIRY_TIMER_DELAY_MS = 2147483647;
9
+ class SessionInteractionRequest {
10
+ constructor(owner, candidate, retire) {
11
+ this.owner = owner;
12
+ this.candidate = candidate;
13
+ this.retire = retire;
14
+ const terminal = new Promise((resolve) => {
15
+ this.resolveTerminal = resolve;
16
+ });
17
+ this.handle = Object.freeze({
18
+ request: candidate.request,
19
+ deadline: candidate.deadline,
20
+ signal: this.presentation.signal,
21
+ terminal,
22
+ respond: (input) => this.respond(input)
23
+ });
24
+ }
25
+ handle;
26
+ state = { kind: "pending" };
27
+ presentation = new AbortController();
28
+ resolveTerminal;
29
+ callback;
30
+ callbackSettled = false;
31
+ responseWork = 0;
32
+ rawTerminalSettled = false;
33
+ nativeTerminal;
34
+ lastAttempt;
35
+ stopped;
36
+ unavailable = false;
37
+ retired = false;
38
+ expiryTimer;
39
+ terminalTimer;
40
+ nativeAborted = () => {
41
+ this.unavailable = true;
42
+ this.presentation.abort(new DOMException("The provider interaction was stopped.", "AbortError"));
43
+ this.expectTerminal();
44
+ };
45
+ observe() {
46
+ this.candidate.signal.addEventListener("abort", this.nativeAborted, { once: true });
47
+ void this.candidate.terminal.then((candidate) => {
48
+ this.rawTerminalSettled = true;
49
+ if (this.terminalTimer) clearTimeout(this.terminalTimer);
50
+ try {
51
+ this.nativeTerminal = validateSessionInteractionTerminal(candidate);
52
+ this.observeTerminal();
53
+ } catch (cause) {
54
+ this.protocolFailure(cause);
55
+ }
56
+ this.maybeRetire();
57
+ }, (cause) => {
58
+ this.rawTerminalSettled = true;
59
+ if (this.terminalTimer) clearTimeout(this.terminalTimer);
60
+ this.protocolFailure(cause);
61
+ this.maybeRetire();
62
+ });
63
+ if (this.candidate.signal.aborted) this.nativeAborted();
64
+ this.scheduleExpiry();
65
+ }
66
+ setCallback(callback) {
67
+ this.callback = callback;
68
+ void callback.then(
69
+ () => {
70
+ this.callbackSettled = true;
71
+ this.maybeRetire();
72
+ },
73
+ () => {
74
+ this.callbackSettled = true;
75
+ this.maybeRetire();
76
+ }
77
+ );
78
+ }
79
+ scheduleExpiry() {
80
+ if (this.candidate.deadlineAt === void 0 || this.state.kind === "terminal") return;
81
+ const remainingMs = this.candidate.deadlineAt - Date.now();
82
+ if (remainingMs <= 0) {
83
+ this.expire();
84
+ return;
85
+ }
86
+ this.expiryTimer = setTimeout(() => {
87
+ this.expiryTimer = void 0;
88
+ this.scheduleExpiry();
89
+ }, Math.min(remainingMs, MAX_EXPIRY_TIMER_DELAY_MS));
90
+ }
91
+ expire() {
92
+ if (this.state.kind === "terminal") return;
93
+ this.stop(Object.freeze({ kind: "expired", source: this.candidate.deadline.kind === "deadline" ? this.candidate.deadline.source : "provider" }));
94
+ this.owner.fail(interactionContractError(this.owner.providerKey, "Session interaction expired before final delivery."));
95
+ }
96
+ protocolFailure(cause) {
97
+ const error = sessionInteractionError("session_interaction_failed", "Provider session interaction protocol failed.");
98
+ this.stop(Object.freeze({ kind: "failed", error }));
99
+ this.owner.fail(cause instanceof AgentProviderContractError ? cause : new AgentProviderContractError(
100
+ this.owner.providerKey,
101
+ "invalid_session_interaction",
102
+ "Provider session interaction protocol failed.",
103
+ { cause }
104
+ ));
105
+ }
106
+ observeTerminal() {
107
+ const terminal = this.nativeTerminal;
108
+ if (!terminal) return;
109
+ if (terminal.kind === "failed") {
110
+ this.stop(terminal);
111
+ this.owner.fail(interactionContractError(this.owner.providerKey, "Provider session interaction producer failed."));
112
+ return;
113
+ }
114
+ if (terminal.kind === "expired") {
115
+ this.stop(terminal);
116
+ this.owner.fail(interactionContractError(this.owner.providerKey, "Provider session interaction expired."));
117
+ return;
118
+ }
119
+ if (terminal.kind === "delivery_uncertain") this.owner.fence(terminal.error, this);
120
+ const attempt = this.lastAttempt;
121
+ if (terminal.kind !== "answered" && this.state.kind !== "terminal") {
122
+ this.stopped ??= terminal;
123
+ this.unavailable = true;
124
+ this.presentation.abort(new DOMException("The provider interaction is no longer answerable.", "AbortError"));
125
+ this.finalize(this.stopped, attempt);
126
+ }
127
+ if (attempt && !attempt.actualReceipt) return;
128
+ if (attempt?.actualReceipt && this.receiptContradiction(attempt, attempt.actualReceipt)) {
129
+ throw interactionContractError(
130
+ this.owner.providerKey,
131
+ "Provider session interaction terminal contradicts its response delivery receipt."
132
+ );
133
+ }
134
+ if (terminal.kind === "answered") {
135
+ if (!attempt || JSON.stringify(terminal.response) !== JSON.stringify(attempt.response) || attempt.actualReceipt?.status !== "delivered") {
136
+ throw interactionContractError(this.owner.providerKey, "Provider interaction acceptance disagrees with its delivery receipt.");
137
+ }
138
+ this.finalize(terminal, attempt);
139
+ return;
140
+ }
141
+ if (this.state.kind === "terminal") return;
142
+ this.finalize(this.stopped ?? terminal, attempt);
143
+ }
144
+ expectTerminal(deadline = Date.now() + this.owner.limits.responseTimeoutMs) {
145
+ if (this.rawTerminalSettled || this.terminalTimer) return;
146
+ const active = this.state.kind === "answering" ? this.state.attempt.deadline : this.state.kind === "terminal" && this.state.attempt ? this.state.attempt.deadline : deadline;
147
+ this.terminalTimer = setTimeout(() => {
148
+ this.terminalTimer = void 0;
149
+ if (!this.rawTerminalSettled) this.protocolFailure(interactionContractError(
150
+ this.owner.providerKey,
151
+ "Provider did not settle its stopped session interaction terminal."
152
+ ));
153
+ }, Math.max(0, Math.min(active, deadline) - Date.now()));
154
+ }
155
+ finalize(terminal, attempt, nativeRetirementExpected = true) {
156
+ if (this.state.kind === "terminal") return;
157
+ this.state = { kind: "terminal", terminal, ...attempt === void 0 ? {} : { attempt } };
158
+ this.unavailable = true;
159
+ if (this.expiryTimer) clearTimeout(this.expiryTimer);
160
+ this.presentation.abort(new DOMException("The session interaction is no longer answerable.", "AbortError"));
161
+ this.resolveTerminal(terminal);
162
+ if (nativeRetirementExpected && (!attempt || attempt.actualReceipt || this.responseWork === 0)) this.expectTerminal();
163
+ this.maybeRetire();
164
+ }
165
+ stop(terminal, nativeRetirementExpected = true) {
166
+ this.stopped ??= terminal;
167
+ this.unavailable = true;
168
+ this.presentation.abort(new DOMException("The session interaction was stopped.", "AbortError"));
169
+ if (this.state.kind !== "terminal") this.finalize(this.stopped, void 0, nativeRetirementExpected);
170
+ if (nativeRetirementExpected) this.expectTerminal();
171
+ }
172
+ refusal(active = false) {
173
+ return Object.freeze({
174
+ status: "rejected",
175
+ requestState: active ? "pending" : "unavailable",
176
+ error: sessionInteractionError(
177
+ active ? "session_interaction_response_active" : "session_interaction_unavailable",
178
+ active ? "A session interaction response is already active." : "The session interaction is no longer available."
179
+ )
180
+ });
181
+ }
182
+ uncertain(attempt, cause) {
183
+ const error = sessionInteractionError(
184
+ "session_interaction_delivery_uncertain",
185
+ "Session interaction response delivery could not be confirmed.",
186
+ true
187
+ );
188
+ const receipt = Object.freeze({ status: "delivery_uncertain", error });
189
+ attempt.receipt ??= receipt;
190
+ this.finalize(Object.freeze({ kind: "delivery_uncertain", error }), attempt);
191
+ this.owner.fence(cause === void 0 ? error : new AgentProviderContractError(
192
+ this.owner.providerKey,
193
+ "invalid_session_interaction",
194
+ "Session interaction response delivery failed after provider entry.",
195
+ { cause }
196
+ ), this);
197
+ if (this.candidate.kind === "prepared") this.owner.quiesce();
198
+ return receipt;
199
+ }
200
+ receiptContradiction(attempt, result) {
201
+ const terminal = this.nativeTerminal;
202
+ if (!terminal) return false;
203
+ if (result.status === "delivery_uncertain") return terminal.kind === "rejected";
204
+ if (terminal.kind === "answered") return JSON.stringify(terminal.response) !== JSON.stringify(attempt.response) || result.status !== "delivered";
205
+ if (result.status === "delivered") return terminal.kind === "rejected" || terminal.kind === "delivery_uncertain";
206
+ if (terminal.kind === "delivery_uncertain") return true;
207
+ return result.requestState === "pending" && terminal.kind === "rejected";
208
+ }
209
+ async respond(input) {
210
+ if (input === null || typeof input !== "object" || Array.isArray(input)) throw new TypeError("Session response must be an object.");
211
+ const { signal: responseSignal, ...rawResponse } = input;
212
+ if (responseSignal !== void 0 && !(responseSignal instanceof AbortSignal)) throw new TypeError("Session interaction response signal must be an AbortSignal.");
213
+ const response = parseAgentSessionResponseFor(this.handle.request, rawResponse);
214
+ throwIfAgentOperationAborted(responseSignal);
215
+ const deadline = new AbortController();
216
+ const signal = AbortSignal.any([this.presentation.signal, deadline.signal, ...responseSignal ? [responseSignal] : []]);
217
+ if (this.candidate.deadlineAt !== void 0 && this.candidate.deadlineAt <= Date.now()) this.expire();
218
+ if (this.unavailable || !this.owner.accepting || this.state.kind === "terminal") return this.refusal();
219
+ if (this.state.kind === "answering") return this.refusal(true);
220
+ const attempt = { response: projectResponse(response), deadline: Date.now() + this.owner.limits.responseTimeoutMs, entered: false };
221
+ this.lastAttempt = attempt;
222
+ this.state = { kind: "answering", attempt };
223
+ this.responseWork += 1;
224
+ let entered;
225
+ const requireCurrent = () => {
226
+ if (this.state.kind !== "answering" || this.state.attempt !== attempt || this.unavailable) throw new DOMException("Session response is no longer eligible.", "AbortError");
227
+ if (this.candidate.deadlineAt !== void 0 && this.candidate.deadlineAt <= Date.now()) {
228
+ this.expire();
229
+ throw new DOMException("Session response expired before entry.", "AbortError");
230
+ }
231
+ };
232
+ if (this.candidate.kind === "prepared") {
233
+ entered = dispatchPreparedSessionResponse({
234
+ owner: this.owner,
235
+ candidate: this.candidate,
236
+ response,
237
+ attemptId: mintSessionResponseAttemptId(),
238
+ signal,
239
+ requireCurrent,
240
+ onDispatch: (deadlineAt) => {
241
+ attempt.entered = true;
242
+ attempt.deadline = deadlineAt;
243
+ },
244
+ observeActualReceipt: (work) => {
245
+ this.responseWork += 1;
246
+ const actual2 = this.owner.track(work.then((result2) => {
247
+ attempt.actualReceipt = result2;
248
+ try {
249
+ this.observeTerminal();
250
+ } catch (cause) {
251
+ this.protocolFailure(cause);
252
+ }
253
+ }));
254
+ void actual2.then(
255
+ () => {
256
+ this.responseWork -= 1;
257
+ this.maybeRetire();
258
+ },
259
+ () => {
260
+ this.responseWork -= 1;
261
+ this.maybeRetire();
262
+ }
263
+ );
264
+ }
265
+ });
266
+ } else {
267
+ attempt.entered = true;
268
+ try {
269
+ entered = Promise.resolve(this.candidate.respond({ ...response, signal }));
270
+ } catch (cause) {
271
+ entered = Promise.reject(cause);
272
+ }
273
+ }
274
+ const actual = this.owner.track(entered.then((candidate) => {
275
+ const result2 = validateAgentRequestResolutionResult(candidate, this.owner.providerKey);
276
+ if (this.candidate.kind === "direct") attempt.actualReceipt = result2;
277
+ if (this.state.kind === "terminal") {
278
+ try {
279
+ this.observeTerminal();
280
+ } catch (cause) {
281
+ this.protocolFailure(cause);
282
+ }
283
+ this.expectTerminal(attempt.deadline);
284
+ }
285
+ return result2;
286
+ }));
287
+ void actual.then(
288
+ () => {
289
+ this.responseWork -= 1;
290
+ this.maybeRetire();
291
+ },
292
+ () => {
293
+ this.responseWork -= 1;
294
+ this.maybeRetire();
295
+ }
296
+ );
297
+ let timer;
298
+ const timeout = new Promise((resolve) => {
299
+ if (this.candidate.kind === "prepared") return;
300
+ timer = setTimeout(
301
+ () => {
302
+ deadline.abort(new DOMException("Session interaction response timed out.", "TimeoutError"));
303
+ resolve(null);
304
+ },
305
+ Math.max(0, attempt.deadline - Date.now())
306
+ );
307
+ });
308
+ let result;
309
+ let responseFailure;
310
+ try {
311
+ result = await Promise.race([actual, timeout]);
312
+ } catch (cause) {
313
+ if (!attempt.entered) {
314
+ if (this.state.kind === "answering" && this.state.attempt === attempt) this.state = { kind: "pending" };
315
+ this.lastAttempt = void 0;
316
+ throw cause;
317
+ }
318
+ responseFailure = cause;
319
+ result = null;
320
+ }
321
+ if (timer) clearTimeout(timer);
322
+ if (result === null) return this.uncertain(attempt, responseFailure);
323
+ if (this.receiptContradiction(attempt, result)) {
324
+ const uncertain = this.uncertain(attempt);
325
+ this.protocolFailure(interactionContractError(
326
+ this.owner.providerKey,
327
+ "Provider session interaction terminal contradicts its response delivery receipt."
328
+ ));
329
+ return uncertain;
330
+ }
331
+ attempt.receipt = result;
332
+ if (result.status === "delivery_uncertain") {
333
+ this.finalize(Object.freeze({ kind: "delivery_uncertain", error: result.error }), attempt);
334
+ this.owner.fence(result.error, this);
335
+ if (this.candidate.kind === "prepared") this.owner.quiesce();
336
+ } else if (result.status === "delivered") {
337
+ this.finalize(this.stopped ?? Object.freeze({ kind: "answered", response: attempt.response }), attempt);
338
+ } else if (result.requestState === "unavailable") {
339
+ this.finalize(this.stopped ?? Object.freeze({ kind: "rejected", error: result.error }), attempt);
340
+ } else if (this.stopped || this.unavailable || !this.owner.accepting) {
341
+ if (this.stopped || !this.owner.accepting) this.finalize(this.stopped ?? Object.freeze({ kind: "session_closed" }), attempt);
342
+ else {
343
+ this.state = { kind: "pending" };
344
+ this.expectTerminal(attempt.deadline);
345
+ }
346
+ } else {
347
+ this.state = { kind: "pending" };
348
+ }
349
+ try {
350
+ this.observeTerminal();
351
+ } catch (cause) {
352
+ this.protocolFailure(cause);
353
+ }
354
+ return result;
355
+ }
356
+ maybeRetire() {
357
+ if (this.retired || this.state.kind !== "terminal" || !this.callbackSettled || this.responseWork !== 0 || !this.rawTerminalSettled) return;
358
+ this.retired = true;
359
+ if (this.expiryTimer) clearTimeout(this.expiryTimer);
360
+ if (this.terminalTimer) clearTimeout(this.terminalTimer);
361
+ this.candidate.signal.removeEventListener("abort", this.nativeAborted);
362
+ this.retire();
363
+ }
364
+ async join() {
365
+ await Promise.allSettled([this.candidate.terminal, ...this.callback ? [this.callback] : []]);
366
+ }
367
+ }
368
+ function projectResponse(response) {
369
+ if (response.kind === "form") return Object.freeze({ kind: "form", action: response.action, choiceId: response.choiceId });
370
+ if (response.kind === "plan_review") return Object.freeze({
371
+ kind: "plan_review",
372
+ action: response.action,
373
+ choiceId: response.choiceId,
374
+ planId: response.planId,
375
+ revision: response.revision
376
+ });
377
+ return response;
378
+ }
379
+ export {
380
+ SessionInteractionRequest
381
+ };
@@ -0,0 +1,110 @@
1
+ import type { AgentError, AgentSessionAcceptedResponse, AgentSessionDecisionResponse, AgentSessionRequest, AgentSessionRequestKind, AgentSessionResponse, AgentSessionFormRequest, AgentSessionPlanReviewRequest } from "@agen-ai/agent-protocol";
2
+ import type { MaybePromise } from "../foundation.js";
3
+ import type { AgentRequestResolutionResult } from "../sessions.js";
4
+ import type { AgentPreparedSessionResponse, AgentSessionResponseAttemptId } from "../nativeContinuations/types.js";
5
+ export type AgentSessionInteractionOpeningOperation = "create" | "resume" | "branch";
6
+ export type AgentSessionHumanWaitKind = "bounded" | "until_withdrawn_or_closed";
7
+ export type AgentSessionHumanWaitPolicy = Readonly<{
8
+ kind: "bounded";
9
+ }> | Readonly<{
10
+ kind: "until_withdrawn_or_closed";
11
+ }>;
12
+ export interface AgentSessionInteractionMapping {
13
+ readonly openingOperation: AgentSessionInteractionOpeningOperation;
14
+ readonly requestKind: AgentSessionRequestKind;
15
+ }
16
+ export type AgentSessionInteractionSupport = Readonly<{
17
+ kind: "unsupported";
18
+ }> | Readonly<{
19
+ kind: "supported";
20
+ mappings: readonly [AgentSessionInteractionMapping, ...AgentSessionInteractionMapping[]];
21
+ producerOwnership: "exclusive";
22
+ humanWait: readonly [AgentSessionHumanWaitKind, ...AgentSessionHumanWaitKind[]];
23
+ }>;
24
+ export interface AgentSessionInteractionLimits {
25
+ readonly maxRetainedRequests: number;
26
+ readonly maxRetainedBytes: number;
27
+ readonly requestTimeoutMs: number;
28
+ readonly responseTimeoutMs: number;
29
+ readonly cleanupTimeoutMs: number;
30
+ }
31
+ export type AgentSessionInteractionOptions = Readonly<{
32
+ humanWait?: Readonly<{
33
+ kind: "bounded";
34
+ }>;
35
+ limits?: Partial<AgentSessionInteractionLimits>;
36
+ }> | Readonly<{
37
+ humanWait: Readonly<{
38
+ kind: "until_withdrawn_or_closed";
39
+ }>;
40
+ limits?: Partial<Omit<AgentSessionInteractionLimits, "requestTimeoutMs">>;
41
+ }>;
42
+ export type AgentSessionInteractionDeadline = Readonly<{
43
+ kind: "no_deadline";
44
+ }> | Readonly<{
45
+ kind: "deadline";
46
+ expiresAt: import("@agen-ai/agent-protocol").AgentIsoDateTime;
47
+ source: "provider" | "host_policy";
48
+ }>;
49
+ export type AgentSessionResponseInput = AgentSessionResponse & Readonly<{
50
+ signal?: AbortSignal;
51
+ }>;
52
+ export type AgentSessionDecisionResponseInput = AgentSessionDecisionResponse & Readonly<{
53
+ signal?: AbortSignal;
54
+ }>;
55
+ export type AgentSessionInteractionTerminal = Readonly<{
56
+ kind: "answered";
57
+ response: AgentSessionAcceptedResponse;
58
+ }> | Readonly<{
59
+ kind: "rejected";
60
+ error: AgentError;
61
+ }> | Readonly<{
62
+ kind: "delivery_uncertain";
63
+ error: AgentError;
64
+ }> | Readonly<{
65
+ kind: "withdrawn";
66
+ }> | Readonly<{
67
+ kind: "expired";
68
+ source: "provider" | "host_policy";
69
+ }> | Readonly<{
70
+ kind: "session_closed";
71
+ }> | Readonly<{
72
+ kind: "failed";
73
+ error: AgentError;
74
+ }>;
75
+ export interface AgentSessionInteraction {
76
+ readonly request: AgentSessionRequest;
77
+ readonly deadline: AgentSessionInteractionDeadline;
78
+ readonly signal: AbortSignal;
79
+ readonly terminal: Promise<AgentSessionInteractionTerminal>;
80
+ readonly respond: (input: AgentSessionResponseInput) => Promise<AgentRequestResolutionResult>;
81
+ }
82
+ export type AgentSessionInteractionHandler = (interaction: AgentSessionInteraction) => MaybePromise<void>;
83
+ export type AgentSessionInteractionContext = AgentSessionInteractionOptions & Readonly<{
84
+ onRequest: AgentSessionInteractionHandler;
85
+ }>;
86
+ export interface AgentProviderDirectSessionInteraction {
87
+ readonly kind: "direct";
88
+ readonly request: AgentSessionRequest;
89
+ readonly signal: AbortSignal;
90
+ readonly terminal: Promise<AgentSessionInteractionTerminal>;
91
+ readonly respond: (input: AgentSessionResponseInput) => Promise<AgentRequestResolutionResult>;
92
+ }
93
+ export interface AgentProviderPrepareSessionResponseInput {
94
+ readonly response: AgentSessionResponse;
95
+ readonly responseAttemptId: AgentSessionResponseAttemptId;
96
+ readonly signal: AbortSignal;
97
+ }
98
+ export interface AgentProviderPreparedSessionInteraction {
99
+ readonly kind: "prepared";
100
+ readonly request: AgentSessionFormRequest | AgentSessionPlanReviewRequest;
101
+ readonly signal: AbortSignal;
102
+ readonly terminal: Promise<AgentSessionInteractionTerminal>;
103
+ readonly prepareResponse: (input: AgentProviderPrepareSessionResponseInput) => MaybePromise<AgentPreparedSessionResponse>;
104
+ }
105
+ export type AgentProviderSessionInteraction = AgentProviderDirectSessionInteraction | AgentProviderPreparedSessionInteraction;
106
+ export type AgentProviderSessionInteractionContext = AgentSessionInteractionOptions & Readonly<{
107
+ onRequest: (interaction: AgentProviderSessionInteraction) => MaybePromise<void>;
108
+ }>;
109
+ export declare const DEFAULT_AGENT_SESSION_INTERACTION_LIMITS: Readonly<AgentSessionInteractionLimits>;
110
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,10 @@
1
+ const DEFAULT_AGENT_SESSION_INTERACTION_LIMITS = Object.freeze({
2
+ maxRetainedRequests: 8,
3
+ maxRetainedBytes: 524288,
4
+ requestTimeoutMs: 3e5,
5
+ responseTimeoutMs: 3e4,
6
+ cleanupTimeoutMs: 3e4
7
+ });
8
+ export {
9
+ DEFAULT_AGENT_SESSION_INTERACTION_LIMITS
10
+ };
@@ -0,0 +1,25 @@
1
+ import { type AgentCapabilities, type AgentProviderKey, type AgentSessionId } from "@agen-ai/agent-protocol";
2
+ import { AgentProviderContractError } from "../contractErrors.js";
3
+ import type { AgentProviderAdapter } from "../sessions.js";
4
+ import type { AgentNativeContinuationSupport, AgentNativeContinuationContext } from "../nativeContinuations/types.js";
5
+ import { type AgentSessionInteractionContext, type AgentSessionInteractionLimits, type AgentSessionInteractionSupport, type AgentSessionInteractionTerminal, type AgentSessionHumanWaitKind, type AgentProviderSessionInteraction, type AgentSessionInteractionDeadline } from "./types.js";
6
+ export declare function interactionRecord(input: unknown): Record<string, unknown>;
7
+ export declare function interactionContractError(providerKey: AgentProviderKey, message: string): AgentProviderContractError;
8
+ export declare function validateSessionInteractionSupport(capabilities: AgentCapabilities, adapter: AgentProviderAdapter): AgentSessionInteractionSupport;
9
+ export declare function validateNativeContinuationSupport(capabilities: AgentCapabilities, adapter: AgentProviderAdapter, interactions: AgentSessionInteractionSupport): AgentNativeContinuationSupport;
10
+ export interface ValidatedSessionInteractionContext {
11
+ readonly onRequest: AgentSessionInteractionContext["onRequest"];
12
+ readonly humanWait: AgentSessionHumanWaitKind;
13
+ readonly limits: Readonly<AgentSessionInteractionLimits>;
14
+ }
15
+ export declare function validateSessionInteractionContext(input: AgentSessionInteractionContext): ValidatedSessionInteractionContext;
16
+ export declare function validateNativeContinuationContext(input: AgentNativeContinuationContext | undefined): AgentNativeContinuationContext | undefined;
17
+ export type CapturedSessionInteractionCandidate = AgentProviderSessionInteraction;
18
+ export declare function captureSessionInteractionCandidate(input: AgentProviderSessionInteraction, observe: (terminal: Promise<unknown>) => void): CapturedSessionInteractionCandidate;
19
+ export type ValidatedSessionInteractionCandidate = CapturedSessionInteractionCandidate & Readonly<{
20
+ deadline: AgentSessionInteractionDeadline;
21
+ deadlineAt?: number;
22
+ }>;
23
+ export declare function validateSessionInteractionCandidate(input: CapturedSessionInteractionCandidate, sessionId: AgentSessionId, context: ValidatedSessionInteractionContext): ValidatedSessionInteractionCandidate;
24
+ export declare function validateSessionInteractionTerminal(input: unknown): AgentSessionInteractionTerminal;
25
+ //# sourceMappingURL=validation.d.ts.map