@agen-ai/agent-runtime 0.4.3 → 0.4.4
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 +297 -10
- package/dist/adapterValidation.js +38 -4
- package/dist/contractErrors.d.ts +2 -2
- package/dist/contractErrors.js +8 -1
- package/dist/executionInput/index.d.ts +3 -0
- package/dist/executionInput/index.js +4 -0
- package/dist/executionInput/lifetime.d.ts +47 -0
- package/dist/executionInput/lifetime.js +241 -0
- package/dist/executionInput/types.d.ts +61 -0
- package/dist/executionInput/types.js +0 -0
- package/dist/executionInput/validation.d.ts +25 -0
- package/dist/executionInput/validation.js +178 -0
- package/dist/generation/cleanup.d.ts +15 -0
- package/dist/generation/cleanup.js +108 -0
- package/dist/generation/deadline.d.ts +16 -0
- package/dist/generation/deadline.js +81 -0
- package/dist/generation/decoding.d.ts +4 -0
- package/dist/generation/decoding.js +59 -0
- package/dist/generation/errors.d.ts +29 -0
- package/dist/generation/errors.js +39 -0
- package/dist/generation/generateObject.d.ts +3 -0
- package/dist/generation/generateObject.js +148 -0
- package/dist/generation/index.d.ts +5 -0
- package/dist/generation/index.js +8 -0
- package/dist/generation/preflight.d.ts +25 -0
- package/dist/generation/preflight.js +48 -0
- package/dist/generation/requests.d.ts +17 -0
- package/dist/generation/requests.js +117 -0
- package/dist/generation/types.d.ts +22 -0
- package/dist/generation/types.js +0 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +7 -1
- package/dist/nativeContinuations/admission.js +1 -0
- package/dist/outputValidation.d.ts +2 -0
- package/dist/outputValidation.js +29 -1
- package/dist/sessionInteractions/lifetime.d.ts +1 -0
- package/dist/sessionInteractions/lifetime.js +4 -0
- package/dist/sessionInteractions/request.d.ts +1 -0
- package/dist/sessionInteractions/request.js +3 -0
- package/dist/sessionValidation.d.ts +13 -3
- package/dist/sessionValidation.js +80 -6
- package/dist/sessions.d.ts +7 -1
- package/dist/structuredOutput/admission.d.ts +16 -0
- package/dist/structuredOutput/admission.js +89 -0
- package/dist/structuredOutput/candidate.d.ts +22 -0
- package/dist/structuredOutput/candidate.js +64 -0
- package/dist/structuredOutput/validation.d.ts +8 -0
- package/dist/structuredOutput/validation.js +26 -0
- package/dist/testing/conformance.d.ts +20 -1
- package/dist/testing/conformance.js +103 -3
- package/dist/testing/fakeProvider.js +5 -4
- package/dist/turnExecution/execution.d.ts +9 -1
- package/dist/turnExecution/execution.js +88 -7
- package/dist/turnExecution/terminalBuffer.d.ts +9 -0
- package/dist/turnExecution/terminalBuffer.js +38 -0
- package/package.json +6 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type AgentCapabilities, type AgentCollaborationId, type AgentGeneratedResourceId, type AgentOperationInvocationId, type AgentProviderKey, type AgentSessionId, type AgentTurnId } from "@agen-ai/agent-protocol";
|
|
2
2
|
import { type AgentProviderOutput } from "./outputs.js";
|
|
3
3
|
import type { AgentProviderOperationResult } from "./sessions.js";
|
|
4
|
+
import type { AgentStructuredOutputBinding } from "./structuredOutput/admission.js";
|
|
4
5
|
export interface AgentProviderOutputValidationContext {
|
|
5
6
|
readonly capabilities: AgentCapabilities;
|
|
6
7
|
readonly providerKey: AgentProviderKey;
|
|
@@ -10,6 +11,7 @@ export interface AgentProviderOutputValidationContext {
|
|
|
10
11
|
readonly operationInvocationId?: AgentOperationInvocationId;
|
|
11
12
|
readonly collaborationId?: AgentCollaborationId;
|
|
12
13
|
readonly generatedResourceId?: AgentGeneratedResourceId;
|
|
14
|
+
readonly structuredOutputBinding?: AgentStructuredOutputBinding;
|
|
13
15
|
}
|
|
14
16
|
export declare function validateAgentProviderOutputForContext(candidate: AgentProviderOutput, context: AgentProviderOutputValidationContext): AgentProviderOutput;
|
|
15
17
|
export declare function validateAgentProviderOperationResult(candidate: AgentProviderOperationResult, context: AgentProviderOutputValidationContext): AgentProviderOperationResult;
|
package/dist/outputValidation.js
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
AGENT_PROTOCOL_EVENT_BYTES_LIMIT,
|
|
3
|
+
agentProtocolSerializedJsonBytes,
|
|
4
|
+
parseAgentError,
|
|
5
|
+
parseAgentEvent
|
|
3
6
|
} from "@agen-ai/agent-protocol";
|
|
4
7
|
import { throwAgentProviderContractError } from "./contractErrors.js";
|
|
5
8
|
import {
|
|
6
9
|
validateAgentProviderOutput
|
|
7
10
|
} from "./outputs.js";
|
|
11
|
+
import { validateAgentStructuredOutputResult } from "./structuredOutput/validation.js";
|
|
8
12
|
function unsupportedCapabilitySemantic(value) {
|
|
9
13
|
throw new TypeError(
|
|
10
14
|
`Unsupported Agent Protocol capability semantic: ${String(value)}.`
|
|
@@ -206,6 +210,30 @@ function validateAgentProviderOutputForContext(candidate, context) {
|
|
|
206
210
|
);
|
|
207
211
|
}
|
|
208
212
|
assertOutputCapability(context, output);
|
|
213
|
+
if (output.kind === "event" && output.event.type === "turn.completed") {
|
|
214
|
+
let structuredOutput = validateAgentStructuredOutputResult({
|
|
215
|
+
providerKey: context.providerKey,
|
|
216
|
+
...context.structuredOutputBinding === void 0 ? {} : { binding: context.structuredOutputBinding },
|
|
217
|
+
result: output.event.payload.structuredOutput
|
|
218
|
+
});
|
|
219
|
+
if (output.event.payload.outcome !== "completed") return output;
|
|
220
|
+
let event = {
|
|
221
|
+
...output.event,
|
|
222
|
+
payload: { ...output.event.payload, structuredOutput }
|
|
223
|
+
};
|
|
224
|
+
if (structuredOutput.kind === "unavailable" && structuredOutput.reason === "schema_mismatch" && structuredOutput.issues !== void 0 && agentProtocolSerializedJsonBytes(event) > AGENT_PROTOCOL_EVENT_BYTES_LIMIT) {
|
|
225
|
+
structuredOutput = Object.freeze({ kind: "unavailable", reason: "schema_mismatch" });
|
|
226
|
+
event = { ...event, payload: { ...event.payload, structuredOutput } };
|
|
227
|
+
}
|
|
228
|
+
parseAgentEvent(event);
|
|
229
|
+
return Object.freeze({
|
|
230
|
+
...output,
|
|
231
|
+
event: Object.freeze({
|
|
232
|
+
...event,
|
|
233
|
+
payload: Object.freeze(event.payload)
|
|
234
|
+
})
|
|
235
|
+
});
|
|
236
|
+
}
|
|
209
237
|
return output;
|
|
210
238
|
}
|
|
211
239
|
function validateAgentProviderOperationResult(candidate, context) {
|
|
@@ -49,6 +49,7 @@ export declare class SessionInteractionOwner {
|
|
|
49
49
|
constructor(providerKey: AgentProviderKey, sessionId: AgentSessionId, context: AgentSessionInteractionContext, validationOwner: AgentSessionValidationOwner, operation: AgentSessionInteractionOpeningOperation, support: AgentSessionInteractionSupport, nativeSupport: AgentNativeContinuationSupport, continuations?: AgentNativeContinuationContext, signal?: AbortSignal);
|
|
50
50
|
track<Result>(promise: Promise<Result>): Promise<Result>;
|
|
51
51
|
get accepting(): boolean;
|
|
52
|
+
get hasLiveRequests(): boolean;
|
|
52
53
|
requireUsable(): void;
|
|
53
54
|
private offer;
|
|
54
55
|
requireContinuation(kind: "form" | "plan_review"): void;
|
|
@@ -102,6 +102,10 @@ class SessionInteractionOwner {
|
|
|
102
102
|
get accepting() {
|
|
103
103
|
return this.state === "opening" || this.state === "open";
|
|
104
104
|
}
|
|
105
|
+
get hasLiveRequests() {
|
|
106
|
+
for (const request of this.requests.values()) if (request.blocksExecutionInput) return true;
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
105
109
|
requireUsable() {
|
|
106
110
|
if (this.fatal) throw this.fatal.cause;
|
|
107
111
|
this.validationOwner.requireUsable();
|
|
@@ -25,6 +25,7 @@ export declare class SessionInteractionRequest {
|
|
|
25
25
|
constructor(owner: SessionInteractionOwner, candidate: Candidate, retire: () => void);
|
|
26
26
|
observe(): void;
|
|
27
27
|
setCallback(callback: Promise<void>): void;
|
|
28
|
+
get blocksExecutionInput(): boolean;
|
|
28
29
|
private scheduleExpiry;
|
|
29
30
|
private expire;
|
|
30
31
|
private protocolFailure;
|
|
@@ -76,6 +76,9 @@ class SessionInteractionRequest {
|
|
|
76
76
|
}
|
|
77
77
|
);
|
|
78
78
|
}
|
|
79
|
+
get blocksExecutionInput() {
|
|
80
|
+
return this.state.kind !== "terminal" || this.responseWork > 0 || !this.rawTerminalSettled;
|
|
81
|
+
}
|
|
79
82
|
scheduleExpiry() {
|
|
80
83
|
if (this.candidate.deadlineAt === void 0 || this.state.kind === "terminal") return;
|
|
81
84
|
const remainingMs = this.candidate.deadlineAt - Date.now();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type AgentCapabilities, type AgentCollaborationNode, type AgentContextCumulativeUsage, type AgentContextMeasurementScope, type AgentContextUsage, type AgentGeneratedResourceDescriptor, type AgentItemKind, type AgentItemStatus, type AgentOperationInvocation, type AgentOperationResult, type AgentProviderKey, type AgentSessionBinding, type AgentSessionId, type AgentTurnId } from "@agen-ai/agent-protocol";
|
|
1
|
+
import { type AgentCapabilities, type AgentCollaborationNode, type AgentContextCumulativeUsage, type AgentContextMeasurementScope, type AgentContextUsage, type AgentGeneratedResourceDescriptor, type AgentItemKind, type AgentItemStatus, type AgentOperationInputCapability, type AgentOperationInvocation, type AgentOperationResult, type AgentProviderKey, type AgentSessionBinding, type AgentSessionId, type AgentTurnId } from "@agen-ai/agent-protocol";
|
|
2
2
|
import { type AgentHostBindingLease } from "./hostBindings/lifetime.js";
|
|
3
3
|
import { type MaybePromise } from "./foundation.js";
|
|
4
4
|
import { type AgentProviderOutputValidationContext } from "./outputValidation.js";
|
|
@@ -6,6 +6,8 @@ import type { AgentProviderStartTurnInput, AgentProviderSession, AgentSessionBin
|
|
|
6
6
|
import { type ValidatedAgentTurnExecution, type AdoptedAgentTurnExecution } from "./turnExecution/execution.js";
|
|
7
7
|
import { type PendingAgentRequest } from "./turnExecution/requests.js";
|
|
8
8
|
import type { SessionInteractionOwner } from "./sessionInteractions/lifetime.js";
|
|
9
|
+
import type { AgentExecutionInputSupport } from "./executionInput/types.js";
|
|
10
|
+
import { type AgentStructuredOutputBinding } from "./structuredOutput/admission.js";
|
|
9
11
|
interface ObservedAgentItem {
|
|
10
12
|
readonly itemKind: AgentItemKind;
|
|
11
13
|
readonly status: AgentItemStatus;
|
|
@@ -47,7 +49,12 @@ interface ActiveAgentTurn {
|
|
|
47
49
|
readonly inFlightOperations: Set<Promise<void>>;
|
|
48
50
|
readonly owner: ValidatedAgentTurnExecution;
|
|
49
51
|
}
|
|
50
|
-
export declare function
|
|
52
|
+
export declare function assertAgentTurnInputCapability(input: {
|
|
53
|
+
readonly capability: AgentOperationInputCapability;
|
|
54
|
+
readonly parts: AgentProviderStartTurnInput["parts"];
|
|
55
|
+
readonly providerKey: AgentProviderKey;
|
|
56
|
+
}): void;
|
|
57
|
+
export declare function createAgentSessionValidationOwner(capabilities: AgentCapabilities, sessionId: AgentSessionId, structuredOutputBinding?: AgentStructuredOutputBinding, executionInputSupport?: AgentExecutionInputSupport): {
|
|
51
58
|
sessionAdmission: {
|
|
52
59
|
trackOperation(): () => void;
|
|
53
60
|
joinOperations(): Promise<void>;
|
|
@@ -71,11 +78,14 @@ export declare function createAgentSessionValidationOwner(capabilities: AgentCap
|
|
|
71
78
|
stop(): void;
|
|
72
79
|
completeClose(): void;
|
|
73
80
|
installClose(close: () => Promise<void>): void;
|
|
81
|
+
installInputContextGuard(guard: () => void): void;
|
|
74
82
|
reserveExecution: () => object;
|
|
75
83
|
ownsExecution: (token: object) => boolean;
|
|
76
84
|
releaseExecution: (token: object) => void;
|
|
85
|
+
admitTurnOutput(output: unknown, hasOutput: boolean): AgentStructuredOutputBinding | undefined;
|
|
86
|
+
requireNativeContinuationSupport: () => void;
|
|
77
87
|
installNativeExecution(token: object, turnId: AgentTurnId, createCandidate: (signal: AbortSignal) => AgentProviderTurnExecution): AdoptedAgentTurnExecution;
|
|
78
|
-
installCallerExecution(token: object, turnInput: AgentProviderStartTurnInput, start: (input: AgentProviderStartTurnInput) => AgentProviderTurnExecution): ValidatedAgentTurnExecution;
|
|
88
|
+
installCallerExecution(token: object, turnInput: AgentProviderStartTurnInput, start: (input: AgentProviderStartTurnInput) => AgentProviderTurnExecution, binding?: AgentStructuredOutputBinding): ValidatedAgentTurnExecution;
|
|
79
89
|
};
|
|
80
90
|
export type AgentSessionValidationOwner = ReturnType<typeof createAgentSessionValidationOwner>;
|
|
81
91
|
export declare function validateAgentProviderSession(input: {
|
|
@@ -48,6 +48,10 @@ import { createValidatedAgentTurnExecution, adoptValidatedAgentTurnExecution } f
|
|
|
48
48
|
import { validateAgentProviderTurnInterruptionResult } from "./turnExecution/receipts.js";
|
|
49
49
|
import { createAgentTurnRequestAdmission } from "./turnExecution/requests.js";
|
|
50
50
|
import { createAgentSessionAdmission } from "./sessionAdmission.js";
|
|
51
|
+
import { createExecutionInputCensus } from "./executionInput/lifetime.js";
|
|
52
|
+
import {
|
|
53
|
+
admitAgentStructuredOutputTurn
|
|
54
|
+
} from "./structuredOutput/admission.js";
|
|
51
55
|
function validateCloseReason(reason) {
|
|
52
56
|
if (reason !== void 0 && !["idle", "shutdown", "replaced", "contract_rejected", "error", "other"].includes(reason)) {
|
|
53
57
|
throw new TypeError("Provider session close reason is unsupported.");
|
|
@@ -620,7 +624,7 @@ function assertAgentTurnInputCapability(input) {
|
|
|
620
624
|
});
|
|
621
625
|
if (textIssue) rejectReference(`${textIssue.target} must use ${textIssue.format} text`);
|
|
622
626
|
}
|
|
623
|
-
function createAgentSessionValidationOwner(capabilities, sessionId) {
|
|
627
|
+
function createAgentSessionValidationOwner(capabilities, sessionId, structuredOutputBinding, executionInputSupport) {
|
|
624
628
|
const providerKey = capabilities.providerKey;
|
|
625
629
|
const sessionLifetime = new AbortController();
|
|
626
630
|
const sessionAdmission = createAgentSessionAdmission(providerKey);
|
|
@@ -639,6 +643,15 @@ function createAgentSessionValidationOwner(capabilities, sessionId) {
|
|
|
639
643
|
let closed = false;
|
|
640
644
|
let unusable = false;
|
|
641
645
|
let closing;
|
|
646
|
+
let requireInputContext = () => {
|
|
647
|
+
};
|
|
648
|
+
const executionInputCensus = createExecutionInputCensus(providerKey, () => {
|
|
649
|
+
unusable = true;
|
|
650
|
+
queueMicrotask(() => {
|
|
651
|
+
void closing?.().catch(() => {
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
});
|
|
642
655
|
const requireOpen = () => {
|
|
643
656
|
if (closed)
|
|
644
657
|
throwAgentProviderContractError(
|
|
@@ -677,6 +690,11 @@ function createAgentSessionValidationOwner(capabilities, sessionId) {
|
|
|
677
690
|
const inFlightOperations = /* @__PURE__ */ new Set();
|
|
678
691
|
const common = {
|
|
679
692
|
providerKey,
|
|
693
|
+
...executionInputSupport === void 0 ? {} : { executionInputSupport },
|
|
694
|
+
executionInputCensus,
|
|
695
|
+
ownsExecution: () => sessionAdmission.ownsExecution(token),
|
|
696
|
+
requireInputContext: () => requireInputContext(),
|
|
697
|
+
structuredOutputBound: source.kind === "caller" && source.binding !== void 0,
|
|
680
698
|
pendingRequests,
|
|
681
699
|
sessionAdmission,
|
|
682
700
|
inFlightOperations,
|
|
@@ -684,7 +702,10 @@ function createAgentSessionValidationOwner(capabilities, sessionId) {
|
|
|
684
702
|
isTerminal: () => state.terminal,
|
|
685
703
|
canRestoreRequest: (pending) => hasLiveApprovalSubject(pending.request, state),
|
|
686
704
|
observe(candidate, requests) {
|
|
687
|
-
const output = validateAgentProviderOutputForContext(candidate,
|
|
705
|
+
const output = validateAgentProviderOutputForContext(candidate, {
|
|
706
|
+
...outputContext(turnId),
|
|
707
|
+
...source.kind !== "caller" || source.binding === void 0 ? {} : { structuredOutputBinding: source.binding }
|
|
708
|
+
});
|
|
688
709
|
observeTurnOutput({
|
|
689
710
|
capabilities,
|
|
690
711
|
providerKey,
|
|
@@ -719,6 +740,15 @@ function createAgentSessionValidationOwner(capabilities, sessionId) {
|
|
|
719
740
|
}
|
|
720
741
|
return owner;
|
|
721
742
|
}
|
|
743
|
+
const requireNativeContinuationSupport = () => {
|
|
744
|
+
if (structuredOutputBinding !== void 0) {
|
|
745
|
+
throwAgentProviderContractError(
|
|
746
|
+
providerKey,
|
|
747
|
+
"structured_output_unsupported",
|
|
748
|
+
"Schema-bound sessions cannot dispatch native continuations without structured-output admission."
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
};
|
|
722
752
|
return {
|
|
723
753
|
sessionAdmission,
|
|
724
754
|
sessionLifetime,
|
|
@@ -749,14 +779,38 @@ function createAgentSessionValidationOwner(capabilities, sessionId) {
|
|
|
749
779
|
installClose(close) {
|
|
750
780
|
closing = close;
|
|
751
781
|
},
|
|
782
|
+
installInputContextGuard(guard) {
|
|
783
|
+
requireInputContext = guard;
|
|
784
|
+
},
|
|
752
785
|
reserveExecution: sessionAdmission.reserveExecution,
|
|
753
786
|
ownsExecution: sessionAdmission.ownsExecution,
|
|
754
787
|
releaseExecution: sessionAdmission.releaseExecution,
|
|
788
|
+
admitTurnOutput(output, hasOutput) {
|
|
789
|
+
if (structuredOutputBinding !== void 0 && hasOutput) {
|
|
790
|
+
throwAgentProviderContractError(
|
|
791
|
+
providerKey,
|
|
792
|
+
"structured_output_scope_mismatch",
|
|
793
|
+
"A schema-bound session cannot override or remove its opening structured-output request."
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
return admitAgentStructuredOutputTurn({
|
|
797
|
+
capabilities,
|
|
798
|
+
...structuredOutputBinding === void 0 ? {} : { binding: structuredOutputBinding },
|
|
799
|
+
output
|
|
800
|
+
});
|
|
801
|
+
},
|
|
802
|
+
requireNativeContinuationSupport,
|
|
755
803
|
installNativeExecution(token, turnId, createCandidate) {
|
|
804
|
+
requireNativeContinuationSupport();
|
|
756
805
|
return installExecution(token, turnId, { kind: "native", createCandidate });
|
|
757
806
|
},
|
|
758
|
-
installCallerExecution(token, turnInput, start) {
|
|
759
|
-
return installExecution(token, turnInput.turnId, {
|
|
807
|
+
installCallerExecution(token, turnInput, start, binding) {
|
|
808
|
+
return installExecution(token, turnInput.turnId, {
|
|
809
|
+
kind: "caller",
|
|
810
|
+
input: turnInput,
|
|
811
|
+
start,
|
|
812
|
+
...binding === void 0 ? {} : { binding }
|
|
813
|
+
});
|
|
760
814
|
}
|
|
761
815
|
};
|
|
762
816
|
}
|
|
@@ -796,6 +850,14 @@ function validateAgentProviderSession(input) {
|
|
|
796
850
|
}
|
|
797
851
|
validateSessionPorts(capabilities, input.candidate);
|
|
798
852
|
const validationOwner = input.validationOwner ?? createAgentSessionValidationOwner(capabilities, sessionId);
|
|
853
|
+
validationOwner.installInputContextGuard(() => {
|
|
854
|
+
input.sessionInteractionOwner?.requireUsable();
|
|
855
|
+
if (input.sessionInteractionOwner?.hasLiveRequests) throwAgentProviderContractError(
|
|
856
|
+
providerKey,
|
|
857
|
+
"request_pending",
|
|
858
|
+
"Execution input cannot enter while a session interaction remains unsettled."
|
|
859
|
+
);
|
|
860
|
+
});
|
|
799
861
|
const { sessionLifetime, contextUsageState, interactionState, outputContext } = validationOwner;
|
|
800
862
|
const collaborationNodes = interactionState.collaborationNodes;
|
|
801
863
|
const collaborationSpawnReservations = interactionState.collaborationSpawnReservations;
|
|
@@ -862,6 +924,7 @@ function validateAgentProviderSession(input) {
|
|
|
862
924
|
turnId: turnInput.turnId,
|
|
863
925
|
interactionMode: turnInput.interactionMode,
|
|
864
926
|
parts: turnInput.parts,
|
|
927
|
+
...turnInput.output === void 0 ? {} : { output: turnInput.output },
|
|
865
928
|
...turnInput.summary === void 0 ? {} : { summary: turnInput.summary },
|
|
866
929
|
...turnInput.deadlineAt === void 0 ? {} : { deadlineAt: turnInput.deadlineAt }
|
|
867
930
|
});
|
|
@@ -873,13 +936,15 @@ function validateAgentProviderSession(input) {
|
|
|
873
936
|
`Provider ${providerKey} does not support ${parsedInput.interactionMode} turn interaction mode.`
|
|
874
937
|
);
|
|
875
938
|
}
|
|
939
|
+
const binding2 = validationOwner.admitTurnOutput(parsedInput.output, Reflect.has(turnInput, "output"));
|
|
876
940
|
const token = validationOwner.reserveExecution();
|
|
877
941
|
try {
|
|
878
942
|
return validationOwner.installCallerExecution(token, {
|
|
879
943
|
...parsedInput,
|
|
944
|
+
...parsedInput.output === void 0 || binding2 === void 0 ? {} : { output: binding2.request },
|
|
880
945
|
...turnInput.signal === void 0 ? {} : { signal: turnInput.signal },
|
|
881
946
|
...turnInput.onProviderExecutionStarted === void 0 ? {} : { onProviderExecutionStarted: turnInput.onProviderExecutionStarted }
|
|
882
|
-
}, (inputTurn) => input.candidate.startTurn(inputTurn)).execution;
|
|
947
|
+
}, (inputTurn) => input.candidate.startTurn(inputTurn), binding2).execution;
|
|
883
948
|
} catch (error) {
|
|
884
949
|
validationOwner.releaseExecution(token);
|
|
885
950
|
throw error;
|
|
@@ -908,6 +973,7 @@ function validateAgentProviderSession(input) {
|
|
|
908
973
|
const settleActiveInterruption = trackActiveTurnOperation(
|
|
909
974
|
targetedActiveTurn
|
|
910
975
|
);
|
|
976
|
+
targetedTurn.owner.closeInputAdmission();
|
|
911
977
|
try {
|
|
912
978
|
const suspendedRequests = targetedTurn.owner.suspendRequests();
|
|
913
979
|
let result;
|
|
@@ -939,6 +1005,13 @@ function validateAgentProviderSession(input) {
|
|
|
939
1005
|
steerTurn: async (steeringInput) => {
|
|
940
1006
|
requireUsable();
|
|
941
1007
|
throwIfAgentOperationAborted(steeringInput.signal);
|
|
1008
|
+
if (Reflect.has(steeringInput, "output")) {
|
|
1009
|
+
throwAgentProviderContractError(
|
|
1010
|
+
providerKey,
|
|
1011
|
+
"structured_output_scope_mismatch",
|
|
1012
|
+
"Steering cannot change a turn's structured-output request."
|
|
1013
|
+
);
|
|
1014
|
+
}
|
|
942
1015
|
const turnId = parseAgentTurnId(steeringInput.turnId);
|
|
943
1016
|
if (validationOwner.activeTurn?.turnId !== turnId || !validationOwner.activeTurn.owner.hasEntered() || validationOwner.activeTurn.state.terminal || validationOwner.activeTurn.pendingRequests.size > 0) {
|
|
944
1017
|
throwAgentProviderContractError(
|
|
@@ -1455,7 +1528,7 @@ function validateAgentProviderSession(input) {
|
|
|
1455
1528
|
validationOwner.stop();
|
|
1456
1529
|
input.hostBindingLease?.stop();
|
|
1457
1530
|
const closingTurn = validationOwner.activeTurn;
|
|
1458
|
-
closingTurn?.owner.stop(new DOMException("The provider session was closed.", "AbortError"));
|
|
1531
|
+
closingTurn?.owner.stop(new DOMException("The provider session was closed.", "AbortError"), "closed");
|
|
1459
1532
|
const cleanup = async () => {
|
|
1460
1533
|
if (!providerClosed) {
|
|
1461
1534
|
await input.candidate.close(closeInput);
|
|
@@ -1623,6 +1696,7 @@ async function openIdentityCreatingAgentProviderSession(input) {
|
|
|
1623
1696
|
}
|
|
1624
1697
|
}
|
|
1625
1698
|
export {
|
|
1699
|
+
assertAgentTurnInputCapability,
|
|
1626
1700
|
closeRejectedAgentProviderSession,
|
|
1627
1701
|
createAgentSessionValidationOwner,
|
|
1628
1702
|
openIdentityCreatingAgentProviderSession,
|
package/dist/sessions.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentAuthenticationFlow, AgentCollaborationControlInput, AgentCollaborationNode, AgentCollaborationSpawnInput, AgentConfigurationCatalog, AgentConfigurationSelectionInput, AgentError, AgentGeneratedResourceDescriptor, AgentGeneratedResourceId, AgentManagedContentCatalog, AgentOperationCatalog, AgentOperationInvocation, AgentOperationResult, AgentRequestResolution, AgentSessionBinding, AgentSessionBranchSource, AgentSessionConfiguration, AgentSessionId, AgentTurnId, AgentTurnInputContent, AgentTurnInteractionMode, AgentTurnInputPart, AgentTurnInterruptionReason } from "@agen-ai/agent-protocol";
|
|
1
|
+
import type { AgentAuthenticationFlow, AgentCollaborationControlInput, AgentCollaborationNode, AgentCollaborationSpawnInput, AgentConfigurationCatalog, AgentConfigurationSelectionInput, AgentError, AgentGeneratedResourceDescriptor, AgentGeneratedResourceId, AgentManagedContentCatalog, AgentOperationCatalog, AgentOperationInvocation, AgentOperationResult, AgentRequestResolution, AgentSessionBinding, AgentSessionBranchSource, AgentSessionConfiguration, AgentSessionId, AgentStructuredOutputRequest, AgentTurnId, AgentTurnInputContent, AgentTurnInteractionMode, AgentTurnInputPart, AgentTurnInterruptionReason } from "@agen-ai/agent-protocol";
|
|
2
2
|
import type { AgentNativeContinuationContext, AgentNativeContinuationSupport } from "./nativeContinuations/types.js";
|
|
3
3
|
import type { MaybePromise } from "./foundation.js";
|
|
4
4
|
import type { AgentSessionHostBinding, AgentSessionHostBindingSupport } from "./hostBindings/types.js";
|
|
@@ -6,6 +6,7 @@ import type { AgentProviderOutput } from "./outputs.js";
|
|
|
6
6
|
import type { AgentArtifactCandidate } from "./artifacts.js";
|
|
7
7
|
import type { AgentProviderSessionInteractionContext, AgentSessionInteractionContext, AgentSessionInteractionSupport } from "./sessionInteractions/types.js";
|
|
8
8
|
import type { AgentEnvironmentObservationPort } from "./environment/types.js";
|
|
9
|
+
import type { AgentExecutionInput, AgentExecutionInputSupport } from "./executionInput/types.js";
|
|
9
10
|
export interface AgentProviderSessionContext {
|
|
10
11
|
readonly sessionId: AgentSessionId;
|
|
11
12
|
readonly workingDirectory: string;
|
|
@@ -17,6 +18,7 @@ export interface AgentProviderSessionContext {
|
|
|
17
18
|
export type AgentSessionBindingCreatedObserver = (binding: AgentSessionBinding) => void;
|
|
18
19
|
export interface AgentProviderCreateSessionInput extends AgentProviderSessionContext {
|
|
19
20
|
readonly onBindingCreated: AgentSessionBindingCreatedObserver;
|
|
21
|
+
readonly output?: AgentStructuredOutputRequest;
|
|
20
22
|
}
|
|
21
23
|
export interface AgentProviderResumeSessionInput extends AgentProviderSessionContext {
|
|
22
24
|
readonly binding: AgentSessionBinding;
|
|
@@ -33,6 +35,7 @@ export interface AgentProviderStartTurnInput {
|
|
|
33
35
|
readonly parts: readonly AgentTurnInputPart[];
|
|
34
36
|
readonly summary?: string;
|
|
35
37
|
readonly deadlineAt?: string;
|
|
38
|
+
readonly output?: AgentStructuredOutputRequest;
|
|
36
39
|
readonly signal?: AbortSignal;
|
|
37
40
|
readonly onProviderExecutionStarted?: AgentProviderExecutionStartedObserver;
|
|
38
41
|
}
|
|
@@ -55,6 +58,7 @@ export type AgentRequestResolutionResult = Readonly<{
|
|
|
55
58
|
export interface AgentProviderTurnExecution {
|
|
56
59
|
readonly turnId: AgentTurnId;
|
|
57
60
|
readonly outputs: AsyncIterable<AgentProviderOutput>;
|
|
61
|
+
readonly input?: AgentExecutionInput;
|
|
58
62
|
readonly resolveRequest: (input: AgentProviderResolveRequestInput) => Promise<AgentRequestResolutionResult>;
|
|
59
63
|
}
|
|
60
64
|
export interface AgentProviderInterruptTurnInput {
|
|
@@ -215,6 +219,7 @@ export type AgentProviderAuthentication = Readonly<{
|
|
|
215
219
|
cancel: (input: AgentProviderAuthenticationCancelInput) => MaybePromise<AgentProviderOperationResult>;
|
|
216
220
|
}>;
|
|
217
221
|
export interface AgentProviderAdapter {
|
|
222
|
+
readonly executionInput?: AgentExecutionInputSupport;
|
|
218
223
|
readonly sessionInteractions?: AgentSessionInteractionSupport;
|
|
219
224
|
readonly hostBinding?: AgentSessionHostBindingSupport;
|
|
220
225
|
readonly nativeContinuations?: AgentNativeContinuationSupport;
|
|
@@ -229,6 +234,7 @@ export type AgentSessionOpenContext = Omit<AgentProviderSessionContext, "interac
|
|
|
229
234
|
}>;
|
|
230
235
|
export type AgentCreateSessionInput = AgentSessionOpenContext & Readonly<{
|
|
231
236
|
onBindingCreated: AgentSessionBindingCreatedObserver;
|
|
237
|
+
output?: AgentStructuredOutputRequest;
|
|
232
238
|
}>;
|
|
233
239
|
export type AgentResumeSessionInput = AgentSessionOpenContext & Readonly<{
|
|
234
240
|
binding: AgentSessionBinding;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type AgentCapabilities, type AgentStructuredOutputRequest } from "@agen-ai/agent-protocol";
|
|
2
|
+
export interface AgentStructuredOutputBinding {
|
|
3
|
+
readonly request: AgentStructuredOutputRequest;
|
|
4
|
+
readonly maxOutputBytes: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function admitAgentStructuredOutputOpening(input: Readonly<{
|
|
7
|
+
capabilities: AgentCapabilities;
|
|
8
|
+
operation: "create" | "resume" | "branch";
|
|
9
|
+
output: unknown;
|
|
10
|
+
}>): AgentStructuredOutputBinding | undefined;
|
|
11
|
+
export declare function admitAgentStructuredOutputTurn(input: Readonly<{
|
|
12
|
+
capabilities: AgentCapabilities;
|
|
13
|
+
binding?: AgentStructuredOutputBinding;
|
|
14
|
+
output: unknown;
|
|
15
|
+
}>): AgentStructuredOutputBinding | undefined;
|
|
16
|
+
//# sourceMappingURL=admission.d.ts.map
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentProtocolValidationError,
|
|
3
|
+
agentProtocolSerializedJsonBytes,
|
|
4
|
+
parseAgentOutputSchema
|
|
5
|
+
} from "@agen-ai/agent-protocol";
|
|
6
|
+
import { throwAgentProviderContractError } from "../contractErrors.js";
|
|
7
|
+
import { hasExactOwnKeys } from "../internal/objectShape.js";
|
|
8
|
+
function parseOutputRequest(input, maxOutputBytes) {
|
|
9
|
+
const invalid = () => {
|
|
10
|
+
throw new AgentProtocolValidationError([{
|
|
11
|
+
code: "invalid_structured_output_request",
|
|
12
|
+
message: "Structured output must be a plain json_schema request with only kind and schema data properties.",
|
|
13
|
+
path: ["output"]
|
|
14
|
+
}]);
|
|
15
|
+
};
|
|
16
|
+
if (input === null || typeof input !== "object") return invalid();
|
|
17
|
+
let kind;
|
|
18
|
+
let schema;
|
|
19
|
+
try {
|
|
20
|
+
const prototype = Object.getPrototypeOf(input);
|
|
21
|
+
if (prototype !== Object.prototype && prototype !== null || !hasExactOwnKeys(input, ["kind", "schema"])) return invalid();
|
|
22
|
+
const kindDescriptor = Object.getOwnPropertyDescriptor(input, "kind");
|
|
23
|
+
const schemaDescriptor = Object.getOwnPropertyDescriptor(input, "schema");
|
|
24
|
+
if (!kindDescriptor || !("value" in kindDescriptor) || !kindDescriptor.enumerable || !schemaDescriptor || !("value" in schemaDescriptor) || !schemaDescriptor.enumerable) return invalid();
|
|
25
|
+
kind = kindDescriptor.value;
|
|
26
|
+
schema = schemaDescriptor.value;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error instanceof AgentProtocolValidationError) throw error;
|
|
29
|
+
return invalid();
|
|
30
|
+
}
|
|
31
|
+
if (kind !== "json_schema") return invalid();
|
|
32
|
+
return Object.freeze({ kind, schema: parseAgentOutputSchema(schema, { maxOutputBytes }) });
|
|
33
|
+
}
|
|
34
|
+
function admitRequest(capabilities, output) {
|
|
35
|
+
const capability = capabilities.turns.structuredOutput;
|
|
36
|
+
if (capability.kind === "unsupported") {
|
|
37
|
+
throwAgentProviderContractError(
|
|
38
|
+
capabilities.providerKey,
|
|
39
|
+
"structured_output_unsupported",
|
|
40
|
+
"Provider does not support structured output."
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const request = parseOutputRequest(output, capability.maxOutputBytes);
|
|
44
|
+
if (agentProtocolSerializedJsonBytes(request.schema) > capability.maxSchemaBytes) {
|
|
45
|
+
throwAgentProviderContractError(
|
|
46
|
+
capabilities.providerKey,
|
|
47
|
+
"invalid_structured_output",
|
|
48
|
+
"Structured output schema exceeds the provider's advertised byte limit."
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return Object.freeze({ request, maxOutputBytes: capability.maxOutputBytes });
|
|
52
|
+
}
|
|
53
|
+
function admitAgentStructuredOutputOpening(input) {
|
|
54
|
+
if (input.output === void 0) return void 0;
|
|
55
|
+
const { capabilities } = input;
|
|
56
|
+
if (input.operation !== "create") {
|
|
57
|
+
throwAgentProviderContractError(
|
|
58
|
+
capabilities.providerKey,
|
|
59
|
+
"structured_output_unsupported",
|
|
60
|
+
"Structured output cannot be restored through resume or branch."
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
const capability = capabilities.turns.structuredOutput;
|
|
64
|
+
if (capability.kind === "supported" && capability.scope !== "session") {
|
|
65
|
+
throwAgentProviderContractError(
|
|
66
|
+
capabilities.providerKey,
|
|
67
|
+
"structured_output_scope_mismatch",
|
|
68
|
+
"Provider accepts structured output only when starting a turn."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
return admitRequest(capabilities, input.output);
|
|
72
|
+
}
|
|
73
|
+
function admitAgentStructuredOutputTurn(input) {
|
|
74
|
+
if (input.output === void 0) return input.binding;
|
|
75
|
+
const { capabilities } = input;
|
|
76
|
+
const capability = capabilities.turns.structuredOutput;
|
|
77
|
+
if (input.binding || capability.kind === "supported" && capability.scope !== "turn") {
|
|
78
|
+
throwAgentProviderContractError(
|
|
79
|
+
capabilities.providerKey,
|
|
80
|
+
"structured_output_scope_mismatch",
|
|
81
|
+
"Session-scoped structured output cannot be overridden or supplied on a turn."
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
return admitRequest(capabilities, input.output);
|
|
85
|
+
}
|
|
86
|
+
export {
|
|
87
|
+
admitAgentStructuredOutputOpening,
|
|
88
|
+
admitAgentStructuredOutputTurn
|
|
89
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type AgentOutputSchema, type AgentStructuredOutputResult, type AgentStructuredOutputUnavailableReason } from "@agen-ai/agent-protocol";
|
|
2
|
+
export type AgentStructuredOutputCandidate = Readonly<{
|
|
3
|
+
kind: "json_text";
|
|
4
|
+
text: string;
|
|
5
|
+
}> | Readonly<{
|
|
6
|
+
kind: "json_value";
|
|
7
|
+
value: unknown;
|
|
8
|
+
}> | Readonly<{
|
|
9
|
+
kind: "unavailable";
|
|
10
|
+
reason: AgentStructuredOutputUnavailableReason;
|
|
11
|
+
}>;
|
|
12
|
+
export interface CreateAgentStructuredOutputCandidateInput {
|
|
13
|
+
readonly schema: AgentOutputSchema;
|
|
14
|
+
readonly maxOutputBytes?: number;
|
|
15
|
+
readonly candidate: AgentStructuredOutputCandidate;
|
|
16
|
+
}
|
|
17
|
+
export type AgentStructuredOutputCandidateResult = Exclude<AgentStructuredOutputResult, Readonly<{
|
|
18
|
+
kind: "not_requested";
|
|
19
|
+
}>>;
|
|
20
|
+
export declare function validateAgentStructuredOutputCandidate(schema: AgentOutputSchema, value: unknown, maxOutputBytes: number): AgentStructuredOutputCandidateResult;
|
|
21
|
+
export declare function createAgentStructuredOutputCandidate(input: CreateAgentStructuredOutputCandidateInput): AgentStructuredOutputCandidateResult;
|
|
22
|
+
//# sourceMappingURL=candidate.d.ts.map
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AGENT_OUTPUT_RAW_JSON_BYTES_LIMIT,
|
|
3
|
+
AGENT_OUTPUT_VALUE_BYTES_LIMIT,
|
|
4
|
+
AGENT_STRUCTURED_OUTPUT_UNAVAILABLE_REASONS,
|
|
5
|
+
parseAgentOutputSchema,
|
|
6
|
+
validateAgentOutputValue
|
|
7
|
+
} from "@agen-ai/agent-protocol";
|
|
8
|
+
function freezeJson(value) {
|
|
9
|
+
if (value === null || typeof value !== "object") return;
|
|
10
|
+
for (const child of Object.values(value)) freezeJson(child);
|
|
11
|
+
Object.freeze(value);
|
|
12
|
+
}
|
|
13
|
+
function validateAgentStructuredOutputCandidate(schema, value, maxOutputBytes) {
|
|
14
|
+
const parsed = validateAgentOutputValue(schema, value, { maxOutputBytes });
|
|
15
|
+
if (!parsed.success) {
|
|
16
|
+
if (parsed.issues.some((issue) => issue.code === "output_limit_exceeded")) {
|
|
17
|
+
return Object.freeze({ kind: "unavailable", reason: "output_limit_exceeded" });
|
|
18
|
+
}
|
|
19
|
+
if (parsed.issues.some((issue) => issue.code === "invalid_json_data")) {
|
|
20
|
+
return Object.freeze({ kind: "unavailable", reason: "invalid_json" });
|
|
21
|
+
}
|
|
22
|
+
return Object.freeze({ kind: "unavailable", reason: "schema_mismatch", issues: Object.freeze(parsed.issues.map((issue) => Object.freeze({
|
|
23
|
+
...issue,
|
|
24
|
+
path: Object.freeze([...issue.path])
|
|
25
|
+
}))) });
|
|
26
|
+
}
|
|
27
|
+
freezeJson(parsed.data);
|
|
28
|
+
return Object.freeze({ kind: "json", value: parsed.data });
|
|
29
|
+
}
|
|
30
|
+
function createAgentStructuredOutputCandidate(input) {
|
|
31
|
+
const schema = parseAgentOutputSchema(input.schema);
|
|
32
|
+
const maxOutputBytes = input.maxOutputBytes ?? AGENT_OUTPUT_VALUE_BYTES_LIMIT;
|
|
33
|
+
if (!Number.isSafeInteger(maxOutputBytes) || maxOutputBytes <= 0 || maxOutputBytes > AGENT_OUTPUT_VALUE_BYTES_LIMIT) {
|
|
34
|
+
throw new RangeError("Structured output byte limit must be a positive integer within the portable profile ceiling.");
|
|
35
|
+
}
|
|
36
|
+
const { candidate } = input;
|
|
37
|
+
switch (candidate.kind) {
|
|
38
|
+
case "unavailable":
|
|
39
|
+
if (!AGENT_STRUCTURED_OUTPUT_UNAVAILABLE_REASONS.includes(candidate.reason)) {
|
|
40
|
+
throw new TypeError("Structured output candidate has an unsupported unavailable reason.");
|
|
41
|
+
}
|
|
42
|
+
return Object.freeze({ kind: "unavailable", reason: candidate.reason });
|
|
43
|
+
case "json_text": {
|
|
44
|
+
if (typeof candidate.text !== "string") throw new TypeError("Structured JSON text candidate must contain a string.");
|
|
45
|
+
if (candidate.text.length > AGENT_OUTPUT_RAW_JSON_BYTES_LIMIT || Buffer.byteLength(candidate.text, "utf8") > AGENT_OUTPUT_RAW_JSON_BYTES_LIMIT) {
|
|
46
|
+
return Object.freeze({ kind: "unavailable", reason: "output_limit_exceeded" });
|
|
47
|
+
}
|
|
48
|
+
let value;
|
|
49
|
+
try {
|
|
50
|
+
value = JSON.parse(candidate.text);
|
|
51
|
+
} catch {
|
|
52
|
+
return Object.freeze({ kind: "unavailable", reason: "invalid_json" });
|
|
53
|
+
}
|
|
54
|
+
return validateAgentStructuredOutputCandidate(schema, value, maxOutputBytes);
|
|
55
|
+
}
|
|
56
|
+
case "json_value":
|
|
57
|
+
return validateAgentStructuredOutputCandidate(schema, candidate.value, maxOutputBytes);
|
|
58
|
+
}
|
|
59
|
+
throw new TypeError("Structured output candidate kind is unsupported.");
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
createAgentStructuredOutputCandidate,
|
|
63
|
+
validateAgentStructuredOutputCandidate
|
|
64
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentProviderKey, AgentStructuredOutputResult } from "@agen-ai/agent-protocol";
|
|
2
|
+
import type { AgentStructuredOutputBinding } from "./admission.js";
|
|
3
|
+
export declare function validateAgentStructuredOutputResult(input: Readonly<{
|
|
4
|
+
providerKey: AgentProviderKey;
|
|
5
|
+
binding?: AgentStructuredOutputBinding;
|
|
6
|
+
result: AgentStructuredOutputResult;
|
|
7
|
+
}>): AgentStructuredOutputResult;
|
|
8
|
+
//# sourceMappingURL=validation.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { throwAgentProviderContractError } from "../contractErrors.js";
|
|
2
|
+
import { validateAgentStructuredOutputCandidate } from "./candidate.js";
|
|
3
|
+
function validateAgentStructuredOutputResult(input) {
|
|
4
|
+
const { binding, result } = input;
|
|
5
|
+
if (!binding) {
|
|
6
|
+
if (result.kind !== "not_requested") {
|
|
7
|
+
throwAgentProviderContractError(
|
|
8
|
+
input.providerKey,
|
|
9
|
+
"invalid_structured_output",
|
|
10
|
+
"Provider reported structured output for a turn without an admitted schema."
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
return result;
|
|
14
|
+
}
|
|
15
|
+
if (result.kind === "not_requested") {
|
|
16
|
+
throwAgentProviderContractError(
|
|
17
|
+
input.providerKey,
|
|
18
|
+
"invalid_structured_output",
|
|
19
|
+
"Provider omitted the admitted structured-output contract."
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return result.kind === "json" ? validateAgentStructuredOutputCandidate(binding.request.schema, result.value, binding.maxOutputBytes) : result;
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
validateAgentStructuredOutputResult
|
|
26
|
+
};
|