@desplega.ai/agent-swarm 2.6.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.
- package/README.md +2 -0
- package/dist/{acp-adapter-dgfakfpw.js → acp-adapter-8dn5tq56.js} +6 -6
- package/dist/{actions-fbqma8aa.js → actions-3r6gw7dy.js} +18 -18
- package/dist/{amp-adapter-en0jy6hs.js → amp-adapter-wjtq413p.js} +3 -3
- package/dist/{anthropic-messages-txs190dd.js → anthropic-messages-n4cby1rz.js} +4 -4
- package/dist/{app-k8a5cgpp.js → app-d53yhykk.js} +3 -3
- package/dist/{assistant-a16433gr.js → assistant-ksrawj3k.js} +20 -20
- package/dist/{boot-reembed-6c1sjfnr.js → boot-reembed-fxfw17m2.js} +11 -3
- package/dist/{boot-reembed-f4nn561n.js → boot-reembed-k5y5xbj0.js} +15 -8
- package/dist/{boot-scrub-sweep-d4w9gajf.js → boot-scrub-sweep-se41j9fd.js} +3 -3
- package/dist/{boot-seeds-9bmkspyw.js → boot-seeds-r3kwwv8b.js} +4 -4
- package/dist/{claude-adapter-nys1kjxa.js → claude-adapter-ahmyf231.js} +8 -8
- package/dist/{claude-managed-adapter-55207973.js → claude-managed-adapter-5knamegc.js} +3 -3
- package/dist/{claude-managed-setup-3cm35gey.js → claude-managed-setup-mdc7dy6b.js} +3 -3
- package/dist/{claude-sdk-session-nw5yd8cp.js → claude-sdk-session-n5wen9zk.js} +8729 -8600
- package/dist/{cli-683y0b3a.js → cli-0dqtv2jg.js} +2 -2
- package/dist/{cli-a34pr3w1.js → cli-0tww7dnz.js} +2 -2
- package/dist/{cli-w2656ka1.js → cli-0w4e4v58.js} +7 -7
- package/dist/{cli-5sckpqcx.js → cli-2sjm3t4r.js} +1 -1
- package/dist/{cli-gf2850q7.js → cli-3cywb44q.js} +18 -1
- package/dist/{cli-8wkb09q5.js → cli-3k9jej0c.js} +2 -2
- package/dist/{cli-3aqd4jaa.js → cli-3v2cyqb8.js} +3 -3
- package/dist/{cli-emhjcj2y.js → cli-5qt9vzmq.js} +89 -20
- package/dist/{cli-abkm71vr.js → cli-5rp1w4cr.js} +1 -1
- package/dist/{cli-gf95q3bm.js → cli-6vwjsetx.js} +4 -4
- package/dist/{cli-k21gx5ht.js → cli-6w2yrrc0.js} +10 -10
- package/dist/{cli-m70bajzr.js → cli-75tdydgv.js} +1 -1
- package/dist/{cli-5rj83bam.js → cli-8feswf2v.js} +47 -36
- package/dist/{cli-sxgtf5fw.js → cli-8wd3mbyj.js} +1 -1
- package/dist/{cli-ca6banwz.js → cli-9csfthbw.js} +10 -8
- package/dist/{cli-dqygeeh5.js → cli-b41p764a.js} +31 -3
- package/dist/{cli-m5a9m0ak.js → cli-c1t533hh.js} +3 -3
- package/dist/{cli-2sjhpsns.js → cli-c28jxpcv.js} +1 -1
- package/dist/{cli-bqztfyve.js → cli-cb50g9cd.js} +1 -1
- package/dist/{cli-ag2yrnt5.js → cli-d8gaphtr.js} +2 -2
- package/dist/{cli-9abdgn5t.js → cli-dgtfysne.js} +3 -3
- package/dist/{cli-nq677csy.js → cli-dscnhn18.js} +1 -1
- package/dist/{cli-3fwqy71j.js → cli-dv11pgpv.js} +39 -32
- package/dist/{cli-v49fkghp.js → cli-ekptgk2m.js} +6 -6
- package/dist/{cli-c2habvsf.js → cli-f3mzy662.js} +17 -17
- package/dist/{cli-zqne1qcj.js → cli-fk7k8s9x.js} +2 -2
- package/dist/{cli-1tem6ns9.js → cli-gt4h8cxw.js} +3 -2
- package/dist/{cli-vbhgkw9h.js → cli-h3e7bhvn.js} +3 -3
- package/dist/{cli-ffvsj2qw.js → cli-hkxqdmnb.js} +3 -3
- package/dist/{cli-a2rr0fmg.js → cli-hpkvgdad.js} +7 -4
- package/dist/{cli-art7c1zh.js → cli-hq2v4rr5.js} +37 -9
- package/dist/{cli-sqma6vw1.js → cli-k1zb7raw.js} +5 -5
- package/dist/{cli-4rvr7zfx.js → cli-k4awgvzm.js} +5 -0
- package/dist/{cli-3ndmpxxv.js → cli-k7d3hvya.js} +2 -2
- package/dist/{cli-3gfvmzht.js → cli-kbtdftbw.js} +74 -26
- package/dist/{cli-hfeb68z4.js → cli-kj69b9tw.js} +34 -6
- package/dist/{cli-az25fn5f.js → cli-kk9jy4nm.js} +2 -2
- package/dist/{cli-39aet655.js → cli-m52t4cta.js} +1 -1
- package/dist/{cli-cz37jqss.js → cli-mdadewqp.js} +5 -5
- package/dist/{cli-esakngh8.js → cli-nf6k60sn.js} +1 -1
- package/dist/{cli-j6rktc91.js → cli-nzdf09js.js} +1 -1
- package/dist/{cli-rr7zx19j.js → cli-prcyzecg.js} +12 -12
- package/dist/{cli-4hxrf0p4.js → cli-pzafyqtk.js} +393 -62
- package/dist/{cli-g8ka5j4j.js → cli-qvaa1gjp.js} +173 -52
- package/dist/{cli-d2dpf95n.js → cli-rg4b2g6j.js} +1 -1
- package/dist/{cli-kf4jree9.js → cli-rm66vqdz.js} +1 -1
- package/dist/{cli-4rf0f5vg.js → cli-s504c3w7.js} +5 -3
- package/dist/{cli-nn6vx2mq.js → cli-swkx9jm2.js} +7 -5
- package/dist/{cli-g20jjwt4.js → cli-thsaq4pd.js} +16 -16
- package/dist/{cli-aj8djyqt.js → cli-twjnyvs8.js} +2 -2
- package/dist/{cli-03gg9pd1.js → cli-typdpe8g.js} +4 -4
- package/dist/{cli-mtnj4fwa.js → cli-vg8pwmsd.js} +6 -6
- package/dist/{cli-gnsb1zxa.js → cli-vhpckzvp.js} +1 -1
- package/dist/{cli-7enjwya9.js → cli-vz78s5wm.js} +1 -1
- package/dist/{cli-dv97kdzv.js → cli-wdxgsdz5.js} +2 -2
- package/dist/{cli-7a6p4e65.js → cli-wtjg6je3.js} +1 -1
- package/dist/{cli-6y51ryva.js → cli-x3cngb1h.js} +44 -12
- package/dist/{cli-n7asmce6.js → cli-xbz6mcg4.js} +3 -3
- package/dist/{cli-24j1jeeb.js → cli-y4tdxsqb.js} +3 -3
- package/dist/{cli-mvjz5an3.js → cli-yqrsp3ny.js} +7 -7
- package/dist/cli.js +31 -21
- package/dist/{codex-adapter-d95q4qsn.js → codex-adapter-7wepzq15.js} +6 -6
- package/dist/{codex-hook-brpnycn5.js → codex-hook-pbdh4xhx.js} +2 -2
- package/dist/{codex-session-runner-gdwd8h0c.js → codex-session-runner-02sb49e4.js} +6 -6
- package/dist/{commands-jqmgk54b.js → commands-3rcspxct.js} +2 -2
- package/dist/{controller-z3jq589f.js → controller-8ar4avd6.js} +3 -3
- package/dist/{controllers-connect-r2za39ef.js → controllers-connect-ajvh9h0v.js} +19 -19
- package/dist/{cursor-adapter-4mr4jgkw.js → cursor-adapter-gd0sa7bh.js} +1 -1
- package/dist/{db-w36wwb5g.js → db-dv9j7ts5.js} +2 -2
- package/dist/{db-ppv2tze7.js → db-z26vgdvj.js} +3 -3
- package/dist/{dispatcher-pv5h77vf.js → dispatcher-8m0htjq8.js} +17 -17
- package/dist/{dsh-adapter-d4pdpb3r.js → dsh-adapter-y8gyk130.js} +1 -1
- package/dist/{e2b-fn3zacvt.js → e2b-74vg9b7e.js} +1 -1
- package/dist/{e2b-222hsajc.js → e2b-jyay8wzn.js} +1 -1
- package/dist/{easter-egg-3d-4sp4dvmc.js → easter-egg-3d-28f880xx.js} +1 -1
- package/dist/{execute-jev839y1.js → execute-9seb79vh.js} +1 -1
- package/dist/{external-channel-y6nkzhnn.js → external-channel-smz7jyth.js} +2 -2
- package/dist/{getMachineId-bsd-brn0xym3.js → getMachineId-bsd-whfre6gr.js} +3 -3
- package/dist/{getMachineId-darwin-t339sfxm.js → getMachineId-darwin-5zjynb19.js} +3 -3
- package/dist/{getMachineId-linux-5eq95d8b.js → getMachineId-linux-8mksrrsq.js} +3 -3
- package/dist/{getMachineId-unsupported-qavrtc7j.js → getMachineId-unsupported-fxtqsdt2.js} +3 -3
- package/dist/{getMachineId-win-q7fe1wx7.js → getMachineId-win-nzfmz857.js} +3 -3
- package/dist/{grok-adapter-t08b9ntm.js → grok-adapter-z0nnvtbn.js} +7 -7
- package/dist/handlers-pspryh6g.js +41 -0
- package/dist/{heartbeat-vn31xwdk.js → heartbeat-f928aqyp.js} +20 -20
- package/dist/{hook-cpjs8q51.js → hook-d7c605r4.js} +7 -7
- package/dist/{hook-6d0zbvvt.js → hook-q9hv5xf9.js} +5 -5
- package/dist/{http-9c6medda.js → http-q6j4k989.js} +1000 -251
- package/dist/{index-k0yt1tvq.js → index-5nb266jr.js} +17 -17
- package/dist/{index-ysd45kgc.js → index-8fxt5eah.js} +10 -10
- package/dist/{index-zgvqzjsw.js → index-cekzwhez.js} +5 -5
- package/dist/{index-38t35h0n.js → index-ch0c1xff.js} +17 -17
- package/dist/{index-pkma1yf8.js → index-ebnjhxh1.js} +1 -1
- package/dist/{index-yqgbfgaj.js → index-ed8dy8rn.js} +20 -20
- package/dist/{index-qhjf2htm.js → index-ejqdkkqx.js} +262 -96
- package/dist/{index-dr94zbnh.js → index-farm1zsn.js} +32661 -29443
- package/dist/{index-g6k9tctj.js → index-yn1yxg85.js} +1 -1
- package/dist/{keepalive-em0117bp.js → keepalive-zzc3hks1.js} +3 -3
- package/dist/lead-c0pjcaw4.js +79 -0
- package/dist/{maintenance-kbme3qy9.js → maintenance-kqsxzpzx.js} +1 -1
- package/dist/{oauth-refresh-sweep-xysj4yse.js → oauth-refresh-sweep-7qt0g55z.js} +8 -3
- package/dist/{onboard-p6q0vz97.js → onboard-k7x13fqg.js} +121 -8
- package/dist/{opencode-adapter-esv3k9yn.js → opencode-adapter-tqvrtter.js} +5 -5
- package/dist/{otel-impl-54qhqh1z.js → otel-impl-sqkf6k3b.js} +97 -97
- package/dist/{pi-mono-adapter-mymbwhj0.js → pi-mono-adapter-m2qnafxm.js} +89 -14
- package/dist/{pricing-refresh-yb75wv33.js → pricing-refresh-wkpwhgvs.js} +3 -3
- package/dist/{rbac-roles-dexhc9x8.js → rbac-roles-dpn0c0wj.js} +7 -4
- package/dist/{rbac-roles-1vp2mw4p.js → rbac-roles-wk7xd6a6.js} +2 -2
- package/dist/{render-v2-tjay5hhf.js → render-v2-ex2m4g2k.js} +3 -3
- package/dist/{resume-8ayf37g5.js → resume-725g9b0b.js} +7 -7
- package/dist/{runtime-hqe5cqcd.js → runtime-kajas15g.js} +1 -1
- package/dist/{session-access-fdhp987s.js → session-access-0j2ezjje.js} +8 -4
- package/dist/{session-source-backfill-qgtc86z1.js → session-source-backfill-62202awe.js} +2 -2
- package/dist/{setup-4rrmqcq3.js → setup-9sj11ax6.js} +1 -1
- package/dist/{virtual-modules-52km00d6.js → virtual-modules-c6fcq6zr.js} +2 -2
- package/dist/{work-objects-p28fgd70.js → work-objects-0y07495y.js} +20 -20
- package/dist/worker-d4q9sqbc.js +79 -0
- package/openapi.json +1536 -407
- package/package.json +7 -5
- package/src/be/automation-preflight.ts +2 -0
- package/src/be/connector-codes.ts +65 -22
- package/src/be/db/api-keys.ts +9 -0
- package/src/be/db/workflow-runs.ts +36 -5
- package/src/be/db.ts +80 -22
- package/src/be/memory/boot-reembed.ts +4 -1
- package/src/be/memory/constants.ts +6 -0
- package/src/be/memory/embedding-recovery.ts +48 -0
- package/src/be/memory/index-content.ts +5 -2
- package/src/be/memory/providers/openai-embedding.ts +65 -14
- package/src/be/memory/task-learning.ts +257 -0
- package/src/be/memory/types.ts +13 -2
- package/src/be/migrations/245_script_executor.sql +3 -0
- package/src/be/migrations/246_connector_code_kind.sql +11 -0
- package/src/be/oauth-refresh-sweep.ts +2 -1
- package/src/be/onboarding.ts +125 -15
- package/src/be/rbac-roles.ts +4 -1
- package/src/be/scripts/boot-reembed.ts +2 -0
- package/src/be/scripts/db.ts +14 -4
- package/src/be/scripts/embeddings.ts +4 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +9 -3
- package/src/be/seed/agent-fs-provision.ts +75 -14
- package/src/be/seed-skills/index.ts +7 -0
- package/src/be/swarm-config-guard.ts +3 -0
- package/src/cli.tsx +9 -0
- package/src/comb/config.ts +6 -1
- package/src/commands/onboard/agent-fs-version.ts +5 -0
- package/src/commands/onboard/compose-generator.ts +117 -4
- package/src/commands/onboard/env-generator.ts +9 -0
- package/src/commands/onboard/tei-image.ts +12 -0
- package/src/commands/onboard/types.ts +7 -0
- package/src/commands/onboard.tsx +11 -1
- package/src/commands/provider-credentials.ts +2 -1
- package/src/commands/runner.ts +14 -1
- package/src/heartbeat/heartbeat.ts +14 -1
- package/src/heartbeat/script-runner-probe.ts +47 -0
- package/src/http/agentfs-proxy.ts +369 -0
- package/src/http/all-routes.ts +1 -0
- package/src/http/api-keys.ts +24 -9
- package/src/http/codex-oauth-device.ts +8 -1
- package/src/http/fs.ts +64 -10
- package/src/http/idempotency-key.ts +1 -1
- package/src/http/inbox-state.ts +27 -1
- package/src/http/index.ts +7 -4
- package/src/http/memory.ts +7 -4
- package/src/http/onboarding.ts +139 -11
- package/src/http/pages-public.ts +38 -5
- package/src/http/scripts.ts +27 -0
- package/src/http/session-access.ts +24 -0
- package/src/http/sessions.ts +10 -6
- package/src/http/tasks.ts +85 -11
- package/src/http/telemetry-ui.ts +1 -1
- package/src/http/user-roles.ts +4 -1
- package/src/http/users.ts +272 -3
- package/src/http/utils.ts +22 -3
- package/src/http/workflows.ts +10 -0
- package/src/http/x.ts +5 -0
- package/src/prompts/base-prompt.ts +45 -10
- package/src/prompts/session-templates.ts +43 -5
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/codex-adapter.ts +6 -1
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/pi-mono-adapter.ts +99 -14
- package/src/rbac/legacy-policy.ts +1 -0
- package/src/rbac/permissions.ts +4 -0
- package/src/scheduler/scheduler.ts +2 -1
- package/src/scripts-runtime/eval-harness.ts +8 -1
- package/src/scripts-runtime/executors/native.ts +22 -16
- package/src/scripts-runtime/executors/quickjs-prelude.ts +103 -1
- package/src/scripts-runtime/executors/quickjs-runner.ts +2 -1
- package/src/scripts-runtime/executors/quickjs.ts +7 -0
- package/src/scripts-runtime/executors/registry.ts +32 -0
- package/src/scripts-runtime/executors/types.ts +7 -0
- package/src/scripts-runtime/host-validated-args.ts +133 -0
- package/src/scripts-runtime/loader.ts +30 -3
- package/src/scripts-runtime/swarm-sdk.ts +9 -2
- package/src/scripts-runtime/types/stdlib.d.ts +9 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +9 -1
- package/src/tests/agent-fs-provision-seeder.test.ts +261 -92
- package/src/tests/agentfs-proxy.test.ts +1106 -0
- package/src/tests/api-key-status-by-suffix.test.ts +242 -0
- package/src/tests/base-prompt.test.ts +139 -4
- package/src/tests/codex-adapter.test.ts +46 -8
- package/src/tests/codex-oauth-device.test.ts +12 -1
- package/src/tests/comb-config-guard.test.ts +20 -0
- package/src/tests/comb-links.test.ts +79 -1
- package/src/tests/comb-status.test.ts +44 -0
- package/src/tests/community-linear-delivery-loop.test.ts +2099 -0
- package/src/tests/credential-check.test.ts +4 -2
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/docs-index.test.ts +135 -0
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/fetch-resolved-env.test.ts +16 -2
- package/src/tests/fixtures/onboard/baseline-states.ts +68 -0
- package/src/tests/fixtures/onboard/content.compose.yml.txt +190 -0
- package/src/tests/fixtures/onboard/content.env.txt +29 -0
- package/src/tests/fixtures/onboard/dev.compose.yml.txt +155 -0
- package/src/tests/fixtures/onboard/dev.env.txt +28 -0
- package/src/tests/fixtures/onboard/full-all.compose.yml.txt +582 -0
- package/src/tests/fixtures/onboard/full-all.env.txt +59 -0
- package/src/tests/fixtures/onboard/full.compose.yml.txt +435 -0
- package/src/tests/fixtures/onboard/full.env.txt +36 -0
- package/src/tests/fixtures/onboard/research.compose.yml.txt +155 -0
- package/src/tests/fixtures/onboard/research.env.txt +28 -0
- package/src/tests/fixtures/onboard/solo.compose.yml.txt +85 -0
- package/src/tests/fixtures/onboard/solo.env.txt +26 -0
- package/src/tests/heartbeat-checklist.test.ts +89 -0
- package/src/tests/heartbeat-script-runner-probe.test.ts +83 -0
- package/src/tests/http-log-scrubbing.test.ts +34 -1
- package/src/tests/http-task-write-ownership.test.ts +5 -1
- package/src/tests/invites-http.test.ts +464 -0
- package/src/tests/memory-embedding-input-cap.test.ts +122 -1
- package/src/tests/memory-embedding-recovery.test.ts +137 -0
- package/src/tests/oauth-refresh-sweep.test.ts +34 -1
- package/src/tests/onboard-compose.test.ts +162 -0
- package/src/tests/onboard-env.test.ts +24 -0
- package/src/tests/onboard-non-interactive.test.ts +29 -0
- package/src/tests/onboard-tei-image.test.ts +36 -0
- package/src/tests/onboarding.test.ts +451 -4
- package/src/tests/openai-embedding-provider.test.ts +105 -2
- package/src/tests/opencode-adapter.test.ts +2 -1
- package/src/tests/pages-frame-ancestors.test.ts +162 -0
- package/src/tests/pi-codemode.test.ts +2 -1
- package/src/tests/pi-mono-adapter.test.ts +54 -0
- package/src/tests/pi-mono-session-cost-on-abort.test.ts +270 -0
- package/src/tests/pi-native-mcp.test.ts +13 -1
- package/src/tests/pi-tool-exposure.test.ts +8 -8
- package/src/tests/preload-env.test.ts +4 -0
- package/src/tests/preload.ts +4 -0
- package/src/tests/probe-tool-schema-tokens.test.ts +144 -0
- package/src/tests/prompt-template-session.test.ts +20 -3
- package/src/tests/rbac-admission-e2e.test.ts +22 -6
- package/src/tests/rbac-admission.test.ts +342 -4
- package/src/tests/rbac-engine.test.ts +1 -0
- package/src/tests/rbac-roles.test.ts +9 -1
- package/src/tests/request-composition-derive.test.ts +329 -0
- package/src/tests/script-connections.test.ts +2 -0
- package/src/tests/script-executor-conformance.test.ts +36 -1
- package/src/tests/script-executor-quickjs-pool.test.ts +50 -0
- package/src/tests/script-executor-quickjs.test.ts +140 -0
- package/src/tests/script-host-validated-args-native.test.ts +196 -0
- package/src/tests/script-per-script-executor.test.ts +415 -0
- package/src/tests/scripts-external-api.test.ts +45 -0
- package/src/tests/sdk-allowlist.test.ts +3 -2
- package/src/tests/self-improvement.test.ts +4 -4
- package/src/tests/send-task-requester-gate.test.ts +64 -3
- package/src/tests/sessions-move.test.ts +39 -1
- package/src/tests/store-progress-learning.test.ts +381 -0
- package/src/tests/ui-logs-parser.test.ts +180 -0
- package/src/tests/whoami-route.test.ts +41 -0
- package/src/tests/workflow-engine-v2.test.ts +116 -1
- package/src/tests/workflow-mcp-trigger-schema.test.ts +209 -0
- package/src/tests/workflow-run-finished-event.test.ts +263 -0
- package/src/tests/workflow-swarm-script.test.ts +34 -0
- package/src/tools/inject-learning.ts +1 -1
- package/src/tools/memory-edit.ts +1 -1
- package/src/tools/memory-search.ts +1 -1
- package/src/tools/script-common.ts +1 -0
- package/src/tools/script-run.ts +7 -0
- package/src/tools/script-upsert.ts +7 -0
- package/src/tools/store-progress.ts +71 -1
- package/src/tools/utils.ts +12 -1
- package/src/tools/workflows/trigger-workflow.ts +104 -10
- package/src/types.ts +12 -1
- package/src/utils/constants.ts +39 -0
- package/src/utils/credentials.ts +5 -2
- package/src/utils/task-attachment-links.ts +15 -3
- package/src/workflows/engine.ts +18 -16
- package/src/workflows/executors/swarm-script.ts +5 -0
- package/src/workflows/foreach-driver.ts +5 -11
- package/src/workflows/node-timeout.ts +30 -0
- package/templates/community/linear-delivery-loop/PLAYBOOK.md +323 -0
- package/templates/community/linear-delivery-loop/README.md +38 -0
- package/templates/community/linear-delivery-loop/config.example.json +31 -0
- package/templates/community/linear-delivery-loop/lead-prompt.md +34 -0
- package/templates/community/linear-delivery-loop/schedule.json +10 -0
- package/templates/community/linear-delivery-loop/scripts/linear-delivery-setup.ts +148 -0
- package/templates/community/linear-delivery-loop/scripts/linear-delivery-tick.ts +1781 -0
- package/templates/skills/swarm-docs/config.json +14 -0
- package/templates/skills/swarm-docs/content.md +144 -0
- package/dist/handlers-eqsnmv95.js +0 -41
- package/dist/lead-23e7z59t.js +0 -79
- package/dist/worker-e3w7vye1.js +0 -79
- package/dist/{azure-openai-responses-9kfwhmn7.js → azure-openai-responses-43asa23s.js} +0 -0
- package/dist/{node-vxx896fa.js → node-t28cc56b.js} +0 -0
- package/dist/{openai-codex-responses-79s8xnbh.js → openai-codex-responses-jhr3sjtm.js} +3 -3
- package/dist/{openai-completions-tdbyts0x.js → openai-completions-gs6yn37k.js} +3 -3
- /package/dist/{openai-responses-dm3t5vqp.js → openai-responses-jqm9vwwk.js} +0 -0
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getSwarmConfigs,
|
|
9
9
|
upsertSwarmConfig,
|
|
10
10
|
} from "../db";
|
|
11
|
+
import { getUserGrant } from "../rbac-roles";
|
|
11
12
|
import type { Seeder, SeedItem } from "./types";
|
|
12
13
|
|
|
13
14
|
const KIND = "agent-fs-provision";
|
|
@@ -16,6 +17,10 @@ const PROVISION_VERSION = 1;
|
|
|
16
17
|
const ORG_NAME = "swarm";
|
|
17
18
|
const DRIVE_NAME = "shared";
|
|
18
19
|
const PROVISION_HASH_KEY = "AGENT_FS_PROVISION_HASH";
|
|
20
|
+
// Stored in place of the hash when invites failed transiently. upstreamHash() maps it to
|
|
21
|
+
// null, so the next boot re-applies even when the org, drive and key rows already exist
|
|
22
|
+
// (otherwise the adopt-current-state fallback below would mark the failed run as in sync).
|
|
23
|
+
const PROVISION_RETRY_MARKER = "retry-pending";
|
|
19
24
|
const API_KEY_CONFIG = "API_AGENT_FS_API_KEY";
|
|
20
25
|
const LEGACY_SHARED_KEY_CONFIG = "AGENT_FS_API_KEY";
|
|
21
26
|
|
|
@@ -80,6 +85,7 @@ export const agentFsProvisionSeeder: Seeder<AgentFsSeedItem> = {
|
|
|
80
85
|
|
|
81
86
|
async upstreamHash(): Promise<string | null> {
|
|
82
87
|
const existingHash = await getConfigValue(PROVISION_HASH_KEY);
|
|
88
|
+
if (existingHash === PROVISION_RETRY_MARKER) return null;
|
|
83
89
|
if (existingHash) return existingHash;
|
|
84
90
|
|
|
85
91
|
const hasOrg = !!(await getConfigValue("AGENT_FS_DEFAULT_ORG_ID"));
|
|
@@ -113,16 +119,33 @@ async function provisionAgentFs(item: AgentFsSeedItem): Promise<void> {
|
|
|
113
119
|
shared.orgId,
|
|
114
120
|
);
|
|
115
121
|
|
|
122
|
+
let transientFailures = 0;
|
|
116
123
|
for (const invite of item.invites) {
|
|
117
124
|
const currentRole = currentRoles.get(invite.email.toLowerCase());
|
|
118
125
|
if (currentRole && roleRank(currentRole) >= roleRank(invite.role)) continue;
|
|
119
|
-
await inviteToSharedOrg(item.apiUrl, shared.authHeaders, shared.orgId, invite);
|
|
126
|
+
const outcome = await inviteToSharedOrg(item.apiUrl, shared.authHeaders, shared.orgId, invite);
|
|
127
|
+
if (outcome === "transient-failure") transientFailures++;
|
|
120
128
|
}
|
|
129
|
+
// "no-account" is not a failure to retry: agent-fs has no pending invites. The person's
|
|
130
|
+
// account is created later in the browser, by the /setup Files step or Comb's connect card,
|
|
131
|
+
// and both invite in the same flow. A transient failure (network, 5xx other than not-found,
|
|
132
|
+
// 401/403) must not store the hash, so the next boot re-runs the invites. The org and drive
|
|
133
|
+
// config rows were already written by ensureAgentFsSharedProvisioning above.
|
|
134
|
+
if (transientFailures > 0) {
|
|
135
|
+
await storeProvisionHash(PROVISION_RETRY_MARKER);
|
|
136
|
+
throw new Error(
|
|
137
|
+
`agent-fs invites failed for ${transientFailures} member(s); will retry on next boot`,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
await storeProvisionHash(item.contentHash);
|
|
142
|
+
}
|
|
121
143
|
|
|
144
|
+
async function storeProvisionHash(value: string): Promise<void> {
|
|
122
145
|
await upsertSwarmConfig({
|
|
123
146
|
scope: "global",
|
|
124
147
|
key: PROVISION_HASH_KEY,
|
|
125
|
-
value
|
|
148
|
+
value,
|
|
126
149
|
isSecret: false,
|
|
127
150
|
description: "Internal hash for agent-fs provisioning reconciliation",
|
|
128
151
|
});
|
|
@@ -203,17 +226,31 @@ export async function ensureAgentFsSharedProvisioning(options?: {
|
|
|
203
226
|
return { apiUrl, apiKey, orgId, driveId, authHeaders };
|
|
204
227
|
}
|
|
205
228
|
|
|
229
|
+
export type SharedOrgInviteResult = {
|
|
230
|
+
orgId: string;
|
|
231
|
+
invited: boolean;
|
|
232
|
+
status: "already_member" | "added" | "pending";
|
|
233
|
+
inviteId?: string;
|
|
234
|
+
expiresAt?: string;
|
|
235
|
+
acceptUrl?: string;
|
|
236
|
+
};
|
|
237
|
+
|
|
206
238
|
/**
|
|
207
239
|
* Invite an external (non-agent) member into the shared org using the
|
|
208
240
|
* API-owned bootstrap credentials. Powers `POST /api/fs/members/invite` so
|
|
209
241
|
* callers holding the tenant API key (e.g. the cloud control plane's
|
|
210
242
|
* Connect-to-Drive flow) never need the bootstrap key itself — it is
|
|
211
243
|
* API-only and never served over HTTP.
|
|
244
|
+
*
|
|
245
|
+
* agent-fs (>= 0.18.9) adds an email that has an account directly
|
|
246
|
+
* (`status: "added"`) and answers an email without one with a pending invite
|
|
247
|
+
* (`status: "pending"`, plus `acceptUrl` when its app URL is configured).
|
|
248
|
+
* agent-fs sends no email, so the accept link is passed back to the caller.
|
|
212
249
|
*/
|
|
213
250
|
export async function inviteEmailToSharedOrg(
|
|
214
251
|
email: string,
|
|
215
252
|
role: Role,
|
|
216
|
-
): Promise<
|
|
253
|
+
): Promise<SharedOrgInviteResult> {
|
|
217
254
|
const shared = await ensureAgentFsSharedProvisioning();
|
|
218
255
|
const currentRoles = await getCurrentOrgMemberRoles(
|
|
219
256
|
shared.apiUrl,
|
|
@@ -222,15 +259,31 @@ export async function inviteEmailToSharedOrg(
|
|
|
222
259
|
);
|
|
223
260
|
const currentRole = currentRoles.get(email.trim().toLowerCase());
|
|
224
261
|
if (currentRole && roleRank(currentRole) >= roleRank(role)) {
|
|
225
|
-
return { orgId: shared.orgId, invited: false };
|
|
262
|
+
return { orgId: shared.orgId, invited: false, status: "already_member" };
|
|
226
263
|
}
|
|
227
|
-
await agentFsRequest
|
|
264
|
+
const response = await agentFsRequest<{
|
|
265
|
+
status?: unknown;
|
|
266
|
+
inviteId?: unknown;
|
|
267
|
+
expiresAt?: unknown;
|
|
268
|
+
acceptUrl?: unknown;
|
|
269
|
+
}>(shared.apiUrl, `/orgs/${encodeURIComponent(shared.orgId)}/members/invite`, {
|
|
228
270
|
method: "POST",
|
|
229
271
|
headers: shared.authHeaders,
|
|
230
272
|
body: { email: email.trim(), role },
|
|
231
273
|
allowConflict: true,
|
|
232
274
|
});
|
|
233
|
-
|
|
275
|
+
// Older agent-fs answers a direct add with a bare `{ ok: true }`.
|
|
276
|
+
if (response.status !== "pending") {
|
|
277
|
+
return { orgId: shared.orgId, invited: true, status: "added" };
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
orgId: shared.orgId,
|
|
281
|
+
invited: true,
|
|
282
|
+
status: "pending",
|
|
283
|
+
...(typeof response.inviteId === "string" ? { inviteId: response.inviteId } : {}),
|
|
284
|
+
...(typeof response.expiresAt === "string" ? { expiresAt: response.expiresAt } : {}),
|
|
285
|
+
...(typeof response.acceptUrl === "string" ? { acceptUrl: response.acceptUrl } : {}),
|
|
286
|
+
};
|
|
234
287
|
}
|
|
235
288
|
|
|
236
289
|
export async function ensureAgentFsCredentialsForAgent(agentId: string): Promise<{
|
|
@@ -396,7 +449,7 @@ async function inviteToSharedOrg(
|
|
|
396
449
|
headers: Record<string, string>,
|
|
397
450
|
orgId: string,
|
|
398
451
|
invite: InviteTarget,
|
|
399
|
-
): Promise<
|
|
452
|
+
): Promise<"invited" | "no-account" | "transient-failure"> {
|
|
400
453
|
try {
|
|
401
454
|
await agentFsRequest(apiUrl, `/orgs/${encodeURIComponent(orgId)}/members/invite`, {
|
|
402
455
|
method: "POST",
|
|
@@ -404,6 +457,7 @@ async function inviteToSharedOrg(
|
|
|
404
457
|
body: invite,
|
|
405
458
|
allowConflict: true,
|
|
406
459
|
});
|
|
460
|
+
return "invited";
|
|
407
461
|
} catch (error) {
|
|
408
462
|
console.warn(
|
|
409
463
|
scrubSecrets(
|
|
@@ -412,6 +466,12 @@ async function inviteToSharedOrg(
|
|
|
412
466
|
}`,
|
|
413
467
|
),
|
|
414
468
|
);
|
|
469
|
+
// agent-fs answers an unregistered invitee with HTTP 500 "User with email ... not found".
|
|
470
|
+
const noAccount =
|
|
471
|
+
error instanceof AgentFsRequestError &&
|
|
472
|
+
error.status === 500 &&
|
|
473
|
+
/not found/i.test(error.message);
|
|
474
|
+
return noAccount ? "no-account" : "transient-failure";
|
|
415
475
|
}
|
|
416
476
|
}
|
|
417
477
|
|
|
@@ -499,18 +559,19 @@ async function resolveInviteTargets(): Promise<InviteTarget[]> {
|
|
|
499
559
|
const targets = new Map<string, InviteTarget>();
|
|
500
560
|
|
|
501
561
|
for (const user of await getAllUsers()) {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
562
|
+
const email = user.email?.trim();
|
|
563
|
+
if (!email) continue;
|
|
564
|
+
// Only active users get a seat: invited and suspended users cannot sign in yet.
|
|
565
|
+
if ((user.status ?? "active") !== "active") continue;
|
|
566
|
+
// Follow the RBAC grant, not the free-text profile role, so an RBAC Viewer stays a viewer.
|
|
567
|
+
const grant = await getUserGrant(user.id);
|
|
568
|
+
const role: Role = grant.grantsAll || grant.verbs.has("task.fs.mutate") ? "editor" : "viewer";
|
|
569
|
+
targets.set(email.toLowerCase(), { email, role });
|
|
505
570
|
}
|
|
506
571
|
|
|
507
572
|
return [...targets.values()].sort((a, b) => a.email.localeCompare(b.email));
|
|
508
573
|
}
|
|
509
574
|
|
|
510
|
-
function isExplicitViewerRole(role: string | undefined): boolean {
|
|
511
|
-
return /\b(viewer|read[-\s]?only|guest)\b/i.test(role ?? "");
|
|
512
|
-
}
|
|
513
|
-
|
|
514
575
|
async function provisionHashFromCurrentState(): Promise<string> {
|
|
515
576
|
return provisionHash({
|
|
516
577
|
apiUrl: await resolveApiUrl(),
|
|
@@ -208,6 +208,12 @@ import stepRunningConfig from "../../../templates/skills/step-running/config.jso
|
|
|
208
208
|
import stepRunningContent from "../../../templates/skills/step-running/content.md" with {
|
|
209
209
|
type: "text",
|
|
210
210
|
};
|
|
211
|
+
import swarmDocsConfig from "../../../templates/skills/swarm-docs/config.json" with {
|
|
212
|
+
type: "text",
|
|
213
|
+
};
|
|
214
|
+
import swarmDocsContent from "../../../templates/skills/swarm-docs/content.md" with {
|
|
215
|
+
type: "text",
|
|
216
|
+
};
|
|
211
217
|
import swarmExtensionsConfig from "../../../templates/skills/swarm-extensions/config.json" with {
|
|
212
218
|
type: "text",
|
|
213
219
|
};
|
|
@@ -367,6 +373,7 @@ const BUILT_IN_SKILL_SOURCES = [
|
|
|
367
373
|
{ config: reviewingConfig, body: reviewingContent },
|
|
368
374
|
{ config: scheduledTaskResilienceConfig, body: scheduledTaskResilienceContent },
|
|
369
375
|
{ config: schedulingConfig, body: schedulingContent },
|
|
376
|
+
{ config: swarmDocsConfig, body: swarmDocsContent },
|
|
370
377
|
{ config: swarmExtensionsConfig, body: swarmExtensionsContent },
|
|
371
378
|
{ config: scriptBuilderConfig, body: scriptBuilderContent },
|
|
372
379
|
{ config: scriptWorkflowsConfig, body: scriptWorkflowsContent },
|
|
@@ -410,6 +410,8 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
|
|
|
410
410
|
value,
|
|
411
411
|
"Invalid AGENT_FS_PUBLIC_URL (must be an http(s) URL with no query string or fragment, e.g. https://agent-fs.example.com. Leave blank to use AGENT_FS_API_URL)",
|
|
412
412
|
),
|
|
413
|
+
// Where people-facing file links point. Blank keeps the automatic choice.
|
|
414
|
+
...enumValidator("AGENT_FS_LINK_TARGET", ["dashboard", "live", ""]),
|
|
413
415
|
HARNESS_PROVIDER: (value) => {
|
|
414
416
|
const parsed = ProviderNameSchema.safeParse(value);
|
|
415
417
|
if (parsed.success) return null;
|
|
@@ -520,6 +522,7 @@ const VALIDATED_KEYS: Record<string, ConfigValidator> = {
|
|
|
520
522
|
"DB_RETENTION_DRY_RUN",
|
|
521
523
|
"MODEL_AUTO_UPGRADE",
|
|
522
524
|
"COMB_ENABLED",
|
|
525
|
+
"AGENT_FS_PROXY",
|
|
523
526
|
]),
|
|
524
527
|
...enumValidator("SLACK_MODE", ["socket", "http"]),
|
|
525
528
|
...enumValidator("SLACK_THREAD_STEERING", ["off", "lead", "all"]),
|
package/src/cli.tsx
CHANGED
|
@@ -41,6 +41,7 @@ interface ParsedArgs {
|
|
|
41
41
|
maxConcurrentTasks: string | undefined;
|
|
42
42
|
pullPolicy: string | undefined;
|
|
43
43
|
containerEngine: string | undefined;
|
|
44
|
+
noAgentFs: boolean;
|
|
44
45
|
open: boolean;
|
|
45
46
|
showHelp: boolean;
|
|
46
47
|
dbPath: string;
|
|
@@ -63,6 +64,7 @@ function parseArgs(args: string[]): ParsedArgs {
|
|
|
63
64
|
let maxConcurrentTasks: string | undefined;
|
|
64
65
|
let pullPolicy: string | undefined;
|
|
65
66
|
let containerEngine: string | undefined;
|
|
67
|
+
let noAgentFs = false;
|
|
66
68
|
let open = false;
|
|
67
69
|
let showHelp = false;
|
|
68
70
|
let dbPath = "";
|
|
@@ -122,6 +124,8 @@ function parseArgs(args: string[]): ParsedArgs {
|
|
|
122
124
|
if (value && !value.startsWith("-")) i++;
|
|
123
125
|
} else if (arg?.startsWith("--container-engine=")) {
|
|
124
126
|
containerEngine = arg.slice("--container-engine=".length);
|
|
127
|
+
} else if (arg === "--no-agent-fs") {
|
|
128
|
+
noAgentFs = true;
|
|
125
129
|
} else if (arg === "--open") {
|
|
126
130
|
open = true;
|
|
127
131
|
} else if (arg === "--help" || arg === "-h") {
|
|
@@ -149,6 +153,7 @@ function parseArgs(args: string[]): ParsedArgs {
|
|
|
149
153
|
maxConcurrentTasks,
|
|
150
154
|
pullPolicy,
|
|
151
155
|
containerEngine,
|
|
156
|
+
noAgentFs,
|
|
152
157
|
open,
|
|
153
158
|
showHelp,
|
|
154
159
|
dbPath,
|
|
@@ -185,6 +190,7 @@ const COMMAND_HELP: Record<
|
|
|
185
190
|
" --max-concurrent-tasks <n> Tasks per agent (1-100; default: lead 2, worker 1)",
|
|
186
191
|
" --pull-policy <policy> Pull policy: always, missing, never (default: always)",
|
|
187
192
|
" --container-engine <engine> auto, docker, podman (default: $AGENT_SWARM_CONTAINER_ENGINE, else auto; auto prefers Docker)",
|
|
193
|
+
" --no-agent-fs With --yes: skip the bundled agent-fs (files, Comb) and TEI (memory embeddings)",
|
|
188
194
|
" -h, --help Show this help",
|
|
189
195
|
].join("\n"),
|
|
190
196
|
examples: [
|
|
@@ -192,6 +198,7 @@ const COMMAND_HELP: Record<
|
|
|
192
198
|
` ${binName} onboard --dry-run`,
|
|
193
199
|
` ${binName} onboard --yes --preset=full`,
|
|
194
200
|
` ${binName} onboard --yes --preset=dev`,
|
|
201
|
+
` ${binName} onboard --yes --preset=solo --no-agent-fs`,
|
|
195
202
|
` ${binName} onboard --container-engine=podman`,
|
|
196
203
|
` ANTHROPIC_API_KEY=sk-... ${binName} onboard --yes --preset=solo`,
|
|
197
204
|
].join("\n"),
|
|
@@ -693,6 +700,7 @@ function App({ args }: { args: ParsedArgs }) {
|
|
|
693
700
|
maxConcurrentTasks,
|
|
694
701
|
pullPolicy,
|
|
695
702
|
containerEngine,
|
|
703
|
+
noAgentFs,
|
|
696
704
|
} = args;
|
|
697
705
|
|
|
698
706
|
switch (command) {
|
|
@@ -707,6 +715,7 @@ function App({ args }: { args: ParsedArgs }) {
|
|
|
707
715
|
maxConcurrentTasks,
|
|
708
716
|
pullPolicy,
|
|
709
717
|
containerEngine,
|
|
718
|
+
noAgentFs,
|
|
710
719
|
}}
|
|
711
720
|
/>
|
|
712
721
|
);
|
package/src/comb/config.ts
CHANGED
|
@@ -2,6 +2,8 @@ import {
|
|
|
2
2
|
getAgentFsDefaultDriveId,
|
|
3
3
|
getAgentFsDefaultOrgId,
|
|
4
4
|
getAgentFsLiveUrl,
|
|
5
|
+
getPublicMcpBaseUrl,
|
|
6
|
+
isAgentFsProxyEnabled,
|
|
5
7
|
isCombEnabled,
|
|
6
8
|
} from "../utils/constants";
|
|
7
9
|
|
|
@@ -27,9 +29,12 @@ function trimUrl(value: string | undefined): string | null {
|
|
|
27
29
|
*/
|
|
28
30
|
export function getCombConfig(): CombConfig {
|
|
29
31
|
const internalUrl = trimUrl(process.env.AGENT_FS_API_URL);
|
|
32
|
+
// With the proxy on, the browser reaches agent-fs through the API itself.
|
|
33
|
+
const browserDefault =
|
|
34
|
+
isAgentFsProxyEnabled() && internalUrl ? `${getPublicMcpBaseUrl()}/agentfs` : internalUrl;
|
|
30
35
|
return {
|
|
31
36
|
enabled: isCombEnabled(),
|
|
32
|
-
apiUrl: trimUrl(process.env.AGENT_FS_PUBLIC_URL) ??
|
|
37
|
+
apiUrl: trimUrl(process.env.AGENT_FS_PUBLIC_URL) ?? browserDefault,
|
|
33
38
|
liveUrl: getAgentFsLiveUrl(),
|
|
34
39
|
orgId: getAgentFsDefaultOrgId() ?? null,
|
|
35
40
|
driveId: getAgentFsDefaultDriveId() ?? null,
|
|
@@ -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(
|
|
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,14 +337,22 @@ 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"`);
|
|
244
349
|
lines.push("");
|
|
245
350
|
lines.push(" volumes:");
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
lines.push(
|
|
351
|
+
// Same targets as docker-compose.example.yml: the worker logs to /logs and
|
|
352
|
+
// keeps its clones and files under /workspace.
|
|
353
|
+
lines.push(" - swarm_logs:/logs");
|
|
354
|
+
lines.push(" - swarm_shared:/workspace/shared");
|
|
355
|
+
lines.push(` - swarm_${svc.sanitizedName}:/workspace/personal`);
|
|
249
356
|
if (state.provider === "bedrock" && state.awsProfile) {
|
|
250
357
|
lines.push(engine === "podman" ? AWS_PROFILE_VOLUME_SELINUX : AWS_PROFILE_VOLUME);
|
|
251
358
|
}
|
|
@@ -253,6 +360,8 @@ export function generateCompose(state: OnboardState): string {
|
|
|
253
360
|
lines.push(" restart: unless-stopped");
|
|
254
361
|
}
|
|
255
362
|
|
|
363
|
+
if (state.bundleAgentFs) appendBundleServices(lines, state, port);
|
|
364
|
+
|
|
256
365
|
// ── Volumes section ──
|
|
257
366
|
lines.push("");
|
|
258
367
|
lines.push("volumes:");
|
|
@@ -262,6 +371,10 @@ export function generateCompose(state: OnboardState): string {
|
|
|
262
371
|
for (const svc of expanded) {
|
|
263
372
|
lines.push(` swarm_${svc.sanitizedName}:`);
|
|
264
373
|
}
|
|
374
|
+
if (state.bundleAgentFs) {
|
|
375
|
+
lines.push(" agent_fs_data:");
|
|
376
|
+
lines.push(" tei_data:");
|
|
377
|
+
}
|
|
265
378
|
|
|
266
379
|
return `${lines.join("\n")}\n`;
|
|
267
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
|
};
|
package/src/commands/onboard.tsx
CHANGED
|
@@ -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(() => {
|
|
@@ -49,6 +49,7 @@ import {
|
|
|
49
49
|
CREDENTIAL_POOL_VARS,
|
|
50
50
|
splitCredentialPool,
|
|
51
51
|
} from "../utils/credentials";
|
|
52
|
+
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
52
53
|
import {
|
|
53
54
|
checkAnthropicApiKey,
|
|
54
55
|
checkDeepSeekApiKey,
|
|
@@ -664,7 +665,7 @@ export async function validateProviderCredentials(
|
|
|
664
665
|
* the dashboard surfaces "unreported".
|
|
665
666
|
*/
|
|
666
667
|
export function isCredCheckDisabled(env: NodeJS.ProcessEnv): boolean {
|
|
667
|
-
return
|
|
668
|
+
return isEnvFlagEnabled("CRED_CHECK_DISABLE", false, env);
|
|
668
669
|
}
|
|
669
670
|
|
|
670
671
|
/**
|