@desplega.ai/agent-swarm 1.152.2 → 1.154.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 (284) hide show
  1. package/README.md +2 -2
  2. package/dist/{acp-adapter-pfeje2v5.js → acp-adapter-eb2aj8xy.js} +4 -4
  3. package/dist/{actions-0sttc7f5.js → actions-kpnwp1kz.js} +31 -27
  4. package/dist/{anthropic-messages-2y8nktar.js → anthropic-messages-9vqsbznt.js} +112 -84
  5. package/dist/{app-p8teva95.js → app-zk1apkf6.js} +10 -7
  6. package/dist/{assistant-r45jnsrt.js → assistant-kwq4y50q.js} +32 -28
  7. package/dist/{azure-openai-responses-f38x2avq.js → azure-openai-responses-04qwdwfq.js} +27 -13
  8. package/dist/{boot-reembed-je26h5y7.js → boot-reembed-22hd3jjn.js} +9 -7
  9. package/dist/{boot-reembed-1qmybsd4.js → boot-reembed-qe168424.js} +10 -8
  10. package/dist/{boot-scrub-logs-gte3h1mm.js → boot-scrub-logs-pkdpsrjd.js} +7 -5
  11. package/dist/{claude-adapter-csc1mzka.js → claude-adapter-3fx90nww.js} +18 -16
  12. package/dist/{claude-managed-adapter-dsmkcrjy.js → claude-managed-adapter-ea2aga6w.js} +3 -3
  13. package/dist/{claude-sdk-session-fcd6f078.js → claude-sdk-session-z7fahf1k.js} +18 -16
  14. package/dist/{cli-r2fpe7cx.js → cli-00w2c66p.js} +61 -55
  15. package/dist/{cli-wbyk465z.js → cli-09y3tjxz.js} +1 -1
  16. package/dist/{cli-ht5rs63n.js → cli-0e31nm4n.js} +16 -7
  17. package/dist/cli-0x5qzvkg.js +4279 -0
  18. package/dist/{cli-d3p82erb.js → cli-18amys3y.js} +9 -9
  19. package/dist/{cli-4ahpr4sw.js → cli-1jpjafw4.js} +5 -5
  20. package/dist/{cli-jbmc0r7r.js → cli-243tzws8.js} +1 -1
  21. package/dist/{cli-ch38q5z4.js → cli-24k806sc.js} +6789 -2542
  22. package/dist/cli-3bkz2p7j.js +2828 -0
  23. package/dist/cli-3er6gcsn.js +1849 -0
  24. package/dist/cli-4k7jazkq.js +3339 -0
  25. package/dist/{cli-c4eeb5q2.js → cli-5b6b62tz.js} +1 -1
  26. package/dist/{cli-qd65dvr6.js → cli-5vs0nh43.js} +65 -44
  27. package/dist/{cli-z3wkng35.js → cli-6r3cgpk2.js} +224 -156
  28. package/dist/{cli-pgj4a5fb.js → cli-71cj99hx.js} +4 -3
  29. package/dist/cli-8sea27q4.js +14075 -0
  30. package/dist/{cli-jvy9qgjs.js → cli-913yakhv.js} +22 -7
  31. package/dist/{cli-pf9q3696.js → cli-927erqqt.js} +5 -2
  32. package/dist/cli-95jnpnqg.js +230 -0
  33. package/dist/{cli-wpv5rgg2.js → cli-abp3g4ax.js} +15 -2
  34. package/dist/{cli-ckz5t2hb.js → cli-acy6bfhr.js} +10 -7
  35. package/dist/{cli-4yc5d8fk.js → cli-avkd6mqv.js} +50 -0
  36. package/dist/{cli-8wrympd7.js → cli-bzr0ftht.js} +26 -7
  37. package/dist/{cli-qn042eh7.js → cli-c1v10xb2.js} +194 -1913
  38. package/dist/cli-cgj4hc12.js +18902 -0
  39. package/dist/{cli-2nnd56zt.js → cli-e0pg4zeh.js} +3 -2
  40. package/dist/{cli-r84ctdxn.js → cli-e31ehqwy.js} +2 -2
  41. package/dist/{cli-gphgnvpf.js → cli-e3229na9.js} +3 -3
  42. package/dist/{cli-gpqcs935.js → cli-e3cyf59d.js} +2 -2
  43. package/dist/{cli-s25avqg9.js → cli-e781c6f9.js} +1 -0
  44. package/dist/{cli-s2qjdd6z.js → cli-eetrvv91.js} +1 -1
  45. package/dist/{cli-j4nv2wqy.js → cli-fdzg6jhf.js} +10 -4
  46. package/dist/{cli-fm4ytsdk.js → cli-g2h29qar.js} +2 -2
  47. package/dist/{cli-zvgj5zg8.js → cli-ge67p080.js} +302 -3497
  48. package/dist/cli-h38x0qhg.js +6912 -0
  49. package/dist/{cli-9xvdm3bx.js → cli-h60qfasa.js} +742 -278
  50. package/dist/{cli-jew3jda5.js → cli-hws0vn86.js} +2 -2
  51. package/dist/{cli-j8dggbcr.js → cli-k0g1sjzm.js} +23 -31
  52. package/dist/{cli-xw7vak96.js → cli-kp3qs53m.js} +5 -5
  53. package/dist/{cli-rgvp6r2x.js → cli-mcnhgnn1.js} +193 -4
  54. package/dist/{cli-zvkq5csn.js → cli-myaxtgh8.js} +7 -6
  55. package/dist/{cli-56h18ng2.js → cli-n62atwh9.js} +1 -1
  56. package/dist/cli-n7h1kqpf.js +29 -0
  57. package/dist/{cli-fmy65jdn.js → cli-pf1v8xhb.js} +7 -5
  58. package/dist/{cli-xy1cchaf.js → cli-q85qhckh.js} +238 -11
  59. package/dist/{cli-3bpzj8me.js → cli-r1d3dzt6.js} +2 -2
  60. package/dist/{pi-mono-adapter-jcqt71cg.js → cli-rxkqvngf.js} +67343 -101083
  61. package/dist/{cli-kj76p1ez.js → cli-scwq51gn.js} +13 -7
  62. package/dist/{cli-b9dd0h3k.js → cli-stwsmd6k.js} +3 -2
  63. package/dist/{cli-c2mk1kgf.js → cli-v4en75c5.js} +8 -1
  64. package/dist/{cli-z61ykvam.js → cli-wg04s9kr.js} +4 -3
  65. package/dist/cli-yn0a417a.js +4069 -0
  66. package/dist/{cli-zfzznn7c.js → cli-ytxs7mn1.js} +26 -2
  67. package/dist/{cli-4j8k1m4w.js → cli-zt1227k1.js} +1162 -192
  68. package/dist/cli.js +28 -35
  69. package/dist/{codex-adapter-fxmpsabw.js → codex-adapter-ttdm995v.js} +12 -11
  70. package/dist/{codex-hook-8jexc34x.js → codex-hook-8gx7bcz0.js} +3 -3
  71. package/dist/{codex-session-runner-rr1e47ea.js → codex-session-runner-3v8nh4c8.js} +12 -11
  72. package/dist/{commands-0f5rxz51.js → commands-1cxwbhhq.js} +7 -5
  73. package/dist/{db-r3jxf3wy.js → db-y9zwsr79.js} +25 -5
  74. package/dist/{dispatcher-06vph6q4.js → dispatcher-9m9zss36.js} +30 -26
  75. package/dist/dsh-adapter-gsb2qqf9.js +19 -0
  76. package/dist/{e2b-413b8t4v.js → e2b-93x1k0j5.js} +6 -7
  77. package/dist/{google-generative-ai-ndjmj5fa.js → google-generative-ai-gwwrnzqn.js} +33 -73
  78. package/dist/{google-vertex-fr665tqs.js → google-vertex-5wfawpwz.js} +38 -68
  79. package/dist/{handlers-0hgtc910.js → handlers-36fm1bwn.js} +33 -29
  80. package/dist/{hook-9kvrv1er.js → hook-pntw4r8h.js} +12 -10
  81. package/dist/{hook-fbfhkat3.js → hook-vwq8y26p.js} +13 -11
  82. package/dist/{http-xbyx8k5j.js → http-20jesakk.js} +357 -261
  83. package/dist/{index-jsw3aynb.js → index-6artrehg.js} +30 -26
  84. package/dist/{cli-pdz9qde4.js → index-9ch1n761.js} +10 -11
  85. package/dist/{index-rnyahfn5.js → index-9n5z2492.js} +30 -26
  86. package/dist/{index-66xz5e9j.js → index-h5gs261z.js} +521 -9
  87. package/dist/{index-tfsdxyv6.js → index-j5wrf1yw.js} +40 -25
  88. package/dist/{index-2sp0384z.js → index-kkeftv5h.js} +738 -21
  89. package/dist/{index-sgk50mbg.js → index-m2xqpz5r.js} +31 -27
  90. package/dist/{index-gpfn1741.js → index-m9ks8a7t.js} +9 -7
  91. package/dist/index-w097eg0x.js +5 -0
  92. package/dist/jiti-loader-b4837mtm.js +34 -0
  93. package/dist/jiti-static-loader-q2g5ds0y.js +31267 -0
  94. package/dist/{keepalive-s3xpr7sw.js → keepalive-pwxvxd2c.js} +9 -7
  95. package/dist/{lead-rq4n5r16.js → lead-m789wqa3.js} +46 -41
  96. package/dist/{maintenance-f0atj1ab.js → maintenance-bvg6w7e2.js} +10 -8
  97. package/dist/{mistral-conversations-qhr84ph3.js → mistral-conversations-zx0kn554.js} +24 -18
  98. package/dist/{node-x1g4v0pq.js → node-5qtycf6a.js} +16 -11
  99. package/dist/{oauth-refresh-sweep-q0t3bxre.js → oauth-refresh-sweep-6v4bd737.js} +8 -6
  100. package/dist/{onboard-br5j1kch.js → onboard-snckpcj1.js} +115 -35
  101. package/dist/{openai-codex-responses-wy6a43wd.js → openai-codex-responses-4vjqzvjp.js} +33 -27
  102. package/dist/{openai-completions-32rdwmze.js → openai-completions-pxsmym7g.js} +52 -64
  103. package/dist/{openai-responses-6xwf7bzg.js → openai-responses-tmn0rqp0.js} +23 -24
  104. package/dist/{opencode-adapter-28axqa09.js → opencode-adapter-qbmv4tpy.js} +6 -6
  105. package/dist/{otel-impl-vdqge2nt.js → otel-impl-e0ytens5.js} +4 -4
  106. package/dist/{pi-messages-b1mbr6gp.js → pi-messages-txpjj39q.js} +3 -3
  107. package/dist/pi-mono-adapter-c4ggemhz.js +1316 -0
  108. package/dist/{pricing-refresh-hb3691fd.js → pricing-refresh-52g2ywrw.js} +9 -7
  109. package/dist/{rbac-roles-t78xt39b.js → rbac-roles-5455kfdn.js} +8 -6
  110. package/dist/{rbac-roles-jh280k9g.js → rbac-roles-hbf0xa52.js} +9 -7
  111. package/dist/{render-v2-7p8r2ymg.js → render-v2-npm8xdzh.js} +16 -9
  112. package/dist/{seed-pricing-hf889enh.js → seed-pricing-650wbr1n.js} +8 -6
  113. package/dist/{setup-w6mb03jv.js → setup-k1mew5rf.js} +4 -5
  114. package/dist/virtual-modules-2q5b2pk4.js +54 -0
  115. package/dist/{work-objects-nt8gy1kj.js → work-objects-2ea3kvwg.js} +33 -29
  116. package/dist/{worker-dwy617t0.js → worker-ec6hvc4m.js} +46 -41
  117. package/openapi.json +109 -16
  118. package/package.json +7 -6
  119. package/plugin/opencode-plugins/lib/memory-raters.ts +7 -0
  120. package/src/be/automation-preflight.ts +6 -4
  121. package/src/be/db/agents.ts +75 -2
  122. package/src/be/db/tasks/read.ts +2 -0
  123. package/src/be/db/tasks/write.ts +7 -1
  124. package/src/be/db.ts +140 -18
  125. package/src/be/extensions/db.ts +35 -4
  126. package/src/be/memory/raters/llm.ts +2 -6
  127. package/src/be/memory/raters/noop.ts +2 -3
  128. package/src/be/memory/raters/registry.ts +4 -10
  129. package/src/be/migrations/157_defer_provenance_and_marker.sql +27 -0
  130. package/src/be/models-catalog.ts +2 -0
  131. package/src/be/modelsdev-cache.json +213 -0
  132. package/src/be/rbac-audit.ts +2 -0
  133. package/src/be/seed/agent-fs-provision.ts +23 -0
  134. package/src/be/seed-pricing.ts +3 -1
  135. package/src/be/swarm-config-guard.ts +1 -0
  136. package/src/commands/onboard/compose-generator.ts +16 -1
  137. package/src/commands/onboard/env-generator.ts +14 -1
  138. package/src/commands/onboard/manifest.ts +1 -0
  139. package/src/commands/onboard/steps/integration-slack.tsx +56 -16
  140. package/src/commands/onboard/steps/review.tsx +5 -0
  141. package/src/commands/onboard/types.ts +6 -0
  142. package/src/commands/onboard.tsx +5 -1
  143. package/src/commands/provider-credentials.ts +14 -2
  144. package/src/commands/runner.ts +18 -2
  145. package/src/extensions/identity.ts +15 -7
  146. package/src/extensions/lifecycle.ts +15 -21
  147. package/src/hooks/codex-hook.ts +7 -1
  148. package/src/http/agents.ts +12 -4
  149. package/src/http/config.ts +1 -1
  150. package/src/http/core.ts +5 -3
  151. package/src/http/extensions.ts +108 -34
  152. package/src/http/poll.ts +7 -0
  153. package/src/http/schedules.ts +10 -0
  154. package/src/http/script-runs.ts +35 -26
  155. package/src/http/status.ts +24 -11
  156. package/src/http/tasks.ts +6 -1
  157. package/src/prompts/base-prompt.ts +15 -7
  158. package/src/prompts/memories.ts +5 -7
  159. package/src/prompts/session-templates.ts +3 -2
  160. package/src/prompts/steering-delivery.ts +2 -0
  161. package/src/providers/claude-managed-models.ts +8 -0
  162. package/src/providers/codex-adapter.ts +3 -6
  163. package/src/providers/codex-models.ts +15 -1
  164. package/src/providers/dsh-adapter.ts +248 -0
  165. package/src/providers/index.ts +5 -1
  166. package/src/providers/modelsdev-reasoning.json +50 -0
  167. package/src/providers/pi-mono-extension.ts +2 -5
  168. package/src/rbac/legacy-policy.ts +15 -1
  169. package/src/rbac/types.ts +2 -0
  170. package/src/server.ts +7 -1
  171. package/src/slack/ack.ts +43 -8
  172. package/src/slack/app.ts +32 -10
  173. package/src/slack/config.ts +29 -0
  174. package/src/slack/handlers.ts +7 -1
  175. package/src/slack/render-v2.ts +186 -17
  176. package/src/slack/responses.ts +1 -3
  177. package/src/slack/task-output.ts +66 -8
  178. package/src/slack/thread-buffer.ts +27 -3
  179. package/src/telemetry.ts +2 -3
  180. package/src/tests/agent-fs-provision-seeder.test.ts +56 -2
  181. package/src/tests/agents-harness-provider.test.ts +19 -0
  182. package/src/tests/agents-list-model-display.test.ts +60 -1
  183. package/src/tests/base-prompt.test.ts +25 -0
  184. package/src/tests/claude-managed-adapter.test.ts +6 -0
  185. package/src/tests/codex-gpt6-release.test.ts +97 -0
  186. package/src/tests/codex-steering-hook.test.ts +2 -2
  187. package/src/tests/config-api-only-keys.test.ts +9 -0
  188. package/src/tests/context-window.test.ts +1 -0
  189. package/src/tests/db-task-read-contract.test.ts +9 -0
  190. package/src/tests/db-task-write-contract.test.ts +9 -0
  191. package/src/tests/defer-task.test.ts +115 -16
  192. package/src/tests/dsh-adapter.test.ts +276 -0
  193. package/src/tests/e2e-nightly-report.test.ts +3 -3
  194. package/src/tests/e2e-redact.test.ts +2 -0
  195. package/src/tests/env-flag.test.ts +6 -0
  196. package/src/tests/extension-agent-visibility.test.ts +474 -0
  197. package/src/tests/extensions-db.test.ts +41 -0
  198. package/src/tests/extensions-http.test.ts +148 -4
  199. package/src/tests/extensions-lifecycle.test.ts +21 -1
  200. package/src/tests/extensions-mcp-tools.test.ts +9 -5
  201. package/src/tests/fetch-resolved-env.test.ts +43 -0
  202. package/src/tests/internal-ai/complete-structured.test.ts +32 -9
  203. package/src/tests/internal-ai/credentials.test.ts +4 -4
  204. package/src/tests/internal-ai/models.test.ts +20 -0
  205. package/src/tests/memory-rate-tool.test.ts +7 -10
  206. package/src/tests/memory-rater-defaults.test.ts +23 -0
  207. package/src/tests/memory-rater-e2e.test.ts +2 -3
  208. package/src/tests/migration-046-budgets.test.ts +2 -0
  209. package/src/tests/model-control.test.ts +2 -2
  210. package/src/tests/onboard-compose.test.ts +14 -0
  211. package/src/tests/onboard-env.test.ts +17 -0
  212. package/src/tests/onboard-manifest.test.ts +12 -0
  213. package/src/tests/opus-5-5-registry.test.ts +48 -0
  214. package/src/tests/pricing-refresh.test.ts +1 -1
  215. package/src/tests/pricing-routes.test.ts +15 -3
  216. package/src/tests/provider-registration.test.ts +5 -2
  217. package/src/tests/rbac-admission-e2e.test.ts +54 -0
  218. package/src/tests/rbac-e2e-helpers.ts +2 -0
  219. package/src/tests/rbac-engine.test.ts +32 -0
  220. package/src/tests/rbac-wire-e2e.test.ts +33 -0
  221. package/src/tests/reasoning-effort.test.ts +8 -0
  222. package/src/tests/reload-config.test.ts +33 -0
  223. package/src/tests/script-connections.test.ts +3 -0
  224. package/src/tests/session-costs-model-key-normalize.test.ts +1 -0
  225. package/src/tests/slack-config.test.ts +136 -0
  226. package/src/tests/slack-mode-lifecycle.test.ts +69 -0
  227. package/src/tests/slack-render-v2.test.ts +446 -16
  228. package/src/tests/slack-steering.test.ts +69 -1
  229. package/src/tests/slack-task-output.test.ts +33 -12
  230. package/src/tests/status.test.ts +22 -2
  231. package/src/tests/steering-core.test.ts +35 -0
  232. package/src/tests/steering-delivery.test.ts +39 -0
  233. package/src/tests/steering-transport.test.ts +2 -2
  234. package/src/tests/task-tool-preload-mcp.test.ts +3 -1
  235. package/src/tests/telemetry-init.test.ts +18 -0
  236. package/src/tests/workflow-live-recovery.test.ts +126 -0
  237. package/src/tests/workflow-llm.test.ts +3 -3
  238. package/src/tools/defer-task.ts +64 -26
  239. package/src/tools/extension-common.ts +4 -0
  240. package/src/tools/extension-install.ts +1 -1
  241. package/src/tools/extension-list.ts +4 -3
  242. package/src/tools/join-swarm.ts +1 -1
  243. package/src/tools/schedules/create-schedule.ts +11 -1
  244. package/src/tools/schedules/patch-schedule.ts +5 -0
  245. package/src/tools/schedules/update-schedule.ts +5 -0
  246. package/src/tools/send-task.ts +6 -0
  247. package/src/tools/utils.ts +1 -1
  248. package/src/types.ts +30 -8
  249. package/src/utils/context-window.ts +1 -0
  250. package/src/utils/credentials.ts +8 -0
  251. package/src/utils/internal-ai/complete-structured.ts +8 -0
  252. package/src/utils/internal-ai/models.ts +5 -5
  253. package/src/utils/memory-raters.ts +3 -0
  254. package/src/workflows/engine.ts +28 -0
  255. package/src/workflows/recovery.ts +7 -4
  256. package/templates/schedules/daily-status-report/content.md +25 -12
  257. package/templates/schedules/daily-workflow-health-audit/content.md +1 -1
  258. package/templates/skills/swarm-extensions/content.md +9 -5
  259. package/dist/cli-4wppfkcm.js +0 -16384
  260. package/dist/cli-55qrx3q8.js +0 -6041
  261. package/dist/cli-cg4vnyh4.js +0 -305
  262. package/dist/cli-jyetr64j.js +0 -52
  263. package/dist/cli-pp9ax9pa.js +0 -520
  264. package/dist/cli-qa66qaf0.js +0 -6076
  265. package/dist/cli-qghpvca2.js +0 -590
  266. package/dist/cli-rembwgt8.js +0 -861
  267. package/dist/cli-tcvj7j2r.js +0 -1971
  268. package/dist/cli-vfcth11k.js +0 -36
  269. package/dist/cli-w1d1bgkk.js +0 -1422
  270. package/dist/cli-y6x0gqtg.js +0 -5977
  271. package/dist/es5-tj3tn4jj.js +0 -844
  272. package/dist/index-1kq5hw2p.js +0 -467
  273. package/dist/index-1p8wdstt.js +0 -7
  274. package/dist/index-8fdjzb2f.js +0 -100
  275. package/dist/index-bxmwzbgw.js +0 -365
  276. package/dist/index-nzerxd5z.js +0 -7
  277. package/dist/index-pyymnzat.js +0 -1168
  278. package/dist/index-qv6atbab.js +0 -619
  279. package/dist/index-rja32qa7.js +0 -801
  280. package/dist/index-tzg5srfp.js +0 -211
  281. package/dist/index-vhncw983.js +0 -90
  282. package/dist/index-xk036zsk.js +0 -859
  283. package/dist/index-zyazbzcb.js +0 -6
  284. package/dist/{claude-managed-setup-48dwg9bv.js → claude-managed-setup-f5pmsyrp.js} +3 -3
