@desplega.ai/agent-swarm 1.149.1 → 1.151.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 (538) hide show
  1. package/README.md +18 -3
  2. package/dist/{acp-adapter-vhkzfpjg.js → acp-adapter-ex8hzjfc.js} +5 -5
  3. package/dist/{actions-9d2694yk.js → actions-2bgpyhww.js} +39 -11
  4. package/dist/{app-fq2ggynt.js → app-1706zhr1.js} +7 -7
  5. package/dist/{artifact-gj9arwrr.js → artifact-td4q4dch.js} +1 -1
  6. package/dist/{assistant-edb6n9nn.js → assistant-bavke5p7.js} +44 -20
  7. package/dist/{azure-openai-responses-cqar64rc.js → azure-openai-responses-f38x2avq.js} +13 -13
  8. package/dist/{boot-reembed-msweabbp.js → boot-reembed-3cmrrmpa.js} +9 -9
  9. package/dist/{boot-reembed-q5wd3tha.js → boot-reembed-nafcmmmc.js} +14 -16
  10. package/dist/{boot-scrub-logs-3g1az933.js → boot-scrub-logs-cd6a2sq0.js} +5 -5
  11. package/dist/{claude-adapter-v3rnzsdc.js → claude-adapter-wfp2gzvz.js} +15 -16
  12. package/dist/{claude-managed-adapter-qvsmh6mv.js → claude-managed-adapter-dsmkcrjy.js} +3 -3
  13. package/dist/{claude-sdk-session-qxrpsna1.js → claude-sdk-session-bht9jjak.js} +15 -16
  14. package/dist/{cli-5m0qmvdp.js → cli-0qb1z6s2.js} +1 -1
  15. package/dist/{cli-9d8ntetj.js → cli-2658f6at.js} +1 -1
  16. package/dist/{cli-7evafqvy.js → cli-2tbvf1z1.js} +85 -69
  17. package/dist/{cli-k351hv5k.js → cli-3v9xhjcn.js} +24 -12
  18. package/dist/{cli-1ebpar1q.js → cli-4wppfkcm.js} +350 -20
  19. package/dist/{cli-4260r1tg.js → cli-5jd2z7av.js} +97 -84
  20. package/dist/{cli-cv7s5zdq.js → cli-5tpgq60f.js} +9865 -715
  21. package/dist/{cli-6skz3rk8.js → cli-7tgcstn2.js} +9 -4
  22. package/dist/{cli-01g3x1ca.js → cli-9004vfdf.js} +108 -56
  23. package/dist/{cli-1c94wvcw.js → cli-a1z3h107.js} +124 -99
  24. package/dist/{cli-9br8ypfv.js → cli-czjtgfys.js} +2 -2
  25. package/dist/{cli-5my3bjsd.js → cli-d3p82erb.js} +7 -7
  26. package/dist/{cli-e29gmdmw.js → cli-dv6cdjs2.js} +2 -1
  27. package/dist/{cli-wby1xnnb.js → cli-f1wky6zp.js} +1 -1
  28. package/dist/{cli-zvz62chv.js → cli-fm4ytsdk.js} +4 -4
  29. package/dist/{cli-tg8qj8ee.js → cli-frcta2w4.js} +6 -6
  30. package/dist/{cli-7xx10h0a.js → cli-g69fdc9g.js} +2 -2
  31. package/dist/{cli-cmp8g3sw.js → cli-gbfwcd3k.js} +44 -9
  32. package/dist/{handlers-nsg0bcye.js → cli-gjyvhmmh.js} +97 -45
  33. package/dist/{cli-08b07b4r.js → cli-ht5rs63n.js} +1 -1
  34. package/dist/{cli-jecc01cb.js → cli-j4nv2wqy.js} +2 -4
  35. package/dist/{cli-cd60fv6j.js → cli-j9xczhaq.js} +1 -1
  36. package/dist/cli-pf9q3696.js +172 -0
  37. package/dist/{cli-xm87hzbw.js → cli-pgj4a5fb.js} +1 -1
  38. package/dist/{cli-jezx9b9c.js → cli-ppm4975n.js} +9 -3
  39. package/dist/{cli-3z634pqe.js → cli-q88st9aj.js} +2 -2
  40. package/dist/{cli-3sysyjve.js → cli-r2q6pevn.js} +142 -49
  41. package/dist/{cli-07jd68a1.js → cli-re8z5p8p.js} +1 -1
  42. package/dist/{cli-qgd4sqz5.js → cli-s14agm5s.js} +121 -14
  43. package/dist/{cli-svbrpf5q.js → cli-sjaae6ff.js} +9872 -424
  44. package/dist/{cli-73gq0zxn.js → cli-vwm416m6.js} +13 -13
  45. package/dist/{cli-4wtq5jjv.js → cli-wbyk465z.js} +1 -1
  46. package/dist/{cli-3apbzgyk.js → cli-z61ykvam.js} +19 -14
  47. package/dist/{cli-e06a8a7y.js → cli-zkxymas5.js} +4 -3
  48. package/dist/cli.js +26 -25
  49. package/dist/{codex-adapter-jyw7a91z.js → codex-adapter-jjjk8w4m.js} +8 -9
  50. package/dist/{codex-hook-hfrt9shr.js → codex-hook-8jexc34x.js} +3 -3
  51. package/dist/{codex-session-runner-bmngj0s5.js → codex-session-runner-nd6ayxkx.js} +8 -9
  52. package/dist/{commands-n755g391.js → commands-9v4psyq1.js} +5 -5
  53. package/dist/{db-s1cgh5gv.js → db-wnt58tpe.js} +5 -5
  54. package/dist/dispatcher-05jh1aqk.js +74 -0
  55. package/dist/{e2b-p04vmtx0.js → e2b-413b8t4v.js} +1 -1
  56. package/dist/{google-generative-ai-tsskx7te.js → google-generative-ai-ndjmj5fa.js} +7 -7
  57. package/dist/{google-vertex-ppw8ydpa.js → google-vertex-fr665tqs.js} +10 -10
  58. package/dist/handlers-tw90pkh5.js +65 -0
  59. package/dist/{hook-jf0xe8zh.js → hook-123e2scb.js} +11 -12
  60. package/dist/{hook-h9cqrm8q.js → hook-sxe3r349.js} +11 -12
  61. package/dist/{http-nc6pydw5.js → http-ecsar8ez.js} +1442 -581
  62. package/dist/{index-ezxkds2n.js → index-16js521z.js} +335 -107
  63. package/dist/{index-769nc012.js → index-hw26vj40.js} +25 -19
  64. package/dist/{index-0wdy6gwc.js → index-nnrbpcjp.js} +25 -17
  65. package/dist/index-ymn7em0p.js +25 -0
  66. package/dist/{index-x1zcj09z.js → index-zj518gf9.js} +26 -20
  67. package/dist/{keepalive-nesm3xb6.js → keepalive-asqtcm4y.js} +7 -7
  68. package/dist/{lead-bwy6t2za.js → lead-xbfr7fvt.js} +40 -48
  69. package/dist/{maintenance-8w393zf0.js → maintenance-qma55qvw.js} +9 -9
  70. package/dist/{oauth-refresh-sweep-sh8xjy08.js → oauth-refresh-sweep-3s04c6qw.js} +6 -6
  71. package/dist/{onboard-25ps29h1.js → onboard-drskd386.js} +13 -4
  72. package/dist/{openai-codex-responses-g7w48y30.js → openai-codex-responses-wy6a43wd.js} +13 -13
  73. package/dist/{openai-responses-nmeyptke.js → openai-responses-6xwf7bzg.js} +19 -19
  74. package/dist/{opencode-adapter-dce4wskd.js → opencode-adapter-28axqa09.js} +4 -4
  75. package/dist/{otel-impl-b93gxnz5.js → otel-impl-943c96er.js} +1 -1
  76. package/dist/{pi-mono-adapter-zvshk5cj.js → pi-mono-adapter-jcqt71cg.js} +17 -19
  77. package/dist/{pricing-refresh-5v56x7gb.js → pricing-refresh-mx51az05.js} +7 -7
  78. package/dist/{rbac-roles-x55cnezn.js → rbac-roles-78baecqd.js} +13 -9
  79. package/dist/{rbac-roles-0p0s6pbj.js → rbac-roles-wcmrg6sv.js} +7 -7
  80. package/dist/{render-v2-hyd45w8b.js → render-v2-8zjntgf5.js} +7 -7
  81. package/dist/{seed-pricing-49gbgn96.js → seed-pricing-jqjs6cws.js} +6 -6
  82. package/dist/{setup-qvq64vzq.js → setup-4pks0vfk.js} +2 -2
  83. package/dist/work-objects-wangt792.js +165 -0
  84. package/dist/{worker-scj60cxg.js → worker-p2mr422x.js} +40 -48
  85. package/openapi.json +1365 -268
  86. package/package.json +4 -3
  87. package/src/agentmail/handlers.ts +95 -66
  88. package/src/be/budget-refusal-notify.ts +1 -0
  89. package/src/be/db/tasks/read.ts +3 -0
  90. package/src/be/db/tasks/write.ts +13 -1
  91. package/src/be/db-client.ts +5 -0
  92. package/src/be/db.ts +15 -5
  93. package/src/be/extensions/db.ts +461 -0
  94. package/src/be/extensions/validate.ts +107 -0
  95. package/src/be/memory/boot-reembed.ts +17 -12
  96. package/src/be/memory/index.ts +12 -0
  97. package/src/be/memory/providers/openai-embedding.ts +4 -0
  98. package/src/be/memory/types.ts +2 -0
  99. package/src/be/migrations/153_deferred_task_wait_members.sql +25 -0
  100. package/src/be/migrations/154_routing_source.sql +3 -0
  101. package/src/be/migrations/155_extensions.sql +66 -0
  102. package/src/be/migrations/156_inbox_item_state_read_at.sql +7 -0
  103. package/src/be/rbac-roles.ts +3 -2
  104. package/src/be/scripts/typecheck.ts +59 -41
  105. package/src/be/seed/schedules-seeder.ts +25 -2
  106. package/src/be/seed/workflows-seeder.ts +17 -0
  107. package/src/be/seed-scripts/catalog/delegate.ts +3 -1
  108. package/src/be/seed-skills/bundled-files.generated.json +1 -1
  109. package/src/be/seed-skills/index.ts +7 -0
  110. package/src/be/steering.ts +1 -0
  111. package/src/be/swarm-config-guard.ts +3 -1
  112. package/src/commands/credential-refresh.ts +70 -0
  113. package/src/commands/onboard/compose-generator.ts +14 -2
  114. package/src/commands/onboard/env-generator.ts +7 -0
  115. package/src/commands/provider-credentials.ts +2 -25
  116. package/src/commands/runner.ts +24 -57
  117. package/src/extensions/apply-task-create.ts +135 -0
  118. package/src/extensions/bundle-path.ts +10 -0
  119. package/src/extensions/contract-runtime.ts +7 -0
  120. package/src/extensions/contract-types.generated.ts +4 -0
  121. package/src/extensions/contract.ts +270 -0
  122. package/src/extensions/ctx.ts +186 -0
  123. package/src/extensions/dispatcher.ts +479 -0
  124. package/src/extensions/identity.ts +44 -0
  125. package/src/extensions/lifecycle.ts +281 -0
  126. package/src/extensions/loader.ts +207 -0
  127. package/src/extensions/post-bridge.ts +161 -0
  128. package/src/github/handlers.ts +185 -140
  129. package/src/gitlab/handlers.ts +97 -77
  130. package/src/heartbeat/heartbeat.ts +155 -83
  131. package/src/http/agents.ts +1 -1
  132. package/src/http/all-routes.ts +1 -0
  133. package/src/http/approval-requests.ts +1 -0
  134. package/src/http/apps.ts +14 -9
  135. package/src/http/config.ts +4 -1
  136. package/src/http/core.ts +38 -2
  137. package/src/http/extensions.ts +547 -0
  138. package/src/http/inbox-state.ts +2 -0
  139. package/src/http/index.ts +41 -3
  140. package/src/http/mcp-bridge.ts +96 -62
  141. package/src/http/mcp.ts +1 -1
  142. package/src/http/script-runs.ts +5 -0
  143. package/src/http/status.ts +6 -4
  144. package/src/http/tasks.ts +51 -30
  145. package/src/integrations/kapso/inbound.ts +15 -10
  146. package/src/jira/sync.ts +26 -16
  147. package/src/linear/sync.ts +26 -16
  148. package/src/prompts/session-templates.ts +18 -13
  149. package/src/providers/claude-adapter.ts +21 -8
  150. package/src/rbac/admission.ts +1 -1
  151. package/src/rbac/elevated-agents.ts +24 -0
  152. package/src/rbac/legacy-policy.ts +35 -6
  153. package/src/rbac/permissions.ts +8 -0
  154. package/src/scheduler/deferred-task-waits.ts +138 -27
  155. package/src/scheduler/schedule-task.ts +54 -24
  156. package/src/scheduler/scheduler.ts +108 -125
  157. package/src/scripts-runtime/executors/native.ts +5 -1
  158. package/src/scripts-runtime/executors/types.ts +5 -0
  159. package/src/scripts-runtime/import-allowlist.ts +79 -19
  160. package/src/scripts-runtime/sdk-allowlist.ts +4 -0
  161. package/src/scripts-runtime/swarm-config.ts +8 -0
  162. package/src/scripts-runtime/swarm-sdk.ts +3 -0
  163. package/src/scripts-runtime/types/stdlib.d.ts +16 -3
  164. package/src/scripts-runtime/types/swarm-extension.d.ts +562 -0
  165. package/src/scripts-runtime/types/swarm-sdk.d.ts +16 -3
  166. package/src/server.ts +6 -0
  167. package/src/slack/HEURISTICS.md +3 -1
  168. package/src/slack/actions.ts +21 -16
  169. package/src/slack/app.ts +2 -0
  170. package/src/slack/assistant.ts +4 -12
  171. package/src/slack/blocks.ts +1 -1
  172. package/src/slack/handlers.ts +107 -19
  173. package/src/slack/inbound-files.ts +9 -5
  174. package/src/slack/render-v2.ts +188 -38
  175. package/src/slack/router.ts +13 -3
  176. package/src/slack/steering.ts +3 -3
  177. package/src/slack/thread-buffer.ts +66 -23
  178. package/src/slack/work-objects.test.ts +252 -0
  179. package/src/slack/work-objects.ts +118 -0
  180. package/src/tasks/errors.ts +9 -0
  181. package/src/tasks/sibling-awareness.ts +35 -1
  182. package/src/tasks/worker-follow-up.ts +67 -11
  183. package/src/tests/acp-adapter.test.ts +10 -10
  184. package/src/tests/agent-fs-live-url.test.ts +40 -0
  185. package/src/tests/agent-fs-provision-seeder.test.ts +12 -12
  186. package/src/tests/api-key-tracking.test.ts +18 -18
  187. package/src/tests/api-key.test.ts +4 -2
  188. package/src/tests/apps-rbac.test.ts +1 -1
  189. package/src/tests/apps-spike5.test.ts +1 -1
  190. package/src/tests/apps-sync-engine.test.ts +8 -8
  191. package/src/tests/apps-user-config.test.ts +1 -1
  192. package/src/tests/artifact-sdk.test.ts +8 -8
  193. package/src/tests/asset-key-mcp.test.ts +2 -0
  194. package/src/tests/automation-preflight-alert.test.ts +1 -1
  195. package/src/tests/base-prompt.test.ts +7 -6
  196. package/src/tests/budget-user-scope.test.ts +1 -1
  197. package/src/tests/budgets-routes.test.ts +1 -1
  198. package/src/tests/claude-adapter-binary.test.ts +22 -40
  199. package/src/tests/claude-adapter-otel.test.ts +13 -7
  200. package/src/tests/claude-adapter.test.ts +8 -6
  201. package/src/tests/claude-hook-credentials.test.ts +3 -3
  202. package/src/tests/claude-managed-adapter.test.ts +4 -4
  203. package/src/tests/claude-managed-setup.test.ts +3 -3
  204. package/src/tests/claude-sdk-lifecycle.test.ts +1 -1
  205. package/src/tests/claude-sdk-transport.test.ts +6 -6
  206. package/src/tests/claude-stop-hook.test.ts +8 -8
  207. package/src/tests/claude-worker-parity.test.ts +3 -3
  208. package/src/tests/codex-adapter-pool-auth-revalidate.test.ts +5 -5
  209. package/src/tests/codex-adapter.test.ts +7 -5
  210. package/src/tests/codex-app-server.test.ts +2 -2
  211. package/src/tests/codex-login.test.ts +15 -15
  212. package/src/tests/codex-oauth-credential-info.test.ts +4 -4
  213. package/src/tests/codex-oauth-keep-warm.test.ts +4 -4
  214. package/src/tests/codex-oauth-refresh-lock.test.ts +1 -1
  215. package/src/tests/codex-oauth-storage.test.ts +7 -7
  216. package/src/tests/codex-pool.test.ts +1 -1
  217. package/src/tests/codex-steering-hook.test.ts +1 -1
  218. package/src/tests/codex-swarm-events.test.ts +1 -1
  219. package/src/tests/config-api-only-keys.test.ts +1 -1
  220. package/src/tests/config-session-auth.test.ts +2 -2
  221. package/src/tests/connection-embedded-auth.test.ts +20 -18
  222. package/src/tests/core-auth.test.ts +1 -1
  223. package/src/tests/create-page-tool.test.ts +3 -3
  224. package/src/tests/credential-refresh.test.ts +115 -0
  225. package/src/tests/credential-wait.test.ts +2 -2
  226. package/src/tests/credentials.test.ts +6 -4
  227. package/src/tests/db-queries-oauth.test.ts +40 -40
  228. package/src/tests/defer-task.test.ts +73 -8
  229. package/src/tests/deferred-task-wait-migration.test.ts +64 -0
  230. package/src/tests/deferred-task-wake.test.ts +349 -8
  231. package/src/tests/devin-adapter.test.ts +1 -1
  232. package/src/tests/devin-api.test.ts +1 -1
  233. package/src/tests/docs-index-footprint.test.js +3 -3
  234. package/src/tests/e2b-dispatch.test.ts +21 -19
  235. package/src/tests/e2e-claude-transport.test.ts +3 -3
  236. package/src/tests/e2e-redact.test.ts +6 -6
  237. package/src/tests/ensure-token.test.ts +68 -68
  238. package/src/tests/entrypoint-api-readiness.test.ts +1 -1
  239. package/src/tests/entrypoint-codex-oauth-seed.test.ts +13 -13
  240. package/src/tests/env-flag.test.ts +1 -0
  241. package/src/tests/events-http.test.ts +1 -1
  242. package/src/tests/extensions-db.test.ts +216 -0
  243. package/src/tests/extensions-dispatcher.test.ts +275 -0
  244. package/src/tests/extensions-example-heartbeat-remediate.test.ts +69 -0
  245. package/src/tests/extensions-example-mcp-install.test.ts +63 -0
  246. package/src/tests/extensions-example-no-exclamation-marks.test.ts +72 -0
  247. package/src/tests/extensions-example-rewrite-and-suppress.test.ts +70 -0
  248. package/src/tests/extensions-example-route-slack-channel.test.ts +217 -0
  249. package/src/tests/extensions-heartbeat.test.ts +291 -0
  250. package/src/tests/extensions-http.test.ts +431 -0
  251. package/src/tests/extensions-lead-equivalence.test.ts +49 -0
  252. package/src/tests/extensions-lifecycle.test.ts +209 -0
  253. package/src/tests/extensions-loader.test.ts +95 -0
  254. package/src/tests/extensions-mcp-tools.test.ts +245 -0
  255. package/src/tests/extensions-pre-task.test.ts +487 -0
  256. package/src/tests/extensions-run-context.test.ts +41 -0
  257. package/src/tests/extensions-tool-call.test.ts +288 -0
  258. package/src/tests/extensions-validate.test.ts +196 -0
  259. package/src/tests/fixtures/extensions/bad-import/hooks.ts +8 -0
  260. package/src/tests/fixtures/extensions/bad-import/manifest.json +9 -0
  261. package/src/tests/fixtures/extensions/bad-return-shape/hooks.ts +10 -0
  262. package/src/tests/fixtures/extensions/bad-return-shape/manifest.json +9 -0
  263. package/src/tests/fixtures/extensions/block-tasks-from-source/hooks.ts +22 -0
  264. package/src/tests/fixtures/extensions/block-tasks-from-source/manifest.json +9 -0
  265. package/src/tests/fixtures/extensions/ignore-channel/hooks.ts +22 -0
  266. package/src/tests/fixtures/extensions/ignore-channel/manifest.json +9 -0
  267. package/src/tests/fixtures/extensions/load.ts +10 -0
  268. package/src/tests/fixtures/extensions/minimal/hooks.ts +7 -0
  269. package/src/tests/fixtures/extensions/minimal/manifest.json +9 -0
  270. package/src/tests/fixtures/extensions/never-fail-long-tasks/hooks.ts +11 -0
  271. package/src/tests/fixtures/extensions/never-fail-long-tasks/manifest.json +9 -0
  272. package/src/tests/fixtures/extensions/no-exclamation-marks/hooks.ts +23 -0
  273. package/src/tests/fixtures/extensions/no-exclamation-marks/manifest.json +9 -0
  274. package/src/tests/fixtures/extensions/post-logger/hooks.ts +9 -0
  275. package/src/tests/fixtures/extensions/post-logger/manifest.json +9 -0
  276. package/src/tests/fixtures/extensions/priority-a/hooks.ts +7 -0
  277. package/src/tests/fixtures/extensions/priority-a/manifest.json +9 -0
  278. package/src/tests/fixtures/extensions/priority-b/hooks.ts +7 -0
  279. package/src/tests/fixtures/extensions/priority-b/manifest.json +9 -0
  280. package/src/tests/fixtures/extensions/record-only-on-tag/hooks.ts +16 -0
  281. package/src/tests/fixtures/extensions/record-only-on-tag/manifest.json +9 -0
  282. package/src/tests/fixtures/extensions/reserved-assets/hooks.ts +5 -0
  283. package/src/tests/fixtures/extensions/reserved-assets/manifest.json +10 -0
  284. package/src/tests/fixtures/extensions/rewrite-progress-prefix/hooks.ts +22 -0
  285. package/src/tests/fixtures/extensions/rewrite-progress-prefix/manifest.json +9 -0
  286. package/src/tests/fixtures/extensions/rewrite-task-priority/hooks.ts +7 -0
  287. package/src/tests/fixtures/extensions/rewrite-task-priority/manifest.json +9 -0
  288. package/src/tests/fixtures/extensions/route-channel-to-agent/hooks.ts +26 -0
  289. package/src/tests/fixtures/extensions/route-channel-to-agent/manifest.json +9 -0
  290. package/src/tests/fixtures/extensions/slow/hooks.ts +10 -0
  291. package/src/tests/fixtures/extensions/slow/manifest.json +9 -0
  292. package/src/tests/fixtures/extensions/suppress-lead-follow-up/hooks.ts +12 -0
  293. package/src/tests/fixtures/extensions/suppress-lead-follow-up/manifest.json +9 -0
  294. package/src/tests/fixtures/extensions/throws/hooks.ts +12 -0
  295. package/src/tests/fixtures/extensions/throws/manifest.json +9 -0
  296. package/src/tests/fixtures/extensions/worker-runtime/hooks.ts +5 -0
  297. package/src/tests/fixtures/extensions/worker-runtime/manifest.json +9 -0
  298. package/src/tests/fs-routes.test.ts +1 -1
  299. package/src/tests/gitlab-auth.test.ts +10 -10
  300. package/src/tests/harness-provider-resolution.test.ts +8 -5
  301. package/src/tests/heartbeat-reroute-decision.test.ts +1 -0
  302. package/src/tests/helper-credentials.test.ts +137 -0
  303. package/src/tests/http/context-routes.test.ts +2 -2
  304. package/src/tests/http-api-integration.test.ts +5 -2
  305. package/src/tests/http-users.test.ts +1 -1
  306. package/src/tests/identity-refresh.test.ts +2 -2
  307. package/src/tests/internal-ai/complete-structured.test.ts +2 -2
  308. package/src/tests/internal-ai/credentials.test.ts +19 -17
  309. package/src/tests/jira-metadata.test.ts +1 -1
  310. package/src/tests/jira-oauth.test.ts +5 -5
  311. package/src/tests/jira-sync.test.ts +1 -1
  312. package/src/tests/jira-webhook-lifecycle.test.ts +3 -3
  313. package/src/tests/jira-webhook.test.ts +2 -2
  314. package/src/tests/kapso-inbound.test.ts +2 -2
  315. package/src/tests/kv-http.test.ts +1 -1
  316. package/src/tests/kv-namespace-resolution.test.ts +1 -1
  317. package/src/tests/kv-page-proxy.test.ts +2 -2
  318. package/src/tests/launch-password-rejection.test.ts +2 -2
  319. package/src/tests/linear-webhook.test.ts +1 -1
  320. package/src/tests/mcp-oauth-dcr-reuse.test.ts +6 -6
  321. package/src/tests/mcp-oauth-ensure-token.test.ts +28 -22
  322. package/src/tests/mcp-oauth-manual-client.test.ts +16 -12
  323. package/src/tests/mcp-oauth-queries.test.ts +35 -32
  324. package/src/tests/mcp-oauth-resolve-secrets.test.ts +8 -8
  325. package/src/tests/mcp-oauth-wrapper.test.ts +20 -20
  326. package/src/tests/mcp-user-route.test.ts +1 -1
  327. package/src/tests/memory-edges.test.ts +1 -1
  328. package/src/tests/memory-edit-authorization.test.ts +32 -0
  329. package/src/tests/memory-rate-endpoint.test.ts +1 -1
  330. package/src/tests/memory-rate-tool.test.ts +2 -2
  331. package/src/tests/memory-rater-e2e.test.ts +1 -1
  332. package/src/tests/memory-rater-llm-summarizer.test.ts +3 -3
  333. package/src/tests/memory-rater-llm.test.ts +1 -1
  334. package/src/tests/model-control.test.ts +3 -0
  335. package/src/tests/multi-runtime-enabled-stats.test.ts +2 -2
  336. package/src/tests/multi-runtime-registration.test.ts +111 -17
  337. package/src/tests/oauth-access-token-tool.test.ts +18 -18
  338. package/src/tests/oauth-callback-flow.test.ts +8 -8
  339. package/src/tests/oauth-credential-bindings.test.ts +29 -27
  340. package/src/tests/oauth-keepalive.test.ts +10 -10
  341. package/src/tests/oauth-presets.test.ts +13 -5
  342. package/src/tests/oauth-refresh-failure.test.ts +9 -9
  343. package/src/tests/oauth-refresh-sweep.test.ts +20 -13
  344. package/src/tests/oauth-wrapper.test.ts +1 -1
  345. package/src/tests/onboard-compose.test.ts +47 -3
  346. package/src/tests/onboard-env.test.ts +26 -26
  347. package/src/tests/onboard-non-interactive.test.ts +4 -4
  348. package/src/tests/opencode-adapter.test.ts +1 -1
  349. package/src/tests/opencode-plugin.test.ts +2 -2
  350. package/src/tests/otel-session-cost-metrics.test.ts +1 -1
  351. package/src/tests/page-proxy-authed.test.ts +2 -2
  352. package/src/tests/page-proxy.test.ts +2 -2
  353. package/src/tests/page-session.test.ts +7 -7
  354. package/src/tests/page-viewer-auth.test.ts +2 -2
  355. package/src/tests/pages-authed-mode.test.ts +1 -1
  356. package/src/tests/pages-http.test.ts +1 -1
  357. package/src/tests/pages-password-mode.test.ts +1 -1
  358. package/src/tests/pages-public-authed-401.test.ts +1 -1
  359. package/src/tests/pages-public-html.test.ts +2 -2
  360. package/src/tests/pages-view-count.test.ts +1 -1
  361. package/src/tests/pi-mono-adapter.test.ts +10 -10
  362. package/src/tests/pi-mono-extension.test.ts +2 -2
  363. package/src/tests/preload.ts +5 -0
  364. package/src/tests/pricing-routes.test.ts +1 -1
  365. package/src/tests/profile-sync-warning.test.ts +8 -8
  366. package/src/tests/profile-sync.test.ts +8 -8
  367. package/src/tests/prompt-template-session.test.ts +36 -5
  368. package/src/tests/provider-process-group.test.ts +95 -4
  369. package/src/tests/providers/pi-cost.test.ts +1 -1
  370. package/src/tests/queue-stall-alarm.test.ts +1 -1
  371. package/src/tests/rbac-admission.test.ts +19 -4
  372. package/src/tests/rbac-charact-http.test.ts +1 -1
  373. package/src/tests/rbac-e2e-helpers.ts +1 -1
  374. package/src/tests/rbac-engine.test.ts +39 -0
  375. package/src/tests/realtime-room-auth.test.ts +1 -1
  376. package/src/tests/realtime-room-surfaces.test.ts +1 -1
  377. package/src/tests/reload-config.test.ts +45 -1
  378. package/src/tests/routing-affinity-inventory.test.ts +1 -1
  379. package/src/tests/routing-reason-contract.test.ts +76 -3
  380. package/src/tests/routing-reason-inventory.test.ts +11 -6
  381. package/src/tests/routing-source.test.ts +53 -0
  382. package/src/tests/runner-agent-fs-provision-retry.test.ts +1 -1
  383. package/src/tests/runner-context-preamble.test.ts +1 -1
  384. package/src/tests/runner-deployment-resume.test.ts +1 -1
  385. package/src/tests/runner-fallback-output.test.ts +1 -1
  386. package/src/tests/runner-identity-refresh.test.ts +1 -1
  387. package/src/tests/runner-skills-refresh.test.ts +1 -1
  388. package/src/tests/schedule-target-type.test.ts +3 -3
  389. package/src/tests/scheduled-tasks.test.ts +14 -5
  390. package/src/tests/scheduler-occurrence.test.ts +347 -0
  391. package/src/tests/script-apis-mcp.test.ts +1 -1
  392. package/src/tests/script-connections-http.test.ts +61 -58
  393. package/src/tests/script-connections-mcp.test.ts +1 -1
  394. package/src/tests/script-connections.test.ts +3 -1
  395. package/src/tests/script-runs-http.test.ts +15 -7
  396. package/src/tests/script-workflows-runtime-e2e.test.ts +1 -1
  397. package/src/tests/scripts-boot-reembed.test.ts +4 -0
  398. package/src/tests/scripts-embeddings.test.ts +4 -0
  399. package/src/tests/scripts-external-api.test.ts +1 -1
  400. package/src/tests/scripts-http.test.ts +1 -1
  401. package/src/tests/scripts-import-allowlist.test.ts +44 -1
  402. package/src/tests/scripts-mcp-e2e.test.ts +81 -1
  403. package/src/tests/scripts-only-gating.test.ts +4 -2
  404. package/src/tests/scripts-retention.test.ts +1 -1
  405. package/src/tests/scripts-runtime-identity.test.ts +2 -2
  406. package/src/tests/scripts-runtime-secret-egress.test.ts +1 -1
  407. package/src/tests/scripts-runtime.test.ts +6 -4
  408. package/src/tests/scripts-typecheck.test.ts +21 -0
  409. package/src/tests/sdk-allowlist.test.ts +1 -1
  410. package/src/tests/secret-scrubber.test.ts +38 -31
  411. package/src/tests/seed-registry.test.ts +46 -8
  412. package/src/tests/seed-schedules.test.ts +44 -9
  413. package/src/tests/seed-workflows.test.ts +21 -9
  414. package/src/tests/send-task-output-schema.test.ts +9 -1
  415. package/src/tests/send-task-requested-by.test.ts +1 -0
  416. package/src/tests/send-task-slack-routing-guard.test.ts +2 -0
  417. package/src/tests/session-costs-codex-recompute.test.ts +1 -1
  418. package/src/tests/session-costs-golden.test.ts +2 -2
  419. package/src/tests/session-costs-model-key-normalize.test.ts +2 -2
  420. package/src/tests/session-costs-recompute-all-providers.test.ts +1 -1
  421. package/src/tests/session-tokens.test.ts +1 -1
  422. package/src/tests/shutdown-error-scrubbing.test.ts +1 -1
  423. package/src/tests/slack-blocks.test.ts +12 -1
  424. package/src/tests/slack-file-tools-attachments.test.ts +1 -1
  425. package/src/tests/slack-inbound-files.test.ts +222 -86
  426. package/src/tests/slack-reaction-config.test.ts +5 -4
  427. package/src/tests/slack-read-boundaries.test.ts +1 -1
  428. package/src/tests/slack-render-v2.test.ts +196 -4
  429. package/src/tests/slack-router.test.ts +17 -2
  430. package/src/tests/slack-steering.test.ts +19 -0
  431. package/src/tests/status.test.ts +19 -7
  432. package/src/tests/steering-core.test.ts +1 -1
  433. package/src/tests/steering-enabled.test.ts +6 -8
  434. package/src/tests/steering-transport.test.ts +4 -4
  435. package/src/tests/store-progress-output-guidance.test.ts +34 -0
  436. package/src/tests/swarm-tool-result-gate.test.ts +11 -11
  437. package/src/tests/swarm-x-tool.test.ts +7 -5
  438. package/src/tests/sync-ai-toolbox-skills.test.ts +19 -0
  439. package/src/tests/task-supersede-resume.test.ts +1 -1
  440. package/src/tests/task-tool-preload-mcp.test.ts +4 -1
  441. package/src/tests/task-tools-ctx.test.ts +2 -0
  442. package/src/tests/tasks-requested-by-filter.test.ts +2 -2
  443. package/src/tests/telemetry-init.test.ts +11 -3
  444. package/src/tests/tool-annotations.test.ts +1 -1
  445. package/src/tests/tool-output-agent-id.test.ts +1 -0
  446. package/src/tests/tool-registrar-no-input.test.ts +42 -1
  447. package/src/tests/tracker-fold.test.ts +7 -7
  448. package/src/tests/tracker-tools.test.ts +3 -3
  449. package/src/tests/ui-followup-lead-delegation.test.ts +1 -0
  450. package/src/tests/unified-oauth-migration.test.ts +5 -5
  451. package/src/tests/user-token-rest-auth.test.ts +1 -1
  452. package/src/tests/user-token-routes.test.ts +1 -1
  453. package/src/tests/whoami-route.test.ts +1 -1
  454. package/src/tests/workflow-agent-task.test.ts +15 -13
  455. package/src/tests/workflow-ctx.test.ts +1 -1
  456. package/src/tests/workflow-e2e.test.ts +1 -1
  457. package/src/tests/workflow-engine-v2.test.ts +3 -1
  458. package/src/tests/workflow-executors.test.ts +2 -2
  459. package/src/tests/workflow-http-v2.test.ts +8 -6
  460. package/src/tests/workflow-input-redaction.test.ts +7 -5
  461. package/src/tests/workflow-integration-io.test.ts +2 -2
  462. package/src/tests/workflow-llm.test.ts +5 -5
  463. package/src/tests/workflow-registry.test.ts +1 -1
  464. package/src/tests/workflow-swarm-script.test.ts +1 -1
  465. package/src/tests/workflow-triggers-v2.test.ts +23 -21
  466. package/src/tests/x-composio.test.ts +9 -7
  467. package/src/tests/x402-client.test.ts +1 -1
  468. package/src/tests/x402-config.test.ts +28 -41
  469. package/src/tools/defer-task.ts +156 -24
  470. package/src/tools/extension-common.ts +84 -0
  471. package/src/tools/extension-install.ts +65 -0
  472. package/src/tools/extension-list.ts +66 -0
  473. package/src/tools/script-common.ts +43 -18
  474. package/src/tools/send-task.ts +87 -105
  475. package/src/tools/skills/skill-publish.ts +1 -0
  476. package/src/tools/store-progress.ts +1 -1
  477. package/src/tools/task-action.ts +43 -22
  478. package/src/tools/task-tool-ctx.ts +2 -0
  479. package/src/tools/templates.ts +2 -1
  480. package/src/tools/tool-config.ts +3 -1
  481. package/src/tools/utils.ts +140 -16
  482. package/src/types.ts +144 -0
  483. package/src/utils/constants.ts +7 -1
  484. package/src/utils/credentials.test.ts +16 -16
  485. package/src/utils/multi-runtime.ts +2 -2
  486. package/src/utils/steering-enabled.ts +4 -4
  487. package/src/workflows/executors/agent-task.ts +18 -3
  488. package/templates/ai-toolbox.manifest.json +7 -1
  489. package/templates/extensions/README.md +17 -0
  490. package/templates/extensions/notify-on-complete/README.md +11 -0
  491. package/templates/extensions/notify-on-complete/hooks.ts +61 -0
  492. package/templates/extensions/notify-on-complete/manifest.json +7 -0
  493. package/templates/extensions/require-ticket-ref/README.md +11 -0
  494. package/templates/extensions/require-ticket-ref/hooks.ts +30 -0
  495. package/templates/extensions/require-ticket-ref/manifest.json +7 -0
  496. package/templates/extensions/require-verification-note/README.md +11 -0
  497. package/templates/extensions/require-verification-note/hooks.ts +32 -0
  498. package/templates/extensions/require-verification-note/manifest.json +7 -0
  499. package/templates/schedules/daily-hn-briefing/config.json +1 -1
  500. package/templates/schedules/gtm-weekly-review/config.json +1 -1
  501. package/templates/schedules/weekly-code-health-reports/config.json +1 -1
  502. package/templates/schedules/weekly-dependabot-triage/config.json +1 -1
  503. package/templates/schedules/weekly-dora-metrics/config.json +1 -1
  504. package/templates/schedules/weekly-harness-upgrade-check/config.json +1 -1
  505. package/templates/skills/delegate-work/files/scripts/codex-exec.sh +1 -1
  506. package/templates/skills/scheduling/content.md +2 -0
  507. package/templates/skills/serply-search/SKILL.md +95 -0
  508. package/templates/skills/serply-search/config.json +13 -0
  509. package/templates/skills/serply-search/content.md +90 -0
  510. package/templates/skills/swarm-extensions/config.json +14 -0
  511. package/templates/skills/swarm-extensions/content.md +120 -0
  512. package/templates/skills/swarm-scripts/SKILL.md +2 -2
  513. package/templates/skills/swarm-scripts/content.md +2 -2
  514. package/templates/workflows/claude-code-changelog-watch/config.json +1 -1
  515. package/templates/workflows/gsc-topic-miner/config.json +1 -1
  516. package/templates/workflows/linear-drain-loop/config.json +1 -1
  517. package/templates/workflows/llm-safe-release-context/config.json +1 -1
  518. package/templates/workflows/ralph-loop/config.json +1 -1
  519. package/dist/cli-7fehefdf.js +0 -562
  520. package/dist/cli-ayvy5kde.js +0 -164
  521. package/dist/cli-ddfw1mc4.js +0 -4322
  522. package/dist/cli-hzqmgcm2.js +0 -3066
  523. package/dist/cli-j4d4f6hv.js +0 -338
  524. package/dist/cli-qgm2pfpq.js +0 -6377
  525. package/dist/cli-sdzq01t9.js +0 -823
  526. package/dist/cli-xvkmedgn.js +0 -332
  527. package/dist/cli-y3pq4v9g.js +0 -664
  528. package/dist/{anthropic-messages-vs2rabzp.js → anthropic-messages-2y8nktar.js} +19 -19
  529. package/dist/{claude-managed-setup-f5pmsyrp.js → claude-managed-setup-48dwg9bv.js} +3 -3
  530. package/dist/{cli-81r683bv.js → cli-ch38q5z4.js} +0 -0
  531. package/dist/{cli-6664w7y4.js → cli-kj76p1ez.js} +8 -8
  532. package/dist/{cli-c71mg51n.js → cli-r2fpe7cx.js} +5 -5
  533. package/dist/{cli-4xz3pmrq.js → cli-y6x0gqtg.js} +16 -16
  534. package/dist/{index-aa3sa6s8.js → index-2wsdsnmm.js} +1 -1
  535. package/dist/{mistral-conversations-4ryk7h83.js → mistral-conversations-qhr84ph3.js} +9 -9
  536. package/dist/{openai-completions-0bqmsajw.js → openai-completions-32rdwmze.js} +19 -19
  537. package/dist/{openrouter-images-qx18fyp8.js → openrouter-images-9f9ek4rw.js} +3 -3
  538. package/dist/{pi-messages-79jvzz1d.js → pi-messages-b1mbr6gp.js} +4 -4
