@yielded/agent 0.1.0-beta.172 → 0.1.0-beta.174

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 (226) hide show
  1. package/dist/{Admin-BX9ns28E.d.mts → Admin-BHmp2V9p.d.mts} +25 -16
  2. package/dist/{Agent-9aBoIi74.d.mts → Agent-B39jRnFv.d.mts} +2 -2
  3. package/dist/{Agent-0WvBWWbM.mjs → Agent-BiRbr73L.mjs} +7 -6
  4. package/dist/Agent-BiRbr73L.mjs.map +1 -0
  5. package/dist/{AgentRuntime-CQ-qcETl.mjs → AgentRuntime-B6qZlD3f.mjs} +199 -191
  6. package/dist/AgentRuntime-B6qZlD3f.mjs.map +1 -0
  7. package/dist/{AgentRuntime-BfP14534.d.mts → AgentRuntime-BD3ZHAMq.d.mts} +10 -10
  8. package/dist/{Digest-DCuPlhNk.mjs → Digest-EpeqWEdv.mjs} +41 -14
  9. package/dist/Digest-EpeqWEdv.mjs.map +1 -0
  10. package/dist/{DurableAgentRuntime-BAmSkWYr.mjs → DurableAgentRuntime-CBBjRNJN.mjs} +1447 -1424
  11. package/dist/DurableAgentRuntime-CBBjRNJN.mjs.map +1 -0
  12. package/dist/{EventSource-BwliwQz9.d.mts → EventSource-C9aaJaXT.d.mts} +2 -2
  13. package/dist/{MessageDelivery-CeSDfHZa.d.mts → MessageDelivery-BGDm-c46.d.mts} +4 -4
  14. package/dist/{Messaging-C_6OOg_s.d.mts → Messaging-SVu6rWV8.d.mts} +12 -6
  15. package/dist/{MessagingHost-B8oKM7AC.d.mts → MessagingHost-C6SOAcoG.d.mts} +2 -2
  16. package/dist/{Output-Dsx6k52t.d.mts → Output-CRamN1Fy.d.mts} +2 -2
  17. package/dist/{PreparedInputAdmission-CxSJSiTl.d.mts → PreparedInputAdmission-BvDqlgiP.d.mts} +3 -3
  18. package/dist/{RunContinuation-DHYNAQFi.mjs → RunContinuation-4ZATcVLB.mjs} +113 -56
  19. package/dist/RunContinuation-4ZATcVLB.mjs.map +1 -0
  20. package/dist/{RunContinuation-FHM7XPjq.d.mts → RunContinuation-CTJ1jGrO.d.mts} +6 -6
  21. package/dist/{RunJournal-kfKVxJj7.mjs → RunJournal-CNZqA3Ge.mjs} +33 -5
  22. package/dist/RunJournal-CNZqA3Ge.mjs.map +1 -0
  23. package/dist/{RunOptions-D8zxFIrZ.d.mts → RunOptions-Be77lKVZ.d.mts} +2 -2
  24. package/dist/{RunStorage-uqPxps09.mjs → RunStorage-BHjuuERI.mjs} +9 -6
  25. package/dist/RunStorage-BHjuuERI.mjs.map +1 -0
  26. package/dist/{Scheduling-CVyfXlBR.mjs → Scheduling-NG8slKdI.mjs} +11 -11
  27. package/dist/Scheduling-NG8slKdI.mjs.map +1 -0
  28. package/dist/{Subagent-vpffemql.mjs → Subagent-CTIpnzlB.mjs} +53 -40
  29. package/dist/Subagent-CTIpnzlB.mjs.map +1 -0
  30. package/dist/{Subagent-E6tvd7-k.d.mts → Subagent-DKhZA72u.d.mts} +19 -8
  31. package/dist/{SubagentHost-B6w2m-SI.d.mts → SubagentHost-D1xBgn9g.d.mts} +2 -2
  32. package/dist/{Subscription-DONig54Q.d.mts → Subscription-BNg9VCRl.d.mts} +2 -2
  33. package/dist/{SubscriptionInput-mJIRxWJM.d.mts → SubscriptionInput-BUoXv-_K.d.mts} +2 -2
  34. package/dist/{ThreadImport-CoQTZywm.d.mts → ThreadImport-CMgzttvr.d.mts} +43 -43
  35. package/dist/{ThreadImport-DckUMEqJ.mjs → ThreadImport-CodYoJoa.mjs} +7 -7
  36. package/dist/ThreadImport-CodYoJoa.mjs.map +1 -0
  37. package/dist/{ThreadStore-CEekRa80.mjs → ThreadStore-59uDGXul.mjs} +163 -84
  38. package/dist/ThreadStore-59uDGXul.mjs.map +1 -0
  39. package/dist/{ThreadTransfer-B4gTQLIl.mjs → ThreadTransfer-3jigUl3g.mjs} +3 -3
  40. package/dist/{ThreadTransfer-B4gTQLIl.mjs.map → ThreadTransfer-3jigUl3g.mjs.map} +1 -1
  41. package/dist/{WorkerAdmission-DFVbbVh2.mjs → WorkerAdmission-DDYJdOsU.mjs} +4 -4
  42. package/dist/{WorkerAdmission-DFVbbVh2.mjs.map → WorkerAdmission-DDYJdOsU.mjs.map} +1 -1
  43. package/dist/{agent-registration-ByMZ_cK5.mjs → agent-registration-DRbyhAu-.mjs} +69 -56
  44. package/dist/agent-registration-DRbyhAu-.mjs.map +1 -0
  45. package/dist/capabilities/Approval.mjs +2 -2
  46. package/dist/capabilities/Approval.mjs.map +1 -1
  47. package/dist/capabilities/BrowserUse.d.mts +102 -1867
  48. package/dist/capabilities/BrowserUse.mjs +74 -798
  49. package/dist/capabilities/BrowserUse.mjs.map +1 -1
  50. package/dist/capabilities/Budget.mjs +3 -1
  51. package/dist/capabilities/Budget.mjs.map +1 -1
  52. package/dist/capabilities/CodeMode.d.mts +1 -1
  53. package/dist/capabilities/CodeMode.mjs +16 -9
  54. package/dist/capabilities/CodeMode.mjs.map +1 -1
  55. package/dist/capabilities/Commands.d.mts +1 -1
  56. package/dist/capabilities/McpClient.mjs +1 -1
  57. package/dist/capabilities/McpClient.mjs.map +1 -1
  58. package/dist/capabilities/Messaging.d.mts +1 -1
  59. package/dist/capabilities/Messaging.mjs +4 -4
  60. package/dist/capabilities/Messaging.mjs.map +1 -1
  61. package/dist/capabilities/ModelContext.mjs +7 -5
  62. package/dist/capabilities/ModelContext.mjs.map +1 -1
  63. package/dist/capabilities/Redaction.mjs +49 -19
  64. package/dist/capabilities/Redaction.mjs.map +1 -1
  65. package/dist/capabilities/RunHooks.d.mts +1 -1
  66. package/dist/capabilities/RunHooks.mjs +1 -1
  67. package/dist/capabilities/RunHooks.mjs.map +1 -1
  68. package/dist/capabilities/Subagent.d.mts +1 -1
  69. package/dist/capabilities/Subagent.mjs +1 -1
  70. package/dist/capabilities/SubagentReservations.mjs +3 -1
  71. package/dist/capabilities/SubagentReservations.mjs.map +1 -1
  72. package/dist/capabilities/WebCapture.mjs.map +1 -1
  73. package/dist/capabilities/WebSearch.mjs +7 -7
  74. package/dist/capabilities/WebSearch.mjs.map +1 -1
  75. package/dist/core/Agent.d.mts +1 -1
  76. package/dist/core/Agent.mjs +1 -1
  77. package/dist/core/AgentUpdates.mjs +8 -8
  78. package/dist/core/AgentUpdates.mjs.map +1 -1
  79. package/dist/core/Thread.mjs +1 -1
  80. package/dist/core/Thread.mjs.map +1 -1
  81. package/dist/core/Usage.mjs +2 -2
  82. package/dist/core/Usage.mjs.map +1 -1
  83. package/dist/durable/Admin.d.mts +1 -1
  84. package/dist/durable/AgentRegistration.d.mts +1 -1
  85. package/dist/durable/AgentRegistration.mjs +1 -1
  86. package/dist/durable/Certification.d.mts +1 -1
  87. package/dist/durable/CommittedActivity.d.mts +1 -1
  88. package/dist/durable/CommittedActivity.mjs +2 -2
  89. package/dist/durable/Digest.mjs +1 -1
  90. package/dist/durable/DurableAgentRuntime.d.mts +1 -1
  91. package/dist/durable/DurableAgentRuntime.mjs +2 -2
  92. package/dist/durable/EventSource.d.mts +1 -1
  93. package/dist/durable/EventSource.mjs +6 -6
  94. package/dist/durable/EventSource.mjs.map +1 -1
  95. package/dist/durable/GitHubWorkflowSource.d.mts +3 -3
  96. package/dist/durable/LifecyclePublication.d.mts +1 -1
  97. package/dist/durable/LifecyclePublication.mjs +1 -1
  98. package/dist/durable/MessageDelivery.d.mts +1 -1
  99. package/dist/durable/MessageDelivery.mjs +1 -1
  100. package/dist/durable/MessageDeliveryStoreConformance.d.mts +2 -2
  101. package/dist/durable/MessageDeliveryStoreConformance.mjs +1 -1
  102. package/dist/durable/PersistentHistory.d.mts +1 -1
  103. package/dist/durable/PersistentHistory.mjs +3 -3
  104. package/dist/durable/PreparedInputAdmission.d.mts +1 -1
  105. package/dist/durable/RecordFormat.mjs +2 -2
  106. package/dist/durable/RecordFormat.mjs.map +1 -1
  107. package/dist/durable/Recovery.d.mts +1 -1
  108. package/dist/durable/RunContinuation.d.mts +2 -2
  109. package/dist/durable/RunContinuation.mjs +2 -2
  110. package/dist/durable/RunJournal.d.mts +1 -1
  111. package/dist/durable/RunJournal.mjs +1 -1
  112. package/dist/durable/RunStorage.d.mts +1 -1
  113. package/dist/durable/RunStorage.mjs +1 -1
  114. package/dist/durable/Scheduling.d.mts +1 -1
  115. package/dist/durable/Scheduling.mjs +1 -1
  116. package/dist/durable/SettlementPublisher.d.mts +1 -1
  117. package/dist/durable/SettlementPublisher.mjs +2 -2
  118. package/dist/durable/SubmissionLedger.d.mts +1 -1
  119. package/dist/durable/SubmissionLedger.mjs +5 -1
  120. package/dist/durable/SubmissionLedger.mjs.map +1 -1
  121. package/dist/durable/SubmissionLedgerConformance.d.mts +1 -1
  122. package/dist/durable/SubmissionLedgerConformance.mjs +4 -4
  123. package/dist/durable/SubmissionStatus.d.mts +1 -1
  124. package/dist/durable/Subscription.d.mts +1 -1
  125. package/dist/durable/SubscriptionInput.d.mts +1 -1
  126. package/dist/durable/SubscriptionInput.mjs +3 -3
  127. package/dist/durable/SubscriptionInput.mjs.map +1 -1
  128. package/dist/durable/SubscriptionStoreConformance.d.mts +1 -1
  129. package/dist/durable/SubscriptionStoreConformance.mjs +2 -2
  130. package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -1
  131. package/dist/durable/SubscriptionTools.d.mts +2 -2
  132. package/dist/durable/SubscriptionTransition.d.mts +1 -1
  133. package/dist/durable/Subscriptions.d.mts +5 -5
  134. package/dist/durable/Subscriptions.mjs +2 -2
  135. package/dist/durable/Subscriptions.mjs.map +1 -1
  136. package/dist/durable/ThreadArchiveRange.d.mts +1 -1
  137. package/dist/durable/ThreadContextHistory.d.mts +1 -1
  138. package/dist/durable/ThreadContextHistory.mjs +1 -1
  139. package/dist/durable/ThreadImport.d.mts +1 -1
  140. package/dist/durable/ThreadImport.mjs +1 -1
  141. package/dist/durable/ThreadInvariants.d.mts +3 -3
  142. package/dist/durable/ThreadInvariants.mjs +4 -4
  143. package/dist/durable/ThreadInvariants.mjs.map +1 -1
  144. package/dist/durable/ThreadProjectionMaintenance.d.mts +1 -1
  145. package/dist/durable/ThreadReader.d.mts +1 -1
  146. package/dist/durable/ThreadReader.mjs +1 -1
  147. package/dist/durable/ThreadStore.d.mts +1 -1
  148. package/dist/durable/ThreadStore.mjs +1 -1
  149. package/dist/durable/ThreadStoreConformance.d.mts +1 -1
  150. package/dist/durable/ThreadStoreConformance.mjs +3 -3
  151. package/dist/durable/ThreadTransfer.d.mts +1 -1
  152. package/dist/durable/ThreadTransfer.mjs +1 -1
  153. package/dist/durable/ThreadWork.d.mts +1 -1
  154. package/dist/durable/ThreadWork.mjs +4 -4
  155. package/dist/durable/ThreadWork.mjs.map +1 -1
  156. package/dist/durable/WorkerAdmission.d.mts +1 -1
  157. package/dist/durable/WorkerAdmission.mjs +1 -1
  158. package/dist/durable/WorkerHost.d.mts +2 -2
  159. package/dist/engine/AgentRuntime.d.mts +1 -1
  160. package/dist/engine/AgentRuntime.mjs +1 -1
  161. package/dist/engine/MessagingHost.d.mts +1 -1
  162. package/dist/engine/Output.d.mts +1 -1
  163. package/dist/engine/RunOptions.d.mts +1 -1
  164. package/dist/engine/SubagentHost.d.mts +1 -1
  165. package/dist/index.d.mts +19 -19
  166. package/dist/index.mjs +14 -14
  167. package/dist/{run-context-reader-OcsZr4bk.d.mts → run-context-reader-CC7ZD95F.d.mts} +2 -2
  168. package/package.json +1 -1
  169. package/src/capabilities/Approval.ts +58 -60
  170. package/src/capabilities/BrowserUse.ts +89 -944
  171. package/src/capabilities/Budget.ts +8 -1
  172. package/src/capabilities/CodeMode.ts +57 -33
  173. package/src/capabilities/McpClient.ts +2 -2
  174. package/src/capabilities/Messaging.ts +51 -55
  175. package/src/capabilities/ModelContext.ts +5 -2
  176. package/src/capabilities/Redaction.ts +64 -34
  177. package/src/capabilities/RunHooks.ts +52 -55
  178. package/src/capabilities/Subagent.ts +33 -33
  179. package/src/capabilities/SubagentReservations.ts +9 -1
  180. package/src/capabilities/WebCapture.ts +6 -0
  181. package/src/capabilities/WebSearch.ts +10 -7
  182. package/src/capabilities/internal/subagent-background.ts +202 -158
  183. package/src/core/Agent.ts +11 -6
  184. package/src/core/AgentUpdates.ts +8 -8
  185. package/src/core/Thread.ts +9 -10
  186. package/src/core/Usage.ts +7 -8
  187. package/src/core/internal/agent-updates.ts +1 -0
  188. package/src/durable/DurableAgentRuntime.ts +645 -625
  189. package/src/durable/EventSource.ts +15 -9
  190. package/src/durable/RecordFormat.ts +5 -3
  191. package/src/durable/RunContinuation.ts +233 -81
  192. package/src/durable/RunJournal.ts +10 -9
  193. package/src/durable/RunStorage.ts +122 -124
  194. package/src/durable/Scheduling.ts +639 -651
  195. package/src/durable/SubmissionLedger.ts +4 -0
  196. package/src/durable/SubscriptionInput.ts +5 -3
  197. package/src/durable/SubscriptionStoreConformance.ts +23 -23
  198. package/src/durable/Subscriptions.ts +18 -19
  199. package/src/durable/ThreadImport.ts +18 -19
  200. package/src/durable/ThreadInvariants.ts +2 -1
  201. package/src/durable/ThreadStore.ts +215 -111
  202. package/src/durable/ThreadWork.ts +1 -2
  203. package/src/durable/internal/StorageOwner.ts +10 -4
  204. package/src/durable/internal/agent-registration.ts +96 -89
  205. package/src/durable/internal/canonical-json.ts +61 -20
  206. package/src/durable/internal/prompt-history-cache.ts +13 -4
  207. package/src/durable/internal/record-encoding.ts +120 -64
  208. package/src/durable/internal/schedule-time.ts +6 -6
  209. package/src/durable/internal/usage-totals.ts +38 -0
  210. package/src/durable/internal/worker-host.ts +69 -74
  211. package/src/engine/internal/agent-runtime.ts +1067 -1018
  212. package/src/engine/internal/provisional-text.ts +12 -10
  213. package/src/engine/internal/tool-exposure.ts +22 -18
  214. package/src/engine/internal/tool-telemetry.ts +12 -7
  215. package/dist/Agent-0WvBWWbM.mjs.map +0 -1
  216. package/dist/AgentRuntime-CQ-qcETl.mjs.map +0 -1
  217. package/dist/Digest-DCuPlhNk.mjs.map +0 -1
  218. package/dist/DurableAgentRuntime-BAmSkWYr.mjs.map +0 -1
  219. package/dist/RunContinuation-DHYNAQFi.mjs.map +0 -1
  220. package/dist/RunJournal-kfKVxJj7.mjs.map +0 -1
  221. package/dist/RunStorage-uqPxps09.mjs.map +0 -1
  222. package/dist/Scheduling-CVyfXlBR.mjs.map +0 -1
  223. package/dist/Subagent-vpffemql.mjs.map +0 -1
  224. package/dist/ThreadImport-DckUMEqJ.mjs.map +0 -1
  225. package/dist/ThreadStore-CEekRa80.mjs.map +0 -1
  226. package/dist/agent-registration-ByMZ_cK5.mjs.map +0 -1
@@ -16,33 +16,33 @@ import { a as PeerMessageCapacity, d as MessageAdmission, f as MessagingError, i
16
16
  import { SubagentHost } from "./engine/SubagentHost.mjs";
17
17
  import { ThreadHistory } from "./engine/ThreadHistory.mjs";
18
18
  import { n as RunToolVisibility } from "./ToolExposure-DBATXxmL.mjs";
19
- import { C as boundedValueFootprint, n as AgentChildPending, p as renderInputPrompt, u as executeWithUsageAccountingUnknown } from "./AgentRuntime-CQ-qcETl.mjs";
19
+ import { C as boundedValueFootprint, n as AgentChildPending, p as renderInputPrompt, u as executeWithUsageAccountingUnknown } from "./AgentRuntime-B6qZlD3f.mjs";
20
20
  import { ContextRolloverTool } from "./engine/ContextWindow.mjs";
21
21
  import { getToolExecutionClass } from "./engine/DurableStep.mjs";
22
22
  import { CompactionError, ContextCompactor } from "./engine/ContextCompactor.mjs";
23
23
  import { AgentUpdateAcceptance, CurrentToolFailureObserver, ModelUsageAccounting, RunContextPreparation, RunContextPreparationPassthrough, RunToolAuthorization, RunToolScheduling } from "./engine/RunOptions.mjs";
24
24
  import { A as MAX_RUN_EVIDENCE_RECORDS, At as WorkHandoffCompleted, Bt as WorkerReportingIntent, Ct as ToolCallResolved, Dt as ToolStepSettled, Et as ToolOperation, Ft as WorkerInputRequested, G as PromptRecord, H as PeerMessagePrepared, I as ModelCallAborted, It as WorkerOrigin, Mt as WorkerContinuation, Nt as WorkerInputCompleted, O as MAX_RUN_CONTINUATION_BYTES, Ot as ToolUnavailable, P as MAX_RUN_TOOL_CALL_IDENTITIES, Pt as WorkerInputRefused, R as ModelResponseInterrupted, Rt as WorkerReportPrepared, Tt as ToolCallUnknown, U as PersistedJson, V as PROMPT_EVIDENCE_TAGS, Vt as WorkerStopRequested, X as RecordEnvelope, Z as RecordId, _t as SubmissionSettledRecord, at as RunDurationExhausted, bt as ToolApprovalDecided, c as CanonicalBatch, et as RepairAnnotated, f as CanonicalSequence, ft as SubagentJoined, g as DeclaredToolCall, gt as SubmissionSettled, ht as SubagentStarted, i as BatchId, jt as WorkerAdmission, kt as UserInputRecorded, lt as RunStartedRecord, mt as SubagentRequested, n as AgentUpdateEmitted, o as CURRENT_RECORD_FORMAT, p as CompactionCreated, pt as SubagentLineageRecorded, rt as RunContextRecorded, st as RunPolicyUsageReserved, t as AbortRequested, ut as SettlementFailureDiagnostic, v as DefinitionDigests, vt as SubtreeBudgetReserved, w as MAX_PERSISTED_JSON_BYTES, wt as ToolCallSettled, xt as ToolApprovalRequested, zt as WorkerReportRefused } from "./Records-BiuJDWNe.mjs";
25
- import { i as digestCanonicalJson, r as canonicalJson, s as digestJson } from "./Digest-DCuPlhNk.mjs";
25
+ import { i as digestCanonicalJson, r as canonicalJson, s as digestJson } from "./Digest-EpeqWEdv.mjs";
26
26
  import { AbortCommand, AbortIntentRequest, AdmissionPolicyError, AdmissionRequest, ApprovalDecisionCommand, ApprovalPendingSuspension, BeginChildBudgetReleaseRequest, ChildReservationId, ChildSettledNotification, ClaimHandoff, ClaimRequest, FundingOwnerRequest, LedgerError, MarkReadyRequest, MarkUnknownRequest, ParentLinkage, RecoverySnapshotRequest, ReleaseChildBudgetRequest, RevertJoiningRequest, Settlement, SettlementFinalization, SubmissionLedger, SubmissionLookupById, SubmissionLookupByKey, SubmissionScheduling, UnknownResolutionCommand, WaitingChild, WaitingForChildSuspension, WorkerLedgerState, submissionAbortBatchId, submissionAbortRecordId, submissionInputBatchId, submissionInputRecordId, submissionSettlementBatchId, submissionSettlementId, submissionSettlementRecordId, unknownResolutionKind } from "./durable/SubmissionLedger.mjs";
27
27
  import { DeclaredPendingBatchEvidence, OpenDelegationCallEvidence, OpenToolCallEvidence, PendingApprovalEvidence, RecoveryDecision, RecoveryEvidence, classifyRecovery, pendingApprovalForRecovery } from "./durable/Recovery.mjs";
28
28
  import { ExplainedEvidence, ExplainedSubmission, ExplainedUnknownCall, ObligationEntry, ObligationReport, RecoveryExplanation, RetryRefused, obligationSeverityOf, predictRecoveryDisposition, recoveryDecisionMeaning } from "./durable/Admin.mjs";
29
- import { a as compileRegistrations, c as resolveDefinitionBinding, l as resolveWorkerBinding, n as CurrentBindingSelection, o as definitionDigestsEqual, s as makeLegacyWorkerBinding, t as BindingUnavailable, u as toolReplayContracts } from "./agent-registration-ByMZ_cK5.mjs";
30
- import { A as subagentStartedBatchId, B as turnApprovalsBatchId, C as runStartedRecordId, D as subagentLineageRecordId, E as subagentLineageBatchId, F as toolCallResolvedRecordId, G as turnResponseBatchId, H as turnCanonicalBatch, I as toolCallResultBatchId, J as workerInputRecordId, K as turnResultsBatch, L as toolCallUnknownRecordId, M as toolApprovalDecisionRecordId, N as toolApprovalRequestRecordId, O as subagentRequestedBatchId, P as toolCallResolutionBatchId, Q as toolCallSettledRecordId, R as toolStepSettledBatchId, S as runStartedBatchId, T as subagentJoinedRecordId, U as turnIdForRun, W as turnResponseBatch, X as workerReportRecordId, Y as workerOriginRecordId, Z as makeJournalMetadata, a as childIdempotencyKeyFor, b as runDurationRecordId, c as compactionRecordId, d as modelResponseInterruptedBatchId, f as modelResponseInterruptedRecordId, g as projectRunJournalStream, i as approvalDecisionBatchId, j as subagentStartedRecordId, k as subagentRequestedRecordId, l as firstWorkerInputRecordId, m as peerMessageRecordId, o as childThreadIdFor, p as modelResponseRecordId, r as agentUpdateRecordId, s as compactionBatchId, t as RunJournalError, u as markUnknownBatchId, v as runCompletedRecordId, w as subagentJoinBatchId, x as runIdForSubmission, y as runDurationBatchId, z as toolStepSettledRecordId } from "./RunJournal-kfKVxJj7.mjs";
31
- import { $ as ThreadTailRequest, B as ThreadPromptRead, F as ThreadIdentityRequest, I as ThreadMaterialization, J as ThreadStore, R as ThreadObservation, U as ThreadReader, V as ThreadRead, X as ThreadStoreError, Y as ThreadStoreDiagnostic, _t as isPreContinuationFact, bt as terminalUsageCharge, gt as executionRunIds, ht as canonicalRunIds, lt as readWorkerState, n as AppendRequest, ot as getRecord, p as MAX_THREAD_EXPORT_PAGE_BYTES, pt as captureRecord, st as getRunInput } from "./ThreadStore-CEekRa80.mjs";
29
+ import { a as compileRegistrations, c as resolveDefinitionBinding, l as resolveWorkerBinding, n as CurrentBindingSelection, o as definitionDigestsEqual, s as makeLegacyWorkerBinding, t as BindingUnavailable, u as toolReplayContracts } from "./agent-registration-DRbyhAu-.mjs";
30
+ import { $ as toolCallSettledRecordId, A as subagentStartedBatchId, B as turnApprovalsBatchId, C as runStartedRecordId, D as subagentLineageRecordId, E as subagentLineageBatchId, F as toolCallResolvedRecordId, G as turnResponseBatchId, H as turnCanonicalBatch, I as toolCallResultBatchId, J as workerInputRecordId, K as turnResultsBatch, L as toolCallUnknownRecordId, M as toolApprovalDecisionRecordId, N as toolApprovalRequestRecordId, O as subagentRequestedBatchId, P as toolCallResolutionBatchId, Q as makeJournalMetadata, R as toolStepSettledBatchId, S as runStartedBatchId, T as subagentJoinedRecordId, U as turnIdForRun, W as turnResponseBatch, X as workerReportRecordId, Y as workerOriginRecordId, a as childIdempotencyKeyFor, b as runDurationRecordId, c as compactionRecordId, d as modelResponseInterruptedBatchId, f as modelResponseInterruptedRecordId, g as projectRunJournalStream, i as approvalDecisionBatchId, j as subagentStartedRecordId, k as subagentRequestedRecordId, l as firstWorkerInputRecordId, m as peerMessageRecordId, o as childThreadIdFor, p as modelResponseRecordId, r as agentUpdateRecordId, s as compactionBatchId, t as RunJournalError, u as markUnknownBatchId, v as runCompletedRecordId, w as subagentJoinBatchId, x as runIdForSubmission, y as runDurationBatchId, z as toolStepSettledRecordId } from "./RunJournal-CNZqA3Ge.mjs";
31
+ import { $ as ThreadTailRequest, B as ThreadPromptRead, F as ThreadIdentityRequest, I as ThreadMaterialization, J as ThreadStore, R as ThreadObservation, U as ThreadReader, V as ThreadRead, X as ThreadStoreError, Y as ThreadStoreDiagnostic, _t as isPreContinuationFact, bt as terminalUsageCharge, gt as executionRunIds, ht as canonicalRunIds, lt as readWorkerState, n as AppendRequest, ot as getRecord, p as MAX_THREAD_EXPORT_PAGE_BYTES, pt as captureRecord, st as getRunInput } from "./ThreadStore-59uDGXul.mjs";
32
32
  import { ScheduledInputRefused, ScheduledInputRetryable } from "./durable/Schedule.mjs";
33
33
  import { PreparedInputAdmission } from "./durable/PreparedInputAdmission.mjs";
34
34
  import { PreparedInput } from "./durable/Subscription.mjs";
35
35
  import { MessageDeliveryDriver, MessageDeliveryFailpoint, MessageDeliveryRecord, MessageDeliveryStore, prepareMessageDelivery } from "./durable/MessageDelivery.mjs";
36
36
  import { DurableRuntimeFailpoint } from "./durable/DurableFailpoint.mjs";
37
- import { _ as readRunContext, a as canonicalRecordBytes, b as reference, f as runEvidence, g as digestRunHistory, l as readContinuation, m as validateSuffix, n as CurrentRunWriter, s as makeProgressWriter, t as CurrentRunSettlement, u as readRunEvidenceSnapshot, x as resolveEvidence, y as RunContextReader } from "./RunContinuation-DHYNAQFi.mjs";
37
+ import { _ as readRunContext, a as canonicalRecordBytes, b as reference, f as runEvidence, g as digestRunHistory, l as readContinuation, m as validateSuffix, n as CurrentRunWriter, s as makeProgressWriter, t as CurrentRunSettlement, u as readRunEvidenceSnapshot, x as resolveEvidence, y as RunContextReader } from "./RunContinuation-4ZATcVLB.mjs";
38
38
  import { MAX_WORK_CURSOR_CHARS, ThreadWorkDiscovery, ThreadWorkEntry, ThreadWorkRequest, WorkDiscoveryUnavailable, decodeWorkCursor, deliveryPredecessor, encodeWorkCursor, operationEvidence, resolveWorkEvidence, validateWorkPage, workId } from "./durable/ThreadWork.mjs";
39
39
  import { WakeScheduler } from "./durable/WakeScheduler.mjs";
40
40
  import { n as safeUnknownString, t as inspectForeignDiagnostic } from "./foreign-diagnostic-DBQ1XHKh.mjs";
41
- import { c as threadCreatedBatchId, l as threadCreatedRecordId, n as WorkerAdmissionPort, o as ensureThreadCreated, r as WorkerAdmissionRequest, s as ensureWorkerOrigin } from "./WorkerAdmission-DFVbbVh2.mjs";
41
+ import { c as threadCreatedBatchId, l as threadCreatedRecordId, n as WorkerAdmissionPort, o as ensureThreadCreated, r as WorkerAdmissionRequest, s as ensureWorkerOrigin } from "./WorkerAdmission-DDYJdOsU.mjs";
42
42
  import { i as unresolvedToolOperations, n as isUnresolvedToolOperation, r as toolOperationStates, t as initialDispatchBlockedTurns } from "./tool-operations-BXBmagY1.mjs";
43
43
  import { WorkerBudgetAuthorizer, WorkerConcurrencyLimit, WorkerConcurrencyResolver, WorkerHostAuthorizer, WorkerHostConfig, WorkerPolicyResolver } from "./durable/WorkerHost.mjs";
44
44
  import { OperationAuthorizationRequest, OperationAuthorizer, OperationDenied } from "./durable/OperationAuthorizer.mjs";
45
- import { o as makeRunWriter, r as RunStorage, s as StorageOwner } from "./RunStorage-uqPxps09.mjs";
45
+ import { o as makeRunWriter, r as RunStorage, s as StorageOwner } from "./RunStorage-BHjuuERI.mjs";
46
46
  import { SettlementPublication } from "./durable/SettlementPublisher.mjs";
47
47
  import { PendingSubmission, SettledSubmission } from "./durable/SubmissionStatus.mjs";
48
48
  import { DeclaredToolCallEvidence, ToolReconciler } from "./durable/ToolReconciler.mjs";
@@ -736,7 +736,7 @@ function hydratePart(part) {
736
736
  case "tool-approval-request": return Prompt.toolApprovalRequestPart(part);
737
737
  case "tool-approval-response": return Prompt.toolApprovalResponsePart(part);
738
738
  }
739
- throw new Error(`Unhandled Prompt part: ${part}`);
739
+ return part;
740
740
  }