@@ -147175,6 +147175,33 @@
147175
147175
  "name": "Anthropic",
147176
147176
  "doc": "https://docs.anthropic.com/en/docs/about-claude/models",
147177
147177
  "models": {
147178
+ "claude-opus-5-5": {
147179
+ "id": "claude-opus-5-5",
147180
+ "name": "Claude Opus 5.5",
147181
+ "reasoning": true,
147182
+ "reasoning_options": [
147183
+ {
147184
+ "type": "effort",
147185
+ "values": [
147186
+ "low",
147187
+ "medium",
147188
+ "high",
147189
+ "xhigh",
147190
+ "max"
147191
+ ]
147192
+ }
147193
+ ],
147194
+ "cost": {
147195
+ "input": 4,
147196
+ "output": 20,
147197
+ "cache_read": 0.2,
147198
+ "cache_write": 5
147199
+ },
147200
+ "limit": {
147201
+ "context": 1000000,
147202
+ "output": 128000
147203
+ }
147204
+ },
147178
147205
  "claude-sonnet-4-6": {
147179
147206
  "id": "claude-sonnet-4-6",
147180
147207
  "name": "Claude Sonnet 4.6",
@@ -285334,6 +285361,192 @@
285334
285361
  "output": 40,
285335
285362
  "cache_read": 2.5
285336
285363
  }
285364
+ },
285365
+ "gpt-6-sol": {
285366
+ "id": "gpt-6-sol",
285367
+ "name": "GPT-6 Sol",
285368
+ "description": "OpenAI model for complex coding and agentic workflows",
285369
+ "family": "gpt-sol",
285370
+ "attachment": true,
285371
+ "reasoning": true,
285372
+ "reasoning_options": [
285373
+ {
285374
+ "type": "effort",
285375
+ "values": [
285376
+ "none",
285377
+ "low",
285378
+ "medium",
285379
+ "high",
285380
+ "xhigh",
285381
+ "max"
285382
+ ]
285383
+ }
285384
+ ],
285385
+ "tool_call": true,
285386
+ "structured_output": true,
285387
+ "temperature": false,
285388
+ "knowledge": "2026-04-20",
285389
+ "release_date": "2026-09-22",
285390
+ "last_updated": "2026-09-22",
285391
+ "modalities": {
285392
+ "input": [
285393
+ "text",
285394
+ "image",
285395
+ "pdf"
285396
+ ],
285397
+ "output": [
285398
+ "text"
285399
+ ]
285400
+ },
285401
+ "open_weights": false,
285402
+ "limit": {
285403
+ "context": 1050000,
285404
+ "input": 922000,
285405
+ "output": 128000
285406
+ },
285407
+ "experimental": {
285408
+ "modes": {
285409
+ "fast": {
285410
+ "cost": {
285411
+ "input": 4,
285412
+ "output": 20,
285413
+ "cache_read": 0.4,
285414
+ "cache_write": 5
285415
+ },
285416
+ "provider": {
285417
+ "body": {
285418
+ "service_tier": "priority"
285419
+ }
285420
+ }
285421
+ },
285422
+ "pro": {
285423
+ "provider": {
285424
+ "body": {
285425
+ "reasoning": {
285426
+ "mode": "pro"
285427
+ }
285428
+ }
285429
+ }
285430
+ }
285431
+ }
285432
+ },
285433
+ "cost": {
285434
+ "input": 2,
285435
+ "output": 10,
285436
+ "cache_read": 0.2,
285437
+ "cache_write": 2.5,
285438
+ "tiers": [
285439
+ {
285440
+ "input": 4,
285441
+ "output": 15,
285442
+ "cache_read": 0.4,
285443
+ "cache_write": 5,
285444
+ "tier": {
285445
+ "type": "context",
285446
+ "size": 272000
285447
+ }
285448
+ }
285449
+ ],
285450
+ "context_over_200k": {
285451
+ "input": 4,
285452
+ "output": 15,
285453
+ "cache_read": 0.4,
285454
+ "cache_write": 5
285455
+ }
285456
+ }
285457
+ },
285458
+ "gpt-6-luna": {
285459
+ "id": "gpt-6-luna",
285460
+ "name": "GPT-6 Luna",
285461
+ "description": "OpenAI's most efficient model for focused, high-volume tasks",
285462
+ "family": "gpt-luna",
285463
+ "attachment": true,
285464
+ "reasoning": true,
285465
+ "reasoning_options": [
285466
+ {
285467
+ "type": "effort",
285468
+ "values": [
285469
+ "none",
285470
+ "low",
285471
+ "medium",
285472
+ "high",
285473
+ "xhigh",
285474
+ "max"
285475
+ ]
285476
+ }
285477
+ ],
285478
+ "tool_call": true,
285479
+ "structured_output": true,
285480
+ "temperature": false,
285481
+ "knowledge": "2026-05-18",
285482
+ "release_date": "2026-09-22",
285483
+ "last_updated": "2026-09-22",
285484
+ "modalities": {
285485
+ "input": [
285486
+ "text",
285487
+ "image",
285488
+ "pdf"
285489
+ ],
285490
+ "output": [
285491
+ "text"
285492
+ ]
285493
+ },
285494
+ "open_weights": false,
285495
+ "limit": {
285496
+ "context": 1050000,
285497
+ "input": 922000,
285498
+ "output": 128000
285499
+ },
285500
+ "experimental": {
285501
+ "modes": {
285502
+ "fast": {
285503
+ "cost": {
285504
+ "input": 0.2,
285505
+ "output": 1,
285506
+ "cache_read": 0.02,
285507
+ "cache_write": 0.25
285508
+ },
285509
+ "provider": {
285510
+ "body": {
285511
+ "service_tier": "priority"
285512
+ }
285513
+ }
285514
+ },
285515
+ "pro": {
285516
+ "provider": {
285517
+ "body": {
285518
+ "reasoning": {
285519
+ "mode": "pro"
285520
+ }
285521
+ }
285522
+ }
285523
+ }
285524
+ }
285525
+ },
285526
+ "cost": {
285527
+ "input": 0.1,
285528
+ "output": 0.5,
285529
+ "cache_read": 0.01,
285530
+ "cache_write": 0.125,
285531
+ "tiers": [
285532
+ {
285533
+ "input": 0.2,
285534
+ "output": 0.75,
285535
+ "cache_read": 0.02,
285536
+ "cache_write": 0.25,
285537
+ "tier": {
285538
+ "type": "context",
285539
+ "size": 272000
285540
+ }
285541
+ }
285542
+ ],
285543
+ "context_over_200k": {
285544
+ "input": 0.2,
285545
+ "output": 0.75,
285546
+ "cache_read": 0.02,
285547
+ "cache_write": 0.25
285548
+ }
285549
+ }
285337
285550
  }
