@agen-ai/agent-runtime 0.2.2 → 0.2.3
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 +25 -8
- package/dist/configurationValidation.js +12 -17
- package/dist/contractErrors.d.ts +2 -2
- package/dist/contractErrors.js +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/interactionValidation.d.ts +23 -0
- package/dist/interactionValidation.js +238 -0
- package/dist/outputValidation.d.ts +4 -1
- package/dist/outputValidation.js +42 -4
- package/dist/sessionValidation.js +678 -18
- package/dist/sessions.d.ts +70 -4
- package/dist/testing/conformance.d.ts +5 -2
- package/dist/testing/conformance.js +161 -4
- package/dist/testing/fakeProvider.js +220 -17
- package/package.json +2 -2
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AGENT_COLLABORATION_GRAPH_LIMITS,
|
|
2
3
|
matchesAgentSessionBinding,
|
|
4
|
+
parseAgentCollaborationControlInput,
|
|
5
|
+
parseAgentCollaborationSpawnInput,
|
|
6
|
+
parseAgentConfigurationSelectionFor,
|
|
7
|
+
parseAgentGeneratedResourceId,
|
|
8
|
+
parseAgentOperationInvocation,
|
|
9
|
+
parseAgentOperationInvocationFor,
|
|
3
10
|
parseAgentRequestResolution,
|
|
4
11
|
parseAgentRequestResolutionFor,
|
|
5
12
|
parseAgentSessionBinding,
|
|
6
|
-
parseAgentSessionConfiguration,
|
|
7
13
|
parseAgentTurnId,
|
|
8
14
|
parseAgentTurnInputContent,
|
|
9
15
|
parseAgentTurnInterruptionInput,
|
|
10
16
|
parseAgentTurnRunInput
|
|
11
17
|
} from "@agen-ai/agent-protocol";
|
|
12
18
|
import {
|
|
13
|
-
|
|
14
|
-
} from "./
|
|
19
|
+
createAgentArtifactCandidate
|
|
20
|
+
} from "./artifacts.js";
|
|
21
|
+
import {
|
|
22
|
+
validateAgentCollaborationNodeForCapabilities,
|
|
23
|
+
validateAgentConfigurationCatalogForCapabilities,
|
|
24
|
+
validateAgentGeneratedResourceForCapabilities,
|
|
25
|
+
validateAgentIntegrationCatalogForCapabilities,
|
|
26
|
+
validateAgentManagedContentCatalogForCapabilities,
|
|
27
|
+
validateAgentOperationCatalogForCapabilities,
|
|
28
|
+
validateAgentOperationResultForInvocation,
|
|
29
|
+
validateAgentOperationResultTransition
|
|
30
|
+
} from "./interactionValidation.js";
|
|
15
31
|
import {
|
|
16
32
|
AgentProviderDelegatedOperationError,
|
|
17
33
|
throwAgentProviderContractError
|
|
@@ -24,15 +40,59 @@ import {
|
|
|
24
40
|
validateAgentProviderOutputForContext
|
|
25
41
|
} from "./outputValidation.js";
|
|
26
42
|
import { validateAgentTurnSteeringResult } from "./steeringValidation.js";
|
|
43
|
+
function hasExactOwnKeys(candidate, expectedKeys) {
|
|
44
|
+
const ownKeys = Reflect.ownKeys(candidate);
|
|
45
|
+
if (ownKeys.some((key) => typeof key !== "string")) return false;
|
|
46
|
+
const actualKeys = ownKeys.sort();
|
|
47
|
+
const canonicalExpectedKeys = [...expectedKeys].sort();
|
|
48
|
+
return actualKeys.length === canonicalExpectedKeys.length && actualKeys.every((key, index) => key === canonicalExpectedKeys[index]);
|
|
49
|
+
}
|
|
27
50
|
function validateSessionPorts(capabilities, session) {
|
|
28
|
-
if (
|
|
51
|
+
if (!hasExactOwnKeys(session, [
|
|
52
|
+
"binding",
|
|
53
|
+
"runTurn",
|
|
54
|
+
"resolveRequest",
|
|
55
|
+
"interruption",
|
|
56
|
+
"steering",
|
|
57
|
+
"configuration",
|
|
58
|
+
"operations",
|
|
59
|
+
"managedContent",
|
|
60
|
+
"integrations",
|
|
61
|
+
"collaboration",
|
|
62
|
+
"generatedResources",
|
|
63
|
+
"close"
|
|
64
|
+
]) || typeof session.runTurn !== "function" || typeof session.resolveRequest !== "function" || typeof session.close !== "function" || session.interruption === null || typeof session.interruption !== "object" || !["supported", "unsupported"].includes(session.interruption.kind) || session.steering === null || typeof session.steering !== "object" || !["supported", "unsupported"].includes(session.steering.kind) || session.configuration === null || typeof session.configuration !== "object" || !["managed", "selectable"].includes(session.configuration.kind) || session.operations === null || typeof session.operations !== "object" || !["supported", "unsupported"].includes(session.operations.kind) || session.managedContent === null || typeof session.managedContent !== "object" || !["supported", "unsupported"].includes(session.managedContent.kind) || session.integrations === null || typeof session.integrations !== "object" || !["supported", "unsupported"].includes(session.integrations.kind) || session.collaboration === null || typeof session.collaboration !== "object" || !["supported", "unsupported"].includes(session.collaboration.kind) || session.generatedResources === null || typeof session.generatedResources !== "object" || !["supported", "unsupported"].includes(session.generatedResources.kind)) {
|
|
29
65
|
throwAgentProviderContractError(
|
|
30
66
|
capabilities.providerKey,
|
|
31
67
|
"invalid_session",
|
|
32
68
|
`Provider ${capabilities.providerKey} returned an incomplete session.`
|
|
33
69
|
);
|
|
34
70
|
}
|
|
35
|
-
if (
|
|
71
|
+
if (!hasExactOwnKeys(
|
|
72
|
+
session.interruption,
|
|
73
|
+
session.interruption.kind === "supported" ? ["kind", "interruptTurn"] : ["kind"]
|
|
74
|
+
) || !hasExactOwnKeys(
|
|
75
|
+
session.steering,
|
|
76
|
+
session.steering.kind === "supported" ? ["kind", "steerTurn"] : ["kind"]
|
|
77
|
+
) || !hasExactOwnKeys(
|
|
78
|
+
session.configuration,
|
|
79
|
+
session.configuration.kind === "selectable" ? ["kind", "listConfiguration", "applyConfigurationSelection"] : ["kind"]
|
|
80
|
+
) || !hasExactOwnKeys(
|
|
81
|
+
session.operations,
|
|
82
|
+
session.operations.kind === "supported" ? ["kind", "listOperations", "invokeOperation"] : ["kind"]
|
|
83
|
+
) || !hasExactOwnKeys(
|
|
84
|
+
session.managedContent,
|
|
85
|
+
session.managedContent.kind === "supported" ? ["kind", "listManagedContent"] : ["kind"]
|
|
86
|
+
) || !hasExactOwnKeys(
|
|
87
|
+
session.integrations,
|
|
88
|
+
session.integrations.kind === "supported" ? ["kind", "observeIntegrations"] : ["kind"]
|
|
89
|
+
) || !hasExactOwnKeys(
|
|
90
|
+
session.collaboration,
|
|
91
|
+
session.collaboration.kind === "supported" ? ["kind", "spawnCollaboration", "controlCollaboration"] : ["kind"]
|
|
92
|
+
) || !hasExactOwnKeys(
|
|
93
|
+
session.generatedResources,
|
|
94
|
+
session.generatedResources.kind === "supported" ? ["kind", "getGeneratedResource"] : ["kind"]
|
|
95
|
+
) || session.interruption.kind === "supported" !== capabilities.turns.interrupt || session.steering.kind === "supported" !== (capabilities.turns.steer.kind === "supported") || session.configuration.kind !== capabilities.configuration.kind || session.interruption.kind === "supported" && typeof session.interruption.interruptTurn !== "function" || session.steering.kind === "supported" && typeof session.steering.steerTurn !== "function" || session.configuration.kind === "selectable" && (typeof session.configuration.listConfiguration !== "function" || typeof session.configuration.applyConfigurationSelection !== "function") || session.operations.kind === "supported" !== (capabilities.operations.kind === "supported") || session.operations.kind === "supported" && (typeof session.operations.listOperations !== "function" || typeof session.operations.invokeOperation !== "function") || session.managedContent.kind === "supported" !== (capabilities.managedContent.kind === "supported") || session.managedContent.kind === "supported" && typeof session.managedContent.listManagedContent !== "function" || session.integrations.kind === "supported" !== (capabilities.integrations.kind === "supported") || session.integrations.kind === "supported" && typeof session.integrations.observeIntegrations !== "function" || session.collaboration.kind === "supported" !== (capabilities.collaboration.kind === "supported") || session.collaboration.kind === "supported" && (typeof session.collaboration.spawnCollaboration !== "function" || typeof session.collaboration.controlCollaboration !== "function") || session.generatedResources.kind === "supported" !== (capabilities.generatedResources.kind === "supported") || session.generatedResources.kind === "supported" && typeof session.generatedResources.getGeneratedResource !== "function") {
|
|
36
96
|
throwAgentProviderContractError(
|
|
37
97
|
capabilities.providerKey,
|
|
38
98
|
"capability_port_mismatch",
|
|
@@ -40,6 +100,58 @@ function validateSessionPorts(capabilities, session) {
|
|
|
40
100
|
);
|
|
41
101
|
}
|
|
42
102
|
}
|
|
103
|
+
const TERMINAL_COLLABORATION_STATUSES = /* @__PURE__ */ new Set([
|
|
104
|
+
"completed",
|
|
105
|
+
"failed",
|
|
106
|
+
"canceled"
|
|
107
|
+
]);
|
|
108
|
+
function evaluateCollaborationGraphAdmission(input) {
|
|
109
|
+
const existing = input.nodes.get(input.candidate.collaborationId);
|
|
110
|
+
if (existing !== void 0) {
|
|
111
|
+
const parent2 = existing.parentCollaborationId === void 0 ? void 0 : input.nodes.get(existing.parentCollaborationId);
|
|
112
|
+
return parent2 === void 0 ? Object.freeze({ kind: "admitted" }) : Object.freeze({ kind: "admitted", parent: parent2 });
|
|
113
|
+
}
|
|
114
|
+
const reservation = input.reservations.get(input.candidate.collaborationId);
|
|
115
|
+
if (reservation !== void 0 && reservation.parentCollaborationId !== input.candidate.parentCollaborationId) {
|
|
116
|
+
return Object.freeze({ kind: "conflict" });
|
|
117
|
+
}
|
|
118
|
+
const parent = input.candidate.parentCollaborationId === void 0 ? void 0 : input.nodes.get(input.candidate.parentCollaborationId);
|
|
119
|
+
if (input.candidate.parentCollaborationId === void 0 && input.candidate.rootCollaborationId !== input.candidate.collaborationId || input.candidate.parentCollaborationId !== void 0 && (parent === void 0 || input.candidate.rootCollaborationId !== parent.rootCollaborationId || TERMINAL_COLLABORATION_STATUSES.has(parent.status) || parent.closedAt !== void 0)) {
|
|
120
|
+
return Object.freeze({ kind: "conflict" });
|
|
121
|
+
}
|
|
122
|
+
let depth = 1;
|
|
123
|
+
const visitedIds = /* @__PURE__ */ new Set([input.candidate.collaborationId]);
|
|
124
|
+
for (let ancestor = parent; ancestor !== void 0; ) {
|
|
125
|
+
if (visitedIds.has(ancestor.collaborationId)) {
|
|
126
|
+
return Object.freeze({ kind: "conflict" });
|
|
127
|
+
}
|
|
128
|
+
visitedIds.add(ancestor.collaborationId);
|
|
129
|
+
depth += 1;
|
|
130
|
+
if (ancestor.parentCollaborationId === void 0) break;
|
|
131
|
+
ancestor = input.nodes.get(ancestor.parentCollaborationId);
|
|
132
|
+
if (ancestor === void 0) {
|
|
133
|
+
return Object.freeze({ kind: "conflict" });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (reservation !== void 0) {
|
|
137
|
+
return parent === void 0 ? Object.freeze({ kind: "admitted" }) : Object.freeze({ kind: "admitted", parent });
|
|
138
|
+
}
|
|
139
|
+
const unmaterializedReservations = [...input.reservations].filter(
|
|
140
|
+
([collaborationId]) => !input.nodes.has(collaborationId)
|
|
141
|
+
);
|
|
142
|
+
const childCount = parent === void 0 ? 0 : [...input.nodes.values()].filter(
|
|
143
|
+
(node) => node.parentCollaborationId === parent.collaborationId
|
|
144
|
+
).length + unmaterializedReservations.filter(
|
|
145
|
+
([, retainedReservation]) => retainedReservation.parentCollaborationId === parent.collaborationId
|
|
146
|
+
).length;
|
|
147
|
+
const activeCount = [...input.nodes.values()].filter(
|
|
148
|
+
(node) => !TERMINAL_COLLABORATION_STATUSES.has(node.status)
|
|
149
|
+
).length + unmaterializedReservations.length;
|
|
150
|
+
if (input.nodes.size + unmaterializedReservations.length >= AGENT_COLLABORATION_GRAPH_LIMITS.maxNodes || childCount >= input.capability.maxChildrenPerNode || depth > input.capability.maxDepth || input.candidate.active && activeCount >= input.capability.maxActiveNodes) {
|
|
151
|
+
return Object.freeze({ kind: "capacity_exceeded" });
|
|
152
|
+
}
|
|
153
|
+
return parent === void 0 ? Object.freeze({ kind: "admitted" }) : Object.freeze({ kind: "admitted", parent });
|
|
154
|
+
}
|
|
43
155
|
function invalidTurnSequence(providerKey, message) {
|
|
44
156
|
return throwAgentProviderContractError(
|
|
45
157
|
providerKey,
|
|
@@ -59,7 +171,10 @@ function completeTurnSequence(input) {
|
|
|
59
171
|
}
|
|
60
172
|
const FINAL_DIFF_TRAILING_EVENT_TYPES = [
|
|
61
173
|
"artifact.referenced",
|
|
174
|
+
"collaboration.updated",
|
|
175
|
+
"operation.updated",
|
|
62
176
|
"provider.diagnostic",
|
|
177
|
+
"resource.updated",
|
|
63
178
|
"runtime.error",
|
|
64
179
|
"runtime.warning",
|
|
65
180
|
"turn.completed"
|
|
@@ -305,6 +420,84 @@ function observeTurnOutput(input) {
|
|
|
305
420
|
observeContextMaterializationBoundary(input.contextUsageState);
|
|
306
421
|
}
|
|
307
422
|
if (input.output.kind !== "event") return;
|
|
423
|
+
if (input.output.event.type === "operation.updated") {
|
|
424
|
+
const result = validateAgentOperationResultTransition({
|
|
425
|
+
providerKey: input.providerKey,
|
|
426
|
+
candidate: input.output.event.payload.result,
|
|
427
|
+
previous: input.interactionState.operationResults.get(
|
|
428
|
+
input.output.event.payload.result.invocationId
|
|
429
|
+
)
|
|
430
|
+
});
|
|
431
|
+
input.interactionState.operationResults.set(result.invocationId, result);
|
|
432
|
+
const invocation = input.interactionState.operationInvocations.get(
|
|
433
|
+
result.invocationId
|
|
434
|
+
);
|
|
435
|
+
if (invocation !== void 0) invocation.result = result;
|
|
436
|
+
}
|
|
437
|
+
if (input.output.event.type === "collaboration.updated") {
|
|
438
|
+
const node = validateAgentCollaborationNodeForCapabilities({
|
|
439
|
+
capabilities: input.capabilities,
|
|
440
|
+
candidate: input.output.event.payload.node,
|
|
441
|
+
previous: input.interactionState.collaborationNodes.get(
|
|
442
|
+
input.output.event.payload.node.collaborationId
|
|
443
|
+
)
|
|
444
|
+
});
|
|
445
|
+
const capability = input.capabilities.collaboration;
|
|
446
|
+
if (capability.kind !== "supported") {
|
|
447
|
+
throwAgentProviderContractError(
|
|
448
|
+
input.providerKey,
|
|
449
|
+
"output_capability_mismatch",
|
|
450
|
+
"Provider emitted collaboration state without declaring support."
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
const admission = evaluateCollaborationGraphAdmission({
|
|
454
|
+
capability,
|
|
455
|
+
candidate: {
|
|
456
|
+
collaborationId: node.collaborationId,
|
|
457
|
+
rootCollaborationId: node.rootCollaborationId,
|
|
458
|
+
...node.parentCollaborationId === void 0 ? {} : { parentCollaborationId: node.parentCollaborationId },
|
|
459
|
+
active: !TERMINAL_COLLABORATION_STATUSES.has(node.status)
|
|
460
|
+
},
|
|
461
|
+
nodes: input.interactionState.collaborationNodes,
|
|
462
|
+
reservations: input.interactionState.collaborationSpawnReservations
|
|
463
|
+
});
|
|
464
|
+
if (admission.kind === "conflict") {
|
|
465
|
+
throwAgentProviderContractError(
|
|
466
|
+
input.providerKey,
|
|
467
|
+
"output_collaboration_mismatch",
|
|
468
|
+
"Provider emitted a collaboration node outside the canonical graph."
|
|
469
|
+
);
|
|
470
|
+
}
|
|
471
|
+
if (admission.kind === "capacity_exceeded") {
|
|
472
|
+
throwAgentProviderContractError(
|
|
473
|
+
input.providerKey,
|
|
474
|
+
"output_capability_mismatch",
|
|
475
|
+
"Provider emitted a collaboration graph outside its declared limits."
|
|
476
|
+
);
|
|
477
|
+
}
|
|
478
|
+
input.interactionState.collaborationNodes.set(node.collaborationId, node);
|
|
479
|
+
}
|
|
480
|
+
if (input.output.event.type === "resource.updated") {
|
|
481
|
+
const capability = input.capabilities.generatedResources;
|
|
482
|
+
const resourceId = input.output.event.payload.resource.resourceId;
|
|
483
|
+
if (capability.kind !== "supported" || !input.state.generatedResourceIds.has(resourceId) && input.state.generatedResourceIds.size >= capability.maxResourcesPerTurn) {
|
|
484
|
+
throwAgentProviderContractError(
|
|
485
|
+
input.providerKey,
|
|
486
|
+
"output_capability_mismatch",
|
|
487
|
+
"Provider exceeded its declared generated-resource count for the turn."
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
const resource = validateAgentGeneratedResourceForCapabilities({
|
|
491
|
+
capabilities: input.capabilities,
|
|
492
|
+
candidate: input.output.event.payload.resource,
|
|
493
|
+
expectedResourceId: input.output.event.payload.resource.resourceId,
|
|
494
|
+
previous: input.interactionState.generatedResources.get(
|
|
495
|
+
input.output.event.payload.resource.resourceId
|
|
496
|
+
)
|
|
497
|
+
});
|
|
498
|
+
input.state.generatedResourceIds.add(resource.resourceId);
|
|
499
|
+
input.interactionState.generatedResources.set(resource.resourceId, resource);
|
|
500
|
+
}
|
|
308
501
|
observeTurnEvent({
|
|
309
502
|
providerKey: input.providerKey,
|
|
310
503
|
event: input.output.event,
|
|
@@ -355,7 +548,9 @@ function observeTurnOperationOutputs(input) {
|
|
|
355
548
|
state: input.state,
|
|
356
549
|
pendingRequests: input.pendingRequests,
|
|
357
550
|
openedRequestIds: input.openedRequestIds,
|
|
358
|
-
contextUsageState: input.contextUsageState
|
|
551
|
+
contextUsageState: input.contextUsageState,
|
|
552
|
+
capabilities: input.capabilities,
|
|
553
|
+
interactionState: input.interactionState
|
|
359
554
|
});
|
|
360
555
|
}
|
|
361
556
|
}
|
|
@@ -462,6 +657,15 @@ function validateAgentProviderSession(input) {
|
|
|
462
657
|
cumulativeByScope: /* @__PURE__ */ new Map(),
|
|
463
658
|
compactionReadyScopes: /* @__PURE__ */ new Set()
|
|
464
659
|
};
|
|
660
|
+
const interactionState = {
|
|
661
|
+
operationResults: /* @__PURE__ */ new Map(),
|
|
662
|
+
operationInvocations: /* @__PURE__ */ new Map(),
|
|
663
|
+
collaborationNodes: /* @__PURE__ */ new Map(),
|
|
664
|
+
collaborationSpawnReservations: /* @__PURE__ */ new Map(),
|
|
665
|
+
generatedResources: /* @__PURE__ */ new Map()
|
|
666
|
+
};
|
|
667
|
+
const collaborationNodes = interactionState.collaborationNodes;
|
|
668
|
+
const collaborationSpawnReservations = interactionState.collaborationSpawnReservations;
|
|
465
669
|
let activeTurn = null;
|
|
466
670
|
let closePromise = null;
|
|
467
671
|
let closed = false;
|
|
@@ -501,6 +705,39 @@ function validateAgentProviderSession(input) {
|
|
|
501
705
|
throw error;
|
|
502
706
|
}
|
|
503
707
|
};
|
|
708
|
+
const delegateProviderMutation = async (input2) => {
|
|
709
|
+
let executionStarted = false;
|
|
710
|
+
const onProviderExecutionStarted = () => {
|
|
711
|
+
if (executionStarted) {
|
|
712
|
+
throwAgentProviderContractError(
|
|
713
|
+
providerKey,
|
|
714
|
+
"invalid_operation_result",
|
|
715
|
+
"Provider reported operation execution more than once."
|
|
716
|
+
);
|
|
717
|
+
}
|
|
718
|
+
input2.observer?.();
|
|
719
|
+
executionStarted = true;
|
|
720
|
+
};
|
|
721
|
+
try {
|
|
722
|
+
const candidate = await input2.invoke(onProviderExecutionStarted);
|
|
723
|
+
if (!executionStarted) {
|
|
724
|
+
throwAgentProviderContractError(
|
|
725
|
+
providerKey,
|
|
726
|
+
"invalid_operation_result",
|
|
727
|
+
"Provider completed an operation without reporting execution start."
|
|
728
|
+
);
|
|
729
|
+
}
|
|
730
|
+
return input2.validate(candidate);
|
|
731
|
+
} catch (error) {
|
|
732
|
+
if (!executionStarted) throw error;
|
|
733
|
+
unusable = true;
|
|
734
|
+
throw new AgentProviderDelegatedOperationError(
|
|
735
|
+
providerKey,
|
|
736
|
+
input2.operation,
|
|
737
|
+
error
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
};
|
|
504
741
|
const runTurn = async function* (turnInput) {
|
|
505
742
|
requireUsable();
|
|
506
743
|
throwIfAgentOperationAborted(turnInput.signal);
|
|
@@ -545,6 +782,7 @@ function validateAgentProviderSession(input) {
|
|
|
545
782
|
fileChangeMode: capabilities.output.fileChanges,
|
|
546
783
|
observedItems: /* @__PURE__ */ new Map(),
|
|
547
784
|
proposedPlans: /* @__PURE__ */ new Map(),
|
|
785
|
+
generatedResourceIds: /* @__PURE__ */ new Set(),
|
|
548
786
|
started: false,
|
|
549
787
|
terminal: false,
|
|
550
788
|
waiting: false,
|
|
@@ -564,12 +802,14 @@ function validateAgentProviderSession(input) {
|
|
|
564
802
|
outputContext(parsedInput.turnId)
|
|
565
803
|
);
|
|
566
804
|
observeTurnOutput({
|
|
805
|
+
capabilities,
|
|
567
806
|
providerKey,
|
|
568
807
|
output,
|
|
569
808
|
state: currentTurn.state,
|
|
570
809
|
pendingRequests: currentTurn.pendingRequests,
|
|
571
810
|
openedRequestIds,
|
|
572
|
-
contextUsageState
|
|
811
|
+
contextUsageState,
|
|
812
|
+
interactionState
|
|
573
813
|
});
|
|
574
814
|
yield output;
|
|
575
815
|
}
|
|
@@ -663,12 +903,14 @@ function validateAgentProviderSession(input) {
|
|
|
663
903
|
outputContext(pending.turnId)
|
|
664
904
|
);
|
|
665
905
|
observeTurnOutput({
|
|
906
|
+
capabilities,
|
|
666
907
|
providerKey,
|
|
667
908
|
output,
|
|
668
909
|
state: currentTurn.state,
|
|
669
910
|
pendingRequests: currentTurn.pendingRequests,
|
|
670
911
|
openedRequestIds,
|
|
671
|
-
contextUsageState
|
|
912
|
+
contextUsageState,
|
|
913
|
+
interactionState
|
|
672
914
|
});
|
|
673
915
|
yield output;
|
|
674
916
|
}
|
|
@@ -743,12 +985,14 @@ function validateAgentProviderSession(input) {
|
|
|
743
985
|
}
|
|
744
986
|
try {
|
|
745
987
|
observeTurnOperationOutputs({
|
|
988
|
+
capabilities,
|
|
746
989
|
providerKey,
|
|
747
990
|
outputs: result.outputs,
|
|
748
991
|
state: targetedTurn.state,
|
|
749
992
|
pendingRequests: targetedTurn.pendingRequests,
|
|
750
993
|
openedRequestIds,
|
|
751
|
-
contextUsageState
|
|
994
|
+
contextUsageState,
|
|
995
|
+
interactionState
|
|
752
996
|
});
|
|
753
997
|
if (terminalized && !targetedTurn.state.terminal) {
|
|
754
998
|
completeTurnSequence({
|
|
@@ -821,22 +1065,433 @@ function validateAgentProviderSession(input) {
|
|
|
821
1065
|
const declaredConfiguration = input.candidate.configuration;
|
|
822
1066
|
const configuration = declaredConfiguration.kind === "managed" ? Object.freeze({ kind: "managed" }) : Object.freeze({
|
|
823
1067
|
kind: "selectable",
|
|
824
|
-
|
|
1068
|
+
listConfiguration: async (listInput = {}) => {
|
|
825
1069
|
requireUsable();
|
|
826
|
-
throwIfAgentOperationAborted(
|
|
827
|
-
|
|
828
|
-
|
|
1070
|
+
throwIfAgentOperationAborted(listInput.signal);
|
|
1071
|
+
return validateAgentConfigurationCatalogForCapabilities(
|
|
1072
|
+
capabilities,
|
|
1073
|
+
await declaredConfiguration.listConfiguration(
|
|
1074
|
+
listInput.signal === void 0 ? {} : { signal: listInput.signal }
|
|
1075
|
+
)
|
|
829
1076
|
);
|
|
830
|
-
|
|
1077
|
+
},
|
|
1078
|
+
applyConfigurationSelection: async (configurationInput) => {
|
|
1079
|
+
requireUsable();
|
|
1080
|
+
throwIfAgentOperationAborted(configurationInput.signal);
|
|
1081
|
+
const catalog = validateAgentConfigurationCatalogForCapabilities(
|
|
831
1082
|
capabilities,
|
|
832
|
-
|
|
1083
|
+
await declaredConfiguration.listConfiguration(
|
|
1084
|
+
configurationInput.signal === void 0 ? {} : { signal: configurationInput.signal }
|
|
1085
|
+
)
|
|
833
1086
|
);
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
1087
|
+
let selection;
|
|
1088
|
+
try {
|
|
1089
|
+
selection = parseAgentConfigurationSelectionFor(
|
|
1090
|
+
catalog,
|
|
1091
|
+
configurationInput.selection
|
|
1092
|
+
);
|
|
1093
|
+
} catch {
|
|
1094
|
+
return throwAgentProviderContractError(
|
|
1095
|
+
providerKey,
|
|
1096
|
+
"configuration_value_unsupported",
|
|
1097
|
+
"Configuration selection is stale or outside the offered catalog."
|
|
1098
|
+
);
|
|
1099
|
+
}
|
|
1100
|
+
return delegateProviderMutation({
|
|
1101
|
+
operation: "apply_configuration",
|
|
1102
|
+
observer: configurationInput.onProviderExecutionStarted,
|
|
1103
|
+
invoke: (onProviderExecutionStarted) => declaredConfiguration.applyConfigurationSelection({
|
|
1104
|
+
selection,
|
|
1105
|
+
onProviderExecutionStarted,
|
|
837
1106
|
...configurationInput.signal === void 0 ? {} : { signal: configurationInput.signal }
|
|
1107
|
+
}),
|
|
1108
|
+
validate: (candidate) => validateAgentProviderOperationResult(
|
|
1109
|
+
candidate,
|
|
1110
|
+
outputContext()
|
|
1111
|
+
)
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
});
|
|
1115
|
+
const declaredOperations = input.candidate.operations;
|
|
1116
|
+
const operations = declaredOperations.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
1117
|
+
kind: "supported",
|
|
1118
|
+
listOperations: async (listInput = {}) => {
|
|
1119
|
+
requireUsable();
|
|
1120
|
+
throwIfAgentOperationAborted(listInput.signal);
|
|
1121
|
+
return validateAgentOperationCatalogForCapabilities(
|
|
1122
|
+
capabilities,
|
|
1123
|
+
await declaredOperations.listOperations(
|
|
1124
|
+
listInput.signal === void 0 ? {} : { signal: listInput.signal }
|
|
1125
|
+
)
|
|
1126
|
+
);
|
|
1127
|
+
},
|
|
1128
|
+
invokeOperation: async (operationInput) => {
|
|
1129
|
+
requireUsable();
|
|
1130
|
+
throwIfAgentOperationAborted(operationInput.signal);
|
|
1131
|
+
let invocation;
|
|
1132
|
+
try {
|
|
1133
|
+
invocation = parseAgentOperationInvocation(operationInput.invocation);
|
|
1134
|
+
} catch {
|
|
1135
|
+
return throwAgentProviderContractError(
|
|
1136
|
+
providerKey,
|
|
1137
|
+
"input_operation_mismatch",
|
|
1138
|
+
"Operation invocation is invalid."
|
|
1139
|
+
);
|
|
1140
|
+
}
|
|
1141
|
+
const catalog = validateAgentOperationCatalogForCapabilities(
|
|
1142
|
+
capabilities,
|
|
1143
|
+
await declaredOperations.listOperations(
|
|
1144
|
+
operationInput.signal === void 0 ? {} : { signal: operationInput.signal }
|
|
1145
|
+
)
|
|
1146
|
+
);
|
|
1147
|
+
const descriptor = catalog.operations.find(
|
|
1148
|
+
(operation) => operation.operationId === invocation.operationId
|
|
1149
|
+
);
|
|
1150
|
+
if (descriptor === void 0) {
|
|
1151
|
+
return throwAgentProviderContractError(
|
|
1152
|
+
providerKey,
|
|
1153
|
+
"input_operation_mismatch",
|
|
1154
|
+
"Operation invocation does not identify an offered operation."
|
|
1155
|
+
);
|
|
1156
|
+
}
|
|
1157
|
+
try {
|
|
1158
|
+
invocation = parseAgentOperationInvocationFor(
|
|
1159
|
+
descriptor,
|
|
1160
|
+
invocation
|
|
1161
|
+
);
|
|
1162
|
+
} catch {
|
|
1163
|
+
return throwAgentProviderContractError(
|
|
1164
|
+
providerKey,
|
|
1165
|
+
"input_operation_mismatch",
|
|
1166
|
+
"Operation invocation is stale or outside the offered descriptor."
|
|
1167
|
+
);
|
|
1168
|
+
}
|
|
1169
|
+
const existing = interactionState.operationInvocations.get(
|
|
1170
|
+
invocation.invocationId
|
|
1171
|
+
);
|
|
1172
|
+
if (existing !== void 0) {
|
|
1173
|
+
if (JSON.stringify(existing.invocation) !== JSON.stringify(invocation)) {
|
|
1174
|
+
return throwAgentProviderContractError(
|
|
1175
|
+
providerKey,
|
|
1176
|
+
"input_operation_mismatch",
|
|
1177
|
+
"Operation invocation ID was reused with conflicting input."
|
|
1178
|
+
);
|
|
1179
|
+
}
|
|
1180
|
+
if (descriptor.idempotency === "required" && existing.result !== void 0) {
|
|
1181
|
+
return existing.result;
|
|
1182
|
+
}
|
|
1183
|
+
return throwAgentProviderContractError(
|
|
1184
|
+
providerKey,
|
|
1185
|
+
"input_operation_mismatch",
|
|
1186
|
+
"Operation invocation ID is already active or is not replayable."
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1189
|
+
const trackedInvocation = {
|
|
1190
|
+
invocation
|
|
1191
|
+
};
|
|
1192
|
+
interactionState.operationInvocations.set(
|
|
1193
|
+
invocation.invocationId,
|
|
1194
|
+
trackedInvocation
|
|
1195
|
+
);
|
|
1196
|
+
try {
|
|
1197
|
+
const result = await delegateProviderMutation({
|
|
1198
|
+
operation: "invoke_operation",
|
|
1199
|
+
observer: operationInput.onProviderExecutionStarted,
|
|
1200
|
+
invoke: (onProviderExecutionStarted) => declaredOperations.invokeOperation({
|
|
1201
|
+
invocation,
|
|
1202
|
+
onProviderExecutionStarted,
|
|
1203
|
+
...operationInput.signal === void 0 ? {} : { signal: operationInput.signal }
|
|
1204
|
+
}),
|
|
1205
|
+
validate: (candidate) => {
|
|
1206
|
+
const result2 = validateAgentOperationResultTransition({
|
|
1207
|
+
providerKey,
|
|
1208
|
+
candidate: validateAgentOperationResultForInvocation(
|
|
1209
|
+
providerKey,
|
|
1210
|
+
descriptor,
|
|
1211
|
+
invocation,
|
|
1212
|
+
candidate
|
|
1213
|
+
),
|
|
1214
|
+
previous: interactionState.operationResults.get(
|
|
1215
|
+
invocation.invocationId
|
|
1216
|
+
)
|
|
1217
|
+
});
|
|
1218
|
+
interactionState.operationResults.set(
|
|
1219
|
+
result2.invocationId,
|
|
1220
|
+
result2
|
|
1221
|
+
);
|
|
1222
|
+
return result2;
|
|
1223
|
+
}
|
|
1224
|
+
});
|
|
1225
|
+
trackedInvocation.result = result;
|
|
1226
|
+
return result;
|
|
1227
|
+
} catch (error) {
|
|
1228
|
+
if (!(error instanceof AgentProviderDelegatedOperationError)) {
|
|
1229
|
+
interactionState.operationInvocations.delete(
|
|
1230
|
+
invocation.invocationId
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
throw error;
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
});
|
|
1237
|
+
const declaredManagedContent = input.candidate.managedContent;
|
|
1238
|
+
const managedContent = declaredManagedContent.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
1239
|
+
kind: "supported",
|
|
1240
|
+
listManagedContent: async (listInput = {}) => {
|
|
1241
|
+
requireUsable();
|
|
1242
|
+
throwIfAgentOperationAborted(listInput.signal);
|
|
1243
|
+
return validateAgentManagedContentCatalogForCapabilities(
|
|
1244
|
+
capabilities,
|
|
1245
|
+
await declaredManagedContent.listManagedContent(
|
|
1246
|
+
listInput.signal === void 0 ? {} : { signal: listInput.signal }
|
|
1247
|
+
)
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
});
|
|
1251
|
+
const declaredIntegrations = input.candidate.integrations;
|
|
1252
|
+
const integrations = declaredIntegrations.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
1253
|
+
kind: "supported",
|
|
1254
|
+
observeIntegrations: async (listInput = {}) => {
|
|
1255
|
+
requireUsable();
|
|
1256
|
+
throwIfAgentOperationAborted(listInput.signal);
|
|
1257
|
+
return validateAgentIntegrationCatalogForCapabilities(
|
|
1258
|
+
capabilities,
|
|
1259
|
+
await declaredIntegrations.observeIntegrations(
|
|
1260
|
+
listInput.signal === void 0 ? {} : { signal: listInput.signal }
|
|
1261
|
+
)
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1264
|
+
});
|
|
1265
|
+
const declaredCollaboration = input.candidate.collaboration;
|
|
1266
|
+
const collaboration = declaredCollaboration.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
1267
|
+
kind: "supported",
|
|
1268
|
+
spawnCollaboration: async (collaborationInput) => {
|
|
1269
|
+
requireUsable();
|
|
1270
|
+
throwIfAgentOperationAborted(collaborationInput.signal);
|
|
1271
|
+
let spawn;
|
|
1272
|
+
try {
|
|
1273
|
+
spawn = parseAgentCollaborationSpawnInput(collaborationInput.spawn);
|
|
1274
|
+
} catch {
|
|
1275
|
+
return throwAgentProviderContractError(
|
|
1276
|
+
providerKey,
|
|
1277
|
+
"input_operation_mismatch",
|
|
1278
|
+
"Collaboration spawn input is invalid."
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
const capability = capabilities.collaboration;
|
|
1282
|
+
if (capability.kind !== "supported" || !capability.controlActions.includes("spawn") || !capability.roles.includes(spawn.role) || collaborationNodes.has(spawn.collaborationId) || collaborationSpawnReservations.has(spawn.collaborationId)) {
|
|
1283
|
+
return throwAgentProviderContractError(
|
|
1284
|
+
providerKey,
|
|
1285
|
+
"input_capability_mismatch",
|
|
1286
|
+
"Collaboration spawn is outside the provider's declared capability."
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
const observedParent = spawn.parentCollaborationId === void 0 ? void 0 : collaborationNodes.get(spawn.parentCollaborationId);
|
|
1290
|
+
const admission = evaluateCollaborationGraphAdmission({
|
|
1291
|
+
capability,
|
|
1292
|
+
candidate: {
|
|
1293
|
+
collaborationId: spawn.collaborationId,
|
|
1294
|
+
rootCollaborationId: observedParent?.rootCollaborationId ?? spawn.collaborationId,
|
|
1295
|
+
...spawn.parentCollaborationId === void 0 ? {} : { parentCollaborationId: spawn.parentCollaborationId },
|
|
1296
|
+
active: true
|
|
1297
|
+
},
|
|
1298
|
+
nodes: collaborationNodes,
|
|
1299
|
+
reservations: collaborationSpawnReservations
|
|
1300
|
+
});
|
|
1301
|
+
if (admission.kind === "conflict") {
|
|
1302
|
+
return throwAgentProviderContractError(
|
|
1303
|
+
providerKey,
|
|
1304
|
+
"input_operation_mismatch",
|
|
1305
|
+
"Collaboration parent is unavailable in the canonical graph."
|
|
1306
|
+
);
|
|
1307
|
+
}
|
|
1308
|
+
if (admission.kind === "capacity_exceeded") {
|
|
1309
|
+
return throwAgentProviderContractError(
|
|
1310
|
+
providerKey,
|
|
1311
|
+
"input_capability_mismatch",
|
|
1312
|
+
"Collaboration graph limit would be exceeded."
|
|
1313
|
+
);
|
|
1314
|
+
}
|
|
1315
|
+
const parent = admission.parent;
|
|
1316
|
+
collaborationSpawnReservations.set(
|
|
1317
|
+
spawn.collaborationId,
|
|
1318
|
+
Object.freeze({
|
|
1319
|
+
...spawn.parentCollaborationId === void 0 ? {} : { parentCollaborationId: spawn.parentCollaborationId }
|
|
838
1320
|
})
|
|
839
1321
|
);
|
|
1322
|
+
try {
|
|
1323
|
+
const node = await delegateProviderMutation({
|
|
1324
|
+
operation: "spawn_collaboration",
|
|
1325
|
+
observer: collaborationInput.onProviderExecutionStarted,
|
|
1326
|
+
invoke: (onProviderExecutionStarted) => declaredCollaboration.spawnCollaboration({
|
|
1327
|
+
spawn,
|
|
1328
|
+
onProviderExecutionStarted,
|
|
1329
|
+
...collaborationInput.signal === void 0 ? {} : { signal: collaborationInput.signal }
|
|
1330
|
+
}),
|
|
1331
|
+
validate: (candidate) => {
|
|
1332
|
+
const node2 = validateAgentCollaborationNodeForCapabilities({
|
|
1333
|
+
capabilities,
|
|
1334
|
+
candidate
|
|
1335
|
+
});
|
|
1336
|
+
if (node2.collaborationId !== spawn.collaborationId || node2.parentCollaborationId !== spawn.parentCollaborationId || node2.role !== spawn.role || node2.title !== spawn.title || node2.objective !== spawn.objective || node2.createdAt !== spawn.createdAt || node2.rootCollaborationId !== (parent?.rootCollaborationId ?? spawn.collaborationId)) {
|
|
1337
|
+
return throwAgentProviderContractError(
|
|
1338
|
+
providerKey,
|
|
1339
|
+
"output_collaboration_mismatch",
|
|
1340
|
+
"Provider collaboration node does not match the spawn input."
|
|
1341
|
+
);
|
|
1342
|
+
}
|
|
1343
|
+
return node2;
|
|
1344
|
+
}
|
|
1345
|
+
});
|
|
1346
|
+
collaborationNodes.set(node.collaborationId, node);
|
|
1347
|
+
collaborationSpawnReservations.delete(spawn.collaborationId);
|
|
1348
|
+
return node;
|
|
1349
|
+
} catch (error) {
|
|
1350
|
+
if (!(error instanceof AgentProviderDelegatedOperationError)) {
|
|
1351
|
+
collaborationSpawnReservations.delete(spawn.collaborationId);
|
|
1352
|
+
}
|
|
1353
|
+
throw error;
|
|
1354
|
+
}
|
|
1355
|
+
},
|
|
1356
|
+
controlCollaboration: async (collaborationInput) => {
|
|
1357
|
+
requireUsable();
|
|
1358
|
+
throwIfAgentOperationAborted(collaborationInput.signal);
|
|
1359
|
+
let control;
|
|
1360
|
+
try {
|
|
1361
|
+
control = parseAgentCollaborationControlInput(
|
|
1362
|
+
collaborationInput.control
|
|
1363
|
+
);
|
|
1364
|
+
} catch {
|
|
1365
|
+
return throwAgentProviderContractError(
|
|
1366
|
+
providerKey,
|
|
1367
|
+
"input_operation_mismatch",
|
|
1368
|
+
"Collaboration control input is invalid."
|
|
1369
|
+
);
|
|
1370
|
+
}
|
|
1371
|
+
const capability = capabilities.collaboration;
|
|
1372
|
+
const previous = collaborationNodes.get(control.collaborationId);
|
|
1373
|
+
if (capability.kind !== "supported" || !capability.controlActions.includes(control.action) || previous === void 0) {
|
|
1374
|
+
return throwAgentProviderContractError(
|
|
1375
|
+
providerKey,
|
|
1376
|
+
"input_capability_mismatch",
|
|
1377
|
+
"Collaboration control is outside the observed graph or declared capability."
|
|
1378
|
+
);
|
|
1379
|
+
}
|
|
1380
|
+
const terminal = ["completed", "failed", "canceled"].includes(
|
|
1381
|
+
previous.status
|
|
1382
|
+
);
|
|
1383
|
+
if (control.action === "close" && previous.closedAt !== void 0) {
|
|
1384
|
+
return previous;
|
|
1385
|
+
}
|
|
1386
|
+
if (control.action === "close" && !terminal || control.action === "stop" && terminal || control.action === "steer" && terminal || control.action !== "inspect" && previous.closedAt !== void 0) {
|
|
1387
|
+
return throwAgentProviderContractError(
|
|
1388
|
+
providerKey,
|
|
1389
|
+
"input_capability_mismatch",
|
|
1390
|
+
"Collaboration control is unavailable in the current lifecycle state."
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
const node = await delegateProviderMutation({
|
|
1394
|
+
operation: "control_collaboration",
|
|
1395
|
+
observer: collaborationInput.onProviderExecutionStarted,
|
|
1396
|
+
invoke: (onProviderExecutionStarted) => declaredCollaboration.controlCollaboration({
|
|
1397
|
+
control,
|
|
1398
|
+
onProviderExecutionStarted,
|
|
1399
|
+
...collaborationInput.signal === void 0 ? {} : { signal: collaborationInput.signal }
|
|
1400
|
+
}),
|
|
1401
|
+
validate: (candidate) => {
|
|
1402
|
+
const validated = validateAgentCollaborationNodeForCapabilities({
|
|
1403
|
+
capabilities,
|
|
1404
|
+
candidate,
|
|
1405
|
+
previous
|
|
1406
|
+
});
|
|
1407
|
+
if (control.action === "stop" && validated.status !== "canceled" || control.action === "close" && (validated.status !== previous.status || validated.closedAt === void 0)) {
|
|
1408
|
+
return throwAgentProviderContractError(
|
|
1409
|
+
providerKey,
|
|
1410
|
+
"output_collaboration_mismatch",
|
|
1411
|
+
"Provider collaboration result does not settle the requested control action."
|
|
1412
|
+
);
|
|
1413
|
+
}
|
|
1414
|
+
return validated;
|
|
1415
|
+
}
|
|
1416
|
+
});
|
|
1417
|
+
collaborationNodes.set(node.collaborationId, node);
|
|
1418
|
+
return node;
|
|
1419
|
+
}
|
|
1420
|
+
});
|
|
1421
|
+
function validateGeneratedResourceInspection(candidate, resourceId) {
|
|
1422
|
+
if (candidate === null || typeof candidate !== "object" || !hasExactOwnKeys(candidate, [
|
|
1423
|
+
"descriptor",
|
|
1424
|
+
..."candidate" in candidate ? ["candidate"] : []
|
|
1425
|
+
])) {
|
|
1426
|
+
return throwAgentProviderContractError(
|
|
1427
|
+
providerKey,
|
|
1428
|
+
"output_resource_mismatch",
|
|
1429
|
+
"Provider returned an invalid generated-resource inspection."
|
|
1430
|
+
);
|
|
1431
|
+
}
|
|
1432
|
+
const rawInspection = candidate;
|
|
1433
|
+
const descriptor = validateAgentGeneratedResourceForCapabilities({
|
|
1434
|
+
capabilities,
|
|
1435
|
+
candidate: rawInspection.descriptor,
|
|
1436
|
+
expectedResourceId: resourceId,
|
|
1437
|
+
previous: interactionState.generatedResources.get(resourceId)
|
|
1438
|
+
});
|
|
1439
|
+
const hasCandidate = Object.prototype.hasOwnProperty.call(
|
|
1440
|
+
rawInspection,
|
|
1441
|
+
"candidate"
|
|
1442
|
+
);
|
|
1443
|
+
if (descriptor.status === "available" !== hasCandidate) {
|
|
1444
|
+
return throwAgentProviderContractError(
|
|
1445
|
+
providerKey,
|
|
1446
|
+
"output_resource_mismatch",
|
|
1447
|
+
"Exactly available generated resources must include owned artifact bytes."
|
|
1448
|
+
);
|
|
1449
|
+
}
|
|
1450
|
+
if (!hasCandidate) return Object.freeze({ descriptor });
|
|
1451
|
+
let artifactCandidate;
|
|
1452
|
+
try {
|
|
1453
|
+
artifactCandidate = createAgentArtifactCandidate(
|
|
1454
|
+
rawInspection.candidate
|
|
1455
|
+
);
|
|
1456
|
+
} catch {
|
|
1457
|
+
return throwAgentProviderContractError(
|
|
1458
|
+
providerKey,
|
|
1459
|
+
"output_resource_mismatch",
|
|
1460
|
+
"Provider returned invalid generated-resource artifact bytes."
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1463
|
+
const artifact = artifactCandidate.descriptor;
|
|
1464
|
+
const expectedArtifactKind = descriptor.kind === "image" ? "image" : "file";
|
|
1465
|
+
if (artifactCandidate.delivery !== "required_before_reference" || artifact.artifactId !== descriptor.artifactId || artifact.kind !== expectedArtifactKind || artifact.displayName !== descriptor.displayName || artifact.mediaType !== descriptor.mediaType || artifact.byteSize !== descriptor.byteSize || artifact.digest?.algorithm !== "sha256" || artifact.digest?.value !== descriptor.sha256 || artifact.summary !== descriptor.summary) {
|
|
1466
|
+
return throwAgentProviderContractError(
|
|
1467
|
+
providerKey,
|
|
1468
|
+
"output_resource_mismatch",
|
|
1469
|
+
"Generated-resource metadata does not match its immutable artifact candidate."
|
|
1470
|
+
);
|
|
1471
|
+
}
|
|
1472
|
+
return Object.freeze({ descriptor, candidate: artifactCandidate });
|
|
1473
|
+
}
|
|
1474
|
+
const declaredGeneratedResources = input.candidate.generatedResources;
|
|
1475
|
+
const generatedResources = declaredGeneratedResources.kind === "unsupported" ? Object.freeze({ kind: "unsupported" }) : Object.freeze({
|
|
1476
|
+
kind: "supported",
|
|
1477
|
+
getGeneratedResource: async (resourceInput) => {
|
|
1478
|
+
requireUsable();
|
|
1479
|
+
throwIfAgentOperationAborted(resourceInput.signal);
|
|
1480
|
+
const resourceId = parseAgentGeneratedResourceId(
|
|
1481
|
+
resourceInput.resourceId
|
|
1482
|
+
);
|
|
1483
|
+
const inspection = validateGeneratedResourceInspection(
|
|
1484
|
+
await declaredGeneratedResources.getGeneratedResource({
|
|
1485
|
+
resourceId,
|
|
1486
|
+
...resourceInput.signal === void 0 ? {} : { signal: resourceInput.signal }
|
|
1487
|
+
}),
|
|
1488
|
+
resourceId
|
|
1489
|
+
);
|
|
1490
|
+
interactionState.generatedResources.set(
|
|
1491
|
+
inspection.descriptor.resourceId,
|
|
1492
|
+
inspection.descriptor
|
|
1493
|
+
);
|
|
1494
|
+
return inspection;
|
|
840
1495
|
}
|
|
841
1496
|
});
|
|
842
1497
|
const close = (closeInput) => {
|
|
@@ -868,6 +1523,11 @@ function validateAgentProviderSession(input) {
|
|
|
868
1523
|
interruption,
|
|
869
1524
|
steering,
|
|
870
1525
|
configuration,
|
|
1526
|
+
operations,
|
|
1527
|
+
managedContent,
|
|
1528
|
+
integrations,
|
|
1529
|
+
collaboration,
|
|
1530
|
+
generatedResources,
|
|
871
1531
|
close
|
|
872
1532
|
});
|
|
873
1533
|
}
|