@capybara-hq/kernel 0.1.0-rc.4 → 0.1.0-rc.6

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 (534) hide show
  1. package/bootstrap.json +61 -5
  2. package/dist/admin/admin.controller.d.ts +51 -14
  3. package/dist/admin/admin.controller.js +60 -19
  4. package/dist/admin/extensions.controller.d.ts +16 -2
  5. package/dist/admin/extensions.controller.js +26 -6
  6. package/dist/admin/setup-lock.d.ts +1 -1
  7. package/dist/admin/setup-lock.js +1 -1
  8. package/dist/admin/setup.controller.d.ts +1 -1
  9. package/dist/admin/setup.controller.js +1 -1
  10. package/dist/admin/setup.service.d.ts +4 -4
  11. package/dist/admin/setup.service.js +8 -8
  12. package/dist/agents/agent-lookup.d.ts +16 -0
  13. package/dist/agents/agent-lookup.js +11 -0
  14. package/dist/agents/agents.controller.d.ts +76 -1
  15. package/dist/agents/agents.controller.js +90 -11
  16. package/dist/agents/agents.module.d.ts +4 -1
  17. package/dist/agents/agents.module.js +32 -6
  18. package/dist/agents/agents.service.d.ts +54 -23
  19. package/dist/agents/agents.service.js +180 -76
  20. package/dist/agents/definition.d.ts +49 -0
  21. package/dist/agents/definition.js +45 -0
  22. package/dist/agents/from-template.d.ts +106 -0
  23. package/dist/agents/from-template.js +649 -0
  24. package/dist/agents/from-template.service.d.ts +60 -0
  25. package/dist/agents/from-template.service.js +161 -0
  26. package/dist/agents/models.controller.d.ts +34 -5
  27. package/dist/agents/models.controller.js +50 -6
  28. package/dist/agents/org-templates.d.ts +176 -0
  29. package/dist/agents/org-templates.js +827 -0
  30. package/dist/agents/pending-connector-requests.d.ts +77 -0
  31. package/dist/agents/pending-connector-requests.js +215 -0
  32. package/dist/agents/pending-connectors.controller.d.ts +39 -0
  33. package/dist/agents/pending-connectors.controller.js +91 -0
  34. package/dist/agents/pending-connectors.service.d.ts +62 -0
  35. package/dist/agents/pending-connectors.service.js +282 -0
  36. package/dist/agents/readiness.controller.d.ts +5 -5
  37. package/dist/agents/readiness.controller.js +6 -6
  38. package/dist/agents/templates.controller.d.ts +86 -5
  39. package/dist/agents/templates.controller.js +171 -7
  40. package/dist/agents/templates.d.ts +127 -23
  41. package/dist/agents/templates.js +475 -52
  42. package/dist/background/background.module.js +8 -1
  43. package/dist/background/finish.d.ts +3 -2
  44. package/dist/background/launch-lock.d.ts +4 -3
  45. package/dist/background/launch-lock.js +4 -3
  46. package/dist/background/poll.job.d.ts +9 -6
  47. package/dist/background/poll.job.js +30 -22
  48. package/dist/background/session.d.ts +13 -2
  49. package/dist/background/session.js +13 -0
  50. package/dist/background/stop.d.ts +12 -6
  51. package/dist/background/stop.js +57 -39
  52. package/dist/background/store.d.ts +18 -6
  53. package/dist/background/store.js +12 -6
  54. package/dist/background/tasks.service.d.ts +15 -5
  55. package/dist/background/tasks.service.js +42 -17
  56. package/dist/background/wake-rules.d.ts +27 -18
  57. package/dist/background/wake-rules.js +52 -22
  58. package/dist/background/wake.d.ts +13 -11
  59. package/dist/background/wake.js +20 -14
  60. package/dist/catalog/admin-catalog.controller.d.ts +129 -30
  61. package/dist/catalog/admin-catalog.controller.js +213 -42
  62. package/dist/catalog/catalog-content.d.ts +58 -32
  63. package/dist/catalog/catalog-content.js +34 -8
  64. package/dist/catalog/catalog-import.module.d.ts +7 -0
  65. package/dist/catalog/catalog-import.module.js +60 -0
  66. package/dist/catalog/catalog-items.d.ts +111 -7
  67. package/dist/catalog/catalog-items.js +279 -13
  68. package/dist/catalog/catalog-scope.service.d.ts +260 -0
  69. package/dist/catalog/catalog-scope.service.js +1116 -0
  70. package/dist/catalog/catalog.module.d.ts +7 -9
  71. package/dist/catalog/catalog.module.js +41 -31
  72. package/dist/catalog/catalog.service.d.ts +101 -29
  73. package/dist/catalog/catalog.service.js +104 -106
  74. package/dist/catalog/cli.d.ts +11 -1
  75. package/dist/catalog/cli.js +26 -1
  76. package/dist/catalog/component-promotion.d.ts +96 -0
  77. package/dist/catalog/component-promotion.js +395 -0
  78. package/dist/catalog/component-scope.controller.d.ts +152 -0
  79. package/dist/catalog/component-scope.controller.js +287 -0
  80. package/dist/catalog/component-scope.service.d.ts +303 -0
  81. package/dist/catalog/component-scope.service.js +936 -0
  82. package/dist/catalog/component-state.d.ts +174 -0
  83. package/dist/catalog/component-state.js +437 -0
  84. package/dist/catalog/job-ids.d.ts +30 -0
  85. package/dist/catalog/job-ids.js +25 -0
  86. package/dist/catalog/marketplace-fetch.d.ts +1 -1
  87. package/dist/catalog/marketplaces.controller.d.ts +22 -5
  88. package/dist/catalog/marketplaces.controller.js +56 -7
  89. package/dist/catalog/marketplaces.service.d.ts +54 -14
  90. package/dist/catalog/marketplaces.service.js +71 -22
  91. package/dist/catalog/org-catalog.controller.d.ts +125 -34
  92. package/dist/catalog/org-catalog.controller.js +181 -65
  93. package/dist/catalog/org-catalog.service.d.ts +65 -33
  94. package/dist/catalog/org-catalog.service.js +324 -157
  95. package/dist/catalog/org-extension-switch.d.ts +41 -0
  96. package/dist/catalog/org-extension-switch.js +115 -0
  97. package/dist/catalog/org-extension.controller.d.ts +119 -0
  98. package/dist/catalog/org-extension.controller.js +266 -0
  99. package/dist/catalog/org-plugin-uploads.controller.d.ts +98 -0
  100. package/dist/catalog/org-plugin-uploads.controller.js +213 -0
  101. package/dist/catalog/org-plugin-uploads.d.ts +63 -0
  102. package/dist/catalog/org-plugin-uploads.js +116 -0
  103. package/dist/catalog/owned-items.d.ts +184 -0
  104. package/dist/catalog/owned-items.js +789 -0
  105. package/dist/catalog/owned-plugin-cleanup.d.ts +56 -0
  106. package/dist/catalog/owned-plugin-cleanup.js +194 -0
  107. package/dist/catalog/ownership.d.ts +172 -0
  108. package/dist/catalog/ownership.js +326 -0
  109. package/dist/catalog/platform-components.d.ts +221 -0
  110. package/dist/catalog/platform-components.js +761 -0
  111. package/dist/catalog/platform-migration.d.ts +115 -0
  112. package/dist/catalog/platform-migration.js +582 -0
  113. package/dist/catalog/plugin-import.d.ts +178 -34
  114. package/dist/catalog/plugin-import.js +622 -82
  115. package/dist/catalog/plugin-install.d.ts +185 -41
  116. package/dist/catalog/plugin-install.js +758 -126
  117. package/dist/catalog/plugin-upgrade.d.ts +260 -225
  118. package/dist/catalog/plugin-upgrade.js +1147 -1136
  119. package/dist/catalog/request-rules.d.ts +65 -0
  120. package/dist/catalog/request-rules.js +217 -0
  121. package/dist/catalog/requests.service.d.ts +193 -118
  122. package/dist/catalog/requests.service.js +526 -343
  123. package/dist/catalog/reserved-names.d.ts +8 -0
  124. package/dist/catalog/reserved-names.js +42 -0
  125. package/dist/catalog/scope-orgs.d.ts +21 -0
  126. package/dist/catalog/scope-orgs.js +67 -0
  127. package/dist/catalog/scope-state.d.ts +35 -0
  128. package/dist/catalog/scope-state.js +87 -0
  129. package/dist/catalog/scope-sync-workers.d.ts +7 -0
  130. package/dist/catalog/scope-sync-workers.js +29 -0
  131. package/dist/catalog/scope-sync.d.ts +176 -0
  132. package/dist/catalog/scope-sync.js +576 -0
  133. package/dist/catalog/scope.d.ts +42 -0
  134. package/dist/catalog/scope.js +42 -0
  135. package/dist/catalog/unshare.d.ts +22 -0
  136. package/dist/catalog/unshare.js +118 -0
  137. package/dist/channels/actions.js +1 -0
  138. package/dist/channels/cards.js +20 -2
  139. package/dist/channels/channels.module.js +2 -0
  140. package/dist/channels/inbound.d.ts +9 -1
  141. package/dist/channels/inbound.js +67 -5
  142. package/dist/channels/phrases.d.ts +35 -0
  143. package/dist/channels/phrases.js +29 -0
  144. package/dist/config/docs.js +3 -1
  145. package/dist/config/schema.d.ts +10 -2
  146. package/dist/config/schema.js +70 -22
  147. package/dist/conversations/access.d.ts +6 -4
  148. package/dist/conversations/access.js +27 -5
  149. package/dist/conversations/agent-tree.d.ts +46 -0
  150. package/dist/conversations/agent-tree.js +92 -0
  151. package/dist/conversations/conversations.controller.d.ts +43 -18
  152. package/dist/conversations/conversations.controller.js +79 -38
  153. package/dist/conversations/conversations.module.d.ts +1 -1
  154. package/dist/conversations/conversations.module.js +7 -7
  155. package/dist/conversations/conversations.service.d.ts +73 -15
  156. package/dist/conversations/conversations.service.js +115 -35
  157. package/dist/conversations/environment-status.d.ts +24 -0
  158. package/dist/conversations/environment-status.js +71 -0
  159. package/dist/conversations/event-log.d.ts +20 -5
  160. package/dist/conversations/event-log.js +60 -0
  161. package/dist/conversations/events.d.ts +84 -2
  162. package/dist/conversations/events.js +91 -17
  163. package/dist/conversations/queue.service.d.ts +1 -1
  164. package/dist/conversations/queue.service.js +5 -0
  165. package/dist/conversations/titles.d.ts +5 -3
  166. package/dist/conversations/titles.js +21 -8
  167. package/dist/conversations/tree.d.ts +17 -0
  168. package/dist/conversations/tree.js +42 -0
  169. package/dist/ctx/create-ctx.d.ts +20 -1
  170. package/dist/ctx/create-ctx.js +38 -7
  171. package/dist/db/kernel-schema.d.ts +386 -18
  172. package/dist/environments/access.d.ts +41 -0
  173. package/dist/environments/access.js +77 -0
  174. package/dist/environments/conversation-environments.d.ts +61 -0
  175. package/dist/environments/conversation-environments.js +170 -0
  176. package/dist/environments/dto.d.ts +25 -0
  177. package/dist/environments/dto.js +12 -0
  178. package/dist/environments/environments.controller.d.ts +33 -0
  179. package/dist/environments/environments.controller.js +110 -0
  180. package/dist/environments/environments.module.d.ts +8 -0
  181. package/dist/environments/environments.module.js +27 -0
  182. package/dist/environments/environments.service.d.ts +153 -0
  183. package/dist/environments/environments.service.js +541 -0
  184. package/dist/environments/legacy-cleanup.job.d.ts +34 -0
  185. package/dist/environments/legacy-cleanup.job.js +141 -0
  186. package/dist/errors.d.ts +85 -2
  187. package/dist/errors.js +85 -2
  188. package/dist/evals/reconstruct.d.ts +18 -9
  189. package/dist/evals/reconstruct.js +26 -7
  190. package/dist/evals/run-replay.d.ts +4 -2
  191. package/dist/evals/run-replay.js +20 -6
  192. package/dist/evals/runs.service.d.ts +2 -1
  193. package/dist/evals/runs.service.js +13 -12
  194. package/dist/evals/step-replay.d.ts +4 -6
  195. package/dist/evals/step-replay.js +4 -3
  196. package/dist/evals/trajectory.service.d.ts +8 -3
  197. package/dist/evals/trajectory.service.js +26 -14
  198. package/dist/evals/worker.d.ts +5 -5
  199. package/dist/evals/worker.js +9 -3
  200. package/dist/extensions/admin-ops.d.ts +36 -10
  201. package/dist/extensions/admin-ops.js +65 -42
  202. package/dist/extensions/admin-view.d.ts +37 -10
  203. package/dist/extensions/admin-view.js +103 -20
  204. package/dist/extensions/bootstrap.d.ts +17 -4
  205. package/dist/extensions/bootstrap.js +70 -9
  206. package/dist/extensions/cli.d.ts +12 -0
  207. package/dist/extensions/cli.js +11 -2
  208. package/dist/extensions/config-hash.d.ts +10 -0
  209. package/dist/extensions/config-hash.js +38 -0
  210. package/dist/extensions/deployment-config.d.ts +28 -5
  211. package/dist/extensions/deployment-config.js +48 -7
  212. package/dist/extensions/effective-config.d.ts +127 -0
  213. package/dist/extensions/effective-config.js +368 -0
  214. package/dist/extensions/extensions.module.js +11 -11
  215. package/dist/extensions/hooks.d.ts +37 -4
  216. package/dist/extensions/hooks.js +82 -16
  217. package/dist/extensions/host.d.ts +24 -10
  218. package/dist/extensions/host.js +49 -54
  219. package/dist/extensions/installs.d.ts +20 -8
  220. package/dist/extensions/installs.js +37 -15
  221. package/dist/extensions/org-config.d.ts +75 -6
  222. package/dist/extensions/org-config.js +184 -32
  223. package/dist/extensions/org-levels.d.ts +37 -0
  224. package/dist/extensions/org-levels.js +71 -0
  225. package/dist/extensions/org-overrides.d.ts +151 -0
  226. package/dist/extensions/org-overrides.js +524 -0
  227. package/dist/extensions/permission-view.d.ts +16 -4
  228. package/dist/extensions/permission-view.js +4 -4
  229. package/dist/extensions/plugin-items.d.ts +21 -0
  230. package/dist/extensions/plugin-items.js +42 -0
  231. package/dist/extensions/point-defaults.d.ts +12 -5
  232. package/dist/extensions/point-defaults.js +37 -9
  233. package/dist/extensions/resolve.d.ts +5 -1
  234. package/dist/extensions/resolve.js +15 -2
  235. package/dist/extensions/state.module.d.ts +9 -0
  236. package/dist/extensions/state.module.js +38 -0
  237. package/dist/files/previewers.d.ts +8 -1
  238. package/dist/files/previewers.js +35 -6
  239. package/dist/http/api.module.js +25 -3
  240. package/dist/http/app.d.ts +11 -2
  241. package/dist/http/app.js +31 -5
  242. package/dist/http/plugin-dispatch.d.ts +4 -1
  243. package/dist/http/plugin-dispatch.js +14 -2
  244. package/dist/identity/accounts.d.ts +29 -29
  245. package/dist/identity/accounts.js +47 -47
  246. package/dist/identity/audit.d.ts +2 -1
  247. package/dist/identity/auth.guard.d.ts +13 -5
  248. package/dist/identity/auth.guard.js +26 -9
  249. package/dist/identity/identity.module.d.ts +1 -1
  250. package/dist/identity/identity.module.js +4 -4
  251. package/dist/identity/me.controller.js +1 -1
  252. package/dist/identity/principal.d.ts +3 -3
  253. package/dist/identity/principal.js +3 -3
  254. package/dist/identity/settings.d.ts +22 -11
  255. package/dist/identity/settings.js +53 -18
  256. package/dist/identity/{enterprise-admin.d.ts → super-admin.d.ts} +5 -5
  257. package/dist/identity/{enterprise-admin.js → super-admin.js} +24 -24
  258. package/dist/inbox/inbox.module.d.ts +4 -1
  259. package/dist/inbox/inbox.module.js +7 -3
  260. package/dist/inbox/inbox.service.d.ts +62 -3
  261. package/dist/inbox/inbox.service.js +74 -4
  262. package/dist/inbox/org-notices.d.ts +63 -0
  263. package/dist/inbox/org-notices.js +91 -0
  264. package/dist/inbox/platform-inbox.controller.d.ts +23 -0
  265. package/dist/inbox/platform-inbox.controller.js +58 -0
  266. package/dist/inbox/platform-inbox.service.d.ts +151 -0
  267. package/dist/inbox/platform-inbox.service.js +263 -0
  268. package/dist/inbox/platform-notices.d.ts +19 -0
  269. package/dist/inbox/platform-notices.js +9 -0
  270. package/dist/index.d.ts +1 -1
  271. package/dist/index.js +1 -1
  272. package/dist/infra/cli/kernel-cli.module.js +9 -1
  273. package/dist/infra/config/kernel-config.service.js +24 -1
  274. package/dist/infra/database/xact-lock.d.ts +1 -1
  275. package/dist/infra/database/xact-lock.js +1 -1
  276. package/dist/infra/events/kernel-events.d.ts +19 -2
  277. package/dist/infra/queue/add-job-once.d.ts +14 -0
  278. package/dist/infra/queue/add-job-once.js +16 -0
  279. package/dist/kernel.module.js +6 -0
  280. package/dist/lifecycle/kernel-lifecycle.d.ts +1 -1
  281. package/dist/lifecycle/kernel-lifecycle.js +4 -4
  282. package/dist/models/embeddings.d.ts +82 -0
  283. package/dist/models/embeddings.js +326 -0
  284. package/dist/models/enablement.controller.d.ts +40 -0
  285. package/dist/models/enablement.controller.js +74 -0
  286. package/dist/models/enablement.d.ts +99 -0
  287. package/dist/models/enablement.js +263 -0
  288. package/dist/models/models.module.d.ts +5 -1
  289. package/dist/models/models.module.js +16 -4
  290. package/dist/models/prices.d.ts +5 -5
  291. package/dist/models/prices.js +4 -4
  292. package/dist/models/purposes.controller.d.ts +6 -4
  293. package/dist/models/purposes.controller.js +13 -7
  294. package/dist/models/purposes.d.ts +37 -12
  295. package/dist/models/purposes.js +63 -17
  296. package/dist/orgs/directory-sync.d.ts +14 -5
  297. package/dist/orgs/directory-sync.js +41 -17
  298. package/dist/orgs/offboarding.d.ts +9 -7
  299. package/dist/orgs/offboarding.js +28 -17
  300. package/dist/orgs/org-lock.d.ts +5 -0
  301. package/dist/orgs/org-lock.js +13 -0
  302. package/dist/orgs/org.guard.d.ts +10 -0
  303. package/dist/orgs/org.guard.js +43 -32
  304. package/dist/orgs/orgs.module.js +3 -0
  305. package/dist/orgs/orgs.service.d.ts +20 -7
  306. package/dist/orgs/orgs.service.js +32 -12
  307. package/dist/orgs/roles.d.ts +1 -1
  308. package/dist/orgs/roles.js +5 -1
  309. package/dist/orgs/settings.controller.d.ts +1 -1
  310. package/dist/orgs/settings.service.d.ts +15 -3
  311. package/dist/orgs/settings.service.js +6 -2
  312. package/dist/overrides.d.ts +3 -0
  313. package/dist/overrides.js +2 -0
  314. package/dist/platform/actor.d.ts +48 -0
  315. package/dist/platform/actor.js +100 -0
  316. package/dist/platform/agent-docs.d.ts +18 -0
  317. package/dist/platform/agent-docs.js +59 -0
  318. package/dist/platform/availability.d.ts +14 -0
  319. package/dist/platform/availability.js +43 -0
  320. package/dist/platform/errors.d.ts +11 -0
  321. package/dist/platform/errors.js +26 -0
  322. package/dist/platform/exclusions.d.ts +12 -0
  323. package/dist/platform/exclusions.js +1405 -0
  324. package/dist/platform/method.d.ts +6 -0
  325. package/dist/platform/method.js +15 -0
  326. package/dist/platform/operation.d.ts +92 -0
  327. package/dist/platform/operation.js +35 -0
  328. package/dist/platform/ops/agent-templates.ops.d.ts +14 -0
  329. package/dist/platform/ops/agent-templates.ops.js +92 -0
  330. package/dist/platform/ops/agents.ops.d.ts +19 -0
  331. package/dist/platform/ops/agents.ops.js +294 -0
  332. package/dist/platform/ops/connectors.ops.d.ts +15 -0
  333. package/dist/platform/ops/connectors.ops.js +126 -0
  334. package/dist/platform/ops/errors.d.ts +11 -0
  335. package/dist/platform/ops/errors.js +22 -0
  336. package/dist/platform/ops/extensions.ops.d.ts +19 -0
  337. package/dist/platform/ops/extensions.ops.js +116 -0
  338. package/dist/platform/ops/marketplaces.ops.d.ts +16 -0
  339. package/dist/platform/ops/marketplaces.ops.js +157 -0
  340. package/dist/platform/ops/paging.d.ts +14 -0
  341. package/dist/platform/ops/paging.js +20 -0
  342. package/dist/platform/ops/platform.ops.d.ts +23 -0
  343. package/dist/platform/ops/platform.ops.js +158 -0
  344. package/dist/platform/ops/plugins.ops.d.ts +33 -0
  345. package/dist/platform/ops/plugins.ops.js +377 -0
  346. package/dist/platform/ops/requests.ops.d.ts +14 -0
  347. package/dist/platform/ops/requests.ops.js +153 -0
  348. package/dist/platform/ops/role.d.ts +4 -0
  349. package/dist/platform/ops/role.js +10 -0
  350. package/dist/platform/ops/skills.ops.d.ts +13 -0
  351. package/dist/platform/ops/skills.ops.js +98 -0
  352. package/dist/platform/ops/summary.d.ts +10 -0
  353. package/dist/platform/ops/summary.js +18 -0
  354. package/dist/platform/platform-ops.module.d.ts +7 -0
  355. package/dist/platform/platform-ops.module.js +55 -0
  356. package/dist/platform/platform.module.d.ts +8 -0
  357. package/dist/platform/platform.module.js +25 -0
  358. package/dist/platform/redact-orgs.d.ts +7 -0
  359. package/dist/platform/redact-orgs.js +52 -0
  360. package/dist/platform/registry.d.ts +30 -0
  361. package/dist/platform/registry.js +111 -0
  362. package/dist/roles/worker-role.d.ts +6 -4
  363. package/dist/roles/worker-role.js +14 -7
  364. package/dist/roles/worker.module.d.ts +1 -1
  365. package/dist/roles/worker.module.js +9 -1
  366. package/dist/runtime/context/build.d.ts +6 -4
  367. package/dist/runtime/context/build.js +26 -7
  368. package/dist/runtime/context/claude-tools.d.ts +2 -1
  369. package/dist/runtime/context/claude-tools.js +5 -4
  370. package/dist/runtime/context/compaction.js +9 -0
  371. package/dist/runtime/context/reminders.d.ts +2 -0
  372. package/dist/runtime/context/reminders.js +2 -0
  373. package/dist/runtime/context/skills.js +9 -2
  374. package/dist/runtime/context/tool-changes.d.ts +27 -0
  375. package/dist/runtime/context/tool-changes.js +60 -0
  376. package/dist/runtime/hook-calls.d.ts +8 -1
  377. package/dist/runtime/hook-calls.js +40 -7
  378. package/dist/runtime/langgraph-loop.d.ts +3 -1
  379. package/dist/runtime/langgraph-loop.js +35 -17
  380. package/dist/runtime/loop.d.ts +32 -4
  381. package/dist/runtime/maintenance.d.ts +7 -4
  382. package/dist/runtime/maintenance.js +23 -8
  383. package/dist/runtime/model-call.d.ts +38 -11
  384. package/dist/runtime/model-call.js +97 -24
  385. package/dist/runtime/providers.d.ts +146 -32
  386. package/dist/runtime/providers.js +321 -67
  387. package/dist/runtime/run-control.d.ts +11 -1
  388. package/dist/runtime/run-control.js +12 -0
  389. package/dist/runtime/run-drafts.d.ts +85 -0
  390. package/dist/runtime/run-drafts.js +230 -0
  391. package/dist/runtime/run-jobs.d.ts +3 -5
  392. package/dist/runtime/run-jobs.js +3 -7
  393. package/dist/runtime/run-queue.d.ts +37 -3
  394. package/dist/runtime/run-queue.js +188 -11
  395. package/dist/runtime/run-worker.d.ts +12 -6
  396. package/dist/runtime/run-worker.js +58 -35
  397. package/dist/runtime/runtime.module.js +3 -0
  398. package/dist/runtime/step-log.d.ts +9 -4
  399. package/dist/runtime/step-log.js +8 -5
  400. package/dist/runtime/stream.controller.d.ts +23 -1
  401. package/dist/runtime/stream.controller.js +60 -3
  402. package/dist/runtime/stream.d.ts +4 -1
  403. package/dist/runtime/stream.js +27 -3
  404. package/dist/runtime/subagents/child.d.ts +55 -7
  405. package/dist/runtime/subagents/child.js +105 -7
  406. package/dist/runtime/subagents/definition.d.ts +12 -3
  407. package/dist/runtime/subagents/definition.js +46 -32
  408. package/dist/runtime/subagents/deliveries.d.ts +71 -0
  409. package/dist/runtime/subagents/deliveries.js +228 -0
  410. package/dist/runtime/subagents/dispatch.d.ts +115 -26
  411. package/dist/runtime/subagents/dispatch.js +212 -141
  412. package/dist/runtime/subagents/limits.d.ts +24 -5
  413. package/dist/runtime/subagents/limits.js +40 -6
  414. package/dist/runtime/subagents/messages.d.ts +95 -0
  415. package/dist/runtime/subagents/messages.js +328 -0
  416. package/dist/runtime/subagents/preamble.d.ts +4 -4
  417. package/dist/runtime/subagents/preamble.js +9 -7
  418. package/dist/runtime/subagents/progress.d.ts +8 -6
  419. package/dist/runtime/subagents/progress.js +11 -6
  420. package/dist/runtime/subagents/render.d.ts +30 -0
  421. package/dist/runtime/subagents/render.js +53 -0
  422. package/dist/runtime/subagents/roster.d.ts +24 -7
  423. package/dist/runtime/subagents/roster.js +47 -11
  424. package/dist/runtime/subagents/skill-fork.d.ts +3 -2
  425. package/dist/runtime/subagents/skill-fork.js +8 -4
  426. package/dist/runtime/subagents/status.d.ts +14 -0
  427. package/dist/runtime/subagents/status.js +23 -0
  428. package/dist/runtime/subagents/subagents.service.d.ts +7 -4
  429. package/dist/runtime/subagents/subagents.service.js +11 -6
  430. package/dist/runtime/usage-report-jobs.d.ts +88 -0
  431. package/dist/runtime/usage-report-jobs.js +158 -0
  432. package/dist/runtime/usage-report.d.ts +33 -38
  433. package/dist/runtime/usage-report.js +169 -96
  434. package/dist/runtime/waits.d.ts +140 -37
  435. package/dist/runtime/waits.js +394 -106
  436. package/dist/sandbox/jobs.d.ts +40 -13
  437. package/dist/sandbox/jobs.js +57 -20
  438. package/dist/sandbox/leases.d.ts +37 -54
  439. package/dist/sandbox/leases.js +71 -115
  440. package/dist/sandbox/providers.d.ts +2 -2
  441. package/dist/sandbox/providers.js +1 -1
  442. package/dist/sandbox/sandbox.module.d.ts +3 -2
  443. package/dist/sandbox/sandbox.module.js +4 -3
  444. package/dist/sandbox/sandbox.service.d.ts +229 -134
  445. package/dist/sandbox/sandbox.service.js +630 -409
  446. package/dist/skills/catalog.d.ts +3 -2
  447. package/dist/skills/catalog.js +21 -43
  448. package/dist/skills/changes.controller.d.ts +7 -0
  449. package/dist/skills/changes.controller.js +19 -1
  450. package/dist/skills/invoke.js +8 -3
  451. package/dist/skills/package.d.ts +20 -1
  452. package/dist/skills/package.js +28 -1
  453. package/dist/skills/skills.controller.d.ts +39 -4
  454. package/dist/skills/skills.controller.js +88 -10
  455. package/dist/skills/skills.module.js +10 -1
  456. package/dist/skills/skills.service.d.ts +106 -26
  457. package/dist/skills/skills.service.js +421 -75
  458. package/dist/skills/usable.d.ts +81 -0
  459. package/dist/skills/usable.js +379 -0
  460. package/dist/tools/approvals.service.d.ts +20 -2
  461. package/dist/tools/approvals.service.js +23 -4
  462. package/dist/tools/builtin-names.d.ts +21 -5
  463. package/dist/tools/builtin-names.js +30 -5
  464. package/dist/tools/builtins/agent.d.ts +23 -21
  465. package/dist/tools/builtins/agent.js +62 -55
  466. package/dist/tools/builtins/builtin-tools.d.ts +6 -2
  467. package/dist/tools/builtins/builtin-tools.js +37 -12
  468. package/dist/tools/builtins/handback.d.ts +28 -0
  469. package/dist/tools/builtins/handback.js +53 -0
  470. package/dist/tools/builtins/platform.d.ts +34 -0
  471. package/dist/tools/builtins/platform.js +362 -0
  472. package/dist/tools/builtins/sandbox/bash.js +13 -3
  473. package/dist/tools/builtins/sandbox/common.d.ts +43 -24
  474. package/dist/tools/builtins/sandbox/common.js +80 -45
  475. package/dist/tools/builtins/sandbox/edit.js +2 -2
  476. package/dist/tools/builtins/sandbox/glob.js +2 -2
  477. package/dist/tools/builtins/sandbox/grep.js +2 -4
  478. package/dist/tools/builtins/sandbox/index.d.ts +1 -1
  479. package/dist/tools/builtins/sandbox/index.js +1 -1
  480. package/dist/tools/builtins/sandbox/read.js +1 -1
  481. package/dist/tools/builtins/sandbox/task-output.d.ts +14 -3
  482. package/dist/tools/builtins/sandbox/task-output.js +30 -5
  483. package/dist/tools/builtins/sandbox/task-stop.js +2 -1
  484. package/dist/tools/builtins/sandbox/write.js +2 -2
  485. package/dist/tools/builtins/send-message.d.ts +56 -0
  486. package/dist/tools/builtins/send-message.js +100 -0
  487. package/dist/tools/builtins/skill-load.d.ts +22 -14
  488. package/dist/tools/builtins/skill-load.js +86 -57
  489. package/dist/tools/builtins/skill-write.js +1 -1
  490. package/dist/tools/builtins/web/extract.js +5 -1
  491. package/dist/tools/builtins/web/fetch.js +1 -0
  492. package/dist/tools/builtins/web/search.js +1 -0
  493. package/dist/tools/connectors.controller.d.ts +10 -0
  494. package/dist/tools/connectors.controller.js +12 -0
  495. package/dist/tools/connectors.service.d.ts +46 -5
  496. package/dist/tools/connectors.service.js +94 -15
  497. package/dist/tools/extension-tools.controller.d.ts +14 -0
  498. package/dist/tools/extension-tools.controller.js +37 -0
  499. package/dist/tools/info.d.ts +42 -1
  500. package/dist/tools/info.js +64 -1
  501. package/dist/tools/org-tool-switches.d.ts +74 -0
  502. package/dist/tools/org-tool-switches.js +184 -0
  503. package/dist/tools/pipeline.d.ts +46 -40
  504. package/dist/tools/pipeline.js +193 -364
  505. package/dist/tools/policy.d.ts +1 -1
  506. package/dist/tools/policy.js +36 -16
  507. package/dist/tools/registry.d.ts +98 -5
  508. package/dist/tools/registry.js +87 -9
  509. package/dist/tools/tools.module.js +12 -2
  510. package/dist/ui/views.d.ts +2 -1
  511. package/dist/ui/views.js +17 -3
  512. package/package.json +3 -3
  513. package/src/migrations/0074_subagent_tree.sql +50 -0
  514. package/src/migrations/0075_plugin_scope.sql +61 -0
  515. package/src/migrations/0076_skills_created_by_nullable.sql +6 -0
  516. package/src/migrations/0077_scope_requests.sql +52 -0
  517. package/src/migrations/0078_scope_grant_switches.sql +18 -0
  518. package/src/migrations/0079_scope_live_install_switches.sql +19 -0
  519. package/src/migrations/0080_rename_enterprise_admin.sql +18 -0
  520. package/src/migrations/0081_platform_components.sql +129 -0
  521. package/src/migrations/0082_platform_migration.sql +33 -0
  522. package/src/migrations/0083_plugin_scope_sync_failures.sql +15 -0
  523. package/src/migrations/0084_org_owned_items.sql +85 -0
  524. package/src/migrations/0085_agent_templates_phase4.sql +45 -0
  525. package/src/migrations/0086_org_layering.sql +30 -0
  526. package/src/migrations/0087_approval_summary.sql +6 -0
  527. package/src/migrations/0088_environments.sql +80 -0
  528. package/src/migrations/0089_model_kinds_usage.sql +38 -0
  529. package/dist/catalog/upgrade-targets.d.ts +0 -56
  530. package/dist/catalog/upgrade-targets.js +0 -90
  531. package/dist/conversations/sandbox-status.d.ts +0 -24
  532. package/dist/conversations/sandbox-status.js +0 -52
  533. package/dist/extensions/org-config.controller.d.ts +0 -32
  534. package/dist/extensions/org-config.controller.js +0 -70
