@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
@@ -25,6 +25,43 @@ export function isPageFeedbackRequested(queryParams: URLSearchParams): boolean {
25
25
  return value !== "0" && value !== "false";
26
26
  }
27
27
 
28
+ // Keys typed in the overlay must never reach the page's own key handlers. A
29
+ // listener on the overlay runs too late: page capture listeners on window and
30
+ // document fire first. So this guard is served at the top of <head>, before any
31
+ // page script, and is the first window capture listener. For a key from the
32
+ // overlay it stops dispatch outright and hands the event to the overlay
33
+ // (window.__swarmFeedbackKeys.handle). A press that started in the overlay
34
+ // stays owned until its keyup, so the release is swallowed even after the
35
+ // composer closed and focus moved to the page. Every other key passes through.
36
+ // The overlay script repeats it as a fallback; the second run is a no-op.
37
+ const FEEDBACK_KEY_GUARD_JS = `
38
+ (function () {
39
+ if (window.__swarmFeedbackKeys) return;
40
+ var keys = window.__swarmFeedbackKeys = { host: null, handle: null };
41
+ var owned = {};
42
+ function id(e) { return e.code || e.key; }
43
+ function fromOverlay(e) {
44
+ return !!keys.host && typeof e.composedPath === 'function' && e.composedPath().indexOf(keys.host) !== -1;
45
+ }
46
+ function guard(e) {
47
+ var k = id(e);
48
+ var mine = fromOverlay(e);
49
+ if (!mine && !owned[k]) return;
50
+ if (e.type === 'keydown') {
51
+ if (mine) owned[k] = true;
52
+ else if (!e.repeat) { delete owned[k]; return; }
53
+ }
54
+ if (e.type === 'keyup') delete owned[k];
55
+ e.stopImmediatePropagation();
56
+ if (mine && keys.handle) keys.handle(e);
57
+ }
58
+ ['keydown', 'keypress', 'keyup'].forEach(function (type) {
59
+ window.addEventListener(type, guard, true);
60
+ });
61
+ window.addEventListener('blur', function () { owned = {}; });
62
+ })();
63
+ `;
64
+
28
65
  const FEEDBACK_OVERLAY_JS = `
29
66
  (function () {
30
67
  var cfg = window.__swarmFeedback;
@@ -135,6 +172,7 @@ const FEEDBACK_OVERLAY_JS = `
135
172
  var panel = document.createElement('div');
136
173
  panel.className = 'panel';
137
174
  var composer = null;
175
+ var composerInput = null;
138
176
  root.appendChild(hl);
139
177
  root.appendChild(markers);
140
178
  root.appendChild(panel);
@@ -207,11 +245,25 @@ const FEEDBACK_OVERLAY_JS = `
207
245
  }
208
246
  render();
209
247
  }
210
- document.addEventListener('keydown', function (e) {
211
- if (e.key !== 'Escape') return;
248
+ function onEscape() {
212
249
  if (state.draft) { closeComposer(); return; }
213
250
  if (state.selecting) setSelecting(false);
251
+ }
252
+ // Escape pressed on the page while selecting. Keys typed in the overlay never
253
+ // get here: the key guard stops them and calls onOverlayKey instead.
254
+ document.addEventListener('keydown', function (e) {
255
+ if (e.key === 'Escape') onEscape();
214
256
  }, true);
257
+ function onOverlayKey(e) {
258
+ if (e.type !== 'keydown') return;
259
+ if (e.key === 'Escape') { onEscape(); return; }
260
+ if (e.key === 'Enter' && (e.metaKey || e.ctrlKey) && composerInput && e.composedPath()[0] === composerInput) {
261
+ e.preventDefault();
262
+ commitDraft(composerInput.value);
263
+ }
264
+ }
265
+ window.__swarmFeedbackKeys.host = host;
266
+ window.__swarmFeedbackKeys.handle = onOverlayKey;
215
267
 
216
268
  // ─── Composer ──────────────────────────────────────────────────────────
217
269
  function openComposer(target) {
@@ -230,9 +282,7 @@ const FEEDBACK_OVERLAY_JS = `
230
282
  add.type = 'button';