285338
285551
  }
285339
285552
  },
@@ -74,6 +74,8 @@ function resourceIdOf(resource: RbacCheck["resource"]): string | null {
74
74
  return resource.agentId;
75
75
  case "kv-namespace":
76
76
  return resource.namespace;
77
+ case "extension":
78
+ return resource.extensionId ?? null;
77
79
  case "app":
78
80
  return resource.appId;
79
81
  case "owned":
@@ -255,6 +255,7 @@ export async function ensureAgentFsCredentialsForAgent(agentId: string): Promise
255
255
  })
256
256
  )[0];
257
257
  if (existing?.value) {
258
+ await syncAgentFsDisplayName(apiUrl, existing.value, agent.name);
258
259
  return {
259
260
  enabled: true,
260
261
  created: false,
@@ -305,6 +306,8 @@ export async function ensureAgentFsCredentialsForAgent(agentId: string): Promise
305
306
  description: `agent-fs API key for ${email}`,
306
307
  });
307
308
 
309
+ await syncAgentFsDisplayName(apiUrl, apiKey, agent.name);
310
+
308
311
  return {
309
312
  enabled: true,
310
313
  created: true,
@@ -315,6 +318,26 @@ export async function ensureAgentFsCredentialsForAgent(agentId: string): Promise
315
318
  };