package/src/types.ts CHANGED
@@ -3,6 +3,7 @@
3
3
  // reference them emit `$ref`s and SDK generators produce named types.
4
4
 
5
5
  import { normalizeAssetKey } from "./assets/key";
6
+ import { isSafeBundlePath } from "./extensions/bundle-path";
6
7
  import { MAX_PROFILE_FILE_LENGTH } from "./utils/constants";
7
8
  import { z } from "./utils/zod-openapi";
8
9
  // ─── Asset namespaces ──────────────────────────────────────────────────────
@@ -349,6 +350,9 @@ export const RoutingReasonSchema = z.enum([
349
350
  ]);
350
351
  export type RoutingReason = z.infer<typeof RoutingReasonSchema>;
351
352
 
353
+ export const RoutingSourceSchema = z.enum(["declared", "engine_default"]);
354
+ export type RoutingSource = z.infer<typeof RoutingSourceSchema>;
355
+
352
356
  // ---------------------------------------------------------------------------
353
357
  // Harness Provider
354
358
  // ---------------------------------------------------------------------------
@@ -514,6 +518,9 @@ export const AgentTaskSchema = z
514
518
  status: AgentTaskStatusSchema,
515
519
  source: AgentTaskSourceSchema.default("mcp"),
516
520
  routingReason: RoutingReasonSchema.optional(),
