@desplega.ai/agent-swarm 1.173.0 → 2.1.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 (511) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-kr4abrsk.js} +17 -16
  3. package/dist/{actions-sgeyv08k.js → actions-eh4g6w2r.js} +39 -34
  4. package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-7h7wdt8q.js} +8 -7
  5. package/dist/{app-km9qnv2f.js → app-7k8s9w5p.js} +18 -14
  6. package/dist/{assistant-5r8tcvvd.js → assistant-wswt2y7p.js} +40 -35
  7. package/dist/{boot-reembed-16rv9843.js → boot-reembed-9apm9qw6.js} +10 -9
  8. package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-whzbdthj.js} +10 -9
  9. package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-ndzmvmgt.js} +11 -10
  10. package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-e9sta0yt.js} +16 -13
  11. package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-4mqd3r6r.js} +19 -18
  12. package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-9wswb52m.js} +7 -5
  13. package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-tpe1effx.js} +6 -4
  14. package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-q49ghmh9.js} +12402 -11850
  15. package/dist/{cli-ne7smj1b.js → cli-01xvj1rq.js} +10 -10
  16. package/dist/{cli-nwrdx840.js → cli-035vekcw.js} +3 -3
  17. package/dist/{cli-9xf7fdtp.js → cli-0pd8hzhc.js} +29 -6
  18. package/dist/{cli-tmhsxhb8.js → cli-0veb92a3.js} +28 -6
  19. package/dist/{cli-c3rk1v0x.js → cli-10jesr25.js} +3 -3
  20. package/dist/{cli-6thk4jz3.js → cli-1y7yywmj.js} +6 -6
  21. package/dist/{cli-6r2f7edk.js → cli-20krdhz5.js} +47 -19
  22. package/dist/{cli-rfs4vddv.js → cli-29rja109.js} +39 -20
  23. package/dist/cli-2m1ktfzz.js +17795 -0
  24. package/dist/{cli-na2pxe4f.js → cli-2pwa0q4d.js} +15 -4
  25. package/dist/{cli-7a93cv8c.js → cli-4mengw46.js} +441 -43
  26. package/dist/{cli-94b48jhk.js → cli-5twdke5x.js} +16 -14
  27. package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
  28. package/dist/cli-6cvfxs8r.js +47 -0
  29. package/dist/{cli-w1apjecb.js → cli-711vwbxn.js} +2 -2
  30. package/dist/{cli-r4fqfpwf.js → cli-78vv7446.js} +50 -27
  31. package/dist/{cli-srqq3gc5.js → cli-7n6s5man.js} +5 -5
  32. package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
  33. package/dist/{cli-2bw3w47j.js → cli-8wwxw8a3.js} +1 -1
  34. package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
  35. package/dist/{cli-ywm1azg9.js → cli-9jzdj90z.js} +8 -4
  36. package/dist/cli-9traj3dn.js +638 -0
  37. package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
  38. package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
  39. package/dist/cli-cvv9k0hh.js +10143 -0
  40. package/dist/{cli-anzdk0z4.js → cli-d9286m9h.js} +2 -2
  41. package/dist/cli-e3g5mbkz.js +776 -0
  42. package/dist/cli-f527ce74.js +781 -0
  43. package/dist/{cli-gmdajfw5.js → cli-gxzkg1de.js} +5020 -1729
  44. package/dist/{cli-451ks6aw.js → cli-h1arqn31.js} +1 -1
  45. package/dist/cli-hjwmhcg1.js +10622 -0
  46. package/dist/{cli-jpc4r224.js → cli-hqr88ew6.js} +19 -3
  47. package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
  48. package/dist/{cli-cd0hv9nh.js → cli-j67mh2vg.js} +2 -2
  49. package/dist/cli-jta2eyzc.js +619 -0
  50. package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
  51. package/dist/cli-kceah1eh.js +92 -0
  52. package/dist/{cli-d603qf86.js → cli-ksphgh48.js} +10 -8
  53. package/dist/{cli-3nxdmjrc.js → cli-mgz4nbgg.js} +4 -4
  54. package/dist/{cli-saqyage0.js → cli-mz5as5ha.js} +179 -27
  55. package/dist/cli-n2wq4j7m.js +6985 -0
  56. package/dist/{cli-ppy4nnnh.js → cli-n8ndw8j7.js} +2 -2
  57. package/dist/{cli-1w0vj3gw.js → cli-naqzr17j.js} +7 -7
  58. package/dist/{cli-0a7mm3zp.js → cli-nm1p8jfr.js} +25 -21
  59. package/dist/{cli-wrh08zjd.js → cli-p3zbc1rw.js} +5 -18
  60. package/dist/{cli-hsem16hb.js → cli-pe05f8yk.js} +29 -6
  61. package/dist/{cli-5wpw4rab.js → cli-qmzsbkvy.js} +5 -5
  62. package/dist/{cli-bv2etw2y.js → cli-qnm4e9e4.js} +99 -590
  63. package/dist/{cli-1x7da0de.js → cli-qqy4q48b.js} +8 -8
  64. package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
  65. package/dist/{cli-5er5gjbm.js → cli-r35rw5de.js} +15 -15
  66. package/dist/{cli-v3zhnxsb.js → cli-r610p9bs.js} +2 -2
  67. package/dist/{cli-7jykv7ef.js → cli-rc6pf5kv.js} +1 -1
  68. package/dist/{cli-x119kdba.js → cli-rdxm77k3.js} +1 -1
  69. package/dist/cli-rhs9pz33.js +294 -0
  70. package/dist/{cli-0p3enk35.js → cli-s69nfyeh.js} +9 -1
  71. package/dist/{cli-0kxf81jj.js → cli-sawv63e8.js} +2 -2
  72. package/dist/{cli-e3pmyt39.js → cli-sg19gbf0.js} +1 -1
  73. package/dist/{cli-d161g69q.js → cli-shk7r5cs.js} +57 -6
  74. package/dist/{cli-7pz3b7x5.js → cli-sksetb2q.js} +36 -1
  75. package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
  76. package/dist/{cli-db3m6zdt.js → cli-t02z59f2.js} +1 -1
  77. package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
  78. package/dist/{cli-s8z6x4b4.js → cli-v7g551te.js} +225 -113
  79. package/dist/{cli-rfz2ve55.js → cli-vgqzp4em.js} +3341 -955
  80. package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
  81. package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
  82. package/dist/cli-wfnemr1t.js +86 -0
  83. package/dist/cli-wmgrkscj.js +23254 -0
  84. package/dist/{cli-qm1448f9.js → cli-wms6x9db.js} +8 -8
  85. package/dist/{cli-tadfgd0t.js → cli-x1r545x8.js} +33 -4
  86. package/dist/{cli-xc7p7s3g.js → cli-xczsgshn.js} +6 -6
  87. package/dist/{cli-fmhj1ehj.js → cli-y3167wt1.js} +882 -271
  88. package/dist/{cli-r0byd61h.js → cli-yjmqpxt3.js} +17 -16
  89. package/dist/{cli-81r1wjyv.js → cli-z780ec7c.js} +1 -1
  90. package/dist/{cli-phcqp1b9.js → cli-zm9t2vde.js} +2 -2
  91. package/dist/cli.js +34 -49
  92. package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-4z16v9n0.js} +15 -14
  93. package/dist/{codex-login-841kv5fk.js → codex-login-pkepy2j1.js} +3 -2
  94. package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-rvms9y2x.js} +15 -14
  95. package/dist/{commands-z8fq9qna.js → commands-2a9rtyat.js} +11 -10
  96. package/dist/{controller-hq5ggpcp.js → controller-3k3madbn.js} +5 -4
  97. package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-v9yn8zb9.js} +42 -37
  98. package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-98gbhyzn.js} +7 -6
  99. package/dist/{db-qfpq4bt7.js → db-eywwsnjw.js} +30 -9
  100. package/dist/{db-yyhqqrbf.js → db-ncypk9np.js} +12 -11
  101. package/dist/{devin-adapter-xgtj680j.js → devin-adapter-zeq8b9gz.js} +3 -2
  102. package/dist/{dispatcher-x0x7qfcq.js → dispatcher-w94kc575.js} +38 -33
  103. package/dist/{docker-f503k9p0.js → docker-b1e4cqab.js} +3 -2
  104. package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-47ztej36.js} +7 -6
  105. package/dist/{e2b-66xra4az.js → e2b-bbt8ey45.js} +4 -3
  106. package/dist/{e2b-xwhyj8cw.js → e2b-dp804sen.js} +4 -3
  107. package/dist/{event-bus-vjtv82gm.js → event-bus-j2jdg3qb.js} +3 -2
  108. package/dist/{external-channel-h1fjecwe.js → external-channel-zrkg8ar9.js} +11 -10
  109. package/dist/{google-generative-ai-szdxbpqg.js → google-generative-ai-g8db7x0f.js} +4 -2
  110. package/dist/{google-vertex-qzw3p36d.js → google-vertex-r2692q0r.js} +4 -2
  111. package/dist/{grok-adapter-e7mr287e.js → grok-adapter-s9ncp9vy.js} +18 -17
  112. package/dist/{handlers-znb9n7d4.js → handlers-kqftvjgw.js} +41 -36
  113. package/dist/{heartbeat-bm4qkn8d.js → heartbeat-9q96p8v9.js} +43 -38
  114. package/dist/{hook-254r4mza.js → hook-56qe10dp.js} +11 -23
  115. package/dist/{hook-xaa3q80s.js → hook-yy6rw42k.js} +12 -11
  116. package/dist/{http-3dgrgp8y.js → http-r2dnb8f8.js} +2411 -275
  117. package/dist/{index-fx3jqq1e.js → index-3gtmkhc6.js} +38 -33
  118. package/dist/{index-bdsqa799.js → index-3k5hkz7r.js} +43 -38
  119. package/dist/index-52j1aja4.js +3465 -0
  120. package/dist/{index-g2byveez.js → index-5e101240.js} +38 -33
  121. package/dist/{index-2ybk7khy.js → index-5wyfjc2c.js} +845 -683
  122. package/dist/index-9gw58n4k.js +193 -0
  123. package/dist/index-9j87mcm8.js +56305 -0
  124. package/dist/index-bsmcresk.js +79424 -0
  125. package/dist/index-mh85qhec.js +475 -0
  126. package/dist/{index-jd7sejm2.js → index-vxvhxxbn.js} +10 -9
  127. package/dist/index-we27kd31.js +12810 -0
  128. package/dist/{keepalive-6ywhpja1.js → keepalive-psj6j54c.js} +12 -11
  129. package/dist/{lead-cw45n21s.js → lead-hajz4688.js} +61 -56
  130. package/dist/{maintenance-ss1a1ge9.js → maintenance-ps02sb5m.js} +10 -9
  131. package/dist/{node-fkajaq96.js → node-mwb5r697.js} +2 -1
  132. package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-0284h93b.js} +11 -10
  133. package/dist/{onboard-8hzdhc1k.js → onboard-rbf6bg01.js} +11 -3
  134. package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-13dcatgq.js} +18 -13
  135. package/dist/{otel-impl-e6mnvc4v.js → otel-impl-zvqcbhp7.js} +242 -868
  136. package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-xxy47q4v.js} +244 -106
  137. package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-kefx9v3t.js} +12 -11
  138. package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-3m36rxm2.js} +11 -10
  139. package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-z76xv0hq.js} +12 -11
  140. package/dist/{render-v2-907cy6sa.js → render-v2-wz73bs25.js} +18 -14
  141. package/dist/{resume-42stcaz0.js → resume-k4wzge8w.js} +25 -21
  142. package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
  143. package/dist/{setup-adbc1c10.js → setup-2fp2pypp.js} +2 -2
  144. package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
  145. package/dist/{work-objects-wpj8ck95.js → work-objects-6k0ywz3m.js} +41 -36
  146. package/dist/{worker-bzdra9rf.js → worker-5v3rxsdh.js} +61 -56
  147. package/dist/{x-qfmygqqv.js → x-4mtdeym1.js} +3 -2
  148. package/openapi.json +1279 -329
  149. package/package.json +15 -15
  150. package/src/agentmail/handlers.ts +21 -11
  151. package/src/apps/definition.ts +16 -0
  152. package/src/azure-devops/api.ts +52 -2
  153. package/src/azure-devops/boards-sync.ts +50 -20
  154. package/src/azure-devops/index.ts +1 -0
  155. package/src/azure-devops/outbound.ts +95 -0
  156. package/src/be/boot-seeds.ts +11 -0
  157. package/src/be/config-refs.ts +60 -0
  158. package/src/be/db/model-profiles.ts +315 -0
  159. package/src/be/db/page-versions.ts +15 -0
  160. package/src/be/db/runtime.ts +35 -8
  161. package/src/be/db/skill-name-resolution.ts +36 -0
  162. package/src/be/db/tasks/read.ts +237 -0
  163. package/src/be/db/tasks/write.ts +7 -0
  164. package/src/be/db.ts +87 -36
  165. package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
  166. package/src/be/migrations/216_task_resolved_effort.sql +5 -0
  167. package/src/be/migrations/217_chat_sdk_state.sql +104 -0
  168. package/src/be/migrations/219_relabel_pi_context_compactions.sql +22 -0
  169. package/src/be/migrations/220_model_profiles.sql +137 -0
  170. package/src/be/model-catalog-store.ts +5 -1
  171. package/src/be/model-tier-resolution.ts +155 -10
  172. package/src/be/model-validation.ts +12 -2
  173. package/src/be/models-catalog.ts +26 -1
  174. package/src/be/modelsdev-cache.json +198 -63
  175. package/src/be/modelsdev-cache.ts +9 -1
  176. package/src/be/script-credential-broker.ts +39 -2
  177. package/src/be/scripts/run-saved.ts +1 -0
  178. package/src/be/scripts/typecheck.ts +22 -8
  179. package/src/be/secret-registry.ts +6 -2
  180. package/src/be/seed/runner.ts +13 -1
  181. package/src/be/seed/state-db.ts +5 -0
  182. package/src/be/seed/types.ts +6 -0
  183. package/src/be/seed-model-profiles.ts +41 -0
  184. package/src/be/seed-pricing.ts +19 -2
  185. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +368 -0
  186. package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
  187. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
  188. package/src/be/seed-scripts/index.ts +9 -0
  189. package/src/be/seed-skills/bundled-files.generated.json +0 -18
  190. package/src/be/seed-skills/index.ts +104 -3
  191. package/src/be/swarm-config-guard.ts +53 -0
  192. package/src/cli.tsx +0 -16
  193. package/src/commands/onboard/non-interactive.ts +4 -2
  194. package/src/commands/provider-credentials.ts +52 -6
  195. package/src/commands/runner.ts +193 -71
  196. package/src/e2b/env.ts +5 -0
  197. package/src/extensions/catalog.generated.json +17 -0
  198. package/src/extensions/contract-types.generated.ts +1 -1
  199. package/src/extensions/contract.ts +45 -0
  200. package/src/extensions/dispatcher.ts +7 -0
  201. package/src/extensions/loader.ts +10 -5
  202. package/src/extensions/post-bridge.ts +40 -0
  203. package/src/github/handlers.ts +11 -4
  204. package/src/heartbeat/heartbeat.ts +2 -1
  205. package/src/heartbeat/templates.ts +8 -5
  206. package/src/hooks/hook.ts +0 -26
  207. package/src/http/agents.ts +49 -2
  208. package/src/http/all-routes.ts +1 -1
  209. package/src/http/apps.ts +30 -3
  210. package/src/http/config.ts +62 -19
  211. package/src/http/core.ts +8 -0
  212. package/src/http/index.ts +25 -3
  213. package/src/http/integrations.ts +88 -1
  214. package/src/http/mcp.ts +15 -5
  215. package/src/http/model-profiles.ts +303 -0
  216. package/src/http/page-proxy.ts +2 -4
  217. package/src/http/pages-public.ts +13 -7
  218. package/src/http/pages.ts +3 -13
  219. package/src/http/poll.ts +42 -71
  220. package/src/http/requested-by.ts +54 -0
  221. package/src/http/script-runs.ts +1 -1
  222. package/src/http/scripts.ts +26 -2
  223. package/src/http/stats.ts +1 -30
  224. package/src/http/tasks.ts +79 -5
  225. package/src/http/utils.ts +14 -0
  226. package/src/http/webhooks.ts +160 -3
  227. package/src/http/x.ts +1 -0
  228. package/src/integrations/chat-sdk/adapters.ts +129 -0
  229. package/src/integrations/chat-sdk/attachments.ts +232 -0
  230. package/src/integrations/chat-sdk/background.ts +36 -0
  231. package/src/integrations/chat-sdk/commands.ts +194 -0
  232. package/src/integrations/chat-sdk/config.ts +198 -0
  233. package/src/integrations/chat-sdk/discord-api.ts +63 -0
  234. package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
  235. package/src/integrations/chat-sdk/handlers.ts +28 -0
  236. package/src/integrations/chat-sdk/inbound.ts +426 -0
  237. package/src/integrations/chat-sdk/limits.ts +48 -0
  238. package/src/integrations/chat-sdk/logger.ts +81 -0
  239. package/src/integrations/chat-sdk/outbound.ts +123 -0
  240. package/src/integrations/chat-sdk/relay.ts +172 -0
  241. package/src/integrations/chat-sdk/router.ts +169 -0
  242. package/src/integrations/chat-sdk/runtime.ts +351 -0
  243. package/src/integrations/chat-sdk/schema.ts +245 -0
  244. package/src/integrations/chat-sdk/state.ts +243 -0
  245. package/src/integrations/chat-sdk/status.ts +244 -0
  246. package/src/integrations/chat-sdk/steering.ts +58 -0
  247. package/src/integrations/chat-sdk/teams-origin.ts +77 -0
  248. package/src/integrations/chat-sdk/telegram-api.ts +56 -0
  249. package/src/integrations/chat-sdk/templates.ts +16 -0
  250. package/src/integrations/chat-sdk/test-hooks.ts +37 -0
  251. package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
  252. package/src/integrations/chat-sdk/typing.ts +65 -0
  253. package/src/{artifact-sdk → pages}/feedback-overlay.ts +65 -6
  254. package/src/pages/version.ts +4 -5
  255. package/src/prompts/base-prompt.ts +111 -45
  256. package/src/providers/acp-target-catalog.ts +6 -0
  257. package/src/providers/acp-targets.ts +56 -3
  258. package/src/providers/amp-adapter.ts +1 -1
  259. package/src/providers/claude-adapter.ts +1 -1
  260. package/src/providers/claude-flag-settings.ts +17 -5
  261. package/src/providers/claude-managed-adapter.ts +1 -1
  262. package/src/providers/claude-session-events.ts +6 -1
  263. package/src/providers/dsh-adapter.ts +1 -1
  264. package/src/providers/opencode-adapter.ts +243 -26
  265. package/src/providers/opencode-swarm-plugin.ts +31 -0
  266. package/src/providers/pi-mono-adapter.ts +398 -153
  267. package/src/providers/pi-mono-extension.ts +17 -3
  268. package/src/providers/pricing-sources.md +33 -2
  269. package/src/providers/reasoning-effort.ts +37 -0
  270. package/src/providers/types.ts +6 -2
  271. package/src/rbac/legacy-policy.ts +16 -2
  272. package/src/rbac/permissions.ts +26 -0
  273. package/src/scheduler/deferred-task-waits.ts +18 -5
  274. package/src/scheduler/scheduler.ts +11 -3
  275. package/src/scripts-runtime/executors/quickjs-prelude.ts +75 -6
  276. package/src/scripts-runtime/executors/quickjs-runner.ts +85 -8
  277. package/src/scripts-runtime/executors/quickjs-web-shims.ts +1041 -0
  278. package/src/scripts-runtime/extract-args-schema.ts +9 -8
  279. package/src/scripts-runtime/loader.ts +19 -7
  280. package/src/scripts-runtime/quickjs-compat.ts +464 -0
  281. package/src/scripts-runtime/sdk-allowlist.ts +12 -6
  282. package/src/scripts-runtime/swarm-sdk.ts +0 -11
  283. package/src/scripts-runtime/types/stdlib.d.ts +39 -15
  284. package/src/scripts-runtime/types/swarm-extension.d.ts +66 -1
  285. package/src/scripts-runtime/types/swarm-sdk.d.ts +39 -15
  286. package/src/server.ts +62 -19
  287. package/src/slack/blocks.ts +4 -2
  288. package/src/slack/event-dedup.ts +1 -1
  289. package/src/slack/reaction-shortcode.ts +14 -0
  290. package/src/slack/render-v2.ts +12 -7
  291. package/src/slack/responses.ts +5 -4
  292. package/src/slack/thread-buffer.ts +41 -22
  293. package/src/tasks/additive-buffer.ts +4 -2
  294. package/src/tasks/context-key.ts +60 -1
  295. package/src/tasks/model-pin.ts +67 -0
  296. package/src/tasks/worker-follow-up.ts +15 -33
  297. package/src/tests/acp-adapter.test.ts +42 -0
  298. package/src/tests/agentmail-filters.test.ts +47 -0
  299. package/src/tests/api-drain-worker-e2e.test.ts +1 -6
  300. package/src/tests/apps-spike2.test.ts +35 -0
  301. package/src/tests/azure-devops-outbound.test.ts +420 -0
  302. package/src/tests/base-prompt.test.ts +58 -54
  303. package/src/tests/chat-sdk-commands.test.ts +191 -0
  304. package/src/tests/chat-sdk-config.test.ts +334 -0
  305. package/src/tests/chat-sdk-discord-api.test.ts +68 -0
  306. package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
  307. package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
  308. package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
  309. package/src/tests/chat-sdk-harness.ts +146 -0
  310. package/src/tests/chat-sdk-inbound.test.ts +363 -0
  311. package/src/tests/chat-sdk-relay.test.ts +470 -0
  312. package/src/tests/chat-sdk-reload.test.ts +128 -0
  313. package/src/tests/chat-sdk-shutdown.test.ts +220 -0
  314. package/src/tests/chat-sdk-slack.test.ts +268 -0
  315. package/src/tests/chat-sdk-state.test.ts +163 -0
  316. package/src/tests/chat-sdk-status-route.test.ts +382 -0
  317. package/src/tests/chat-sdk-teams.test.ts +277 -0
  318. package/src/tests/chat-sdk-tools.test.ts +520 -0
  319. package/src/tests/chat-sdk-typing.test.ts +120 -0
  320. package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
  321. package/src/tests/claude-adapter-binary.test.ts +9 -4
  322. package/src/tests/claude-flag-settings.test.ts +11 -3
  323. package/src/tests/claude-managed-adapter.test.ts +1 -1
  324. package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
  325. package/src/tests/claude-thinking-tokens.test.ts +57 -0
  326. package/src/tests/claude-worker-parity.test.ts +2 -7
  327. package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
  328. package/src/tests/config-refs.test.ts +66 -0
  329. package/src/tests/context-key.test.ts +19 -0
  330. package/src/tests/cors-allowlist.test.ts +25 -0
  331. package/src/tests/create-page-tool.test.ts +18 -0
  332. package/src/tests/credential-check.test.ts +139 -0
  333. package/src/tests/credentials.test.ts +21 -0
  334. package/src/tests/db-runtime.test.ts +61 -0
  335. package/src/tests/db-task-read-contract.test.ts +22 -0
  336. package/src/tests/db-task-write-contract.test.ts +11 -0
  337. package/src/tests/deferred-task-wake.test.ts +78 -1
  338. package/src/tests/docs-index-footprint.test.js +3 -3
  339. package/src/tests/dsh-adapter.test.ts +1 -1
  340. package/src/tests/enabled-capabilities.test.ts +20 -0
  341. package/src/tests/entrypoint-api-readiness.test.ts +14 -8
  342. package/src/tests/entrypoint-config-env-export.test.ts +5 -2
  343. package/src/tests/entrypoint-export-to-env.test.ts +78 -0
  344. package/src/tests/env-flag.test.ts +1 -0
  345. package/src/tests/explicit-model-validation.test.ts +105 -1
  346. package/src/tests/extensions-catalog.test.ts +1 -0
  347. package/src/tests/extensions-example-comms-adherence-gate.test.ts +413 -0
  348. package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
  349. package/src/tests/extensions-loader.test.ts +15 -0
  350. package/src/tests/extensions-post-bridge.test.ts +51 -0
  351. package/src/tests/fetch-resolved-env.test.ts +128 -0
  352. package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
  353. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
  354. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
  355. package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
  356. package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
  357. package/src/tests/github-handlers.test.ts +35 -0
  358. package/src/tests/harness-provider-resolution.test.ts +12 -0
  359. package/src/tests/heartbeat-checklist.test.ts +3 -2
  360. package/src/tests/heartbeat-jev-gate-credentials.test.ts +168 -0
  361. package/src/tests/heartbeat-jev-gate.test.ts +385 -0
  362. package/src/tests/hook-runtime-close.test.ts +0 -2
  363. package/src/tests/http-api-integration.test.ts +0 -25
  364. package/src/tests/migration-046-budgets.test.ts +17 -16
  365. package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
  366. package/src/tests/model-profile-backcompat.test.ts +327 -0
  367. package/src/tests/model-profile-providers.test.ts +302 -0
  368. package/src/tests/model-profile-runtime-secrets.test.ts +223 -0
  369. package/src/tests/model-profiles-api.test.ts +614 -0
  370. package/src/tests/model-tier-resolution.test.ts +93 -0
  371. package/src/tests/models-catalog.test.ts +42 -1
  372. package/src/tests/openai-compatible-providers.test.ts +134 -0
  373. package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
  374. package/src/tests/opencode-adapter.test.ts +216 -2
  375. package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
  376. package/src/tests/opencode-shell-env.test.ts +145 -0
  377. package/src/tests/openrouter-base-url.test.ts +101 -151
  378. package/src/tests/page-proxy.test.ts +1 -1
  379. package/src/tests/pages-browser-sdk.test.ts +76 -0
  380. package/src/tests/pages-feedback-keys.test.ts +121 -0
  381. package/src/tests/pages-feedback.test.ts +4 -1
  382. package/src/tests/paused-tasks-requested-by.test.ts +102 -0
  383. package/src/tests/pi-context-compaction.test.ts +193 -0
  384. package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
  385. package/src/tests/pi-mono-adapter.test.ts +385 -5
  386. package/src/tests/pi-shell-env.test.ts +170 -0
  387. package/src/tests/profile-claim.test.ts +269 -0
  388. package/src/tests/prompt-template-remaining.test.ts +35 -0
  389. package/src/tests/quickjs-compat.test.ts +213 -0
  390. package/src/tests/rbac-engine.test.ts +32 -3
  391. package/src/tests/runner-exit-after-tasks.test.ts +0 -4
  392. package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
  393. package/src/tests/script-connections.test.ts +6 -0
  394. package/src/tests/script-executor-conformance.test.ts +252 -1
  395. package/src/tests/script-executor-quickjs.test.ts +96 -0
  396. package/src/tests/script-runs-http.test.ts +89 -0
  397. package/src/tests/scripts-http.test.ts +217 -1
  398. package/src/tests/scripts-only-gating.test.ts +2 -3
  399. package/src/tests/scripts-runtime.test.ts +58 -40
  400. package/src/tests/secret-scrubber.test.ts +96 -0
  401. package/src/tests/seed-model-profiles.test.ts +174 -0
  402. package/src/tests/seed-scripts.test.ts +2 -2
  403. package/src/tests/seed-skills-bundled-files.test.ts +45 -53
  404. package/src/tests/seed-skills-retire.test.ts +182 -0
  405. package/src/tests/send-task-requester-gate.test.ts +58 -0
  406. package/src/tests/session-cost-recompute-unit.test.ts +46 -0
  407. package/src/tests/skill-get-name-resolution.test.ts +137 -0
  408. package/src/tests/skill-invocations.test.ts +4 -2
  409. package/src/tests/slack-blocks.test.ts +36 -0
  410. package/src/tests/slack-inline-output.test.ts +14 -0
  411. package/src/tests/slack-reaction-config.test.ts +20 -0
  412. package/src/tests/slack-render-v2.test.ts +37 -0
  413. package/src/tests/slack-thread-buffer.test.ts +98 -1
  414. package/src/tests/sonnet-5-5-registry.test.ts +9 -1
  415. package/src/tests/swarm-config-export-to-env.test.ts +267 -0
  416. package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
  417. package/src/tests/swarm-diff.test.ts +1 -1
  418. package/src/tests/task-model-effort-rerun.test.ts +164 -0
  419. package/src/tests/task-session-prompts.test.ts +132 -0
  420. package/src/tests/task-tool-manifest.test.ts +14 -0
  421. package/src/tests/task-tools-ctx.test.ts +2 -0
  422. package/src/tests/tool-annotations.test.ts +6 -6
  423. package/src/tests/ui-logs-parser.test.ts +43 -0
  424. package/src/tests/used-by-route.test.ts +6 -0
  425. package/src/tests/vercel-ai-gateway.test.ts +149 -0
  426. package/src/tests/workflow-llm.test.ts +61 -0
  427. package/src/tests/workflow-swarm-script.test.ts +38 -0
  428. package/src/tests/workflow-wait-filter.test.ts +5 -3
  429. package/src/tools/chat-access.ts +41 -0
  430. package/src/tools/chat-open-dm.ts +59 -0
  431. package/src/tools/chat-post.ts +74 -0
  432. package/src/tools/chat-read-thread.ts +100 -0
  433. package/src/tools/chat-reply.ts +75 -0
  434. package/src/tools/create-page.ts +3 -13
  435. package/src/tools/model-catalog/index.ts +2 -1
  436. package/src/tools/model-profiles/list-model-profiles.ts +54 -0
  437. package/src/tools/register-chat-channel.ts +139 -0
  438. package/src/tools/request-human-input.ts +11 -3
  439. package/src/tools/script-apis.ts +5 -1
  440. package/src/tools/script-upsert.ts +4 -1
  441. package/src/tools/send-task.ts +48 -1
  442. package/src/tools/skills/skill-get.ts +17 -9
  443. package/src/tools/swarm-config/get-config.ts +2 -1
  444. package/src/tools/swarm-config/list-config.ts +2 -1
  445. package/src/tools/swarm-config/set-config.ts +16 -3
  446. package/src/tools/system-one-decide.ts +104 -0
  447. package/src/tools/task-action.ts +22 -1
  448. package/src/tools/tool-config.ts +14 -6
  449. package/src/types.ts +48 -3
  450. package/src/utils/config-env-export.ts +74 -0
  451. package/src/utils/credentials.test.ts +92 -0
  452. package/src/utils/credentials.ts +52 -4
  453. package/src/utils/harness-provider.ts +15 -6
  454. package/src/utils/runtime-model-catalog.ts +11 -1
  455. package/src/utils/secret-scrubber.ts +86 -10
  456. package/src/utils/task-tool-manifest.ts +19 -2
  457. package/src/utils/vcs-repo-match.ts +29 -0
  458. package/src/workflows/executors/raw-llm.ts +8 -3
  459. package/src/workflows/executors/swarm-script.ts +1 -0
  460. package/src/workflows/executors/system-one-decision.ts +21 -11
  461. package/src/workflows/executors/workflow-llm.ts +22 -0
  462. package/src/workflows/index.ts +21 -12
  463. package/templates/extensions/README.md +1 -0
  464. package/templates/extensions/comms-adherence-gate/README.md +88 -0
  465. package/templates/extensions/comms-adherence-gate/hooks.ts +489 -0
  466. package/templates/extensions/comms-adherence-gate/manifest.json +8 -0
  467. package/templates/skills/agent-browser/SKILL.md +1 -1
  468. package/templates/skills/agent-browser/content.md +1 -1
  469. package/templates/skills/apps/SKILL.md +8 -1
  470. package/templates/skills/apps/content.md +8 -1
  471. package/templates/skills/chat-sdk/config.json +14 -0
  472. package/templates/skills/chat-sdk/content.md +84 -0
  473. package/templates/skills/composio-gmail/content.md +7 -0
  474. package/templates/skills/composio-google-docs/content.md +1 -1
  475. package/templates/skills/email-domain-health/config.json +14 -0
  476. package/templates/skills/email-domain-health/content.md +131 -0
  477. package/templates/skills/kv-storage/content.md +2 -2
  478. package/templates/skills/pages/content.md +8 -10
  479. package/templates/skills/swarm-extensions/content.md +2 -0
  480. package/templates/skills/swarm-scripts/SKILL.md +4 -2
  481. package/templates/skills/swarm-scripts/config.json +1 -1
  482. package/templates/skills/swarm-scripts/content.md +4 -2
  483. package/templates/skills/workflow-iterate/content.md +38 -0
  484. package/dist/artifact-eczsknc3.js +0 -3843
  485. package/dist/cli-42qhyvwx.js +0 -33
  486. package/dist/cli-bd957dgb.js +0 -153
  487. package/dist/cli-q51yprfq.js +0 -1104
  488. package/dist/cli-t1ze64h3.js +0 -811
  489. package/dist/cli-tcc4wd5d.js +0 -56471
  490. package/dist/index-9ch1n761.js +0 -1102
  491. package/src/artifact-sdk/index.ts +0 -2
  492. package/src/artifact-sdk/localtunnel.d.ts +0 -20
  493. package/src/artifact-sdk/port.ts +0 -12
  494. package/src/artifact-sdk/server.ts +0 -183
  495. package/src/artifact-sdk/tunnel.ts +0 -19
  496. package/src/commands/artifact.ts +0 -249
  497. package/src/http/ecosystem.ts +0 -77
  498. package/src/tests/artifact-commands.test.ts +0 -92
  499. package/src/tests/artifact-sdk.test.ts +0 -793
  500. package/src/tests/register-service-security.test.ts +0 -194
  501. package/src/tools/list-services.ts +0 -107
  502. package/src/tools/register-service.ts +0 -177
  503. package/src/tools/unregister-service.ts +0 -73
  504. package/src/tools/update-service-status.ts +0 -96
  505. package/templates/skills/artifacts/config.json +0 -14
  506. package/templates/skills/artifacts/content.md +0 -344
  507. package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
  508. package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
  509. package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
  510. package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
  511. /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