231
283
  cancel.addEventListener('click', closeComposer);
232
284
  add.addEventListener('click', function () { commitDraft(input.value); });
233
- input.addEventListener('keydown', function (e) {
234
- if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) { e.preventDefault(); commitDraft(input.value); }
235
- });
285
+ composerInput = input;
236
286
  row.appendChild(cancel);
237
287
  row.appendChild(add);
238
288
  composer.appendChild(row);
@@ -253,6 +303,7 @@ const FEEDBACK_OVERLAY_JS = `
253
303
  function closeComposer() {
254
304
  if (composer) composer.remove();
255
305
  composer = null;
306
+ composerInput = null;
256
307
  state.draft = null;
257
308
  hideHighlight();
258
309
  }
@@ -524,5 +575,13 @@ const FEEDBACK_OVERLAY_JS = `
524
575
  */
525
576
  export function feedbackOverlayScripts(pageId: string): string {
526
577
  const config = JSON.stringify({ pageId }).replace(/</g, "\\u003c");
527
- return `<script>window.__swarmFeedback = ${config};</script><script>${FEEDBACK_OVERLAY_JS}</script>`;
578
+ return `<script>window.__swarmFeedback = ${config};</script><script>${FEEDBACK_KEY_GUARD_JS}${FEEDBACK_OVERLAY_JS}</script>`;
579
+ }
580
+
581
+ /**
582
+ * Key guard served at the top of `<head>` when feedback mode is on, so it runs
583
+ * before any page script and its window capture listeners come first.
584
+ */
585
+ export function feedbackKeyGuardScript(): string {
586
+ return `<script>${FEEDBACK_KEY_GUARD_JS}</script>`;
528
587
  }
@@ -1,4 +1,5 @@
1
- import { createPageVersion, getPage, getPageVersions } from "../be/db";
1
+ import { createPageVersion, getPage } from "../be/db";
2
+ import { getPageEditCounter } from "../be/db/page-versions";
2
3
  import type { PageSnapshot, PageVersion } from "../types";
3
4
 
4
5
  /**
@@ -8,7 +9,7 @@ import type { PageSnapshot, PageVersion } from "../types";
8
9
  * Mirrors `snapshotWorkflow` (src/workflows/version.ts:13-44).
9
10
  *
10
11
  * 1. Load current page state
11
- * 2. Get max version number for this page (page_versions ORDER BY version DESC)
12
+ * 2. Get max version number for this page (MAX(page_versions.version))
12
13
  * 3. Insert page_versions row with version+1 and the pre-update snapshot
13
14
  *
14
15
  * Throws on missing parent. Callers in HTTP handlers wrap this in a try/catch
@@ -24,9 +25,7 @@ export async function snapshotPage(
24
25
  throw new Error(`Page ${pageId} not found — cannot create snapshot`);
25
26
  }
26
27
 
27
- const existingVersions = await getPageVersions(pageId);
28
- const maxVersion = existingVersions.length > 0 ? existingVersions[0]!.version : 0;
29
- const nextVersion = maxVersion + 1;
28
+ const nextVersion = await getPageEditCounter(pageId);
30
29
 
31
30
  const snapshot: PageSnapshot = {
32
31
  title: page.title,
@@ -8,11 +8,15 @@
8
8
  * E outputs (gated on AGENT_FS_API_URL and the pages capability)
9
9
  * H deployment-gated notes: slack, steering
10
10
  * I tools and skills (harness tool discovery, skills, MCP server names)
11
- * J agent notes: CLAUDE.md for codex, opencode, pi, only when edited
12
- * K repository (per task)
11
+ * J agent notes: CLAUDE.md, only when edited
13
12
  *
14
- * The runner appends the requester profile, the operator SYSTEM_PROMPT, and a
15
- * cwd warning after this.
13
+ * The runner appends the operator SYSTEM_PROMPT after this.
14
+ *
15
+ * Nothing here may vary per task, requester, or session: the provider caches
16
+ * the system prompt as a prefix, and one changed byte re-bills everything
17
+ * after it. Per-task context (repository, scripts-only Slack, requester
18
+ * profile, cwd warning) goes into the task prompt instead; see
19
+ * `getTaskContextPrompt` and the runner's `buildTaskSessionPrompts`.
16
20
  */
