effect-agent 0.1.0-beta.85 → 0.1.0-beta.87

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 (751) hide show
  1. package/dist/Agent-CN0EWRsR.d.mts +226 -0
  2. package/dist/Agent-RklVROrm.mjs +83 -0
  3. package/dist/Agent-RklVROrm.mjs.map +1 -0
  4. package/dist/AgentError-CggcAQ7V.d.mts +101 -0
  5. package/dist/AgentPolicy-CetmQrf3.d.mts +96 -0
  6. package/dist/AgentRuntime-BLyETCPo.mjs +4562 -0
  7. package/dist/AgentRuntime-BLyETCPo.mjs.map +1 -0
  8. package/dist/AgentRuntime-uxR_a4VM.d.mts +346 -0
  9. package/dist/AgentUpdates-DMJ-_xow.d.mts +53 -0
  10. package/dist/ContextCompactor-Dxu5zhOL.d.mts +161 -0
  11. package/dist/ContextWindow-DRQ5Mbm2.d.mts +58 -0
  12. package/dist/DurableAgentRuntime-uggeJpv3.mjs +6368 -0
  13. package/dist/DurableAgentRuntime-uggeJpv3.mjs.map +1 -0
  14. package/dist/DurableFailpoint-Oinuuedm.d.mts +41 -0
  15. package/dist/DurableStep-Cry_iol4.d.mts +103 -0
  16. package/dist/Ephemeral.d.mts +22 -0
  17. package/dist/Ephemeral.mjs +22 -0
  18. package/dist/Ephemeral.mjs.map +1 -0
  19. package/dist/EventSource-OqS_P9ug.d.mts +51 -0
  20. package/dist/Identifiers-CN2s30fF.d.mts +40 -0
  21. package/dist/MemoryNamespace-BbRW5p71.d.mts +36 -0
  22. package/dist/MemoryReference-B8Q3UJoJ.d.mts +79 -0
  23. package/dist/Messaging-CkcIdt4I.d.mts +490 -0
  24. package/dist/MessagingHost-CRk0kXzT.d.mts +246 -0
  25. package/dist/MessagingHost-CWi_PP3g.mjs +137 -0
  26. package/dist/MessagingHost-CWi_PP3g.mjs.map +1 -0
  27. package/dist/OperationAuthorizer-TzcQtpX5.d.mts +61 -0
  28. package/dist/Output-D6SkedVx.d.mts +25 -0
  29. package/dist/PageCapture-Df8Xwskw.d.mts +583 -0
  30. package/dist/PageScreenshot-BpgZKAxl.d.mts +48 -0
  31. package/dist/PreparedInputAdmission-C4HbjHgl.d.mts +38 -0
  32. package/dist/Receipt-BAHyigAF.d.mts +33 -0
  33. package/dist/Records-BAGkekt8.d.mts +3570 -0
  34. package/dist/RunEvent-DIrzkjLr.d.mts +460 -0
  35. package/dist/RunEventSink-D5aVhISG.d.mts +108 -0
  36. package/dist/RunJournal-Cgg1kNvc.mjs +825 -0
  37. package/dist/RunJournal-Cgg1kNvc.mjs.map +1 -0
  38. package/dist/RunOptions-g1aigcKI.d.mts +915 -0
  39. package/dist/RunPolicyUsage-ClZxyR46.d.mts +21 -0
  40. package/dist/Sandbox-CEsDWBLq.d.mts +173 -0
  41. package/dist/Schedule-H3SEYX9g.d.mts +842 -0
  42. package/dist/Scheduling-C9aIP8zT.mjs +691 -0
  43. package/dist/Scheduling-C9aIP8zT.mjs.map +1 -0
  44. package/dist/Subagent-Cy_hU1tv.mjs +1469 -0
  45. package/dist/Subagent-Cy_hU1tv.mjs.map +1 -0
  46. package/dist/Subagent-DyfzHNdv.d.mts +826 -0
  47. package/dist/SubagentContract-DdT7Cqe6.d.mts +116 -0
  48. package/dist/SubagentHost-CJUBQlcc.d.mts +140 -0
  49. package/dist/Subscription-BEP8oQO5.d.mts +921 -0
  50. package/dist/SubscriptionInput-vAAOBrK7.d.mts +41 -0
  51. package/dist/Thread-DOBQ0QUY.d.mts +96 -0
  52. package/dist/ThreadHistory-tS1KwxHR.d.mts +60 -0
  53. package/dist/ToolBroker-DWs4tZra.d.mts +133 -0
  54. package/dist/ToolExposure-9uF_Yo0T.mjs +10 -0
  55. package/dist/ToolExposure-9uF_Yo0T.mjs.map +1 -0
  56. package/dist/ToolExposure-C93U1sPu.mjs +30 -0
  57. package/dist/ToolExposure-C93U1sPu.mjs.map +1 -0
  58. package/dist/ToolExposure-UCN12eCd.d.mts +39 -0
  59. package/dist/ToolExposure-r2eOWk4F.d.mts +46 -0
  60. package/dist/ToolExposure.d.mts +6 -5
  61. package/dist/ToolExposure.mjs +17 -9
  62. package/dist/ToolExposure.mjs.map +1 -1
  63. package/dist/ToolReconciler-DQVaJfpE.d.mts +76 -0
  64. package/dist/ToolResult-DmmgoChv.d.mts +61 -0
  65. package/dist/Usage-Dx0aknfk.d.mts +121 -0
  66. package/dist/WakeScheduler-EjUF-GhC.d.mts +56 -0
  67. package/dist/Worker-CaPYykpe.d.mts +228 -0
  68. package/dist/agent-registration-CWDMOAZA.mjs +172 -0
  69. package/dist/agent-registration-CWDMOAZA.mjs.map +1 -0
  70. package/dist/capabilities/Approval.d.mts +114 -0
  71. package/dist/capabilities/Approval.mjs +226 -0
  72. package/dist/capabilities/Approval.mjs.map +1 -0
  73. package/dist/capabilities/Budget.d.mts +112 -0
  74. package/dist/capabilities/Budget.mjs +346 -0
  75. package/dist/capabilities/Budget.mjs.map +1 -0
  76. package/dist/capabilities/CodeMode.d.mts +157 -0
  77. package/dist/capabilities/CodeMode.mjs +522 -0
  78. package/dist/capabilities/CodeMode.mjs.map +1 -0
  79. package/dist/capabilities/Commands.d.mts +55 -0
  80. package/dist/capabilities/Commands.mjs +57 -0
  81. package/dist/capabilities/Commands.mjs.map +1 -0
  82. package/dist/capabilities/ContextTools.d.mts +321 -0
  83. package/dist/capabilities/ContextTools.mjs +126 -0
  84. package/dist/capabilities/ContextTools.mjs.map +1 -0
  85. package/dist/capabilities/Mcp.d.mts +108 -0
  86. package/dist/capabilities/Mcp.mjs +260 -0
  87. package/dist/capabilities/Mcp.mjs.map +1 -0
  88. package/dist/capabilities/McpClient.d.mts +115 -0
  89. package/dist/capabilities/McpClient.mjs +506 -0
  90. package/dist/capabilities/McpClient.mjs.map +1 -0
  91. package/dist/capabilities/MemoryNotes.d.mts +424 -0
  92. package/dist/capabilities/MemoryNotes.mjs +128 -0
  93. package/dist/capabilities/MemoryNotes.mjs.map +1 -0
  94. package/dist/capabilities/Messaging.d.mts +3 -0
  95. package/dist/capabilities/Messaging.mjs +151 -0
  96. package/dist/capabilities/Messaging.mjs.map +1 -0
  97. package/dist/capabilities/ModelContext.d.mts +89 -0
  98. package/dist/capabilities/ModelContext.mjs +168 -0
  99. package/dist/capabilities/ModelContext.mjs.map +1 -0
  100. package/dist/capabilities/Redaction.d.mts +37 -0
  101. package/dist/capabilities/Redaction.mjs +104 -0
  102. package/dist/capabilities/Redaction.mjs.map +1 -0
  103. package/dist/capabilities/Remembering.d.mts +434 -0
  104. package/dist/capabilities/Remembering.mjs +290 -0
  105. package/dist/capabilities/Remembering.mjs.map +1 -0
  106. package/dist/capabilities/RunHooks.d.mts +82 -0
  107. package/dist/capabilities/RunHooks.mjs +144 -0
  108. package/dist/capabilities/RunHooks.mjs.map +1 -0
  109. package/dist/capabilities/SemanticMemory.d.mts +431 -0
  110. package/dist/capabilities/SemanticMemory.mjs +315 -0
  111. package/dist/capabilities/SemanticMemory.mjs.map +1 -0
  112. package/dist/capabilities/Subagent.d.mts +4 -0
  113. package/dist/capabilities/Subagent.mjs +5 -0
  114. package/dist/capabilities/SubagentReservations.d.mts +186 -0
  115. package/dist/capabilities/SubagentReservations.mjs +479 -0
  116. package/dist/capabilities/SubagentReservations.mjs.map +1 -0
  117. package/dist/capabilities/ToolDiscovery.d.mts +109 -0
  118. package/dist/capabilities/ToolDiscovery.mjs +211 -0
  119. package/dist/capabilities/ToolDiscovery.mjs.map +1 -0
  120. package/dist/capabilities/WebCapture.d.mts +163 -0
  121. package/dist/capabilities/WebCapture.mjs +335 -0
  122. package/dist/capabilities/WebCapture.mjs.map +1 -0
  123. package/dist/capabilities/WebSearch.d.mts +71 -0
  124. package/dist/capabilities/WebSearch.mjs +112 -0
  125. package/dist/capabilities/WebSearch.mjs.map +1 -0
  126. package/dist/compaction-C2OTceKw.mjs +505 -0
  127. package/dist/compaction-C2OTceKw.mjs.map +1 -0
  128. package/dist/core/Agent.d.mts +2 -0
  129. package/dist/core/Agent.mjs +2 -0
  130. package/dist/core/AgentError.d.mts +2 -0
  131. package/dist/core/AgentError.mjs +117 -0
  132. package/dist/core/AgentError.mjs.map +1 -0
  133. package/dist/core/AgentPolicy.d.mts +2 -0
  134. package/dist/core/AgentPolicy.mjs +94 -0
  135. package/dist/core/AgentPolicy.mjs.map +1 -0
  136. package/dist/core/AgentUpdates.d.mts +2 -0
  137. package/dist/core/AgentUpdates.mjs +63 -0
  138. package/dist/core/AgentUpdates.mjs.map +1 -0
  139. package/dist/core/IdGenerator.d.mts +26 -0
  140. package/dist/core/IdGenerator.mjs +27 -0
  141. package/dist/core/IdGenerator.mjs.map +1 -0
  142. package/dist/core/Identifiers.d.mts +2 -0
  143. package/dist/core/Identifiers.mjs +43 -0
  144. package/dist/core/Identifiers.mjs.map +1 -0
  145. package/dist/core/Memory.d.mts +57 -0
  146. package/dist/core/Memory.mjs +203 -0
  147. package/dist/core/Memory.mjs.map +1 -0
  148. package/dist/core/MemoryNamespace.d.mts +2 -0
  149. package/dist/core/MemoryNamespace.mjs +116 -0
  150. package/dist/core/MemoryNamespace.mjs.map +1 -0
  151. package/dist/core/MemoryReference.d.mts +2 -0
  152. package/dist/core/MemoryReference.mjs +109 -0
  153. package/dist/core/MemoryReference.mjs.map +1 -0
  154. package/dist/core/MemoryRevalidation.d.mts +65 -0
  155. package/dist/core/MemoryRevalidation.mjs +126 -0
  156. package/dist/core/MemoryRevalidation.mjs.map +1 -0
  157. package/dist/core/MemoryStore.d.mts +186 -0
  158. package/dist/core/MemoryStore.mjs +243 -0
  159. package/dist/core/MemoryStore.mjs.map +1 -0
  160. package/dist/core/Receipt.d.mts +2 -0
  161. package/dist/core/Receipt.mjs +36 -0
  162. package/dist/core/Receipt.mjs.map +1 -0
  163. package/dist/core/RememberingStore.d.mts +1562 -0
  164. package/dist/core/RememberingStore.mjs +190 -0
  165. package/dist/core/RememberingStore.mjs.map +1 -0
  166. package/dist/core/RunEvent.d.mts +2 -0
  167. package/dist/core/RunEvent.mjs +337 -0
  168. package/dist/core/RunEvent.mjs.map +1 -0
  169. package/dist/core/RunPolicyUsage.d.mts +2 -0
  170. package/dist/core/RunPolicyUsage.mjs +21 -0
  171. package/dist/core/RunPolicyUsage.mjs.map +1 -0
  172. package/dist/core/SemanticMemoryIndex.d.mts +826 -0
  173. package/dist/core/SemanticMemoryIndex.mjs +185 -0
  174. package/dist/core/SemanticMemoryIndex.mjs.map +1 -0
  175. package/dist/core/SemanticMemoryRevalidation.d.mts +45 -0
  176. package/dist/core/SemanticMemoryRevalidation.mjs +191 -0
  177. package/dist/core/SemanticMemoryRevalidation.mjs.map +1 -0
  178. package/dist/core/SubagentContract.d.mts +2 -0
  179. package/dist/core/SubagentContract.mjs +148 -0
  180. package/dist/core/SubagentContract.mjs.map +1 -0
  181. package/dist/core/Thread.d.mts +2 -0
  182. package/dist/core/Thread.mjs +250 -0
  183. package/dist/core/Thread.mjs.map +1 -0
  184. package/dist/core/ToolResult.d.mts +2 -0
  185. package/dist/core/ToolResult.mjs +140 -0
  186. package/dist/core/ToolResult.mjs.map +1 -0
  187. package/dist/core/Usage.d.mts +2 -0
  188. package/dist/core/Usage.mjs +319 -0
  189. package/dist/core/Usage.mjs.map +1 -0
  190. package/dist/core/Worker.d.mts +3 -0
  191. package/dist/core/Worker.mjs +147 -0
  192. package/dist/core/Worker.mjs.map +1 -0
  193. package/dist/durable/ActivityStore.d.mts +116 -0
  194. package/dist/durable/ActivityStore.mjs +131 -0
  195. package/dist/durable/ActivityStore.mjs.map +1 -0
  196. package/dist/durable/Admin.d.mts +2 -0
  197. package/dist/durable/Admin.mjs +328 -0
  198. package/dist/durable/Admin.mjs.map +1 -0
  199. package/dist/durable/AgentRegistration.d.mts +2 -0
  200. package/dist/durable/AgentRegistration.mjs +14 -0
  201. package/dist/durable/AgentRegistration.mjs.map +1 -0
  202. package/dist/durable/Certification.d.mts +111 -0
  203. package/dist/durable/Certification.mjs +159 -0
  204. package/dist/durable/Certification.mjs.map +1 -0
  205. package/dist/durable/CommittedActivity.d.mts +62 -0
  206. package/dist/durable/CommittedActivity.mjs +159 -0
  207. package/dist/durable/CommittedActivity.mjs.map +1 -0
  208. package/dist/durable/Digest.d.mts +2 -0
  209. package/dist/durable/Digest.mjs +50 -0
  210. package/dist/durable/Digest.mjs.map +1 -0
  211. package/dist/durable/DurableAgentRuntime.d.mts +3 -0
  212. package/dist/durable/DurableAgentRuntime.mjs +3 -0
  213. package/dist/durable/DurableFailpoint.d.mts +2 -0
  214. package/dist/durable/DurableFailpoint.mjs +94 -0
  215. package/dist/durable/DurableFailpoint.mjs.map +1 -0
  216. package/dist/durable/DurableFailpointTestControl.d.mts +15 -0
  217. package/dist/durable/DurableFailpointTestControl.mjs +19 -0
  218. package/dist/durable/DurableFailpointTestControl.mjs.map +1 -0
  219. package/dist/durable/EventSource.d.mts +2 -0
  220. package/dist/durable/EventSource.mjs +65 -0
  221. package/dist/durable/EventSource.mjs.map +1 -0
  222. package/dist/durable/GitHubWorkflowSource.d.mts +144 -0
  223. package/dist/durable/GitHubWorkflowSource.mjs +209 -0
  224. package/dist/durable/GitHubWorkflowSource.mjs.map +1 -0
  225. package/dist/durable/MessageDelivery.d.mts +492 -0
  226. package/dist/durable/MessageDelivery.mjs +495 -0
  227. package/dist/durable/MessageDelivery.mjs.map +1 -0
  228. package/dist/durable/MessageDeliveryStoreConformance.d.mts +358 -0
  229. package/dist/durable/MessageDeliveryStoreConformance.mjs +243 -0
  230. package/dist/durable/MessageDeliveryStoreConformance.mjs.map +1 -0
  231. package/dist/durable/OperationAuthorizer.d.mts +2 -0
  232. package/dist/durable/OperationAuthorizer.mjs +70 -0
  233. package/dist/durable/OperationAuthorizer.mjs.map +1 -0
  234. package/dist/durable/PersistentHistory.d.mts +16 -0
  235. package/dist/durable/PersistentHistory.mjs +125 -0
  236. package/dist/durable/PersistentHistory.mjs.map +1 -0
  237. package/dist/durable/PreparedInputAdmission.d.mts +2 -0
  238. package/dist/durable/PreparedInputAdmission.mjs +34 -0
  239. package/dist/durable/PreparedInputAdmission.mjs.map +1 -0
  240. package/dist/durable/Records.d.mts +2 -0
  241. package/dist/durable/Records.mjs +795 -0
  242. package/dist/durable/Records.mjs.map +1 -0
  243. package/dist/durable/Recovery.d.mts +2 -0
  244. package/dist/durable/Recovery.mjs +739 -0
  245. package/dist/durable/Recovery.mjs.map +1 -0
  246. package/dist/durable/RunJournal.d.mts +2 -0
  247. package/dist/durable/RunJournal.mjs +2 -0
  248. package/dist/durable/Schedule.d.mts +2 -0
  249. package/dist/durable/Schedule.mjs +382 -0
  250. package/dist/durable/Schedule.mjs.map +1 -0
  251. package/dist/durable/ScheduleStoreConformance.d.mts +18 -0
  252. package/dist/durable/ScheduleStoreConformance.mjs +420 -0
  253. package/dist/durable/ScheduleStoreConformance.mjs.map +1 -0
  254. package/dist/durable/ScheduleTransition.d.mts +24 -0
  255. package/dist/durable/ScheduleTransition.mjs +180 -0
  256. package/dist/durable/ScheduleTransition.mjs.map +1 -0
  257. package/dist/durable/Scheduling.d.mts +54 -0
  258. package/dist/durable/Scheduling.mjs +2 -0
  259. package/dist/durable/SqlMemoryStore.d.mts +30 -0
  260. package/dist/durable/SqlMemoryStore.mjs +435 -0
  261. package/dist/durable/SqlMemoryStore.mjs.map +1 -0
  262. package/dist/durable/SqlMessageDeliveryStore.d.mts +40 -0
  263. package/dist/durable/SqlMessageDeliveryStore.mjs +167 -0
  264. package/dist/durable/SqlMessageDeliveryStore.mjs.map +1 -0
  265. package/dist/durable/SqlStorageV2Upgrade.d.mts +22 -0
  266. package/dist/durable/SqlStorageV2Upgrade.mjs +459 -0
  267. package/dist/durable/SqlStorageV2Upgrade.mjs.map +1 -0
  268. package/dist/durable/SqlSubscriptionStore.d.mts +63 -0
  269. package/dist/durable/SqlSubscriptionStore.mjs +751 -0
  270. package/dist/durable/SqlSubscriptionStore.mjs.map +1 -0
  271. package/dist/durable/SubmissionLedger.d.mts +3 -0
  272. package/dist/durable/SubmissionLedger.mjs +914 -0
  273. package/dist/durable/SubmissionLedger.mjs.map +1 -0
  274. package/dist/durable/SubmissionLedgerConformance.d.mts +30 -0
  275. package/dist/durable/SubmissionLedgerConformance.mjs +1986 -0
  276. package/dist/durable/SubmissionLedgerConformance.mjs.map +1 -0
  277. package/dist/durable/SubmissionStatus.d.mts +2 -0
  278. package/dist/durable/SubmissionStatus.mjs +18 -0
  279. package/dist/durable/SubmissionStatus.mjs.map +1 -0
  280. package/dist/durable/Subscription.d.mts +2 -0
  281. package/dist/durable/Subscription.mjs +360 -0
  282. package/dist/durable/Subscription.mjs.map +1 -0
  283. package/dist/durable/SubscriptionInput.d.mts +2 -0
  284. package/dist/durable/SubscriptionInput.mjs +52 -0
  285. package/dist/durable/SubscriptionInput.mjs.map +1 -0
  286. package/dist/durable/SubscriptionStoreConformance.d.mts +17 -0
  287. package/dist/durable/SubscriptionStoreConformance.mjs +625 -0
  288. package/dist/durable/SubscriptionStoreConformance.mjs.map +1 -0
  289. package/dist/durable/SubscriptionTools.d.mts +273 -0
  290. package/dist/durable/SubscriptionTools.mjs +190 -0
  291. package/dist/durable/SubscriptionTools.mjs.map +1 -0
  292. package/dist/durable/SubscriptionTransition.d.mts +21 -0
  293. package/dist/durable/SubscriptionTransition.mjs +148 -0
  294. package/dist/durable/SubscriptionTransition.mjs.map +1 -0
  295. package/dist/durable/Subscriptions.d.mts +73 -0
  296. package/dist/durable/Subscriptions.mjs +627 -0
  297. package/dist/durable/Subscriptions.mjs.map +1 -0
  298. package/dist/durable/ThreadContextHistory.d.mts +32 -0
  299. package/dist/durable/ThreadContextHistory.mjs +152 -0
  300. package/dist/durable/ThreadContextHistory.mjs.map +1 -0
  301. package/dist/durable/ThreadContextHistoryProjection.d.mts +60 -0
  302. package/dist/durable/ThreadContextHistoryProjection.mjs +149 -0
  303. package/dist/durable/ThreadContextHistoryProjection.mjs.map +1 -0
  304. package/dist/durable/ThreadInvariants.d.mts +74 -0
  305. package/dist/durable/ThreadInvariants.mjs +200 -0
  306. package/dist/durable/ThreadInvariants.mjs.map +1 -0
  307. package/dist/durable/ThreadProjection.d.mts +78 -0
  308. package/dist/durable/ThreadProjection.mjs +158 -0
  309. package/dist/durable/ThreadProjection.mjs.map +1 -0
  310. package/dist/durable/ThreadProjectionMaintenance.d.mts +49 -0
  311. package/dist/durable/ThreadProjectionMaintenance.mjs +33 -0
  312. package/dist/durable/ThreadProjectionMaintenance.mjs.map +1 -0
  313. package/dist/durable/ThreadStore.d.mts +2 -0
  314. package/dist/durable/ThreadStore.mjs +147 -0
  315. package/dist/durable/ThreadStore.mjs.map +1 -0
  316. package/dist/durable/ThreadStoreConformance.d.mts +29 -0
  317. package/dist/durable/ThreadStoreConformance.mjs +248 -0
  318. package/dist/durable/ThreadStoreConformance.mjs.map +1 -0
  319. package/dist/durable/ToolReconciler.d.mts +2 -0
  320. package/dist/durable/ToolReconciler.mjs +81 -0
  321. package/dist/durable/ToolReconciler.mjs.map +1 -0
  322. package/dist/durable/WakeScheduler.d.mts +2 -0
  323. package/dist/durable/WakeScheduler.mjs +85 -0
  324. package/dist/durable/WakeScheduler.mjs.map +1 -0
  325. package/dist/durable/WorkerHost.d.mts +129 -0
  326. package/dist/durable/WorkerHost.mjs +77 -0
  327. package/dist/durable/WorkerHost.mjs.map +1 -0
  328. package/dist/engine/AgentRuntime.d.mts +2 -0
  329. package/dist/engine/AgentRuntime.mjs +2 -0
  330. package/dist/engine/Compaction.d.mts +7 -0
  331. package/dist/engine/Compaction.mjs +16 -0
  332. package/dist/engine/Compaction.mjs.map +1 -0
  333. package/dist/engine/ContextCompactor.d.mts +2 -0
  334. package/dist/engine/ContextCompactor.mjs +119 -0
  335. package/dist/engine/ContextCompactor.mjs.map +1 -0
  336. package/dist/engine/ContextHistory.d.mts +65 -0
  337. package/dist/engine/ContextHistory.mjs +76 -0
  338. package/dist/engine/ContextHistory.mjs.map +1 -0
  339. package/dist/engine/ContextWindow.d.mts +2 -0
  340. package/dist/engine/ContextWindow.mjs +59 -0
  341. package/dist/engine/ContextWindow.mjs.map +1 -0
  342. package/dist/engine/DurableStep.d.mts +2 -0
  343. package/dist/engine/DurableStep.mjs +62 -0
  344. package/dist/engine/DurableStep.mjs.map +1 -0
  345. package/dist/engine/MessagingHost.d.mts +2 -0
  346. package/dist/engine/MessagingHost.mjs +2 -0
  347. package/dist/engine/Output.d.mts +2 -0
  348. package/dist/engine/Output.mjs +8 -0
  349. package/dist/engine/Output.mjs.map +1 -0
  350. package/dist/engine/RunEventSink.d.mts +2 -0
  351. package/dist/engine/RunEventSink.mjs +22 -0
  352. package/dist/engine/RunEventSink.mjs.map +1 -0
  353. package/dist/engine/RunOptions.d.mts +2 -0
  354. package/dist/engine/RunOptions.mjs +122 -0
  355. package/dist/engine/RunOptions.mjs.map +1 -0
  356. package/dist/engine/SubagentHost.d.mts +2 -0
  357. package/dist/engine/SubagentHost.mjs +72 -0
  358. package/dist/engine/SubagentHost.mjs.map +1 -0
  359. package/dist/engine/ThreadHistory.d.mts +2 -0
  360. package/dist/engine/ThreadHistory.mjs +67 -0
  361. package/dist/engine/ThreadHistory.mjs.map +1 -0
  362. package/dist/engine/ToolBroker.d.mts +2 -0
  363. package/dist/engine/ToolBroker.mjs +42 -0
  364. package/dist/engine/ToolBroker.mjs.map +1 -0
  365. package/dist/foreign-diagnostic-DBQ1XHKh.mjs +37 -0
  366. package/dist/foreign-diagnostic-DBQ1XHKh.mjs.map +1 -0
  367. package/dist/index.d.mts +88 -54
  368. package/dist/index.mjs +97 -54
  369. package/dist/output-contract-BC7tjlGw.mjs +84 -0
  370. package/dist/output-contract-BC7tjlGw.mjs.map +1 -0
  371. package/dist/rolldown-runtime-D7D4PA-g.mjs +13 -0
  372. package/dist/sandbox/CodeExecutor.d.mts +194 -0
  373. package/dist/sandbox/CodeExecutor.mjs +278 -0
  374. package/dist/sandbox/CodeExecutor.mjs.map +1 -0
  375. package/dist/sandbox/InteractiveBrowser.d.mts +142 -0
  376. package/dist/sandbox/InteractiveBrowser.mjs +165 -0
  377. package/dist/sandbox/InteractiveBrowser.mjs.map +1 -0
  378. package/dist/sandbox/PageCapture.d.mts +2 -0
  379. package/dist/sandbox/PageCapture.mjs +450 -0
  380. package/dist/sandbox/PageCapture.mjs.map +1 -0
  381. package/dist/sandbox/PageCrawl.d.mts +88 -0
  382. package/dist/sandbox/PageCrawl.mjs +124 -0
  383. package/dist/sandbox/PageCrawl.mjs.map +1 -0
  384. package/dist/sandbox/PageScreenshot.d.mts +2 -0
  385. package/dist/sandbox/PageScreenshot.mjs +53 -0
  386. package/dist/sandbox/PageScreenshot.mjs.map +1 -0
  387. package/dist/sandbox/ProtectedBrowser.d.mts +252 -0
  388. package/dist/sandbox/ProtectedBrowser.mjs +270 -0
  389. package/dist/sandbox/ProtectedBrowser.mjs.map +1 -0
  390. package/dist/sandbox/Sandbox.d.mts +2 -0
  391. package/dist/sandbox/Sandbox.mjs +208 -0
  392. package/dist/sandbox/Sandbox.mjs.map +1 -0
  393. package/dist/utf8-BYfhEkcj.mjs +11 -0
  394. package/dist/utf8-BYfhEkcj.mjs.map +1 -0
  395. package/dist/utf8-DchGZRBd.mjs +23 -0
  396. package/dist/utf8-DchGZRBd.mjs.map +1 -0
  397. package/package.json +1 -1
  398. package/src/Ephemeral.ts +17 -0
  399. package/src/ToolExposure.ts +2 -2
  400. package/src/capabilities/Approval.ts +352 -0
  401. package/src/capabilities/Budget.ts +536 -0
  402. package/src/capabilities/CodeMode.ts +1090 -0
  403. package/src/capabilities/Commands.ts +86 -0
  404. package/src/capabilities/ContextTools.ts +184 -0
  405. package/src/capabilities/Mcp.ts +427 -0
  406. package/src/capabilities/McpClient.ts +967 -0
  407. package/src/capabilities/MemoryNotes.ts +174 -0
  408. package/src/capabilities/Messaging.ts +261 -0
  409. package/src/capabilities/ModelContext.ts +354 -0
  410. package/src/capabilities/Redaction.ts +157 -0
  411. package/src/capabilities/Remembering.ts +550 -0
  412. package/src/capabilities/RunHooks.ts +280 -0
  413. package/src/capabilities/SemanticMemory.ts +447 -0
  414. package/src/capabilities/Subagent.ts +2277 -0
  415. package/src/capabilities/SubagentReservations.ts +850 -0
  416. package/src/capabilities/ToolDiscovery.ts +339 -0
  417. package/src/capabilities/WebCapture.ts +722 -0
  418. package/src/capabilities/WebSearch.ts +184 -0
  419. package/src/capabilities/internal/subagent-background.ts +1106 -0
  420. package/src/capabilities/internal/subagent-contract.ts +142 -0
  421. package/src/capabilities/internal/subagent-policy.ts +235 -0
  422. package/src/capabilities/internal/subagent-reporting.ts +261 -0
  423. package/src/capabilities/internal/utf8.ts +10 -0
  424. package/src/core/Agent.ts +575 -0
  425. package/src/core/AgentError.ts +152 -0
  426. package/src/core/AgentPolicy.ts +153 -0
  427. package/src/core/AgentUpdates.ts +100 -0
  428. package/src/core/IdGenerator.ts +39 -0
  429. package/src/core/Identifiers.ts +48 -0
  430. package/src/core/Memory.ts +290 -0
  431. package/src/core/MemoryNamespace.ts +196 -0
  432. package/src/core/MemoryReference.ts +121 -0
  433. package/src/core/MemoryRevalidation.ts +185 -0
  434. package/src/core/MemoryStore.ts +368 -0
  435. package/src/core/Messaging.ts +90 -0
  436. package/src/core/Receipt.ts +42 -0
  437. package/src/core/RememberingStore.ts +300 -0
  438. package/src/core/RunEvent.ts +366 -0
  439. package/src/core/RunPolicyUsage.ts +17 -0
  440. package/src/core/SemanticMemoryIndex.ts +250 -0
  441. package/src/core/SemanticMemoryRevalidation.ts +254 -0
  442. package/src/core/SubagentContract.ts +196 -0
  443. package/src/core/Thread.ts +371 -0
  444. package/src/core/ToolExposure.ts +74 -0
  445. package/src/core/ToolResult.ts +170 -0
  446. package/src/core/Usage.ts +529 -0
  447. package/src/core/Worker.ts +173 -0
  448. package/src/core/internal/agent-updates.ts +32 -0
  449. package/src/core/internal/utf8.ts +23 -0
  450. package/src/durable/ActivityStore.ts +160 -0
  451. package/src/durable/Admin.ts +496 -0
  452. package/src/durable/AgentRegistration.ts +13 -0
  453. package/src/durable/Certification.ts +210 -0
  454. package/src/durable/CommittedActivity.ts +296 -0
  455. package/src/durable/Digest.ts +93 -0
  456. package/src/durable/DurableAgentRuntime.ts +10340 -0
  457. package/src/durable/DurableFailpoint.ts +103 -0
  458. package/src/durable/DurableFailpointTestControl.ts +39 -0
  459. package/src/durable/EventSource.ts +172 -0
  460. package/src/durable/GitHubWorkflowSource.ts +453 -0
  461. package/src/durable/MessageDelivery.ts +708 -0
  462. package/src/durable/MessageDeliveryStoreConformance.ts +363 -0
  463. package/src/durable/OperationAuthorizer.ts +85 -0
  464. package/src/durable/PersistentHistory.ts +260 -0
  465. package/src/durable/PreparedInputAdmission.ts +44 -0
  466. package/src/durable/Records.ts +1010 -0
  467. package/src/durable/Recovery.ts +1018 -0
  468. package/src/durable/RunJournal.ts +1479 -0
  469. package/src/durable/Schedule.ts +504 -0
  470. package/src/durable/ScheduleStoreConformance.ts +638 -0
  471. package/src/durable/ScheduleTransition.ts +265 -0
  472. package/src/durable/Scheduling.ts +1077 -0
  473. package/src/durable/SqlMemoryStore.ts +774 -0
  474. package/src/durable/SqlMessageDeliveryStore.ts +302 -0
  475. package/src/durable/SqlStorageV2Upgrade.ts +500 -0
  476. package/src/durable/SqlSubscriptionStore.ts +1440 -0
  477. package/src/durable/SubmissionLedger.ts +1201 -0
  478. package/src/durable/SubmissionLedgerConformance.ts +4579 -0
  479. package/src/durable/SubmissionStatus.ts +14 -0
  480. package/src/durable/Subscription.ts +544 -0
  481. package/src/durable/SubscriptionInput.ts +144 -0
  482. package/src/durable/SubscriptionStoreConformance.ts +945 -0
  483. package/src/durable/SubscriptionTools.ts +327 -0
  484. package/src/durable/SubscriptionTransition.ts +302 -0
  485. package/src/durable/Subscriptions.ts +1210 -0
  486. package/src/durable/ThreadContextHistory.ts +227 -0
  487. package/src/durable/ThreadContextHistoryProjection.ts +216 -0
  488. package/src/durable/ThreadInvariants.ts +442 -0
  489. package/src/durable/ThreadProjection.ts +269 -0
  490. package/src/durable/ThreadProjectionMaintenance.ts +67 -0
  491. package/src/durable/ThreadStore.ts +242 -0
  492. package/src/durable/ThreadStoreConformance.ts +710 -0
  493. package/src/durable/ToolReconciler.ts +105 -0
  494. package/src/durable/WakeScheduler.ts +134 -0
  495. package/src/durable/WorkerHost.ts +171 -0
  496. package/src/durable/internal/agent-registration.ts +525 -0
  497. package/src/durable/internal/agent-updates.ts +302 -0
  498. package/src/durable/internal/foreign-diagnostic.ts +47 -0
  499. package/src/durable/internal/journal-checkpoint.ts +104 -0
  500. package/src/durable/internal/journal-metadata.ts +107 -0
  501. package/src/durable/internal/messaging-host.ts +608 -0
  502. package/src/durable/internal/schedule-time.ts +303 -0
  503. package/src/durable/internal/storage-v2-layout.ts +163 -0
  504. package/src/durable/internal/storage-v2.ts +73 -0
  505. package/src/durable/internal/worker-host.ts +2467 -0
  506. package/src/durable/internal/worker-runtime.ts +9 -0
  507. package/src/engine/AgentRuntime.ts +37 -0
  508. package/src/engine/Compaction.ts +11 -0
  509. package/src/engine/ContextCompactor.ts +277 -0
  510. package/src/engine/ContextHistory.ts +73 -0
  511. package/src/engine/ContextWindow.ts +72 -0
  512. package/src/engine/DurableStep.ts +132 -0
  513. package/src/engine/MessagingHost.ts +110 -0
  514. package/src/engine/Output.ts +2 -0
  515. package/src/engine/RunEventSink.ts +132 -0
  516. package/src/engine/RunOptions.ts +1077 -0
  517. package/src/engine/SubagentHost.ts +181 -0
  518. package/src/engine/ThreadHistory.ts +120 -0
  519. package/src/engine/ToolBroker.ts +157 -0
  520. package/src/engine/ToolExposure.ts +48 -0
  521. package/src/engine/internal/agent-runtime.ts +10117 -0
  522. package/src/engine/internal/bounded-value.ts +315 -0
  523. package/src/engine/internal/compaction.ts +678 -0
  524. package/src/engine/internal/error-diagnostic.ts +39 -0
  525. package/src/engine/internal/output-contract.ts +173 -0
  526. package/src/engine/internal/primitive-delta.ts +80 -0
  527. package/src/engine/internal/provider-result-staging.ts +211 -0
  528. package/src/engine/internal/tool-derivative.ts +106 -0
  529. package/src/engine/internal/tool-exposure.ts +224 -0
  530. package/src/engine/internal/tool-telemetry.ts +484 -0
  531. package/src/index.ts +96 -53
  532. package/src/sandbox/CodeExecutor.ts +352 -0
  533. package/src/sandbox/InteractiveBrowser.ts +257 -0
  534. package/src/sandbox/PageCapture.ts +692 -0
  535. package/src/sandbox/PageCrawl.ts +148 -0
  536. package/src/sandbox/PageScreenshot.ts +81 -0
  537. package/src/sandbox/ProtectedBrowser.ts +413 -0
  538. package/src/sandbox/Sandbox.ts +241 -0
  539. package/dist/Agent.d.mts +0 -5
  540. package/dist/Agent.mjs +0 -10
  541. package/dist/Agent.mjs.map +0 -1
  542. package/dist/AgentError.d.mts +0 -5
  543. package/dist/AgentError.mjs +0 -10
  544. package/dist/AgentError.mjs.map +0 -1
  545. package/dist/AgentPolicy.d.mts +0 -5
  546. package/dist/AgentPolicy.mjs +0 -10
  547. package/dist/AgentPolicy.mjs.map +0 -1
  548. package/dist/AgentRuntime.d.mts +0 -5
  549. package/dist/AgentRuntime.mjs +0 -10
  550. package/dist/AgentRuntime.mjs.map +0 -1
  551. package/dist/AgentUpdates.d.mts +0 -5
  552. package/dist/AgentUpdates.mjs +0 -10
  553. package/dist/AgentUpdates.mjs.map +0 -1
  554. package/dist/Approval.d.mts +0 -5
  555. package/dist/Approval.mjs +0 -10
  556. package/dist/Approval.mjs.map +0 -1
  557. package/dist/Budget.d.mts +0 -5
  558. package/dist/Budget.mjs +0 -10
  559. package/dist/Budget.mjs.map +0 -1
  560. package/dist/CodeMode.d.mts +0 -5
  561. package/dist/CodeMode.mjs +0 -10
  562. package/dist/CodeMode.mjs.map +0 -1
  563. package/dist/Commands.d.mts +0 -5
  564. package/dist/Commands.mjs +0 -10
  565. package/dist/Commands.mjs.map +0 -1
  566. package/dist/Compaction.d.mts +0 -5
  567. package/dist/Compaction.mjs +0 -10
  568. package/dist/Compaction.mjs.map +0 -1
  569. package/dist/ContextCompactor.d.mts +0 -5
  570. package/dist/ContextCompactor.mjs +0 -10
  571. package/dist/ContextCompactor.mjs.map +0 -1
  572. package/dist/ContextHistory.d.mts +0 -5
  573. package/dist/ContextHistory.mjs +0 -10
  574. package/dist/ContextHistory.mjs.map +0 -1
  575. package/dist/ContextTools.d.mts +0 -5
  576. package/dist/ContextTools.mjs +0 -10
  577. package/dist/ContextTools.mjs.map +0 -1
  578. package/dist/ContextWindow.d.mts +0 -5
  579. package/dist/ContextWindow.mjs +0 -10
  580. package/dist/ContextWindow.mjs.map +0 -1
  581. package/dist/DurableStep.d.mts +0 -5
  582. package/dist/DurableStep.mjs +0 -10
  583. package/dist/DurableStep.mjs.map +0 -1
  584. package/dist/EphemeralThreads.d.mts +0 -5
  585. package/dist/EphemeralThreads.mjs +0 -10
  586. package/dist/EphemeralThreads.mjs.map +0 -1
  587. package/dist/IdGenerator.d.mts +0 -5
  588. package/dist/IdGenerator.mjs +0 -10
  589. package/dist/IdGenerator.mjs.map +0 -1
  590. package/dist/Identifiers.d.mts +0 -5
  591. package/dist/Identifiers.mjs +0 -10
  592. package/dist/Identifiers.mjs.map +0 -1
  593. package/dist/Mcp.d.mts +0 -5
  594. package/dist/Mcp.mjs +0 -10
  595. package/dist/Mcp.mjs.map +0 -1
  596. package/dist/McpClient.d.mts +0 -5
  597. package/dist/McpClient.mjs +0 -10
  598. package/dist/McpClient.mjs.map +0 -1
  599. package/dist/Memory.d.mts +0 -5
  600. package/dist/Memory.mjs +0 -10
  601. package/dist/Memory.mjs.map +0 -1
  602. package/dist/MemoryNamespace.d.mts +0 -5
  603. package/dist/MemoryNamespace.mjs +0 -10
  604. package/dist/MemoryNamespace.mjs.map +0 -1
  605. package/dist/MemoryNotes.d.mts +0 -5
  606. package/dist/MemoryNotes.mjs +0 -10
  607. package/dist/MemoryNotes.mjs.map +0 -1
  608. package/dist/MemoryReference.d.mts +0 -5
  609. package/dist/MemoryReference.mjs +0 -10
  610. package/dist/MemoryReference.mjs.map +0 -1
  611. package/dist/MemoryRevalidation.d.mts +0 -5
  612. package/dist/MemoryRevalidation.mjs +0 -10
  613. package/dist/MemoryRevalidation.mjs.map +0 -1
  614. package/dist/MemoryStore.d.mts +0 -5
  615. package/dist/MemoryStore.mjs +0 -10
  616. package/dist/MemoryStore.mjs.map +0 -1
  617. package/dist/Messaging.d.mts +0 -5
  618. package/dist/Messaging.mjs +0 -10
  619. package/dist/Messaging.mjs.map +0 -1
  620. package/dist/MessagingHost.d.mts +0 -5
  621. package/dist/MessagingHost.mjs +0 -10
  622. package/dist/MessagingHost.mjs.map +0 -1
  623. package/dist/ModelContext.d.mts +0 -5
  624. package/dist/ModelContext.mjs +0 -10
  625. package/dist/ModelContext.mjs.map +0 -1
  626. package/dist/Receipt.d.mts +0 -5
  627. package/dist/Receipt.mjs +0 -10
  628. package/dist/Receipt.mjs.map +0 -1
  629. package/dist/Redaction.d.mts +0 -5
  630. package/dist/Redaction.mjs +0 -10
  631. package/dist/Redaction.mjs.map +0 -1
  632. package/dist/Remembering.d.mts +0 -5
  633. package/dist/Remembering.mjs +0 -10
  634. package/dist/Remembering.mjs.map +0 -1
  635. package/dist/RememberingStore.d.mts +0 -5
  636. package/dist/RememberingStore.mjs +0 -10
  637. package/dist/RememberingStore.mjs.map +0 -1
  638. package/dist/RunEvent.d.mts +0 -5
  639. package/dist/RunEvent.mjs +0 -10
  640. package/dist/RunEvent.mjs.map +0 -1
  641. package/dist/RunEventSink.d.mts +0 -5
  642. package/dist/RunEventSink.mjs +0 -10
  643. package/dist/RunEventSink.mjs.map +0 -1
  644. package/dist/RunHooks.d.mts +0 -5
  645. package/dist/RunHooks.mjs +0 -10
  646. package/dist/RunHooks.mjs.map +0 -1
  647. package/dist/RunOptions.d.mts +0 -5
  648. package/dist/RunOptions.mjs +0 -10
  649. package/dist/RunOptions.mjs.map +0 -1
  650. package/dist/RunPolicyUsage.d.mts +0 -5
  651. package/dist/RunPolicyUsage.mjs +0 -10
  652. package/dist/RunPolicyUsage.mjs.map +0 -1
  653. package/dist/SemanticMemory.d.mts +0 -5
  654. package/dist/SemanticMemory.mjs +0 -10
  655. package/dist/SemanticMemory.mjs.map +0 -1
  656. package/dist/SemanticMemoryIndex.d.mts +0 -5
  657. package/dist/SemanticMemoryIndex.mjs +0 -10
  658. package/dist/SemanticMemoryIndex.mjs.map +0 -1
  659. package/dist/SemanticMemoryRevalidation.d.mts +0 -5
  660. package/dist/SemanticMemoryRevalidation.mjs +0 -10
  661. package/dist/SemanticMemoryRevalidation.mjs.map +0 -1
  662. package/dist/Subagent.d.mts +0 -5
  663. package/dist/Subagent.mjs +0 -10
  664. package/dist/Subagent.mjs.map +0 -1
  665. package/dist/SubagentContract.d.mts +0 -5
  666. package/dist/SubagentContract.mjs +0 -10
  667. package/dist/SubagentContract.mjs.map +0 -1
  668. package/dist/SubagentHost.d.mts +0 -5
  669. package/dist/SubagentHost.mjs +0 -10
  670. package/dist/SubagentHost.mjs.map +0 -1
  671. package/dist/SubagentReservations.d.mts +0 -5
  672. package/dist/SubagentReservations.mjs +0 -10
  673. package/dist/SubagentReservations.mjs.map +0 -1
  674. package/dist/ThreadHistory.d.mts +0 -5
  675. package/dist/ThreadHistory.mjs +0 -10
  676. package/dist/ThreadHistory.mjs.map +0 -1
  677. package/dist/ToolBroker.d.mts +0 -5
  678. package/dist/ToolBroker.mjs +0 -10
  679. package/dist/ToolBroker.mjs.map +0 -1
  680. package/dist/ToolDiscovery.d.mts +0 -5
  681. package/dist/ToolDiscovery.mjs +0 -10
  682. package/dist/ToolDiscovery.mjs.map +0 -1
  683. package/dist/ToolResult.d.mts +0 -5
  684. package/dist/ToolResult.mjs +0 -10
  685. package/dist/ToolResult.mjs.map +0 -1
  686. package/dist/Usage.d.mts +0 -5
  687. package/dist/Usage.mjs +0 -10
  688. package/dist/Usage.mjs.map +0 -1
  689. package/dist/WebCapture.d.mts +0 -5
  690. package/dist/WebCapture.mjs +0 -10
  691. package/dist/WebCapture.mjs.map +0 -1
  692. package/dist/WebSearch.d.mts +0 -5
  693. package/dist/WebSearch.mjs +0 -10
  694. package/dist/WebSearch.mjs.map +0 -1
  695. package/dist/Worker.d.mts +0 -5
  696. package/dist/Worker.mjs +0 -10
  697. package/dist/Worker.mjs.map +0 -1
  698. package/dist/rolldown-runtime-BBjsoOtd.mjs +0 -27
  699. package/src/Agent.ts +0 -1
  700. package/src/AgentError.ts +0 -1
  701. package/src/AgentPolicy.ts +0 -1
  702. package/src/AgentRuntime.ts +0 -1
  703. package/src/AgentUpdates.ts +0 -1
  704. package/src/Approval.ts +0 -1
  705. package/src/Budget.ts +0 -1
  706. package/src/CodeMode.ts +0 -1
  707. package/src/Commands.ts +0 -1
  708. package/src/Compaction.ts +0 -1
  709. package/src/ContextCompactor.ts +0 -1
  710. package/src/ContextHistory.ts +0 -1
  711. package/src/ContextTools.ts +0 -1
  712. package/src/ContextWindow.ts +0 -1
  713. package/src/DurableStep.ts +0 -1
  714. package/src/EphemeralThreads.ts +0 -1
  715. package/src/IdGenerator.ts +0 -1
  716. package/src/Identifiers.ts +0 -1
  717. package/src/Mcp.ts +0 -1
  718. package/src/McpClient.ts +0 -1
  719. package/src/Memory.ts +0 -1
  720. package/src/MemoryNamespace.ts +0 -1
  721. package/src/MemoryNotes.ts +0 -1
  722. package/src/MemoryReference.ts +0 -1
  723. package/src/MemoryRevalidation.ts +0 -1
  724. package/src/MemoryStore.ts +0 -1
  725. package/src/Messaging.ts +0 -1
  726. package/src/MessagingHost.ts +0 -1
  727. package/src/ModelContext.ts +0 -1
  728. package/src/Receipt.ts +0 -1
  729. package/src/Redaction.ts +0 -1
  730. package/src/Remembering.ts +0 -1
  731. package/src/RememberingStore.ts +0 -1
  732. package/src/RunEvent.ts +0 -1
  733. package/src/RunEventSink.ts +0 -1
  734. package/src/RunHooks.ts +0 -1
  735. package/src/RunOptions.ts +0 -1
  736. package/src/RunPolicyUsage.ts +0 -1
  737. package/src/SemanticMemory.ts +0 -1
  738. package/src/SemanticMemoryIndex.ts +0 -1
  739. package/src/SemanticMemoryRevalidation.ts +0 -1
  740. package/src/Subagent.ts +0 -1
  741. package/src/SubagentContract.ts +0 -1
  742. package/src/SubagentHost.ts +0 -1
  743. package/src/SubagentReservations.ts +0 -1
  744. package/src/ThreadHistory.ts +0 -1
  745. package/src/ToolBroker.ts +0 -1
  746. package/src/ToolDiscovery.ts +0 -1
  747. package/src/ToolResult.ts +0 -1
  748. package/src/Usage.ts +0 -1
  749. package/src/WebCapture.ts +0 -1
  750. package/src/WebSearch.ts +0 -1
  751. package/src/Worker.ts +0 -1