316
319
  }
317
320
 
321
+ // Reconcile on every credential request, including agents provisioned before profiles
322
+ // existed. PATCH is idempotent and uses the agent's own key, never the bootstrap key.
323
+ async function syncAgentFsDisplayName(apiUrl: string, apiKey: string, name: string): Promise<void> {
324
+ try {
325
+ await agentFsRequest(apiUrl, "/auth/profile", {
326
+ method: "PATCH",
327
+ headers: { authorization: `Bearer ${apiKey}` },
328
+ body: { displayName: name },
329
+ });
330
+ } catch (error) {
331
+ // Older servers return 404/405. Timeouts and other profile failures must
332
+ // likewise leave boot and existing credentials usable; retry next time.
333
+ console.warn(
334
+ scrubSecrets(
335
+ `[agent-fs] display name sync skipped: ${error instanceof AgentFsRequestError ? `HTTP ${error.status}` : "request failed"}`,
336
+ ),
337
+ );
338
+ }
339
+ }
340
+
318
341
  async function ensureSharedOrg(apiUrl: string, headers: Record<string, string>): Promise<string> {
319
342
  const configured =
320
343
  (await getConfigValue("AGENT_FS_DEFAULT_ORG_ID")) ||
@@ -89,13 +89,15 @@ const MANUAL_PRICING_OVERRIDES: Array<{
89
89
  const ANTHROPIC_SHORTNAME_TO_MODELSDEV: Record<string, string> = {
90
90
  fable: "claude-fable-5-1",
91
91
  mythos: "claude-mythos-5-1",
92
- opus: "claude-opus-5",
92
+ opus: "claude-opus-5-5",
93
93
  sonnet: "claude-sonnet-5",
94
94
  haiku: "claude-haiku-4-5",
95
95
  };
96
96
 
97
97
  /** Official rates used until a newly released model reaches the vendored models.dev snapshot. */
98
98
  const ANTHROPIC_SHORTNAME_PRICING_FALLBACKS: Record<string, ModelsDevCostBlock> = {
99
+ // https://platform.claude.com/docs/en/about-claude/pricing (verified 2026-09-22)
100
+ "claude-opus-5-5": { input: 4, output: 20, cache_read: 0.2, cache_write: 5 },
99
101
  "claude-fable-5-1": { input: 10, output: 50, cache_read: 0.25, cache_write: 12.5 },
100
102
  "claude-mythos-5-1": { input: 10, output: 50, cache_read: 0.25, cache_write: 12.5 },
101
103
  };
@@ -290,6 +290,7 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
290
290
  "DB_QUERY_BOUNDED_ENABLED",
291
291
  "DB_RETENTION_DRY_RUN",
292
292
  ]),
