@desplega.ai/agent-swarm 1.157.0 → 1.159.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 (403) hide show
  1. package/dist/{acp-adapter-qhqrk4q0.js → acp-adapter-qhch0n2v.js} +1 -1
  2. package/dist/{actions-9rrg0zxm.js → actions-dtsh1mfb.js} +33 -29
  3. package/dist/{anthropic-messages-51pz26qe.js → anthropic-messages-f2h06k64.js} +8 -3
  4. package/dist/{app-enysy1zd.js → app-y1b9srva.js} +10 -9
  5. package/dist/{artifact-td4q4dch.js → artifact-3v5t9jtg.js} +1 -1
  6. package/dist/{assistant-zegamy48.js → assistant-31hwy5xj.js} +34 -30
  7. package/dist/{azure-openai-responses-8gksqtmz.js → azure-openai-responses-0k1mfax5.js} +12 -13
  8. package/dist/{boot-reembed-zfxb937k.js → boot-reembed-48d2qpkt.js} +11 -11
  9. package/dist/{boot-reembed-r6shx5qx.js → boot-reembed-w0bryhkr.js} +12 -12
  10. package/dist/{boot-scrub-logs-k5y0se6r.js → boot-scrub-logs-t65wbrn7.js} +9 -8
  11. package/dist/boot-seeds-h7c32hvm.js +27 -0
  12. package/dist/{claude-adapter-5yc7hxwv.js → claude-adapter-1t6611ne.js} +26 -21
  13. package/dist/{claude-managed-adapter-ea2aga6w.js → claude-managed-adapter-werp659j.js} +4 -2
  14. package/dist/{claude-managed-setup-60g8aazx.js → claude-managed-setup-y6rdgbc1.js} +11 -2
  15. package/dist/claude-sdk-session-zhkyk8yw.js +29319 -0
  16. package/dist/{cli-vj6h9kc2.js → cli-0m7wct0d.js} +59 -1
  17. package/dist/{cli-xf5b7y1f.js → cli-0n2e4x49.js} +13 -5
  18. package/dist/cli-0xqde53b.js +176 -0
  19. package/dist/{cli-nbp6m6gp.js → cli-10ym38qc.js} +53 -28
  20. package/dist/{cli-5b6b62tz.js → cli-13hw4z91.js} +1 -1
  21. package/dist/{cli-tpv97m71.js → cli-20035trh.js} +286 -84
  22. package/dist/{cli-k0g1sjzm.js → cli-31nkw3g3.js} +3 -3
  23. package/dist/cli-3gvrr8vj.js +1422 -0
  24. package/dist/{cli-sgyqyyxe.js → cli-48527fpw.js} +10 -8
  25. package/dist/{cli-24k806sc.js → cli-4aj25szq.js} +2 -2
  26. package/dist/{cli-s98skd5r.js → cli-4tvgz99m.js} +7 -7
  27. package/dist/cli-503ya656.js +455 -0
  28. package/dist/{cli-cw9zck8j.js → cli-5f2hq128.js} +8 -4
  29. package/dist/{cli-p37sg0a9.js → cli-68bmme5p.js} +11078 -27833
  30. package/dist/{cli-01vfmq8c.js → cli-79aq9cgb.js} +1318 -644
  31. package/dist/cli-7cxw8b60.js +14910 -0
  32. package/dist/cli-7kyk9jr3.js +22 -0
  33. package/dist/cli-7zttzetj.js +324 -0
  34. package/dist/{cli-y95wp3tg.js → cli-96qd5psa.js} +1 -1
  35. package/dist/{cli-ytxs7mn1.js → cli-9yg65c1j.js} +39 -0
  36. package/dist/{cli-3gmcwfyx.js → cli-ardpzhjm.js} +5 -5
  37. package/dist/{cli-y3nxwx0t.js → cli-b6thtzac.js} +20 -13
  38. package/dist/{cli-00w2c66p.js → cli-bgv70kym.js} +13 -2
  39. package/dist/{cli-r9ee9c4w.js → cli-bv0a38v9.js} +162 -42
  40. package/dist/cli-ca2w7zv7.js +115 -0
  41. package/dist/cli-cpvsaqsw.js +333 -0
  42. package/dist/cli-cygyqj3b.js +754 -0
  43. package/dist/{cli-5j7bm4tb.js → cli-dvjpkkjd.js} +6 -6
  44. package/dist/{cli-005pze6s.js → cli-e0ndxhtk.js} +4 -4
  45. package/dist/{cli-h0wdadsx.js → cli-e4xnc0qp.js} +21 -5
  46. package/dist/{cli-jytrw2na.js → cli-eg7cdg68.js} +8 -8
  47. package/dist/cli-ejpygnqz.js +3815 -0
  48. package/dist/{cli-c41wjx0r.js → cli-fjtp3463.js} +1917 -134
  49. package/dist/{cli-zt1227k1.js → cli-fkqhbg8g.js} +5 -3
  50. package/dist/{cli-awwphhcs.js → cli-g9df2m37.js} +765 -288
  51. package/dist/cli-gzyh0j0g.js +8455 -0
  52. package/dist/cli-hgqfttfc.js +183 -0
  53. package/dist/cli-hj65wsts.js +17755 -0
  54. package/dist/cli-j9z8mfx3.js +476 -0
  55. package/dist/{cli-aehm1rbq.js → cli-kc3dp84d.js} +1135 -61
  56. package/dist/{cli-h38x0qhg.js → cli-kdnehe0t.js} +4 -3
  57. package/dist/{cli-yscm6cv8.js → cli-m4excttz.js} +1993 -2216
  58. package/dist/{cli-74h6f2bp.js → cli-mg24hkt4.js} +2 -2
  59. package/dist/{cli-vx9p3qdt.js → cli-mzkqpxee.js} +1 -1
  60. package/dist/{cli-tjmghmm5.js → cli-phsaj4xq.js} +29 -4
  61. package/dist/{cli-pw9rj5t9.js → cli-pqetb83f.js} +1 -176
  62. package/dist/{cli-n6zq3kbd.js → cli-qjxy52w7.js} +1 -1
  63. package/dist/{cli-wb2zvbfg.js → cli-qv4jv8bx.js} +1 -1
  64. package/dist/cli-qvnnx4ct.js +1051 -0
  65. package/dist/cli-rb9m6rpe.js +4980 -0
  66. package/dist/{cli-tt9k8r35.js → cli-rfezr056.js} +476 -909
  67. package/dist/{cli-ggm92wcn.js → cli-rgjprct3.js} +1 -0
  68. package/dist/{cli-9n76jszt.js → cli-rrqmqr1s.js} +1 -1
  69. package/dist/cli-rykfmgwg.js +102 -0
  70. package/dist/cli-t1ze64h3.js +811 -0
  71. package/dist/{cli-eetrvv91.js → cli-t3p77qk1.js} +1 -1
  72. package/dist/{cli-scwq51gn.js → cli-vn0qv9cj.js} +25 -82
  73. package/dist/{cli-wsed24mk.js → cli-vwbbaecp.js} +2 -2
  74. package/dist/cli-wd9hz40d.js +69 -0
  75. package/dist/{cli-9p33cz9h.js → cli-wgjx0q33.js} +90 -32
  76. package/dist/cli-xgpf00sk.js +2149 -0
  77. package/dist/{cli-mcnhgnn1.js → cli-ykk5jaax.js} +184 -26
  78. package/dist/{cli-f3va018d.js → cli-z9x0sh1t.js} +26 -93
  79. package/dist/{cli-58rgvkt4.js → cli-zw65mab6.js} +5 -5
  80. package/dist/cli.js +56 -33
  81. package/dist/cloudflare-workers-ai-system-one-1sg586qv.js +46 -0
  82. package/dist/{codex-adapter-gns3s6c3.js → codex-adapter-jqfqqa21.js} +20 -13
  83. package/dist/{codex-hook-9hptmdhj.js → codex-hook-5eys3dya.js} +2 -2
  84. package/dist/{codex-session-runner-gqnxys5w.js → codex-session-runner-zd341dsm.js} +20 -13
  85. package/dist/{commands-hxy2y2sp.js → commands-vfsysz4s.js} +9 -8
  86. package/dist/{db-w8ghhsgf.js → db-s3znhvbn.js} +29 -10
  87. package/dist/{dispatcher-cp1rknjz.js → dispatcher-5xn0c7rf.js} +32 -28
  88. package/dist/{dsh-adapter-1dwg97zv.js → dsh-adapter-894mgfvs.js} +3 -3
  89. package/dist/{e2b-93x1k0j5.js → e2b-ez07znam.js} +4 -3
  90. package/dist/execute-71ysgv35.js +965 -0
  91. package/dist/{google-generative-ai-bxmv50nc.js → google-generative-ai-1nfcdphp.js} +5 -4
  92. package/dist/{google-vertex-809af514.js → google-vertex-1tqcd7b1.js} +5 -4
  93. package/dist/{handlers-egfhr351.js → handlers-5w4jwycr.js} +35 -31
  94. package/dist/{hook-x4kftwzt.js → hook-853bxrr6.js} +32 -21
  95. package/dist/{hook-fbxjqfjz.js → hook-z0hbxj85.js} +16 -13
  96. package/dist/{http-c7jfx990.js → http-akc3wy3m.js} +989 -275
  97. package/dist/{index-f6cryxwe.js → index-4a5njnm1.js} +2 -59
  98. package/dist/{index-jtvpgb8f.js → index-5sz16ksh.js} +208 -65
  99. package/dist/{index-dc2ek6bw.js → index-bjmjh9h4.js} +11 -11
  100. package/dist/{index-yy07ef2s.js → index-cd151qkq.js} +32 -28
  101. package/dist/{index-r6bty6tb.js → index-k661dzzr.js} +33 -29
  102. package/dist/{index-4k9hct21.js → index-ttpbhnjg.js} +32 -28
  103. package/dist/{keepalive-f7ekefyc.js → keepalive-8p9rpvz5.js} +11 -10
  104. package/dist/{lead-h053syts.js → lead-jp69z5h3.js} +49 -45
  105. package/dist/llama-cpp-classify-t2tccams.js +335 -0
  106. package/dist/{maintenance-a3w6zs54.js → maintenance-fwx4ev0k.js} +12 -12
  107. package/dist/{mistral-conversations-zx0kn554.js → mistral-conversations-bhvwqcnk.js} +14 -17
  108. package/dist/{oauth-refresh-sweep-vra1dhkd.js → oauth-refresh-sweep-cwcq1ctx.js} +10 -9
  109. package/dist/{onboard-mfgzeqxs.js → onboard-2b4q0t84.js} +282 -84
  110. package/dist/{openai-codex-responses-4vjqzvjp.js → openai-codex-responses-nekthgks.js} +21 -8
  111. package/dist/{openai-completions-9hjrqbw8.js → openai-completions-hxtzwj0s.js} +8 -11
  112. package/dist/{openai-responses-7b1pn0xt.js → openai-responses-w4r118w7.js} +22 -17
  113. package/dist/{opencode-adapter-z64xjzec.js → opencode-adapter-zz7xvjj6.js} +6 -4
  114. package/dist/{openrouter-images-9f9ek4rw.js → openrouter-images-b6sqqjgn.js} +4 -6
  115. package/dist/{otel-impl-2ez6xk57.js → otel-impl-g8rs4vwr.js} +416 -301
  116. package/dist/{pi-messages-txpjj39q.js → pi-messages-vxdt8v7j.js} +2 -1
  117. package/dist/{pi-mono-adapter-2b7mw16r.js → pi-mono-adapter-n0me28wt.js} +29 -17
  118. package/dist/pricing-refresh-0v77385v.js +39 -0
  119. package/dist/{rbac-roles-nm6924sy.js → rbac-roles-krjyazbj.js} +10 -9
  120. package/dist/{render-v2-f026j6c4.js → render-v2-3wjsp9aw.js} +10 -9
  121. package/dist/runtime-ktjysacx.js +24 -0
  122. package/dist/{setup-w606fr1q.js → setup-yeqryke6.js} +6 -5
  123. package/dist/typesafe-system-one-96960jxp.js +27 -0
  124. package/dist/{virtual-modules-8qheft18.js → virtual-modules-dzdeq1sf.js} +21 -13
  125. package/dist/{work-objects-ezmggdne.js → work-objects-3pakpkw0.js} +35 -31
  126. package/dist/{worker-1mbyv29k.js → worker-85testgj.js} +49 -45
  127. package/openapi.json +3288 -1442
  128. package/package.json +10 -8
  129. package/src/apps/catalog.generated.json +229 -0
  130. package/src/apps/page-validator.ts +71 -16
  131. package/src/apps/row-store.ts +66 -11
  132. package/src/apps/sync.ts +59 -17
  133. package/src/artifact-sdk/browser-sdk.ts +436 -2
  134. package/src/be/approval-sweeps.ts +109 -0
  135. package/src/be/boot-seeds.ts +40 -0
  136. package/src/be/chunking.ts +1 -1
  137. package/src/be/db/agents.ts +40 -0
  138. package/src/be/db/approvals.ts +78 -0
  139. package/src/be/db/tasks/human-free.ts +442 -0
  140. package/src/be/db/tasks/read.ts +252 -39
  141. package/src/be/db/tasks/write.ts +148 -20
  142. package/src/be/db-client.ts +107 -48
  143. package/src/be/db.ts +308 -241
  144. package/src/be/events.ts +33 -1
  145. package/src/be/harness-model-support.ts +182 -0
  146. package/src/be/human-free-drain.ts +67 -0
  147. package/src/be/memory/graph-expansion.ts +10 -3
  148. package/src/be/memory/providers/sqlite-store.ts +55 -13
  149. package/src/be/memory/raters/retrieval.ts +5 -2
  150. package/src/be/memory/reranker.ts +26 -2
  151. package/src/be/memory/types.ts +2 -0
  152. package/src/be/migrations/166_approval_request_auto_cancellation.sql +9 -0
  153. package/src/be/migrations/171_memory_retrieval_relevance.sql +8 -0
  154. package/src/be/migrations/175_workflow_runs_list_index.sql +11 -0
  155. package/src/be/migrations/177_events_event_agent_created_index.sql +11 -0
  156. package/src/be/migrations/182_task_human_free_flag.sql +63 -0
  157. package/src/be/migrations/183_human_free_reclassify_queue.sql +25 -0
  158. package/src/be/migrations/184_model_catalog.sql +120 -0
  159. package/src/be/model-catalog-store.ts +644 -0
  160. package/src/be/model-tier-keys.ts +31 -0
  161. package/src/be/model-tier-resolution.ts +489 -0
  162. package/src/be/model-validation.ts +112 -0
  163. package/src/be/models-catalog.ts +63 -7
  164. package/src/be/modelsdev-cache.json +1939 -0
  165. package/src/be/modelsdev-cache.ts +16 -1
  166. package/src/be/pricing-normalize.ts +2 -0
  167. package/src/be/pricing-refresh.ts +154 -12
  168. package/src/be/scripts/typecheck.ts +16 -0
  169. package/src/be/seed-pricing.ts +3 -1
  170. package/src/be/seed-scripts/catalog/task-failure-audit.ts +61 -9
  171. package/src/be/seed-skills/bundled-files.generated.json +1 -1
  172. package/src/be/steering.ts +53 -3
  173. package/src/be/swarm-config-guard.ts +9 -0
  174. package/src/be/task-citations.ts +29 -0
  175. package/src/cli.tsx +24 -1
  176. package/src/commands/claude-managed-setup.ts +3 -1
  177. package/src/commands/onboard/compose-generator.ts +8 -3
  178. package/src/commands/onboard/container-engine.ts +220 -0
  179. package/src/commands/onboard/manifest.ts +1 -0
  180. package/src/commands/onboard/steps/health-check.tsx +4 -1
  181. package/src/commands/onboard/steps/prereq-check.tsx +50 -54
  182. package/src/commands/onboard/steps/start.tsx +31 -16
  183. package/src/commands/onboard/types.ts +7 -2
  184. package/src/commands/onboard.tsx +39 -4
  185. package/src/commands/profile-sync.ts +79 -26
  186. package/src/commands/runner.ts +84 -3
  187. package/src/extensions/catalog.generated.json +17 -0
  188. package/src/extensions/contract-types.generated.ts +1 -1
  189. package/src/heartbeat/heartbeat.ts +323 -114
  190. package/src/heartbeat/templates.ts +2 -2
  191. package/src/hooks/hook.ts +21 -12
  192. package/src/http/agents.ts +84 -1
  193. package/src/http/approval-requests.ts +136 -64
  194. package/src/http/apps.ts +14 -3
  195. package/src/http/config.ts +15 -1
  196. package/src/http/events.ts +62 -2
  197. package/src/http/index.ts +14 -4
  198. package/src/http/memory.ts +21 -7
  199. package/src/http/models-catalog.ts +357 -8
  200. package/src/http/poll.ts +45 -2
  201. package/src/http/schedules.ts +37 -7
  202. package/src/http/session-data.ts +11 -9
  203. package/src/http/sessions.ts +25 -18
  204. package/src/http/stats.ts +25 -15
  205. package/src/http/status.ts +11 -1
  206. package/src/http/tasks.ts +66 -9
  207. package/src/http/usage-cache.ts +56 -15
  208. package/src/http/webhooks.ts +67 -46
  209. package/src/http/workflows.ts +50 -28
  210. package/src/linear/outbound.ts +37 -15
  211. package/src/otel-impl.ts +151 -1
  212. package/src/otel.ts +14 -3
  213. package/src/prompts/memories.ts +19 -2
  214. package/src/prompts/session-templates.ts +1 -0
  215. package/src/providers/claude-managed-models.ts +47 -153
  216. package/src/providers/codex-adapter.ts +4 -4
  217. package/src/providers/codex-models.ts +65 -198
  218. package/src/providers/reasoning-effort.ts +44 -140
  219. package/src/rbac/legacy-policy.ts +41 -0
  220. package/src/rbac/permissions.ts +14 -0
  221. package/src/scheduler/schedule-task.ts +3 -0
  222. package/src/scripts-runtime/sdk-allowlist.ts +5 -0
  223. package/src/scripts-runtime/swarm-sdk.ts +9 -0
  224. package/src/scripts-runtime/types/stdlib.d.ts +16 -0
  225. package/src/scripts-runtime/types/swarm-extension.d.ts +4 -0
  226. package/src/scripts-runtime/types/swarm-sdk.d.ts +16 -0
  227. package/src/server.ts +18 -7
  228. package/src/slack/app.ts +35 -4
  229. package/src/slack/connection-state.ts +17 -0
  230. package/src/slack/message-text.ts +56 -2
  231. package/src/slack/thread-buffer.ts +10 -2
  232. package/src/tasks/context-key.ts +1 -0
  233. package/src/tasks/worker-follow-up.ts +6 -2
  234. package/src/tests/agent-task-activity.test.ts +74 -0
  235. package/src/tests/agents-list-model-display.test.ts +9 -6
  236. package/src/tests/approval-auto-cancellation-migration.test.ts +104 -0
  237. package/src/tests/approval-requests.test.ts +395 -0
  238. package/src/tests/approval-sweeps-config.test.ts +47 -0
  239. package/src/tests/approval-sweeps.test.ts +508 -0
  240. package/src/tests/apps-kibo-blocks.test.ts +77 -0
  241. package/src/tests/apps-spike.test.ts +56 -1
  242. package/src/tests/apps-sync-engine.test.ts +20 -9
  243. package/src/tests/base-prompt.test.ts +3 -0
  244. package/src/tests/boot-seeds.test.ts +170 -0
  245. package/src/tests/cancel-approval-request-tool.test.ts +115 -0
  246. package/src/tests/claude-adapter.test.ts +10 -0
  247. package/src/tests/claude-managed-adapter.test.ts +17 -17
  248. package/src/tests/codex-adapter.test.ts +2 -1
  249. package/src/tests/codex-gpt6-release.test.ts +66 -5
  250. package/src/tests/config-key-filter.test.ts +80 -0
  251. package/src/tests/context-window.test.ts +8 -5
  252. package/src/tests/db-client-busy-retry.test.ts +96 -0
  253. package/src/tests/db-client.test.ts +60 -1
  254. package/src/tests/db-extraction-contract.test.ts +1 -0
  255. package/src/tests/db-task-read-contract.test.ts +15 -1
  256. package/src/tests/db-task-write-contract.test.ts +13 -1
  257. package/src/tests/docs-index-footprint.test.js +3 -3
  258. package/src/tests/events-http.test.ts +103 -0
  259. package/src/tests/explicit-model-validation.test.ts +332 -0
  260. package/src/tests/extensions-catalog.test.ts +22 -17
  261. package/src/tests/extensions-pre-task.test.ts +107 -0
  262. package/src/tests/fixtures/kibo-blocks-definition.json.txt +105 -0
  263. package/src/tests/follow-up-config-inheritance.test.ts +260 -0
  264. package/src/tests/harness-model-support.test.ts +374 -0
  265. package/src/tests/heartbeat-checklist-config.test.ts +71 -0
  266. package/src/tests/heartbeat-checklist.test.ts +4 -2
  267. package/src/tests/heartbeat-orphan-resume.test.ts +132 -0
  268. package/src/tests/heartbeat-reboot-live.test.ts +95 -0
  269. package/src/tests/heartbeat-stall-cas.test.ts +80 -0
  270. package/src/tests/heartbeat.test.ts +99 -3
  271. package/src/tests/hook-mcp-config.test.ts +29 -0
  272. package/src/tests/http-api-integration.test.ts +16 -2
  273. package/src/tests/human-free-flag.test.ts +279 -0
  274. package/src/tests/human-free-oracle.ts +57 -0
  275. package/src/tests/human-free-reclassify.test.ts +669 -0
  276. package/src/tests/kv-storage.test.ts +62 -0
  277. package/src/tests/linear-outbound-sync.test.ts +120 -5
  278. package/src/tests/list-endpoint-slimming.test.ts +91 -0
  279. package/src/tests/memory-graph-organic-route.test.ts +155 -0
  280. package/src/tests/memory-http-recall-gating.test.ts +14 -4
  281. package/src/tests/memory-hybrid.test.ts +161 -1
  282. package/src/tests/memory-prompt-recall-crowdout.test.ts +297 -0
  283. package/src/tests/memory.test.ts +22 -0
  284. package/src/tests/migration-046-budgets.test.ts +3 -3
  285. package/src/tests/model-catalog-migration.test.ts +134 -0
  286. package/src/tests/model-catalog-table.test.ts +249 -0
  287. package/src/tests/model-catalog-write-access.test.ts +387 -0
  288. package/src/tests/model-tier-resolution.test.ts +519 -0
  289. package/src/tests/models-catalog.test.ts +1 -1
  290. package/src/tests/multi-runtime-enabled-stats.test.ts +65 -1
  291. package/src/tests/onboard-container-engine.test.ts +240 -0
  292. package/src/tests/otel-event-loop-and-logs.test.ts +99 -0
  293. package/src/tests/package-publish.test.ts +137 -36
  294. package/src/tests/pricing-routes.test.ts +16 -2
  295. package/src/tests/profile-sync-warning.test.ts +8 -4
  296. package/src/tests/promote-draft-task-route.test.ts +19 -0
  297. package/src/tests/provider-registration.test.ts +296 -42
  298. package/src/tests/rbac-engine.test.ts +72 -2
  299. package/src/tests/reasoning-effort.test.ts +117 -0
  300. package/src/tests/refresh-modelsdev-carryforward.test.ts +5 -5
  301. package/src/tests/runtime-model-catalog.test.ts +86 -0
  302. package/src/tests/script-connections.test.ts +12 -0
  303. package/src/tests/sdk-allowlist.test.ts +39 -0
  304. package/src/tests/seed-scripts.test.ts +89 -0
  305. package/src/tests/session-costs-model-key-normalize.test.ts +1 -0
  306. package/src/tests/session-costs.test.ts +14 -11
  307. package/src/tests/sessions-detail-batch.test.ts +250 -0
  308. package/src/tests/sessions.test.ts +118 -0
  309. package/src/tests/slack-config.test.ts +22 -0
  310. package/src/tests/slack-message-text.test.ts +101 -0
  311. package/src/tests/slack-thread-buffer-context.test.ts +93 -0
  312. package/src/tests/sonnet-5-5-registry.test.ts +44 -0
  313. package/src/tests/status.test.ts +36 -1
  314. package/src/tests/swarm-diff.test.ts +316 -10
  315. package/src/tests/task-cascade-fail.test.ts +148 -2
  316. package/src/tests/task-completion-idempotency.test.ts +2 -1
  317. package/src/tests/tasks-requested-by-filter.test.ts +3 -1
  318. package/src/tests/tool-annotations.test.ts +1 -1
  319. package/src/tests/ui-list-slim-projections.test.ts +158 -0
  320. package/src/tests/usage-cache.test.ts +166 -0
  321. package/src/tests/webhooks-task-blocked.test.ts +127 -0
  322. package/src/tests/workflow-approval-recovery.test.ts +203 -0
  323. package/src/tests/workflow-executors.test.ts +5 -2
  324. package/src/tests/workflow-hitl-routing.test.ts +22 -1
  325. package/src/tests/workflow-hitl-slack-card.test.ts +52 -0
  326. package/src/tests/workflow-http-v2.test.ts +99 -8
  327. package/src/tests/workflow-retry-validation.test.ts +56 -0
  328. package/src/tests/workflow-system-one-decision-review.test.ts +1021 -0
  329. package/src/tests/workflow-system-one-decision-save-warnings.test.ts +365 -0
  330. package/src/tests/workflow-system-one-decision.test.ts +2063 -0
  331. package/src/tests/workflow-tla-races.test.ts +389 -0
  332. package/src/tests/workflow-validation-port-routing.test.ts +113 -1
  333. package/src/tools/cancel-approval-request.ts +57 -0
  334. package/src/tools/memory-search.ts +1 -0
  335. package/src/tools/model-catalog/index.ts +137 -0
  336. package/src/tools/request-human-input.ts +4 -2
  337. package/src/tools/schedules/create-schedule.ts +16 -1
  338. package/src/tools/schedules/patch-schedule.ts +17 -0
  339. package/src/tools/schedules/update-schedule.ts +17 -0
  340. package/src/tools/send-task.ts +18 -0
  341. package/src/tools/task-action.ts +12 -0
  342. package/src/tools/templates.ts +19 -0
  343. package/src/tools/tool-config.ts +5 -2
  344. package/src/tools/workflows/create-workflow.ts +9 -2
  345. package/src/tools/workflows/list-workflow-runs.ts +1 -0
  346. package/src/tools/workflows/patch-workflow-node.ts +17 -7
  347. package/src/tools/workflows/patch-workflow.ts +9 -2
  348. package/src/tools/workflows/update-workflow.ts +9 -2
  349. package/src/types.ts +68 -1
  350. package/src/utils/context-window.ts +47 -52
  351. package/src/utils/harness-cli-version.ts +115 -0
  352. package/src/utils/harness-model-error.ts +33 -0
  353. package/src/utils/runtime-model-catalog.ts +137 -0
  354. package/src/workflows/approval-cancel.ts +152 -0
  355. package/src/workflows/approval-notifications.ts +84 -0
  356. package/src/workflows/approval-resolution.ts +39 -0
  357. package/src/workflows/checkpoint.ts +10 -5
  358. package/src/workflows/definition.ts +28 -0
  359. package/src/workflows/engine.ts +221 -22
  360. package/src/workflows/executors/agent-task.ts +9 -0
  361. package/src/workflows/executors/base.ts +53 -0
  362. package/src/workflows/executors/human-in-the-loop.ts +9 -9
  363. package/src/workflows/executors/index.ts +1 -0
  364. package/src/workflows/executors/registry.ts +2 -0
  365. package/src/workflows/executors/system-one-decision.ts +1232 -0
  366. package/src/workflows/executors/system-one-providers.ts +301 -0
  367. package/src/workflows/executors/workflow-llm.ts +13 -1
  368. package/src/workflows/readiness.ts +86 -0
  369. package/src/workflows/recovery.ts +100 -45
  370. package/src/workflows/resume.ts +71 -26
  371. package/src/workflows/retry-poller.ts +71 -21
  372. package/templates/extensions/README.md +1 -0
  373. package/templates/extensions/github-sender-allowlist/README.md +18 -0
  374. package/templates/extensions/github-sender-allowlist/hooks.ts +55 -0
  375. package/templates/extensions/github-sender-allowlist/manifest.json +8 -0
  376. package/templates/schedules/daily-blocker-digest/content.md +4 -5
  377. package/templates/skills/agent-browser/SKILL.md +6 -5
  378. package/templates/skills/agent-browser/content.md +6 -5
  379. package/templates/skills/apps/content.md +20 -1
  380. package/templates/skills/code-quality/content.md +26 -1
  381. package/templates/skills/heartbeat-runbook/config.json +1 -1
  382. package/templates/skills/heartbeat-runbook/content.md +2 -2
  383. package/templates/skills/pages/content.md +16 -4
  384. package/templates/skills/pages/files/examples/multiplayer-board.html +3 -12
  385. package/templates/skills/swarm-scripts/SKILL.md +1 -1
  386. package/templates/skills/swarm-scripts/content.md +1 -1
  387. package/templates/skills/workflow-iterate/content.md +81 -1
  388. package/templates/workflows/claude-code-changelog-watch/content.md +2 -0
  389. package/templates/workflows/pr-review-status-sweep/content.md +2 -0
  390. package/dist/claude-sdk-session-j4ywn3xf.js +0 -39108
  391. package/dist/cli-2daksqps.js +0 -378
  392. package/dist/cli-6jjzxv3b.js +0 -246
  393. package/dist/cli-avkd6mqv.js +0 -6052
  394. package/dist/cli-aw1jwp1r.js +0 -14075
  395. package/dist/cli-e781c6f9.js +0 -60
  396. package/dist/cli-v53rbqp3.js +0 -1101
  397. package/dist/cli-vapyk8sw.js +0 -20
  398. package/dist/pricing-refresh-6sw65tck.js +0 -27
  399. package/dist/rbac-roles-3gxmnb20.js +0 -37
  400. package/dist/seed-pricing-vqxa06qf.js +0 -26
  401. package/src/providers/modelsdev-reasoning.json +0 -5902
  402. package/dist/{codex-login-x3jk4etn.js → codex-login-he9vrn90.js} +3 -3
  403. package/dist/{index-f24115ge.js → index-2wsdsnmm.js} +3 -3
