@desplega.ai/agent-swarm 2.7.0 → 2.7.1

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 (236) hide show
  1. package/dist/{acp-adapter-ma1js5n7.js → acp-adapter-8dn5tq56.js} +6 -6
  2. package/dist/{actions-1vhmtvg9.js → actions-3r6gw7dy.js} +18 -18
  3. package/dist/{amp-adapter-sxqqvmdk.js → amp-adapter-wjtq413p.js} +3 -3
  4. package/dist/{anthropic-messages-txs190dd.js → anthropic-messages-n4cby1rz.js} +4 -4
  5. package/dist/{app-mwx1d5a9.js → app-d53yhykk.js} +3 -3
  6. package/dist/{assistant-yx1p6g82.js → assistant-ksrawj3k.js} +20 -20
  7. package/dist/{boot-reembed-7h78vmvv.js → boot-reembed-fxfw17m2.js} +10 -3
  8. package/dist/{boot-reembed-5h37a2c2.js → boot-reembed-k5y5xbj0.js} +15 -8
  9. package/dist/{boot-scrub-sweep-8mawd4gw.js → boot-scrub-sweep-se41j9fd.js} +3 -3
  10. package/dist/{boot-seeds-ca84dhnn.js → boot-seeds-r3kwwv8b.js} +4 -4
  11. package/dist/{claude-adapter-wqt4hfkq.js → claude-adapter-ahmyf231.js} +7 -7
  12. package/dist/{claude-managed-adapter-6fjqtr2z.js → claude-managed-adapter-5knamegc.js} +3 -3
  13. package/dist/{claude-managed-setup-rqv98sea.js → claude-managed-setup-mdc7dy6b.js} +2 -2
  14. package/dist/{claude-sdk-session-f29f3b2x.js → claude-sdk-session-n5wen9zk.js} +8728 -8599
  15. package/dist/{cli-m5e802r7.js → cli-0dqtv2jg.js} +2 -2
  16. package/dist/{cli-e1595bgx.js → cli-0tww7dnz.js} +2 -2
  17. package/dist/{cli-2y7v133v.js → cli-0w4e4v58.js} +7 -7
  18. package/dist/{cli-d20qvpr2.js → cli-2sjm3t4r.js} +1 -1
  19. package/dist/{cli-gf2850q7.js → cli-3cywb44q.js} +18 -1
  20. package/dist/{cli-8wkb09q5.js → cli-3k9jej0c.js} +2 -2
  21. package/dist/{cli-twctnkng.js → cli-3v2cyqb8.js} +3 -3
  22. package/dist/{cli-he9gbdx0.js → cli-5qt9vzmq.js} +39 -20
  23. package/dist/{cli-a6ds2epe.js → cli-5rp1w4cr.js} +1 -1
  24. package/dist/{cli-6srv653c.js → cli-6vwjsetx.js} +4 -4
  25. package/dist/{cli-1hhbzkbb.js → cli-6w2yrrc0.js} +8 -8
  26. package/dist/{cli-f12mr20z.js → cli-75tdydgv.js} +1 -1
  27. package/dist/{cli-j3y0x2n4.js → cli-8feswf2v.js} +43 -33
  28. package/dist/{cli-07q03xm2.js → cli-8wd3mbyj.js} +1 -1
  29. package/dist/{cli-ymjpkxgn.js → cli-9csfthbw.js} +8 -6
  30. package/dist/{cli-f1e0ptjj.js → cli-b41p764a.js} +21 -2
  31. package/dist/{cli-kv7sbc2c.js → cli-c1t533hh.js} +3 -3
  32. package/dist/{cli-54sj64fc.js → cli-c28jxpcv.js} +1 -1
  33. package/dist/{cli-8mbc9za9.js → cli-cb50g9cd.js} +1 -1
  34. package/dist/{cli-c668vvcf.js → cli-d8gaphtr.js} +1 -1
  35. package/dist/{cli-86ehn4s5.js → cli-dgtfysne.js} +2 -2
  36. package/dist/{cli-sjctjr48.js → cli-dscnhn18.js} +1 -1
  37. package/dist/{cli-j0ppywdr.js → cli-dv11pgpv.js} +12 -12
  38. package/dist/{cli-1m9x8dr5.js → cli-ekptgk2m.js} +5 -5
  39. package/dist/{cli-9gsm2rzp.js → cli-f3mzy662.js} +17 -17
  40. package/dist/{cli-s0mgx214.js → cli-fk7k8s9x.js} +2 -2
  41. package/dist/{cli-vbhgkw9h.js → cli-h3e7bhvn.js} +3 -3
  42. package/dist/{cli-yd2nreqw.js → cli-hkxqdmnb.js} +2 -2
  43. package/dist/{cli-8wmj18cz.js → cli-hpkvgdad.js} +7 -4
  44. package/dist/{cli-wqr7cea4.js → cli-hq2v4rr5.js} +37 -9
  45. package/dist/{cli-sgqm2582.js → cli-k1zb7raw.js} +5 -5
  46. package/dist/{cli-4rvr7zfx.js → cli-k4awgvzm.js} +5 -0
  47. package/dist/{cli-ay40dnj3.js → cli-k7d3hvya.js} +2 -2
  48. package/dist/{cli-j9bpmykh.js → cli-kbtdftbw.js} +5 -5
  49. package/dist/{cli-x37r7qwf.js → cli-kj69b9tw.js} +25 -5
  50. package/dist/{cli-gsfk58nw.js → cli-kk9jy4nm.js} +1 -1
  51. package/dist/{cli-39aet655.js → cli-m52t4cta.js} +1 -1
  52. package/dist/{cli-h5jeg46p.js → cli-mdadewqp.js} +5 -5
  53. package/dist/{cli-a89zdqz9.js → cli-nf6k60sn.js} +1 -1
  54. package/dist/{cli-v6shg7na.js → cli-nzdf09js.js} +1 -1
  55. package/dist/{cli-rr7zx19j.js → cli-prcyzecg.js} +12 -12
  56. package/dist/{cli-6a9qfa8b.js → cli-pzafyqtk.js} +118 -48
  57. package/dist/{cli-48gxjmcz.js → cli-qvaa1gjp.js} +87 -24
  58. package/dist/{cli-qj442fws.js → cli-rg4b2g6j.js} +1 -1
  59. package/dist/{cli-aypd09nf.js → cli-rm66vqdz.js} +1 -1
  60. package/dist/{cli-9pshx6rd.js → cli-s504c3w7.js} +1 -1
  61. package/dist/{cli-ptfq202x.js → cli-swkx9jm2.js} +3 -3
  62. package/dist/{cli-m30k9777.js → cli-thsaq4pd.js} +16 -16
  63. package/dist/{cli-60sty27p.js → cli-twjnyvs8.js} +2 -2
  64. package/dist/{cli-rd5m70gj.js → cli-typdpe8g.js} +4 -4
  65. package/dist/{cli-yxbsmx56.js → cli-vg8pwmsd.js} +6 -6
  66. package/dist/{cli-s09j9vp5.js → cli-vhpckzvp.js} +1 -1
  67. package/dist/{cli-dv97kdzv.js → cli-wdxgsdz5.js} +2 -2
  68. package/dist/{cli-7a6p4e65.js → cli-wtjg6je3.js} +1 -1
  69. package/dist/{cli-b3yzyc57.js → cli-x3cngb1h.js} +44 -12
  70. package/dist/{cli-6mgdba42.js → cli-xbz6mcg4.js} +2 -2
  71. package/dist/{cli-2pvzmas1.js → cli-y4tdxsqb.js} +3 -3
  72. package/dist/{cli-f4dbh7a5.js → cli-yqrsp3ny.js} +7 -7
  73. package/dist/cli.js +27 -19
  74. package/dist/{codex-adapter-zk59x2zh.js → codex-adapter-7wepzq15.js} +5 -5
  75. package/dist/{codex-hook-xyjhvxwd.js → codex-hook-pbdh4xhx.js} +2 -2
  76. package/dist/{codex-session-runner-kh6s4j3n.js → codex-session-runner-02sb49e4.js} +5 -5
  77. package/dist/{commands-68et1qv2.js → commands-3rcspxct.js} +2 -2
  78. package/dist/{controller-fyrbnzg4.js → controller-8ar4avd6.js} +3 -3
  79. package/dist/{controllers-connect-nep9h2xv.js → controllers-connect-ajvh9h0v.js} +19 -19
  80. package/dist/{cursor-adapter-yss3pg7t.js → cursor-adapter-gd0sa7bh.js} +1 -1
  81. package/dist/{db-28gjyvxj.js → db-dv9j7ts5.js} +2 -2
  82. package/dist/{db-8ftwvzba.js → db-z26vgdvj.js} +3 -3
  83. package/dist/{dispatcher-hayexmkr.js → dispatcher-8m0htjq8.js} +17 -17
  84. package/dist/{dsh-adapter-46wawff9.js → dsh-adapter-y8gyk130.js} +1 -1
  85. package/dist/{e2b-fn3zacvt.js → e2b-74vg9b7e.js} +1 -1
  86. package/dist/{e2b-222hsajc.js → e2b-jyay8wzn.js} +1 -1
  87. package/dist/{easter-egg-3d-8d1e0h4m.js → easter-egg-3d-28f880xx.js} +1 -1
  88. package/dist/{execute-cjrfxfnm.js → execute-9seb79vh.js} +1 -1
  89. package/dist/{external-channel-xbmxcg09.js → external-channel-smz7jyth.js} +2 -2
  90. package/dist/{getMachineId-bsd-brn0xym3.js → getMachineId-bsd-whfre6gr.js} +3 -3
  91. package/dist/{getMachineId-darwin-t339sfxm.js → getMachineId-darwin-5zjynb19.js} +3 -3
  92. package/dist/{getMachineId-linux-5eq95d8b.js → getMachineId-linux-8mksrrsq.js} +3 -3
  93. package/dist/{getMachineId-unsupported-qavrtc7j.js → getMachineId-unsupported-fxtqsdt2.js} +3 -3
  94. package/dist/{getMachineId-win-q7fe1wx7.js → getMachineId-win-nzfmz857.js} +3 -3
  95. package/dist/{grok-adapter-ag4wks2a.js → grok-adapter-z0nnvtbn.js} +7 -7
  96. package/dist/handlers-pspryh6g.js +41 -0
  97. package/dist/{heartbeat-psfvcgwp.js → heartbeat-f928aqyp.js} +20 -20
  98. package/dist/{hook-cyq4mryn.js → hook-d7c605r4.js} +7 -7
  99. package/dist/{hook-8pz04697.js → hook-q9hv5xf9.js} +5 -5
  100. package/dist/{http-haj1nd6k.js → http-q6j4k989.js} +934 -180
  101. package/dist/{index-z5h22pes.js → index-5nb266jr.js} +17 -17
  102. package/dist/{index-ysd45kgc.js → index-8fxt5eah.js} +10 -10
  103. package/dist/{index-zgvqzjsw.js → index-cekzwhez.js} +5 -5
  104. package/dist/{index-zyq8ct52.js → index-ch0c1xff.js} +17 -17
  105. package/dist/{index-syvhnvtw.js → index-ebnjhxh1.js} +1 -1
  106. package/dist/{index-y1ajx04a.js → index-ed8dy8rn.js} +20 -20
  107. package/dist/{index-jwt2bj6f.js → index-ejqdkkqx.js} +11 -10
  108. package/dist/{index-dr94zbnh.js → index-farm1zsn.js} +32661 -29443
  109. package/dist/{index-q52f47pe.js → index-yn1yxg85.js} +1 -1
  110. package/dist/{keepalive-xdvsamvj.js → keepalive-zzc3hks1.js} +3 -3
  111. package/dist/{lead-hqg57kdp.js → lead-c0pjcaw4.js} +36 -36
  112. package/dist/{maintenance-4y2xzh3a.js → maintenance-kqsxzpzx.js} +1 -1
  113. package/dist/{oauth-refresh-sweep-jd4r7zbs.js → oauth-refresh-sweep-7qt0g55z.js} +2 -2
  114. package/dist/{onboard-18447q9q.js → onboard-k7x13fqg.js} +118 -5
  115. package/dist/{opencode-adapter-26b2frdf.js → opencode-adapter-tqvrtter.js} +5 -5
  116. package/dist/{otel-impl-f9tgr8yw.js → otel-impl-sqkf6k3b.js} +97 -97
  117. package/dist/{pi-mono-adapter-qn6qbga1.js → pi-mono-adapter-m2qnafxm.js} +63 -9
  118. package/dist/{pricing-refresh-dw2tgb53.js → pricing-refresh-wkpwhgvs.js} +3 -3
  119. package/dist/{rbac-roles-s4nwj2m3.js → rbac-roles-dpn0c0wj.js} +7 -4
  120. package/dist/{rbac-roles-aygm2760.js → rbac-roles-wk7xd6a6.js} +2 -2
  121. package/dist/{render-v2-yfvdfr0x.js → render-v2-ex2m4g2k.js} +3 -3
  122. package/dist/{resume-1bmvjbf3.js → resume-725g9b0b.js} +7 -7
  123. package/dist/{runtime-f7tpzedy.js → runtime-kajas15g.js} +1 -1
  124. package/dist/{session-access-r5garej6.js → session-access-0j2ezjje.js} +8 -4
  125. package/dist/{session-source-backfill-424wzv0r.js → session-source-backfill-62202awe.js} +2 -2
  126. package/dist/{setup-8tygvxkq.js → setup-9sj11ax6.js} +1 -1
  127. package/dist/{virtual-modules-xsw323b3.js → virtual-modules-c6fcq6zr.js} +2 -2
  128. package/dist/{work-objects-ggnghpgf.js → work-objects-0y07495y.js} +20 -20
  129. package/dist/{worker-sqjd1nqf.js → worker-d4q9sqbc.js} +36 -36
  130. package/openapi.json +1070 -9
  131. package/package.json +3 -3
  132. package/src/be/connector-codes.ts +65 -22
  133. package/src/be/memory/boot-reembed.ts +4 -1
  134. package/src/be/memory/constants.ts +6 -0
  135. package/src/be/memory/embedding-recovery.ts +48 -0
  136. package/src/be/memory/index-content.ts +5 -2
  137. package/src/be/memory/providers/openai-embedding.ts +65 -14
  138. package/src/be/memory/task-learning.ts +110 -8
  139. package/src/be/memory/types.ts +13 -2
  140. package/src/be/migrations/246_connector_code_kind.sql +11 -0
  141. package/src/be/onboarding.ts +125 -15
  142. package/src/be/rbac-roles.ts +4 -1
  143. package/src/be/scripts/embeddings.ts +2 -2
  144. package/src/be/seed/agent-fs-provision.ts +75 -14
  145. package/src/be/swarm-config-guard.ts +3 -0
  146. package/src/cli.tsx +9 -0
  147. package/src/comb/config.ts +6 -1
  148. package/src/commands/onboard/agent-fs-version.ts +5 -0
  149. package/src/commands/onboard/compose-generator.ts +112 -1
  150. package/src/commands/onboard/env-generator.ts +9 -0
  151. package/src/commands/onboard/tei-image.ts +12 -0
  152. package/src/commands/onboard/types.ts +7 -0
  153. package/src/commands/onboard.tsx +11 -1
  154. package/src/commands/runner.ts +14 -1
  155. package/src/http/agentfs-proxy.ts +369 -0
  156. package/src/http/all-routes.ts +1 -0
  157. package/src/http/codex-oauth-device.ts +8 -1
  158. package/src/http/fs.ts +64 -10
  159. package/src/http/inbox-state.ts +27 -1
  160. package/src/http/index.ts +4 -1
  161. package/src/http/memory.ts +7 -4
  162. package/src/http/onboarding.ts +139 -11
  163. package/src/http/session-access.ts +24 -0
  164. package/src/http/sessions.ts +10 -6
  165. package/src/http/tasks.ts +85 -11
  166. package/src/http/telemetry-ui.ts +1 -1
  167. package/src/http/user-roles.ts +4 -1
  168. package/src/http/users.ts +272 -3
  169. package/src/http/utils.ts +22 -3
  170. package/src/prompts/base-prompt.ts +24 -9
  171. package/src/prompts/session-templates.ts +26 -2
  172. package/src/providers/amp-adapter.ts +1 -1
  173. package/src/providers/codex-adapter.ts +6 -1
  174. package/src/providers/cursor-adapter.ts +1 -1
  175. package/src/providers/pi-mono-adapter.ts +58 -3
  176. package/src/rbac/legacy-policy.ts +1 -0
  177. package/src/rbac/permissions.ts +4 -0
  178. package/src/tests/agent-fs-provision-seeder.test.ts +261 -92
  179. package/src/tests/agentfs-proxy.test.ts +1106 -0
  180. package/src/tests/base-prompt.test.ts +69 -2
  181. package/src/tests/codex-adapter.test.ts +46 -8
  182. package/src/tests/codex-oauth-device.test.ts +12 -1
  183. package/src/tests/comb-config-guard.test.ts +20 -0
  184. package/src/tests/comb-links.test.ts +79 -1
  185. package/src/tests/comb-status.test.ts +44 -0
  186. package/src/tests/docs-index-footprint.test.js +3 -3
  187. package/src/tests/fixtures/onboard/baseline-states.ts +68 -0
  188. package/src/tests/fixtures/onboard/content.compose.yml.txt +190 -0
  189. package/src/tests/fixtures/onboard/content.env.txt +29 -0
  190. package/src/tests/fixtures/onboard/dev.compose.yml.txt +155 -0
  191. package/src/tests/fixtures/onboard/dev.env.txt +28 -0
  192. package/src/tests/fixtures/onboard/full-all.compose.yml.txt +582 -0
  193. package/src/tests/fixtures/onboard/full-all.env.txt +59 -0
  194. package/src/tests/fixtures/onboard/full.compose.yml.txt +435 -0
  195. package/src/tests/fixtures/onboard/full.env.txt +36 -0
  196. package/src/tests/fixtures/onboard/research.compose.yml.txt +155 -0
  197. package/src/tests/fixtures/onboard/research.env.txt +28 -0
  198. package/src/tests/fixtures/onboard/solo.compose.yml.txt +85 -0
  199. package/src/tests/fixtures/onboard/solo.env.txt +26 -0
  200. package/src/tests/http-log-scrubbing.test.ts +34 -1
  201. package/src/tests/http-task-write-ownership.test.ts +5 -1
  202. package/src/tests/invites-http.test.ts +464 -0
  203. package/src/tests/memory-embedding-input-cap.test.ts +122 -1
  204. package/src/tests/memory-embedding-recovery.test.ts +137 -0
  205. package/src/tests/onboard-compose.test.ts +142 -0
  206. package/src/tests/onboard-env.test.ts +24 -0
  207. package/src/tests/onboard-non-interactive.test.ts +29 -0
  208. package/src/tests/onboard-tei-image.test.ts +36 -0
  209. package/src/tests/onboarding.test.ts +451 -4
  210. package/src/tests/openai-embedding-provider.test.ts +105 -2
  211. package/src/tests/pi-mono-session-cost-on-abort.test.ts +270 -0
  212. package/src/tests/preload-env.test.ts +4 -0
  213. package/src/tests/preload.ts +4 -0
  214. package/src/tests/prompt-template-session.test.ts +19 -3
  215. package/src/tests/rbac-admission-e2e.test.ts +22 -6
  216. package/src/tests/rbac-admission.test.ts +342 -4
  217. package/src/tests/rbac-engine.test.ts +1 -0
  218. package/src/tests/rbac-roles.test.ts +9 -1
  219. package/src/tests/send-task-requester-gate.test.ts +64 -3
  220. package/src/tests/sessions-move.test.ts +39 -1
  221. package/src/tests/store-progress-learning.test.ts +95 -2
  222. package/src/tests/whoami-route.test.ts +41 -0
  223. package/src/tools/inject-learning.ts +1 -1
  224. package/src/tools/memory-edit.ts +1 -1
  225. package/src/tools/memory-search.ts +1 -1
  226. package/src/tools/store-progress.ts +5 -1
  227. package/src/tools/utils.ts +12 -1
  228. package/src/utils/constants.ts +39 -0
  229. package/src/utils/task-attachment-links.ts +15 -3
  230. package/templates/skills/swarm-docs/content.md +1 -1
  231. package/dist/handlers-tzmevqb5.js +0 -41
  232. package/dist/{azure-openai-responses-9kfwhmn7.js → azure-openai-responses-43asa23s.js} +0 -0
  233. package/dist/{node-vxx896fa.js → node-t28cc56b.js} +0 -0
  234. package/dist/{openai-codex-responses-79s8xnbh.js → openai-codex-responses-jhr3sjtm.js} +3 -3
  235. package/dist/{openai-completions-tdbyts0x.js → openai-completions-gs6yn37k.js} +3 -3
  236. /package/dist/{openai-responses-dm3t5vqp.js → openai-responses-jqm9vwwk.js} +0 -0
