@assemblyline-agents/runtime 1.0.0 → 3.0.0

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 (460) hide show
  1. package/LICENSE +1 -1
  2. package/dist/a2a-client.d.ts +22 -0
  3. package/dist/a2a-client.d.ts.map +1 -0
  4. package/dist/a2a-client.js +211 -0
  5. package/dist/a2a-client.js.map +1 -0
  6. package/dist/agent-capability-snapshot.d.ts +32 -0
  7. package/dist/agent-capability-snapshot.d.ts.map +1 -0
  8. package/dist/agent-capability-snapshot.js +77 -0
  9. package/dist/agent-capability-snapshot.js.map +1 -0
  10. package/dist/agent-event-handlers.d.ts +21 -0
  11. package/dist/agent-event-handlers.d.ts.map +1 -0
  12. package/dist/agent-event-handlers.js +64 -0
  13. package/dist/agent-event-handlers.js.map +1 -0
  14. package/dist/agent-hook-context.d.ts +8 -0
  15. package/dist/agent-hook-context.d.ts.map +1 -0
  16. package/dist/agent-hook-context.js +29 -0
  17. package/dist/agent-hook-context.js.map +1 -0
  18. package/dist/agent-hook-evaluation.d.ts +61 -0
  19. package/dist/agent-hook-evaluation.d.ts.map +1 -0
  20. package/dist/agent-hook-evaluation.js +197 -0
  21. package/dist/agent-hook-evaluation.js.map +1 -0
  22. package/dist/agent-hook-run-lifecycle.d.ts +44 -0
  23. package/dist/agent-hook-run-lifecycle.d.ts.map +1 -0
  24. package/dist/agent-hook-run-lifecycle.js +76 -0
  25. package/dist/agent-hook-run-lifecycle.js.map +1 -0
  26. package/dist/agent-state.d.ts +31 -0
  27. package/dist/agent-state.d.ts.map +1 -0
  28. package/dist/agent-state.js +80 -0
  29. package/dist/agent-state.js.map +1 -0
  30. package/dist/agent-surface.d.ts +32 -0
  31. package/dist/agent-surface.d.ts.map +1 -0
  32. package/dist/agent-surface.js +85 -0
  33. package/dist/agent-surface.js.map +1 -0
  34. package/dist/attachments.d.ts +5 -1
  35. package/dist/attachments.d.ts.map +1 -1
  36. package/dist/attachments.js +58 -32
  37. package/dist/attachments.js.map +1 -1
  38. package/dist/audience.d.ts +30 -0
  39. package/dist/audience.d.ts.map +1 -0
  40. package/dist/audience.js +68 -0
  41. package/dist/audience.js.map +1 -0
  42. package/dist/authored-hooks.d.ts +6 -0
  43. package/dist/authored-hooks.d.ts.map +1 -0
  44. package/dist/authored-hooks.js +17 -0
  45. package/dist/authored-hooks.js.map +1 -0
  46. package/dist/automation-event-match.d.ts +8 -0
  47. package/dist/automation-event-match.d.ts.map +1 -0
  48. package/dist/automation-event-match.js +25 -0
  49. package/dist/automation-event-match.js.map +1 -0
  50. package/dist/background-review-trigger.d.ts +9 -0
  51. package/dist/background-review-trigger.d.ts.map +1 -0
  52. package/dist/background-review-trigger.js +72 -0
  53. package/dist/background-review-trigger.js.map +1 -0
  54. package/dist/background-review-types.d.ts +60 -0
  55. package/dist/background-review-types.d.ts.map +1 -0
  56. package/dist/background-review-types.js +2 -0
  57. package/dist/background-review-types.js.map +1 -0
  58. package/dist/background-review-worker.d.ts +14 -0
  59. package/dist/background-review-worker.d.ts.map +1 -0
  60. package/dist/background-review-worker.js +61 -0
  61. package/dist/background-review-worker.js.map +1 -0
  62. package/dist/background-review.d.ts +5 -0
  63. package/dist/background-review.d.ts.map +1 -0
  64. package/dist/background-review.js +332 -0
  65. package/dist/background-review.js.map +1 -0
  66. package/dist/builtin-tool-executors.d.ts +50 -27
  67. package/dist/builtin-tool-executors.d.ts.map +1 -1
  68. package/dist/builtin-tool-executors.js +332 -124
  69. package/dist/builtin-tool-executors.js.map +1 -1
  70. package/dist/builtin-tools.d.ts +16 -9
  71. package/dist/builtin-tools.d.ts.map +1 -1
  72. package/dist/builtin-tools.js +308 -116
  73. package/dist/builtin-tools.js.map +1 -1
  74. package/dist/capability-catalog.d.ts +3 -2
  75. package/dist/capability-catalog.d.ts.map +1 -1
  76. package/dist/capability-catalog.js +12 -7
  77. package/dist/capability-catalog.js.map +1 -1
  78. package/dist/capability-inspection.d.ts +31 -0
  79. package/dist/capability-inspection.d.ts.map +1 -0
  80. package/dist/capability-inspection.js +58 -0
  81. package/dist/capability-inspection.js.map +1 -0
  82. package/dist/channel-http-util.d.ts.map +1 -1
  83. package/dist/channel-http-util.js +6 -5
  84. package/dist/channel-http-util.js.map +1 -1
  85. package/dist/channel-ingress.d.ts +16 -1
  86. package/dist/channel-ingress.d.ts.map +1 -1
  87. package/dist/channel-ingress.js +152 -14
  88. package/dist/channel-ingress.js.map +1 -1
  89. package/dist/channel.d.ts +73 -3
  90. package/dist/channel.d.ts.map +1 -1
  91. package/dist/checkpoints.d.ts +1 -1
  92. package/dist/checkpoints.d.ts.map +1 -1
  93. package/dist/checkpoints.js +6 -6
  94. package/dist/checkpoints.js.map +1 -1
  95. package/dist/child-process-env.d.ts +7 -0
  96. package/dist/child-process-env.d.ts.map +1 -0
  97. package/dist/child-process-env.js +41 -0
  98. package/dist/child-process-env.js.map +1 -0
  99. package/dist/computer-relay-protocol.d.ts.map +1 -1
  100. package/dist/computer-relay-protocol.js +4 -4
  101. package/dist/computer-relay-protocol.js.map +1 -1
  102. package/dist/concurrency.d.ts +1 -1
  103. package/dist/concurrency.js +1 -1
  104. package/dist/connection-auth-util.d.ts +1 -0
  105. package/dist/connection-auth-util.d.ts.map +1 -1
  106. package/dist/connection-auth-util.js +3 -1
  107. package/dist/connection-auth-util.js.map +1 -1
  108. package/dist/connection-clients.d.ts +11 -3
  109. package/dist/connection-clients.d.ts.map +1 -1
  110. package/dist/connection-clients.js +71 -8
  111. package/dist/connection-clients.js.map +1 -1
  112. package/dist/connection-event-store.d.ts +98 -0
  113. package/dist/connection-event-store.d.ts.map +1 -0
  114. package/dist/connection-event-store.js +162 -0
  115. package/dist/connection-event-store.js.map +1 -0
  116. package/dist/connection-events.d.ts +51 -0
  117. package/dist/connection-events.d.ts.map +1 -0
  118. package/dist/connection-events.js +343 -0
  119. package/dist/connection-events.js.map +1 -0
  120. package/dist/connection-stores.d.ts +6 -0
  121. package/dist/connection-stores.d.ts.map +1 -1
  122. package/dist/connection-stores.js +20 -1
  123. package/dist/connection-stores.js.map +1 -1
  124. package/dist/connection-util.d.ts +3 -2
  125. package/dist/connection-util.d.ts.map +1 -1
  126. package/dist/connection-util.js +18 -1
  127. package/dist/connection-util.js.map +1 -1
  128. package/dist/connections.d.ts +60 -5
  129. package/dist/connections.d.ts.map +1 -1
  130. package/dist/connections.js +390 -57
  131. package/dist/connections.js.map +1 -1
  132. package/dist/context-policy-util.d.ts.map +1 -1
  133. package/dist/context-policy-util.js +1 -3
  134. package/dist/context-policy-util.js.map +1 -1
  135. package/dist/conversation-context.d.ts +9 -4
  136. package/dist/conversation-context.d.ts.map +1 -1
  137. package/dist/conversation-context.js +65 -19
  138. package/dist/conversation-context.js.map +1 -1
  139. package/dist/conversation-transcript.d.ts +8 -5
  140. package/dist/conversation-transcript.d.ts.map +1 -1
  141. package/dist/conversation-transcript.js +24 -5
  142. package/dist/conversation-transcript.js.map +1 -1
  143. package/dist/conversation-turn-coalescing.d.ts +22 -0
  144. package/dist/conversation-turn-coalescing.d.ts.map +1 -0
  145. package/dist/conversation-turn-coalescing.js +121 -0
  146. package/dist/conversation-turn-coalescing.js.map +1 -0
  147. package/dist/conversation-turn-dispatch.d.ts +5 -2
  148. package/dist/conversation-turn-dispatch.d.ts.map +1 -1
  149. package/dist/conversation-turn-dispatch.js +59 -22
  150. package/dist/conversation-turn-dispatch.js.map +1 -1
  151. package/dist/default-outbound-route.d.ts +29 -0
  152. package/dist/default-outbound-route.d.ts.map +1 -0
  153. package/dist/default-outbound-route.js +105 -0
  154. package/dist/default-outbound-route.js.map +1 -0
  155. package/dist/delivery-artifacts.d.ts +2 -0
  156. package/dist/delivery-artifacts.d.ts.map +1 -0
  157. package/dist/delivery-artifacts.js +34 -0
  158. package/dist/delivery-artifacts.js.map +1 -0
  159. package/dist/delivery-files.d.ts +5 -0
  160. package/dist/delivery-files.d.ts.map +1 -0
  161. package/dist/delivery-files.js +33 -0
  162. package/dist/delivery-files.js.map +1 -0
  163. package/dist/delivery-queue.d.ts +21 -1
  164. package/dist/delivery-queue.d.ts.map +1 -1
  165. package/dist/delivery-queue.js +144 -1
  166. package/dist/delivery-queue.js.map +1 -1
  167. package/dist/delivery-send.d.ts +2 -2
  168. package/dist/delivery-send.d.ts.map +1 -1
  169. package/dist/delivery-send.js +256 -100
  170. package/dist/delivery-send.js.map +1 -1
  171. package/dist/durable-files.d.ts +37 -0
  172. package/dist/durable-files.d.ts.map +1 -0
  173. package/dist/durable-files.js +63 -0
  174. package/dist/durable-files.js.map +1 -0
  175. package/dist/harness-loop.d.ts +18 -9
  176. package/dist/harness-loop.d.ts.map +1 -1
  177. package/dist/harness-loop.js +245 -50
  178. package/dist/harness-loop.js.map +1 -1
  179. package/dist/heic-transcode-worker.d.ts +2 -0
  180. package/dist/heic-transcode-worker.d.ts.map +1 -0
  181. package/dist/heic-transcode-worker.js +59 -0
  182. package/dist/heic-transcode-worker.js.map +1 -0
  183. package/dist/heic-transcode.d.ts +18 -0
  184. package/dist/heic-transcode.d.ts.map +1 -0
  185. package/dist/heic-transcode.js +99 -0
  186. package/dist/heic-transcode.js.map +1 -0
  187. package/dist/human-input-routing.d.ts +22 -0
  188. package/dist/human-input-routing.d.ts.map +1 -0
  189. package/dist/human-input-routing.js +26 -0
  190. package/dist/human-input-routing.js.map +1 -0
  191. package/dist/in-memory-agent-state-store.d.ts +21 -0
  192. package/dist/in-memory-agent-state-store.d.ts.map +1 -0
  193. package/dist/in-memory-agent-state-store.js +97 -0
  194. package/dist/in-memory-agent-state-store.js.map +1 -0
  195. package/dist/in-memory-conversation-turn-store.d.ts +3 -1
  196. package/dist/in-memory-conversation-turn-store.d.ts.map +1 -1
  197. package/dist/in-memory-conversation-turn-store.js +41 -2
  198. package/dist/in-memory-conversation-turn-store.js.map +1 -1
  199. package/dist/in-memory-run-store.d.ts +8 -0
  200. package/dist/in-memory-run-store.d.ts.map +1 -1
  201. package/dist/in-memory-run-store.js +28 -5
  202. package/dist/in-memory-run-store.js.map +1 -1
  203. package/dist/in-memory-sandbox-session-store.d.ts +2 -1
  204. package/dist/in-memory-sandbox-session-store.d.ts.map +1 -1
  205. package/dist/in-memory-sandbox-session-store.js +65 -1
  206. package/dist/in-memory-sandbox-session-store.js.map +1 -1
  207. package/dist/in-memory-small-stores.d.ts +18 -1
  208. package/dist/in-memory-small-stores.d.ts.map +1 -1
  209. package/dist/in-memory-small-stores.js +107 -1
  210. package/dist/in-memory-small-stores.js.map +1 -1
  211. package/dist/in-memory-workspace-store.d.ts +40 -0
  212. package/dist/in-memory-workspace-store.d.ts.map +1 -0
  213. package/dist/in-memory-workspace-store.js +370 -0
  214. package/dist/in-memory-workspace-store.js.map +1 -0
  215. package/dist/index.d.ts +116 -45
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js +637 -566
  218. package/dist/index.js.map +1 -1
  219. package/dist/json-util.d.ts +8 -0
  220. package/dist/json-util.d.ts.map +1 -1
  221. package/dist/json-util.js +8 -0
  222. package/dist/json-util.js.map +1 -1
  223. package/dist/learning-store.d.ts +111 -0
  224. package/dist/learning-store.d.ts.map +1 -0
  225. package/dist/learning-store.js +193 -0
  226. package/dist/learning-store.js.map +1 -0
  227. package/dist/local-sandbox.d.ts +3 -2
  228. package/dist/local-sandbox.d.ts.map +1 -1
  229. package/dist/local-sandbox.js +69 -25
  230. package/dist/local-sandbox.js.map +1 -1
  231. package/dist/mcp-client.d.ts.map +1 -1
  232. package/dist/mcp-client.js +3 -2
  233. package/dist/mcp-client.js.map +1 -1
  234. package/dist/media-processor.d.ts +42 -0
  235. package/dist/media-processor.d.ts.map +1 -0
  236. package/dist/media-processor.js +2 -0
  237. package/dist/media-processor.js.map +1 -0
  238. package/dist/model-media.d.ts +13 -1
  239. package/dist/model-media.d.ts.map +1 -1
  240. package/dist/model-media.js +81 -18
  241. package/dist/model-media.js.map +1 -1
  242. package/dist/model-visible-interrupts.d.ts +10 -0
  243. package/dist/model-visible-interrupts.d.ts.map +1 -0
  244. package/dist/model-visible-interrupts.js +41 -0
  245. package/dist/model-visible-interrupts.js.map +1 -0
  246. package/dist/operator-controls.d.ts.map +1 -1
  247. package/dist/operator-controls.js +16 -3
  248. package/dist/operator-controls.js.map +1 -1
  249. package/dist/outbound-http-policy.d.ts +7 -0
  250. package/dist/outbound-http-policy.d.ts.map +1 -0
  251. package/dist/outbound-http-policy.js +155 -0
  252. package/dist/outbound-http-policy.js.map +1 -0
  253. package/dist/principals.d.ts +18 -0
  254. package/dist/principals.d.ts.map +1 -0
  255. package/dist/principals.js +90 -0
  256. package/dist/principals.js.map +1 -0
  257. package/dist/public-api.d.ts +21 -0
  258. package/dist/public-api.d.ts.map +1 -0
  259. package/dist/public-api.js +19 -0
  260. package/dist/public-api.js.map +1 -0
  261. package/dist/replay-resume.d.ts +15 -3
  262. package/dist/replay-resume.d.ts.map +1 -1
  263. package/dist/replay-resume.js +256 -24
  264. package/dist/replay-resume.js.map +1 -1
  265. package/dist/resource-projection-util.d.ts +1 -1
  266. package/dist/resource-projection-util.d.ts.map +1 -1
  267. package/dist/resource-projection-util.js +21 -10
  268. package/dist/resource-projection-util.js.map +1 -1
  269. package/dist/resource-projection.d.ts +8 -1
  270. package/dist/resource-projection.d.ts.map +1 -1
  271. package/dist/resource-projection.js +230 -26
  272. package/dist/resource-projection.js.map +1 -1
  273. package/dist/run-heartbeat.d.ts +12 -2
  274. package/dist/run-heartbeat.d.ts.map +1 -1
  275. package/dist/run-heartbeat.js +31 -4
  276. package/dist/run-heartbeat.js.map +1 -1
  277. package/dist/run-outcome.d.ts +9 -5
  278. package/dist/run-outcome.d.ts.map +1 -1
  279. package/dist/run-outcome.js +16 -5
  280. package/dist/run-outcome.js.map +1 -1
  281. package/dist/run-recovery.d.ts +31 -2
  282. package/dist/run-recovery.d.ts.map +1 -1
  283. package/dist/run-recovery.js +211 -32
  284. package/dist/run-recovery.js.map +1 -1
  285. package/dist/run-replay.d.ts +35 -0
  286. package/dist/run-replay.d.ts.map +1 -0
  287. package/dist/run-replay.js +193 -0
  288. package/dist/run-replay.js.map +1 -0
  289. package/dist/run-result.d.ts +4 -0
  290. package/dist/run-result.d.ts.map +1 -0
  291. package/dist/run-result.js +18 -0
  292. package/dist/run-result.js.map +1 -0
  293. package/dist/run-timeline-query.d.ts +38 -0
  294. package/dist/run-timeline-query.d.ts.map +1 -0
  295. package/dist/run-timeline-query.js +99 -0
  296. package/dist/run-timeline-query.js.map +1 -0
  297. package/dist/runs-query.d.ts.map +1 -1
  298. package/dist/runs-query.js +12 -4
  299. package/dist/runs-query.js.map +1 -1
  300. package/dist/runtime-bundle.d.ts.map +1 -1
  301. package/dist/runtime-bundle.js +2 -0
  302. package/dist/runtime-bundle.js.map +1 -1
  303. package/dist/runtime-learning.d.ts +88 -0
  304. package/dist/runtime-learning.d.ts.map +1 -0
  305. package/dist/runtime-learning.js +260 -0
  306. package/dist/runtime-learning.js.map +1 -0
  307. package/dist/runtime-types.d.ts +79 -10
  308. package/dist/runtime-types.d.ts.map +1 -1
  309. package/dist/sandbox-fs.d.ts +9 -5
  310. package/dist/sandbox-fs.d.ts.map +1 -1
  311. package/dist/sandbox-fs.js +50 -33
  312. package/dist/sandbox-fs.js.map +1 -1
  313. package/dist/sandbox-handle.d.ts +25 -0
  314. package/dist/sandbox-handle.d.ts.map +1 -0
  315. package/dist/sandbox-handle.js +120 -0
  316. package/dist/sandbox-handle.js.map +1 -0
  317. package/dist/sandbox-session-identity.d.ts +14 -0
  318. package/dist/sandbox-session-identity.d.ts.map +1 -0
  319. package/dist/sandbox-session-identity.js +33 -0
  320. package/dist/sandbox-session-identity.js.map +1 -0
  321. package/dist/sandbox-session-key.d.ts.map +1 -1
  322. package/dist/sandbox-session-key.js +14 -10
  323. package/dist/sandbox-session-key.js.map +1 -1
  324. package/dist/sandbox-session-lifecycle.d.ts +12 -0
  325. package/dist/sandbox-session-lifecycle.d.ts.map +1 -0
  326. package/dist/sandbox-session-lifecycle.js +261 -0
  327. package/dist/sandbox-session-lifecycle.js.map +1 -0
  328. package/dist/sandbox-snapshot-policy.js +3 -3
  329. package/dist/sandbox-snapshot-policy.js.map +1 -1
  330. package/dist/sandbox-state-sync.d.ts +22 -0
  331. package/dist/sandbox-state-sync.d.ts.map +1 -0
  332. package/dist/sandbox-state-sync.js +147 -0
  333. package/dist/sandbox-state-sync.js.map +1 -0
  334. package/dist/sandbox-sync-worker.d.ts +11 -2
  335. package/dist/sandbox-sync-worker.d.ts.map +1 -1
  336. package/dist/sandbox-sync-worker.js +143 -31
  337. package/dist/sandbox-sync-worker.js.map +1 -1
  338. package/dist/schedule-execution.d.ts.map +1 -1
  339. package/dist/schedule-execution.js +187 -57
  340. package/dist/schedule-execution.js.map +1 -1
  341. package/dist/sdk-api-client.d.ts +17 -0
  342. package/dist/sdk-api-client.d.ts.map +1 -0
  343. package/dist/sdk-api-client.js +55 -0
  344. package/dist/sdk-api-client.js.map +1 -0
  345. package/dist/security.js +2 -2
  346. package/dist/security.js.map +1 -1
  347. package/dist/self-improvement.d.ts +34 -6
  348. package/dist/self-improvement.d.ts.map +1 -1
  349. package/dist/self-improvement.js +140 -34
  350. package/dist/self-improvement.js.map +1 -1
  351. package/dist/skill-bundles.d.ts +55 -0
  352. package/dist/skill-bundles.d.ts.map +1 -0
  353. package/dist/skill-bundles.js +134 -0
  354. package/dist/skill-bundles.js.map +1 -0
  355. package/dist/source-loader.d.ts +8 -0
  356. package/dist/source-loader.d.ts.map +1 -1
  357. package/dist/source-loader.js +41 -10
  358. package/dist/source-loader.js.map +1 -1
  359. package/dist/state-store-helpers.d.ts +2 -0
  360. package/dist/state-store-helpers.d.ts.map +1 -1
  361. package/dist/state-store-helpers.js +11 -1
  362. package/dist/state-store-helpers.js.map +1 -1
  363. package/dist/state-stores.d.ts +2 -0
  364. package/dist/state-stores.d.ts.map +1 -1
  365. package/dist/state-stores.js +40 -7
  366. package/dist/state-stores.js.map +1 -1
  367. package/dist/state.d.ts +344 -5
  368. package/dist/state.d.ts.map +1 -1
  369. package/dist/state.js +44 -2
  370. package/dist/state.js.map +1 -1
  371. package/dist/storage.d.ts +59 -2
  372. package/dist/storage.d.ts.map +1 -1
  373. package/dist/storage.js +183 -6
  374. package/dist/storage.js.map +1 -1
  375. package/dist/subagent-execution.d.ts +7 -6
  376. package/dist/subagent-execution.d.ts.map +1 -1
  377. package/dist/subagent-execution.js +58 -19
  378. package/dist/subagent-execution.js.map +1 -1
  379. package/dist/target-instructions.d.ts +14 -0
  380. package/dist/target-instructions.d.ts.map +1 -0
  381. package/dist/target-instructions.js +18 -0
  382. package/dist/target-instructions.js.map +1 -0
  383. package/dist/tool-apis.d.ts.map +1 -1
  384. package/dist/tool-apis.js +55 -10
  385. package/dist/tool-apis.js.map +1 -1
  386. package/dist/tool-execution.d.ts +26 -13
  387. package/dist/tool-execution.d.ts.map +1 -1
  388. package/dist/tool-execution.js +368 -239
  389. package/dist/tool-execution.js.map +1 -1
  390. package/dist/turn-media.d.ts +29 -0
  391. package/dist/turn-media.d.ts.map +1 -0
  392. package/dist/turn-media.js +233 -0
  393. package/dist/turn-media.js.map +1 -0
  394. package/dist/usage-reconciliation.d.ts +1 -1
  395. package/dist/usage-reconciliation.js +1 -1
  396. package/dist/workspace-id.d.ts +10 -0
  397. package/dist/workspace-id.d.ts.map +1 -0
  398. package/dist/workspace-id.js +55 -0
  399. package/dist/workspace-id.js.map +1 -0
  400. package/dist/workspace-manifest.d.ts +24 -0
  401. package/dist/workspace-manifest.d.ts.map +1 -0
  402. package/dist/workspace-manifest.js +111 -0
  403. package/dist/workspace-manifest.js.map +1 -0
  404. package/dist/workspace-operation-limiter.d.ts +16 -0
  405. package/dist/workspace-operation-limiter.d.ts.map +1 -0
  406. package/dist/workspace-operation-limiter.js +31 -0
  407. package/dist/workspace-operation-limiter.js.map +1 -0
  408. package/dist/workspace-operations.d.ts +145 -0
  409. package/dist/workspace-operations.d.ts.map +1 -0
  410. package/dist/workspace-operations.js +420 -0
  411. package/dist/workspace-operations.js.map +1 -0
  412. package/dist/workspace-runtime.d.ts +110 -0
  413. package/dist/workspace-runtime.d.ts.map +1 -0
  414. package/dist/workspace-runtime.js +240 -0
  415. package/dist/workspace-runtime.js.map +1 -0
  416. package/dist/workspace-search.d.ts +55 -0
  417. package/dist/workspace-search.d.ts.map +1 -0
  418. package/dist/workspace-search.js +262 -0
  419. package/dist/workspace-search.js.map +1 -0
  420. package/dist/workspace-service.d.ts +173 -0
  421. package/dist/workspace-service.d.ts.map +1 -0
  422. package/dist/workspace-service.js +619 -0
  423. package/dist/workspace-service.js.map +1 -0
  424. package/dist/workspace.d.ts +7 -0
  425. package/dist/workspace.d.ts.map +1 -0
  426. package/dist/workspace.js +7 -0
  427. package/dist/workspace.js.map +1 -0
  428. package/package.json +7 -4
  429. package/dist/agent-harness.d.ts +0 -108
  430. package/dist/agent-harness.d.ts.map +0 -1
  431. package/dist/agent-harness.js +0 -2
  432. package/dist/agent-harness.js.map +0 -1
  433. package/dist/attachments-legacy.d.ts +0 -17
  434. package/dist/attachments-legacy.d.ts.map +0 -1
  435. package/dist/attachments-legacy.js +0 -273
  436. package/dist/attachments-legacy.js.map +0 -1
  437. package/dist/code-mode.d.ts +0 -20
  438. package/dist/code-mode.d.ts.map +0 -1
  439. package/dist/code-mode.js +0 -658
  440. package/dist/code-mode.js.map +0 -1
  441. package/dist/hook-dispatch.d.ts +0 -19
  442. package/dist/hook-dispatch.d.ts.map +0 -1
  443. package/dist/hook-dispatch.js +0 -37
  444. package/dist/hook-dispatch.js.map +0 -1
  445. package/dist/pi-agent-harness.d.ts +0 -40
  446. package/dist/pi-agent-harness.d.ts.map +0 -1
  447. package/dist/pi-agent-harness.js +0 -222
  448. package/dist/pi-agent-harness.js.map +0 -1
  449. package/dist/pi-harness.d.ts +0 -42
  450. package/dist/pi-harness.d.ts.map +0 -1
  451. package/dist/pi-harness.js +0 -142
  452. package/dist/pi-harness.js.map +0 -1
  453. package/dist/run-resolver.d.ts +0 -35
  454. package/dist/run-resolver.d.ts.map +0 -1
  455. package/dist/run-resolver.js +0 -84
  456. package/dist/run-resolver.js.map +0 -1
  457. package/dist/usage-budget.d.ts +0 -29
  458. package/dist/usage-budget.d.ts.map +0 -1
  459. package/dist/usage-budget.js +0 -145
  460. package/dist/usage-budget.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,91 +1,109 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { join, resolve } from "node:path";
