@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.
@@ -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
- assertAgentSessionConfigurationSupported
14
- } from "./configurationValidation.js";
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 (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)) {
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 (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.applyConfiguration !== "function") {
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
- applyConfiguration: async (configurationInput) => {
1068
+ listConfiguration: async (listInput = {}) => {
825
1069
  requireUsable();
826
- throwIfAgentOperationAborted(configurationInput.signal);
827
- const configuration2 = parseAgentSessionConfiguration(
828
- configurationInput.configuration
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
- assertAgentSessionConfigurationSupported(
1077
+ },
1078
+ applyConfigurationSelection: async (configurationInput) => {
1079
+ requireUsable();
1080
+ throwIfAgentOperationAborted(configurationInput.signal);
1081
+ const catalog = validateAgentConfigurationCatalogForCapabilities(
831
1082
  capabilities,
832
- configuration2
1083
+ await declaredConfiguration.listConfiguration(
1084
+ configurationInput.signal === void 0 ? {} : { signal: configurationInput.signal }
1085
+ )
833
1086
  );
834
- return delegateOperation(
835
- () => declaredConfiguration.applyConfiguration({
836
- configuration: configuration2,
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
  }