17
21
 
18
22
  import type { ProviderTraits } from "../providers/types";
@@ -44,13 +48,28 @@ const BOOTSTRAP_TOTAL_MAX_CHARS = 120_000;
44
48
 
45
49
  /**
46
50
  * Per-section cap applied to the *repo* CLAUDE.md when it is inlined (opencode
47
- * only). The agent-swarm OSS one is ~18 KB and the biggest volatile component
48
- * of the system prompt.
51
+ * only). The agent-swarm OSS one is ~18 KB and the biggest piece of the task
52
+ * context.
49
53
  */
50
54
  const REPO_CLAUDE_MD_MAX_CHARS = 12_000;
51
55
 
52
- /** Providers that do not load the agent's CLAUDE.md natively. Claude does. */
53
- const CLAUDE_MD_INJECT_PROVIDERS: ReadonlySet<string> = new Set(["codex", "opencode", "pi"]);
56
+ /**
57
+ * Providers that get the agent's CLAUDE.md in the system prompt. Claude also
58
+ * keeps the editable copy at ~/.claude/CLAUDE.md but excludes it from its
59
+ * memory load (claude-flag-settings.ts), so it is read once, from the cached
60
+ * system prompt instead of an uncached message.
61
+ */
62
+ const CLAUDE_MD_INJECT_PROVIDERS: ReadonlySet<string> = new Set([
63
+ "claude",
64
+ "codex",
65
+ "opencode",
66
+ "pi",
67
+ ]);
68
+
69
+ /** Where each provider's editable CLAUDE.md lives, for the truncation notice. */
70
+ function claudeMdSourcePath(provider: string): string {
71
+ return provider === "claude" ? "~/.claude/CLAUDE.md" : "/workspace/CLAUDE.md";
72
+ }
54
73
 
55
74
  /** Providers that get the repo CLAUDE.md inlined until native loading is verified. */
56
75
  const REPO_CLAUDE_MD_INLINE_PROVIDERS: ReadonlySet<string> = new Set(["opencode"]);
@@ -95,36 +114,61 @@ export type BasePromptArgs = {
95
114
  soulMd?: string;
96
115
  identityMd?: string;
97
116
  claudeMd?: string;
98
- repoContext?: {
99
- claudeMd?: string | null;
100
- clonePath: string;
101
- warning?: string | null;
102
- autoStashes?: { ref: string; message: string }[];
103
- guidelines?: {
104
- prChecks: string[];
105
- mergeChecks: string[];
106
- allowMerge?: boolean;
107
- review: string[];
108
- } | null;
109
- };
110
- /** Slack context from the current task, if present */
111
- slackContext?: { channelId: string; threadTs?: string };
112
117
  /** Pre-fetched skill summaries for the tools and skills section */
113
118
  skillsSummary?: { name: string; description: string }[];
114
119
  /** Names of the MCP servers connected for this agent */
115
120
  mcpServers?: string[];
116
121
  };
117
122
 