3
3
  import { builtInToolDefinition } from "./builtin-tools.js";
4
- export { builtInToolDefaults } from "./builtin-tools.js";
5
- import { createHookDispatcher } from "./hook-dispatch.js";
4
+ export * from "./public-api.js";
5
+ export { builtInToolDefaults, FILES_MOUNT_TOOL_NAME, FILES_SEARCH_TOOL_NAME, HISTORY_SEARCH_TOOL_NAME, PAIR_TOOL_NAME } from "./builtin-tools.js";
6
+ export { inspectAgentCapabilities } from "./capability-inspection.js";
7
+ export { CONNECTION_PAIRING_UNAVAILABLE_EVENT, executePairTool } from "./builtin-tool-executors.js";
6
8
  import { resolveEvalToolStub, validateEvalRunOptions } from "./eval-run-options.js";
7
- import { resolveRunCapabilitiesImpl } from "./run-resolver.js";
9
+ import { rememberDefaultOutboundRoute } from "./default-outbound-route.js";
10
+ import { audienceFromRun, audienceUserKey, normalizeAgentAudience } from "./audience.js";
8
11
  import { AgentSourceModuleLoader } from "./source-loader.js";
12
+ import { AgentEventHandlerRegistry } from "./agent-event-handlers.js";
13
+ import { immutableAgentRunContext } from "./agent-hook-evaluation.js";
14
+ import { hookCapabilityCatalog } from "./agent-hook-context.js";
15
+ import { flattenSubagents, rootAgentSurface, subagentSurface, surfaceForPath, surfaceForRun, durableAgentSurfaceScope } from "./agent-surface.js";
16
+ import { createRuntimeAgentHookController, recoverAgentHookController, removeTerminalAgentHookState, resolvedInstructionsForRun as resolvedHookInstructionsForRun } from "./agent-hook-run-lifecycle.js";
9
17
  import { compiledChannelProvider, providerIngressSecurityError, providerIngressSecurityWarnings, resolveCoreToolPolicy, trustedAttachmentProviderForTurn } from "./security.js";
10
18
  export { constantTimeSecretEqual } from "./security.js";
11
19
  export { RUN_STREAM_TERMINAL_EVENTS } from "./run-stream.js";
12
20
  export { failRun } from "./run-outcome.js";
13
- import { OPENEVE_MANIFEST_SCHEMA_VERSION, applyEnvAliases, hasCurrentSandboxFilesystemContract, sandboxFilesystemContractMetadata } from "@assemblyline-agents/core";
21
+ export { MAX_CHANNEL_TURN_COALESCING_WINDOW_MS, QUEUED_CHANNEL_TURN_COALESCING_KEY, QUEUED_CHANNEL_TURN_KEY, QUEUED_CHANNEL_TURN_MERGED_INTO_KEY, QUEUED_CHANNEL_TURN_PARTS_KEY } from "./conversation-turn-coalescing.js";
22
+ import { ARTIFACT_DIR_NAME, ASSEMBLY_LINE_MANIFEST_SCHEMA_VERSION } from "@assemblyline-agents/core";
14
23
  import { resolveBooleanEnv, resolveNonNegativeIntegerEnv, resolvePositiveIntegerEnv } from "./env-config.js";
24
+ import { humanInputModeForChannel, withHumanInputMode } from "./human-input-routing.js";
15
25
  import { RunEventBus, withRunEventPublishing } from "./run-stream.js";
16
- import { handleRunExecutionError, logTerminalRunEvent, settleCompletionBoundaryControlImpl } from "./run-outcome.js";
17
- import { registerRunAbortController, startRunHeartbeatImpl } from "./run-heartbeat.js";
26
+ import { failRun as failRunImpl, handleRunExecutionError, logTerminalRunEvent, settleCompletionBoundaryControlImpl } from "./run-outcome.js";
27
+ import { cacheRunControlSignal, registerRunAbortController, startRunHeartbeatImpl, trackActiveRunHeartbeat } from "./run-heartbeat.js";
18
28
  import { redactTruncateJson } from "./content-capture.js";
29
+ import { isJsonObject, safeJson } from "./json-util.js";
19
30
  import { sandboxSessionKeyForRun } from "./sandbox-session-key.js";
20
31
  export { sandboxSessionKeyForRun } from "./sandbox-session-key.js";
21
- import { InMemoryConnectionAuthorizationSessionStore, InMemoryConnectionGrantStore, materializeConnectionCredentialsIntoSandbox } from "./connections.js";
22
- import { InMemoryConnectionDefinitionStore, InMemoryScheduleStore, InMemorySkillStore, compiledConnectionFromStored, isHostAllowed, liveSkills, resolveSkillsConfig, resolveSchedulesConfig, resolveConnectionsConfig, seedSkills, writeSkill } from "./self-improvement.js";
32
+ import { conversationInitiator, defaultUserPrincipal, initiatorFromRun, normalizeAgentPrincipal, principalFromRun, principalUserId } from "./principals.js";
33
+ import { InMemoryConnectionEventStore } from "./connection-event-store.js";
34
+ import { acceptConnectionEvent, checkConnectionEvents, drainConnectionEventInbox, reconcileConnectionEvents } from "./connection-events.js";
35
+ import { InMemoryConnectionAuthorizationSessionStore, InMemoryConnectionGrantStore, RuntimeConnectionRegistry } from "./connections.js";
36
+ export { FileConnectionEventStore, InMemoryConnectionEventStore } from "./connection-event-store.js";
37
+ export { connectionEventUrl } from "./connection-events.js";
38
+ import { InMemoryConnectionDefinitionStore, InMemoryScheduleStore, InMemorySkillStore, compiledConnectionFromStored, isHostAllowed, resolveSkillsConfig, resolveSchedulesConfig, resolveConnectionsConfig } from "./self-improvement.js";
39
+ import { InMemoryLearningStore } from "./learning-store.js";
40
+ import { RuntimeLearningManager } from "./runtime-learning.js";
23
41
  import { materializeTurnAttachments } from "./attachments.js";
24
- // Attachment helpers for channel modules implementing `resolveAttachment`.
42
+ import { mergeJsonObjects, processRuntimeTurnMedia } from "./turn-media.js";
43
+ export { mergeJsonObjects, processTurnMedia } from "./turn-media.js";
25
44
  export { attachmentFetchTimeoutMs, attachmentRemoteUrl, attachmentTrustedForProvider, firstDownloadableUrl } from "./attachments.js";
45
+ export { assertExternalHttpUrl, fetchExternalHttp, isPublicAddress } from "./outbound-http-policy.js";
26
46
  import { LocalSandboxAdapter } from "./local-sandbox.js";
27
47
  import { schedulerAdapterForKind } from "./scheduler.js";
28
48
  import { isTelemetrySink, telemetrySinkFromSetupResult } from "./telemetry.js";
29
- import { InMemoryStateAdapter, LocalBlobAdapter, StateMemoryStore, memoryBodyText, positiveLimit } from "./storage.js";
49
+ import { InMemoryStateAdapter, LocalBlobAdapter, StateMemoryStore, positiveLimit } from "./storage.js";
30
50
  import { createJsonConsoleLogger, normalizeLogLevel } from "./logging.js";
31
51
  import { runDueDeliveriesImpl, startDeliveryWorkerImpl } from "./delivery-queue.js";
32
52
  import { recoverIncompleteRunsImpl, startBackgroundWorkersImpl } from "./run-recovery.js";
33
53
  import { captureSandboxSnapshotImpl, disposeSandboxSessionImpl, inspectSandboxSyncJobImpl, retrySandboxSyncJobImpl, runDueSandboxSyncJobsImpl, sandboxSyncDiagnosticsImpl, startSandboxSyncWorkerImpl } from "./sandbox-sync-worker.js";
34
- import { beginChannelTurnImpl, completeRunImpl, enqueueSandboxSyncAfterDeliveryImpl, latestRunFailureMessageImpl, recordChannelTurnStartImpl, sendDeliveryImpl, stopUnclaimedChannelTurnImpl, stopChannelTurnImpl } from "./delivery-send.js";
35
- import { backfillMemoryDocumentsFromFileIndexesImpl, hydrateLogicalPathForToolImpl, listResourcesForRunImpl, memoryScopeForRunImpl, projectResourcesForRunImpl, projectSkillIntoSandboxImpl, readResourceForRunImpl, readSandboxTombstonesWithMissingProjectedFilesImpl, recordSandboxTombstoneImpl, runMemoryEmbeddingBackfillImpl } from "./resource-projection.js";
54
+ import { beginChannelTurnImpl, completeRunImpl, latestRunFailureMessageImpl, recordChannelTurnStartImpl, sendDeliveryImpl, stopUnclaimedChannelTurnImpl, stopChannelTurnImpl } from "./delivery-send.js";
55
+ import { backfillMemoryDocumentsFromFileIndexesImpl, hydrateLogicalPathForToolImpl, listResourcesForRunImpl, memoryScopeForRunImpl, projectLoadedSkillsIntoSandboxImpl, projectResourcesForRunImpl, projectSkillIntoSandboxImpl, readResourceForRunImpl, readSandboxTombstonesWithMissingProjectedFilesImpl, recordSandboxTombstoneImpl, runMemoryEmbeddingBackfillImpl } from "./resource-projection.js";
56
+ import { createSkillBundleIndex, createSkillResourceReader } from "./skill-bundles.js";
57
+ import { createSandboxHandleImpl } from "./sandbox-handle.js";
58
+ import { RuntimeWorkspaceManager, WorkspaceRuntimeMethods } from "./workspace-runtime.js";
36
59
  import { beginConnectionAuthorizationImpl, createConnectionRegistryForRunImpl, createConnectionRegistryForSessionImpl, createConnectionRegistryImpl, executeConnectionToolWithRecordImpl, skillLoadDetailsImpl } from "./builtin-tool-executors.js";