@@ -1,14 +1,16 @@
1
1
  import {
2
2
  BROWSER_SDK_JS,
3
3
  SWARM_UI_JS
4
- } from "./cli-2daksqps.js";
4
+ } from "./cli-t1ze64h3.js";
5
5
  import {
6
6
  ACP_TARGET_IDS
7
7
  } from "./cli-dgnj0zcc.js";
8
8
  import {
9
9
  SIMILARITY_THRESHOLD,
10
+ isUnknownModelError,
11
+ memoryRelevance,
10
12
  writeSkillsToFilesystem
11
- } from "./cli-tjmghmm5.js";
13
+ } from "./cli-phsaj4xq.js";
12
14
  import {
13
15
  Anthropic
14
16
  } from "./cli-j490egb5.js";
@@ -16,7 +18,7 @@ import {
16
18
  checkHeartbeatChecklist,
17
19
  runHeartbeatSweep,
18
20
  stopHeartbeat
19
- } from "./cli-tpv97m71.js";
21
+ } from "./cli-20035trh.js";
20
22
  import {
21
23
  isClaudeBridgeEffective,
22
24
  resolveClaudeTransport
@@ -26,11 +28,11 @@ import {
26
28
  } from "./cli-npssxgaz.js";
27
29
  import {
28
30
  reasoningCapability
29
- } from "./cli-avkd6mqv.js";
31
+ } from "./cli-ca2w7zv7.js";
30
32
  import {
31
33
  ensureAgentFsCredentialsForAgent,
32
34
  inviteEmailToSharedOrg
33
- } from "./cli-vx9p3qdt.js";
35
+ } from "./cli-mzkqpxee.js";
34
36
  import {
35
37
  AGENT_MAX_TASKS_CONFIG_KEY,
36
38
  ALL_CAPABILITIES,
@@ -57,6 +59,7 @@ import {
57
59
  TriggerSchemaError,
58
60
  WebhookError,
59
61
  activateVersion,
62
+ agentRanModel,
60
63
  agentWithCapacity,
61
64
  allowedCredentialRedirect,
62
65
  applyRating,
@@ -70,6 +73,7 @@ import {
70
73
  calculateNextRun,
71
74
  canClaim,
72
75
  canReadMemory,
76
+ cancelApprovalRequest,
73
77
  cancelTaskHandler,
74
78
  cancelTaskInputSchema,
75
79
  cancelTaskOutputSchema,
@@ -100,10 +104,13 @@ import {
100
104
  executeRawLlm,
101
105
  executeReadOnlyQuery,
102
106
  expandCandidatesWithGraph,
107
+ explicitModelError,
108
+ explicitModelErrorForAgent,
103
109
  extractAndVerifyCookie,
104
110
  findUserById,
105
111
  fingerprintApiKey,
106
112
  flushAuditBuffer,
113
+ getAgentHarnessCliVersion,
107
114
  getAutomationSetupStates,
108
115
  getEnabledCapabilities,
109
116
  getEventCountsFiltered,
@@ -182,6 +189,7 @@ import {
182
189
  listExtensionRuns,
183
190
  listExtensionVersions,
184
191
  listExtensions,
192
+ listHarnessModelSupport,
185
193
  listOAuthPresetIds,
186
194
  listOAuthPresets,
187
195
  listRuntimeInstancesForAgent,
@@ -198,13 +206,17 @@ import {
198
206
  mintToken,
199
207
  parseBody,
200
208
  parseCookieHeader,
209
+ parseModelTierOverridesHeader,
201
210
  parseQueryParams,
202
211
  parseSkillContent,
203
212
  patchWorkflowDefinition,
204
213
  preflightAutomation,
214
+ previewModelTiers,
205
215
  readScriptSdkJsonResponse,
206
216
  reconcileAgentMaxTasksPolicy,
207
217
  reconcileAgentStatusFromRuntimes,
218
+ recordClaimModelResolution,
219
+ recordHarnessModelSupport,
208
220
  recordIdentityEvent,
209
221
  recordMemoryAccesses,
210
222
  recordRetrievals,
@@ -241,11 +253,14 @@ import {
241
253
  runtimeInstanceHeader,
242
254
  runtimeStaleThresholdMinutes,
243
255
  safeRequestUrlForLog,
256
+ sanitizeModelTierOverrides,
244
257
  scheduleIntegrationsReload,
245
258
  scopedResourceScopeIdSchema,
246
259
  sendKapsoReaction,
247
260
  sendTaskHandler,
248
261
  sendTaskOutputSchema,
262
+ setAgentHarnessCliVersion,
263
+ setAgentModelTierOverrides,
249
264
  setCorsHeaders,
250
265
  setExtensionLoopbackBaseUrl,
251
266
  setRuntimeCredentialReady,
@@ -284,38 +299,25 @@ import {
284
299
  verifyHmacSignature,
285
300
  verifyWebhookSignature,
286
301
  warnIfCorsAllowsAnyOrigin,
287
- wireHttpSpanLifecycle
288
- } from "./cli-01vfmq8c.js";
302
+ wireHttpSpanLifecycle,
303
+ workflowSaveWarnings
304
+ } from "./cli-79aq9cgb.js";
289
305
  import"./cli-0z2v4nhw.js";
290
306
  import {
291
307
  REFERENCES_SOURCE_MAX_LENGTH,
292
308
  sanitizeReferencesSource
293
- } from "./cli-tt9k8r35.js";
294
- import {
295
- CLIENT_ID,
296
- MAX_CODEX_OAUTH_SLOT,
297
- _fetchHolder,
298
- codexOAuthKeyForSlot,
299
- deriveCodexKeySuffix,
300
- exchangeAuthorizationCode as exchangeAuthorizationCode2,
301
- getAccountId,
302
- getValidCodexOAuth,
303
- loadAllCodexOAuthSlots
304
- } from "./cli-vhjwh6cz.js";
309
+ } from "./cli-cpvsaqsw.js";
305
310
  import {
306
311
  isMultiRuntimeEnabled
307
312
  } from "./cli-re8z5p8p.js";
308
- import"./cli-3dpj7atn.js";
309
- import"./cli-aw1jwp1r.js";
310
- import {
311
- getModelsCatalog
312
- } from "./cli-6jjzxv3b.js";
313
313
  import {
314
- normalizeModelKey
315
- } from "./cli-xf5b7y1f.js";
314
+ FilesError,
315
+ getFileStorageProvider,
316
+ normalizeFilesError
317
+ } from "./cli-jsp14b6c.js";
316
318
  import {
317
319
  getUserGrant
318
- } from "./cli-f3va018d.js";
320
+ } from "./cli-z9x0sh1t.js";
319
321
  import {
320
322
  LEGACY_RULES,
321
323
  can,
@@ -323,7 +325,17 @@ import {
323
325
  decideToolAdmission,
324
326
  isRbacEnabled,
325
327
  setAuditSink
326
- } from "./cli-ytxs7mn1.js";
328
+ } from "./cli-9yg65c1j.js";
329
+ import {
330
+ deleteModelCatalogOverlay,
331
+ loadModelsCatalog,
332
+ requestModelCatalogRefresh,
333
+ upsertModelCatalogOverlay
334
+ } from "./cli-cygyqj3b.js";
335
+ import"./cli-m4excttz.js";
336
+ import {
337
+ normalizeModelKey
338
+ } from "./cli-0n2e4x49.js";
327
339
  import {
328
340
  ConnectionAuthInputSchema,
329
341
  MAX_SCRIPT_WALL_CLOCK_MS,
@@ -344,6 +356,7 @@ import {
344
356
  connectionAuthInputFromFlat,
345
357
  connectionAuthSummary,
346
358
  consumeMcpOAuthPending,
359
+ createApprovalFollowUpTask,
347
360
  createScriptApi,
348
361
  definitionNodeIds,
349
362
  deleteMcpOAuthToken,
@@ -415,7 +428,7 @@ import {
415
428
  upsertScriptByName,
416
429
  upsertScriptConnection,
417
430
  validateDefinition
418
- } from "./cli-c41wjx0r.js";
431
+ } from "./cli-fjtp3463.js";
419
432
  import"./cli-epan13p1.js";
420
433
  import {
421
434
  detachedProcessGroup,
@@ -427,9 +440,25 @@ import {
427
440
  import {
428
441
  getApiKey
429
442
  } from "./cli-f14fvzag.js";
443
+ import"./cli-rfezr056.js";
444
+ import {
445
+ CLIENT_ID,
446
+ MAX_CODEX_OAUTH_SLOT,
447
+ _fetchHolder,
448
+ codexOAuthKeyForSlot,
449
+ deriveCodexKeySuffix,
450
+ exchangeAuthorizationCode as exchangeAuthorizationCode2,
451
+ getAccountId,
452
+ getValidCodexOAuth,
453
+ loadAllCodexOAuthSlots
454
+ } from "./cli-vhjwh6cz.js";
455
+ import"./cli-3dpj7atn.js";
456
+ import"./cli-gzyh0j0g.js";
457
+ import"./cli-rb9m6rpe.js";
458
+ import"./cli-rykfmgwg.js";
430
459
  import {
431
460
  searchScripts
432
- } from "./cli-wsed24mk.js";
461
+ } from "./cli-vwbbaecp.js";
433
462
  import {
434
463
  acquireOAuthRefreshLock,
435
464
  buildAuthorizationUrl,
@@ -453,34 +482,29 @@ import {
453
482
  updateAuthorizationIdentity,
454
483
  updateOAuthAppById,
455
484
  upsertAuthorization
456
- } from "./cli-wb2zvbfg.js";
457
- import {
458
- FilesError,
459
- getFileStorageProvider,
460
- normalizeFilesError
461
- } from "./cli-jsp14b6c.js";
485
+ } from "./cli-qv4jv8bx.js";
486
+ import"./cli-fad8m16k.js";
462
487
  import {
463
488
  CANDIDATE_SET_MULTIPLIER,
464
489
  EMBEDDING_DIMENSIONS,
490
+ OpenAI,
465
491
  getEmbeddingProvider,
466
492
  getMemoryStore,
467
493
  init_constants as init_constants2,
494
+ init_openai,
468
495
  init_reranker,
469
496
  rerank
470
- } from "./cli-v53rbqp3.js";
471
- import"./cli-nbp6m6gp.js";
497
+ } from "./cli-kc3dp84d.js";
498
+ import"./cli-10ym38qc.js";
472
499
  import"./cli-bsakbbkm.js";
473
- import"./cli-fad8m16k.js";
474
500
  import"./cli-51tf7ac3.js";
475
- import {
476
- OpenAI,
477
- init_openai
478
- } from "./cli-aehm1rbq.js";
479
501
  import {
480
502
  TaskCitationSchema,
481
503
  ensure,
482
504
  getSlackApp,
505
+ getSlackConnectionState,
483
506
  getTaskCitations,
507
+ getTaskCitationsForTasks,
484
508
  initOtel,
485
509
  initialize,
486
510
  isPollTracingEnabled,
@@ -493,7 +517,7 @@ import {
493
517
  withRemoteContext,
494
518
  withSpan,
495
519
  withSpanContext
496
- } from "./cli-9p33cz9h.js";
520
+ } from "./cli-wgjx0q33.js";
497
521
  import"./cli-q51yprfq.js";
498
522
  import"./cli-3er6gcsn.js";
499
523
  import"./cli-2658f6at.js";
@@ -571,6 +595,7 @@ import {
571
595
  deleteTaskAttachment,
572
596
  deleteUser,
573
597
  deleteWorkflow,
598
+ drainHumanFreeReclassifyQueue,
574
599
  emitBuiltInIntegrationConnectedOnce,
575
600
  emitIntegrationConnected,
576
601
  emitMcpServerConnectedTelemetry,
@@ -580,9 +605,11 @@ import {
580
605
  getActivePricingRow,
581
606
  getActiveSessions,
582
607
  getAgentById,
608
+ getAgentDailyTaskCounts,
583
609
  getAgentHarnessProviders,
584
610
  getAgentMcpServers,
585
611
  getAgentSkills,
612
+ getAgentStatusCounts,
586
613
  getAgentWithTasks,
587
614
  getAllAgents,
588
615
  getAllAgentsWithTasks,
@@ -668,9 +695,9 @@ import {
668
695
  getTaskById,
669
696
  getTaskStats,
670
697
  getTaskSteeringFields,
698
+ getTaskSteeringFieldsForTasks,
671
699
  getTasksCount,
672
700
  getUnassignedTaskIdsForAgent,
673
- getUsageDataVersion,
674
701
  getUserById,
675
702
  getWorkflow,
676
703
  getWorkflowRun,
@@ -692,6 +719,7 @@ import {
692
719
  init_db,
693
720
  init_default_drift,
694
721
  init_heartbeat_expiry,
722
+ init_human_free,
695
723
  init_request_auth_context,
696
724
  init_steering,
697
725
  init_swarm_config_guard,
@@ -710,6 +738,7 @@ import {
710
738
  listAgentsWithCredStatusByProvider,
711
739
  listAllMetrics,
712
740
  listAllPages,
741
+ listApprovalRequestSummaries,
713
742
  listApprovalRequests,
714
743
  listAssetSummaries,
715
744
  listFavorites,
@@ -724,7 +753,6 @@ import {
724
753
  listSkillFileManifest,
725
754
  listSkills,
726
755
  listTaskTemplates,
727
- listWorkflowRuns,
728
756
  listWorkflowRunsPage,
729
757
  listWorkflows,
730
758
  markKeyRateLimited,
@@ -757,7 +785,9 @@ import {
757
785
  setApiKeyName,
758
786
  setApiKeyPlan,
759
787
  setFavorite,
788
+ setHumanFreeQueueListener,
760
789
  setRequestAuth,
790
+ settleSupersededTaskDependents,
761
791
  startTask,
762
792
  supersedeTask,
763
793
  sweepExpiredKv,
@@ -801,7 +831,7 @@ import {
801
831
  upsertSwarmConfig,
802
832
  validateConfigValue,
803
833
  withFavoriteFlags
804
- } from "./cli-awwphhcs.js";
834
+ } from "./cli-g9df2m37.js";
805
835
  import {
806
836
  ActiveSessionSchema,
807
837
  AgentAcpStatusSchema,
@@ -851,6 +881,7 @@ import {
851
881
  KvKeySchema,
852
882
  KvNamespaceSchema,
853
883
  KvValueTypeSchema,
884
+ MODEL_TIERS,
854
885
  McpAuthMethodSchema,
855
886
  McpServerSchema,
856
887
  McpServerWithInstallInfoSchema,
@@ -918,6 +949,7 @@ import {
918
949
  WorkflowRunSchema,
919
950
  WorkflowRunStatusSchema,
920
951
  WorkflowRunStepSchema,
952
+ WorkflowRunSummarySchema,
921
953
  WorkflowSchema,
922
954
  WorkflowVersionSchema,
923
955
  init_bundle_path,
@@ -926,12 +958,16 @@ import {
926
958
  isSafeBundlePath,
927
959
  isTerminalTaskStatus,
928
960
  splitLegacyModelAlias
929
- } from "./cli-h0wdadsx.js";
961
+ } from "./cli-e4xnc0qp.js";
930
962
  import {
931
963
  IDENTITY_FIELD_BUDGETS,
932
964
  IdentityFieldBudgetError,
933
965
  init_identity_field_budget
934
- } from "./cli-3gmcwfyx.js";
966
+ } from "./cli-ardpzhjm.js";
967
+ import {
968
+ getSlackConfiguration,
969
+ init_config
970
+ } from "./cli-n7h1kqpf.js";
935
971
  import {
936
972
  getAllTemplateDefinitions,
937
973
  getTemplateDefinition,
@@ -942,8 +978,7 @@ import {
942
978
  interpolate,
943
979
  isSteeringEnabled,
944
980
  resolveTemplate
945
- } from "./cli-ggm92wcn.js";
946
- import"./cli-19jenss3.js";
981
+ } from "./cli-rgjprct3.js";
947
982
  import {
948
983
  MAX_PROFILE_FILE_LENGTH,
949
984
  getAppUrl,
@@ -952,26 +987,27 @@ import {
952
987
  getPublicMcpBaseUrl,
953
988
  init_constants
954
989
  } from "./cli-dv6cdjs2.js";
955
- import {
956
- getSlackConfiguration,
957
- init_config
958
- } from "./cli-n7h1kqpf.js";
959
- import {
960
- MODEL_SCOPED_WINDOWS,
961
- activeModelBlocks,
962
- init_model_rate_limit_windows
963
- } from "./cli-de1396j2.js";
964
990
  import {
965
991
  SUBSCRIPTION_PLANS,
966
992
  SUBSCRIPTION_PLANS_CHECKED_AT,
967
993
  init_subscription_plans,
968
994
  isSubscriptionPlanId
969
995
  } from "./cli-cqt19wg6.js";
996
+ import"./cli-19jenss3.js";
997
+ import {
998
+ MODEL_SCOPED_WINDOWS,
999
+ activeModelBlocks,
1000
+ init_model_rate_limit_windows
1001
+ } from "./cli-de1396j2.js";
970
1002
  import {
971
1003
  init_env_flag,
972
1004
  isEnvFlagEnabled,
973
1005
  parseEnvFlag
974
1006
  } from "./cli-ej6gbxfb.js";
1007
+ import {
1008
+ init_src,
1009
+ isAlias
1010
+ } from "./cli-7zttzetj.js";
975
1011
  import {
976
1012
  exports_zod,
977
1013
  init_zod
@@ -988,7 +1024,7 @@ import {
988
1024
  import {
989
1025
  init_package,
990
1026
  package_default
991
- } from "./cli-sgyqyyxe.js";
1027
+ } from "./cli-48527fpw.js";
992
1028
  import {
993
1029
  init_secret_scrubber,
994
1030
  registerVolatileSecret,
@@ -997,20 +1033,20 @@ import {
997
1033
  } from "./cli-r2ap2czm.js";
998
1034
  import {
999
1035
  bedrockProviderModule
1000
- } from "./cli-h38x0qhg.js";
1036
+ } from "./cli-kdnehe0t.js";
1001
1037
  import"./cli-yn0a417a.js";
1002
1038
  import"./cli-cgj4hc12.js";
1003
1039
  import"./cli-txgcknmy.js";
1004
1040
  import"./cli-6map995v.js";
1005
- import"./cli-k0g1sjzm.js";
1041
+ import"./cli-31nkw3g3.js";
1006
1042
  import"./cli-y2apkfe2.js";
1007
- import"./cli-vapyk8sw.js";
1043
+ import"./cli-7kyk9jr3.js";
1008
1044
  import {
1009
1045
  setBedrockProviderModule
1010
- } from "./cli-5b6b62tz.js";
1046
+ } from "./cli-13hw4z91.js";
1011
1047
  import"./cli-btbzvq95.js";
1012
1048
  import"./cli-1m2e086m.js";
1013
- import"./cli-mcnhgnn1.js";
1049
+ import"./cli-ykk5jaax.js";
1014
1050
  import"./cli-bzr0ftht.js";
1015
1051
  import"./cli-bd957dgb.js";
1016
1052
  import {
@@ -1501,6 +1537,62 @@ async function stopDbRetention() {
1501
1537
  await retentionTickPromise;
1502
1538
  }
1503
1539
 
1540
+ // src/be/human-free-drain.ts
1541
+ init_human_free();
1542
+ var YIELD_MS2 = 25;
1543
+ var IDLE_INTERVAL_MS = 60000;
1544
+ var running = false;
1545
+ var idleTimer = null;
1546
+ var passTimer = null;
1547
+ function scheduleIdle() {
1548
+ if (!running)
1549
+ return;
1550
+ if (idleTimer)
1551
+ clearTimeout(idleTimer);
1552
+ idleTimer = setTimeout(() => schedulePass(0), IDLE_INTERVAL_MS);
1553
+ idleTimer.unref?.();
1554
+ }
1555
+ function schedulePass(delayMs) {
1556
+ if (!running || passTimer)
1557
+ return;
1558
+ passTimer = setTimeout(() => {
1559
+ passTimer = null;
1560
+ runPass();
1561
+ }, delayMs);
1562
+ passTimer.unref?.();
1563
+ }
1564
+ async function runPass() {
1565
+ if (!running)
1566
+ return;
1567
+ try {
1568
+ const { batches, remaining } = await drainHumanFreeReclassifyQueue({ maxBatches: 1 });
1569
+ if (batches > 0 && remaining > 0) {
1570
+ schedulePass(YIELD_MS2);
1571
+ return;
1572
+ }
1573
+ } catch (err) {
1574
+ console.error("[human-free-drain] batch failed, retrying later:", err instanceof Error ? err.message : String(err));
1575
+ }
1576
+ scheduleIdle();
1577
+ }
1578
+ function startHumanFreeDrain() {
1579
+ if (running)
1580
+ return;
1581
+ running = true;
1582
+ setHumanFreeQueueListener(() => schedulePass(0));
1583
+ schedulePass(0);
1584
+ }
1585
+ function stopHumanFreeDrain() {
1586
+ running = false;
1587
+ setHumanFreeQueueListener(undefined);
1588
+ if (idleTimer)
1589
+ clearTimeout(idleTimer);
1590
+ if (passTimer)
1591
+ clearTimeout(passTimer);
1592
+ idleTimer = null;
1593
+ passTimer = null;
1594
+ }
1595
+
1504
1596
  // src/be/scripts/retention.ts
1505
1597
  init_db();
1506
1598
  var SCRATCH_RETENTION_DAYS = 14;
@@ -3318,6 +3410,7 @@ async function handleActiveSessions(req, res, pathSegments, queryParams, myAgent
3318
3410
  }
3319
3411
 
3320
3412
  // src/http/agents.ts
3413
+ init_src();
3321
3414
  init_zod();
3322
3415
  init_db();
3323
3416
  init_telemetry();
@@ -3370,7 +3463,9 @@ var registerAgent = route({
3370
3463
  maxTasks: exports_external.number().int().optional(),
3371
3464
  provider: ProviderNameSchema.optional(),
3372
3465
  harness_provider: ProviderNameSchema.optional(),
3373
- runtimeInstanceId: exports_external.string().min(1).optional()
3466
+ runtimeInstanceId: exports_external.string().min(1).optional(),
3467
+ modelTierOverrides: exports_external.record(exports_external.string(), exports_external.record(exports_external.string(), exports_external.string())).optional(),
3468
+ harnessCliVersion: exports_external.string().max(64).optional()
3374
3469
  }),
3375
3470
  responses: {
3376
3471
  200: {
@@ -3450,7 +3545,7 @@ var updateAgentRuntimeRoute = route({
3450
3545
  path: "/api/agents/{id}/runtime",
3451
3546
  pattern: ["api", "agents", null, "runtime"],
3452
3547
  summary: "Update an agent's runtime harness and default model",
3453
- description: "Updates `agents.harness_provider` and agent-scoped runtime config. The settings apply to future provider sessions. For `model`, `reasoning_effort`, and `claude.transport`: omit the field to leave it unchanged, send `null` to clear the corresponding override, or send a value to set it.",
3548
+ description: "Updates `agents.harness_provider` and agent-scoped runtime config. The settings apply to future provider sessions. For `model`, `reasoning_effort`, and `claude.transport`: omit the field to leave it unchanged, send `null` to clear the corresponding override, or send a value to set it. A `model` the model catalog does not list is a 400 unless `allow_custom_model` is true. A `latest:` alias is not accepted here (aliases resolve for a task's model and for `MODEL_TIER_*` values); `reasoning_effort` must be one the harness and model support.",
3454
3549
  tags: ["Agents"],
3455
3550
  params: exports_external.object({ id: exports_external.string() }),
3456
3551
  query: exports_external.object({ repoId: exports_external.string().optional() }),
@@ -3584,6 +3679,25 @@ var listAgentRuntimeInstances = route({
3584
3679
  404: { description: "Agent not found" }
3585
3680
  }
3586
3681
  });
3682
+ var getAgentTaskActivity = route({
3683
+ method: "get",
3684
+ path: "/api/agents/{id}/task-activity",
3685
+ pattern: ["api", "agents", null, "task-activity"],
3686
+ summary: "Daily task counts for an agent",
3687
+ description: "Number of tasks created for the agent per UTC day over the last `days` days (default 365, max 730), oldest first. Days with no tasks are omitted. Backs the activity heatmap on the agent page.",
3688
+ tags: ["Agents"],
3689
+ params: exports_external.object({ id: exports_external.string() }),
3690
+ query: exports_external.object({ days: exports_external.coerce.number().int().min(1).max(730).optional() }),
3691
+ responses: {
3692
+ 200: {
3693
+ description: "Daily task counts",
3694
+ schema: exports_external.object({
3695
+ days: exports_external.array(exports_external.object({ date: exports_external.string(), count: exports_external.number().int() }))
3696
+ })
3697
+ },
3698
+ 404: { description: "Agent not found" }
3699
+ }
3700
+ });
3587
3701
  var ContentHashSchema = exports_external.string().regex(/^[0-9a-f]{64}$/, "sha256 hex");
3588
3702
  var ProfileSyncRejectionSchema = exports_external.object({
3589
3703
  field: exports_external.enum(["soulMd", "identityMd", "claudeMd", "toolsMd"]),
@@ -3782,6 +3896,12 @@ async function handleAgentRegister(req, res, pathSegments, myAgentId) {
3782
3896
  }
3783
3897
  return { agent, created: true };
3784
3898
  });
3899
+ if (parsed.body.harnessCliVersion !== undefined) {
3900
+ await setAgentHarnessCliVersion(agentId, parsed.body.harnessCliVersion.trim() || null);
3901
+ }
3902
+ if (parsed.body.modelTierOverrides) {
3903
+ await setAgentModelTierOverrides(agentId, sanitizeModelTierOverrides(parsed.body.modelTierOverrides));
3904
+ }
3785
3905
  telemetry.agent("registered", {
3786
3906
  role: parsed.body.role,
3787
3907
  capabilities: parsed.body.capabilities ?? [],
@@ -3890,6 +4010,19 @@ async function handleAgentsRest(req, res, pathSegments, queryParams, _myAgentId)
3890
4010
  });
3891
4011
  return true;
3892
4012
  }
4013
+ if (getAgentTaskActivity.match(req.method, pathSegments)) {
4014
+ const parsed = await getAgentTaskActivity.parse(req, res, pathSegments, queryParams);
4015
+ if (!parsed)
4016
+ return true;
4017
+ if (!await getAgentById(parsed.params.id)) {
4018
+ jsonError(res, "Agent not found", 404);
4019
+ return true;
4020
+ }
4021
+ getAgentTaskActivity.respond(res, 200, {
4022
+ days: await getAgentDailyTaskCounts(parsed.params.id, parsed.query.days ?? 365)
4023
+ });
4024
+ return true;
4025
+ }
3893
4026
  if (updateAgentProfileRoute.match(req.method, pathSegments)) {
3894
4027
  const parsed = await updateAgentProfileRoute.parse(req, res, pathSegments, queryParams);
3895
4028
  if (!parsed)
@@ -4074,6 +4207,21 @@ async function handleAgentsRest(req, res, pathSegments, queryParams, _myAgentId)
4074
4207
  return true;
4075
4208
  }
4076
4209
  }
4210
+ if (typeof model === "string" && isAlias(model)) {
4211
+ jsonError(res, `A latest: alias cannot be an agent's default model ("${model}"). Set the alias on a task, or as a MODEL_TIER_<PROVIDER>_<TIER> value.`, 400);
4212
+ return true;
4213
+ }
4214
+ if (typeof model === "string") {
4215
+ const modelError = await explicitModelError({
4216
+ model,
4217
+ allowCustomModel: allow_custom_model,
4218
+ harnessProvider: harness_provider
4219
+ });
4220
+ if (modelError) {
4221
+ jsonError(res, modelError, 400);
4222
+ return true;
4223
+ }
4224
+ }
4077
4225
  let agent;
4078
4226
  try {
4079
4227
  agent = await getDbClient().transaction(async () => {
@@ -4333,22 +4481,50 @@ init_subscription_plans();
4333
4481
 
4334
4482
  // src/http/usage-cache.ts
4335
4483
  var USAGE_CACHE_TTL_MS = 30000;
4484
+ var USAGE_CACHE_MAX_STALE_MS = 120000;
4336
4485
  var MAX_ENTRIES = 100;
4337
4486
  var entries = new Map;
4338
- async function cachedUsageReport(key, load) {
4339
- const now = Date.now();
4487
+ var loading = new Map;
4488
+ var generation = 0;
4489
+ function load(key, loader) {
4490
+ const running2 = loading.get(key);
4491
+ if (running2)
4492
+ return running2;
4493
+ const startedIn = generation;
4494
+ const promise = Promise.resolve().then(loader).then((value) => {
4495
+ if (startedIn === generation) {
4496
+ entries.delete(key);
4497
+ if (entries.size >= MAX_ENTRIES)
4498
+ entries.delete(entries.keys().next().value);
4499
+ entries.set(key, { fetchedAt: Date.now(), value });
4500
+ }
4501
+ return value;
4502
+ }).finally(() => {
4503
+ if (loading.get(key) === promise)
4504
+ loading.delete(key);
4505
+ });
4506
+ loading.set(key, promise);
4507
+ return promise;
4508
+ }
4509
+ async function cachedUsageReport(key, loader) {
4340
4510
  const hit = entries.get(key);
4341
- if (hit && hit.expiresAt > now)
4342
- return hit.value;
4343
- const value = await load();
4344
- entries.delete(key);
4345
- if (entries.size >= MAX_ENTRIES)
4346
- entries.delete(entries.keys().next().value);
4347
- entries.set(key, { expiresAt: now + USAGE_CACHE_TTL_MS, value });
4348
- return value;
4511
+ if (hit) {
4512
+ const age = Date.now() - hit.fetchedAt;
4513
+ if (age < USAGE_CACHE_TTL_MS)
4514
+ return hit.value;
4515
+ if (age < USAGE_CACHE_MAX_STALE_MS) {
4516
+ load(key, loader).catch((error) => {
4517
+ console.error(`[usage-cache] background refresh failed for ${key.split(":")[0]}:`, error);
4518
+ });
4519
+ return hit.value;
4520
+ }
4521
+ }
4522
+ return load(key, loader);
4349
4523
  }
4350
4524
  function clearUsageCache() {
4525
+ generation++;
4351
4526
  entries.clear();
4527
+ loading.clear();
4352
4528
  }
4353
4529
 
4354
4530
  // src/http/api-keys.ts
@@ -4850,7 +5026,6 @@ async function handleApiKeys(req, res, pathSegments, queryParams) {
4850
5026
  // src/http/approval-requests.ts
4851
5027
  init_zod();
4852
5028
  init_db();
4853
- init_resolver();
4854
5029
  init_request_auth_context();
4855
5030
  init_event_bus();
4856
5031
  var QuestionSchema = exports_external.object({
@@ -4900,6 +5075,13 @@ var ApprovalRequestSchema = exports_external.object({
4900
5075
  createdAt: exports_external.string(),
4901
5076
  updatedAt: exports_external.string()
4902
5077
  });
5078
+ var ApprovalRequestSummarySchema = ApprovalRequestSchema.omit({
5079
+ questions: true,
5080
+ approvers: true,
5081
+ responses: true,
5082
+ resolutionReason: true,
5083
+ notificationChannels: true
5084
+ }).extend({ questionCount: exports_external.number().int() });
4903
5085
  function toApprovalRequestResponse(request) {
4904
5086
  return {
4905
5087
  ...request,
@@ -4976,7 +5158,7 @@ var createRoute = route({
4976
5158
  workflowRunId: exports_external.string().uuid().optional(),
4977
5159
  workflowRunStepId: exports_external.string().uuid().optional(),
4978
5160
  sourceTaskId: exports_external.string().uuid().optional(),
4979
- timeoutSeconds: exports_external.number().int().min(1).optional(),
5161
+ timeoutSeconds: exports_external.number().int().min(1).optional().describe("Seconds until the request expires. After that the request becomes 'timeout' and you get a hitl-follow-up task. A request with no timeout is cancelled after APPROVAL_REQUEST_AUTO_CANCELLATION_DAYS days (default 7)."),
4980
5162
  notifications: exports_external.array(exports_external.object({
4981
5163
  channel: exports_external.enum(["slack", "email"]),
4982
5164
  target: exports_external.string()
@@ -5029,21 +5211,54 @@ var respondRoute = route({
5029
5211
  },
5030
5212
  auth: { apiKey: true }
5031
5213
  });
5214
+ var cancelRoute = route({
5215
+ method: "post",
5216
+ path: "/api/approval-requests/{id}/cancel",
5217
+ pattern: ["api", "approval-requests", null, "cancel"],
5218
+ summary: "Cancel a pending approval request",
5219
+ tags: ["ApprovalRequests"],
5220
+ params: exports_external.object({ id: exports_external.string().uuid() }),
5221
+ body: exports_external.object({ reason: exports_external.string().max(500).optional() }),
5222
+ responses: {
5223
+ 200: {
5224
+ description: "Request cancelled, or already cancelled. A request that gates a running or waiting workflow run cancels that run too.",
5225
+ schema: exports_external.object({
5226
+ approvalRequest: ApprovalRequestSchema,
5227
+ alreadyCancelled: exports_external.boolean(),
5228
+ runCancelled: exports_external.boolean()
5229
+ })
5230
+ },
5231
+ 403: { description: "Caller may not cancel this request" },
5232
+ 404: { description: "Not found" },
5233
+ 409: {
5234
+ description: "Already resolved with approved, rejected, or timeout, or its expiresAt passed"
5235
+ }
5236
+ },
5237
+ auth: { apiKey: true },
5238
+ rbac: { permission: "approval.cancel.any" }
5239
+ });
5032
5240
  var listRoute = route({
5033
5241
  method: "get",
5034
5242
  path: "/api/approval-requests",
5035
5243
  pattern: ["api", "approval-requests"],
5036
5244
  summary: "List approval requests with optional filters",
5245
+ description: "Returns full approval requests by default. Pass `fields=slim` for the list-view shape: `questions`, `approvers`, `responses`, `resolutionReason` and `notificationChannels` are dropped and `questionCount` is added. Fetch one request in full via `GET /api/approval-requests/{id}`.",
5037
5246
  tags: ["ApprovalRequests"],
5038
5247
  query: exports_external.object({
5039
5248
  status: exports_external.string().optional(),
5040
5249
  workflowRunId: exports_external.string().optional(),
5041
- limit: exports_external.coerce.number().optional()
5250
+ limit: exports_external.coerce.number().optional(),
5251
+ fields: exports_external.enum(["full", "slim"]).optional()
5042
5252
  }),
5043
5253
  responses: {
5044
5254
  200: {
5045
5255
  description: "List of approval requests",
5046
- schema: exports_external.object({ approvalRequests: exports_external.array(ApprovalRequestSchema) })
5256
+ schema: exports_external.object({
5257
+ approvalRequests: exports_external.union([
5258
+ exports_external.array(ApprovalRequestSchema),
5259
+ exports_external.array(ApprovalRequestSummarySchema)
5260
+ ])
5261
+ })
5047
5262
  }
5048
5263
  },
5049
5264
  auth: { apiKey: true }
@@ -5063,6 +5278,19 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
5063
5278
  jsonError(res, `Approval request already resolved with status: ${existing.status}${reason}`, 409);
5064
5279
  return true;
5065
5280
  }
5281
+ if (existing.expiresAt && new Date(existing.expiresAt) < new Date) {
5282
+ await getDbClient().transaction(async () => {
5283
+ const timedOut = await resolveApprovalRequest(existing.id, {
5284
+ status: "timeout",
5285
+ resolutionReason: `Timed out: the answer arrived after the deadline ${existing.expiresAt}`
5286
+ });
5287
+ if (timedOut && !existing.workflowRunId) {
5288
+ await createApprovalFollowUpTask(timedOut, "hitl.timeout");
5289
+ }
5290
+ });
5291
+ jsonError(res, `Approval request expired at ${existing.expiresAt}`, 409);
5292
+ return true;
5293
+ }
5066
5294
  const unavailableReason = await getWorkflowApprovalUnavailableReason(existing);
5067
5295
  if (unavailableReason) {
5068
5296
  jsonError(res, unavailableReason, 409);
@@ -5104,33 +5332,32 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
5104
5332
  workflowRunStepId: updated.workflowRunStepId
5105
5333
  });
5106
5334
  }
5107
- if (!updated.workflowRunId && updated.sourceTaskId) {
5108
- const sourceTask = await getTaskById(updated.sourceTaskId);
5109
- if (sourceTask) {
5110
- const formattedResponses = formatResponses(updated.questions, updated.responses);
5111
- const { text: taskText } = resolveTemplate("hitl.follow_up", {
5112
- request_id: updated.id,
5113
- title: updated.title,
5114
- status: updated.status,
5115
- responses: formattedResponses
5116
- });
5117
- await createTaskExtended(taskText, {
5118
- agentId: sourceTask.agentId,
5119
- routingReason: sourceTask.agentId ? "continuity" : undefined,
5120
- routingSource: sourceTask.agentId ? "engine_default" : undefined,
5121
- parentTaskId: updated.sourceTaskId,
5122
- source: "system",
5123
- taskType: "hitl-follow-up",
5124
- tags: ["hitl", "follow-up"],
5125
- slackChannelId: sourceTask.slackChannelId ?? undefined,
5126
- slackThreadTs: sourceTask.slackThreadTs ?? undefined,
5127
- slackUserId: sourceTask.slackUserId ?? undefined
5128
- });
5129
- }
5130
- }
5335
+ await createApprovalFollowUpTask(updated, "hitl.follow_up");
5131
5336
  respondRoute.respond(res, 200, { approvalRequest: toApprovalRequestResponse(updated) });
5132
5337
  return true;
5133
5338
  }
5339
+ if (cancelRoute.match(req.method, pathSegments)) {
5340
+ const parsed = await cancelRoute.parse(req, res, pathSegments, queryParams);
5341
+ if (!parsed)
5342
+ return true;
5343
+ const { principal, resolvedBy } = await approvalCancelPrincipal(req);
5344
+ const result = await cancelApprovalRequest({
5345
+ id: parsed.params.id,
5346
+ reason: parsed.body.reason,
5347
+ principal,
5348
+ resolvedBy
5349
+ });
5350
+ if (!result.ok) {
5351
+ jsonError(res, result.message, result.status);
5352
+ return true;
5353
+ }
5354
+ cancelRoute.respond(res, 200, {
5355
+ approvalRequest: toApprovalRequestResponse(result.request),
5356
+ alreadyCancelled: result.alreadyCancelled,
5357
+ runCancelled: result.runCancelled
5358
+ });
5359
+ return true;
5360
+ }
5134
5361
  if (getByIdRoute.match(req.method, pathSegments)) {
5135
5362
  const parsed = await getByIdRoute.parse(req, res, pathSegments, queryParams);
5136
5363
  if (!parsed)
@@ -5171,11 +5398,18 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
5171
5398
  const parsed = await listRoute.parse(req, res, pathSegments, queryParams);
5172
5399
  if (!parsed)
5173
5400
  return true;
5174
- const requests = await listApprovalRequests({
5401
+ const filters = {
5175
5402
  status: parsed.query.status || undefined,
5176
5403
  workflowRunId: parsed.query.workflowRunId || undefined,
5177
5404
  limit: parsed.query.limit || undefined
5178
- });
5405
+ };
5406
+ if (parsed.query.fields === "slim") {
5407
+ listRoute.respond(res, 200, {
5408
+ approvalRequests: await listApprovalRequestSummaries(filters)
5409
+ });
5410
+ return true;
5411
+ }
5412
+ const requests = await listApprovalRequests(filters);
5179
5413
  listRoute.respond(res, 200, {
5180
5414
  approvalRequests: requests.map(toApprovalRequestResponse)
5181
5415
  });
@@ -5183,25 +5417,21 @@ async function handleApprovalRequests(req, res, pathSegments, queryParams) {
5183
5417
  }
5184
5418
  return false;
5185
5419
  }
5186
- function formatResponses(questions, responses) {
5187
- return questions.map((q) => {
5188
- const answer = responses[q.id];
5189
- let answerText;
5190
- if (answer == null) {
5191
- answerText = "(no answer)";
5192
- } else if (q.type === "approval") {
5193
- const a = answer;
5194
- answerText = a.approved ? "Approved" : "Rejected";
5195
- if (a.comment)
5196
- answerText += ` — ${a.comment}`;
5197
- } else if (typeof answer === "object") {
5198
- answerText = JSON.stringify(answer);
5199
- } else {
5200
- answerText = String(answer);
5201
- }
5202
- return `- ${q.label}: ${answerText}`;
5203
- }).join(`
5204
- `);
5420
+ async function approvalCancelPrincipal(req) {
5421
+ const auth = getRequestAuth(req);
5422
+ if (auth?.kind === "user") {
5423
+ return { principal: { kind: "user", userId: auth.userId }, resolvedBy: auth.userId };
5424
+ }
5425
+ const rawAgentId = req.headers["x-agent-id"];
5426
+ const agentId = auth?.kind === "agent" ? auth.agentId : Array.isArray(rawAgentId) ? rawAgentId[0] : rawAgentId;
5427
+ if (agentId) {
5428
+ const agent = await getAgentById(agentId);
5429
+ return {
5430
+ principal: { kind: "agent", agentId, isLead: agent?.isLead ?? false },
5431
+ resolvedBy: agentId
5432
+ };
5433
+ }
5434
+ return { principal: { kind: "operator" }, resolvedBy: "operator" };
5205
5435
  }
5206
5436
 
5207
5437
  // src/http/assets.ts
@@ -6363,6 +6593,7 @@ var getResolvedConfigRoute = route({
6363
6593
  query: exports_external.object({
6364
6594
  agentId: exports_external.string().optional(),
6365
6595
  repoId: exports_external.string().optional(),
6596
+ key: exports_external.string().min(1).optional().describe("Return only the entry with this exact key. Omit to return every resolved entry."),
6366
6597
  includeSecrets: exports_external.enum(["true", "false"]).optional()
6367
6598
  }),
6368
6599
  responses: {
@@ -6439,6 +6670,7 @@ var listConfig = route({
6439
6670
  query: exports_external.object({
6440
6671
  scope: exports_external.string().optional(),
6441
6672
  scopeId: exports_external.string().optional(),
6673
+ key: exports_external.string().min(1).optional().describe("Return only entries with this exact key. Omit to return every entry."),
6442
6674
  includeSecrets: exports_external.enum(["true", "false"]).optional()
6443
6675
  }),
6444
6676
  responses: {
@@ -6495,7 +6727,8 @@ async function handleConfig(req, res, pathSegments, queryParams) {
6495
6727
  return true;
6496
6728
  const includeSecrets = parsed.query.includeSecrets === "true";
6497
6729
  const { effectiveIncludeSecrets, secretsNote } = await resolveSecretsRead(req, includeSecrets);
6498
- const configs = stripApiOnlyKeys(await getResolvedConfig(parsed.query.agentId || undefined, parsed.query.repoId || undefined));
6730
+ const key = parsed.query.key;
6731
+ const configs = stripApiOnlyKeys(await getResolvedConfig(parsed.query.agentId || undefined, parsed.query.repoId || undefined)).filter((c) => !key || c.key === key);
6499
6732
  const result = effectiveIncludeSecrets ? configs : maskSecrets(configs);
6500
6733
  if (effectiveIncludeSecrets) {
6501
6734
  for (const c of result) {
@@ -6568,7 +6801,8 @@ async function handleConfig(req, res, pathSegments, queryParams) {
6568
6801
  const { effectiveIncludeSecrets, secretsNote } = await resolveSecretsRead(req, includeSecrets);
6569
6802
  const configs = stripApiOnlyKeys(await getSwarmConfigs({
6570
6803
  scope: parsed.query.scope || undefined,
6571
- scopeId: parsed.query.scopeId || undefined
6804
+ scopeId: parsed.query.scopeId || undefined,
6805
+ key: parsed.query.key
6572
6806
  }));
6573
6807
  const listResult = effectiveIncludeSecrets ? configs : maskSecrets(configs);
6574
6808
  if (effectiveIncludeSecrets) {
@@ -7258,13 +7492,20 @@ var getEventsRoute = route({
7258
7492
  dataField: exports_external.string().optional(),
7259
7493
  since: exports_external.string().optional(),
7260
7494
  until: exports_external.string().optional(),
7261
- limit: exports_external.coerce.number().int().min(1).max(1000).optional()
7495
+ limit: exports_external.coerce.number().int().min(1).max(1000).optional(),
7496
+ events: exports_external.string().optional().describe("Comma-separated event names; matches any of them (ANDed with `event`)"),
7497
+ dataFields: exports_external.string().optional().describe("Comma-separated `data.field` values, used with latestPerDataField"),
7498
+ latestPerDataField: exports_external.enum(["true", "false"]).optional().describe("When true, return only the newest event per (event, data.field) pair for every name in `event`/`events` and every value in `dataFields`")
7262
7499
  }),
7263
7500
  responses: {
7264
7501
  200: {
7265
7502
  description: "List of events",
7266
- schema: exports_external.object({ events: exports_external.array(SwarmEventSchema) })
7267
- }
7503
+ schema: exports_external.object({
7504
+ events: exports_external.array(SwarmEventSchema),
7505
+ latestPerDataField: exports_external.literal(true).optional().describe("Present only when the request asked for latestPerDataField=true")
7506
+ })
7507
+ },
7508
+ 400: { description: "Validation error" }
7268
7509
  },
7269
7510
  auth: { apiKey: true }
7270
7511
  });
@@ -7293,6 +7534,7 @@ var getEventCountsRoute = route({
7293
7534
  },
7294
7535
  auth: { apiKey: true }
7295
7536
  });
7537
+ var MAX_LATEST_PAIRS = 50;
7296
7538
  async function handleEvents(req, res, pathSegments, queryParams, _myAgentId) {
7297
7539
  if (createEventsBatchRoute.match(req.method, pathSegments)) {
7298
7540
  const parsed = await createEventsBatchRoute.parse(req, res, pathSegments, queryParams);
@@ -7340,6 +7582,20 @@ async function handleEvents(req, res, pathSegments, queryParams, _myAgentId) {
7340
7582
  const parsed = await getEventsRoute.parse(req, res, pathSegments, queryParams);
7341
7583
  if (!parsed)
7342
7584
  return true;
7585
+ const eventNames = parsed.query.events ? parsed.query.events.split(",").map((name) => EventNameSchema.safeParse(name.trim())) : [];
7586
+ const invalid = eventNames.find((result) => !result.success);
7587
+ if (invalid) {
7588
+ jsonError(res, "Invalid event name in `events`", 400);
7589
+ return true;
7590
+ }
7591
+ const eventFilter = eventNames.flatMap((result) => result.success ? [result.data] : []);
7592
+ const latestPerDataField = parsed.query.latestPerDataField === "true";
7593
+ const dataFields = (parsed.query.dataFields ?? "").split(",").map((field) => field.trim()).filter(Boolean);
7594
+ const latestEvents = eventFilter.length > 0 ? eventFilter : parsed.query.event ? [parsed.query.event] : [];
7595
+ if (latestPerDataField && (latestEvents.length === 0 || dataFields.length === 0 || latestEvents.length * dataFields.length > MAX_LATEST_PAIRS)) {
7596
+ jsonError(res, `latestPerDataField needs \`event\` or \`events\` and \`dataFields\`, at most ${MAX_LATEST_PAIRS} pairs`, 400);
7597
+ return true;
7598
+ }
7343
7599
  const events = await getEventsFiltered({
7344
7600
  category: parsed.query.category || undefined,
7345
7601
  event: parsed.query.event || undefined,
@@ -7351,9 +7607,11 @@ async function handleEvents(req, res, pathSegments, queryParams, _myAgentId) {
7351
7607
  dataField: parsed.query.dataField || undefined,
7352
7608
  since: parsed.query.since || undefined,
7353
7609
  until: parsed.query.until || undefined,
7354
- limit: parsed.query.limit ?? 100
7610
+ limit: parsed.query.limit ?? 100,
7611
+ events: eventFilter,
7612
+ latestPerDataField: latestPerDataField ? { events: latestEvents, dataFields } : undefined
7355
7613
  });
7356
- getEventsRoute.respond(res, 200, { events });
7614
+ getEventsRoute.respond(res, 200, latestPerDataField ? { events, latestPerDataField: true } : { events });
7357
7615
  return true;
7358
7616
  }
7359
7617
  return false;
@@ -7433,6 +7691,7 @@ declare module "swarm-extension" {
7433
7691
  outputSchema?: Record<string, unknown> | undefined;
7434
7692
  inheritParentOutputSchema?: boolean | undefined;
7435
7693
  inheritParentRoutingAffinity?: boolean | undefined;
7694
+ inheritParentFollowUpConfig?: boolean | undefined;
7436
7695
  followUpConfig?:
7437
7696
  | {
7438
7697
  disabled?: boolean | undefined;
@@ -7548,6 +7807,9 @@ declare module "swarm-extension" {
7548
7807
  model?: string | undefined;
7549
7808
  modelTier?: "smol" | "regular" | "smart" | "ultra" | undefined;
7550
7809
  effort?: "off" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
7810
+ resolvedModel?: string | undefined;
7811
+ modelSource?: string | undefined;
7812
+ modelAlias?: string | undefined;
7551
7813
  scheduleId?: string | undefined;
7552
7814
  workflowRunId?: string | null | undefined;
7553
7815
  workflowRunStepId?: string | null | undefined;
@@ -8049,6 +8311,78 @@ void _configIsValid;
8049
8311
 
8050
8312
  // src/extensions/catalog.generated.json
8051
8313
  var catalog_generated_default = {
8314
+ "github-sender-allowlist": {
8315
+ manifestFile: "manifest.json",
8316
+ manifest: {
8317
+ $schema: "../manifest.schema.json",
8318
+ name: "github-sender-allowlist",
8319
+ description: "Blocks GitHub webhook tasks from senders outside configured allowlists",
8320
+ version: "1.0.0",
8321
+ runtime: "api",
8322
+ assets: {
8323
+ hooks: "hooks.ts"
8324
+ }
8325
+ },
8326
+ files: {
8327
+ "hooks.ts": `import { block, type SwarmExtension } from "swarm-extension";
8328
+ import { z } from "zod";
8329
+
8330
+ export const config = z.object({
8331
+ internal: z.array(z.string()).default([]),
8332
+ external: z.array(z.string()).default([]),
8333
+ reviewBots: z.array(z.string()).default([]),
8334
+ exemptTaskTypes: z.array(z.string()).default([]),
8335
+ });
8336
+
8337
+ const manifest = {
8338
+ name: "github-sender-allowlist",
8339
+ description: "Blocks GitHub webhook tasks from senders outside configured allowlists",
8340
+ version: "1.0.0",
8341
+ runtime: "api",
8342
+ assets: { hooks: "hooks.ts" },
8343
+ config,
8344
+ } as const;
8345
+
8346
+ function includesLogin(logins: string[], login: string): boolean {
8347
+ return logins.some((allowed) => allowed.toLowerCase() === login.toLowerCase());
8348
+ }
8349
+
8350
+ const extension: SwarmExtension<typeof manifest> = (api) => {
8351
+ api.on("pre.task.create", (event, ctx) => {
8352
+ const { options } = event;
8353
+ if (options.source !== "github") return;
8354
+
8355
+ const taskType = options.taskType ?? "unknown";
8356
+ const login = options.vcsAuthor ?? "";
8357
+ if (includesLogin(ctx.config.internal, login)) return;
8358
+
8359
+ const isReviewBot = includesLogin(ctx.config.reviewBots, login);
8360
+ if (isReviewBot && taskType === "github-review") return;
8361
+ if (!isReviewBot && ctx.config.exemptTaskTypes.includes(taskType)) return;
8362
+
8363
+ const isPullRequest = options.vcsUrl?.includes("/pull/") ?? false;
8364
+ const isExternalPullRequestTask =
8365
+ (taskType === "github-comment" || taskType === "github-pr" || taskType === "github-review") &&
8366
+ isPullRequest;
8367
+ const isExternalSender = includesLogin(ctx.config.external, login);
8368
+ if (!isReviewBot && isExternalSender && isExternalPullRequestTask) return;
8369
+
8370
+ const rule = isReviewBot
8371
+ ? "review bots are allowed only for github-review tasks"
8372
+ : isExternalSender
8373
+ ? "external senders are allowed only for PR comments, reviews, and github-pr tasks on pull requests"
8374
+ : "sender is not on the internal, external, or reviewBots allowlist";
8375
+ const reason = \`GitHub sender "\${login || "unknown"}" is blocked: \${rule}.\`;
8376
+ ctx.log.warn(reason, { login: login || null, taskType, vcsUrl: options.vcsUrl ?? null });
8377
+ return block(reason);
8378
+ });
8379
+ };
8380
+
8381
+ export default extension;
8382
+ `
8383
+ },
8384
+ readme: '# github-sender-allowlist\n\nBlocks GitHub webhook tasks from senders outside the configured allowlists. Login matching is case-insensitive. Tasks from other sources pass through. No task type is exempt by default.\n\nConfig:\n\n```json\n{\n "internal": ["tarasyarema", "harlequinetcie"],\n "external": ["fuvidani", "capchase-bot"],\n "reviewBots": [],\n "exemptTaskTypes": []\n}\n```\n\nInternal senders can create any GitHub task, including reviews. Logins in `reviewBots` can create `github-review` tasks only. External senders can create `github-comment` or `github-pr` tasks on pull requests, and `github-review` tasks when `vcsUrl` contains `/pull/`. Choose any review-bot logins from the sender census in the [security audit](https://live.agent-fs.dev/file/~/648a5f3c-35c8-4f11-8673-b89de52cd6bd/2faf73ba-4eee-4472-8b3b-359c4ed6bfbb/thoughts/a09d19a4-bd35-4593-9b6f-c2ccafccead8/reviews/2026-09-28-github-sender-authorization-audit.md) when installing the extension; the template intentionally defaults to an empty list.\n\n`exemptTaskTypes` is an optional operator override for explicitly exempting task types. It defaults to an empty list. The GitHub handler does not pass the action for `github-pr` tasks, so external `github-pr` access also permits assignment and label events on pull requests.\n'
8385
+ },
8052
8386
  "notify-on-complete": {
8053
8387
  manifestFile: "manifest.json",
8054
8388
  manifest: {
@@ -14072,18 +14406,20 @@ async function handleMemory(req, res, pathSegments, callerAgentId) {
14072
14406
  source,
14073
14407
  isLead: false
14074
14408
  });
14075
- const ranked = rerank(expanded, { limit: Math.min(limit, 20) });
14409
+ const resultLimit = Math.min(limit, 20);
14410
+ const consumptionHeader = req.headers["x-memory-consumption"];
14411
+ const consumptionMode = Array.isArray(consumptionHeader) ? consumptionHeader[0] : consumptionHeader;
14412
+ const ranked = consumptionMode === "prompt" ? rerank(expanded, { limit: expanded.length }).map((r) => ({ r, eligible: memoryRelevance(r) > SIMILARITY_THRESHOLD })).sort((a, b) => Number(b.eligible) - Number(a.eligible)).slice(0, resultLimit).map(({ r }) => r) : rerank(expanded, { limit: resultLimit });
14076
14413
  const sourceTaskIdHeader = req.headers["x-source-task-id"];
14077
14414
  const sourceTaskId = Array.isArray(sourceTaskIdHeader) ? sourceTaskIdHeader[0] : sourceTaskIdHeader;
14078
14415
  const contextKeyHeader = req.headers["x-context-key"];
14079
14416
  const contextKey = Array.isArray(contextKeyHeader) ? contextKeyHeader[0] : contextKeyHeader;
14080
- const consumptionHeader = req.headers["x-memory-consumption"];
14081
- const consumptionMode = Array.isArray(consumptionHeader) ? consumptionHeader[0] : consumptionHeader;
14082
14417
  if (sourceTaskId && intent) {
14083
14418
  try {
14084
14419
  await recordRetrievals(sourceTaskId, myAgentId, ranked.map((r) => ({
14085
14420
  memoryId: r.id,
14086
14421
  similarity: r.similarity,
14422
+ relevance: r.rawSimilarity,
14087
14423
  retrievalSource: r.retrievalSource
14088
14424
  })), undefined, { intent, contextKey, eventType: "search" });
14089
14425
  } catch (err) {
@@ -14092,7 +14428,7 @@ async function handleMemory(req, res, pathSegments, callerAgentId) {
14092
14428
  }
14093
14429
  let consumedIds = [];
14094
14430
  if (intent) {
14095
- const consumed = consumptionMode === "prompt" ? ranked.filter((r) => r.similarity > SIMILARITY_THRESHOLD) : ranked;
14431
+ const consumed = consumptionMode === "prompt" ? ranked.filter((r) => memoryRelevance(r) > SIMILARITY_THRESHOLD) : ranked;
14096
14432
  consumedIds = dedupeMemoryDocumentIds(consumed);
14097
14433
  try {
14098
14434
  await recordMemoryAccesses(consumedIds);
@@ -14976,11 +15312,21 @@ async function handleMetrics(req, res, pathSegments, queryParams, myAgentId) {
14976
15312
 
14977
15313
  // src/http/models-catalog.ts
14978
15314
  init_zod();
15315
+ init_db();
15316
+ init_types();
15317
+ init_request_auth_context();
14979
15318
  var CatalogModelSchema = exports_external.object({
14980
15319
  id: exports_external.string(),
14981
15320
  name: exports_external.string().optional(),
14982
- cost: exports_external.object({ input: exports_external.number().optional(), output: exports_external.number().optional() }).optional(),
15321
+ cost: exports_external.object({
15322
+ input: exports_external.number().optional(),
15323
+ output: exports_external.number().optional(),
15324
+ cache_read: exports_external.number().optional(),
15325
+ cache_write: exports_external.number().optional()
15326
+ }).optional(),
14983
15327
  limit: exports_external.object({ context: exports_external.number().optional() }).optional(),
15328
+ release_date: exports_external.string().optional(),
15329
+ status: exports_external.string().optional(),
14984
15330
  reasoning: exports_external.boolean().optional(),
14985
15331
  reasoning_options: exports_external.array(exports_external.object({ type: exports_external.string(), values: exports_external.array(exports_external.string()).optional() })).optional()
14986
15332
  });
@@ -14989,6 +15335,55 @@ var CatalogProviderSchema = exports_external.object({
14989
15335
  name: exports_external.string().optional(),
14990
15336
  models: exports_external.record(exports_external.string(), CatalogModelSchema)
14991
15337
  });
15338
+ var ReasoningOptionSchema = exports_external.object({
15339
+ type: exports_external.string(),
15340
+ values: exports_external.array(exports_external.string()).optional()
15341
+ });
15342
+ var OverlayPricingSchema = exports_external.object({
15343
+ input: exports_external.number().nonnegative().optional(),
15344
+ output: exports_external.number().nonnegative().optional(),
15345
+ cache_read: exports_external.number().nonnegative().optional(),
15346
+ cache_write: exports_external.number().nonnegative().optional()
15347
+ });
15348
+ var ModelCatalogRefreshResultSchema = exports_external.object({
15349
+ status: exports_external.enum(["updated", "not-modified", "skipped-fresh", "skipped-cooldown", "error"]),
15350
+ models: exports_external.number(),
15351
+ added: exports_external.array(exports_external.string()),
15352
+ checkedAt: exports_external.number().nullable(),
15353
+ retryAfterMs: exports_external.number().optional(),
15354
+ error: exports_external.string().optional()
15355
+ });
15356
+ var ModelCatalogOverlayBodySchema = exports_external.object({
15357
+ provider: exports_external.string().min(1),
15358
+ modelId: exports_external.string().min(1),
15359
+ name: exports_external.string().optional(),
15360
+ family: exports_external.string().optional(),
15361
+ releaseDate: exports_external.string().optional(),
15362
+ contextWindow: exports_external.number().int().positive().optional(),
15363
+ maxOutput: exports_external.number().int().positive().optional(),
15364
+ reasoning: exports_external.boolean().optional(),
15365
+ reasoningOptions: exports_external.array(ReasoningOptionSchema).optional(),
15366
+ pricing: OverlayPricingSchema.optional(),
15367
+ status: exports_external.string().optional(),
15368
+ reason: exports_external.string().min(1),
15369
+ verifiedBy: exports_external.string().optional(),
15370
+ expiresWhenUpstreamMatches: exports_external.boolean().optional()
15371
+ });
15372
+ var OverlayEntrySchema = ModelCatalogOverlayBodySchema.extend({
15373
+ name: exports_external.string().nullish(),
15374
+ family: exports_external.string().nullish(),
15375
+ releaseDate: exports_external.string().nullish(),
15376
+ contextWindow: exports_external.number().nullish(),
15377
+ maxOutput: exports_external.number().nullish(),
15378
+ reasoning: exports_external.boolean().nullish(),
15379
+ reasoningOptions: exports_external.array(ReasoningOptionSchema).nullish(),
15380
+ pricing: OverlayPricingSchema.nullish(),
15381
+ status: exports_external.string().nullish(),
15382
+ verifiedBy: exports_external.string().nullish(),
15383
+ expiresWhenUpstreamMatches: exports_external.boolean(),
15384
+ createdAt: exports_external.number(),
15385
+ updatedAt: exports_external.number()
15386
+ });
14992
15387
  var getCatalog = route({
14993
15388
  method: "get",
14994
15389
  path: "/api/models-catalog",
@@ -15007,12 +15402,218 @@ var getCatalog = route({
15007
15402
  }
15008
15403
  }
15009
15404
  });
15405
+ var ModelTierPreviewSchema = exports_external.object({
15406
+ provider: ProviderNameSchema,
15407
+ tier: exports_external.enum(MODEL_TIERS),
15408
+ key: exports_external.string(),
15409
+ defaultValue: exports_external.string(),
15410
+ configured: exports_external.string().nullable(),
15411
+ source: exports_external.enum(["tier-config", "tier-default"]),
15412
+ resolvedModel: exports_external.string().nullable(),
15413
+ alias: exports_external.string().nullable()
15414
+ });
15415
+ var getTiers = route({
15416
+ method: "get",
15417
+ path: "/api/models-catalog/tiers",
15418
+ pattern: ["api", "models-catalog", "tiers"],
15419
+ summary: "Preview what each model tier resolves to per harness provider",
15420
+ description: "One row per provider and tier: the built-in default, the `MODEL_TIER_<PROVIDER>_<TIER>` value stored in swarm config (if any), which layer wins, and the concrete model it resolves to against the current catalog (`latest:` aliases resolved with the same soak and auto-upgrade rules as claim time, without recording a resolution). Ignores per-worker `MODEL_TIER_*` overrides and per-task models.",
15421
+ tags: ["Pricing"],
15422
+ responses: {
15423
+ 200: {
15424
+ description: "Tier previews",
15425
+ schema: exports_external.object({ tiers: exports_external.array(ModelTierPreviewSchema) })
15426
+ }
15427
+ }
15428
+ });
15429
+ var refreshCatalog = route({
15430
+ method: "post",
15431
+ path: "/api/models-catalog/refresh",
15432
+ pattern: ["api", "models-catalog", "refresh"],
15433
+ summary: "Refresh the model catalog from models.dev",
15434
+ description: "Unforced calls skip the network when the last models.dev check is younger than 4h (`skipped-fresh`). `force: true` always fetches, still conditional on the stored ETag (`not-modified` on 304), but a forced call within a minute of the previous one returns `skipped-cooldown` with `retryAfterMs`. Concurrent refreshes share one fetch. Lead agent or operator only. `added` lists provider/modelId keys new since the previous fetch.",
15435
+ tags: ["Pricing"],
15436
+ rbac: { permission: "models.catalog.write" },
15437
+ body: exports_external.object({ force: exports_external.boolean().optional() }),
15438
+ responses: {
15439
+ 200: { description: "Refresh outcome", schema: ModelCatalogRefreshResultSchema },
15440
+ 403: { description: "Forbidden" }
15441
+ }
15442
+ });
15443
+ var upsertOverlay = route({
15444
+ method: "put",
15445
+ path: "/api/models-catalog/overlay",
15446
+ pattern: ["api", "models-catalog", "overlay"],
15447
+ summary: "Upsert one model-catalog overlay row",
15448
+ description: "Overlay facts win per non-null field over the models.dev row; overlay-only models are served too. Overlay prices fill pricing-table gaps (never override an active price). With `expiresWhenUpstreamMatches` (default true) the row is deleted once upstream matches every non-null fact.",
15449
+ tags: ["Pricing"],
15450
+ rbac: { permission: "models.catalog.write" },
15451
+ body: ModelCatalogOverlayBodySchema,
15452
+ responses: {
15453
+ 200: { description: "Overlay row upserted", schema: OverlayEntrySchema },
15454
+ 403: { description: "Forbidden" }
15455
+ }
15456
+ });
15457
+ var deleteOverlay = route({
15458
+ method: "delete",
15459
+ path: "/api/models-catalog/overlay",
15460
+ pattern: ["api", "models-catalog", "overlay"],
15461
+ summary: "Delete one model-catalog overlay row",
15462
+ tags: ["Pricing"],
15463
+ rbac: { permission: "models.catalog.write" },
15464
+ body: exports_external.object({ provider: exports_external.string().min(1), modelId: exports_external.string().min(1) }),
15465
+ responses: {
15466
+ 200: { description: "Overlay row deleted", schema: exports_external.object({ deleted: exports_external.boolean() }) },
15467
+ 403: { description: "Forbidden" }
15468
+ }
15469
+ });
15470
+ var HarnessSupportRowSchema = exports_external.object({
15471
+ harness: exports_external.string(),
15472
+ cliVersion: exports_external.string(),
15473
+ modelId: exports_external.string(),
15474
+ status: exports_external.enum(["ok", "unsupported", "unknown"]),
15475
+ checkedAt: exports_external.number(),
15476
+ error: exports_external.string().nullable()
15477
+ });
15478
+ var listHarnessSupport = route({
15479
+ method: "get",
15480
+ path: "/api/models-catalog/harness-support",
15481
+ pattern: ["api", "models-catalog", "harness-support"],
15482
+ summary: "List harness CLI model support rows",
15483
+ description: "Whether a catalog model runs on a given `claude` / `codex` CLI version, as recorded by workers after a model's first run. No row means unknown (allowed at claim).",
15484
+ tags: ["Pricing"],
15485
+ query: exports_external.object({ harness: exports_external.string().optional(), cliVersion: exports_external.string().optional() }),
15486
+ responses: {
15487
+ 200: {
15488
+ description: "Support rows, newest first",
15489
+ schema: exports_external.object({ rows: exports_external.array(HarnessSupportRowSchema) })
15490
+ }
15491
+ }
15492
+ });
15493
+ var recordHarnessSupport = route({
15494
+ method: "put",
15495
+ path: "/api/models-catalog/harness-support",
15496
+ pattern: ["api", "models-catalog", "harness-support"],
15497
+ summary: "Record whether a harness CLI version accepts a model",
15498
+ description: "Written by workers: `ok` after a model's first successful run, `unsupported` when the CLI rejects the model id. Claim-time resolution falls back (alias/tier) or fails fast (explicit model) on `unsupported`.",
15499
+ tags: ["Pricing"],
15500
+ rbac: { permission: "models.harness-support.write" },
15501
+ body: exports_external.object({
15502
+ harness: exports_external.string().min(1).max(32),
15503
+ cliVersion: exports_external.string().min(1).max(64),
15504
+ modelId: exports_external.string().min(1).max(200),
15505
+ status: exports_external.enum(["ok", "unsupported", "unknown"]),
15506
+ error: exports_external.string().max(4000).optional()
15507
+ }),
15508
+ responses: {
15509
+ 200: { description: "Support row upserted", schema: HarnessSupportRowSchema },
15510
+ 403: { description: "Forbidden" }
15511
+ }
15512
+ });
15513
+ async function ensureCatalogWriter(req, res, verb = "models.catalog.write") {
15514
+ const auth = getRequestAuth(req);
15515
+ const header2 = req.headers["x-agent-id"];
15516
+ const agentId = auth?.kind === "agent" ? auth.agentId : Array.isArray(header2) ? header2[0] : header2;
15517
+ let principal;
15518
+ if (auth?.kind === "user") {
15519
+ principal = { kind: "user", userId: auth.userId };
15520
+ } else if (agentId) {
15521
+ const agent = await getAgentById(agentId);
15522
+ principal = { kind: "agent", agentId, isLead: agent?.isLead ?? false };
15523
+ } else if (auth?.kind === "operator") {
15524
+ principal = { kind: "operator" };
15525
+ } else {
15526
+ principal = { kind: "agent", agentId: "", isLead: false };
15527
+ }
15528
+ const decision = can({
15529
+ principal,
15530
+ verb,
15531
+ resource: { kind: "none" },
15532
+ source: "http"
15533
+ });
15534
+ if (!decision.allow) {
15535
+ jsonError(res, verb === "models.catalog.write" ? "Writing the model catalog requires the lead agent or an operator" : "Recording harness model support requires a registered agent or an operator", 403);
15536
+ return null;
15537
+ }
15538
+ return {
15539
+ userId: auth?.kind === "user" ? auth.userId : null,
15540
+ agentId: principal.kind === "agent" && principal.agentId ? principal.agentId : null
15541
+ };
15542
+ }
15543
+ async function callerOwnsSupportRow(agentId, body) {
15544
+ const agent = await getAgentById(agentId);
15545
+ if (!agent || agent.harnessProvider !== body.harness)
15546
+ return false;
15547
+ return await getAgentHarnessCliVersion(agentId) === body.cliVersion;
15548
+ }
15010
15549
  async function handleModelsCatalog(req, res, pathSegments, queryParams) {
15011
15550
  if (getCatalog.match(req.method, pathSegments)) {
15012
15551
  const parsed = await getCatalog.parse(req, res, pathSegments, queryParams);
15013
15552
  if (!parsed)
15014
15553
  return true;
15015
- json(res, getModelsCatalog());
15554
+ getCatalog.respond(res, 200, await loadModelsCatalog());
15555
+ return true;
15556
+ }
15557
+ if (getTiers.match(req.method, pathSegments)) {
15558
+ const parsed = await getTiers.parse(req, res, pathSegments, queryParams);
15559
+ if (!parsed)
15560
+ return true;
15561
+ getTiers.respond(res, 200, { tiers: await previewModelTiers() });
15562
+ return true;
15563
+ }
15564
+ if (refreshCatalog.match(req.method, pathSegments)) {
15565
+ const parsed = await refreshCatalog.parse(req, res, pathSegments, queryParams);
15566
+ if (!parsed)
15567
+ return true;
15568
+ if (!await ensureCatalogWriter(req, res))
15569
+ return true;
15570
+ refreshCatalog.respond(res, 200, await requestModelCatalogRefresh({ force: parsed.body.force }));
15571
+ return true;
15572
+ }
15573
+ if (upsertOverlay.match(req.method, pathSegments)) {
15574
+ const parsed = await upsertOverlay.parse(req, res, pathSegments, queryParams);
15575
+ if (!parsed)
15576
+ return true;
15577
+ const writer = await ensureCatalogWriter(req, res);
15578
+ if (!writer)
15579
+ return true;
15580
+ const entry = await upsertModelCatalogOverlay(parsed.body, { userId: writer.userId });
15581
+ upsertOverlay.respond(res, 200, entry);
15582
+ return true;
15583
+ }
15584
+ if (deleteOverlay.match(req.method, pathSegments)) {
15585
+ const parsed = await deleteOverlay.parse(req, res, pathSegments, queryParams);
15586
+ if (!parsed)
15587
+ return true;
15588
+ if (!await ensureCatalogWriter(req, res))
15589
+ return true;
15590
+ const deleted = await deleteModelCatalogOverlay(parsed.body.provider, parsed.body.modelId);
15591
+ deleteOverlay.respond(res, 200, { deleted });
15592
+ return true;
15593
+ }
15594
+ if (listHarnessSupport.match(req.method, pathSegments)) {
15595
+ const parsed = await listHarnessSupport.parse(req, res, pathSegments, queryParams);
15596
+ if (!parsed)
15597
+ return true;
15598
+ listHarnessSupport.respond(res, 200, { rows: await listHarnessModelSupport(parsed.query) });
15599
+ return true;
15600
+ }
15601
+ if (recordHarnessSupport.match(req.method, pathSegments)) {
15602
+ const parsed = await recordHarnessSupport.parse(req, res, pathSegments, queryParams);
15603
+ if (!parsed)
15604
+ return true;
15605
+ const writer = await ensureCatalogWriter(req, res, "models.harness-support.write");
15606
+ if (!writer)
15607
+ return true;
15608
+ if (writer.agentId && !await callerOwnsSupportRow(writer.agentId, parsed.body)) {
15609
+ jsonError(res, "Harness support can only be recorded for the calling agent's own harness and registered CLI version", 403);
15610
+ return true;
15611
+ }
15612
+ if (writer.agentId && parsed.body.status === "unsupported" && !(isUnknownModelError(parsed.body.error, parsed.body.modelId) && await agentRanModel(writer.agentId, parsed.body.modelId))) {
15613
+ jsonError(res, "An unsupported report needs a model the calling agent ran and the CLI's model-rejection error", 403);
15614
+ return true;
15615
+ }
15616
+ recordHarnessSupport.respond(res, 200, await recordHarnessModelSupport(parsed.body));
15016
15617
  return true;
15017
15618
  }
15018
15619
  return false;
@@ -15803,11 +16404,19 @@ function slackMilestone(state) {
15803
16404
  action_url: automationIntegrationFixUrl("slack")
15804
16405
  };
15805
16406
  }
16407
+ if (config.mode === "socket" && getSlackConnectionState() === "connected") {
16408
+ return {
16409
+ id: "slack",
16410
+ label: "Slack configured",
16411
+ state: "verified",
16412
+ action_url: automationIntegrationFixUrl("slack")
16413
+ };
16414
+ }
15806
16415
  return {
15807
16416
  id: "slack",
15808
16417
  label: "Slack configured",
15809
16418
  state: "configured",
15810
- hint: config.mode === "http" ? "HTTP credentials are configured, but HTTP ingress is unavailable until the receiver is installed." : "Socket Mode credentials are configured; a live connection has not been verified.",
16419
+ hint: config.mode === "http" ? "HTTP credentials are configured, but HTTP ingress is unavailable until the receiver is installed." : "Socket Mode credentials are configured, but the bot is not connected to Slack.",
15811
16420
  action_url: automationIntegrationFixUrl("slack")
15812
16421
  };
15813
16422
  }
@@ -17663,7 +18272,9 @@ var pollTriggers = route({
17663
18272
  summary: "Poll for triggers (tasks, mentions)",
17664
18273
  tags: ["Poll"],
17665
18274
  auth: { apiKey: true, agentId: true },
17666
- headers: runtimeInstanceHeader("poll for work"),
18275
+ headers: runtimeInstanceHeader("poll for work").extend({
18276
+ "X-Model-Tier-Overrides": exports_external.string().optional().describe("URL-encoded JSON {provider: {tier: model}} of the worker's MODEL_TIER_* env overrides. " + "Stored on the agent row and applied at claim time (modelSource=worker-env).")
18277
+ }),
17667
18278
  responses: {
17668
18279
  200: { description: "Trigger data or null", schema: pollResponseSchema },
17669
18280
  400: { description: "Missing X-Agent-ID" },
@@ -17700,6 +18311,14 @@ async function attachmentsForTrigger(taskId) {
17700
18311
  sizeBytes: a.sizeBytes
17701
18312
  }));
17702
18313
  }
18314
+ async function claimModelFields(task, agent) {
18315
+ try {
18316
+ return await recordClaimModelResolution(task, agent);
18317
+ } catch (error) {
18318
+ console.warn(`[/api/poll] model resolution failed for task ${task.id}:`, error);
18319
+ return {};
18320
+ }
18321
+ }
17703
18322
  var commitCursorsRoute = route({
17704
18323
  method: "post",
17705
18324
  path: "/api/channel-activity/commit-cursors",
@@ -17723,6 +18342,7 @@ var commitCursorsRoute = route({
17723
18342
  });
17724
18343
  async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
17725
18344
  const runtimeInstanceId = ((h) => Array.isArray(h) ? h[0] : h)(req.headers["x-runtime-instance-id"]);
18345
+ const modelTierOverrides = parseModelTierOverridesHeader(((h) => Array.isArray(h) ? h[0] : h)(req.headers["x-model-tier-overrides"]));
17726
18346
  if (commitCursorsRoute.match(req.method, pathSegments)) {
17727
18347
  const parsed = await commitCursorsRoute.parse(req, res, pathSegments, queryParams);
17728
18348
  if (!parsed)
@@ -17750,6 +18370,9 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
17750
18370
  if (!agent) {
17751
18371
  return { error: "Agent not found", status: 404 };
17752
18372
  }
18373
+ if (modelTierOverrides) {
18374
+ await setAgentModelTierOverrides(agent.id, modelTierOverrides);
18375
+ }
17753
18376
  if (isExtensionAgent(agent)) {
17754
18377
  return { trigger: null };
17755
18378
  }
@@ -17847,6 +18470,7 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
17847
18470
  taskId: pendingTask.id,
17848
18471
  task: {
17849
18472
  ...pendingTask,
18473
+ ...await claimModelFields(pendingTask, agent),
17850
18474
  status: "in_progress",
17851
18475
  attachments: await attachmentsForTrigger(pendingTask.id)
17852
18476
  },
@@ -17931,7 +18555,11 @@ async function handlePoll(req, res, pathSegments, queryParams, myAgentId) {
17931
18555
  trigger: {
17932
18556
  type: "task_assigned",
17933
18557
  taskId: claimed.id,
17934
- task: { ...claimed, attachments: await attachmentsForTrigger(claimed.id) },
18558
+ task: {
18559
+ ...claimed,
18560
+ ...await claimModelFields(claimed, agent),
18561
+ attachments: await attachmentsForTrigger(claimed.id)
18562
+ },
17935
18563
  ...claimedRequestedBy && { requestedBy: claimedRequestedBy }
17936
18564
  }
17937
18565
  };
@@ -19093,6 +19721,7 @@ var scheduleUpdateBodySchema = exports_external.object({
19093
19721
  timezone: exports_external.string().optional(),
19094
19722
  model: exports_external.string().nullable().optional(),
19095
19723
  modelTier: ModelTierSchema.nullable().optional(),
19724
+ allowCustomModel: exports_external.boolean().optional(),
19096
19725
  nextRunAt: exports_external.string().nullable().optional(),
19097
19726
  targetType: ScheduledTaskTargetTypeSchema.optional(),
19098
19727
  workflowId: exports_external.string().uuid().nullable().optional(),
@@ -19133,6 +19762,7 @@ var createSchedule = route({
19133
19762
  timezone: exports_external.string().optional(),
19134
19763
  model: exports_external.string().optional(),
19135
19764
  modelTier: ModelTierSchema.optional(),
19765
+ allowCustomModel: exports_external.boolean().optional(),
19136
19766
  scheduleType: exports_external.enum(["recurring", "one_time"]).optional(),
19137
19767
  targetType: ScheduledTaskTargetTypeSchema.optional(),
19138
19768
  workflowId: exports_external.string().uuid().optional(),
@@ -19370,6 +20000,15 @@ async function handleSchedules(req, res, pathSegments, queryParams, myAgentId) {
19370
20000
  return true;
19371
20001
  }
19372
20002
  }
20003
+ const modelError = await explicitModelErrorForAgent({
20004
+ model: splitLegacyModelAlias({ model: body.model, modelTier: body.modelTier }).model,
20005
+ allowCustomModel: body.allowCustomModel,
20006
+ agentId: body.targetAgentId
20007
+ });
20008
+ if (modelError) {
20009
+ jsonError(res, modelError, 400);
20010
+ return true;
20011
+ }
19373
20012
  try {
19374
20013
  const trustedUserId = await resolveHttpAuditUserId(req, myAgentId);
19375
20014
  let key;
@@ -19498,22 +20137,35 @@ async function handleSchedules(req, res, pathSegments, queryParams, myAgentId) {
19498
20137
  throw error;
19499
20138
  }
19500
20139
  }
20140
+ const allowCustomModel = parsed.body.allowCustomModel;
20141
+ delete body.allowCustomModel;
20142
+ const existing = await getScheduledTaskById(parsed.params.id);
20143
+ if (!existing) {
20144
+ jsonError(res, "Schedule not found", 404);
20145
+ return true;
20146
+ }
19501
20147
  if (parsed.body.model !== undefined || parsed.body.modelTier !== undefined) {
19502
20148
  const normalizedModel = splitLegacyModelAlias({
19503
20149
  model: parsed.body.model,
19504
20150
  modelTier: parsed.body.modelTier
19505
20151
  });
20152
+ if (normalizedModel.model !== existing.model) {
20153
+ const modelError = await explicitModelErrorForAgent({
20154
+ model: normalizedModel.model,
20155
+ allowCustomModel,
20156
+ agentId: parsed.body.targetAgentId ?? existing.targetAgentId
20157
+ });
20158
+ if (modelError) {
20159
+ jsonError(res, modelError, 400);
20160
+ return true;
20161
+ }
20162
+ }
19506
20163
  if (parsed.body.model !== undefined)
19507
20164
  body.model = normalizedModel.model ?? null;
19508
20165
  if (parsed.body.modelTier !== undefined || normalizedModel.modelTier) {
19509
20166
  body.modelTier = normalizedModel.modelTier ?? null;
19510
20167
  }
19511
20168
  }
19512
- const existing = await getScheduledTaskById(parsed.params.id);
19513
- if (!existing) {
19514
- jsonError(res, "Schedule not found", 404);
19515
- return true;
19516
- }
19517
20169
  if (existing.scheduleType === "one_time" && !existing.enabled && existing.lastRunAt) {
19518
20170
  jsonError(res, "One-time schedule has already executed. Create a new one instead.", 400);
19519
20171
  return true;
@@ -23348,7 +24000,7 @@ var createSessionCostRoute = route({
23348
24000
  model: exports_external.string().optional(),
23349
24001
  models: exports_external.array(SessionCostModelBreakdownSchema.omit({ costUsd: true })).optional(),
23350
24002
  isError: exports_external.boolean().optional(),
23351
- provider: exports_external.enum(["claude", "claude-managed", "codex", "pi", "opencode", "devin", "gemini", "acp"]).optional(),
24003
+ provider: PricingProviderSchema.optional(),
23352
24004
  createdAt: exports_external.number().int().nonnegative().optional()
23353
24005
  }),
23354
24006
  responses: {
@@ -23547,8 +24199,7 @@ async function handleSessionData(req, res, pathSegments, queryParams, _myAgentId
23547
24199
  userId: parsed.query.userId || undefined,
23548
24200
  groupBy: parsed.query.groupBy || "both"
23549
24201
  };
23550
- const version = await getUsageDataVersion();
23551
- const summary = await cachedUsageReport(`summary:${version}:${JSON.stringify(opts)}`, () => getSessionCostSummary(opts));
24202
+ const summary = await cachedUsageReport(`summary:${JSON.stringify(opts)}`, () => getSessionCostSummary(opts));
23552
24203
  getSessionCostSummaryRoute.respond(res, 200, summary);
23553
24204
  return true;
23554
24205
  }
@@ -23565,8 +24216,7 @@ async function handleSessionData(req, res, pathSegments, queryParams, _myAgentId
23565
24216
  startDate: parsed.query.startDate || undefined,
23566
24217
  endDate: parsed.query.endDate || undefined
23567
24218
  };
23568
- const version = await getUsageDataVersion();
23569
- const rows = await cachedUsageReport(`attribution:${version}:${JSON.stringify(opts)}`, () => getAttributionByPerson(opts));
24219
+ const rows = await cachedUsageReport(`attribution:${JSON.stringify(opts)}`, () => getAttributionByPerson(opts));
23570
24220
  getAttributionByPersonRoute.respond(res, 200, { rows });
23571
24221
  return true;
23572
24222
  }
@@ -23700,6 +24350,7 @@ var listSessions = route({
23700
24350
  source: exports_external.string().optional(),
23701
24351
  q: exports_external.string().optional(),
23702
24352
  requestedByUserId: exports_external.string().min(1).optional(),
24353
+ contextKeyPrefix: exports_external.string().min(1).optional(),
23703
24354
  fields: exports_external.enum(["full", "slim"]).optional()
23704
24355
  }),
23705
24356
  responses: {
@@ -23773,13 +24424,15 @@ async function handleSessions(req, res, pathSegments, queryParams) {
23773
24424
  offset: parsed.query.offset,
23774
24425
  source: sources,
23775
24426
  q: parsed.query.q,
23776
- requestedByUserId: parsed.query.requestedByUserId
24427
+ requestedByUserId: parsed.query.requestedByUserId,
24428
+ contextKeyPrefix: parsed.query.contextKeyPrefix
23777
24429
  };
23778
24430
  const sessions = parsed.query.fields === "full" ? await listRecentSessions(baseOpts) : await listRecentSessions({ ...baseOpts, slim: true });
23779
24431
  const total = await countSessions({
23780
24432
  source: sources,
23781
24433
  q: parsed.query.q,
23782
- requestedByUserId: parsed.query.requestedByUserId
24434
+ requestedByUserId: parsed.query.requestedByUserId,
24435
+ contextKeyPrefix: parsed.query.contextKeyPrefix
23783
24436
  });
23784
24437
  listSessions.respond(res, 200, {
23785
24438
  sessions,
@@ -23799,18 +24452,17 @@ async function handleSessions(req, res, pathSegments, queryParams) {
23799
24452
  return true;
23800
24453
  }
23801
24454
  const chain = await getRootTaskChain(parsed.params.rootTaskId);
23802
- getSession.respond(res, 200, {
23803
- root: {
23804
- ...root,
23805
- ...await getTaskSteeringFields(root),
23806
- citations: await getTaskCitations(root.id)
23807
- },
23808
- chain: await Promise.all(chain.map(async (task) => ({
23809
- ...task,
23810
- ...await getTaskSteeringFields(task),
23811
- citations: await getTaskCitations(task.id)
23812
- })))
24455
+ const tasks = [root, ...chain];
24456
+ const [steering, citations] = await Promise.all([
24457
+ getTaskSteeringFieldsForTasks(tasks),
24458
+ getTaskCitationsForTasks(tasks.map((task) => task.id))
24459
+ ]);
24460
+ const decorate = (task) => ({
24461
+ ...task,
24462
+ ...steering.get(task.id),
24463
+ citations: citations.get(task.id)
23813
24464
  });
24465
+ getSession.respond(res, 200, { root: decorate(root), chain: chain.map(decorate) });
23814
24466
  return true;
23815
24467
  }
23816
24468
  return false;
@@ -24597,6 +25249,7 @@ init_zod();
24597
25249
  init_db();
24598
25250
  init_steering();
24599
25251
  init_types();
25252
+ init_env_flag();
24600
25253
  var AgentCountsSchema = exports_external.object({
24601
25254
  total: exports_external.number(),
24602
25255
  idle: exports_external.number(),
@@ -24618,7 +25271,8 @@ var DashboardStatsSchema = exports_external.object({
24618
25271
  agents: AgentCountsSchema,
24619
25272
  tasks: TaskCountsSchema,
24620
25273
  steeringEnabled: exports_external.boolean(),
24621
- multiRuntimeEnabled: exports_external.boolean()
25274
+ multiRuntimeEnabled: exports_external.boolean(),
25275
+ devMode: exports_external.boolean()
24622
25276
  });
24623
25277
  var RetentionTableStatsSchema = exports_external.object({
24624
25278
  at: exports_external.string(),
@@ -24732,6 +25386,7 @@ var listScheduledTasks = route({
24732
25386
  path: "/api/scheduled-tasks",
24733
25387
  pattern: ["api", "scheduled-tasks"],
24734
25388
  summary: "List scheduled tasks",
25389
+ description: "Returns full schedules by default. Pass `fields=slim` for the list-view shape, which swaps the full `taskTemplate` for a bounded `taskTemplatePreview`. Fetch one schedule in full via `GET /api/schedules/{id}`.",
24735
25390
  tags: ["Stats"],
24736
25391
  query: exports_external.object({
24737
25392
  enabled: exports_external.enum(["true", "false"]).optional(),
@@ -24740,12 +25395,18 @@ var listScheduledTasks = route({
24740
25395
  hideCompleted: exports_external.enum(["true", "false"]).optional(),
24741
25396
  targetType: exports_external.enum(["agent-task", "workflow", "script"]).optional(),
24742
25397
  workflowId: exports_external.string().uuid().optional(),
24743
- scriptName: exports_external.string().optional()
25398
+ scriptName: exports_external.string().optional(),
25399
+ fields: exports_external.enum(["full", "slim"]).optional()
24744
25400
  }),
24745
25401
  responses: {
24746
25402
  200: {
24747
25403
  description: "Scheduled tasks list",
24748
- schema: exports_external.object({ scheduledTasks: exports_external.array(ScheduledTaskSchema) })
25404
+ schema: exports_external.object({
25405
+ scheduledTasks: exports_external.union([
25406
+ exports_external.array(ScheduledTaskSchema),
25407
+ exports_external.array(scheduleSummaryWithFavoriteSchema)
25408
+ ])
25409
+ })
24749
25410
  }
24750
25411
  }
24751
25412
  });
@@ -24776,15 +25437,10 @@ async function handleStats(req, res, pathSegments, queryParams, myAgentId) {
24776
25437
  return true;
24777
25438
  }
24778
25439
  if (getStats.match(req.method, pathSegments)) {
24779
- const agents = await getAllAgents();
25440
+ const agents = await getAgentStatusCounts();
24780
25441
  const taskStats = await getTaskStats();
24781
25442
  const stats = {
24782
- agents: {
24783
- total: agents.length,
24784
- idle: agents.filter((a) => a.status === "idle").length,
24785
- busy: agents.filter((a) => a.status === "busy").length,
24786
- offline: agents.filter((a) => a.status === "offline").length
24787
- },
25443
+ agents,
24788
25444
  tasks: {
24789
25445
  total: taskStats.total,
24790
25446
  unassigned: taskStats.unassigned,
@@ -24797,6 +25453,7 @@ async function handleStats(req, res, pathSegments, queryParams, myAgentId) {
24797
25453
  failed: taskStats.failed
24798
25454
  },
24799
25455
  steeringEnabled: isSteeringEnabled2(),
25456
+ devMode: isEnvFlagEnabled("SWARM_DEV_MODE", false),
24800
25457
  multiRuntimeEnabled: isMultiRuntimeEnabled()
24801
25458
  };
24802
25459
  getStats.respond(res, 200, stats);
@@ -24825,7 +25482,7 @@ async function handleStats(req, res, pathSegments, queryParams, myAgentId) {
24825
25482
  const parsed = await listScheduledTasks.parse(req, res, pathSegments, queryParams);
24826
25483
  if (!parsed)
24827
25484
  return true;
24828
- const scheduledTasks = await getScheduledTasks({
25485
+ const filters = {
24829
25486
  enabled: parsed.query.enabled !== undefined ? parsed.query.enabled === "true" : undefined,
24830
25487
  name: parsed.query.name || undefined,
24831
25488
  scheduleType: parsed.query.scheduleType || undefined,
@@ -24833,13 +25490,11 @@ async function handleStats(req, res, pathSegments, queryParams, myAgentId) {
24833
25490
  targetType: parsed.query.targetType,
24834
25491
  workflowId: parsed.query.workflowId,
24835
25492
  scriptName: parsed.query.scriptName
24836
- });
25493
+ };
24837
25494
  const favoriteScope = (await resolveHttpFavoriteOwner(req, myAgentId))?.scope;
25495
+ const favoriteOpts = { favoriteScope, itemType: "schedule" };
24838
25496
  listScheduledTasks.respond(res, 200, {
24839
- scheduledTasks: await withFavoriteFlags(scheduledTasks, {
24840
- favoriteScope,
24841
- itemType: "schedule"
24842
- })
25497
+ scheduledTasks: parsed.query.fields === "slim" ? await withFavoriteFlags(await getScheduledTasks(filters, { slim: true }), favoriteOpts) : await withFavoriteFlags(await getScheduledTasks(filters), favoriteOpts)
24843
25498
  });
24844
25499
  return true;
24845
25500
  }
@@ -24917,6 +25572,9 @@ var AgentTaskSummarySchema2 = AgentTaskSchema.pick({
24917
25572
  scheduleId: true,
24918
25573
  model: true,
24919
25574
  modelTier: true,
25575
+ resolvedModel: true,
25576
+ modelSource: true,
25577
+ modelAlias: true,
24920
25578
  effort: true,
24921
25579
  provider: true,
24922
25580
  requestedByUserId: true,
@@ -24927,6 +25585,19 @@ var AgentTaskSummarySchema2 = AgentTaskSchema.pick({
24927
25585
  peakContextPercent: true,
24928
25586
  totalCostUsd: true
24929
25587
  });
25588
+ var AgentTaskTimelineItemSchema = AgentTaskSchema.pick({
25589
+ id: true,
25590
+ agentId: true,
25591
+ parentTaskId: true,
25592
+ task: true,
25593
+ title: true,
25594
+ status: true,
25595
+ createdAt: true,
25596
+ lastUpdatedAt: true,
25597
+ finishedAt: true,
25598
+ peakContextTokens: true,
25599
+ totalCostUsd: true
25600
+ });
24930
25601
  var TaskActionResultSchema = exports_external.object({
24931
25602
  success: exports_external.literal(true),
24932
25603
  task: AgentTaskSchema
@@ -24971,7 +25642,7 @@ var listTasks = route({
24971
25642
  path: "/api/tasks",
24972
25643
  pattern: ["api", "tasks"],
24973
25644
  summary: "List tasks with filters",
24974
- description: "Returns tasks with the full `task` text replaced by a bounded `taskPreview` and completion/integration blobs dropped by default — list views only need the preview. Pass `fields=full` to restore the full `AgentTask`. Fetch a single task in full via `GET /api/tasks/{id}`.",
25645
+ description: "Returns tasks with the full `task` text replaced by a bounded `taskPreview` and completion/integration blobs dropped by default — list views only need the preview. Pass `fields=full` to restore the full `AgentTask`, or `fields=timeline` for the narrow shape the dashboard timeline draws. Fetch a single task in full via `GET /api/tasks/{id}`. `total` (the filtered row count, ignoring limit/offset) is computed only with `includeTotal=true`.",
24975
25646
  tags: ["Tasks"],
24976
25647
  query: exports_external.object({
24977
25648
  status: exports_external.string().optional(),
@@ -24988,14 +25659,19 @@ var listTasks = route({
24988
25659
  orderBy: exports_external.enum(["lastUpdatedAt", "createdAt"]).optional(),
24989
25660
  limit: exports_external.coerce.number().int().optional(),
24990
25661
  offset: exports_external.coerce.number().int().optional(),
24991
- fields: exports_external.enum(["full", "slim"]).optional()
25662
+ fields: exports_external.enum(["full", "slim", "timeline"]).optional(),
25663
+ includeTotal: exports_external.enum(["true", "false"]).optional()
24992
25664
  }),
24993
25665
  responses: {
24994
25666
  200: {
24995
25667
  description: "Paginated task list",
24996
25668
  schema: exports_external.object({
24997
- tasks: exports_external.union([exports_external.array(AgentTaskSchema), exports_external.array(AgentTaskSummarySchema2)]),
24998
- total: exports_external.number().int()
25669
+ tasks: exports_external.union([
25670
+ exports_external.array(AgentTaskSchema),
25671
+ exports_external.array(AgentTaskSummarySchema2),
25672
+ exports_external.array(AgentTaskTimelineItemSchema)
25673
+ ]),
25674
+ total: exports_external.number().int().optional()
24999
25675
  })
25000
25676
  },
25001
25677
  400: { description: "Validation error (e.g. unknown status token)" }
@@ -25026,6 +25702,7 @@ var createTask = route({
25026
25702
  requestedByUserId: exports_external.string().optional(),
25027
25703
  model: exports_external.string().optional(),
25028
25704
  modelTier: ModelTierSchema.optional(),
25705
+ allowCustomModel: exports_external.boolean().optional(),
25029
25706
  effort: ReasoningEffortSchema.optional(),
25030
25707
  draft: exports_external.boolean().optional()
25031
25708
  }).superRefine((body, ctx) => {
@@ -25039,7 +25716,9 @@ var createTask = route({
25039
25716
  }),
25040
25717
  responses: {
25041
25718
  201: { description: "Task created", schema: AgentTaskSchema },
25042
- 400: { description: "Validation error, or agentId/offeredTo targets an extension identity" },
25719
+ 400: {
25720
+ description: "Validation error, an unknown `model` (set `allowCustomModel` to store a custom id), or agentId/offeredTo targets an extension identity"
25721
+ },
25043
25722
  422: {
25044
25723
  description: "Task creation blocked by an extension",
25045
25724
  schema: exports_external.object({
@@ -25489,9 +26168,13 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
25489
26168
  limit: parsed.query.limit,
25490
26169
  offset: parsed.query.offset
25491
26170
  };
25492
- const tasks = parsed.query.fields === "full" ? await getAllTasks(filters) : await getAllTasks(filters, { slim: true });
25493
- const total = await getTasksCount(filters);
25494
- listTasks.respond(res, 200, { tasks, total });
26171
+ const tasks = parsed.query.fields === "full" ? await getAllTasks(filters) : parsed.query.fields === "timeline" ? await getAllTasks(filters, { fields: "timeline" }) : await getAllTasks(filters, { slim: true });
26172
+ if (parsed.query.includeTotal === "true") {
26173
+ const total = await getTasksCount(filters);
26174
+ listTasks.respond(res, 200, { tasks, total });
26175
+ } else {
26176
+ listTasks.respond(res, 200, { tasks });
26177
+ }
25495
26178
  return true;
25496
26179
  }
25497
26180
  if (createTask.match(req.method, pathSegments)) {
@@ -25512,6 +26195,15 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
25512
26195
  if (lead)
25513
26196
  defaultAgentId = lead.id;
25514
26197
  }
26198
+ const modelError = await explicitModelErrorForAgent({
26199
+ model: splitLegacyModelAlias({ model: parsed.body.model, modelTier: parsed.body.modelTier }).model,
26200
+ allowCustomModel: parsed.body.allowCustomModel,
26201
+ agentId: defaultAgentId
26202
+ });
26203
+ if (modelError) {
26204
+ jsonError(res, modelError, 400);
26205
+ return true;
26206
+ }
25515
26207
  const parentTask = parsed.body.parentTaskId ? await getTaskById(parsed.body.parentTaskId) : null;
25516
26208
  let assetKey;
25517
26209
  try {
@@ -26189,6 +26881,7 @@ async function handleTasks(req, res, pathSegments, queryParams, myAgentId) {
26189
26881
  reason: parsed.body.reason
26190
26882
  });
26191
26883
  if (followUp.kind !== "created") {
26884
+ await settleSupersededTaskDependents(parsed.params.id, null);
26192
26885
  console.warn(`[Supersede] Task ${parsed.params.id.slice(0, 8)} superseded but resume creation skipped (${followUp.kind === "skipped" ? followUp.reason : followUp.kind})`);
26193
26886
  supersedeTaskRoute.respond(res, 200, {
26194
26887
  success: true,
@@ -27890,8 +28583,21 @@ async function routeKapsoInbound(payload) {
27890
28583
  init_event_bus();
27891
28584
  var WebhookDispatchResultSchema = exports_external.object({
27892
28585
  created: exports_external.boolean(),
27893
- taskId: exports_external.string().optional()
28586
+ taskId: exports_external.string().optional(),
28587
+ skipped: exports_external.boolean().optional(),
28588
+ reason: exports_external.string().optional(),
28589
+ extension: exports_external.object({ id: exports_external.string(), name: exports_external.string() }).optional()
27894
28590
  });
28591
+ async function runBlockableHandler(source, handler) {
28592
+ try {
28593
+ return await handler();
28594
+ } catch (err) {
28595
+ if (!(err instanceof TaskCreationBlockedError))
28596
+ throw err;
28597
+ console.log(`[${source}] Task creation blocked by extension ${err.extension.name}: ${err.reason}`);
28598
+ return { created: false, skipped: true, reason: err.reason, extension: err.extension };
28599
+ }
28600
+ }
27895
28601
  var githubWebhook = route({
27896
28602
  method: "post",
27897
28603
  path: "/api/github/webhook",
@@ -28039,34 +28745,29 @@ async function handleWebhooks(req, res, pathSegments) {
28039
28745
  console.log(`[GitHub] Received ${eventType} event`);
28040
28746
  let result = { created: false };
28041
28747
  try {
28042
- switch (eventType) {
28043
- case "pull_request":
28044
- result = await handlePullRequest(body);
28045
- break;
28046
- case "issues":
28047
- result = await handleIssue(body);
28048
- break;
28049
- case "issue_comment":
28050
- result = await handleComment(body, "issue_comment");
28051
- break;
28052
- case "pull_request_review_comment":
28053
- result = await handleComment(body, "pull_request_review_comment");
28054
- break;
28055
- case "pull_request_review":
28056
- result = await handlePullRequestReview(body);
28057
- break;
28058
- case "check_run":
28059
- result = await handleCheckRun(body);
28060
- break;
28061
- case "check_suite":
28062
- result = await handleCheckSuite(body);
28063
- break;
28064
- case "workflow_run":
28065
- result = await handleWorkflowRun(body);
28066
- break;
28067
- default:
28068
- console.log(`[GitHub] Ignoring unsupported event type: ${eventType}`);
28069
- }
28748
+ result = await runBlockableHandler("GitHub", async () => {
28749
+ switch (eventType) {
28750
+ case "pull_request":
28751
+ return await handlePullRequest(body);
28752
+ case "issues":
28753
+ return await handleIssue(body);
28754
+ case "issue_comment":
28755
+ return await handleComment(body, "issue_comment");
28756
+ case "pull_request_review_comment":
28757
+ return await handleComment(body, "pull_request_review_comment");
28758
+ case "pull_request_review":
28759
+ return await handlePullRequestReview(body);
28760
+ case "check_run":
28761
+ return await handleCheckRun(body);
28762
+ case "check_suite":
28763
+ return await handleCheckSuite(body);
28764
+ case "workflow_run":
28765
+ return await handleWorkflowRun(body);
28766
+ default:
28767
+ console.log(`[GitHub] Ignoring unsupported event type: ${eventType}`);
28768
+ return { created: false };
28769
+ }
28770
+ });
28070
28771
  switch (eventType) {
28071
28772
  case "pull_request": {
28072
28773
  const pr = body;
@@ -28155,22 +28856,21 @@ async function handleWebhooks(req, res, pathSegments) {
28155
28856
  console.log(`[GitLab] Received ${objectKind} event`);
28156
28857
  let result = { created: false };
28157
28858
  try {
28158
- switch (objectKind) {
28159
- case "merge_request":
28160
- result = await handleMergeRequest(body);
28161
- break;
28162
- case "issue":
28163
- result = await handleIssue2(body);
28164
- break;
28165
- case "note":
28166
- result = await handleNote(body);
28167
- break;
28168
- case "pipeline":
28169
- result = await handlePipeline(body);
28170
- break;
28171
- default:
28172
- console.log(`[GitLab] Ignoring unsupported event type: ${objectKind}`);
28173
- }
28859
+ result = await runBlockableHandler("GitLab", async () => {
28860
+ switch (objectKind) {
28861
+ case "merge_request":
28862
+ return await handleMergeRequest(body);
28863
+ case "issue":
28864
+ return await handleIssue2(body);
28865
+ case "note":
28866
+ return await handleNote(body);
28867
+ case "pipeline":
28868
+ return await handlePipeline(body);
28869
+ default:
28870
+ console.log(`[GitLab] Ignoring unsupported event type: ${objectKind}`);
28871
+ return { created: false };
28872
+ }
28873
+ });
28174
28874
  switch (objectKind) {
28175
28875
  case "merge_request": {
28176
28876
  const mr = body;
@@ -28450,6 +29150,9 @@ init_zod();
28450
29150
  init_db();
28451
29151
  init_types();
28452
29152
  var WorkflowWithFavoriteSchema = WorkflowSchema.extend({ favorite: exports_external.boolean() });
29153
+ var WorkflowSaveResponseSchema = WorkflowSchema.extend({
29154
+ warnings: exports_external.array(exports_external.string()).optional()
29155
+ });
28453
29156
  var WorkflowSummarySchema = WorkflowSchema.omit({
28454
29157
  definition: true,
28455
29158
  triggers: true,
@@ -28463,8 +29166,9 @@ var ExecutorTypeInfoSchema = exports_external.object({
28463
29166
  configSchema: exports_external.record(exports_external.string(), exports_external.unknown()),
28464
29167
  outputSchema: exports_external.record(exports_external.string(), exports_external.unknown())
28465
29168
  });
29169
+ var DEFAULT_WORKFLOW_RUNS_LIMIT = 50;
28466
29170
  var WorkflowRunPageSchema = exports_external.object({
28467
- runs: exports_external.array(WorkflowRunSchema),
29171
+ runs: exports_external.array(WorkflowRunSummarySchema),
28468
29172
  page: exports_external.object({
28469
29173
  limit: exports_external.number().int(),
28470
29174
  offset: exports_external.number().int(),
@@ -28474,6 +29178,10 @@ var WorkflowRunPageSchema = exports_external.object({
28474
29178
  })
28475
29179
  });
28476
29180
  var SuccessResponseSchema = exports_external.object({ success: exports_external.literal(true) });
29181
+ async function withSaveWarnings(workflow) {
29182
+ const warnings = await workflowSaveWarnings(workflow.definition, getExecutorRegistry());
29183
+ return warnings.length > 0 ? { ...workflow, warnings } : workflow;
29184
+ }
28477
29185
  var listWorkflowsRoute = route({
28478
29186
  method: "get",
28479
29187
  path: "/api/workflows",
@@ -28518,7 +29226,7 @@ var createWorkflowRoute = route({
28518
29226
  vcsRepo: exports_external.string().min(1).optional()
28519
29227
  }),
28520
29228
  responses: {
28521
- 201: { description: "Workflow created", schema: WorkflowSchema },
29229
+ 201: { description: "Workflow created", schema: WorkflowSaveResponseSchema },
28522
29230
  400: { description: "Invalid definition" }
28523
29231
  }
28524
29232
  });
@@ -28564,7 +29272,10 @@ var updateWorkflowRoute = route({
28564
29272
  enabled: exports_external.boolean().optional()
28565
29273
  }),
28566
29274
  responses: {
28567
- 200: { description: "Workflow updated (version snapshot created)", schema: WorkflowSchema },
29275
+ 200: {
29276
+ description: "Workflow updated (version snapshot created)",
29277
+ schema: WorkflowSaveResponseSchema
29278
+ },
28568
29279
  400: { description: "Invalid definition" },
28569
29280
  404: { description: "Workflow not found" }
28570
29281
  }
@@ -28578,7 +29289,10 @@ var patchWorkflowRoute = route({
28578
29289
  params: exports_external.object({ id: exports_external.string() }),
28579
29290
  body: WorkflowPatchSchema.extend({ key: AssetKeySchema.optional() }),
28580
29291
  responses: {
28581
- 200: { description: "Workflow patched (version snapshot created)", schema: WorkflowSchema },
29292
+ 200: {
29293
+ description: "Workflow patched (version snapshot created)",
29294
+ schema: WorkflowSaveResponseSchema
29295
+ },
28582
29296
  400: { description: "Invalid patch or resulting definition" },
28583
29297
  404: { description: "Workflow not found" }
28584
29298
  }
@@ -28592,7 +29306,10 @@ var patchWorkflowNodeRoute = route({
28592
29306
  params: exports_external.object({ id: exports_external.string(), nodeId: exports_external.string() }),
28593
29307
  body: WorkflowNodePatchSchema,
28594
29308
  responses: {
28595
- 200: { description: "Node patched (version snapshot created)", schema: WorkflowSchema },
29309
+ 200: {
29310
+ description: "Node patched (version snapshot created)",
29311
+ schema: WorkflowSaveResponseSchema
29312
+ },
28596
29313
  400: { description: "Invalid patch or resulting definition" },
28597
29314
  404: { description: "Workflow or node not found" }
28598
29315
  }
@@ -28646,7 +29363,8 @@ var listWorkflowRunsRoute = route({
28646
29363
  method: "get",
28647
29364
  path: "/api/workflows/{id}/runs",
28648
29365
  pattern: ["api", "workflows", null, "runs"],
28649
- summary: "List runs for a workflow",
29366
+ summary: "List runs for a workflow, newest first",
29367
+ description: `Returns one page of runs without \`context\` (fetch it with GET /api/workflow-runs/{id}). \`limit\` defaults to ${DEFAULT_WORKFLOW_RUNS_LIMIT} and is capped at 100; follow \`page.nextOffset\` while \`page.hasMore\` is true.`,
28650
29368
  tags: ["Workflows"],
28651
29369
  params: exports_external.object({ id: exports_external.string() }),
28652
29370
  query: exports_external.object({
@@ -28656,8 +29374,8 @@ var listWorkflowRunsRoute = route({
28656
29374
  }),
28657
29375
  responses: {
28658
29376
  200: {
28659
- description: "Workflow run list",
28660
- schema: exports_external.union([exports_external.array(WorkflowRunSchema), WorkflowRunPageSchema])
29377
+ description: "One page of workflow runs",
29378
+ schema: WorkflowRunPageSchema
28661
29379
  }
28662
29380
  }
28663
29381
  });
@@ -28899,7 +29617,7 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
28899
29617
  createdByAgentId: myAgentId ?? undefined,
28900
29618
  createdBy: await resolveHttpAuditUserId(req, myAgentId) ?? undefined
28901
29619
  }, "api");
28902
- createWorkflowRoute.respond(res, 201, workflow);
29620
+ createWorkflowRoute.respond(res, 201, await withSaveWarnings(workflow));
28903
29621
  return true;
28904
29622
  }
28905
29623
  if (getWorkflowRoute.match(req.method, pathSegments)) {
@@ -28944,7 +29662,7 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
28944
29662
  jsonError(res, result.reason === "patch" ? result.errors.join("; ") : `Invalid definition: ${result.errors.join("; ")}`, 400);
28945
29663
  return true;
28946
29664
  }
28947
- patchWorkflowNodeRoute.respond(res, 200, result.workflow);
29665
+ patchWorkflowNodeRoute.respond(res, 200, await withSaveWarnings(result.workflow));
28948
29666
  return true;
28949
29667
  }
28950
29668
  if (patchWorkflowRoute.match(req.method, pathSegments)) {
@@ -28995,7 +29713,7 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
28995
29713
  jsonError(res, result.reason === "patch" ? result.errors.join("; ") : `Invalid definition: ${result.errors.join("; ")}`, 400);
28996
29714
  return true;
28997
29715
  }
28998
- patchWorkflowRoute.respond(res, 200, result.workflow);
29716
+ patchWorkflowRoute.respond(res, 200, await withSaveWarnings(result.workflow));
28999
29717
  return true;
29000
29718
  }
29001
29719
  if (updateWorkflowRoute.match(req.method, pathSegments)) {
@@ -29054,7 +29772,7 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
29054
29772
  res.end();
29055
29773
  return true;
29056
29774
  }
29057
- updateWorkflowRoute.respond(res, 200, workflow);
29775
+ updateWorkflowRoute.respond(res, 200, await withSaveWarnings(workflow));
29058
29776
  return true;
29059
29777
  }
29060
29778
  if (deleteWorkflowRoute.match(req.method, pathSegments)) {
@@ -29132,18 +29850,12 @@ async function handleWorkflows(req, res, pathSegments, queryParams, myAgentId) {
29132
29850
  const parsed = await listWorkflowRunsRoute.parse(req, res, pathSegments, queryParams);
29133
29851
  if (!parsed)
29134
29852
  return true;
29135
- const paginationRequested = parsed.query?.limit !== undefined || parsed.query?.offset !== undefined;
29136
- if (paginationRequested) {
29137
- const page = await listWorkflowRunsPage(parsed.params.id, {
29138
- status: parsed.query?.status,
29139
- limit: parsed.query?.limit ?? 20,
29140
- offset: parsed.query?.offset ?? 0
29141
- });
29142
- listWorkflowRunsRoute.respond(res, 200, page);
29143
- return true;
29144
- }
29145
- const runs = await listWorkflowRuns(parsed.params.id, { status: parsed.query?.status });
29146
- listWorkflowRunsRoute.respond(res, 200, runs);
29853
+ const page = await listWorkflowRunsPage(parsed.params.id, {
29854
+ status: parsed.query?.status,
29855
+ limit: parsed.query?.limit ?? DEFAULT_WORKFLOW_RUNS_LIMIT,
29856
+ offset: parsed.query?.offset ?? 0
29857
+ });
29858
+ listWorkflowRunsRoute.respond(res, 200, page);
29147
29859
  return true;
29148
29860
  }
29149
29861
  if (getWorkflowRunRoute.match(req.method, pathSegments)) {
@@ -29613,7 +30325,7 @@ async function shutdown() {
29613
30325
  sessionsProcessed: getServerSessionsProcessed()
29614
30326
  });
29615
30327
  if (hasCapability("scheduling")) {
29616
- const { stopScheduler } = await import("./index-yy07ef2s.js");
30328
+ const { stopScheduler } = await import("./index-cd151qkq.js");
29617
30329
  stopScheduler();
29618
30330
  }
29619
30331
  stopHeartbeat();
@@ -29621,12 +30333,13 @@ async function shutdown() {
29621
30333
  await stopScriptRunSupervisor();
29622
30334
  await stopSlackApp();
29623
30335
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
29624
- const { stopOAuthKeepalive } = await import("./keepalive-f7ekefyc.js");
30336
+ const { stopOAuthKeepalive } = await import("./keepalive-8p9rpvz5.js");
29625
30337
  await stopOAuthKeepalive();
29626
30338
  }
29627
30339
  stopOAuthPendingGc();
29628
30340
  stopMemoryGc();
29629
30341
  await stopDbRetention();
30342
+ stopHumanFreeDrain();
29630
30343
  stopScratchScriptGc();
29631
30344
  await stopExtensionRuntime();
29632
30345
  stopAuditGc();
@@ -29689,23 +30402,23 @@ try {
29689
30402
  console.warn("[startup] CAPABILITIES upgrade seed failed (non-fatal):", err);
29690
30403
  }
29691
30404
  try {
29692
- const { seedPricingFromModelsDev } = await import("./seed-pricing-vqxa06qf.js");
29693
- seedPricingFromModelsDev();
29694
- const { startPricingRefreshLoop } = await import("./pricing-refresh-6sw65tck.js");
30405
+ const { ensurePricingSeeded } = await import("./boot-seeds-h7c32hvm.js");
30406
+ ensurePricingSeeded();
30407
+ const { startPricingRefreshLoop } = await import("./pricing-refresh-0v77385v.js");
29695
30408
  startPricingRefreshLoop();
29696
30409
  } catch (err) {
29697
30410
  console.error("[startup] Failed to seed pricing rows:", err);
29698
30411
  }
29699
30412
  try {
29700
- const { ensureRbacSeedsSynced } = await import("./rbac-roles-3gxmnb20.js");
29701
- ensureRbacSeedsSynced();
30413
+ const { ensureRbacSeeded } = await import("./boot-seeds-h7c32hvm.js");
30414
+ ensureRbacSeeded();
29702
30415
  } catch (err) {
29703
30416
  console.error("[startup] Failed to sync RBAC seed rows:", err);
29704
30417
  if (isRbacEnabled())
29705
30418
  throw err;
29706
30419
  }
29707
30420
  try {
29708
- const { runAllSeeders } = await import("./index-jtvpgb8f.js");
30421
+ const { runAllSeeders } = await import("./index-5sz16ksh.js");
29709
30422
  await runAllSeeders({ scriptEmbeddingMode: "skip" });
29710
30423
  } catch (err) {
29711
30424
  console.error("[startup] Failed to seed built-in entities:", err);
@@ -29759,36 +30472,37 @@ httpServer.listen(port, async () => {
29759
30472
  await initWorkflows();
29760
30473
  await startScriptRunSupervisor(getMcpBaseUrl());
29761
30474
  if (hasCapability("scheduling")) {
29762
- const { startScheduler } = await import("./index-yy07ef2s.js");
29763
- const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-4k9hct21.js");
30475
+ const { startScheduler } = await import("./index-cd151qkq.js");
30476
+ const { getExecutorRegistry: getExecutorRegistry2 } = await import("./index-ttpbhnjg.js");
29764
30477
  const intervalMs = Number(process.env.SCHEDULER_INTERVAL_MS) || 1e4;
29765
30478
  startScheduler(getExecutorRegistry2(), intervalMs, {
29766
30479
  runId: globalState.__runId
29767
30480
  });
29768
30481
  }
29769
30482
  if (!isEnvFlagEnabled("HEARTBEAT_DISABLE", false)) {
29770
- const { startHeartbeat } = await import("./index-r6bty6tb.js");
30483
+ const { startHeartbeat } = await import("./index-k661dzzr.js");
29771
30484
  const heartbeatMs = Number(process.env.HEARTBEAT_INTERVAL_MS) || 90000;
29772
30485
  startHeartbeat(heartbeatMs);
29773
30486
  }
29774
30487
  if (process.env.OAUTH_KEEPALIVE_DISABLE !== "true") {
29775
- const { startOAuthKeepalive } = await import("./keepalive-f7ekefyc.js");
30488
+ const { startOAuthKeepalive } = await import("./keepalive-8p9rpvz5.js");
29776
30489
  startOAuthKeepalive();
29777
30490
  }
29778
30491
  if (process.env.OAUTH_REFRESH_SWEEP_DISABLE !== "true") {
29779
- const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-vra1dhkd.js");
30492
+ const { startOAuthRefreshSweep } = await import("./oauth-refresh-sweep-cwcq1ctx.js");
29780
30493
  startOAuthRefreshSweep();
29781
30494
  }
29782
30495
  startOAuthPendingGc();
29783
30496
  await startMemoryGc();
29784
30497
  await startDbRetention();
29785
- import("./boot-reembed-zfxb937k.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
30498
+ startHumanFreeDrain();
30499
+ import("./boot-reembed-48d2qpkt.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
29786
30500
  console.error("[boot-reembed] startup backfill failed (non-fatal):", err);
29787
30501
  });
29788
- import("./boot-reembed-r6shx5qx.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
30502
+ import("./boot-reembed-w0bryhkr.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
29789
30503
  console.error("[boot-reembed-scripts] startup backfill failed (non-fatal):", err);
29790
30504
  });
29791
- import("./boot-scrub-logs-k5y0se6r.js").then(({ runBootScrubLogs }) => runBootScrubLogs()).catch((err) => {
30505
+ import("./boot-scrub-logs-t65wbrn7.js").then(({ runBootScrubLogs }) => runBootScrubLogs()).catch((err) => {
29792
30506
  console.error("[boot-scrub-logs] startup scrub failed (non-fatal):", err);
29793
30507
  });
29794
30508
  }).on("error", (err) => {