741
741
  const hydrateMessage = (message) => {
742
742
  switch (message.role) {
@@ -754,7 +754,7 @@ const hydrateMessage = (message) => {
754
754
  content: message.content.map((p) => hydratePart(p))
755
755
  });
756
756
  }
757
- throw new Error(`Unhandled Prompt message: ${message}`);
757
+ return message;
758
758
  };
759
759
  /** Internal canonical projection; ownership comes from the ThreadStore read contract. */
760
760
  const preparePromptHistory = (prompt) => prompt.content.length > MAX_ENTRIES ? void 0 : {
@@ -851,7 +851,12 @@ const makeCommittedPromptSuffix = (original) => {
851
851
  }
852
852
  try {
853
853
  for (const fact of facts) {
854
- const owned = captureRecord(fact);
854
+ const captured = captureRecord(fact);
855
+ if (Result.isFailure(captured)) {
856
+ discard();
857
+ return;
858
+ }
859
+ const owned = captured.success;
855
860
  const payload = owned.canonical.payload;
856
861
  if (payload._tag !== "UserInputRecorded" && payload._tag !== "ModelResponseRecorded" && payload._tag !== "ToolCallSettled" && payload._tag !== "SubmissionSettled") {
857
862
  discard();
@@ -2384,7 +2389,7 @@ const makeWorkerRuntime = Effect.fnUntraced(function* (options) {
2384
2389
  ownerThreadId: context.source.threadId,
2385
2390
  messageId
2386
2391
  }).pipe(Effect.mapError(storageFailure("start")));
2387
- const replay = (saved) => Effect.gen(function* () {
2392
+ const replay = Effect.fnUntraced(function* (saved) {
2388
2393
  const currentPrevious = command.continuationOf === void 0 ? void 0 : yield* completedContinuation(context.source, command.continuationOf, command.target.id, command.delegationId, previous?.evidence);
2389
2394
  const replayPrincipal = yield* authorize("start", "send", void 0, currentPrevious?.evidence);
2390
2395
  yield* binding(command.target, "start");
@@ -2476,7 +2481,7 @@ const makeWorkerRuntime = Effect.fnUntraced(function* (options) {
2476
2481
  ownerThreadId: context.source.threadId,
2477
2482
  messageId
2478
2483
  }).pipe(Effect.mapError(storageFailure("followUp")));
2479
- const replay = (saved) => Effect.gen(function* () {
2484
+ const replay = Effect.fnUntraced(function* (saved) {
2480
2485
  const replayPrincipal = yield* authorize("followUp", "send", command.worker);
2481
2486
  yield* currentPolicy;
2482
2487
  return yield* send(origin, messageId, saved.envelope.input, command.encodedParameters, replayPrincipal, "followUp");
@@ -3257,6 +3262,7 @@ const make = Effect.fnUntraced(function* (bindings) {
3257
3262
  let context;
3258
3263
  let progress;
3259
3264
  let progressThrough;
3265
+ let operational = [];
3260
3266
  const invalid = (message) => ThreadStoreError.make({
3261
3267
  operation: "read Run continuation",
3262
3268
  message
@@ -3325,20 +3331,20 @@ const make = Effect.fnUntraced(function* (bindings) {
3325
3331
  context = saved;
3326
3332
  progress = cursor;
3327
3333
  progressThrough = envelope.throughSequence;
3334
+ operational = envelope.operational;
3328
3335
  }
3329
3336
  }
3330
- const records = [...new Map([...identity.records.filter((entry) => entry.sequence <= throughSequence), ...selected].map((entry) => [entry.sequence, entry])).values()].sort((left, right) => left.sequence - right.sequence);
3331
3337
  return {
3332
- canonical: Stream.fromIterable(records),
3338
+ records: [...new Map([...identity.records.filter((entry) => entry.sequence <= throughSequence), ...selected].map((entry) => [entry.sequence, entry])).values()].sort((left, right) => left.sequence - right.sequence),
3333
3339
  context,
3334
3340
  progress,
3335
- progressThrough
3341
+ progressThrough,
3342
+ operational
3336
3343
  };
3337
3344
  });
3338
3345
  const readControl = Effect.fnUntraced(function* (threadId, submissionIds) {
3339
3346
  const tail = yield* store.inspectTail(ThreadTailRequest.make({ threadId }));
3340
- const view = yield* recoveryView(threadId, tail.tailSequence, submissionIds);
3341
- return yield* Stream.runCollect(view.canonical.pipe(Stream.filter(controlRecords(submissionIds))));
3347
+ return (yield* recoveryView(threadId, tail.tailSequence, submissionIds)).records.filter(controlRecords(submissionIds));
3342
3348
  });
3343
3349
  const readAllTolerant = (threadId, submissionIds) => Effect.suspend(() => readControl(threadId, submissionIds).pipe(Effect.map((records) => ({
3344
3350
  records,
@@ -3360,7 +3366,7 @@ const make = Effect.fnUntraced(function* (bindings) {
3360
3366
  submissionIds
3361
3367
  };
3362
3368
  return {
3363
- records: yield* recoveryView(threadId, tail.value.tailSequence, submissionIds).pipe(Effect.flatMap((view) => Stream.runCollect(view.canonical.pipe(Stream.filter(controlRecords(submissionIds))))), Effect.catchTag("ThreadNotMaterialized", (error) => ThreadStoreError.make({
3369
+ records: yield* recoveryView(threadId, tail.value.tailSequence, submissionIds).pipe(Effect.map((view) => view.records.filter(controlRecords(submissionIds))), Effect.catchTag("ThreadNotMaterialized", (error) => ThreadStoreError.make({
3364
3370
  operation: "read recovery history",
3365
3371
  message: `Thread ${threadId} disappeared after its recovery tail was captured`,
3366
3372
  cause: error
@@ -3747,7 +3753,7 @@ const make = Effect.fnUntraced(function* (bindings) {
3747
3753
  });
3748
3754
  const progressStore = ThreadStore.of({
3749
3755
  ...store,
3750
- append: (request) => Effect.gen(function* () {
3756
+ append: Effect.fnUntraced(function* (request) {
3751
3757
  const progress = activeProgress.get(request.threadId)?.writer ?? (yield* makeProgressWriter(request.threadId, config.deploymentId).pipe(Effect.provideService(ThreadReader, reader), Effect.provideService(Crypto.Crypto, crypto)));
3752
3758
  let tail = { sequence: request.expectedTailSequence };
3753
3759
  return yield* progress.commit(request.batch).pipe(Effect.provideService(CurrentRunWriter, {
@@ -3776,7 +3782,7 @@ const make = Effect.fnUntraced(function* (bindings) {
3776
3782
  threadId: ctx.threadId,
3777
3783
  tail: ctx.tail,
3778
3784
  withProgress: ctx.withProgress,
3779
- publishSettlement: (prepared, executions) => Effect.gen(function* () {
3785
+ publishSettlement: Effect.fnUntraced(function* (prepared, executions) {
3780
3786
  let tail = yield* ctx.tail;
3781
3787
  for (let retries = 0;; retries++) {
3782
3788
  const result = yield* runStorage.publishSettlement(SettlementPublication.make({
@@ -4079,23 +4085,26 @@ const make = Effect.fnUntraced(function* (bindings) {
4079
4085
  sequence: result.firstSequence
4080
4086
  });
4081
4087
  });
4082
- const readRunStart = Effect.fnUntraced(function* (threadId, runId) {
4083
- const loaded = yield* reader.readExecution({
4084
- threadId,
4085
- runId
4086
- }).pipe(Effect.catchTag("ThreadNotMaterialized", () => Effect.succeed(Option.none())));
4087
- if (Option.isNone(loaded)) return void 0;
4088
+ const readRunStart = Effect.fnUntraced(function* (threadId, runId, operational) {
4089
+ if (operational === void 0) {
4090
+ const loaded = yield* reader.readExecution({
4091
+ threadId,
4092
+ runId
4093
+ }).pipe(Effect.catchTag("ThreadNotMaterialized", () => Effect.succeed(Option.none())));
4094
+ if (Option.isNone(loaded)) return void 0;
4095
+ operational = loaded.value.operational;
4096
+ }
4088
4097
  const recordId = runStartedRecordId(runId);
4089
- const starts = loaded.value.operational.filter(({ payload }) => payload._tag === "RunStarted");
4090
- const existing = loaded.value.operational.find((record) => record.recordId === recordId);
4098
+ const starts = operational.filter(({ payload }) => payload._tag === "RunStarted");
4099
+ const existing = operational.find((record) => record.recordId === recordId);
4091
4100
  if (starts.length > 1 || starts.length === 1 && starts[0]?.recordId !== recordId || existing !== void 0 && (existing.payload._tag !== "RunStarted" || existing.payload.runId !== runId)) return yield* RunJournalError.make({ message: `Run ${runId} has conflicting active start state` });
4092
4101
  return existing;
4093
4102
  });
4094
- const makeRunStart = Effect.fnUntraced(function* (submission, maxDurationMillis, records) {
4103
+ const makeRunStart = Effect.fnUntraced(function* (submission, maxDurationMillis, records, operational) {
4095
4104
  const writer = yield* CurrentRunWriter;
4096
4105
  const runId = runIdForSubmission(submission.submissionId);
4097
4106
  const recordId = runStartedRecordId(runId);
4098
- const existing = yield* readRunStart(submission.threadId, runId);
4107
+ const existing = yield* readRunStart(submission.threadId, runId, operational);
4099
4108
  let start;
4100
4109
  let allowance = maxDurationMillis;
4101
4110
  let committed = existing !== void 0;
@@ -4942,1474 +4951,1476 @@ const make = Effect.fnUntraced(function* (bindings) {
4942
4951
  })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
4943
4952
  knownIds.add(recordId);
4944
4953
  });
4945
- /**
4946
- * Drive the shared interpreter Effect with history rebuilt by the run journal, commit
4947
- * each Turn under the local owner, and watch for durable abort intent. Engine Run failures settle `failed`; coordinator failures abort the
4948
- * Attempt cleanly with the obligation still owed.
4949
- *
4950
- * The interpreter supplies validated response, closed Tool-result, and completion facts.
4951
- * Responses precede approval and effectful dispatch; readonly responses may join their closed
4952
- * results. Tool results precede input drains and the next Turn. A no-tool response and Run
4953
- * completion share one batch. A completion Tool's result
4954
- * precedes its terminal-only completion batch, so recovery can repeat a pure output projection
4955
- * without replaying the handler. Pending batches resume from their canonical declarations.
4956
- */
4957
- const runModel = (agent, ctx, submission, session, records, canonical, initialJournal, canonicalThrough, progressThrough, continuation, priorContext, journalMetadata, lineage, approvalDecisions, currentContracts, runTiming, yieldAfter) => Effect.gen(function* () {
4958
- const submissionId = submission.submissionId;
4959
- const runId = runIdForSubmission(submissionId);
4960
- const boundaries = [];
4961
- const cached = projectedJournal;
4962
- const projectionThrough = Math.max(progressThrough ?? 0, records.at(-1)?.sequence ?? 0);
4963
- const originalInput = records.find(({ record: { payload } }) => payload._tag === "UserInputRecorded" && payload.kind === "user" && payload.submissionId === submissionId);
4964
- if (originalInput === void 0) return yield* RunJournalError.make({ message: "Run has no original context boundary" });
4965
- const historyEvidence = /* @__PURE__ */ new Map();
4966
- const retainHistory = (entry) => {
4967
- if (priorContext === void 0 && entry.sequence < originalInput.sequence) historyEvidence.set(entry.record.recordId, entry);
4968
- };
4969
- let journal = cached !== void 0 && cached.threadId === ctx.threadId && cached.through === projectionThrough && cached.runId === runId && cached.contextRecordId === priorContext?.recordId ? (boundaries.push(...cached.boundaries), cached.contextEvidence.forEach(retainHistory), cached.journal) : yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), priorContext, journalMetadata, priorContext === void 0 ? retainHistory : void 0);
4970
- if (initialJournal?.prefix !== void 0) {
4971
- const prompt = initialJournal.prefix.prompt;
4972
- journal = {
4973
- ...journal,
4974
- prompt,
4975
- historyBefore: prompt
4954
+ const runModel = Effect.fnUntraced(
4955
+ /**
4956
+ * Drive the shared interpreter Effect with history rebuilt by the run journal, commit
4957
+ * each Turn under the local owner, and watch for durable abort intent. Engine Run failures settle `failed`; coordinator failures abort the
4958
+ * Attempt cleanly with the obligation still owed.
4959
+ *
4960
+ * The interpreter supplies validated response, closed Tool-result, and completion facts.
4961
+ * Responses precede approval and effectful dispatch; readonly responses may join their closed
4962
+ * results. Tool results precede input drains and the next Turn. A no-tool response and Run
4963
+ * completion share one batch. A completion Tool's result
4964
+ * precedes its terminal-only completion batch, so recovery can repeat a pure output projection
4965
+ * without replaying the handler. Pending batches resume from their canonical declarations.
4966
+ */
4967
+ function* (agent, ctx, submission, session, records, canonical, initialJournal, canonicalThrough, progressThrough, continuation, priorContext, journalMetadata, lineage, approvalDecisions, currentContracts, runTiming, yieldAfter) {
4968
+ const submissionId = submission.submissionId;
4969
+ const runId = runIdForSubmission(submissionId);
4970
+ const boundaries = [];
4971
+ const cached = projectedJournal;
4972
+ const projectionThrough = Math.max(progressThrough ?? 0, records.at(-1)?.sequence ?? 0);
4973
+ const originalInput = records.find(({ record: { payload } }) => payload._tag === "UserInputRecorded" && payload.kind === "user" && payload.submissionId === submissionId);
4974
+ if (originalInput === void 0) return yield* RunJournalError.make({ message: "Run has no original context boundary" });
4975
+ const historyEvidence = /* @__PURE__ */ new Map();
4976
+ const retainHistory = (entry) => {
4977
+ if (priorContext === void 0 && entry.sequence < originalInput.sequence) historyEvidence.set(entry.record.recordId, entry);
4976
4978
  };
4977
- }
4978
- journalMetadata = void 0;
4979
- historyEvidence.forEach((entry, id) => {
4980
- if (entry.sequence >= journal.historyFrom) historyEvidence.delete(id);
4981
- });
4982
- projectedJournal = {
4983
- threadId: ctx.threadId,
4984
- through: CanonicalSequence.make(projectionThrough),
4985
- runId,
4986
- contextRecordId: priorContext?.recordId,
4987
- contextEvidence: [...historyEvidence.values()],
4988
- journal,
4989
- boundaries
4990
- };
4991
- if (continuation !== void 0) {
4992
- const accounting = continuation.accounting;
4993
- if ([
4994
- "committedTurns",
4995
- "toolCalls",
4996
- "programmaticToolCalls",
4997
- "consecutiveToolFailures",
4998
- "finalizationUsed",
4999
- "modelRestarts"
5000
- ].some((field) => (journal.policyUsage[field] ?? 0) !== accounting[field]) || [
5001
- "modelCalls",
5002
- "inputTokens",
5003
- "outputTokens",
5004
- "lastInputTokens",
5005
- "lastOutputTokens",
5006
- "costMicrousd"
5007
- ].some((field) => journal.usage[field] !== accounting[field]) || (journal.usage.unobservedModelCalls ?? 0) !== accounting.unobservedModelCalls) return yield* RunJournalError.make({ message: "Canonical continuation accounting differs from its exact execution evidence" });
5008
- }
5009
- const childLineage = records.find(({ record }) => record.recordId === subagentLineageRecordId(submission.threadId))?.record.payload;
5010
- const inheritedGrant = submission.workerAdmission?.origin.grant ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.grant : void 0);
5011
- const delegationDepth = submission.workerAdmission?.origin.depth ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.parentLink.depth : 0);
5012
- const inheritedBudget = submission.workerAdmission?.origin.budget ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.budget : void 0);
5013
- if (submission.parentLinkage !== void 0 && (childLineage?._tag !== "SubagentLineageRecorded" || childLineage.parentSubmissionId !== submission.parentLinkage.parentSubmissionId || childLineage.parentLink.parentToolCallId !== submission.parentLinkage.parentToolCallId || !definitionDigestsEqual(childLineage.childDefinitionDigests, submission.agentDigests) || childLineage.childInputDigest !== submission.inputDigest)) return yield* RunJournalError.make({ message: "The child Run has no matching canonical lineage and execution bounds" });
5014
- const completionTools = [...agent.definition.completion === void 0 ? [] : [agent.definition.completion.tool], ...agent.definition.completionFromTools?.map((declaration) => declaration.tool) ?? []];
5015
- const pending = yield* pendingToolBatchFor(records, runId, completionTools);
5016
- const resumeProjection = pending === void 0 ? journal : yield* projectRunJournalStream(withoutPendingBatch(canonical, pending, runId), runId, void 0, priorContext);
5017
- if (initialJournal !== void 0 && (journal.committedTurns !== 0 || journal.historyFrom !== 1 || journal.contextWindowId !== void 0 || historyEvidence.size !== 0 || pending !== void 0 || boundaries.some((boundary) => boundary.incomplete))) initialJournal.cacheable = false;
5018
- if (initialJournal?.cacheable) initialJournal.history = initialJournal.prefix ?? preparePromptHistory(journal.historyBefore);
5019
- if (initialJournal !== void 0) initialJournal.records = void 0;
5020
- const rolloverOperation = journal.pendingContextToolCallId === void 0 ? void 0 : operationsFor(records, runId).get(journal.pendingContextToolCallId);
5021
- const rolloverTool = rolloverOperation === void 0 ? void 0 : agent.definition.toolkit.tools[rolloverOperation.toolName];
5022
- const pendingContextToolCallId = rolloverOperation !== void 0 && rolloverTool !== void 0 && Context.get(rolloverTool.annotations, ContextRolloverTool) && currentContracts[rolloverOperation.toolName] === rolloverOperation.replay ? journal.pendingContextToolCallId : void 0;
5023
- const applicationCalls = pending?.calls.filter((call) => !call.providerExecuted);
5024
- const completionCandidate = applicationCalls?.length === 1 && completionTools.some((tool) => tool === applicationCalls[0]?.name) && pending?.settled.some((result) => result.id === applicationCalls[0]?.id && !result.isFailure) ? applicationCalls[0] : void 0;
5025
- const settledCompletion = pending !== void 0 && completionCandidate !== void 0 && supportsOperation(OpenToolCallEvidence.make({
5026
- toolCallId: Schema.decodeSync(ToolCallId)(completionCandidate.id),
5027
- toolName: completionCandidate.name,
5028
- turn: pending.turn
5029
- }), pending.toolOperations.find((operation) => operation.toolCallId === completionCandidate.id), {
5030
- definition: agent.definition,
5031
- contracts: currentContracts
5032
- }) ? Schema.decodeSync(ToolCallId)(completionCandidate.id) : void 0;
5033
- const knownIds = knownRecordIdsOf(records);
5034
- const stepOutputs = /* @__PURE__ */ new Map();
5035
- for (const envelope of records) {
5036
- const payload = envelope.record.payload;
5037
- if (payload._tag === "ToolStepSettled" && payload.runId === runId) stepOutputs.set(toolStepSettledRecordId(runId, payload.toolCallId, payload.stepName), payload.output);
5038
- }
5039
- const canonicalApprovalDecisions = /* @__PURE__ */ new Map();
5040
- const approvalRequestedTurns = /* @__PURE__ */ new Set();
5041
- for (const envelope of records) {
5042
- const payload = envelope.record.payload;
5043
- if (payload._tag === "ToolApprovalDecided" && payload.runId === runId) canonicalApprovalDecisions.set(payload.toolCallId, payload.decision);
5044
- else if (payload._tag === "ToolApprovalRequested" && payload.runId === runId) approvalRequestedTurns.add(payload.turn);
5045
- }
5046
- const approvalIntents = /* @__PURE__ */ new Map();
5047
- for (const intent of approvalDecisions) approvalIntents.set(intent.toolCallId, intent);
5048
- const joinedInputEnvelopes = /* @__PURE__ */ new Map();
5049
- let lastHostResponseSequence;
5050
- for (const envelope of records) {
5051
- const payload = envelope.record.payload;
5052
- if (payload._tag === "UserInputRecorded" && payload.runId === runId && payload.submissionId !== void 0 && payload.submissionId !== submissionId) joinedInputEnvelopes.set(payload.submissionId, envelope);
5053
- else if (payload._tag === "ModelResponseRecorded" && payload.runId === runId) {
5054
- if (lastHostResponseSequence === void 0 || envelope.sequence > lastHostResponseSequence) lastHostResponseSequence = envelope.sequence;
4979
+ let journal = cached !== void 0 && cached.threadId === ctx.threadId && cached.through === projectionThrough && cached.runId === runId && cached.contextRecordId === priorContext?.recordId ? (boundaries.push(...cached.boundaries), cached.contextEvidence.forEach(retainHistory), cached.journal) : yield* projectRunJournalStream(canonical, runId, (boundary) => boundaries.push(boundary), priorContext, journalMetadata, priorContext === void 0 ? retainHistory : void 0);
4980
+ if (initialJournal?.prefix !== void 0) {
4981
+ const prompt = initialJournal.prefix.prompt;
4982
+ journal = {
4983
+ ...journal,
4984
+ prompt,
4985
+ historyBefore: prompt
4986
+ };
5055
4987
  }
5056
- }
5057
- const stagedUsage = /* @__PURE__ */ new Map();
5058
- const committedUsageLengths = /* @__PURE__ */ new Map();
5059
- const committedUnobservedCalls = /* @__PURE__ */ new Map();
5060
- const usageForCommit = (turn) => {
5061
- const staged = stagedUsage.get(turn);
5062
- if (staged === void 0) return void 0;
5063
- const modelUsage = staged.modelUsage.slice(committedUsageLengths.get(turn) ?? 0);
5064
- if (modelUsage.length === 0) return void 0;
5065
- return {
5066
- modelUsage,
5067
- inputTokens: modelUsage.reduce((sum, call) => sum + call.inputTokens.total, 0),
5068
- outputTokens: modelUsage.reduce((sum, call) => sum + call.outputTokens.total, 0),
5069
- costMicrousd: modelUsage.reduce((sum, call) => sum + call.costMicrousd, 0)
4988
+ journalMetadata = void 0;
4989
+ historyEvidence.forEach((entry, id) => {
4990
+ if (entry.sequence >= journal.historyFrom) historyEvidence.delete(id);
4991
+ });
4992
+ projectedJournal = {
4993
+ threadId: ctx.threadId,
4994
+ through: CanonicalSequence.make(projectionThrough),
4995
+ runId,
4996
+ contextRecordId: priorContext?.recordId,
4997
+ contextEvidence: [...historyEvidence.values()],
4998
+ journal,
4999
+ boundaries
5070
5000
  };
5071
- };
5072
- const unobservedForCommit = (turn) => (stagedUnobservedCalls.get(turn) ?? 0) - (committedUnobservedCalls.get(turn) ?? 0);
5073
- const recordCommittedUsage = (batch) => {
5074
- for (const record of batch.records) {
5075
- if (record.payload._tag !== "ModelResponseRecorded" && record.payload._tag !== "ModelCallAborted") continue;
5076
- const payload = record.payload;
5077
- committedUsageLengths.set(payload.turn, (committedUsageLengths.get(payload.turn) ?? 0) + (payload.modelUsage?.length ?? 0));
5078
- committedUnobservedCalls.set(payload.turn, (committedUnobservedCalls.get(payload.turn) ?? 0) + (payload.unobservedModelCalls ?? 0));
5001
+ if (continuation !== void 0) {
5002
+ const accounting = continuation.accounting;
5003
+ if ([
5004
+ "committedTurns",
5005
+ "toolCalls",
5006
+ "programmaticToolCalls",
5007
+ "consecutiveToolFailures",
5008
+ "finalizationUsed",
5009
+ "modelRestarts"
5010
+ ].some((field) => (journal.policyUsage[field] ?? 0) !== accounting[field]) || [
5011
+ "modelCalls",
5012
+ "inputTokens",
5013
+ "outputTokens",
5014
+ "lastInputTokens",
5015
+ "lastOutputTokens",
5016
+ "costMicrousd"
5017
+ ].some((field) => journal.usage[field] !== accounting[field]) || (journal.usage.unobservedModelCalls ?? 0) !== accounting.unobservedModelCalls) return yield* RunJournalError.make({ message: "Canonical continuation accounting differs from its exact execution evidence" });
5079
5018
  }
5080
- progressWriters.get(ctx)?.stageUsage(runId, terminalUsageCharge(uncommittedModelUsage()));
5081
- };
5082
- const uncommittedModelUsage = () => [...stagedUsage.entries()].flatMap(([turn, usage]) => usage.modelUsage.slice(committedUsageLengths.get(turn) ?? 0));
5083
- const stagedUnobservedCalls = /* @__PURE__ */ new Map();
5084
- let interruptedUsage = records.some(({ record }) => record.payload._tag === "ModelResponseInterrupted" && record.payload.runId === runId);
5085
- const checkedUsageTotal = (field, value) => decodeUsageTotal(value).pipe(Effect.mapError((cause) => RunJournalError.make({
5086
- message: `Run usage summary exceeds safe-integer bounds at ${field}`,
5087
- cause
5088
- })));
5089
- const addUsageTotal = (field, left, right) => checkedUsageTotal(field, left + right);
5090
- const subtractUsageTotal = (field, left, right) => checkedUsageTotal(field, left - right);
5091
- const currentUsageSummary = () => Effect.gen(function* () {
5092
- const stagedCalls = [...stagedUsage.values()].flatMap((usage) => usage.modelUsage);
5093
- let unobservedModelCalls = journal.usage.unobservedModelCalls ?? 0;
5094
- for (const count of stagedUnobservedCalls.values()) unobservedModelCalls = yield* addUsageTotal("unobservedModelCalls", unobservedModelCalls, count);
5095
- const detailedCalls = [...journal.usage.modelUsage, ...stagedCalls];
5096
- const detailed = yield* summarizeModelUsage(detailedCalls, journal.usage.summarizedModelUsage).pipe(Effect.mapError((cause) => RunJournalError.make({
5097
- message: "Run detailed usage exceeds safe-integer accounting bounds",
5019
+ const childLineage = records.find(({ record }) => record.recordId === subagentLineageRecordId(submission.threadId))?.record.payload;
5020
+ const inheritedGrant = submission.workerAdmission?.origin.grant ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.grant : void 0);
5021
+ const delegationDepth = submission.workerAdmission?.origin.depth ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.parentLink.depth : 0);
5022
+ const inheritedBudget = submission.workerAdmission?.origin.budget ?? (childLineage?._tag === "SubagentLineageRecorded" ? childLineage.budget : void 0);
5023
+ if (submission.parentLinkage !== void 0 && (childLineage?._tag !== "SubagentLineageRecorded" || childLineage.parentSubmissionId !== submission.parentLinkage.parentSubmissionId || childLineage.parentLink.parentToolCallId !== submission.parentLinkage.parentToolCallId || !definitionDigestsEqual(childLineage.childDefinitionDigests, submission.agentDigests) || childLineage.childInputDigest !== submission.inputDigest)) return yield* RunJournalError.make({ message: "The child Run has no matching canonical lineage and execution bounds" });
5024
+ const completionTools = [...agent.definition.completion === void 0 ? [] : [agent.definition.completion.tool], ...agent.definition.completionFromTools?.map((declaration) => declaration.tool) ?? []];
5025
+ const pending = yield* pendingToolBatchFor(records, runId, completionTools);
5026
+ const resumeProjection = pending === void 0 ? journal : yield* projectRunJournalStream(withoutPendingBatch(canonical, pending, runId), runId, void 0, priorContext);
5027
+ if (initialJournal !== void 0 && (journal.committedTurns !== 0 || journal.historyFrom !== 1 || journal.contextWindowId !== void 0 || historyEvidence.size !== 0 || pending !== void 0 || boundaries.some((boundary) => boundary.incomplete))) initialJournal.cacheable = false;
5028
+ if (initialJournal?.cacheable) initialJournal.history = initialJournal.prefix ?? preparePromptHistory(journal.historyBefore);
5029
+ if (initialJournal !== void 0) initialJournal.records = void 0;
5030
+ const rolloverOperation = journal.pendingContextToolCallId === void 0 ? void 0 : operationsFor(records, runId).get(journal.pendingContextToolCallId);
5031
+ const rolloverTool = rolloverOperation === void 0 ? void 0 : agent.definition.toolkit.tools[rolloverOperation.toolName];
5032
+ const pendingContextToolCallId = rolloverOperation !== void 0 && rolloverTool !== void 0 && Context.get(rolloverTool.annotations, ContextRolloverTool) && currentContracts[rolloverOperation.toolName] === rolloverOperation.replay ? journal.pendingContextToolCallId : void 0;
5033
+ const applicationCalls = pending?.calls.filter((call) => !call.providerExecuted);
5034
+ const completionCandidate = applicationCalls?.length === 1 && completionTools.some((tool) => tool === applicationCalls[0]?.name) && pending?.settled.some((result) => result.id === applicationCalls[0]?.id && !result.isFailure) ? applicationCalls[0] : void 0;
5035
+ const settledCompletion = pending !== void 0 && completionCandidate !== void 0 && supportsOperation(OpenToolCallEvidence.make({
5036
+ toolCallId: Schema.decodeSync(ToolCallId)(completionCandidate.id),
5037
+ toolName: completionCandidate.name,
5038
+ turn: pending.turn
5039
+ }), pending.toolOperations.find((operation) => operation.toolCallId === completionCandidate.id), {
5040
+ definition: agent.definition,
5041
+ contracts: currentContracts
5042
+ }) ? Schema.decodeSync(ToolCallId)(completionCandidate.id) : void 0;
5043
+ const knownIds = knownRecordIdsOf(records);
5044
+ const stepOutputs = /* @__PURE__ */ new Map();
5045
+ for (const envelope of records) {
5046
+ const payload = envelope.record.payload;
5047
+ if (payload._tag === "ToolStepSettled" && payload.runId === runId) stepOutputs.set(toolStepSettledRecordId(runId, payload.toolCallId, payload.stepName), payload.output);
5048
+ }
5049
+ const canonicalApprovalDecisions = /* @__PURE__ */ new Map();
5050
+ const approvalRequestedTurns = /* @__PURE__ */ new Set();
5051
+ for (const envelope of records) {
5052
+ const payload = envelope.record.payload;
5053
+ if (payload._tag === "ToolApprovalDecided" && payload.runId === runId) canonicalApprovalDecisions.set(payload.toolCallId, payload.decision);
5054
+ else if (payload._tag === "ToolApprovalRequested" && payload.runId === runId) approvalRequestedTurns.add(payload.turn);
5055
+ }
5056
+ const approvalIntents = /* @__PURE__ */ new Map();
5057
+ for (const intent of approvalDecisions) approvalIntents.set(intent.toolCallId, intent);
5058
+ const joinedInputEnvelopes = /* @__PURE__ */ new Map();
5059
+ let lastHostResponseSequence;
5060
+ for (const envelope of records) {
5061
+ const payload = envelope.record.payload;
5062
+ if (payload._tag === "UserInputRecorded" && payload.runId === runId && payload.submissionId !== void 0 && payload.submissionId !== submissionId) joinedInputEnvelopes.set(payload.submissionId, envelope);
5063
+ else if (payload._tag === "ModelResponseRecorded" && payload.runId === runId) {
5064
+ if (lastHostResponseSequence === void 0 || envelope.sequence > lastHostResponseSequence) lastHostResponseSequence = envelope.sequence;
5065
+ }
5066
+ }
5067
+ const stagedUsage = /* @__PURE__ */ new Map();
5068
+ const committedUsageLengths = /* @__PURE__ */ new Map();
5069
+ const committedUnobservedCalls = /* @__PURE__ */ new Map();
5070
+ const usageForCommit = (turn) => {
5071
+ const staged = stagedUsage.get(turn);
5072
+ if (staged === void 0) return void 0;
5073
+ const modelUsage = staged.modelUsage.slice(committedUsageLengths.get(turn) ?? 0);
5074
+ if (modelUsage.length === 0) return void 0;
5075
+ return {
5076
+ modelUsage,
5077
+ inputTokens: modelUsage.reduce((sum, call) => sum + call.inputTokens.total, 0),
5078
+ outputTokens: modelUsage.reduce((sum, call) => sum + call.outputTokens.total, 0),
5079
+ costMicrousd: modelUsage.reduce((sum, call) => sum + call.costMicrousd, 0)
5080
+ };
5081
+ };
5082
+ const unobservedForCommit = (turn) => (stagedUnobservedCalls.get(turn) ?? 0) - (committedUnobservedCalls.get(turn) ?? 0);
5083
+ const recordCommittedUsage = (batch) => {
5084
+ for (const record of batch.records) {
5085
+ if (record.payload._tag !== "ModelResponseRecorded" && record.payload._tag !== "ModelCallAborted") continue;
5086
+ const payload = record.payload;
5087
+ committedUsageLengths.set(payload.turn, (committedUsageLengths.get(payload.turn) ?? 0) + (payload.modelUsage?.length ?? 0));
5088
+ committedUnobservedCalls.set(payload.turn, (committedUnobservedCalls.get(payload.turn) ?? 0) + (payload.unobservedModelCalls ?? 0));
5089
+ }
5090
+ progressWriters.get(ctx)?.stageUsage(runId, terminalUsageCharge(uncommittedModelUsage()));
5091
+ };
5092
+ const uncommittedModelUsage = () => [...stagedUsage.entries()].flatMap(([turn, usage]) => usage.modelUsage.slice(committedUsageLengths.get(turn) ?? 0));
5093
+ const stagedUnobservedCalls = /* @__PURE__ */ new Map();
5094
+ let interruptedUsage = records.some(({ record }) => record.payload._tag === "ModelResponseInterrupted" && record.payload.runId === runId);
5095
+ const checkedUsageTotal = (field, value) => decodeUsageTotal(value).pipe(Effect.mapError((cause) => RunJournalError.make({
5096
+ message: `Run usage summary exceeds safe-integer bounds at ${field}`,
5098
5097
  cause
5099
5098
  })));
5100
- let inputTokens = journal.usage.inputTokens;
5101
- let outputTokens = journal.usage.outputTokens;
5102
- let costMicrousd = journal.usage.costMicrousd;
5103
- for (const usage of stagedUsage.values()) {
5104
- inputTokens = yield* addUsageTotal("inputTokens", inputTokens, usage.inputTokens);
5105
- outputTokens = yield* addUsageTotal("outputTokens", outputTokens, usage.outputTokens);
5106
- costMicrousd = yield* addUsageTotal("costMicrousd", costMicrousd, usage.costMicrousd);
5107
- }
5108
- const modelCalls = yield* addUsageTotal("modelCalls", journal.usage.modelCalls, stagedCalls.length);
5109
- const legacyCalls = yield* subtractUsageTotal("legacy.modelCalls", modelCalls, detailed.modelCalls);
5110
- const legacyInput = yield* subtractUsageTotal("legacy.inputTokens", inputTokens, detailed.inputTokens.total);
5111
- const legacyOutput = yield* subtractUsageTotal("legacy.outputTokens", outputTokens, detailed.outputTokens.total);
5112
- const legacyCost = yield* subtractUsageTotal("legacy.costMicrousd", costMicrousd, detailed.costMicrousd);
5113
- if (legacyCalls === 0 && (legacyInput !== 0 || legacyOutput !== 0 || legacyCost !== 0)) return yield* RunJournalError.make({ message: "Run aggregate usage has legacy totals without a legacy model call" });
5114
- const byModel = [...detailed.byModel];
5115
- if (legacyCalls > 0) {
5116
- const existingIndex = byModel.findIndex((group) => group.provider === "unknown" && group.model === "legacy-record" && group.responseModel === void 0 && group.serviceTier === void 0 && group.pricingVersion === void 0);
5117
- const existing = existingIndex < 0 ? void 0 : byModel[existingIndex];
5118
- const legacyGroup = ModelUsageGroup.make({
5119
- provider: "unknown",
5120
- model: "legacy-record",
5121
- modelCalls: yield* addUsageTotal("byModel.modelCalls", existing?.modelCalls ?? 0, legacyCalls),
5099
+ const addUsageTotal = (field, left, right) => checkedUsageTotal(field, left + right);
5100
+ const subtractUsageTotal = (field, left, right) => checkedUsageTotal(field, left - right);
5101
+ const currentUsageSummary = () => Effect.gen(function* () {
5102
+ const stagedCalls = [...stagedUsage.values()].flatMap((usage) => usage.modelUsage);
5103
+ let unobservedModelCalls = journal.usage.unobservedModelCalls ?? 0;
5104
+ for (const count of stagedUnobservedCalls.values()) unobservedModelCalls = yield* addUsageTotal("unobservedModelCalls", unobservedModelCalls, count);
5105
+ const detailedCalls = [...journal.usage.modelUsage, ...stagedCalls];
5106
+ const detailed = yield* summarizeModelUsage(detailedCalls, journal.usage.summarizedModelUsage).pipe(Effect.mapError((cause) => RunJournalError.make({
5107
+ message: "Run detailed usage exceeds safe-integer accounting bounds",
5108
+ cause
5109
+ })));
5110
+ let inputTokens = journal.usage.inputTokens;
5111
+ let outputTokens = journal.usage.outputTokens;
5112
+ let costMicrousd = journal.usage.costMicrousd;
5113
+ for (const usage of stagedUsage.values()) {
5114
+ inputTokens = yield* addUsageTotal("inputTokens", inputTokens, usage.inputTokens);
5115
+ outputTokens = yield* addUsageTotal("outputTokens", outputTokens, usage.outputTokens);
5116
+ costMicrousd = yield* addUsageTotal("costMicrousd", costMicrousd, usage.costMicrousd);
5117
+ }
5118
+ const modelCalls = yield* addUsageTotal("modelCalls", journal.usage.modelCalls, stagedCalls.length);
5119
+ const legacyCalls = yield* subtractUsageTotal("legacy.modelCalls", modelCalls, detailed.modelCalls);
5120
+ const legacyInput = yield* subtractUsageTotal("legacy.inputTokens", inputTokens, detailed.inputTokens.total);
5121
+ const legacyOutput = yield* subtractUsageTotal("legacy.outputTokens", outputTokens, detailed.outputTokens.total);
5122
+ const legacyCost = yield* subtractUsageTotal("legacy.costMicrousd", costMicrousd, detailed.costMicrousd);
5123
+ if (legacyCalls === 0 && (legacyInput !== 0 || legacyOutput !== 0 || legacyCost !== 0)) return yield* RunJournalError.make({ message: "Run aggregate usage has legacy totals without a legacy model call" });
5124
+ const byModel = [...detailed.byModel];
5125
+ if (legacyCalls > 0) {
5126
+ const existingIndex = byModel.findIndex((group) => group.provider === "unknown" && group.model === "legacy-record" && group.responseModel === void 0 && group.serviceTier === void 0 && group.pricingVersion === void 0);
5127
+ const existing = existingIndex < 0 ? void 0 : byModel[existingIndex];
5128
+ const legacyGroup = ModelUsageGroup.make({
5129
+ provider: "unknown",
5130
+ model: "legacy-record",
5131
+ modelCalls: yield* addUsageTotal("byModel.modelCalls", existing?.modelCalls ?? 0, legacyCalls),
5132
+ inputTokens: InputTokenUsage.make({
5133
+ total: yield* addUsageTotal("byModel.inputTokens.total", existing?.inputTokens.total ?? 0, legacyInput),
5134
+ uncached: yield* addUsageTotal("byModel.inputTokens.uncached", existing?.inputTokens.uncached ?? 0, legacyInput),
5135
+ cacheRead: existing?.inputTokens.cacheRead ?? 0,
5136
+ cacheWrite: existing?.inputTokens.cacheWrite ?? 0
5137
+ }),
5138
+ outputTokens: OutputTokenUsage.make({
5139
+ total: yield* addUsageTotal("byModel.outputTokens.total", existing?.outputTokens.total ?? 0, legacyOutput),
5140
+ text: yield* addUsageTotal("byModel.outputTokens.text", existing?.outputTokens.text ?? 0, legacyOutput),
5141
+ reasoning: existing?.outputTokens.reasoning ?? 0
5142
+ }),
5143
+ costMicrousd: yield* addUsageTotal("byModel.costMicrousd", existing?.costMicrousd ?? 0, legacyCost)
5144
+ });
5145
+ if (existingIndex < 0) byModel.push(legacyGroup);
5146
+ else byModel[existingIndex] = legacyGroup;
5147
+ }
5148
+ const uncached = yield* addUsageTotal("inputTokens.uncached", detailed.inputTokens.uncached, legacyInput);
5149
+ const text = yield* addUsageTotal("outputTokens.text", detailed.outputTokens.text, legacyOutput);
5150
+ return RunUsageSummary.make({
5151
+ ...legacyCalls === 0 && detailed.webSearchCalls !== void 0 ? { webSearchCalls: detailed.webSearchCalls } : {},
5152
+ modelCalls,
5122
5153
  inputTokens: InputTokenUsage.make({
5123
- total: yield* addUsageTotal("byModel.inputTokens.total", existing?.inputTokens.total ?? 0, legacyInput),
5124
- uncached: yield* addUsageTotal("byModel.inputTokens.uncached", existing?.inputTokens.uncached ?? 0, legacyInput),
5125
- cacheRead: existing?.inputTokens.cacheRead ?? 0,
5126
- cacheWrite: existing?.inputTokens.cacheWrite ?? 0
5154
+ total: inputTokens,
5155
+ uncached,
5156
+ cacheRead: detailed.inputTokens.cacheRead,
5157
+ cacheWrite: detailed.inputTokens.cacheWrite
5127
5158
  }),
5128
5159
  outputTokens: OutputTokenUsage.make({
5129
- total: yield* addUsageTotal("byModel.outputTokens.total", existing?.outputTokens.total ?? 0, legacyOutput),
5130
- text: yield* addUsageTotal("byModel.outputTokens.text", existing?.outputTokens.text ?? 0, legacyOutput),
5131
- reasoning: existing?.outputTokens.reasoning ?? 0
5160
+ total: outputTokens,
5161
+ text,
5162
+ reasoning: detailed.outputTokens.reasoning
5132
5163
  }),
5133
- costMicrousd: yield* addUsageTotal("byModel.costMicrousd", existing?.costMicrousd ?? 0, legacyCost)
5164
+ costMicrousd,
5165
+ byModel,
5166
+ unobservedModelCalls,
5167
+ usageStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.usageStatus === "unknown" ? "unknown" : "partial" : detailed.usageStatus,
5168
+ pricingStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.pricingStatus === "unknown" ? "unknown" : "partial" : detailed.pricingStatus
5134
5169
  });
5135
- if (existingIndex < 0) byModel.push(legacyGroup);
5136
- else byModel[existingIndex] = legacyGroup;
5137
- }
5138
- const uncached = yield* addUsageTotal("inputTokens.uncached", detailed.inputTokens.uncached, legacyInput);
5139
- const text = yield* addUsageTotal("outputTokens.text", detailed.outputTokens.text, legacyOutput);
5140
- return RunUsageSummary.make({
5141
- ...legacyCalls === 0 && detailed.webSearchCalls !== void 0 ? { webSearchCalls: detailed.webSearchCalls } : {},
5142
- modelCalls,
5143
- inputTokens: InputTokenUsage.make({
5144
- total: inputTokens,
5145
- uncached,
5146
- cacheRead: detailed.inputTokens.cacheRead,
5147
- cacheWrite: detailed.inputTokens.cacheWrite
5148
- }),
5149
- outputTokens: OutputTokenUsage.make({
5150
- total: outputTokens,
5151
- text,
5152
- reasoning: detailed.outputTokens.reasoning
5153
- }),
5154
- costMicrousd,
5155
- byModel,
5156
- unobservedModelCalls,
5157
- usageStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.usageStatus === "unknown" ? "unknown" : "partial" : detailed.usageStatus,
5158
- pricingStatus: legacyCalls > 0 || unobservedModelCalls > 0 || interruptedUsage ? detailed.pricingStatus === "unknown" ? "unknown" : "partial" : detailed.pricingStatus
5159
5170
  });
5160
- });
5161
- const activeExecution = yield* reader.readExecution({
5162
- threadId: ctx.threadId,
5163
- runId
5164
- });
5165
- const recordedCompletion = Option.isSome(activeExecution) ? activeExecution.value.operational.find((record) => record.recordId === runCompletedRecordId(runId))?.payload : void 0;
5166
- if (recordedCompletion !== void 0) {
5167
- if (recordedCompletion._tag !== "RunCompleted" || recordedCompletion.runId !== runId) return yield* RunJournalError.make({ message: `Run ${runId} has an invalid terminal completion marker` });
5168
- const response = [...records].reverse().find((envelope) => envelope.record.payload._tag === "ModelResponseRecorded" && envelope.record.payload.runId === runId)?.record.payload;
5169
- if (response?._tag !== "ModelResponseRecorded") return yield* RunJournalError.make({ message: `Run ${runId} has a terminal completion marker without a response` });
5170
- const calls = (yield* declaredToolCalls(response.messages)).application;
5171
- if (calls.length > 0) {
5172
- const call = calls[0];
5173
- const settled = call === void 0 ? void 0 : records.find(({ record }) => record.payload._tag === "ToolCallSettled" && record.payload.runId === runId && record.payload.toolCallId === call.id)?.record.payload;
5174
- if (calls.length !== 1 || call === void 0 || settled?._tag !== "ToolCallSettled" || settled.toolName !== call.name || settled.isFailure) return yield* RunJournalError.make({ message: `Run ${runId} has a terminal completion marker without one successful declared Tool result` });
5175
- }
5176
- return {
5177
- _tag: "completed",
5178
- result: recordedCompletion.output,
5179
- ...recordedCompletion.runDisposition === void 0 ? {} : { runDisposition: recordedCompletion.runDisposition },
5180
- ...recordedCompletion.finishReason === void 0 ? {} : { finishReason: recordedCompletion.finishReason },
5181
- ...recordedCompletion.exhausted === void 0 ? {} : { exhausted: recordedCompletion.exhausted },
5182
- usageSummary: yield* currentUsageSummary()
5183
- };
5184
- }
5185
- let ownerFirstSequence;
5186
- for (const envelope of records) {
5187
- const payload = envelope.record.payload;
5188
- if ("runId" in payload && payload.runId === runId) {
5189
- ownerFirstSequence = envelope.sequence;
5190
- break;
5171
+ const activeExecution = yield* reader.readExecution({
5172
+ threadId: ctx.threadId,
5173
+ runId
5174
+ });
5175
+ const recordedCompletion = Option.isSome(activeExecution) ? activeExecution.value.operational.find((record) => record.recordId === runCompletedRecordId(runId))?.payload : void 0;
5176
+ if (recordedCompletion !== void 0) {
5177
+ if (recordedCompletion._tag !== "RunCompleted" || recordedCompletion.runId !== runId) return yield* RunJournalError.make({ message: `Run ${runId} has an invalid terminal completion marker` });
5178
+ const response = [...records].reverse().find((envelope) => envelope.record.payload._tag === "ModelResponseRecorded" && envelope.record.payload.runId === runId)?.record.payload;
5179
+ if (response?._tag !== "ModelResponseRecorded") return yield* RunJournalError.make({ message: `Run ${runId} has a terminal completion marker without a response` });
5180
+ const calls = (yield* declaredToolCalls(response.messages)).application;
5181
+ if (calls.length > 0) {
5182
+ const call = calls[0];
5183
+ const settled = call === void 0 ? void 0 : records.find(({ record }) => record.payload._tag === "ToolCallSettled" && record.payload.runId === runId && record.payload.toolCallId === call.id)?.record.payload;
5184
+ if (calls.length !== 1 || call === void 0 || settled?._tag !== "ToolCallSettled" || settled.toolName !== call.name || settled.isFailure) return yield* RunJournalError.make({ message: `Run ${runId} has a terminal completion marker without one successful declared Tool result` });
5185
+ }
5186
+ return {
5187
+ _tag: "completed",
5188
+ result: recordedCompletion.output,
5189
+ ...recordedCompletion.runDisposition === void 0 ? {} : { runDisposition: recordedCompletion.runDisposition },
5190
+ ...recordedCompletion.finishReason === void 0 ? {} : { finishReason: recordedCompletion.finishReason },
5191
+ ...recordedCompletion.exhausted === void 0 ? {} : { exhausted: recordedCompletion.exhausted },
5192
+ usageSummary: yield* currentUsageSummary()
5193
+ };
5191
5194
  }
5192
- }
5193
- /** Only canonical joined inputs can require restoration from an earlier Attempt. */
5194
- let joinBacklog = joinedInputEnvelopes.size === 0 ? [] : void 0;
5195
- /** Joined inputs already handed to the engine during THIS Attempt (never re-deliver). */
5196
- const deliveredJoinInputs = /* @__PURE__ */ new Set();
5197
- const encodedParamsByCallId = /* @__PURE__ */ new Map();
5198
- const declaredNamesByCallId = /* @__PURE__ */ new Map();
5199
- const subagentState = subagentRecordsOf(records, runId);
5200
- const declaredToolIds = new Set(subagentState.declaredNames.keys());
5201
- if (declaredToolIds.size > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
5202
- for (const [callId, name] of subagentState.declaredNames) declaredNamesByCallId.set(callId, name);
5203
- if (pending !== void 0) for (const call of pending.calls) {
5204
- encodedParamsByCallId.set(call.id, call.params);
5205
- declaredNamesByCallId.set(call.id, call.name);
5206
- }
5207
- let resumeLeadingMessages;
5208
- let resumeResponseMessages;
5209
- if (pending !== void 0) {
5210
- const pendingMessages = yield* decodePrompt(pending.messages).pipe(Effect.mapError((cause) => RunJournalError.make({
5211
- message: "Pending ModelResponseRecorded messages are not Schema-encoded Prompt messages",
5212
- cause
5213
- })));
5214
- const firstAssistant = pendingMessages.content.findIndex((message) => message.role === "assistant");
5215
- if (firstAssistant > 0) resumeLeadingMessages = Prompt.fromMessages(pendingMessages.content.slice(0, firstAssistant).filter((message) => message.role !== "system"));
5216
- if (firstAssistant >= 0) resumeResponseMessages = Prompt.fromMessages(pendingMessages.content.slice(firstAssistant));
5217
- }
5218
- const initialDispatchProofTurns = new Set(initialDispatchBlockedTurns(records, runId));
5219
- let currentToolTurn = pending === void 0 ? void 0 : {
5220
- turn: pending.turn,
5221
- turnId: pending.turnId
5222
- };
5223
- const haltRef = yield* Ref.make(void 0);
5224
- const yieldSignal = yield* Deferred.make();
5225
- const recordHalt = (effect) => effect.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, (failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? failure.cause : new CoordinatorHalt(failure)))));
5226
- const checkpoint = recordHalt(Effect.gen(function* () {
5227
- const failure = yield* Ref.get(haltRef);
5228
- if (failure !== void 0) return yield* failure;
5229
- const progress = progressWriters.get(ctx);
5230
- if (progress !== void 0) yield* progress.check(runId).pipe(Effect.provideService(CurrentRunWriter, ctx));
5231
- }));
5232
- const responseGate = yield* Semaphore.make(1);
5233
- let deferredResponse;
5234
- const acceptResponseDeclarations = (batch) => {
5235
- for (const record of batch.records) {
5236
- if (record.payload._tag !== "ModelResponseRecorded") continue;
5237
- for (const call of record.payload.toolOperations) {
5238
- declaredToolIds.add(call.toolCallId);
5239
- declaredNamesByCallId.set(call.toolCallId, call.toolName);
5195
+ let ownerFirstSequence;
5196
+ for (const envelope of records) {
5197
+ const payload = envelope.record.payload;
5198
+ if ("runId" in payload && payload.runId === runId) {
5199
+ ownerFirstSequence = envelope.sequence;
5200
+ break;
5240
5201
  }
5241
5202
  }
5242
- };
5243
- const promoteResponse = Effect.gen(function* () {
5244
- const halted = yield* Ref.get(haltRef);
5245
- if (halted !== void 0) return yield* halted;
5246
- const deferred = deferredResponse;
5247
- if (deferred === void 0) return;
5248
- const record = deferred.batch.records[0];
5249
- if (record?.payload._tag !== "ModelResponseRecorded") return yield* RunJournalError.make({ message: "Deferred Turn has no owned response" });
5250
- const calls = yield* declaredToolCalls(record.payload.messages);
5251
- const batch = CanonicalBatch.make({
5252
- ...deferred.batch,
5253
- batchId: turnResponseBatchId(runId, deferred.turn)
5254
- });
5255
- yield* appendBatch(ctx, batch);
5256
- acceptResponseDeclarations(batch);
5257
- for (const call of calls.application) encodedParamsByCallId.set(call.id, call.params);
5258
- recordCommittedUsage(batch);
5259
- for (const entry of batch.records) knownIds.add(entry.recordId);
5260
- deferredResponse = void 0;
5261
- yield* hit("turn:after-response-append");
5262
- });
5263
- const flushDeferredResponse = promoteResponse.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), responseGate.withPermits(1));
5264
- let initialHistoryLength = 0;
5265
- let initialInstructions = [];
5266
- const completionState = {};
5267
- const turnCounter = yield* Ref.make(journal.committedTurns + (journal.policyUsage.modelRestarts ?? 0));
5268
- const idGenerator = {
5269
- nextThreadId: Effect.succeed(submission.threadId),
5270
- nextRunId: Effect.succeed(runId),
5271
- nextTurnId: Ref.modify(turnCounter, (turn) => [turnIdForRun(runId, turn + 1), turn + 1])
5272
- };
5273
- const instructionView = (messages, instructions, insertWhenAbsent, priorRunPrefixLength) => {
5274
- const projected = [];
5275
- const lengths = [0];
5276
- let inserted = false;
5277
- for (const [index, message] of messages.entries()) {
5278
- if (index >= priorRunPrefixLength && message.role === "system") {
5279
- if (!inserted) projected.push(...instructions);
5280
- inserted = true;
5281
- } else projected.push(message);
5282
- lengths.push(projected.length);
5203
+ /** Only canonical joined inputs can require restoration from an earlier Attempt. */
5204
+ let joinBacklog = joinedInputEnvelopes.size === 0 ? [] : void 0;
5205
+ /** Joined inputs already handed to the engine during THIS Attempt (never re-deliver). */
5206
+ const deliveredJoinInputs = /* @__PURE__ */ new Set();
5207
+ const encodedParamsByCallId = /* @__PURE__ */ new Map();
5208
+ const declaredNamesByCallId = /* @__PURE__ */ new Map();
5209
+ const subagentState = subagentRecordsOf(records, runId);
5210
+ const declaredToolIds = new Set(subagentState.declaredNames.keys());
5211
+ if (declaredToolIds.size > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
5212
+ for (const [callId, name] of subagentState.declaredNames) declaredNamesByCallId.set(callId, name);
5213
+ if (pending !== void 0) for (const call of pending.calls) {
5214
+ encodedParamsByCallId.set(call.id, call.params);
5215
+ declaredNamesByCallId.set(call.id, call.name);
5283
5216
  }
5284
- if (!inserted && insertWhenAbsent) projected.push(...instructions);
5285
- return {
5286
- messages: projected,
5287
- prefixLength: (length) => lengths[length] ?? projected.length
5288
- };
5289
- };
5290
- const resumeContext = { prepare: ({ source }) => Effect.sync(() => {
5291
- const prefix = journal.committedTurns === 0 && priorContext !== void 0 ? priorContext.prompt.content.slice(priorContext.priorHistoryLength) : [];
5292
- const priorRunPrefixLength = journal.committedTurns === 0 ? resumeProjection.prompt.content.length : resumeProjection.historyBefore.content.length;
5293
- const view = instructionView(prefix.length === 0 ? resumeProjection.prompt.content : [...resumeProjection.prompt.content, ...prefix], initialInstructions, true, priorRunPrefixLength);
5294
- return {
5295
- prompt: Prompt.fromMessages([...view.messages, ...source.content.slice(initialHistoryLength)]),
5296
- priorRunPrefixLength: view.prefixLength(priorRunPrefixLength)
5297
- };
5298
- }) };
5299
- const externalContext = runContextPreparation.hook;
5300
- const needsContextReplay = priorContext !== void 0 || journal.committedTurns > 0;
5301
- const preparedContext = externalContext === void 0 ? needsContextReplay ? resumeContext : void 0 : { prepare: (request) => (needsContextReplay ? resumeContext.prepare(request) : Effect.succeed({
5302
- prompt: request.source,
5303
- priorRunPrefixLength: journal.historyBefore.content.length
5304
- })).pipe(Effect.flatMap(({ prompt, priorRunPrefixLength }) => externalContext.prepare({
5305
- ...request,
5306
- source: prompt,
5307
- priorRunPrefixLength
5308
- })), Effect.map((prepared) => {
5309
- if (prepared.rollover === void 0 || !knownIds.has(compactionRecordId(runId, request.turn, "rollover"))) return prepared;
5310
- const { rollover: _, ...retained } = prepared;
5311
- return retained;
5312
- })) };
5313
- const durability = {
5314
- toolResultMaxBytes: MAX_PERSISTED_JSON_BYTES,
5315
- checkpoint,
5316
- initialize: ({ initialHistory, priorHistoryLength }) => recordHalt(Effect.gen(function* () {
5317
- initialHistoryLength = initialHistory.content.length;
5318
- initialInstructions = initialHistory.content.slice(priorHistoryLength).filter((message) => message.role === "system");
5319
- if (priorContext !== void 0) return;
5320
- const recordId = decodeRecordIdSync(JSON.stringify(["run-context@1", runId]));
5321
- const prompt = yield* Schema.encodeEffect(Prompt.Prompt)(Prompt.fromMessages(initialHistory.content.slice(priorHistoryLength))).pipe(Effect.flatMap(decodePersisted), Effect.mapError((cause) => RunJournalError.make({
5322
- message: "Original Run context exceeds persistence bounds",
5323
- cause
5324
- })));
5325
- const history = Prompt.fromMessages(initialHistory.content.slice(0, priorHistoryLength));
5326
- const historyDigest = yield* withCrypto(digestPromptHistory(history, initialJournal?.history));
5327
- const retained = yield* Effect.forEach([...historyEvidence.values()].filter((entry) => entry.sequence < journal.historyFrom).sort((left, right) => left.sequence - right.sequence), (entry) => Effect.gen(function* () {
5328
- const full = yield* getRecord({
5329
- threadId: ctx.threadId,
5330
- recordId: entry.record.recordId
5331
- });
5332
- if (Option.isNone(full) || full.value.sequence !== entry.sequence) return yield* RunJournalError.make({ message: "Retained history has no exact canonical fact" });
5333
- return {
5334
- ...yield* withCrypto(reference(full.value.record)),
5335
- sequence: entry.sequence
5336
- };
5337
- }).pipe(Effect.provideService(ThreadReader, reader)));
5338
- const payload = yield* RunContextRecorded.makeEffect({
5339
- version: 1,
5340
- runId,
5341
- runScopedInput: prompt,
5342
- historyFrom: journal.historyFrom,
5343
- historyThrough: CanonicalSequence.make(originalInput.sequence - 1),
5344
- retained,
5345
- historyDigest,
5346
- priorHistoryLength,
5347
- ...journal.contextWindowId === void 0 ? {} : { contextWindowId: journal.contextWindowId }
5348
- }).pipe(Effect.mapError((cause) => RunJournalError.make({
5349
- message: "Original Run context mapping exceeds its bounds",
5217
+ let resumeLeadingMessages;
5218
+ let resumeResponseMessages;
5219
+ if (pending !== void 0) {
5220
+ const pendingMessages = yield* decodePrompt(pending.messages).pipe(Effect.mapError((cause) => RunJournalError.make({
5221
+ message: "Pending ModelResponseRecorded messages are not Schema-encoded Prompt messages",
5350
5222
  cause
5351
5223
  })));
5352
- yield* (yield* CurrentRunStart).commit(yield* makeEnvelope(recordId, payload));
5353
- knownIds.add(runStartedRecordId(runId));
5354
- knownIds.add(recordId);
5355
- historyEvidence.clear();
5356
- projectedJournal = void 0;
5357
- })),
5358
- commitModelRestart: (restart) => recordHalt(Effect.gen(function* () {
5359
- if (knownIds.has(modelResponseRecordId(runId, restart.turn))) return yield* RunJournalError.make({ message: "Cannot restart a canonical model response" });
5360
- const recordId = decodeRecordIdSync(`model-aborted:${runId}:${restart.restart}`);
5361
- const record = yield* makeEnvelope(recordId, ModelCallAborted.make({
5362
- runId,
5363
- ...restart,
5364
- reason: "joined-input",
5365
- modelUsage: usageForCommit(restart.turn)?.modelUsage ?? [],
5366
- unobservedModelCalls: unobservedForCommit(restart.turn)
5367
- }));
5224
+ const firstAssistant = pendingMessages.content.findIndex((message) => message.role === "assistant");
5225
+ if (firstAssistant > 0) resumeLeadingMessages = Prompt.fromMessages(pendingMessages.content.slice(0, firstAssistant).filter((message) => message.role !== "system"));
5226
+ if (firstAssistant >= 0) resumeResponseMessages = Prompt.fromMessages(pendingMessages.content.slice(firstAssistant));
5227
+ }
5228
+ const initialDispatchProofTurns = new Set(initialDispatchBlockedTurns(records, runId));
5229
+ let currentToolTurn = pending === void 0 ? void 0 : {
5230
+ turn: pending.turn,
5231
+ turnId: pending.turnId
5232
+ };
5233
+ const haltRef = yield* Ref.make(void 0);
5234
+ const yieldSignal = yield* Deferred.make();
5235
+ const recordHalt = (effect) => effect.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), Effect.catchCause((cause) => Effect.failCause(Cause.map(cause, (failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? failure.cause : new CoordinatorHalt(failure)))));
5236
+ const checkpoint = recordHalt(Effect.gen(function* () {
5237
+ const failure = yield* Ref.get(haltRef);
5238
+ if (failure !== void 0) return yield* failure;
5239
+ const progress = progressWriters.get(ctx);
5240
+ if (progress !== void 0) yield* progress.check(runId).pipe(Effect.provideService(CurrentRunWriter, ctx));
5241
+ }));
5242
+ const responseGate = yield* Semaphore.make(1);
5243
+ let deferredResponse;
5244
+ const acceptResponseDeclarations = (batch) => {
5245
+ for (const record of batch.records) {
5246
+ if (record.payload._tag !== "ModelResponseRecorded") continue;
5247
+ for (const call of record.payload.toolOperations) {
5248
+ declaredToolIds.add(call.toolCallId);
5249
+ declaredNamesByCallId.set(call.toolCallId, call.toolName);
5250
+ }
5251
+ }
5252
+ };
5253
+ const promoteResponse = Effect.gen(function* () {
5254
+ const halted = yield* Ref.get(haltRef);
5255
+ if (halted !== void 0) return yield* halted;
5256
+ const deferred = deferredResponse;
5257
+ if (deferred === void 0) return;
5258
+ const record = deferred.batch.records[0];
5259
+ if (record?.payload._tag !== "ModelResponseRecorded") return yield* RunJournalError.make({ message: "Deferred Turn has no owned response" });
5260
+ const calls = yield* declaredToolCalls(record.payload.messages);
5368
5261
  const batch = CanonicalBatch.make({
5369
- batchId: decodeBatchIdSync(recordId),
5370
- producerId: config.producerId,
5371
- records: [record]
5262
+ ...deferred.batch,
5263
+ batchId: turnResponseBatchId(runId, deferred.turn)
5372
5264
  });
5373
5265
  yield* appendBatch(ctx, batch);
5266
+ acceptResponseDeclarations(batch);
5267
+ for (const call of calls.application) encodedParamsByCallId.set(call.id, call.params);
5374
5268
  recordCommittedUsage(batch);
5375
- knownIds.add(recordId);
5376
- })),
5377
- reservePolicyUsage: (usage) => recordHalt(Effect.gen(function* () {
5378
- yield* flushDeferredResponse;
5379
- const recordId = decodeRecordIdSync(`policy:${runId}:${usage.programmaticToolCalls}:${usage.finalizationUsed}`);
5380
- if (knownIds.has(recordId)) return;
5381
- const record = yield* makeEnvelope(recordId, RunPolicyUsageReserved.make({
5382
- runId,
5383
- ...usage
5384
- }));
5385
- yield* hit("policy:before-reservation-append");
5386
- yield* appendBatch(ctx, CanonicalBatch.make({
5387
- batchId: decodeBatchIdSync(recordId),
5388
- producerId: config.producerId,
5389
- records: [record]
5390
- }));
5391
- knownIds.add(recordId);
5392
- yield* hit("policy:after-reservation-append");
5393
- })),
5394
- commitTurn: (commit) => recordHalt(Effect.gen(function* () {
5395
- const halted = yield* Ref.get(haltRef);
5396
- if (halted !== void 0) return yield* halted;
5397
- if (deferredResponse !== void 0 && (deferredResponse.turn !== commit.turn || deferredResponse.turnId !== commit.turnId)) return yield* RunJournalError.make({ message: "A new Turn preceded settlement of its deferred response" });
5398
- if (commit._tag === "Partial") yield* promoteResponse;
5399
- const deferred = deferredResponse;
5400
- if (commit._tag === "Response" && deferred !== void 0) return yield* RunJournalError.make({ message: "Turn response was already deferred" });
5401
- const responseId = modelResponseRecordId(runId, commit.turn);
5402
- const suppliedResponse = commit._tag === "Partial" ? void 0 : commit.response;
5403
- const response = knownIds.has(responseId) || deferred !== void 0 ? void 0 : suppliedResponse;
5404
- if (suppliedResponse !== void 0) currentToolTurn = {
5405
- turn: commit.turn,
5406
- turnId: commit.turnId
5407
- };
5408
- if (commit._tag === "Response" && response === void 0) return "committed";
5409
- const toolOperations = [];
5410
- const responseToolIds = /* @__PURE__ */ new Set();
5411
- for (const call of response?.calls ?? []) {
5412
- if (declaredToolIds.has(call.toolCallId) || responseToolIds.has(call.toolCallId)) return yield* RunJournalError.make({ message: "Tool Call identity is reused within a Run" });
5413
- if (declaredToolIds.size + responseToolIds.size + 1 > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
5414
- const replay = currentContracts[call.toolName];
5415
- if (replay === void 0) return yield* RunJournalError.make({ message: "Canonical Tool declaration has no original operation contract" });
5416
- toolOperations.push(ToolOperation.make({
5417
- toolCallId: call.toolCallId,
5418
- toolName: call.toolName,
5419
- executionClass: call.executionClass,
5420
- executionKind: call.executionKind,
5421
- replay
5422
- }));
5423
- responseToolIds.add(call.toolCallId);
5269
+ for (const entry of batch.records) knownIds.add(entry.recordId);
5270
+ deferredResponse = void 0;
5271
+ yield* hit("turn:after-response-append");
5272
+ });
5273
+ const flushDeferredResponse = promoteResponse.pipe(Effect.tapError((failure) => failure instanceof ThreadStoreError && failure.cause instanceof AgentPersistenceCapacityError ? Effect.void : Ref.set(haltRef, failure)), responseGate.withPermits(1));
5274
+ let initialHistoryLength = 0;
5275
+ let initialInstructions = [];
5276
+ const completionState = {};
5277
+ const turnCounter = yield* Ref.make(journal.committedTurns + (journal.policyUsage.modelRestarts ?? 0));
5278
+ const idGenerator = {
5279
+ nextThreadId: Effect.succeed(submission.threadId),
5280
+ nextRunId: Effect.succeed(runId),
5281
+ nextTurnId: Ref.modify(turnCounter, (turn) => [turnIdForRun(runId, turn + 1), turn + 1])
5282
+ };
5283
+ const instructionView = (messages, instructions, insertWhenAbsent, priorRunPrefixLength) => {
5284
+ const projected = [];
5285
+ const lengths = [0];
5286
+ let inserted = false;
5287
+ for (const [index, message] of messages.entries()) {
5288
+ if (index >= priorRunPrefixLength && message.role === "system") {
5289
+ if (!inserted) projected.push(...instructions);
5290
+ inserted = true;
5291
+ } else projected.push(message);
5292
+ lengths.push(projected.length);
5424
5293
  }
5425
- const toolResults = commit._tag === "Response" ? [] : commit.results.filter((result) => !knownIds.has(toolCallSettledRecordId(runId, commit.turn, result.toolCallId)));
5426
- let runCompletion;
5427
- if (commit._tag === "Settled" && commit.completion !== void 0) {
5428
- const completion = commit.completion;
5429
- const output = yield* decodePersisted(completion.output).pipe(Effect.mapError((cause) => LedgerError.make({
5430
- operation: "recordCompleted",
5431
- message: "Run output exceeds canonical persistence bounds",
5294
+ if (!inserted && insertWhenAbsent) projected.push(...instructions);
5295
+ return {
5296
+ messages: projected,
5297
+ prefixLength: (length) => lengths[length] ?? projected.length
5298
+ };
5299
+ };
5300
+ const resumeContext = { prepare: ({ source }) => Effect.sync(() => {
5301
+ const prefix = journal.committedTurns === 0 && priorContext !== void 0 ? priorContext.prompt.content.slice(priorContext.priorHistoryLength) : [];
5302
+ const priorRunPrefixLength = journal.committedTurns === 0 ? resumeProjection.prompt.content.length : resumeProjection.historyBefore.content.length;
5303
+ const view = instructionView(prefix.length === 0 ? resumeProjection.prompt.content : [...resumeProjection.prompt.content, ...prefix], initialInstructions, true, priorRunPrefixLength);
5304
+ return {
5305
+ prompt: Prompt.fromMessages([...view.messages, ...source.content.slice(initialHistoryLength)]),
5306
+ priorRunPrefixLength: view.prefixLength(priorRunPrefixLength)
5307
+ };
5308
+ }) };
5309
+ const externalContext = runContextPreparation.hook;
5310
+ const needsContextReplay = priorContext !== void 0 || journal.committedTurns > 0;
5311
+ const preparedContext = externalContext === void 0 ? needsContextReplay ? resumeContext : void 0 : { prepare: (request) => (needsContextReplay ? resumeContext.prepare(request) : Effect.succeed({
5312
+ prompt: request.source,
5313
+ priorRunPrefixLength: journal.historyBefore.content.length
5314
+ })).pipe(Effect.flatMap(({ prompt, priorRunPrefixLength }) => externalContext.prepare({
5315
+ ...request,
5316
+ source: prompt,
5317
+ priorRunPrefixLength
5318
+ })), Effect.map((prepared) => {
5319
+ if (prepared.rollover === void 0 || !knownIds.has(compactionRecordId(runId, request.turn, "rollover"))) return prepared;
5320
+ const { rollover: _, ...retained } = prepared;
5321
+ return retained;
5322
+ })) };
5323
+ const durability = {
5324
+ toolResultMaxBytes: MAX_PERSISTED_JSON_BYTES,
5325
+ checkpoint,
5326
+ initialize: ({ initialHistory, priorHistoryLength }) => recordHalt(Effect.gen(function* () {
5327
+ initialHistoryLength = initialHistory.content.length;
5328
+ initialInstructions = initialHistory.content.slice(priorHistoryLength).filter((message) => message.role === "system");
5329
+ if (priorContext !== void 0) return;
5330
+ const recordId = decodeRecordIdSync(JSON.stringify(["run-context@1", runId]));
5331
+ const prompt = yield* Schema.encodeEffect(Prompt.Prompt)(Prompt.fromMessages(initialHistory.content.slice(priorHistoryLength))).pipe(Effect.flatMap(decodePersisted), Effect.mapError((cause) => RunJournalError.make({
5332
+ message: "Original Run context exceeds persistence bounds",
5432
5333
  cause
5433
5334
  })));
5434
- if (completion.finishReason === "budget-exhausted" && completion.runDisposition !== void 0) return yield* LedgerError.make({
5435
- operation: "recordCompleted",
5436
- message: "A budget-exhausted Run cannot declare an application run disposition"
5437
- });
5438
- const runDisposition = completion.runDisposition === void 0 ? void 0 : yield* decodePersisted(completion.runDisposition).pipe(Effect.mapError((cause) => LedgerError.make({
5439
- operation: "recordCompleted",
5440
- message: "Run disposition exceeds canonical persistence bounds",
5335
+ const history = Prompt.fromMessages(initialHistory.content.slice(0, priorHistoryLength));
5336
+ const historyDigest = yield* withCrypto(digestPromptHistory(history, initialJournal?.history));
5337
+ const retained = yield* Effect.forEach([...historyEvidence.values()].filter((entry) => entry.sequence < journal.historyFrom).sort((left, right) => left.sequence - right.sequence), (entry) => Effect.gen(function* () {
5338
+ const full = yield* getRecord({
5339
+ threadId: ctx.threadId,
5340
+ recordId: entry.record.recordId
5341
+ });
5342
+ if (Option.isNone(full) || full.value.sequence !== entry.sequence) return yield* RunJournalError.make({ message: "Retained history has no exact canonical fact" });
5343
+ return {
5344
+ ...yield* withCrypto(reference(full.value.record)),
5345
+ sequence: entry.sequence
5346
+ };
5347
+ }).pipe(Effect.provideService(ThreadReader, reader)));
5348
+ const payload = yield* RunContextRecorded.makeEffect({
5349
+ version: 1,
5350
+ runId,
5351
+ runScopedInput: prompt,
5352
+ historyFrom: journal.historyFrom,
5353
+ historyThrough: CanonicalSequence.make(originalInput.sequence - 1),
5354
+ retained,
5355
+ historyDigest,
5356
+ priorHistoryLength,
5357
+ ...journal.contextWindowId === void 0 ? {} : { contextWindowId: journal.contextWindowId }
5358
+ }).pipe(Effect.mapError((cause) => RunJournalError.make({
5359
+ message: "Original Run context mapping exceeds its bounds",
5441
5360
  cause
5442
5361
  })));
5443
- runCompletion = {
5444
- output,
5445
- ...runDisposition === void 0 ? {} : { runDisposition },
5446
- ...completion.finishReason === "budget-exhausted" ? {
5447
- finishReason: completion.finishReason,
5448
- ...completion.exhausted === void 0 ? {} : { exhausted: completion.exhausted }
5449
- } : {}
5450
- };
5451
- }
5452
- if (response === void 0 && deferred === void 0 && toolResults.length === 0 && runCompletion === void 0) return "committed";
5453
- if (response === void 0 && deferred === void 0 && !knownIds.has(responseId)) return yield* RunJournalError.make({ message: "Tool results or completion preceded the canonical response" });
5454
- const input = {
5455
- toolResultMaxBytes: Math.min(agent.definition.policy.toolResultBounds.maxBytes, MAX_PERSISTED_JSON_BYTES),
5456
- toolSelectionMaxBytes: utf8ByteLength(JSON.stringify({ toolSelection: { toolNames: Object.keys(currentContracts) } })),
5457
- runId,
5458
- turn: commit.turn,
5459
- turnId: commit.turnId,
5460
- responseMessages: response?.messages ?? [],
5461
- toolResults,
5462
- toolOperations,
5463
- toolExposure: response?.toolExposure,
5464
- toolParameterRejections: response?.toolParameterRejections,
5465
- runScopedPrefixLength: response?.runScopedPrefixLength,
5466
- producerId: config.producerId,
5467
- deploymentId: config.deploymentId,
5468
- createdAt: yield* nowUtc,
5469
- runCompletion,
5470
- usage: usageForCommit(commit.turn),
5471
- unobservedModelCalls: unobservedForCommit(commit.turn)
5472
- };
5473
- if (commit._tag === "Partial") {
5474
- for (const result of toolResults) {
5475
- const batch = yield* withCrypto(turnResultsBatch({
5476
- ...input,
5477
- toolResults: [result]
5478
- }));
5479
- yield* appendBatch(ctx, CanonicalBatch.make({
5480
- ...batch,
5481
- batchId: toolCallResultBatchId(runId, commit.turn, result.toolCallId)
5482
- }));
5483
- for (const record of batch.records) knownIds.add(record.recordId);
5484
- yield* hit("subagent:after-sibling-settle");
5485
- }
5486
- return "committed";
5487
- }
5488
- if (commit._tag === "Response" && commit.defer === true) {
5489
- if (toolOperations.length === 0 || toolOperations.some((call) => call.executionClass !== "readonly" || call.executionKind !== "ordinary")) return yield* RunJournalError.make({ message: "Only ordinary readonly Tool responses may be deferred" });
5490
- const candidate = {
5491
- turn: commit.turn,
5492
- turnId: commit.turnId,
5493
- batch: yield* withCrypto(turnCanonicalBatch({
5494
- ...input,
5495
- toolParameterRejections: input.toolParameterRejections?.map((rejection) => ({
5496
- ...rejection,
5497
- parameters: copyJson(rejection.parameters),
5498
- error: {
5499
- ...rejection.error,
5500
- reason: { ...rejection.error.reason }
5501
- }
5502
- })),
5503
- toolExposure: input.toolExposure === void 0 ? void 0 : Snapshot.make({
5504
- exposedToolNames: [...input.toolExposure.exposedToolNames],
5505
- ...input.toolExposure.selection === void 0 ? {} : { selection: Selection.make({ toolNames: [...input.toolExposure.selection.toolNames] }) }
5506
- }),
5507
- usage: input.usage === void 0 ? void 0 : {
5508
- ...input.usage,
5509
- modelUsage: input.usage.modelUsage?.map((usage) => ModelCallUsage.make({
5510
- ...usage,
5511
- ...usage.response === void 0 ? {} : { response: ModelResponseIdentity.make({ ...usage.response }) },
5512
- inputTokens: InputTokenUsage.make({ ...usage.inputTokens }),
5513
- outputTokens: OutputTokenUsage.make({ ...usage.outputTokens })
5514
- }))
5515
- }
5516
- }))
5517
- };
5518
- const progress = progressWriters.get(ctx);
5519
- if (progress === void 0) return yield* ThreadStoreError.make({
5520
- operation: "reserve readonly dispatch",
5521
- message: "Dispatch has no scoped progress writer"
5522
- });
5523
- const batch = yield* progress.defer(candidate.batch).pipe(Effect.provideService(CurrentRunWriter, ctx));
5524
- deferredResponse = {
5525
- ...candidate,
5526
- batch
5527
- };
5528
- return "deferred";
5529
- }
5530
- let batch;
5531
- if (deferred === void 0) batch = yield* withCrypto(commit._tag === "Response" ? turnResponseBatch(input) : response === void 0 ? turnResultsBatch(input) : turnCanonicalBatch(input));
5532
- else if (toolResults.length === 0 && runCompletion === void 0) batch = deferred.batch;
5533
- else {
5534
- const results = yield* withCrypto(turnResultsBatch(input));
5535
- batch = CanonicalBatch.make({
5536
- ...deferred.batch,
5537
- records: [...deferred.batch.records, ...results.records]
5538
- });
5539
- }
5540
- yield* appendBatch(ctx, batch);
5541
- for (const call of response?.calls ?? []) {
5542
- declaredToolIds.add(call.toolCallId);
5543
- encodedParamsByCallId.set(call.toolCallId, call.parameters);
5544
- declaredNamesByCallId.set(call.toolCallId, call.toolName);
5545
- }
5546
- if (deferred !== void 0) {
5547
- acceptResponseDeclarations(batch);
5548
- deferredResponse = void 0;
5549
- }
5550
- if (commit._tag === "Response") initialDispatchProofTurns.add(commit.turn);
5551
- recordCommittedUsage(batch);
5552
- for (const record of batch.records) knownIds.add(record.recordId);
5553
- if (runCompletion !== void 0) completionState.committed = runCompletion;
5554
- yield* hit(commit._tag === "Response" ? "turn:after-response-append" : response === void 0 && deferred === void 0 ? "turn:after-results-append" : "turn:after-canonical-append");
5555
- return "committed";
5556
- }).pipe(responseGate.withPermits(1))),
5557
- checkToolDispatch: recordHalt(Effect.gen(function* () {
5558
- if (currentToolTurn === void 0) return yield* RunJournalError.make({ message: "Tool dispatch preceded its canonical response" });
5559
- yield* hit("tools:before-dispatch-fence");
5560
- yield* ctx.checkActive;
5561
- initialDispatchProofTurns.delete(currentToolTurn.turn);
5562
- yield* hit("tools:after-dispatch-fence");
5563
- })),
5564
- step: {
5565
- lookup: (key) => recordHalt(Effect.gen(function* () {
5566
- yield* flushDeferredResponse;
5567
- const output = stepOutputs.get(toolStepSettledRecordId(runId, key.toolCallId, key.stepName));
5568
- return output === void 0 ? Option.none() : Option.some({ encodedOutput: output });
5362
+ yield* (yield* CurrentRunStart).commit(yield* makeEnvelope(recordId, payload));
5363
+ knownIds.add(runStartedRecordId(runId));
5364
+ knownIds.add(recordId);
5365
+ historyEvidence.clear();
5366
+ projectedJournal = void 0;
5569
5367
  })),
5570
- reserve: (key) => recordHalt(Effect.gen(function* () {
5571
- yield* flushDeferredResponse;
5572
- const recordId = toolStepSettledRecordId(runId, key.toolCallId, key.stepName);
5573
- const template = yield* makeEnvelope(recordId, yield* ToolStepSettled.makeEffect({
5368
+ commitModelRestart: (restart) => recordHalt(Effect.gen(function* () {
5369
+ if (knownIds.has(modelResponseRecordId(runId, restart.turn))) return yield* RunJournalError.make({ message: "Cannot restart a canonical model response" });
5370
+ const recordId = decodeRecordIdSync(`model-aborted:${runId}:${restart.restart}`);
5371
+ const record = yield* makeEnvelope(recordId, ModelCallAborted.make({
5574
5372
  runId,
5575
- toolCallId: key.toolCallId,
5576
- stepName: key.stepName,
5577
- output: null,
5578
- outputDigest: yield* withCrypto(digestJson(null))
5579
- }).pipe(Effect.mapError(() => ThreadStoreError.make({
5580
- operation: "reserve Step dispatch",
5581
- message: "Durable Step identity exceeds canonical persistence bounds",
5582
- cause: AgentPersistenceCapacityError.make({ message: "Durable Step identity exceeds canonical persistence bounds" })
5583
- }))));
5584
- const progress = progressWriters.get(ctx);
5585
- if (progress === void 0) return yield* ThreadStoreError.make({
5586
- operation: "reserve Step dispatch",
5587
- message: "Dispatch has no scoped progress writer"
5588
- });
5589
- return yield* progress.reserve(runId, CanonicalBatch.make({
5373
+ ...restart,
5374
+ reason: "joined-input",
5375
+ modelUsage: usageForCommit(restart.turn)?.modelUsage ?? [],
5376
+ unobservedModelCalls: unobservedForCommit(restart.turn)
5377
+ }));
5378
+ const batch = CanonicalBatch.make({
5590
5379
  batchId: decodeBatchIdSync(recordId),
5591
5380
  producerId: config.producerId,
5592
- records: [template]
5593
- }), canonicalRecordBytes(template) + MAX_PERSISTED_JSON_BYTES + MAX_RUN_CONTINUATION_BYTES).pipe(Effect.provideService(CurrentRunWriter, ctx));
5381
+ records: [record]
5382
+ });
5383
+ yield* appendBatch(ctx, batch);
5384
+ recordCommittedUsage(batch);
5385
+ knownIds.add(recordId);
5594
5386
  })),
5595
- commit: (key, encodedOutput) => recordHalt(Effect.gen(function* () {
5387
+ reservePolicyUsage: (usage) => recordHalt(Effect.gen(function* () {
5596
5388
  yield* flushDeferredResponse;
5597
- const recordId = toolStepSettledRecordId(runId, key.toolCallId, key.stepName);
5389
+ const recordId = decodeRecordIdSync(`policy:${runId}:${usage.programmaticToolCalls}:${usage.finalizationUsed}`);
5598
5390
  if (knownIds.has(recordId)) return;
5599
- const output = yield* decodePersisted(encodedOutput).pipe(Effect.mapError(() => ThreadStoreError.make({
5600
- operation: "commit Step result",
5601
- message: "Durable Step output exceeds canonical persistence bounds",
5602
- cause: AgentPersistenceCapacityError.make({ message: "Durable Step output exceeds canonical persistence bounds" })
5603
- })));
5604
- const outputDigest = yield* withCrypto(digestJson(output));
5605
- const envelope = yield* makeEnvelope(recordId, ToolStepSettled.make({
5391
+ const record = yield* makeEnvelope(recordId, RunPolicyUsageReserved.make({
5606
5392
  runId,
5607
- toolCallId: key.toolCallId,
5608
- stepName: key.stepName,
5609
- output,
5610
- outputDigest
5393
+ ...usage
5611
5394
  }));
5395
+ yield* hit("policy:before-reservation-append");
5612
5396
  yield* appendBatch(ctx, CanonicalBatch.make({
5613
- batchId: toolStepSettledBatchId(runId, key.toolCallId, key.stepName),
5397
+ batchId: decodeBatchIdSync(recordId),
5614
5398
  producerId: config.producerId,
5615
- records: [envelope]
5399
+ records: [record]
5616
5400
  }));
5617
5401
  knownIds.add(recordId);
5618
- stepOutputs.set(recordId, output);
5619
- yield* hit("step:after-step-append");
5620
- }))
5621
- },
5622
- noteTurnUsage: (usage) => Effect.sync(() => {
5623
- const key = usage.turn;
5624
- const prior = stagedUsage.get(key);
5625
- stagedUsage.set(key, {
5626
- inputTokens: (prior?.inputTokens ?? 0) + usage.usage.inputTokens.total,
5627
- outputTokens: (prior?.outputTokens ?? 0) + usage.usage.outputTokens.total,
5628
- costMicrousd: (prior?.costMicrousd ?? 0) + usage.usage.costMicrousd,
5629
- modelUsage: [...prior?.modelUsage ?? [], usage.usage]
5630
- });
5631
- progressWriters.get(ctx)?.stageUsage(runId, terminalUsageCharge(uncommittedModelUsage()));
5632
- }),
5633
- commitCompaction: (commit) => Effect.gen(function* () {
5634
- const canonicalTurn = commit.turn;
5635
- const recordId = compactionRecordId(runId, canonicalTurn, commit.kind);
5636
- if (knownIds.has(recordId)) return yield* CompactionError.make({ message: "Compaction is already committed for this Turn and kind" });
5637
- let sourceJournal = journal;
5638
- let sourceBoundaries = boundaries;
5639
- if (initialJournal !== void 0) {
5640
- initialJournal.cacheable = false;
5641
- initialJournal.history = void 0;
5642
- }
5643
- if (commit.kind !== "summarize" || initialJournal?.prefix !== void 0) {
5644
- const tail = yield* ctx.tail;
5645
- const source = initialJournal === void 0 ? canonical : Stream.fromIterable(yield* recordHalt(readInitialJournal(initialJournal.original, initialJournal.suffix)));
5646
- sourceBoundaries = [];
5647
- sourceJournal = yield* recordHalt(projectRunJournalStream(Stream.concat(source, Stream.fromIterable(yield* recordHalt(selectedRange(ctx.threadId, [submissionId], tail.sequence, canonicalThrough)))).pipe(Stream.filter((envelope) => envelope.record.payload._tag !== "CompactionCreated" || envelope.sequence <= canonicalThrough)), runId, (boundary) => sourceBoundaries.push(boundary), priorContext));
5648
- }
5649
- const coverable = sourceBoundaries.filter((boundary) => commit.kind !== "summarize" || ownerFirstSequence === void 0 || boundary.sequence < ownerFirstSequence);
5650
- if (coverable.length === 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Durable rollover requires complete canonical records" : "Durable compaction requires eligible canonical records" });
5651
- const comparisonView = instructionView(sourceJournal.prompt.content, initialInstructions, false, sourceJournal.historyBefore.content.length);
5652
- let matchingPrefix = 0;
5653
- let requiredThrough = 0;
5654
- const comparisonLimit = Math.min(comparisonView.messages.length, commit.through);
5655
- for (let index = 0; index < commit.through; index += 1) {
5656
- const message = commit.source.content[index];
5657
- if (message !== void 0 && (commit.kind === "clear-tool-results" ? message.role === "tool" : message.role !== "system")) requiredThrough = index + 1;
5658
- if (index >= comparisonLimit || index !== matchingPrefix || message === void 0) continue;
5659
- const canonicalMessage = comparisonView.messages[index];
5660
- if (canonicalMessage === void 0) continue;
5661
- const encode = (entry) => encodeCompactionMessageJson(entry).pipe(Effect.flatMap(decodeCompactionMessageJson), Effect.map(canonicalJson), Effect.mapError((cause) => CompactionError.make({
5662
- message: "Could not encode the canonical compaction prefix",
5402
+ yield* hit("policy:after-reservation-append");
5403
+ })),
5404
+ commitTurn: (commit) => recordHalt(Effect.gen(function* () {
5405
+ const halted = yield* Ref.get(haltRef);
5406
+ if (halted !== void 0) return yield* halted;
5407
+ if (deferredResponse !== void 0 && (deferredResponse.turn !== commit.turn || deferredResponse.turnId !== commit.turnId)) return yield* RunJournalError.make({ message: "A new Turn preceded settlement of its deferred response" });
5408
+ if (commit._tag === "Partial") yield* promoteResponse;
5409
+ const deferred = deferredResponse;
5410
+ if (commit._tag === "Response" && deferred !== void 0) return yield* RunJournalError.make({ message: "Turn response was already deferred" });
5411
+ const responseId = modelResponseRecordId(runId, commit.turn);
5412
+ const suppliedResponse = commit._tag === "Partial" ? void 0 : commit.response;
5413
+ const response = knownIds.has(responseId) || deferred !== void 0 ? void 0 : suppliedResponse;
5414
+ if (suppliedResponse !== void 0) currentToolTurn = {
5415
+ turn: commit.turn,
5416
+ turnId: commit.turnId
5417
+ };
5418
+ if (commit._tag === "Response" && response === void 0) return "committed";
5419
+ const toolOperations = [];
5420
+ const responseToolIds = /* @__PURE__ */ new Set();
5421
+ for (const call of response?.calls ?? []) {
5422
+ if (declaredToolIds.has(call.toolCallId) || responseToolIds.has(call.toolCallId)) return yield* RunJournalError.make({ message: "Tool Call identity is reused within a Run" });
5423
+ if (declaredToolIds.size + responseToolIds.size + 1 > 4096) return yield* RunJournalError.make({ message: `Run exceeds the ${MAX_RUN_TOOL_CALL_IDENTITIES} Tool Call identity limit` });
5424
+ const replay = currentContracts[call.toolName];
5425
+ if (replay === void 0) return yield* RunJournalError.make({ message: "Canonical Tool declaration has no original operation contract" });
5426
+ toolOperations.push(ToolOperation.make({
5427
+ toolCallId: call.toolCallId,
5428
+ toolName: call.toolName,
5429
+ executionClass: call.executionClass,
5430
+ executionKind: call.executionKind,
5431
+ replay
5432
+ }));
5433
+ responseToolIds.add(call.toolCallId);
5434
+ }
5435
+ const toolResults = commit._tag === "Response" ? [] : commit.results.filter((result) => !knownIds.has(toolCallSettledRecordId(runId, commit.turn, result.toolCallId)));
5436
+ let runCompletion;
5437
+ if (commit._tag === "Settled" && commit.completion !== void 0) {
5438
+ const completion = commit.completion;
5439
+ const output = yield* decodePersisted(completion.output).pipe(Effect.mapError((cause) => LedgerError.make({
5440
+ operation: "recordCompleted",
5441
+ message: "Run output exceeds canonical persistence bounds",
5442
+ cause
5443
+ })));
5444
+ if (completion.finishReason === "budget-exhausted" && completion.runDisposition !== void 0) return yield* LedgerError.make({
5445
+ operation: "recordCompleted",
5446
+ message: "A budget-exhausted Run cannot declare an application run disposition"
5447
+ });
5448
+ const runDisposition = completion.runDisposition === void 0 ? void 0 : yield* decodePersisted(completion.runDisposition).pipe(Effect.mapError((cause) => LedgerError.make({
5449
+ operation: "recordCompleted",
5450
+ message: "Run disposition exceeds canonical persistence bounds",
5451
+ cause
5452
+ })));
5453
+ runCompletion = {
5454
+ output,
5455
+ ...runDisposition === void 0 ? {} : { runDisposition },
5456
+ ...completion.finishReason === "budget-exhausted" ? {
5457
+ finishReason: completion.finishReason,
5458
+ ...completion.exhausted === void 0 ? {} : { exhausted: completion.exhausted }
5459
+ } : {}
5460
+ };
5461
+ }
5462
+ if (response === void 0 && deferred === void 0 && toolResults.length === 0 && runCompletion === void 0) return "committed";
5463
+ if (response === void 0 && deferred === void 0 && !knownIds.has(responseId)) return yield* RunJournalError.make({ message: "Tool results or completion preceded the canonical response" });
5464
+ const input = {
5465
+ toolResultMaxBytes: Math.min(agent.definition.policy.toolResultBounds.maxBytes, MAX_PERSISTED_JSON_BYTES),
5466
+ toolSelectionMaxBytes: utf8ByteLength(JSON.stringify({ toolSelection: { toolNames: Object.keys(currentContracts) } })),
5467
+ runId,
5468
+ turn: commit.turn,
5469
+ turnId: commit.turnId,
5470
+ responseMessages: response?.messages ?? [],
5471
+ toolResults,
5472
+ toolOperations,
5473
+ toolExposure: response?.toolExposure,
5474
+ toolParameterRejections: response?.toolParameterRejections,
5475
+ runScopedPrefixLength: response?.runScopedPrefixLength,
5476
+ producerId: config.producerId,
5477
+ deploymentId: config.deploymentId,
5478
+ createdAt: yield* nowUtc,
5479
+ runCompletion,
5480
+ usage: usageForCommit(commit.turn),
5481
+ unobservedModelCalls: unobservedForCommit(commit.turn)
5482
+ };
5483
+ if (commit._tag === "Partial") {
5484
+ for (const result of toolResults) {
5485
+ const batch = yield* turnResultsBatch({
5486
+ ...input,
5487
+ toolResults: [result]
5488
+ });
5489
+ yield* appendBatch(ctx, CanonicalBatch.make({
5490
+ ...batch,
5491
+ batchId: toolCallResultBatchId(runId, commit.turn, result.toolCallId)
5492
+ }));
5493
+ for (const record of batch.records) knownIds.add(record.recordId);
5494
+ yield* hit("subagent:after-sibling-settle");
5495
+ }
5496
+ return "committed";
5497
+ }
5498
+ if (commit._tag === "Response" && commit.defer === true) {
5499
+ if (toolOperations.length === 0 || toolOperations.some((call) => call.executionClass !== "readonly" || call.executionKind !== "ordinary")) return yield* RunJournalError.make({ message: "Only ordinary readonly Tool responses may be deferred" });
5500
+ const candidate = {
5501
+ turn: commit.turn,
5502
+ turnId: commit.turnId,
5503
+ batch: yield* turnCanonicalBatch({
5504
+ ...input,
5505
+ toolParameterRejections: input.toolParameterRejections?.map((rejection) => ({
5506
+ ...rejection,
5507
+ parameters: copyJson(rejection.parameters),
5508
+ error: {
5509
+ ...rejection.error,
5510
+ reason: { ...rejection.error.reason }
5511
+ }
5512
+ })),
5513
+ toolExposure: input.toolExposure === void 0 ? void 0 : Snapshot.make({
5514
+ exposedToolNames: [...input.toolExposure.exposedToolNames],
5515
+ ...input.toolExposure.selection === void 0 ? {} : { selection: Selection.make({ toolNames: [...input.toolExposure.selection.toolNames] }) }
5516
+ }),
5517
+ usage: input.usage === void 0 ? void 0 : {
5518
+ ...input.usage,
5519
+ modelUsage: input.usage.modelUsage?.map((usage) => ModelCallUsage.make({
5520
+ ...usage,
5521
+ ...usage.response === void 0 ? {} : { response: ModelResponseIdentity.make({ ...usage.response }) },
5522
+ inputTokens: InputTokenUsage.make({ ...usage.inputTokens }),
5523
+ outputTokens: OutputTokenUsage.make({ ...usage.outputTokens })
5524
+ }))
5525
+ }
5526
+ })
5527
+ };
5528
+ const progress = progressWriters.get(ctx);
5529
+ if (progress === void 0) return yield* ThreadStoreError.make({
5530
+ operation: "reserve readonly dispatch",
5531
+ message: "Dispatch has no scoped progress writer"
5532
+ });
5533
+ const batch = yield* progress.defer(candidate.batch).pipe(Effect.provideService(CurrentRunWriter, ctx));
5534
+ deferredResponse = {
5535
+ ...candidate,
5536
+ batch
5537
+ };
5538
+ return "deferred";
5539
+ }
5540
+ let batch;
5541
+ if (deferred === void 0) batch = yield* commit._tag === "Response" ? turnResponseBatch(input) : response === void 0 ? turnResultsBatch(input) : turnCanonicalBatch(input);
5542
+ else if (toolResults.length === 0 && runCompletion === void 0) batch = deferred.batch;
5543
+ else {
5544
+ const results = yield* turnResultsBatch(input);
5545
+ batch = CanonicalBatch.make({
5546
+ ...deferred.batch,
5547
+ records: [...deferred.batch.records, ...results.records]
5548
+ });
5549
+ }
5550
+ yield* appendBatch(ctx, batch);
5551
+ for (const call of response?.calls ?? []) {
5552
+ declaredToolIds.add(call.toolCallId);
5553
+ encodedParamsByCallId.set(call.toolCallId, call.parameters);
5554
+ declaredNamesByCallId.set(call.toolCallId, call.toolName);
5555
+ }
5556
+ if (deferred !== void 0) {
5557
+ acceptResponseDeclarations(batch);
5558
+ deferredResponse = void 0;
5559
+ }
5560
+ if (commit._tag === "Response") initialDispatchProofTurns.add(commit.turn);
5561
+ recordCommittedUsage(batch);
5562
+ for (const record of batch.records) knownIds.add(record.recordId);
5563
+ if (runCompletion !== void 0) completionState.committed = runCompletion;
5564
+ yield* hit(commit._tag === "Response" ? "turn:after-response-append" : response === void 0 && deferred === void 0 ? "turn:after-results-append" : "turn:after-canonical-append");
5565
+ return "committed";
5566
+ }).pipe(responseGate.withPermits(1))),
5567
+ checkToolDispatch: recordHalt(Effect.gen(function* () {
5568
+ if (currentToolTurn === void 0) return yield* RunJournalError.make({ message: "Tool dispatch preceded its canonical response" });
5569
+ yield* hit("tools:before-dispatch-fence");
5570
+ yield* ctx.checkActive;
5571
+ initialDispatchProofTurns.delete(currentToolTurn.turn);
5572
+ yield* hit("tools:after-dispatch-fence");
5573
+ })),
5574
+ step: {
5575
+ lookup: (key) => recordHalt(Effect.gen(function* () {
5576
+ yield* flushDeferredResponse;
5577
+ const output = stepOutputs.get(toolStepSettledRecordId(runId, key.toolCallId, key.stepName));
5578
+ return output === void 0 ? Option.none() : Option.some({ encodedOutput: output });
5579
+ })),
5580
+ reserve: (key) => recordHalt(Effect.gen(function* () {
5581
+ yield* flushDeferredResponse;
5582
+ const recordId = toolStepSettledRecordId(runId, key.toolCallId, key.stepName);
5583
+ const template = yield* makeEnvelope(recordId, yield* ToolStepSettled.makeEffect({
5584
+ runId,
5585
+ toolCallId: key.toolCallId,
5586
+ stepName: key.stepName,
5587
+ output: null,
5588
+ outputDigest: yield* withCrypto(digestJson(null))
5589
+ }).pipe(Effect.mapError(() => ThreadStoreError.make({
5590
+ operation: "reserve Step dispatch",
5591
+ message: "Durable Step identity exceeds canonical persistence bounds",
5592
+ cause: AgentPersistenceCapacityError.make({ message: "Durable Step identity exceeds canonical persistence bounds" })
5593
+ }))));
5594
+ const progress = progressWriters.get(ctx);
5595
+ if (progress === void 0) return yield* ThreadStoreError.make({
5596
+ operation: "reserve Step dispatch",
5597
+ message: "Dispatch has no scoped progress writer"
5598
+ });
5599
+ return yield* progress.reserve(runId, CanonicalBatch.make({
5600
+ batchId: decodeBatchIdSync(recordId),
5601
+ producerId: config.producerId,
5602
+ records: [template]
5603
+ }), canonicalRecordBytes(template) + MAX_PERSISTED_JSON_BYTES + MAX_RUN_CONTINUATION_BYTES).pipe(Effect.provideService(CurrentRunWriter, ctx));
5604
+ })),
5605
+ commit: (key, encodedOutput) => recordHalt(Effect.gen(function* () {
5606
+ yield* flushDeferredResponse;
5607
+ const recordId = toolStepSettledRecordId(runId, key.toolCallId, key.stepName);
5608
+ if (knownIds.has(recordId)) return;
5609
+ const output = yield* decodePersisted(encodedOutput).pipe(Effect.mapError(() => ThreadStoreError.make({
5610
+ operation: "commit Step result",
5611
+ message: "Durable Step output exceeds canonical persistence bounds",
5612
+ cause: AgentPersistenceCapacityError.make({ message: "Durable Step output exceeds canonical persistence bounds" })
5613
+ })));
5614
+ const outputDigest = yield* withCrypto(digestJson(output));
5615
+ const envelope = yield* makeEnvelope(recordId, ToolStepSettled.make({
5616
+ runId,
5617
+ toolCallId: key.toolCallId,
5618
+ stepName: key.stepName,
5619
+ output,
5620
+ outputDigest
5621
+ }));
5622
+ yield* appendBatch(ctx, CanonicalBatch.make({
5623
+ batchId: toolStepSettledBatchId(runId, key.toolCallId, key.stepName),
5624
+ producerId: config.producerId,
5625
+ records: [envelope]
5626
+ }));
5627
+ knownIds.add(recordId);
5628
+ stepOutputs.set(recordId, output);
5629
+ yield* hit("step:after-step-append");
5630
+ }))
5631
+ },
5632
+ noteTurnUsage: (usage) => Effect.sync(() => {
5633
+ const key = usage.turn;
5634
+ const prior = stagedUsage.get(key);
5635
+ stagedUsage.set(key, {
5636
+ inputTokens: (prior?.inputTokens ?? 0) + usage.usage.inputTokens.total,
5637
+ outputTokens: (prior?.outputTokens ?? 0) + usage.usage.outputTokens.total,
5638
+ costMicrousd: (prior?.costMicrousd ?? 0) + usage.usage.costMicrousd,
5639
+ modelUsage: [...prior?.modelUsage ?? [], usage.usage]
5640
+ });
5641
+ progressWriters.get(ctx)?.stageUsage(runId, terminalUsageCharge(uncommittedModelUsage()));
5642
+ }),
5643
+ commitCompaction: Effect.fnUntraced(function* (commit) {
5644
+ const canonicalTurn = commit.turn;
5645
+ const recordId = compactionRecordId(runId, canonicalTurn, commit.kind);
5646
+ if (knownIds.has(recordId)) return yield* CompactionError.make({ message: "Compaction is already committed for this Turn and kind" });
5647
+ let sourceJournal = journal;
5648
+ let sourceBoundaries = boundaries;
5649
+ if (initialJournal !== void 0) {
5650
+ initialJournal.cacheable = false;
5651
+ initialJournal.history = void 0;
5652
+ }
5653
+ if (commit.kind !== "summarize" || initialJournal?.prefix !== void 0) {
5654
+ const tail = yield* ctx.tail;
5655
+ const source = initialJournal === void 0 ? canonical : Stream.fromIterable(yield* recordHalt(readInitialJournal(initialJournal.original, initialJournal.suffix)));
5656
+ sourceBoundaries = [];
5657
+ sourceJournal = yield* recordHalt(projectRunJournalStream(Stream.concat(source, Stream.fromIterable(yield* recordHalt(selectedRange(ctx.threadId, [submissionId], tail.sequence, canonicalThrough)))).pipe(Stream.filter((envelope) => envelope.record.payload._tag !== "CompactionCreated" || envelope.sequence <= canonicalThrough)), runId, (boundary) => sourceBoundaries.push(boundary), priorContext));
5658
+ }
5659
+ const coverable = sourceBoundaries.filter((boundary) => commit.kind !== "summarize" || ownerFirstSequence === void 0 || boundary.sequence < ownerFirstSequence);
5660
+ if (coverable.length === 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Durable rollover requires complete canonical records" : "Durable compaction requires eligible canonical records" });
5661
+ const comparisonView = instructionView(sourceJournal.prompt.content, initialInstructions, false, sourceJournal.historyBefore.content.length);
5662
+ let matchingPrefix = 0;
5663
+ let requiredThrough = 0;
5664
+ const comparisonLimit = Math.min(comparisonView.messages.length, commit.through);
5665
+ for (let index = 0; index < commit.through; index += 1) {
5666
+ const message = commit.source.content[index];
5667
+ if (message !== void 0 && (commit.kind === "clear-tool-results" ? message.role === "tool" : message.role !== "system")) requiredThrough = index + 1;
5668
+ if (index >= comparisonLimit || index !== matchingPrefix || message === void 0) continue;
5669
+ const canonicalMessage = comparisonView.messages[index];
5670
+ if (canonicalMessage === void 0) continue;
5671
+ const encode = (entry) => encodeCompactionMessageJson(entry).pipe(Effect.flatMap(decodeCompactionMessageJson), Effect.map(canonicalJson), Effect.mapError((cause) => CompactionError.make({
5672
+ message: "Could not encode the canonical compaction prefix",
5673
+ cause
5674
+ })));
5675
+ if ((yield* encode(canonicalMessage)) === (yield* encode(message))) matchingPrefix += 1;
5676
+ }
5677
+ let lastCovered;
5678
+ for (let index = 0; index < coverable.length; index += 1) {
5679
+ const candidate = coverable[index];
5680
+ if (candidate === void 0) continue;
5681
+ if (coverable[index + 1]?.tag === "ToolCallSettled") continue;
5682
+ const length = comparisonView.prefixLength(candidate.promptLength);
5683
+ if (length === 0 || length > commit.through) continue;
5684
+ if (length < requiredThrough || length > matchingPrefix) continue;
5685
+ lastCovered = candidate;
5686
+ }
5687
+ if (lastCovered === void 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Rollover coverage cannot be mapped to complete canonical records" : "Compaction coverage cannot be mapped to complete canonical records" });
5688
+ const coveredSequence = lastCovered.sequence;
5689
+ if (commit.kind !== "summarize" && sourceBoundaries.some((boundary) => boundary.incomplete === true && boundary.terminalPriorRun !== true && boundary.sequence <= coveredSequence)) return yield* CompactionError.make({ message: "Compaction cannot cover an incomplete Tool batch" });
5690
+ if (commit.kind === "summarize" && (commit.summary ?? "").trim().length === 0) return yield* CompactionError.make({ message: "A summarize compaction commit carried no summary" });
5691
+ const payload = yield* Schema.decodeEffect(CompactionCreated)({
5692
+ _tag: "CompactionCreated",
5693
+ runId,
5694
+ turn: canonicalTurn,
5695
+ kind: commit.kind,
5696
+ coversThrough: lastCovered.sequence,
5697
+ ...commit.kind === "summarize" ? { summary: commit.summary } : {},
5698
+ ...commit.kind === "rollover" && commit.handoff !== void 0 ? { handoff: commit.handoff } : {}
5699
+ }).pipe(Effect.mapError((cause) => CompactionError.make({
5700
+ message: "Compaction decision exceeds canonical persistence bounds",
5663
5701
  cause
5664
5702
  })));
5665
- if ((yield* encode(canonicalMessage)) === (yield* encode(message))) matchingPrefix += 1;
5666
- }
5667
- let lastCovered;
5668
- for (let index = 0; index < coverable.length; index += 1) {
5669
- const candidate = coverable[index];
5670
- if (candidate === void 0) continue;
5671
- if (coverable[index + 1]?.tag === "ToolCallSettled") continue;
5672
- const length = comparisonView.prefixLength(candidate.promptLength);
5673
- if (length === 0 || length > commit.through) continue;
5674
- if (length < requiredThrough || length > matchingPrefix) continue;
5675
- lastCovered = candidate;
5676
- }
5677
- if (lastCovered === void 0) return yield* CompactionError.make({ message: commit.kind === "rollover" ? "Rollover coverage cannot be mapped to complete canonical records" : "Compaction coverage cannot be mapped to complete canonical records" });
5678
- const coveredSequence = lastCovered.sequence;
5679
- if (commit.kind !== "summarize" && sourceBoundaries.some((boundary) => boundary.incomplete === true && boundary.terminalPriorRun !== true && boundary.sequence <= coveredSequence)) return yield* CompactionError.make({ message: "Compaction cannot cover an incomplete Tool batch" });
5680
- if (commit.kind === "summarize" && (commit.summary ?? "").trim().length === 0) return yield* CompactionError.make({ message: "A summarize compaction commit carried no summary" });
5681
- const payload = yield* Schema.decodeEffect(CompactionCreated)({
5682
- _tag: "CompactionCreated",
5683
- runId,
5684
- turn: canonicalTurn,
5685
- kind: commit.kind,
5686
- coversThrough: lastCovered.sequence,
5687
- ...commit.kind === "summarize" ? { summary: commit.summary } : {},
5688
- ...commit.kind === "rollover" && commit.handoff !== void 0 ? { handoff: commit.handoff } : {}
5689
- }).pipe(Effect.mapError((cause) => CompactionError.make({
5690
- message: "Compaction decision exceeds canonical persistence bounds",
5703
+ const envelope = yield* recordHalt(makeEnvelope(recordId, payload));
5704
+ yield* recordHalt(hit("compaction:before-canonical-append"));
5705
+ yield* recordHalt(appendBatch(ctx, CanonicalBatch.make({
5706
+ batchId: compactionBatchId(runId, canonicalTurn, commit.kind),
5707
+ producerId: config.producerId,
5708
+ records: [envelope]
5709
+ })));
5710
+ knownIds.add(recordId);
5711
+ yield* recordHalt(hit("compaction:after-canonical-append"));
5712
+ })
5713
+ };
5714
+ /** Digest of one declared call's canonical encoded parameters (the original normalized wire). */
5715
+ const approvalParametersDigest = (toolCallId) => Effect.gen(function* () {
5716
+ if (!encodedParamsByCallId.has(toolCallId)) return yield* RunJournalError.make({ message: `Tool Call ${toolCallId} requested approval before its response commit` });
5717
+ const parameters = yield* decodePersisted(encodedParamsByCallId.get(toolCallId)).pipe(Effect.mapError((cause) => RunJournalError.make({
5718
+ message: `Tool Call ${toolCallId} parameters exceed canonical persistence bounds`,
5691
5719
  cause
5692
5720
  })));
5693
- const envelope = yield* recordHalt(makeEnvelope(recordId, payload));
5694
- yield* recordHalt(hit("compaction:before-canonical-append"));
5695
- yield* recordHalt(appendBatch(ctx, CanonicalBatch.make({
5696
- batchId: compactionBatchId(runId, canonicalTurn, commit.kind),
5697
- producerId: config.producerId,
5698
- records: [envelope]
5699
- })));
5700
- knownIds.add(recordId);
5701
- yield* recordHalt(hit("compaction:after-canonical-append"));
5702
- })
5703
- };
5704
- /** Digest of one declared call's canonical encoded parameters (the original normalized wire). */
5705
- const approvalParametersDigest = (toolCallId) => Effect.gen(function* () {
5706
- if (!encodedParamsByCallId.has(toolCallId)) return yield* RunJournalError.make({ message: `Tool Call ${toolCallId} requested approval before its response commit` });
5707
- const parameters = yield* decodePersisted(encodedParamsByCallId.get(toolCallId)).pipe(Effect.mapError((cause) => RunJournalError.make({
5708
- message: `Tool Call ${toolCallId} parameters exceed canonical persistence bounds`,
5709
- cause
5710
- })));
5711
- return yield* withCrypto(digestJson(parameters));
5712
- });
5713
- /**
5714
- * Append the canonical approval records for one declared call: the `ToolApprovalRequested`
5715
- * record — plus the immediate `ToolApprovalDecided` for a policy-auto or intent-backed
5716
- * decision, one atomic batch — or the decision alone when the request is already canonical.
5717
- * Batch identity: the Turn's FIRST canonical approval append owns
5718
- * `turn-approvals:{runId}:{turn}`; later appends of the same Turn (across suspension
5719
- * cycles) use deterministic per-call batches so committed batch content is never
5720
- * contradicted; decision-only appends use `approval-decision:{sid}:{toolCallId}`. Record
5721
- * identity dedupes every replay; an identity conflict means another pass already committed
5722
- * the same records.
5723
- */
5724
- const appendApprovalRecords = (turnInfo, toolCallId, toolName, decided) => Effect.gen(function* () {
5725
- const requestRecordId = toolApprovalRequestRecordId(runId, turnInfo.turn, toolCallId);
5726
- const decisionRecordId = toolApprovalDecisionRecordId(runId, turnInfo.turn, toolCallId);
5727
- const envelopes = [];
5728
- const appendRequest = !knownIds.has(requestRecordId);
5729
- if (appendRequest) {
5730
- const parametersDigest = yield* approvalParametersDigest(toolCallId);
5731
- envelopes.push(yield* makeEnvelope(requestRecordId, ToolApprovalRequested.make({
5732
- blocksInitialDispatch: initialDispatchProofTurns.has(turnInfo.turn),
5721
+ return yield* withCrypto(digestJson(parameters));
5722
+ });
5723
+ /**
5724
+ * Append the canonical approval records for one declared call: the `ToolApprovalRequested`
5725
+ * record — plus the immediate `ToolApprovalDecided` for a policy-auto or intent-backed
5726
+ * decision, one atomic batch — or the decision alone when the request is already canonical.
5727
+ * Batch identity: the Turn's FIRST canonical approval append owns
5728
+ * `turn-approvals:{runId}:{turn}`; later appends of the same Turn (across suspension
5729
+ * cycles) use deterministic per-call batches so committed batch content is never
5730
+ * contradicted; decision-only appends use `approval-decision:{sid}:{toolCallId}`. Record
5731
+ * identity dedupes every replay; an identity conflict means another pass already committed
5732
+ * the same records.
5733
+ */
5734
+ const appendApprovalRecords = (turnInfo, toolCallId, toolName, decided) => Effect.gen(function* () {
5735
+ const requestRecordId = toolApprovalRequestRecordId(runId, turnInfo.turn, toolCallId);
5736
+ const decisionRecordId = toolApprovalDecisionRecordId(runId, turnInfo.turn, toolCallId);
5737
+ const envelopes = [];
5738
+ const appendRequest = !knownIds.has(requestRecordId);
5739
+ if (appendRequest) {
5740
+ const parametersDigest = yield* approvalParametersDigest(toolCallId);
5741
+ envelopes.push(yield* makeEnvelope(requestRecordId, ToolApprovalRequested.make({
5742
+ blocksInitialDispatch: initialDispatchProofTurns.has(turnInfo.turn),
5743
+ runId,
5744
+ turnId: turnInfo.turnId,
5745
+ turn: turnInfo.turn,
5746
+ toolCallId,
5747
+ toolName,
5748
+ parametersDigest
5749
+ })));
5750
+ }
5751
+ if (decided !== void 0 && !knownIds.has(decisionRecordId)) envelopes.push(yield* makeEnvelope(decisionRecordId, ToolApprovalDecided.make({
5733
5752
  runId,
5734
- turnId: turnInfo.turnId,
5735
5753
  turn: turnInfo.turn,
5736
5754
  toolCallId,
5737
- toolName,
5738
- parametersDigest
5755
+ decision: decided.decision,
5756
+ resolver: decided.resolver,
5757
+ reason: decided.reason
5739
5758
  })));
5740
- }
5741
- if (decided !== void 0 && !knownIds.has(decisionRecordId)) envelopes.push(yield* makeEnvelope(decisionRecordId, ToolApprovalDecided.make({
5742
- runId,
5743
- turn: turnInfo.turn,
5744
- toolCallId,
5745
- decision: decided.decision,
5746
- resolver: decided.resolver,
5747
- reason: decided.reason
5748
- })));
5749
- const head = envelopes[0];
5750
- if (head !== void 0) {
5751
- const batchId = appendRequest ? approvalRequestedTurns.has(turnInfo.turn) ? decodeBatchId(`approval-request:${runId}:${turnInfo.turn}:${toolCallId}`) : turnApprovalsBatchId(runId, turnInfo.turn) : approvalDecisionBatchId(submissionId, toolCallId);
5752
- yield* appendBatch(ctx, CanonicalBatch.make({
5753
- batchId,
5754
- producerId: config.producerId,
5755
- records: [head, ...envelopes.slice(1)]
5756
- })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
5757
- for (const record of envelopes) knownIds.add(record.recordId);
5758
- }
5759
- if (appendRequest) {
5760
- approvalRequestedTurns.add(turnInfo.turn);
5761
- yield* hit("approval:after-request-append");
5762
- }
5763
- if (decided !== void 0) canonicalApprovalDecisions.set(toolCallId, decided.decision);
5764
- });
5765
- /**
5766
- * Retain every required request before any decision can remove initial-dispatch proof.
5767
- * Policy preparation shares the engine deadline; canonical acceptance is a separate,
5768
- * fenced commit. Canonical decisions and accepted resolver intents keep their audit.
5769
- */
5770
- const approval = {
5771
- prepareBatch: (requests) => recordHalt(Effect.gen(function* () {
5772
- if (requests.length === 0) return;
5773
- yield* flushDeferredResponse;
5774
- const turnInfo = currentToolTurn;
5775
- if (turnInfo === void 0) return yield* RunJournalError.make({ message: "Approval preparation preceded its canonical response" });
5776
- for (const request of requests) {
5777
- if (request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval preparation does not match its original declaration" });
5778
- yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, void 0);
5779
- }
5780
- })),
5781
- request: (request) => recordHalt(Effect.gen(function* () {
5782
- const canonical = canonicalApprovalDecisions.get(request.toolCallId);
5783
- if (canonical !== void 0) return canonical === "approved" ? { _tag: "approved" } : { _tag: "denied" };
5784
- const intent = approvalIntents.get(request.toolCallId);
5785
- if (intent !== void 0) return intent.decision === "approved" ? {
5786
- _tag: "approved",
5787
- reason: intent.reason
5788
- } : {
5789
- _tag: "denied",
5790
- reason: intent.reason
5791
- };
5792
- return approvalResolver === void 0 ? { _tag: "unresolved" } : yield* approvalResolver.request(request);
5793
- })),
5794
- commit: (request, decision) => recordHalt(Effect.gen(function* () {
5795
- const turnInfo = currentToolTurn;
5796
- if (turnInfo === void 0 || request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval acceptance does not match its original declaration" });
5797
- const canonical = canonicalApprovalDecisions.get(request.toolCallId);
5798
- if (canonical !== void 0) {
5799
- if (decision._tag !== canonical) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its canonical decision" });
5800
- return;
5759
+ const head = envelopes[0];
5760
+ if (head !== void 0) {
5761
+ const batchId = appendRequest ? approvalRequestedTurns.has(turnInfo.turn) ? decodeBatchId(`approval-request:${runId}:${turnInfo.turn}:${toolCallId}`) : turnApprovalsBatchId(runId, turnInfo.turn) : approvalDecisionBatchId(submissionId, toolCallId);
5762
+ yield* appendBatch(ctx, CanonicalBatch.make({
5763
+ batchId,
5764
+ producerId: config.producerId,
5765
+ records: [head, ...envelopes.slice(1)]
5766
+ })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
5767
+ for (const record of envelopes) knownIds.add(record.recordId);
5801
5768
  }
5802
- const intent = approvalIntents.get(request.toolCallId);
5803
- if (intent !== void 0 && decision._tag !== intent.decision) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its accepted intent" });
5804
- yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, intent !== void 0 ? {
5805
- decision: intent.decision,
5806
- resolver: intent.resolver,
5807
- reason: intent.reason
5808
- } : decision._tag === "unresolved" ? void 0 : {
5809
- decision: decision._tag,
5810
- resolver: APPROVAL_POLICY_RESOLVER,
5811
- reason: boundedApprovalReason(decision.reason, "The configured approval policy decided immediately")
5812
- });
5813
- }))
5814
- };
5815
- /**
5816
- * Joining/Joined queued input hook (plan §2.5, DUR-016). At every engine drain seam:
5817
- *
5818
- * 1. Reattach first — pre-existing joins whose canonical `input:{sid}` record is not yet
5819
- * prompt-covered re-deliver WITHOUT re-appending (record identity is the dedupe);
5820
- * covered inputs are already inside the journal prompt. A `joining` row whose input is
5821
- * canonical only lost its marker: it is repaired from history under the host's live
5822
- * ownership (DUR-015). A `joining` row WITHOUT canonical input was never consumed and
5823
- * is recovery's to revert — the hook never guesses at it (fail-closed).
5824
- * 2. Claim fresh — `claimJoining` atomically transitions the contiguous ready prefix of
5825
- * strictly-later queue sequences to `joining` under the host's local generation (an
5826
- * admitted-not-ready row breaks the prefix). Per fresh claim: honor a
5827
- * pre-consumption abort intent by reverting (revert-then-abort), else append the
5828
- * deterministic `UserInputRecorded` (batch `submission-input:{sid}`, record
5829
- * `input:{sid}`, `runId` = host Run, kind `steering`) → `join:after-canonical-append`
5830
- * → `markJoined` → hand the engine the `RunInputCommand`.
5831
- *
5832
- * Delivered input is `steering`: the engine appends it to official history at the seam,
5833
- * so the next Turn's response commit makes it model-visible canonically — exactly the
5834
- * prompt-coverage rule recovery relies on.
5835
- */
5836
- const renderJoinedInput = ({ input: encodedInput, messageAdmission }) => Effect.gen(function* () {
5837
- if (Schema.is(FrameworkMessage)(messageAdmission)) return yield* Schema.encodeEffect(Schema.fromJsonString(FrameworkMessage))(messageAdmission).pipe(Effect.mapError(() => AgentInputError.make({ message: "Invalid worker completion message" })));
5838
- const inputPrompt = agent.definition.inputPrompt;
5839
- if (inputPrompt === void 0) return yield* renderInputPrompt(void 0, encodedInput, encodedInput);
5840
- const decodedInput = yield* Schema.decodeEffect(agent.definition.input)(encodedInput).pipe(Effect.mapError((cause) => AgentInputDecodeError.make({ message: cause.message })));
5841
- return yield* renderInputPrompt(inputPrompt, decodedInput, encodedInput);
5842
- });
5843
- const pendingJoinClaims = [];
5844
- const claimInputs = Effect.fnUntraced(function* (maxCount) {
5845
- const claims = yield* session.claimJoining(maxCount);
5846
- pendingJoinClaims.push(...claims.map((claim) => ({ claim })));
5847
- return claims.length;
5848
- }, Effect.uninterruptible);
5849
- const revertClaims = Effect.fnUntraced(function* (claims) {
5850
- for (const pending of claims) {
5851
- yield* session.revertJoining(pending.claim.submissionId);
5852
- pendingJoinClaims.splice(pendingJoinClaims.indexOf(pending), 1);
5853
- }
5854
- }, Effect.uninterruptible);
5855
- const prepareInputs = Effect.fnUntraced(function* (limit, firstReady = false) {
5856
- if (pendingJoinClaims.length < limit && (yield* claimInputs(limit - pendingJoinClaims.length)) > 0) yield* hit("join:after-claim");
5857
- const prepared = [];
5858
- for (const pending of pendingJoinClaims.slice(0, limit)) {
5859
- const claim = pending.claim;
5860
- const snapshot = yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: claim.submissionId }));
5861
- if (snapshot.abortIntent !== void 0) {
5862
- yield* revertClaims([pending]);
5863
- continue;
5769
+ if (appendRequest) {
5770
+ approvalRequestedTurns.add(turnInfo.turn);
5771
+ yield* hit("approval:after-request-append");
5864
5772
  }
5865
- if (pending.prepared === void 0) {
5866
- const input = {
5867
- input: claim.inputPayload,
5868
- ...snapshot.submission.messageAdmission === void 0 ? {} : { messageAdmission: snapshot.submission.messageAdmission }
5869
- };
5870
- const rendered = yield* Effect.result(renderJoinedInput(input));
5871
- if (Result.isFailure(rendered)) {
5872
- yield* revertClaims(pendingJoinClaims.slice(pendingJoinClaims.indexOf(pending)));
5873
- break;
5773
+ if (decided !== void 0) canonicalApprovalDecisions.set(toolCallId, decided.decision);
5774
+ });
5775
+ /**
5776
+ * Retain every required request before any decision can remove initial-dispatch proof.
5777
+ * Policy preparation shares the engine deadline; canonical acceptance is a separate,
5778
+ * fenced commit. Canonical decisions and accepted resolver intents keep their audit.
5779
+ */
5780
+ const approval = {
5781
+ prepareBatch: (requests) => recordHalt(Effect.gen(function* () {
5782
+ if (requests.length === 0) return;
5783
+ yield* flushDeferredResponse;
5784
+ const turnInfo = currentToolTurn;
5785
+ if (turnInfo === void 0) return yield* RunJournalError.make({ message: "Approval preparation preceded its canonical response" });
5786
+ for (const request of requests) {
5787
+ if (request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval preparation does not match its original declaration" });
5788
+ yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, void 0);
5874
5789
  }
5875
- pending.prepared = {
5876
- claim,
5877
- input,
5878
- rendered: rendered.success
5790
+ })),
5791
+ request: (request) => recordHalt(Effect.gen(function* () {
5792
+ const canonical = canonicalApprovalDecisions.get(request.toolCallId);
5793
+ if (canonical !== void 0) return canonical === "approved" ? { _tag: "approved" } : { _tag: "denied" };
5794
+ const intent = approvalIntents.get(request.toolCallId);
5795
+ if (intent !== void 0) return intent.decision === "approved" ? {
5796
+ _tag: "approved",
5797
+ reason: intent.reason
5798
+ } : {
5799
+ _tag: "denied",
5800
+ reason: intent.reason
5879
5801
  };
5802
+ return approvalResolver === void 0 ? { _tag: "unresolved" } : yield* approvalResolver.request(request);
5803
+ })),
5804
+ commit: (request, decision) => recordHalt(Effect.gen(function* () {
5805
+ const turnInfo = currentToolTurn;
5806
+ if (turnInfo === void 0 || request.threadId !== submission.threadId || request.runId !== runId || request.turnId !== turnInfo.turnId || declaredNamesByCallId.get(request.toolCallId) !== request.toolName) return yield* RunJournalError.make({ message: "Approval acceptance does not match its original declaration" });
5807
+ const canonical = canonicalApprovalDecisions.get(request.toolCallId);
5808
+ if (canonical !== void 0) {
5809
+ if (decision._tag !== canonical) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its canonical decision" });
5810
+ return;
5811
+ }
5812
+ const intent = approvalIntents.get(request.toolCallId);
5813
+ if (intent !== void 0 && decision._tag !== intent.decision) return yield* RunJournalError.make({ message: "Approval preparation disagrees with its accepted intent" });
5814
+ yield* appendApprovalRecords(turnInfo, request.toolCallId, request.toolName, intent !== void 0 ? {
5815
+ decision: intent.decision,
5816
+ resolver: intent.resolver,
5817
+ reason: intent.reason
5818
+ } : decision._tag === "unresolved" ? void 0 : {
5819
+ decision: decision._tag,
5820
+ resolver: APPROVAL_POLICY_RESOLVER,
5821
+ reason: boundedApprovalReason(decision.reason, "The configured approval policy decided immediately")
5822
+ });
5823
+ }))
5824
+ };
5825
+ /**
5826
+ * Joining/Joined queued input hook (plan §2.5, DUR-016). At every engine drain seam:
5827
+ *
5828
+ * 1. Reattach first — pre-existing joins whose canonical `input:{sid}` record is not yet
5829
+ * prompt-covered re-deliver WITHOUT re-appending (record identity is the dedupe);
5830
+ * covered inputs are already inside the journal prompt. A `joining` row whose input is
5831
+ * canonical only lost its marker: it is repaired from history under the host's live
5832
+ * ownership (DUR-015). A `joining` row WITHOUT canonical input was never consumed and
5833
+ * is recovery's to revert — the hook never guesses at it (fail-closed).
5834
+ * 2. Claim fresh — `claimJoining` atomically transitions the contiguous ready prefix of
5835
+ * strictly-later queue sequences to `joining` under the host's local generation (an
5836
+ * admitted-not-ready row breaks the prefix). Per fresh claim: honor a
5837
+ * pre-consumption abort intent by reverting (revert-then-abort), else append the
5838
+ * deterministic `UserInputRecorded` (batch `submission-input:{sid}`, record
5839
+ * `input:{sid}`, `runId` = host Run, kind `steering`) → `join:after-canonical-append`
5840
+ * → `markJoined` → hand the engine the `RunInputCommand`.
5841
+ *
5842
+ * Delivered input is `steering`: the engine appends it to official history at the seam,
5843
+ * so the next Turn's response commit makes it model-visible canonically — exactly the
5844
+ * prompt-coverage rule recovery relies on.
5845
+ */
5846
+ const renderJoinedInput = Effect.fnUntraced(function* (encodedInput, messageAdmission) {
5847
+ if (Schema.is(FrameworkMessage)(messageAdmission)) return yield* Schema.encodeEffect(Schema.fromJsonString(FrameworkMessage))(messageAdmission).pipe(Effect.mapError(() => AgentInputError.make({ message: "Invalid worker completion message" })));
5848
+ const inputPrompt = agent.definition.inputPrompt;
5849
+ if (inputPrompt === void 0) return yield* renderInputPrompt(void 0, encodedInput, encodedInput);
5850
+ const decodedInput = yield* Schema.decodeEffect(agent.definition.input)(encodedInput).pipe(Effect.mapError((cause) => AgentInputDecodeError.make({ message: cause.message })));
5851
+ return yield* renderInputPrompt(inputPrompt, decodedInput, encodedInput);
5852
+ });
5853
+ const pendingJoinClaims = [];
5854
+ const claimInputs = Effect.fnUntraced(function* (maxCount) {
5855
+ const claims = yield* session.claimJoining(maxCount);
5856
+ pendingJoinClaims.push(...claims.map((claim) => ({ claim })));
5857
+ return claims.length;
5858
+ }, Effect.uninterruptible);
5859
+ const revertClaims = Effect.fnUntraced(function* (claims) {
5860
+ for (const pending of claims) {
5861
+ yield* session.revertJoining(pending.claim.submissionId);
5862
+ pendingJoinClaims.splice(pendingJoinClaims.indexOf(pending), 1);
5880
5863
  }
5881
- prepared.push(pending.prepared);
5882
- if (firstReady) break;
5883
- }
5884
- return prepared;
5885
- });
5886
- const input = {
5887
- awaitJoin: recordHalt(Effect.gen(function* () {
5888
- while (true) if (yield* Effect.scoped(Effect.gen(function* () {
5889
- const notified = yield* wake.subscribe(submission.threadId);
5890
- if ((yield* prepareInputs(MAX_JOIN_DRAIN, true)).length > 0) return true;
5891
- yield* notified;
5892
- return false;
5893
- }))) return;
5894
- })),
5895
- drain: (policy) => Effect.gen(function* () {
5896
- const joinedInputs = yield* recordHalt(Effect.gen(function* () {
5897
- const limit = policy === "one" ? 1 : MAX_JOIN_DRAIN;
5898
- const joinedInputs = [];
5899
- if (joinBacklog === void 0) joinBacklog = (yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId }))).joins;
5900
- for (const join of joinBacklog) {
5901
- const joinId = join.submissionId;
5902
- if (deliveredJoinInputs.has(joinId)) continue;
5903
- if (join.state !== "joining" && join.state !== "joined") continue;
5904
- const existing = joinedInputEnvelopes.get(joinId);
5905
- if (existing === void 0) continue;
5906
- if (join.state === "joining") yield* session.markJoined(joinId, {
5907
- recordId: existing.record.recordId,
5908
- sequence: existing.sequence
5909
- });
5910
- deliveredJoinInputs.add(joinId);
5911
- if (lastHostResponseSequence !== void 0 && lastHostResponseSequence > existing.sequence) continue;
5912
- const payload = existing.record.payload;
5913
- if (payload._tag !== "UserInputRecorded") continue;
5914
- joinedInputs.push(payload);
5864
+ }, Effect.uninterruptible);
5865
+ const prepareInputs = Effect.fnUntraced(function* (limit, firstReady = false) {
5866
+ if (pendingJoinClaims.length < limit && (yield* claimInputs(limit - pendingJoinClaims.length)) > 0) yield* hit("join:after-claim");
5867
+ const prepared = [];
5868
+ for (const pending of pendingJoinClaims.slice(0, limit)) {
5869
+ const claim = pending.claim;
5870
+ const snapshot = yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: claim.submissionId }));
5871
+ if (snapshot.abortIntent !== void 0) {
5872
+ yield* revertClaims([pending]);
5873
+ continue;
5915
5874
  }
5916
- const claims = yield* prepareInputs(limit);
5917
- pendingJoinClaims.splice(0, claims.length);
5918
- for (const { claim, input: payload, rendered } of claims) {
5919
- const recordId = submissionInputRecordId(claim.submissionId);
5920
- let sequence;
5921
- const existing = joinedInputEnvelopes.get(claim.submissionId);
5922
- if (existing !== void 0) sequence = existing.sequence;
5923
- else {
5924
- const envelope = yield* makeEnvelope(recordId, UserInputRecorded.make({
5925
- submissionId: claim.submissionId,
5926
- kind: "steering",
5927
- runId,
5928
- input: claim.inputPayload,
5929
- ...payload.messageAdmission === void 0 ? {} : { messageAdmission: payload.messageAdmission }
5930
- }));
5931
- sequence = (yield* appendBatch(ctx, CanonicalBatch.make({
5932
- batchId: submissionInputBatchId(claim.submissionId),
5933
- producerId: config.producerId,
5934
- records: [envelope]
5935
- }))).firstSequence;
5936
- knownIds.add(recordId);
5937
- yield* hit("join:after-canonical-append");
5875
+ if (pending.prepared === void 0) {
5876
+ const input = {
5877
+ input: claim.inputPayload,
5878
+ ...snapshot.submission.messageAdmission === void 0 ? {} : { messageAdmission: snapshot.submission.messageAdmission }
5879
+ };
5880
+ const rendered = yield* Effect.result(renderJoinedInput(input.input, input.messageAdmission));
5881
+ if (Result.isFailure(rendered)) {
5882
+ yield* revertClaims(pendingJoinClaims.slice(pendingJoinClaims.indexOf(pending)));
5883
+ break;
5938
5884
  }
5939
- yield* session.markJoined(claim.submissionId, {
5940
- recordId,
5941
- sequence
5942
- });
5943
- deliveredJoinInputs.add(claim.submissionId);
5944
- joinedInputs.push({
5945
- ...payload,
5946
- rendered
5947
- });
5885
+ pending.prepared = {
5886
+ claim,
5887
+ input,
5888
+ rendered: rendered.success
5889
+ };
5948
5890
  }
5949
- return joinedInputs;
5950
- }));
5951
- return yield* Effect.forEach(joinedInputs, (joinedInput) => (joinedInput.rendered === void 0 ? renderJoinedInput(joinedInput) : Effect.succeed(joinedInput.rendered)).pipe(Effect.map((input) => ({
5952
- kind: "steering",
5953
- input
5954
- }))));
5955
- })
5956
- };
5957
- /**
5958
- * Durable child establishment: `establish` performs or replays
5959
- * the idempotent get-or-create establishment protocol under the
5960
- * parent's ownership fence and reports where the one child stands; `join` appends the
5961
- * atomic `[SubagentJoined, ToolCallSettled]` settlement batch (SUB-019) and applies the
5962
- * reservation release. Both use the halt side channel exactly like the durability/step
5963
- * hooks: the engine wraps a `CoordinatorHalt` into `SubagentDurabilityError` in the
5964
- * handler channel while the Attempt aborts with the original infrastructure failure.
5965
- */
5966
- const establishmentGate = yield* Semaphore.make(1);
5967
- const establishSubagent = (request) => recordHalt(Effect.gen(function* () {
5968
- const toolCallId = request.toolCallId;
5969
- const turnInfo = currentToolTurn;
5970
- if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} established before any canonical response commit` });
5971
- const denied = (errorTag, message) => ({
5972
- _tag: "denied",
5973
- errorTag,
5974
- message: boundedText(message)
5975
- });
5976
- let requestedPayload = subagentState.requested.get(toolCallId);
5977
- if (requestedPayload === void 0) {
5978
- if (request.depth !== delegationDepth + 1) return denied("SubagentDepthUnsupported", `The child depth must be exactly one greater than its source depth ${delegationDepth}`);
5979
- let targetDigests = request.targetDigests;
5980
- if (request.target !== void 0) {
5981
- if (request.target.id !== request.targetAgentId) return denied("SubagentBindingUnavailable", "The child target identity differs from its Definition");
5982
- const binding = yield* resolveDefinitionBinding(registeredBindings, request.target).pipe(Effect.result);
5983
- if (binding._tag === "Failure") return denied("SubagentBindingUnavailable", binding.failure.message);
5984
- if (targetDigests !== void 0 && (targetDigests.agent !== binding.success.digests.agent || targetDigests.model !== binding.success.digests.model || targetDigests.tools !== binding.success.digests.tools)) return denied("SubagentDigestsInvalid", "The explicit child digests differ from its exact registration");
5985
- targetDigests = binding.success.digests;
5891
+ prepared.push(pending.prepared);
5892
+ if (firstReady) break;
5986
5893
  }
5987
- const decodedDigests = yield* decodeDefinitionDigests(targetDigests).pipe(Effect.option);
5988
- if (Option.isNone(decodedDigests)) return denied("SubagentDigestsInvalid", "The declared child Binding digests are not valid stored digests");
5989
- const childInput = yield* decodePersisted(request.encodedChildInput).pipe(Effect.option);
5990
- if (Option.isNone(childInput)) return denied("SubagentInputUnpersistable", "The prepared child input does not satisfy the canonical persistence bounds");
5991
- const grant = yield* decodePersisted(request.encodedGrant).pipe(Effect.option);
5992
- const allocation = yield* decodePersisted(request.encodedAllocation).pipe(Effect.option);
5993
- if (Option.isNone(grant) || Option.isNone(allocation)) return denied("SubagentDeclarationUnpersistable", "The delegation grant or allocation does not satisfy the canonical persistence bounds");
5994
- const decodedGrant = Schema.decodeUnknownOption(SubagentGrant)(grant.value);
5995
- if (Option.isNone(decodedGrant)) return denied("SubagentGrantInvalid", "The child authority grant is invalid");
5996
- if (request.policy === void 0 || request.budget === void 0) return denied("SubagentBudgetInvalid", "New durable children require their full execution policy and subtree allocation");
5997
- if (request.toolCallAllowance !== void 0 && !Schema.is(SubagentRequested.fields.toolCallAllowance)(request.toolCallAllowance)) return denied("SubagentAllowanceInvalid", "The child Tool Call allowance must be a positive integer");
5998
- if (request.policy !== void 0 && !Schema.is(AgentPolicy)(request.policy)) return denied("SubagentPolicyInvalid", "The resolved child policy is invalid");
5999
- if (request.budget !== void 0) {
6000
- if (!Schema.is(SubagentBudgetReservation)(request.budget)) return denied("SubagentBudgetInvalid", "The shared delegation budget is invalid");
6001
- const decodedAllocation = Schema.decodeUnknownOption(SubagentReservationAmounts)(allocation.value);
6002
- if (Option.isNone(decodedAllocation) || !Equal.equals(decodedAllocation.value, request.budget.allocation)) return denied("SubagentBudgetInvalid", "The reserved allocation differs from its budget declaration");
6003
- const { caps, allocation: requested } = request.budget;
6004
- const prior = [...subagentState.requested.values()];
6005
- if (prior.some((entry) => entry.budget === void 0 || !Equal.equals(entry.budget.caps, caps))) return denied("SubagentParentBudgetConflict", "Delegations in one parent Run must share the same caps");
6006
- if (caps.maxTotalChildInvocations !== void 0 && prior.reduce((sum, entry) => sum + 1 + (entry.budget?.descendantInvocations ?? 0), 1 + (request.budget.descendantInvocations ?? 0)) > caps.maxTotalChildInvocations) return denied("SubagentBudgetExhausted", "The parent Run exhausted its child invocation budget");
6007
- const active = prior.filter((entry) => !subagentState.joined.has(entry.toolCallId));
6008
- if (caps.maxConcurrentChildren !== void 0 && active.length >= caps.maxConcurrentChildren) return denied("SubagentBudgetExhausted", "The parent Run exhausted its concurrent child budget");
6009
- const dimensions = [
6010
- ["turns", "maxTurns"],
6011
- ["toolCalls", "maxToolCalls"],
6012
- ["durationMillis", "maxDurationMillis"],
6013
- ["inputTokens", "maxInputTokens"],
6014
- ["outputTokens", "maxOutputTokens"],
6015
- ["costMicrousd", "maxCostMicrousd"],
6016
- ["resultBytes", "maxResultBytes"]
6017
- ];
6018
- const accounting = Schema.Struct({ consumed: SubagentReservationAmounts });
6019
- for (const [amount, cap] of dimensions) {
6020
- const limit = caps[cap];
6021
- if (limit === void 0) continue;
6022
- let consumed = requested[amount];
6023
- for (const entry of prior) {
6024
- const joined = subagentState.joined.get(entry.toolCallId);
6025
- const observed = joined === void 0 ? Option.none() : Schema.decodeUnknownOption(accounting)(joined.finalAccounting);
6026
- consumed += Option.isSome(observed) ? observed.value.consumed[amount] : entry.budget?.allocation[amount] ?? limit;
5894
+ return prepared;
5895
+ });
5896
+ const input = {
5897
+ awaitJoin: recordHalt(Effect.gen(function* () {
5898
+ while (true) if (yield* Effect.scoped(Effect.gen(function* () {
5899
+ const notified = yield* wake.subscribe(submission.threadId);
5900
+ if ((yield* prepareInputs(MAX_JOIN_DRAIN, true)).length > 0) return true;
5901
+ yield* notified;
5902
+ return false;
5903
+ }))) return;
5904
+ })),
5905
+ drain: Effect.fnUntraced(function* (policy) {
5906
+ const joinedInputs = yield* recordHalt(Effect.gen(function* () {
5907
+ const limit = policy === "one" ? 1 : MAX_JOIN_DRAIN;
5908
+ const joinedInputs = [];
5909
+ if (joinBacklog === void 0) joinBacklog = (yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId }))).joins;
5910
+ for (const join of joinBacklog) {
5911
+ const joinId = join.submissionId;
5912
+ if (deliveredJoinInputs.has(joinId)) continue;
5913
+ if (join.state !== "joining" && join.state !== "joined") continue;
5914
+ const existing = joinedInputEnvelopes.get(joinId);
5915
+ if (existing === void 0) continue;
5916
+ if (join.state === "joining") yield* session.markJoined(joinId, {
5917
+ recordId: existing.record.recordId,
5918
+ sequence: existing.sequence
5919
+ });
5920
+ deliveredJoinInputs.add(joinId);
5921
+ if (lastHostResponseSequence !== void 0 && lastHostResponseSequence > existing.sequence) continue;
5922
+ const payload = existing.record.payload;
5923
+ if (payload._tag !== "UserInputRecorded") continue;
5924
+ joinedInputs.push(payload);
5925
+ }
5926
+ const claims = yield* prepareInputs(limit);
5927
+ pendingJoinClaims.splice(0, claims.length);
5928
+ for (const { claim, input: payload, rendered } of claims) {
5929
+ const recordId = submissionInputRecordId(claim.submissionId);
5930
+ let sequence;
5931
+ const existing = joinedInputEnvelopes.get(claim.submissionId);
5932
+ if (existing !== void 0) sequence = existing.sequence;
5933
+ else {
5934
+ const envelope = yield* makeEnvelope(recordId, UserInputRecorded.make({
5935
+ submissionId: claim.submissionId,
5936
+ kind: "steering",
5937
+ runId,
5938
+ input: claim.inputPayload,
5939
+ ...payload.messageAdmission === void 0 ? {} : { messageAdmission: payload.messageAdmission }
5940
+ }));
5941
+ sequence = (yield* appendBatch(ctx, CanonicalBatch.make({
5942
+ batchId: submissionInputBatchId(claim.submissionId),
5943
+ producerId: config.producerId,
5944
+ records: [envelope]
5945
+ }))).firstSequence;
5946
+ knownIds.add(recordId);
5947
+ yield* hit("join:after-canonical-append");
5948
+ }
5949
+ yield* session.markJoined(claim.submissionId, {
5950
+ recordId,
5951
+ sequence
5952
+ });
5953
+ deliveredJoinInputs.add(claim.submissionId);
5954
+ joinedInputs.push({
5955
+ ...payload,
5956
+ rendered
5957
+ });
5958
+ }
5959
+ return joinedInputs;
5960
+ }));
5961
+ return yield* Effect.forEach(joinedInputs, (joinedInput) => (joinedInput.rendered === void 0 ? renderJoinedInput(joinedInput.input, joinedInput.messageAdmission) : Effect.succeed(joinedInput.rendered)).pipe(Effect.map((input) => ({
5962
+ kind: "steering",
5963
+ input
5964
+ }))));
5965
+ })
5966
+ };
5967
+ /**
5968
+ * Durable child establishment: `establish` performs or replays
5969
+ * the idempotent get-or-create establishment protocol under the
5970
+ * parent's ownership fence and reports where the one child stands; `join` appends the
5971
+ * atomic `[SubagentJoined, ToolCallSettled]` settlement batch (SUB-019) and applies the
5972
+ * reservation release. Both use the halt side channel exactly like the durability/step
5973
+ * hooks: the engine wraps a `CoordinatorHalt` into `SubagentDurabilityError` in the
5974
+ * handler channel while the Attempt aborts with the original infrastructure failure.
5975
+ */
5976
+ const establishmentGate = yield* Semaphore.make(1);
5977
+ const establishSubagent = (request) => recordHalt(Effect.gen(function* () {
5978
+ const toolCallId = request.toolCallId;
5979
+ const turnInfo = currentToolTurn;
5980
+ if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} established before any canonical response commit` });
5981
+ const denied = (errorTag, message) => ({
5982
+ _tag: "denied",
5983
+ errorTag,
5984
+ message: boundedText(message)
5985
+ });
5986
+ let requestedPayload = subagentState.requested.get(toolCallId);
5987
+ if (requestedPayload === void 0) {
5988
+ if (request.depth !== delegationDepth + 1) return denied("SubagentDepthUnsupported", `The child depth must be exactly one greater than its source depth ${delegationDepth}`);
5989
+ let targetDigests = request.targetDigests;
5990
+ if (request.target !== void 0) {
5991
+ if (request.target.id !== request.targetAgentId) return denied("SubagentBindingUnavailable", "The child target identity differs from its Definition");
5992
+ const binding = yield* resolveDefinitionBinding(registeredBindings, request.target).pipe(Effect.result);
5993
+ if (binding._tag === "Failure") return denied("SubagentBindingUnavailable", binding.failure.message);
5994
+ if (targetDigests !== void 0 && (targetDigests.agent !== binding.success.digests.agent || targetDigests.model !== binding.success.digests.model || targetDigests.tools !== binding.success.digests.tools)) return denied("SubagentDigestsInvalid", "The explicit child digests differ from its exact registration");
5995
+ targetDigests = binding.success.digests;
5996
+ }
5997
+ const decodedDigests = yield* decodeDefinitionDigests(targetDigests).pipe(Effect.option);
5998
+ if (Option.isNone(decodedDigests)) return denied("SubagentDigestsInvalid", "The declared child Binding digests are not valid stored digests");
5999
+ const childInput = yield* decodePersisted(request.encodedChildInput).pipe(Effect.option);
6000
+ if (Option.isNone(childInput)) return denied("SubagentInputUnpersistable", "The prepared child input does not satisfy the canonical persistence bounds");
6001
+ const grant = yield* decodePersisted(request.encodedGrant).pipe(Effect.option);
6002
+ const allocation = yield* decodePersisted(request.encodedAllocation).pipe(Effect.option);
6003
+ if (Option.isNone(grant) || Option.isNone(allocation)) return denied("SubagentDeclarationUnpersistable", "The delegation grant or allocation does not satisfy the canonical persistence bounds");
6004
+ const decodedGrant = Schema.decodeUnknownOption(SubagentGrant)(grant.value);
6005
+ if (Option.isNone(decodedGrant)) return denied("SubagentGrantInvalid", "The child authority grant is invalid");
6006
+ if (request.policy === void 0 || request.budget === void 0) return denied("SubagentBudgetInvalid", "New durable children require their full execution policy and subtree allocation");
6007
+ if (request.toolCallAllowance !== void 0 && !Schema.is(SubagentRequested.fields.toolCallAllowance)(request.toolCallAllowance)) return denied("SubagentAllowanceInvalid", "The child Tool Call allowance must be a positive integer");
6008
+ if (request.policy !== void 0 && !Schema.is(AgentPolicy)(request.policy)) return denied("SubagentPolicyInvalid", "The resolved child policy is invalid");
6009
+ if (request.budget !== void 0) {
6010
+ if (!Schema.is(SubagentBudgetReservation)(request.budget)) return denied("SubagentBudgetInvalid", "The shared delegation budget is invalid");
6011
+ const decodedAllocation = Schema.decodeUnknownOption(SubagentReservationAmounts)(allocation.value);
6012
+ if (Option.isNone(decodedAllocation) || !Equal.equals(decodedAllocation.value, request.budget.allocation)) return denied("SubagentBudgetInvalid", "The reserved allocation differs from its budget declaration");
6013
+ const { caps, allocation: requested } = request.budget;
6014
+ const prior = [...subagentState.requested.values()];
6015
+ if (prior.some((entry) => entry.budget === void 0 || !Equal.equals(entry.budget.caps, caps))) return denied("SubagentParentBudgetConflict", "Delegations in one parent Run must share the same caps");
6016
+ if (caps.maxTotalChildInvocations !== void 0 && prior.reduce((sum, entry) => sum + 1 + (entry.budget?.descendantInvocations ?? 0), 1 + (request.budget.descendantInvocations ?? 0)) > caps.maxTotalChildInvocations) return denied("SubagentBudgetExhausted", "The parent Run exhausted its child invocation budget");
6017
+ const active = prior.filter((entry) => !subagentState.joined.has(entry.toolCallId));
6018
+ if (caps.maxConcurrentChildren !== void 0 && active.length >= caps.maxConcurrentChildren) return denied("SubagentBudgetExhausted", "The parent Run exhausted its concurrent child budget");
6019
+ const dimensions = [
6020
+ ["turns", "maxTurns"],
6021
+ ["toolCalls", "maxToolCalls"],
6022
+ ["durationMillis", "maxDurationMillis"],
6023
+ ["inputTokens", "maxInputTokens"],
6024
+ ["outputTokens", "maxOutputTokens"],
6025
+ ["costMicrousd", "maxCostMicrousd"],
6026
+ ["resultBytes", "maxResultBytes"]
6027
+ ];
6028
+ const accounting = Schema.Struct({ consumed: SubagentReservationAmounts });
6029
+ for (const [amount, cap] of dimensions) {
6030
+ const limit = caps[cap];
6031
+ if (limit === void 0) continue;
6032
+ let consumed = requested[amount];
6033
+ for (const entry of prior) {
6034
+ const joined = subagentState.joined.get(entry.toolCallId);
6035
+ const observed = joined === void 0 ? Option.none() : Schema.decodeUnknownOption(accounting)(joined.finalAccounting);
6036
+ consumed += Option.isSome(observed) ? observed.value.consumed[amount] : entry.budget?.allocation[amount] ?? limit;
6037
+ }
6038
+ if (consumed > limit) return denied("SubagentBudgetExhausted", `The parent Run exhausted its shared ${amount} budget`);
6027
6039
  }
6028
- if (consumed > limit) return denied("SubagentBudgetExhausted", `The parent Run exhausted its shared ${amount} budget`);
6029
6040
  }
6030
- }
6031
- const childInputDigest = yield* withCrypto(digestJson(childInput.value));
6032
- const grantDigest = yield* withCrypto(digestJson(grant.value));
6033
- const allocationDigest = yield* withCrypto(digestJson(allocation.value));
6034
- const reservationId = childReservationIdFor(runId, toolCallId);
6035
- const subtree = delegationDepth === 0 ? void 0 : yield* workerRuntime.reserveSubtree(submission.threadId, SubtreeBudgetReserved.make({
6036
- reservationId,
6037
- executionRunId: runId,
6038
- sourceSubmissionId: submissionId,
6039
- childThreadId: childThreadIdFor(submissionId, toolCallId),
6040
- lifetime: "attached",
6041
- depth: request.depth,
6042
- policy: request.policy,
6043
- grant: decodedGrant.value,
6044
- budget: request.budget
6045
- })).pipe(Effect.result);
6046
- if (subtree?._tag === "Failure") {
6047
- if (subtree.failure.reason === "storage") return yield* LedgerError.make({
6048
- operation: "reserve-subtree",
6049
- message: "Subtree reservation is unavailable"
6041
+ const childInputDigest = yield* withCrypto(digestJson(childInput.value));
6042
+ const grantDigest = yield* withCrypto(digestJson(grant.value));
6043
+ const allocationDigest = yield* withCrypto(digestJson(allocation.value));
6044
+ const reservationId = childReservationIdFor(runId, toolCallId);
6045
+ const subtree = delegationDepth === 0 ? void 0 : yield* workerRuntime.reserveSubtree(submission.threadId, SubtreeBudgetReserved.make({
6046
+ reservationId,
6047
+ executionRunId: runId,
6048
+ sourceSubmissionId: submissionId,
6049
+ childThreadId: childThreadIdFor(submissionId, toolCallId),
6050
+ lifetime: "attached",
6051
+ depth: request.depth,
6052
+ policy: request.policy,
6053
+ grant: decodedGrant.value,
6054
+ budget: request.budget
6055
+ })).pipe(Effect.result);
6056
+ if (subtree?._tag === "Failure") {
6057
+ if (subtree.failure.reason === "storage") return yield* LedgerError.make({
6058
+ operation: "reserve-subtree",
6059
+ message: "Subtree reservation is unavailable"
6060
+ });
6061
+ return denied("SubagentBudgetExhausted", `The subtree reservation was refused: ${subtree.failure.reason}`);
6062
+ }
6063
+ yield* session.reserveChildBudget({
6064
+ reservationId,
6065
+ parentToolCallId: toolCallId,
6066
+ allocation: allocation.value,
6067
+ allocationDigest
6068
+ }).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("reserveChildBudget")));
6069
+ yield* hit("subagent:after-reserve");
6070
+ requestedPayload = SubagentRequested.make({
6071
+ runId,
6072
+ turnId: turnInfo.turnId,
6073
+ turn: turnInfo.turn,
6074
+ toolCallId,
6075
+ delegationId: request.delegationId,
6076
+ targetAgentId: request.targetAgentId,
6077
+ targetDigests: decodedDigests.value,
6078
+ childInput: childInput.value,
6079
+ childInputDigest,
6080
+ grantDigest,
6081
+ grant: decodedGrant.value,
6082
+ depth: request.depth,
6083
+ reservationId,
6084
+ reservationDigest: allocationDigest,
6085
+ childThreadId: childThreadIdFor(submissionId, toolCallId),
6086
+ childPrincipal: submission.principal,
6087
+ childIdempotencyKey: childIdempotencyKeyFor(runId, toolCallId),
6088
+ ...request.toolCallAllowance === void 0 ? {} : { toolCallAllowance: request.toolCallAllowance },
6089
+ ...request.policy === void 0 ? {} : { policy: request.policy },
6090
+ ...request.budget === void 0 ? {} : { budget: request.budget }
6050
6091
  });
6051
- return denied("SubagentBudgetExhausted", `The subtree reservation was refused: ${subtree.failure.reason}`);
6092
+ const requestRecordId = subagentRequestedRecordId(runId, toolCallId);
6093
+ if (!knownIds.has(requestRecordId)) {
6094
+ const envelope = yield* makeEnvelope(requestRecordId, requestedPayload);
6095
+ yield* appendBatch(ctx, CanonicalBatch.make({
6096
+ batchId: subagentRequestedBatchId(runId, toolCallId),
6097
+ producerId: config.producerId,
6098
+ records: [envelope]
6099
+ })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
6100
+ knownIds.add(requestRecordId);
6101
+ }
6102
+ subagentState.requested.set(toolCallId, requestedPayload);
6103
+ yield* hit("subagent:after-request-append");
6052
6104
  }
6053
- yield* session.reserveChildBudget({
6054
- reservationId,
6055
- parentToolCallId: toolCallId,
6056
- allocation: allocation.value,
6057
- allocationDigest
6058
- }).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("reserveChildBudget")));
6059
- yield* hit("subagent:after-reserve");
6060
- requestedPayload = SubagentRequested.make({
6061
- runId,
6062
- turnId: turnInfo.turnId,
6063
- turn: turnInfo.turn,
6064
- toolCallId,
6065
- delegationId: request.delegationId,
6066
- targetAgentId: request.targetAgentId,
6067
- targetDigests: decodedDigests.value,
6068
- childInput: childInput.value,
6069
- childInputDigest,
6070
- grantDigest,
6071
- grant: decodedGrant.value,
6072
- depth: request.depth,
6073
- reservationId,
6074
- reservationDigest: allocationDigest,
6075
- childThreadId: childThreadIdFor(submissionId, toolCallId),
6076
- childPrincipal: submission.principal,
6077
- childIdempotencyKey: childIdempotencyKeyFor(runId, toolCallId),
6078
- ...request.toolCallAllowance === void 0 ? {} : { toolCallAllowance: request.toolCallAllowance },
6079
- ...request.policy === void 0 ? {} : { policy: request.policy },
6080
- ...request.budget === void 0 ? {} : { budget: request.budget }
6105
+ const admission = yield* establishChildFromRequest(submission, requestedPayload);
6106
+ if (admission._tag === "indeterminate") return yield* LedgerError.make({
6107
+ operation: "establishSubagent",
6108
+ message: `Child admission for Tool Call ${toolCallId} is indeterminate (${admission.reason}); retrying without a second admission (SUB-031)`
6081
6109
  });
6082
- const requestRecordId = subagentRequestedRecordId(runId, toolCallId);
6083
- if (!knownIds.has(requestRecordId)) {
6084
- const envelope = yield* makeEnvelope(requestRecordId, requestedPayload);
6085
- yield* appendBatch(ctx, CanonicalBatch.make({
6086
- batchId: subagentRequestedBatchId(runId, toolCallId),
6087
- producerId: config.producerId,
6088
- records: [envelope]
6089
- })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
6090
- knownIds.add(requestRecordId);
6091
- }
6092
- subagentState.requested.set(toolCallId, requestedPayload);
6093
- yield* hit("subagent:after-request-append");
6094
- }
6095
- const admission = yield* establishChildFromRequest(submission, requestedPayload);
6096
- if (admission._tag === "indeterminate") return yield* LedgerError.make({
6097
- operation: "establishSubagent",
6098
- message: `Child admission for Tool Call ${toolCallId} is indeterminate (${admission.reason}); retrying without a second admission (SUB-031)`
6099
- });
6100
- const childRunId = runIdForSubmission(admission.childSubmissionId);
6101
- let startedPayload = subagentState.started.get(toolCallId);
6102
- if (startedPayload === void 0) {
6103
- startedPayload = SubagentStarted.make({
6104
- runId,
6105
- toolCallId,
6106
- childThreadId: requestedPayload.childThreadId,
6107
- childSubmissionId: admission.childSubmissionId,
6108
- childReceiptId: admission.receiptId,
6109
- childRunId
6110
+ const childRunId = runIdForSubmission(admission.childSubmissionId);
6111
+ let startedPayload = subagentState.started.get(toolCallId);
6112
+ if (startedPayload === void 0) {
6113
+ startedPayload = SubagentStarted.make({
6114
+ runId,
6115
+ toolCallId,
6116
+ childThreadId: requestedPayload.childThreadId,
6117
+ childSubmissionId: admission.childSubmissionId,
6118
+ childReceiptId: admission.receiptId,
6119
+ childRunId
6120
+ });
6121
+ const startRecordId = subagentStartedRecordId(runId, toolCallId);
6122
+ if (!knownIds.has(startRecordId)) {
6123
+ const envelope = yield* makeEnvelope(startRecordId, startedPayload);
6124
+ yield* appendBatch(ctx, CanonicalBatch.make({
6125
+ batchId: subagentStartedBatchId(runId, toolCallId),
6126
+ producerId: config.producerId,
6127
+ records: [envelope]
6128
+ })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
6129
+ knownIds.add(startRecordId);
6130
+ }
6131
+ subagentState.started.set(toolCallId, startedPayload);
6132
+ yield* hit("subagent:after-start-append");
6133
+ } else if (startedPayload.childSubmissionId !== admission.childSubmissionId) return yield* LedgerError.make({
6134
+ operation: "establishSubagent",
6135
+ message: `The canonical SubagentStarted record names child ${startedPayload.childSubmissionId} but admission resolved ${admission.childSubmissionId}; establishment fails closed (SUB-016)`
6110
6136
  });
6111
- const startRecordId = subagentStartedRecordId(runId, toolCallId);
6112
- if (!knownIds.has(startRecordId)) {
6113
- const envelope = yield* makeEnvelope(startRecordId, startedPayload);
6137
+ yield* session.attachChildToReservation({
6138
+ reservationId: decodeChildReservationIdSync(requestedPayload.reservationId),
6139
+ childSubmissionId: startedPayload.childSubmissionId
6140
+ }).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("attachChildToReservation")));
6141
+ const identity = {
6142
+ childThreadId: startedPayload.childThreadId,
6143
+ childSubmissionId: startedPayload.childSubmissionId,
6144
+ childRunId: startedPayload.childRunId,
6145
+ receiptId: startedPayload.childReceiptId
6146
+ };
6147
+ const child = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: startedPayload.childSubmissionId }));
6148
+ if (Option.isNone(child)) return yield* LedgerError.make({
6149
+ operation: "establishSubagent",
6150
+ message: `Established child ${startedPayload.childSubmissionId} is unknown to the ledger`
6151
+ });
6152
+ if (child.value.state !== "settled") return {
6153
+ _tag: "waiting",
6154
+ ...identity
6155
+ };
6156
+ const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
6157
+ if (verification._tag === "mismatch") return denied("SubagentVerificationFailed", verification.message);
6158
+ return {
6159
+ _tag: "settled",
6160
+ ...identity,
6161
+ outcome: verification.value.outcome,
6162
+ encodedResult: verification.value.encodedResult,
6163
+ ...yield* verifiedChildUsage(verification.value, startedPayload.childRunId),
6164
+ ...verification.value.settlement.finishReason === void 0 ? {} : { finishReason: verification.value.settlement.finishReason }
6165
+ };
6166
+ }).pipe(establishmentGate.withPermits(1)));
6167
+ const joinSubagent = (request) => recordHalt(Effect.gen(function* () {
6168
+ const toolCallId = request.toolCallId;
6169
+ const turnInfo = currentToolTurn;
6170
+ if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined before any canonical response commit` });
6171
+ const requestedPayload = subagentState.requested.get(toolCallId);
6172
+ const startedPayload = subagentState.started.get(toolCallId);
6173
+ if (requestedPayload === void 0 || startedPayload === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without canonical establishment records` });
6174
+ const reservationId = decodeChildReservationIdSync(requestedPayload.reservationId);
6175
+ const joinedRecordId = subagentJoinedRecordId(runId, toolCallId);
6176
+ let finalAccounting;
6177
+ const existingJoined = subagentState.joined.get(toolCallId);
6178
+ if (existingJoined !== void 0) finalAccounting = existingJoined.finalAccounting;
6179
+ else {
6180
+ const encodedResult = yield* decodePersisted(request.encodedResult).pipe(Effect.mapError((cause) => RunJournalError.make({
6181
+ message: `The projected result of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
6182
+ cause
6183
+ })));
6184
+ const accounting = yield* decodePersisted(request.encodedAccounting).pipe(Effect.mapError((cause) => RunJournalError.make({
6185
+ message: `The join accounting of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
6186
+ cause
6187
+ })));
6188
+ const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
6189
+ if (verification._tag === "mismatch") return yield* LedgerError.make({
6190
+ operation: "joinSubagent",
6191
+ message: `Child Settlement verification failed for Tool Call ${toolCallId}: ${verification.message}`
6192
+ });
6193
+ const verified = verification.value;
6194
+ const toolName = declaredNamesByCallId.get(toolCallId);
6195
+ if (toolName === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without a declared Tool name` });
6196
+ yield* hit("subagent:before-join-append");
6197
+ const joinedPayload = SubagentJoined.make({
6198
+ runId,
6199
+ toolCallId,
6200
+ childSubmissionId: startedPayload.childSubmissionId,
6201
+ childSettlementId: verified.settlement.settlementId,
6202
+ childOutcome: verified.outcome,
6203
+ usageSummary: yield* childUsageSummaryOf(verified.childRecords, startedPayload.childRunId),
6204
+ ...yield* verifiedChildUsage(verified, startedPayload.childRunId),
6205
+ reservationId: requestedPayload.reservationId,
6206
+ finalAccounting: accounting
6207
+ });
6208
+ const settledRecordId = toolCallSettledRecordId(runId, turnInfo.turn, toolCallId);
6209
+ const joinedEnvelope = yield* makeEnvelope(joinedRecordId, joinedPayload);
6210
+ const settledEnvelope = yield* makeEnvelope(settledRecordId, ToolCallSettled.make({
6211
+ runId,
6212
+ toolCallId,
6213
+ toolName,
6214
+ result: encodedResult,
6215
+ isFailure: request.isFailure
6216
+ }));
6114
6217
  yield* appendBatch(ctx, CanonicalBatch.make({
6115
- batchId: subagentStartedBatchId(runId, toolCallId),
6218
+ batchId: subagentJoinBatchId(runId, toolCallId),
6116
6219
  producerId: config.producerId,
6117
- records: [envelope]
6220
+ records: [joinedEnvelope, settledEnvelope]
6118
6221
  })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
6119
- knownIds.add(startRecordId);
6222
+ knownIds.add(joinedRecordId);
6223
+ knownIds.add(settledRecordId);
6224
+ subagentState.joined.set(toolCallId, joinedPayload);
6225
+ finalAccounting = accounting;
6226
+ yield* hit("subagent:after-join-append");
6120
6227
  }
6121
- subagentState.started.set(toolCallId, startedPayload);
6122
- yield* hit("subagent:after-start-append");
6123
- } else if (startedPayload.childSubmissionId !== admission.childSubmissionId) return yield* LedgerError.make({
6124
- operation: "establishSubagent",
6125
- message: `The canonical SubagentStarted record names child ${startedPayload.childSubmissionId} but admission resolved ${admission.childSubmissionId}; establishment fails closed (SUB-016)`
6126
- });
6127
- yield* session.attachChildToReservation({
6128
- reservationId: decodeChildReservationIdSync(requestedPayload.reservationId),
6129
- childSubmissionId: startedPayload.childSubmissionId
6130
- }).pipe(Effect.catchTag("ChildReservationConflict", conflictToLedgerError("attachChildToReservation")));
6131
- const identity = {
6132
- childThreadId: startedPayload.childThreadId,
6133
- childSubmissionId: startedPayload.childSubmissionId,
6134
- childRunId: startedPayload.childRunId,
6135
- receiptId: startedPayload.childReceiptId
6136
- };
6137
- const child = yield* ledger.lookup(SubmissionLookupById.make({ submissionId: startedPayload.childSubmissionId }));
6138
- if (Option.isNone(child)) return yield* LedgerError.make({
6139
- operation: "establishSubagent",
6140
- message: `Established child ${startedPayload.childSubmissionId} is unknown to the ledger`
6141
- });
6142
- if (child.value.state !== "settled") return {
6143
- _tag: "waiting",
6144
- ...identity
6145
- };
6146
- const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
6147
- if (verification._tag === "mismatch") return denied("SubagentVerificationFailed", verification.message);
6148
- return {
6149
- _tag: "settled",
6150
- ...identity,
6151
- outcome: verification.value.outcome,
6152
- encodedResult: verification.value.encodedResult,
6153
- ...yield* verifiedChildUsage(verification.value, startedPayload.childRunId),
6154
- ...verification.value.settlement.finishReason === void 0 ? {} : { finishReason: verification.value.settlement.finishReason }
6155
- };
6156
- }).pipe(establishmentGate.withPermits(1)));
6157
- const joinSubagent = (request) => recordHalt(Effect.gen(function* () {
6158
- const toolCallId = request.toolCallId;
6159
- const turnInfo = currentToolTurn;
6160
- if (turnInfo === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined before any canonical response commit` });
6161
- const requestedPayload = subagentState.requested.get(toolCallId);
6162
- const startedPayload = subagentState.started.get(toolCallId);
6163
- if (requestedPayload === void 0 || startedPayload === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without canonical establishment records` });
6164
- const reservationId = decodeChildReservationIdSync(requestedPayload.reservationId);
6165
- const joinedRecordId = subagentJoinedRecordId(runId, toolCallId);
6166
- let finalAccounting;
6167
- const existingJoined = subagentState.joined.get(toolCallId);
6168
- if (existingJoined !== void 0) finalAccounting = existingJoined.finalAccounting;
6169
- else {
6170
- const encodedResult = yield* decodePersisted(request.encodedResult).pipe(Effect.mapError((cause) => RunJournalError.make({
6171
- message: `The projected result of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
6172
- cause
6173
- })));
6174
- const accounting = yield* decodePersisted(request.encodedAccounting).pipe(Effect.mapError((cause) => RunJournalError.make({
6175
- message: `The join accounting of Tool Call ${toolCallId} exceeds canonical persistence bounds`,
6176
- cause
6177
- })));
6178
- const verification = yield* verifySettledChild(submission, requestedPayload, startedPayload.childSubmissionId);
6179
- if (verification._tag === "mismatch") return yield* LedgerError.make({
6180
- operation: "joinSubagent",
6181
- message: `Child Settlement verification failed for Tool Call ${toolCallId}: ${verification.message}`
6182
- });
6183
- const verified = verification.value;
6184
- const toolName = declaredNamesByCallId.get(toolCallId);
6185
- if (toolName === void 0) return yield* RunJournalError.make({ message: `Delegation Tool Call ${toolCallId} joined without a declared Tool name` });
6186
- yield* hit("subagent:before-join-append");
6187
- const joinedPayload = SubagentJoined.make({
6228
+ yield* applyReservationRelease(reservationId, finalAccounting, {
6229
+ threadId: submission.threadId,
6188
6230
  runId,
6189
- toolCallId,
6190
- childSubmissionId: startedPayload.childSubmissionId,
6191
- childSettlementId: verified.settlement.settlementId,
6192
- childOutcome: verified.outcome,
6193
- usageSummary: yield* childUsageSummaryOf(verified.childRecords, startedPayload.childRunId),
6194
- ...yield* verifiedChildUsage(verified, startedPayload.childRunId),
6195
- reservationId: requestedPayload.reservationId,
6196
- finalAccounting: accounting
6231
+ toolCallId
6197
6232
  });
6198
- const settledRecordId = toolCallSettledRecordId(runId, turnInfo.turn, toolCallId);
6199
- const joinedEnvelope = yield* makeEnvelope(joinedRecordId, joinedPayload);
6200
- const settledEnvelope = yield* makeEnvelope(settledRecordId, ToolCallSettled.make({
6201
- runId,
6202
- toolCallId,
6203
- toolName,
6204
- result: encodedResult,
6205
- isFailure: request.isFailure
6206
- }));
6207
- yield* appendBatch(ctx, CanonicalBatch.make({
6208
- batchId: subagentJoinBatchId(runId, toolCallId),
6209
- producerId: config.producerId,
6210
- records: [joinedEnvelope, settledEnvelope]
6211
- })).pipe(Effect.catchTag("AppendConflict", () => Effect.void), Effect.asVoid);
6212
- knownIds.add(joinedRecordId);
6213
- knownIds.add(settledRecordId);
6214
- subagentState.joined.set(toolCallId, joinedPayload);
6215
- finalAccounting = accounting;
6216
- yield* hit("subagent:after-join-append");
6217
- }
6218
- yield* applyReservationRelease(reservationId, finalAccounting, {
6233
+ }));
6234
+ const subagent = {
6235
+ establish: establishSubagent,
6236
+ join: joinSubagent
6237
+ };
6238
+ const toolAuthorization = inheritedGrant === void 0 && runToolAuthorization === RunToolAuthorization.allowAllPolicy ? runToolAuthorization : { authorize: (request) => inheritedGrant !== void 0 && !inheritedGrant.allowedToolNames.includes(request.call.toolName) ? Effect.succeed({
6239
+ _tag: "denied",
6240
+ reason: "Tool exceeds the worker's immutable grant"
6241
+ }) : runToolAuthorization.authorize({
6242
+ ...request,
6243
+ input: submission.inputPayload,
6244
+ ...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {}
6245
+ }) };
6246
+ const options = {
6219
6247
  threadId: submission.threadId,
6220
6248
  runId,
6221
- toolCallId
6222
- });
6223
- }));
6224
- const subagent = {
6225
- establish: establishSubagent,
6226
- join: joinSubagent
6227
- };
6228
- const toolAuthorization = inheritedGrant === void 0 && runToolAuthorization === RunToolAuthorization.allowAllPolicy ? runToolAuthorization : { authorize: (request) => inheritedGrant !== void 0 && !inheritedGrant.allowedToolNames.includes(request.call.toolName) ? Effect.succeed({
6229
- _tag: "denied",
6230
- reason: "Tool exceeds the worker's immutable grant"
6231
- }) : runToolAuthorization.authorize({
6232
- ...request,
6233
- input: submission.inputPayload,
6234
- ...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {}
6235
- }) };
6236
- const options = {
6237
- threadId: submission.threadId,
6238
- runId,
6239
- history: pending === void 0 ? journal.historyBefore : resumeProjection.historyBefore,
6240
- input,
6241
- commandDrainPolicy: "all",
6242
- ...priorContext !== void 0 || journal.committedTurns > 0 || Schema.is(FrameworkMessage)(submission.messageAdmission) ? { retainedInput: submission.inputPayload } : {},
6243
- ...priorContext === void 0 ? {} : { retainedContext: Prompt.fromMessages(priorContext.prompt.content.slice(priorContext.priorHistoryLength)) },
6244
- ...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {},
6245
- approval,
6246
- toolAuthorization,
6247
- ...journal.toolSelection === void 0 ? {} : { toolSelection: { toolNames: journal.toolSelection.toolNames.filter((name) => Object.hasOwn(agent.definition.toolkit.tools, name)) } },
6248
- durability,
6249
- subagent,
6250
- delegationDepth,
6251
- ...inheritedGrant === void 0 ? {} : { subagentGrant: inheritedGrant },
6252
- ...inheritedBudget === void 0 ? {} : { subagentBudget: inheritedBudget },
6253
- ...submission.workerAdmission?.origin.budgetScope === void 0 ? {} : { subagentBudgetScope: submission.workerAdmission.origin.budgetScope },
6254
- runStartedAt: runTiming.startedAt,
6255
- durationDeadline: runTiming.deadline,
6256
- ...submission.workerAdmission === void 0 ? {} : { toolCallAllowance: submission.workerAdmission.origin.toolCallAllowance },
6257
- ...submission.parentLinkage !== void 0 && childLineage?._tag === "SubagentLineageRecorded" ? { toolCallAllowance: childLineage.toolCallAllowance } : {},
6258
- ...pending === void 0 ? {} : { resume: {
6259
- ...settledCompletion === void 0 ? {} : { settledCompletion },
6260
- turn: pending.turn,
6261
- toolResultMaxBytes: pending.toolResultMaxBytes,
6262
- turnId: pending.turnId,
6263
- calls: pending.calls,
6264
- toolParameterRejections: pending.toolParameterRejections,
6265
- settled: pending.settled,
6266
- toolExposure: pending.toolExposure ?? Snapshot.make({ exposedToolNames: [...new Set(pending.calls.map((call) => call.name))] }),
6267
- ...resumeLeadingMessages === void 0 ? {} : { leadingMessages: resumeLeadingMessages },
6268
- ...resumeResponseMessages === void 0 ? {} : { responseMessages: resumeResponseMessages }
6269
- } },
6270
- ...preparedContext === void 0 ? {} : { context: preparedContext },
6271
- beforeTurn: () => Effect.gen(function* () {
6272
- if (yieldAfter !== void 0 && (yield* Clock.currentTimeMillis) >= DateTime.toEpochMillis(yieldAfter)) {
6273
- yield* Deferred.succeed(yieldSignal, void 0);
6274
- return yield* Effect.never;
6275
- }
6276
- if (submissionScheduling.yieldTo !== void 0 && (yield* Ref.get(turnCounter)) > 0) {
6277
- const candidate = yield* recordHalt(eligibleThreadHead(submission.threadId, submission.queueSequence));
6278
- if (Option.isSome(candidate) && (candidate.value.state === "ready" || candidate.value.state === "input-applied")) {
6279
- const next = yield* recordHalt(ledger.lookup(SubmissionLookupById.make({ submissionId: candidate.value.submissionId })));
6280
- if (Option.isSome(next) && next.value.agentId === submission.agentId && (next.value.state === "ready" || next.value.state === "input-applied") && (yield* recordHalt(submissionScheduling.yieldTo({
6281
- active: submission,
6282
- next: next.value
6283
- })))) {
6284
- yield* Deferred.succeed(yieldSignal, next.value.submissionId);
6285
- return yield* Effect.never;
6249
+ history: pending === void 0 ? journal.historyBefore : resumeProjection.historyBefore,
6250
+ input,
6251
+ commandDrainPolicy: "all",
6252
+ ...priorContext !== void 0 || journal.committedTurns > 0 || Schema.is(FrameworkMessage)(submission.messageAdmission) ? { retainedInput: submission.inputPayload } : {},
6253
+ ...priorContext === void 0 ? {} : { retainedContext: Prompt.fromMessages(priorContext.prompt.content.slice(priorContext.priorHistoryLength)) },
6254
+ ...Schema.is(FrameworkMessage)(submission.messageAdmission) ? { frameworkMessage: submission.messageAdmission } : {},
6255
+ approval,
6256
+ toolAuthorization,
6257
+ ...journal.toolSelection === void 0 ? {} : { toolSelection: { toolNames: journal.toolSelection.toolNames.filter((name) => Object.hasOwn(agent.definition.toolkit.tools, name)) } },
6258
+ durability,
6259
+ subagent,
6260
+ delegationDepth,
6261
+ ...inheritedGrant === void 0 ? {} : { subagentGrant: inheritedGrant },
6262
+ ...inheritedBudget === void 0 ? {} : { subagentBudget: inheritedBudget },
6263
+ ...submission.workerAdmission?.origin.budgetScope === void 0 ? {} : { subagentBudgetScope: submission.workerAdmission.origin.budgetScope },
6264
+ runStartedAt: runTiming.startedAt,
6265
+ durationDeadline: runTiming.deadline,
6266
+ ...submission.workerAdmission === void 0 ? {} : { toolCallAllowance: submission.workerAdmission.origin.toolCallAllowance },
6267
+ ...submission.parentLinkage !== void 0 && childLineage?._tag === "SubagentLineageRecorded" ? { toolCallAllowance: childLineage.toolCallAllowance } : {},
6268
+ ...pending === void 0 ? {} : { resume: {
6269
+ ...settledCompletion === void 0 ? {} : { settledCompletion },
6270
+ turn: pending.turn,
6271
+ toolResultMaxBytes: pending.toolResultMaxBytes,
6272
+ turnId: pending.turnId,
6273
+ calls: pending.calls,
6274
+ toolParameterRejections: pending.toolParameterRejections,
6275
+ settled: pending.settled,
6276
+ toolExposure: pending.toolExposure ?? Snapshot.make({ exposedToolNames: [...new Set(pending.calls.map((call) => call.name))] }),
6277
+ ...resumeLeadingMessages === void 0 ? {} : { leadingMessages: resumeLeadingMessages },
6278
+ ...resumeResponseMessages === void 0 ? {} : { responseMessages: resumeResponseMessages }
6279
+ } },
6280
+ ...preparedContext === void 0 ? {} : { context: preparedContext },
6281
+ beforeTurn: Effect.fnUntraced(function* () {
6282
+ if (yieldAfter !== void 0 && (yield* Clock.currentTimeMillis) >= DateTime.toEpochMillis(yieldAfter)) {
6283
+ yield* Deferred.succeed(yieldSignal, void 0);
6284
+ return yield* Effect.never;
6285
+ }
6286
+ if (submissionScheduling.yieldTo !== void 0 && (yield* Ref.get(turnCounter)) > 0) {
6287
+ const candidate = yield* recordHalt(eligibleThreadHead(submission.threadId, submission.queueSequence));
6288
+ if (Option.isSome(candidate) && (candidate.value.state === "ready" || candidate.value.state === "input-applied")) {
6289
+ const next = yield* recordHalt(ledger.lookup(SubmissionLookupById.make({ submissionId: candidate.value.submissionId })));
6290
+ if (Option.isSome(next) && next.value.agentId === submission.agentId && (next.value.state === "ready" || next.value.state === "input-applied") && (yield* recordHalt(submissionScheduling.yieldTo({
6291
+ active: submission,
6292
+ next: next.value
6293
+ })))) {
6294
+ yield* Deferred.succeed(yieldSignal, next.value.submissionId);
6295
+ return yield* Effect.never;
6296
+ }
6286
6297
  }
6287
6298
  }
6288
- }
6289
- }),
6290
- ...runContextPreparation.transientContext === void 0 ? {} : { transientContext: runContextPreparation.transientContext },
6291
- ...config.estimateCostMicrousd === void 0 ? {} : { estimateCostMicrousd: config.estimateCostMicrousd },
6292
- resumeUsage: {
6293
- ...journal.usage,
6294
- ...journal.policyUsage,
6295
- ...journal.usage.modelCalls === 0 && (journal.usage.unobservedModelCalls ?? 0) === 0 && !records.some(({ record }) => record.payload._tag === "ModelResponseInterrupted" && record.payload.runId === runId) ? emptyRunTotals() : runTotalsFromSummary(yield* currentUsageSummary()),
6296
- children: childUsageReportsOf(subagentState)
6297
- },
6298
- ...journal.contextWindowId === void 0 ? {} : { initialContextWindowId: journal.contextWindowId },
6299
- ...journal.protectedContext === void 0 ? {} : { protectedContext: journal.protectedContext },
6300
- ...pendingContextToolCallId === void 0 ? {} : { pendingContextToolCallId }
6301
- };
6302
- if (pending === void 0 && lineage.inputWasRecorded) {
6303
- yield* appendInterruptedAudit(ctx, runId, knownIds);
6304
- interruptedUsage = true;
6305
- }
6306
- const consume = executeWithUsageAccountingUnknown(agent, submission.inputPayload, options).pipe(Effect.provideService(AgentUpdateAcceptance, { accept: (update) => flushDeferredResponse.pipe(Effect.catch((failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" }))))), Effect.andThen(() => updateRuntime.emit({
6307
- updateId: update.updateId,
6308
- value: update.value,
6309
- submission,
6310
- runId,
6311
- definitions: submission.agentDigests
6312
- }).pipe(Effect.provideService(CurrentRunWriter, ctx))), Effect.catchTag(["LedgerError", "DurableRuntimeFailpointError"], (failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" })))))) }), Effect.provideService(ModelUsageAccounting, { noteIncompleteUsage: (turn) => Effect.sync(() => {
6313
- stagedUnobservedCalls.set(turn, (stagedUnobservedCalls.get(turn) ?? 0) + 1);
6314
- }) }), Effect.provide(ThreadHistory.layer), Effect.provideService(SubagentHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? SubagentHost.unavailable : workerRuntime.facet({
6315
- source,
6316
- policy: agent.definition.policy,
6317
- depth: delegationDepth,
6318
- ...inheritedGrant === void 0 ? {} : { grant: inheritedGrant }
6319
- }, submission.principal, submission.submissionId)), Effect.provideService(MessagingHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? MessagingHost.unavailable : messagingRuntime.forTool(source, submission.principal)), Effect.provideService(CurrentToolFailureObserver, toolFailureObserver), Effect.provideService(RunToolVisibility, runToolVisibility), Effect.provideService(RunToolScheduling, runToolScheduling), Effect.provideService(ContextCompactor, compactor), Effect.provideService(RunContextPreparation, runContextPreparation), Effect.andThen(checkpoint), Effect.catchCause((cause) => Ref.get(haltRef).pipe(Effect.flatMap((failure) => failure === void 0 ? Effect.failCause(cause) : Effect.failCause(Cause.map(cause, (error) => error instanceof CoordinatorHalt ? error : new CoordinatorHalt(failure)))))), Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
6320
- const abortWatcher = halt(Effect.gen(function* () {
6321
- while (true) {
6322
- yield* Effect.sleep(config.abortPollInterval);
6323
- const intent = yield* ledger.readAbortIntent(AbortIntentRequest.make({ submissionId }));
6324
- if (intent === void 0) continue;
6325
- yield* appendAbortRecord(ctx, intent);
6326
- return { _tag: "aborted" };
6327
- }
6328
- }));
6329
- const execution = Effect.raceFirst(consume, abortWatcher);
6330
- const result = yield* (yieldAfter === void 0 && submissionScheduling.yieldTo === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.map((nextSubmissionId) => ({
6331
- _tag: "yielded",
6332
- ...nextSubmissionId === void 0 ? {} : { nextSubmissionId }
6333
- }))))).pipe(Effect.provideService(IdGenerator$1, idGenerator)).pipe(Effect.catchCauseFilter(Cause.findError, (error, cause) => {
6334
- if (isCoordinatorHaltCause(cause)) return Effect.failCause(Cause.map(cause, (halt) => halt.failure));
6335
- if (cause.reasons.some((reason) => reason._tag === "Fail" && reason.error instanceof AgentInputDecodeError)) return Effect.failCause(Cause.map(cause, () => BindingUnavailable.make({
6336
- agentId: agent.definition.id,
6337
- message: "The current Binding cannot decode accepted input"
6338
- })));
6339
- const approvalPending = agentApprovalPendingOption(cause);
6340
- if (Option.isSome(approvalPending)) {
6341
- const residual = Cause.fromReasons(cause.reasons.filter((reason) => reason._tag !== "Fail"));
6342
- if (residual.reasons.length > 0) return Effect.failCause(residual);
6343
- return decodeToolCallIdUnknown(approvalPending.value.toolCallId).pipe(Effect.orDie, Effect.map((toolCallId) => ({
6344
- _tag: "suspendedRun",
6345
- toolCallId
6346
- })));
6299
+ }),
6300
+ ...runContextPreparation.transientContext === void 0 ? {} : { transientContext: runContextPreparation.transientContext },
6301
+ ...config.estimateCostMicrousd === void 0 ? {} : { estimateCostMicrousd: config.estimateCostMicrousd },
6302
+ resumeUsage: {
6303
+ ...journal.usage,
6304
+ ...journal.policyUsage,
6305
+ ...journal.usage.modelCalls === 0 && (journal.usage.unobservedModelCalls ?? 0) === 0 && !records.some(({ record }) => record.payload._tag === "ModelResponseInterrupted" && record.payload.runId === runId) ? emptyRunTotals() : runTotalsFromSummary(yield* currentUsageSummary()),
6306
+ children: childUsageReportsOf(subagentState)
6307
+ },
6308
+ ...journal.contextWindowId === void 0 ? {} : { initialContextWindowId: journal.contextWindowId },
6309
+ ...journal.protectedContext === void 0 ? {} : { protectedContext: journal.protectedContext },
6310
+ ...pendingContextToolCallId === void 0 ? {} : { pendingContextToolCallId }
6311
+ };
6312
+ if (pending === void 0 && lineage.inputWasRecorded) {
6313
+ yield* appendInterruptedAudit(ctx, runId, knownIds);
6314
+ interruptedUsage = true;
6347
6315
  }
6348
- const childPending = agentChildPendingOption(error);
6349
- if (Option.isSome(childPending)) return Effect.succeed({
6350
- _tag: "suspendedChildRun",
6351
- children: childPending.value.children
6352
- });
6353
- return Effect.gen(function* () {
6354
- const halted = yield* Ref.get(haltRef);
6355
- if (halted !== void 0) return yield* halted;
6356
- yield* flushDeferredResponse;
6357
- if (error instanceof AgentToolAuthorizationDenied) {
6316
+ const consume = executeWithUsageAccountingUnknown(agent, submission.inputPayload, options).pipe(Effect.provideService(AgentUpdateAcceptance, { accept: (update) => flushDeferredResponse.pipe(Effect.catch((failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" }))))), Effect.andThen(() => updateRuntime.emit({
6317
+ updateId: update.updateId,
6318
+ value: update.value,
6319
+ submission,
6320
+ runId,
6321
+ definitions: submission.agentDigests
6322
+ }).pipe(Effect.provideService(CurrentRunWriter, ctx))), Effect.catchTag(["LedgerError", "DurableRuntimeFailpointError"], (failure) => Ref.set(haltRef, failure).pipe(Effect.andThen(Effect.fail(UpdateError.make({ reason: "storage" })))))) }), Effect.provideService(ModelUsageAccounting, { noteIncompleteUsage: (turn) => Effect.sync(() => {
6323
+ stagedUnobservedCalls.set(turn, (stagedUnobservedCalls.get(turn) ?? 0) + 1);
6324
+ }) }), Effect.provide(ThreadHistory.layer), Effect.provideService(SubagentHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? SubagentHost.unavailable : workerRuntime.facet({
6325
+ source,
6326
+ policy: agent.definition.policy,
6327
+ depth: delegationDepth,
6328
+ ...inheritedGrant === void 0 ? {} : { grant: inheritedGrant }
6329
+ }, submission.principal, submission.submissionId)), Effect.provideService(MessagingHost.forTool, (source) => source.threadId !== submission.threadId || source.agentId !== submission.agentId || source.runId !== runId ? MessagingHost.unavailable : messagingRuntime.forTool(source, submission.principal)), Effect.provideService(CurrentToolFailureObserver, toolFailureObserver), Effect.provideService(RunToolVisibility, runToolVisibility), Effect.provideService(RunToolScheduling, runToolScheduling), Effect.provideService(ContextCompactor, compactor), Effect.provideService(RunContextPreparation, runContextPreparation), Effect.andThen(checkpoint), Effect.catchCause((cause) => Ref.get(haltRef).pipe(Effect.flatMap((failure) => failure === void 0 ? Effect.failCause(cause) : Effect.failCause(Cause.map(cause, (error) => error instanceof CoordinatorHalt ? error : new CoordinatorHalt(failure)))))), Effect.tapCause((cause) => Option.isSome(agentApprovalPendingOption(cause)) && cause.reasons.every(Cause.isFailReason) ? Effect.flatMap(DurableApprovalSuspension, (retain) => retain === void 0 ? Effect.void : halt(retain)) : Effect.void), Effect.as({ _tag: "run" }));
6330
+ const abortWatcher = halt(Effect.gen(function* () {
6331
+ while (true) {
6332
+ yield* Effect.sleep(config.abortPollInterval);
6358
6333
  const intent = yield* ledger.readAbortIntent(AbortIntentRequest.make({ submissionId }));
6359
- if (intent !== void 0) {
6360
- yield* appendAbortRecord(ctx, intent);
6361
- return { _tag: "aborted" };
6362
- }
6334
+ if (intent === void 0) continue;
6335
+ yield* appendAbortRecord(ctx, intent);
6336
+ return { _tag: "aborted" };
6363
6337
  }
6364
- if (cause.reasons.some((reason) => reason._tag === "Die" || reason._tag === "Fail" && !(reason.error instanceof AgentApprovalDenied) && !(reason.error instanceof AgentToolAuthorizationDenied))) yield* Effect.logError("Agent run failed", cause).pipe(Effect.annotateLogs({
6338
+ }));
6339
+ const execution = Effect.raceFirst(consume, abortWatcher);
6340
+ const result = yield* (yieldAfter === void 0 && submissionScheduling.yieldTo === void 0 ? execution : Effect.raceFirst(execution, Deferred.await(yieldSignal).pipe(Effect.map((nextSubmissionId) => ({
6341
+ _tag: "yielded",
6342
+ ...nextSubmissionId === void 0 ? {} : { nextSubmissionId }
6343
+ }))))).pipe(Effect.provideService(IdGenerator$1, idGenerator)).pipe(Effect.catchCauseFilter(Cause.findError, (error, cause) => {
6344
+ if (isCoordinatorHaltCause(cause)) return Effect.failCause(Cause.map(cause, (halt) => halt.failure));
6345
+ if (cause.reasons.some((reason) => reason._tag === "Fail" && reason.error instanceof AgentInputDecodeError)) return Effect.failCause(Cause.map(cause, () => BindingUnavailable.make({
6365
6346
  agentId: agent.definition.id,
6366
- runId,
6367
- threadId: ctx.threadId,
6368
- submissionId,
6369
- attemptId: lineage.attemptId
6370
- }));
6371
- return {
6372
- _tag: "failedRun",
6373
- outcome: yield* failureOutcome(error, cause, {
6347
+ message: "The current Binding cannot decode accepted input"
6348
+ })));
6349
+ const approvalPending = agentApprovalPendingOption(cause);
6350
+ if (Option.isSome(approvalPending)) {
6351
+ const residual = Cause.fromReasons(cause.reasons.filter((reason) => reason._tag !== "Fail"));
6352
+ if (residual.reasons.length > 0) return Effect.failCause(residual);
6353
+ return decodeToolCallIdUnknown(approvalPending.value.toolCallId).pipe(Effect.orDie, Effect.map((toolCallId) => ({
6354
+ _tag: "suspendedRun",
6355
+ toolCallId
6356
+ })));
6357
+ }
6358
+ const childPending = agentChildPendingOption(error);
6359
+ if (Option.isSome(childPending)) return Effect.succeed({
6360
+ _tag: "suspendedChildRun",
6361
+ children: childPending.value.children
6362
+ });
6363
+ return Effect.gen(function* () {
6364
+ const halted = yield* Ref.get(haltRef);
6365
+ if (halted !== void 0) return yield* halted;
6366
+ yield* flushDeferredResponse;
6367
+ if (error instanceof AgentToolAuthorizationDenied) {
6368
+ const intent = yield* ledger.readAbortIntent(AbortIntentRequest.make({ submissionId }));
6369
+ if (intent !== void 0) {
6370
+ yield* appendAbortRecord(ctx, intent);
6371
+ return { _tag: "aborted" };
6372
+ }
6373
+ }
6374
+ if (cause.reasons.some((reason) => reason._tag === "Die" || reason._tag === "Fail" && !(reason.error instanceof AgentApprovalDenied) && !(reason.error instanceof AgentToolAuthorizationDenied))) yield* Effect.logError("Agent run failed", cause).pipe(Effect.annotateLogs({
6374
6375
  agentId: agent.definition.id,
6375
6376
  runId,
6376
6377
  threadId: ctx.threadId,
6377
6378
  submissionId,
6378
6379
  attemptId: lineage.attemptId
6379
- })
6380
+ }));
6381
+ return {
6382
+ _tag: "failedRun",
6383
+ outcome: yield* failureOutcome(error, cause, {
6384
+ agentId: agent.definition.id,
6385
+ runId,
6386
+ threadId: ctx.threadId,
6387
+ submissionId,
6388
+ attemptId: lineage.attemptId
6389
+ })
6390
+ };
6391
+ });
6392
+ }));
6393
+ if (result._tag === "yielded") return result;
6394
+ if (result._tag === "suspendedRun") return approvalSuspension(result.toolCallId);
6395
+ if (result._tag === "suspendedChildRun") return childSuspension(result.children);
6396
+ if (result._tag === "aborted") {
6397
+ yield* flushDeferredResponse;
6398
+ return {
6399
+ ...abortedRunPhase(yield* currentUsageSummary()),
6400
+ uncommittedModelUsage: uncommittedModelUsage()
6380
6401
  };
6402
+ }
6403
+ if (result._tag === "failedRun") return {
6404
+ ...result.outcome,
6405
+ usageSummary: yield* currentUsageSummary(),
6406
+ uncommittedModelUsage: uncommittedModelUsage()
6407
+ };
6408
+ const committedCompletion = completionState.committed;
6409
+ if (committedCompletion === void 0) return yield* LedgerError.make({
6410
+ operation: "runModel",
6411
+ message: "Agent Run ended without a committed completion"
6381
6412
  });
6382
- }));
6383
- if (result._tag === "yielded") return result;
6384
- if (result._tag === "suspendedRun") return approvalSuspension(result.toolCallId);
6385
- if (result._tag === "suspendedChildRun") return childSuspension(result.children);
6386
- if (result._tag === "aborted") {
6387
- yield* flushDeferredResponse;
6388
6413
  return {
6389
- ...abortedRunPhase(yield* currentUsageSummary()),
6414
+ _tag: "completed",
6415
+ result: committedCompletion.output,
6416
+ ...committedCompletion.runDisposition === void 0 ? {} : { runDisposition: committedCompletion.runDisposition },
6417
+ ...committedCompletion.finishReason === void 0 ? {} : { finishReason: committedCompletion.finishReason },
6418
+ ...committedCompletion.exhausted === void 0 ? {} : { exhausted: committedCompletion.exhausted },
6419
+ usageSummary: yield* currentUsageSummary(),
6390
6420
  uncommittedModelUsage: uncommittedModelUsage()
6391
6421
  };
6392
6422
  }
6393
- if (result._tag === "failedRun") return {
6394
- ...result.outcome,
6395
- usageSummary: yield* currentUsageSummary(),
6396
- uncommittedModelUsage: uncommittedModelUsage()
6397
- };
6398
- const committedCompletion = completionState.committed;
6399
- if (committedCompletion === void 0) return yield* LedgerError.make({
6400
- operation: "runModel",
6401
- message: "Agent Run ended without a committed completion"
6402
- });
6403
- return {
6404
- _tag: "completed",
6405
- result: committedCompletion.output,
6406
- ...committedCompletion.runDisposition === void 0 ? {} : { runDisposition: committedCompletion.runDisposition },
6407
- ...committedCompletion.finishReason === void 0 ? {} : { finishReason: committedCompletion.finishReason },
6408
- ...committedCompletion.exhausted === void 0 ? {} : { exhausted: committedCompletion.exhausted },
6409
- usageSummary: yield* currentUsageSummary(),
6410
- uncommittedModelUsage: uncommittedModelUsage()
6411
- };
6412
- });
6423
+ );
6413
6424
  /**
6414
6425
  * One ownership period over the claimed lane head. The step order mirrors the pure recovery
6415
6426
  * classifier's decision table, so a fresh Attempt and a recovering Attempt take the same path
@@ -6417,7 +6428,7 @@ const make = Effect.fnUntraced(function* (bindings) {
6417
6428
  * (Unknown Outcomes, or a durable approval suspension) — no settlement occurs and the
6418
6429
  * obligation stays owed.
6419
6430
  */
6420
- const runAttempt = (registeredAgent, session, resumeAfterRetention, onHandoff, yieldAfter) => Effect.gen(function* () {
6431
+ const runAttempt = Effect.fnUntraced(function* (registeredAgent, session, resumeAfterRetention, onHandoff, yieldAfter) {
6421
6432
  yield* session.checkActive;
6422
6433
  const checkpointPrompt = yield* promptHistory.take({ threadId: session.threadId }).pipe(Effect.provideService(ThreadStore, store), Effect.provideService(ThreadReader, reader), Effect.provideService(Crypto.Crypto, crypto));
6423
6434
  let committedPromptSuffix;
@@ -6473,7 +6484,7 @@ const make = Effect.fnUntraced(function* (bindings) {
6473
6484
  journalMetadata = void 0;
6474
6485
  return metadata;
6475
6486
  };
6476
- let records = yield* Stream.runCollect(initialView.canonical.pipe(Stream.filter(collectControl)));
6487
+ let records = initialView.records.filter(collectControl);
6477
6488
  const refreshControl = Effect.fnUntraced(function* (throughSequence) {
6478
6489
  const through = throughSequence ?? (yield* store.inspectTail(ThreadTailRequest.make({ threadId }))).tailSequence;
6479
6490
  if (through > controlThrough) {
@@ -6513,7 +6524,7 @@ const make = Effect.fnUntraced(function* (bindings) {
6513
6524
  return Option.some(yield* settleAborted(ctx, submission, session.publishSettlement, snapshot.abortIntent, evidence, knownIds));
6514
6525
  }
6515
6526
  yield* applyCanonicalInput(ctx, submission, session, records, snapshot.inputApplied);
6516
- const start = yield* makeRunStart(submission, Duration.toMillis(agent.definition.policy.maxDuration), yield* refreshControl()).pipe(Effect.provideService(CurrentRunWriter, ctx));
6527
+ const start = yield* makeRunStart(submission, Duration.toMillis(agent.definition.policy.maxDuration), yield* refreshControl(), initialView.operational).pipe(Effect.provideService(CurrentRunWriter, ctx));
6517
6528
  const savedRunTiming = start.timing;
6518
6529
  const commitStart = Effect.flatMap(CurrentRunStart, (publication) => publication.commit()).pipe(Effect.provideService(CurrentRunStart, start.publication));
6519
6530
  const runTiming = workerOrigin === void 0 ? savedRunTiming : {
@@ -6623,7 +6634,7 @@ const make = Effect.fnUntraced(function* (bindings) {
6623
6634
  const tail = yield* session.tail;
6624
6635
  const currentRecords = yield* refreshControl(tail.sequence);
6625
6636
  const view = yield* recoveryView(threadId, tail.sequence, [submissionId], runIdForSubmission(submissionId), currentRecords);
6626
- let canonical = view.canonical;
6637
+ let canonical = Stream.fromIterable(view.records);
6627
6638
  let initialJournal;
6628
6639
  if (view.context === void 0) {
6629
6640
  const original = currentRecords.find(({ record }) => record.payload._tag === "UserInputRecorded" && record.payload.kind === "user" && record.payload.submissionId === submissionId);
@@ -6733,7 +6744,7 @@ const make = Effect.fnUntraced(function* (bindings) {
6733
6744
  if (outcome._tag === "completed" && initialJournal?.cacheable && initialJournal.history !== void 0) yield* promptHistory.complete({ threadId: session.threadId }, initialJournal.original, initialJournal.history, committedPromptSuffix).pipe(Effect.provideService(CurrentRunWriter, session), Effect.provideService(ThreadStore, store), Effect.provideService(ThreadReader, reader));
6734
6745
  return Option.some(settlement);
6735
6746
  }
6736
- }).pipe(Effect.scoped);
6747
+ }, (effect) => effect.pipe(Effect.scoped));
6737
6748
  const acquireAdministrativeClaim = (threadId, handoff) => runStorage.claim(ClaimRequest.make({
6738
6749
  threadId,
6739
6750
  ...handoff === void 0 ? {} : { handoff }
@@ -6819,7 +6830,7 @@ const make = Effect.fnUntraced(function* (bindings) {
6819
6830
  settlements.push(settlement.value);
6820
6831
  }
6821
6832
  }).pipe((body) => withProcessing(threadId, body));
6822
- const processThreadImpl = (agent, threadId) => Effect.gen(function* () {
6833
+ const processThreadImpl = Effect.fnUntraced(function* (agent, threadId) {
6823
6834
  const binding = yield* makeLegacyWorkerBinding(agent);
6824
6835
  return yield* drainThread((submission) => submission.agentId === binding.agentId ? Effect.succeed(binding) : Effect.fail(BindingUnavailable.make({
6825
6836
  agentId: submission.agentId,
@@ -7221,8 +7232,7 @@ const make = Effect.fnUntraced(function* (bindings) {
7221
7232
  const snapshot = yield* ledger.loadRecoverySnapshot(RecoverySnapshotRequest.make({ submissionId: submission.submissionId }));
7222
7233
  if (snapshot.hostSubmissionId !== void 0 && !history.submissionIds.includes(snapshot.hostSubmissionId)) {
7223
7234
  const hostId = snapshot.hostSubmissionId;
7224
- const hostView = yield* recoveryView(submission.threadId, history.throughSequence, [hostId]);
7225
- const hostRecords = yield* Stream.runCollect(hostView.canonical.pipe(Stream.filter(controlRecords([hostId]))));
7235
+ const hostRecords = (yield* recoveryView(submission.threadId, history.throughSequence, [hostId])).records.filter(controlRecords([hostId]));
7226
7236
  const merged = new Map(history.records.map((entry) => [entry.sequence, entry]));
7227
7237
  for (const entry of hostRecords) merged.set(entry.sequence, entry);
7228
7238
  history = {
@@ -7776,10 +7786,6 @@ const make = Effect.fnUntraced(function* (bindings) {
7776
7786
  submissionId: receipt.submissionId
7777
7787
  });
7778
7788
  if (snapshot.value.state !== "settled") return Option.none();
7779
- const settlement = yield* ledger.finalizeSettlement(SettlementFinalization.make({
7780
- submissionId: receipt.submissionId,
7781
- settlementId: submissionSettlementId(receipt.submissionId)
7782
- }));
7783
7789
  const canonical = yield* getRecord({
7784
7790
  threadId: receipt.threadId,
7785
7791
  recordId: submissionSettlementRecordId(receipt.submissionId)
@@ -7793,6 +7799,23 @@ const make = Effect.fnUntraced(function* (bindings) {
7793
7799
  message: "Finalized Submission has no canonical Settlement"
7794
7800
  });
7795
7801
  const record = yield* settlementPayloadFromRecord(canonical.value.record, receipt.submissionId);
7802
+ const finalized = snapshot.value;
7803
+ const retainedFinalization = finalized.settledAt !== void 0 && finalized.settledRecordId !== void 0 && finalized.settledOutcome !== void 0;
7804
+ if (retainedFinalization && (finalized.settledRecordId !== canonical.value.record.recordId || finalized.settledOutcome !== record.outcome || canonical.value.batchId !== submissionSettlementBatchId(receipt.submissionId))) return yield* LedgerError.make({
7805
+ operation: "awaitSettlement",
7806
+ message: "Settled projection disagrees with its canonical Settlement"
7807
+ });
7808
+ const settlement = retainedFinalization ? Settlement.make({
7809
+ submissionId: receipt.submissionId,
7810
+ settlementId: record.settlementId,
7811
+ receiptId: record.receiptId,
7812
+ outcome: record.outcome,
7813
+ ...record.outcome === "failed" ? { failure: record.result } : {},
7814
+ settledAt: finalized.settledAt
7815
+ }) : yield* ledger.finalizeSettlement(SettlementFinalization.make({
7816
+ submissionId: receipt.submissionId,
7817
+ settlementId: submissionSettlementId(receipt.submissionId)
7818
+ }));
7796
7819
  if (record.receiptId !== receipt.receiptId || record.settlementId !== settlement.settlementId || record.outcome !== settlement.outcome) return yield* LedgerError.make({
7797
7820
  operation: "awaitSettlement",
7798
7821
  message: "Canonical Settlement disagrees with the receipt or finalized outcome"
@@ -8348,4 +8371,4 @@ var DurableAgentRuntime = class DurableAgentRuntime extends Context.Service()("@
8348
8371
  //#endregion
8349
8372
  export { DurableApprovalSuspension as a, RecoveryFailure as c, WorkRecoveryReport as d, WorkRecoveryRequest as f, recoveryRepairRecordId as g, recoveryRepairBatchId as h, DurableApprovalResolver as i, RecoveryReport as l, isolateRecovery as m, DurableAgentRuntime as n, DurableRuntimeConfig as o, childReservationIdFor as p, DurableAgentRuntime_exports as r, RecoveryBlocked as s, ApprovalSuspensionError as t, RecoverySweepResult as u };
8350
8373
 
8351
- //# sourceMappingURL=DurableAgentRuntime-BAmSkWYr.mjs.map
8374
+ //# sourceMappingURL=DurableAgentRuntime-CBBjRNJN.mjs.map