37
60
  import { createMemoryToolApiImpl, createResourceToolApiImpl, durableStepImpl } from "./tool-apis.js";
38
61
  import { executeToolImpl, executeToolWithRecordImpl, harnessExecuteToolImpl, modelToolsImpl, selectToolImpl, visibleToolSetImpl, wrapSandboxImpl } from "./tool-execution.js";
39
62
  import { dispatchAutomationEventImpl, normalizeScheduleTriggerDefinitionImpl, registerManifestSchedulesImpl, runDueSchedulesImpl, startSchedulerPollingLoopImpl } from "./schedule-execution.js";
40
63
  import { completeConnectionAuthorizationCallbackImpl, replayImpl, resumeApprovalNowImpl, resumeHarnessLoopImpl, resumeInputNowImpl, resumeRunFromContinuationImpl, resumeSuspendedNowImpl } from "./replay-resume.js";
64
+ import { recordRunReplayStarted, rerunFromSnapshot } from "./run-replay.js";
65
+ export { RunReplayError } from "./run-replay.js";
66
+ import { buildRunAgentResult } from "./run-result.js";
41
67
  import { readSubagentImpl, runSubagentImpl, sendSubagentFollowupImpl } from "./subagent-execution.js";
42
- import { createHarnessContextImpl, DEFAULT_MAX_MODEL_ITERATIONS, DEFAULT_OUTPUT_VALIDATION_MAX_RETRIES, executeHarnessTurnImpl, persistHarnessContinuationImpl, piHarnessImpl, resolveAgentHarnessImpl, runHarnessLoopImpl } from "./harness-loop.js";
68
+ import { createHarnessContextImpl, DEFAULT_MAX_MODEL_ITERATIONS, DEFAULT_OUTPUT_VALIDATION_MAX_RETRIES, executeHarnessTurnImpl, persistHarnessContinuationImpl, resolveAgentHarnessImpl, runHarnessLoopImpl } from "./harness-loop.js";
43
69
  import { getAgentControlImpl, requestRunControlImpl, setAgentEnabledImpl, setAgentMaintenanceImpl } from "./operator-controls.js";
44
- import { acceptChannelTurnImpl, channelAttachmentResolverImpl, dispatchHttpChannelImpl, loadChannelModuleImpl, startChannelIngressImpl } from "./channel-ingress.js";
70
+ import { acceptChannelTurnImpl, channelAttachmentResolverImpl, dispatchHttpChannelImpl, loadChannelModuleImpl, observeChannelMessageImpl, startChannelAgentTurnImpl, startChannelIngressImpl } from "./channel-ingress.js";
45
71
  import { augmentChannelContextImpl, buildContextBundleImpl, prepareConversationImpl, recentHistoryImpl } from "./conversation-context.js";
46
72
  import { loadResumableConversationTranscriptImpl } from "./conversation-transcript.js";
47
73
  import { ConversationTurnDispatcher } from "./conversation-turn-dispatch.js";
48
- import { instructionsForRunTargetImpl } from "./run-resolver.js";
74
+ import { instructionsForRunTargetImpl } from "./target-instructions.js";
49
75
  import { emitTelemetrySpanImpl, runSpanAttributesImpl } from "./telemetry.js";
50
76
  import { normalizeRuntimeState } from "./state-stores.js";
51
77
  import { COMPACTABLE_ACTIVE_CHECKPOINT_NAMES, checkpointDataForStorage as checkpointDataForBlobStorage, emptyCheckpointRetentionResult, hydrateCheckpointData as hydrateCheckpointDataFromBlob, resolveCheckpointRetentionPolicy } from "./checkpoints.js";
52
- // State record types, capability facets (RunStore & friends), the
53
- // StateAdapter intersection, StateStores, and the capability guards.
54
78
  export * from "./state.js";
79
+ export * from "./principals.js";
80
+ export * from "./audience.js";
55
81
  export { evalRunOptionsForRun, validateEvalRunOptions } from "./eval-run-options.js";
56
- export { InMemoryConversationStore, InMemoryConversationTurnStore, InMemoryFileIndexStore, InMemoryMemoryStateStore, InMemoryRunStore, InMemorySandboxSessionStore, InMemoryScheduleStateStore, InMemoryUsageStore, composeStateStores, normalizeRuntimeState } from "./state-stores.js";
82
+ export { InMemoryConversationStore, InMemoryConversationTurnStore, InMemoryFileIndexStore, InMemoryMemoryStateStore, InMemoryRunStore, InMemorySandboxSessionStore, InMemoryScheduleStateStore, InMemoryUsageStore, InMemoryWorkspaceStore, composeStateStores, normalizeMemoryPath, normalizeRuntimeState } from "./state-stores.js";
83
+ export * from "./workspace.js";
57
84
  export { applyDeliveryPatch, createDeliveryRecord, deliveryQueueRetryDelayMs, isDeliveryDue, normalizeDeliveryRecord, stateSupportsDeliveryQueue } from "./delivery-queue.js";
58
85
  export { defaultRunStaleAfterMs } from "./run-recovery.js";
59
86
  export { BoundedSemaphore, RunCapacityError, retryAfterSeconds } from "./concurrency.js";
60
87
  import { BoundedSemaphore, RunCapacityError } from "./concurrency.js";
61
88
  import { DEFAULT_MODEL_OUTPUT_MAX_CHARS } from "@assemblyline-agents/core";
62
- export { FileConnectionAuthorizationSessionStore, FileConnectionGrantStore, InMemoryConnectionAuthorizationSessionStore, InMemoryConnectionGrantStore, RuntimeConnectionRegistry, connectionToolAccess } from "./connections.js";
63
- export { FileConnectionDefinitionStore, FileScheduleStore, FileSkillStore, InMemoryConnectionDefinitionStore, InMemoryScheduleStore, InMemorySkillStore, computeNextRun, resolveSkillsConfig, resolveSchedulesConfig, resolveConnectionsConfig } from "./self-improvement.js";
64
- export { LocalSandboxAdapter } from "./local-sandbox.js";
65
- export { FileMemoryStore, FileStateAdapter, InMemoryMemoryStore, InMemoryStateAdapter, LocalBlobAdapter, StateMemoryStore } from "./storage.js";
66
- export { gatewaySchedulerAdapter, localSchedulerAdapter, postgresSchedulerAdapter, schedulerAdapterForKind } from "./scheduler.js";
67
- export { createOpenTelemetrySink } from "./telemetry.js";
68
- export { createJsonConsoleLogger, noopLogger, normalizeLogLevel } from "./logging.js";
69
- export { capabilityCatalogForManifest, capabilityForModel, capabilityMatchesId, connectionSearchResultForModel, normalizeCapabilityKind, normalizeCapabilityRouterInput, normalizeDeferredToolSearchInput, routerShouldSearchConnections, scoreCapability, searchCapabilityCatalog, tokenizeCapabilityQuery } from "./capability-catalog.js";
70
- export { fetchJson, fetchWithPolicy, readBodyCapped, retryAfterMs, HttpResponseTooLargeError } from "./http.js";
71
- import { hydrateSandboxFilesystem, memoryPathFromSandboxRelativePath, scanSandboxFiles, visibleToolsForSkills } from "./sandbox-fs.js";
72
- export { buildDefaultContextBundle, hydrateSandboxFilesystem, syncSandboxFilesystem, visibleToolsForSkills } from "./sandbox-fs.js";
73
- export { queryAgentRuns } from "./runs-query.js";
74
- export { UsageAccountingError, createUsageRecord, matchesUsageQuery, microsToUsd, queryUsageRecords, reconcileUsageRecord, sha256Json, summarizeUsageRecords, usageTokensAreAuthoritative, usageRecordInput, usdToMicros } from "./usage-records.js";
75
- export { reconcileOpenAIOrganization, reconcileOpenRouterUsage, usageReconciliationReport } from "./usage-reconciliation.js";
76
- import { isValidSandboxSkillBody, resolveResourceProjectionPolicy, sandboxFileContentsToUtf8, sha256Text, skillNameFromSandboxRelativePath, skillNameFromSkillPath } from "./resource-projection-util.js";
89
+ import { visibleToolsForSkills } from "./sandbox-fs.js";
90
+ import { resolveResourceProjectionPolicy } from "./resource-projection-util.js";
91
+ import { syncMemoryFromSandbox, syncSkillsFromSandbox } from "./sandbox-state-sync.js";
92
+ import { acquireSandboxForRun as acquireSandboxSessionForRun } from "./sandbox-session-lifecycle.js";
77
93
  import { resolveSandboxSnapshotPolicy } from "./sandbox-snapshot-policy.js";
78
94
  import { inferToolInput } from "./channel-http-util.js";
79
95
  import { connectionPrincipalKeyForGrant, durableAgentScopeForManifest, isInstrumentationDefinition, normalizeCapturePolicy, randomHex, stringValue, timestamp, } from "./runtime-util.js";
80
- export { currentModulePath, durableAgentScopeForManifest } from "./runtime-util.js";
81
- export { loadRuntimeBundle } from "./runtime-bundle.js";
82
- export class AssemblyLineRuntime {
96
+ export class AssemblyLineRuntime extends WorkspaceRuntimeMethods {
83
97
  manifest;
84
98
  state;
85
99
  runEventBus = new RunEventBus();
100
+ eventHandlers;
101
+ agentHookControllers = new Map();
102
+ agentStateHandles = new Map();
86
103
  blob;
87
104
  sandbox;
88
105
  scheduler;
106
+ mediaProcessors;
89
107
  deliveryMode;
90
108
  toolStubs;
91
109
  /** Per-run {results:[...]} stub cursors; in-memory by design (see eval-run-options.ts). */
@@ -103,19 +121,21 @@ export class AssemblyLineRuntime {
103
121
  connections;
104
122
  env;
105
123
  fetch;
124
+ attachmentHostResolver;
106
125
  logger;
107
126
  connectionGrantStore;
108
127
  connectionAuthorizationSessionStore;
128
+ connectionEventStore;
109
129
  connectionCallbackBaseUrl;
110
130
  skillStore;
131
+ learningStore;
111
132
  memoryStore;
112
133
  scheduleStore;
113
134
  connectionDefinitionStore;
114
135
  skillsConfig;
115
136
  schedulesConfig;
116
137
  connectionsConfig;
117
- skillsSeeded = false;
118
- skillScopeMigrated = false;
138
+ runtimeLearning;
119
139
  connectionScopeMigrated = false;
120
140
  dynamicConnectionsCache;
121
141
  schedulerEnabled;
@@ -150,31 +170,39 @@ export class AssemblyLineRuntime {
150
170
  hostInstrumentationProvided;
151
171
  instrumentationConfig;
152
172
  sourceLoader;
173
+ skillBundleIndex;
174
+ skillResourceReader;
153
175
  contextPolicyPromise;
154
176
  /** Fast local view of durable control intents, refreshed by run heartbeats. */
155
177
  runControlIntents = new Map();
178
+ /** Runs currently owned by this process, used to route immediate control signals without leaking orphan ids. */
179
+ activeRunExecutions = new Set();
156
180
  /** Deadline-fired runs (read by shouldStopRun) + their in-flight abort controllers. */
157
181
  runDeadlines = new Set();
158
182
  runAbortControllers = new Map();
159
183
  maxRunDurationMs;
160
184
  constructor(options) {
185
+ super();
161
186
  this.manifest = options.manifest;
162
187
  const normalizedState = normalizeRuntimeState(options.state ?? new InMemoryStateAdapter());
163
188
  // Events fan out to live streams; terminal outcomes become log lines at
164
189
  // this one choke point (logger read lazily — assigned below).
165
- this.state = withRunEventPublishing(normalizedState.state, this.runEventBus, (runId, event) => logTerminalRunEvent(this.logger, runId, event), (runId, event) => this.dispatchHookEvent(runId, event));
190
+ this.state = withRunEventPublishing(normalizedState.state, this.runEventBus, (runId, event) => logTerminalRunEvent(this.logger, runId, event), (runId, event) => this.handleRuntimeEvent(runId, event));
166
191
  this.blob = options.blob ?? new LocalBlobAdapter();
167
192
  this.sandbox = options.sandbox ?? new LocalSandboxAdapter();
168
193
  this.scheduler = options.scheduler ?? schedulerAdapterForKind(this.manifest.gateway.scheduler?.kind);
194
+ this.mediaProcessors = options.mediaProcessors ?? [];
169
195
  this.deliveryMode = options.deliveryMode ?? "send";
170
196
  this.toolStubs = options.toolStubs ?? {};
171
197
  this.devMode = options.devMode ?? false;
172
198
  this.sourceBundle = options.sourceBundle ?? {};
173
199
  this.connections = options.connections ?? {};
174
- this.env = applyEnvAliases(options.env ?? process.env).env;
200
+ this.env = { ...(options.env ?? process.env) };
175
201
  this.fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
202
+ this.attachmentHostResolver = options.attachmentHostResolver;
176
203
  this.logger = options.logger ??
177
- createJsonConsoleLogger({ level: normalizeLogLevel(this.env.OPENEVE_LOG_LEVEL) ?? "info" });
204
+ createJsonConsoleLogger({ level: normalizeLogLevel(this.env.ASSEMBLY_LINE_LOG_LEVEL) ?? "info" });
205
+ this.eventHandlers = new AgentEventHandlerRegistry(this.agentName(), (runId, type, data) => this.state.appendEvent(runId, type, data), this.logger);
178
206
  if (normalizedState.degradedFacets.length > 0) {
179
207
  this.logger.warn("state.degraded", {
180
208
  missingFacets: normalizedState.degradedFacets,
@@ -185,7 +213,7 @@ export class AssemblyLineRuntime {
185
213
  this.models = options.models;
186
214
  this.agentHarnessOverride = options.agentHarness;
187
215
  this.modelHarnesses = options.modelHarnesses ?? {};
188
- this.checkpointEveryIteration = resolveBooleanEnv(this.env.OPENEVE_CHECKPOINT_EVERY_ITERATION, true);
216
+ this.checkpointEveryIteration = resolveBooleanEnv(this.env.ASSEMBLY_LINE_CHECKPOINT_EVERY_ITERATION, true);
189
217
  this.checkpointRetention = resolveCheckpointRetentionPolicy(options.checkpointRetention, this.env);
190
218
  this.checkpointBlobStorageEnabled = options.blob !== undefined && this.checkpointRetention.blobThresholdBytes > 0;
191
219
  this.telemetry = options.telemetry;
@@ -201,11 +229,13 @@ export class AssemblyLineRuntime {
201
229
  };
202
230
  this.connectionGrantStore = options.connectionGrantStore ?? new InMemoryConnectionGrantStore();
203
231
  this.connectionAuthorizationSessionStore = options.connectionAuthorizationSessionStore ?? new InMemoryConnectionAuthorizationSessionStore();
232
+ this.connectionEventStore = options.connectionEventStore ?? new InMemoryConnectionEventStore();
204
233
  this.connectionCallbackBaseUrl = options.connectionCallbackBaseUrl;
205
234
  this.skillStore = options.skillStore ?? new InMemorySkillStore();
235
+ this.learningStore = options.learningStore ?? new InMemoryLearningStore();
206
236
  this.memoryEmbeddingProvider = options.memoryEmbeddingProvider;
207
237
  const memoryEmbeddingsRequested = options.memoryEmbeddingsEnabled ??
208
- resolveBooleanEnv(this.env.OPENEVE_MEMORY_EMBEDDINGS_ENABLED, Boolean(options.memoryEmbeddingProvider));
238
+ resolveBooleanEnv(this.env.ASSEMBLY_LINE_MEMORY_EMBEDDINGS_ENABLED, Boolean(options.memoryEmbeddingProvider));
209
239
  const memoryEmbeddingStoreAvailable = this.state.supportsMemoryEmbeddings?.() ?? true;
210
240
  this.memoryEmbeddingsEnabled = memoryEmbeddingsRequested && memoryEmbeddingStoreAvailable;
211
241
  if (memoryEmbeddingsRequested && !memoryEmbeddingStoreAvailable) {
@@ -221,27 +251,48 @@ export class AssemblyLineRuntime {
221
251
  this.connectionsConfig = resolveConnectionsConfig(this.manifest.agent.dynamicConnections, this.env);
222
252
  this.schedulerEnabled = options.schedulerEnabled;
223
253
  this.schedulerTickMs = options.schedulerTickMs ?? 60_000;
224
- this.scheduleMaxConsecutiveFailures = resolvePositiveIntegerEnv(this.env.OPENEVE_SCHEDULE_MAX_FAILURES, 5);
254
+ this.scheduleMaxConsecutiveFailures = resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_SCHEDULE_MAX_FAILURES, 5);
225
255
  this.now = options.now ?? (() => new Date());
256
+ this.workspaceRuntime = new RuntimeWorkspaceManager({
257
+ state: this.state,
258
+ blob: this.blob,
259
+ agentScope: this.durableAgentScope(),
260
+ now: this.now,
261
+ env: this.env,
262
+ ...(this.memoryEmbeddingProvider ? { embeddingProvider: this.memoryEmbeddingProvider } : {}),
263
+ sandboxSessionKey: (run) => this.sandboxSessionKey(run)
264
+ });
265
+ this.runtimeLearning = new RuntimeLearningManager({
266
+ state: this.state, manifest: this.manifest,
267
+ env: this.env, logger: this.logger,
268
+ learningStore: this.learningStore,
269
+ skillStore: this.skillStore, memoryStore: this.memoryStore,
270
+ skillsConfigForSurface: (surfacePath) => this.skillsConfigForSurface(surfacePath),
271
+ skillScopeForSurface: (surfacePath) => this.skillScopeForSurface(surfacePath),
272
+ anySkillsEnabled: () => this.anySkillsEnabled(),
273
+ memoryScopeForRun: (run) => this.memoryScopeForRun(run),
274
+ resolveAgentHarness: (modelSpec) => this.resolveAgentHarness(modelSpec),
275
+ now: () => this.now()
276
+ });
226
277
  this.sandboxSnapshotPolicy = resolveSandboxSnapshotPolicy(this.manifest, this.env, options.sandboxSnapshotPolicy);
227
- this.sandboxSyncInline = options.sandboxSyncInline ?? resolveBooleanEnv(this.env.OPENEVE_SANDBOX_SYNC_INLINE, false);
228
- this.sandboxSyncLeaseMs = options.sandboxSyncLeaseMs ?? resolvePositiveIntegerEnv(this.env.OPENEVE_SANDBOX_SYNC_LEASE_MS, 5 * 60_000);
229
- this.sandboxSyncBatchSize = options.sandboxSyncBatchSize ?? resolvePositiveIntegerEnv(this.env.OPENEVE_SANDBOX_SYNC_BATCH_SIZE, 10);
230
- this.sandboxSyncMaxAttempts = options.sandboxSyncMaxAttempts ?? resolvePositiveIntegerEnv(this.env.OPENEVE_SANDBOX_SYNC_MAX_ATTEMPTS, 5);
231
- this.deliveryQueueLeaseMs = options.deliveryQueueLeaseMs ?? resolvePositiveIntegerEnv(this.env.OPENEVE_DELIVERY_QUEUE_LEASE_MS, 60_000);
232
- this.toolOutputMaxChars = resolvePositiveIntegerEnv(this.env.OPENEVE_TOOL_OUTPUT_MAX_CHARS, DEFAULT_MODEL_OUTPUT_MAX_CHARS);
233
- this.toolTimeoutMs = resolveNonNegativeIntegerEnv(this.env.OPENEVE_TOOL_TIMEOUT_MS, 600_000);
234
- this.deliveryQueueBatchSize = options.deliveryQueueBatchSize ?? resolvePositiveIntegerEnv(this.env.OPENEVE_DELIVERY_QUEUE_BATCH_SIZE, 10);
235
- this.deliveryQueueMaxAttempts = options.deliveryQueueMaxAttempts ?? resolvePositiveIntegerEnv(this.env.OPENEVE_DELIVERY_QUEUE_MAX_ATTEMPTS, 5);
236
- this.deliveryQueueIntervalMs = options.deliveryQueueIntervalMs ?? resolvePositiveIntegerEnv(this.env.OPENEVE_DELIVERY_QUEUE_INTERVAL_MS, 15_000);
237
- this.runHeartbeatMs = options.runHeartbeatMs ?? resolvePositiveIntegerEnv(this.env.OPENEVE_RUN_HEARTBEAT_MS, 30_000);
238
- this.maxRunDurationMs = options.maxRunDurationMs ?? resolveNonNegativeIntegerEnv(this.env.OPENEVE_MAX_RUN_DURATION_MS, 3_600_000);
239
- this.runRecoveryIntervalMs = options.runRecoveryIntervalMs ?? resolvePositiveIntegerEnv(this.env.OPENEVE_RUN_RECOVERY_INTERVAL_MS, 60_000);
240
- this.maxModelIterations = resolvePositiveIntegerEnv(this.env.OPENEVE_MAX_MODEL_ITERATIONS, DEFAULT_MAX_MODEL_ITERATIONS);
241
- this.outputValidationMaxRetries = resolveNonNegativeIntegerEnv(this.env.OPENEVE_OUTPUT_VALIDATION_MAX_RETRIES, DEFAULT_OUTPUT_VALIDATION_MAX_RETRIES);
278
+ this.sandboxSyncInline = options.sandboxSyncInline ?? resolveBooleanEnv(this.env.ASSEMBLY_LINE_SANDBOX_SYNC_INLINE, false);
279
+ this.sandboxSyncLeaseMs = options.sandboxSyncLeaseMs ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_SANDBOX_SYNC_LEASE_MS, 5 * 60_000);
280
+ this.sandboxSyncBatchSize = options.sandboxSyncBatchSize ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_SANDBOX_SYNC_BATCH_SIZE, 10);
281
+ this.sandboxSyncMaxAttempts = options.sandboxSyncMaxAttempts ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_SANDBOX_SYNC_MAX_ATTEMPTS, 5);
282
+ this.deliveryQueueLeaseMs = options.deliveryQueueLeaseMs ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_DELIVERY_QUEUE_LEASE_MS, 60_000);
283
+ this.toolOutputMaxChars = resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_TOOL_OUTPUT_MAX_CHARS, DEFAULT_MODEL_OUTPUT_MAX_CHARS);
284
+ this.toolTimeoutMs = resolveNonNegativeIntegerEnv(this.env.ASSEMBLY_LINE_TOOL_TIMEOUT_MS, 600_000);
285
+ this.deliveryQueueBatchSize = options.deliveryQueueBatchSize ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_DELIVERY_QUEUE_BATCH_SIZE, 10);
286
+ this.deliveryQueueMaxAttempts = options.deliveryQueueMaxAttempts ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_DELIVERY_QUEUE_MAX_ATTEMPTS, 5);
287
+ this.deliveryQueueIntervalMs = options.deliveryQueueIntervalMs ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_DELIVERY_QUEUE_INTERVAL_MS, 15_000);
288
+ this.runHeartbeatMs = options.runHeartbeatMs ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_RUN_HEARTBEAT_MS, 30_000);
289
+ this.maxRunDurationMs = options.maxRunDurationMs ?? resolveNonNegativeIntegerEnv(this.env.ASSEMBLY_LINE_MAX_RUN_DURATION_MS, 3_600_000);
290
+ this.runRecoveryIntervalMs = options.runRecoveryIntervalMs ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_RUN_RECOVERY_INTERVAL_MS, 60_000);
291
+ this.maxModelIterations = resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_MAX_MODEL_ITERATIONS, DEFAULT_MAX_MODEL_ITERATIONS);
292
+ this.outputValidationMaxRetries = resolveNonNegativeIntegerEnv(this.env.ASSEMBLY_LINE_OUTPUT_VALIDATION_MAX_RETRIES, DEFAULT_OUTPUT_VALIDATION_MAX_RETRIES);
242
293
  this.runSemaphore = new BoundedSemaphore({
243
- maxConcurrent: options.maxConcurrentRuns ?? resolvePositiveIntegerEnv(this.env.OPENEVE_MAX_CONCURRENT_RUNS, Infinity),
244
- maxQueued: options.maxQueuedRuns ?? resolvePositiveIntegerEnv(this.env.OPENEVE_MAX_QUEUED_RUNS, 0)
294
+ maxConcurrent: options.maxConcurrentRuns ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_MAX_CONCURRENT_RUNS, Infinity),
295
+ maxQueued: options.maxQueuedRuns ?? resolvePositiveIntegerEnv(this.env.ASSEMBLY_LINE_MAX_QUEUED_RUNS, 0)
245
296
  });