293
+ ...enumValidator("SLACK_MODE", ["socket", "http"]),
293
294
  ...enumValidator("SLACK_THREAD_STEERING", ["off", "lead", "all"]),
294
295
  ...enumValidator("SLACK_THREAD_STEERING_MODE", ["steer", "queue"]),
295
296
  ...shortcodeValidators([
@@ -23,6 +23,10 @@ const ENV_SLACK_BOT_TOKEN = " - SLACK_BOT_TOKEN=${SLACK_BOT_TOKEN}";
23
23
  // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
24
24
  const ENV_SLACK_APP_TOKEN = " - SLACK_APP_TOKEN=${SLACK_APP_TOKEN}";
25
25
  // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
26
+ const ENV_SLACK_SIGNING_SECRET = " - SLACK_SIGNING_SECRET=${SLACK_SIGNING_SECRET}";
27
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
28
+ const ENV_SLACK_MODE = " - SLACK_MODE=${SLACK_MODE:-socket}";
29
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
26
30
  const ENV_CLAUDE_OAUTH = " - CLAUDE_CODE_OAUTH_TOKEN=${CLAUDE_CODE_OAUTH_TOKEN}";
27
31
  // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
28
32
  const ENV_ANTHROPIC_KEY = " - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}";
@@ -136,14 +140,23 @@ export function generateCompose(state: OnboardState): string {
136
140
  lines.push(ENV_API_KEY);
137
141
  lines.push(ENV_INSTALL_METHOD);
138
142
  lines.push(ENV_INSTALL_PRESET);
143
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
144
+ lines.push(" - MEMORY_HYBRID_SEARCH=${MEMORY_HYBRID_SEARCH-1}");
145
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
146
+ lines.push(" - MEMORY_GRAPH_EXPANSION=${MEMORY_GRAPH_EXPANSION-1}");
147
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
148
+ lines.push(" - MEMORY_RATERS=${MEMORY_RATERS-implicit-citation,explicit-self}");
149
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
150
+ lines.push(" - MEMORY_DEMOTION_FLOOR=${MEMORY_DEMOTION_FLOOR-1.0}");
139
151
  appendProviderEnvironment(lines, state, false);
140
152
  lines.push(` - MCP_BASE_URL=http://localhost:${port}`);
141
153
  lines.push(" - APP_URL=https://app.agent-swarm.dev");
142
154
 
143
155
  if (state.integrations.slack) {
144
156
  lines.push(" - SLACK_DISABLE=false");
157
+ lines.push(ENV_SLACK_MODE);
145
158
  lines.push(ENV_SLACK_BOT_TOKEN);
146
- lines.push(ENV_SLACK_APP_TOKEN);
159
+ lines.push(state.slackMode === "http" ? ENV_SLACK_SIGNING_SECRET : ENV_SLACK_APP_TOKEN);
147
160
  }
148
161
 
149
162
  if (state.integrations.github) {
@@ -189,6 +202,8 @@ export function generateCompose(state: OnboardState): string {
189
202
  lines.push(" environment:");
190
203
  appendProviderEnvironment(lines, state, true);
191
204
  lines.push(ENV_API_KEY);
205
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
206
+ lines.push(" - MEMORY_RATERS=${MEMORY_RATERS-implicit-citation,explicit-self}");
192
207
  lines.push(` - AGENT_ID=${svc.agentId}`);
193
208
  lines.push(` - AGENT_NAME=${agentName}`);
194
209
  lines.push(` - AGENT_ROLE=${agentRole}`);
@@ -35,6 +35,14 @@ export function generateEnv(state: OnboardState): string {
35
35
  lines.push(`INSTALL_PRESET=${state.presetId}`);
36
36
  }
37
37
 
38
+ lines.push("");
39
+ lines.push("# New-deployment memory preset: retrieval, citation ratings, self-rating hints.");
40
+ lines.push("# Set MEMORY_RATERS= to disable all raters; leave SKIP_SESSION_SUMMARY unset.");
41
+ lines.push("MEMORY_HYBRID_SEARCH=1");
42
+ lines.push("MEMORY_GRAPH_EXPANSION=1");
43
+ lines.push("MEMORY_RATERS=implicit-citation,explicit-self");
44
+ lines.push("MEMORY_DEMOTION_FLOOR=1.0");
45
+
38
46
  // ── Authentication ──
39
47
  lines.push("");
40
48
  lines.push("# === Authentication ===");
@@ -92,8 +100,13 @@ export function generateEnv(state: OnboardState): string {
92
100
  if (state.integrations.slack) {
93
101
  lines.push("");
94
102
  lines.push("# Slack");
103
+ lines.push(`SLACK_MODE=${state.slackMode}`);
95
104
  lines.push(`SLACK_BOT_TOKEN=${state.slackBotToken}`);
96
- lines.push(`SLACK_APP_TOKEN=${state.slackAppToken}`);
105
+ if (state.slackMode === "http") {
106
+ lines.push(`SLACK_SIGNING_SECRET=${state.slackSigningSecret}`);
107
+ } else {
108
+ lines.push(`SLACK_APP_TOKEN=${state.slackAppToken}`);
109
+ }
97
110
  lines.push("SLACK_DISABLE=false");
98
111
  } else {
99
112
  lines.push("SLACK_DISABLE=true");
@@ -32,6 +32,7 @@ export function generateManifest(state: OnboardState): object {
32
32
  gitlab: state.integrations.gitlab,
33
33
  sentry: state.integrations.sentry,
34
34
  },
35
+ slackMode: state.slackMode,
35
36
  composePath: "./docker-compose.yml",
36
37
  envPath: "./.env",
37
38
  apiUrl: `http://localhost:${state.apiPort || 3013}`,
@@ -1,9 +1,10 @@
1
1
  import { Select, TextInput } from "@inkjs/ui";
2
2
  import { Box, Text } from "ink";
3
3
  import { useState } from "react";
4
+ import type { SlackMode } from "../../../slack/config.ts";
4
5
  import type { StepProps } from "../types.ts";
5
6
 
6
- type SubStep = "manifest_options" | "app_created" | "bot_token" | "app_token";
7
+ type SubStep = "manifest_options" | "app_created" | "mode" | "bot_token" | "credential";
7
8
 
8
9
  const MANIFEST_URL =
9
10
  "https://raw.githubusercontent.com/desplega-ai/agent-swarm/main/slack-manifest.json";
@@ -21,6 +22,7 @@ export function IntegrationSlackStep({ goToNext }: StepProps) {
21
22
  const [subStep, setSubStep] = useState<SubStep>("manifest_options");
22
23
  const [copied, setCopied] = useState(false);
23
24
  const [botToken, setBotToken] = useState("");
25
+ const [mode, setMode] = useState<SlackMode>("socket");
24
26
  const [error, setError] = useState("");
25
27
 
26
28
  return (
@@ -53,7 +55,7 @@ export function IntegrationSlackStep({ goToNext }: StepProps) {
53
55
  setCopied(false);
54
56
  setSubStep("app_created");
55
57
  } else {
56
- setSubStep("bot_token");
58
+ setSubStep("mode");
57
59
  }
58
60
  }}
59
61
  />
@@ -89,7 +91,28 @@ export function IntegrationSlackStep({ goToNext }: StepProps) {
89
91
  <Box marginTop={1}>
90
92
  <Select
91
93
  options={[{ label: "Continue — I've created the app", value: "continue" }]}
92
- onChange={() => setSubStep("bot_token")}
94
+ onChange={() => setSubStep("mode")}
95
+ />
96
+ </Box>
97
+ </Box>
98
+ )}
99
+
100
+ {subStep === "mode" && (
101
+ <Box marginTop={1} flexDirection="column">
102
+ <Text>Select the Slack transport:</Text>
103
+ <Box marginTop={1}>
104
+ <Select
105
+ options={[
106
+ { label: "Socket Mode (default)", value: "socket" },
107
+ {
108
+ label: "HTTP (configuration only; receiver not installed yet)",
109
+ value: "http",
110
+ },
111
+ ]}
112
+ onChange={(value) => {
113
+ setMode(value as SlackMode);
114
+ setSubStep("bot_token");
115
+ }}
93
116
  />
94
117
  </Box>
95
118
  </Box>
@@ -118,42 +141,59 @@ export function IntegrationSlackStep({ goToNext }: StepProps) {
118
141
  }
119
142
  setError("");
120
143
  setBotToken(trimmed);
121
- setSubStep("app_token");
144
+ setSubStep("credential");
122
145
  }}
123
146
  />
124
147
  </Box>
125
148
  </Box>
126
149
  )}
127
150
 
128
- {subStep === "app_token" && (
151
+ {subStep === "credential" && (
129
152
  <Box marginTop={1} flexDirection="column">
130
153
  <Text dimColor>Bot Token: {botToken.slice(0, 10)}...</Text>
131
154
  <Box marginTop={1} flexDirection="column">
132
- <Text>
133
- Find your App-Level Token under <Text bold>Basic Information → App-Level Tokens</Text>
134
- .
135
- </Text>
136
- <Text dimColor>Create one with connections:write scope if you don't have one.</Text>
155
+ {mode === "socket" ? (
156
+ <>
157
+ <Text>
158
+ Find your App-Level Token under{" "}
159
+ <Text bold>Basic Information → App-Level Tokens</Text>.
160
+ </Text>
161
+ <Text dimColor>Create one with connections:write scope if you don't have one.</Text>
162
+ </>
163
+ ) : (
164
+ <Text>
165
+ Find your Signing Secret under <Text bold>Basic Information → App Credentials</Text>
166
+ .
167
+ </Text>
168
+ )}
137
169
  </Box>
138
170
  <Box marginTop={1} flexDirection="column">
139
- <Text bold>App Token (SLACK_APP_TOKEN):</Text>
171
+ <Text bold>
172
+ {mode === "socket"
173
+ ? "App Token (SLACK_APP_TOKEN):"
174
+ : "Signing Secret (SLACK_SIGNING_SECRET):"}
175
+ </Text>
140
176
  <TextInput
141
- key="slack-app-token"
142
- placeholder="xapp-..."
177
+ key={`slack-${mode}-credential`}
178
+ placeholder={mode === "socket" ? "xapp-..." : "signing secret"}
143
179
  onSubmit={(value) => {
144
180
  const trimmed = value.trim();
145
181
  if (!trimmed) {
146
- setError("App token is required. Please enter it above.");
182
+ setError(
183
+ `${mode === "socket" ? "App token" : "Signing secret"} is required. Please enter it above.`,
184
+ );
147
185
  return;
148
186
  }
149
- if (!trimmed.startsWith("xapp-")) {
187
+ if (mode === "socket" && !trimmed.startsWith("xapp-")) {
150
188
  setError("App token should start with xapp- — please check and re-enter.");
151
189
  return;
152
190
  }
153
191
  setError("");
154
192
  goToNext({
155
193
  slackBotToken: botToken,
156
- slackAppToken: trimmed,
194
+ slackMode: mode,
195
+ slackAppToken: mode === "socket" ? trimmed : "",
196
+ slackSigningSecret: mode === "http" ? trimmed : "",
157
197
  });
158
198
  }}
159
199
  />
@@ -51,6 +51,11 @@ export function ReviewStep({ state, dryRun, goToNext, goToStep }: StepProps) {
51
51
  {enabledIntegrations.length > 0 ? enabledIntegrations.join(", ") : "none"}
52
52
  </Text>
53
53
  </Text>
54
+ {state.integrations.slack ? (
55
+ <Text>
56
+ Slack transport: <Text color="cyan">{state.slackMode}</Text>
57
+ </Text>
58
+ ) : null}
54
59
  <Text>
55
60
  Output directory: <Text color="cyan">{state.outputDir}</Text>
56
61
  </Text>
@@ -1,3 +1,5 @@
1
+ import type { SlackMode } from "../../slack/config";
2
+
1
3
  export type OnboardStep =
2
4
  | "welcome"
3
5
  | "deploy_type"
@@ -79,6 +81,8 @@ export interface OnboardState {
79
81
  githubName: string;
80
82
  slackBotToken: string;
81
83
  slackAppToken: string;
84
+ slackSigningSecret: string;
85
+ slackMode: SlackMode;
82
86
  gitlabToken: string;
83
87
  gitlabEmail: string;
84
88
  sentryToken: string;
@@ -192,6 +196,8 @@ export const INITIAL_STATE: OnboardState = {
192
196
  githubName: "",
193
197
  slackBotToken: "",
194
198
  slackAppToken: "",
199
+ slackSigningSecret: "",
200
+ slackMode: "socket",
195
201
  gitlabToken: "",
196
202
  gitlabEmail: "",
197
203
  sentryToken: "",
@@ -3,6 +3,7 @@ import { Select } from "@inkjs/ui";
3
3
  import { Box, Text, useApp, useInput } from "ink";
4
4
  import { useCallback, useEffect, useRef, useState } from "react";
5
5
  import pkg from "../../package.json";
6
+ import { getSlackConfiguration, isSlackConfigured } from "../slack/config.ts";
6
7
  import { getApiKey } from "../utils/api-key.ts";
7
8
  import { buildOnboardDashboardUrl } from "./onboard/dashboard-url.ts";
8
9
  import {
@@ -189,9 +190,10 @@ export function Onboard({
189
190
  }
190
191
  }
191
192
 
193
+ const slackConfig = getSlackConfiguration(process.env);
192
194
  const integrations = {
193
195
  github: !!process.env.GITHUB_TOKEN,
194
- slack: !!process.env.SLACK_BOT_TOKEN,
196
+ slack: isSlackConfigured(process.env),
195
197
  gitlab: !!process.env.GITLAB_TOKEN,
196
198
  sentry: !!process.env.SENTRY_AUTH_TOKEN,
197
199
  };
@@ -223,6 +225,8 @@ export function Onboard({
223
225
  githubName: process.env.GITHUB_NAME || "",
224
226
  slackBotToken: process.env.SLACK_BOT_TOKEN || "",
225
227
  slackAppToken: process.env.SLACK_APP_TOKEN || "",
228
+ slackSigningSecret: process.env.SLACK_SIGNING_SECRET || "",
229
+ slackMode: slackConfig.mode ?? "socket",
226
230
  gitlabToken: process.env.GITLAB_TOKEN || "",
227
231
  gitlabEmail: process.env.GITLAB_EMAIL || "",
228
232
  sentryToken: process.env.SENTRY_AUTH_TOKEN || "",
@@ -22,6 +22,7 @@ import { checkClaudeCredentials } from "../providers/claude-adapter";
22
22
  import { checkClaudeManagedCredentials } from "../providers/claude-managed-adapter";
23
23
  import { checkCodexCredentials } from "../providers/codex-adapter";
24
24
  import { checkDevinCredentials } from "../providers/devin-adapter";
25
+ import { checkDshCredentials } from "../providers/dsh-adapter";
25
26
  import { checkOpencodeCredentials } from "../providers/opencode-adapter";
26
27
  import type { CredCheckOptions, CredStatus } from "../providers/types";
27
28
  import type {
@@ -41,7 +42,8 @@ export type SupportedProvider =
41
42
  | "devin"
42
43
  | "opencode"
43
44
  | "pi"
44
- | "acp";
45
+ | "acp"
46
+ | "dsh";
45
47
 
46
48
  /**
47
49
  * True when the pi harness authenticates against Bedrock rather than a provider
@@ -105,6 +107,7 @@ export const REQUIRED_CRED_VARS_BY_PROVIDER: Record<SupportedProvider, readonly
105
107
  pi: ["ANTHROPIC_API_KEY", "OPENROUTER_API_KEY", "OPENAI_API_KEY"],
106
108
  // The ACP target process owns its own auth, so the swarm requires nothing.
107
109
  acp: [],
110
+ dsh: ["DEEPSEEK_API_KEY", "OPENROUTER_API_KEY"],
108
111
  };
109
112
 
110
113
  type CredentialChecker = (
@@ -114,6 +117,7 @@ type CredentialChecker = (
114
117
 
115
118
  /** The handlers used by the credential-readiness dispatcher. */
116
119
  export const CREDENTIAL_PROVIDER_CHECKERS: Record<SupportedProvider, CredentialChecker> = {
120
+ dsh: (env) => checkDshCredentials(env),
117
121
  claude: (env) => checkClaudeCredentials(env),
118
122
  "claude-managed": (env) => checkClaudeManagedCredentials(env),
119
123
  codex: (env, opts) => checkCodexCredentials(env, opts),
@@ -416,12 +420,20 @@ export async function validateProviderCredentials(provider: string): Promise<Liv
416
420
  latency_ms: r.latency_ms,
417
421
  };
418
422
  }
423
+ case "dsh":
424
+ return checkDshCredentials(env).ready
425
+ ? presenceCheckOk()
426
+ : {
427
+ ok: false,
428
+ error: "Set DEEPSEEK_API_KEY or OPENROUTER_API_KEY for dsh.",
429
+ latency_ms: Date.now() - startedAt,
430
+ };
419
431
  case "acp":
420
432
  return presenceCheckOk();
421
433
  default:
422
434
  return {
423
435
  ok: false,
424
- error: `Unknown provider "${provider}". Supported: claude, claude-managed, codex, devin, opencode, pi, acp.`,
436
+ error: `Unknown provider "${provider}". Supported: claude, claude-managed, codex, devin, opencode, pi, acp, dsh.`,
425
437
  latency_ms: Date.now() - startedAt,
426
438
  };
427
439
  }