118
- export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
119
- const { role, agentId, traits } = args;
123
+ export type RepoContext = {
124
+ claudeMd?: string | null;
125
+ clonePath: string;
126
+ warning?: string | null;
127
+ autoStashes?: { ref: string; message: string }[];
128
+ guidelines?: {
129
+ prChecks: string[];
130
+ mergeChecks: string[];
131
+ allowMerge?: boolean;
132
+ review: string[];
133
+ } | null;
134
+ };
135
+
136
+ export type SlackTaskContext = { channelId: string; threadTs?: string };
137
+
138
+ /** Inputs for the per-task context that rides in the task prompt. */
139
+ export type TaskContextPromptArgs = Pick<
140
+ BasePromptArgs,
141
+ "role" | "traits" | "provider" | "scriptsOnly" | "serverCapabilities"
142
+ > & {
143
+ repoContext?: RepoContext;
144
+ /** Slack context from the current task, if present */
145
+ slackContext?: SlackTaskContext;
146
+ };
147
+
148
+ function promptFlags(args: Pick<BasePromptArgs, "traits" | "provider" | "scriptsOnly">) {
120
149
  const {
121
150
  hasMcp = true,
122
151
  hasToolSearch = false,
123
152
  hasLocalEnvironment: hasLocalEnv = true,
124
153
  nativeSkillDiscovery = true,
125
- } = traits ?? {};
154
+ } = args.traits ?? {};
155
+ const scriptsOnly = args.scriptsOnly ?? process.env.SCRIPTS_ONLY_MCP === "true";
156
+ return {
157
+ hasMcp,
158
+ hasToolSearch,
159
+ hasLocalEnv,
160
+ nativeSkillDiscovery,
161
+ provider: args.provider ?? "claude",
162
+ // Experimental scripts-only MCP surface (code-mode).
163
+ scriptsOnlyMode: hasMcp && scriptsOnly,
164
+ };
165
+ }
166
+
167
+ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
168
+ const { role, agentId, traits } = args;
169
+ const { hasMcp, hasToolSearch, hasLocalEnv, nativeSkillDiscovery, provider, scriptsOnlyMode } =
170
+ promptFlags(args);
126
171
  const steerModes = traits?.steerModes ?? [];
127
- const provider = args.provider ?? "claude";
128
172
 
129
173
  const defaultsInput = {
130
174
  name: args.name ?? agentId,
@@ -168,8 +212,6 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
168
212
 
169
213
  // Experimental scripts-only MCP surface (code-mode): named swarm tools are
170
214
  // not registered, so tell the agent everything goes through script-run.
171
- const scriptsOnly = args.scriptsOnly ?? process.env.SCRIPTS_ONLY_MCP === "true";
172
- const scriptsOnlyMode = hasMcp && scriptsOnly;
173
215
  if (scriptsOnlyMode) {
174
216
  const scriptsOnlyResult = await resolveTemplateAsync("system.agent.scripts_only_mode", {});
175
217
  prompt += `\n${scriptsOnlyResult.text}`;
@@ -199,13 +241,6 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
199
241
  const slackResult = await resolveTemplateAsync("system.agent.slack", {});
200
242
  prompt += slackResult.text;
201
243
  }
202
- if (role !== "lead" && args.slackContext && scriptsOnlyMode && slackPromptToolsEnabled) {
203
- const slackResult = await resolveTemplateAsync("system.agent.scripts_only_mode.slack", {
204
- slackChannelId: args.slackContext.channelId,
205
- slackThreadTs: args.slackContext.threadTs ?? "",
206
- });
207
- prompt += slackResult.text;
208
- }
209
244
 
210
245
  if (
211
246
  hasMcp &&
@@ -244,9 +279,9 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
244
279
  prompt += toolsResult.text;
245
280
  }
246
281
 
247
- // J. Agent notes (CLAUDE.md). Claude loads ~/.claude/CLAUDE.md natively and
248
- // excludes the /workspace/CLAUDE.md copy (claude-flag-settings.ts); the others
249
- // get it here, and only when it differs from the generated default.
282
+ // J. Agent notes (CLAUDE.md), only when it differs from the generated
283
+ // default. Claude excludes both ~/.claude/CLAUDE.md and /workspace/CLAUDE.md
284
+ // from its memory load (claude-flag-settings.ts), so this is its only copy.
250
285
  if (
251
286
  hasLocalEnv &&
252
287
  args.claudeMd &&
@@ -257,10 +292,42 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
257
292
  BOOTSTRAP_MAX_CHARS,
258
293
  Math.max(0, BOOTSTRAP_TOTAL_MAX_CHARS - prompt.length),
259
294
  );
260
- prompt += truncateSection(args.claudeMd, "## Your notes (CLAUDE.md)", "CLAUDE.md", budget);
295
+ prompt += truncateSection(
296
+ args.claudeMd,
297
+ "## Your notes (CLAUDE.md)",
298
+ claudeMdSourcePath(provider),
299
+ budget,
300
+ );
261
301
  }