246
297
  this.conversationTurnDispatcher = new ConversationTurnDispatcher({
247
298
  state: this.state, logger: this.logger,
@@ -258,13 +309,21 @@ export class AssemblyLineRuntime {
258
309
  this.sourceLoader = new AgentSourceModuleLoader({
259
310
  manifest: this.manifest,
260
311
  sourceBundle: this.sourceBundle,
261
- ...(options.artifactRoot ? { cacheRoot: join(resolve(options.artifactRoot), ".assembly-line", "module-cache") } : {})
312
+ ...(options.artifactRoot ? { cacheRoot: join(resolve(options.artifactRoot), ARTIFACT_DIR_NAME, "module-cache") } : {})
313
+ });
314
+ this.skillBundleIndex = createSkillBundleIndex(this.manifest);
315
+ this.skillResourceReader = createSkillResourceReader({
316
+ manifest: this.manifest,
317
+ ...(options.resourcesRoot ? { resourcesRoot: options.resourcesRoot } : {}),
318
+ manifestRoot: this.manifest.root,
319
+ sourceBundle: this.sourceBundle
262
320
  });
263
321
  }
264
322
  boot() {
265
- if (this.manifest.schemaVersion !== OPENEVE_MANIFEST_SCHEMA_VERSION) {
266
- throw new Error(`Unsupported OpenEve manifest schema ${this.manifest.schemaVersion}.`);
323
+ if (this.manifest.schemaVersion !== ASSEMBLY_LINE_MANIFEST_SCHEMA_VERSION) {
324
+ throw new Error(`Unsupported Assembly Line manifest schema ${this.manifest.schemaVersion}.`);
267
325
  }
326
+ this.sourceLoader.ensureCacheReady();
268
327
  if (!this.devMode) {
269
328
  const missing = this.manifest.preflight.filter((requirement) => requirement.kind === "env" &&
270
329
  requirement.required &&
@@ -348,46 +407,41 @@ export class AssemblyLineRuntime {
348
407
  this.logger.warn("provider ingress security warning", { warning });
349
408
  }
350
409
  }
351
- skillScope() {
352
- return this.durableAgentScope();
353
- }
354
- connectionScope() {
355
- return this.durableAgentScope();
356
- }
357
- durableAgentScope() {
358
- return durableAgentScopeForManifest(this.manifest);
359
- }
360
- usesRevisionScopedDurableState() {
361
- return this.durableAgentScope() === this.manifest.agentRevision;
362
- }
410
+ skillScope() { return this.skillScopeForSurface("root"); }
411
+ skillScopeForSurface(surfacePath) {
412
+ surfaceForPath(this.manifest, surfacePath);
413
+ return durableAgentSurfaceScope(this.durableAgentScope(), surfacePath);
414
+ }
415
+ skillScopeForRun(run) {
416
+ return this.skillScopeForSurface(surfaceForRun(this.manifest, run).path);
417
+ }
418
+ skillsConfigForSurface(surfacePath) {
419
+ if (surfacePath === "root")
420
+ return this.skillsConfig;
421
+ const surface = surfaceForPath(this.manifest, surfacePath);
422
+ return resolveSkillsConfig({
423
+ ...(this.manifest.agent.selfImprovement ?? {}),
424
+ ...(surface.selfImprovement ?? {})
425
+ }, this.env);
426
+ }
427
+ skillsConfigForRun(run) {
428
+ return this.skillsConfigForSurface(surfaceForRun(this.manifest, run).path);
429
+ }
430
+ anySkillsEnabled() {
431
+ return ["root", ...flattenSubagents(this.manifest.subagents).map((subagent) => subagent.path)]
432
+ .some((surfacePath) => this.skillsConfigForSurface(surfacePath).enabled);
433
+ }
434
+ connectionScope() { return this.durableAgentScope(); }
435
+ durableAgentScope() { return durableAgentScopeForManifest(this.manifest); }
436
+ usesRevisionScopedDurableState() { return this.durableAgentScope() === this.manifest.agentRevision; }
363
437
  scheduleScopeForRun(run) {
364
- const userId = typeof run.input.userId === "string" ? run.input.userId : undefined;
365
- const conversationId = typeof run.input.conversationId === "string" ? run.input.conversationId : undefined;
366
- return userId ?? conversationId ?? this.manifest.agentRevision;
438
+ const audience = audienceFromRun(run);
439
+ return audienceUserKey(audience)
440
+ ?? (!audience.private ? audience.conversationId : undefined)
441
+ ?? this.durableAgentScope();
367
442
  }
368
443
  /** Seed the durable skill store from compiled manifest skills (idempotent). */
369
- async ensureSkillsSeeded() {
370
- if (this.skillsSeeded)
371
- return;
372
- await this.migrateLegacySkillScope();
373
- await seedSkills(this.skillStore, this.skillScope(), this.manifest.skills);
374
- this.skillsSeeded = true;
375
- }
376
- async migrateLegacySkillScope() {
377
- if (this.skillScopeMigrated)
378
- return;
379
- this.skillScopeMigrated = true;
380
- const scope = this.skillScope();
381
- const legacyScope = this.manifest.agentRevision;
382
- if (scope === legacyScope)
383
- return;
384
- const current = await this.skillStore.list(scope);
385
- if (current.length > 0)
386
- return;
387
- for (const skill of await this.skillStore.list(legacyScope)) {
388
- await this.skillStore.put(scope, skill);
389
- }
390
- }
444
+ async ensureSkillsSeeded(surfacePath = "root") { return this.runtimeLearning.ensureSkillsSeeded(surfacePath); }
391
445
  async migrateLegacyConnectionScope() {
392
446
  if (this.connectionScopeMigrated)
393
447
  return;
@@ -404,30 +458,24 @@ export class AssemblyLineRuntime {
404
458
  }
405
459
  }
406
460
  /** Live skill catalog (durable store, post-seed) for context assembly and inspection. */
407
- async listSkills() {
408
- await this.ensureSkillsSeeded();
409
- return liveSkills(this.skillStore, this.skillScope());
410
- }
461
+ async listSkills(surfacePath = "root") { return this.runtimeLearning.listSkills(surfacePath); }
411
462
  /** Persist an agent/user authored skill, honoring the write-approval gate. */
412
- async saveSkill(input) {
413
- if (!this.skillsConfig.writable) {
414
- throw new Error("Skill writing is disabled (selfImprovement.writable is false).");
415
- }
416
- await this.ensureSkillsSeeded();
417
- const writeInput = { name: input.name, body: input.body };
418
- if (input.origin)
419
- writeInput.origin = input.origin;
420
- const record = await writeSkill(this.skillStore, this.skillScope(), writeInput, {
421
- requireApproval: this.skillsConfig.writeApproval
422
- });
423
- return { name: record.name, pending: record.pending ?? false };
424
- }
425
- async deleteSkill(name) {
426
- if (!this.skillsConfig.writable) {
427
- throw new Error("Skill writing is disabled (selfImprovement.writable is false).");
428
- }
429
- await this.ensureSkillsSeeded();
430
- await this.skillStore.delete(this.skillScope(), name);
463
+ async saveSkill(input, surfacePath = "root") { return this.runtimeLearning.saveSkill(input, surfacePath); }
464
+ async deleteSkill(name, surfacePath = "root") { return this.runtimeLearning.deleteSkill(name, surfacePath); }
465
+ async listSkillRevisions(name, surfacePath = "root") { return this.runtimeLearning.listSkillRevisions(name, surfacePath); }
466
+ async restoreSkillRevision(name, revision, surfacePath = "root") { return this.runtimeLearning.restoreSkillRevision(name, revision, surfacePath); }
467
+ async listPendingSkillChanges(surfacePath = "root") { return this.runtimeLearning.listPendingSkillChanges(surfacePath); }
468
+ async approveSkillChange(id, surfacePath = "root") { return this.runtimeLearning.approveSkillChange(id, surfacePath); }
469
+ async rejectSkillChange(id, surfacePath = "root") { return this.runtimeLearning.rejectSkillChange(id, surfacePath); }
470
+ async recordRunFeedback(runId, feedback) {
471
+ return this.runtimeLearning.recordRunFeedback(runId, feedback);
472
+ }
473
+ async listBackgroundReviews(surfacePath = "root") { return this.runtimeLearning.listBackgroundReviews(surfacePath); }
474
+ async runDueBackgroundReviews(options = {}) {
475
+ return this.runtimeLearning.runDueBackgroundReviews(options);
476
+ }
477
+ startBackgroundReviewWorker(options = {}) {
478
+ return this.runtimeLearning.startBackgroundReviewWorker(options);
431
479
  }
432
480
  async createDynamicSchedule(input) {
433
481
  if (!this.schedulesConfig.dynamic) {
@@ -538,301 +586,53 @@ export class AssemblyLineRuntime {
538
586
  this.dynamicConnectionsCache = undefined;
539
587
  }
540
588
  async syncMemoryFromSandbox(run, sandboxSession, tombstones) {
541
- const scope = this.memoryScopeForRun(run);
542
- const deleted = [];
543
- const tombstonedPaths = new Set(tombstones
544
- .map((tombstone) => tombstone.path)
545
- .filter((path) => path.startsWith("/memory/")));
546
- for (const path of tombstonedPaths) {
547
- await this.state.deleteMemoryDocument(scope, path);
548
- deleted.push(path);
549
- }
550
- let files;
551
- try {
552
- files = await scanSandboxFiles(sandboxSession, "/memory");
553
- }
554
- catch {
555
- return { written: [], deleted };
556
- }
557
- const written = [];
558
- for (const file of files) {
559
- const path = memoryPathFromSandboxRelativePath(file.relativePath);
560
- if (!path || tombstonedPaths.has(path))
561
- continue;
562
- const content = sandboxFileContentsToUtf8(file.contents);
563
- const current = await this.memoryStore.read(scope, { path });
564
- if (current && memoryBodyText(current) === content)
565
- continue;
566
- await this.memoryStore.write(scope, {
567
- path,
568
- content,
569
- mode: "replace",
570
- metadata: {
571
- tags: ["sandbox"],
572
- sourceRefs: [`sandbox:${run.id}`]
573
- }
574
- });
575
- written.push(path);
576
- }
577
- if (written.length > 0 || deleted.length > 0) {
578
- await this.state.appendEvent(run.id, "memory.documents_synced", {
579
- written,
580
- deleted
581
- });
582
- }
583
- return { written, deleted };
589
+ return syncMemoryFromSandbox(this.sandboxStateSyncHost(), run, sandboxSession, tombstones);
584
590
  }
585
591
  /** Reconcile skill files the agent explicitly edited/deleted under `/skills`. */
586
592
  async syncSkillsFromSandbox(run, sandboxSession, tombstones) {
587
- let files;
588
- try {
589
- files = await scanSandboxFiles(sandboxSession, "/skills");
590
- }
591
- catch {
592
- files = [];
593
- }
594
- const skillScope = this.skillScope();
595
- const before = await this.skillStore.list(skillScope);
596
- const beforeByName = new Map(before.map((skill) => [skill.name, skill]));
597
- const deletedSkillNames = new Set(tombstones
598
- .map((tombstone) => skillNameFromSkillPath(tombstone.path))
599
- .filter((name) => Boolean(name)));
600
- const sandboxSkills = [];
601
- const invalid = [];
602
- for (const file of files) {
603
- const name = skillNameFromSandboxRelativePath(file.relativePath);
604
- if (!name) {
605
- if (file.relativePath.endsWith("SKILL.md"))
606
- invalid.push(file.relativePath);
607
- continue;
608
- }
609
- const body = sandboxFileContentsToUtf8(file.contents);
610
- if (!isValidSandboxSkillBody(body)) {
611
- invalid.push(`/skills/${file.relativePath}`);
612
- continue;
613
- }
614
- sandboxSkills.push({ name, body });
615
- }
616
- const changed = sandboxSkills.filter((skill) => {
617
- if (deletedSkillNames.has(skill.name))
618
- return false;
619
- return beforeByName.get(skill.name)?.bodySha256 !== sha256Text(skill.body);
620
- });
621
- if (!this.skillsConfig.writable) {
622
- if (changed.length > 0 || deletedSkillNames.size > 0 || invalid.length > 0) {
623
- throw new Error("Sandbox skill writes are blocked because self-improvement is disabled.");
624
- }
625
- return;
626
- }
627
- if (invalid.length > 0) {
628
- throw new Error(`Invalid sandbox skill file(s): ${invalid.join(", ")}`);
629
- }
630
- const created = [];
631
- const updated = [];
632
- const deleted = [];
633
- for (const name of deletedSkillNames) {
634
- if (!beforeByName.has(name))
635
- continue;
636
- await this.skillStore.delete(skillScope, name);
637
- deleted.push(name);
638
- }
639
- for (const skill of changed) {
640
- const existing = beforeByName.get(skill.name);
641
- await writeSkill(this.skillStore, skillScope, {
642
- name: skill.name,
643
- body: skill.body,
644
- origin: "agent"
645
- }, {
646
- requireApproval: this.skillsConfig.writeApproval
647
- });
648
- if (existing)
649
- updated.push(skill.name);
650
- else
651
- created.push(skill.name);
652
- }
653
- if (created.length || updated.length || deleted.length) {
654
- await this.state.appendEvent(run.id, "skill.synced", {
655
- created,
656
- updated,
657
- deleted,
658
- pending: this.skillsConfig.writeApproval
659
- });
660
- }
593
+ return syncSkillsFromSandbox(this.sandboxStateSyncHost(), run, sandboxSession, tombstones);
661
594
  }
662
- createSandboxHandle(getRun, setRun, getBundle) {
663
- const runtime = this;
664
- let sandboxSession;
665
- let acquiring;
666
- const acquire = async () => {
667
- const run = getRun();
668
- sandboxSession = await runtime.acquireSandboxForRun(run);
669
- const updatedRun = await runtime.state.updateRun(run.id, { sandboxId: sandboxSession.id });
670
- setRun(updatedRun);
671
- await runtime.state.appendEvent(run.id, "sandbox.acquired", { sandboxId: sandboxSession.id, root: sandboxSession.root });
672
- await runtime.createCheckpoint({ runId: run.id, name: "sandbox.acquired", data: { sandboxId: sandboxSession.id } });
673
- await hydrateSandboxFilesystem(sandboxSession, getBundle(), {
674
- fullHydration: runtime.legacyFullSandboxHydration(),
675
- blob: runtime.blob
676
- });
677
- await runtime.state.appendEvent(run.id, "filesystem.hydrated", {
678
- memory: "/memory",
679
- history: "/history",
680
- files: "/files",
681
- workspace: "/workspace",
682
- mode: runtime.legacyFullSandboxHydration() ? "full" : "minimal"
683
- });
684
- await runtime.createCheckpoint({
685
- runId: run.id,
686
- name: "filesystem.hydrated",
687
- data: {
688
- memory: "/memory",
689
- history: "/history",
690
- files: "/files",
691
- workspace: "/workspace",
692
- mode: runtime.legacyFullSandboxHydration() ? "full" : "minimal"
693
- }
694
- });
695
- await materializeConnectionCredentialsIntoSandbox(run, runtime.createConnectionRegistryForRun(run, "local"), sandboxSession, (eventType, payload) => runtime.state.appendEvent(run.id, eventType, payload));
696
- return sandboxSession;
697
- };
595
+ sandboxStateSyncHost() {
698
596
  return {
699
- current() {
700
- return sandboxSession;
701
- },
702
- async get() {
703
- if (sandboxSession)
704
- return sandboxSession;
705
- // Memoize the in-flight acquisition: parallel tool calls must share
706
- // one sandbox session instead of racing to create two.
707
- acquiring ??= acquire().catch((error) => {
708
- acquiring = undefined;
709
- throw error;
710
- });
711
- return acquiring;
712
- },
713
- async getWrapped() {
714
- const run = getRun();
715
- return runtime.wrapSandbox(run.id, await this.get());
716
- },
717
- async dispose() {
718
- if (!sandboxSession)
719
- return;
720
- await runtime.disposeSandboxSession(getRun().id, sandboxSession);
721
- }
597
+ state: this.state,
598
+ memoryStore: this.memoryStore,
599
+ skillStore: this.skillStore,
600
+ skillBundleIndex: this.skillBundleIndex,
601
+ learningStore: this.learningStore,
602
+ skillsConfigForRun: (run) => this.skillsConfigForRun(run),
603
+ memoryScopeForRun: (candidate) => this.memoryScopeForRun(candidate),
604
+ skillScopeForRun: (run) => this.skillScopeForRun(run)
722
605
  };
723
606
  }
607
+ createSandboxHandle(getRun, setRun, getBundle) {
608
+ return createSandboxHandleImpl({
609
+ state: this.state,
610
+ blob: this.blob,
611
+ acquireSandboxForRun: (run) => this.acquireSandboxForRun(run),
612
+ createCheckpoint: (input) => this.createCheckpoint(input),
613
+ legacyFullSandboxHydration: () => this.legacyFullSandboxHydration(),
614
+ hydrateWorkspace: (run, session) => this.workspaceRuntime.service.hydrate(run, session, this.sandboxSessionKey(run)),
615
+ projectLoadedSkills: (run, session) => this.projectLoadedSkillsIntoSandbox(run, session),
616
+ createConnectionRegistryForRun: (run, channel, selectedConnections) => this.createConnectionRegistryForRun(run, channel, undefined, selectedConnections),
617
+ wrapSandbox: (runId, session) => this.wrapSandbox(runId, session),
618
+ disposeSandboxSession: (runId, session) => this.disposeSandboxSession(runId, session)
619
+ }, getRun, setRun, getBundle);
620
+ }
724
621
  sandboxSessionKey(run) {
725
622
  return sandboxSessionKeyForRun(this.durableAgentScope(), run);
726
623
  }
727
624
  async acquireSandboxForRun(run) {
728
- const sessionKey = this.sandboxSessionKey(run);
729
- const provider = this.sandbox.provider ?? "sandbox";
730
- const existing = await this.state.getSandboxSession(sessionKey);
731
- const reconnectManifest = existing?.manifest ?? {};
732
- const reconnectCompatible = hasCurrentSandboxFilesystemContract(reconnectManifest);
733
- const reconnectInput = {
734
- runId: run.id,
735
- sandboxId: existing?.sandboxId ?? "",
736
- sessionKey,
737
- manifest: reconnectManifest
738
- };
739
- const root = stringValue(reconnectManifest.sandboxRoot);
740
- if (root)
741
- reconnectInput.root = root;
742
- if (existing?.sandboxId && reconnectCompatible) {
743
- const connected = await this.sandbox.connect?.(reconnectInput)
744
- .catch(this.debugSwallow("sandbox connect probe failed", { runId: run.id, sessionKey }));
745
- if (connected) {
746
- await this.upsertSandboxSessionForRun(run, sessionKey, provider, connected, existing.dirty, existing.syncJobId, {
747
- ...existing.manifest,
748
- sandboxRoot: connected.root,
749
- ...sandboxFilesystemContractMetadata(connected.provider === "local" ? "emulated" : "physical")
750
- }, "live");
751
- await this.state.appendEvent(run.id, "sandbox.reused", { sandboxId: connected.id, sessionKey, mode: "connect" });
752
- return connected;
753
- }
754
- const woken = await this.sandbox.wake?.(reconnectInput)
755
- .catch(this.debugSwallow("sandbox wake probe failed", { runId: run.id, sessionKey }));
756
- if (woken) {
757
- await this.upsertSandboxSessionForRun(run, sessionKey, provider, woken, existing.dirty, existing.syncJobId, {
758
- ...existing.manifest,
759
- sandboxRoot: woken.root,
760
- ...sandboxFilesystemContractMetadata(woken.provider === "local" ? "emulated" : "physical")
761
- }, "live");
762
- await this.state.appendEvent(run.id, "sandbox.reused", { sandboxId: woken.id, sessionKey, mode: "wake" });
763
- return woken;
764
- }
765
- }
766
- const lookup = (!existing || reconnectCompatible) ? await this.sandbox.lookup?.({
767
- sessionKey,
768
- runId: run.id,
769
- agentRevision: run.agentRevision,
770
- manifest: {
771
- ...reconnectManifest,
772
- ...sandboxFilesystemContractMetadata(this.sandbox.provider === "local" ? "emulated" : "physical")
773
- }
774
- }).catch(this.debugSwallow("sandbox lookup probe failed", { runId: run.id, sessionKey })) : undefined;
775
- if (lookup) {
776
- const lookupInput = {
777
- runId: run.id,
778
- sandboxId: lookup.sandboxId,
779
- sessionKey,
780
- manifest: lookup.manifest ?? reconnectManifest
781
- };
782
- if (lookup.root)
783
- lookupInput.root = lookup.root;
784
- const connected = await this.sandbox.connect?.(lookupInput)
785
- .catch(this.debugSwallow("sandbox connect probe failed", { runId: run.id, sessionKey })) ??
786
- await this.sandbox.wake?.(lookupInput)
787
- .catch(this.debugSwallow("sandbox wake probe failed", { runId: run.id, sessionKey }));
788
- if (connected) {
789
- await this.upsertSandboxSessionForRun(run, sessionKey, provider, connected, existing?.dirty ?? false, existing?.syncJobId, {
790
- ...(lookup.manifest ?? existing?.manifest ?? {}),
791
- sandboxRoot: connected.root,
792
- ...sandboxFilesystemContractMetadata(connected.provider === "local" ? "emulated" : "physical")
793
- }, "live");
794
- await this.state.appendEvent(run.id, "sandbox.reused", { sandboxId: connected.id, sessionKey, mode: lookup.state ?? "lookup" });
795
- return connected;
796
- }
797
- }
798
- const createInput = {
799
- sessionKey,
800
- metadata: {
801
- sessionKey,
802
- runId: run.id,
803
- agentRevision: run.agentRevision,
804
- ...sandboxFilesystemContractMetadata(this.sandbox.provider === "local" ? "emulated" : "physical")
805
- }
806
- };
807
- if (existing?.snapshotId && reconnectCompatible)
808
- createInput.snapshotId = existing.snapshotId;
809
- const created = this.sandbox.create
810
- ? await this.sandbox.create(run, createInput)
811
- : await this.sandbox.acquire(run);
812
- await this.upsertSandboxSessionForRun(run, sessionKey, provider, created, existing?.dirty ?? false, existing?.syncJobId, {
813
- ...(existing?.manifest ?? {}),
814
- sandboxRoot: created.root,
815
- ...sandboxFilesystemContractMetadata(created.provider === "local" ? "emulated" : "physical")
816
- }, existing?.dirty ? "dirty" : "live");
817
- await this.state.appendEvent(run.id, "sandbox.created", { sandboxId: created.id, sessionKey });
818
- return created;
819
- }
820
- async upsertSandboxSessionForRun(run, sessionKey, provider, session, dirty, syncJobId, manifest, state) {
821
- return this.state.upsertSandboxSession({
822
- sessionKey,
823
- provider: session.provider ?? provider,
824
- sandboxId: session.id,
825
- runId: run.id,
826
- state: dirty ? "dirty" : state,
827
- dirty,
828
- lastSeenAt: timestamp(),
829
- ...(syncJobId ? { syncJobId } : {}),
830
- manifest
831
- });
625
+ return acquireSandboxSessionForRun({
626
+ manifest: this.manifest,
627
+ state: this.state,
628
+ sandbox: this.sandbox,
629
+ sessionKey: (candidate) => this.sandboxSessionKey(candidate),
630
+ swallow: (message, fields) => this.debugSwallow(message, fields)
631
+ }, run);
832
632
  }
833
633
  legacyFullSandboxHydration() {
834
- return this.env.OPENEVE_LEGACY_FULL_SANDBOX_HYDRATION === "1" ||
835
- this.env.OPENEVE_LEGACY_FULL_SANDBOX_HYDRATION === "true";
634
+ return this.env.ASSEMBLY_LINE_LEGACY_FULL_SANDBOX_HYDRATION === "1" ||
635
+ this.env.ASSEMBLY_LINE_LEGACY_FULL_SANDBOX_HYDRATION === "true";
836
636
  }
837
637
  async ensureDynamicConnections() {
838
638
  if (!this.connectionsConfig.dynamic) {
@@ -924,22 +724,59 @@ export class AssemblyLineRuntime {
924
724
  await this.ensureSkillsSeeded();
925
725
  await this.ensureDynamicConnections();
926
726
  const spanStartedAt = timestamp();
927
- const channel = options.turn?.channel ?? options.channel ?? "local";
727
+ const channel = (options.existingRun && typeof options.existingRun.input.channel === "string"
728
+ ? options.existingRun.input.channel
729
+ : undefined) ?? options.turn?.channel ?? options.channel ?? "local";
928
730
  const channelDefinition = this.manifest.channels.find((candidate) => candidate.name === channel);
929
- const targetModel = options.target?.type === "agent" ? options.target.model : undefined;
930
- const model = options.model ?? options.turn?.model ?? targetModel;
731
+ const suppliedConversationId = (options.existingRun && typeof options.existingRun.input.conversationId === "string"
732
+ ? options.existingRun.input.conversationId
733
+ : undefined) ?? options.turn?.conversationId ?? options.conversationId;
734
+ const legacyUserId = options.turn?.userId ?? options.userId;
735
+ const principal = (options.existingRun ? principalFromRun(options.existingRun) : undefined)
736
+ ?? normalizeAgentPrincipal(options.turn?.principal ?? options.principal)
737
+ ?? defaultUserPrincipal(legacyUserId, channel);
738
+ const initiator = (options.existingRun ? initiatorFromRun(options.existingRun) : undefined)
739
+ ?? normalizeAgentPrincipal(options.turn?.initiator ?? options.initiator)
740
+ ?? principal;
741
+ // Channel turns derive their audience from the authenticated turn, so it
742
+ // cannot disagree with the principal or conversation; other callers are
743
+ // trusted embedders and default to a private direct run.
744
+ const audience = (options.existingRun ? normalizeAgentAudience(options.existingRun.input.audience) : undefined)
745
+ ?? normalizeAgentAudience(options.turn?.audience ?? options.audience)
746
+ ?? { private: true };
747
+ const replyTarget = options.existingRun && isJsonObject(options.existingRun.input.replyTarget)
748
+ ? options.existingRun.input.replyTarget
749
+ : safeJson({
750
+ channel,
751
+ conversationId: suppliedConversationId ?? null,
752
+ delivery: options.turn?.delivery ?? options.delivery ?? null
753
+ });
931
754
  const runInput = {
932
755
  message: options.message,
933
- model: model ?? this.manifest.agent.model,
756
+ agentSurface: "root",
934
757
  channel,
935
758
  eventId: options.turn?.eventId ?? options.eventId ?? null,
936
- conversationId: options.turn?.conversationId ?? options.conversationId ?? null,
937
- userId: options.turn?.userId ?? options.userId ?? null,
759
+ conversationId: suppliedConversationId ?? options.existingRun?.input.conversationId ?? null,
760
+ autoConversation: suppliedConversationId
761
+ ? false
762
+ : options.existingRun
763
+ ? options.existingRun.input.autoConversation === true
764
+ : true,
765
+ userId: principalUserId(principal) ?? legacyUserId ?? null,
766
+ principal: principal ? safeJson(principal) : null,
767
+ initiator: initiator ? safeJson(initiator) : null,
768
+ audience: safeJson(audience),
938
769
  projectId: options.projectId ?? options.existingRun?.input.projectId ?? null,
939
- delivery: options.turn?.delivery ?? options.delivery ?? null,
770
+ workspaceId: options.workspaceId ?? options.existingRun?.input.workspaceId ?? null,
771
+ tenantId: options.tenantId ?? options.existingRun?.input.tenantId ?? null,
772
+ delivery: isJsonObject(replyTarget.delivery) ? replyTarget.delivery : null,
773
+ replyTarget,
940
774
  metadata: options.metadata ?? options.turn?.metadata ?? {},
775
+ sandboxCredentials: options.sandboxCredentials ?? (options.existingRun && isJsonObject(options.existingRun.input.sandboxCredentials) ? options.existingRun.input.sandboxCredentials : {}),
776
+ ...(options.replay !== undefined ? { replay: safeJson(options.replay) } : {}),
941
777
  ...(options.eval !== undefined ? { eval: validateEvalRunOptions(options.eval) } : {})
942
778
  };
779
+ await rememberDefaultOutboundRoute({ manifest: this.manifest, state: this.state, agentScope: this.durableAgentScope(), now: this.now() }, options, runInput);
943
780
  let run = options.existingRun
944
781
  ? await this.state.updateRun(options.existingRun.id, {
945
782
  input: {
@@ -958,14 +795,20 @@ export class AssemblyLineRuntime {
958
795
  catch (error) {
959
796
  this.logger.warn("onRunCreated hook failed", { runId: run.id, error: error instanceof Error ? error.message : String(error) });
960
797
  }
961
- await this.state.appendEvent(run.id, "run.accepted", { agentRevision: this.manifest.agentRevision, model: model ?? this.manifest.agent.model });
962
- if (this.usesRevisionScopedDurableState() && (this.skillsConfig.writable || this.connectionsConfig.dynamic)) {
798
+ await this.state.appendEvent(run.id, "run.accepted", { agentRevision: this.manifest.agentRevision });
799
+ if (options.replay)
800
+ await recordRunReplayStarted(this.state, run.id, options.replay);
801
+ if (this.usesRevisionScopedDurableState() && (this.skillsConfig.enabled || this.connectionsConfig.dynamic)) {
963
802
  await this.state.appendEvent(run.id, "agent.scope_fallback", {
964
803
  reason: "missing_agent_id",
965
804
  scope: this.manifest.agentRevision,
966
805
  message: "Durable learned state is scoped to agentRevision because agent.id is not configured."
967
806
  });
968
807
  }
808
+ const preExecution = await this.state.getRun(run.id);
809
+ if (preExecution?.status === "cancelled") {
810
+ return this.result(preExecution, "Run was cancelled before execution started.");
811
+ }
969
812
  run = await this.state.updateRun(run.id, { status: "running" });
970
813
  const heartbeat = this.startRunHeartbeat(run.id);
971
814
  const channelTurnStart = earlyChannelTurn
@@ -983,43 +826,101 @@ export class AssemblyLineRuntime {
983
826
  await this.stopChannelTurn(channelLifecycle, run, channel);
984
827
  };
985
828
  try {
986
- const resolveAttachment = await this.channelAttachmentResolver(channelDefinition, trustedProvider);
987
- const attachments = await materializeTurnAttachments({
988
- run,
829
+ const channelModule = channelDefinition
830
+ ? await this.loadChannelModule(channelDefinition)
831
+ : undefined;
832
+ const humanInputMode = humanInputModeForChannel(channelModule);
833
+ run = await this.state.updateRun(run.id, {
834
+ input: withHumanInputMode(run.input, humanInputMode)
835
+ });
836
+ await this.state.appendEvent(run.id, "human_input.route_selected", {
989
837
  channel,
990
- attachments: options.attachments ?? options.turn?.attachments ?? [],
991
- ...(trustedProvider ? { trustedProvider } : {}),
992
- ...(resolveAttachment ? { resolveAttachment } : {}),
993
- env: this.env,
994
- fetch: this.fetch,
995
- blob: this.blob,
996
- state: this.state
838
+ mode: humanInputMode
997
839
  });
840
+ const turnAttachments = options.attachments ?? options.turn?.attachments ?? [];
841
+ let attachments = [];
842
+ if (turnAttachments.length > 0) {
843
+ if (typeof run.input.conversationId !== "string" || !run.input.conversationId) {
844
+ run = await this.state.updateRun(run.id, {
845
+ input: { ...run.input, conversationId: run.id }
846
+ });
847
+ }
848
+ const fileWorkspace = await this.workspaceRuntime.service.resolveForRun(run);
849
+ const resolveAttachment = await this.channelAttachmentResolver(channelDefinition, trustedProvider);
850
+ attachments = await materializeTurnAttachments({
851
+ run,
852
+ workspaceId: fileWorkspace.id,
853
+ channel,
854
+ attachments: turnAttachments,
855
+ ...(trustedProvider ? { trustedProvider } : {}),
856
+ ...(resolveAttachment ? { resolveAttachment } : {}),
857
+ allowRemoteDownload: options.allowRemoteAttachments === true,
858
+ env: this.env,
859
+ fetch: this.fetch,
860
+ ...(this.attachmentHostResolver ? { hostResolver: this.attachmentHostResolver } : {}),
861
+ blob: this.blob,
862
+ state: this.state
863
+ });
864
+ }
998
865
  const hydratedOptions = { ...options, attachments };
999
866
  if (options.turn)
1000
867
  hydratedOptions.turn = { ...options.turn, attachments };
1001
868
  const conversation = await this.prepareConversation(run, hydratedOptions, channel);
869
+ if (!conversation)
870
+ throw new Error("Every run must resolve a conversation before agent hook evaluation.");
871
+ hydratedOptions.conversationId = conversation.id;
872
+ const persistedInitiator = conversationInitiator(conversation.metadata) ?? initiatorFromRun(run);
873
+ if (persistedInitiator) {
874
+ hydratedOptions.initiator = persistedInitiator;
875
+ if (hydratedOptions.turn)
876
+ hydratedOptions.turn = { ...hydratedOptions.turn, initiator: persistedInitiator };
877
+ }
878
+ if (run.input.conversationId !== conversation.id || persistedInitiator) {
879
+ run = await this.state.updateRun(run.id, {
880
+ input: {
881
+ ...run.input,
882
+ conversationId: conversation.id,
883
+ ...(persistedInitiator ? { initiator: safeJson(persistedInitiator) } : {})
884
+ }
885
+ });
886
+ }
887
+ const hookController = await this.createAgentHookController(run, hydratedOptions, channel, conversation.id, attachments);
888
+ const capabilitySnapshot = await hookController.evaluate(options.existingRun ? "recovery" : "run_start");
889
+ const capabilities = capabilitySnapshot.declaration;
890
+ run = await this.state.updateRun(run.id, {
891
+ input: {
892
+ ...run.input,
893
+ model: capabilities.model,
894
+ agentSandbox: capabilities.sandbox ?? null,
895
+ agentConnections: capabilities.connections,
896
+ agentSubagents: capabilities.subagents,
897
+ attachmentMetadata: attachments
898
+ }
899
+ });
900
+ const media = await processRuntimeTurnMedia(this, run, attachments, hydratedOptions, channel, principalUserId(principal) ?? legacyUserId, conversation.id);
1002
901
  const augmentation = hydratedOptions.turn
1003
902
  ? await this.augmentChannelContext(channel, hydratedOptions.turn, run)
1004
903
  : undefined;
1005
904
  const recentHistory = hydratedOptions.recentHistory ??
1006
905
  hydratedOptions.turn?.recentHistory ??
1007
906
  augmentation?.recentHistory ??
1008
- (conversation ? await this.recentHistory(conversation.id) : []);
907
+ (conversation ? await this.recentHistory(conversation.id, run.id) : []);
1009
908
  const contextInput = {
1010
909
  message: hydratedOptions.message,
1011
910
  channel,
1012
911
  recentHistory,
1013
912
  attachments,
913
+ capabilities,
1014
914
  run
1015
915
  };
1016
- if (augmentation?.channelContext)
1017
- contextInput.channelContext = augmentation.channelContext;
916
+ const channelContext = mergeJsonObjects(media.channelContext, augmentation?.channelContext);
917
+ if (channelContext)
918
+ contextInput.channelContext = channelContext;
1018
919
  if (hydratedOptions.promptContext)
1019
920
  contextInput.promptContext = hydratedOptions.promptContext;
1020
921
  if (hydratedOptions.target)
1021
922
  contextInput.target = hydratedOptions.target;
1022
- const bundle = await this.buildContextBundle(contextInput);
923
+ let bundle = options.contextSnapshot ? structuredClone(options.contextSnapshot) : await this.buildContextBundle(contextInput);
1023
924
  const contextBlob = await this.blob.put(`context/${run.id}.json`, JSON.stringify(bundle, null, 2), "application/json");
1024
925
  run = await this.state.updateRun(run.id, { contextBundleId: contextBlob.id });
1025
926
  await this.state.appendEvent(run.id, "context.bundle_built", { contextBundleId: contextBlob.id });
@@ -1028,44 +929,31 @@ export class AssemblyLineRuntime {
1028
929
  name: "context.bundle_built",
1029
930
  data: { contextBundleId: contextBlob.id }
1030
931
  });
1031
- const missingConnections = this.missingRequiredConnections();
1032
- if (missingConnections.length > 0) {
1033
- const waitingRun = await this.state.updateRun(run.id, { status: "waiting_for_connection" });
1034
- await this.state.appendEvent(run.id, "connection.required", {
1035
- missingConnections,
1036
- recoverable: true
1037
- });
1038
- await this.emitSpan("ai.assembly-line.turn", spanStartedAt, this.runSpanAttributes(waitingRun, {
1039
- status: "waiting_for_connection"
1040
- }), {
1041
- spanId: this.turnSpanId(waitingRun.id),
1042
- status: "ok"
1043
- });
1044
- await this.emitSpan("assembly-line.run", spanStartedAt, {
1045
- runId: run.id,
1046
- status: "waiting_for_connection",
1047
- agentRevision: this.manifest.agentRevision
1048
- });
1049
- return this.result(waitingRun, `Connection required: ${missingConnections.join(", ")}`, false, false, true);
1050
- }
1051
- const resolution = await this.resolveRunCapabilities(run, hydratedOptions, conversation?.id);
1052
932
  const sandboxHandle = this.createSandboxHandle(() => run, (nextRun) => {
1053
933
  run = nextRun;
1054
934
  }, () => bundle);
1055
935
  await this.state.appendEvent(run.id, "harness.started", { harness: this.manifest.gateway.runtime?.kind ?? "node" });
1056
- const baseInstructions = await this.instructionsForRunTarget(run, hydratedOptions.target, bundle.instructions);
1057
- const targetInstructions = resolution?.instructions
1058
- ? `${baseInstructions}\n\n${resolution.instructions}`
1059
- : baseInstructions;
936
+ const targetInstructions = await this.instructionsForRunTarget(run, hydratedOptions.target, bundle.instructions);
1060
937
  let response = options.message;
1061
938
  let structuredOutput;
1062
939
  const tool = this.selectTool(hydratedOptions);
1063
940
  if (tool) {
941
+ if (!capabilities.tools.includes(tool.name) && tool.visibility !== "deferred") {
942
+ const message = `Forced tool ${tool.name} is not enabled by the current agent capability snapshot.`;
943
+ const error = new Error(message);
944
+ error.name = "AgentCapabilityViolationError";
945
+ run = await failRunImpl({ state: this.state }, run.id, {
946
+ reason: "run.capability_violation",
947
+ error: message,
948
+ data: { toolName: tool.name }
949
+ });
950
+ throw error;
951
+ }
1064
952
  const modelSpanStartedAt = timestamp();
1065
- await this.state.appendEvent(run.id, "model.request_started", { model: model ?? this.manifest.agent.model, forcedTool: tool.name });
1066
- await this.state.appendEvent(run.id, "model.response_completed", { model: model ?? this.manifest.agent.model, simulated: true });
953
+ await this.state.appendEvent(run.id, "model.request_started", { model: capabilities.model, forcedTool: tool.name });
954
+ await this.state.appendEvent(run.id, "model.response_completed", { model: capabilities.model, simulated: true });
1067
955
  await this.emitSpan("ai.streamText", modelSpanStartedAt, this.runSpanAttributes(run, {
1068
- model: model ?? this.manifest.agent.model,
956
+ model: capabilities.model,
1069
957
  stepIndex: 0,
1070
958
  forcedTool: tool.name,
1071
959
  simulated: true,
@@ -1096,21 +984,23 @@ export class AssemblyLineRuntime {
1096
984
  sandboxHandle,
1097
985
  message: hydratedOptions.message,
1098
986
  channel,
987
+ controller: hookController,
988
+ refreshBundle: async (nextCapabilities) => {
989
+ contextInput.capabilities = nextCapabilities;
990
+ run = await this.state.getRun(run.id) ?? run;
991
+ contextInput.run = run;
992
+ bundle = await this.buildContextBundle(contextInput);
993
+ return bundle;
994
+ },
1099
995
  instructions: targetInstructions
1100
996
  };
1101
997
  if (hydratedOptions.turn)
1102
998
  loopInput.turn = hydratedOptions.turn;
1103
999
  if (conversation?.id) {
1104
1000
  loopInput.conversationId = conversation.id;
1105
- loopInput.transcript = await this.loadConversationTranscript(conversation.id, run.id);
1001
+ if (!options.contextSnapshot)
1002
+ loopInput.transcript = await this.loadConversationTranscript(conversation.id, run.id);
1106
1003
  }
1107
- // A host-forced model wins over the resolver; the resolver wins over the manifest default.
1108
- if (model)
1109
- loopInput.model = model;
1110
- else if (resolution?.model)
1111
- loopInput.model = resolution.model;
1112
- if (resolution?.defaultTools)
1113
- loopInput.defaultToolNames = resolution.defaultTools;
1114
1004
  const outcome = await this.runHarnessLoop(loopInput);
1115
1005
  run = outcome.run;
1116
1006
  if (outcome.waitingForApproval || outcome.waitingForInput || outcome.waitingForConnection) {
@@ -1156,10 +1046,12 @@ export class AssemblyLineRuntime {
1156
1046
  return result;
1157
1047
  }
1158
1048
  catch (error) {
1159
- // Fatal model errors terminalize with a durable reason; anything else is
1160
- // evented + logged but left "running" so the recovery sweep can resume
1161
- // from the latest continuation (the crash-durability contract).
1162
- await handleRunExecutionError({ state: this.state, logger: this.logger }, run.id, error);
1049
+ await handleRunExecutionError({
1050
+ state: this.state,
1051
+ logger: this.logger,
1052
+ deliveryQueueMaxAttempts: this.deliveryQueueMaxAttempts,
1053
+ now: () => this.now()
1054
+ }, run.id, error);
1163
1055
  throw error;
1164
1056
  }
1165
1057
  finally {
@@ -1173,7 +1065,7 @@ export class AssemblyLineRuntime {
1173
1065
  }
1174
1066
  /** Bump `updatedAt` while a run executes; enforces the wall-clock deadline (run-heartbeat.ts). */
1175
1067
  startRunHeartbeat(runId) {
1176
- return startRunHeartbeatImpl({
1068
+ return trackActiveRunHeartbeat(this.activeRunExecutions, runId, startRunHeartbeatImpl({
1177
1069
  state: this.state,
1178
1070
  logger: this.logger,
1179
1071
  runHeartbeatMs: this.runHeartbeatMs,
@@ -1185,10 +1077,10 @@ export class AssemblyLineRuntime {
1185
1077
  controller.abort();
1186
1078
  },
1187
1079
  debugSwallow: (message, fields) => this.debugSwallow(message, fields)
1188
- }, runId);
1080
+ }, runId));
1189
1081
  }
1190
1082
  registerRunAbort(runId, controller) {
1191
- return registerRunAbortController(this.runAbortControllers, this.runDeadlines, runId, controller);
1083
+ return registerRunAbortController(this.runAbortControllers, this.runDeadlines, runId, controller, this.runControlIntents);
1192
1084
  }
1193
1085
  conversationContextHost() {
1194
1086
  const runtime = this;
@@ -1199,6 +1091,7 @@ export class AssemblyLineRuntime {
1199
1091
  coreToolPolicy: this.coreToolPolicy,
1200
1092
  memoryStore: this.memoryStore,
1201
1093
  skillStore: this.skillStore,
1094
+ skillBundleIndex: this.skillBundleIndex,
1202
1095
  sourceLoader: this.sourceLoader,
1203
1096
  get contextPolicyPromise() {
1204
1097
  return runtime.contextPolicyPromise;
@@ -1211,15 +1104,16 @@ export class AssemblyLineRuntime {
1211
1104
  warnSwallow: (message, fields) => this.warnSwallow(message, fields),
1212
1105
  memoryScopeForRun: (run) => this.memoryScopeForRun(run),
1213
1106
  durableAgentScope: () => this.durableAgentScope(),
1214
- ensureSkillsSeeded: () => this.ensureSkillsSeeded(),
1215
- skillScope: () => this.skillScope()
1107
+ ensureSkillsSeeded: (surfacePath) => this.ensureSkillsSeeded(surfacePath),
1108
+ skillScopeForSurface: (surfacePath) => this.skillScopeForSurface(surfacePath),
1109
+ surfaceForRun: (run) => surfaceForRun(this.manifest, run)
1216
1110
  };
1217
1111
  }
1218
1112
  async prepareConversation(run, options, channel) {
1219
1113
  return prepareConversationImpl(this.conversationContextHost(), run, options, channel);
1220
1114
  }
1221
- async recentHistory(conversationId) {
1222
- return recentHistoryImpl(this.conversationContextHost(), conversationId);
1115
+ async recentHistory(conversationId, excludeRunId) {
1116
+ return recentHistoryImpl(this.conversationContextHost(), conversationId, excludeRunId);
1223
1117
  }
1224
1118
  async augmentChannelContext(channelName, turn, run) {
1225
1119
  return augmentChannelContextImpl(this.conversationContextHost(), channelName, turn, run);
@@ -1258,28 +1152,34 @@ export class AssemblyLineRuntime {
1258
1152
  return runtime.instrumentationConfig;
1259
1153
  },
1260
1154
  createConnectionRegistry: (channel, turn) => this.createConnectionRegistry(channel, turn),
1261
- createConnectionRegistryForRun: (run, fallbackChannel, sandboxHandle) => this.createConnectionRegistryForRun(run, fallbackChannel, sandboxHandle),
1155
+ createConnectionRegistryForRun: (run, fallbackChannel, sandboxHandle, selectedConnections) => this.createConnectionRegistryForRun(run, fallbackChannel, sandboxHandle, selectedConnections),
1156
+ missingRequiredConnections: (selected) => this.missingRequiredConnections(selected),
1262
1157
  visibleToolSet: (defaultToolNames, activeSkills) => this.visibleToolSet(defaultToolNames, activeSkills),
1263
- modelTools: (activeToolNames, connectionRegistry, discoveredConnectionTools) => this.modelTools(activeToolNames, connectionRegistry, discoveredConnectionTools),
1158
+ modelTools: (run, activeToolNames, connectionRegistry, discoveredConnectionTools, options) => this.modelTools(run, activeToolNames, connectionRegistry, discoveredConnectionTools, options),
1264
1159
  harnessExecuteTool: (call, state) => this.harnessExecuteTool(call, state),
1265
1160
  createCheckpoint: (input) => this.createCheckpoint(input),
1161
+ hydrateCheckpointData: (data) => this.hydrateCheckpointData(data),
1266
1162
  emitSpan: (name, startedAt, attributes, options) => this.emitSpan(name, startedAt, attributes, options),
1267
1163
  runSpanAttributes: (run, extra) => this.runSpanAttributes(run, extra),
1268
1164
  turnSpanId: (runId) => this.turnSpanId(runId)
1269
1165
  };
1270
1166
  }
1271
1167
  async resolveAgentHarness(modelSpec) {
1272
- return resolveAgentHarnessImpl(this.harnessLoopHost(), modelSpec);
1273
- }
1274
- piHarness() {
1275
- return piHarnessImpl(this.harnessLoopHost());
1168
+ const resolvedModel = modelSpec ?? this.manifest.possibleModels[0];
1169
+ if (!resolvedModel)
1170
+ throw new Error("No compiled model is available for harness resolution.");
1171
+ return resolveAgentHarnessImpl(this.harnessLoopHost(), resolvedModel);
1276
1172
  }
1277
1173
  async runHarnessLoop(input) {
1278
1174
  return runHarnessLoopImpl(this.harnessLoopHost(), input);
1279
1175
  }
1280
1176
  /** Load the conversation's stored transcript for resume, or undefined when disabled/absent. */
1281
1177
  async loadConversationTranscript(conversationId, runId) {
1282
- return loadResumableConversationTranscriptImpl(this.conversationContextHost(), { state: this.state, createCheckpoint: (input) => this.createCheckpoint(input) }, conversationId, runId);
1178
+ return loadResumableConversationTranscriptImpl(this.conversationContextHost(), {
1179
+ state: this.state,
1180
+ createCheckpoint: (input) => this.createCheckpoint(input),
1181
+ hydrateCheckpointData: (data) => this.hydrateCheckpointData(data)
1182
+ }, conversationId, runId);
1283
1183
  }
1284
1184
  createHarnessContext(session, loopState, resumed) {
1285
1185
  return createHarnessContextImpl(this.harnessLoopHost(), session, loopState, resumed);
@@ -1328,29 +1228,37 @@ export class AssemblyLineRuntime {
1328
1228
  ensureDynamicConnections: () => this.ensureDynamicConnections(),
1329
1229
  withRunAdmission: (work) => this.withRunAdmission(work),
1330
1230
  listHydratedCheckpoints: (runId) => this.listHydratedCheckpoints(runId),
1231
+ hydrateCheckpointData: (data) => this.hydrateCheckpointData(data),
1331
1232
  resolveAgentHarness: (modelSpec) => this.resolveAgentHarness(modelSpec),
1233
+ ensureAgentHookController: (run) => this.ensureAgentHookController(run),
1234
+ resolvedInstructionsForRun: (run, bundle, capabilities) => resolvedHookInstructionsForRun(this.manifest, run, bundle.instructions, capabilities),
1332
1235
  buildContextBundle: (input) => this.buildContextBundle(input),
1333
1236
  createSandboxHandle: (getRun, setRun, getBundle) => this.createSandboxHandle(getRun, setRun, getBundle),
1334
1237
  executeToolWithRecord: (run, tool, toolCall, input, sandboxHandle, approvedToolCall) => this.executeToolWithRecord(run, tool, toolCall, input, sandboxHandle, approvedToolCall),
1335
1238
  executeConnectionToolWithRecord: (run, registry, toolName, toolCall, input) => this.executeConnectionToolWithRecord(run, registry, toolName, toolCall, input),
1336
1239
  createConnectionRegistry: (channel, turn) => this.createConnectionRegistry(channel, turn),
1337
- createConnectionRegistryForRun: (run, fallbackChannel, sandboxHandle) => this.createConnectionRegistryForRun(run, fallbackChannel, sandboxHandle),
1240
+ createConnectionRegistryForRun: (run, fallbackChannel, sandboxHandle, selectedConnections) => this.createConnectionRegistryForRun(run, fallbackChannel, sandboxHandle, selectedConnections),
1338
1241
  createConnectionRegistryForSession: (session) => this.createConnectionRegistryForSession(session),
1339
1242
  mergedConnections: () => this.mergedConnections(),
1340
1243
  loadConnectionDefinition: (connection) => this.loadConnectionDefinition(connection),
1341
1244
  startRunHeartbeat: (runId) => this.startRunHeartbeat(runId),
1342
1245
  createHarnessContext: (session, loopState, resumed) => this.createHarnessContext(session, loopState, resumed),
1343
- executeHarnessTurn: (harness, input, session, loopState, resumed) => executeHarnessTurnImpl(this.harnessLoopHost(), harness, input, session, loopState, resumed),
1246
+ executeHarnessTurn: (harness, input, session, loopState, resumed, refreshCapabilities) => executeHarnessTurnImpl(this.harnessLoopHost(), harness, input, session, loopState, resumed, refreshCapabilities),
1344
1247
  persistHarnessContinuation: (runId, session, continuation, pause) => this.persistHarnessContinuation(runId, session, continuation, pause),
1345
1248
  createCheckpoint: (input) => this.createCheckpoint(input),
1346
1249
  result: (run, response, waitingForApproval, waitingForInput, waitingForConnection) => this.result(run, response, waitingForApproval, waitingForInput, waitingForConnection),
1347
1250
  completeRun: (run, sandboxHandle, response, channel, turn, conversationId) => this.completeRun(run, sandboxHandle, response, channel, turn, conversationId),
1348
- runDeliveryChannel: (run) => this.runDeliveryChannel(run)
1251
+ runDeliveryChannel: (run) => this.runDeliveryChannel(run),
1252
+ enqueueConversationTurn: (input) => this.conversationTurnDispatcher.enqueue(input)
1349
1253
  };
1350
1254
  }
1351
1255
  async replay(runId) {
1352
1256
  return replayImpl(this.replayResumeHost(), runId);
1353
1257
  }
1258
+ /** Start a new, isolated run from a terminal run's verified durable input snapshot. */
1259
+ async rerun(runId, lifecycle) {
1260
+ return rerunFromSnapshot({ runId, state: this.state, blob: this.blob, manifest: this.manifest, run: (options) => this.run(options) }, lifecycle);
1261
+ }
1354
1262
  /** Resumes never consume run capacity (deadlock risk); they only count toward `onIdle()`. */
1355
1263
  async resumeApproval(runId) {
1356
1264
  const result = await this.withRunAdmission(() => this.resumeApprovalNow(runId));
@@ -1361,9 +1269,22 @@ export class AssemblyLineRuntime {
1361
1269
  return resumeApprovalNowImpl(this.replayResumeHost(), runId);
1362
1270
  }
1363
1271
  async completeConnectionAuthorizationCallback(callback) {
1272
+ const authorizationSession = callback.params.state
1273
+ ? await this.connectionAuthorizationSessionStore.getSessionByState(callback.params.state)
1274
+ : undefined;
1364
1275
  const result = await completeConnectionAuthorizationCallbackImpl(this.replayResumeHost(), callback);
1365
1276
  if (result.runResult)
1366
1277
  await this.conversationTurnDispatcher.settleRunResult(result.runResult);
1278
+ if (authorizationSession) {
1279
+ await this.reconcileConnectionEvents({
1280
+ connection: authorizationSession.connectionName,
1281
+ principal: authorizationSession.principal,
1282
+ force: true
1283
+ }).catch((error) => this.logger.warn("connection event reconcile after authorization failed", {
1284
+ connection: authorizationSession.connectionName,
1285
+ error: error instanceof Error ? error.message : String(error)
1286
+ }));
1287
+ }
1367
1288
  return result;
1368
1289
  }
1369
1290
  /**
@@ -1379,6 +1300,65 @@ export class AssemblyLineRuntime {
1379
1300
  async beginConnectionAuthorization(connectionName, session = {}) {
1380
1301
  return beginConnectionAuthorizationImpl(this.toolExecutionHost(), connectionName, session);
1381
1302
  }
1303
+ connectionEventsHost(publicUrl) {
1304
+ const resolvedPublicUrl = publicUrl ?? this.connectionCallbackBaseUrl;
1305
+ return {
1306
+ manifest: this.manifest,
1307
+ env: this.env,
1308
+ fetch: this.fetch,
1309
+ logger: this.logger,
1310
+ agentScope: this.durableAgentScope(),
1311
+ store: this.connectionEventStore,
1312
+ grantStore: this.connectionGrantStore,
1313
+ ...(resolvedPublicUrl ? { publicUrl: resolvedPublicUrl } : {}),
1314
+ createRegistry: (principal) => new RuntimeConnectionRegistry({
1315
+ connections: this.mergedConnections(),
1316
+ env: this.env,
1317
+ fetch: this.fetch,
1318
+ session: {
1319
+ channel: "connection-event",
1320
+ principal,
1321
+ ...(principal.type === "user" ? { userId: principal.id } : {})
1322
+ },
1323
+ agentId: this.manifest.agent.id ?? this.manifest.agentRevision,
1324
+ grantStore: this.connectionGrantStore,
1325
+ authorizationSessionStore: this.connectionAuthorizationSessionStore,
1326
+ ...(this.connectionCallbackBaseUrl ? { callbackBaseUrl: this.connectionCallbackBaseUrl } : {}),
1327
+ loadDefinition: async (connection) => this.loadConnectionDefinition(connection)
1328
+ }),
1329
+ dispatchAutomationEvent: (event) => this.dispatchAutomationEvent(event),
1330
+ appendAudit: (type, data) => this.state.appendRuntimeControlEvent(this.durableAgentScope(), type, data)
1331
+ };
1332
+ }
1333
+ async reconcileConnectionEvents(options = {}) {
1334
+ return reconcileConnectionEvents(this.connectionEventsHost(options.publicUrl), options);
1335
+ }
1336
+ async checkConnectionEvents(connection) {
1337
+ return checkConnectionEvents(this.connectionEventsHost(), connection);
1338
+ }
1339
+ async acceptConnectionEvent(connectionName, bindingId, request) {
1340
+ return acceptConnectionEvent(this.connectionEventsHost(), connectionName, bindingId, request);
1341
+ }
1342
+ async runDueConnectionEvents(options = {}) {
1343
+ return drainConnectionEventInbox(this.connectionEventsHost(), options);
1344
+ }
1345
+ startConnectionEventWorker(options = {}) {
1346
+ const intervalMs = positiveLimit(options.intervalMs, 1_000);
1347
+ const tick = () => this.runDueConnectionEvents({
1348
+ ...(options.batchSize !== undefined ? { limit: options.batchSize } : {}),
1349
+ ...(options.leaseForMs !== undefined ? { leaseForMs: options.leaseForMs } : {})
1350
+ }).catch((error) => this.logger.warn("connection event worker tick failed", { error: error instanceof Error ? error.message : String(error) }));
1351
+ void tick();
1352
+ const timer = setInterval(() => void tick(), intervalMs);
1353
+ timer.unref?.();
1354
+ const reconcile = () => this.reconcileConnectionEvents().catch((error) => this.logger.warn("connection event reconcile tick failed", {
1355
+ error: error instanceof Error ? error.message : String(error)
1356
+ }));
1357
+ void reconcile();
1358
+ const reconcileTimer = setInterval(() => void reconcile(), 60_000);
1359
+ reconcileTimer.unref?.();
1360
+ return { stop: () => { clearInterval(timer); clearInterval(reconcileTimer); } };
1361
+ }
1382
1362
  /** Resumes never consume run capacity (deadlock risk); they only count toward `onIdle()`. */
1383
1363
  async resumeInput(runId, answer) {
1384
1364
  const result = await this.withRunAdmission(() => this.resumeInputNow(runId, answer));
@@ -1431,12 +1411,7 @@ export class AssemblyLineRuntime {
1431
1411
  state: this.state,
1432
1412
  boot: () => this.boot(),
1433
1413
  durableAgentScope: () => this.durableAgentScope(),
1434
- cacheRunControl: (runId, intent) => {
1435
- if (intent)
1436
- this.runControlIntents.set(runId, intent);
1437
- else
1438
- this.runControlIntents.delete(runId);
1439
- }
1414
+ cacheRunControl: (runId, intent) => cacheRunControlSignal(this.runControlIntents, this.activeRunExecutions, this.runAbortControllers, runId, intent)
1440
1415
  };
1441
1416
  }
1442
1417
  async resumeHarnessLoop(run, harness, restored, resume) {
@@ -1451,6 +1426,7 @@ export class AssemblyLineRuntime {
1451
1426
  replay: (runId) => this.replay(runId),
1452
1427
  listHydratedCheckpoints: (runId) => this.listHydratedCheckpoints(runId),
1453
1428
  buildContextBundle: (input) => this.buildContextBundle(input),
1429
+ createSubagentHookController: (run, subagent, message, conversationId) => this.createSubagentHookController(run, subagent, message, conversationId),
1454
1430
  createSandboxHandle: (getRun, setRun, getBundle) => this.createSandboxHandle(getRun, setRun, getBundle),
1455
1431
  startRunHeartbeat: (runId) => this.startRunHeartbeat(runId),
1456
1432
  runHarnessLoop: (input) => this.runHarnessLoop(input),
@@ -1471,7 +1447,15 @@ export class AssemblyLineRuntime {
1471
1447
  return sendSubagentFollowupImpl(this.subagentExecutionHost(), childRunId, message);
1472
1448
  }
1473
1449
  async loadSkill(runId, skillName) {
1474
- const loaded = await this.skillLoadDetails(skillName);
1450
+ const run = await this.state.getRun(runId);
1451
+ if (!run)
1452
+ throw new Error(`Run not found: ${runId}`);
1453
+ const controller = await this.ensureAgentHookController(run);
1454
+ const snapshot = await controller.refreshIfDirty();
1455
+ if (!snapshot.declaration.skills.includes(skillName)) {
1456
+ throw new Error(`Skill ${skillName} is not enabled by the current agent capability snapshot.`);
1457
+ }
1458
+ const loaded = await this.skillLoadDetails(run, skillName);
1475
1459
  const output = {
1476
1460
  name: loaded.name,
1477
1461
  skillName: loaded.name,
@@ -1556,7 +1540,7 @@ export class AssemblyLineRuntime {
1556
1540
  shouldStartScheduler() {
1557
1541
  if (this.schedulerEnabled === false)
1558
1542
  return false;
1559
- if (this.env.OPENEVE_SCHEDULER_ENABLED === "false" || this.env.OPENEVE_SCHEDULER_ENABLED === "0")
1543
+ if (this.env.ASSEMBLY_LINE_SCHEDULER_ENABLED === "false" || this.env.ASSEMBLY_LINE_SCHEDULER_ENABLED === "0")
1560
1544
  return false;
1561
1545
  return true;
1562
1546
  }
@@ -1580,6 +1564,8 @@ export class AssemblyLineRuntime {
1580
1564
  runHeartbeatMs: this.runHeartbeatMs,
1581
1565
  sandboxSyncMaxAttempts: this.sandboxSyncMaxAttempts,
1582
1566
  deliveryQueueMaxAttempts: this.deliveryQueueMaxAttempts,
1567
+ connectionAuthorizationSessionStore: this.connectionAuthorizationSessionStore,
1568
+ missingRequiredConnections: (selected) => this.missingRequiredConnections(selected),
1583
1569
  resumeRunFromContinuation: (run, context) => this.withRunAdmission(() => this.resumeRunFromContinuation(run, context)),
1584
1570
  listHydratedCheckpoints: (runId) => this.listHydratedCheckpoints(runId)
1585
1571
  };
@@ -1594,7 +1580,7 @@ export class AssemblyLineRuntime {
1594
1580
  async resumeRunFromContinuation(run, context) {
1595
1581
  return resumeRunFromContinuationImpl(this.replayResumeHost(), run, context);
1596
1582
  }
1597
- /** Start delivery, sandbox-sync, conversation-turn, and orphan-recovery workers. */
1583
+ /** Start delivery, sandbox-sync, conversation-turn, background-review, and orphan-recovery workers. */
1598
1584
  startBackgroundWorkers(options = {}) {
1599
1585
  return startBackgroundWorkersImpl({
1600
1586
  env: this.env,
@@ -1603,6 +1589,8 @@ export class AssemblyLineRuntime {
1603
1589
  startDeliveryWorker: (workerOptions) => this.startDeliveryWorker(workerOptions),
1604
1590
  startSandboxSyncWorker: (workerOptions) => this.startSandboxSyncWorker(workerOptions),
1605
1591
  startConversationTurnWorker: (workerOptions) => this.conversationTurnDispatcher.startWorker(workerOptions?.intervalMs),
1592
+ startBackgroundReviewWorker: (workerOptions) => this.startBackgroundReviewWorker(workerOptions),
1593
+ startConnectionEventWorker: (workerOptions) => this.startConnectionEventWorker(workerOptions),
1606
1594
  recoverIncompleteRuns: (recoveryOptions) => this.recoverIncompleteRuns(recoveryOptions),
1607
1595
  agentEnabled: () => this.agentEnabled()
1608
1596
  }, options);
@@ -1647,6 +1635,10 @@ export class AssemblyLineRuntime {
1647
1635
  deliveryQueueLeaseMs: this.deliveryQueueLeaseMs,
1648
1636
  deliveryQueueMaxAttempts: this.deliveryQueueMaxAttempts,
1649
1637
  sandboxSyncMaxAttempts: this.sandboxSyncMaxAttempts,
1638
+ workspaceFilesForDelivery: async (run) => {
1639
+ const workspace = await this.workspaceRuntime.service.resolveForRun(run);
1640
+ return (await this.workspaceRuntime.service.loadManifest(workspace)).manifest.entries;
1641
+ },
1650
1642
  result: (run, response, waitingForApproval, waitingForInput, waitingForConnection) => this.result(run, response, waitingForApproval, waitingForInput, waitingForConnection),
1651
1643
  sandboxSessionKey: (run) => this.sandboxSessionKey(run),
1652
1644
  debugSwallow: (message, fields) => this.debugSwallow(message, fields),
@@ -1664,9 +1656,6 @@ export class AssemblyLineRuntime {
1664
1656
  async latestRunFailureMessage(runId) {
1665
1657
  return latestRunFailureMessageImpl(this.deliverySendHost(), runId);
1666
1658
  }
1667
- async enqueueSandboxSyncAfterDelivery(run, sandboxSession) {
1668
- return enqueueSandboxSyncAfterDeliveryImpl(this.deliverySendHost(), run, sandboxSession);
1669
- }
1670
1659
  sandboxSyncWorkerHost() {
1671
1660
  return {
1672
1661
  state: this.state,
@@ -1681,6 +1670,7 @@ export class AssemblyLineRuntime {
1681
1670
  readSandboxTombstonesWithMissingProjectedFiles: (sandbox) => this.readSandboxTombstonesWithMissingProjectedFiles(sandbox),
1682
1671
  syncMemoryFromSandbox: (run, sandboxSession, tombstones) => this.syncMemoryFromSandbox(run, sandboxSession, tombstones),
1683
1672
  syncSkillsFromSandbox: (run, sandboxSession, tombstones) => this.syncSkillsFromSandbox(run, sandboxSession, tombstones),
1673
+ syncWorkspace: (run, sandboxSession, syncJob) => this.workspaceRuntime.sync(run, sandboxSession, syncJob),
1684
1674
  emitSpan: (name, startedAt, attributes, options) => this.emitSpan(name, startedAt, attributes, options),
1685
1675
  runSpanAttributes: (run, extra) => this.runSpanAttributes(run, extra),
1686
1676
  turnSpanId: (runId) => this.turnSpanId(runId),
@@ -1729,14 +1719,14 @@ export class AssemblyLineRuntime {
1729
1719
  visibleToolSet(defaultToolNames, activeSkills) {
1730
1720
  return visibleToolSetImpl(this.toolExecutionHost(), defaultToolNames, activeSkills);
1731
1721
  }
1732
- async skillLoadDetails(skillName) {
1733
- return skillLoadDetailsImpl(this.toolExecutionHost(), skillName);
1722
+ async skillLoadDetails(run, skillName) {
1723
+ return skillLoadDetailsImpl(this.toolExecutionHost(), run, skillName);
1734
1724
  }
1735
1725
  async instructionsForRunTarget(run, target, baseInstructions) {
1736
- return instructionsForRunTargetImpl({ appendEvent: (runId, type, data) => this.state.appendEvent(runId, type, data), skillLoadDetails: (skillName) => this.skillLoadDetails(skillName) }, run, target, baseInstructions);
1726
+ return instructionsForRunTargetImpl({ appendEvent: (runId, type, data) => this.state.appendEvent(runId, type, data), skillLoadDetails: (skillName) => this.skillLoadDetails(run, skillName) }, run, target, baseInstructions);
1737
1727
  }
1738
- async modelTools(activeToolNames, connectionRegistry, discoveredConnectionTools = new Map()) {
1739
- return modelToolsImpl(this.toolExecutionHost(), activeToolNames, connectionRegistry, discoveredConnectionTools);
1728
+ async modelTools(run, activeToolNames, connectionRegistry, discoveredConnectionTools = new Map(), options) {
1729
+ return modelToolsImpl(this.toolExecutionHost(), run, activeToolNames, connectionRegistry, discoveredConnectionTools, options);
1740
1730
  }
1741
1731
  async harnessExecuteTool(call, state) {
1742
1732
  return harnessExecuteToolImpl(this.toolExecutionHost(), call, state);
@@ -1744,8 +1734,8 @@ export class AssemblyLineRuntime {
1744
1734
  createConnectionRegistry(channel, turn) {
1745
1735
  return createConnectionRegistryImpl(this.toolExecutionHost(), channel, turn);
1746
1736
  }
1747
- createConnectionRegistryForRun(run, fallbackChannel, sandboxHandle) {
1748
- return createConnectionRegistryForRunImpl(this.toolExecutionHost(), run, fallbackChannel, sandboxHandle);
1737
+ createConnectionRegistryForRun(run, fallbackChannel, sandboxHandle, selectedConnections) {
1738
+ return createConnectionRegistryForRunImpl(this.toolExecutionHost(), run, fallbackChannel, sandboxHandle, selectedConnections);
1749
1739
  }
1750
1740
  createConnectionRegistryForSession(session) {
1751
1741
  return createConnectionRegistryForSessionImpl(this.toolExecutionHost(), session);
@@ -1779,12 +1769,18 @@ export class AssemblyLineRuntime {
1779
1769
  env: this.env,
1780
1770
  fetch: this.fetch,
1781
1771
  state: this.state,
1782
- blob: this.blob
1772
+ blob: this.blob,
1773
+ agent: {
1774
+ start: (turn) => startChannelAgentTurnImpl(this.channelIngressHost(), channel.name, turn),
1775
+ observe: (observation) => observeChannelMessageImpl(this.channelIngressHost(), channel, observation),
1776
+ cancel: (runId) => this.cancelRun(runId)
1777
+ }
1783
1778
  };
1784
1779
  }
1785
- missingRequiredConnections() {
1780
+ missingRequiredConnections(selected) {
1781
+ const selectedNames = new Set(selected);
1786
1782
  return this.manifest.connections
1787
- .filter((connection) => connection.required && connection.protocol === "declaration")
1783
+ .filter((connection) => selectedNames.has(connection.name) && connection.required && connection.protocol === "declaration")
1788
1784
  .map((connection) => connection.name)
1789
1785
  .filter((name) => this.connections[name] === undefined);
1790
1786
  }
@@ -1796,11 +1792,11 @@ export class AssemblyLineRuntime {
1796
1792
  this.instrumentationLoaded = true;
1797
1793
  return;
1798
1794
  }
1799
- const instrumentation = await this.loadInstrumentationModule();
1795
+ const instrumentation = this.manifest.instrumentation
1796
+ ? await this.sourceLoader.load(this.manifest.instrumentation)
1797
+ : {};
1800
1798
  const defaultExport = instrumentation.default;
1801
1799
  const definition = isInstrumentationDefinition(defaultExport) ? defaultExport : undefined;
1802
- // Host/gateway-supplied instrumentation wins over instrumentation.ts, mirroring
1803
- // the telemetry-sink precedence below.
1804
1800
  if (definition && !this.hostInstrumentationProvided) {
1805
1801
  this.instrumentationConfig = {
1806
1802
  recordInputs: definition.recordInputs ?? false,
@@ -1826,7 +1822,7 @@ export class AssemblyLineRuntime {
1826
1822
  this.instrumentationLoaded = true;
1827
1823
  }
1828
1824
  agentName() {
1829
- return this.manifest.agent.name ?? this.manifest.agent.description ?? `openeve-${this.manifest.agentRevision.slice(0, 12)}`;
1825
+ return this.manifest.agent.name ?? this.manifest.agent.description ?? `assembly-line-${this.manifest.agentRevision.slice(0, 12)}`;
1830
1826
  }
1831
1827
  traceIdForRun(runId) {
1832
1828
  return createHash("sha256").update(runId).digest("hex").slice(0, 32);
@@ -1853,11 +1849,13 @@ export class AssemblyLineRuntime {
1853
1849
  toolExecutionHost() {
1854
1850
  return {
1855
1851
  state: this.state,
1852
+ blob: this.blob,
1856
1853
  env: this.env,
1857
1854
  fetch: this.fetch,
1858
1855
  manifest: this.manifest,
1859
1856
  coreToolPolicy: this.coreToolPolicy,
1860
1857
  skillStore: this.skillStore,
1858
+ skillBundleIndex: this.skillBundleIndex,
1861
1859
  memoryStore: this.memoryStore,
1862
1860
  sandbox: this.sandbox,
1863
1861
  connections: this.connections,
@@ -1867,11 +1865,13 @@ export class AssemblyLineRuntime {
1867
1865
  toolOutputMaxChars: this.toolOutputMaxChars,
1868
1866
  toolTimeoutMs: this.toolTimeoutMs,
1869
1867
  sandboxSyncMaxAttempts: this.sandboxSyncMaxAttempts,
1870
- skillsConfig: this.skillsConfig,
1868
+ skillsConfigForRun: (run) => this.skillsConfigForRun(run),
1871
1869
  schedulesConfig: this.schedulesConfig,
1872
1870
  connectionsConfig: this.connectionsConfig,
1873
- ensureSkillsSeeded: () => this.ensureSkillsSeeded(),
1874
- skillScope: () => this.skillScope(),
1871
+ surfaceForRun: (run) => surfaceForRun(this.manifest, run),
1872
+ agentStateForRun: (runId) => this.agentStateForRun(runId),
1873
+ ensureSkillsSeeded: (run) => this.ensureSkillsSeeded(surfaceForRun(this.manifest, run).path),
1874
+ skillScopeForRun: (run) => this.skillScopeForRun(run),
1875
1875
  scheduleScopeForRun: (run) => this.scheduleScopeForRun(run),
1876
1876
  memoryScopeForRun: (run) => this.memoryScopeForRun(run),
1877
1877
  sandboxSessionKey: (run) => this.sandboxSessionKey(run),
@@ -1884,13 +1884,14 @@ export class AssemblyLineRuntime {
1884
1884
  recordSandboxTombstone: (run, sandbox, path) => this.recordSandboxTombstone(run, sandbox, path),
1885
1885
  createCheckpoint: (input) => this.createCheckpoint(input),
1886
1886
  listHydratedCheckpoints: (runId) => this.listHydratedCheckpoints(runId),
1887
+ executeWorkspaceTool: (run, toolName, input, sandboxHandle) => this.workspaceRuntime.executeTool(run, toolName, input, sandboxHandle),
1887
1888
  emitSpan: (name, startedAt, attributes, options) => this.emitSpan(name, startedAt, attributes, options),
1888
1889
  runSpanAttributes: (run, extra) => this.runSpanAttributes(run, extra),
1889
1890
  turnSpanId: (runId) => this.turnSpanId(runId),
1890
1891
  toolContentAttributes: (input, output) => this.toolContentAttributes(input, output),
1891
- saveSkill: (input) => this.saveSkill(input),
1892
- listSkills: () => this.listSkills(),
1893
- deleteSkill: (name) => this.deleteSkill(name),
1892
+ saveSkill: (input, run) => this.saveSkill(input, surfaceForRun(this.manifest, run).path),
1893
+ listSkills: (run) => this.listSkills(surfaceForRun(this.manifest, run).path),
1894
+ deleteSkill: (name, run) => this.deleteSkill(name, surfaceForRun(this.manifest, run).path),
1894
1895
  createDynamicSchedule: (input) => this.createDynamicSchedule(input),
1895
1896
  listDynamicSchedules: (scope) => this.listDynamicSchedules(scope),
1896
1897
  updateDynamicSchedule: (scope, id, patch) => this.updateDynamicSchedule(scope, id, patch),
@@ -1930,11 +1931,14 @@ export class AssemblyLineRuntime {
1930
1931
  blob: this.blob,
1931
1932
  memoryStore: this.memoryStore,
1932
1933
  skillStore: this.skillStore,
1934
+ skillBundleIndex: this.skillBundleIndex,
1935
+ skillResourceReader: this.skillResourceReader,
1933
1936
  resourceProjectionPolicy: this.resourceProjectionPolicy,
1934
1937
  memoryEmbeddingProvider: this.memoryEmbeddingProvider,
1935
1938
  memoryEmbeddingsEnabled: this.memoryEmbeddingsEnabled,
1936
- skillScope: () => this.skillScope(),
1937
- durableAgentScope: () => this.durableAgentScope()
1939
+ skillScopeForRun: (run) => this.skillScopeForRun(run),
1940
+ durableAgentScope: () => this.durableAgentScope(),
1941
+ surfaceForRun: (run) => surfaceForRun(this.manifest, run)
1938
1942
  };
1939
1943
  }
1940
1944
  async listResourcesForRun(run, scope, input = {}) {
@@ -1949,6 +1953,9 @@ export class AssemblyLineRuntime {
1949
1953
  async projectSkillIntoSandbox(run, sandbox, skillName) {
1950
1954
  return projectSkillIntoSandboxImpl(this.resourceProjectionHost(), run, sandbox, skillName);
1951
1955
  }
1956
+ async projectLoadedSkillsIntoSandbox(run, sandbox) {
1957
+ return projectLoadedSkillsIntoSandboxImpl(this.resourceProjectionHost(), run, sandbox);
1958
+ }
1952
1959
  async hydrateLogicalPathForTool(run, sandbox, path, options = {}) {
1953
1960
  return hydrateLogicalPathForToolImpl(this.resourceProjectionHost(), run, sandbox, path, options);
1954
1961
  }
@@ -1967,33 +1974,117 @@ export class AssemblyLineRuntime {
1967
1974
  async runMemoryEmbeddingBackfill(options = {}) {
1968
1975
  return runMemoryEmbeddingBackfillImpl(this.resourceProjectionHost(), options);
1969
1976
  }
1970
- hookDispatcher;
1971
- dispatchHookEvent(runId, event) {
1972
- if (!this.manifest.hooks?.length)
1973
- return;
1974
- this.hookDispatcher ??= createHookDispatcher({
1975
- agentName: this.agentName(),
1976
- hooks: this.manifest.hooks,
1977
- loadModule: (source) => this.sourceLoader.load(source),
1978
- logger: this.logger
1977
+ async dispatchHookEvent(runId, event) {
1978
+ await this.eventHandlers?.dispatch(runId, event);
1979
+ if (this.eventHandlers)
1980
+ removeTerminalAgentHookState(runId, event, this.eventHandlers, this.agentHookControllers, this.agentStateHandles);
1981
+ }
1982
+ async handleRuntimeEvent(runId, event) {
1983
+ await this.dispatchHookEvent(runId, event);
1984
+ await this.runtimeLearning.handleRuntimeEvent(runId, event.type);
1985
+ }
1986
+ async createAgentHookController(run, options, channel, conversationId, attachments) {
1987
+ const disabledTools = this.disabledToolsForRun(run);
1988
+ const surface = rootAgentSurface(this.manifest);
1989
+ const liveSkills = (await this.listSkills(surface.path)).map((skill) => skill.name).sort();
1990
+ const baseCatalog = hookCapabilityCatalog(this.manifest, surface);
1991
+ const created = await createRuntimeAgentHookController({
1992
+ manifest: this.manifest,
1993
+ state: this.state,
1994
+ blob: this.blob,
1995
+ sourceLoader: this.sourceLoader,
1996
+ eventHandlers: this.eventHandlers,
1997
+ logger: this.logger,
1998
+ agentScope: this.durableAgentScope(),
1999
+ conversationId,
2000
+ run: immutableAgentRunContext({
2001
+ id: run.id,
2002
+ message: options.message,
2003
+ channel,
2004
+ conversationId,
2005
+ ...(typeof run.input.userId === "string" ? { userId: run.input.userId } : {}),
2006
+ ...(principalFromRun(run) ? { principal: principalFromRun(run) } : {}),
2007
+ ...(initiatorFromRun(run) ? { initiator: initiatorFromRun(run) } : {}),
2008
+ audience: audienceFromRun(run),
2009
+ ...((options.metadata ?? options.turn?.metadata) ? {
2010
+ metadata: (options.metadata ?? options.turn?.metadata)
2011
+ } : {}),
2012
+ attachments
2013
+ }),
2014
+ surface,
2015
+ catalog: { ...baseCatalog, skills: new Set(liveSkills) },
2016
+ defaultSkills: liveSkills,
2017
+ disabledTools,
2018
+ createCheckpoint: (input) => this.createCheckpoint(input),
2019
+ listCheckpoints: (runId) => this.listHydratedCheckpoints(runId)
1979
2020
  });
1980
- return this.hookDispatcher(runId, event);
1981
- }
1982
- /** Per-run capability resolution from `resolvers.ts` (run-resolver.ts). */
1983
- resolveRunCapabilities(run, options, conversationId) {
1984
- const input = { runId: run.id, message: options.message };
1985
- if (options.channel !== undefined)
1986
- input.channel = options.channel;
1987
- if (conversationId !== undefined)
1988
- input.conversationId = conversationId;
1989
- if (options.metadata !== undefined)
1990
- input.metadata = options.metadata;
1991
- return resolveRunCapabilitiesImpl({
2021
+ this.agentStateHandles.set(run.id, created.agentState);
2022
+ this.agentHookControllers.set(run.id, created.controller);
2023
+ return created.controller;
2024
+ }
2025
+ async createSubagentHookController(run, subagent, message, conversationId) {
2026
+ const surface = subagentSurface(subagent);
2027
+ const liveSkills = (await this.listSkills(surface.path)).map((skill) => skill.name).sort();
2028
+ const baseCatalog = hookCapabilityCatalog(this.manifest, surface);
2029
+ const created = await createRuntimeAgentHookController({
1992
2030
  manifest: this.manifest,
1993
- env: this.env,
1994
- loadModule: (source) => this.sourceLoader.load(source),
1995
- appendEvent: (runId, type, data) => this.state.appendEvent(runId, type, data)
1996
- }, input);
2031
+ state: this.state,
2032
+ blob: this.blob,
2033
+ sourceLoader: this.sourceLoader,
2034
+ eventHandlers: this.eventHandlers,
2035
+ logger: this.logger,
2036
+ agentScope: `${this.durableAgentScope()}:subagent:${subagent.path}`,
2037
+ conversationId,
2038
+ agentSource: subagent.agentSource,
2039
+ surface,
2040
+ catalog: {
2041
+ ...baseCatalog,
2042
+ skills: new Set(liveSkills),
2043
+ models: new Set(subagent.possibleModels),
2044
+ connections: new Set(subagent.connections),
2045
+ ...(subagent.maxReasoning !== undefined ? { maxReasoning: subagent.maxReasoning } : {})
2046
+ },
2047
+ defaultSkills: liveSkills,
2048
+ run: immutableAgentRunContext({
2049
+ id: run.id,
2050
+ message,
2051
+ channel: "subagent",
2052
+ conversationId,
2053
+ ...(typeof run.input.userId === "string" ? { userId: run.input.userId } : {}),
2054
+ ...(principalFromRun(run) ? { principal: principalFromRun(run) } : {}),
2055
+ ...(initiatorFromRun(run) ? { initiator: initiatorFromRun(run) } : {}),
2056
+ audience: audienceFromRun(run),
2057
+ ...(isJsonObject(run.input.metadata) ? { metadata: run.input.metadata } : {}),
2058
+ attachments: []
2059
+ }),
2060
+ disabledTools: this.disabledToolsForRun(run),
2061
+ createCheckpoint: (input) => this.createCheckpoint(input),
2062
+ listCheckpoints: (runId) => this.listHydratedCheckpoints(runId)
2063
+ });
2064
+ this.agentStateHandles.set(run.id, created.agentState);
2065
+ this.agentHookControllers.set(run.id, created.controller);
2066
+ return created.controller;
2067
+ }
2068
+ disabledToolsForRun(run) {
2069
+ const disabledTools = new Set(Object.entries(this.coreToolPolicy).filter(([, mode]) => mode === "disabled").map(([name]) => name));
2070
+ return disabledTools;
2071
+ }
2072
+ agentStateForRun(runId) {
2073
+ const handle = this.agentStateHandles.get(runId);
2074
+ if (!handle)
2075
+ throw new Error(`Agent state is unavailable before hook evaluation for run ${runId}.`);
2076
+ return handle;
2077
+ }
2078
+ async ensureAgentHookController(run) {
2079
+ const existing = this.agentHookControllers.get(run.id);
2080
+ if (existing)
2081
+ return existing;
2082
+ return recoverAgentHookController({
2083
+ run,
2084
+ manifest: this.manifest,
2085
+ createMain: (message, metadata, channel, conversationId, attachments) => this.createAgentHookController(run, { message, ...(metadata ? { metadata } : {}) }, channel, conversationId, attachments),
2086
+ createSubagent: (subagent, message, conversationId) => this.createSubagentHookController(run, subagent, message, conversationId)
2087
+ });
1997
2088
  }
1998
2089
  async loadTool(tool, run) {
1999
2090
  const stub = resolveEvalToolStub(this.evalStubCursors, run, tool.name) ?? this.toolStubs[tool.name];
@@ -2004,8 +2095,6 @@ export class AssemblyLineRuntime {
2004
2095
  execute: async (input) => stub(input)
2005
2096
  };
2006
2097
  }
2007
- // Only builtin-sourced entries resolve to the built-in implementation; an
2008
- // authored tool that shares a built-in's name is an override and loads its module.
2009
2098
  if (tool.source.path.startsWith("__builtin__")) {
2010
2099
  const builtIn = builtInToolDefinition(tool.name);
2011
2100
  if (builtIn)
@@ -2014,26 +2103,8 @@ export class AssemblyLineRuntime {
2014
2103
  const module = await this.sourceLoader.load(tool.source);
2015
2104
  return module.default;
2016
2105
  }
2017
- async loadInstrumentationModule() {
2018
- if (!this.manifest.instrumentation)
2019
- return {};
2020
- return this.sourceLoader.load(this.manifest.instrumentation);
2021
- }
2022
2106
  async result(run, response, waitingForApproval, waitingForInput, waitingForConnection) {
2023
- const result = {
2024
- run,
2025
- events: await this.state.listEvents(run.id),
2026
- toolCalls: await this.state.listToolCalls(run.id),
2027
- deliveries: await this.state.listDeliveries(run.id),
2028
- response
2029
- };
2030
- if (waitingForApproval !== undefined)
2031
- result.waitingForApproval = waitingForApproval;
2032
- if (waitingForInput !== undefined)
2033
- result.waitingForInput = waitingForInput;
2034
- if (waitingForConnection !== undefined)
2035
- result.waitingForConnection = waitingForConnection;
2036
- return result;
2107
+ return buildRunAgentResult(this.state, run, response, waitingForApproval, waitingForInput, waitingForConnection);
2037
2108
  }
2038
2109
  }
2039
2110
  export async function runLocalAgent(options) {