@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
|
@@ -4,10 +4,12 @@ import {
|
|
|
4
4
|
closeDb,
|
|
5
5
|
createAgent,
|
|
6
6
|
createUser,
|
|
7
|
+
deleteSwarmConfigByKey,
|
|
7
8
|
getSwarmConfigs,
|
|
8
9
|
initDb,
|
|
9
10
|
upsertSwarmConfig,
|
|
10
11
|
} from "../be/db";
|
|
12
|
+
import { attachRole, detachRole, ensureRbacSeedsSynced } from "../be/rbac-roles";
|
|
11
13
|
import { runSeeder } from "../be/seed";
|
|
12
14
|
import {
|
|
13
15
|
agentFsProvisionSeeder,
|
|
@@ -62,13 +64,38 @@ function restoreEnv(): void {
|
|
|
62
64
|
}
|
|
63
65
|
}
|
|
64
66
|
|
|
67
|
+
async function makeRbacViewer(userId: string): Promise<void> {
|
|
68
|
+
await attachRole(userId, "viewer");
|
|
69
|
+
await detachRole(userId, "admin");
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
async function seedSharedConfig(): Promise<void> {
|
|
73
|
+
await upsertSwarmConfig({
|
|
74
|
+
scope: "global",
|
|
75
|
+
key: "API_AGENT_FS_API_KEY",
|
|
76
|
+
value: "example-afs-admin-key",
|
|
77
|
+
isSecret: true,
|
|
78
|
+
});
|
|
79
|
+
await upsertSwarmConfig({ scope: "global", key: "AGENT_FS_DEFAULT_ORG_ID", value: "shared-org" });
|
|
80
|
+
await upsertSwarmConfig({
|
|
81
|
+
scope: "global",
|
|
82
|
+
key: "AGENT_FS_DEFAULT_DRIVE_ID",
|
|
83
|
+
value: "shared-drive",
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
65
87
|
async function configValue(key: string): Promise<string | undefined> {
|
|
66
88
|
return (await getSwarmConfigs({ scope: "global", key }))[0]?.value;
|
|
67
89
|
}
|
|
68
90
|
|
|
69
91
|
function createFetchStub(
|
|
70
92
|
records: RequestRecord[],
|
|
71
|
-
options: {
|
|
93
|
+
options: {
|
|
94
|
+
members?: StubMember[];
|
|
95
|
+
registerConflictEmail?: string;
|
|
96
|
+
/** A body to send, or a function of the invited email (undefined: the default). */
|
|
97
|
+
inviteResponse?: Record<string, unknown> | ((email: string) => Response | undefined);
|
|
98
|
+
} = {},
|
|
72
99
|
): typeof fetch {
|
|
73
100
|
return (async (input, init) => {
|
|
74
101
|
const url = new URL(String(input));
|
|
@@ -135,7 +162,10 @@ function createFetchStub(
|
|
|
135
162
|
return Response.json({ members: options.members ?? [] });
|
|
136
163
|
}
|
|
137
164
|
if (url.pathname === "/orgs/shared-org/members/invite" && method === "POST") {
|
|
138
|
-
|
|
165
|
+
const invite = options.inviteResponse;
|
|
166
|
+
if (typeof invite !== "function") return Response.json(invite ?? { ok: true });
|
|
167
|
+
const email = body && typeof body === "object" && "email" in body ? String(body.email) : "";
|
|
168
|
+
return invite(email) ?? Response.json({ ok: true });
|
|
139
169
|
}
|
|
140
170
|
|
|
141
171
|
return Response.json(
|
|
@@ -149,6 +179,7 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
149
179
|
beforeAll(async () => {
|
|
150
180
|
await removeDbFiles(TEST_DB_PATH);
|
|
151
181
|
initDb(TEST_DB_PATH);
|
|
182
|
+
ensureRbacSeedsSynced({ quiet: true });
|
|
152
183
|
});
|
|
153
184
|
|
|
154
185
|
afterEach(() => {
|
|
@@ -197,11 +228,12 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
197
228
|
email: `operator-${suffix}@example.test`,
|
|
198
229
|
role: "Operator",
|
|
199
230
|
});
|
|
200
|
-
await createUser({
|
|
231
|
+
const viewer = await createUser({
|
|
201
232
|
name: "Explicit Viewer User",
|
|
202
233
|
email: `viewer-${suffix}@example.test`,
|
|
203
234
|
role: "read-only contractor",
|
|
204
235
|
});
|
|
236
|
+
await makeRbacViewer(viewer.id);
|
|
205
237
|
const records: RequestRecord[] = [];
|
|
206
238
|
setAgentFsProvisionFetchForTests(createFetchStub(records));
|
|
207
239
|
|
|
@@ -249,46 +281,35 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
249
281
|
expect(records).toEqual([]);
|
|
250
282
|
});
|
|
251
283
|
|
|
252
|
-
test("
|
|
284
|
+
test("follows the RBAC grant, not the free-text profile role", async () => {
|
|
253
285
|
const suffix = crypto.randomUUID().slice(0, 8);
|
|
254
286
|
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
255
287
|
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
256
|
-
await
|
|
257
|
-
scope: "global",
|
|
258
|
-
key: "API_AGENT_FS_API_KEY",
|
|
259
|
-
value: "example-afs-admin-key",
|
|
260
|
-
isSecret: true,
|
|
261
|
-
});
|
|
262
|
-
await upsertSwarmConfig({
|
|
263
|
-
scope: "global",
|
|
264
|
-
key: "AGENT_FS_DEFAULT_ORG_ID",
|
|
265
|
-
value: "shared-org",
|
|
266
|
-
});
|
|
267
|
-
await upsertSwarmConfig({
|
|
268
|
-
scope: "global",
|
|
269
|
-
key: "AGENT_FS_DEFAULT_DRIVE_ID",
|
|
270
|
-
value: "shared-drive",
|
|
271
|
-
});
|
|
288
|
+
await seedSharedConfig();
|
|
272
289
|
|
|
290
|
+
// Default trigger role is admin (grant-all): editor even with a "Viewer" profile role.
|
|
273
291
|
await createUser({
|
|
274
|
-
name: "
|
|
275
|
-
email: `
|
|
276
|
-
role: "
|
|
292
|
+
name: "Admin With Viewer Title",
|
|
293
|
+
email: `admin-viewer-title-${suffix}@example.test`,
|
|
294
|
+
role: "Viewer",
|
|
277
295
|
});
|
|
278
|
-
await createUser({
|
|
279
|
-
name: "
|
|
280
|
-
email: `
|
|
281
|
-
role: "
|
|
296
|
+
const requester = await createUser({
|
|
297
|
+
name: "Requester Human",
|
|
298
|
+
email: `requester-${suffix}@example.test`,
|
|
299
|
+
role: "guest",
|
|
282
300
|
});
|
|
283
|
-
await
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
301
|
+
await attachRole(requester.id, "requester");
|
|
302
|
+
await detachRole(requester.id, "admin");
|
|
303
|
+
const viewer = await createUser({
|
|
304
|
+
name: "RBAC Viewer",
|
|
305
|
+
email: `rbac-viewer-${suffix}@example.test`,
|
|
306
|
+
role: "co-founder, CTO",
|
|
287
307
|
});
|
|
308
|
+
await makeRbacViewer(viewer.id);
|
|
288
309
|
await createUser({
|
|
289
|
-
name: "
|
|
290
|
-
email: `
|
|
291
|
-
role: "
|
|
310
|
+
name: "Padded Email",
|
|
311
|
+
email: ` padded-${suffix}@example.test `,
|
|
312
|
+
role: "designer",
|
|
292
313
|
});
|
|
293
314
|
|
|
294
315
|
const records: RequestRecord[] = [];
|
|
@@ -301,59 +322,31 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
301
322
|
.filter((r) => r.path === "/orgs/shared-org/members/invite")
|
|
302
323
|
.map((r) => r.body);
|
|
303
324
|
expect(invites).toContainEqual({
|
|
304
|
-
email: `
|
|
305
|
-
role: "editor",
|
|
306
|
-
});
|
|
307
|
-
expect(invites).toContainEqual({
|
|
308
|
-
email: `eze-founder-${suffix}@example.test`,
|
|
309
|
-
role: "editor",
|
|
310
|
-
});
|
|
311
|
-
expect(invites).toContainEqual({
|
|
312
|
-
email: `designer-${suffix}@example.test`,
|
|
313
|
-
role: "editor",
|
|
314
|
-
});
|
|
315
|
-
expect(invites).toContainEqual({
|
|
316
|
-
email: `whatever-${suffix}@example.test`,
|
|
325
|
+
email: `admin-viewer-title-${suffix}@example.test`,
|
|
317
326
|
role: "editor",
|
|
318
327
|
});
|
|
328
|
+
expect(invites).toContainEqual({ email: `requester-${suffix}@example.test`, role: "editor" });
|
|
329
|
+
expect(invites).toContainEqual({ email: `rbac-viewer-${suffix}@example.test`, role: "viewer" });
|
|
330
|
+
expect(invites).toContainEqual({ email: `padded-${suffix}@example.test`, role: "editor" });
|
|
319
331
|
});
|
|
320
332
|
|
|
321
|
-
test("
|
|
333
|
+
test("does not invite invited or suspended users", async () => {
|
|
322
334
|
const suffix = crypto.randomUUID().slice(0, 8);
|
|
323
335
|
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
324
336
|
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
325
|
-
await
|
|
326
|
-
scope: "global",
|
|
327
|
-
key: "API_AGENT_FS_API_KEY",
|
|
328
|
-
value: "example-afs-admin-key",
|
|
329
|
-
isSecret: true,
|
|
330
|
-
});
|
|
331
|
-
await upsertSwarmConfig({
|
|
332
|
-
scope: "global",
|
|
333
|
-
key: "AGENT_FS_DEFAULT_ORG_ID",
|
|
334
|
-
value: "shared-org",
|
|
335
|
-
});
|
|
336
|
-
await upsertSwarmConfig({
|
|
337
|
-
scope: "global",
|
|
338
|
-
key: "AGENT_FS_DEFAULT_DRIVE_ID",
|
|
339
|
-
value: "shared-drive",
|
|
340
|
-
});
|
|
337
|
+
await seedSharedConfig();
|
|
341
338
|
|
|
342
339
|
await createUser({
|
|
343
|
-
name: "
|
|
344
|
-
email: `
|
|
345
|
-
|
|
346
|
-
});
|
|
347
|
-
await createUser({
|
|
348
|
-
name: "Read Only Human",
|
|
349
|
-
email: `read-only-${suffix}@example.test`,
|
|
350
|
-
role: "read only",
|
|
340
|
+
name: "Pending",
|
|
341
|
+
email: `pending-${suffix}@example.test`,
|
|
342
|
+
status: "invited",
|
|
351
343
|
});
|
|
352
344
|
await createUser({
|
|
353
|
-
name: "
|
|
354
|
-
email: `
|
|
355
|
-
|
|
345
|
+
name: "Suspended",
|
|
346
|
+
email: `suspended-${suffix}@example.test`,
|
|
347
|
+
status: "suspended",
|
|
356
348
|
});
|
|
349
|
+
await createUser({ name: "Active", email: `active-${suffix}@example.test` });
|
|
357
350
|
|
|
358
351
|
const records: RequestRecord[] = [];
|
|
359
352
|
setAgentFsProvisionFetchForTests(createFetchStub(records));
|
|
@@ -361,21 +354,106 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
361
354
|
const result = await runSeeder(agentFsProvisionSeeder, { quiet: true });
|
|
362
355
|
|
|
363
356
|
expect(result.failed).toEqual([]);
|
|
364
|
-
const
|
|
357
|
+
const invited = records
|
|
365
358
|
.filter((r) => r.path === "/orgs/shared-org/members/invite")
|
|
366
|
-
.map((r) => r.body);
|
|
367
|
-
expect(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
359
|
+
.map((r) => (r.body as { email: string }).email);
|
|
360
|
+
expect(invited).toContain(`active-${suffix}@example.test`);
|
|
361
|
+
expect(invited).not.toContain(`pending-${suffix}@example.test`);
|
|
362
|
+
expect(invited).not.toContain(`suspended-${suffix}@example.test`);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
test("a transient invite failure keeps org and drive rows and retries on the next boot", async () => {
|
|
366
|
+
const suffix = crypto.randomUUID().slice(0, 8);
|
|
367
|
+
const flaky = `flaky-${suffix}@example.test`;
|
|
368
|
+
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
369
|
+
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
370
|
+
delete process.env.AGENT_FS_DEFAULT_ORG_ID;
|
|
371
|
+
delete process.env.AGENT_FS_SHARED_ORG_ID;
|
|
372
|
+
delete process.env.AGENT_FS_DEFAULT_DRIVE_ID;
|
|
373
|
+
// Fresh-install shape: no hash and no org or drive rows yet.
|
|
374
|
+
for (const key of [
|
|
375
|
+
"AGENT_FS_PROVISION_HASH",
|
|
376
|
+
"AGENT_FS_DEFAULT_ORG_ID",
|
|
377
|
+
"AGENT_FS_SHARED_ORG_ID",
|
|
378
|
+
"AGENT_FS_DEFAULT_DRIVE_ID",
|
|
379
|
+
]) {
|
|
380
|
+
await deleteSwarmConfigByKey("global", null, key);
|
|
381
|
+
}
|
|
382
|
+
await createUser({ name: "Flaky", email: flaky });
|
|
383
|
+
|
|
384
|
+
const warn = spyOn(console, "warn").mockImplementation(() => {});
|
|
385
|
+
try {
|
|
386
|
+
const records: RequestRecord[] = [];
|
|
387
|
+
setAgentFsProvisionFetchForTests(
|
|
388
|
+
createFetchStub(records, {
|
|
389
|
+
inviteResponse: (email) =>
|
|
390
|
+
email === flaky ? Response.json({ error: "busy" }, { status: 503 }) : undefined,
|
|
391
|
+
}),
|
|
392
|
+
);
|
|
393
|
+
|
|
394
|
+
const failed = await runSeeder(agentFsProvisionSeeder, { quiet: true });
|
|
395
|
+
|
|
396
|
+
expect(failed.failed).toHaveLength(1);
|
|
397
|
+
expect(failed.failed[0]?.error).toContain("will retry on next boot");
|
|
398
|
+
expect(await configValue("AGENT_FS_DEFAULT_ORG_ID")).toBe("shared-org");
|
|
399
|
+
expect(await configValue("AGENT_FS_SHARED_ORG_ID")).toBe("shared-org");
|
|
400
|
+
expect(await configValue("AGENT_FS_DEFAULT_DRIVE_ID")).toBe("shared-drive");
|
|
401
|
+
const [item] = await agentFsProvisionSeeder.items();
|
|
402
|
+
expect(await configValue("AGENT_FS_PROVISION_HASH")).not.toBe(item?.contentHash);
|
|
403
|
+
|
|
404
|
+
records.length = 0;
|
|
405
|
+
setAgentFsProvisionFetchForTests(createFetchStub(records));
|
|
406
|
+
const retried = await runSeeder(agentFsProvisionSeeder, { quiet: true });
|
|
407
|
+
|
|
408
|
+
expect(retried.failed).toEqual([]);
|
|
409
|
+
expect(
|
|
410
|
+
records.filter((r) => r.path === "/orgs/shared-org/members/invite").map((r) => r.body),
|
|
411
|
+
).toContainEqual({ email: flaky, role: "editor" });
|
|
412
|
+
expect(await configValue("AGENT_FS_PROVISION_HASH")).toBe(item?.contentHash);
|
|
413
|
+
|
|
414
|
+
records.length = 0;
|
|
415
|
+
const unchanged = await runSeeder(agentFsProvisionSeeder, { quiet: true });
|
|
416
|
+
expect(unchanged.failed).toEqual([]);
|
|
417
|
+
expect(unchanged.skippedUnchanged).toBe(1);
|
|
418
|
+
expect(records).toEqual([]);
|
|
419
|
+
} finally {
|
|
420
|
+
warn.mockRestore();
|
|
421
|
+
}
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
test("an invite for an unregistered email (500 not found) still stores the hash", async () => {
|
|
425
|
+
const suffix = crypto.randomUUID().slice(0, 8);
|
|
426
|
+
const unregistered = `unregistered-${suffix}@example.test`;
|
|
427
|
+
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
428
|
+
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
429
|
+
await seedSharedConfig();
|
|
430
|
+
await createUser({ name: "Unregistered", email: unregistered });
|
|
431
|
+
|
|
432
|
+
const warn = spyOn(console, "warn").mockImplementation(() => {});
|
|
433
|
+
try {
|
|
434
|
+
const records: RequestRecord[] = [];
|
|
435
|
+
setAgentFsProvisionFetchForTests(
|
|
436
|
+
createFetchStub(records, {
|
|
437
|
+
inviteResponse: (email) =>
|
|
438
|
+
email === unregistered
|
|
439
|
+
? Response.json({ error: `User with email ${email} not found` }, { status: 500 })
|
|
440
|
+
: undefined,
|
|
441
|
+
}),
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
const result = await runSeeder(agentFsProvisionSeeder, { quiet: true });
|
|
445
|
+
|
|
446
|
+
expect(result.failed).toEqual([]);
|
|
447
|
+
const [item] = await agentFsProvisionSeeder.items();
|
|
448
|
+
expect(await configValue("AGENT_FS_PROVISION_HASH")).toBe(item?.contentHash);
|
|
449
|
+
|
|
450
|
+
records.length = 0;
|
|
451
|
+
const second = await runSeeder(agentFsProvisionSeeder, { quiet: true });
|
|
452
|
+
expect(second.skippedUnchanged).toBe(1);
|
|
453
|
+
expect(records).toEqual([]);
|
|
454
|
+
} finally {
|
|
455
|
+
warn.mockRestore();
|
|
456
|
+
}
|
|
379
457
|
});
|
|
380
458
|
|
|
381
459
|
test("does not invite existing members when provisioning would keep or lower their role", async () => {
|
|
@@ -406,7 +484,12 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
406
484
|
await createUser({ name: "Existing Admin", email: existingAdmin, role: "Customer" });
|
|
407
485
|
await createUser({ name: "Existing Editor", email: existingEditor, role: "Designer" });
|
|
408
486
|
await createUser({ name: "Existing Viewer", email: existingViewer, role: "Whatever" });
|
|
409
|
-
await createUser({
|
|
487
|
+
const explicitViewerUser = await createUser({
|
|
488
|
+
name: "Explicit Viewer",
|
|
489
|
+
email: explicitViewer,
|
|
490
|
+
role: "Guest",
|
|
491
|
+
});
|
|
492
|
+
await makeRbacViewer(explicitViewerUser.id);
|
|
410
493
|
|
|
411
494
|
const records: RequestRecord[] = [];
|
|
412
495
|
setAgentFsProvisionFetchForTests(
|
|
@@ -645,7 +728,8 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
645
728
|
|
|
646
729
|
const result = await inviteEmailToSharedOrg("Customer@Example.test ", "admin");
|
|
647
730
|
|
|
648
|
-
|
|
731
|
+
// Default stub answers like pre-0.18.9 agent-fs: a bare `{ ok: true }`.
|
|
732
|
+
expect(result).toEqual({ orgId: "shared-org", invited: true, status: "added" });
|
|
649
733
|
const invite = records.find((r) => r.path === "/orgs/shared-org/members/invite");
|
|
650
734
|
expect(invite?.method).toBe("POST");
|
|
651
735
|
expect(invite?.body).toEqual({ email: "Customer@Example.test", role: "admin" });
|
|
@@ -665,7 +749,92 @@ describe("agent-fs provisioning seeder", () => {
|
|
|
665
749
|
|
|
666
750
|
const result = await inviteEmailToSharedOrg("customer@example.test", "editor");
|
|
667
751
|
|
|
668
|
-
expect(result).toEqual({ orgId: "shared-org", invited: false });
|
|
752
|
+
expect(result).toEqual({ orgId: "shared-org", invited: false, status: "already_member" });
|
|
669
753
|
expect(records.filter((r) => r.path === "/orgs/shared-org/members/invite")).toEqual([]);
|
|
670
754
|
});
|
|
755
|
+
|
|
756
|
+
test("reports an email with an agent-fs account as added, with no accept link", async () => {
|
|
757
|
+
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
758
|
+
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
759
|
+
|
|
760
|
+
const records: RequestRecord[] = [];
|
|
761
|
+
setAgentFsProvisionFetchForTests(
|
|
762
|
+
createFetchStub(records, {
|
|
763
|
+
inviteResponse: {
|
|
764
|
+
ok: true,
|
|
765
|
+
status: "added",
|
|
766
|
+
userId: "customer-user",
|
|
767
|
+
email: "customer@example.test",
|
|
768
|
+
drives: [{ driveId: "shared-drive", role: "editor" }],
|
|
769
|
+
},
|
|
770
|
+
}),
|
|
771
|
+
);
|
|
772
|
+
|
|
773
|
+
const result = await inviteEmailToSharedOrg("customer@example.test", "editor");
|
|
774
|
+
|
|
775
|
+
expect(result).toEqual({ orgId: "shared-org", invited: true, status: "added" });
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
test("returns the pending invite and accept link for an email with no agent-fs account", async () => {
|
|
779
|
+
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
780
|
+
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
781
|
+
|
|
782
|
+
const token = "a".repeat(43);
|
|
783
|
+
const records: RequestRecord[] = [];
|
|
784
|
+
setAgentFsProvisionFetchForTests(
|
|
785
|
+
createFetchStub(records, {
|
|
786
|
+
inviteResponse: {
|
|
787
|
+
ok: true,
|
|
788
|
+
status: "pending",
|
|
789
|
+
inviteId: "invite-1",
|
|
790
|
+
email: "new@example.test",
|
|
791
|
+
token,
|
|
792
|
+
expiresAt: "2026-11-03T00:00:00.000Z",
|
|
793
|
+
drives: [{ driveId: "shared-drive", role: "editor" }],
|
|
794
|
+
acceptUrl: `https://live.agent-fs.example.test/invite/${token}`,
|
|
795
|
+
},
|
|
796
|
+
}),
|
|
797
|
+
);
|
|
798
|
+
|
|
799
|
+
const result = await inviteEmailToSharedOrg("new@example.test", "editor");
|
|
800
|
+
|
|
801
|
+
expect(result).toEqual({
|
|
802
|
+
orgId: "shared-org",
|
|
803
|
+
invited: true,
|
|
804
|
+
status: "pending",
|
|
805
|
+
inviteId: "invite-1",
|
|
806
|
+
expiresAt: "2026-11-03T00:00:00.000Z",
|
|
807
|
+
acceptUrl: `https://live.agent-fs.example.test/invite/${token}`,
|
|
808
|
+
});
|
|
809
|
+
});
|
|
810
|
+
|
|
811
|
+
test("omits acceptUrl on a pending invite when agent-fs has no app URL", async () => {
|
|
812
|
+
process.env.AGENT_FS_API_URL = "https://agent-fs.example.test/";
|
|
813
|
+
process.env.AGENT_FS_REGISTER_EMAIL = "admin@example.test";
|
|
814
|
+
|
|
815
|
+
const records: RequestRecord[] = [];
|
|
816
|
+
setAgentFsProvisionFetchForTests(
|
|
817
|
+
createFetchStub(records, {
|
|
818
|
+
inviteResponse: {
|
|
819
|
+
ok: true,
|
|
820
|
+
status: "pending",
|
|
821
|
+
inviteId: "invite-2",
|
|
822
|
+
email: "new@example.test",
|
|
823
|
+
token: "b".repeat(43),
|
|
824
|
+
expiresAt: "2026-11-03T00:00:00.000Z",
|
|
825
|
+
drives: [],
|
|
826
|
+
},
|
|
827
|
+
}),
|
|
828
|
+
);
|
|
829
|
+
|
|
830
|
+
const result = await inviteEmailToSharedOrg("new@example.test", "viewer");
|
|
831
|
+
|
|
832
|
+
expect(result).toEqual({
|
|
833
|
+
orgId: "shared-org",
|
|
834
|
+
invited: true,
|
|
835
|
+
status: "pending",
|
|
836
|
+
inviteId: "invite-2",
|
|
837
|
+
expiresAt: "2026-11-03T00:00:00.000Z",
|
|
838
|
+
});
|
|
839
|
+
});
|
|
671
840
|
});
|