@spine-event-engine/server 2.0.0-snapshot.23 → 2.0.0-snapshot.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (300) hide show
  1. package/README.md +38 -11
  2. package/REFERENCE.md +278 -141
  3. package/dist/agent/agent-acceptance-receipts.d.ts +69 -0
  4. package/dist/agent/agent-acceptance-receipts.d.ts.map +1 -0
  5. package/dist/agent/agent-acceptance-receipts.js +198 -0
  6. package/dist/agent/agent-acceptance-receipts.js.map +1 -0
  7. package/dist/agent/agent-execution-capacity.d.ts +37 -9
  8. package/dist/agent/agent-execution-capacity.d.ts.map +1 -1
  9. package/dist/agent/agent-execution-capacity.js +73 -15
  10. package/dist/agent/agent-execution-capacity.js.map +1 -1
  11. package/dist/agent/agent-history.d.ts +15 -10
  12. package/dist/agent/agent-history.d.ts.map +1 -1
  13. package/dist/agent/agent-history.js +26 -14
  14. package/dist/agent/agent-history.js.map +1 -1
  15. package/dist/agent/agent-live-ai-audit.d.ts +95 -0
  16. package/dist/agent/agent-live-ai-audit.d.ts.map +1 -0
  17. package/dist/agent/agent-live-ai-audit.js +290 -0
  18. package/dist/agent/agent-live-ai-audit.js.map +1 -0
  19. package/dist/agent/agent-live-ai-runtime.d.ts +300 -0
  20. package/dist/agent/agent-live-ai-runtime.d.ts.map +1 -0
  21. package/dist/agent/agent-live-ai-runtime.js +611 -0
  22. package/dist/agent/agent-live-ai-runtime.js.map +1 -0
  23. package/dist/agent/agent-live-audit.d.ts +67 -0
  24. package/dist/agent/agent-live-audit.d.ts.map +1 -0
  25. package/dist/agent/agent-live-audit.js +121 -0
  26. package/dist/agent/agent-live-audit.js.map +1 -0
  27. package/dist/agent/agent-live-budget.d.ts +84 -0
  28. package/dist/agent/agent-live-budget.d.ts.map +1 -0
  29. package/dist/agent/agent-live-budget.js +161 -0
  30. package/dist/agent/agent-live-budget.js.map +1 -0
  31. package/dist/agent/agent-live-fault.d.ts +18 -0
  32. package/dist/agent/agent-live-fault.d.ts.map +1 -0
  33. package/dist/agent/{agent-execution-fault.js → agent-live-fault.js} +7 -7
  34. package/dist/agent/agent-live-fault.js.map +1 -0
  35. package/dist/agent/agent-live-inputs.d.ts +74 -0
  36. package/dist/agent/agent-live-inputs.d.ts.map +1 -0
  37. package/dist/agent/agent-live-inputs.js +15 -0
  38. package/dist/agent/agent-live-inputs.js.map +1 -0
  39. package/dist/agent/agent-live-interaction-events.d.ts +46 -0
  40. package/dist/agent/agent-live-interaction-events.d.ts.map +1 -0
  41. package/dist/agent/agent-live-interaction-events.js +104 -0
  42. package/dist/agent/agent-live-interaction-events.js.map +1 -0
  43. package/dist/agent/agent-live-mcp-controls.d.ts +129 -0
  44. package/dist/agent/agent-live-mcp-controls.d.ts.map +1 -0
  45. package/dist/agent/agent-live-mcp-controls.js +228 -0
  46. package/dist/agent/agent-live-mcp-controls.js.map +1 -0
  47. package/dist/agent/agent-live-mcp-host.d.ts +88 -0
  48. package/dist/agent/agent-live-mcp-host.d.ts.map +1 -0
  49. package/dist/agent/{agent-mcp-host.js → agent-live-mcp-host.js} +1 -1
  50. package/dist/agent/agent-live-mcp-host.js.map +1 -0
  51. package/dist/agent/{agent-mcp-runtime.d.ts → agent-live-mcp-runtime.d.ts} +6 -6
  52. package/dist/agent/agent-live-mcp-runtime.d.ts.map +1 -0
  53. package/dist/agent/{agent-mcp-runtime.js → agent-live-mcp-runtime.js} +13 -42
  54. package/dist/agent/agent-live-mcp-runtime.js.map +1 -0
  55. package/dist/agent/agent-live-read-runtime.d.ts +61 -0
  56. package/dist/agent/agent-live-read-runtime.d.ts.map +1 -0
  57. package/dist/agent/agent-live-read-runtime.js +121 -0
  58. package/dist/agent/agent-live-read-runtime.js.map +1 -0
  59. package/dist/agent/agent-model-selection.d.ts +21 -34
  60. package/dist/agent/agent-model-selection.d.ts.map +1 -1
  61. package/dist/agent/agent-model-selection.js +61 -78
  62. package/dist/agent/agent-model-selection.js.map +1 -1
  63. package/dist/bus/command-bus.d.ts +14 -18
  64. package/dist/bus/command-bus.d.ts.map +1 -1
  65. package/dist/bus/command-bus.js +31 -48
  66. package/dist/bus/command-bus.js.map +1 -1
  67. package/dist/bus/event-bus.d.ts +82 -104
  68. package/dist/bus/event-bus.d.ts.map +1 -1
  69. package/dist/bus/event-bus.js +87 -127
  70. package/dist/bus/event-bus.js.map +1 -1
  71. package/dist/context/bounded-context.d.ts +143 -91
  72. package/dist/context/bounded-context.d.ts.map +1 -1
  73. package/dist/context/bounded-context.js +753 -359
  74. package/dist/context/bounded-context.js.map +1 -1
  75. package/dist/context/entity-inbox.d.ts +7 -2
  76. package/dist/context/entity-inbox.d.ts.map +1 -1
  77. package/dist/context/entity-inbox.js +43 -20
  78. package/dist/context/entity-inbox.js.map +1 -1
  79. package/dist/context/local-inbox-handoff.d.ts +35 -34
  80. package/dist/context/local-inbox-handoff.d.ts.map +1 -1
  81. package/dist/context/local-inbox-handoff.js +123 -135
  82. package/dist/context/local-inbox-handoff.js.map +1 -1
  83. package/dist/context/projection-handoff.d.ts +2 -2
  84. package/dist/context/projection-handoff.d.ts.map +1 -1
  85. package/dist/context/projection-handoff.js +12 -8
  86. package/dist/context/projection-handoff.js.map +1 -1
  87. package/dist/context/tenant-index.d.ts +36 -31
  88. package/dist/context/tenant-index.d.ts.map +1 -1
  89. package/dist/context/tenant-index.js +123 -125
  90. package/dist/context/tenant-index.js.map +1 -1
  91. package/dist/context/tenant-unknown-error.d.ts +33 -0
  92. package/dist/context/tenant-unknown-error.d.ts.map +1 -0
  93. package/dist/context/tenant-unknown-error.js +75 -0
  94. package/dist/context/tenant-unknown-error.js.map +1 -0
  95. package/dist/delivery/agent-delivery-scope.d.ts +66 -0
  96. package/dist/delivery/agent-delivery-scope.d.ts.map +1 -0
  97. package/dist/delivery/agent-delivery-scope.js +44 -0
  98. package/dist/delivery/agent-delivery-scope.js.map +1 -0
  99. package/dist/delivery/delivery-builder.d.ts +25 -1
  100. package/dist/delivery/delivery-builder.d.ts.map +1 -1
  101. package/dist/delivery/delivery-builder.js +89 -0
  102. package/dist/delivery/delivery-builder.js.map +1 -1
  103. package/dist/delivery/delivery-monitor.d.ts +12 -9
  104. package/dist/delivery/delivery-monitor.d.ts.map +1 -1
  105. package/dist/delivery/delivery-monitor.js +15 -9
  106. package/dist/delivery/delivery-monitor.js.map +1 -1
  107. package/dist/delivery/delivery-ports.d.ts +6 -13
  108. package/dist/delivery/delivery-ports.d.ts.map +1 -1
  109. package/dist/delivery/delivery-run-control.d.ts +21 -0
  110. package/dist/delivery/delivery-run-control.d.ts.map +1 -1
  111. package/dist/delivery/delivery-run-control.js +10 -0
  112. package/dist/delivery/delivery-run-control.js.map +1 -1
  113. package/dist/delivery/delivery-supervisor.d.ts +33 -5
  114. package/dist/delivery/delivery-supervisor.d.ts.map +1 -1
  115. package/dist/delivery/delivery-supervisor.js +178 -26
  116. package/dist/delivery/delivery-supervisor.js.map +1 -1
  117. package/dist/delivery/delivery-tenant.d.ts +17 -0
  118. package/dist/delivery/delivery-tenant.d.ts.map +1 -0
  119. package/dist/delivery/delivery-tenant.js +50 -0
  120. package/dist/delivery/delivery-tenant.js.map +1 -0
  121. package/dist/delivery/delivery.d.ts +96 -2
  122. package/dist/delivery/delivery.d.ts.map +1 -1
  123. package/dist/delivery/delivery.js +803 -89
  124. package/dist/delivery/delivery.js.map +1 -1
  125. package/dist/delivery/inbox-records.d.ts.map +1 -1
  126. package/dist/delivery/inbox-records.js +9 -16
  127. package/dist/delivery/inbox-records.js.map +1 -1
  128. package/dist/delivery/inbox-storage.d.ts +14 -11
  129. package/dist/delivery/inbox-storage.d.ts.map +1 -1
  130. package/dist/delivery/inbox-storage.js +72 -78
  131. package/dist/delivery/inbox-storage.js.map +1 -1
  132. package/dist/delivery/inbox.d.ts +9 -12
  133. package/dist/delivery/inbox.d.ts.map +1 -1
  134. package/dist/delivery/inbox.js +13 -15
  135. package/dist/delivery/inbox.js.map +1 -1
  136. package/dist/delivery/reception-observation.d.ts +64 -0
  137. package/dist/delivery/reception-observation.d.ts.map +1 -0
  138. package/dist/delivery/reception-observation.js +78 -0
  139. package/dist/delivery/reception-observation.js.map +1 -0
  140. package/dist/delivery/sharded-work-registry.d.ts +6 -0
  141. package/dist/delivery/sharded-work-registry.d.ts.map +1 -1
  142. package/dist/delivery/sharded-work-registry.js +41 -4
  143. package/dist/delivery/sharded-work-registry.js.map +1 -1
  144. package/dist/entity/entity-storage-descriptor.d.ts.map +1 -1
  145. package/dist/entity/entity-storage-descriptor.js +7 -4
  146. package/dist/entity/entity-storage-descriptor.js.map +1 -1
  147. package/dist/index.d.ts +4 -2
  148. package/dist/index.d.ts.map +1 -1
  149. package/dist/index.js +2 -1
  150. package/dist/index.js.map +1 -1
  151. package/dist/integration/external-messages.d.ts.map +1 -1
  152. package/dist/integration/external-messages.js +9 -15
  153. package/dist/integration/external-messages.js.map +1 -1
  154. package/dist/integration/integration-broker.d.ts.map +1 -1
  155. package/dist/integration/integration-broker.js +112 -6
  156. package/dist/integration/integration-broker.js.map +1 -1
  157. package/dist/integration/third-party-context.d.ts.map +1 -1
  158. package/dist/integration/third-party-context.js +7 -10
  159. package/dist/integration/third-party-context.js.map +1 -1
  160. package/dist/repository/primitive-id.js +26 -11
  161. package/dist/repository/primitive-id.js.map +1 -1
  162. package/dist/repository/repository.d.ts +33 -62
  163. package/dist/repository/repository.d.ts.map +1 -1
  164. package/dist/repository/repository.js +1475 -1827
  165. package/dist/repository/repository.js.map +1 -1
  166. package/dist/runtime/runtime.d.ts +24 -0
  167. package/dist/runtime/runtime.d.ts.map +1 -1
  168. package/dist/runtime/runtime.js +31 -0
  169. package/dist/runtime/runtime.js.map +1 -1
  170. package/dist/runtime/signal-metadata.d.ts.map +1 -1
  171. package/dist/runtime/signal-metadata.js +8 -15
  172. package/dist/runtime/signal-metadata.js.map +1 -1
  173. package/dist/runtime/signal-publisher.d.ts +8 -36
  174. package/dist/runtime/signal-publisher.d.ts.map +1 -1
  175. package/dist/runtime/signal-publisher.js +68 -61
  176. package/dist/runtime/signal-publisher.js.map +1 -1
  177. package/dist/runtime/standalone-handler-runtime.d.ts +0 -7
  178. package/dist/runtime/standalone-handler-runtime.d.ts.map +1 -1
  179. package/dist/runtime/standalone-handler-runtime.js +14 -130
  180. package/dist/runtime/standalone-handler-runtime.js.map +1 -1
  181. package/dist/server/managed-delivery-gate.d.ts +34 -0
  182. package/dist/server/managed-delivery-gate.d.ts.map +1 -0
  183. package/dist/server/managed-delivery-gate.js +70 -0
  184. package/dist/server/managed-delivery-gate.js.map +1 -0
  185. package/dist/server/managed-server-application.d.ts +2 -2
  186. package/dist/server/managed-server-application.d.ts.map +1 -1
  187. package/dist/server/managed-server-application.js +471 -178
  188. package/dist/server/managed-server-application.js.map +1 -1
  189. package/dist/server/node-coordinator.d.ts +14 -0
  190. package/dist/server/node-coordinator.d.ts.map +1 -1
  191. package/dist/server/node-coordinator.js +266 -45
  192. package/dist/server/node-coordinator.js.map +1 -1
  193. package/dist/server/server-environment.d.ts +203 -25
  194. package/dist/server/server-environment.d.ts.map +1 -1
  195. package/dist/server/server-environment.js +661 -133
  196. package/dist/server/server-environment.js.map +1 -1
  197. package/dist/server/server-log.d.ts +7 -0
  198. package/dist/server/server-log.d.ts.map +1 -1
  199. package/dist/server/server-log.js +18 -1
  200. package/dist/server/server-log.js.map +1 -1
  201. package/dist/server/server.d.ts +18 -32
  202. package/dist/server/server.d.ts.map +1 -1
  203. package/dist/server/server.js +62 -203
  204. package/dist/server/server.js.map +1 -1
  205. package/dist/services/spine-services.d.ts +1 -1
  206. package/dist/services/spine-services.d.ts.map +1 -1
  207. package/dist/services/spine-services.js +399 -370
  208. package/dist/services/spine-services.js.map +1 -1
  209. package/dist/stand/event-origin-filter.d.ts +16 -0
  210. package/dist/stand/event-origin-filter.d.ts.map +1 -0
  211. package/dist/stand/event-origin-filter.js +124 -0
  212. package/dist/stand/event-origin-filter.js.map +1 -0
  213. package/dist/stand/stand.d.ts +14 -0
  214. package/dist/stand/stand.d.ts.map +1 -1
  215. package/dist/stand/stand.js +53 -9
  216. package/dist/stand/stand.js.map +1 -1
  217. package/dist/stand/subscription-observer.d.ts.map +1 -1
  218. package/dist/stand/subscription-observer.js +61 -40
  219. package/dist/stand/subscription-observer.js.map +1 -1
  220. package/dist/stand/subscription-registry.d.ts +6 -2
  221. package/dist/stand/subscription-registry.d.ts.map +1 -1
  222. package/dist/stand/subscription-registry.js +15 -11
  223. package/dist/stand/subscription-registry.js.map +1 -1
  224. package/dist/stand/subscription-runtime.d.ts +23 -4
  225. package/dist/stand/subscription-runtime.d.ts.map +1 -1
  226. package/dist/stand/subscription-runtime.js +84 -13
  227. package/dist/stand/subscription-runtime.js.map +1 -1
  228. package/dist/testing/index.d.ts.map +1 -1
  229. package/dist/testing/index.js +3 -2
  230. package/dist/testing/index.js.map +1 -1
  231. package/dist/tsconfig.tsbuildinfo +1 -1
  232. package/package.json +15 -15
  233. package/dist/agent/agent-admission.d.ts +0 -80
  234. package/dist/agent/agent-admission.d.ts.map +0 -1
  235. package/dist/agent/agent-admission.js +0 -127
  236. package/dist/agent/agent-admission.js.map +0 -1
  237. package/dist/agent/agent-ai-runtime.d.ts +0 -76
  238. package/dist/agent/agent-ai-runtime.d.ts.map +0 -1
  239. package/dist/agent/agent-ai-runtime.js +0 -1269
  240. package/dist/agent/agent-ai-runtime.js.map +0 -1
  241. package/dist/agent/agent-execution-fault.d.ts +0 -18
  242. package/dist/agent/agent-execution-fault.d.ts.map +0 -1
  243. package/dist/agent/agent-execution-fault.js.map +0 -1
  244. package/dist/agent/agent-execution-session.d.ts +0 -103
  245. package/dist/agent/agent-execution-session.d.ts.map +0 -1
  246. package/dist/agent/agent-execution-session.js +0 -238
  247. package/dist/agent/agent-execution-session.js.map +0 -1
  248. package/dist/agent/agent-interaction-audit.d.ts +0 -58
  249. package/dist/agent/agent-interaction-audit.d.ts.map +0 -1
  250. package/dist/agent/agent-interaction-audit.js +0 -114
  251. package/dist/agent/agent-interaction-audit.js.map +0 -1
  252. package/dist/agent/agent-interaction-events.d.ts +0 -40
  253. package/dist/agent/agent-interaction-events.d.ts.map +0 -1
  254. package/dist/agent/agent-interaction-events.js +0 -129
  255. package/dist/agent/agent-interaction-events.js.map +0 -1
  256. package/dist/agent/agent-mcp-budget.d.ts +0 -125
  257. package/dist/agent/agent-mcp-budget.d.ts.map +0 -1
  258. package/dist/agent/agent-mcp-budget.js +0 -566
  259. package/dist/agent/agent-mcp-budget.js.map +0 -1
  260. package/dist/agent/agent-mcp-host.d.ts +0 -125
  261. package/dist/agent/agent-mcp-host.d.ts.map +0 -1
  262. package/dist/agent/agent-mcp-host.js.map +0 -1
  263. package/dist/agent/agent-mcp-runtime.d.ts.map +0 -1
  264. package/dist/agent/agent-mcp-runtime.js.map +0 -1
  265. package/dist/agent/agent-read-runtime.d.ts +0 -70
  266. package/dist/agent/agent-read-runtime.d.ts.map +0 -1
  267. package/dist/agent/agent-read-runtime.js +0 -320
  268. package/dist/agent/agent-read-runtime.js.map +0 -1
  269. package/dist/agent/agent-revisions.d.ts +0 -35
  270. package/dist/agent/agent-revisions.d.ts.map +0 -1
  271. package/dist/agent/agent-revisions.js +0 -133
  272. package/dist/agent/agent-revisions.js.map +0 -1
  273. package/dist/agent/agent-scheduler.d.ts +0 -99
  274. package/dist/agent/agent-scheduler.d.ts.map +0 -1
  275. package/dist/agent/agent-scheduler.js +0 -398
  276. package/dist/agent/agent-scheduler.js.map +0 -1
  277. package/dist/bus/saved-dispatcher-binding.d.ts +0 -96
  278. package/dist/bus/saved-dispatcher-binding.d.ts.map +0 -1
  279. package/dist/bus/saved-dispatcher-binding.js +0 -35
  280. package/dist/bus/saved-dispatcher-binding.js.map +0 -1
  281. package/dist/delivery/delivery-run-coordinator.d.ts +0 -218
  282. package/dist/delivery/delivery-run-coordinator.d.ts.map +0 -1
  283. package/dist/delivery/delivery-run-coordinator.js +0 -609
  284. package/dist/delivery/delivery-run-coordinator.js.map +0 -1
  285. package/dist/delivery/parked-delivery-obligations.d.ts +0 -182
  286. package/dist/delivery/parked-delivery-obligations.d.ts.map +0 -1
  287. package/dist/delivery/parked-delivery-obligations.js +0 -390
  288. package/dist/delivery/parked-delivery-obligations.js.map +0 -1
  289. package/dist/server/environment-attachment.d.ts +0 -356
  290. package/dist/server/environment-attachment.d.ts.map +0 -1
  291. package/dist/server/environment-attachment.js +0 -2062
  292. package/dist/server/environment-attachment.js.map +0 -1
  293. package/dist/server/environment-delivery-records.d.ts +0 -77
  294. package/dist/server/environment-delivery-records.d.ts.map +0 -1
  295. package/dist/server/environment-delivery-records.js +0 -282
  296. package/dist/server/environment-delivery-records.js.map +0 -1
  297. package/dist/server/environment-delivery-worker.d.ts +0 -161
  298. package/dist/server/environment-delivery-worker.d.ts.map +0 -1
  299. package/dist/server/environment-delivery-worker.js +0 -673
  300. package/dist/server/environment-delivery-worker.js.map +0 -1