521
+ routingSource: RoutingSourceSchema.optional().describe(
522
+ "Origin of the routing reason: declared by the caller or chosen by the engine. Absent for unknown historical provenance or no reason.",
523
+ ),
517
524
  routingNote: z.string().max(200).optional(),
518
525
 
519
526
  // Task metadata
@@ -676,6 +683,7 @@ export const CreateTaskOptionsSchema = z.object({
676
683
  creatorAgentId: z.string().optional(),
677
684
  source: AgentTaskSourceSchema.optional(),
678
685
  routingReason: RoutingReasonSchema.optional(),
686
+ routingSource: RoutingSourceSchema.optional(),
679
687
  routingNote: z.string().max(200).optional(),
680
688
  taskType: z.string().max(50).optional(),
681
689
  tags: z.array(z.string()).optional(),
@@ -941,6 +949,9 @@ export type IdentityEventType = z.infer<typeof IdentityEventTypeSchema>;
941
949
  // - broken_task — tasks in failed/cancelled status
942
950
  // - to_read — sessions/tasks marked unread for the user
943
951
  // - to_start_template — task-templates the user hasn't dismissed
952
+ // - notification — dashboard notification-center items (see
953
+ // apps/ui/src/lib/notifications/definitions.ts);
954
+ // itemId is the notification definition's key
944
955
  //
945
956
  // Statuses:
946
957
  // - open — visible in inbox
@@ -953,6 +964,7 @@ export const InboxItemTypeSchema = z.enum([
953
964
  "broken_task",
954
965
  "to_read",
955
966
  "to_start_template",
967
+ "notification",
956
968
  ]);
957
969
  export type InboxItemType = z.infer<typeof InboxItemTypeSchema>;
958
970
 
@@ -969,6 +981,8 @@ export const InboxItemStateSchema = z
969
981
  snoozeUntil: z.string().optional(),
970
982
  dismissedAt: z.string().optional(),
971
983
  doneAt: z.string().optional(),
984
+ /** First-viewed timestamp, set once on first panel open. Independent of status. */
985
+ readAt: z.string().optional(),
972
986
  createdAt: z.string(),
973
987
  lastUpdatedAt: z.string(),
974
988
  })