@@ -20,6 +20,7 @@ import {
20
20
  RoutingAffinitySchema,
21
21
  } from "../../../types";
22
22
  import { parseProviderMeta } from "../../../utils/provider-metadata";
23
+ import { scrubSecrets } from "../../../utils/secret-scrubber";
23
24
  import { getAgentById } from "../agents";
24
25
  import { getDbClient } from "../runtime";
25
26
 
@@ -87,9 +88,12 @@ export type AgentTaskRow = {
87
88
  model: string | null;
88
89
  modelTier: string | null;
89
90
  effort: string | null;
91
+ resolvedEffort?: string | null;
90
92
  resolvedModel?: string | null;
91
93
  modelSource?: string | null;
92
94
  modelAlias?: string | null;
95
+ profile?: string | null;
96
+ resolvedProfile?: string | null;
93
97
  scheduleId: string | null;
94
98
  workflowRunId: string | null;
95
99
  workflowRunStepId: string | null;
@@ -154,6 +158,7 @@ type AgentTaskSummaryRow = Pick<
154
158
  | "modelSource"
155
159
  | "modelAlias"
156
160
  | "effort"
161
+ | "resolvedEffort"
157
162
  | "provider"
158
163
  | "requestedByUserId"
159
164
  | "progress"
@@ -207,6 +212,7 @@ const LIST_COLUMNS = {
207
212
  agent_tasks.offeredTo, agent_tasks.acceptedAt, agent_tasks.parentTaskId,
208
213
  agent_tasks.scheduleId, agent_tasks.model, agent_tasks.modelTier,
209
214
  agent_tasks.resolvedModel, agent_tasks.modelSource, agent_tasks.modelAlias, agent_tasks.effort,
215
+ agent_tasks.resolvedEffort,
210
216
  agent_tasks.provider, agent_tasks.requestedByUserId, agent_tasks.progress,
211
217
  agent_tasks.createdAt, agent_tasks.lastUpdatedAt, agent_tasks.finishedAt,
212
218
  agent_tasks.peakContextPercent`,
@@ -315,6 +321,11 @@ export function rowToAgentTask(row: AgentTaskRow): AgentTask {
315
321
  effort: ReasoningEffortSchema.safeParse(row.effort).success
316
322
  ? (row.effort as ReasoningEffort)
317
323
  : undefined,
324
+ resolvedEffort: ReasoningEffortSchema.safeParse(row.resolvedEffort).success
325
+ ? (row.resolvedEffort as ReasoningEffort)
326
+ : undefined,
327
+ profile: row.profile ?? undefined,
328
+ resolvedProfile: row.resolvedProfile ?? undefined,
318
329
  scheduleId: row.scheduleId ?? undefined,
319
330
  workflowRunId: row.workflowRunId ?? undefined,
320
331
  workflowRunStepId: row.workflowRunStepId ?? undefined,
@@ -381,6 +392,9 @@ export function rowToAgentTaskSummary(row: AgentTaskSummaryRow): AgentTaskSummar
381
392
  effort: ReasoningEffortSchema.safeParse(row.effort).success
382
393
  ? (row.effort as ReasoningEffort)
383
394
  : undefined,
395
+ resolvedEffort: ReasoningEffortSchema.safeParse(row.resolvedEffort).success
396
+ ? (row.resolvedEffort as ReasoningEffort)
397
+ : undefined,
384
398
  provider: (row.provider as ProviderName | null) ?? undefined,
385
399
  requestedByUserId: row.requestedByUserId ?? undefined,
386
400
  progress: row.progress ?? undefined,
@@ -446,6 +460,9 @@ export async function hasNonTerminalResumeChild(parentId: string): Promise<boole
446
460
  return row !== undefined && row !== null;
447
461
  }
448
462
 
463
+ /** How far back the heartbeat repairs a superseded task that never got a resume. */
464
+ export const SUPERSEDED_RESUME_REPAIR_WINDOW_MS = 24 * 60 * 60 * 1000;
465
+
449
466
  /**
450
467
  * Superseded tasks that never got a resume child. Both supersede paths
451
468
  * (heartbeat remediation and `POST /api/tasks/:id/supersede`) supersede
@@ -1035,6 +1052,163 @@ export async function markFinalizedSlackRelaysDelivered(): Promise<number> {
1035
1052
  return result.changes;
1036
1053
  }
1037
1054
 
1055
+ /** Pending Chat SDK relay row: the terminal task plus its obligation bookkeeping. */
1056
+ export interface PendingChatRelay {
1057
+ task: AgentTask;
1058
+ createdAt: string;
1059
+ lastError: string | null;
1060
+ }
1061
+
1062
+ /**
1063
+ * Backoff gate for a chat relay obligation: eligible when never attempted, or
1064
+ * when `min(3 s * 2^attempt_count, 10 min)` passed since `last_attempt_at`.
1065
+ * `attempt_count >= 8` is already past the cap (3 s * 2^8 = 768 s). The one
1066
+ * parameter is the reference time as ISO text.
1067
+ */
1068
+ const CHAT_RELAY_ELIGIBLE_SQL = `(obligation.last_attempt_at IS NULL
1069
+ OR (julianday(?) - julianday(obligation.last_attempt_at)) * 86400000.0 >=
1070
+ CASE WHEN obligation.attempt_count >= 8 THEN 600000
1071
+ ELSE 3000 * (1 << obligation.attempt_count) END)`;
1072
+
1073
+ /**
1074
+ * Terminal chat tasks whose relay obligation is pending, out of backoff at
1075
+ * `now`, and whose `task:chat-sdk:<adapter>:` contextKey names one of
1076
+ * `adapters` (the adapters that are running). Rows of other adapters are left
1077
+ * out of the query, so a stopped adapter cannot fill the window and starve the
1078
+ * healthy ones. Returns no rows when `adapters` is empty. Never-attempted rows
1079
+ * sort first, then the oldest attempts. A contextKey that does not parse as a
1080
+ * chat key is not selected here; `giveUpStaleChatRelays` retires such rows once
1081
+ * they age out.
1082
+ */
1083
+ export async function getPendingChatRelayTasks(
1084
+ now: number = Date.now(),
1085
+ limit = 200,
1086
+ adapters: readonly string[] = [],
1087
+ ): Promise<PendingChatRelay[]> {
1088
+ if (adapters.length === 0) return [];
1089
+ for (const adapter of adapters) {
1090
+ if (!/^[a-z]+$/.test(adapter)) throw new Error(`invalid chat adapter name: ${adapter}`);
1091
+ }
1092
+ const adapterFilter = adapters.map(() => "task.contextKey GLOB ?").join(" OR ");
1093
+ const rows = await getDbClient().query<
1094
+ AgentTaskRow & {
1095
+ relay_created_at: string;
1096
+ relay_last_error: string | null;
1097
+ }
1098
+ >(
1099
+ `SELECT task.*,
1100
+ obligation.created_at AS relay_created_at,
1101
+ obligation.last_error AS relay_last_error
1102
+ FROM chat_relay_obligations obligation
1103
+ JOIN agent_tasks task ON task.id = obligation.task_id
1104
+ WHERE obligation.delivered_at IS NULL
1105
+ AND obligation.given_up_at IS NULL
1106
+ AND task.status IN ('completed', 'failed', 'cancelled')
1107
+ AND (${adapterFilter})
1108
+ AND ${CHAT_RELAY_ELIGIBLE_SQL}
1109
+ ORDER BY obligation.last_attempt_at IS NOT NULL,
1110
+ obligation.last_attempt_at ASC,
1111
+ obligation.created_at ASC
1112
+ LIMIT ?`,
1113
+ [
1114
+ ...adapters.map((adapter) => `task:chat-sdk:${adapter}:*`),
1115
+ new Date(now).toISOString(),
1116
+ limit,
1117
+ ],
1118
+ );
1119
+ return rows.map((row) => ({
1120
+ task: rowToAgentTask(row),
1121
+ createdAt: row.relay_created_at,
1122
+ lastError: row.relay_last_error,
1123
+ }));
1124
+ }
1125
+
1126
+ /**
1127
+ * Give up every pending chat relay obligation created more than `olderThanMs`
1128
+ * before `now`, whatever the adapter state. Returns how many rows were retired.
1129
+ */
1130
+ export async function giveUpStaleChatRelays(now: number, olderThanMs: number): Promise<number> {
1131
+ const at = new Date(now).toISOString();
1132
+ const cutoff = new Date(now - olderThanMs).toISOString();
1133
+ const result = await getDbClient().run(
1134
+ `UPDATE chat_relay_obligations
1135
+ SET given_up_at = ?, last_error = 'gave up: older than 24h', updated_at = ?
1136
+ WHERE delivered_at IS NULL AND given_up_at IS NULL AND created_at < ?`,
1137
+ [at, at, cutoff],
1138
+ );
1139
+ return result.changes;
1140
+ }
1141
+
1142
+ /**
1143
+ * Claim a chat relay row before the send: bump `attempt_count` and set
1144
+ * `last_attempt_at`. Conditional on the row still being pending and out of
1145
+ * backoff, so two concurrent ticks cannot both send. Returns true when claimed.
1146
+ */
1147
+ export async function markChatRelayAttempted(
1148
+ taskId: string,
1149
+ now: number = Date.now(),
1150
+ ): Promise<boolean> {
1151
+ const at = new Date(now).toISOString();
1152
+ const result = await getDbClient().run(
1153
+ `UPDATE chat_relay_obligations AS obligation
1154
+ SET attempt_count = attempt_count + 1,
1155
+ last_attempt_at = ?,
1156
+ updated_at = ?
1157
+ WHERE task_id = ?
1158
+ AND delivered_at IS NULL
1159
+ AND given_up_at IS NULL
1160
+ AND ${CHAT_RELAY_ELIGIBLE_SQL}`,
1161
+ [at, at, taskId, at],
1162
+ );
1163
+ return result.changes > 0;
1164
+ }
1165
+
1166
+ /** Record why the last chat relay attempt failed. The text is scrubbed before it is stored. */
1167
+ export async function recordChatRelayError(
1168
+ taskId: string,
1169
+ error: string,
1170
+ now: number = Date.now(),
1171
+ ): Promise<boolean> {
1172
+ const result = await getDbClient().run(
1173
+ `UPDATE chat_relay_obligations
1174
+ SET last_error = ?, updated_at = ?
1175
+ WHERE task_id = ? AND delivered_at IS NULL`,
1176
+ [scrubSecrets(error), new Date(now).toISOString(), taskId],
1177
+ );
1178
+ return result.changes > 0;
1179
+ }
1180
+
1181
+ /** Mark a chat relay obligation delivered after the platform accepted every chunk. Idempotent. */
1182
+ export async function markChatRelayDelivered(
1183
+ taskId: string,
1184
+ now: number = Date.now(),
1185
+ ): Promise<boolean> {
1186
+ const at = new Date(now).toISOString();
1187
+ const result = await getDbClient().run(
1188
+ `UPDATE chat_relay_obligations
1189
+ SET delivered_at = ?, updated_at = ?
1190
+ WHERE task_id = ? AND delivered_at IS NULL`,
1191
+ [at, at, taskId],
1192
+ );
1193
+ return result.changes > 0;
1194
+ }
1195
+
1196
+ /** Stop retrying a chat relay obligation. The reason is scrubbed before it is stored. */
1197
+ export async function markChatRelayGivenUp(
1198
+ taskId: string,
1199
+ error: string,
1200
+ now: number = Date.now(),
1201
+ ): Promise<boolean> {
1202
+ const at = new Date(now).toISOString();
1203
+ const result = await getDbClient().run(
1204
+ `UPDATE chat_relay_obligations
1205
+ SET given_up_at = ?, last_error = ?, updated_at = ?
1206
+ WHERE task_id = ? AND delivered_at IS NULL AND given_up_at IS NULL`,
1207
+ [at, scrubSecrets(error), at, taskId],
1208
+ );
1209
+ return result.changes > 0;
1210
+ }
1211
+
1038
1212
  /**
1039
1213
  * Get tasks that were recently finished (completed/failed) by workers (non-lead agents).
1040
1214
  * Used by leads to know when workers complete tasks.
@@ -1334,6 +1508,69 @@ export async function getLatestLeadTaskInThread(
1334
1508
  return row ? rowToAgentTask(row) : null;
1335
1509
  }
1336
1510
 
1511
+ /**
1512
+ * ContextKey twins of the Slack thread lookups above, for channels that key a
1513
+ * conversation by `contextKey` only (Chat SDK). `source` narrows to the
1514
+ * channel's ingress tasks, as the Slack twins do with `source = 'slack'`:
1515
+ * follow-ups and delegated worker tasks inherit the parent's contextKey.
1516
+ * All three use `idx_agent_tasks_context_key_status`.
1517
+ */
1518
+ export async function getAgentWorkingOnContextKey(
1519
+ contextKey: string,
1520
+ source?: string,
1521
+ ): Promise<Agent | null> {
1522
+ const taskRow = await getDbClient().get<AgentTaskRow>(
1523
+ `SELECT agentId FROM agent_tasks
1524
+ WHERE contextKey = ?
1525
+ AND (? IS NULL OR source = ?)
1526
+ ORDER BY createdAt DESC, rowid DESC
1527
+ LIMIT 1`,
1528
+ [contextKey, source ?? null, source ?? null],
1529
+ );
1530
+
1531
+ if (taskRow?.agentId) return getAgentById(taskRow.agentId);
1532
+
1533
+ return null;
1534
+ }
1535
+
1536
+ /** Latest `in_progress` or `pending` task on a contextKey (dependency chaining). */
1537
+ export async function getLatestActiveTaskByContextKey(
1538
+ contextKey: string,
1539
+ source?: string,
1540
+ ): Promise<AgentTask | null> {
1541
+ const row = await getDbClient().get<AgentTaskRow>(
1542
+ `SELECT * FROM agent_tasks
1543
+ WHERE contextKey = ?
1544
+ AND (? IS NULL OR source = ?)
1545
+ AND status IN ('in_progress', 'pending')
1546
+ ORDER BY createdAt DESC, rowid DESC
1547
+ LIMIT 1`,
1548
+ [contextKey, source ?? null, source ?? null],
1549
+ );
1550
+
1551
+ return row ? rowToAgentTask(row) : null;
1552
+ }
1553
+
1554
+ /** Latest task assigned to a lead agent on a contextKey (the steering target). */
1555
+ export async function getLatestLeadTaskByContextKey(
1556
+ contextKey: string,
1557
+ source?: string,
1558
+ ): Promise<AgentTask | null> {
1559
+ const row = await getDbClient().get<AgentTaskRow>(
1560
+ `SELECT t.*
1561
+ FROM agent_tasks t
1562
+ JOIN agents a ON a.id = t.agentId
1563
+ WHERE t.contextKey = ?
1564
+ AND (? IS NULL OR t.source = ?)
1565
+ AND a.isLead = 1
1566
+ ORDER BY t.createdAt DESC, t.rowid DESC
1567
+ LIMIT 1`,
1568
+ [contextKey, source ?? null, source ?? null],
1569
+ );
1570
+
1571
+ return row ? rowToAgentTask(row) : null;
1572
+ }
1573
+
1337
1574
  /**
1338
1575
  * Find the most recent task in a Slack thread, regardless of source or status.
1339
1576
  * Unlike getAgentWorkingOnThread (which filters source='slack'), this finds ALL tasks
@@ -8,6 +8,7 @@ import type {
8
8
  AgentTask,
9
9
  AgentTaskSource,
10
10
  ProviderName,
11
+ ReasoningEffort,
11
12
  RuntimePool,
12
13
  TaskAttachment,
13
14
  } from "../../../types";
@@ -312,6 +313,8 @@ export async function updateTaskClaudeSessionId(
312
313
  model?: string,
313
314
  harnessVariant?: string,
314
315
  harnessVariantMeta?: Record<string, unknown>,
316
+ /** Effort the session runs at; null records that the harness default applied. */
317
+ resolvedEffort?: ReasoningEffort | null,
315
318
  ): Promise<AgentTask | null> {
316
319
  const setClauses = ["claudeSessionId = ?", "lastUpdatedAt = ?"];
317
320
  const params: (string | null)[] = [claudeSessionId, new Date().toISOString()];
@@ -336,6 +339,10 @@ export async function updateTaskClaudeSessionId(
336
339
  setClauses.push("harnessVariantMeta = ?");
337
340
  params.push(JSON.stringify(harnessVariantMeta));
338
341
  }
342
+ if (resolvedEffort !== undefined) {
343
+ setClauses.push("resolvedEffort = ?");
344
+ params.push(resolvedEffort);
345
+ }
339
346
 
340
347
  params.push(taskId);
341
348
 
package/src/be/db.ts CHANGED
@@ -136,6 +136,12 @@ import {
136
136
  CODEX_AUTH_WATCH_NAMESPACE,
137
137
  codexAuthBenchMarkerKey,
138
138
  } from "../utils/codex-auth-failure";
139
+ import {
140
+ defaultExportToEnv,
141
+ effectiveExportToEnv,
142
+ envExportRestrictedError,
143
+ isEnvExportRestrictedKey,
144
+ } from "../utils/config-env-export";
139
145
  import { MASKED_SECRET_VALUE } from "../utils/config-secrets";
140
146
  import { deriveProviderFromKeyType } from "../utils/credentials";
141
147
  import type { RateLimitWindowTelemetry } from "../utils/error-tracker";
@@ -187,6 +193,7 @@ import {
187
193
  createContextVersion,
188
194
  getLatestContextVersion,
189
195
  } from "./db/context-versions";
196
+ import { clearAgentModelProfileOnOverrideChange } from "./db/model-profiles";
190
197
  import { getDb, getDbClient } from "./db/runtime";
191
198
  import { classifyTaskHumanFree, reclassifyTaskHumanFree } from "./db/tasks/human-free";
192
199
  import {
@@ -205,7 +212,12 @@ import { scrubJsonValue } from "./scrub-json";
205
212
  import { openSealedJson, sealedJsonForDisplay, sealJson } from "./sealed-json";
206
213
  import { configSecretName, registerStoredSecret } from "./secret-registry";
207
214
  import { promotePendingSteeringForTask } from "./steering";
208
- import { isInternalConfigKey, isReservedConfigKey, reservedKeyError } from "./swarm-config-guard";
215
+ import {
216
+ isInternalConfigKey,
217
+ isReservedConfigKey,
218
+ reservedKeyError,
219
+ teamsSdkEnvKeysSql,
220
+ } from "./swarm-config-guard";
209
221
  import { emitTaskStarted } from "./task-lifecycle-events";
210
222
  import { publishWorkerConfigNudge, publishWorkerNudge } from "./worker-nudges";
211
223
  import { defineWorkflowPayload, type WorkflowPayloadView } from "./workflow-replay";
@@ -292,17 +304,21 @@ export {
292
304
  findTaskByGitHub,
293
305
  findTaskByVcs,
294
306
  getAgentCurrentTask,
307
+ getAgentWorkingOnContextKey,
295
308
  getAgentWorkingOnThread,
296
309
  getAllTasks,
297
310
  getChildTasks,
298
311
  getCompletedSlackTasks,
299
312
  getInProgressSlackTasks,
300
313
  getInProgressTasksByContextKey,
314
+ getLatestActiveTaskByContextKey,
301
315
  getLatestActiveTaskInThread,
316
+ getLatestLeadTaskByContextKey,
302
317
  getLatestLeadTaskInThread,
303
318
  getLatestScriptRunStepTaskByContextKey,
304
319
  getLatestTaskByContextKey,
305
320
  getMostRecentTaskInThread,
321
+ getPendingChatRelayTasks,
306
322
  getPendingSlackRelayTasks,
307
323
  getRecentlyFinishedWorkerTasks,
308
324
  getSlackTasksMissingTree,
@@ -313,14 +329,21 @@ export {
313
329
  getTasksByAgentId,
314
330
  getTasksByStatus,
315
331
  getTasksCount,
332
+ giveUpStaleChatRelays,
316
333
  hasNonTerminalRerouteDecisionChild,
317
334
  hasNonTerminalResumeChild,
318
335
  isLinearTrackerContextKey,
336
+ markChatRelayAttempted,
337
+ markChatRelayDelivered,
338
+ markChatRelayGivenUp,
319
339
  markFinalizedSlackRelaysDelivered,
320
340
  markSlackRelayAttempted,
321
341
  markSlackRelayDelivered,
322
342
  markTasksNotified,
343
+ type PendingChatRelay,
344
+ recordChatRelayError,
323
345
  resetTasksNotified,
346
+ SUPERSEDED_RESUME_REPAIR_WINDOW_MS,
324
347
  type TaskFilters,
325
348
  } from "./db/tasks/read";
326
349
 
@@ -2836,9 +2859,9 @@ export async function createTaskExtended(
2836
2859
  vcsProvider, vcsRepo, vcsEventType, vcsNumber, vcsCommentId, vcsAuthor, vcsUrl,
2837
2860
  vcsInstallationId, vcsNodeId,
2838
2861
  agentmailInboxId, agentmailMessageId, agentmailThreadId,
2839
- mentionMessageId, mentionChannelId, dir, parentTaskId, model, modelTier, effort, scheduleId,
2862
+ mentionMessageId, mentionChannelId, dir, parentTaskId, model, modelTier, effort, profile, scheduleId,
2840
2863
  workflowRunId, workflowRunStepId, outputSchema, followUpConfig, requestedByUserId, requestedByUserIdInherited, contextKey, routingAffinity, swarmVersion, createdAt, lastUpdatedAt, created_by, updated_by, isHumanFree
2841
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
2864
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
2842
2865
  [
2843
2866
  id,
2844
2867
  assetKey,
@@ -2880,6 +2903,7 @@ export async function createTaskExtended(
2880
2903
  options?.model ?? null,
2881
2904
  options?.modelTier ?? null,
2882
2905
  options?.effort ?? null,
2906
+ options?.profile?.trim() || null,
2883
2907
  options?.scheduleId ?? null,
2884
2908
  options?.workflowRunId ?? null,
2885
2909
  options?.workflowRunStepId ?? null,
@@ -4375,7 +4399,8 @@ export async function releaseStaleMentionProcessing(timeoutMinutes: number = 30)
4375
4399
  }
4376
4400
 
4377
4401
  // ============================================================================
4378
- // Service Operations (PM2/background services)
4402
+ // Service Operations (removed PM2 service registry; the table and these
4403
+ // accessors stay until a drop migration lands)
4379
4404
  // ============================================================================
4380
4405
 
4381
4406
  type ServiceRow = {
@@ -6342,6 +6367,7 @@ type SwarmConfigRow = {
6342
6367
  createdAt: string;
6343
6368
  lastUpdatedAt: string;
6344
6369
  encrypted: number; // SQLite boolean: 0 = plaintext, 1 = AES-256-GCM ciphertext
6370
+ exportToEnv?: number; // SQLite boolean; absent only on pre-215 test schemas
6345
6371
  };
6346
6372
 
6347
6373
  type SwarmConfigLookupRow = {
@@ -6370,6 +6396,7 @@ function rowToSwarmConfig(row: SwarmConfigRow): SwarmConfig {
6370
6396
  createdAt: row.createdAt,
6371
6397
  lastUpdatedAt: row.lastUpdatedAt,
6372
6398
  encrypted: isEncrypted,
6399
+ exportToEnv: effectiveExportToEnv(row.key, row.exportToEnv !== 0),
6373
6400
  };
6374
6401
  }
6375
6402
 
@@ -6396,6 +6423,7 @@ function rowToSwarmConfig(row: SwarmConfigRow): SwarmConfig {
6396
6423
  createdAt: row.createdAt,
6397
6424
  lastUpdatedAt: row.lastUpdatedAt,
6398
6425
  encrypted: isEncrypted,
6426
+ exportToEnv: effectiveExportToEnv(row.key, row.exportToEnv !== 0),
6399
6427
  };
6400
6428
  }
6401
6429
 
@@ -6550,7 +6578,7 @@ export async function getInjectableGlobalConfigs(): Promise<SwarmConfig[]> {
6550
6578
  const rows = await getDbClient().query<SwarmConfigRow>(
6551
6579
  `SELECT * FROM swarm_config
6552
6580
  WHERE scope = 'global'
6553
- AND UPPER(key) NOT IN ('API_KEY', 'SECRETS_ENCRYPTION_KEY', 'CORS_ALLOW_ANY_ORIGIN', 'EXTENSION_ALLOW_LEAD_ACTIVATION')
6581
+ AND UPPER(key) NOT IN ('API_KEY', 'SECRETS_ENCRYPTION_KEY', 'CORS_ALLOW_ANY_ORIGIN', 'EXTENSION_ALLOW_LEAD_ACTIVATION', 'CHAT_SDK_API_URL_OVERRIDES', ${teamsSdkEnvKeysSql()})
6554
6582
  ORDER BY key ASC`,
6555
6583
  );
6556
6584
  return rows.filter((row) => !isInternalConfigKey(row.key)).map(rowToSwarmConfig);
@@ -6604,10 +6632,16 @@ export async function upsertSwarmConfig(data: {
6604
6632
  isSecret?: boolean;
6605
6633
  envPath?: string | null;
6606
6634
  description?: string | null;
6635
+ /** Omitted: an update keeps the stored flag; an insert uses `defaultExportToEnv`. */
6636
+ exportToEnv?: boolean;
6607
6637
  }): Promise<SwarmConfig> {
6608
6638
  if (isReservedConfigKey(data.key)) {
6609
6639
  throw reservedKeyError(data.key);
6610
6640
  }
6641
+ if (data.exportToEnv === true && isEnvExportRestrictedKey(data.key)) {
6642
+ throw new Error(envExportRestrictedError(data.key));
6643
+ }
6644
+ const restricted = isEnvExportRestrictedKey(data.key);
6611
6645
 
6612
6646
  const now = new Date().toISOString();
6613
6647
  const scopeId = data.scope === "global" ? null : (data.scopeId ?? null);
@@ -6631,41 +6665,55 @@ export async function upsertSwarmConfig(data: {
6631
6665
  const row = await getDbClient().transaction(async () => {
6632
6666
  const existing =
6633
6667
  scopeId === null
6634
- ? await getDbClient().get<{ id: string }>(
6635
- "SELECT id FROM swarm_config WHERE scope = ? AND scopeId IS NULL AND key = ?",
6668
+ ? await getDbClient().get<SwarmConfigRow>(
6669
+ "SELECT * FROM swarm_config WHERE scope = ? AND scopeId IS NULL AND key = ?",
6636
6670
  [data.scope, data.key],
6637
6671
  )
6638
- : await getDbClient().get<{ id: string }>(
6639
- "SELECT id FROM swarm_config WHERE scope = ? AND scopeId = ? AND key = ?",
6672
+ : await getDbClient().get<SwarmConfigRow>(
6673
+ "SELECT * FROM swarm_config WHERE scope = ? AND scopeId = ? AND key = ?",
6640
6674
  [data.scope, scopeId, data.key],
6641
6675
  );
6642
6676
 
6643
- if (existing) {
6644
- return await getDbClient().get<SwarmConfigRow>(
6645
- `UPDATE swarm_config SET value = ?, isSecret = ?, envPath = ?, description = ?, encrypted = ?, lastUpdatedAt = ?
6646
- WHERE id = ? RETURNING *`,
6647
- [storedValue, isSecret, envPath, description, encryptedFlag, now, existing.id],
6648
- );
6677
+ // COALESCE keeps the stored flag when the caller did not send one.
6678
+ const written = existing
6679
+ ? await getDbClient().get<SwarmConfigRow>(
6680
+ `UPDATE swarm_config SET value = ?, isSecret = ?, envPath = ?, description = ?, encrypted = ?, lastUpdatedAt = ?,
6681
+ exportToEnv = CASE WHEN ? THEN 0 ELSE COALESCE(?, exportToEnv) END
6682
+ WHERE id = ? RETURNING *`,
6683
+ [
6684
+ storedValue,
6685
+ isSecret,
6686
+ envPath,
6687
+ description,
6688
+ encryptedFlag,
6689
+ now,
6690
+ restricted ? 1 : 0,
6691
+ data.exportToEnv === undefined ? null : data.exportToEnv ? 1 : 0,
6692
+ existing.id,
6693
+ ],
6694
+ )
6695
+ : await getDbClient().get<SwarmConfigRow>(
6696
+ `INSERT INTO swarm_config (id, scope, scopeId, key, value, isSecret, envPath, description, createdAt, lastUpdatedAt, encrypted, exportToEnv)
6697
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
6698
+ [
6699
+ crypto.randomUUID(),
6700
+ data.scope,
6701
+ scopeId,
6702
+ data.key,
6703
+ storedValue,
6704
+ isSecret,
6705
+ envPath,
6706
+ description,
6707
+ now,
6708
+ now,
6709
+ encryptedFlag,
6710
+ restricted ? 0 : (data.exportToEnv ?? defaultExportToEnv(data.key)) ? 1 : 0,
6711
+ ],
6712
+ );
6713
+ if (data.scope === "agent" && scopeId) {
6714
+ await clearAgentModelProfileOnOverrideChange(scopeId, data.key, existing, written);
6649
6715
  }
6650
-
6651
- const id = crypto.randomUUID();
6652
- return await getDbClient().get<SwarmConfigRow>(
6653
- `INSERT INTO swarm_config (id, scope, scopeId, key, value, isSecret, envPath, description, createdAt, lastUpdatedAt, encrypted)
6654
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING *`,
6655
- [
6656
- id,
6657
- data.scope,
6658
- scopeId,
6659
- data.key,
6660
- storedValue,
6661
- isSecret,
6662
- envPath,
6663
- description,
6664
- now,
6665
- now,
6666
- encryptedFlag,
6667
- ],
6668
- );
6716
+ return written;
6669
6717
  });
