@desplega.ai/agent-swarm 1.173.0 → 2.0.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 (432) hide show
  1. package/README.md +1 -1
  2. package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-sj2g0m84.js} +17 -16
  3. package/dist/{actions-sgeyv08k.js → actions-fegk44gr.js} +39 -34
  4. package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-ad8ft89x.js} +8 -7
  5. package/dist/{app-km9qnv2f.js → app-kfvgbvzy.js} +18 -14
  6. package/dist/{assistant-5r8tcvvd.js → assistant-z7zdy9ja.js} +40 -35
  7. package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-5c2z0mbe.js} +10 -9
  8. package/dist/{boot-reembed-16rv9843.js → boot-reembed-j8xa181e.js} +10 -9
  9. package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-hnkn3rgt.js} +11 -10
  10. package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-kwjq4d2z.js} +14 -13
  11. package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-9vmvpvgd.js} +19 -18
  12. package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-k9qae05j.js} +7 -5
  13. package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-q54zx5q2.js} +6 -4
  14. package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-9jye6cxr.js} +11881 -11472
  15. package/dist/{cli-94b48jhk.js → cli-03gedhng.js} +16 -14
  16. package/dist/{cli-1w0vj3gw.js → cli-1e4b6bzh.js} +7 -7
  17. package/dist/{cli-d603qf86.js → cli-29jc5q7w.js} +10 -8
  18. package/dist/cli-2m1ktfzz.js +17795 -0
  19. package/dist/{cli-x119kdba.js → cli-3dj8k4vy.js} +1 -1
  20. package/dist/{cli-srqq3gc5.js → cli-3fbmmawm.js} +5 -5
  21. package/dist/{cli-gmdajfw5.js → cli-4jxm2qtz.js} +4987 -1708
  22. package/dist/{cli-tadfgd0t.js → cli-5hkm7whv.js} +33 -4
  23. package/dist/{cli-42qhyvwx.js → cli-5t4f29ez.js} +3 -3
  24. package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
  25. package/dist/cli-6cvfxs8r.js +47 -0
  26. package/dist/{cli-0kxf81jj.js → cli-6jyj59nb.js} +2 -2
  27. package/dist/{cli-w1apjecb.js → cli-6razj6t4.js} +2 -2
  28. package/dist/{cli-anzdk0z4.js → cli-74ahz61x.js} +2 -2
  29. package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
  30. package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
  31. package/dist/{cli-81r1wjyv.js → cli-9nfx44eh.js} +1 -1
  32. package/dist/cli-9traj3dn.js +638 -0
  33. package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
  34. package/dist/{cli-na2pxe4f.js → cli-apx87jne.js} +2 -2
  35. package/dist/{cli-rfz2ve55.js → cli-bzszjf2p.js} +2855 -862
  36. package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
  37. package/dist/{cli-hsem16hb.js → cli-cgtksawx.js} +7 -4
  38. package/dist/{cli-db3m6zdt.js → cli-d2qr7aj4.js} +1 -1
  39. package/dist/{cli-rfs4vddv.js → cli-d5f9ed5c.js} +5 -5
  40. package/dist/cli-e3g5mbkz.js +776 -0
  41. package/dist/{cli-7jykv7ef.js → cli-e6mpjhed.js} +1 -1
  42. package/dist/{cli-7a93cv8c.js → cli-ee9gtz70.js} +98 -23
  43. package/dist/{cli-3nxdmjrc.js → cli-eejsgvm4.js} +4 -4
  44. package/dist/{cli-fmhj1ehj.js → cli-ef1hg1wv.js} +470 -51
  45. package/dist/cli-f527ce74.js +781 -0
  46. package/dist/{cli-ppy4nnnh.js → cli-f7kr7svz.js} +2 -2
  47. package/dist/cli-hjwmhcg1.js +10622 -0
  48. package/dist/{cli-2bw3w47j.js → cli-hnhtk6cj.js} +1 -1
  49. package/dist/{cli-ywm1azg9.js → cli-hnmhtzvh.js} +6 -4
  50. package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
  51. package/dist/{cli-s8z6x4b4.js → cli-j0pfptdp.js} +218 -102
  52. package/dist/cli-jta2eyzc.js +619 -0
  53. package/dist/{cli-5er5gjbm.js → cli-k382tshb.js} +10 -11
  54. package/dist/{cli-v3zhnxsb.js → cli-k3dp5tpf.js} +2 -2
  55. package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
  56. package/dist/cli-kceah1eh.js +92 -0
  57. package/dist/{cli-ne7smj1b.js → cli-ke896fcf.js} +10 -10
  58. package/dist/{cli-xc7p7s3g.js → cli-kt6zqg0e.js} +6 -6
  59. package/dist/{cli-wrh08zjd.js → cli-m50t4309.js} +5 -18
  60. package/dist/cli-n2wq4j7m.js +6985 -0
  61. package/dist/{cli-bv2etw2y.js → cli-n3hzg89b.js} +46 -15
  62. package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
  63. package/dist/{cli-qm1448f9.js → cli-ne236afy.js} +8 -8
  64. package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
  65. package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
  66. package/dist/{cli-0a7mm3zp.js → cli-q0ke1yww.js} +25 -21
  67. package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
  68. package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
  69. package/dist/{cli-phcqp1b9.js → cli-r2pnvj8g.js} +2 -2
  70. package/dist/{cli-jpc4r224.js → cli-r62a35ea.js} +19 -3
  71. package/dist/{cli-cd0hv9nh.js → cli-ra0xzggj.js} +2 -2
  72. package/dist/cli-rhs9pz33.js +294 -0
  73. package/dist/{cli-r4fqfpwf.js → cli-s2sp957d.js} +50 -27
  74. package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
  75. package/dist/{cli-6thk4jz3.js → cli-se8w6wny.js} +6 -6
  76. package/dist/cli-skxvvpap.js +10140 -0
  77. package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
  78. package/dist/{cli-0p3enk35.js → cli-tqaazemc.js} +9 -1
  79. package/dist/{cli-nwrdx840.js → cli-tr4sxp68.js} +3 -3
  80. package/dist/{cli-r0byd61h.js → cli-tsde1hdr.js} +15 -15
  81. package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
  82. package/dist/{cli-6r2f7edk.js → cli-v1yb0rqb.js} +6 -6
  83. package/dist/{cli-saqyage0.js → cli-vatyhshy.js} +179 -27
  84. package/dist/{cli-5wpw4rab.js → cli-vdach5a9.js} +5 -5
  85. package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
  86. package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
  87. package/dist/{cli-c3rk1v0x.js → cli-wayw93nt.js} +3 -3
  88. package/dist/cli-wmgrkscj.js +23254 -0
  89. package/dist/{cli-9xf7fdtp.js → cli-z5jjpaxw.js} +29 -6
  90. package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
  91. package/dist/cli.js +29 -45
  92. package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-y81sssk0.js} +15 -14
  93. package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
  94. package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-8vx4j6a9.js} +15 -14
  95. package/dist/{commands-z8fq9qna.js → commands-kcpvpcrr.js} +11 -10
  96. package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
  97. package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-kwpvj3rf.js} +42 -37
  98. package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
  99. package/dist/{db-yyhqqrbf.js → db-k8ankj20.js} +12 -11
  100. package/dist/{db-qfpq4bt7.js → db-ww5d7jq3.js} +28 -9
  101. package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
  102. package/dist/{dispatcher-x0x7qfcq.js → dispatcher-e8gq5m68.js} +38 -33
  103. package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
  104. package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-3epjm3af.js} +7 -6
  105. package/dist/{e2b-66xra4az.js → e2b-8ygwhg0f.js} +4 -3
  106. package/dist/{e2b-xwhyj8cw.js → e2b-swhnpw3n.js} +4 -3
  107. package/dist/{event-bus-vjtv82gm.js → event-bus-6axnngdj.js} +3 -2
  108. package/dist/{external-channel-h1fjecwe.js → external-channel-h3359cwn.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-0d4x7gkx.js} +18 -17
  112. package/dist/{handlers-znb9n7d4.js → handlers-an1gzv21.js} +41 -36
  113. package/dist/{heartbeat-bm4qkn8d.js → heartbeat-6dakeb61.js} +43 -38
  114. package/dist/{hook-254r4mza.js → hook-6v6cv6d5.js} +11 -23
  115. package/dist/{hook-xaa3q80s.js → hook-sa5xye4y.js} +12 -11
  116. package/dist/{http-3dgrgp8y.js → http-r7f3eky0.js} +1499 -251
  117. package/dist/index-52j1aja4.js +3465 -0
  118. package/dist/{index-fx3jqq1e.js → index-7ep4gzdk.js} +38 -33
  119. package/dist/index-9gw58n4k.js +193 -0
  120. package/dist/index-9j87mcm8.js +56305 -0
  121. package/dist/index-bsmcresk.js +79424 -0
  122. package/dist/index-mh85qhec.js +475 -0
  123. package/dist/{index-g2byveez.js → index-rmpw9a8q.js} +38 -33
  124. package/dist/{index-2ybk7khy.js → index-s2wxgzr0.js} +468 -683
  125. package/dist/{index-bdsqa799.js → index-v1v6n7hg.js} +43 -38
  126. package/dist/index-we27kd31.js +12810 -0
  127. package/dist/{index-jd7sejm2.js → index-zk96aq1k.js} +10 -9
  128. package/dist/{keepalive-6ywhpja1.js → keepalive-be9vwy5h.js} +12 -11
  129. package/dist/{lead-cw45n21s.js → lead-0861cwrf.js} +61 -56
  130. package/dist/{maintenance-ss1a1ge9.js → maintenance-mzzgc8bn.js} +10 -9
  131. package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
  132. package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-cpdnfwdj.js} +11 -10
  133. package/dist/{onboard-8hzdhc1k.js → onboard-fh8qs4r3.js} +11 -3
  134. package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-nm42wwj8.js} +18 -13
  135. package/dist/{otel-impl-e6mnvc4v.js → otel-impl-x6c1c9g4.js} +242 -868
  136. package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-9n2ya240.js} +244 -106
  137. package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-qb0rv0ap.js} +12 -11
  138. package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-1gzdwbh1.js} +11 -10
  139. package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-3mraey52.js} +12 -11
  140. package/dist/{render-v2-907cy6sa.js → render-v2-agpa45zz.js} +18 -14
  141. package/dist/{resume-42stcaz0.js → resume-x0ydy9s9.js} +25 -21
  142. package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
  143. package/dist/{setup-adbc1c10.js → setup-as9ga0d6.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-y5g1y7ev.js} +41 -36
  146. package/dist/{worker-bzdra9rf.js → worker-860c3e38.js} +61 -56
  147. package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
  148. package/openapi.json +523 -344
  149. package/package.json +10 -11
  150. package/src/be/config-refs.ts +60 -0
  151. package/src/be/db/page-versions.ts +15 -0
  152. package/src/be/db/runtime.ts +35 -8
  153. package/src/be/db/skill-name-resolution.ts +36 -0
  154. package/src/be/db/tasks/read.ts +230 -0
  155. package/src/be/db/tasks/write.ts +7 -0
  156. package/src/be/db.ts +52 -7
  157. package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
  158. package/src/be/migrations/216_task_resolved_effort.sql +5 -0
  159. package/src/be/migrations/217_chat_sdk_state.sql +104 -0
  160. package/src/be/model-catalog-store.ts +5 -1
  161. package/src/be/model-tier-resolution.ts +12 -1
  162. package/src/be/model-validation.ts +5 -2
  163. package/src/be/models-catalog.ts +26 -1
  164. package/src/be/modelsdev-cache.json +198 -63
  165. package/src/be/modelsdev-cache.ts +9 -1
  166. package/src/be/script-credential-broker.ts +39 -2
  167. package/src/be/scripts/run-saved.ts +1 -0
  168. package/src/be/scripts/typecheck.ts +10 -8
  169. package/src/be/seed/runner.ts +13 -1
  170. package/src/be/seed/state-db.ts +5 -0
  171. package/src/be/seed/types.ts +6 -0
  172. package/src/be/seed-pricing.ts +19 -2
  173. package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
  174. package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
  175. package/src/be/seed-skills/bundled-files.generated.json +0 -18
  176. package/src/be/seed-skills/index.ts +104 -3
  177. package/src/be/swarm-config-guard.ts +52 -0
  178. package/src/cli.tsx +0 -16
  179. package/src/commands/onboard/non-interactive.ts +4 -2
  180. package/src/commands/provider-credentials.ts +52 -6
  181. package/src/commands/runner.ts +190 -54
  182. package/src/e2b/env.ts +5 -0
  183. package/src/extensions/contract-types.generated.ts +1 -1
  184. package/src/extensions/contract.ts +45 -0
  185. package/src/extensions/dispatcher.ts +7 -0
  186. package/src/extensions/post-bridge.ts +40 -0
  187. package/src/github/handlers.ts +11 -4
  188. package/src/heartbeat/templates.ts +8 -5
  189. package/src/hooks/hook.ts +0 -26
  190. package/src/http/all-routes.ts +0 -1
  191. package/src/http/config.ts +36 -17
  192. package/src/http/core.ts +4 -0
  193. package/src/http/index.ts +14 -2
  194. package/src/http/integrations.ts +88 -1
  195. package/src/http/mcp.ts +15 -5
  196. package/src/http/page-proxy.ts +2 -4
  197. package/src/http/pages-public.ts +3 -3
  198. package/src/http/pages.ts +3 -13
  199. package/src/http/poll.ts +28 -68
  200. package/src/http/requested-by.ts +54 -0
  201. package/src/http/scripts.ts +1 -0
  202. package/src/http/stats.ts +1 -30
  203. package/src/http/tasks.ts +61 -5
  204. package/src/http/utils.ts +14 -0
  205. package/src/http/webhooks.ts +159 -1
  206. package/src/http/x.ts +1 -0
  207. package/src/integrations/chat-sdk/adapters.ts +129 -0
  208. package/src/integrations/chat-sdk/attachments.ts +232 -0
  209. package/src/integrations/chat-sdk/background.ts +36 -0
  210. package/src/integrations/chat-sdk/commands.ts +194 -0
  211. package/src/integrations/chat-sdk/config.ts +198 -0
  212. package/src/integrations/chat-sdk/discord-api.ts +63 -0
  213. package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
  214. package/src/integrations/chat-sdk/handlers.ts +28 -0
  215. package/src/integrations/chat-sdk/inbound.ts +426 -0
  216. package/src/integrations/chat-sdk/limits.ts +48 -0
  217. package/src/integrations/chat-sdk/logger.ts +81 -0
  218. package/src/integrations/chat-sdk/outbound.ts +123 -0
  219. package/src/integrations/chat-sdk/relay.ts +172 -0
  220. package/src/integrations/chat-sdk/router.ts +169 -0
  221. package/src/integrations/chat-sdk/runtime.ts +351 -0
  222. package/src/integrations/chat-sdk/schema.ts +245 -0
  223. package/src/integrations/chat-sdk/state.ts +243 -0
  224. package/src/integrations/chat-sdk/status.ts +244 -0
  225. package/src/integrations/chat-sdk/steering.ts +58 -0
  226. package/src/integrations/chat-sdk/teams-origin.ts +77 -0
  227. package/src/integrations/chat-sdk/telegram-api.ts +56 -0
  228. package/src/integrations/chat-sdk/templates.ts +16 -0
  229. package/src/integrations/chat-sdk/test-hooks.ts +37 -0
  230. package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
  231. package/src/integrations/chat-sdk/typing.ts +65 -0
  232. package/src/pages/version.ts +4 -5
  233. package/src/prompts/base-prompt.ts +111 -45
  234. package/src/providers/acp-target-catalog.ts +6 -0
  235. package/src/providers/acp-targets.ts +55 -2
  236. package/src/providers/amp-adapter.ts +1 -1
  237. package/src/providers/claude-adapter.ts +1 -1
  238. package/src/providers/claude-flag-settings.ts +17 -5
  239. package/src/providers/claude-managed-adapter.ts +1 -1
  240. package/src/providers/claude-session-events.ts +6 -1
  241. package/src/providers/dsh-adapter.ts +1 -1
  242. package/src/providers/opencode-adapter.ts +243 -26
  243. package/src/providers/opencode-swarm-plugin.ts +31 -0
  244. package/src/providers/pi-mono-adapter.ts +398 -153
  245. package/src/providers/pricing-sources.md +33 -2
  246. package/src/providers/reasoning-effort.ts +27 -0
  247. package/src/providers/types.ts +6 -2
  248. package/src/rbac/legacy-policy.ts +8 -2
  249. package/src/rbac/permissions.ts +21 -0
  250. package/src/scheduler/scheduler.ts +4 -2
  251. package/src/scripts-runtime/loader.ts +19 -7
  252. package/src/scripts-runtime/sdk-allowlist.ts +8 -6
  253. package/src/scripts-runtime/swarm-sdk.ts +0 -11
  254. package/src/scripts-runtime/types/stdlib.d.ts +27 -15
  255. package/src/scripts-runtime/types/swarm-extension.d.ts +63 -1
  256. package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -15
  257. package/src/server.ts +52 -18
  258. package/src/slack/event-dedup.ts +1 -1
  259. package/src/tasks/additive-buffer.ts +4 -2
  260. package/src/tasks/context-key.ts +60 -1
  261. package/src/tasks/model-pin.ts +67 -0
  262. package/src/tasks/worker-follow-up.ts +4 -31
  263. package/src/tests/acp-adapter.test.ts +42 -0
  264. package/src/tests/api-drain-worker-e2e.test.ts +1 -6
  265. package/src/tests/base-prompt.test.ts +58 -54
  266. package/src/tests/chat-sdk-commands.test.ts +191 -0
  267. package/src/tests/chat-sdk-config.test.ts +334 -0
  268. package/src/tests/chat-sdk-discord-api.test.ts +68 -0
  269. package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
  270. package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
  271. package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
  272. package/src/tests/chat-sdk-harness.ts +146 -0
  273. package/src/tests/chat-sdk-inbound.test.ts +363 -0
  274. package/src/tests/chat-sdk-relay.test.ts +470 -0
  275. package/src/tests/chat-sdk-reload.test.ts +128 -0
  276. package/src/tests/chat-sdk-shutdown.test.ts +220 -0
  277. package/src/tests/chat-sdk-slack.test.ts +268 -0
  278. package/src/tests/chat-sdk-state.test.ts +163 -0
  279. package/src/tests/chat-sdk-status-route.test.ts +382 -0
  280. package/src/tests/chat-sdk-teams.test.ts +277 -0
  281. package/src/tests/chat-sdk-tools.test.ts +520 -0
  282. package/src/tests/chat-sdk-typing.test.ts +120 -0
  283. package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
  284. package/src/tests/claude-adapter-binary.test.ts +9 -4
  285. package/src/tests/claude-flag-settings.test.ts +11 -3
  286. package/src/tests/claude-managed-adapter.test.ts +1 -1
  287. package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
  288. package/src/tests/claude-thinking-tokens.test.ts +57 -0
  289. package/src/tests/claude-worker-parity.test.ts +2 -7
  290. package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
  291. package/src/tests/config-refs.test.ts +66 -0
  292. package/src/tests/context-key.test.ts +19 -0
  293. package/src/tests/cors-allowlist.test.ts +25 -0
  294. package/src/tests/create-page-tool.test.ts +18 -0
  295. package/src/tests/credential-check.test.ts +139 -0
  296. package/src/tests/credentials.test.ts +21 -0
  297. package/src/tests/db-runtime.test.ts +61 -0
  298. package/src/tests/db-task-read-contract.test.ts +20 -0
  299. package/src/tests/db-task-write-contract.test.ts +10 -0
  300. package/src/tests/docs-index-footprint.test.js +3 -3
  301. package/src/tests/dsh-adapter.test.ts +1 -1
  302. package/src/tests/enabled-capabilities.test.ts +20 -0
  303. package/src/tests/entrypoint-api-readiness.test.ts +14 -8
  304. package/src/tests/entrypoint-config-env-export.test.ts +5 -2
  305. package/src/tests/entrypoint-export-to-env.test.ts +78 -0
  306. package/src/tests/explicit-model-validation.test.ts +105 -1
  307. package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
  308. package/src/tests/extensions-post-bridge.test.ts +51 -0
  309. package/src/tests/fetch-resolved-env.test.ts +128 -0
  310. package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
  311. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
  312. package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
  313. package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
  314. package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
  315. package/src/tests/github-handlers.test.ts +35 -0
  316. package/src/tests/harness-provider-resolution.test.ts +12 -0
  317. package/src/tests/heartbeat-checklist.test.ts +3 -2
  318. package/src/tests/hook-runtime-close.test.ts +0 -2
  319. package/src/tests/http-api-integration.test.ts +0 -25
  320. package/src/tests/migration-046-budgets.test.ts +17 -16
  321. package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
  322. package/src/tests/model-tier-resolution.test.ts +93 -0
  323. package/src/tests/models-catalog.test.ts +42 -1
  324. package/src/tests/openai-compatible-providers.test.ts +134 -0
  325. package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
  326. package/src/tests/opencode-adapter.test.ts +216 -2
  327. package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
  328. package/src/tests/opencode-shell-env.test.ts +145 -0
  329. package/src/tests/openrouter-base-url.test.ts +101 -151
  330. package/src/tests/page-proxy.test.ts +1 -1
  331. package/src/tests/pages-browser-sdk.test.ts +76 -0
  332. package/src/tests/pages-feedback.test.ts +1 -1
  333. package/src/tests/paused-tasks-requested-by.test.ts +102 -0
  334. package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
  335. package/src/tests/pi-mono-adapter.test.ts +385 -5
  336. package/src/tests/pi-shell-env.test.ts +170 -0
  337. package/src/tests/prompt-template-remaining.test.ts +35 -0
  338. package/src/tests/rbac-engine.test.ts +11 -3
  339. package/src/tests/runner-exit-after-tasks.test.ts +0 -4
  340. package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
  341. package/src/tests/script-connections.test.ts +2 -0
  342. package/src/tests/scripts-http.test.ts +201 -1
  343. package/src/tests/scripts-only-gating.test.ts +2 -3
  344. package/src/tests/scripts-runtime.test.ts +58 -40
  345. package/src/tests/secret-scrubber.test.ts +86 -0
  346. package/src/tests/seed-skills-bundled-files.test.ts +45 -53
  347. package/src/tests/seed-skills-retire.test.ts +182 -0
  348. package/src/tests/send-task-requester-gate.test.ts +58 -0
  349. package/src/tests/session-cost-recompute-unit.test.ts +46 -0
  350. package/src/tests/skill-get-name-resolution.test.ts +137 -0
  351. package/src/tests/sonnet-5-5-registry.test.ts +9 -1
  352. package/src/tests/swarm-config-export-to-env.test.ts +267 -0
  353. package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
  354. package/src/tests/swarm-diff.test.ts +1 -1
  355. package/src/tests/task-model-effort-rerun.test.ts +164 -0
  356. package/src/tests/task-session-prompts.test.ts +132 -0
  357. package/src/tests/task-tool-manifest.test.ts +14 -0
  358. package/src/tests/task-tools-ctx.test.ts +2 -0
  359. package/src/tests/tool-annotations.test.ts +6 -6
  360. package/src/tests/ui-logs-parser.test.ts +43 -0
  361. package/src/tests/used-by-route.test.ts +6 -0
  362. package/src/tests/vercel-ai-gateway.test.ts +149 -0
  363. package/src/tests/workflow-swarm-script.test.ts +38 -0
  364. package/src/tests/workflow-wait-filter.test.ts +5 -3
  365. package/src/tools/chat-access.ts +41 -0
  366. package/src/tools/chat-open-dm.ts +59 -0
  367. package/src/tools/chat-post.ts +74 -0
  368. package/src/tools/chat-read-thread.ts +100 -0
  369. package/src/tools/chat-reply.ts +75 -0
  370. package/src/tools/create-page.ts +3 -13
  371. package/src/tools/model-catalog/index.ts +2 -1
  372. package/src/tools/register-chat-channel.ts +139 -0
  373. package/src/tools/send-task.ts +24 -0
  374. package/src/tools/skills/skill-get.ts +17 -9
  375. package/src/tools/swarm-config/get-config.ts +2 -1
  376. package/src/tools/swarm-config/list-config.ts +2 -1
  377. package/src/tools/swarm-config/set-config.ts +16 -3
  378. package/src/tools/tool-config.ts +8 -6
  379. package/src/types.ts +12 -2
  380. package/src/utils/config-env-export.ts +74 -0
  381. package/src/utils/credentials.test.ts +92 -0
  382. package/src/utils/credentials.ts +52 -4
  383. package/src/utils/harness-provider.ts +15 -6
  384. package/src/utils/runtime-model-catalog.ts +11 -1
  385. package/src/utils/secret-scrubber.ts +71 -2
  386. package/src/utils/task-tool-manifest.ts +19 -2
  387. package/src/workflows/executors/swarm-script.ts +1 -0
  388. package/templates/skills/agent-browser/SKILL.md +1 -1
  389. package/templates/skills/agent-browser/content.md +1 -1
  390. package/templates/skills/apps/SKILL.md +8 -1
  391. package/templates/skills/apps/content.md +8 -1
  392. package/templates/skills/chat-sdk/config.json +14 -0
  393. package/templates/skills/chat-sdk/content.md +84 -0
  394. package/templates/skills/composio-gmail/content.md +7 -0
  395. package/templates/skills/composio-google-docs/content.md +1 -1
  396. package/templates/skills/email-domain-health/config.json +14 -0
  397. package/templates/skills/email-domain-health/content.md +131 -0
  398. package/templates/skills/kv-storage/content.md +2 -2
  399. package/templates/skills/pages/content.md +8 -10
  400. package/templates/skills/swarm-extensions/content.md +2 -0
  401. package/templates/skills/swarm-scripts/SKILL.md +4 -2
  402. package/templates/skills/swarm-scripts/config.json +1 -1
  403. package/templates/skills/swarm-scripts/content.md +4 -2
  404. package/templates/skills/workflow-iterate/content.md +38 -0
  405. package/dist/artifact-eczsknc3.js +0 -3843
  406. package/dist/cli-bd957dgb.js +0 -153
  407. package/dist/cli-q51yprfq.js +0 -1104
  408. package/dist/cli-t1ze64h3.js +0 -811
  409. package/dist/cli-tcc4wd5d.js +0 -56471
  410. package/dist/index-9ch1n761.js +0 -1102
  411. package/src/artifact-sdk/index.ts +0 -2
  412. package/src/artifact-sdk/localtunnel.d.ts +0 -20
  413. package/src/artifact-sdk/port.ts +0 -12
  414. package/src/artifact-sdk/server.ts +0 -183
  415. package/src/artifact-sdk/tunnel.ts +0 -19
  416. package/src/commands/artifact.ts +0 -249
  417. package/src/http/ecosystem.ts +0 -77
  418. package/src/tests/artifact-commands.test.ts +0 -92
  419. package/src/tests/artifact-sdk.test.ts +0 -793
  420. package/src/tests/register-service-security.test.ts +0 -194
  421. package/src/tools/list-services.ts +0 -107
  422. package/src/tools/register-service.ts +0 -177
  423. package/src/tools/unregister-service.ts +0 -73
  424. package/src/tools/update-service-status.ts +0 -96
  425. package/templates/skills/artifacts/config.json +0 -14
  426. package/templates/skills/artifacts/content.md +0 -344
  427. package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
  428. package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
  429. package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
  430. package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
  431. /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
  432. /package/src/{artifact-sdk → pages}/feedback-overlay.ts +0 -0