@@ -1,3 +1,4 @@
1
+ import { AGENT_FS_VERSION } from "./agent-fs-version.ts";
1
2
  import { composeCommandText, engineForCommands } from "./container-engine.ts";
2
3
  import { expandServices } from "./service-names.ts";
3
4
  import type { OnboardState } from "./types.ts";
@@ -71,6 +72,91 @@ const ENV_SENTRY_AUTH_TOKEN = " - SENTRY_AUTH_TOKEN=${SENTRY_AUTH_TOKEN}";
71
72
  // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
72
73
  const ENV_SENTRY_ORG = " - SENTRY_ORG=${SENTRY_ORG}";
73
74
 
75
+ // ── Bundled agent-fs + TEI (`onboard --yes`, flag `bundleAgentFs`) ──
76
+ const APP_URL = "https://app.agent-swarm.dev";
77
+ const AGENT_FS_INTERNAL_URL = "http://agent-fs:7433";
78
+ const TEI_MODEL = "nomic-ai/nomic-embed-text-v1.5";
79
+ // Compose `${PUBLIC_MCP_BASE_URL:-http://localhost:<port>}`; the caller appends `<port>}`.
80
+ const ENV_AGENT_FS_PUBLIC_URL_PREFIX =
81
+ " - AGENT_FS_PUBLIC_URL=${PUBLIC_MCP_BASE_URL:-http://localhost:";
82
+ const TEI_IMAGE_EXPRESSION =
83
+ // biome-ignore lint/suspicious/noTemplateCurlyInString: Docker Compose env var syntax
84
+ "${TEI_IMAGE:-ghcr.io/huggingface/text-embeddings-inference:cpu-1.9.4}";
85
+
86
+ /** The API side of the bundle: agent-fs proxy, Comb, dashboard links, TEI memory. */
87
+ function appendBundleApiEnvironment(lines: string[]) {
88
+ lines.push(` - AGENT_FS_API_URL=${AGENT_FS_INTERNAL_URL}`);
89
+ lines.push(" - AGENT_FS_PROXY=true");
90
+ lines.push(" - COMB_ENABLED=true");
91
+ lines.push(" - AGENT_FS_LINK_TARGET=dashboard");
92
+ lines.push(" - EMBEDDING_API_BASE_URL=http://tei:80/v1");
93
+ lines.push(` - EMBEDDING_MODEL=${TEI_MODEL}`);
94
+ lines.push(" - EMBEDDING_API_KEY=local-tei");
95
+ // Quoted: unquoted, `KEY=search_query: ` parses as a mapping and drops the trailing space.
96
+ lines.push(' - "EMBEDDING_QUERY_PREFIX=search_query: "');
97
+ lines.push(' - "EMBEDDING_DOCUMENT_PREFIX=search_document: "');
98
+ }
99
+
100
+ function appendBundleServices(lines: string[], state: OnboardState, apiPort: number) {
101
+ lines.push("");
102
+ lines.push(" agent-fs:");
103
+ lines.push(` image: "ghcr.io/desplega-ai/agent-fs:${AGENT_FS_VERSION}"`);
104
+ lines.push(" container_name: swarm-agent-fs");
105
+ lines.push(` pull_policy: ${state.pullPolicy}`);
106
+ lines.push("");
107
+ lines.push(" environment:");
108
+ lines.push(" - AGENT_FS_HOME=/data");
109
+ lines.push(" - AGENT_FS_STORAGE_PROVIDER=local");
110
+ lines.push(" - AGENT_FS_LOCAL_ROOT=/data/storage");
111
+ lines.push(" - HOST=0.0.0.0");
112
+ lines.push(" - SERVER_HOST=0.0.0.0");
113
+ lines.push(" - PORT=7433");
114
+ lines.push(" - SERVER_PORT=7433");
115
+ lines.push(" - EMBEDDING_PROVIDER=local");
116
+ // The browser reaches agent-fs through the API proxy, on the tunnel URL when there is one.
117
+ lines.push(`${ENV_AGENT_FS_PUBLIC_URL_PREFIX}${apiPort}}/agentfs`);
118
+ lines.push(` - AGENT_FS_APP_URL=${APP_URL}`);
119
+ lines.push("");
120
+ lines.push(" volumes:");
121
+ lines.push(" - agent_fs_data:/data");
122
+ lines.push("");
123
+ lines.push(" healthcheck:");
124
+ lines.push(" # The agent-fs image has no curl or wget.");
125
+ lines.push(
126
+ ` test: ["CMD-SHELL", "node -e \\"fetch('http://127.0.0.1:7433/health').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))\\""]`,
127
+ );
128
+ lines.push(" interval: 10s");
129
+ lines.push(" timeout: 5s");
130
+ lines.push(" retries: 30");
131
+ lines.push(" start_period: 10s");
132
+ lines.push("");
133
+ lines.push(" restart: unless-stopped");
134
+
135
+ lines.push("");
136
+ lines.push(" tei:");
137
+ lines.push(` image: "${TEI_IMAGE_EXPRESSION}"`);
138
+ lines.push(" container_name: swarm-tei");
139
+ lines.push(` pull_policy: ${state.pullPolicy}`);
140
+ // --max-batch-tokens 2048: the default warmup passed 5.4 GB and was OOM-killed on an 8 GB box.
141
+ // --max-client-batch-size 256: the default 32 rejects documents with more than 32 chunks.
142
+ lines.push(
143
+ ` command: ["--model-id", "${TEI_MODEL}", "--max-batch-tokens", "2048", "--max-client-batch-size", "256"]`,
144
+ );
145
+ lines.push(" mem_limit: 2g");
146
+ lines.push("");
147
+ lines.push(" volumes:");
148
+ lines.push(" - tei_data:/data");
149
+ lines.push("");
150
+ lines.push(" healthcheck:");
151
+ lines.push(' test: ["CMD-SHELL", "curl -sf http://127.0.0.1:80/health || exit 1"]');
152
+ lines.push(" interval: 10s");
153
+ lines.push(" timeout: 5s");
154
+ lines.push(" retries: 30");
155
+ lines.push(" start_period: 180s");
156
+ lines.push("");
157
+ lines.push(" restart: unless-stopped");
158
+ }
159
+
74
160
  function appendProviderEnvironment(lines: string[], state: OnboardState, includeHarness: boolean) {
75
161
  if (includeHarness) lines.push(ENV_HARNESS_PROVIDER);
76
162
  switch (state.provider) {
@@ -155,7 +241,7 @@ export function generateCompose(state: OnboardState): string {
155
241
  lines.push(" - MEMORY_DEMOTION_FLOOR=${MEMORY_DEMOTION_FLOOR-1.0}");
156
242
  appendProviderEnvironment(lines, state, false);
157
243
  lines.push(` - MCP_BASE_URL=http://localhost:${port}`);
158
- lines.push(" - APP_URL=https://app.agent-swarm.dev");
244
+ lines.push(` - APP_URL=${APP_URL}`);
159
245
 
160
246
  if (state.integrations.slack) {
161
247
  lines.push(" - SLACK_DISABLE=false");
@@ -168,6 +254,19 @@ export function generateCompose(state: OnboardState): string {
168
254
  lines.push(" - GITHUB_DISABLE=false");
169
255
  }
170
256
 
257
+ if (state.bundleAgentFs) {
258
+ appendBundleApiEnvironment(lines);
259
+ lines.push("");
260
+ // The boot seeder provisions agent-fs, so it must be up first. TEI only needs to
261
+ // start: a first boot downloads 1.1 GB of weights, and memory falls back to
262
+ // keyword search until it is ready.
263
+ lines.push(" depends_on:");
264
+ lines.push(" agent-fs:");
265
+ lines.push(" condition: service_healthy");
266
+ lines.push(" tei:");
267
+ lines.push(" condition: service_started");
268
+ }
269
+
171
270
  lines.push("");
172
271
  lines.push(" ports:");
173
272
  lines.push(` - "${port}:3013"`);
@@ -238,6 +337,12 @@ export function generateCompose(state: OnboardState): string {
238
337
  lines.push(ENV_SENTRY_ORG);
239
338
  }
240
339
 
340
+ if (state.bundleAgentFs) {
341
+ lines.push(` - AGENT_FS_API_URL=${AGENT_FS_INTERNAL_URL}`);
342
+ lines.push(` - APP_URL=${APP_URL}`);
343
+ lines.push(" - AGENT_FS_LINK_TARGET=dashboard");
344
+ }
345
+
241
346
  lines.push("");
242
347
  lines.push(" ports:");
243
348
  lines.push(` - "${port}:3000"`);
@@ -255,6 +360,8 @@ export function generateCompose(state: OnboardState): string {
255
360
  lines.push(" restart: unless-stopped");
256
361
  }
257
362
 
363
+ if (state.bundleAgentFs) appendBundleServices(lines, state, port);
364
+
258
365
  // ── Volumes section ──
259
366
  lines.push("");
260
367
  lines.push("volumes:");
@@ -264,6 +371,10 @@ export function generateCompose(state: OnboardState): string {
264
371
  for (const svc of expanded) {
265
372
  lines.push(` swarm_${svc.sanitizedName}:`);
266
373
  }
374
+ if (state.bundleAgentFs) {
375
+ lines.push(" agent_fs_data:");
376
+ lines.push(" tei_data:");
377
+ }
267
378
 
268
379
  return `${lines.join("\n")}\n`;
269
380
  }
@@ -43,6 +43,15 @@ export function generateEnv(state: OnboardState): string {
43
43
  lines.push("MEMORY_RATERS=implicit-citation,explicit-self");
44
44
  lines.push("MEMORY_DEMOTION_FLOOR=1.0");
45
45
 
46
+ if (state.bundleAgentFs) {
47
+ lines.push("");
48
+ lines.push("# Bundled agent-fs (local disk) and TEI (memory embeddings); settings are in");
49
+ lines.push(
50
+ "# docker-compose.yml. Generate without them: agent-swarm onboard --yes --no-agent-fs",
51
+ );
52
+ if (state.teiImage) lines.push(`TEI_IMAGE=${state.teiImage}`);
53
+ }
54
+
46
55
  // ── Authentication ──
47
56
  lines.push("");
48
57
  lines.push("# === Authentication ===");
@@ -0,0 +1,12 @@
1
+ /** TEI image for the bundled embeddings server on arm64 hosts. */
2
+ export const TEI_ARM64_IMAGE = "ghcr.io/huggingface/text-embeddings-inference:cpu-arm64-1.9.4";
3
+
4
+ /**
5
+ * TEI publishes one tag per CPU architecture, so Compose `platform:` cannot
6
+ * pick it. `install.sh` runs onboard on the Docker host, so the host arch is
7
+ * the engine arch. Returns `null` for amd64 and anything else: the compose
8
+ * default (`cpu-1.9.4`, amd64) applies.
9
+ */
10
+ export function teiImageForArch(arch: string): string | null {
11
+ return arch === "arm64" || arch === "aarch64" ? TEI_ARM64_IMAGE : null;
12
+ }
@@ -95,6 +95,10 @@ export interface OnboardState {
95
95
  containerEngine: ContainerEnginePreference;
96
96
  outputDir: string;
97
97
  nonInteractive: boolean;
98
+ /** Bundle agent-fs (local disk) and TEI. Only `--yes` without `--no-agent-fs` sets it. */
99
+ bundleAgentFs: boolean;
100
+ /** TEI image override for the host arch; `null` keeps the compose default (amd64). */
101
+ teiImage: string | null;
98
102
  error: string | null;
99
103
  logs: LogLine[];
100
104
  }
@@ -114,6 +118,7 @@ export interface OnboardProps {
114
118
  maxConcurrentTasks?: string;
115
119
  pullPolicy?: string;
116
120
  containerEngine?: string;
121
+ noAgentFs?: boolean;
117
122
  }
118
123
 
119
124
  export type PullPolicy = "always" | "missing" | "never";
@@ -212,6 +217,8 @@ export const INITIAL_STATE: OnboardState = {
212
217
  containerEngine: "auto",
213
218
  outputDir: process.cwd(),
214
219
  nonInteractive: false,
220
+ bundleAgentFs: false,
221
+ teiImage: null,
215
222
  error: null,
216
223
  logs: [],
217
224
  };
@@ -1,4 +1,5 @@
1
1
  import crypto from "node:crypto";
2
+ import os from "node:os";
2
3
  import { Select } from "@inkjs/ui";
3
4
  import { Box, Text, useApp, useInput } from "ink";
4
5
  import { useCallback, useEffect, useRef, useState } from "react";
@@ -35,6 +36,7 @@ import { PostTaskStep } from "./onboard/steps/post-task.tsx";
35
36
  import { PrereqCheckStep } from "./onboard/steps/prereq-check.tsx";
36
37
  import { ReviewStep } from "./onboard/steps/review.tsx";
37
38
  import { StartStep } from "./onboard/steps/start.tsx";
39
+ import { teiImageForArch } from "./onboard/tei-image.ts";
38
40
  import {
39
41
  getStepProgress,
40
42
  INITIAL_STATE,
@@ -61,6 +63,7 @@ export function Onboard({
61
63
  maxConcurrentTasks,
62
64
  pullPolicy,
63
65
  containerEngine,
66
+ noAgentFs = false,
64
67
  }: OnboardProps) {
65
68
  const { exit } = useApp();
66
69
  const [state, setState] = useState<OnboardState>(() => {
@@ -229,8 +232,15 @@ export function Onboard({
229
232
  addLog(`Integrations: ${enabled.join(", ")}`);
230
233
  }
231
234
 
235
+ const bundleAgentFs = !noAgentFs;
236
+ if (bundleAgentFs) {
237
+ addLog("Bundling agent-fs and TEI (local files and memory; --no-agent-fs to skip)");
238
+ }
239
+
232
240
  goToStep("generate", {
233
241
  nonInteractive: true,
242
+ bundleAgentFs,
243
+ teiImage: bundleAgentFs ? teiImageForArch(os.arch()) : null,
234
244
  deployType: "local",
235
245
  presetId: selectedPreset.id,
236
246
  services: selectedPreset.services,
@@ -250,7 +260,7 @@ export function Onboard({
250
260
  sentryToken: process.env.SENTRY_AUTH_TOKEN || "",
251
261
  sentryOrg: process.env.SENTRY_ORG || "",
252
262
  });
253
- }, [yes, preset, state.step, addLog, goToStep, goToError]);
263
+ }, [yes, preset, noAgentFs, state.step, addLog, goToStep, goToError]);
254
264
 
255
265
  // Interactive welcome: auto-advance after detecting existing setup
256
266
  useEffect(() => {
@@ -1222,6 +1222,7 @@ export async function provisionAgentFsAfterRegistration(opts: {
1222
1222
  * - TEMPLATE_REGISTRY_URL — read per registry fetch.
1223
1223
  * - SLACK_DISABLE — read by the prompt builder to gate the Slack tool section.
1224
1224
  * - SWARM_ORG_NAME — read per telemetry event for org identity.
1225
+ * - AGENT_FS_LINK_TARGET — read by the prompt builder for the file-link base.
1225
1226
  *
1226
1227
  * CLAUDE_TRANSPORT stays in the per-session environment. Caching a scoped
1227
1228
  * value here would prevent deletion from restoring the configured default.
@@ -1241,6 +1242,7 @@ export const RELOADABLE_ENV_KEYS: ReadonlySet<string> = new Set([
1241
1242
  "TEMPLATE_REGISTRY_URL",
1242
1243
  "SLACK_DISABLE",
1243
1244
  "SWARM_ORG_NAME",
1245
+ "AGENT_FS_LINK_TARGET",
1244
1246
  // Gate the public-ranking `ranking.usage` emit, so clearing the website or
1245
1247
  // turning the setting off stops it on running workers.
1246
1248
  "SWARM_ORG_WEBSITE",
@@ -2714,6 +2716,8 @@ export interface RunningTask {
2714
2716
  assistantText?: { value?: string };
2715
2717
  /** Last progress value, retained until the final API writes settle. */
2716
2718
  finalProgress?: { value?: string };
2719
+ /** Latest cost snapshot captured from `result` events before completion settles. */
2720
+ lastCost?: { value?: CostData };
2717
2721
  /** Last time `reconcileActiveTasks` read this task's server-side status. */
2718
2722
  lastReconcileAt?: number;
2719
2723
  /** When the runner asked the session to abort (cancel or reconcile). */
@@ -4553,6 +4557,7 @@ async function spawnProviderProcess(
4553
4557
  // session promise resolves (see `trackAssistantText`).
4554
4558
  const assistantTextHolder: { value?: string } = {};
4555
4559
  const finalProgressHolder: { value?: string } = {};
4560
+ const lastCostHolder: { value?: CostData } = {};
4556
4561
 
4557
4562
  // Context usage throttle: max 1 snapshot per 30 seconds
4558
4563
  let lastContextPostTime = 0;
@@ -4761,6 +4766,11 @@ async function spawnProviderProcess(
4761
4766
  break;
4762
4767
  }
4763
4768
  case "result":
4769
+ lastCostHolder.value = {
4770
+ ...event.cost,
4771
+ taskId: realTaskId,
4772
+ sessionId: opts.runnerSessionId,
4773
+ };
4764
4774
  {
4765
4775
  // Mid-session snapshot — fires on each streamed "result" event,
4766
4776
  // necessarily before `ProviderResult.appliedReasoningEffort` exists
@@ -4968,6 +4978,7 @@ async function spawnProviderProcess(
4968
4978
  }
4969
4979
 
4970
4980
  // Retain cost data for the concurrent final API writes.
4981
+ result.cost ??= lastCostHolder.value;
4971
4982
  if (result.cost) {
4972
4983
  result.cost = { ...result.cost, taskId: realTaskId, sessionId: opts.runnerSessionId };
4973
4984
  sessionSpan.setAttributes({
@@ -5130,6 +5141,7 @@ async function spawnProviderProcess(
5130
5141
  model: model || undefined,
5131
5142
  assistantText: assistantTextHolder,
5132
5143
  finalProgress: finalProgressHolder,
5144
+ lastCost: lastCostHolder,
5133
5145
  };
5134
5146
  runningTaskForSessionInit = runningTask;
5135
5147
  if (pendingHarnessVariant !== undefined) {
@@ -5146,7 +5158,7 @@ async function spawnProviderProcess(
5146
5158
  runningTask.result ??= r;
5147
5159
  })
5148
5160
  .catch(() => {
5149
- runningTask.result ??= { exitCode: 1, isError: true };
5161
+ runningTask.result ??= { exitCode: 1, isError: true, cost: lastCostHolder.value };
5150
5162
  });
5151
5163
 
5152
5164
  return runningTask;
@@ -5316,6 +5328,7 @@ export async function reconcileActiveTasks(
5316
5328
  exitCode: 1,
5317
5329
  isError: true,
5318
5330
  sessionId: task.session.sessionId,
5331
+ cost: task.lastCost?.value,
5319
5332
  failureReason: "runner exited without result: provider session did not settle after abort",
5320
5333
  };
5321
5334
  }