6670
6718
 
6671
6719
  if (!row) throw new Error("Failed to upsert swarm config");
@@ -6714,10 +6762,13 @@ export async function emitBuiltInIntegrationConnectedOnce(
6714
6762
  * predate hardening must remain removable through remediation paths.
6715
6763
  */
6716
6764
  export async function deleteSwarmConfig(id: string): Promise<boolean> {
6717
- const row = await getDbClient().get<Pick<SwarmConfigRow, "scope" | "scopeId">>(
6718
- "DELETE FROM swarm_config WHERE id = ? RETURNING scope, scopeId",
6765
+ const row = await getDbClient().get<SwarmConfigRow>(
6766
+ "DELETE FROM swarm_config WHERE id = ? RETURNING *",
6719
6767
  [id],
6720
6768
  );
6769
+ if (row?.scope === "agent" && row.scopeId) {
6770
+ await clearAgentModelProfileOnOverrideChange(row.scopeId, row.key, row, null);
6771
+ }
6721
6772
  if (row) getDbClient().afterCommit(() => publishWorkerConfigNudge(row.scope, row.scopeId));
6722
6773
  return row !== null;
6723
6774
  }
@@ -0,0 +1,34 @@
1
+ -- Per-row flag: does this swarm_config row reach an agent's process env?
2
+ -- Workers export a row into the harness env (and so into every agent shell)
3
+ -- only when exportToEnv = 1. Rows with 0 stay server-side and are used through
4
+ -- connections or script credential bindings.
5
+ --
6
+ -- Existing rows keep today's behaviour (exported), so nothing breaks at deploy.
7
+ ALTER TABLE swarm_config ADD COLUMN exportToEnv INTEGER NOT NULL DEFAULT 1;
8
+
9
+ -- Deny list: rows only the API server reads. The first block matches
10
+ -- ENV_EXPORT_RESTRICTED_KEYS in src/utils/config-env-export.ts (never
11
+ -- exportable); the second block (ENV_EXPORT_DEFAULT_OFF_KEYS, also the insert
12
+ -- default for new rows) is off by default but operators may turn it
13
+ -- back on per row.
14
+ UPDATE swarm_config SET exportToEnv = 0
15
+ WHERE upper(key) IN (
16
+ 'SLACK_APP_TOKEN',
17
+ 'SLACK_SIGNING_SECRET',
18
+ 'GITHUB_APP_PRIVATE_KEY',
19
+ 'GITHUB_WEBHOOK_SECRET',
20
+ 'GITLAB_WEBHOOK_SECRET',
21
+ 'LINEAR_CLIENT_SECRET',
22
+ 'LINEAR_SIGNING_SECRET',
23
+ 'JIRA_CLIENT_SECRET',
24
+ 'JIRA_WEBHOOK_TOKEN',
25
+ 'AZURE_DEVOPS_WEBHOOK_SECRET',
26
+ 'AGENTMAIL_WEBHOOK_SECRET',
27
+ 'API_AGENT_FS_API_KEY',
28
+ 'KAPSO_WEBHOOK_HMAC_SECRET',
29
+ 'SENTRY_TEST_APP_WEBHOOK_SECRET',
30
+ 'TELEMETRY_CH_AUTH',
31
+ 'HACK_AGENT_FS_ADMIN_KEY',
32
+ 'X_CLIENT_SECRET'
33
+ )
34
+ OR key GLOB 'connection.*.secret';
@@ -0,0 +1,5 @@
1
+ -- The reasoning effort a task's session actually ran at. `effort` stays the
2
+ -- requested value (a task-level pin); the effective one usually comes from the
3
+ -- agent's REASONING_EFFORT_OVERRIDE and was never recorded. NULL means the
4
+ -- harness default applied, or the row predates this column.
5
+ ALTER TABLE agent_tasks ADD COLUMN resolvedEffort TEXT;