@@ -1,2 +0,0 @@
1
- export type { ArtifactServer, ArtifactServerOptions } from "./server";
2
- export { createArtifactServer } from "./server";
@@ -1,20 +0,0 @@
1
- declare module "@desplega.ai/localtunnel" {
2
- interface TunnelOptions {
3
- port: number;
4
- subdomain?: string;
5
- host?: string;
6
- auth?: string;
7
- username?: string;
8
- local_host?: string;
9
- }
10
-
11
- interface Tunnel {
12
- url: string;
13
- close(): void;
14
- on(event: "close", listener: () => void): void;
15
- on(event: "error", listener: (err: Error) => void): void;
16
- }
17
-
18
- function localtunnel(opts: TunnelOptions): Promise<Tunnel>;
19
- export default localtunnel;
20
- }
@@ -1,12 +0,0 @@
1
- import { createServer } from "node:net";
2
-
3
- export async function getAvailablePort(): Promise<number> {
4
- return new Promise((resolve, reject) => {
5
- const server = createServer();
6
- server.listen(0, () => {
7
- const { port } = server.address() as { port: number };
8
- server.close(() => resolve(port));
9
- });
10
- server.on("error", reject);
11
- });
12
- }
@@ -1,183 +0,0 @@
1
- import { Hono } from "hono";
2
- import { serveStatic } from "hono/bun";
3
- import { getApiKey } from "../utils/api-key";
4
- import { getMcpBaseUrl } from "../utils/constants";
5
- import { BROWSER_SDK_JS } from "./browser-sdk";
6
- import { getAvailablePort } from "./port";
7
- import { createTunnel } from "./tunnel";
8
-
9
- export interface ArtifactServerOptions {
10
- name: string;
11
- static?: string;
12
- app?: Hono;
13
- port?: number;
14
- auth?: boolean;
15
- subdomain?: string;
16
- }
17
-
18
- export interface ArtifactServer {
19
- start(): Promise<void>;
20
- stop(): Promise<void>;
21
- url: string;
22
- port: number;
23
- tunnel: ReturnType<typeof createTunnel> extends Promise<infer T> ? T | null : never;
24
- }
25
-
26
- const NativeResponse = globalThis.Response;
27
-
28
- type NativeResponseArgs = ConstructorParameters<typeof Response>;
29
-
30
- export function createBunResponse(
31
- body?: NativeResponseArgs[0],
32
- init?: NativeResponseArgs[1],
33
- ): Response {
34
- return new NativeResponse(body, init);
35
- }
36
-
37
- export function createBunHonoFetchHandler(app: Hono): (req: Request) => Promise<Response> {
38
- return async (req: Request) => {
39
- const response = await app.fetch(req);
40
- return createBunResponse(response.body, {
41
- status: response.status,
42
- statusText: response.statusText,
43
- headers: response.headers,
44
- });
45
- };
46
- }
47
-
48
- export function createArtifactServer(opts: ArtifactServerOptions): ArtifactServer {
49
- const agentId = process.env.AGENT_ID || "unknown";
50
- const apiKey = getApiKey();
51
- const mcpBaseUrl = getMcpBaseUrl();
52
-
53
- const app = new Hono();
54
-
55
- // Inject swarm middleware
56
- app.get("/@swarm/sdk.js", (c) => {
57
- c.header("Content-Type", "application/javascript");
58
- return c.body(BROWSER_SDK_JS);
59
- });
60
-
61
- app.get("/@swarm/config", (c) => {
62
- return c.json({ agentId, artifactName: opts.name });
63
- });
64
-
65
- // API proxy — forwards /@swarm/api/* to MCP server
66
- app.all("/@swarm/api/*", async (c) => {
67
- const path = c.req.path.replace("/@swarm/api", "/api");
68
- const targetUrl = `${mcpBaseUrl}${path}`;
69
- const headers: Record<string, string> = {
70
- Authorization: `Bearer ${apiKey}`,
71
- "X-Agent-ID": agentId,
72
- };
73
- if (c.req.method !== "GET") {
74
- headers["Content-Type"] = "application/json";
75
- }
76
- try {
77
- const res = await fetch(targetUrl, {
78
- method: c.req.method,
79
- headers,
80
- body: c.req.method !== "GET" ? await c.req.text() : undefined,
81
- });
82
- return new Response(res.body, {
83
- status: res.status,
84
- headers: {
85
- "Access-Control-Allow-Origin": "*",
86
- "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
87
- "Access-Control-Allow-Headers": "Content-Type",
88
- },
89
- });
90
- } catch (e) {
91
- return c.json({ error: "Proxy error", message: String(e) }, 502);
92
- }
93
- });
94
-
95
- // CORS preflight
96
- app.options("/@swarm/api/*", (_c) => {
97
- return new Response(null, {
98
- status: 204,
99
- headers: {
100
- "Access-Control-Allow-Origin": "*",
101
- "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
102
- "Access-Control-Allow-Headers": "Content-Type",
103
- },
104
- });
105
- });
106
-
107
- // User app or static serving
108
- if (opts.app) {
109
- app.route("/", opts.app);
110
- } else if (opts.static) {
111
- app.use("/*", serveStatic({ root: opts.static }));
112
- }
113
-
114
- let server: ReturnType<typeof Bun.serve> | null = null;
115
- // biome-ignore lint/suspicious/noExplicitAny: localtunnel tunnel type
116
- let tunnel: any = null;
117
- let actualPort = 0;
118
-
119
- const artifact: ArtifactServer = {
120
- url: "",
121
- port: 0,
122
- tunnel: null,
123
-
124
- async start() {
125
- actualPort = opts.port || (await getAvailablePort());
126
- server = Bun.serve({ port: actualPort, fetch: createBunHonoFetchHandler(app) });
127
- artifact.port = actualPort;
128
-
129
- const subdomain = opts.subdomain || `${agentId}-${opts.name}`;
130
- const authPassword = opts.auth === false ? undefined : apiKey;
131
-
132
- tunnel = await createTunnel({
133
- port: actualPort,
134
- subdomain,
135
- auth: authPassword,
136
- });
137
-
138
- artifact.url = tunnel.url;
139
- artifact.tunnel = tunnel;
140
-
141
- // Register in service registry
142
- try {
143
- await fetch(`${mcpBaseUrl}/api/services`, {
144
- method: "POST",
145
- headers: {
146
- Authorization: `Bearer ${apiKey}`,
147
- "X-Agent-ID": agentId,
148
- "Content-Type": "application/json",
149
- },
150
- body: JSON.stringify({
151
- script: `artifact-${opts.name}`,
152
- metadata: {
153
- type: "artifact",
154
- artifactName: opts.name,
155
- port: actualPort,
156
- publicUrl: tunnel.url,
157
- },
158
- }),
159
- });
160
- } catch (e) {
161
- console.warn("Failed to register artifact in service registry:", e);
162
- }
163
-
164
- console.log(`Artifact "${opts.name}" live at ${tunnel.url} (port ${actualPort})`);
165
- },
166
-
167
- async stop() {
168
- if (tunnel) {
169
- tunnel.close();
170
- tunnel = null;
171
- }
172
- if (server) {
173
- // Bun >= 1.4 makes stop() wait for in-flight requests and idle
174
- // keep-alive connections. Callers stop on SIGINT/SIGTERM and then
175
- // exit, so close active connections instead of waiting on a hung client.
176
- await server.stop(true);
177
- server = null;
178
- }
179
- },
180
- };
181
-
182
- return artifact;
183
- }
@@ -1,19 +0,0 @@
1
- import localtunnel from "@desplega.ai/localtunnel";
2
-
3
- interface TunnelOptions {
4
- port: number;
5
- subdomain: string;
6
- auth?: string;
7
- username?: string;
8
- }
9
-
10
- export async function createTunnel(opts: TunnelOptions) {
11
- const tunnel = await localtunnel({
12
- port: opts.port,
13
- subdomain: opts.subdomain,
14
- auth: opts.auth,
15
- username: opts.username || "hi", // default "hi" for MVP (custom username deferred)
16
- // host defaults to lt.desplega.ai in our fork
17
- });
18
- return tunnel;
19
- }
@@ -1,249 +0,0 @@
1
- import { Hono } from "hono";
2
- import { createArtifactServer } from "../artifact-sdk";
3
- import { getApiKey } from "../utils/api-key";
4
- import { getMcpBaseUrl } from "../utils/constants";
5
-
6
- interface ArtifactArgs {
7
- additionalArgs: string[];
8
- port?: string;
9
- key?: string;
10
- }
11
-
12
- export async function runArtifact(subcommand: string, args: ArtifactArgs) {
13
- switch (subcommand) {
14
- case "serve":
15
- return artifactServe(args);
16
- case "list":
17
- return artifactList();
18
- case "stop":
19
- return artifactStop(args);
20
- default:
21
- printHelp();
22
- }
23
- }
24
-
25
- function printHelp() {
26
- console.log(`Usage: agent-swarm artifact <subcommand>
27
-
28
- Subcommands:
29
- serve <path> --name <name> [--port <port>] [--no-auth] [--subdomain <sub>]
30
- Serve a directory or script as an artifact via localtunnel
31
-
32
- list
33
- List active artifacts (from service registry)
34
-
35
- stop <name>
36
- Stop an artifact and close its tunnel
37
-
38
- Examples:
39
- agent-swarm artifact serve ./my-report --name my-report
40
- agent-swarm artifact serve ./server.ts --name dashboard
41
- agent-swarm artifact list
42
- agent-swarm artifact stop my-report`);
43
- }
44
-
45
- async function artifactServe(args: ArtifactArgs) {
46
- const additionalArgs = args.additionalArgs || [];
47
-
48
- // Parse artifact-specific args from additionalArgs
49
- let path = "";
50
- let name = "";
51
- let port: number | undefined;
52
- let noAuth = false;
53
- let subdomain: string | undefined;
54
-
55
- for (let i = 0; i < additionalArgs.length; i++) {
56
- const arg = additionalArgs[i] ?? "";
57
- if (arg === "--name") {
58
- name = additionalArgs[i + 1] ?? "";
59
- i++;
60
- } else if (arg === "--port") {
61
- port = Number.parseInt(additionalArgs[i + 1] ?? "0", 10);
62
- i++;
63
- } else if (arg === "--no-auth") {
64
- noAuth = true;
65
- } else if (arg === "--subdomain") {
66
- subdomain = additionalArgs[i + 1] ?? "";
67
- i++;
68
- } else if (!arg.startsWith("-") && !path) {
69
- path = arg;
70
- }
71
- }
72
-
73
- if (!path) {
74
- console.error("Error: path is required. Usage: artifact serve <path> --name <name>");
75
- process.exit(1);
76
- }
77
-
78
- if (!name) {
79
- // Derive name from path
80
- name = path.split("/").filter(Boolean).pop() || "artifact";
81
- }
82
-
83
- // Determine if path is a directory or a script
84
- const file = Bun.file(path);
85
- const isFile = await file.exists();
86
-
87
- let app: Hono | undefined;
88
- let staticDir: string | undefined;
89
-
90
- if (isFile && (path.endsWith(".ts") || path.endsWith(".js"))) {
91
- // Script mode — import the module and use its default export as a Hono app
92
- try {
93
- const mod = await import(path.startsWith("/") ? path : `${process.cwd()}/${path}`);
94
- if (mod.default instanceof Hono) {
95
- app = mod.default;
96
- } else {
97
- console.error(`Error: ${path} must export a default Hono app instance`);
98
- process.exit(1);
99
- }
100
- } catch (e) {
101
- console.error(`Error loading ${path}:`, e);
102
- process.exit(1);
103
- }
104
- } else {
105
- // Static directory mode
106
- const { existsSync } = await import("node:fs");
107
- if (!existsSync(path)) {
108
- console.error(`Error: path "${path}" does not exist`);
109
- process.exit(1);
110
- }
111
- staticDir = path;
112
- }
113
-
114
- const server = createArtifactServer({
115
- name,
116
- app,
117
- static: staticDir,
118
- port,
119
- auth: noAuth ? false : undefined,
120
- subdomain,
121
- });
122
-
123
- await server.start();
124
-
125
- // Keep the process alive
126
- process.on("SIGINT", async () => {
127
- console.log(`\nStopping artifact "${name}"...`);
128
- await server.stop();
129
- process.exit(0);
130
- });
131
-
132
- process.on("SIGTERM", async () => {
133
- await server.stop();
134
- process.exit(0);
135
- });
136
-
137
- // Keep alive
138
- await new Promise(() => {});
139
- }
140
-
141
- async function artifactList() {
142
- const apiKey = getApiKey();
143
- const mcpBaseUrl = getMcpBaseUrl();
144
- const agentId = process.env.AGENT_ID || "";
145
-
146
- try {
147
- const res = await fetch(`${mcpBaseUrl}/api/services`, {
148
- headers: {
149
- Authorization: `Bearer ${apiKey}`,
150
- "X-Agent-ID": agentId,
151
- },
152
- });
153
-
154
- if (!res.ok) {
155
- console.error(`Failed to fetch services: ${res.status} ${res.statusText}`);
156
- process.exit(1);
157
- }
158
-
159
- const body = (await res.json()) as {
160
- services?: Array<{
161
- name: string;
162
- agentId: string;
163
- status: string;
164
- metadata?: { type?: string; artifactName?: string; port?: number; publicUrl?: string };
165
- }>;
166
- };
167
- const services = body.services ?? [];
168
-
169
- const artifacts = services.filter((s) => s.metadata?.type === "artifact");
170
-
171
- if (artifacts.length === 0) {
172
- console.log("No active artifacts");
173
- return;
174
- }
175
-
176
- // Format as table
177
- console.log(
178
- `${"NAME".padEnd(20)} ${"AGENT".padEnd(16)} ${"PORT".padEnd(8)} ${"URL".padEnd(50)} STATUS`,
179
- );
180
- for (const a of artifacts) {
181
- const name = (a.metadata?.artifactName || a.name).padEnd(20);
182
- const agent = (a.agentId || "").substring(0, 14).padEnd(16);
183
- const port = String(a.metadata?.port || "?").padEnd(8);
184
- const url = (a.metadata?.publicUrl || "").padEnd(50);
185
- console.log(`${name} ${agent} ${port} ${url} ${a.status}`);
186
- }
187
- } catch (e) {
188
- console.error("Failed to list artifacts:", e);
189
- process.exit(1);
190
- }
191
- }
192
-
193
- async function artifactStop(args: ArtifactArgs) {
194
- const name = args.additionalArgs?.[0];
195
- if (!name) {
196
- console.error("Error: name is required. Usage: artifact stop <name>");
197
- process.exit(1);
198
- }
199
-
200
- const apiKey = getApiKey();
201
- const mcpBaseUrl = getMcpBaseUrl();
202
- const agentId = process.env.AGENT_ID || "";
203
-
204
- // 1. Try to stop PM2 process
205
- try {
206
- await Bun.$`pm2 delete artifact-${name} 2>/dev/null`.quiet();
207
- console.log(`Stopped PM2 process: artifact-${name}`);
208
- } catch {
209
- // Process might not exist in PM2
210
- }
211
-
212
- // 2. Unregister from service registry
213
- try {
214
- const res = await fetch(`${mcpBaseUrl}/api/services`, {
215
- headers: {
216
- Authorization: `Bearer ${apiKey}`,
217
- "X-Agent-ID": agentId,
218
- },
219
- });
220
-
221
- if (res.ok) {
222
- const body = (await res.json()) as {
223
- services?: Array<{
224
- id: string;
225
- name: string;
226
- metadata?: { type?: string; artifactName?: string };
227
- }>;
228
- };
229
- const services = body.services ?? [];
230
- const service = services.find(
231
- (s) => s.metadata?.type === "artifact" && s.metadata?.artifactName === name,
232
- );
233
-
234
- if (service) {
235
- await fetch(`${mcpBaseUrl}/api/services/${service.id}`, {
236
- method: "DELETE",
237
- headers: {
238
- Authorization: `Bearer ${apiKey}`,
239
- "X-Agent-ID": agentId,
240
- },
241
- });
242
- }
243
- }
244
- } catch {
245
- // Non-fatal
246
- }
247
-
248
- console.log(`Artifact '${name}' stopped.`);
249
- }
@@ -1,77 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from "node:http";
2
- import { z } from "zod";
3
- import { getServicesByAgentId } from "../be/db";
4
- import { route } from "./route-def";
5
- import { jsonError } from "./utils";
6
-
7
- // ─── Route Definitions ───────────────────────────────────────────────────────
8
-
9
- const EcosystemAppSchema = z.object({
10
- name: z.string(),
11
- script: z.string(),
12
- cwd: z.string().optional(),
13
- interpreter: z.string().optional(),
14
- args: z.array(z.string()).optional(),
15
- env: z.record(z.string(), z.string()).optional(),
16
- });
17
-
18
- type EcosystemApp = z.infer<typeof EcosystemAppSchema>;
19
-
20
- const getEcosystem = route({
21
- method: "get",
22
- path: "/ecosystem",
23
- pattern: ["ecosystem"],
24
- summary: "Get PM2 ecosystem config for agent services",
25
- tags: ["Ecosystem"],
26
- auth: { apiKey: true, agentId: true },
27
- responses: {
28
- 200: {
29
- description: "PM2 ecosystem config",
30
- schema: z.object({ apps: z.array(EcosystemAppSchema) }),
31
- },
32
- 400: { description: "Missing X-Agent-ID" },
33
- },
34
- });
35
-
36
- // ─── Handler ─────────────────────────────────────────────────────────────────
37
-
38
- export async function handleEcosystem(
39
- req: IncomingMessage,
40
- res: ServerResponse,
41
- pathSegments: string[],
42
- myAgentId: string | undefined,
43
- ): Promise<boolean> {
44
- if (getEcosystem.match(req.method, pathSegments)) {
45
- if (!myAgentId) {
46
- jsonError(res, "Missing X-Agent-ID header", 400);
47
- return true;
48
- }
49
-
50
- const services = await getServicesByAgentId(myAgentId);
51
-
52
- // Generate PM2 ecosystem format
53
- const ecosystem = {
54
- apps: services
55
- .filter((s) => s.script) // Only include services with script path
56
- .map((s) => {
57
- const app: EcosystemApp = {
58
- name: s.name,
59
- script: s.script,
60
- };
61
-
62
- if (s.cwd) app.cwd = s.cwd;
63
- if (s.interpreter) app.interpreter = s.interpreter;
64
- if (s.args && s.args.length > 0) app.args = s.args;
65
- if (s.env && Object.keys(s.env).length > 0) app.env = s.env;
66
- if (s.port) app.env = { ...(app.env || {}), PORT: String(s.port) };
67
-
68
- return app;
69
- }),
70
- };
71
-
72
- getEcosystem.respond(res, 200, ecosystem);
73
- return true;
74
- }
75
-
76
- return false;
77
- }
@@ -1,92 +0,0 @@
1
- /**
2
- * Regression test for the `/api/services` response-shape bug in
3
- * `src/commands/artifact.ts` (artifactList / artifactStop).
4
- *
5
- * The endpoint returns `{ services: [...] }`, but earlier the code
6
- * cast the JSON as a bare `Array<...>` and crashed with
7
- * `services.filter is not a function`.
8
- */
9
-
10
- import { afterAll, afterEach, beforeAll, describe, expect, mock, test } from "bun:test";
11
- import { runArtifact } from "../commands/artifact";
12
-
13
- const originalFetch = globalThis.fetch;
14
- const originalLog = console.log;
15
- const originalError = console.error;
16
-
17
- let capturedOut: string[] = [];
18
- let capturedErr: string[] = [];
19
-
20
- beforeAll(() => {
21
- console.log = (...args: unknown[]) => {
22
- capturedOut.push(args.map(String).join(" "));
23
- };
24
- console.error = (...args: unknown[]) => {
25
- capturedErr.push(args.map(String).join(" "));
26
- };
27
- });
28
-
29
- afterEach(() => {
30
- globalThis.fetch = originalFetch;
31
- capturedOut = [];
32
- capturedErr = [];
33
- });
34
-
35
- afterAll(() => {
36
- globalThis.fetch = originalFetch;
37
- console.log = originalLog;
38
- console.error = originalError;
39
- });
40
-
41
- function jsonResponse(body: unknown, status = 200): Response {
42
- return new Response(JSON.stringify(body), {
43
- status,
44
- headers: { "Content-Type": "application/json" },
45
- });
46
- }
47
-
48
- describe("runArtifact('list')", () => {
49
- test("handles wrapped { services: [] } without throwing", async () => {
50
- globalThis.fetch = mock(() => Promise.resolve(jsonResponse({ services: [] })));
51
-
52
- await expect(runArtifact("list", { additionalArgs: [] })).resolves.toBeUndefined();
53
- expect(capturedOut.join("\n")).toContain("No active artifacts");
54
- expect(capturedErr.join("\n")).not.toContain("services.filter");
55
- });
56
-
57
- test("renders artifact rows from { services: [...] }", async () => {
58
- globalThis.fetch = mock(() =>
59
- Promise.resolve(
60
- jsonResponse({
61
- services: [
62
- {
63
- name: "artifact-testart",
64
- agentId: "agent-xyz",
65
- status: "healthy",
66
- metadata: {
67
- type: "artifact",
68
- artifactName: "testart",
69
- port: 4242,
70
- publicUrl: "https://testart.loca.lt",
71
- },
72
- },
73
- ],
74
- }),
75
- ),
76
- );
77
-
78
- await expect(runArtifact("list", { additionalArgs: [] })).resolves.toBeUndefined();
79
- const out = capturedOut.join("\n");
80
- expect(out).toContain("testart");
81
- expect(out).toContain("4242");
82
- expect(out).toContain("https://testart.loca.lt");
83
- expect(out).toContain("healthy");
84
- });
85
-
86
- test("falls back to [] when response omits services key", async () => {
87
- globalThis.fetch = mock(() => Promise.resolve(jsonResponse({})));
88
-
89
- await expect(runArtifact("list", { additionalArgs: [] })).resolves.toBeUndefined();
90
- expect(capturedOut.join("\n")).toContain("No active artifacts");
91
- });
92
- });