@desplega.ai/agent-swarm 1.152.2 → 1.153.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 (224) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-pfeje2v5.js → acp-adapter-ahmjxhek.js} +4 -4
  3. package/dist/{actions-0sttc7f5.js → actions-jzrfpkmn.js} +30 -26
  4. package/dist/{anthropic-messages-2y8nktar.js → anthropic-messages-9vqsbznt.js} +112 -84
  5. package/dist/{app-p8teva95.js → app-03na2vwb.js} +9 -6
  6. package/dist/{assistant-r45jnsrt.js → assistant-hfkxvhgt.js} +31 -27
  7. package/dist/{azure-openai-responses-f38x2avq.js → azure-openai-responses-04qwdwfq.js} +27 -13
  8. package/dist/{boot-reembed-je26h5y7.js → boot-reembed-c98xrad3.js} +8 -6
  9. package/dist/{boot-reembed-1qmybsd4.js → boot-reembed-zt3qm9xn.js} +9 -7
  10. package/dist/{boot-scrub-logs-gte3h1mm.js → boot-scrub-logs-jcqd8ksj.js} +6 -4
  11. package/dist/{claude-adapter-csc1mzka.js → claude-adapter-mgryg8g3.js} +17 -15
  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-jjf4zss1.js} +17 -15
  14. package/dist/{cli-r2fpe7cx.js → cli-00w2c66p.js} +61 -55
  15. package/dist/{cli-fm4ytsdk.js → cli-0d9nbqxf.js} +1 -1
  16. package/dist/cli-0x5qzvkg.js +4279 -0
  17. package/dist/{cli-d3p82erb.js → cli-18amys3y.js} +9 -9
  18. package/dist/{cli-wbyk465z.js → cli-1hwnb4hc.js} +1 -1
  19. package/dist/{cli-xw7vak96.js → cli-3bcmp015.js} +5 -5
  20. package/dist/cli-3er6gcsn.js +1849 -0
  21. package/dist/{cli-c4eeb5q2.js → cli-5b6b62tz.js} +1 -1
  22. package/dist/{cli-4ahpr4sw.js → cli-5mbmvxnn.js} +5 -5
  23. package/dist/{cli-xy1cchaf.js → cli-5taqtpze.js} +235 -8
  24. package/dist/{cli-fmy65jdn.js → cli-6ks9xf1n.js} +7 -5
  25. package/dist/cli-7g9s78jf.js +2827 -0
  26. package/dist/{cli-jew3jda5.js → cli-7pnz2v6s.js} +2 -2
  27. package/dist/{cli-r84ctdxn.js → cli-83wkg402.js} +2 -2
  28. package/dist/{cli-jvy9qgjs.js → cli-a9scg8sv.js} +4 -4
  29. package/dist/{cli-4yc5d8fk.js → cli-avkd6mqv.js} +50 -0
  30. package/dist/{cli-ht5rs63n.js → cli-b2g6mzjc.js} +15 -6
  31. package/dist/{cli-jbmc0r7r.js → cli-bw0dfwkr.js} +1 -1
  32. package/dist/{cli-8wrympd7.js → cli-bzr0ftht.js} +26 -7
  33. package/dist/{cli-wpv5rgg2.js → cli-cdq08v3r.js} +2 -2
  34. package/dist/cli-cgj4hc12.js +18902 -0
  35. package/dist/cli-d6hk10xx.js +14075 -0
  36. package/dist/{cli-zvgj5zg8.js → cli-djvxhnc4.js} +31 -3324
  37. package/dist/{cli-s25avqg9.js → cli-e781c6f9.js} +1 -0
  38. package/dist/{cli-3bpzj8me.js → cli-eazstkad.js} +2 -2
  39. package/dist/{cli-s2qjdd6z.js → cli-eetrvv91.js} +1 -1
  40. package/dist/cli-h38x0qhg.js +6912 -0
  41. package/dist/{cli-9xvdm3bx.js → cli-h60qfasa.js} +742 -278
  42. package/dist/{pi-mono-adapter-jcqt71cg.js → cli-ja7mrygn.js} +67343 -101083
  43. package/dist/{cli-j8dggbcr.js → cli-k0g1sjzm.js} +23 -31
  44. package/dist/{cli-gphgnvpf.js → cli-m04pt18h.js} +2 -2
  45. package/dist/{cli-rgvp6r2x.js → cli-mcnhgnn1.js} +193 -4
  46. package/dist/{cli-j4nv2wqy.js → cli-mzgyhxbe.js} +10 -4
  47. package/dist/{cli-qn042eh7.js → cli-n0q9b7j4.js} +46 -1870
  48. package/dist/cli-n7h1kqpf.js +29 -0
  49. package/dist/{cli-ckz5t2hb.js → cli-nq0kgyxe.js} +5 -5
  50. package/dist/{cli-z3wkng35.js → cli-qrqhc31j.js} +151 -125
  51. package/dist/{cli-56h18ng2.js → cli-r8tdds6s.js} +1 -1
  52. package/dist/{cli-ch38q5z4.js → cli-rj7de4b2.js} +6788 -2541
  53. package/dist/{cli-qd65dvr6.js → cli-s5s1f2yn.js} +56 -40
  54. package/dist/{cli-kj76p1ez.js → cli-scwq51gn.js} +13 -7
  55. package/dist/{cli-2nnd56zt.js → cli-tdh4hjr2.js} +3 -2
  56. package/dist/{cli-c2mk1kgf.js → cli-v4en75c5.js} +8 -1
  57. package/dist/{cli-b9dd0h3k.js → cli-vw03hg5t.js} +3 -2
  58. package/dist/{cli-zvkq5csn.js → cli-ybpp1srm.js} +6 -6
  59. package/dist/cli-yn0a417a.js +4069 -0
  60. package/dist/{cli-gpqcs935.js → cli-ysc1kbet.js} +2 -2
  61. package/dist/{cli-zfzznn7c.js → cli-ytxs7mn1.js} +26 -2
  62. package/dist/cli-zcsyfw2z.js +3335 -0
  63. package/dist/{cli-4j8k1m4w.js → cli-zt1227k1.js} +1162 -192
  64. package/dist/cli-zy5w9gpt.js +230 -0
  65. package/dist/cli.js +26 -34
  66. package/dist/{codex-adapter-fxmpsabw.js → codex-adapter-8548daap.js} +12 -11
  67. package/dist/{codex-session-runner-rr1e47ea.js → codex-session-runner-2dad8p4x.js} +12 -11
  68. package/dist/{commands-0f5rxz51.js → commands-355dbpa8.js} +6 -4
  69. package/dist/{db-r3jxf3wy.js → db-4jjvwz1s.js} +6 -4
  70. package/dist/{dispatcher-06vph6q4.js → dispatcher-ca590nkz.js} +29 -25
  71. package/dist/dsh-adapter-rgvj6ykp.js +19 -0
  72. package/dist/{e2b-413b8t4v.js → e2b-93x1k0j5.js} +6 -7
  73. package/dist/{google-generative-ai-ndjmj5fa.js → google-generative-ai-xtw7tggr.js} +33 -73
  74. package/dist/{google-vertex-fr665tqs.js → google-vertex-zdqpms6n.js} +38 -68
  75. package/dist/{handlers-0hgtc910.js → handlers-2y6dqpvf.js} +32 -28
  76. package/dist/{hook-9kvrv1er.js → hook-0s8knepr.js} +11 -9
  77. package/dist/{hook-fbfhkat3.js → hook-k0gec254.js} +12 -10
  78. package/dist/{http-xbyx8k5j.js → http-jp2nb4zw.js} +300 -237
  79. package/dist/{index-tfsdxyv6.js → index-0wzg3sp3.js} +39 -24
  80. package/dist/{index-rnyahfn5.js → index-3mq6ce93.js} +29 -25
  81. package/dist/{index-jsw3aynb.js → index-42s7eezq.js} +29 -25
  82. package/dist/{cli-pdz9qde4.js → index-9ch1n761.js} +10 -11
  83. package/dist/{index-gpfn1741.js → index-b56xkbc7.js} +8 -6
  84. package/dist/{index-66xz5e9j.js → index-h5gs261z.js} +521 -9
  85. package/dist/{index-2sp0384z.js → index-kkeftv5h.js} +738 -21
  86. package/dist/{index-sgk50mbg.js → index-s37dbevy.js} +30 -26
  87. package/dist/index-w097eg0x.js +5 -0
  88. package/dist/jiti-loader-b4837mtm.js +34 -0
  89. package/dist/jiti-static-loader-q2g5ds0y.js +31267 -0
  90. package/dist/{keepalive-s3xpr7sw.js → keepalive-9pfw7t02.js} +8 -6
  91. package/dist/{lead-rq4n5r16.js → lead-7vcmcdq4.js} +44 -39
  92. package/dist/{maintenance-f0atj1ab.js → maintenance-x277jbpd.js} +9 -7
  93. package/dist/{mistral-conversations-qhr84ph3.js → mistral-conversations-zx0kn554.js} +24 -18
  94. package/dist/{node-x1g4v0pq.js → node-5qtycf6a.js} +16 -11
  95. package/dist/{oauth-refresh-sweep-q0t3bxre.js → oauth-refresh-sweep-5fwa7th2.js} +7 -5
  96. package/dist/{onboard-br5j1kch.js → onboard-17sv0f51.js} +103 -35
  97. package/dist/{openai-codex-responses-wy6a43wd.js → openai-codex-responses-4vjqzvjp.js} +33 -27
  98. package/dist/{openai-completions-32rdwmze.js → openai-completions-pxsmym7g.js} +52 -64
  99. package/dist/{openai-responses-6xwf7bzg.js → openai-responses-tmn0rqp0.js} +23 -24
  100. package/dist/{opencode-adapter-28axqa09.js → opencode-adapter-qbmv4tpy.js} +6 -6
  101. package/dist/{otel-impl-vdqge2nt.js → otel-impl-srjy4be4.js} +4 -4
  102. package/dist/{pi-messages-b1mbr6gp.js → pi-messages-txpjj39q.js} +3 -3
  103. package/dist/pi-mono-adapter-946a0sdd.js +1316 -0
  104. package/dist/{pricing-refresh-hb3691fd.js → pricing-refresh-vetcm563.js} +8 -6
  105. package/dist/{rbac-roles-jh280k9g.js → rbac-roles-cfzgr6r1.js} +8 -6
  106. package/dist/{rbac-roles-t78xt39b.js → rbac-roles-cmxaddmy.js} +7 -5
  107. package/dist/{render-v2-7p8r2ymg.js → render-v2-f9hzff72.js} +9 -6
  108. package/dist/{seed-pricing-hf889enh.js → seed-pricing-jggk6rsy.js} +7 -5
  109. package/dist/{setup-w6mb03jv.js → setup-8mfceb9t.js} +4 -5
  110. package/dist/virtual-modules-ax661xp0.js +54 -0
  111. package/dist/{work-objects-nt8gy1kj.js → work-objects-vdsdcczj.js} +32 -28
  112. package/dist/{worker-dwy617t0.js → worker-cd0nhyv1.js} +44 -39
  113. package/openapi.json +36 -14
  114. package/package.json +6 -6
  115. package/src/be/automation-preflight.ts +6 -4
  116. package/src/be/extensions/db.ts +35 -4
  117. package/src/be/models-catalog.ts +2 -0
  118. package/src/be/modelsdev-cache.json +213 -0
  119. package/src/be/rbac-audit.ts +2 -0
  120. package/src/be/seed-pricing.ts +3 -1
  121. package/src/be/swarm-config-guard.ts +1 -0
  122. package/src/commands/onboard/compose-generator.ts +6 -1
  123. package/src/commands/onboard/env-generator.ts +6 -1
  124. package/src/commands/onboard/manifest.ts +1 -0
  125. package/src/commands/onboard/steps/integration-slack.tsx +56 -16
  126. package/src/commands/onboard/steps/review.tsx +5 -0
  127. package/src/commands/onboard/types.ts +6 -0
  128. package/src/commands/onboard.tsx +5 -1
  129. package/src/commands/provider-credentials.ts +14 -2
  130. package/src/extensions/lifecycle.ts +15 -21
  131. package/src/http/agents.ts +2 -2
  132. package/src/http/config.ts +1 -1
  133. package/src/http/core.ts +5 -3
  134. package/src/http/extensions.ts +108 -34
  135. package/src/http/status.ts +22 -10
  136. package/src/prompts/base-prompt.ts +15 -7
  137. package/src/providers/claude-managed-models.ts +8 -0
  138. package/src/providers/codex-models.ts +15 -1
  139. package/src/providers/dsh-adapter.ts +248 -0
  140. package/src/providers/index.ts +5 -1
  141. package/src/providers/modelsdev-reasoning.json +50 -0
  142. package/src/rbac/legacy-policy.ts +15 -1
  143. package/src/rbac/types.ts +2 -0
  144. package/src/server.ts +7 -1
  145. package/src/slack/app.ts +32 -10
  146. package/src/slack/config.ts +29 -0
  147. package/src/telemetry.ts +2 -3
  148. package/src/tests/agents-harness-provider.test.ts +19 -0
  149. package/src/tests/agents-list-model-display.test.ts +60 -1
  150. package/src/tests/base-prompt.test.ts +25 -0
  151. package/src/tests/claude-managed-adapter.test.ts +6 -0
  152. package/src/tests/codex-gpt6-release.test.ts +97 -0
  153. package/src/tests/config-api-only-keys.test.ts +9 -0
  154. package/src/tests/context-window.test.ts +1 -0
  155. package/src/tests/dsh-adapter.test.ts +276 -0
  156. package/src/tests/e2e-nightly-report.test.ts +3 -3
  157. package/src/tests/e2e-redact.test.ts +2 -0
  158. package/src/tests/env-flag.test.ts +6 -0
  159. package/src/tests/extensions-db.test.ts +41 -0
  160. package/src/tests/extensions-http.test.ts +148 -4
  161. package/src/tests/extensions-lifecycle.test.ts +18 -0
  162. package/src/tests/extensions-mcp-tools.test.ts +9 -5
  163. package/src/tests/internal-ai/complete-structured.test.ts +32 -9
  164. package/src/tests/internal-ai/credentials.test.ts +4 -4
  165. package/src/tests/internal-ai/models.test.ts +20 -0
  166. package/src/tests/migration-046-budgets.test.ts +2 -0
  167. package/src/tests/model-control.test.ts +2 -2
  168. package/src/tests/onboard-compose.test.ts +14 -0
  169. package/src/tests/onboard-env.test.ts +17 -0
  170. package/src/tests/onboard-manifest.test.ts +12 -0
  171. package/src/tests/opus-5-5-registry.test.ts +48 -0
  172. package/src/tests/pricing-refresh.test.ts +1 -1
  173. package/src/tests/pricing-routes.test.ts +15 -3
  174. package/src/tests/provider-registration.test.ts +5 -2
  175. package/src/tests/rbac-admission-e2e.test.ts +54 -0
  176. package/src/tests/rbac-e2e-helpers.ts +2 -0
  177. package/src/tests/rbac-engine.test.ts +32 -0
  178. package/src/tests/rbac-wire-e2e.test.ts +33 -0
  179. package/src/tests/reasoning-effort.test.ts +8 -0
  180. package/src/tests/reload-config.test.ts +33 -0
  181. package/src/tests/session-costs-model-key-normalize.test.ts +1 -0
  182. package/src/tests/slack-config.test.ts +136 -0
  183. package/src/tests/slack-mode-lifecycle.test.ts +69 -0
  184. package/src/tests/status.test.ts +22 -2
  185. package/src/tests/task-tool-preload-mcp.test.ts +3 -1
  186. package/src/tests/telemetry-init.test.ts +18 -0
  187. package/src/tests/workflow-llm.test.ts +3 -3
  188. package/src/tools/extension-common.ts +4 -0
  189. package/src/tools/extension-install.ts +1 -1
  190. package/src/tools/extension-list.ts +4 -3
  191. package/src/types.ts +17 -8
  192. package/src/utils/context-window.ts +1 -0
  193. package/src/utils/credentials.ts +8 -0
  194. package/src/utils/internal-ai/complete-structured.ts +8 -0
  195. package/src/utils/internal-ai/models.ts +5 -5
  196. package/templates/schedules/daily-status-report/content.md +25 -12
  197. package/templates/schedules/daily-workflow-health-audit/content.md +1 -1
  198. package/templates/skills/swarm-extensions/content.md +9 -5
  199. package/dist/cli-4wppfkcm.js +0 -16384
  200. package/dist/cli-55qrx3q8.js +0 -6041
  201. package/dist/cli-cg4vnyh4.js +0 -305
  202. package/dist/cli-jyetr64j.js +0 -52
  203. package/dist/cli-pp9ax9pa.js +0 -520
  204. package/dist/cli-qa66qaf0.js +0 -6076
  205. package/dist/cli-qghpvca2.js +0 -590
  206. package/dist/cli-rembwgt8.js +0 -861
  207. package/dist/cli-tcvj7j2r.js +0 -1971
  208. package/dist/cli-vfcth11k.js +0 -36
  209. package/dist/cli-w1d1bgkk.js +0 -1422
  210. package/dist/cli-y6x0gqtg.js +0 -5977
  211. package/dist/es5-tj3tn4jj.js +0 -844
  212. package/dist/index-1kq5hw2p.js +0 -467
  213. package/dist/index-1p8wdstt.js +0 -7
  214. package/dist/index-8fdjzb2f.js +0 -100
  215. package/dist/index-bxmwzbgw.js +0 -365
  216. package/dist/index-nzerxd5z.js +0 -7
  217. package/dist/index-pyymnzat.js +0 -1168
  218. package/dist/index-qv6atbab.js +0 -619
  219. package/dist/index-rja32qa7.js +0 -801
  220. package/dist/index-tzg5srfp.js +0 -211
  221. package/dist/index-vhncw983.js +0 -90
  222. package/dist/index-xk036zsk.js +0 -859
  223. package/dist/index-zyazbzcb.js +0 -6
  224. package/dist/{claude-managed-setup-48dwg9bv.js → claude-managed-setup-f5pmsyrp.js} +3 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@desplega.ai/agent-swarm",