@@ -0,0 +1,2467 @@
1
+ import {
2
+ Cause,
3
+ Clock,
4
+ Context,
5
+ Crypto,
6
+ DateTime,
7
+ Duration,
8
+ Effect,
9
+ Option,
10
+ Schema,
11
+ Stream,
12
+ } from "effect";
13
+
14
+ import type * as Agent from "../../core/Agent.ts";
15
+ import { AgentPolicy } from "../../core/AgentPolicy.ts";
16
+ import { Update, UpdateError } from "../../core/AgentUpdates.ts";
17
+ import { ThreadId, type AgentId, type SubmissionId } from "../../core/Identifiers.ts";
18
+ import { IdempotencyKey, Receipt } from "../../core/Receipt.ts";
19
+ import { SubagentDelegationCaps, SubagentGrant } from "../../core/SubagentContract.ts";
20
+ import {
21
+ WorkerCompletion,
22
+ FrameworkMessage,
23
+ WorkerUpdate,
24
+ WorkerError,
25
+ WorkerHistoryEntry,
26
+ type WorkerContext,
27
+ WorkerRef,
28
+ } from "../../core/Worker.ts";
29
+ import {
30
+ type SubagentHost,
31
+ type WorkerObservation,
32
+ type WorkerReceiptRequest,
33
+ type WorkerRunReport,
34
+ } from "../../engine/SubagentHost.ts";
35
+ import { digestJson } from "../Digest.ts";
36
+ import type {
37
+ DurableAbortFailure,
38
+ DurableAwaitFailure,
39
+ DurableSubmitFailure,
40
+ DurableSubmitOptions,
41
+ } from "../DurableAgentRuntime.ts";
42
+ import {
43
+ DurableRuntimeFailpoint,
44
+ type DurableRuntimeFailpointLocation,
45
+ } from "../DurableFailpoint.ts";
46
+ import {
47
+ MessageDeliveryDriver,
48
+ MessageDeliveryStore,
49
+ prepareMessageDelivery,
50
+ } from "../MessageDelivery.ts";
51
+ import { PreparedInputAdmission } from "../PreparedInputAdmission.ts";
52
+ import {
53
+ BatchId,
54
+ CanonicalBatch,
55
+ CanonicalSequence,
56
+ type Digest,
57
+ type DeploymentId,
58
+ type ProducerId,
59
+ RecordEnvelope,
60
+ RecordId,
61
+ WorkerAdmission,
62
+ WorkerInputRequested,
63
+ WorkerOrigin,
64
+ WorkerOriginRecorded,
65
+ WorkerInputCompleted,
66
+ WorkerReportPrepared,
67
+ WorkerReportRefused,
68
+ WorkerReportingIntent,
69
+ SubtreeBudgetReserved,
70
+ PersistedJson,
71
+ } from "../Records.ts";
72
+ import {
73
+ type ScheduledInputFailure,
74
+ ScheduledInputRefused,
75
+ ScheduledInputRetryable,
76
+ } from "../Schedule.ts";
77
+ import {
78
+ SubmissionLedger,
79
+ LedgerError,
80
+ AbortCommand,
81
+ type AbortIntent,
82
+ type Principal,
83
+ type Settlement,
84
+ SubmissionLookupById,
85
+ SubmissionLookupByKey,
86
+ type SubmissionSnapshot,
87
+ } from "../SubmissionLedger.ts";
88
+ import type { SubmissionStatus } from "../SubmissionStatus.ts";
89
+ import { PreparedInput } from "../Subscription.ts";
90
+ import {
91
+ ThreadStore,
92
+ FencedAppendRequest,
93
+ ThreadExportRequest,
94
+ ThreadRead,
95
+ ThreadTailRequest,
96
+ } from "../ThreadStore.ts";
97
+ import {
98
+ WorkerBudgetAuthorizer,
99
+ WorkerConcurrencyLimit,
100
+ WorkerConcurrencyResolver,
101
+ WorkerHostAuthorizer,
102
+ WorkerHostConfig,
103
+ WorkerPolicyResolver,
104
+ type WorkerPolicyTarget,
105
+ } from "../WorkerHost.ts";
106
+ import {
107
+ definitionDigestsEqual,
108
+ resolveDefinitionBinding,
109
+ type ResolvedBinding,
110
+ } from "./agent-registration.ts";
111
+ import { lastWorkerReportMessageId } from "./agent-updates.ts";
112
+
113
+ const failure = (operation: WorkerError["operation"], reason: WorkerError["reason"]) =>
114
+ WorkerError.make({ operation, reason });
115
+
116
+ const storageFailure = (operation: WorkerError["operation"]) => () => failure(operation, "storage");
117
+
118
+ const decode = <S extends Schema.Top>(
119
+ schema: S,
120
+ value: unknown,
121
+ operation: WorkerError["operation"],
122
+ ) =>
123
+ Schema.decodeUnknownEffect(Schema.toType(schema))(value).pipe(
124
+ Effect.mapError(() => failure(operation, "corrupt")),
125
+ );
126
+
127
+ const sameOrigin = Schema.toEquivalence(WorkerOrigin);
128
+ const sameAdmission = Schema.toEquivalence(WorkerAdmission);
129
+ const sameReporting = Schema.toEquivalence(Schema.UndefinedOr(WorkerReportingIntent));
130
+ const sameJson = Schema.toEquivalence(PersistedJson);
131
+ const sameCaps = Schema.toEquivalence(SubagentDelegationCaps);
132
+ const samePolicy = Schema.toEquivalence(AgentPolicy);
133
+
134
+ const amountCaps = [
135
+ ["turns", "maxTurns"],
136
+ ["toolCalls", "maxToolCalls"],
137
+ ["durationMillis", "maxDurationMillis"],
138
+ ["inputTokens", "maxInputTokens"],
139
+ ["outputTokens", "maxOutputTokens"],
140
+ ["costMicrousd", "maxCostMicrousd"],
141
+ ["resultBytes", "maxResultBytes"],
142
+ ] as const;
143
+
144
+ const sourceCaps = (policy: AgentPolicy): SubagentDelegationCaps =>
145
+ SubagentDelegationCaps.make({
146
+ maxTotalChildInvocations: policy.maxToolCalls,
147
+ maxConcurrentChildren: policy.toolConcurrency,
148
+ maxTurns: policy.maxTurns,
149
+ maxToolCalls: policy.maxToolCalls,
150
+ maxDurationMillis: Math.ceil(Duration.toMillis(policy.maxDuration)),
151
+ maxResultBytes: Math.min(
152
+ Number.MAX_SAFE_INTEGER,
153
+ policy.toolResultBounds.maxBytes * policy.maxToolCalls,
154
+ ),
155
+ ...(policy.tokenBudget === undefined
156
+ ? {}
157
+ : { maxInputTokens: policy.tokenBudget, maxOutputTokens: policy.tokenBudget }),
158
+ ...(policy.costBudgetMicrousd === undefined
159
+ ? {}
160
+ : { maxCostMicrousd: policy.costBudgetMicrousd }),
161
+ });
162
+
163
+ const withinPolicy = (origin: WorkerOrigin, source: AgentPolicy, target: AgentPolicy): boolean => {
164
+ const policy = origin.policy;
165
+ const allocation = origin.budget.allocation;
166
+ const caps = origin.budget.caps;
167
+ const ceilings = sourceCaps(source);
168
+
169
+ for (const [, name] of origin.budgetScope === "worker-run" ? [] : amountCaps) {
170
+ if (caps[name] !== undefined && ceilings[name] !== undefined && caps[name] > ceilings[name])
171
+ return false;
172
+ }
173
+ if (
174
+ origin.budgetScope !== "worker-run" &&
175
+ ((caps.maxTotalChildInvocations !== undefined &&
176
+ caps.maxTotalChildInvocations > source.maxToolCalls) ||
177
+ (caps.maxConcurrentChildren !== undefined &&
178
+ caps.maxConcurrentChildren > source.toolConcurrency))
179
+ )
180
+ return false;
181
+ const tokenCeiling = Math.min(source.tokenBudget ?? Infinity, target.tokenBudget ?? Infinity);
182
+
183
+ const costCeiling = Math.min(
184
+ source.costBudgetMicrousd ?? Infinity,
185
+ target.costBudgetMicrousd ?? Infinity,
186
+ );
187
+
188
+ return (
189
+ policy.maxTurns <= Math.min(allocation.turns, source.maxTurns, target.maxTurns) &&
190
+ policy.maxToolCalls <=
191
+ Math.min(allocation.toolCalls, source.maxToolCalls, target.maxToolCalls) &&
192
+ Duration.toMillis(policy.maxDuration) <=
193
+ Math.min(
194
+ allocation.durationMillis,
195
+ Duration.toMillis(source.maxDuration),
196
+ Duration.toMillis(target.maxDuration),
197
+ ) &&
198
+ policy.toolConcurrency <= Math.min(source.toolConcurrency, target.toolConcurrency) &&
199
+ policy.toolResultBounds.maxBytes <=
200
+ Math.min(source.toolResultBounds.maxBytes, target.toolResultBounds.maxBytes) &&
201
+ (tokenCeiling === Infinity ||
202
+ (policy.tokenBudget !== undefined && policy.tokenBudget <= tokenCeiling)) &&
203
+ (costCeiling === Infinity ||
204
+ (policy.costBudgetMicrousd !== undefined && policy.costBudgetMicrousd <= costCeiling)) &&
205
+ (source.tokenBudget === undefined ||
206
+ (allocation.inputTokens > 0 &&
207
+ allocation.outputTokens > 0 &&
208
+ policy.tokenBudget !== undefined &&
209
+ policy.tokenBudget <= allocation.inputTokens + allocation.outputTokens)) &&
210
+ (source.costBudgetMicrousd === undefined ||
211
+ (policy.costBudgetMicrousd !== undefined &&
212
+ policy.costBudgetMicrousd <= allocation.costMicrousd))
213
+ );
214
+ };
215
+
216
+ export interface WorkerRuntimeOptions {
217
+ readonly bindings: ReadonlyArray<ResolvedBinding>;
218
+ readonly deploymentId: DeploymentId;
219
+ readonly producerId: ProducerId;
220
+ readonly settlementPollInterval: Duration.Duration;
221
+ }
222
+
223
+ /** Admission and cancellation enter the owning runtime, never the raw ledger. */
224
+ export class WorkerInputControl extends Context.Service<
225
+ WorkerInputControl,
226
+ {
227
+ readonly submit: (envelope: PreparedInput) => Effect.Effect<Receipt, DurableSubmitFailure>;
228
+ readonly status: (
229
+ receipt: Receipt,
230
+ ) => Effect.Effect<SubmissionStatus, DurableAwaitFailure | ScheduledInputFailure>;
231
+ readonly abort: (command: AbortCommand) => Effect.Effect<AbortIntent, DurableAbortFailure>;
232
+ }
233
+ >()("@effect-agent/thread/internal/WorkerInputControl") {}
234
+
235
+ /** No in-memory ownership: every mutation is reserved in source canonical history with CAS. */
236
+ export const makeWorkerRuntime = Effect.fn("WorkerHost.make")(function* (
237
+ options: WorkerRuntimeOptions,
238
+ ) {
239
+ const control = yield* WorkerInputControl;
240
+ // A routed read may belong to another owner; capture it before exposing worker operations.
241
+ const admission = yield* Effect.serviceOption(PreparedInputAdmission);
242
+
243
+ const deps = {
244
+ ...options,
245
+ ...control,
246
+ store: yield* ThreadStore,
247
+ ledger: yield* SubmissionLedger,
248
+ deliveries: yield* Effect.serviceOption(MessageDeliveryStore),
249
+ crypto: yield* Crypto.Crypto,
250
+ authorizer: yield* WorkerHostAuthorizer,
251
+ budgetAuthorizer: yield* WorkerBudgetAuthorizer,
252
+ policyResolver: yield* WorkerPolicyResolver,
253
+ concurrencyResolver: yield* WorkerConcurrencyResolver,
254
+ limits: yield* WorkerHostConfig,
255
+ failpoint: yield* DurableRuntimeFailpoint,
256
+ status: Option.getOrUndefined(admission)?.submissionStatus ?? control.status,
257
+ };
258
+
259
+ const withCrypto = <A, E>(effect: Effect.Effect<A, E, Crypto.Crypto>) =>
260
+ Effect.provideService(effect, Crypto.Crypto, deps.crypto);
261
+
262
+ const authorizeBudget = Effect.fn("WorkerHost.authorizeBudget")(function* (
263
+ origin: WorkerOrigin,
264
+ principal: Principal,
265
+ ) {
266
+ if (origin.budgetScope !== "worker-run") return;
267
+ // Independence changes accounting ownership, never delegation generations.
268
+ if (origin.depth !== 1) return yield* failure("start", "denied");
269
+
270
+ yield* deps.budgetAuthorizer.authorize({
271
+ source: origin.source,
272
+ principal,
273
+ worker: origin.worker,
274
+ policy: origin.policy,
275
+ budget: origin.budget,
276
+ });
277
+ });
278
+
279
+ const read = (threadId: ThreadId, operation: WorkerError["operation"]) =>
280
+ deps.store
281
+ .export(ThreadExportRequest.make({ threadId }))
282
+ .pipe(Effect.mapError(storageFailure(operation)));
283
+
284
+ const hit = (location: DurableRuntimeFailpointLocation, operation: WorkerError["operation"]) =>
285
+ deps.failpoint.hit(location).pipe(Effect.mapError(storageFailure(operation)));
286
+
287
+ const append = Effect.fn("WorkerHost.append")(
288
+ function* (
289
+ threadId: ThreadId,
290
+ id: string,
291
+ payload:
292
+ | WorkerInputRequested
293
+ | WorkerOriginRecorded
294
+ | WorkerInputCompleted
295
+ | WorkerReportPrepared
296
+ | WorkerReportRefused
297
+ | SubtreeBudgetReserved,
298
+ current: Effect.Success<ReturnType<typeof read>>,
299
+ phase: "source" | "origin" | "completion" | "subtree" | "report",
300
+ ) {
301
+ const operation = "start";
302
+ const tail = yield* deps.store.inspectTail(ThreadTailRequest.make({ threadId }));
303
+
304
+ // Never append against a tail newer than the prefix whose capacity was checked.
305
+ if (tail.tailSequence !== current.tailSequence || tail.tailDigest !== current.tailDigest)
306
+ return false;
307
+ yield* hit(`worker:before-${phase}-append`, operation);
308
+
309
+ const result = yield* deps.store
310
+ .append(
311
+ FencedAppendRequest.make({
312
+ threadId,
313
+ producerEpoch: tail.producerEpoch,
314
+ expectedTailSequence: current.tailSequence,
315
+ expectedTailDigest: current.tailDigest,
316
+ batch: CanonicalBatch.make({
317
+ batchId: Schema.decodeSync(BatchId)(id),
318
+ producerId: deps.producerId,
319
+ records: [
320
+ RecordEnvelope.make({
321
+ recordId: Schema.decodeSync(RecordId)(id),
322
+ family: "thread",
323
+ schemaVersion: 1,
324
+ createdAt: DateTime.makeUnsafe(
325
+ payload._tag === "WorkerInputRequested"
326
+ ? payload.admission.createdAtMillis
327
+ : payload._tag === "WorkerOriginRecorded"
328
+ ? payload.origin.createdAtMillis
329
+ : payload._tag === "WorkerInputCompleted"
330
+ ? payload.completedAtMillis
331
+ : yield* Clock.currentTimeMillis,
332
+ ),
333
+ deploymentId: deps.deploymentId,
334
+ payload,
335
+ }),
336
+ ],
337
+ }),
338
+ }),
339
+ )
340
+ .pipe(
341
+ Effect.as(true),
342
+ Effect.catchTag(["AppendConflict", "FenceRejected"], () => Effect.succeed(false)),
343
+ );
344
+
345
+ if (result) yield* hit(`worker:after-${phase}-append`, operation);
346
+
347
+ return result;
348
+ },
349
+ Effect.mapError(storageFailure("start")),
350
+ );
351
+
352
+ const requests = (records: Effect.Success<ReturnType<typeof read>>["records"]) =>
353
+ records.flatMap(({ record }) =>
354
+ record.payload._tag === "WorkerInputRequested" ? [record.payload] : [],
355
+ );
356
+
357
+ const reportIntent = Effect.fn("WorkerHost.reportIntent")(function* (
358
+ source: ResolvedBinding,
359
+ target: ResolvedBinding,
360
+ delegationId: WorkerRef["delegationId"],
361
+ ): Effect.fn.Return<WorkerOrigin["reporting"], WorkerError> {
362
+ const reports = source.reporting?.filter((entry) => entry.delegationId === delegationId) ?? [];
363
+ const report = reports[0];
364
+
365
+ if (report === undefined) return undefined;
366
+ if (
367
+ reports.length !== 1 ||
368
+ !Object.is(report.target, target.definition) ||
369
+ (report.mode !== "standard" && !Object.is(report.input, source.definition.input)) ||
370
+ (report.destination !== undefined && !Object.is(report.destination.target, source.definition))
371
+ )
372
+ return yield* failure("start", "declaration-unavailable");
373
+
374
+ return {
375
+ sourceDigests: source.digests,
376
+ ...(report.mode === undefined ? {} : { mode: report.mode }),
377
+ ...(report.destination === undefined
378
+ ? {}
379
+ : { destinationDelegationId: report.destination.delegationId }),
380
+ };
381
+ });
382
+
383
+ const sourceAuthority = Effect.fn("WorkerHost.sourceAuthority")(function* (
384
+ threadId: ThreadId,
385
+ submissionId?: SubmissionId,
386
+ ) {
387
+ const current = yield* read(threadId, "start");
388
+ const created = current.records[0]?.record.payload;
389
+
390
+ if (created?._tag !== "ThreadCreated") return yield* failure("start", "not-found");
391
+
392
+ const binding = deps.bindings.find(
393
+ (entry) =>
394
+ entry.agentId === created.agentId &&
395
+ definitionDigestsEqual(entry.digests, created.definitions),
396
+ );
397
+
398
+ const worker = current.records.find(
399
+ ({ record }) => record.payload._tag === "WorkerOriginRecorded",
400
+ )?.record.payload;
401
+
402
+ const attached = current.records.find(
403
+ ({ record }) => record.payload._tag === "SubagentLineageRecorded",
404
+ )?.record.payload;
405
+
406
+ const nested =
407
+ worker?._tag === "WorkerOriginRecorded" || attached?._tag === "SubagentLineageRecorded";
408
+
409
+ let ownerSubmission: SubmissionSnapshot | undefined;
410
+
411
+ if (nested && submissionId === undefined) return yield* failure("start", "denied");
412
+ if (submissionId !== undefined) {
413
+ const submission = yield* deps.ledger
414
+ .lookup(SubmissionLookupById.make({ submissionId }))
415
+ .pipe(Effect.mapError(storageFailure("start")));
416
+
417
+ if (
418
+ Option.isNone(submission) ||
419
+ submission.value.threadId !== threadId ||
420
+ (nested && submission.value.agentId !== created.agentId)
421
+ )
422
+ return yield* failure("start", "denied");
423
+ ownerSubmission = submission.value;
424
+ if (
425
+ worker?._tag === "WorkerOriginRecorded" &&
426
+ (submission.value.workerAdmission === undefined ||
427
+ !sameOrigin(submission.value.workerAdmission.origin, worker.origin))
428
+ )
429
+ return yield* failure("start", "denied");
430
+ if (
431
+ attached?._tag === "SubagentLineageRecorded" &&
432
+ (submission.value.parentLinkage?.parentSubmissionId !== attached.parentSubmissionId ||
433
+ submission.value.parentLinkage.parentToolCallId !== attached.parentLink.parentToolCallId)
434
+ )
435
+ return yield* failure("start", "denied");
436
+ }
437
+
438
+ if (worker?._tag === "WorkerOriginRecorded")
439
+ return {
440
+ current,
441
+ binding,
442
+ submission: ownerSubmission,
443
+ policyOverride: Option.none<AgentPolicy>(),
444
+ policy: worker.origin.policy,
445
+ budget: worker.origin.budget,
446
+ budgetScope: worker.origin.budgetScope,
447
+ grant: worker.origin.grant,
448
+ depth: worker.origin.depth,
449
+ };
450
+ if (attached?._tag === "SubagentLineageRecorded") {
451
+ if (
452
+ attached.policy === undefined ||
453
+ attached.budget === undefined ||
454
+ attached.grant === undefined
455
+ )
456
+ return yield* failure("start", "denied");
457
+
458
+ return {
459
+ current,
460
+ binding,
461
+ submission: ownerSubmission,
462
+ policyOverride: Option.none<AgentPolicy>(),
463
+ policy: attached.policy,
464
+ budget: attached.budget,
465
+ budgetScope: undefined,
466
+ grant: attached.grant,
467
+ depth: attached.parentLink.depth,
468
+ };
469
+ }
470
+
471
+ const ownerBinding =
472
+ ownerSubmission === undefined
473
+ ? undefined
474
+ : deps.bindings.find(
475
+ (entry) =>
476
+ entry.agentId === ownerSubmission.agentId &&
477
+ definitionDigestsEqual(entry.digests, ownerSubmission.agentDigests),
478
+ );
479
+
480
+ const selectedBinding = ownerBinding ?? binding;
481
+
482
+ const changedRootAgent =
483
+ ownerSubmission !== undefined && ownerSubmission.agentId !== created.agentId;
484
+
485
+ // A root conversation may admit a new registered Agent after deployment.
486
+ // Its immutable owner input selects authority; child lineage never changes.
487
+ if (selectedBinding === undefined || (changedRootAgent && ownerBinding === undefined))
488
+ return yield* failure("start", "declaration-unavailable");
489
+
490
+ const selected = yield* deps.policyResolver.resolveSource({
491
+ threadId,
492
+ definition: selectedBinding.definition,
493
+ definitions: ownerSubmission?.agentDigests ?? selectedBinding.digests,
494
+ ...(ownerSubmission === undefined ? {} : { submission: ownerSubmission }),
495
+ });
496
+
497
+ if (Option.isSome(selected) && ownerSubmission !== undefined && ownerBinding === undefined)
498
+ return yield* failure("start", "declaration-unavailable");
499
+
500
+ const effectiveBinding =
501
+ Option.isSome(selected) || changedRootAgent ? selectedBinding : binding;
502
+
503
+ if (effectiveBinding === undefined) return yield* failure("start", "declaration-unavailable");
504
+
505
+ const policy = Option.isNone(selected)
506
+ ? effectiveBinding.definition.policy
507
+ : yield* decode(AgentPolicy, selected.value, "start");
508
+
509
+ return {
510
+ current,
511
+ binding: effectiveBinding,
512
+ submission: ownerSubmission,
513
+ policyOverride: Option.map(selected, () => policy),
514
+ policy,
515
+ budget: undefined,
516
+ budgetScope: undefined,
517
+ grant: undefined,
518
+ depth: 0,
519
+ };
520
+ });
521
+
522
+ const resolveTargetPolicy = Effect.fn("WorkerHost.resolveTargetPolicy")(function* (
523
+ request: WorkerPolicyTarget,
524
+ ) {
525
+ const selected = yield* deps.policyResolver.resolveTarget(request);
526
+
527
+ if (Option.isNone(selected)) return selected;
528
+ const policy = yield* decode(AgentPolicy, selected.value, "start");
529
+
530
+ if (request._tag === "RetainedWorker" && !samePolicy(policy, request.origin.policy))
531
+ return yield* failure("start", "worker-mismatch");
532
+
533
+ return Option.some(policy);
534
+ });
535
+
536
+ const reserveSubtree = Effect.fn("WorkerHost.reserveSubtree")(function* (
537
+ sourceThreadId: ThreadId,
538
+ requested: SubtreeBudgetReserved,
539
+ ): Effect.fn.Return<void, WorkerError> {
540
+ const payload = yield* decode(SubtreeBudgetReserved, requested, "start");
541
+ const recordId = `subtree:${payload.reservationId}`;
542
+
543
+ for (let attempt = 0; attempt < 16; attempt++) {
544
+ const source = yield* sourceAuthority(sourceThreadId, payload.sourceSubmissionId);
545
+
546
+ const previous = source.current.records.find(({ record }) => record.recordId === recordId)
547
+ ?.record.payload;
548
+
549
+ if (previous !== undefined) {
550
+ if (
551
+ previous._tag !== "SubtreeBudgetReserved" ||
552
+ !Schema.toEquivalence(SubtreeBudgetReserved)(previous, payload)
553
+ )
554
+ return yield* failure("start", "idempotency-conflict");
555
+
556
+ return;
557
+ }
558
+ if (payload.depth !== source.depth + 1 || payload.depth > payload.grant.maxDepth)
559
+ return yield* failure("start", "denied");
560
+ const inherited = source.grant;
561
+ const lifetimes = inherited?.childLifetimes;
562
+
563
+ if (
564
+ inherited !== undefined &&
565
+ (payload.depth > inherited.maxDepth ||
566
+ payload.grant.maxDepth > inherited.maxDepth ||
567
+ (lifetimes !== undefined && !lifetimes.includes(payload.lifetime)) ||
568
+ payload.grant.allowedToolNames.some(
569
+ (name) => !inherited.allowedToolNames.includes(name),
570
+ ) ||
571
+ (lifetimes !== undefined &&
572
+ (payload.grant.childLifetimes ?? ["attached", "background"]).some(
573
+ (lifetime) => !lifetimes.includes(lifetime),
574
+ )))
575
+ )
576
+ return yield* failure("start", "denied");
577
+
578
+ const rows = source.current.records.flatMap(({ record }) =>
579
+ record.payload._tag === "SubtreeBudgetReserved" &&
580
+ record.payload.sourceSubmissionId === payload.sourceSubmissionId
581
+ ? [record.payload]
582
+ : [],
583
+ );
584
+
585
+ const caps = payload.budget.caps;
586
+
587
+ if (rows.some((row) => !sameCaps(row.budget.caps, caps)))
588
+ return yield* failure("start", "capacity");
589
+
590
+ const own = {
591
+ turns: source.policy.maxTurns,
592
+ toolCalls: source.policy.maxToolCalls,
593
+ durationMillis: Math.ceil(Duration.toMillis(source.policy.maxDuration)),
594
+ inputTokens: source.policy.tokenBudget ?? source.budget?.allocation.inputTokens ?? 0,
595
+ outputTokens: source.policy.tokenBudget ?? source.budget?.allocation.outputTokens ?? 0,
596
+ costMicrousd:
597
+ source.policy.costBudgetMicrousd ?? source.budget?.allocation.costMicrousd ?? 0,
598
+ resultBytes: source.policy.toolResultBounds.maxBytes,
599
+ };
600
+
601
+ const ceilings = sourceCaps(source.policy);
602
+ const child = payload.policy;
603
+ const allocation = payload.budget.allocation;
604
+
605
+ if (
606
+ child.maxTurns > Math.min(source.policy.maxTurns, allocation.turns) ||
607
+ child.maxToolCalls > Math.min(source.policy.maxToolCalls, allocation.toolCalls) ||
608
+ Duration.toMillis(child.maxDuration) >
609
+ Math.min(Duration.toMillis(source.policy.maxDuration), allocation.durationMillis) ||
610
+ child.toolConcurrency > source.policy.toolConcurrency ||
611
+ child.toolResultBounds.maxBytes > source.policy.toolResultBounds.maxBytes ||
612
+ (source.policy.tokenBudget !== undefined &&
613
+ (child.tokenBudget === undefined ||
614
+ child.tokenBudget > source.policy.tokenBudget ||
615
+ child.tokenBudget > allocation.inputTokens + allocation.outputTokens)) ||
616
+ (source.policy.costBudgetMicrousd !== undefined &&
617
+ (child.costBudgetMicrousd === undefined ||
618
+ child.costBudgetMicrousd >
619
+ Math.min(source.policy.costBudgetMicrousd, allocation.costMicrousd)))
620
+ )
621
+ return yield* failure("start", "capacity");
622
+ for (const [, cap] of amountCaps) {
623
+ if (caps[cap] !== undefined && ceilings[cap] !== undefined && caps[cap] > ceilings[cap])
624
+ return yield* failure("start", "capacity");
625
+ }
626
+ if (
627
+ (caps.maxTotalChildInvocations ?? 0) > source.policy.maxToolCalls ||
628
+ (caps.maxConcurrentChildren ?? 0) > source.policy.toolConcurrency
629
+ )
630
+ return yield* failure("start", "capacity");
631
+ const slots = 1 + (payload.budget.descendantInvocations ?? 0);
632
+
633
+ const chargedSlots = rows.reduce(
634
+ (sum, row) => sum + 1 + (row.budget.descendantInvocations ?? 0),
635
+ slots,
636
+ );
637
+
638
+ const slotLimit = Math.min(
639
+ caps.maxTotalChildInvocations ?? Infinity,
640
+ source.budget === undefined
641
+ ? source.policy.maxToolCalls
642
+ : (source.budget.descendantInvocations ?? 0),
643
+ );
644
+
645
+ if (chargedSlots > slotLimit) return yield* failure("start", "capacity");
646
+ for (const [amount, cap] of amountCaps) {
647
+ // Zero is the encoded absence of an allocation when this dimension is unconfigured.
648
+ // It must not become a new cumulative token or dollar ceiling in a descendant.
649
+ if (
650
+ source.budgetScope === "worker-run" &&
651
+ (amount === "inputTokens" || amount === "outputTokens" || amount === "costMicrousd") &&
652
+ source.budget !== undefined &&
653
+ source.budget.caps[cap] === undefined &&
654
+ source.budget.allocation[amount] === 0 &&
655
+ ceilings[cap] === undefined
656
+ ) {
657
+ const charged = rows.reduce(
658
+ (sum, row) => sum + row.budget.allocation[amount],
659
+ allocation[amount],
660
+ );
661
+
662
+ if (charged > (caps[cap] ?? Infinity)) return yield* failure("start", "capacity");
663
+ continue;
664
+ }
665
+
666
+ const residual =
667
+ source.budget === undefined
668
+ ? (ceilings[cap] ?? Infinity)
669
+ : Math.max(0, source.budget.allocation[amount] - own[amount]);
670
+
671
+ const limit = Math.min(caps[cap] ?? Infinity, residual);
672
+
673
+ const charged = rows.reduce(
674
+ (sum, row) => sum + row.budget.allocation[amount],
675
+ payload.budget.allocation[amount],
676
+ );
677
+
678
+ if (charged > limit) return yield* failure("start", "capacity");
679
+ }
680
+
681
+ // Include unreconciled reservations conservatively; only canonical completion frees an
682
+ // active slot. A worker Thread consumes one slot even when multiple inputs safely join it.
683
+ const completedWorkers = new Set<string>(
684
+ source.current.records.flatMap(({ record }) =>
685
+ record.payload._tag === "WorkerInputCompleted" ? [record.payload.messageId] : [],
686
+ ),
687
+ );
688
+
689
+ const completedAttached = new Set<string>(
690
+ source.current.records.flatMap(({ record }) =>
691
+ record.payload._tag === "SubagentJoined" ? [record.payload.reservationId] : [],
692
+ ),
693
+ );
694
+
695
+ const active = new Set(
696
+ rows
697
+ .filter((row) =>
698
+ row.lifetime === "background"
699
+ ? !completedWorkers.has(row.reservationId)
700
+ : !completedAttached.has(row.reservationId),
701
+ )
702
+ .map((row) => row.childThreadId),
703
+ );
704
+
705
+ if (
706
+ !active.has(payload.childThreadId) &&
707
+ active.size >=
708
+ Math.min(caps.maxConcurrentChildren ?? Infinity, source.policy.toolConcurrency)
709
+ )
710
+ return yield* failure("start", "capacity");
711
+ if (yield* append(sourceThreadId, recordId, payload, source.current, "subtree")) return;
712
+ }
713
+
714
+ return yield* failure("start", "storage");
715
+ });
716
+
717
+ const reservation = Effect.fn("WorkerHost.reserveInput")(function* (
718
+ admission: WorkerAdmission,
719
+ inputDigest: Digest,
720
+ input: PersistedJson,
721
+ principal: Principal,
722
+ ): Effect.fn.Return<void, WorkerError> {
723
+ const origin = admission.origin;
724
+ const id = `worker-input:${admission.messageId}`;
725
+
726
+ for (let attempt = 0; attempt < 16; attempt++) {
727
+ const source = yield* sourceAuthority(origin.source.threadId, admission.sourceSubmissionId);
728
+ const current = source.current;
729
+ const rows = requests(current.records);
730
+ const existing = current.records.find(({ record }) => record.recordId === id)?.record.payload;
731
+
732
+ if (existing !== undefined) {
733
+ if (
734
+ existing._tag !== "WorkerInputRequested" ||
735
+ existing.inputDigest !== inputDigest ||
736
+ !sameAdmission(existing.admission, admission)
737
+ )
738
+ return yield* failure("start", "idempotency-conflict");
739
+ }
740
+ const first = current.records[0]?.record.payload;
741
+
742
+ if (first?._tag !== "ThreadCreated") return yield* failure("start", "denied");
743
+
744
+ const own = rows.filter(
745
+ (row) => row.admission.origin.worker.threadId === origin.worker.threadId,
746
+ );
747
+
748
+ const origins = new Map(
749
+ rows.map((row) => [row.admission.origin.worker.threadId, row.admission.origin]),
750
+ );
751
+
752
+ const prior = origins.get(origin.worker.threadId);
753
+
754
+ if (
755
+ prior === undefined &&
756
+ (source.submission?.agentId ?? first.agentId) !== origin.source.agentId
757
+ )
758
+ return yield* failure("start", "denied");
759
+ if (prior !== undefined && !sameOrigin(prior, origin))
760
+ return yield* failure("start", "worker-mismatch");
761
+ if (prior === undefined && admission.messageId !== origin.firstMessageId)
762
+ return yield* failure("start", "not-found");
763
+ const caps = origin.budget.caps;
764
+
765
+ const sourceBinding = source.binding;
766
+
767
+ const targetBinding = deps.bindings.find(
768
+ (entry) =>
769
+ entry.agentId === origin.worker.targetAgentId &&
770
+ definitionDigestsEqual(entry.digests, origin.targetDigests),
771
+ );
772
+
773
+ if (sourceBinding === undefined || targetBinding === undefined)
774
+ return yield* failure("start", "declaration-unavailable");
775
+ yield* Schema.decodeEffect(Schema.toEncoded(targetBinding.definition.input))(input).pipe(
776
+ Effect.mapError(() => failure("start", "corrupt")),
777
+ );
778
+
779
+ const targetRequest = {
780
+ definition: targetBinding.definition,
781
+ definitions: targetBinding.digests,
782
+ source: origin.source,
783
+ };
784
+
785
+ const selected = yield* resolveTargetPolicy(
786
+ admission.messageId === origin.firstMessageId
787
+ ? {
788
+ ...targetRequest,
789
+ _tag: "InitialInput",
790
+ input,
791
+ inputDigest,
792
+ ...(source.submission === undefined ? {} : { sourceSubmission: source.submission }),
793
+ }
794
+ : { ...targetRequest, _tag: "RetainedWorker", origin: prior ?? origin },
795
+ );
796
+
797
+ const independent = origin.budgetScope === "worker-run";
798
+
799
+ const targetPolicy = Option.isSome(selected)
800
+ ? selected.value
801
+ : independent
802
+ ? targetBinding.definition.policy
803
+ : AgentPolicy.resolve(
804
+ targetBinding.definition.policyOverrides ?? targetBinding.definition.policy,
805
+ source.policy,
806
+ );
807
+
808
+ // Captured authority is checked on replay too, before the retained reservation returns.
809
+ // Static callers retain the old idempotent-return behavior.
810
+ if (
811
+ (existing === undefined || Option.isSome(selected)) &&
812
+ !withinPolicy(origin, independent ? targetPolicy : source.policy, targetPolicy)
813
+ )
814
+ return yield* failure("start", "capacity");
815
+ if (existing !== undefined) return;
816
+ const now = yield* Clock.currentTimeMillis;
817
+
818
+ if (now >= origin.expiresAtMillis) return yield* failure("start", "capacity");
819
+ if (
820
+ (prior === undefined && origins.size >= deps.limits.maxWorkersPerSource) ||
821
+ own.filter((row) => row.admission.reportKind === admission.reportKind).length >=
822
+ (admission.reportKind === "update"
823
+ ? (deps.limits.maxUpdateInputsPerWorker ?? 256)
824
+ : deps.limits.maxInputsPerWorker)
825
+ )
826
+ return yield* failure("start", "capacity");
827
+ if (
828
+ prior === undefined &&
829
+ !sameReporting(
830
+ yield* reportIntent(sourceBinding, targetBinding, origin.worker.delegationId),
831
+ origin.reporting,
832
+ )
833
+ )
834
+ return yield* failure("start", "denied");
835
+ if (independent && source.depth !== 0) return yield* failure("start", "denied");
836
+ const ceilings = sourceCaps(source.policy);
837
+
838
+ const conservedRows = rows.filter((row) => row.admission.origin.budgetScope !== "worker-run");
839
+
840
+ const chargedRows =
841
+ source.depth === 0
842
+ ? conservedRows
843
+ : conservedRows.filter(
844
+ (row) => row.admission.sourceSubmissionId === admission.sourceSubmissionId,
845
+ );
846
+
847
+ // Independent origins do not belong to this pool. Preserve the retained conserved
848
+ // origins' cap identity check separately from the current input's charge selection.
849
+ if (
850
+ !independent &&
851
+ conservedRows.some((row) => !sameCaps(row.admission.origin.budget.caps, caps))
852
+ )
853
+ return yield* failure("start", "capacity");
854
+ if (
855
+ !independent &&
856
+ chargedRows.reduce(
857
+ (sum, row) => sum + 1 + (row.admission.origin.budget.descendantInvocations ?? 0),
858
+ 1 + (origin.budget.descendantInvocations ?? 0),
859
+ ) > Math.min(caps.maxTotalChildInvocations ?? Infinity, source.policy.maxToolCalls)
860
+ )
861
+ return yield* failure("start", "capacity");
862
+ // Worker-owned Run usage is already durable in the destination's Run journal. Each
863
+ // Receipt may join an existing Run, so admitting input must never mint an allowance.
864
+ for (const [amount, cap] of independent ? [] : amountCaps) {
865
+ const limit = Math.min(caps[cap] ?? Infinity, ceilings[cap] ?? Infinity);
866
+
867
+ if (
868
+ chargedRows.reduce(
869
+ (sum, row) => sum + row.admission.origin.budget.allocation[amount],
870
+ origin.budget.allocation[amount],
871
+ ) > limit
872
+ )
873
+ return yield* failure("start", "capacity");
874
+ }
875
+
876
+ // Child owners append acknowledgements before ledger finalization. This works through
877
+ // routed canonical storage; source-local delivery rows are never read from a child owner.
878
+ const completed = new Set(
879
+ current.records.flatMap(({ record }) =>
880
+ record.payload._tag === "WorkerInputCompleted" ? [record.payload.messageId] : [],
881
+ ),
882
+ );
883
+
884
+ const pendingRows = rows.filter((row) => !completed.has(row.admission.messageId));
885
+ const activeWorkers = new Set(pendingRows.map((row) => row.admission.origin.worker.threadId));
886
+
887
+ const pendingOwn = pendingRows.filter(
888
+ (row) =>
889
+ row.admission.origin.worker.threadId === origin.worker.threadId &&
890
+ row.admission.reportKind === admission.reportKind,
891
+ ).length;
892
+
893
+ // Resolve inside the source CAS loop: independently delivered starts must compete
894
+ // against one canonical prefix. A conflict repeats both authority and capacity reads.
895
+ const selectedConcurrency = yield* deps.concurrencyResolver.resolve({
896
+ source: origin.source,
897
+ worker: origin.worker,
898
+ principal,
899
+ ...(source.submission === undefined ? {} : { sourceSubmission: source.submission }),
900
+ });
901
+
902
+ const sourceConcurrency = Option.isSome(selectedConcurrency)
903
+ ? (yield* decode(WorkerConcurrencyLimit, selectedConcurrency.value, "start"))
904
+ .maxActiveWorkersPerSource
905
+ : Infinity;
906
+
907
+ if (
908
+ pendingOwn >=
909
+ (admission.reportKind === "update"
910
+ ? (deps.limits.maxPendingUpdateInputsPerWorker ?? 32)
911
+ : deps.limits.maxPendingInputsPerWorker) ||
912
+ (!activeWorkers.has(origin.worker.threadId) &&
913
+ activeWorkers.size >=
914
+ Math.min(
915
+ sourceConcurrency,
916
+ deps.limits.maxActiveWorkersPerSource ?? source.policy.toolConcurrency,
917
+ independent
918
+ ? Infinity
919
+ : Math.min(caps.maxConcurrentChildren ?? Infinity, source.policy.toolConcurrency),
920
+ ))
921
+ )
922
+ return yield* WorkerError.make({ operation: "start", reason: "capacity", retryable: true });
923
+ if (!independent)
924
+ yield* reserveSubtree(
925
+ origin.source.threadId,
926
+ SubtreeBudgetReserved.make({
927
+ reservationId: Schema.decodeSync(SubtreeBudgetReserved.fields.reservationId)(
928
+ admission.messageId,
929
+ ),
930
+ ...(admission.sourceSubmissionId === undefined
931
+ ? {}
932
+ : { sourceSubmissionId: admission.sourceSubmissionId }),
933
+ childThreadId: origin.worker.threadId,
934
+ lifetime: "background",
935
+ depth: origin.depth,
936
+ policy: origin.policy,
937
+ grant: origin.grant,
938
+ budget: origin.budget,
939
+ }),
940
+ );
941
+ if (
942
+ yield* append(
943
+ origin.source.threadId,
944
+ id,
945
+ WorkerInputRequested.make({ admission, inputDigest }),
946
+ current,
947
+ "source",
948
+ )
949
+ )
950
+ return;
951
+ }
952
+
953
+ return yield* failure("start", "storage");
954
+ });
955
+
956
+ const ensureOrigin = Effect.fn("WorkerHost.ensureOrigin")(function* (origin: WorkerOrigin) {
957
+ for (let attempt = 0; attempt < 16; attempt++) {
958
+ const current = yield* read(origin.worker.threadId, "start");
959
+
960
+ const existing = current.records.find(
961
+ ({ record }) => record.payload._tag === "WorkerOriginRecorded",
962
+ )?.record.payload;
963
+
964
+ if (existing?._tag === "WorkerOriginRecorded") {
965
+ if (!sameOrigin(existing.origin, origin)) return yield* failure("start", "worker-mismatch");
966
+
967
+ return;
968
+ }
969
+ const first = current.records[0]?.record.payload;
970
+
971
+ if (
972
+ first?._tag !== "ThreadCreated" ||
973
+ first.agentId !== origin.worker.targetAgentId ||
974
+ !definitionDigestsEqual(first.definitions, origin.targetDigests) ||
975
+ current.records.some(({ record }) => record.payload._tag === "SubagentLineageRecorded")
976
+ )
977
+ return yield* failure("start", "worker-mismatch");
978
+ if (
979
+ yield* append(
980
+ origin.worker.threadId,
981
+ `worker-origin:${origin.worker.threadId}`,
982
+ WorkerOriginRecorded.make({ origin }),
983
+ current,
984
+ "origin",
985
+ )
986
+ )
987
+ return;
988
+ }
989
+
990
+ return yield* failure("start", "storage");
991
+ });
992
+
993
+ const validateAdmission = Effect.fn("WorkerHost.validateAdmission")(function* (
994
+ unvalidated: WorkerAdmission,
995
+ options: DurableSubmitOptions,
996
+ agentId: Agent.AnyDefinition["id"],
997
+ inputDigest: Digest,
998
+ input: PersistedJson,
999
+ ) {
1000
+ const admission = yield* decode(WorkerAdmission, unvalidated, "start");
1001
+
1002
+ if (admission.reportKind === "update") {
1003
+ if (!Schema.is(WorkerUpdate)(options.messageAdmission))
1004
+ return yield* failure("start", "denied");
1005
+ yield* validateCompletion(options.messageAdmission, options, agentId, inputDigest);
1006
+ }
1007
+
1008
+ yield* deps.authorizer.authorize({
1009
+ sourceThreadId: admission.origin.source.threadId,
1010
+ ...(admission.sourceSubmissionId === undefined
1011
+ ? {}
1012
+ : { sourceSubmissionId: admission.sourceSubmissionId }),
1013
+ principal: options.principal,
1014
+ operation: "start",
1015
+ access: "send",
1016
+ worker: admission.origin.worker,
1017
+ });
1018
+ yield* authorizeBudget(admission.origin, options.principal);
1019
+ if (
1020
+ admission.origin.worker.threadId !== options.threadId ||
1021
+ admission.origin.worker.targetAgentId !== agentId ||
1022
+ !definitionDigestsEqual(admission.origin.targetDigests, options.definitions) ||
1023
+ options.idempotencyKey !== admission.messageId ||
1024
+ (admission.deliveryPrincipal !== undefined &&
1025
+ admission.deliveryPrincipal !== options.principal)
1026
+ )
1027
+ return yield* failure("start", "worker-mismatch");
1028
+ yield* reservation(admission, inputDigest, input, options.principal);
1029
+
1030
+ return admission;
1031
+ });
1032
+
1033
+ const prepareUpdate = Effect.fn("WorkerHost.prepareUpdate")(
1034
+ function* (update: Update, submission: SubmissionSnapshot, messageId: IdempotencyKey) {
1035
+ const origin = submission.workerAdmission?.origin;
1036
+ const intent = origin?.reporting;
1037
+
1038
+ if (origin === undefined || intent?.mode !== "standard") return undefined;
1039
+ if (update.threadId !== submission.threadId || update.agentId !== origin.worker.targetAgentId)
1040
+ return yield* failure("followUp", "worker-mismatch");
1041
+
1042
+ const sourceBinding = deps.bindings.find(
1043
+ (entry) =>
1044
+ entry.agentId === origin.source.agentId &&
1045
+ definitionDigestsEqual(entry.digests, intent.sourceDigests),
1046
+ );
1047
+
1048
+ const targetBinding = deps.bindings.find(
1049
+ (entry) =>
1050
+ entry.agentId === origin.worker.targetAgentId &&
1051
+ definitionDigestsEqual(entry.digests, origin.targetDigests),
1052
+ );
1053
+
1054
+ const reports =
1055
+ sourceBinding?.reporting?.filter(
1056
+ (entry) => entry.delegationId === origin.worker.delegationId,
1057
+ ) ?? [];
1058
+
1059
+ if (
1060
+ sourceBinding === undefined ||
1061
+ targetBinding === undefined ||
1062
+ reports.length !== 1 ||
1063
+ reports[0]?.mode !== "standard" ||
1064
+ reports[0].target !== targetBinding.definition ||
1065
+ !definitionDigestsEqual(submission.agentDigests, origin.targetDigests)
1066
+ )
1067
+ return yield* failure("followUp", "declaration-unavailable");
1068
+ const sourceHistory = yield* read(origin.source.threadId, "followUp");
1069
+
1070
+ const first = requests(sourceHistory.records).find(
1071
+ (row) => row.admission.messageId === origin.firstMessageId,
1072
+ );
1073
+
1074
+ if (first === undefined || !sameOrigin(first.admission.origin, origin))
1075
+ return yield* failure("followUp", "corrupt");
1076
+
1077
+ const source = yield* sourceAuthority(
1078
+ origin.source.threadId,
1079
+ first.admission.sourceSubmissionId,
1080
+ );
1081
+
1082
+ if (
1083
+ source.binding === undefined ||
1084
+ source.submission === undefined ||
1085
+ !definitionDigestsEqual(source.binding.digests, intent.sourceDigests)
1086
+ )
1087
+ return yield* failure("followUp", "declaration-unavailable");
1088
+
1089
+ const recorded = source.current.records.find(
1090
+ ({ record }) => record.payload._tag === "WorkerOriginRecorded",
1091
+ )?.record.payload;
1092
+
1093
+ const receivingOrigin =
1094
+ recorded?._tag === "WorkerOriginRecorded" ? recorded.origin : undefined;
1095
+
1096
+ if (source.depth !== 0 && receivingOrigin === undefined)
1097
+ return yield* failure("followUp", "denied");
1098
+ const now = yield* Clock.currentTimeMillis;
1099
+
1100
+ const deadlineAtMillis = Math.min(
1101
+ origin.expiresAtMillis,
1102
+ receivingOrigin?.expiresAtMillis ?? Infinity,
1103
+ );
1104
+
1105
+ if (now >= deadlineAtMillis) return yield* failure("followUp", "denied");
1106
+ const sourceSubmission = source.submission;
1107
+
1108
+ const input = yield* Schema.decodeEffect(Schema.toEncoded(sourceBinding.definition.input))(
1109
+ source.submission.inputPayload,
1110
+ ).pipe(
1111
+ Effect.flatMap(() => Schema.decodeEffect(PersistedJson)(sourceSubmission.inputPayload)),
1112
+ Effect.mapError(() => failure("followUp", "corrupt")),
1113
+ );
1114
+
1115
+ let workerAdmission: WorkerAdmission | undefined;
1116
+ let principal = submission.principal;
1117
+
1118
+ if (receivingOrigin !== undefined) {
1119
+ const retained = source.submission.workerAdmission;
1120
+
1121
+ if (retained === undefined || !sameOrigin(retained.origin, receivingOrigin))
1122
+ return yield* failure("followUp", "denied");
1123
+ principal = source.submission.principal;
1124
+ workerAdmission = {
1125
+ origin: receivingOrigin,
1126
+ reportKind: "update",
1127
+ messageId,
1128
+ parameters: retained.parameters,
1129
+ createdAtMillis: now,
1130
+ ...(retained.sourceSubmissionId === undefined
1131
+ ? {}
1132
+ : { sourceSubmissionId: retained.sourceSubmissionId }),
1133
+ };
1134
+ }
1135
+
1136
+ const sourceSubmissionId =
1137
+ receivingOrigin === undefined
1138
+ ? first.admission.sourceSubmissionId
1139
+ : workerAdmission?.sourceSubmissionId;
1140
+
1141
+ const authorized = yield* deps.authorizer.authorize({
1142
+ sourceThreadId: receivingOrigin?.source.threadId ?? origin.source.threadId,
1143
+ ...(sourceSubmissionId === undefined ? {} : { sourceSubmissionId }),
1144
+ principal,
1145
+ operation: "followUp",
1146
+ access: "send",
1147
+ worker: receivingOrigin?.worker ?? origin.worker,
1148
+ });
1149
+
1150
+ const message = WorkerUpdate.make({
1151
+ _tag: "WorkerUpdate",
1152
+ schemaVersion: 1,
1153
+ worker: origin.worker,
1154
+ update,
1155
+ });
1156
+
1157
+ const envelope: PreparedInput = {
1158
+ schemaVersion: 1,
1159
+ threadId: origin.source.threadId,
1160
+ deliveryPrincipal: authorized,
1161
+ agentId: origin.source.agentId,
1162
+ definitions: intent.sourceDigests,
1163
+ input,
1164
+ inputDigest: yield* withCrypto(digestJson(input)).pipe(
1165
+ Effect.mapError(storageFailure("followUp")),
1166
+ ),
1167
+ admissionKey: messageId,
1168
+ authorization: { policyId: "worker-report", decisionId: messageId },
1169
+ messageAdmission: message,
1170
+ ...(workerAdmission === undefined
1171
+ ? {}
1172
+ : { workerAdmission: { ...workerAdmission, deliveryPrincipal: authorized } }),
1173
+ };
1174
+
1175
+ return {
1176
+ messageId,
1177
+ envelope: yield* Schema.encodeEffect(PreparedInput)(envelope).pipe(
1178
+ Effect.flatMap(Schema.decodeEffect(PersistedJson)),
1179
+ Effect.mapError(storageFailure("followUp")),
1180
+ ),
1181
+ createdAtMillis: now,
1182
+ deadlineAtMillis,
1183
+ };
1184
+ },
1185
+ Effect.mapError((error) =>
1186
+ error.reason === "storage" || error.reason === "corrupt"
1187
+ ? LedgerError.make({ operation: "worker-update", message: error.reason })
1188
+ : UpdateError.make({ reason: error.reason === "denied" ? "denied" : "unavailable" }),
1189
+ ),
1190
+ );
1191
+
1192
+ const reportRun = Effect.fn("WorkerHost.reportRun")(function* (
1193
+ submission: SubmissionSnapshot,
1194
+ history: Effect.Success<ReturnType<typeof read>>,
1195
+ ): Effect.fn.Return<void, WorkerError> {
1196
+ const admission = submission.workerAdmission;
1197
+ const intent = admission?.origin.reporting;
1198
+
1199
+ if (admission === undefined || intent === undefined) return;
1200
+ const origin = admission.origin;
1201
+
1202
+ const member = history.records.find(
1203
+ ({ record }) =>
1204
+ record.payload._tag === "SubmissionSettled" &&
1205
+ record.payload.submissionId === submission.submissionId,
1206
+ )?.record.payload;
1207
+
1208
+ if (member?._tag !== "SubmissionSettled") return yield* failure("inspect", "corrupt");
1209
+ if (member.runId === undefined) return; // No actual Run means no fabricated report identity.
1210
+ const runId = member.runId;
1211
+
1212
+ const host = history.records.find(
1213
+ ({ record }) => record.payload._tag === "SubmissionSettled" && record.payload.runId === runId,
1214
+ )?.record.payload;
1215
+
1216
+ if (host?._tag !== "SubmissionSettled") return yield* failure("inspect", "corrupt");
1217
+
1218
+ const messageId = yield* withCrypto(
1219
+ digestJson(["worker-report", submission.threadId, runId]),
1220
+ ).pipe(
1221
+ Effect.map((value) => Schema.decodeSync(IdempotencyKey)(`report:${value}`)),
1222
+ Effect.mapError(storageFailure("inspect")),
1223
+ );
1224
+
1225
+ const recordId = `worker-report:${messageId}`;
1226
+
1227
+ const prepare = Effect.fn("WorkerHost.prepareReport")(function* (): Effect.fn.Return<
1228
+ WorkerReportPrepared | WorkerReportRefused,
1229
+ WorkerError
1230
+ > {
1231
+ const refused = (reason: WorkerReportRefused["reason"]) =>
1232
+ WorkerReportRefused.make({ runId, messageId, reason });
1233
+
1234
+ const sourceBinding = deps.bindings.find(
1235
+ (entry) =>
1236
+ entry.agentId === origin.source.agentId &&
1237
+ definitionDigestsEqual(entry.digests, intent.sourceDigests),
1238
+ );
1239
+
1240
+ const targetBinding = deps.bindings.find(
1241
+ (entry) =>
1242
+ entry.agentId === origin.worker.targetAgentId &&
1243
+ definitionDigestsEqual(entry.digests, origin.targetDigests),
1244
+ );
1245
+
1246
+ const reports =
1247
+ sourceBinding?.reporting?.filter(
1248
+ (entry) => entry.delegationId === origin.worker.delegationId,
1249
+ ) ?? [];
1250
+
1251
+ const descriptor = reports[0];
1252
+
1253
+ if (
1254
+ sourceBinding === undefined ||
1255
+ targetBinding === undefined ||
1256
+ descriptor === undefined ||
1257
+ reports.length !== 1 ||
1258
+ !Object.is(descriptor.target, targetBinding.definition) ||
1259
+ (descriptor.mode !== "standard" &&
1260
+ !Object.is(descriptor.input, sourceBinding.definition.input)) ||
1261
+ descriptor.mode !== intent.mode ||
1262
+ descriptor.destination?.delegationId !== intent.destinationDelegationId ||
1263
+ (descriptor.destination !== undefined &&
1264
+ !Object.is(descriptor.destination.target, sourceBinding.definition))
1265
+ )
1266
+ return refused("declaration-unavailable");
1267
+
1268
+ const selected = yield* deps.ledger
1269
+ .lookup(SubmissionLookupById.make({ submissionId: host.submissionId }))
1270
+ .pipe(Effect.mapError(storageFailure("inspect")));
1271
+
1272
+ if (
1273
+ Option.isNone(selected) ||
1274
+ selected.value.threadId !== submission.threadId ||
1275
+ selected.value.receiptId !== host.receiptId ||
1276
+ selected.value.workerAdmission === undefined ||
1277
+ !sameOrigin(selected.value.workerAdmission.origin, origin)
1278
+ )
1279
+ return yield* failure("inspect", "corrupt");
1280
+ const hostSubmission = selected.value;
1281
+ const hostAdmission = selected.value.workerAdmission;
1282
+
1283
+ const sourceHistory = yield* read(origin.source.threadId, "inspect");
1284
+
1285
+ const firstInput = requests(sourceHistory.records).find(
1286
+ (row) => row.admission.messageId === origin.firstMessageId,
1287
+ );
1288
+
1289
+ if (firstInput === undefined || !sameOrigin(firstInput.admission.origin, origin))
1290
+ return yield* failure("inspect", "corrupt");
1291
+
1292
+ // Reporting stays with the original owner even when a later input came from another
1293
+ // source revision. Per-input parameters still belong to the settled Run.
1294
+ const source = yield* sourceAuthority(
1295
+ origin.source.threadId,
1296
+ firstInput.admission.sourceSubmissionId,
1297
+ );
1298
+
1299
+ if (
1300
+ source.binding === undefined ||
1301
+ !definitionDigestsEqual(source.binding.digests, intent.sourceDigests)
1302
+ )
1303
+ return refused("declaration-unavailable");
1304
+
1305
+ const sourceOriginRecord = source.current.records.find(
1306
+ ({ record }) => record.payload._tag === "WorkerOriginRecorded",
1307
+ )?.record.payload;
1308
+
1309
+ const sourceOrigin =
1310
+ sourceOriginRecord?._tag === "WorkerOriginRecorded" ? sourceOriginRecord.origin : undefined;
1311
+
1312
+ if (source.depth !== 0 && sourceOrigin === undefined) return refused("destination");
1313
+ if (
1314
+ descriptor.mode !== "standard" &&
1315
+ sourceOrigin !== undefined &&
1316
+ (descriptor.destination === undefined ||
1317
+ descriptor.destination.delegationId !== sourceOrigin.worker.delegationId ||
1318
+ descriptor.destination.target.id !== sourceOrigin.worker.targetAgentId)
1319
+ )
1320
+ return refused("destination");
1321
+ if (sourceOrigin === undefined && descriptor.destination !== undefined)
1322
+ return refused("destination");
1323
+ const now = yield* Clock.currentTimeMillis;
1324
+
1325
+ const deadlineAtMillis = Math.min(
1326
+ origin.expiresAtMillis,
1327
+ sourceOrigin?.expiresAtMillis ?? Infinity,
1328
+ );
1329
+
1330
+ if (now >= deadlineAtMillis) return refused("expired");
1331
+
1332
+ const context: WorkerContext = {
1333
+ source: origin.source,
1334
+ policy: source.policy,
1335
+ depth: source.depth,
1336
+ ...(source.grant === undefined ? {} : { grant: source.grant }),
1337
+ };
1338
+
1339
+ const report: WorkerRunReport = {
1340
+ worker: origin.worker,
1341
+ context,
1342
+ observation: {
1343
+ _tag: "Settled",
1344
+ receipt: Receipt.make({
1345
+ threadId: hostSubmission.threadId,
1346
+ submissionId: hostSubmission.submissionId,
1347
+ receiptId: hostSubmission.receiptId,
1348
+ queueSequence: hostSubmission.queueSequence,
1349
+ }),
1350
+ runId,
1351
+ settlementId: host.settlementId,
1352
+ outcome: host.outcome,
1353
+ encodedParameters: hostAdmission.parameters,
1354
+ encodedResult: host.result ?? null,
1355
+ budgetExhausted: host.finishReason === "budget-exhausted",
1356
+ },
1357
+ };
1358
+
1359
+ const projection = yield* Effect.suspend(() => descriptor.prepare(report)).pipe(
1360
+ Effect.timeout(
1361
+ Math.min(deps.limits.reportPreparationTimeoutMillis ?? 5_000, deadlineAtMillis - now),
1362
+ ),
1363
+ Effect.map((value) => ({ _tag: "Prepared" as const, value })),
1364
+ Effect.catchTag("WorkerReportPreparationFailure", (error) =>
1365
+ Effect.succeed(refused(error.stage)),
1366
+ ),
1367
+ Effect.catchTag("TimeoutError", () => Effect.succeed(refused("timeout"))),
1368
+ Effect.catchCauseIf(
1369
+ (cause) => !Cause.hasInterrupts(cause),
1370
+ () => Effect.succeed(refused("defect")),
1371
+ ),
1372
+ );
1373
+
1374
+ if (projection._tag === "WorkerReportRefused") return projection;
1375
+
1376
+ if (descriptor.mode === "standard") {
1377
+ const message = projection.value.message;
1378
+
1379
+ if (source.submission === undefined || !Schema.is(WorkerCompletion)(message))
1380
+ return refused("input");
1381
+ if (
1382
+ !Schema.toEquivalence(WorkerRef)(message.report.worker, origin.worker) ||
1383
+ !Schema.toEquivalence(Receipt)(message.report.receipt, report.observation.receipt) ||
1384
+ message.report.runId !== runId ||
1385
+ message.report.settlementId !== host.settlementId ||
1386
+ message.report.outcome !== host.outcome ||
1387
+ message.budgetExhausted !== report.observation.budgetExhausted
1388
+ )
1389
+ return refused("input");
1390
+ } else if (projection.value.message !== undefined) return refused("input");
1391
+
1392
+ const reportInput =
1393
+ descriptor.mode === "standard"
1394
+ ? source.submission?.inputPayload
1395
+ : projection.value.encodedInput;
1396
+
1397
+ const validated = yield* Schema.decodeEffect(
1398
+ Schema.toEncoded(sourceBinding.definition.input),
1399
+ )(reportInput).pipe(
1400
+ Effect.flatMap(() => Schema.decodeUnknownEffect(PersistedJson)(reportInput)),
1401
+ Effect.option,
1402
+ );
1403
+
1404
+ if (Option.isNone(validated)) return refused("input");
1405
+ const input = validated.value;
1406
+
1407
+ const inputDigest = yield* withCrypto(digestJson(input)).pipe(
1408
+ Effect.mapError(storageFailure("inspect")),
1409
+ );
1410
+
1411
+ let workerAdmission: WorkerAdmission | undefined;
1412
+ let principal = hostSubmission.principal;
1413
+
1414
+ if (sourceOrigin !== undefined) {
1415
+ const ownerId =
1416
+ descriptor.mode === "standard"
1417
+ ? firstInput.admission.sourceSubmissionId
1418
+ : hostAdmission.sourceSubmissionId;
1419
+
1420
+ if (ownerId === undefined) return refused("destination");
1421
+
1422
+ const sourceSnapshot = yield* deps.ledger
1423
+ .lookup(SubmissionLookupById.make({ submissionId: ownerId }))
1424
+ .pipe(Effect.mapError(storageFailure("inspect")));
1425
+
1426
+ if (
1427
+ Option.isNone(sourceSnapshot) ||
1428
+ sourceSnapshot.value.threadId !== origin.source.threadId ||
1429
+ sourceSnapshot.value.workerAdmission === undefined ||
1430
+ !sameOrigin(sourceSnapshot.value.workerAdmission.origin, sourceOrigin)
1431
+ )
1432
+ return refused("destination");
1433
+
1434
+ const parameters = yield* Schema.decodeUnknownEffect(PersistedJson)(
1435
+ descriptor.mode === "standard"
1436
+ ? sourceSnapshot.value.workerAdmission.parameters
1437
+ : projection.value.encodedParameters,
1438
+ ).pipe(Effect.option);
1439
+
1440
+ if (Option.isNone(parameters)) return refused("destination");
1441
+ principal = sourceSnapshot.value.principal;
1442
+ workerAdmission = {
1443
+ origin: sourceOrigin,
1444
+ messageId,
1445
+ parameters: parameters.value,
1446
+ createdAtMillis: now,
1447
+ ...(sourceSnapshot.value.workerAdmission.sourceSubmissionId === undefined
1448
+ ? {}
1449
+ : { sourceSubmissionId: sourceSnapshot.value.workerAdmission.sourceSubmissionId }),
1450
+ };
1451
+ }
1452
+
1453
+ // Reporting remains owned by the original allocator, even when a later input joins
1454
+ // or starts another Run. Nested reports authorize the enclosing worker's source owner.
1455
+ const authorizationSourceSubmissionId =
1456
+ sourceOrigin === undefined
1457
+ ? firstInput.admission.sourceSubmissionId
1458
+ : workerAdmission?.sourceSubmissionId;
1459
+
1460
+ const authorized = yield* deps.authorizer
1461
+ .authorize({
1462
+ sourceThreadId: sourceOrigin?.source.threadId ?? origin.source.threadId,
1463
+ ...(authorizationSourceSubmissionId === undefined
1464
+ ? {}
1465
+ : { sourceSubmissionId: authorizationSourceSubmissionId }),
1466
+ principal,
1467
+ operation: "followUp",
1468
+ access: "send",
1469
+ worker: sourceOrigin?.worker ?? origin.worker,
1470
+ })
1471
+ .pipe(
1472
+ Effect.map(Option.some),
1473
+ Effect.catchTag("WorkerError", (error) =>
1474
+ error.reason === "storage" || error.reason === "unavailable"
1475
+ ? Effect.fail(error)
1476
+ : Effect.succeed(Option.none<Principal>()),
1477
+ ),
1478
+ );
1479
+
1480
+ if (Option.isNone(authorized)) return refused("denied");
1481
+
1482
+ const envelope: PreparedInput = {
1483
+ schemaVersion: 1,
1484
+ threadId: origin.source.threadId,
1485
+ deliveryPrincipal: authorized.value,
1486
+ agentId: origin.source.agentId,
1487
+ definitions: intent.sourceDigests,
1488
+ input,
1489
+ inputDigest,
1490
+ admissionKey: messageId,
1491
+ authorization: { policyId: "worker-report", decisionId: messageId },
1492
+ ...(projection.value.message === undefined
1493
+ ? {}
1494
+ : { messageAdmission: projection.value.message }),
1495
+ ...(workerAdmission === undefined
1496
+ ? {}
1497
+ : { workerAdmission: { ...workerAdmission, deliveryPrincipal: authorized.value } }),
1498
+ };
1499
+
1500
+ const encoded = yield* Schema.encodeEffect(PreparedInput)(envelope).pipe(
1501
+ Effect.flatMap(Schema.decodeUnknownEffect(PersistedJson)),
1502
+ Effect.mapError(storageFailure("inspect")),
1503
+ );
1504
+
1505
+ return WorkerReportPrepared.make({
1506
+ runId,
1507
+ messageId,
1508
+ envelope: encoded,
1509
+ createdAtMillis: now,
1510
+ deadlineAtMillis,
1511
+ ...(lastWorkerReportMessageId(history.records) === undefined
1512
+ ? {}
1513
+ : { predecessor: lastWorkerReportMessageId(history.records) }),
1514
+ });
1515
+ });
1516
+
1517
+ let decision: WorkerReportPrepared | WorkerReportRefused | undefined;
1518
+
1519
+ for (let attempt = 0; attempt < 16; attempt++) {
1520
+ const current = yield* read(submission.threadId, "inspect");
1521
+
1522
+ const existing = current.records.find(({ record }) => record.recordId === recordId)?.record
1523
+ .payload;
1524
+
1525
+ if (existing !== undefined) {
1526
+ if (
1527
+ (existing._tag !== "WorkerReportPrepared" && existing._tag !== "WorkerReportRefused") ||
1528
+ existing.runId !== runId ||
1529
+ existing.messageId !== messageId
1530
+ )
1531
+ return yield* failure("inspect", "corrupt");
1532
+ decision = existing;
1533
+ break;
1534
+ }
1535
+ decision ??= yield* prepare();
1536
+ if (yield* append(submission.threadId, recordId, decision, current, "report")) break;
1537
+ if (attempt === 15) return yield* failure("inspect", "storage");
1538
+ }
1539
+ if (decision?._tag !== "WorkerReportPrepared") return;
1540
+ if (Option.isNone(deps.deliveries)) return yield* failure("inspect", "unavailable");
1541
+
1542
+ const envelope = yield* Schema.decodeUnknownEffect(PreparedInput)(decision.envelope).pipe(
1543
+ Effect.mapError(() => failure("inspect", "corrupt")),
1544
+ );
1545
+
1546
+ const prepared = yield* withCrypto(
1547
+ prepareMessageDelivery({
1548
+ key: { ownerThreadId: submission.threadId, messageId },
1549
+ envelope,
1550
+ createdAtMillis: decision.createdAtMillis,
1551
+ deadlineAtMillis: decision.deadlineAtMillis,
1552
+ ...(decision.predecessor === undefined ? {} : { predecessor: decision.predecessor }),
1553
+ }),
1554
+ ).pipe(Effect.mapError(storageFailure("inspect")));
1555
+
1556
+ // Until this insertion commits the child ledger stays nonterminal. Afterwards its independent
1557
+ // due index survives both child and source settlement, including Object eviction.
1558
+ yield* hit("worker:before-report-delivery", "inspect");
1559
+ yield* deps.deliveries.value.insert(prepared).pipe(Effect.mapError(storageFailure("inspect")));
1560
+ yield* hit("worker:after-report-delivery", "inspect");
1561
+ });
1562
+
1563
+ const completeInput = Effect.fn("WorkerHost.completeInput")(function* (
1564
+ submission: SubmissionSnapshot,
1565
+ ) {
1566
+ const admission = submission.workerAdmission;
1567
+
1568
+ if (admission === undefined) return;
1569
+ const child = yield* read(submission.threadId, "inspect");
1570
+
1571
+ yield* reportRun(submission, child);
1572
+
1573
+ const settledEnvelope = child.records.find(
1574
+ ({ record }) =>
1575
+ record.payload._tag === "SubmissionSettled" &&
1576
+ record.payload.submissionId === submission.submissionId,
1577
+ )?.record;
1578
+
1579
+ const settled = settledEnvelope?.payload;
1580
+
1581
+ if (
1582
+ settled?._tag !== "SubmissionSettled" ||
1583
+ settled.receiptId !== submission.receiptId ||
1584
+ settledEnvelope === undefined
1585
+ )
1586
+ return yield* failure("inspect", "corrupt");
1587
+
1588
+ const payload = WorkerInputCompleted.make({
1589
+ messageId: admission.messageId,
1590
+ workerThreadId: submission.threadId,
1591
+ submissionId: submission.submissionId,
1592
+ receiptId: submission.receiptId,
1593
+ settlementId: settled.settlementId,
1594
+ completedAtMillis: DateTime.toEpochMillis(settledEnvelope.createdAt),
1595
+ });
1596
+
1597
+ for (let attempt = 0; attempt < 16; attempt++) {
1598
+ const source = yield* read(admission.origin.source.threadId, "inspect");
1599
+
1600
+ const existing = source.records.find(
1601
+ ({ record }) =>
1602
+ record.payload._tag === "WorkerInputCompleted" &&
1603
+ record.payload.messageId === admission.messageId,
1604
+ )?.record.payload;
1605
+
1606
+ if (existing !== undefined) {
1607
+ if (
1608
+ existing._tag !== "WorkerInputCompleted" ||
1609
+ !Schema.toEquivalence(WorkerInputCompleted)(existing, payload)
1610
+ )
1611
+ return yield* failure("inspect", "corrupt");
1612
+
1613
+ return;
1614
+ }
1615
+ if (
1616
+ yield* append(
1617
+ admission.origin.source.threadId,
1618
+ `worker-completed:${admission.messageId}`,
1619
+ payload,
1620
+ source,
1621
+ "completion",
1622
+ )
1623
+ )
1624
+ return;
1625
+ }
1626
+
1627
+ return yield* failure("inspect", "storage");
1628
+ });
1629
+
1630
+ const facet = (
1631
+ context: WorkerContext,
1632
+ principal: Principal,
1633
+ sourceSubmissionId?: SubmissionId,
1634
+ ): SubagentHost["Service"] => {
1635
+ const authorize = (
1636
+ operation: WorkerError["operation"],
1637
+ access: "context" | "read" | "send" | "control",
1638
+ worker?: WorkerRef,
1639
+ ) =>
1640
+ deps.authorizer.authorize({
1641
+ sourceThreadId: context.source.threadId,
1642
+ ...(sourceSubmissionId === undefined ? {} : { sourceSubmissionId }),
1643
+ principal,
1644
+ operation,
1645
+ access,
1646
+ ...(worker === undefined ? {} : { worker }),
1647
+ });
1648
+
1649
+ const binding = (target: Agent.AnyDefinition, operation: WorkerError["operation"]) =>
1650
+ resolveDefinitionBinding(deps.bindings, target).pipe(
1651
+ Effect.mapError(() => failure(operation, "declaration-unavailable")),
1652
+ );
1653
+
1654
+ const preparedTarget = Effect.fn("WorkerHost.preparedTarget")(function* (
1655
+ target: Agent.AnyDefinition,
1656
+ encodedInput: unknown,
1657
+ ) {
1658
+ const resolved = yield* binding(target, "start");
1659
+
1660
+ yield* Schema.decodeUnknownEffect(Schema.toEncoded(target.input))(encodedInput).pipe(
1661
+ Effect.mapError(() => failure("start", "corrupt")),
1662
+ );
1663
+ const input = yield* decode(PersistedJson, encodedInput, "start");
1664
+
1665
+ const inputDigest = yield* withCrypto(digestJson(input)).pipe(
1666
+ Effect.mapError(storageFailure("start")),
1667
+ );
1668
+
1669
+ const source = yield* sourceAuthority(context.source.threadId, sourceSubmissionId);
1670
+
1671
+ const policy = yield* resolveTargetPolicy({
1672
+ _tag: "InitialInput",
1673
+ definition: resolved.definition,
1674
+ definitions: resolved.digests,
1675
+ source: context.source,
1676
+ ...(source.submission === undefined ? {} : { sourceSubmission: source.submission }),
1677
+ input,
1678
+ inputDigest,
1679
+ });
1680
+
1681
+ return { resolved, source, policy };
1682
+ });
1683
+
1684
+ const findOrigin = Effect.fn("WorkerHost.findOrigin")(function* (
1685
+ worker: WorkerRef,
1686
+ target: Agent.AnyDefinition,
1687
+ operation: WorkerError["operation"],
1688
+ ) {
1689
+ const resolved = yield* binding(target, operation);
1690
+
1691
+ if (worker.targetAgentId !== target.id) return yield* failure(operation, "worker-mismatch");
1692
+ const source = yield* read(context.source.threadId, operation);
1693
+
1694
+ const origin = requests(source.records).find(
1695
+ (row) => row.admission.origin.worker.threadId === worker.threadId,
1696
+ )?.admission.origin;
1697
+
1698
+ if (origin === undefined) return yield* failure(operation, "not-found");
1699
+ if (
1700
+ origin.worker.delegationId !== worker.delegationId ||
1701
+ !definitionDigestsEqual(origin.targetDigests, resolved.digests)
1702
+ )
1703
+ return yield* failure(operation, "worker-mismatch");
1704
+
1705
+ return origin;
1706
+ });
1707
+
1708
+ const receiptInput = Effect.fn("WorkerHost.receiptInput")(function* (
1709
+ request: WorkerReceiptRequest,
1710
+ operation: WorkerError["operation"],
1711
+ ) {
1712
+ const origin = yield* findOrigin(request.worker, request.target, operation);
1713
+ const receipt = request.receipt;
1714
+
1715
+ const snapshot = yield* deps.ledger
1716
+ .lookup(SubmissionLookupById.make({ submissionId: receipt.submissionId }))
1717
+ .pipe(Effect.mapError(storageFailure(operation)));
1718
+
1719
+ if (Option.isNone(snapshot)) return yield* failure(operation, "not-found");
1720
+ const row = snapshot.value;
1721
+
1722
+ if (
1723
+ row.threadId !== request.worker.threadId ||
1724
+ row.threadId !== receipt.threadId ||
1725
+ row.receiptId !== receipt.receiptId ||
1726
+ row.queueSequence !== receipt.queueSequence ||
1727
+ row.workerAdmission === undefined ||
1728
+ !sameOrigin(row.workerAdmission.origin, origin)
1729
+ )
1730
+ return yield* failure(operation, "receipt-mismatch");
1731
+
1732
+ return row.workerAdmission;
1733
+ });
1734
+
1735
+ const observation = Effect.fn("WorkerHost.observation")(function* (
1736
+ request: WorkerReceiptRequest,
1737
+ admission: WorkerAdmission,
1738
+ settlement: Settlement,
1739
+ ): Effect.fn.Return<WorkerObservation, WorkerError> {
1740
+ const history = yield* read(request.worker.threadId, "inspect");
1741
+
1742
+ const record = history.records.find(
1743
+ ({ record }) =>
1744
+ record.payload._tag === "SubmissionSettled" &&
1745
+ record.payload.submissionId === settlement.submissionId,
1746
+ )?.record.payload;
1747
+
1748
+ if (
1749
+ record?._tag !== "SubmissionSettled" ||
1750
+ record.settlementId !== settlement.settlementId ||
1751
+ record.receiptId !== request.receipt.receiptId ||
1752
+ record.outcome !== settlement.outcome
1753
+ )
1754
+ return yield* failure("inspect", "corrupt");
1755
+
1756
+ const input = history.records.find(
1757
+ ({ record }) =>
1758
+ record.payload._tag === "UserInputRecorded" &&
1759
+ record.payload.submissionId === settlement.submissionId,
1760
+ )?.record.payload;
1761
+
1762
+ const inputRunId = input?._tag === "UserInputRecorded" ? input.runId : undefined;
1763
+
1764
+ if (inputRunId !== undefined && record.runId !== undefined && inputRunId !== record.runId)
1765
+ return yield* failure("inspect", "corrupt");
1766
+ const runId = record.runId ?? inputRunId;
1767
+
1768
+ // The host settlement precedes the joined members and carries the Run's actual output.
1769
+ // Both identities come from canonical history; no foreign recovery or finalization is needed.
1770
+ const host =
1771
+ runId === undefined
1772
+ ? undefined
1773
+ : history.records.find(
1774
+ ({ record }) =>
1775
+ record.payload._tag === "SubmissionSettled" && record.payload.runId === runId,
1776
+ )?.record.payload;
1777
+
1778
+ const result = host?._tag === "SubmissionSettled" ? host : record;
1779
+
1780
+ if (result.outcome !== record.outcome) return yield* failure("inspect", "corrupt");
1781
+
1782
+ return {
1783
+ _tag: "Settled",
1784
+ receipt: request.receipt,
1785
+ settlementId: settlement.settlementId,
1786
+ ...(result.runId === undefined ? {} : { runId: result.runId }),
1787
+ outcome: settlement.outcome,
1788
+ encodedParameters: admission.parameters,
1789
+ encodedResult: result.result ?? null,
1790
+ budgetExhausted: result.finishReason === "budget-exhausted",
1791
+ };
1792
+ });
1793
+
1794
+ const send = Effect.fn("WorkerHost.send")(function* (
1795
+ origin: WorkerOrigin,
1796
+ messageId: IdempotencyKey,
1797
+ encodedInput: unknown,
1798
+ encodedParameters: unknown,
1799
+ principal: Principal,
1800
+ operation: "start" | "followUp",
1801
+ ) {
1802
+ if (Option.isNone(deps.deliveries)) return yield* failure(operation, "unavailable");
1803
+ const deliveries = deps.deliveries.value;
1804
+ const input = yield* decode(PersistedJson, encodedInput, operation);
1805
+ const parameters = yield* decode(PersistedJson, encodedParameters, operation);
1806
+
1807
+ const inputDigest = yield* withCrypto(digestJson(input)).pipe(
1808
+ Effect.mapError(storageFailure(operation)),
1809
+ );
1810
+
1811
+ const key = { ownerThreadId: context.source.threadId, messageId };
1812
+ const saved = yield* deliveries.get(key).pipe(Effect.mapError(storageFailure(operation)));
1813
+
1814
+ if (saved !== null) {
1815
+ const metadata = saved.envelope.workerAdmission;
1816
+
1817
+ if (
1818
+ metadata === undefined ||
1819
+ !sameOrigin(metadata.origin, origin) ||
1820
+ !sameJson(metadata.parameters, parameters) ||
1821
+ saved.envelope.inputDigest !== inputDigest ||
1822
+ !sameJson(saved.envelope.input, input)
1823
+ )
1824
+ return yield* failure(operation, "idempotency-conflict");
1825
+ if (saved.receipt !== null) return saved.receipt;
1826
+ } else {
1827
+ const now = yield* Clock.currentTimeMillis;
1828
+
1829
+ if (now >= origin.expiresAtMillis) return yield* failure(operation, "capacity");
1830
+
1831
+ const envelope: PreparedInput = {
1832
+ schemaVersion: 1,
1833
+ threadId: origin.worker.threadId,
1834
+ deliveryPrincipal: principal,
1835
+ agentId: origin.worker.targetAgentId,
1836
+ definitions: origin.targetDigests,
1837
+ input,
1838
+ inputDigest,
1839
+ admissionKey: messageId,
1840
+ authorization: { policyId: "worker-host", decisionId: messageId },
1841
+ workerAdmission: {
1842
+ origin,
1843
+ messageId,
1844
+ parameters,
1845
+ createdAtMillis: now,
1846
+ deliveryPrincipal: principal,
1847
+ ...(sourceSubmissionId === undefined ? {} : { sourceSubmissionId }),
1848
+ },
1849
+ };
1850
+
1851
+ const prepared = yield* withCrypto(
1852
+ prepareMessageDelivery({
1853
+ key,
1854
+ envelope,
1855
+ createdAtMillis: now,
1856
+ deadlineAtMillis: origin.expiresAtMillis,
1857
+ }),
1858
+ ).pipe(Effect.mapError(storageFailure(operation)));
1859
+
1860
+ yield* deliveries
1861
+ .insert(prepared)
1862
+ .pipe(
1863
+ Effect.mapError((error) =>
1864
+ failure(
1865
+ operation,
1866
+ error._tag === "MessageDeliveryError" && error.reason === "capacity"
1867
+ ? "capacity"
1868
+ : "storage",
1869
+ ),
1870
+ ),
1871
+ );
1872
+ }
1873
+
1874
+ // Direct callers and automatic pumps run the same claim/accept/refuse protocol. A
1875
+ // conclusive refusal is retained before it becomes visible to this caller.
1876
+ const processed = yield* MessageDeliveryDriver.pipe(
1877
+ Effect.flatMap((driver) => driver.process(key)),
1878
+ Effect.provide(MessageDeliveryDriver.layer({ batchSize: 1, concurrency: 1 })),
1879
+ Effect.provideService(MessageDeliveryStore, deliveries),
1880
+ Effect.provideService(PreparedInputAdmission, {
1881
+ submit: (prepared) =>
1882
+ deps
1883
+ .submit(prepared)
1884
+ .pipe(
1885
+ Effect.mapError((error) =>
1886
+ error._tag === "AdmissionConflict" || error._tag === "AgentInputError"
1887
+ ? ScheduledInputRefused.make({ code: error._tag })
1888
+ : error._tag === "AdmissionPolicyError" && error.reason === "refused"
1889
+ ? ScheduledInputRefused.make({ code: error.code })
1890
+ : ScheduledInputRetryable.make({ reason: "storage" }),
1891
+ ),
1892
+ ),
1893
+ submissionStatus: (receipt) =>
1894
+ deps
1895
+ .status(receipt)
1896
+ .pipe(Effect.mapError(() => ScheduledInputRetryable.make({ reason: "storage" }))),
1897
+ }),
1898
+ Effect.provideService(Crypto.Crypto, deps.crypto),
1899
+ Effect.mapError(storageFailure(operation)),
1900
+ );
1901
+
1902
+ if (processed.receipt !== null) return processed.receipt;
1903
+ if (processed.status === "refused") {
1904
+ const reason = Schema.decodeUnknownOption(WorkerError.fields.reason)(
1905
+ processed.refusal?.startsWith("worker-")
1906
+ ? processed.refusal.slice("worker-".length)
1907
+ : processed.refusal === "AdmissionConflict"
1908
+ ? "idempotency-conflict"
1909
+ : processed.refusal === "AgentInputError"
1910
+ ? "corrupt"
1911
+ : undefined,
1912
+ );
1913
+
1914
+ return yield* failure(
1915
+ operation,
1916
+ Option.getOrElse(reason, () => "denied"),
1917
+ );
1918
+ }
1919
+
1920
+ // A live claim or a future delivery deadline is not a storage failure. Keep the
1921
+ // receipt-only success contract: retention alone does not mean the child started.
1922
+ return yield* failure(
1923
+ operation,
1924
+ processed.status === "pending" && processed.retry.lastFailure === null
1925
+ ? "delivery-pending"
1926
+ : "storage",
1927
+ );
1928
+ });
1929
+
1930
+ const messageIdFor = (parts: ReadonlyArray<string>) =>
1931
+ withCrypto(digestJson(parts)).pipe(
1932
+ Effect.map((digest) => Schema.decodeSync(IdempotencyKey)(`worker:${digest}`)),
1933
+ Effect.mapError(storageFailure("start")),
1934
+ );
1935
+
1936
+ const summarize = Effect.fn("WorkerHost.summarize")(function* (
1937
+ origin: WorkerOrigin,
1938
+ all: ReadonlyArray<WorkerInputRequested>,
1939
+ operation: "list" | "inspect",
1940
+ ) {
1941
+ yield* authorize(operation, "read", origin.worker);
1942
+ let latestReceipt: Receipt | null = null;
1943
+ let active = false;
1944
+ let starting = false;
1945
+
1946
+ for (const row of all) {
1947
+ if (row.admission.origin.worker.threadId !== origin.worker.threadId) continue;
1948
+
1949
+ const delivery = Option.isNone(deps.deliveries)
1950
+ ? null
1951
+ : yield* deps.deliveries.value
1952
+ .get({
1953
+ ownerThreadId: context.source.threadId,
1954
+ messageId: row.admission.messageId,
1955
+ })
1956
+ .pipe(Effect.mapError(storageFailure(operation)));
1957
+
1958
+ const principal = row.admission.deliveryPrincipal ?? delivery?.envelope.deliveryPrincipal;
1959
+
1960
+ const found =
1961
+ principal === undefined
1962
+ ? Option.none()
1963
+ : yield* deps.ledger
1964
+ .lookup(
1965
+ SubmissionLookupByKey.make({
1966
+ threadId: origin.worker.threadId,
1967
+ principal,
1968
+ idempotencyKey: row.admission.messageId,
1969
+ }),
1970
+ )
1971
+ .pipe(Effect.mapError(storageFailure(operation)));
1972
+
1973
+ if (Option.isNone(found)) {
1974
+ if (delivery?.status !== "refused") starting = true;
1975
+ continue;
1976
+ }
1977
+ active ||= found.value.state !== "settled";
1978
+ if (latestReceipt === null || found.value.queueSequence > latestReceipt.queueSequence) {
1979
+ latestReceipt = {
1980
+ threadId: found.value.threadId,
1981
+ submissionId: found.value.submissionId,
1982
+ receiptId: found.value.receiptId,
1983
+ queueSequence: found.value.queueSequence,
1984
+ };
1985
+ }
1986
+ }
1987
+
1988
+ return {
1989
+ worker: origin.worker,
1990
+ latestReceipt,
1991
+ state: active
1992
+ ? ("active" as const)
1993
+ : starting || latestReceipt === null
1994
+ ? ("starting" as const)
1995
+ : ("idle" as const),
1996
+ };
1997
+ });
1998
+
1999
+ return {
2000
+ context: Effect.gen(function* () {
2001
+ yield* authorize("context", "context");
2002
+ if (context.depth !== 0) return context;
2003
+ const source = yield* sourceAuthority(context.source.threadId, sourceSubmissionId);
2004
+
2005
+ return {
2006
+ ...context,
2007
+ policy: Option.getOrElse(source.policyOverride, () => context.policy),
2008
+ };
2009
+ }),
2010
+ resolveTargetPolicy: Effect.fn("WorkerHost.resolvePreparedTargetPolicy")(function* (request) {
2011
+ yield* authorize("start", "send");
2012
+
2013
+ return (yield* preparedTarget(request.target, request.encodedInput)).policy;
2014
+ }),
2015
+ start: Effect.fn("WorkerHost.start")(function* (request) {
2016
+ const principal = yield* authorize("start", "send");
2017
+
2018
+ if (context.depth !== 0 && sourceSubmissionId === undefined)
2019
+ return yield* failure("start", "denied");
2020
+ const prepared = yield* preparedTarget(request.target, request.encodedInput);
2021
+ const resolved = prepared.resolved;
2022
+ const sourcePolicy = Option.getOrElse(prepared.source.policyOverride, () => context.policy);
2023
+
2024
+ const grant = yield* Schema.decodeUnknownEffect(SubagentGrant)(request.encodedGrant).pipe(
2025
+ Effect.mapError(() => failure("start", "corrupt")),
2026
+ );
2027
+
2028
+ const messageId = yield* messageIdFor([
2029
+ context.source.threadId,
2030
+ request.delegationId,
2031
+ request.idempotencyKey,
2032
+ ]);
2033
+
2034
+ if (Option.isNone(deps.deliveries)) return yield* failure("start", "unavailable");
2035
+
2036
+ const existing = yield* deps.deliveries.value
2037
+ .get({ ownerThreadId: context.source.threadId, messageId })
2038
+ .pipe(Effect.mapError(storageFailure("start")));
2039
+
2040
+ const now = yield* Clock.currentTimeMillis;
2041
+ const previousOrigin = existing?.envelope.workerAdmission?.origin;
2042
+ const sourceBinding = prepared.source.binding;
2043
+
2044
+ if (sourceBinding === undefined) return yield* failure("start", "declaration-unavailable");
2045
+
2046
+ const reporting =
2047
+ previousOrigin === undefined
2048
+ ? yield* reportIntent(sourceBinding, resolved, request.delegationId)
2049
+ : previousOrigin.reporting;
2050
+
2051
+ if (reporting?.mode === "standard" && sourceSubmissionId === undefined)
2052
+ return yield* failure("start", "denied");
2053
+
2054
+ const origin = yield* decode(
2055
+ WorkerOrigin,
2056
+ {
2057
+ worker: {
2058
+ schemaVersion: 1,
2059
+ delegationId: request.delegationId,
2060
+ targetAgentId: request.target.id,
2061
+ threadId: Schema.decodeSync(ThreadId)(messageId),
2062
+ },
2063
+ source: existing?.envelope.workerAdmission?.origin.source ?? context.source,
2064
+ targetDigests: resolved.digests,
2065
+ policy: request.policy,
2066
+ budget: request.budget,
2067
+ ...(request.budgetScope === undefined ? {} : { budgetScope: request.budgetScope }),
2068
+ grant,
2069
+ depth: context.depth + 1,
2070
+ firstMessageId: messageId,
2071
+ createdAtMillis: existing?.envelope.workerAdmission?.origin.createdAtMillis ?? now,
2072
+ expiresAtMillis:
2073
+ existing?.envelope.workerAdmission?.origin.expiresAtMillis ??
2074
+ now + deps.limits.lifetimeMillis,
2075
+ ...(reporting === undefined ? {} : { reporting }),
2076
+ ...(request.toolCallAllowance === undefined
2077
+ ? {}
2078
+ : { toolCallAllowance: request.toolCallAllowance }),
2079
+ },
2080
+ "start",
2081
+ );
2082
+
2083
+ yield* authorizeBudget(origin, principal);
2084
+
2085
+ const targetPolicy = Option.isSome(prepared.policy)
2086
+ ? prepared.policy.value
2087
+ : origin.budgetScope === "worker-run"
2088
+ ? resolved.definition.policy
2089
+ : AgentPolicy.resolve(
2090
+ resolved.definition.policyOverrides ?? resolved.definition.policy,
2091
+ sourcePolicy,
2092
+ );
2093
+
2094
+ if (
2095
+ !withinPolicy(
2096
+ origin,
2097
+ origin.budgetScope === "worker-run" ? targetPolicy : sourcePolicy,
2098
+ targetPolicy,
2099
+ )
2100
+ )
2101
+ return yield* failure("start", "capacity");
2102
+
2103
+ const receipt = yield* send(
2104
+ origin,
2105
+ messageId,
2106
+ request.encodedInput,
2107
+ request.encodedParameters,
2108
+ principal,
2109
+ "start",
2110
+ );
2111
+
2112
+ return { worker: origin.worker, receipt };
2113
+ }),
2114
+ followUp: Effect.fn("WorkerHost.followUp")(function* (request) {
2115
+ const principal = yield* authorize("followUp", "send", request.worker);
2116
+ const origin = yield* findOrigin(request.worker, request.target, "followUp");
2117
+
2118
+ yield* resolveTargetPolicy({
2119
+ _tag: "RetainedWorker",
2120
+ definition: request.target,
2121
+ definitions: origin.targetDigests,
2122
+ source: origin.source,
2123
+ origin,
2124
+ });
2125
+
2126
+ yield* Schema.decodeUnknownEffect(Schema.toEncoded(request.target.input))(
2127
+ request.encodedInput,
2128
+ ).pipe(Effect.mapError(() => failure("followUp", "corrupt")));
2129
+
2130
+ const messageId = yield* messageIdFor([
2131
+ context.source.threadId,
2132
+ request.worker.threadId,
2133
+ "followUp",
2134
+ request.idempotencyKey,
2135
+ ]);
2136
+
2137
+ return yield* send(
2138
+ origin,
2139
+ messageId,
2140
+ request.encodedInput,
2141
+ request.encodedParameters,
2142
+ principal,
2143
+ "followUp",
2144
+ );
2145
+ }),
2146
+ inspect: Effect.fn("WorkerHost.inspect")(function* (request) {
2147
+ yield* authorize("inspect", "read", request.worker);
2148
+ const admission = yield* receiptInput(request, "inspect");
2149
+
2150
+ const status = yield* deps
2151
+ .status(request.receipt)
2152
+ .pipe(Effect.mapError(storageFailure("inspect")));
2153
+
2154
+ return status._tag === "pending"
2155
+ ? { _tag: "Pending" as const, receipt: request.receipt }
2156
+ : yield* observation(request, admission, status.settlement);
2157
+ }),
2158
+ summary: Effect.fn("WorkerHost.inspectWorker")(function* (request) {
2159
+ yield* authorize("inspect", "read", request.worker);
2160
+ const origin = yield* findOrigin(request.worker, request.target, "inspect");
2161
+ const source = yield* read(context.source.threadId, "inspect");
2162
+
2163
+ return yield* summarize(origin, requests(source.records), "inspect");
2164
+ }),
2165
+ observe: (request) =>
2166
+ Stream.unwrap(
2167
+ Effect.gen(function* () {
2168
+ yield* authorize("observe", "read", request.worker);
2169
+ yield* findOrigin(request.worker, request.target, "observe");
2170
+ const after = request.after ?? 0;
2171
+
2172
+ if (!Number.isSafeInteger(after) || after < 0)
2173
+ return yield* failure("observe", "corrupt");
2174
+
2175
+ const tail = yield* deps.store
2176
+ .inspectTail(ThreadTailRequest.make({ threadId: request.worker.threadId }))
2177
+ .pipe(Effect.mapError(storageFailure("observe")));
2178
+
2179
+ return Stream.paginate(after, (cursor) =>
2180
+ Effect.gen(function* () {
2181
+ if (cursor >= tail.tailSequence) return [[], Option.none<number>()] as const;
2182
+ const limit = Math.min(256, tail.tailSequence - cursor);
2183
+
2184
+ const page = yield* deps.store
2185
+ .read(
2186
+ ThreadRead.make({
2187
+ threadId: request.worker.threadId,
2188
+ afterSequence: Schema.decodeSync(CanonicalSequence)(cursor),
2189
+ limit,
2190
+ }),
2191
+ )
2192
+ .pipe(Stream.runCollect, Effect.mapError(storageFailure("observe")));
2193
+
2194
+ if (
2195
+ page.length === 0 ||
2196
+ page.length > limit ||
2197
+ page.some(
2198
+ (entry, index) =>
2199
+ entry.threadId !== request.worker.threadId ||
2200
+ entry.sequence !== cursor + index + 1,
2201
+ )
2202
+ )
2203
+ return yield* failure("observe", "corrupt");
2204
+
2205
+ const entries = yield* Effect.forEach(page, (entry) =>
2206
+ Schema.encodeEffect(RecordEnvelope)(entry.record).pipe(
2207
+ Effect.flatMap((record) =>
2208
+ Schema.decodeEffect(WorkerHistoryEntry)({
2209
+ sequence: entry.sequence,
2210
+ recordId: entry.record.recordId,
2211
+ record,
2212
+ }),
2213
+ ),
2214
+ Effect.mapError(() => failure("observe", "corrupt")),
2215
+ ),
2216
+ );
2217
+
2218
+ const next = cursor + page.length;
2219
+
2220
+ return [
2221
+ entries,
2222
+ next >= tail.tailSequence ? Option.none<number>() : Option.some(next),
2223
+ ] as const;
2224
+ }),
2225
+ );
2226
+ }),
2227
+ ),
2228
+ await: Effect.fn("WorkerHost.await")(function* (request) {
2229
+ yield* authorize("await", "read", request.worker);
2230
+ const admission = yield* receiptInput(request, "await");
2231
+
2232
+ while (true) {
2233
+ const status = yield* deps
2234
+ .status(request.receipt)
2235
+ .pipe(Effect.mapError(storageFailure("await")));
2236
+
2237
+ if (status._tag === "settled")
2238
+ return yield* observation(request, admission, status.settlement);
2239
+ // Poll the same host-routed read used by inspect. Interruption stops only this wait.
2240
+ yield* Effect.sleep(deps.settlementPollInterval);
2241
+ }
2242
+ }),
2243
+ list: Effect.fn("WorkerHost.list")(function* (request) {
2244
+ yield* authorize("list", "read");
2245
+ yield* binding(request.target, "list");
2246
+ if (!Number.isSafeInteger(request.limit) || request.limit < 1 || request.limit > 100)
2247
+ return yield* failure("list", "capacity");
2248
+ const source = yield* read(context.source.threadId, "list");
2249
+ const all = requests(source.records);
2250
+
2251
+ const origins = [
2252
+ ...new Map(
2253
+ all.map((row) => [row.admission.origin.worker.threadId, row.admission.origin]),
2254
+ ).values(),
2255
+ ]
2256
+ .filter(
2257
+ (origin) =>
2258
+ origin.worker.delegationId === request.delegationId &&
2259
+ origin.worker.targetAgentId === request.target.id &&
2260
+ (request.after === undefined || origin.worker.threadId > request.after),
2261
+ )
2262
+ .sort((left, right) => left.worker.threadId.localeCompare(right.worker.threadId));
2263
+
2264
+ const selected = origins.slice(0, request.limit);
2265
+
2266
+ const items = yield* Effect.forEach(selected, (origin) => summarize(origin, all, "list"));
2267
+
2268
+ return {
2269
+ items,
2270
+ next:
2271
+ origins.length > selected.length
2272
+ ? (selected[selected.length - 1]?.worker.threadId ?? null)
2273
+ : null,
2274
+ };
2275
+ }),
2276
+ cancel: Effect.fn("WorkerHost.cancel")(function* (request) {
2277
+ const principal = yield* authorize("cancel", "control", request.worker);
2278
+
2279
+ yield* receiptInput(request, "cancel");
2280
+ yield* deps
2281
+ .abort(
2282
+ AbortCommand.make({
2283
+ submissionId: request.receipt.submissionId,
2284
+ author: principal,
2285
+ reason: "Worker owner requested cancellation of this Receipt",
2286
+ }),
2287
+ )
2288
+ .pipe(
2289
+ Effect.mapError((error) =>
2290
+ error._tag === "JoinedToHost" ? error : failure("cancel", "storage"),
2291
+ ),
2292
+ );
2293
+ }),
2294
+ };
2295
+ };
2296
+
2297
+ const validateCompletion = Effect.fn("WorkerHost.validateCompletion")(function* (
2298
+ unvalidated: FrameworkMessage,
2299
+ options: DurableSubmitOptions,
2300
+ agentId: AgentId,
2301
+ inputDigest: Digest,
2302
+ ) {
2303
+ const message = yield* Schema.decodeEffect(FrameworkMessage)(unvalidated).pipe(
2304
+ Effect.mapError(() => failure("followUp", "corrupt")),
2305
+ );
2306
+
2307
+ const child = yield* read(
2308
+ message._tag === "WorkerCompletion"
2309
+ ? message.report.worker.threadId
2310
+ : message.worker.threadId,
2311
+ "followUp",
2312
+ );
2313
+
2314
+ const frozen =
2315
+ message._tag === "WorkerCompletion"
2316
+ ? child.records.flatMap(({ record }) =>
2317
+ record.payload._tag === "WorkerReportPrepared" &&
2318
+ record.payload.runId === message.report.runId
2319
+ ? [record.payload.envelope]
2320
+ : [],
2321
+ )[0]
2322
+ : child.records.flatMap(({ record }) =>
2323
+ record.payload._tag === "AgentUpdateEmitted" &&
2324
+ Schema.toEquivalence(Update)(record.payload.update, message.update) &&
2325
+ record.payload.delivery !== undefined
2326
+ ? [record.payload.delivery.envelope]
2327
+ : [],
2328
+ )[0];
2329
+
2330
+ if (frozen === undefined) return yield* failure("followUp", "denied");
2331
+
2332
+ const envelope = yield* Schema.decodeUnknownEffect(PreparedInput)(frozen).pipe(
2333
+ Effect.mapError(() => failure("followUp", "corrupt")),
2334
+ );
2335
+
2336
+ if (
2337
+ !Schema.is(FrameworkMessage)(envelope.messageAdmission) ||
2338
+ !Schema.toEquivalence(FrameworkMessage)(envelope.messageAdmission, message) ||
2339
+ envelope.threadId !== options.threadId ||
2340
+ envelope.agentId !== agentId ||
2341
+ envelope.inputDigest !== inputDigest ||
2342
+ envelope.deliveryPrincipal !== options.principal ||
2343
+ envelope.admissionKey !== options.idempotencyKey ||
2344
+ !definitionDigestsEqual(envelope.definitions, options.definitions) ||
2345
+ !Schema.toEquivalence(Schema.UndefinedOr(WorkerAdmission))(
2346
+ envelope.workerAdmission,
2347
+ options.workerAdmission,
2348
+ )
2349
+ )
2350
+ return yield* failure("followUp", "denied");
2351
+
2352
+ const recorded = child.records.find(
2353
+ ({ record }) => record.payload._tag === "WorkerOriginRecorded",
2354
+ )?.record.payload;
2355
+
2356
+ if (recorded?._tag !== "WorkerOriginRecorded" || recorded.origin.reporting?.mode !== "standard")
2357
+ return yield* failure("followUp", "denied");
2358
+ const origin = recorded.origin;
2359
+ const source = yield* read(origin.source.threadId, "followUp");
2360
+
2361
+ const first = requests(source.records).find(
2362
+ (row) => row.admission.messageId === origin.firstMessageId,
2363
+ );
2364
+
2365
+ if (first === undefined || !sameOrigin(first.admission.origin, origin))
2366
+ return yield* failure("followUp", "denied");
2367
+ const receiving = envelope.workerAdmission;
2368
+
2369
+ const sourceSubmissionId =
2370
+ receiving === undefined ? first.admission.sourceSubmissionId : receiving.sourceSubmissionId;
2371
+
2372
+ const principal = yield* deps.authorizer.authorize({
2373
+ sourceThreadId: receiving?.origin.source.threadId ?? origin.source.threadId,
2374
+ ...(sourceSubmissionId === undefined ? {} : { sourceSubmissionId }),
2375
+ principal: options.principal,
2376
+ operation: "followUp",
2377
+ access: "send",
2378
+ worker: receiving?.origin.worker ?? origin.worker,
2379
+ });
2380
+
2381
+ if (principal !== options.principal) return yield* failure("followUp", "denied");
2382
+
2383
+ return message;
2384
+ });
2385
+
2386
+ const acquire = Effect.fn("WorkerHost.acquire")(function* (request: {
2387
+ readonly sourceThreadId: ThreadId;
2388
+ readonly principal: Principal;
2389
+ readonly sourceSubmissionId?: SubmissionId;
2390
+ }) {
2391
+ const { sourceThreadId, principal } = request;
2392
+
2393
+ yield* deps.authorizer.authorize({
2394
+ sourceThreadId,
2395
+ ...(request.sourceSubmissionId === undefined
2396
+ ? {}
2397
+ : { sourceSubmissionId: request.sourceSubmissionId }),
2398
+ principal,
2399
+ operation: "context",
2400
+ access: "context",
2401
+ });
2402
+ const current = yield* read(sourceThreadId, "context");
2403
+ const created = current.records[0]?.record.payload;
2404
+
2405
+ if (created?._tag !== "ThreadCreated") return yield* failure("context", "not-found");
2406
+
2407
+ const resolved = deps.bindings.find(
2408
+ (entry) =>
2409
+ entry.agentId === created.agentId &&
2410
+ definitionDigestsEqual(entry.digests, created.definitions),
2411
+ );
2412
+
2413
+ if (resolved === undefined) return yield* failure("context", "declaration-unavailable");
2414
+
2415
+ const origin = current.records.find(
2416
+ ({ record }) => record.payload._tag === "WorkerOriginRecorded",
2417
+ )?.record.payload;
2418
+
2419
+ const attached = current.records.find(
2420
+ ({ record }) => record.payload._tag === "SubagentLineageRecorded",
2421
+ )?.record.payload;
2422
+
2423
+ const retained =
2424
+ origin?._tag === "WorkerOriginRecorded"
2425
+ ? origin.origin
2426
+ : attached?._tag === "SubagentLineageRecorded"
2427
+ ? attached
2428
+ : undefined;
2429
+
2430
+ const selected =
2431
+ request.sourceSubmissionId === undefined
2432
+ ? undefined
2433
+ : yield* sourceAuthority(sourceThreadId, request.sourceSubmissionId);
2434
+
2435
+ return facet(
2436
+ {
2437
+ source: {
2438
+ _tag: "programmatic",
2439
+ threadId: sourceThreadId,
2440
+ agentId: selected?.submission?.agentId ?? created.agentId,
2441
+ },
2442
+ policy:
2443
+ retained?.policy ?? selected?.binding?.definition.policy ?? resolved.definition.policy,
2444
+ depth:
2445
+ origin?._tag === "WorkerOriginRecorded"
2446
+ ? origin.origin.depth
2447
+ : attached?._tag === "SubagentLineageRecorded"
2448
+ ? attached.parentLink.depth
2449
+ : 0,
2450
+ ...(retained?.grant === undefined ? {} : { grant: retained.grant }),
2451
+ },
2452
+ principal,
2453
+ request.sourceSubmissionId,
2454
+ );
2455
+ });
2456
+
2457
+ return {
2458
+ facet,
2459
+ prepareUpdate,
2460
+ acquire,
2461
+ validateCompletion,
2462
+ validateAdmission,
2463
+ ensureOrigin,
2464
+ completeInput,
2465
+ reserveSubtree,
2466
+ };
2467
+ });