@@ -13,6 +13,7 @@ import { DelayedError } from "bullmq";
13
13
  import { sql } from "kysely";
14
14
  import { BackgroundTaskStopper } from "../background/stop.js";
15
15
  import { EventLog } from "../conversations/event-log.js";
16
+ import { conversationTree } from "../conversations/tree.js";
16
17
  import { KernelDb } from "../infra/database/kernel-db.js";
17
18
  import { TransactionHost } from "../infra/database/transaction-host.js";
18
19
  import { Transactional } from "../infra/database/transactional.decorator.js";
@@ -30,7 +31,8 @@ import { MAINTENANCE_QUEUE_NAME } from "./maintenance-queue.js";
30
31
  import { assistantIdemKey } from "./model-call.js";
31
32
  import { notifyFinished, RunFinish, TERMINAL_STATUSES } from "./run-finish.js";
32
33
  import { ACTIVE_RUN_STATUSES, RunQueue } from "./run-queue.js";
33
- import { childResult, dispatchOfChildRun, finishedEvent } from "./subagents/child.js";
34
+ import { childResult, deliveryRowOfChildRun, finishedEvent, rootSurfaceOf, } from "./subagents/child.js";
35
+ import { SubagentDeliveries } from "./subagents/deliveries.js";
34
36
  /** 等待超时任务所在的内核维护队列(见 maintenance.ts)。 */