@@ -2786,6 +2800,136 @@ export const ScriptVersionRecordSchema = z
2786
2800
  .openapi("ScriptVersionRecord");
2787
2801
  export type ScriptVersionRecord = z.infer<typeof ScriptVersionRecordSchema>;
2788
2802
 
2803
+ // ============================================================================
2804
+ // Extension Types
2805
+ // ============================================================================
2806
+
2807
+ const ExtensionNameSchema = z
2808
+ .string()
2809
+ .min(1)
2810
+ .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/, "must be a lowercase slug");
2811
+
2812
+ const SemverSchema = z
2813
+ .string()
2814
+ .regex(
2815
+ /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/,
2816
+ "must be a semantic version",
2817
+ );
2818
+
2819
+ export const ExtensionManifestSchema = z
2820
+ .object({
2821
+ name: ExtensionNameSchema,
2822
+ description: z.string(),
2823
+ version: SemverSchema,
2824
+ runtime: z.enum(["api", "worker"]),
2825
+ assets: z
2826
+ .object({
2827
+ hooks: z
2828
+ .string()
2829
+ .min(1)
2830
+ .refine(
2831
+ isSafeBundlePath,
2832
+ "Must be a relative POSIX file path without empty, dot, or parent segments, at most 256 characters",
2833
+ ),
2834
+ skills: z.array(z.string()).optional(),
2835
+ workflows: z.array(z.string()).optional(),
2836
+ schedules: z.array(z.string()).optional(),
2837
+ })
2838
+ .strict(),
2839
+ homepage: z.string().url().optional(),
2840
+ author: z.string().min(1).optional(),
2841
+ })
2842
+ .strict()
2843
+ .openapi("ExtensionManifest");
2844
+ const _manifestShapeGuard: import("./extensions/contract").ExtensionManifest = {} as z.infer<
2845
+ typeof ExtensionManifestSchema
2846
+ >;
2847
+ const _manifestSchemaGuard: z.infer<typeof ExtensionManifestSchema> =
2848
+ {} as import("./extensions/contract").ExtensionManifest;
2849
+ void _manifestShapeGuard;
2850
+ void _manifestSchemaGuard;
2851
+ export type ExtensionManifest = z.infer<typeof ExtensionManifestSchema>;
2852
+
2853
+ export const ExtensionStatusSchema = z.enum(["disabled", "enabled", "error", "auto-disabled"]);
2854
+ export type ExtensionStatus = z.infer<typeof ExtensionStatusSchema>;
2855
+
2856
+ export const ExtensionSchema = z
2857
+ .object({
2858
+ id: z.string(),
2859
+ name: ExtensionNameSchema,
2860
+ description: z.string(),
2861
+ runtime: z.enum(["api", "worker"]),
2862
+ manifestJson: z.string(),
2863
+ contentHash: z.string(),
2864
+ version: z.number().int().min(1),
2865
+ activeVersion: z.number().int().min(1),
2866
+ enabled: z.boolean(),
2867
+ priority: z.number().int(),
2868
+ configJson: z.string(),
2869
+ status: ExtensionStatusSchema,
2870
+ consecutiveFailures: z.number().int().min(0),
2871
+ lastError: z.string().nullable(),
2872
+ agentId: z.string().nullable(),
2873
+ createdByAgentId: z.string().nullable(),
2874
+ createdAt: z.string(),
2875
+ updatedAt: z.string(),
2876
+ })
2877
+ .openapi("Extension");
2878
+ export type Extension = z.infer<typeof ExtensionSchema>;
2879
+
2880
+ export const ExtensionFileSchema = z
2881
+ .object({
2882
+ id: z.string(),
2883
+ extensionId: z.string(),
2884
+ path: z.string(),
2885
+ content: z.string(),
2886
+ contentHash: z.string(),
2887
+ })
2888
+ .openapi("ExtensionFile");
2889
+ export type ExtensionFile = z.infer<typeof ExtensionFileSchema>;
2890
+
2891
+ export const ExtensionVersionSchema = z
2892
+ .object({
2893
+ id: z.string(),
2894
+ extensionId: z.string(),
2895
+ version: z.number().int().min(1),
2896
+ manifestJson: z.string(),
2897
+ filesJson: z.string(),
2898
+ contentHash: z.string(),
2899
+ changedByAgentId: z.string().nullable(),
2900
+ changedAt: z.string(),
2901
+ changeReason: z.string().nullable(),
2902
+ })
2903
+ .openapi("ExtensionVersion");
2904
+ export type ExtensionVersion = z.infer<typeof ExtensionVersionSchema>;
2905
+
2906
+ export const ExtensionRunSchema = z
2907
+ .object({
2908
+ id: z.string(),
2909
+ extensionId: z.string(),
2910
+ version: z.number().int().min(1),
2911
+ event: z.string(),
2912
+ action: z.enum(["continue", "modify", "block", "error", "timeout", "load-error"]),
2913
+ durationMs: z.number().int().nullable(),
2914
+ message: z.string().nullable(),
2915
+ agentId: z.string().nullable(),
2916
+ subject: z.string().nullable(),
2917
+ createdAt: z.string(),
2918
+ })
2919
+ .openapi("ExtensionRun");
2920
+ export type ExtensionRun = z.infer<typeof ExtensionRunSchema>;
2921
+
2922
+ export const ExtensionInstallBodySchema = z
2923
+ .object({
2924
+ manifest: ExtensionManifestSchema,
2925
+ files: z.record(z.string(), z.string()),
2926
+ priority: z.number().int().optional(),
2927
+ config: z.record(z.string(), z.unknown()).optional(),
2928
+ })
2929
+ .strict()
2930
+ .openapi("ExtensionInstallBody");
2931
+ export type ExtensionInstallBody = z.infer<typeof ExtensionInstallBodySchema>;
2932
+
2789
2933
  /** Lean projection served by `GET /api/scripts` — omits `source` (payload size) and raw JSON blobs. */