3
- "version": "1.152.2",
3
+ "version": "1.153.0",
4
4
  "description": "agent-swarm.dev — an open-source operating system for AI work: a lead agent breaks goals into tasks, routes them to specialized workers such as Claude Code or Codex, runs each worker in an isolated container, and preserves shared memory, tools, schedules, and review gates so delegated work compounds across sessions.",
5
5
  "keywords": [
6
6
  "agent-swarm.dev",
@@ -188,14 +188,14 @@
188
188
  "@aws-sdk/client-bedrock": "3.1048.0",
189
189
  "@desplega.ai/business-use": "^0.4.2",
190
190
  "@desplega.ai/localtunnel": "^2.2.0",
191
- "@earendil-works/pi-agent-core": "^0.85.1",
192
- "@earendil-works/pi-ai": "^0.85.1",
193
- "@earendil-works/pi-coding-agent": "^0.85.1",
191
+ "@earendil-works/pi-agent-core": "^0.87.1",
192
+ "@earendil-works/pi-ai": "^0.87.1",
193
+ "@earendil-works/pi-coding-agent": "^0.87.1",
194
194
  "@inkjs/ui": "^2.0.0",
195
195
  "@linear/sdk": "^77.0.0",
196
196
  "@modelcontextprotocol/sdk": "1.29.0",
197
- "@openai/codex": "0.154.0",
198
- "@opencode-ai/sdk": "^1.18.31",
197
+ "@openai/codex": "0.156.1",
198
+ "@opencode-ai/sdk": "^1.18.32",
199
199
  "@openfort/openfort-node": "^0.9.1",
200
200
  "@opentelemetry/api": "^1.9.1",
201
201
  "@opentelemetry/exporter-metrics-otlp-http": "^0.218.0",
@@ -1,4 +1,5 @@
1
1
  import type { AutomationIntegrationId, ScheduledTask, Workflow } from "@/types";
2
+ import { getSlackConfiguration, isSlackConfigured } from "../slack/config";
2
3
  import { getDbClient } from "./db";
3
4
  import { getOAuthApp, getOAuthTokens } from "./db-queries/oauth";
4
5
 
@@ -281,11 +282,12 @@ export async function getAutomationSetupStates(): Promise<AutomationSetupStates>
281
282
  present(process.env.GSC_SERVICE_ACCOUNT_JSON);
282
283
 
283
284
  return {
285
+ // Credential presence is configuration evidence, not proof that inbound
286
+ // Slack traffic has been observed successfully.
287
+ // HTTP credentials alone cannot run Slack automations before its receiver lands.
284
288
  slack:
285
- enabled(process.env.SLACK_DISABLE) &&
286
- present(process.env.SLACK_BOT_TOKEN) &&
287
- present(process.env.SLACK_APP_TOKEN)
288
- ? "verified"
289
+ getSlackConfiguration().mode === "socket" && isSlackConfigured()
290
+ ? "configured"
289
291
  : "unverified",
290
292
  github:
291
293
  present(process.env.GITHUB_WEBHOOK_SECRET) &&
@@ -20,8 +20,12 @@ export type InstallExtensionArgs = {
20
20
  createdBy?: string | null;
21
21
  activate?: boolean;
22
22
  changeReason?: string | null;
23
+ /** HTTP worker upserts must not claim another creator's name. */
24
+ ownerOnly?: string;
23
25
  };
24
26
 
27
+ export class ExtensionOwnershipError extends Error {}
28
+
25
29
  export type InstallExtensionResult = {
26
30
  extension: Extension;
27
31
  isNew: boolean;
@@ -60,6 +64,19 @@ export async function installExtension(
60
64
  args.manifest.name,
61
65
  ]);
62
66
  const existing = existingRow ? rowToExtension(existingRow) : null;
67
+ if (existing && args.ownerOnly && existing.createdByAgentId !== args.ownerOnly) {
68
+ throw new ExtensionOwnershipError("Forbidden: extension belongs to another owner");
69
+ }
70
+ if (
71
+ existing?.enabled &&
72
+ args.ownerOnly &&
73
+ ((args.config !== undefined && JSON.stringify(args.config) !== existing.configJson) ||
74
+ (args.priority !== undefined && args.priority !== existing.priority))
75
+ ) {
76
+ throw new ExtensionOwnershipError(
77
+ "Forbidden: only a lead or operator may change live extension configuration",
78
+ );
79
+ }
63
80
  const now = new Date().toISOString();
64
81
 
65
82
  if (!existing) {
@@ -313,6 +330,7 @@ export async function updateExtensionMeta(
313
330
  config?: Record<string, unknown>;
314
331
  description?: string;
315
332
  updatedBy?: string | null;
333
+ ownerOnly?: string;
316
334
  },
317
335
  ): Promise<Extension | null> {
318
336
  const sets: string[] = [];
@@ -329,14 +347,21 @@ export async function updateExtensionMeta(
329
347
  sets.push("description = ?");
330
348
  values.push(args.description);
331
349
  }
332
- if (sets.length === 0) return getExtensionById(id);
350
+ if (sets.length === 0 && !args.ownerOnly) return getExtensionById(id);
333
351
 
334
352
  sets.push("updated_by = ?", "updatedAt = ?");
335
353
  values.push(args.updatedBy ?? null, new Date().toISOString(), id);
354
+ // The enabled check must be part of the write: a lead may enable the draft
355
+ // after the HTTP handler has authorized it but before this UPDATE executes.
356
+ const ownerCondition = args.ownerOnly ? " AND createdByAgentId = ? AND enabled = 0" : "";
357
+ if (args.ownerOnly) values.push(args.ownerOnly);
336
358
  const row = await getDbClient().get<ExtensionRow>(
337
- `UPDATE extensions SET ${sets.join(", ")} WHERE id = ? RETURNING *`,
359
+ `UPDATE extensions SET ${sets.join(", ")} WHERE id = ?${ownerCondition} RETURNING *`,
338
360
  values,
339
361
  );
362
+ if (!row && args.ownerOnly) {
363
+ throw new ExtensionOwnershipError("Forbidden: extension must be your own disabled draft");
364
+ }
340
365
  return row ? rowToExtension(row) : null;
341
366
  }
342
367
 
@@ -401,8 +426,14 @@ export async function recordExtensionFailure(
401
426
  return row ? rowToExtension(row) : null;
402
427
  }
403
428
 
404
- export async function deleteExtension(id: string): Promise<boolean> {
405
- const result = await getDbClient().run("DELETE FROM extensions WHERE id = ?", [id]);
429
+ export async function deleteExtension(id: string, ownerOnly?: string): Promise<boolean> {
430
+ const result = await getDbClient().run(
431
+ `DELETE FROM extensions WHERE id = ?${ownerOnly ? " AND createdByAgentId = ? AND enabled = 0" : ""}`,
432
+ ownerOnly ? [id, ownerOnly] : [id],
433
+ );
434
+ if (result.changes === 0 && ownerOnly) {
435
+ throw new ExtensionOwnershipError("Forbidden: extension must be your own disabled draft");
436
+ }
406
437
  return result.changes > 0;
407
438
  }
408
439
 
@@ -34,6 +34,8 @@ export type CatalogProviderId = (typeof CATALOG_PROVIDER_IDS)[number];
34
34
  * of the picker between models.dev listing gaps.
35
35
  */
36
36
  export const PINNED_MODELSDEV_ENTRIES = [
37
+ // Official launch metadata; retain until models.dev catches up. Verified 2026-09-22.
38
+ "anthropic/claude-opus-5-5",
37
39
  "anthropic/claude-mythos-5",
38
40
  "anthropic/claude-sonnet-5",
39
41
  "amazon-bedrock/anthropic.claude-sonnet-5",
@@ -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":
@@ -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}";
@@ -142,8 +146,9 @@ export function generateCompose(state: OnboardState): string {
142
146
 
143
147
  if (state.integrations.slack) {
144
148
  lines.push(" - SLACK_DISABLE=false");
149
+ lines.push(ENV_SLACK_MODE);
145
150
  lines.push(ENV_SLACK_BOT_TOKEN);
146
- lines.push(ENV_SLACK_APP_TOKEN);
151
+ lines.push(state.slackMode === "http" ? ENV_SLACK_SIGNING_SECRET : ENV_SLACK_APP_TOKEN);
147
152
  }
148
153
 
149
154
  if (state.integrations.github) {
@@ -92,8 +92,13 @@ export function generateEnv(state: OnboardState): string {
92
92
  if (state.integrations.slack) {
93
93
  lines.push("");
94
94
  lines.push("# Slack");
95
+ lines.push(`SLACK_MODE=${state.slackMode}`);
95
96
  lines.push(`SLACK_BOT_TOKEN=${state.slackBotToken}`);
96
- lines.push(`SLACK_APP_TOKEN=${state.slackAppToken}`);
97
+ if (state.slackMode === "http") {
98
+ lines.push(`SLACK_SIGNING_SECRET=${state.slackSigningSecret}`);
99
+ } else {
100
+ lines.push(`SLACK_APP_TOKEN=${state.slackAppToken}`);
101
+ }
97
102
  lines.push("SLACK_DISABLE=false");
98
103
  } else {
99
104
  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 || "",