262
302
 
263
- // K. Repository (per task). Never truncated except the inlined repo CLAUDE.md.
303
+ // Blocks start and end with a newline; collapse the seams to one blank line.
304
+ return prompt.replace(/\n{3,}/g, "\n\n");
305
+ };
306
+
307
+ /**
308
+ * Per-task context that used to close the system prompt: the repository block
309
+ * and the scripts-only Slack note. It rides in the task prompt so the system
310
+ * prompt stays byte-identical across an agent's sessions. Empty when the task
311
+ * has neither.
312
+ */
313
+ export const getTaskContextPrompt = async (args: TaskContextPromptArgs): Promise<string> => {
314
+ const { hasMcp, hasLocalEnv, provider, scriptsOnlyMode } = promptFlags(args);
315
+ let prompt = "";
316
+
317
+ if (
318
+ args.role !== "lead" &&
319
+ args.slackContext &&
320
+ scriptsOnlyMode &&
321
+ areSlackPromptToolsEnabled(process.env, args.serverCapabilities)
322
+ ) {
323
+ const slackResult = await resolveTemplateAsync("system.agent.scripts_only_mode.slack", {
324
+ slackChannelId: args.slackContext.channelId,
325
+ slackThreadTs: args.slackContext.threadTs ?? "",
326
+ });
327
+ prompt += slackResult.text;
328
+ }
329
+
330
+ // Repository. Never truncated except the inlined repo CLAUDE.md.
264
331
  if (args.repoContext) {
265
332
  const repoResult = await resolveTemplateAsync(
266
333
  "system.agent.repository",
@@ -269,8 +336,7 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
269
336
  prompt += repoResult.text;
270
337
  }
271
338
 
272
- // Blocks start and end with a newline; collapse the seams to one blank line.
273
- return prompt.replace(/\n{3,}/g, "\n\n");
339
+ return prompt.replace(/\n{3,}/g, "\n\n").trim();
274
340
  };
275
341
 
276
342
  /**
@@ -331,7 +397,7 @@ function renderToolsAndSkillsVars(input: {
331
397
  * the heading lives in the template, the per-task pieces are built here.
332
398
  */
333
399
  function renderRepositoryVars(
334
- repo: NonNullable<BasePromptArgs["repoContext"]>,
400
+ repo: RepoContext,
335
401
  ctx: { hasMcp: boolean; hasLocalEnv: boolean; provider: string },
336
402
  ): Record<string, string> {
337
403
  const vars: Record<string, string> = {
@@ -432,7 +498,7 @@ export function truncateRepoClaudeMd(content: string, clonePath: string, budget:
432
498
  function truncateSection(
433
499
  content: string | undefined,
434
500
  header: string,
435
- fileName: string,
501
+ sourcePath: string,
436
502
  budget: number,
437
503
  ): string {
438
504
  if (!content || budget <= 0) return "";
@@ -441,7 +507,7 @@ function truncateSection(
441
507
  if (fullSection.length <= budget) return fullSection;
442
508
 
443
509
  const headerStr = `\n\n${header}\n\n`;
444
- const notice = `\n\n[...truncated, see /workspace/${fileName} for full content]\n`;
510
+ const notice = `\n\n[...truncated, see ${sourcePath} for full content]\n`;
445
511
  const contentBudget = budget - headerStr.length - notice.length;
446
512
 
447
513
  if (contentBudget > 0) {
@@ -1,3 +1,5 @@
1
+ import { openAICompatibleBaseUrlVars, openAICompatibleKeyVars } from "@desplega/model-catalog";
2
+
1
3
  export const ACP_TARGET_IDS = [
2
4
  "opencode",
3
5
  "gemini",
@@ -40,6 +42,10 @@ export const ACP_TARGET_CATALOG: readonly AcpTargetCatalogEntry[] = [
40
42
  "OPENAI_API_KEY",
41
43
  "OPENROUTER_API_KEY",
42
44
  "OPENROUTER_BASE_URL",
45
+ // OpenAI-compatible registry providers: keys (canonical and alias),
46
+ // then their `<ID>_BASE_URL` overrides.
47
+ ...openAICompatibleKeyVars(),
48
+ ...openAICompatibleBaseUrlVars(),
43
49
  "GOOGLE_API_KEY",
44
50
  "GEMINI_API_KEY",
45
51
  "OPENCODE_CONFIG",
@@ -1,7 +1,12 @@
1
1
  import { mkdir, mkdtemp, rm } from "node:fs/promises";
2
2
  import { tmpdir } from "node:os";
3
3
  import { join } from "node:path";
4
- import { normalizeGrokModel } from "@desplega/model-catalog";
4
+ import {
5
+ baseUrlOverride,
6
+ normalizeGrokModel,
7
+ providerBaseUrl,
8
+ providerForModel,
9
+ } from "@desplega/model-catalog";
5
10
  import { clampContextPercent, getContextWindowSize } from "../utils/context-window";
6
11
  import {
7
12
  ACP_TARGET_IDS,
@@ -9,7 +14,11 @@ import {
9
14
  getAcpTargetCatalogEntry,
10
15
  isAcpTarget,
11
16
  } from "./acp-target-catalog";
12
- import { applyOpenRouterBaseUrlOverride, type OpencodeConfig } from "./opencode-adapter";
17
+ import {
18
+ applyOpenRouterBaseUrlOverride,
19
+ buildOpenAICompatibleProviderBlock,
20
+ type OpencodeConfig,
21
+ } from "./opencode-adapter";
13
22
  import { applyReasoningEffort } from "./reasoning-effort";
14
23
  import type { CostData, CostModelUsage, ProviderEvent, ProviderSessionConfig } from "./types";
15
24
 
@@ -140,10 +149,54 @@ function withOpencodeConfig(env: Record<string, string>, model: string): void {
140
149
  }
141
150
  }
142
151
  if (model.trim()) value.model = model.trim();
152
+ withCustomProviderBlock(value as OpencodeConfig, model.trim(), env);
143
153
  applyOpenRouterBaseUrlOverride(value as OpencodeConfig, env);
144
154
  env[key] = JSON.stringify(value);
145
155
  }
146
156
 
157
+ /**
158
+ * OpenCode ships no provider for a registry entry models.dev does not list
159
+ * (`catalog: "registry"`, e.g. `helmcode`), so its models need the custom
160
+ * block. The key stays an `{env:…}` reference: the ACP subprocess env is the
161
+ * forwarded per-task env, where the var holds one picked key, so no literal
162
+ * key lands in `OPENCODE_CONFIG_CONTENT`. A built-in registry provider
163
+ * (`nan`) only gets `options.baseURL` when `<ID>_BASE_URL` is set. Values the
164
+ * operator already set in `OPENCODE_CONFIG_CONTENT` win over the defaults.
165
+ */
166
+ function withCustomProviderBlock(
167
+ config: OpencodeConfig,
168
+ model: string,
169
+ env: Record<string, string>,
170
+ ): void {
171
+ const provider = providerForModel(model);
172
+ if (!provider) return;
173
+ const existing = config.provider?.[provider.id];
174
+ if (provider.catalog !== "registry") {
175
+ const baseURL = baseUrlOverride(provider, env);
176
+ if (!baseURL) return;
177
+ config.provider = {
178
+ ...config.provider,
179
+ [provider.id]: { ...existing, options: { baseURL, ...existing?.options } },
180
+ };
181
+ return;
182
+ }
183
+ const block = buildOpenAICompatibleProviderBlock(
184
+ provider,
185
+ `{env:${provider.envVar}}`,
186
+ model.slice(provider.id.length + 1),
187
+ providerBaseUrl(provider, env),
188
+ );
189
+ config.provider = {
190
+ ...config.provider,
191
+ [provider.id]: {
192
+ ...block,
193
+ ...existing,
194
+ options: { ...block.options, ...existing?.options },
195
+ models: { ...block.models, ...existing?.models },
196
+ },
197
+ };
198
+ }
199
+
147
200
  function parseCommand(command: string, args: string | undefined): string[] {
148
201
  const trimmed = command.trim();
149
202
  if (!trimmed) {
@@ -306,7 +359,7 @@ const copilotTargetProfile: AcpTargetProfile = {
306
359
  },
307
360
  };
308
361
 
309
- /** Qwen Code's `--auth-type` choices (0.25.1). `qwen-oauth` needs a browser, so it is left out. */
362
+ /** Qwen Code's `--auth-type` choices (0.25.2). `qwen-oauth` needs a browser, so it is left out. */
310
363
  const QWEN_AUTH_TYPES = ["openai", "openai-responses", "anthropic", "gemini", "vertex-ai"] as const;
311
364
 
312
365
  // Qwen Code is a Gemini CLI fork: QWEN_SYSTEM_MD replaces its built-in prompt
@@ -44,7 +44,7 @@ import type {
44
44
  * default; the image installs exactly this version and the per-task settings
45
45
  * set `amp.updates.mode: "disabled"`. Bump it deliberately, with a live run.
46
46
  */
47
- export const AMP_PACKAGE = "@ampcode/cli@0.0.1791979242-g144271";
47
+ export const AMP_PACKAGE = "@ampcode/cli@0.0.1792152053-g57ff9b";
48
48
 
49
49
  /** MCP server name. Amp exposes its tools as `agent_swarm` / `store_progress` (dashes become underscores). */
50
50
  const AMP_MCP_SERVER_NAME = "agent-swarm";
@@ -1041,7 +1041,7 @@ class ClaudeSession implements ProviderSession {
1041
1041
  "--allow-dangerously-skip-permissions",
1042
1042
  "--permission-mode",
1043
1043
  "bypassPermissions",
1044
- // Skip the workspace copy of claudeMd; ~/.claude/CLAUDE.md already carries it.
1044
+ // Skip both on-disk copies of claudeMd; the system prompt already carries it.
1045
1045
  // createSession merged caller `--settings` into these, so this is the only one.
1046
1046
  "--settings",
1047
1047
  JSON.stringify(this.flagSettings),
@@ -1,5 +1,6 @@
1
1
  import { readFileSync } from "node:fs";
2
- import { resolve } from "node:path";
2
+ import { homedir } from "node:os";
3
+ import { join, resolve } from "node:path";
3
4
  import { scrubSecrets } from "../utils/secret-scrubber";
4
5
 
5
6
  /**
@@ -9,17 +10,28 @@ import { scrubSecrets } from "../utils/secret-scrubber";
9
10
  * and it walks up from its cwd (`/workspace/...`) to load `/workspace/CLAUDE.md`
10
11
  * as project memory too, so every Claude session paid for the notes twice.
11
12
  *
12
- * `claudeMdExcludes` drops only that one path from Claude's memory load. The
13
- * file stays on disk for the other harnesses (one container can live-swap
14
- * providers mid-run), and repo-level `CLAUDE.md` files still load.
13
+ * `claudeMdExcludes` drops that path from Claude's memory load. The file stays
14
+ * on disk for the other harnesses (one container can live-swap providers
15
+ * mid-run), and repo-level `CLAUDE.md` files still load.
16
+ *
17
+ * The user-memory copy (`~/.claude/CLAUDE.md`) is excluded too: the system
18
+ * prompt carries the same notes (base-prompt.ts block J), where the provider
19
+ * caches them across sessions. Claude would load the user-memory copy into an
20
+ * uncached message instead. The SessionStart hook still writes that file: it
21
+ * is the copy the agent edits and the Stop hook syncs back to the profile.
15
22
  */
16
23
  export const WORKSPACE_CLAUDE_MD_EXCLUDE = "/workspace/CLAUDE.md";
17
24
 
25
+ /** `~/.claude/CLAUDE.md` for the HOME the Claude session runs under. */
26
+ export function userClaudeMdExclude(home: string = process.env.HOME ?? homedir()): string {
27
+ return join(home, ".claude", "CLAUDE.md");
28
+ }
29
+
18
30
  export type ClaudeFlagSettings = Record<string, unknown> & { claudeMdExcludes: string[] };
19
31
 
20
32
  /** Flag-level settings (`--settings` / SDK `settings`) for every Claude session. */
21
33
  export function claudeFlagSettings(): ClaudeFlagSettings {
22
- return { claudeMdExcludes: [WORKSPACE_CLAUDE_MD_EXCLUDE] };
34
+ return { claudeMdExcludes: [WORKSPACE_CLAUDE_MD_EXCLUDE, userClaudeMdExclude()] };
23
35
  }
24
36
 
25
37
  const SETTINGS_FLAG = "--settings";
@@ -806,7 +806,7 @@ class ClaudeManagedSession implements ProviderSession {
806
806
  export class ClaudeManagedAdapter implements ProviderAdapter {
807
807
  readonly name = "claude-managed";
808
808
  // Anthropic's cloud sandbox calls back into our /mcp endpoint, but the worker
809
- // process is a thin SSE relay — no /workspace, no PM2, no agent-fs, no skills FS.
809
+ // process is a thin SSE relay — no /workspace, no agent-fs, no skills FS.
810
810
  readonly traits: ProviderTraits = {
811
811
  hasMcp: true,
812
812
  hasToolSearch: false,
@@ -32,6 +32,7 @@ type ClaudeUsage = {
32
32
  cache_read_input_tokens?: number;
33
33
  cache_creation_input_tokens?: number;
34
34
  thinking_input_tokens?: number;
35
+ output_tokens_details?: { thinking_tokens?: number };
35
36
  cache_creation?: Record<string, unknown>;
36
37
  };
37
38
 
@@ -125,7 +126,11 @@ function costFromResult(
125
126
  cacheWriteTokens: usage?.cache_creation_input_tokens ?? 0,
126
127
  cacheWrite5mTokens: finiteNumber(cacheCreation?.ephemeral_5m_input_tokens),
127
128
  cacheWrite1hTokens: finiteNumber(cacheCreation?.ephemeral_1h_input_tokens),
128
- thinkingTokens: usage?.thinking_input_tokens ?? 0,
129
+ // A subset of output_tokens, already billed at the output rate.
130
+ thinkingTokens:
131
+ tokenCount(usage?.output_tokens_details?.thinking_tokens) ??
132
+ tokenCount(usage?.thinking_input_tokens) ??
133
+ 0,
129
134
  models,
130
135
  durationMs: json.duration_ms || 0,
131
136
  numTurns: json.num_turns ?? null,
@@ -37,7 +37,7 @@ import type {
37
37
  } from "./types";
38
38
 
39
39
  // npm's `latest` is older and lacks the JSON/stdin contract used here.
40
- export const DSH_PACKAGE = "@deepseek-ai/dsh@0.2.1-alpha.3";
40
+ export const DSH_PACKAGE = "@deepseek-ai/dsh@0.2.1-alpha.5";
41
41
 
42
42
  export function checkDshCredentials(env: Record<string, string | undefined>): CredStatus {
43
43
  return env.DEEPSEEK_API_KEY?.trim() || env.OPENROUTER_API_KEY?.trim()