2790
2934
  export type ScriptListItem = Omit<
2791
2935
  ScriptRecord,
@@ -130,5 +130,11 @@ export function buildAgentFsLiveUrl(opts: {
130
130
  if (!orgId || !driveId) return null;
131
131
  const host = getAgentFsLiveUrl();
132
132
  const normalizedPath = path.replace(/^\/+/, "");
133
- return `${host}/file/~/${orgId}/${driveId}/${normalizedPath}`;
133
+ // Never double-encode an already-encoded segment: preserve existing %HH
134
+ // escapes byte-for-byte, including in segments that also contain raw text.
135
+ const encodedPath = normalizedPath
136
+ .split("/")
137
+ .map((segment) => encodeURIComponent(segment).replace(/%25([0-9a-f]{2})/gi, "%$1"))
138
+ .join("/");
139
+ return `${host}/file/~/${orgId}/${driveId}/${encodedPath}`;
134
140
  }
@@ -63,30 +63,30 @@ describe("selectRandomCredential", () => {
63
63
  describe("resolveCredentialPools", () => {
64
64
  it("resolves comma-separated CLAUDE_CODE_OAUTH_TOKEN", async () => {
65
65
  const env: Record<string, string | undefined> = {
66
- CLAUDE_CODE_OAUTH_TOKEN: "token1,token2",
66
+ CLAUDE_CODE_OAUTH_TOKEN: "example-token1,example-token2",
67
67
  OTHER_VAR: "unchanged",
68
68
  };
69
69
  await resolveCredentialPools(env);
70
- expect(["token1", "token2"]).toContain(env.CLAUDE_CODE_OAUTH_TOKEN!);
70
+ expect(["example-token1", "example-token2"]).toContain(env.CLAUDE_CODE_OAUTH_TOKEN!);
71
71
  expect(env.OTHER_VAR).toBe("unchanged");
72
72
  });
73
73
 
74
74
  it("resolves comma-separated ANTHROPIC_API_KEY", async () => {
75
75
  const env: Record<string, string | undefined> = {
76
- ANTHROPIC_API_KEY: "key1,key2,key3",
76
+ ANTHROPIC_API_KEY: "example-key1,example-key2,example-key3",
77
77
  };
78
78
  await resolveCredentialPools(env);
79
- expect(["key1", "key2", "key3"]).toContain(env.ANTHROPIC_API_KEY!);
79
+ expect(["example-key1", "example-key2", "example-key3"]).toContain(env.ANTHROPIC_API_KEY!);
80
80
  });
81
81
 
82
82
  it("leaves single values unchanged", async () => {
83
83
  const env: Record<string, string | undefined> = {
84
- CLAUDE_CODE_OAUTH_TOKEN: "single-token",
85
- ANTHROPIC_API_KEY: "single-key",
84
+ CLAUDE_CODE_OAUTH_TOKEN: "example-single-token",
85
+ ANTHROPIC_API_KEY: "example-single-key",
86
86
  };
87
87
  await resolveCredentialPools(env);
88
- expect(env.CLAUDE_CODE_OAUTH_TOKEN).toBe("single-token");
89
- expect(env.ANTHROPIC_API_KEY).toBe("single-key");
88
+ expect(env.CLAUDE_CODE_OAUTH_TOKEN).toBe("example-single-token");
89
+ expect(env.ANTHROPIC_API_KEY).toBe("example-single-key");
90
90
  });
91
91
 
92
92
  it("handles undefined credential vars", async () => {
@@ -116,30 +116,30 @@ describe("resolveCredentialPools", () => {
116
116
 
117
117
  it("resolves both credential vars independently", async () => {
118
118
  const env: Record<string, string | undefined> = {
119
- CLAUDE_CODE_OAUTH_TOKEN: "oauth1,oauth2",
120
- ANTHROPIC_API_KEY: "apikey1,apikey2",
119
+ CLAUDE_CODE_OAUTH_TOKEN: "example-oauth1,example-oauth2",
120
+ ANTHROPIC_API_KEY: "example-apikey1,example-apikey2",
121
121
  };
122
122
  await resolveCredentialPools(env);
123
- expect(["oauth1", "oauth2"]).toContain(env.CLAUDE_CODE_OAUTH_TOKEN!);
124
- expect(["apikey1", "apikey2"]).toContain(env.ANTHROPIC_API_KEY!);
123
+ expect(["example-oauth1", "example-oauth2"]).toContain(env.CLAUDE_CODE_OAUTH_TOKEN!);
124
+ expect(["example-apikey1", "example-apikey2"]).toContain(env.ANTHROPIC_API_KEY!);
125
125
  });
126
126
  });
127
127
 
128
128
  describe("validateClaudeCredentials", () => {
129
129
  it("returns 'oauth' when CLAUDE_CODE_OAUTH_TOKEN is set", () => {
130
- const env = { CLAUDE_CODE_OAUTH_TOKEN: "some-oauth-token" };
130
+ const env = { CLAUDE_CODE_OAUTH_TOKEN: "example-some-oauth-token" };
131
131
  expect(validateClaudeCredentials(env)).toBe("oauth");
132
132
  });
133
133
 
134
134
  it("returns 'api_key' when only ANTHROPIC_API_KEY is set", () => {
135
- const env = { ANTHROPIC_API_KEY: "sk-ant-123" };
135
+ const env = { ANTHROPIC_API_KEY: "example-sk-ant-123" };
136
136
  expect(validateClaudeCredentials(env)).toBe("api_key");
137
137
  });
138
138
 
139
139
  it("returns 'oauth' when both are set (oauth takes priority)", () => {
140
140
  const env = {
141
- CLAUDE_CODE_OAUTH_TOKEN: "some-oauth-token",
142
- ANTHROPIC_API_KEY: "sk-ant-123",
141
+ CLAUDE_CODE_OAUTH_TOKEN: "example-some-oauth-token",
142
+ ANTHROPIC_API_KEY: "example-sk-ant-123",
143
143
  };
144
144
  expect(validateClaudeCredentials(env)).toBe("oauth");
145
145
  });
@@ -1,12 +1,12 @@
1
1
  import { parseEnvFlag } from "./env-flag";
2
2
 
3
3
  /**
4
- * Opt-in, default off: allows one logical agent to be served by several
4
+ * Enabled by default: allows one logical agent to be served by several
5
5
  * worker processes. Lives outside `src/be` so worker-side code can import it
6
6
  * without crossing the DB boundary.
7
7
  */
8
8
  export function isMultiRuntimeEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
9
- return parseEnvFlag(env.MULTI_RUNTIME_ENABLED, false);
9
+ return parseEnvFlag(env.MULTI_RUNTIME_ENABLED, true);
10
10
  }
11
11
 
12
12
  /**
@@ -1,12 +1,12 @@
1
1
  import { parseEnvFlag } from "./env-flag";
2
2
 
3
3
  /**
4
- * Worker-safe steering opt-in reader. Keep this outside `src/be` so
4
+ * Worker-safe steering flag reader. Keep this outside `src/be` so
5
5
  * commands, tools, and providers can use it without crossing the DB boundary.
6
6
  *
7
- * Steering is DISABLED by default: it only turns on when the operator sets
8
- * `STEERING_ENABLED=true|1`.
7
+ * Steering is enabled by default. Operators can opt out with
8
+ * `STEERING_ENABLED=false|0`.
9
9
  */
10
10
  export function isSteeringEnabled(env: NodeJS.ProcessEnv = process.env): boolean {
11
- return parseEnvFlag(env.STEERING_ENABLED, false);
11
+ return parseEnvFlag(env.STEERING_ENABLED, true);
12
12
  }
@@ -1,5 +1,7 @@
1
1
  import { z } from "zod";
2
+ import { applyPreTaskCreate } from "../../extensions/apply-task-create";
2
3
  import { workflowContextKey } from "../../tasks/context-key";
4
+ import { TaskCreationBlockedError } from "../../tasks/errors";
3
5
  import { withSiblingAwareness } from "../../tasks/sibling-awareness";
4
6
  import type { ExecutorMeta } from "../../types";
5
7
  import {
@@ -96,14 +98,19 @@ export class AgentTaskExecutor extends BaseExecutor<
96
98
  }
97
99
 
98
100
  // 3. Create the task (config is already deep-interpolated by the engine)
99
- const { description: taskDescription, options: taskOptions } = await withSiblingAwareness(
100
- config.template,
101
- {
101
+ const preCreate = await applyPreTaskCreate({
102
+ description: config.template,
103
+ options: {
102
104
  key: effectiveKey,
103
105
  agentId: config.agentId ?? null,
104
106
  // A configured workflow target is an author pin, including existing definitions.
105
107
  routingReason: config.routingReason ?? (config.agentId ? "human_pinned" : undefined),
106
108
  routingNote: config.routingNote,
109
+ routingSource: config.routingReason
110
+ ? "declared"
111
+ : config.agentId
112
+ ? "engine_default"
113
+ : undefined,
107
114
  source: "workflow",
108
115
  tags: config.tags,
109
116
  priority: config.priority,
@@ -120,6 +127,14 @@ export class AgentTaskExecutor extends BaseExecutor<
120
127
  followUpConfig: config.followUpConfig,
121
128
  contextKey: workflowContextKey({ workflowRunId: meta.runId }),
122
129
  },
130
+ origin: "workflow",
131
+ });
132
+ if (preCreate.kind === "blocked") {
133
+ throw new TaskCreationBlockedError(preCreate.reason, preCreate.extension);
134
+ }
135
+ const { description: taskDescription, options: taskOptions } = await withSiblingAwareness(
136
+ preCreate.description,
137
+ preCreate.options,
123
138
  );
124
139
  const task = await db.createTaskExtended(taskDescription, taskOptions);
125
140
 
@@ -17,7 +17,7 @@
17
17
  "templates/skills/comms/files/references/visual-shapes.md": "5e07e9250ad4cdc877af2281525185f0de89c01f90a077463a2c77c8a7b998e8",
18
18
  "templates/skills/delegate-work/config.json": "5b1542eb0be359bb8a17117fcf87917e0607d1b939ae3266ddffacdc14efb281",
19
19
  "templates/skills/delegate-work/content.md": "c9562bd17846d3595d40172ecfdc6f85bb99eaf23597eb9d5aa9635d5c14d079",
20
- "templates/skills/delegate-work/files/scripts/codex-exec.sh": "c2222986c46ac608403f28f201230cb34c7d7ac41a2262dc2c8dbd99c8645dbb",
20
+ "templates/skills/delegate-work/files/scripts/codex-exec.sh": "be9b33ba111afc8b38c20a4190eae19099025474d4ed3278d944ee0e6b6621af",
21
21
  "templates/skills/design-docs/config.json": "b78141763541486d67a105e8fa23873c9ffee6a682832c4b7266b8320d55ead7",
22
22
  "templates/skills/design-docs/content.md": "fc860031defbd192c1b8e1c024b46509d78dcf10dbf1b8c93cc4d62396153a52",
23
23
  "templates/skills/design-docs/files/template.md": "72d2cdcf8713c08d525d69892c5fed536107594522e3e799ae44f51df7015a36",
@@ -103,6 +103,12 @@
103
103
  ],
104
104
  "source": "https://github.com/desplega-ai/ai-toolbox.git",
105
105
  "transforms": {
106
+ "bundledCommentRewrites": [
107
+ {
108
+ "path": "scripts/codex-exec.sh",
109
+ "skill": "delegate-work"
110
+ }
111
+ ],
106
112
  "executableBitsDowngraded": [
107
113
  {
108
114
  "path": "scripts/codex-exec.sh",
@@ -0,0 +1,17 @@
1
+ # Extension templates
2
+
3
+ Ready-to-install extension bundles. Each folder holds `manifest.json`, `hooks.ts`, and a README with its config.
4
+
5
+ | Name | Event | What it does |
6
+ |---|---|---|
7
+ | `require-ticket-ref` | `pre.task.create` | Blocks REST, MCP, and Slack tasks that do not name a ticket |
8
+ | `notify-on-complete` | `post.task.completed`, `post.task.failed` | Posts a summary to a Slack channel |
9
+ | `require-verification-note` | `pre.tool.call` | Refuses completion without a `Verified:` line in the output |
10
+
11
+ Install one with the REST route or the `extension-install` MCP tool, then enable it from Settings, Extensions:
12
+
13
+ ```bash
14
+ bun scripts/extensions/install-template.ts require-ticket-ref --config '{"pattern":"\\bDES-\\d+\\b"}'
15
+ ```
16
+
17
+ The hook contract is served at `GET /api/extensions/type-defs`. The `swarm-extensions` seeded skill teaches agents the same flow.
@@ -0,0 +1,11 @@
1
+ # notify-on-complete
2
+
3
+ Posts one Slack message per finished task to a channel of your choice. Uses `ctx.swarm.slack_post`, so the message is sent by the swarm bot on behalf of the `ext:notify-on-complete` identity.
4
+
5
+ Config:
6
+
7
+ ```json
8
+ { "channelId": "C0123456789", "includeFailed": true, "maxOutputChars": 400 }
9
+ ```
10
+
11
+ Post hooks run after the task change is committed and cannot block or modify anything. A Slack failure counts as a handler failure; five in a row auto-disable the extension.
@@ -0,0 +1,61 @@
1
+ import type { CtxFor, SwarmExtension } from "swarm-extension";
2
+ import { z } from "zod";
3
+
4
+ export const config = z.object({
5
+ channelId: z.string().min(1),
6
+ includeFailed: z.boolean().default(true),
7
+ maxOutputChars: z.number().int().min(40).max(2000).default(400),
8
+ });
9
+
10
+ const manifest = {
11
+ name: "notify-on-complete",
12
+ description: "Posts a short summary to a Slack channel when a task completes or fails",
13
+ version: "1.0.0",
14
+ runtime: "api",
15
+ assets: { hooks: "hooks.ts" },
16
+ config,
17
+ } as const;
18
+
19
+ type SdkResult = { success?: boolean; status?: number; data?: unknown };
20
+
21
+ // SDK calls resolve with { success, status, data } and do not throw on a tool error.
22
+ // Throwing here makes the failure visible in the run log and counts toward auto-disable.
23
+ async function post(ctx: CtxFor<typeof manifest>, message: string): Promise<void> {
24
+ const result = (await ctx.swarm.slack_post({
25
+ channelId: ctx.config.channelId,
26
+ message,
27
+ })) as SdkResult;
28
+ if (!result?.success) {
29
+ throw new Error(
30
+ `slack_post failed (${result?.status ?? "no status"}): ${JSON.stringify(result?.data ?? null).slice(0, 200)}`,
31
+ );
32
+ }
33
+ }
34
+
35
+ function clip(text: string, max: number): string {
36
+ const single = text.replace(/\s+/g, " ").trim();
37
+ return single.length > max ? `${single.slice(0, max - 1)}…` : single;
38
+ }
39
+
40
+ const extension: SwarmExtension<typeof manifest> = (api) => {
41
+ api.on("post.task.completed", async (event, ctx) => {
42
+ const title = event.task.title ?? clip(event.task.task, 80);
43
+ await post(
44
+ ctx,
45
+ `:white_check_mark: *${title}* completed (task \`${event.task.id.slice(0, 8)}\`)\n${clip(event.output, ctx.config.maxOutputChars)}`,
46
+ );
47
+ await ctx.state.incr("notified:completed");
48
+ });
49
+
50
+ api.on("post.task.failed", async (event, ctx) => {
51
+ if (!ctx.config.includeFailed) return;
52
+ const title = event.task.title ?? clip(event.task.task, 80);
53
+ await post(
54
+ ctx,
55
+ `:x: *${title}* failed (task \`${event.task.id.slice(0, 8)}\`)\n${clip(event.failureReason, ctx.config.maxOutputChars)}`,
56
+ );
57
+ await ctx.state.incr("notified:failed");
58
+ });
59
+ };
60
+
61
+ export default extension;
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "notify-on-complete",
3
+ "description": "Posts a short summary to a Slack channel when a task completes or fails",
4
+ "version": "1.0.0",
5
+ "runtime": "api",
6
+ "assets": { "hooks": "hooks.ts" }
7
+ }
@@ -0,0 +1,11 @@
1
+ # require-ticket-ref
2
+
3
+ Blocks new tasks that do not name a ticket. Applies to the origins listed in `config.origins` (default `rest`, `mcp`, `slack`), so schedules, workflows, webhooks, and follow-ups keep working.
4
+
5
+ Config:
6
+
7
+ ```json
8
+ { "pattern": "\\bDES-\\d+\\b", "origins": ["rest", "mcp", "slack"] }
9
+ ```
10
+
11
+ Effect: REST returns `422` with the reason, `send-task` returns an error result, and Slack replies with the reason in the thread. The extension state keeps a `blocked:<origin>` counter.
@@ -0,0 +1,30 @@
1
+ import { block, type SwarmExtension } from "swarm-extension";
2
+ import { z } from "zod";
3
+
4
+ // Config: which origins to police and what a ticket reference looks like.
5
+ export const config = z.object({
6
+ pattern: z.string().default("\\b[A-Z]{2,10}-\\d+\\b"),
7
+ origins: z.array(z.string()).default(["rest", "mcp", "slack"]),
8
+ });
9
+
10
+ const manifest = {
11
+ name: "require-ticket-ref",
12
+ description: "Blocks new tasks from selected origins unless the description names a ticket",
13
+ version: "1.0.0",
14
+ runtime: "api",
15
+ assets: { hooks: "hooks.ts" },
16
+ config,
17
+ } as const;
18
+
19
+ const extension: SwarmExtension<typeof manifest> = (api) => {
20
+ api.on("pre.task.create", async (event, ctx) => {
21
+ if (!ctx.config.origins.includes(event.origin)) return;
22
+ if (new RegExp(ctx.config.pattern).test(event.description)) return;
23
+ await ctx.state.incr(`blocked:${event.origin}`);
24
+ return block(
25
+ `Task must reference a ticket (pattern ${ctx.config.pattern}). Add the ticket id to the description and retry.`,
26
+ );
27
+ });
28
+ };
29
+
30
+ export default extension;
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "require-ticket-ref",
3
+ "description": "Blocks new tasks from selected origins unless the description names a ticket",
4
+ "version": "1.0.0",
5
+ "runtime": "api",
6
+ "assets": { "hooks": "hooks.ts" }
7
+ }
@@ -0,0 +1,11 @@
1
+ # require-verification-note
2
+
3
+ Guards `store-progress` with `status: "completed"`. The call is refused until the `output` contains the configured marker (default `Verified:`). The agent sees the reason as a tool error and can retry with a corrected output.
4
+
5
+ Config:
6
+
7
+ ```json
8
+ { "marker": "Verified:" }
9
+ ```
10
+
11
+ The guard covers agent MCP calls only. REST and dashboard completions are not tool calls and pass through.
@@ -0,0 +1,32 @@
1
+ import { block, type SwarmExtension } from "swarm-extension";
2
+ import { z } from "zod";
3
+
4
+ export const config = z.object({
5
+ marker: z.string().min(1).default("Verified:"),
6
+ });
7
+
8
+ const manifest = {
9
+ name: "require-verification-note",
10
+ description: "Refuses task completion unless the output contains a verification line",
11
+ version: "1.0.0",
12
+ runtime: "api",
13
+ assets: { hooks: "hooks.ts" },
14
+ config,
15
+ } as const;
16
+
17
+ type StoreProgressArgs = { status?: unknown; output?: unknown };
18
+
19
+ const extension: SwarmExtension<typeof manifest> = (api) => {
20
+ api.on("pre.tool.call", (event, ctx) => {
21
+ if (event.tool !== "store-progress") return;
22
+ if (!event.args || typeof event.args !== "object") return;
23
+ const { status, output } = event.args as StoreProgressArgs;
24
+ if (status !== "completed") return;
25
+ if (typeof output === "string" && output.includes(ctx.config.marker)) return;
26
+ return block(
27
+ `Completion output must contain a "${ctx.config.marker}" line that says how the result was checked. Add it and call store-progress again.`,
28
+ );
29
+ });
30
+ };
31
+
32
+ export default extension;
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "require-verification-note",
3
+ "description": "Refuses task completion unless the output contains a verification line",
4
+ "version": "1.0.0",
5
+ "runtime": "api",
6
+ "assets": { "hooks": "hooks.ts" }
7
+ }
@@ -9,6 +9,6 @@
9
9
  "category": "schedules",
10
10
  "placeholders": ["REPORT_EMAIL"],
11
11
  "requires": ["agentmail"],
12
- "runAllSeedersCandidate": false,
12
+ "runAllSeedersCandidate": true,
13
13
  "tags": ["research", "briefing", "browser"]
14
14
  }
@@ -9,6 +9,6 @@
9
9
  "category": "schedules",
10
10
  "placeholders": ["REPO_URL", "GSC_PROPERTY"],
11
11
  "requires": ["github", "gsc"],
12
- "runAllSeedersCandidate": false,
12
+ "runAllSeedersCandidate": true,
13
13
  "tags": ["gtm", "metrics", "reporting"]
14
14
  }
@@ -9,6 +9,6 @@
9
9
  "category": "schedules",
10
10
  "placeholders": ["REPO_URL", "BRANCH", "SCOPE_PATH", "REPORT_NAME", "PAGE_ID"],
11
11
  "requires": ["github"],
12
- "runAllSeedersCandidate": false,
12
+ "runAllSeedersCandidate": true,
13
13
  "tags": ["code-quality", "maintenance", "reporting", "community-template"]
14
14
  }
@@ -9,6 +9,6 @@
9
9
  "category": "schedules",
10
10
  "placeholders": ["REPO_URL", "SLACK_CHANNEL_ID", "TIMEZONE"],
11
11
  "requires": ["github", "slack"],
12
- "runAllSeedersCandidate": false,
12
+ "runAllSeedersCandidate": true,
13
13
  "tags": ["github", "dependencies", "maintenance"]
14
14
  }
@@ -9,6 +9,6 @@
9
9
  "category": "schedules",
10
10
  "placeholders": ["REPO_URL", "BRANCH", "TAG_PATTERN", "REPORT_NAME", "PAGE_ID"],
11
11
  "requires": ["github"],
12
- "runAllSeedersCandidate": false,
12
+ "runAllSeedersCandidate": true,
13
13
  "tags": ["dora", "metrics", "engineering-productivity", "reporting", "community-template"]
14
14
  }
@@ -9,6 +9,6 @@
9
9
  "category": "schedules",
10
10
  "placeholders": ["REPO_URL", "PR_REVIEWER"],
11
11
  "requires": ["github"],
12
- "runAllSeedersCandidate": false,
12
+ "runAllSeedersCandidate": true,
13
13
  "tags": ["harness", "upgrade", "maintenance"]
14
14
  }