@desplega.ai/agent-swarm 1.149.1 → 1.151.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -3
- package/dist/{acp-adapter-vhkzfpjg.js → acp-adapter-ex8hzjfc.js} +5 -5
- package/dist/{actions-9d2694yk.js → actions-2bgpyhww.js} +39 -11
- package/dist/{app-fq2ggynt.js → app-1706zhr1.js} +7 -7
- package/dist/{artifact-gj9arwrr.js → artifact-td4q4dch.js} +1 -1
- package/dist/{assistant-edb6n9nn.js → assistant-bavke5p7.js} +44 -20
- package/dist/{azure-openai-responses-cqar64rc.js → azure-openai-responses-f38x2avq.js} +13 -13
- package/dist/{boot-reembed-msweabbp.js → boot-reembed-3cmrrmpa.js} +9 -9
- package/dist/{boot-reembed-q5wd3tha.js → boot-reembed-nafcmmmc.js} +14 -16
- package/dist/{boot-scrub-logs-3g1az933.js → boot-scrub-logs-cd6a2sq0.js} +5 -5
- package/dist/{claude-adapter-v3rnzsdc.js → claude-adapter-wfp2gzvz.js} +15 -16
- package/dist/{claude-managed-adapter-qvsmh6mv.js → claude-managed-adapter-dsmkcrjy.js} +3 -3
- package/dist/{claude-sdk-session-qxrpsna1.js → claude-sdk-session-bht9jjak.js} +15 -16
- package/dist/{cli-5m0qmvdp.js → cli-0qb1z6s2.js} +1 -1
- package/dist/{cli-9d8ntetj.js → cli-2658f6at.js} +1 -1
- package/dist/{cli-7evafqvy.js → cli-2tbvf1z1.js} +85 -69
- package/dist/{cli-k351hv5k.js → cli-3v9xhjcn.js} +24 -12
- package/dist/{cli-1ebpar1q.js → cli-4wppfkcm.js} +350 -20
- package/dist/{cli-4260r1tg.js → cli-5jd2z7av.js} +97 -84
- package/dist/{cli-cv7s5zdq.js → cli-5tpgq60f.js} +9865 -715
- package/dist/{cli-6skz3rk8.js → cli-7tgcstn2.js} +9 -4
- package/dist/{cli-01g3x1ca.js → cli-9004vfdf.js} +108 -56
- package/dist/{cli-1c94wvcw.js → cli-a1z3h107.js} +124 -99
- package/dist/{cli-9br8ypfv.js → cli-czjtgfys.js} +2 -2
- package/dist/{cli-5my3bjsd.js → cli-d3p82erb.js} +7 -7
- package/dist/{cli-e29gmdmw.js → cli-dv6cdjs2.js} +2 -1
- package/dist/{cli-wby1xnnb.js → cli-f1wky6zp.js} +1 -1
- package/dist/{cli-zvz62chv.js → cli-fm4ytsdk.js} +4 -4
- package/dist/{cli-tg8qj8ee.js → cli-frcta2w4.js} +6 -6
- package/dist/{cli-7xx10h0a.js → cli-g69fdc9g.js} +2 -2
- package/dist/{cli-cmp8g3sw.js → cli-gbfwcd3k.js} +44 -9
- package/dist/{handlers-nsg0bcye.js → cli-gjyvhmmh.js} +97 -45
- package/dist/{cli-08b07b4r.js → cli-ht5rs63n.js} +1 -1
- package/dist/{cli-jecc01cb.js → cli-j4nv2wqy.js} +2 -4
- package/dist/{cli-cd60fv6j.js → cli-j9xczhaq.js} +1 -1
- package/dist/cli-pf9q3696.js +172 -0
- package/dist/{cli-xm87hzbw.js → cli-pgj4a5fb.js} +1 -1
- package/dist/{cli-jezx9b9c.js → cli-ppm4975n.js} +9 -3
- package/dist/{cli-3z634pqe.js → cli-q88st9aj.js} +2 -2
- package/dist/{cli-3sysyjve.js → cli-r2q6pevn.js} +142 -49
- package/dist/{cli-07jd68a1.js → cli-re8z5p8p.js} +1 -1
- package/dist/{cli-qgd4sqz5.js → cli-s14agm5s.js} +121 -14
- package/dist/{cli-svbrpf5q.js → cli-sjaae6ff.js} +9872 -424
- package/dist/{cli-73gq0zxn.js → cli-vwm416m6.js} +13 -13
- package/dist/{cli-4wtq5jjv.js → cli-wbyk465z.js} +1 -1
- package/dist/{cli-3apbzgyk.js → cli-z61ykvam.js} +19 -14
- package/dist/{cli-e06a8a7y.js → cli-zkxymas5.js} +4 -3
- package/dist/cli.js +26 -25
- package/dist/{codex-adapter-jyw7a91z.js → codex-adapter-jjjk8w4m.js} +8 -9
- package/dist/{codex-hook-hfrt9shr.js → codex-hook-8jexc34x.js} +3 -3
- package/dist/{codex-session-runner-bmngj0s5.js → codex-session-runner-nd6ayxkx.js} +8 -9
- package/dist/{commands-n755g391.js → commands-9v4psyq1.js} +5 -5
- package/dist/{db-s1cgh5gv.js → db-wnt58tpe.js} +5 -5
- package/dist/dispatcher-05jh1aqk.js +74 -0
- package/dist/{e2b-p04vmtx0.js → e2b-413b8t4v.js} +1 -1
- package/dist/{google-generative-ai-tsskx7te.js → google-generative-ai-ndjmj5fa.js} +7 -7
- package/dist/{google-vertex-ppw8ydpa.js → google-vertex-fr665tqs.js} +10 -10
- package/dist/handlers-tw90pkh5.js +65 -0
- package/dist/{hook-jf0xe8zh.js → hook-123e2scb.js} +11 -12
- package/dist/{hook-h9cqrm8q.js → hook-sxe3r349.js} +11 -12
- package/dist/{http-nc6pydw5.js → http-ecsar8ez.js} +1442 -581
- package/dist/{index-ezxkds2n.js → index-16js521z.js} +335 -107
- package/dist/{index-769nc012.js → index-hw26vj40.js} +25 -19
- package/dist/{index-0wdy6gwc.js → index-nnrbpcjp.js} +25 -17
- package/dist/index-ymn7em0p.js +25 -0
- package/dist/{index-x1zcj09z.js → index-zj518gf9.js} +26 -20
- package/dist/{keepalive-nesm3xb6.js → keepalive-asqtcm4y.js} +7 -7
- package/dist/{lead-bwy6t2za.js → lead-xbfr7fvt.js} +40 -48
- package/dist/{maintenance-8w393zf0.js → maintenance-qma55qvw.js} +9 -9
- package/dist/{oauth-refresh-sweep-sh8xjy08.js → oauth-refresh-sweep-3s04c6qw.js} +6 -6
- package/dist/{onboard-25ps29h1.js → onboard-drskd386.js} +13 -4
- package/dist/{openai-codex-responses-g7w48y30.js → openai-codex-responses-wy6a43wd.js} +13 -13
- package/dist/{openai-responses-nmeyptke.js → openai-responses-6xwf7bzg.js} +19 -19
- package/dist/{opencode-adapter-dce4wskd.js → opencode-adapter-28axqa09.js} +4 -4
- package/dist/{otel-impl-b93gxnz5.js → otel-impl-943c96er.js} +1 -1
- package/dist/{pi-mono-adapter-zvshk5cj.js → pi-mono-adapter-jcqt71cg.js} +17 -19
- package/dist/{pricing-refresh-5v56x7gb.js → pricing-refresh-mx51az05.js} +7 -7
- package/dist/{rbac-roles-x55cnezn.js → rbac-roles-78baecqd.js} +13 -9
- package/dist/{rbac-roles-0p0s6pbj.js → rbac-roles-wcmrg6sv.js} +7 -7
- package/dist/{render-v2-hyd45w8b.js → render-v2-8zjntgf5.js} +7 -7
- package/dist/{seed-pricing-49gbgn96.js → seed-pricing-jqjs6cws.js} +6 -6
- package/dist/{setup-qvq64vzq.js → setup-4pks0vfk.js} +2 -2
- package/dist/work-objects-wangt792.js +165 -0
- package/dist/{worker-scj60cxg.js → worker-p2mr422x.js} +40 -48
- package/openapi.json +1365 -268
- package/package.json +4 -3
- package/src/agentmail/handlers.ts +95 -66
- package/src/be/budget-refusal-notify.ts +1 -0
- package/src/be/db/tasks/read.ts +3 -0
- package/src/be/db/tasks/write.ts +13 -1
- package/src/be/db-client.ts +5 -0
- package/src/be/db.ts +15 -5
- package/src/be/extensions/db.ts +461 -0
- package/src/be/extensions/validate.ts +107 -0
- package/src/be/memory/boot-reembed.ts +17 -12
- package/src/be/memory/index.ts +12 -0
- package/src/be/memory/providers/openai-embedding.ts +4 -0
- package/src/be/memory/types.ts +2 -0
- package/src/be/migrations/153_deferred_task_wait_members.sql +25 -0
- package/src/be/migrations/154_routing_source.sql +3 -0
- package/src/be/migrations/155_extensions.sql +66 -0
- package/src/be/migrations/156_inbox_item_state_read_at.sql +7 -0
- package/src/be/rbac-roles.ts +3 -2
- package/src/be/scripts/typecheck.ts +59 -41
- package/src/be/seed/schedules-seeder.ts +25 -2
- package/src/be/seed/workflows-seeder.ts +17 -0
- package/src/be/seed-scripts/catalog/delegate.ts +3 -1
- package/src/be/seed-skills/bundled-files.generated.json +1 -1
- package/src/be/seed-skills/index.ts +7 -0
- package/src/be/steering.ts +1 -0
- package/src/be/swarm-config-guard.ts +3 -1
- package/src/commands/credential-refresh.ts +70 -0
- package/src/commands/onboard/compose-generator.ts +14 -2
- package/src/commands/onboard/env-generator.ts +7 -0
- package/src/commands/provider-credentials.ts +2 -25
- package/src/commands/runner.ts +24 -57
- package/src/extensions/apply-task-create.ts +135 -0
- package/src/extensions/bundle-path.ts +10 -0
- package/src/extensions/contract-runtime.ts +7 -0
- package/src/extensions/contract-types.generated.ts +4 -0
- package/src/extensions/contract.ts +270 -0
- package/src/extensions/ctx.ts +186 -0
- package/src/extensions/dispatcher.ts +479 -0
- package/src/extensions/identity.ts +44 -0
- package/src/extensions/lifecycle.ts +281 -0
- package/src/extensions/loader.ts +207 -0
- package/src/extensions/post-bridge.ts +161 -0
- package/src/github/handlers.ts +185 -140
- package/src/gitlab/handlers.ts +97 -77
- package/src/heartbeat/heartbeat.ts +155 -83
- package/src/http/agents.ts +1 -1
- package/src/http/all-routes.ts +1 -0
- package/src/http/approval-requests.ts +1 -0
- package/src/http/apps.ts +14 -9
- package/src/http/config.ts +4 -1
- package/src/http/core.ts +38 -2
- package/src/http/extensions.ts +547 -0
- package/src/http/inbox-state.ts +2 -0
- package/src/http/index.ts +41 -3
- package/src/http/mcp-bridge.ts +96 -62
- package/src/http/mcp.ts +1 -1
- package/src/http/script-runs.ts +5 -0
- package/src/http/status.ts +6 -4
- package/src/http/tasks.ts +51 -30
- package/src/integrations/kapso/inbound.ts +15 -10
- package/src/jira/sync.ts +26 -16
- package/src/linear/sync.ts +26 -16
- package/src/prompts/session-templates.ts +18 -13
- package/src/providers/claude-adapter.ts +21 -8
- package/src/rbac/admission.ts +1 -1
- package/src/rbac/elevated-agents.ts +24 -0
- package/src/rbac/legacy-policy.ts +35 -6
- package/src/rbac/permissions.ts +8 -0
- package/src/scheduler/deferred-task-waits.ts +138 -27
- package/src/scheduler/schedule-task.ts +54 -24
- package/src/scheduler/scheduler.ts +108 -125
- package/src/scripts-runtime/executors/native.ts +5 -1
- package/src/scripts-runtime/executors/types.ts +5 -0
- package/src/scripts-runtime/import-allowlist.ts +79 -19
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/swarm-config.ts +8 -0
- package/src/scripts-runtime/swarm-sdk.ts +3 -0
- package/src/scripts-runtime/types/stdlib.d.ts +16 -3
- package/src/scripts-runtime/types/swarm-extension.d.ts +562 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +16 -3
- package/src/server.ts +6 -0
- package/src/slack/HEURISTICS.md +3 -1
- package/src/slack/actions.ts +21 -16
- package/src/slack/app.ts +2 -0
- package/src/slack/assistant.ts +4 -12
- package/src/slack/blocks.ts +1 -1
- package/src/slack/handlers.ts +107 -19
- package/src/slack/inbound-files.ts +9 -5
- package/src/slack/render-v2.ts +188 -38
- package/src/slack/router.ts +13 -3
- package/src/slack/steering.ts +3 -3
- package/src/slack/thread-buffer.ts +66 -23
- package/src/slack/work-objects.test.ts +252 -0
- package/src/slack/work-objects.ts +118 -0
- package/src/tasks/errors.ts +9 -0
- package/src/tasks/sibling-awareness.ts +35 -1
- package/src/tasks/worker-follow-up.ts +67 -11
- package/src/tests/acp-adapter.test.ts +10 -10
- package/src/tests/agent-fs-live-url.test.ts +40 -0
- package/src/tests/agent-fs-provision-seeder.test.ts +12 -12
- package/src/tests/api-key-tracking.test.ts +18 -18
- package/src/tests/api-key.test.ts +4 -2
- package/src/tests/apps-rbac.test.ts +1 -1
- package/src/tests/apps-spike5.test.ts +1 -1
- package/src/tests/apps-sync-engine.test.ts +8 -8
- package/src/tests/apps-user-config.test.ts +1 -1
- package/src/tests/artifact-sdk.test.ts +8 -8
- package/src/tests/asset-key-mcp.test.ts +2 -0
- package/src/tests/automation-preflight-alert.test.ts +1 -1
- package/src/tests/base-prompt.test.ts +7 -6
- package/src/tests/budget-user-scope.test.ts +1 -1
- package/src/tests/budgets-routes.test.ts +1 -1
- package/src/tests/claude-adapter-binary.test.ts +22 -40
- package/src/tests/claude-adapter-otel.test.ts +13 -7
- package/src/tests/claude-adapter.test.ts +8 -6
- package/src/tests/claude-hook-credentials.test.ts +3 -3
- package/src/tests/claude-managed-adapter.test.ts +4 -4
- package/src/tests/claude-managed-setup.test.ts +3 -3
- package/src/tests/claude-sdk-lifecycle.test.ts +1 -1
- package/src/tests/claude-sdk-transport.test.ts +6 -6
- package/src/tests/claude-stop-hook.test.ts +8 -8
- package/src/tests/claude-worker-parity.test.ts +3 -3
- package/src/tests/codex-adapter-pool-auth-revalidate.test.ts +5 -5
- package/src/tests/codex-adapter.test.ts +7 -5
- package/src/tests/codex-app-server.test.ts +2 -2
- package/src/tests/codex-login.test.ts +15 -15
- package/src/tests/codex-oauth-credential-info.test.ts +4 -4
- package/src/tests/codex-oauth-keep-warm.test.ts +4 -4
- package/src/tests/codex-oauth-refresh-lock.test.ts +1 -1
- package/src/tests/codex-oauth-storage.test.ts +7 -7
- package/src/tests/codex-pool.test.ts +1 -1
- package/src/tests/codex-steering-hook.test.ts +1 -1
- package/src/tests/codex-swarm-events.test.ts +1 -1
- package/src/tests/config-api-only-keys.test.ts +1 -1
- package/src/tests/config-session-auth.test.ts +2 -2
- package/src/tests/connection-embedded-auth.test.ts +20 -18
- package/src/tests/core-auth.test.ts +1 -1
- package/src/tests/create-page-tool.test.ts +3 -3
- package/src/tests/credential-refresh.test.ts +115 -0
- package/src/tests/credential-wait.test.ts +2 -2
- package/src/tests/credentials.test.ts +6 -4
- package/src/tests/db-queries-oauth.test.ts +40 -40
- package/src/tests/defer-task.test.ts +73 -8
- package/src/tests/deferred-task-wait-migration.test.ts +64 -0
- package/src/tests/deferred-task-wake.test.ts +349 -8
- package/src/tests/devin-adapter.test.ts +1 -1
- package/src/tests/devin-api.test.ts +1 -1
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/e2b-dispatch.test.ts +21 -19
- package/src/tests/e2e-claude-transport.test.ts +3 -3
- package/src/tests/e2e-redact.test.ts +6 -6
- package/src/tests/ensure-token.test.ts +68 -68
- package/src/tests/entrypoint-api-readiness.test.ts +1 -1
- package/src/tests/entrypoint-codex-oauth-seed.test.ts +13 -13
- package/src/tests/env-flag.test.ts +1 -0
- package/src/tests/events-http.test.ts +1 -1
- package/src/tests/extensions-db.test.ts +216 -0
- package/src/tests/extensions-dispatcher.test.ts +275 -0
- package/src/tests/extensions-example-heartbeat-remediate.test.ts +69 -0
- package/src/tests/extensions-example-mcp-install.test.ts +63 -0
- package/src/tests/extensions-example-no-exclamation-marks.test.ts +72 -0
- package/src/tests/extensions-example-rewrite-and-suppress.test.ts +70 -0
- package/src/tests/extensions-example-route-slack-channel.test.ts +217 -0
- package/src/tests/extensions-heartbeat.test.ts +291 -0
- package/src/tests/extensions-http.test.ts +431 -0
- package/src/tests/extensions-lead-equivalence.test.ts +49 -0
- package/src/tests/extensions-lifecycle.test.ts +209 -0
- package/src/tests/extensions-loader.test.ts +95 -0
- package/src/tests/extensions-mcp-tools.test.ts +245 -0
- package/src/tests/extensions-pre-task.test.ts +487 -0
- package/src/tests/extensions-run-context.test.ts +41 -0
- package/src/tests/extensions-tool-call.test.ts +288 -0
- package/src/tests/extensions-validate.test.ts +196 -0
- package/src/tests/fixtures/extensions/bad-import/hooks.ts +8 -0
- package/src/tests/fixtures/extensions/bad-import/manifest.json +9 -0
- package/src/tests/fixtures/extensions/bad-return-shape/hooks.ts +10 -0
- package/src/tests/fixtures/extensions/bad-return-shape/manifest.json +9 -0
- package/src/tests/fixtures/extensions/block-tasks-from-source/hooks.ts +22 -0
- package/src/tests/fixtures/extensions/block-tasks-from-source/manifest.json +9 -0
- package/src/tests/fixtures/extensions/ignore-channel/hooks.ts +22 -0
- package/src/tests/fixtures/extensions/ignore-channel/manifest.json +9 -0
- package/src/tests/fixtures/extensions/load.ts +10 -0
- package/src/tests/fixtures/extensions/minimal/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/minimal/manifest.json +9 -0
- package/src/tests/fixtures/extensions/never-fail-long-tasks/hooks.ts +11 -0
- package/src/tests/fixtures/extensions/never-fail-long-tasks/manifest.json +9 -0
- package/src/tests/fixtures/extensions/no-exclamation-marks/hooks.ts +23 -0
- package/src/tests/fixtures/extensions/no-exclamation-marks/manifest.json +9 -0
- package/src/tests/fixtures/extensions/post-logger/hooks.ts +9 -0
- package/src/tests/fixtures/extensions/post-logger/manifest.json +9 -0
- package/src/tests/fixtures/extensions/priority-a/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/priority-a/manifest.json +9 -0
- package/src/tests/fixtures/extensions/priority-b/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/priority-b/manifest.json +9 -0
- package/src/tests/fixtures/extensions/record-only-on-tag/hooks.ts +16 -0
- package/src/tests/fixtures/extensions/record-only-on-tag/manifest.json +9 -0
- package/src/tests/fixtures/extensions/reserved-assets/hooks.ts +5 -0
- package/src/tests/fixtures/extensions/reserved-assets/manifest.json +10 -0
- package/src/tests/fixtures/extensions/rewrite-progress-prefix/hooks.ts +22 -0
- package/src/tests/fixtures/extensions/rewrite-progress-prefix/manifest.json +9 -0
- package/src/tests/fixtures/extensions/rewrite-task-priority/hooks.ts +7 -0
- package/src/tests/fixtures/extensions/rewrite-task-priority/manifest.json +9 -0
- package/src/tests/fixtures/extensions/route-channel-to-agent/hooks.ts +26 -0
- package/src/tests/fixtures/extensions/route-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/extensions/slow/hooks.ts +10 -0
- package/src/tests/fixtures/extensions/slow/manifest.json +9 -0
- package/src/tests/fixtures/extensions/suppress-lead-follow-up/hooks.ts +12 -0
- package/src/tests/fixtures/extensions/suppress-lead-follow-up/manifest.json +9 -0
- package/src/tests/fixtures/extensions/throws/hooks.ts +12 -0
- package/src/tests/fixtures/extensions/throws/manifest.json +9 -0
- package/src/tests/fixtures/extensions/worker-runtime/hooks.ts +5 -0
- package/src/tests/fixtures/extensions/worker-runtime/manifest.json +9 -0
- package/src/tests/fs-routes.test.ts +1 -1
- package/src/tests/gitlab-auth.test.ts +10 -10
- package/src/tests/harness-provider-resolution.test.ts +8 -5
- package/src/tests/heartbeat-reroute-decision.test.ts +1 -0
- package/src/tests/helper-credentials.test.ts +137 -0
- package/src/tests/http/context-routes.test.ts +2 -2
- package/src/tests/http-api-integration.test.ts +5 -2
- package/src/tests/http-users.test.ts +1 -1
- package/src/tests/identity-refresh.test.ts +2 -2
- package/src/tests/internal-ai/complete-structured.test.ts +2 -2
- package/src/tests/internal-ai/credentials.test.ts +19 -17
- package/src/tests/jira-metadata.test.ts +1 -1
- package/src/tests/jira-oauth.test.ts +5 -5
- package/src/tests/jira-sync.test.ts +1 -1
- package/src/tests/jira-webhook-lifecycle.test.ts +3 -3
- package/src/tests/jira-webhook.test.ts +2 -2
- package/src/tests/kapso-inbound.test.ts +2 -2
- package/src/tests/kv-http.test.ts +1 -1
- package/src/tests/kv-namespace-resolution.test.ts +1 -1
- package/src/tests/kv-page-proxy.test.ts +2 -2
- package/src/tests/launch-password-rejection.test.ts +2 -2
- package/src/tests/linear-webhook.test.ts +1 -1
- package/src/tests/mcp-oauth-dcr-reuse.test.ts +6 -6
- package/src/tests/mcp-oauth-ensure-token.test.ts +28 -22
- package/src/tests/mcp-oauth-manual-client.test.ts +16 -12
- package/src/tests/mcp-oauth-queries.test.ts +35 -32
- package/src/tests/mcp-oauth-resolve-secrets.test.ts +8 -8
- package/src/tests/mcp-oauth-wrapper.test.ts +20 -20
- package/src/tests/mcp-user-route.test.ts +1 -1
- package/src/tests/memory-edges.test.ts +1 -1
- package/src/tests/memory-edit-authorization.test.ts +32 -0
- package/src/tests/memory-rate-endpoint.test.ts +1 -1
- package/src/tests/memory-rate-tool.test.ts +2 -2
- package/src/tests/memory-rater-e2e.test.ts +1 -1
- package/src/tests/memory-rater-llm-summarizer.test.ts +3 -3
- package/src/tests/memory-rater-llm.test.ts +1 -1
- package/src/tests/model-control.test.ts +3 -0
- package/src/tests/multi-runtime-enabled-stats.test.ts +2 -2
- package/src/tests/multi-runtime-registration.test.ts +111 -17
- package/src/tests/oauth-access-token-tool.test.ts +18 -18
- package/src/tests/oauth-callback-flow.test.ts +8 -8
- package/src/tests/oauth-credential-bindings.test.ts +29 -27
- package/src/tests/oauth-keepalive.test.ts +10 -10
- package/src/tests/oauth-presets.test.ts +13 -5
- package/src/tests/oauth-refresh-failure.test.ts +9 -9
- package/src/tests/oauth-refresh-sweep.test.ts +20 -13
- package/src/tests/oauth-wrapper.test.ts +1 -1
- package/src/tests/onboard-compose.test.ts +47 -3
- package/src/tests/onboard-env.test.ts +26 -26
- package/src/tests/onboard-non-interactive.test.ts +4 -4
- package/src/tests/opencode-adapter.test.ts +1 -1
- package/src/tests/opencode-plugin.test.ts +2 -2
- package/src/tests/otel-session-cost-metrics.test.ts +1 -1
- package/src/tests/page-proxy-authed.test.ts +2 -2
- package/src/tests/page-proxy.test.ts +2 -2
- package/src/tests/page-session.test.ts +7 -7
- package/src/tests/page-viewer-auth.test.ts +2 -2
- package/src/tests/pages-authed-mode.test.ts +1 -1
- package/src/tests/pages-http.test.ts +1 -1
- package/src/tests/pages-password-mode.test.ts +1 -1
- package/src/tests/pages-public-authed-401.test.ts +1 -1
- package/src/tests/pages-public-html.test.ts +2 -2
- package/src/tests/pages-view-count.test.ts +1 -1
- package/src/tests/pi-mono-adapter.test.ts +10 -10
- package/src/tests/pi-mono-extension.test.ts +2 -2
- package/src/tests/preload.ts +5 -0
- package/src/tests/pricing-routes.test.ts +1 -1
- package/src/tests/profile-sync-warning.test.ts +8 -8
- package/src/tests/profile-sync.test.ts +8 -8
- package/src/tests/prompt-template-session.test.ts +36 -5
- package/src/tests/provider-process-group.test.ts +95 -4
- package/src/tests/providers/pi-cost.test.ts +1 -1
- package/src/tests/queue-stall-alarm.test.ts +1 -1
- package/src/tests/rbac-admission.test.ts +19 -4
- package/src/tests/rbac-charact-http.test.ts +1 -1
- package/src/tests/rbac-e2e-helpers.ts +1 -1
- package/src/tests/rbac-engine.test.ts +39 -0
- package/src/tests/realtime-room-auth.test.ts +1 -1
- package/src/tests/realtime-room-surfaces.test.ts +1 -1
- package/src/tests/reload-config.test.ts +45 -1
- package/src/tests/routing-affinity-inventory.test.ts +1 -1
- package/src/tests/routing-reason-contract.test.ts +76 -3
- package/src/tests/routing-reason-inventory.test.ts +11 -6
- package/src/tests/routing-source.test.ts +53 -0
- package/src/tests/runner-agent-fs-provision-retry.test.ts +1 -1
- package/src/tests/runner-context-preamble.test.ts +1 -1
- package/src/tests/runner-deployment-resume.test.ts +1 -1
- package/src/tests/runner-fallback-output.test.ts +1 -1
- package/src/tests/runner-identity-refresh.test.ts +1 -1
- package/src/tests/runner-skills-refresh.test.ts +1 -1
- package/src/tests/schedule-target-type.test.ts +3 -3
- package/src/tests/scheduled-tasks.test.ts +14 -5
- package/src/tests/scheduler-occurrence.test.ts +347 -0
- package/src/tests/script-apis-mcp.test.ts +1 -1
- package/src/tests/script-connections-http.test.ts +61 -58
- package/src/tests/script-connections-mcp.test.ts +1 -1
- package/src/tests/script-connections.test.ts +3 -1
- package/src/tests/script-runs-http.test.ts +15 -7
- package/src/tests/script-workflows-runtime-e2e.test.ts +1 -1
- package/src/tests/scripts-boot-reembed.test.ts +4 -0
- package/src/tests/scripts-embeddings.test.ts +4 -0
- package/src/tests/scripts-external-api.test.ts +1 -1
- package/src/tests/scripts-http.test.ts +1 -1
- package/src/tests/scripts-import-allowlist.test.ts +44 -1
- package/src/tests/scripts-mcp-e2e.test.ts +81 -1
- package/src/tests/scripts-only-gating.test.ts +4 -2
- package/src/tests/scripts-retention.test.ts +1 -1
- package/src/tests/scripts-runtime-identity.test.ts +2 -2
- package/src/tests/scripts-runtime-secret-egress.test.ts +1 -1
- package/src/tests/scripts-runtime.test.ts +6 -4
- package/src/tests/scripts-typecheck.test.ts +21 -0
- package/src/tests/sdk-allowlist.test.ts +1 -1
- package/src/tests/secret-scrubber.test.ts +38 -31
- package/src/tests/seed-registry.test.ts +46 -8
- package/src/tests/seed-schedules.test.ts +44 -9
- package/src/tests/seed-workflows.test.ts +21 -9
- package/src/tests/send-task-output-schema.test.ts +9 -1
- package/src/tests/send-task-requested-by.test.ts +1 -0
- package/src/tests/send-task-slack-routing-guard.test.ts +2 -0
- package/src/tests/session-costs-codex-recompute.test.ts +1 -1
- package/src/tests/session-costs-golden.test.ts +2 -2
- package/src/tests/session-costs-model-key-normalize.test.ts +2 -2
- package/src/tests/session-costs-recompute-all-providers.test.ts +1 -1
- package/src/tests/session-tokens.test.ts +1 -1
- package/src/tests/shutdown-error-scrubbing.test.ts +1 -1
- package/src/tests/slack-blocks.test.ts +12 -1
- package/src/tests/slack-file-tools-attachments.test.ts +1 -1
- package/src/tests/slack-inbound-files.test.ts +222 -86
- package/src/tests/slack-reaction-config.test.ts +5 -4
- package/src/tests/slack-read-boundaries.test.ts +1 -1
- package/src/tests/slack-render-v2.test.ts +196 -4
- package/src/tests/slack-router.test.ts +17 -2
- package/src/tests/slack-steering.test.ts +19 -0
- package/src/tests/status.test.ts +19 -7
- package/src/tests/steering-core.test.ts +1 -1
- package/src/tests/steering-enabled.test.ts +6 -8
- package/src/tests/steering-transport.test.ts +4 -4
- package/src/tests/store-progress-output-guidance.test.ts +34 -0
- package/src/tests/swarm-tool-result-gate.test.ts +11 -11
- package/src/tests/swarm-x-tool.test.ts +7 -5
- package/src/tests/sync-ai-toolbox-skills.test.ts +19 -0
- package/src/tests/task-supersede-resume.test.ts +1 -1
- package/src/tests/task-tool-preload-mcp.test.ts +4 -1
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tasks-requested-by-filter.test.ts +2 -2
- package/src/tests/telemetry-init.test.ts +11 -3
- package/src/tests/tool-annotations.test.ts +1 -1
- package/src/tests/tool-output-agent-id.test.ts +1 -0
- package/src/tests/tool-registrar-no-input.test.ts +42 -1
- package/src/tests/tracker-fold.test.ts +7 -7
- package/src/tests/tracker-tools.test.ts +3 -3
- package/src/tests/ui-followup-lead-delegation.test.ts +1 -0
- package/src/tests/unified-oauth-migration.test.ts +5 -5
- package/src/tests/user-token-rest-auth.test.ts +1 -1
- package/src/tests/user-token-routes.test.ts +1 -1
- package/src/tests/whoami-route.test.ts +1 -1
- package/src/tests/workflow-agent-task.test.ts +15 -13
- package/src/tests/workflow-ctx.test.ts +1 -1
- package/src/tests/workflow-e2e.test.ts +1 -1
- package/src/tests/workflow-engine-v2.test.ts +3 -1
- package/src/tests/workflow-executors.test.ts +2 -2
- package/src/tests/workflow-http-v2.test.ts +8 -6
- package/src/tests/workflow-input-redaction.test.ts +7 -5
- package/src/tests/workflow-integration-io.test.ts +2 -2
- package/src/tests/workflow-llm.test.ts +5 -5
- package/src/tests/workflow-registry.test.ts +1 -1
- package/src/tests/workflow-swarm-script.test.ts +1 -1
- package/src/tests/workflow-triggers-v2.test.ts +23 -21
- package/src/tests/x-composio.test.ts +9 -7
- package/src/tests/x402-client.test.ts +1 -1
- package/src/tests/x402-config.test.ts +28 -41
- package/src/tools/defer-task.ts +156 -24
- package/src/tools/extension-common.ts +84 -0
- package/src/tools/extension-install.ts +65 -0
- package/src/tools/extension-list.ts +66 -0
- package/src/tools/script-common.ts +43 -18
- package/src/tools/send-task.ts +87 -105
- package/src/tools/skills/skill-publish.ts +1 -0
- package/src/tools/store-progress.ts +1 -1
- package/src/tools/task-action.ts +43 -22
- package/src/tools/task-tool-ctx.ts +2 -0
- package/src/tools/templates.ts +2 -1
- package/src/tools/tool-config.ts +3 -1
- package/src/tools/utils.ts +140 -16
- package/src/types.ts +144 -0
- package/src/utils/constants.ts +7 -1
- package/src/utils/credentials.test.ts +16 -16
- package/src/utils/multi-runtime.ts +2 -2
- package/src/utils/steering-enabled.ts +4 -4
- package/src/workflows/executors/agent-task.ts +18 -3
- package/templates/ai-toolbox.manifest.json +7 -1
- package/templates/extensions/README.md +17 -0
- package/templates/extensions/notify-on-complete/README.md +11 -0
- package/templates/extensions/notify-on-complete/hooks.ts +61 -0
- package/templates/extensions/notify-on-complete/manifest.json +7 -0
- package/templates/extensions/require-ticket-ref/README.md +11 -0
- package/templates/extensions/require-ticket-ref/hooks.ts +30 -0
- package/templates/extensions/require-ticket-ref/manifest.json +7 -0
- package/templates/extensions/require-verification-note/README.md +11 -0
- package/templates/extensions/require-verification-note/hooks.ts +32 -0
- package/templates/extensions/require-verification-note/manifest.json +7 -0
- package/templates/schedules/daily-hn-briefing/config.json +1 -1
- package/templates/schedules/gtm-weekly-review/config.json +1 -1
- package/templates/schedules/weekly-code-health-reports/config.json +1 -1
- package/templates/schedules/weekly-dependabot-triage/config.json +1 -1
- package/templates/schedules/weekly-dora-metrics/config.json +1 -1
- package/templates/schedules/weekly-harness-upgrade-check/config.json +1 -1
- package/templates/skills/delegate-work/files/scripts/codex-exec.sh +1 -1
- package/templates/skills/scheduling/content.md +2 -0
- package/templates/skills/serply-search/SKILL.md +95 -0
- package/templates/skills/serply-search/config.json +13 -0
- package/templates/skills/serply-search/content.md +90 -0
- package/templates/skills/swarm-extensions/config.json +14 -0
- package/templates/skills/swarm-extensions/content.md +120 -0
- package/templates/skills/swarm-scripts/SKILL.md +2 -2
- package/templates/skills/swarm-scripts/content.md +2 -2
- package/templates/workflows/claude-code-changelog-watch/config.json +1 -1
- package/templates/workflows/gsc-topic-miner/config.json +1 -1
- package/templates/workflows/linear-drain-loop/config.json +1 -1
- package/templates/workflows/llm-safe-release-context/config.json +1 -1
- package/templates/workflows/ralph-loop/config.json +1 -1
- package/dist/cli-7fehefdf.js +0 -562
- package/dist/cli-ayvy5kde.js +0 -164
- package/dist/cli-ddfw1mc4.js +0 -4322
- package/dist/cli-hzqmgcm2.js +0 -3066
- package/dist/cli-j4d4f6hv.js +0 -338
- package/dist/cli-qgm2pfpq.js +0 -6377
- package/dist/cli-sdzq01t9.js +0 -823
- package/dist/cli-xvkmedgn.js +0 -332
- package/dist/cli-y3pq4v9g.js +0 -664
- package/dist/{anthropic-messages-vs2rabzp.js → anthropic-messages-2y8nktar.js} +19 -19
- package/dist/{claude-managed-setup-f5pmsyrp.js → claude-managed-setup-48dwg9bv.js} +3 -3
- package/dist/{cli-81r683bv.js → cli-ch38q5z4.js} +0 -0
- package/dist/{cli-6664w7y4.js → cli-kj76p1ez.js} +8 -8
- package/dist/{cli-c71mg51n.js → cli-r2fpe7cx.js} +5 -5
- package/dist/{cli-4xz3pmrq.js → cli-y6x0gqtg.js} +16 -16
- package/dist/{index-aa3sa6s8.js → index-2wsdsnmm.js} +1 -1
- package/dist/{mistral-conversations-4ryk7h83.js → mistral-conversations-qhr84ph3.js} +9 -9
- package/dist/{openai-completions-0bqmsajw.js → openai-completions-32rdwmze.js} +19 -19
- package/dist/{openrouter-images-qx18fyp8.js → openrouter-images-9f9ek4rw.js} +3 -3
- package/dist/{pi-messages-79jvzz1d.js → pi-messages-b1mbr6gp.js} +4 -4
|
@@ -427,7 +427,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
427
427
|
test("oauth-apps GET never includes clientSecret", async () => {
|
|
428
428
|
await upsertOAuthApp("vendor_oauth", {
|
|
429
429
|
clientId: "vendor-client",
|
|
430
|
-
clientSecret: "oauth-client-secret-should-not-leak",
|
|
430
|
+
clientSecret: "example-oauth-client-secret-should-not-leak",
|
|
431
431
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
432
432
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
433
433
|
redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
|
|
@@ -447,21 +447,21 @@ describe("/api/script-connections HTTP", () => {
|
|
|
447
447
|
expect(body.oauthApps[0]?.clientId).toBe("vendor-client");
|
|
448
448
|
expect(body.oauthApps[0]).not.toHaveProperty("clientSecret");
|
|
449
449
|
expect(body.oauthApps[0]?.lastRefreshedAt).toBeNull();
|
|
450
|
-
expect(JSON.stringify(body)).not.toContain("oauth-client-secret-should-not-leak");
|
|
450
|
+
expect(JSON.stringify(body)).not.toContain("example-oauth-client-secret-should-not-leak");
|
|
451
451
|
});
|
|
452
452
|
|
|
453
453
|
test("oauth-apps GET includes lastRefreshedAt when tokens are stored", async () => {
|
|
454
454
|
await upsertOAuthApp("vendor_oauth", {
|
|
455
455
|
clientId: "vendor-client",
|
|
456
|
-
clientSecret: "oauth-client-secret-should-not-leak",
|
|
456
|
+
clientSecret: "example-oauth-client-secret-should-not-leak",
|
|
457
457
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
458
458
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
459
459
|
redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
|
|
460
460
|
scopes: "read,write",
|
|
461
461
|
});
|
|
462
462
|
await storeOAuthTokens("vendor_oauth", {
|
|
463
|
-
accessToken: "access-token-should-not-leak",
|
|
464
|
-
refreshToken: "refresh-token-should-not-leak",
|
|
463
|
+
accessToken: "example-access-token-should-not-leak",
|
|
464
|
+
refreshToken: "example-refresh-token-should-not-leak",
|
|
465
465
|
expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
|
|
466
466
|
scope: "read,write",
|
|
467
467
|
});
|
|
@@ -474,8 +474,8 @@ describe("/api/script-connections HTTP", () => {
|
|
|
474
474
|
expect(body.oauthApps[0]?.lastRefreshedAt).toBe(
|
|
475
475
|
(await getOAuthTokens("vendor_oauth"))?.updatedAt,
|
|
476
476
|
);
|
|
477
|
-
expect(res.text).not.toContain("access-token-should-not-leak");
|
|
478
|
-
expect(res.text).not.toContain("refresh-token-should-not-leak");
|
|
477
|
+
expect(res.text).not.toContain("example-access-token-should-not-leak");
|
|
478
|
+
expect(res.text).not.toContain("example-refresh-token-should-not-leak");
|
|
479
479
|
});
|
|
480
480
|
|
|
481
481
|
test("detail returns operations and generated types without secrets", async () => {
|
|
@@ -546,15 +546,15 @@ describe("/api/script-connections HTTP", () => {
|
|
|
546
546
|
test("DELETE oauth app removes app and tokens", async () => {
|
|
547
547
|
await upsertOAuthApp("vendor_oauth", {
|
|
548
548
|
clientId: "vendor-client",
|
|
549
|
-
clientSecret: "oauth-client-secret",
|
|
549
|
+
clientSecret: "example-oauth-client-secret",
|
|
550
550
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
551
551
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
552
552
|
redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
|
|
553
553
|
scopes: "read,write",
|
|
554
554
|
});
|
|
555
555
|
await storeOAuthTokens("vendor_oauth", {
|
|
556
|
-
accessToken: "access-token",
|
|
557
|
-
refreshToken: "refresh-token",
|
|
556
|
+
accessToken: "example-access-token",
|
|
557
|
+
refreshToken: "example-refresh-token",
|
|
558
558
|
expiresAt: "2035-01-01T00:00:00.000Z",
|
|
559
559
|
scope: "read write",
|
|
560
560
|
});
|
|
@@ -573,7 +573,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
573
573
|
// First (oldest) app for the provider + its default authorization.
|
|
574
574
|
await upsertOAuthApp("sibling_oauth", {
|
|
575
575
|
clientId: "first-client",
|
|
576
|
-
clientSecret: "first-secret",
|
|
576
|
+
clientSecret: "example-first-secret",
|
|
577
577
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
578
578
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
579
579
|
redirectUri: "https://api.public.test/api/oauth/callback",
|
|
@@ -583,7 +583,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
583
583
|
if (!first) throw new Error("first app not created");
|
|
584
584
|
const firstAuth = await upsertAuthorization({
|
|
585
585
|
appId: first.id,
|
|
586
|
-
accessToken: "first-access-token",
|
|
586
|
+
accessToken: "example-first-access-token",
|
|
587
587
|
status: "active",
|
|
588
588
|
});
|
|
589
589
|
|
|
@@ -594,14 +594,14 @@ describe("/api/script-connections HTTP", () => {
|
|
|
594
594
|
`INSERT INTO oauth_apps
|
|
595
595
|
(id, provider, clientId, clientSecret, clientSecretEncrypted,
|
|
596
596
|
authorizeUrl, tokenUrl, redirectUri, scopes, createdAt)
|
|
597
|
-
VALUES (?, 'sibling_oauth', 'second-client', 'second-secret', 0,
|
|
597
|
+
VALUES (?, 'sibling_oauth', 'second-client', 'example-second-secret', 0,
|
|
598
598
|
'https://oauth.vendor.test/authorize', 'https://oauth.vendor.test/token',
|
|
599
599
|
'https://api.public.test/api/oauth/callback', '[]', ?)`,
|
|
600
600
|
[secondId, "2035-06-01T00:00:00.000Z"],
|
|
601
601
|
);
|
|
602
602
|
const secondAuth = await upsertAuthorization({
|
|
603
603
|
appId: secondId,
|
|
604
|
-
accessToken: "second-access-token",
|
|
604
|
+
accessToken: "example-second-access-token",
|
|
605
605
|
status: "active",
|
|
606
606
|
});
|
|
607
607
|
|
|
@@ -625,7 +625,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
625
625
|
test("manual authorization refresh failure scrubs echoed secrets from the error", async () => {
|
|
626
626
|
await upsertOAuthApp("leaky_oauth", {
|
|
627
627
|
clientId: "leaky-client",
|
|
628
|
-
clientSecret: "leaky-client-secret-should-not-leak",
|
|
628
|
+
clientSecret: "example-leaky-client-secret-should-not-leak",
|
|
629
629
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
630
630
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
631
631
|
redirectUri: "https://api.public.test/api/oauth/callback",
|
|
@@ -635,8 +635,8 @@ describe("/api/script-connections HTTP", () => {
|
|
|
635
635
|
if (!app) throw new Error("app not created");
|
|
636
636
|
const authorization = await upsertAuthorization({
|
|
637
637
|
appId: app.id,
|
|
638
|
-
accessToken: "leaky-access-token",
|
|
639
|
-
refreshToken: "refresh-secret-should-not-leak",
|
|
638
|
+
accessToken: "example-leaky-access-token",
|
|
639
|
+
refreshToken: "example-refresh-secret-should-not-leak",
|
|
640
640
|
status: "active",
|
|
641
641
|
});
|
|
642
642
|
|
|
@@ -647,7 +647,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
647
647
|
JSON.stringify({
|
|
648
648
|
error: "invalid_grant",
|
|
649
649
|
error_description:
|
|
650
|
-
"bad refresh_token=refresh-secret-should-not-leak client_secret=leaky-client-secret-should-not-leak",
|
|
650
|
+
"bad refresh_token=example-refresh-secret-should-not-leak client_secret=example-leaky-client-secret-should-not-leak",
|
|
651
651
|
}),
|
|
652
652
|
{ status: 400, headers: { "content-type": "application/json" } },
|
|
653
653
|
)) as typeof fetch;
|
|
@@ -657,8 +657,8 @@ describe("/api/script-connections HTTP", () => {
|
|
|
657
657
|
agentId: leadAgentId,
|
|
658
658
|
});
|
|
659
659
|
expect(res.status).toBe(502);
|
|
660
|
-
expect(res.text).not.toContain("refresh-secret-should-not-leak");
|
|
661
|
-
expect(res.text).not.toContain("leaky-client-secret-should-not-leak");
|
|
660
|
+
expect(res.text).not.toContain("example-refresh-secret-should-not-leak");
|
|
661
|
+
expect(res.text).not.toContain("example-leaky-client-secret-should-not-leak");
|
|
662
662
|
});
|
|
663
663
|
|
|
664
664
|
test("oauth app edit (by id) without clientSecret keeps existing secret", async () => {
|
|
@@ -666,7 +666,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
666
666
|
// no-id create must NOT — that path always inserts (see the create tests).
|
|
667
667
|
await upsertOAuthApp("vendor_oauth", {
|
|
668
668
|
clientId: "vendor-client",
|
|
669
|
-
clientSecret: "existing-client-secret",
|
|
669
|
+
clientSecret: "example-existing-client-secret",
|
|
670
670
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
671
671
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
672
672
|
redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
|
|
@@ -690,9 +690,9 @@ describe("/api/script-connections HTTP", () => {
|
|
|
690
690
|
expect(res.status).toBe(200);
|
|
691
691
|
const app = await getOAuthAppById(existing.id);
|
|
692
692
|
expect(app?.clientId).toBe("updated-client");
|
|
693
|
-
expect(app?.clientSecret).toBe("existing-client-secret");
|
|
693
|
+
expect(app?.clientSecret).toBe("example-existing-client-secret");
|
|
694
694
|
expect(app?.scopes).toBe("");
|
|
695
|
-
expect(JSON.stringify(await res.json())).not.toContain("existing-client-secret");
|
|
695
|
+
expect(JSON.stringify(await res.json())).not.toContain("example-existing-client-secret");
|
|
696
696
|
});
|
|
697
697
|
|
|
698
698
|
test("POST without id always creates a new row and never clobbers a same-provider sibling", async () => {
|
|
@@ -702,7 +702,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
702
702
|
body: {
|
|
703
703
|
provider: "multi_vendor",
|
|
704
704
|
clientId: "first-client",
|
|
705
|
-
clientSecret: "first-secret",
|
|
705
|
+
clientSecret: "example-first-secret",
|
|
706
706
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
707
707
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
708
708
|
scopes: ["read"],
|
|
@@ -718,7 +718,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
718
718
|
body: {
|
|
719
719
|
provider: "multi_vendor",
|
|
720
720
|
clientId: "second-client",
|
|
721
|
-
clientSecret: "second-secret",
|
|
721
|
+
clientSecret: "example-second-secret",
|
|
722
722
|
authorizeUrl: "https://oauth.vendor.test/authorize2",
|
|
723
723
|
tokenUrl: "https://oauth.vendor.test/token2",
|
|
724
724
|
scopes: ["write"],
|
|
@@ -732,10 +732,10 @@ describe("/api/script-connections HTTP", () => {
|
|
|
732
732
|
const firstApp = await getOAuthAppById(firstId);
|
|
733
733
|
const secondApp = await getOAuthAppById(secondId);
|
|
734
734
|
expect(firstApp?.clientId).toBe("first-client");
|
|
735
|
-
expect(firstApp?.clientSecret).toBe("first-secret");
|
|
735
|
+
expect(firstApp?.clientSecret).toBe("example-first-secret");
|
|
736
736
|
expect(firstApp?.authorizeUrl).toBe("https://oauth.vendor.test/authorize");
|
|
737
737
|
expect(secondApp?.clientId).toBe("second-client");
|
|
738
|
-
expect(secondApp?.clientSecret).toBe("second-secret");
|
|
738
|
+
expect(secondApp?.clientSecret).toBe("example-second-secret");
|
|
739
739
|
});
|
|
740
740
|
|
|
741
741
|
test("POST with id updates only the targeted row, leaving siblings intact", async () => {
|
|
@@ -745,7 +745,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
745
745
|
body: {
|
|
746
746
|
provider: "target_vendor",
|
|
747
747
|
clientId: "orig-a",
|
|
748
|
-
clientSecret: "secret-a",
|
|
748
|
+
clientSecret: "example-secret-a",
|
|
749
749
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
750
750
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
751
751
|
scopes: ["read"],
|
|
@@ -758,7 +758,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
758
758
|
body: {
|
|
759
759
|
provider: "target_vendor",
|
|
760
760
|
clientId: "orig-b",
|
|
761
|
-
clientSecret: "secret-b",
|
|
761
|
+
clientSecret: "example-secret-b",
|
|
762
762
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
763
763
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
764
764
|
scopes: ["read"],
|
|
@@ -773,7 +773,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
773
773
|
id: firstId,
|
|
774
774
|
provider: "target_vendor",
|
|
775
775
|
clientId: "edited-a",
|
|
776
|
-
clientSecret: "secret-a-new",
|
|
776
|
+
clientSecret: "example-secret-a-new",
|
|
777
777
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
778
778
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
779
779
|
scopes: ["read"],
|
|
@@ -781,10 +781,10 @@ describe("/api/script-connections HTTP", () => {
|
|
|
781
781
|
});
|
|
782
782
|
expect(edit.status).toBe(200);
|
|
783
783
|
expect((await getOAuthAppById(firstId))?.clientId).toBe("edited-a");
|
|
784
|
-
expect((await getOAuthAppById(firstId))?.clientSecret).toBe("secret-a-new");
|
|
784
|
+
expect((await getOAuthAppById(firstId))?.clientSecret).toBe("example-secret-a-new");
|
|
785
785
|
// Sibling is untouched.
|
|
786
786
|
expect((await getOAuthAppById(secondId))?.clientId).toBe("orig-b");
|
|
787
|
-
expect((await getOAuthAppById(secondId))?.clientSecret).toBe("secret-b");
|
|
787
|
+
expect((await getOAuthAppById(secondId))?.clientSecret).toBe("example-secret-b");
|
|
788
788
|
});
|
|
789
789
|
|
|
790
790
|
test("POST without id and without clientSecret is rejected (create requires a secret)", async () => {
|
|
@@ -792,7 +792,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
792
792
|
// fallback for a no-id create.
|
|
793
793
|
await upsertOAuthApp("needs_secret", {
|
|
794
794
|
clientId: "sibling-client",
|
|
795
|
-
clientSecret: "sibling-secret",
|
|
795
|
+
clientSecret: "example-sibling-secret",
|
|
796
796
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
797
797
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
798
798
|
redirectUri: "https://api.public.test/api/oauth/needs_secret/callback",
|
|
@@ -821,7 +821,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
821
821
|
body: {
|
|
822
822
|
provider: "linear",
|
|
823
823
|
clientId: "linear-client",
|
|
824
|
-
clientSecret: "linear-secret",
|
|
824
|
+
clientSecret: "example-linear-secret",
|
|
825
825
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
826
826
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
827
827
|
scopes: [],
|
|
@@ -843,7 +843,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
843
843
|
body: {
|
|
844
844
|
provider: "unsafe_vendor",
|
|
845
845
|
clientId: "unsafe-client",
|
|
846
|
-
clientSecret: "unsafe-secret",
|
|
846
|
+
clientSecret: "example-unsafe-secret",
|
|
847
847
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
848
848
|
tokenUrl: "http://127.0.0.1/token",
|
|
849
849
|
scopes: [],
|
|
@@ -859,7 +859,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
859
859
|
body: {
|
|
860
860
|
provider: "safe_vendor",
|
|
861
861
|
clientId: "safe-client",
|
|
862
|
-
clientSecret: "safe-secret",
|
|
862
|
+
clientSecret: "example-safe-secret",
|
|
863
863
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
864
864
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
865
865
|
scopes: [],
|
|
@@ -1193,7 +1193,7 @@ describe("/api/script-connections HTTP", () => {
|
|
|
1193
1193
|
});
|
|
1194
1194
|
|
|
1195
1195
|
describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
|
|
1196
|
-
const ACCESS_TOKEN = "access-token-should-not-leak";
|
|
1196
|
+
const ACCESS_TOKEN = "example-access-token-should-not-leak";
|
|
1197
1197
|
const realFetch = globalThis.fetch;
|
|
1198
1198
|
|
|
1199
1199
|
afterEach(() => {
|
|
@@ -1203,7 +1203,7 @@ describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
|
|
|
1203
1203
|
async function seedOAuthApp(metadata?: Record<string, unknown>) {
|
|
1204
1204
|
await upsertOAuthApp("vendor_oauth", {
|
|
1205
1205
|
clientId: "vendor-client",
|
|
1206
|
-
clientSecret: "oauth-client-secret-should-not-leak",
|
|
1206
|
+
clientSecret: "example-oauth-client-secret-should-not-leak",
|
|
1207
1207
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
1208
1208
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
1209
1209
|
redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
|
|
@@ -1215,7 +1215,7 @@ describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
|
|
|
1215
1215
|
async function seedTokens() {
|
|
1216
1216
|
await storeOAuthTokens("vendor_oauth", {
|
|
1217
1217
|
accessToken: ACCESS_TOKEN,
|
|
1218
|
-
refreshToken: "refresh-token-should-not-leak",
|
|
1218
|
+
refreshToken: "example-refresh-token-should-not-leak",
|
|
1219
1219
|
expiresAt: new Date(Date.now() + 3_600_000).toISOString(),
|
|
1220
1220
|
scope: "read,write",
|
|
1221
1221
|
});
|
|
@@ -1282,13 +1282,13 @@ describe("DELETE /api/oauth-apps/{provider}/tokens", () => {
|
|
|
1282
1282
|
expect(captured?.body).toContain(`token=${ACCESS_TOKEN}`);
|
|
1283
1283
|
// Tokens and secrets must never leak into the HTTP response.
|
|
1284
1284
|
expect(res.text).not.toContain(ACCESS_TOKEN);
|
|
1285
|
-
expect(res.text).not.toContain("oauth-client-secret-should-not-leak");
|
|
1285
|
+
expect(res.text).not.toContain("example-oauth-client-secret-should-not-leak");
|
|
1286
1286
|
});
|
|
1287
1287
|
});
|
|
1288
1288
|
|
|
1289
1289
|
describe("POST /api/oauth-apps/{provider}/refresh", () => {
|
|
1290
|
-
const ACCESS_TOKEN = "access-token-should-not-leak";
|
|
1291
|
-
const REFRESH_TOKEN = "refresh-token-should-not-leak";
|
|
1290
|
+
const ACCESS_TOKEN = "example-access-token-should-not-leak";
|
|
1291
|
+
const REFRESH_TOKEN = "example-refresh-token-should-not-leak";
|
|
1292
1292
|
const realFetch = globalThis.fetch;
|
|
1293
1293
|
|
|
1294
1294
|
afterEach(() => {
|
|
@@ -1298,7 +1298,7 @@ describe("POST /api/oauth-apps/{provider}/refresh", () => {
|
|
|
1298
1298
|
async function seedOAuthApp() {
|
|
1299
1299
|
await upsertOAuthApp("vendor_oauth", {
|
|
1300
1300
|
clientId: "vendor-client",
|
|
1301
|
-
clientSecret: "oauth-client-secret-should-not-leak",
|
|
1301
|
+
clientSecret: "example-oauth-client-secret-should-not-leak",
|
|
1302
1302
|
authorizeUrl: "https://oauth.vendor.test/authorize",
|
|
1303
1303
|
tokenUrl: "https://oauth.vendor.test/token",
|
|
1304
1304
|
redirectUri: "https://api.public.test/api/oauth/vendor_oauth/callback",
|
|
@@ -1356,10 +1356,10 @@ describe("POST /api/oauth-apps/{provider}/refresh", () => {
|
|
|
1356
1356
|
};
|
|
1357
1357
|
return new Response(
|
|
1358
1358
|
JSON.stringify({
|
|
1359
|
-
access_token: "new-access-token-should-not-leak",
|
|
1359
|
+
access_token: "example-new-access-token-should-not-leak",
|
|
1360
1360
|
token_type: "bearer",
|
|
1361
1361
|
expires_in: 7200,
|
|
1362
|
-
refresh_token: "new-refresh-token-should-not-leak",
|
|
1362
|
+
refresh_token: "example-new-refresh-token-should-not-leak",
|
|
1363
1363
|
scope: "read,write",
|
|
1364
1364
|
}),
|
|
1365
1365
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
@@ -1387,16 +1387,16 @@ describe("POST /api/oauth-apps/{provider}/refresh", () => {
|
|
|
1387
1387
|
|
|
1388
1388
|
// Response carries the NEW expiry from the mocked expires_in=7200.
|
|
1389
1389
|
const stored = await getOAuthTokens("vendor_oauth");
|
|
1390
|
-
expect(stored?.accessToken).toBe("new-access-token-should-not-leak");
|
|
1390
|
+
expect(stored?.accessToken).toBe("example-new-access-token-should-not-leak");
|
|
1391
1391
|
expect(body.expiresAt).toBe(stored?.expiresAt ?? "");
|
|
1392
1392
|
expect(new Date(body.expiresAt ?? 0).getTime()).toBeGreaterThan(Date.now() + 3_600_000);
|
|
1393
1393
|
|
|
1394
1394
|
// No token values in the HTTP response.
|
|
1395
1395
|
expect(res.text).not.toContain(ACCESS_TOKEN);
|
|
1396
1396
|
expect(res.text).not.toContain(REFRESH_TOKEN);
|
|
1397
|
-
expect(res.text).not.toContain("new-access-token-should-not-leak");
|
|
1398
|
-
expect(res.text).not.toContain("new-refresh-token-should-not-leak");
|
|
1399
|
-
expect(res.text).not.toContain("oauth-client-secret-should-not-leak");
|
|
1397
|
+
expect(res.text).not.toContain("example-new-access-token-should-not-leak");
|
|
1398
|
+
expect(res.text).not.toContain("example-new-refresh-token-should-not-leak");
|
|
1399
|
+
expect(res.text).not.toContain("example-oauth-client-secret-should-not-leak");
|
|
1400
1400
|
});
|
|
1401
1401
|
|
|
1402
1402
|
test("502 when the provider token endpoint rejects the refresh", async () => {
|
|
@@ -1434,7 +1434,7 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
|
|
|
1434
1434
|
async function seedRotatingAuthorization() {
|
|
1435
1435
|
await upsertOAuthApp("rotator", {
|
|
1436
1436
|
clientId: "rotator-client",
|
|
1437
|
-
clientSecret: "rotator-secret-should-not-leak",
|
|
1437
|
+
clientSecret: "example-rotator-secret-should-not-leak",
|
|
1438
1438
|
authorizeUrl: "https://rotator.test/authorize",
|
|
1439
1439
|
tokenUrl: "https://rotator.test/token",
|
|
1440
1440
|
redirectUri: "https://api.public.test/api/oauth/callback",
|
|
@@ -1445,8 +1445,8 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
|
|
|
1445
1445
|
if (!app) throw new Error("app not created");
|
|
1446
1446
|
return upsertAuthorization({
|
|
1447
1447
|
appId: app.id,
|
|
1448
|
-
accessToken: "old-access-should-not-leak",
|
|
1449
|
-
refreshToken: "old-refresh-should-not-leak",
|
|
1448
|
+
accessToken: "example-old-access-should-not-leak",
|
|
1449
|
+
refreshToken: "example-old-refresh-should-not-leak",
|
|
1450
1450
|
status: "active",
|
|
1451
1451
|
});
|
|
1452
1452
|
}
|
|
@@ -1458,7 +1458,10 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
|
|
|
1458
1458
|
// refresh token.
|
|
1459
1459
|
globalThis.fetch = (async () =>
|
|
1460
1460
|
new Response(
|
|
1461
|
-
JSON.stringify({
|
|
1461
|
+
JSON.stringify({
|
|
1462
|
+
access_token: "example-new-access-should-not-leak",
|
|
1463
|
+
token_type: "bearer",
|
|
1464
|
+
}),
|
|
1462
1465
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
1463
1466
|
)) as typeof fetch;
|
|
1464
1467
|
|
|
@@ -1475,8 +1478,8 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
|
|
|
1475
1478
|
// token may be provider-invalidated, so the sweep must retry it.
|
|
1476
1479
|
const after = await getAuthorizationById(authorization.id);
|
|
1477
1480
|
expect(after?.lastRefreshedAt).toBeNull();
|
|
1478
|
-
expect(after?.accessToken).toBe("old-access-should-not-leak");
|
|
1479
|
-
expect(after?.refreshToken).toBe("old-refresh-should-not-leak");
|
|
1481
|
+
expect(after?.accessToken).toBe("example-old-access-should-not-leak");
|
|
1482
|
+
expect(after?.refreshToken).toBe("example-old-refresh-should-not-leak");
|
|
1480
1483
|
expect(after?.status).toBe("refresh-failed");
|
|
1481
1484
|
});
|
|
1482
1485
|
|
|
@@ -1485,10 +1488,10 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
|
|
|
1485
1488
|
globalThis.fetch = (async () =>
|
|
1486
1489
|
new Response(
|
|
1487
1490
|
JSON.stringify({
|
|
1488
|
-
access_token: "new-access-should-not-leak",
|
|
1491
|
+
access_token: "example-new-access-should-not-leak",
|
|
1489
1492
|
token_type: "bearer",
|
|
1490
1493
|
expires_in: 7200,
|
|
1491
|
-
refresh_token: "rotated-refresh-should-not-leak",
|
|
1494
|
+
refresh_token: "example-rotated-refresh-should-not-leak",
|
|
1492
1495
|
scope: "read,write",
|
|
1493
1496
|
}),
|
|
1494
1497
|
{ status: 200, headers: { "content-type": "application/json" } },
|
|
@@ -1500,7 +1503,7 @@ describe("POST /api/oauth-authorizations/{id}/refresh", () => {
|
|
|
1500
1503
|
});
|
|
1501
1504
|
|
|
1502
1505
|
expect(res.status).toBe(200);
|
|
1503
|
-
expect(res.text).not.toContain("rotated-refresh-should-not-leak");
|
|
1506
|
+
expect(res.text).not.toContain("example-rotated-refresh-should-not-leak");
|
|
1504
1507
|
const body = (await res.json()) as { ok: boolean; status: string };
|
|
1505
1508
|
expect(body.ok).toBe(true);
|
|
1506
1509
|
const after = await getAuthorizationById(authorization.id);
|
|
@@ -30,7 +30,7 @@ import { registerScriptConnectionsTool } from "../tools/script-connections";
|
|
|
30
30
|
import { refreshSecretScrubberCache } from "../utils/secret-scrubber";
|
|
31
31
|
|
|
32
32
|
const TEST_DB_PATH = "./test-script-connections-mcp.sqlite";
|
|
33
|
-
const API_KEY = "test-script-connections-mcp-key-1234567890";
|
|
33
|
+
const API_KEY = "example-test-script-connections-mcp-key-1234567890";
|
|
34
34
|
const SECRET_VALUE = "mcp-secret-value-1234567890";
|
|
35
35
|
|
|
36
36
|
type RegisteredTool = {
|
|
@@ -256,7 +256,7 @@ function serveOpenapiSpec(initialBody: string, initialEtag = '"v1"') {
|
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
beforeEach(() => {
|
|
259
|
-
process.env.AGENT_SWARM_API_KEY = "script-connections-test-key";
|
|
259
|
+
process.env.AGENT_SWARM_API_KEY = "example-script-connections-test-key";
|
|
260
260
|
delete process.env.API_KEY;
|
|
261
261
|
process.env.MCP_BASE_URL = "http://localhost:3013";
|
|
262
262
|
setOpenapiSpecFetchForTesting(fixtureOpenapiFetch);
|
|
@@ -570,6 +570,8 @@ describe("script connections", () => {
|
|
|
570
570
|
markMigrationApplied(database, "151_repair_scheduled_task_required_params.sql");
|
|
571
571
|
// 152 indexes task routing context absent from this migration-112-only fixture.
|
|
572
572
|
markMigrationApplied(database, "152_routing_decisions.sql");
|
|
573
|
+
// 156 alters inbox_item_state, which this migration-112-only fixture does not create.
|
|
574
|
+
markMigrationApplied(database, "156_inbox_item_state_read_at.sql");
|
|
573
575
|
|
|
574
576
|
const id = crypto.randomUUID();
|
|
575
577
|
const now = new Date().toISOString();
|
|
@@ -20,7 +20,7 @@ import { getPathSegments, parseQueryParams } from "../http/utils";
|
|
|
20
20
|
import { refreshSecretScrubberCache } from "../utils/secret-scrubber";
|
|
21
21
|
|
|
22
22
|
const TEST_DB_PATH = "./test-script-runs-http.sqlite";
|
|
23
|
-
const API_KEY = "test-script-runs-http-key-1234567890";
|
|
23
|
+
const API_KEY = "example-test-script-runs-http-key-1234567890";
|
|
24
24
|
|
|
25
25
|
let agentId: string;
|
|
26
26
|
let savedEnv: NodeJS.ProcessEnv;
|
|
@@ -401,7 +401,10 @@ describe("/api/script-runs HTTP", () => {
|
|
|
401
401
|
expect(stepCount.c).toBe(1);
|
|
402
402
|
});
|
|
403
403
|
|
|
404
|
-
test(
|
|
404
|
+
test.each([
|
|
405
|
+
undefined,
|
|
406
|
+
"skill",
|
|
407
|
+
] as const)("agent-task dispatch preserves author pins and routing provenance for %s", async (routingReason) => {
|
|
405
408
|
const created = await dispatch("/api/script-runs", {
|
|
406
409
|
method: "POST",
|
|
407
410
|
agentId,
|
|
@@ -412,7 +415,7 @@ describe("/api/script-runs HTTP", () => {
|
|
|
412
415
|
const responsePromise = dispatch(`/api/internal/script-runs/${runId}/agent-task`, {
|
|
413
416
|
method: "POST",
|
|
414
417
|
agentId,
|
|
415
|
-
body: JSON.stringify({ stepKey: "pinned", task: "do pinned work", agentId }),
|
|
418
|
+
body: JSON.stringify({ stepKey: "pinned", task: "do pinned work", agentId, routingReason }),
|
|
416
419
|
});
|
|
417
420
|
|
|
418
421
|
let dispatched = await getLatestScriptRunStepTaskByContextKey(`script-run:${runId}:pinned`);
|
|
@@ -426,10 +429,15 @@ describe("/api/script-runs HTTP", () => {
|
|
|
426
429
|
expect(response.status).toBe(200);
|
|
427
430
|
const { taskId } = (await response.json()) as { taskId: string };
|
|
428
431
|
expect(
|
|
429
|
-
await getDbClient().get(
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
432
|
+
await getDbClient().get(
|
|
433
|
+
"SELECT agentId, routing_reason, routing_source FROM agent_tasks WHERE id = ?",
|
|
434
|
+
[taskId],
|
|
435
|
+
),
|
|
436
|
+
).toEqual({
|
|
437
|
+
agentId,
|
|
438
|
+
routing_reason: routingReason ?? "human_pinned",
|
|
439
|
+
routing_source: routingReason ? "declared" : "engine_default",
|
|
440
|
+
});
|
|
433
441
|
});
|
|
434
442
|
|
|
435
443
|
test("agent-task polling returns the step output when a newer completed follow-up shares its context key", async () => {
|
|
@@ -32,7 +32,7 @@ import { CHILD_PROCESS_TEST_BUDGET_MS } from "./test-proc";
|
|
|
32
32
|
|
|
33
33
|
const TEST_DB_PATH = "./test-script-workflows-runtime-e2e.sqlite";
|
|
34
34
|
const WORKFLOW_RUNTIME_DIR = "./test-script-workflows-runtime";
|
|
35
|
-
const API_KEY = "test-script-workflows-runtime-key-1234567890";
|
|
35
|
+
const API_KEY = "example-test-script-workflows-runtime-key-1234567890";
|
|
36
36
|
const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
37
37
|
|
|
38
38
|
let agentId: string;
|
|
@@ -23,7 +23,7 @@ import { SKIP_SANDBOX_SPAWN_TESTS } from "./sandbox-spawn-test-helpers";
|
|
|
23
23
|
const skip = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
24
24
|
|
|
25
25
|
const TEST_DB_PATH = "./test-scripts-external-api.sqlite";
|
|
26
|
-
const API_KEY = "test-external-api-key-1234567890";
|
|
26
|
+
const API_KEY = "example-test-external-api-key-1234567890";
|
|
27
27
|
|
|
28
28
|
const noOpEmbeddingProvider = {
|
|
29
29
|
name: "test/noop-script-embedding",
|
|
@@ -15,7 +15,7 @@ import { SKIP_SANDBOX_SPAWN_TESTS } from "./sandbox-spawn-test-helpers";
|
|
|
15
15
|
const skip = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
16
16
|
|
|
17
17
|
const TEST_DB_PATH = "./test-scripts-http.sqlite";
|
|
18
|
-
const API_KEY = "test-scripts-http-key-1234567890";
|
|
18
|
+
const API_KEY = "example-test-scripts-http-key-1234567890";
|
|
19
19
|
|
|
20
20
|
function fakeEmbedding(text: string): Float32Array {
|
|
21
21
|
const lower = text.toLowerCase();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { validateScriptImports } from "../scripts-runtime/import-allowlist";
|
|
2
|
+
import { checkImportAllowlist, validateScriptImports } from "../scripts-runtime/import-allowlist";
|
|
3
3
|
|
|
4
4
|
describe("script import allowlist", () => {
|
|
5
5
|
test("allows relative imports and runtime barrels", () => {
|
|
@@ -61,6 +61,49 @@ describe("script import allowlist", () => {
|
|
|
61
61
|
if (!result.ok) expect(result.diagnostic).toContain("fs");
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
+
test("allows literal dynamic imports from the existing script allowlist", () => {
|
|
65
|
+
expect(validateScriptImports("export default async () => import('zod')")).toEqual({
|
|
66
|
+
ok: true,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("allows computed dynamic imports by default", () => {
|
|
71
|
+
expect(validateScriptImports("const x = 'zod'; export default async () => import(x)")).toEqual({
|
|
72
|
+
ok: true,
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("strictDynamic rejects computed dynamic imports and requires", () => {
|
|
77
|
+
for (const source of [
|
|
78
|
+
"const name = 'zod'; export default async () => import(name)",
|
|
79
|
+
"const name = 'zod'; export default () => require(name)",
|
|
80
|
+
]) {
|
|
81
|
+
const result = checkImportAllowlist(source, {
|
|
82
|
+
allowedBare: ["swarm-extension", "stdlib", "zod"],
|
|
83
|
+
allowRelative: false,
|
|
84
|
+
strictDynamic: true,
|
|
85
|
+
});
|
|
86
|
+
expect(result.ok).toBe(false);
|
|
87
|
+
if (!result.ok) expect(result.diagnostic).toContain("Computed");
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("strictDynamic checks require and import-equals specifiers", () => {
|
|
92
|
+
for (const source of [
|
|
93
|
+
"export default () => require('node:fs')",
|
|
94
|
+
"import fs = require('node:fs'); export default () => fs",
|
|
95
|
+
]) {
|
|
96
|
+
expect(validateScriptImports(source)).toEqual({ ok: true });
|
|
97
|
+
const result = checkImportAllowlist(source, {
|
|
98
|
+
allowedBare: ["swarm-extension", "stdlib", "zod"],
|
|
99
|
+
allowRelative: false,
|
|
100
|
+
strictDynamic: true,
|
|
101
|
+
});
|
|
102
|
+
expect(result.ok).toBe(false);
|
|
103
|
+
if (!result.ok) expect(result.diagnostic).toContain("node:fs");
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
|
|
64
107
|
test("rejects Function constructor dynamic import bypasses", () => {
|
|
65
108
|
const result = validateScriptImports(
|
|
66
109
|
`export default async () => new Function("return import('node:fs')")()`,
|