@@ -1,1269 +0,0 @@
1
- /*
2
- * Copyright 2026, CodeMatters. All rights reserved.
3
- *
4
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5
- * in compliance with the License. You may obtain a copy of the License at
6
- *
7
- * https://www.apache.org/licenses/LICENSE-2.0
8
- *
9
- * Unless required by applicable law or agreed to in writing, software distributed under the License
10
- * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11
- * or implied. See the License for the specific language governing permissions and limitations under
12
- * the License.
13
- */
14
- import { clone, create, toBinary } from "@bufbuild/protobuf";
15
- import { AnySchema, TimestampSchema } from "@bufbuild/protobuf/wkt";
16
- import { createHash, randomUUID } from "node:crypto";
17
- import { AgentExecutionFault } from "./agent-execution-fault.js";
18
- import { AnyMessages, Time, TypeUrls, Validate, } from "@spine-event-engine/core";
19
- import { admitDecision, backendDefinition, isAiModel, parseCandidate, selectDeployment, } from "@spine-event-engine/ai/spi/runtime";
20
- import { AiMcpSetupFailure } from "@spine-event-engine/ai/spi/adapter";
21
- import { AiAttemptIdSchema, AiCapabilityNameSchema, AiCapabilityRevisionSchema, AiContentDigestSchema, AiDeadlineMillisSchema, AiDiagnosticIdSchema, AiFailureCode, AiInputByteLimitSchema as InputBytesSchema, AiModelKind, AiExecutionMode, AgentAiOperationStartedSchema as OperationStartedSchema, AgentModelAttemptStartedSchema as AttemptStartedSchema, AgentModelAttemptFinishedSchema as AttemptFinishedSchema, AgentAiResultAdmittedSchema as ResultAdmittedSchema, AgentAiOperationFailedSchema as OperationFailedSchema, AiValidationRevisionSchema, ModelRefSchema, AiModelRequestLimitSchema as RequestLimitSchema, AiOperationIdSchema, AiOperationLimitsSchema, AiOutputByteLimitSchema as OutputBytesSchema, AiOutputTokenLimitSchema as OutputTokensSchema, AiOutcome, AiToolCallLimitSchema as ToolLimitSchema, ConversationIdSchema, DecisionRequestSchema, DecisionAnswerSchema, DecisionQuestionIdSchema, DecisionQuestionKind, DecisionResponseSchema, GenerationRequestSchema, GenerationResponseSchema, AgentHistoryEntrySchema, ConversationRecordIdSchema, ConversationRecordSchema, } from "@spine-event-engine/proto/agent";
22
- import { AgentAttemptEvidenceSchema, AgentExecutionJournalEntrySchema as JournalEntrySchema, AgentNamedOperationSchema, AgentExecutionHeadSchema, AgentExecutionRecordSchema, AgentSavedFailureSchema, AgentValidationIssueSchema, } from "@spine-event-engine/proto/generated/spine/server/agent/execution_record_pb.js";
23
- import { AgentExecutionSizes } from "@spine-event-engine/storage/provider";
24
- import { AgentExecutionSession } from "./agent-execution-session.js";
25
- import { AgentMcpBudget } from "./agent-mcp-budget.js";
26
- import { AgentMcpRuntime } from "./agent-mcp-runtime.js";
27
- import { AgentModelSelection } from "./agent-model-selection.js";
28
- import { AgentInteractionAudit } from "./agent-interaction-audit.js";
29
- const failureCodes = Object.freeze({
30
- INVALID_INPUT: AiFailureCode.INVALID_INPUT,
31
- UNSUPPORTED_CAPABILITY: AiFailureCode.UNSUPPORTED_CAPABILITY,
32
- AUTHENTICATION_REQUIRED: AiFailureCode.AUTHENTICATION_REQUIRED,
33
- RATE_LIMITED: AiFailureCode.RATE_LIMITED,
34
- UNAVAILABLE: AiFailureCode.UNAVAILABLE,
35
- REFUSED: AiFailureCode.REFUSED,
36
- INVALID_OUTPUT: AiFailureCode.INVALID_OUTPUT,
37
- BUDGET_EXCEEDED: AiFailureCode.BUDGET_EXCEEDED,
38
- TOOL_FAILED: AiFailureCode.TOOL_FAILED,
39
- TOOL_OUTCOME_UNKNOWN: AiFailureCode.TOOL_OUTCOME_UNKNOWN,
40
- CANCELLED: AiFailureCode.CANCELLED,
41
- DEADLINE_EXCEEDED: AiFailureCode.DEADLINE_EXCEEDED,
42
- });
43
- /**
44
- * Indicates a saved physical request with no recorded response after recovery.
45
- */
46
- export class AgentUncertainAttemptError extends Error {
47
- /**
48
- * Creates an error that prevents replaying an unresolved physical request.
49
- */
50
- constructor() {
51
- super("Agent physical request outcome is uncertain; it cannot be resent.");
52
- }
53
- }
54
- /**
55
- * Provides one handler's named AI calls against a fenced execution journal.
56
- */
57
- export class AgentAiRuntime {
58
- registry;
59
- repository;
60
- scope;
61
- session;
62
- handlerOrdinal;
63
- audit;
64
- #names = new Set();
65
- #controller = new AbortController();
66
- #signal;
67
- #cursor = 0;
68
- #busy = false;
69
- #closed = false;
70
- /**
71
- * Binds named calls to the selected repository and fenced invocation.
72
- *
73
- * @param registry Configured model and MCP registrations.
74
- * @param repository Repository model policy.
75
- * @param scope Accepted actor, source, Bounded Context, and tenant.
76
- * @param session Fenced durable execution session.
77
- * @param handlerOrdinal Saved generated handler order.
78
- * @param audit Paired Agent history and System Event writer.
79
- */
80
- constructor(registry, repository, scope, session, handlerOrdinal, audit) {
81
- this.registry = registry;
82
- this.repository = repository;
83
- this.scope = scope;
84
- this.session = session;
85
- this.handlerOrdinal = handlerOrdinal;
86
- this.audit = audit;
87
- this.#signal = AbortSignal.any([session.signal, this.#controller.signal]);
88
- }
89
- /**
90
- * Returns one saved or newly admitted typed model result.
91
- *
92
- * @typeParam I Generated input descriptor.
93
- * @typeParam O Generated admitted-output descriptor.
94
- * @param model Registered capability to invoke.
95
- * @param request Named call, conversation, and typed input.
96
- * @returns Saved or newly admitted result with its operation identity.
97
- */
98
- async invoke(model, request) {
99
- this.#requireOpen();
100
- if (this.#busy)
101
- throw new Error("Agent AI calls must be sequential within one handler.");
102
- this.#busy = true;
103
- try {
104
- if (!isAiModel(model) || !this.repository.models.includes(model))
105
- throw new TypeError("Agent model is not registered for this repository.");
106
- if (request.call.trim().length === 0 || this.#names.has(request.call))
107
- throw new TypeError("Agent AI call names must be nonblank and unique per handler.");
108
- this.#names.add(request.call);
109
- Validate.check(ConversationIdSchema, request.conversation);
110
- Validate.check(model.definition.input, request.input);
111
- const operation = await this.#operation(model, request);
112
- this.#requireOpen();
113
- return (this.#savedResult(model, operation) ?? (await this.#dispatch(model, request, operation)));
114
- }
115
- finally {
116
- this.#busy = false;
117
- }
118
- }
119
- /**
120
- * Restores a terminal named result without contacting the backend.
121
- *
122
- * @typeParam O Generated admitted-output descriptor.
123
- */
124
- #savedResult(model, operation) {
125
- const operationId = operation.operation;
126
- if (operationId === undefined)
127
- throw new Error("Agent named operation has no durable ID.");
128
- if (operation.result.case === "admittedOutput") {
129
- const value = AnyMessages.unpack(operation.result.value, model.definition.output);
130
- if (value === undefined)
131
- throw new Error("Saved Agent AI output type changed.");
132
- return { ok: true, value, operationId };
133
- }
134
- if (operation.result.case === "failure") {
135
- const saved = operation.result.value;
136
- const code = Object.entries(failureCodes).find(([, value]) => value === saved.code)?.[0];
137
- if (code === undefined || saved.diagnostic === undefined)
138
- throw new Error("Saved Agent AI failure category is invalid.");
139
- return {
140
- ok: false,
141
- operationId,
142
- failure: {
143
- code: code,
144
- retryableByNewSignal: saved.retryableByNewSignal,
145
- diagnosticId: saved.diagnostic.value,
146
- },
147
- };
148
- }
149
- return undefined;
150
- }
151
- /**
152
- * Sets a preference only for a later accepted signal.
153
- *
154
- * @param kind Generation or decision selection.
155
- * @param model Deployment to prefer for later accepted work.
156
- */
157
- select(kind, model) {
158
- this.#requireOpen();
159
- const selectedKind = kind === AiModelKind.GENERATION
160
- ? "generation"
161
- : kind === AiModelKind.DECISION
162
- ? "decision"
163
- : undefined;
164
- if (selectedKind === undefined)
165
- throw new TypeError("Agent model preference requires a supported kind.");
166
- if (model !== undefined) {
167
- Validate.check(ModelRefSchema, model);
168
- selectDeployment(this.registry, {
169
- kind: selectedKind,
170
- models: this.repository.models,
171
- instancePreference: model,
172
- ...(this.repository.allowedModels?.[selectedKind] === undefined
173
- ? {}
174
- : { allowedModels: this.repository.allowedModels[selectedKind] }),
175
- });
176
- }
177
- this.session.stagePreference(kind, model);
178
- }
179
- /**
180
- * Rejects recovery when the accepted handler no longer issues its saved calls.
181
- */
182
- finish() {
183
- this.#requireOpen();
184
- if (this.#busy)
185
- throw new Error("Agent handler returned with a pending AI call.");
186
- const saved = this.#savedOperations(this.session.record());
187
- if (this.#cursor !== saved.length)
188
- throw new AgentExecutionFault("REPLAY_DIVERGENCE", "Agent named operation sequence changed on recovery.");
189
- }
190
- /**
191
- * Rejects callbacks retained after the generated handler returns.
192
- */
193
- close() {
194
- this.#closed = true;
195
- this.#controller.abort();
196
- }
197
- #requireOpen() {
198
- if (this.#closed || this.#signal.aborted)
199
- throw new Error("Agent AI handler capability is closed.");
200
- }
201
- /**
202
- * Loads or persists the next exact handler-scoped named operation.
203
- *
204
- * @typeParam I Generated input descriptor.
205
- * @typeParam O Generated admitted-output descriptor.
206
- */
207
- async #operation(model, request) {
208
- const saved = this.#savedOperations(this.session.record())[this.#cursor++];
209
- if (saved !== undefined) {
210
- this.#verifyOperation(saved, model, request);
211
- return saved;
212
- }
213
- const created = this.#newOperation(model, request);
214
- const change = (record) => {
215
- record.journal.push(create(JournalEntrySchema, {
216
- ordinal: BigInt(record.journal.length),
217
- evidence: { case: "operation", value: created },
218
- }));
219
- return record;
220
- };
221
- if (this.audit === undefined)
222
- await this.session.update(change);
223
- else
224
- await this.audit.save(OperationStartedSchema, this.#operationStarted(model, request, created), change);
225
- return created;
226
- }
227
- /**
228
- * Describes a newly journaled named operation using its original typed input.
229
- *
230
- * @typeParam I Generated input descriptor.
231
- * @typeParam O Generated admitted-output descriptor.
232
- */
233
- #operationStarted(model, request, operation) {
234
- const kind = model.definition.kind === "generation" ? AiModelKind.GENERATION : AiModelKind.DECISION;
235
- const mode = model.definition.kind === "decision"
236
- ? AiExecutionMode.DECISION_DIRECT
237
- : model.definition.outputMode === "native-schema"
238
- ? AiExecutionMode.GENERATION_NATIVE_SCHEMA
239
- : AiExecutionMode.GENERATION_PROMPT_VALIDATE;
240
- const digest = createHash("sha256")
241
- .update(toBinary(model.definition.input, request.input))
242
- .digest("hex");
243
- return create(OperationStartedSchema, {
244
- operation: this.audit?.reference(operation, kind),
245
- capability: operation.capability,
246
- capabilityRevision: operation.capabilityRevision,
247
- input: create(AiContentDigestSchema, { value: digest }),
248
- limits: operation.limits,
249
- startedAt: Time.currentTime(),
250
- mode,
251
- });
252
- }
253
- /**
254
- * Rejects changed call facts before any recovery side effect.
255
- *
256
- * @typeParam I Generated input descriptor.
257
- * @typeParam O Generated admitted-output descriptor.
258
- */
259
- #verifyOperation(saved, model, request) {
260
- if (saved.callName !== request.call ||
261
- saved.conversation?.value !== request.conversation.value ||
262
- saved.capability?.value !== model.definition.name ||
263
- saved.capabilityRevision?.value !== model.definition.version ||
264
- !this.#sameInput(saved, model.definition.input, request.input))
265
- throw new AgentExecutionFault("REPLAY_DIVERGENCE", "Agent named operation changed on recovery.");
266
- }
267
- /**
268
- * Captures one typed call's immutable accepted facts.
269
- *
270
- * @typeParam I Generated input descriptor.
271
- * @typeParam O Generated admitted-output descriptor.
272
- */
273
- #newOperation(model, request) {
274
- const deadline = this.#operationDeadline(model.definition.limits.deadlineMs);
275
- return create(AgentNamedOperationSchema, {
276
- handlerOrdinal: this.handlerOrdinal,
277
- callName: request.call,
278
- conversation: clone(ConversationIdSchema, request.conversation),
279
- operation: create(AiOperationIdSchema, { value: randomUUID() }),
280
- limits: this.#limits(model),
281
- input: AnyMessages.pack(model.definition.input, request.input),
282
- capability: create(AiCapabilityNameSchema, { value: model.definition.name }),
283
- capabilityRevision: create(AiCapabilityRevisionSchema, { value: model.definition.version }),
284
- ...(deadline === undefined ? {} : { deadline }),
285
- });
286
- }
287
- /**
288
- * Samples Time once and caps a capability deadline at the saved invocation deadline.
289
- */
290
- #operationDeadline(durationMs) {
291
- const invocationDeadline = this.#invocationDeadline();
292
- if (durationMs === undefined && invocationDeadline === undefined)
293
- return undefined;
294
- const now = Time.currentTime();
295
- const nowMs = Number(now.seconds) * 1_000 + Math.floor(now.nanos / 1_000_000);
296
- const deadlineMs = durationMs === undefined
297
- ? invocationDeadline
298
- : invocationDeadline === undefined
299
- ? nowMs + durationMs
300
- : Math.min(nowMs + durationMs, invocationDeadline);
301
- if (deadlineMs === undefined)
302
- throw new Error("Agent deadline calculation unavailable.");
303
- return create(TimestampSchema, {
304
- seconds: BigInt(Math.floor(deadlineMs / 1_000)),
305
- nanos: (deadlineMs % 1_000) * 1_000_000,
306
- });
307
- }
308
- /**
309
- * Calls the selected authenticated backend after recording the named operation.
310
- *
311
- * @typeParam I Generated input descriptor.
312
- * @typeParam O Generated admitted-output descriptor.
313
- */
314
- async #dispatch(model, request, operation) {
315
- const prepared = await this.#prepareExecution(model, request, operation);
316
- if (prepared instanceof AiMcpSetupFailure)
317
- return this.#setupFailure(model, operation, prepared);
318
- const { backend, execution, mcp } = prepared;
319
- try {
320
- this.#requireOpen();
321
- const outcome = await AgentModelSelection.awaitHook(backend.execute(execution), this.#signal, this.#deadline(operation));
322
- this.#requireOpen();
323
- if (outcome.ok)
324
- Validate.check(model.definition.output, outcome.value);
325
- await this.#saveOutcome(model, operation, outcome);
326
- return outcome.ok
327
- ? {
328
- ok: true,
329
- value: outcome.value,
330
- operationId: this.#operationId(operation),
331
- }
332
- : { ok: false, failure: outcome.failure, operationId: this.#operationId(operation) };
333
- }
334
- finally {
335
- await this.#closeMcp(mcp, operation);
336
- }
337
- }
338
- /**
339
- * Classifies only a typed MCP setup failure from execution preparation.
340
- *
341
- * @typeParam I Generated input descriptor.
342
- * @typeParam O Generated admitted-output descriptor.
343
- */
344
- async #prepareExecution(model, request, operation) {
345
- try {
346
- return await this.#execution(model, request, operation);
347
- }
348
- catch (error) {
349
- if (error instanceof AiMcpSetupFailure)
350
- return error;
351
- throw error;
352
- }
353
- }
354
- /**
355
- * Saves only a typed MCP preparation denial as the named operation result.
356
- *
357
- * @typeParam O Generated admitted-output descriptor.
358
- */
359
- async #setupFailure(model, operation, error) {
360
- this.#requireOpen();
361
- const failure = await this.#recordFailure(operation, error.code, false);
362
- await this.#saveOutcome(model, operation, { ok: false, failure });
363
- return { ok: false, failure, operationId: this.#operationId(operation) };
364
- }
365
- /**
366
- * Selects the saved deployment under current registry policy.
367
- */
368
- #selectedBackend(model) {
369
- const selected = this.session
370
- .record()
371
- .started?.models.find((item) => item.kind ===
372
- (model.definition.kind === "generation" ? AiModelKind.GENERATION : AiModelKind.DECISION));
373
- if (selected?.model === undefined || selected.connection === undefined)
374
- throw new Error("Agent AI kind has no saved authenticated deployment.");
375
- const registration = selectDeployment(this.registry, {
376
- kind: model.definition.kind,
377
- models: this.repository.models,
378
- instancePreference: selected.model,
379
- ...(this.repository.allowedModels?.[model.definition.kind] === undefined
380
- ? {}
381
- : { allowedModels: this.repository.allowedModels[model.definition.kind] }),
382
- });
383
- const backend = backendDefinition(registration);
384
- return { backend, connection: selected.connection };
385
- }
386
- /**
387
- * Reauthorizes and binds the saved operation to the adapter execution.
388
- *
389
- * @typeParam I Generated input descriptor.
390
- * @typeParam O Generated admitted-output descriptor.
391
- */
392
- async #execution(model, request, operation) {
393
- const { backend, connection } = this.#selectedBackend(model);
394
- const identity = await this.#connectIdentity(backend, connection, operation);
395
- const tools = model.definition.kind === "generation" ? (model.definition.tools ?? []) : [];
396
- const mcp = tools.length
397
- ? new AgentMcpRuntime(this.#mcpHost(backend, operation, model), tools)
398
- : undefined;
399
- try {
400
- const execution = await this.#connectExecution(backend, model, request, operation, identity, mcp);
401
- return { backend, execution, mcp };
402
- }
403
- catch (error) {
404
- await this.#closeMcp(mcp, operation);
405
- throw error;
406
- }
407
- }
408
- /**
409
- * Records safe cleanup failure without replacing a saved result or setup error.
410
- */
411
- async #closeMcp(mcp, operation) {
412
- if (mcp === undefined)
413
- return;
414
- try {
415
- await mcp.close();
416
- }
417
- catch {
418
- try {
419
- await this.#recordFailure(operation, "TOOL_FAILED", false);
420
- }
421
- catch {
422
- // The original result or setup error remains authoritative after cleanup failure.
423
- }
424
- }
425
- }
426
- /**
427
- * Prepares the exact catalog and reconnects the saved model identity.
428
- *
429
- * @typeParam I Generated input descriptor.
430
- * @typeParam O Generated admitted-output descriptor.
431
- */
432
- async #connectExecution(backend, model, request, operation, identity, mcp) {
433
- const advertisedTools = await mcp?.prepare();
434
- const control = this.#control(operation, model, mcp);
435
- const connected = await AgentModelSelection.awaitHook(backend.connect(this.scope, identity, control), this.#signal, control.deadlineEpochMs);
436
- if (!this.#sameIdentity(connected.identity, identity))
437
- throw new AgentExecutionFault("REVISION_CHANGED", "Agent backend connection identity changed.");
438
- return this.#adapterExecution(model, request, operation, identity, connected.model, control, advertisedTools);
439
- }
440
- /**
441
- * Materializes the checked adapter invocation after connection and catalog setup.
442
- *
443
- * @typeParam I Generated input descriptor.
444
- * @typeParam O Generated admitted-output descriptor.
445
- */
446
- #adapterExecution(model, request, operation, identity, connectedModel, control, advertisedTools) {
447
- return {
448
- call: request.call,
449
- operationId: this.#operationId(operation),
450
- scope: this.scope,
451
- identity,
452
- model: connectedModel,
453
- // Adapter SPI erases the factory-validated descriptor pair at this boundary.
454
- definition: model.definition,
455
- input: request.input,
456
- control,
457
- ...(advertisedTools === undefined ? {} : { advertisedTools }),
458
- };
459
- }
460
- /**
461
- * Binds the MCP module to this invocation's single fenced budget authority.
462
- */
463
- #mcpHost(backend, operation, model) {
464
- const deadlineEpochMs = this.#deadline(operation);
465
- const budget = new AgentMcpBudget(this.session, operation, deadlineEpochMs, this.audit);
466
- return {
467
- scope: this.scope,
468
- registry: this.registry,
469
- backend,
470
- operation,
471
- session: this.session,
472
- signal: this.#signal,
473
- ...(deadlineEpochMs === undefined ? {} : { deadlineEpochMs }),
474
- reserveMessage: (server, message) => budget.reserveMessage(server, message),
475
- onReceived: (id, bytes) => {
476
- budget.onReceived(id, bytes);
477
- },
478
- finishMessage: (id, bytes) => budget.finishMessage(id, bytes),
479
- journalToolIntent: (invocation, facts) => budget.journalToolIntent(invocation, facts, model.definition.limits.toolCalls),
480
- markToolDispatched: (id) => budget.markToolDispatched(id),
481
- finishTool: (id, response, history) => budget.finishTool(id, response, [history]),
482
- recordFailure: (code, retryable) => this.#recordFailure(operation, code, retryable),
483
- };
484
- }
485
- /**
486
- * Retains the admitted result before the domain handler can observe it.
487
- */
488
- async #saveOutcome(model, operation, outcome) {
489
- const change = this.#outcomeChange(model, operation, outcome);
490
- if (this.audit === undefined)
491
- await this.session.update(change);
492
- else if (outcome.ok)
493
- await this.audit.save(ResultAdmittedSchema, this.#admittedEvent(model, operation, outcome), change);
494
- else
495
- await this.audit.save(OperationFailedSchema, this.#failedEvent(model, operation, outcome), change);
496
- }
497
- /**
498
- * Applies the final typed result to its named operation.
499
- */
500
- #outcomeChange(model, operation, outcome) {
501
- return (record) => {
502
- const saved = this.#findOperation(record, operation);
503
- saved.result = outcome.ok
504
- ? {
505
- case: "admittedOutput",
506
- value: AnyMessages.pack(model.definition.output, outcome.value),
507
- }
508
- : {
509
- case: "failure",
510
- value: create(AgentSavedFailureSchema, {
511
- code: failureCodes[outcome.failure.code],
512
- retryableByNewSignal: outcome.failure.retryableByNewSignal,
513
- diagnostic: create(AiDiagnosticIdSchema, { value: outcome.failure.diagnosticId }),
514
- }),
515
- };
516
- const response = record.journal.findLast((entry) => entry.evidence.case === "attempt" &&
517
- entry.evidence.value.operation?.value === operation.operation?.value);
518
- saved.outcome =
519
- response?.evidence.case === "attempt" ? response.evidence.value.outcome : AiOutcome.FAILED;
520
- return record;
521
- };
522
- }
523
- /**
524
- * Describes one locally admitted output without exposing its content.
525
- */
526
- #admittedEvent(model, operation, outcome) {
527
- return create(ResultAdmittedSchema, {
528
- operation: this.audit?.reference(operation, this.#modelKind(model)),
529
- result: create(AiContentDigestSchema, {
530
- value: createHash("sha256")
531
- .update(toBinary(model.definition.output, outcome.value))
532
- .digest("hex"),
533
- }),
534
- validationRevision: create(AiValidationRevisionSchema, {
535
- value: model.definition.validation?.version ?? model.definition.version,
536
- }),
537
- admittedAt: Time.currentTime(),
538
- });
539
- }
540
- /**
541
- * Describes one terminal logical failure with its original safe diagnostic.
542
- */
543
- #failedEvent(model, operation, outcome) {
544
- const last = this.#lastAttempt(operation);
545
- return create(OperationFailedSchema, {
546
- operation: this.audit?.reference(operation, this.#modelKind(model)),
547
- outcome: last?.outcome === AiOutcome.TOOL_REQUESTED
548
- ? AiOutcome.FAILED
549
- : (last?.outcome ?? AiOutcome.FAILED),
550
- diagnosticId: create(AiDiagnosticIdSchema, { value: outcome.failure.diagnosticId }),
551
- ...(last?.attempt === undefined ? {} : { attempt: last.attempt }),
552
- failedAt: Time.currentTime(),
553
- failure: failureCodes[outcome.failure.code],
554
- });
555
- }
556
- /**
557
- * Finds the last saved physical attempt of one named operation.
558
- */
559
- #lastAttempt(operation) {
560
- const entry = this.session
561
- .record()
562
- .journal.findLast((item) => item.evidence.case === "attempt" &&
563
- item.evidence.value.operation?.value === operation.operation?.value);
564
- return entry?.evidence.case === "attempt" ? entry.evidence.value : undefined;
565
- }
566
- /**
567
- * Converts the factory-defined API kind to its persisted System-event enum.
568
- */
569
- #modelKind(model) {
570
- return model.definition.kind === "generation" ? AiModelKind.GENERATION : AiModelKind.DECISION;
571
- }
572
- /**
573
- * Requires the durable identity of a named operation.
574
- */
575
- #operationId(operation) {
576
- if (operation.operation === undefined)
577
- throw new Error("Agent named operation has no ID.");
578
- return operation.operation;
579
- }
580
- /**
581
- * Restores nonsecret connection identity and rejects drift before use.
582
- */
583
- async #connectIdentity(backend, saved, operation) {
584
- if (saved === undefined)
585
- throw new Error("Saved Agent connection identity is absent.");
586
- const deadlineEpochMs = this.#deadline(operation);
587
- const control = {
588
- signal: this.#signal,
589
- ...(deadlineEpochMs === undefined ? {} : { deadlineEpochMs }),
590
- };
591
- const identity = await AgentModelSelection.awaitHook(backend.resolveIdentity(this.scope, control), this.#signal, deadlineEpochMs);
592
- const authorized = await AgentModelSelection.awaitHook(backend.authorizeUse(this.scope, identity, control), this.#signal, deadlineEpochMs);
593
- if (!authorized || !this.#sameIdentity(identity, this.#savedIdentity(saved)))
594
- throw new AgentExecutionFault("REVISION_CHANGED", "Agent model identity or authorization changed.");
595
- return identity;
596
- }
597
- /**
598
- * Copies credential-free identity fields from a saved model connection.
599
- *
600
- * @param saved Durable selected connection fields.
601
- * @returns Identity comparable with the current model binding.
602
- */
603
- #savedIdentity(saved) {
604
- return {
605
- provider: saved?.provider?.value ?? "",
606
- account: saved?.account?.value ?? "",
607
- endpoint: saved?.endpoint?.value ?? "",
608
- model: saved?.model?.value ?? "",
609
- };
610
- }
611
- /**
612
- * Compares all credential-free fields of a selected connection.
613
- */
614
- #sameIdentity(left, right) {
615
- return (left.provider === right.provider &&
616
- left.account === right.account &&
617
- left.endpoint === right.endpoint &&
618
- left.model === right.model);
619
- }
620
- /**
621
- * Reads the saved invocation deadline without extending it on restart.
622
- */
623
- #invocationDeadline() {
624
- const deadline = this.session.record().started?.deadline;
625
- if (deadline === undefined) {
626
- if (this.session.record().started?.bounds?.deadlineMillis !== undefined)
627
- throw new Error("Agent invocation deadline was not saved.");
628
- return undefined;
629
- }
630
- return Number(deadline.seconds) * 1_000 + Math.floor(deadline.nanos / 1_000_000);
631
- }
632
- /**
633
- * Reads the persisted per-capability absolute deadline.
634
- */
635
- #deadline(operation) {
636
- const deadline = operation.deadline;
637
- const invocationDeadline = this.#invocationDeadline();
638
- if (deadline === undefined) {
639
- if (operation.limits?.deadlineMs !== undefined)
640
- throw new Error("Agent operation deadline was not saved.");
641
- return invocationDeadline;
642
- }
643
- const operationDeadline = Number(deadline.seconds) * 1_000 + Math.floor(deadline.nanos / 1_000_000);
644
- return invocationDeadline === undefined
645
- ? operationDeadline
646
- : Math.min(invocationDeadline, operationDeadline);
647
- }
648
- /**
649
- * Enumerates this handler's named calls in original order.
650
- */
651
- #savedOperations(record) {
652
- return record.journal.flatMap((entry) => entry.evidence.case === "operation" &&
653
- entry.evidence.value.handlerOrdinal === this.handlerOrdinal
654
- ? [entry.evidence.value]
655
- : []);
656
- }
657
- /**
658
- * Compares exact canonical typed application input.
659
- *
660
- * @typeParam I Generated input descriptor.
661
- */
662
- #sameInput(saved, schema, input) {
663
- const packed = saved.input;
664
- if (packed === undefined)
665
- return false;
666
- const current = AnyMessages.pack(schema, input);
667
- return (packed.typeUrl === current.typeUrl &&
668
- Buffer.compare(Buffer.from(packed.value), Buffer.from(current.value)) === 0);
669
- }
670
- /**
671
- * Materializes per-capability immutable operation limits.
672
- */
673
- #limits(model) {
674
- const limits = model.definition.limits;
675
- return create(AiOperationLimitsSchema, {
676
- ...(limits.modelRequests === undefined
677
- ? {}
678
- : { modelRequests: create(RequestLimitSchema, { value: limits.modelRequests }) }),
679
- ...(limits.toolCalls === undefined
680
- ? {}
681
- : { toolCalls: create(ToolLimitSchema, { value: limits.toolCalls }) }),
682
- ...(limits.deadlineMs === undefined
683
- ? {}
684
- : { deadlineMs: create(AiDeadlineMillisSchema, { value: BigInt(limits.deadlineMs) }) }),
685
- ...(limits.maxInputBytes === undefined
686
- ? {}
687
- : { maxInputBytes: create(InputBytesSchema, { value: BigInt(limits.maxInputBytes) }) }),
688
- ...(limits.maxOutputBytes === undefined
689
- ? {}
690
- : { maxOutputBytes: create(OutputBytesSchema, { value: BigInt(limits.maxOutputBytes) }) }),
691
- ...(limits.maxOutputTokens === undefined
692
- ? {}
693
- : {
694
- maxOutputTokens: create(OutputTokensSchema, {
695
- value: BigInt(limits.maxOutputTokens),
696
- }),
697
- }),
698
- });
699
- }
700
- /**
701
- * Supplies fenced physical-attempt controls for the selected backend.
702
- */
703
- #control(operation, model, mcp) {
704
- const deadlineEpochMs = this.#deadline(operation);
705
- const received = new Map();
706
- let attemptNumber = 0;
707
- return {
708
- signal: this.#signal,
709
- ...(deadlineEpochMs === undefined ? {} : { deadlineEpochMs }),
710
- nowEpochMs: () => Time.currentTimeMillis(),
711
- hasAuthority: () => !this.#signal.aborted &&
712
- (deadlineEpochMs === undefined || Time.currentTimeMillis() < deadlineEpochMs),
713
- beginAttempt: (request) => this.#beginAttempt(operation, model, request, ++attemptNumber),
714
- reserveTransport: (id, bytes, credit) => this.#reserve(id, bytes, credit, model),
715
- onReceived: (id, bytes) => {
716
- this.#providerBytes(received, id, bytes);
717
- },
718
- finishAttempt: (completion) => this.#finishAttempt(operation, completion, received),
719
- recordFailure: (code, retryableByNewSignal) => this.#recordFailure(operation, code, retryableByNewSignal),
720
- admitGeneration: (candidate, definition, input) => parseCandidate(definition.output, candidate, (value) => definition.validation?.check(value, input) ?? []),
721
- admitDecision: (result, definition, input, rounding) => admitDecision(model, result, input, rounding ?? {}),
722
- callTool: (invocation) => this.#callTool(mcp, invocation),
723
- };
724
- }
725
- /**
726
- * Delegates only configured proposals to the selected MCP runtime.
727
- */
728
- #callTool(mcp, invocation) {
729
- if (mcp === undefined)
730
- return Promise.reject(new Error("Agent capability has no configured MCP tools."));
731
- return mcp.call(invocation);
732
- }
733
- /**
734
- * Counts decoded provider bytes before returning control to its transport.
735
- */
736
- #providerBytes(received, id, bytes) {
737
- if (!Number.isSafeInteger(bytes) || bytes < 0)
738
- throw new Error("Agent provider receipt byte count is invalid.");
739
- received.set(id, (received.get(id) ?? 0) + bytes);
740
- }
741
- /**
742
- * Persists a safe diagnostic before exposing its identity to the adapter.
743
- */
744
- async #recordFailure(operation, code, retryableByNewSignal) {
745
- const failure = { code, retryableByNewSignal, diagnosticId: randomUUID() };
746
- await this.session.update((record) => {
747
- const saved = this.#findOperation(record, operation);
748
- saved.diagnostics.push(create(AgentSavedFailureSchema, {
749
- code: failureCodes[code],
750
- retryableByNewSignal,
751
- diagnostic: create(AiDiagnosticIdSchema, { value: failure.diagnosticId }),
752
- }));
753
- const limit = record.started?.bounds?.maxRecoveryBytes;
754
- if (limit !== undefined && BigInt(AgentExecutionSizes.record(record)) > limit)
755
- throw new Error("Agent diagnostic exceeds the invocation recovery byte bound.");
756
- return record;
757
- });
758
- return failure;
759
- }
760
- /**
761
- * Restores only the exact diagnostic referenced by a saved response.
762
- */
763
- #savedDiagnostic(operation, id) {
764
- const saved = this.#findOperation(this.session.record(), operation).diagnostics.find((item) => item.diagnostic?.value === id);
765
- const code = Object.entries(failureCodes).find(([, value]) => value === saved?.code)?.[0];
766
- if (saved === undefined || code === undefined)
767
- throw new Error("Saved Agent model response references an unknown diagnostic.");
768
- return {
769
- code: code,
770
- diagnosticId: id,
771
- retryableByNewSignal: saved.retryableByNewSignal,
772
- };
773
- }
774
- /**
775
- * Finds the current journal image of a previously admitted operation.
776
- */
777
- #findOperation(record, operation) {
778
- const entry = record.journal.find((item) => item.evidence.case === "operation" &&
779
- item.evidence.value.operation?.value === operation.operation?.value);
780
- if (entry?.evidence.case !== "operation")
781
- throw new Error("Agent named operation journal disappeared.");
782
- return entry.evidence.value;
783
- }
784
- /**
785
- * Persists one physical request before an adapter receives a new ticket.
786
- */
787
- async #beginAttempt(operation, model, request, number) {
788
- const prior = this.#priorAttempt(operation, number);
789
- if (prior !== undefined)
790
- return this.#replayAttempt(operation, request, prior);
791
- const deadlineEpochMs = this.#deadline(operation);
792
- this.#checkAttemptBounds(model, number, deadlineEpochMs);
793
- const id = randomUUID();
794
- const requestContent = request.kind === "generation"
795
- ? AnyMessages.pack(GenerationRequestSchema, request.content)
796
- : AnyMessages.pack(DecisionRequestSchema, request.content);
797
- const history = this.#conversationHistory(operation, id, requestContent);
798
- await this.#saveAttempt(operation, request, number, id, history);
799
- return {
800
- id,
801
- ...(model.definition.limits.maxInputBytes === undefined
802
- ? {}
803
- : { maxInputBytes: model.definition.limits.maxInputBytes }),
804
- ...(model.definition.limits.maxOutputBytes === undefined
805
- ? {}
806
- : { maxOutputBytes: model.definition.limits.maxOutputBytes }),
807
- ...(deadlineEpochMs === undefined ? {} : { deadlineEpochMs }),
808
- signal: this.#signal,
809
- };
810
- }
811
- /**
812
- * Checks the selected model's explicit request and deadline bounds before journaling.
813
- */
814
- #checkAttemptBounds(model, number, deadlineEpochMs) {
815
- if (this.#signal.aborted ||
816
- (deadlineEpochMs !== undefined && Time.currentTimeMillis() >= deadlineEpochMs))
817
- throw new Error("Agent model attempt deadline expired.");
818
- const operationLimit = model.definition.limits.modelRequests;
819
- const invocationLimit = this.session.record().started?.bounds?.modelRequests;
820
- if ((operationLimit !== undefined && number > operationLimit) ||
821
- (invocationLimit !== undefined && this.#attemptCount() >= Number(invocationLimit)))
822
- throw new AgentExecutionFault("MODEL_BUDGET_EXCEEDED", "Agent physical model request budget is exhausted.");
823
- }
824
- /**
825
- * Finds the exact physical ordinal already saved for recovery.
826
- */
827
- #priorAttempt(operation, number) {
828
- const entry = this.session
829
- .record()
830
- .journal.find((item) => item.evidence.case === "attempt" &&
831
- item.evidence.value.operation?.value === operation.operation?.value &&
832
- item.evidence.value.physicalAttempt === BigInt(number));
833
- return entry?.evidence.case === "attempt" ? entry.evidence.value : undefined;
834
- }
835
- /**
836
- * Restores saved content and its exact diagnostic without a new ticket.
837
- */
838
- #replayAttempt(operation, request, prior) {
839
- if (!this.#sameRequest(prior, request))
840
- throw new AgentExecutionFault("REPLAY_DIVERGENCE", "Saved Agent provider request changed on recovery.");
841
- if (prior.response.case !== "generationResponse" && prior.response.case !== "decisionResponse")
842
- throw new AgentUncertainAttemptError();
843
- const diagnosticId = prior.response.value.diagnosticId?.value;
844
- const failure = diagnosticId === undefined ? undefined : this.#savedDiagnostic(operation, diagnosticId);
845
- return {
846
- kind: "replay",
847
- id: prior.attempt?.value ?? "",
848
- response: prior.response.value,
849
- issues: prior.validationIssues.map((issue) => ({
850
- code: issue.code,
851
- path: issue.path,
852
- message: issue.message,
853
- })),
854
- ...(failure === undefined ? {} : { failure }),
855
- };
856
- }
857
- /**
858
- * Saves an original request with its conversation row in one provider mutation.
859
- */
860
- async #saveAttempt(operation, request, number, id, history) {
861
- const change = this.#attemptChange(operation, request, number, id);
862
- if (this.audit === undefined)
863
- await this.session.update(change, [history]);
864
- else
865
- await this.audit.save(AttemptStartedSchema, this.#attemptStarted(operation, request, id), change, [history]);
866
- }
867
- /**
868
- * Appends a physical request without consuming a second ticket.
869
- */
870
- #attemptChange(operation, request, number, id) {
871
- return (record) => {
872
- record.journal.push(create(JournalEntrySchema, {
873
- ordinal: BigInt(record.journal.length),
874
- evidence: {
875
- case: "attempt",
876
- value: create(AgentAttemptEvidenceSchema, {
877
- operation: operation.operation,
878
- attempt: create(AiAttemptIdSchema, { value: id }),
879
- physicalAttempt: BigInt(number),
880
- preparedRequest: request.kind === "generation"
881
- ? { case: "generationRequest", value: request.content }
882
- : { case: "decisionRequest", value: request.content },
883
- }),
884
- },
885
- }));
886
- return record;
887
- };
888
- }
889
- /**
890
- * Describes the prepared physical request using its saved digest.
891
- */
892
- #attemptStarted(operation, request, id) {
893
- return create(AttemptStartedSchema, {
894
- operation: this.audit?.reference(operation, request.kind === "generation" ? AiModelKind.GENERATION : AiModelKind.DECISION),
895
- attempt: create(AiAttemptIdSchema, { value: id }),
896
- startedAt: Time.currentTime(),
897
- request: request.content.digest,
898
- ...(request.kind === "generation" && request.content.corrects !== undefined
899
- ? { previousAttempt: request.content.corrects }
900
- : {}),
901
- });
902
- }
903
- /**
904
- * Reserves transport bytes and provider persistence capacity before dispatch.
905
- */
906
- async #reserve(id, bytes, credit, model) {
907
- const inputLimit = model.definition.limits.maxInputBytes;
908
- const outputLimit = model.definition.limits.maxOutputBytes;
909
- const configuredCredit = credit ?? outputLimit;
910
- if (!Number.isSafeInteger(bytes) ||
911
- bytes < 0 ||
912
- (inputLimit !== undefined && bytes > inputLimit) ||
913
- (credit !== undefined && (!Number.isSafeInteger(credit) || credit < 1)) ||
914
- (outputLimit !== undefined && credit !== undefined && credit > outputLimit))
915
- throw new Error("Agent provider request exceeds its operation byte bounds.");
916
- const record = this.session.record();
917
- const previous = this.#findAttempt(record, id);
918
- if (previous.transportReserved)
919
- throw new Error("Agent transport ticket was already reserved.");
920
- const proposedCredit = this.#outputCredit(record, configuredCredit, bytes);
921
- AgentMcpBudget.checkSharedBytes(record, bytes, proposedCredit ?? 0);
922
- if (proposedCredit !== undefined)
923
- this.#checkCapacity(record, proposedCredit, model);
924
- let effectiveCredit;
925
- await this.session.update((current) => {
926
- effectiveCredit = this.#applyReservation(current, id, bytes, configuredCredit, model);
927
- return current;
928
- });
929
- return effectiveCredit;
930
- }
931
- /**
932
- * Narrows explicitly configured provider credit by remaining invocation credit.
933
- */
934
- #outputCredit(record, configured, bytes) {
935
- const remaining = AgentMcpBudget.remainingOutputCredit(record);
936
- if (remaining !== undefined && remaining < 1n)
937
- AgentMcpBudget.checkSharedBytes(record, bytes, 1);
938
- const available = remaining === undefined ? undefined : Number(remaining);
939
- if (available !== undefined && !Number.isSafeInteger(available))
940
- throw new Error("Agent invocation output credit is not a safe byte count.");
941
- return configured === undefined
942
- ? available
943
- : available === undefined
944
- ? configured
945
- : Math.min(configured, available);
946
- }
947
- /**
948
- * Applies one atomic transport reservation to the fenced execution record.
949
- */
950
- #applyReservation(record, id, bytes, configured, model) {
951
- const evidence = this.#findAttempt(record, id);
952
- if (evidence.transportReserved)
953
- throw new Error("Agent transport ticket was already reserved.");
954
- const credit = this.#outputCredit(record, configured, bytes);
955
- AgentMcpBudget.checkSharedBytes(record, bytes, credit ?? 0);
956
- evidence.inputBytes = BigInt(bytes);
957
- if (credit !== undefined)
958
- this.#checkCapacity(record, credit, model);
959
- evidence.reservedResponseBytes = BigInt(credit ?? 0);
960
- evidence.transportReserved = true;
961
- return credit;
962
- }
963
- /**
964
- * Persists a complete response before an adapter can return it to the handler.
965
- */
966
- async #finishAttempt(operation, completion, received) {
967
- const response = completion.response;
968
- const content = response.$typeName === GenerationResponseSchema.typeName
969
- ? AnyMessages.pack(GenerationResponseSchema, response)
970
- : AnyMessages.pack(DecisionResponseSchema, response);
971
- const responseDigest = response.$typeName === GenerationResponseSchema.typeName ? response.digest : undefined;
972
- const history = this.#conversationHistory(operation, completion.ticketId, content);
973
- const change = (record) => {
974
- this.#storeCompletion(this.#findAttempt(record, completion.ticketId), completion, received.get(completion.ticketId));
975
- return record;
976
- };
977
- if (this.audit === undefined)
978
- await this.session.update(change, [history]);
979
- else
980
- await this.audit.save(AttemptFinishedSchema, this.#attemptFinished(operation, completion, responseDigest), change, [history]);
981
- }
982
- /**
983
- * Describes the persisted response and its original physical ticket.
984
- */
985
- #attemptFinished(operation, completion, responseDigest) {
986
- const response = completion.response;
987
- return create(AttemptFinishedSchema, {
988
- operation: this.audit?.reference(operation, response.$typeName === GenerationResponseSchema.typeName
989
- ? AiModelKind.GENERATION
990
- : AiModelKind.DECISION),
991
- attempt: create(AiAttemptIdSchema, { value: completion.ticketId }),
992
- outcome: response.outcome,
993
- ...(responseDigest === undefined ? {} : { response: responseDigest }),
994
- ...(response.usage === undefined ? {} : { usage: response.usage }),
995
- ...(response.diagnosticId === undefined ? {} : { diagnosticId: response.diagnosticId }),
996
- finishedAt: Time.currentTime(),
997
- });
998
- }
999
- /**
1000
- * Applies one bounded observed completion to its reserved attempt.
1001
- */
1002
- #storeCompletion(evidence, completion, observedBytes) {
1003
- if (!evidence.transportReserved || evidence.response.case !== undefined)
1004
- throw new Error("Agent model attempt has no live reservation.");
1005
- if (observedBytes !== undefined &&
1006
- completion.receivedBytes !== undefined &&
1007
- observedBytes !== completion.receivedBytes)
1008
- throw new Error("Agent model receipt byte counts disagree.");
1009
- const bytes = completion.receivedBytes;
1010
- if (bytes !== undefined) {
1011
- if (evidence.reservedResponseBytes !== 0n && bytes > Number(evidence.reservedResponseBytes))
1012
- throw new Error("Agent model response exceeded reserved bytes.");
1013
- evidence.receivedBytes = BigInt(bytes);
1014
- }
1015
- const response = completion.response;
1016
- evidence.response =
1017
- response.$typeName === GenerationResponseSchema.typeName
1018
- ? { case: "generationResponse", value: response }
1019
- : { case: "decisionResponse", value: response };
1020
- evidence.outcome = response.outcome;
1021
- evidence.validationIssues = (completion.issues ?? []).map((issue) => create(AgentValidationIssueSchema, {
1022
- code: issue.code,
1023
- path: issue.path,
1024
- message: issue.message,
1025
- }));
1026
- }
1027
- /**
1028
- * Links one exact typed exchange to the named operation and physical attempt.
1029
- */
1030
- #conversationHistory(operation, attemptId, content) {
1031
- const occurredAt = Time.currentTime();
1032
- return create(AgentHistoryEntrySchema, {
1033
- occurredAt,
1034
- item: {
1035
- case: "conversationRecord",
1036
- value: create(ConversationRecordSchema, {
1037
- id: create(ConversationRecordIdSchema, { value: randomUUID() }),
1038
- conversation: operation.conversation,
1039
- operation: operation.operation,
1040
- attempt: create(AiAttemptIdSchema, { value: attemptId }),
1041
- occurredAt,
1042
- content,
1043
- }),
1044
- },
1045
- });
1046
- }
1047
- /**
1048
- * Finds one journaled attempt under its original ticket.
1049
- */
1050
- #findAttempt(record, id) {
1051
- const entry = record.journal.find((item) => item.evidence.case === "attempt" && item.evidence.value.attempt?.value === id);
1052
- if (entry?.evidence.case !== "attempt")
1053
- throw new Error("Agent model ticket is unknown.");
1054
- return entry.evidence.value;
1055
- }
1056
- /**
1057
- * Counts physical attempts across all handlers in this invocation.
1058
- */
1059
- #attemptCount() {
1060
- return this.session.record().journal.filter((entry) => entry.evidence.case === "attempt")
1061
- .length;
1062
- }
1063
- /**
1064
- * Checks complete provider wrappers with a maximally credited response.
1065
- */
1066
- #checkCapacity(record, credit, model) {
1067
- const recoveryLimit = record.started?.bounds?.maxRecoveryBytes;
1068
- if (recoveryLimit !== undefined && BigInt(credit) > recoveryLimit)
1069
- throw new Error("Agent model credit exceeds invocation recovery bytes.");
1070
- const projected = this.#projectedRecord(record, 1, model);
1071
- const creditBytes = BigInt(credit);
1072
- // The generation envelope can add one ordered Anthropic content copy.
1073
- const orderedContent = model.definition.kind === "generation" ? creditBytes + 64n : 0n;
1074
- // Three response copies: raw/decoded content, typed attempt output, named result.
1075
- // One more credit covers bounded usage, issues, model identity, and proposal metadata.
1076
- const recordBytes = BigInt(AgentExecutionSizes.record(projected)) +
1077
- 3n * (creditBytes - 1n) +
1078
- creditBytes +
1079
- orderedContent +
1080
- 240n;
1081
- const headBytes = this.#projectedHead(record);
1082
- const history = this.#historyBytes(record, 1, model);
1083
- // The response row retains raw/decoded content and typed output, plus metadata credit.
1084
- const responseBytes = BigInt(history.response) + 2n * (creditBytes - 1n) + creditBytes + orderedContent + 120n;
1085
- const auditBytes = this.#capacityAuditBytes(record, model);
1086
- this.#checkProjectedBounds(recoveryLimit, recordBytes, headBytes, [
1087
- BigInt(history.request),
1088
- responseBytes,
1089
- ...auditBytes,
1090
- ]);
1091
- }
1092
- /**
1093
- * Applies invocation and provider byte limits to projected persistent rows.
1094
- */
1095
- #checkProjectedBounds(recoveryLimit, recordBytes, headBytes, historyBytes) {
1096
- const capacity = this.session.capacity();
1097
- if (recoveryLimit !== undefined && recordBytes > recoveryLimit)
1098
- throw new Error("Agent model evidence exceeds invocation recovery bytes.");
1099
- if (capacity.executionRecordBytes !== undefined &&
1100
- recordBytes > BigInt(capacity.executionRecordBytes))
1101
- throw new Error("Agent execution record cannot retain the bounded model response.");
1102
- if (capacity.executionHeadBytes !== undefined && headBytes > capacity.executionHeadBytes)
1103
- throw new Error("Agent execution head exceeds its provider payload bound.");
1104
- if (capacity.historyRecordBytes !== undefined &&
1105
- historyBytes.some((bytes) => bytes > BigInt(capacity.historyRecordBytes ?? 0)))
1106
- throw new Error("Agent conversation history cannot retain the bounded model response.");
1107
- if (capacity.transactionPayloadBytes !== undefined &&
1108
- recordBytes + BigInt(headBytes) + historyBytes.reduce((sum, bytes) => sum + bytes, 0n) >
1109
- BigInt(capacity.transactionPayloadBytes))
1110
- throw new Error("Agent model evidence exceeds provider transaction payload capacity.");
1111
- }
1112
- /**
1113
- * Measures both original outcome audit rows with the accepted scope and actor.
1114
- */
1115
- #capacityAuditBytes(record, model) {
1116
- if (this.audit === undefined)
1117
- return [];
1118
- const operation = record.journal.findLast((entry) => entry.evidence.case === "operation");
1119
- const attempt = record.journal.findLast((entry) => entry.evidence.case === "attempt");
1120
- if (operation?.evidence.case !== "operation" || attempt?.evidence.case !== "attempt")
1121
- throw new Error("Agent audit capacity requires saved operation and attempt.");
1122
- const ref = this.audit.reference(operation.evidence.value, this.#modelKind(model));
1123
- const digest = create(AiContentDigestSchema, { value: "a".repeat(64) });
1124
- const finish = create(AttemptFinishedSchema, {
1125
- operation: ref,
1126
- attempt: attempt.evidence.value.attempt,
1127
- outcome: AiOutcome.ADMITTED,
1128
- response: digest,
1129
- finishedAt: Time.currentTime(),
1130
- });
1131
- const admitted = create(ResultAdmittedSchema, {
1132
- operation: ref,
1133
- result: digest,
1134
- validationRevision: create(AiValidationRevisionSchema, {
1135
- value: model.definition.validation?.version ?? model.definition.version,
1136
- }),
1137
- admittedAt: Time.currentTime(),
1138
- });
1139
- return [
1140
- BigInt(this.audit.historyBytes(AttemptFinishedSchema, finish)),
1141
- BigInt(this.audit.historyBytes(ResultAdmittedSchema, admitted)),
1142
- ];
1143
- }
1144
- /**
1145
- * Measures the full record with raw, response-Any and admitted-output copies.
1146
- */
1147
- #projectedRecord(record, credit, model) {
1148
- const projected = clone(AgentExecutionRecordSchema, record);
1149
- const attempt = projected.journal.findLast((entry) => entry.evidence.case === "attempt");
1150
- const operation = projected.journal.findLast((entry) => entry.evidence.case === "operation");
1151
- if (attempt?.evidence.case !== "attempt" || operation?.evidence.case !== "operation")
1152
- throw new Error("Agent capacity check requires a saved attempt and operation.");
1153
- const admitted = create(AnySchema, {
1154
- typeUrl: TypeUrls.derive(model.definition.output),
1155
- value: new Uint8Array(credit),
1156
- });
1157
- attempt.evidence.value.response =
1158
- model.definition.kind === "generation"
1159
- ? { case: "generationResponse", value: this.#creditedGeneration(credit, admitted) }
1160
- : { case: "decisionResponse", value: this.#creditedDecision(credit, admitted) };
1161
- operation.evidence.value.result = { case: "admittedOutput", value: admitted };
1162
- return projected;
1163
- }
1164
- /**
1165
- * Sizes assistant text and typed output as separate credited copies.
1166
- */
1167
- #creditedGeneration(credit, admitted) {
1168
- return create(GenerationResponseSchema, {
1169
- rawOutput: "x".repeat(credit),
1170
- outcome: AiOutcome.ADMITTED,
1171
- admittedOutput: admitted,
1172
- digest: create(AiContentDigestSchema, { value: "a".repeat(64) }),
1173
- });
1174
- }
1175
- /**
1176
- * Sizes decoded decision answers and typed output as distinct copies.
1177
- */
1178
- #creditedDecision(credit, admitted) {
1179
- return create(DecisionResponseSchema, {
1180
- outcome: AiOutcome.ADMITTED,
1181
- admittedOutput: admitted,
1182
- answers: [
1183
- create(DecisionAnswerSchema, {
1184
- id: create(DecisionQuestionIdSchema, { value: "x".repeat(credit) }),
1185
- kind: DecisionQuestionKind.BOOLEAN,
1186
- value: { case: "booleanProbability", value: 0.5 },
1187
- }),
1188
- ],
1189
- });
1190
- }
1191
- /**
1192
- * Measures a conservative complete claim head including pending Inbox order.
1193
- */
1194
- #projectedHead(record) {
1195
- const accepted = record.accepted;
1196
- if (accepted?.key?.scope === undefined)
1197
- throw new Error("Agent capacity check requires the accepted instance scope.");
1198
- return AgentExecutionSizes.head(create(AgentExecutionHeadSchema, {
1199
- scope: accepted.key.scope,
1200
- active: accepted.key,
1201
- pending: accepted.key,
1202
- pendingOrder: accepted.order,
1203
- lastResolved: accepted.order,
1204
- claimToken: record.claimToken,
1205
- claimExpiresAt: record.claimExpiresAt,
1206
- preferences: [...this.session.preferences()],
1207
- eligibleAt: Time.currentTime(),
1208
- }));
1209
- }
1210
- /**
1211
- * Measures both complete typed conversation rows staged around transport.
1212
- */
1213
- #historyBytes(record, credit, model) {
1214
- const scope = record.accepted?.key?.scope;
1215
- const operation = record.journal.findLast((entry) => entry.evidence.case === "operation");
1216
- const attempt = record.journal.findLast((entry) => entry.evidence.case === "attempt");
1217
- if (scope === undefined ||
1218
- operation?.evidence.case !== "operation" ||
1219
- attempt?.evidence.case !== "attempt")
1220
- throw new Error("Agent conversation capacity requires saved operation and attempt.");
1221
- const named = operation.evidence.value;
1222
- const physical = attempt.evidence.value;
1223
- const id = physical.attempt?.value;
1224
- if (id === undefined)
1225
- throw new Error("Agent capacity check requires an attempt ID.");
1226
- return {
1227
- request: AgentExecutionSizes.history(scope, this.#conversationHistory(named, id, this.#preparedContent(physical))),
1228
- response: AgentExecutionSizes.history(scope, this.#conversationHistory(named, id, this.#creditedContent(model, credit))),
1229
- };
1230
- }
1231
- /**
1232
- * Restores the exact packed prepared request for history sizing.
1233
- */
1234
- #preparedContent(attempt) {
1235
- const prepared = attempt.preparedRequest;
1236
- if (prepared.case !== "generationRequest" && prepared.case !== "decisionRequest")
1237
- throw new Error("Agent prepared request is absent from the attempt journal.");
1238
- const schema = prepared.case === "generationRequest" ? GenerationRequestSchema : DecisionRequestSchema;
1239
- return create(AnySchema, {
1240
- typeUrl: TypeUrls.derive(schema),
1241
- value: prepared.case === "generationRequest"
1242
- ? toBinary(GenerationRequestSchema, prepared.value)
1243
- : toBinary(DecisionRequestSchema, prepared.value),
1244
- });
1245
- }
1246
- /**
1247
- * Models the full credited response Any without dispatching externally.
1248
- */
1249
- #creditedContent(model, credit) {
1250
- const admitted = create(AnySchema, {
1251
- typeUrl: TypeUrls.derive(model.definition.output),
1252
- value: new Uint8Array(credit),
1253
- });
1254
- return model.definition.kind === "generation"
1255
- ? AnyMessages.pack(GenerationResponseSchema, this.#creditedGeneration(credit, admitted))
1256
- : AnyMessages.pack(DecisionResponseSchema, this.#creditedDecision(credit, admitted));
1257
- }
1258
- /**
1259
- * Compares exact prepared request content before a saved response is reused.
1260
- */
1261
- #sameRequest(saved, request) {
1262
- if (request.kind === "generation" && saved.preparedRequest.case === "generationRequest")
1263
- return (Buffer.compare(Buffer.from(toBinary(GenerationRequestSchema, request.content)), Buffer.from(toBinary(GenerationRequestSchema, saved.preparedRequest.value))) === 0);
1264
- if (request.kind === "decision" && saved.preparedRequest.case === "decisionRequest")
1265
- return (Buffer.compare(Buffer.from(toBinary(DecisionRequestSchema, request.content)), Buffer.from(toBinary(DecisionRequestSchema, saved.preparedRequest.value))) === 0);
1266
- return false;
1267
- }
1268
- }
1269
- //# sourceMappingURL=agent-ai-runtime.js.map