35
37
  export { MAINTENANCE_QUEUE_NAME };
36
38
  /** 等待超时任务的名字与 jobId(每个审批 / 输入请求一个,重复投递被 BullMQ 忽略)。 */
@@ -70,8 +72,10 @@ let Waits = class Waits {
70
72
  checkpoints;
71
73
  abort;
72
74
  timeouts;
75
+ events;
73
76
  log;
74
77
  background;
78
+ deliveries;
75
79
  txHost;
76
80
  /** Drops the `run.orphaned` subscription (the events may outlive this instance). */
77
81
  unsubscribe;
@@ -92,7 +96,9 @@ let Waits = class Waits {
92
96
  /** The maintenance queue: wait timeout jobs (`MaintenanceProcessor` consumes them). */
93
97
  timeouts, events, log,
94
98
  /** Stops a finished sub-agent run's background tasks ({@link childFinished}). */
95
- background, txHost) {
99
+ background,
100
+ /** Delivers a background child's finish to its parent ({@link childFinished}). */
101
+ deliveries, txHost) {
96
102
  this.kdb = kdb;
97
103
  this.eventLog = eventLog;
98
104
  this.approvals = approvals;
@@ -103,11 +109,14 @@ let Waits = class Waits {
103
109
  this.checkpoints = checkpoints;
104
110
  this.abort = abort;
105
111
  this.timeouts = timeouts;
112
+ this.events = events;
106
113
  this.log = log;
107
114
  this.background = background;
115
+ this.deliveries = deliveries;
108
116
  this.txHost = txHost;
109
- // an orphaned parent run (marked failed by `ensureRun`) stops its children at once; the
110
- // sweep's `sweepChildrenOfFinished` is the backstop
117
+ // an orphaned parent run (marked failed by `ensureRun`) stops its fork child at once
118
+ // (background children keep running, agent map spec §5.4); the sweep's
119
+ // `sweepForkChildrenOfFinished` is the backstop
111
120
  this.unsubscribe = events.on("run.orphaned", ({ runId }) => this.stopChildren(runId, null)
112
121
  .then(() => { })
113
122
  .catch((err) => this.log.error("cannot stop the sub-agents of an orphaned run", { runId, err })));
@@ -135,12 +144,17 @@ let Waits = class Waits {
135
144
  requeued: 0,
136
145
  orphaned: 0,
137
146
  stopped: 0,
147
+ delivered: 0,
148
+ restarted: 0,
138
149
  };
139
150
  out.cancelled = await this.sweepFinishedRuns();
140
151
  out.expired = await this.sweepOverdue();
141
152
  Object.assign(out, await this.sweepSubagentOrphans());
142
153
  out.repaired = await this.sweepOpenAgentCalls();
143
- out.stopped = await this.sweepChildrenOfFinished();
154
+ out.stopped =
155
+ (await this.sweepForkChildrenOfFinished()) + (await this.sweepTreesOfDeletedRoots());
156
+ out.delivered = await this.sweepUndelivered();
157
+ out.restarted = await this.sweepParkedMessages();
144
158
  out.resumed = await this.sweepStuckRuns();
145
159
  return out;
146
160
  }
@@ -172,28 +186,26 @@ let Waits = class Waits {
172
186
  if (stop && (await this.abortWaiting(conversationId, runId, stop.byAccountId, stop.detail))) {
173
187
  return;
174
188
  }
175
- await this.surfaceInParent(runId, waitingFor);
189
+ await this.surfaceInRoot(runId, conversationId, waitingFor);
176
190
  await this.scheduleTimeout(waitingFor, runId);
177
191
  if (await this.isSettled(waitingFor, runId))
178
192
  await this.resume(runId, waitingFor.id);
179
193
  }
180
194
  /**
181
195
  * A sub-agent's run waits for an approval or an input (sub-agents spec §9): appends
182
- * `subagent_waiting` to the parent conversation (idem `subagent_waiting:<childRunId>:<waitId>`),
183
- * so the web and the channel outbound show the card there. The approval or question itself stays
184
- * the child run's, with the parent run's starter as the person asked. Not a run of a sub-agent,
185
- * or a `subagents` wait: nothing. Display only: a failure is logged, the wait goes on.
196
+ * `subagent_waiting` to the **root** conversation of its tree, whatever its depth (agent map spec
197
+ * §7, {@link rootSurfaceOf}; idem `subagent_waiting:<childRunId>:<waitId>`), so the web and the
198
+ * channel outbound show the card where the person looks. The approval or question itself stays
199
+ * the child run's, with the run's trigger account (inherited down the chain) as the person asked.
200
+ * Not a run of a sub-agent, or a `subagents` wait: nothing. Display only: a failure is logged,
201
+ * the wait goes on.
186
202
  */
187
- async surfaceInParent(runId, waitingFor) {
203
+ async surfaceInRoot(runId, conversationId, waitingFor) {
188
204
  if (waitingFor.kind === "subagents")
189
205
  return;
190
206
  try {
191
- const d = await this.db
192
- .selectFrom("subagent_dispatches")
193
- .select(["parent_conversation_id", "parent_run_id", "child_conversation_id"])
194
- .where("child_run_id", "=", runId)
195
- .executeTakeFirst();
196
- if (!d)
207
+ const target = await rootSurfaceOf(this.db, conversationId, runId);
208
+ if (!target)
197
209
  return;
198
210
  const row = waitingFor.kind === "approval"
199
211
  ? await this.db
@@ -216,14 +228,15 @@ let Waits = class Waits {
216
228
  .executeTakeFirst();
217
229
  if (!row)
218
230
  return;
219
- await this.eventLog.append(d.parent_conversation_id, [
231
+ await this.eventLog.append(target.conversationId, [
220
232
  {
221
233
  type: "subagent_waiting",
222
- runId: d.parent_run_id,
234
+ runId: target.runId,
223
235
  idemKey: subagentWaitingIdemKey(runId, waitingFor.id),
224
236
  payload: {
225
- subagentId: d.child_conversation_id,
237
+ subagentId: conversationId,
226
238
  childRunId: runId,
239
+ path: target.path,
227
240
  kind: waitingFor.kind,
228
241
  ...(waitingFor.kind === "approval"
229
242
  ? {
@@ -238,7 +251,7 @@ let Waits = class Waits {
238
251
  ]);
239
252
  }
240
253
  catch (err) {
241
- this.log.error("cannot surface a sub-agent's wait in its parent", { runId, err });
254
+ this.log.error("cannot surface a sub-agent's wait in its root conversation", { runId, err });
242
255
  }
243
256
  }
244
257
  /**
@@ -267,12 +280,13 @@ let Waits = class Waits {
267
280
  .select(sql `1`.as("one"))
268
281
  .where("questions.run_id", "=", runId)
269
282
  .where("questions.status", "=", "pending"))))
270
- // sub-agents (spec §7.2): no child run of this run is still active, so a step waiting on
271
- // an approval and on sub-agents resumes once both are done, whichever finishes last
283
+ // a fork invocation's sub-agent (phase D; agent map spec §5.4: background `Agent`
284
+ // children never hold their parent run) is no longer active
272
285
  .where(({ not, exists, selectFrom }) => not(exists(selectFrom("subagent_dispatches as sd")
273
286
  .innerJoin("runs as cr", "cr.id", "sd.child_run_id")
274
287
  .select(sql `1`.as("one"))
275
288
  .where("sd.parent_run_id", "=", runId)
289
+ .where("sd.for_skill", "=", true)
276
290
  .where("cr.status", "in", ACTIVE_RUN_STATUSES))))
277
291
  .returning(["conversation_id"])
278
292
  .executeTakeFirst();
@@ -302,8 +316,8 @@ let Waits = class Waits {
302
316
  */
303
317
  async expire(kind, id, at) {
304
318
  if (kind === "subagents") {
305
- // A safety net (spec §7.2, §12): the children of that step still active are stopped; each
306
- // stopped child reports to the parent, and the last one resumes it. The resume tried here
319
+ // A safety net (spec §7.2, §12) of a fork invocation's wait: its child, still active, is
320
+ // stopped and reports to the parent, which then resumes. The resume tried here
307
321
  // covers a step whose children were all done already.
308
322
  if (!at) {
309
323
  this.log.warn("sub-agent wait timeout without its run; ignored", { id });
@@ -348,8 +362,8 @@ let Waits = class Waits {
348
362
  stopped?.fire();
349
363
  // a stopped sub-agent reports to its parent now, not at the next sweep (a no-op for other runs)
350
364
  await this.childFinished(runId).catch((err) => this.log.error("cannot report stopped sub-agent run", { runId, err }));
351
- // a stopped parent stops its children (spec §12), on the parent's behalf (no account: they
352
- // report "stopped with this run"); the wait sweep is the backstop
365
+ // a stopped run stops its fork child (spec §12), on its behalf (no account: it reports
366
+ // "stopped with this run"); background children keep running; the wait sweep is the backstop
353
367
  await this.stopChildren(runId, null).catch((err) => this.log.error("cannot stop the sub-agents of a run", { runId, err }));
354
368
  return true;
355
369
  }
@@ -401,7 +415,7 @@ let Waits = class Waits {
401
415
  if (typeof spec.step === "number")
402
416
  steps.add(spec.step);
403
417
  }
404
- // a parent waiting on sub-agents (spec §12): its open `Agent` calls get their results
418
+ // a run waiting on its fork invocation's sub-agent: the report (`pairStoppedForks`)
405
419
  const agents = await this.pipeline.stopOpenAgentCalls(runId);
406
420
  for (const step of agents.steps)
407
421
  steps.add(step);
@@ -543,9 +557,9 @@ let Waits = class Waits {
543
557
  }
544
558
  /**
545
559
  * Sub-agents waits past their `runs.wait_expires_at` (their timeout job was lost): expired the
546
- * way the timeout job would ({@link expire}: the step's active children stop as `timed out`, the
547
- * parent resumes once they are done). The step is the run's latest dispatch step: a waiting run
548
- * has active children only from the step it waits in. A run stays here until its children have
560
+ * way the timeout job would ({@link expire}: the fork invocation's active child stops as
561
+ * `timed out`, the parent resumes once it is done). Only fork invocations wait (agent map spec
562
+ * §5.4); their step is the run's fork dispatch step. A run stays here until its children have
549
563
  * stopped; a pass that neither stopped a child nor resumed the run is not counted.
550
564
  */
551
565
  async sweepOverdueSubagents() {
@@ -564,6 +578,7 @@ let Waits = class Waits {
564
578
  .selectFrom("subagent_dispatches")
565
579
  .select(sql `max(step)`.as("step"))
566
580
  .where("parent_run_id", "=", r.id)
581
+ .where("for_skill", "=", true)
567
582
  .executeTakeFirst();
568
583
  if (last?.step == null)
569
584
  continue;
@@ -642,33 +657,72 @@ let Waits = class Waits {
642
657
  return out;
643
658
  }
644
659
  /**
645
- * Finished parent runs (past the grace period, within the last day) with an `Agent` call that has
646
- * no `tool_result` (final review I3): a terminal path that skipped `stopOpenAgentCalls`, such as
647
- * an old replica's abort, would otherwise leave an unpaired tool call that every later request of
648
- * the conversation sends and providers refuse. Each is repaired under the conversation row lock
649
- * with the normal `stopOpenCalls` (a child that ended gives its result, an active one the
650
- * stopped text; idempotency keys make it safe against the regular paths); its active children
651
- * are then stopped by {@link sweepChildrenOfFinished}.
660
+ * Idle sub-agent conversations (no active run, not deleted) with a message newer than what they
661
+ * consumed, written past the grace period and within the last day: a `SendMessage` that reached a
662
+ * run after its last model call is started by that run's post-job `ensureRun`
663
+ * (`RunQueue.childWakeIn`), which a replica dying after the terminal commit skips. Re-derived with
664
+ * the same `ensureRun` (its rules decide: a paused root starts nothing). A sub-agent whose last
665
+ * run was stopped (`aborted`) can never start from a message, so it is left out here, and the
666
+ * newest conversations come first (active within the last day), so parked messages that cannot
667
+ * start never fill the batch. Returns how many runs started.
652
668
  */
653
- async sweepOpenAgentCalls() {
654
- const agentCalls = await this.db
655
- .selectFrom("subagent_dispatches as sd")
656
- .innerJoin("runs as pr", "pr.id", "sd.parent_run_id")
657
- .select(["sd.parent_run_id", "sd.parent_conversation_id"])
658
- .distinct()
659
- .where("pr.status", "in", TERMINAL_RUN_STATUSES)
660
- .where("pr.finished_at", "<", sql `now() - ${WAIT_SWEEP_GRACE_MS}::integer * interval '1 millisecond'`)
661
- .where("pr.finished_at", ">", sql `now() - interval '1 day'`)
662
- .where(({ not, exists, selectFrom }) => not(exists(selectFrom("conversation_events as e")
669
+ async sweepParkedMessages() {
670
+ const rows = await this.db
671
+ .selectFrom("conversations as c")
672
+ .select("c.id")
673
+ .where("c.kind", "=", "subagent")
674
+ .where("c.deleted_at", "is", null)
675
+ // every append bumps `updated_at`: a message of the last day implies it (an index-friendly
676
+ // bound before the event lookups)
677
+ .where("c.updated_at", ">", sql `now() - interval '1 day'`)
678
+ .where((eb) => sql `(
679
+ SELECT r.status FROM capybara.runs r WHERE r.conversation_id = ${eb.ref("c.id")}
680
+ ORDER BY r.created_at DESC, r.id DESC LIMIT 1
681
+ ) IS DISTINCT FROM 'aborted'`)
682
+ .where(({ exists, selectFrom }) => exists(selectFrom("conversation_events as e")
683
+ .select(sql `1`.as("one"))
684
+ .whereRef("e.conversation_id", "=", "c.id")
685
+ .where("e.type", "=", "user_message")
686
+ .whereRef("e.seq", ">", "c.consumed_seq")
687
+ .where("e.created_at", "<", sql `now() - ${WAIT_SWEEP_GRACE_MS}::integer * interval '1 millisecond'`)
688
+ .where("e.created_at", ">", sql `now() - interval '1 day'`)))
689
+ .where(({ not, exists, selectFrom }) => not(exists(selectFrom("runs as r")
663
690
  .select(sql `1`.as("one"))
664
- .whereRef("e.conversation_id", "=", "sd.parent_conversation_id")
665
- .where("e.idem_key", "=", sql `'tool_result:' || sd.parent_run_id || ':' || sd.parent_call_id`))))
666
- // a fork invocation's dispatch (phase D) has no tool call: the query below covers it
667
- .where(sql `NOT (sd.step = 0 AND sd.parent_call_id LIKE 'skill-%')`)
691
+ .whereRef("r.conversation_id", "=", "c.id")
692
+ .where("r.status", "in", ACTIVE_RUN_STATUSES))))
693
+ .orderBy("c.updated_at", "desc")
694
+ .orderBy("c.id")
668
695
  .limit(WAIT_SWEEP_BATCH)
669
696
  .execute();
670
- const forkRuns = await unreportedForkRuns(this.db);
671
- const runs = [...agentCalls, ...forkRuns].filter((r, i, all) => all.findIndex((x) => x.parent_run_id === r.parent_run_id) === i);
697
+ let n = 0;
698
+ for (const c of rows) {
699
+ try {
700
+ if ((await this.runQueue.ensureRun(c.id)) === null)
701
+ continue;
702
+ n++;
703
+ this.log.warn("wait sweep: started a sub-agent's parked message", { conversationId: c.id });
704
+ }
705
+ catch (err) {
706
+ this.log.error("wait sweep: cannot start a sub-agent's parked message", {
707
+ conversationId: c.id,
708
+ err,
709
+ });
710
+ }
711
+ }
712
+ return n;
713
+ }
714
+ /**
715
+ * Finished runs (past the grace period, within the last day) triggered by a fork invocation that
716
+ * has no report ({@link unreportedForkRuns}): a terminal path that skipped
717
+ * `stopOpenAgentCalls`, such as an old replica's abort, would otherwise leave a fork lead without
718
+ * its report. Each is repaired under the conversation row lock with the normal
719
+ * `stopOpenAgentCalls` (an ended child gives its result, an active one the stopped text;
720
+ * idempotency keys make it safe against the regular paths); an active fork child is then stopped
721
+ * by {@link sweepForkChildrenOfFinished}. An `Agent` call has its result from its dispatch (agent
722
+ * map spec §4.1).
723
+ */
724
+ async sweepOpenAgentCalls() {
725
+ const runs = await unreportedForkRuns(this.db);
672
726
  let total = 0;
673
727
  for (const r of runs) {
674
728
  try {
@@ -681,13 +735,13 @@ let Waits = class Waits {
681
735
  await this.eventLog.notify(r.parent_conversation_id, toSeq);
682
736
  fire();
683
737
  total++;
684
- this.log.warn("wait sweep: wrote missing agent results of a finished run", {
738
+ this.log.warn("wait sweep: wrote the missing fork report of a finished run", {
685
739
  runId: r.parent_run_id,
686
740
  conversationId: r.parent_conversation_id,
687
741
  });
688
742
  }
689
743
  catch (err) {
690
- this.log.error("wait sweep: cannot write missing agent results of a finished run", {
744
+ this.log.error("wait sweep: cannot write the missing fork report of a finished run", {
691
745
  runId: r.parent_run_id,
692
746
  err,
693
747
  });
@@ -719,16 +773,19 @@ let Waits = class Waits {
719
773
  return stopped.toSeq ?? null;
720
774
  }
721
775
  /**
722
- * Active sub-agent runs of a parent run that finished more than the grace period ago (spec §7.5,
723
- * §12: a parent's terminal state stops its children; this is the backstop) → stopped.
776
+ * Active fork sub-agent runs (phase D, `for_skill`) of a parent run that finished more than the
777
+ * grace period ago (§12: the run's terminal state stops its fork child and reports it stopped;
778
+ * this is the backstop) → stopped. Background `Agent` children of a finished run are the normal
779
+ * case and keep running (agent map spec §5.4).
724
780
  */
725
- async sweepChildrenOfFinished() {
781
+ async sweepForkChildrenOfFinished() {
726
782
  const parents = await this.db
727
783
  .selectFrom("subagent_dispatches as sd")
728
784
  .innerJoin("runs as cr", "cr.id", "sd.child_run_id")
729
785
  .innerJoin("runs as pr", "pr.id", "sd.parent_run_id")
730
786
  .select("sd.parent_run_id")
731
787
  .distinct()
788
+ .where("sd.for_skill", "=", true)
732
789
  .where("cr.status", "in", ACTIVE_RUN_STATUSES)
733
790
  .where("pr.status", "in", TERMINAL_RUN_STATUSES)
734
791
  .where("pr.finished_at", "<", sql `now() - ${WAIT_SWEEP_GRACE_MS}::integer * interval '1 millisecond'`)
@@ -741,13 +798,13 @@ let Waits = class Waits {
741
798
  if (n === 0)
742
799
  continue;
743
800
  total += n;
744
- this.log.warn("wait sweep: stopped sub-agents of a finished run", {
801
+ this.log.warn("wait sweep: stopped the fork sub-agent of a finished run", {
745
802
  runId: p.parent_run_id,
746
803
  count: n,
747
804
  });
748
805
  }
749
806
  catch (err) {
750
- this.log.error("wait sweep: cannot stop sub-agents of a finished run", {
807
+ this.log.error("wait sweep: cannot stop the fork sub-agent of a finished run", {
751
808
  runId: p.parent_run_id,
752
809
  err,
753
810
  });
@@ -755,6 +812,109 @@ let Waits = class Waits {
755
812
  }
756
813
  return total;
757
814
  }
815
+ /**
816
+ * Active sub-agent runs with a deleted ancestor (agent map spec §10: deleting the root stops the
817
+ * whole tree; the delete's own {@link stopTree} is the normal path, this the backstop for a crash
818
+ * between marking the root deleted and stopping its tree, or a dispatch that raced it) → stopped
819
+ * on the deleter's behalf (no account). No grace period: nothing in a deleted tree should run.
820
+ */
821
+ async sweepTreesOfDeletedRoots() {
822
+ const r = await sql `
823
+ WITH RECURSIVE up(run_id, conversation_id, status, ancestor, n) AS (
824
+ SELECT r.id, r.conversation_id, r.status, c.parent_conversation_id, 1
825
+ FROM capybara.runs r JOIN capybara.conversations c ON c.id = r.conversation_id
826
+ WHERE r.status IN ('queued', 'running', 'waiting') AND c.kind = 'subagent'
827
+ AND c.parent_conversation_id IS NOT NULL
828
+ UNION ALL
829
+ SELECT up.run_id, up.conversation_id, up.status, c.parent_conversation_id, up.n + 1
830
+ FROM up JOIN capybara.conversations c ON c.id = up.ancestor
831
+ WHERE c.deleted_at IS NULL AND c.parent_conversation_id IS NOT NULL AND up.n < 16
832
+ )
833
+ SELECT DISTINCT up.run_id, up.conversation_id, up.status
834
+ FROM up JOIN capybara.conversations a ON a.id = up.ancestor
835
+ WHERE a.deleted_at IS NOT NULL
836
+ LIMIT ${WAIT_SWEEP_BATCH}`.execute(this.db);
837
+ let total = 0;
838
+ for (const run of r.rows) {
839
+ try {
840
+ // already asked to stop (a worker holds it and stops it at its next check): not again
841
+ if (run.status === "running" && (await this.abort.requested(run.run_id)) !== null)
842
+ continue;
843
+ await this.stopRun(run.conversation_id, run.run_id, run.status, null);
844
+ total++;
845
+ this.log.warn("wait sweep: stopped a sub-agent run of a deleted conversation's tree", {
846
+ runId: run.run_id,
847
+ });
848
+ }
849
+ catch (err) {
850
+ this.log.error("wait sweep: cannot stop a sub-agent run of a deleted tree", {
851
+ runId: run.run_id,
852
+ err,
853
+ });
854
+ }
855
+ }
856
+ return total;
857
+ }
858
+ /**
859
+ * Background sub-agent runs that finished more than the grace period ago (within the last day)
860
+ * whose parent has no `subagent_finished` for them (agent map spec §10: the finisher died after
861
+ * the child's terminal commit; the finish path writes `subagent_finished` and the delivery in one
862
+ * transaction) → {@link childFinished}, idempotent against a late finisher. Keyed on the child
863
+ * run, so a run nobody dispatched (a wake run, §5.3) is repaired too, and on
864
+ * `subagent_finished`, not on the delivery, so a child that finished before background
865
+ * dispatch (its result was the `Agent` call's, its `subagent_finished` written then) is never
866
+ * delivered a second time. Fork invocations' runs, a run without a terminal event in its log
867
+ * (nothing to deliver), a conversation never dispatched and a child whose parent conversation
868
+ * was deleted are skipped; only a written delivery counts.
869
+ */
870
+ async sweepUndelivered() {
871
+ const runs = await this.db
872
+ .selectFrom("runs as cr")
873
+ .innerJoin("conversations as cc", "cc.id", "cr.conversation_id")
874
+ .innerJoin("conversations as pc", "pc.id", "cc.parent_conversation_id")
875
+ .select("cr.id as child_run_id")
876
+ .where("cc.kind", "=", "subagent")
877
+ .where("pc.deleted_at", "is", null)
878
+ .where("cr.status", "in", TERMINAL_RUN_STATUSES)
879
+ .where("cr.finished_at", "<", sql `now() - ${WAIT_SWEEP_GRACE_MS}::integer * interval '1 millisecond'`)
880
+ .where("cr.finished_at", ">", sql `now() - interval '1 day'`)
881
+ .where(({ exists, selectFrom }) => exists(selectFrom("subagent_dispatches as sd")
882
+ .select(sql `1`.as("one"))
883
+ .whereRef("sd.child_conversation_id", "=", "cc.id")))
884
+ .where(({ not, exists, selectFrom }) => not(exists(selectFrom("subagent_dispatches as fd")
885
+ .select(sql `1`.as("one"))
886
+ .whereRef("fd.child_run_id", "=", "cr.id")
887
+ .where("fd.for_skill", "=", true))))
888
+ .where(({ not, exists, selectFrom }) => not(exists(selectFrom("conversation_events as e")
889
+ .select(sql `1`.as("one"))
890
+ .whereRef("e.conversation_id", "=", "pc.id")
891
+ .where("e.idem_key", "=", sql `'subagent_finished:' || cr.id`))))
892
+ .where(({ exists, selectFrom }) => exists(selectFrom("conversation_events as t")
893
+ .select(sql `1`.as("one"))
894
+ .whereRef("t.conversation_id", "=", "cc.id")
895
+ .whereRef("t.run_id", "=", "cr.id")
896
+ .where("t.type", "in", ["run_finished", "run_failed", "run_aborted"])))
897
+ .limit(WAIT_SWEEP_BATCH)
898
+ .execute();
899
+ let total = 0;
900
+ for (const r of runs) {
901
+ try {
902
+ if (!(await this.childFinished(r.child_run_id)))
903
+ continue;
904
+ total++;
905
+ this.log.warn("wait sweep: delivered the finish of a sub-agent run", {
906
+ childRunId: r.child_run_id,
907
+ });
908
+ }
909
+ catch (err) {
910
+ this.log.error("wait sweep: cannot deliver the finish of a sub-agent run", {
911
+ childRunId: r.child_run_id,
912
+ err,
913
+ });
914
+ }
915
+ }
916
+ return total;
917
+ }
758
918
  /**
759
919
  * 扫描 2:waiting 超过宽限期、却已没有 pending 等待的运行(决定提交后进程崩溃、续跑投递失败回滚等)→
760
920
  * {@link resume}(条件更新 `waiting → queued` + 投递)。续跑任务的 jobId 用该运行最近一次等待的 id
@@ -774,11 +934,12 @@ let Waits = class Waits {
774
934
  .select(sql `1`.as("one"))
775
935
  .whereRef("questions.run_id", "=", "runs.id")
776
936
  .where("questions.status", "=", "pending"))))
777
- // the resume condition's third clause: a parent with an active child is not stuck
937
+ // the resume condition's third clause: a run with an active fork child is not stuck
778
938
  .where(({ not, exists, selectFrom }) => not(exists(selectFrom("subagent_dispatches as sd")
779
939
  .innerJoin("runs as cr", "cr.id", "sd.child_run_id")
780
940
  .select(sql `1`.as("one"))
781
941
  .whereRef("sd.parent_run_id", "=", "runs.id")
942
+ .where("sd.for_skill", "=", true)
782
943
  .where("cr.status", "in", ACTIVE_RUN_STATUSES))))
783
944
  .limit(WAIT_SWEEP_BATCH)
784
945
  .execute();
@@ -802,8 +963,8 @@ let Waits = class Waits {
802
963
  return total;
803
964
  }
804
965
  /**
805
- * The id of the run's latest wait (by creation time): an approval, an input request or a
806
- * sub-agent dispatch, whose wait id is its child run id (the id the child's finisher resumes
966
+ * The id of the run's latest wait (by creation time): an approval, an input request or a fork
967
+ * invocation's dispatch, whose wait id is its child run id (the id the child's finisher resumes
807
968
  * with, so a sweep resume and a late finisher resume share one job id).
808
969
  */
809
970
  async lastWaitId(runId) {
@@ -819,7 +980,8 @@ let Waits = class Waits {
819
980
  .unionAll(this.db
820
981
  .selectFrom("subagent_dispatches")
821
982
  .select(["child_run_id as id", "created_at"])
822
- .where("parent_run_id", "=", runId))
983
+ .where("parent_run_id", "=", runId)
984
+ .where("for_skill", "=", true))
823
985
  .as("w"))
824
986
  .select("w.id")
825
987
  .orderBy("w.created_at", "desc")
@@ -861,7 +1023,7 @@ let Waits = class Waits {
861
1023
  }
862
1024
  /**
863
1025
  * Whether the wait is over: an approval or input request is no longer pending (decided, expired
864
- * or cancelled); `subagents`: no child run of the run is active.
1026
+ * or cancelled); `subagents`: the run's fork invocation child is no longer active.
865
1027
  */
866
1028
  async isSettled(w, runId) {
867
1029
  if (w.kind === "subagents") {
@@ -870,6 +1032,7 @@ let Waits = class Waits {
870
1032
  .innerJoin("runs as cr", "cr.id", "sd.child_run_id")
871
1033
  .select("cr.id")
872
1034
  .where("sd.parent_run_id", "=", runId)
1035
+ .where("sd.for_skill", "=", true)
873
1036
  .where("cr.status", "in", ACTIVE_RUN_STATUSES)
874
1037
  .executeTakeFirst();
875
1038
  return active === undefined;
@@ -935,45 +1098,86 @@ let Waits = class Waits {
935
1098
  return out;
936
1099
  }
937
1100
  /**
938
- * After a child run's terminal state committed (sub-agents spec §7.3): appends
939
- * `subagent_finished` to the parent log (idempotent; allowed while the parent waits, it is not
940
- * model-visible) and tries {@link resume}`(parentRunId, childRunId)`. Every finishing child tries;
941
- * the conditional resume lets exactly one succeed, the last to see all its siblings terminal. A
942
- * run that is not a dispatched child, or not terminal yet, is left alone. A crash in between is
943
- * repaired by the wait sweep and by the parent's tools node, which writes a missing
944
- * `subagent_finished` itself. The running background tasks the terminal child run started are
945
- * then stopped (not those of a later follow-up run of the same child).
1101
+ * After a child run's terminal state committed (sub-agents spec §7.3, agent map spec §4.5,
1102
+ * §5.2): a background child's run, whether dispatched, sent a message or woken
1103
+ * ({@link deliveryRowOfChildRun}), is delivered to its parent
1104
+ * ({@link SubagentDeliveries.childFinished}: `subagent_finished` and a `finished` delivery,
1105
+ * idempotent by the run); a fork invocation's child (phase D, `for_skill`) appends
1106
+ * `subagent_finished` (idempotent; not model-visible) and tries
1107
+ * {@link resume}`(parentRunId, childRunId)`, which succeeds once its parent run waits on nothing
1108
+ * else. A run of a conversation never dispatched, or not terminal yet, is left alone. A crash in
1109
+ * between is repaired by the wait sweep (the orphan repair calls this again). A fork child's
1110
+ * running background tasks the terminal run started are then stopped (not those of a later run);
1111
+ * a stopped background child's are all stopped, whichever of its runs started them; a background
1112
+ * child that ended on its own keeps them, and their finish wakes it (agent map spec §5.3). True
1113
+ * when a background child's finish was written by this call.
946
1114
  */
947
1115
  async childFinished(childRunId) {
948
- const row = await dispatchOfChildRun(this.db, childRunId);
1116
+ const row = await deliveryRowOfChildRun(this.db, childRunId);
949
1117
  if (!row)
950
- return;
1118
+ return false;
951
1119
  const run = await this.db
952
1120
  .selectFrom("runs")
953
1121
  .select("status")
954
1122
  .where("id", "=", childRunId)
955
1123
  .executeTakeFirst();
956
1124
  if (!run || !TERMINAL_STATUSES.has(run.status))
957
- return;
1125
+ return false;
1126
+ if (row.forSkill !== true) {
1127
+ try {
1128
+ return await this.deliveries.childFinished(childRunId);
1129
+ }
1130
+ finally {
1131
+ // a background child that ended on its own keeps its tasks: their finish wakes it (agent
1132
+ // map spec §5.3); a stopped one's tasks all stop with it, also those an earlier run of it
1133
+ // started, so none of them wakes it. Once a later run of it exists (a `SendMessage`
1134
+ // started it again before this late call), only the stopped run's own tasks stop: the
1135
+ // others may be the new run's. Never throws.
1136
+ if (run.status === "aborted") {
1137
+ const later = await this.hasLaterRun(row.childConversationId, childRunId);
1138
+ await this.background.stopSubagentTasks(row.childConversationId, later ? childRunId : undefined);
1139
+ }
1140
+ }
1141
+ }
958
1142
  try {
959
1143
  const r = await childResult(this.eventLog, row);
960
1144
  if (!r) {
961
1145
  this.log.warn("sub-agent run is terminal without a terminal event", { childRunId });
962
- return;
1146
+ return false;
963
1147
  }
964
1148
  await this.eventLog.append(row.parentConversationId, [finishedEvent(row, r.finished)]);
965
1149
  await this.resume(row.parentRunId, childRunId);
1150
+ return false;
966
1151
  }
967
1152
  finally {
968
- // whichever way the child run ended (its worker, a stop while waiting, an orphan repair):
969
- // nobody can read or stop the background tasks it started through its model any more
970
- // (background Bash spec §4.3). Never throws.
1153
+ // a fork child, whichever way its run ended (its worker, a stop while waiting, an orphan
1154
+ // repair): nobody reads or stops the background tasks that run started through its model
1155
+ // any more (background Bash spec §4.3); a background child's are handled above. Never throws.
971
1156
  await this.background.stopSubagentTasks(row.childConversationId, childRunId);
972
1157
  }
973
1158
  }
974
1159
  /**
975
- * Stops the active children of a parent run (sub-agents spec §12), or only those dispatched in
976
- * `opts.step`: a `waiting` child through its own {@link abortWaiting}, a `queued` / `running` one
1160
+ * Whether the conversation has an active run other than `runId`, or one created after it (a
1161
+ * sub-agent started again after `runId` ended).
1162
+ */
1163
+ async hasLaterRun(conversationId, runId) {
1164
+ const hit = await this.db
1165
+ .selectFrom("runs as r")
1166
+ .select("r.id")
1167
+ .where("r.conversation_id", "=", conversationId)
1168
+ .where("r.id", "<>", runId)
1169
+ .where((eb) => eb.or([
1170
+ eb("r.status", "in", ACTIVE_RUN_STATUSES),
1171
+ eb("r.created_at", ">", eb.selectFrom("runs as o").select("o.created_at").where("o.id", "=", runId)),
1172
+ ]))
1173
+ .limit(1)
1174
+ .executeTakeFirst();
1175
+ return hit !== undefined;
1176
+ }
1177
+ /**
1178
+ * Stops the active fork invocation child of a parent run (sub-agents spec §12, phase D;
1179
+ * `for_skill`), or only one dispatched in `opts.step`; background `Agent` children are never
1180
+ * stopped with the run that dispatched them (agent map spec §5.4, §6): a `waiting` child through its own {@link abortWaiting}, a `queued` / `running` one
977
1181
  * that no worker holds directly (`RunQueue.abortIfOrphaned`), any other through
978
1182
  * `RunAbort.request` (the cross-replica broadcast plus the marker key, so a child that starts
979
1183
  * later still sees it), after which a child found `waiting` is stopped through `abortWaiting`
@@ -990,36 +1194,119 @@ let Waits = class Waits {
990
1194
  .innerJoin("runs as cr", "cr.id", "sd.child_run_id")
991
1195
  .select(["sd.child_conversation_id", "sd.child_run_id", "cr.status"])
992
1196
  .where("sd.parent_run_id", "=", parentRunId)
1197
+ .where("sd.for_skill", "=", true)
993
1198
  .where("cr.status", "in", ACTIVE_RUN_STATUSES);
994
1199
  if (opts.step !== undefined)
995
1200
  q = q.where("sd.step", "=", opts.step);
996
1201
  const children = await q.execute();
997
1202
  for (const c of children) {
998
- const conv = c.child_conversation_id;
999
- const runId = c.child_run_id;
1000
- // abortWaiting reports the stopped child to the parent itself (childFinished)
1001
- if (c.status === "waiting" &&
1002
- (await this.abortWaiting(conv, runId, byAccountId, opts.detail))) {
1003
- continue;
1004
- }
1005
- if (await this.runQueue.abortIfOrphaned(conv, runId, byAccountId, opts.detail)) {
1006
- await this.childFinished(runId);
1007
- continue;
1203
+ await this.stopRun(c.child_conversation_id, c.child_run_id, c.status, byAccountId, opts.detail);
1204
+ }
1205
+ return children.length;
1206
+ }
1207
+ /**
1208
+ * Stops a sub-agent with its descendants (agent map spec §6: stopping an agent of the map stops
1209
+ * it and everything below it; deleting the root stops the whole tree): every active run of
1210
+ * `conversationId` (unless `includeSelf` is false) and of each sub-agent conversation below it,
1211
+ * shallowest first, each the way {@link stopChildren} stops a child (a stopped agent delivers its
1212
+ * finish to its own parent as `aborted`). A run a worker holds ends later; its worker's
1213
+ * {@link stopDescendantsOfStopped} stops what it dispatched after this read. Then the running
1214
+ * background tasks of every covered sub-agent conversation stop, whether it was running or idle.
1215
+ * Returns the number of runs asked to stop.
1216
+ *
1217
+ * Lock order: nothing is held across runs. Each run's stop is its own transaction (or none), and
1218
+ * one that writes the terminal state locks that run's conversation row, then its run row, the
1219
+ * order of `StepLog.appendCounted` (conversation row, then the root's budget run row) and of
1220
+ * dispatch (conversation, run, budget run). No stop here locks a budget run, let alone before a
1221
+ * descendant's conversation row, so the order is never inverted.
1222
+ */
1223
+ async stopTree(conversationId, byAccountId, opts = {}) {
1224
+ const tree = await conversationTree(this.db, conversationId);
1225
+ const ids = tree.filter((c) => opts.includeSelf !== false || c.level > 0).map((c) => c.id);
1226
+ if (ids.length === 0)
1227
+ return 0;
1228
+ const level = new Map(tree.map((c) => [c.id, c.level]));
1229
+ const runs = (await this.db
1230
+ .selectFrom("runs")
1231
+ .select(["id", "conversation_id", "status"])
1232
+ .where("conversation_id", "in", ids)
1233
+ .where("status", "in", ACTIVE_RUN_STATUSES)
1234
+ .execute()).sort((a, b) => (level.get(a.conversation_id) ?? 0) - (level.get(b.conversation_id) ?? 0));
1235
+ for (const r of runs) {
1236
+ try {
1237
+ if (await this.stopRun(r.conversation_id, r.id, r.status, byAccountId)) {
1238
+ // its approval / question cards changed (RunControl.abortWaiting's event)
1239
+ await this.events.emit("run.wait-stopped", {
1240
+ conversationId: r.conversation_id,
1241
+ runId: r.id,
1242
+ });
1243
+ }
1008
1244
  }
1009
- await this.abort.request(runId, byAccountId, opts.detail);
1010
- // the suspend handshake (see suspend): a child that became `waiting` after the read above
1011
- // may have checked the marker before it was set, so check `waiting` again after setting it
1012
- // (review M1)
1013
- const now = await this.db
1014
- .selectFrom("runs")
1015
- .select("status")
1016
- .where("id", "=", runId)
1017
- .executeTakeFirst();
1018
- if (now?.status === "waiting") {
1019
- await this.abortWaiting(conv, runId, byAccountId, opts.detail);
1245
+ catch (err) {
1246
+ this.log.error("cannot stop a sub-agent run of the tree", { runId: r.id, err });
1020
1247
  }
1021
1248
  }
1022
- return children.length;
1249
+ // every running background task of the covered sub-agents stops with them, idle ones too
1250
+ // (their finish would wake the idle agent, whose delivery would restart the stopped branch):
1251
+ // all of each conversation's tasks, as a stopped child's run end does (`childFinished`), with
1252
+ // which this is idempotent (only running tasks are stopped; `stoppedBy: "subagent_end"`
1253
+ // never wakes). A root conversation is skipped (`stopSubagentTasks`); never throws.
1254
+ await Promise.all(ids.map((id) => this.background.stopSubagentTasks(id)));
1255
+ return runs.length;
1256
+ }
1257
+ /**
1258
+ * After a sub-agent run's terminal commit (its worker): a run a person stopped (`run_aborted`
1259
+ * with an account and no `detail`; only {@link stopTree} stops a sub-agent's run that way) stops
1260
+ * the active runs below its conversation as well, so a descendant it dispatched after the tree
1261
+ * stop read the tree still stops (dispatch needs its run `running`, so after its terminal commit
1262
+ * the set is final). Any other end leaves its children running (agent map spec §5.4). Returns
1263
+ * the number of runs asked to stop. A root conversation's run never stops its children here.
1264
+ */
1265
+ async stopDescendantsOfStopped(runId) {
1266
+ const ev = await this.db
1267
+ .selectFrom("runs as r")
1268
+ .innerJoin("conversation_events as e", (j) => j.onRef("e.conversation_id", "=", "r.conversation_id").onRef("e.run_id", "=", "r.id"))
1269
+ .innerJoin("conversations as c", "c.id", "r.conversation_id")
1270
+ .select(["r.conversation_id", "e.payload"])
1271
+ .where("r.id", "=", runId)
1272
+ // a root's stop leaves its children running (agent map spec §6): a person-stopped root run
1273
+ // reaching here (a redelivered job, the failure path) stops nothing
1274
+ .where("c.kind", "=", "subagent")
1275
+ .where("r.status", "=", "aborted")
1276
+ .where("e.type", "=", "run_aborted")
1277
+ .executeTakeFirst();
1278
+ const p = ev?.payload;
1279
+ if (!ev || typeof p?.byAccountId !== "string" || p.detail !== undefined)
1280
+ return 0;
1281
+ return this.stopTree(ev.conversation_id, p.byAccountId, { includeSelf: false });
1282
+ }
1283
+ /**
1284
+ * Stops one active sub-agent run: a `waiting` one through its own {@link abortWaiting}, a
1285
+ * `queued` / `running` one that no worker holds directly (`RunQueue.abortIfOrphaned`, then
1286
+ * reported through {@link childFinished}), any other through `RunAbort.request` (the
1287
+ * cross-replica broadcast plus the marker key, so a run that starts later still sees it), after
1288
+ * which a run found `waiting` is stopped through `abortWaiting` too. True when it was stopped
1289
+ * while waiting.
1290
+ */
1291
+ async stopRun(conv, runId, status, byAccountId, detail) {
1292
+ // abortWaiting reports the stopped child to the parent itself (childFinished)
1293
+ if (status === "waiting" && (await this.abortWaiting(conv, runId, byAccountId, detail))) {
1294
+ return true;
1295
+ }
1296
+ if (await this.runQueue.abortIfOrphaned(conv, runId, byAccountId, detail)) {
1297
+ await this.childFinished(runId);
1298
+ return false;
1299
+ }
1300
+ await this.abort.request(runId, byAccountId, detail);
1301
+ // the suspend handshake (see suspend): a run that became `waiting` after the read above may
1302
+ // have checked the marker before it was set, so check `waiting` again after setting it
1303
+ // (review M1)
1304
+ const now = await this.db
1305
+ .selectFrom("runs")
1306
+ .select("status")
1307
+ .where("id", "=", runId)
1308
+ .executeTakeFirst();
1309
+ return now?.status === "waiting" && (await this.abortWaiting(conv, runId, byAccountId, detail));
1023
1310
  }
1024
1311
  };
1025
1312
  __decorate([
@@ -1046,7 +1333,8 @@ Waits = __decorate([
1046
1333
  __param(10, Inject(KernelEvents)),
1047
1334
  __param(11, Inject(KERNEL_LOGGER)),
1048
1335
  __param(12, Inject(BackgroundTaskStopper)),
1049
- __param(13, Inject(TransactionHost))
1336
+ __param(13, Inject(SubagentDeliveries)),
1337
+ __param(14, Inject(TransactionHost))
1050
1338
  ], Waits);
1051
1339
  export { Waits };
1052
1340
  /**