@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
|
@@ -10,6 +10,7 @@ import { handleCore } from "../http/core";
|
|
|
10
10
|
import { handleScriptRuns } from "../http/script-runs";
|
|
11
11
|
import { handleScripts } from "../http/scripts";
|
|
12
12
|
import { getPathSegments, parseQueryParams } from "../http/utils";
|
|
13
|
+
import { proxyScriptsApi } from "../tools/script-common";
|
|
13
14
|
import { registerScriptDeleteTool } from "../tools/script-delete";
|
|
14
15
|
import { registerScriptRunTool } from "../tools/script-run";
|
|
15
16
|
import { registerScriptRunsTools } from "../tools/script-runs";
|
|
@@ -22,7 +23,7 @@ import { SKIP_SANDBOX_SPAWN_TESTS } from "./sandbox-spawn-test-helpers";
|
|
|
22
23
|
import "../prompts/session-templates";
|
|
23
24
|
|
|
24
25
|
const TEST_DB_PATH = "./test-scripts-mcp-e2e.sqlite";
|
|
25
|
-
const API_KEY = "test-scripts-mcp-key-1234567890";
|
|
26
|
+
const API_KEY = "example-test-scripts-mcp-key-1234567890";
|
|
26
27
|
const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
27
28
|
|
|
28
29
|
function fakeEmbedding(text: string): Float32Array {
|
|
@@ -221,6 +222,85 @@ beforeEach(async () => {
|
|
|
221
222
|
});
|
|
222
223
|
|
|
223
224
|
describe("script_ MCP HTTP proxy tools", () => {
|
|
225
|
+
test.each([200, 502])("rejects HTML responses with HTTP %i", async (status) => {
|
|
226
|
+
const tools = buildToolServer();
|
|
227
|
+
const html = "<!doctype html><html><body>Static site fallback</body></html>";
|
|
228
|
+
const previousFetch = globalThis.fetch;
|
|
229
|
+
globalThis.fetch = (async () =>
|
|
230
|
+
new Response(html, {
|
|
231
|
+
status,
|
|
232
|
+
headers: { "Content-Type": "text/html; charset=utf-8" },
|
|
233
|
+
})) as typeof globalThis.fetch;
|
|
234
|
+
try {
|
|
235
|
+
const result = (await tools.listScriptRuns.handler(
|
|
236
|
+
{ limit: 10, offset: 0 },
|
|
237
|
+
meta(workerId),
|
|
238
|
+
)) as StructuredResult<unknown>;
|
|
239
|
+
|
|
240
|
+
expect(result.isError).toBe(true);
|
|
241
|
+
expect(result.structuredContent.success).toBe(false);
|
|
242
|
+
expect(result.structuredContent.status).toBe(status);
|
|
243
|
+
expect(result.structuredContent.message).toContain("non-JSON");
|
|
244
|
+
expect(result.structuredContent.message).toContain(`HTTP ${status}`);
|
|
245
|
+
expect(result.structuredContent.message).toContain("text/html");
|
|
246
|
+
expect(result.content[0]?.text).toContain(html);
|
|
247
|
+
expect(result.content[0]?.text).not.toContain("Found 0 script run(s)");
|
|
248
|
+
} finally {
|
|
249
|
+
globalThis.fetch = previousFetch;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
test("caps invalid JSON diagnostics without retaining the full body", async () => {
|
|
254
|
+
const body = `<html>${"x".repeat(20_000)}BODY_TAIL</html>`;
|
|
255
|
+
const previousFetch = globalThis.fetch;
|
|
256
|
+
globalThis.fetch = (async () =>
|
|
257
|
+
new Response(body, {
|
|
258
|
+
status: 200,
|
|
259
|
+
headers: { "Content-Type": "application/json" },
|
|
260
|
+
})) as typeof globalThis.fetch;
|
|
261
|
+
try {
|
|
262
|
+
const result = await proxyScriptsApi({
|
|
263
|
+
method: "GET",
|
|
264
|
+
path: "/api/script-runs",
|
|
265
|
+
requestInfo: {
|
|
266
|
+
sessionId: "s",
|
|
267
|
+
agentId: workerId,
|
|
268
|
+
runtimeInstanceId: undefined,
|
|
269
|
+
sourceTaskId: undefined,
|
|
270
|
+
contextKey: undefined,
|
|
271
|
+
callOrigin: "mcp",
|
|
272
|
+
},
|
|
273
|
+
successMessage: () => {
|
|
274
|
+
throw new Error("Invalid JSON must not reach the success callback");
|
|
275
|
+
},
|
|
276
|
+
uncappedDetails: true,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
expect(result.ok).toBe(false);
|
|
280
|
+
expect(result.message).toContain("application/json");
|
|
281
|
+
expect(result.details).toContain("<html>");
|
|
282
|
+
expect(result.details).toContain("[truncated");
|
|
283
|
+
expect(result.details?.length).toBeLessThan(16_100);
|
|
284
|
+
expect(JSON.stringify(result)).not.toContain("BODY_TAIL");
|
|
285
|
+
} finally {
|
|
286
|
+
globalThis.fetch = previousFetch;
|
|
287
|
+
}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test("reports a legitimate JSON empty run list as success", async () => {
|
|
291
|
+
const tools = buildToolServer();
|
|
292
|
+
const result = (await tools.listScriptRuns.handler(
|
|
293
|
+
{ limit: 10, offset: 0 },
|
|
294
|
+
meta(workerId),
|
|
295
|
+
)) as StructuredResult<{ total: number; runs: unknown[] }>;
|
|
296
|
+
|
|
297
|
+
expect(result.isError).toBeFalsy();
|
|
298
|
+
expect(result.structuredContent.success).toBe(true);
|
|
299
|
+
expect(result.structuredContent.status).toBe(200);
|
|
300
|
+
expect(result.structuredContent.data?.runs).toEqual([]);
|
|
301
|
+
expect(result.structuredContent.message).toBe("Found 0 script run(s).");
|
|
302
|
+
});
|
|
303
|
+
|
|
224
304
|
test("upserts the canonical script authoring contract example verbatim", async () => {
|
|
225
305
|
const tools = buildToolServer();
|
|
226
306
|
// The authoring contract lives in the seeded `swarm-scripts` skill since
|
|
@@ -17,6 +17,8 @@ import { listenOnFreePort } from "./test-net";
|
|
|
17
17
|
|
|
18
18
|
const TEST_DB_PATH = "./test-scripts-only-gating.sqlite";
|
|
19
19
|
const SCRIPT_TOOL_NAMES = [
|
|
20
|
+
"extension-install",
|
|
21
|
+
"extension-list",
|
|
20
22
|
"get-script-run",
|
|
21
23
|
"launch-script-run",
|
|
22
24
|
"list-script-runs",
|
|
@@ -193,8 +195,8 @@ beforeEach(async () => {
|
|
|
193
195
|
await scriptsOnlyEnvQueue;
|
|
194
196
|
savedSlackBotToken = process.env.SLACK_BOT_TOKEN;
|
|
195
197
|
savedSlackAppToken = process.env.SLACK_APP_TOKEN;
|
|
196
|
-
process.env.SLACK_BOT_TOKEN = "test-bot-token";
|
|
197
|
-
process.env.SLACK_APP_TOKEN = "test-app-token";
|
|
198
|
+
process.env.SLACK_BOT_TOKEN = "example-test-bot-token";
|
|
199
|
+
process.env.SLACK_APP_TOKEN = "example-test-app-token";
|
|
198
200
|
await getDbClient().run("DELETE FROM swarm_config WHERE key = 'SCRIPTS_ONLY_MCP'");
|
|
199
201
|
});
|
|
200
202
|
|
|
@@ -39,7 +39,7 @@ async function addScript(name: string, isScratch: boolean) {
|
|
|
39
39
|
|
|
40
40
|
describe("scratch script retention", () => {
|
|
41
41
|
beforeAll(async () => {
|
|
42
|
-
process.env.AGENT_SWARM_API_KEY = "scripts-retention-test-key";
|
|
42
|
+
process.env.AGENT_SWARM_API_KEY = "example-scripts-retention-test-key";
|
|
43
43
|
await clearDb();
|
|
44
44
|
initDb(TEST_DB_PATH);
|
|
45
45
|
});
|
|
@@ -30,7 +30,7 @@ import { listenOnFreePort } from "./test-net";
|
|
|
30
30
|
|
|
31
31
|
const TEST_DB_PATH = "./test-scripts-runtime-identity.sqlite";
|
|
32
32
|
let baseUrl = "";
|
|
33
|
-
const API_KEY = "scripts-runtime-identity-key-1234567890";
|
|
33
|
+
const API_KEY = "example-scripts-runtime-identity-key-1234567890";
|
|
34
34
|
const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
35
35
|
|
|
36
36
|
const savedEnv = { ...process.env };
|
|
@@ -374,7 +374,7 @@ describe("script SDK dispatch hits the real runtime gates", () => {
|
|
|
374
374
|
});
|
|
375
375
|
|
|
376
376
|
test("with the flag off, the SDK dispatches without runtime identity as before", async () => {
|
|
377
|
-
|
|
377
|
+
process.env.MULTI_RUNTIME_ENABLED = "false";
|
|
378
378
|
const agentId = await makeAgent(1);
|
|
379
379
|
const task = await createTaskExtended("legacy-claim-work");
|
|
380
380
|
|
|
@@ -14,7 +14,7 @@ const savedEnv = { ...process.env };
|
|
|
14
14
|
const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
15
15
|
|
|
16
16
|
beforeEach(() => {
|
|
17
|
-
process.env.AGENT_SWARM_API_KEY = "runtime-egress-secret-1234567890";
|
|
17
|
+
process.env.AGENT_SWARM_API_KEY = "example-runtime-egress-secret-1234567890";
|
|
18
18
|
refreshSecretScrubberCache();
|
|
19
19
|
});
|
|
20
20
|
|
|
@@ -15,7 +15,7 @@ const resources = { memoryMb: 2048, cpuTimeSec: 20, maxStdoutBytes: 1_048_576 };
|
|
|
15
15
|
const spawnTest = test.skipIf(SKIP_SANDBOX_SPAWN_TESTS);
|
|
16
16
|
|
|
17
17
|
beforeEach(() => {
|
|
18
|
-
process.env.AGENT_SWARM_API_KEY = "runtime-test-secret-1234567890";
|
|
18
|
+
process.env.AGENT_SWARM_API_KEY = "example-runtime-test-secret-1234567890";
|
|
19
19
|
delete process.env.API_KEY;
|
|
20
20
|
process.env.MCP_BASE_URL = "http://localhost:3013";
|
|
21
21
|
refreshSecretScrubberCache();
|
|
@@ -99,7 +99,9 @@ describe("runScript", () => {
|
|
|
99
99
|
const server = Bun.serve({
|
|
100
100
|
port: 0,
|
|
101
101
|
async fetch(req) {
|
|
102
|
-
expect(req.headers.get("authorization")).toBe(
|
|
102
|
+
expect(req.headers.get("authorization")).toBe(
|
|
103
|
+
"Bearer example-runtime-test-secret-1234567890",
|
|
104
|
+
);
|
|
103
105
|
expect(req.headers.get("x-agent-id")).toBe("agent-1");
|
|
104
106
|
|
|
105
107
|
const url = new URL(req.url);
|
|
@@ -280,8 +282,8 @@ describe("runScript", () => {
|
|
|
280
282
|
});
|
|
281
283
|
|
|
282
284
|
spawnTest("subprocess env is stripped to the explicit allowlist", async () => {
|
|
283
|
-
process.env.API_KEY = "legacy-secret-that-must-not-leak";
|
|
284
|
-
process.env.AGENT_SWARM_API_KEY = "preferred-secret-that-must-not-leak";
|
|
285
|
+
process.env.API_KEY = "example-legacy-secret-that-must-not-leak";
|
|
286
|
+
process.env.AGENT_SWARM_API_KEY = "example-preferred-secret-that-must-not-leak";
|
|
285
287
|
refreshSecretScrubberCache();
|
|
286
288
|
|
|
287
289
|
const output = await runScript({
|
|
@@ -47,6 +47,27 @@ afterAll(async () => {
|
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
describe("typecheckScript", () => {
|
|
50
|
+
test("task_send requires a routing note for explicit assignments at typecheck", async () => {
|
|
51
|
+
const missing = await typecheckScript(`
|
|
52
|
+
import type { ScriptContext } from "swarm-sdk";
|
|
53
|
+
export default async function(args: unknown, ctx: ScriptContext) {
|
|
54
|
+
return ctx.swarm.task_send({ task: "work", agentId: "worker", routingReason: "skill" });
|
|
55
|
+
}
|
|
56
|
+
`);
|
|
57
|
+
expect(missing.ok).toBe(false);
|
|
58
|
+
if (!missing.ok) expect(missing.diagnostics.join("\n")).toContain("routingNote");
|
|
59
|
+
|
|
60
|
+
const valid = await typecheckScript(`
|
|
61
|
+
import type { ScriptContext } from "swarm-sdk";
|
|
62
|
+
export default async function(args: unknown, ctx: ScriptContext) {
|
|
63
|
+
await ctx.swarm.task_send({ task: "work", agentId: "worker", routingReason: "skill", routingNote: "Owns this code path" });
|
|
64
|
+
await ctx.swarm.task_send({ task: "pool work" });
|
|
65
|
+
await ctx.swarm.task_send({ task: "continue", parentTaskId: "parent" });
|
|
66
|
+
}
|
|
67
|
+
`);
|
|
68
|
+
expect(valid).toEqual({ ok: true });
|
|
69
|
+
});
|
|
70
|
+
|
|
50
71
|
test("task_defer accepts task wakeOn with a required caller-supplied ceiling", async () => {
|
|
51
72
|
const result = await typecheckScript(`
|
|
52
73
|
import type { ScriptContext } from "swarm-sdk";
|
|
@@ -220,7 +220,7 @@ describe("script SDK allowlist", () => {
|
|
|
220
220
|
|
|
221
221
|
describe("mcp-bridge allowlist gate", () => {
|
|
222
222
|
const TEST_DB_PATH = "./test-sdk-allowlist-bridge.sqlite";
|
|
223
|
-
const API_KEY = "test-mcp-bridge-key-1234567890";
|
|
223
|
+
const API_KEY = "example-test-mcp-bridge-key-1234567890";
|
|
224
224
|
let prevApiKey: string | undefined;
|
|
225
225
|
let oversizedTaskId: string;
|
|
226
226
|
|
|
@@ -67,23 +67,23 @@ describe("scrubSecrets — env-based replacement", () => {
|
|
|
67
67
|
});
|
|
68
68
|
|
|
69
69
|
test("redacts any key with _API_KEY suffix", () => {
|
|
70
|
-
process.env.FOO_SERVICE_API_KEY = "supersecretFooApiKey_longerthan12chars";
|
|
70
|
+
process.env.FOO_SERVICE_API_KEY = "example-supersecretFooApiKey_longerthan12chars";
|
|
71
71
|
refreshSecretScrubberCache();
|
|
72
|
-
const out = scrubSecrets("key=supersecretFooApiKey_longerthan12chars tail");
|
|
72
|
+
const out = scrubSecrets("key=example-supersecretFooApiKey_longerthan12chars tail");
|
|
73
73
|
expect(out).toBe("key=[REDACTED:FOO_SERVICE_API_KEY] tail");
|
|
74
74
|
});
|
|
75
75
|
|
|
76
76
|
test("redacts any key with _TOKEN suffix", () => {
|
|
77
|
-
process.env.WEIRD_SERVICE_TOKEN = "weirdserviceTOKENvalue_1234567890";
|
|
77
|
+
process.env.WEIRD_SERVICE_TOKEN = "example-weirdserviceTOKENvalue_1234567890";
|
|
78
78
|
refreshSecretScrubberCache();
|
|
79
|
-
const out = scrubSecrets("t=weirdserviceTOKENvalue_1234567890");
|
|
79
|
+
const out = scrubSecrets("t=example-weirdserviceTOKENvalue_1234567890");
|
|
80
80
|
expect(out).toBe("t=[REDACTED:WEIRD_SERVICE_TOKEN]");
|
|
81
81
|
});
|
|
82
82
|
|
|
83
83
|
test("redacts any key with _SECRET suffix", () => {
|
|
84
|
-
process.env.MY_OAUTH_CLIENT_SECRET = "oauthsecret_verylong_1234567890abcdef";
|
|
84
|
+
process.env.MY_OAUTH_CLIENT_SECRET = "example-oauthsecret_verylong_1234567890abcdef";
|
|
85
85
|
refreshSecretScrubberCache();
|
|
86
|
-
const out = scrubSecrets("secret=oauthsecret_verylong_1234567890abcdef");
|
|
86
|
+
const out = scrubSecrets("secret=example-oauthsecret_verylong_1234567890abcdef");
|
|
87
87
|
expect(out).toBe("secret=[REDACTED:MY_OAUTH_CLIENT_SECRET]");
|
|
88
88
|
});
|
|
89
89
|
|
|
@@ -111,10 +111,11 @@ describe("scrubSecrets — env-based replacement", () => {
|
|
|
111
111
|
|
|
112
112
|
test("handles comma-separated pool values (scrubs both the full pool and each component)", () => {
|
|
113
113
|
process.env.POOL_TOKEN =
|
|
114
|
-
"ghp_poolfirst1234567890abcdefABCDEF1234567890,
|
|
114
|
+
"example-ghp_poolfirst1234567890abcdefABCDEF1234567890," +
|
|
115
|
+
"example-ghp_poolsecond1234567890abcdef1234567890AB";
|
|
115
116
|
refreshSecretScrubberCache();
|
|
116
|
-
const out = scrubSecrets("using ghp_poolfirst1234567890abcdefABCDEF1234567890");
|
|
117
|
-
expect(out).not.toContain("ghp_poolfirst1234567890abcdefABCDEF1234567890");
|
|
117
|
+
const out = scrubSecrets("using example-ghp_poolfirst1234567890abcdefABCDEF1234567890");
|
|
118
|
+
expect(out).not.toContain("example-ghp_poolfirst1234567890abcdefABCDEF1234567890");
|
|
118
119
|
expect(out).toContain("[REDACTED:");
|
|
119
120
|
});
|
|
120
121
|
|
|
@@ -123,7 +124,8 @@ describe("scrubSecrets — env-based replacement", () => {
|
|
|
123
124
|
process.env.OPENAI_API_KEY = "sk-proj-abcd1234567890EFGHefgh1234567890";
|
|
124
125
|
refreshSecretScrubberCache();
|
|
125
126
|
const input =
|
|
126
|
-
"gh=ghp_abcdefghijklmnopqrstuvwxyz0123456789
|
|
127
|
+
"gh=example-ghp_abcdefghijklmnopqrstuvwxyz0123456789 " +
|
|
128
|
+
"and openai=example-sk-proj-abcd1234567890EFGHefgh1234567890";
|
|
127
129
|
const out = scrubSecrets(input);
|
|
128
130
|
expect(out).toContain("[REDACTED:GITHUB_TOKEN]");
|
|
129
131
|
expect(out).toContain("[REDACTED:OPENAI_API_KEY]");
|
|
@@ -146,63 +148,65 @@ describe("scrubSecrets — env-based replacement", () => {
|
|
|
146
148
|
const out1 = scrubSecrets("no secret yet here_abcdefghij");
|
|
147
149
|
expect(out1).toBe("no secret yet here_abcdefghij");
|
|
148
150
|
|
|
149
|
-
process.env.NEW_SERVICE_API_KEY = "here_abcdefghij_andmore1234567890";
|
|
151
|
+
process.env.NEW_SERVICE_API_KEY = "example-here_abcdefghij_andmore1234567890";
|
|
150
152
|
refreshSecretScrubberCache();
|
|
151
|
-
const out2 = scrubSecrets("value=here_abcdefghij_andmore1234567890");
|
|
153
|
+
const out2 = scrubSecrets("value=example-here_abcdefghij_andmore1234567890");
|
|
152
154
|
expect(out2).toBe("value=[REDACTED:NEW_SERVICE_API_KEY]");
|
|
153
155
|
});
|
|
154
156
|
});
|
|
155
157
|
|
|
156
158
|
describe("scrubSecrets — regex patterns", () => {
|
|
157
159
|
test("redacts github_pat_ fine-grained PATs", () => {
|
|
158
|
-
const
|
|
160
|
+
const token = `github_pat_${"a".repeat(32)}`;
|
|
161
|
+
const out = scrubSecrets(`PAT: ${token}`);
|
|
159
162
|
expect(out).toContain("[REDACTED:github_pat]");
|
|
160
|
-
expect(out).not.toContain(
|
|
163
|
+
expect(out).not.toContain(token);
|
|
161
164
|
});
|
|
162
165
|
|
|
163
166
|
test("redacts ghp_ classic tokens", () => {
|
|
164
|
-
const out = scrubSecrets("PAT: ghp_1234567890abcdefABCDEF1234567890ABCD end");
|
|
167
|
+
const out = scrubSecrets("PAT: example-ghp_1234567890abcdefABCDEF1234567890ABCD end");
|
|
165
168
|
expect(out).toContain("[REDACTED:github_token]");
|
|
166
169
|
expect(out).not.toContain("ghp_1234567890abcdef");
|
|
167
170
|
});
|
|
168
171
|
|
|
169
172
|
test("redacts gho_ OAuth tokens", () => {
|
|
170
|
-
const out = scrubSecrets("OAuth: gho_abcdef1234567890ABCDEF1234567890abcd");
|
|
173
|
+
const out = scrubSecrets("OAuth: example-gho_abcdef1234567890ABCDEF1234567890abcd");
|
|
171
174
|
expect(out).toContain("[REDACTED:github_token]");
|
|
172
175
|
});
|
|
173
176
|
|
|
174
177
|
test("redacts ghs_ installation tokens", () => {
|
|
175
|
-
const out = scrubSecrets("Installation: ghs_abcdef1234567890ABCDEF1234567890abcd");
|
|
178
|
+
const out = scrubSecrets("Installation: example-ghs_abcdef1234567890ABCDEF1234567890abcd");
|
|
176
179
|
expect(out).toContain("[REDACTED:github_token]");
|
|
177
180
|
});
|
|
178
181
|
|
|
179
182
|
test("redacts glpat- GitLab PATs", () => {
|
|
180
|
-
const out = scrubSecrets("GL: glpat-abcdef1234567890ABCDEFgh");
|
|
183
|
+
const out = scrubSecrets("GL: example-glpat-abcdef1234567890ABCDEFgh");
|
|
181
184
|
expect(out).toContain("[REDACTED:gitlab_pat]");
|
|
182
185
|
expect(out).not.toContain("glpat-abcdef");
|
|
183
186
|
});
|
|
184
187
|
|
|
185
188
|
test("redacts sk-ant- Anthropic keys", () => {
|
|
186
|
-
const
|
|
189
|
+
const token = `sk-ant-${"a".repeat(32)}`;
|
|
190
|
+
const out = scrubSecrets(`Anthropic: ${token}`);
|
|
187
191
|
expect(out).toContain("[REDACTED:anthropic_key]");
|
|
188
|
-
expect(out).not.toContain(
|
|
192
|
+
expect(out).not.toContain(token);
|
|
189
193
|
});
|
|
190
194
|
|
|
191
195
|
test("redacts sk-proj- OpenAI project keys (preferred over legacy sk-)", () => {
|
|
192
|
-
const out = scrubSecrets("OpenAI: sk-proj-abcdefghijklmnopqrstuvwxyz012345");
|
|
196
|
+
const out = scrubSecrets("OpenAI: example-sk-proj-abcdefghijklmnopqrstuvwxyz012345");
|
|
193
197
|
expect(out).toContain("[REDACTED:openai_proj_key]");
|
|
194
198
|
expect(out).not.toContain("sk-proj-abcdefghijkl");
|
|
195
199
|
});
|
|
196
200
|
|
|
197
201
|
test("redacts legacy sk- keys (catch-all)", () => {
|
|
198
|
-
const out = scrubSecrets("Legacy: sk-abcdefghijklmnopqrstuvwxyz0123");
|
|
202
|
+
const out = scrubSecrets("Legacy: example-sk-abcdefghijklmnopqrstuvwxyz0123");
|
|
199
203
|
expect(out).toContain("[REDACTED:sk_key]");
|
|
200
204
|
});
|
|
201
205
|
|
|
202
206
|
test("redacts Slack xoxb tokens", () => {
|
|
203
|
-
const out = scrubSecrets("slack=xoxb-1234567890-0987654321-abcdefghij");
|
|
207
|
+
const out = scrubSecrets("slack=example-xoxb-1234567890-0987654321-abcdefghij");
|
|
204
208
|
expect(out).toContain("[REDACTED:slack_token]");
|
|
205
|
-
expect(out).not.toContain("xoxb-1234567890");
|
|
209
|
+
expect(out).not.toContain("example-xoxb-1234567890");
|
|
206
210
|
});
|
|
207
211
|
|
|
208
212
|
test("redacts AWS access key IDs", () => {
|
|
@@ -228,7 +232,7 @@ describe("scrubSecrets — regex patterns", () => {
|
|
|
228
232
|
|
|
229
233
|
test("regex patterns catch tokens even when env is empty", () => {
|
|
230
234
|
// Fresh env — no secrets registered — regex should still catch well-known shapes.
|
|
231
|
-
const out = scrubSecrets("token=ghp_1234567890abcdefABCDEF1234567890ABCD");
|
|
235
|
+
const out = scrubSecrets("token=example-ghp_1234567890abcdefABCDEF1234567890ABCD");
|
|
232
236
|
expect(out).toContain("[REDACTED:github_token]");
|
|
233
237
|
});
|
|
234
238
|
|
|
@@ -241,7 +245,7 @@ describe("scrubSecrets — regex patterns", () => {
|
|
|
241
245
|
});
|
|
242
246
|
|
|
243
247
|
test("redacts Linear OAuth tokens", () => {
|
|
244
|
-
const out = scrubSecrets("Authorization: Bearer lin_oauth_test123abcdef end");
|
|
248
|
+
const out = scrubSecrets("Authorization: Bearer example-lin_oauth_test123abcdef end");
|
|
245
249
|
expect(out).toContain("[REDACTED:linear_oauth]");
|
|
246
250
|
expect(out).not.toContain("lin_oauth_test123");
|
|
247
251
|
});
|
|
@@ -279,7 +283,10 @@ describe("scrubSecrets — regex patterns", () => {
|
|
|
279
283
|
});
|
|
280
284
|
|
|
281
285
|
test("redacts tokens in double-encoded JSON with escape sequences", () => {
|
|
282
|
-
const inner = JSON.stringify({
|
|
286
|
+
const inner = JSON.stringify({
|
|
287
|
+
access_token: "example-lin_oauth_test123abcdef",
|
|
288
|
+
scope: "read",
|
|
289
|
+
});
|
|
283
290
|
const content = `{"output":${JSON.stringify(inner)}}`;
|
|
284
291
|
const out = scrubSecrets(content);
|
|
285
292
|
expect(out).toContain("[REDACTED:linear_oauth]");
|
|
@@ -333,14 +340,14 @@ describe("scrubSecrets — does not over-scrub", () => {
|
|
|
333
340
|
|
|
334
341
|
describe("scrubObject", () => {
|
|
335
342
|
test("scrubs nested object and array string leaves", () => {
|
|
336
|
-
process.env.NESTED_TOKEN = "nested-secret-value-1234567890";
|
|
343
|
+
process.env.NESTED_TOKEN = "example-nested-secret-value-1234567890";
|
|
337
344
|
refreshSecretScrubberCache();
|
|
338
345
|
|
|
339
346
|
const out = scrubObject({
|
|
340
347
|
keep: 1,
|
|
341
348
|
nested: {
|
|
342
|
-
secret: "nested-secret-value-1234567890",
|
|
343
|
-
list: ["safe", "nested-secret-value-1234567890"],
|
|
349
|
+
secret: "example-nested-secret-value-1234567890",
|
|
350
|
+
list: ["safe", "example-nested-secret-value-1234567890"],
|
|
344
351
|
},
|
|
345
352
|
nullish: null,
|
|
346
353
|
bool: true,
|
|
@@ -371,7 +378,7 @@ describe("registerVolatileSecret", () => {
|
|
|
371
378
|
});
|
|
372
379
|
|
|
373
380
|
test("scrubs a runtime-registered volatile secret", () => {
|
|
374
|
-
const secret = "volatile_runtime_token_1234567890abcdef";
|
|
381
|
+
const secret = "example-volatile_runtime_token_1234567890abcdef";
|
|
375
382
|
registerVolatileSecret(secret, "RUNTIME_TOKEN");
|
|
376
383
|
const out = scrubSecrets(`key=${secret}`);
|
|
377
384
|
expect(out).toBe("key=[REDACTED:RUNTIME_TOKEN]");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import { unlink } from "node:fs/promises";
|
|
3
|
-
import { closeDb, initDb, listWorkflows } from "../be/db";
|
|
3
|
+
import { closeDb, getScheduledTasks, initDb, listWorkflows } from "../be/db";
|
|
4
4
|
import { runSeeder, SEEDERS } from "../be/seed";
|
|
5
5
|
import { schedulesSeeder } from "../be/seed/schedules-seeder";
|
|
6
6
|
import { workflowsSeeder } from "../be/seed/workflows-seeder";
|
|
@@ -38,17 +38,55 @@ describe("seeder registry", () => {
|
|
|
38
38
|
]);
|
|
39
39
|
});
|
|
40
40
|
|
|
41
|
-
test("the
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
test("the bundled catalogs include every workflow and schedule template", async () => {
|
|
42
|
+
for (const [kind, seeder] of [
|
|
43
|
+
["workflows", workflowsSeeder],
|
|
44
|
+
["schedules", schedulesSeeder],
|
|
45
|
+
] as const) {
|
|
46
|
+
const catalogNames: string[] = [];
|
|
47
|
+
const catalogDir = `${import.meta.dir}/../../templates/${kind}`;
|
|
48
|
+
for await (const path of new Bun.Glob("*/config.json").scan(catalogDir)) {
|
|
49
|
+
const config = await Bun.file(`${catalogDir}/${path}`).json();
|
|
50
|
+
catalogNames.push(config.name);
|
|
51
|
+
}
|
|
52
|
+
expect(
|
|
53
|
+
seeder
|
|
54
|
+
.items()
|
|
55
|
+
.map((item) => item.key)
|
|
56
|
+
.sort(),
|
|
57
|
+
).toEqual(catalogNames.sort());
|
|
58
|
+
}
|
|
44
59
|
});
|
|
45
60
|
|
|
46
|
-
test("seeds all
|
|
61
|
+
test("seeds all 21 automation templates on a fresh database and re-runs as a no-op", async () => {
|
|
62
|
+
expect(await listWorkflows()).toHaveLength(0);
|
|
63
|
+
expect(await getScheduledTasks()).toHaveLength(0);
|
|
64
|
+
|
|
47
65
|
const workflowResult = await runSeeder(workflowsSeeder, { quiet: true });
|
|
48
66
|
const scheduleResult = await runSeeder(schedulesSeeder, { quiet: true });
|
|
49
67
|
|
|
50
|
-
expect(workflowResult).toMatchObject({ created:
|
|
51
|
-
expect(scheduleResult).toMatchObject({ created:
|
|
52
|
-
expect(await listWorkflows()).
|
|
68
|
+
expect(workflowResult).toMatchObject({ created: 10, failed: [] });
|
|
69
|
+
expect(scheduleResult).toMatchObject({ created: 11, failed: [] });
|
|
70
|
+
expect((await listWorkflows()).map((workflow) => workflow.name).sort()).toEqual(
|
|
71
|
+
workflowsSeeder.items().map((item) => item.key),
|
|
72
|
+
);
|
|
73
|
+
expect((await getScheduledTasks()).map((schedule) => schedule.name).sort()).toEqual(
|
|
74
|
+
schedulesSeeder.items().map((item) => item.key),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
expect(await runSeeder(workflowsSeeder, { quiet: true })).toMatchObject({
|
|
78
|
+
created: 0,
|
|
79
|
+
updated: 0,
|
|
80
|
+
skippedUnchanged: 10,
|
|
81
|
+
failed: [],
|
|
82
|
+
});
|
|
83
|
+
expect(await runSeeder(schedulesSeeder, { quiet: true })).toMatchObject({
|
|
84
|
+
created: 0,
|
|
85
|
+
updated: 0,
|
|
86
|
+
skippedUnchanged: 11,
|
|
87
|
+
failed: [],
|
|
88
|
+
});
|
|
89
|
+
expect(await listWorkflows()).toHaveLength(10);
|
|
90
|
+
expect(await getScheduledTasks()).toHaveLength(11);
|
|
53
91
|
});
|
|
54
92
|
});
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import { unlink } from "node:fs/promises";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
closeDb,
|
|
5
|
+
getScheduledTaskByName,
|
|
6
|
+
getScheduledTasks,
|
|
7
|
+
initDb,
|
|
8
|
+
updateScheduledTask,
|
|
9
|
+
} from "../be/db";
|
|
4
10
|
import { runSeeder } from "../be/seed";
|
|
5
11
|
import {
|
|
6
12
|
createSchedulesSeeder,
|
|
@@ -69,6 +75,7 @@ function zeroConfigScheduleSource(opts?: {
|
|
|
69
75
|
const ORIGINAL_SEED_AUTOMATIONS_ENABLED = process.env.SEED_AUTOMATIONS_ENABLED;
|
|
70
76
|
|
|
71
77
|
beforeEach(async () => {
|
|
78
|
+
delete process.env.SEED_AUTOMATIONS_ENABLED;
|
|
72
79
|
await removeDbFiles();
|
|
73
80
|
initDb(TEST_DB_PATH);
|
|
74
81
|
});
|
|
@@ -84,9 +91,9 @@ afterEach(async () => {
|
|
|
84
91
|
});
|
|
85
92
|
|
|
86
93
|
describe("schedules seeder", () => {
|
|
87
|
-
test("loads
|
|
94
|
+
test("loads all eleven schedule templates, including the unfenced schedule block", () => {
|
|
88
95
|
const schedules = loadSeedSchedules();
|
|
89
|
-
expect(schedules).toHaveLength(
|
|
96
|
+
expect(schedules).toHaveLength(11);
|
|
90
97
|
// Zero-config, requires:[], placeholders:[], template enabled:true -> auto-enabled
|
|
91
98
|
// under the default (unset -> on) SEED_AUTOMATIONS_ENABLED switch.
|
|
92
99
|
expect(schedules.find((schedule) => schedule.name === "daily-status-report")).toMatchObject({
|
|
@@ -102,18 +109,46 @@ describe("schedules seeder", () => {
|
|
|
102
109
|
requiredParams: [],
|
|
103
110
|
requires: [],
|
|
104
111
|
});
|
|
105
|
-
expect(
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
112
|
+
expect(
|
|
113
|
+
schedules.find((schedule) => schedule.name === "weekly-harness-upgrade-check"),
|
|
114
|
+
).toMatchObject({
|
|
115
|
+
enabled: false,
|
|
116
|
+
requiredParams: ["REPO_URL", "PR_REVIEWER"],
|
|
117
|
+
requires: ["github"],
|
|
118
|
+
});
|
|
119
|
+
expect(
|
|
120
|
+
schedules.filter((schedule) => schedule.enabled).map((schedule) => schedule.name),
|
|
121
|
+
).toEqual([
|
|
122
|
+
"daily-blocker-digest",
|
|
123
|
+
"daily-compounding-reflection",
|
|
124
|
+
"daily-status-report",
|
|
125
|
+
"daily-swarm-update-check",
|
|
126
|
+
"daily-workflow-health-audit",
|
|
127
|
+
]);
|
|
109
128
|
});
|
|
110
129
|
|
|
111
|
-
test("SEED_AUTOMATIONS_ENABLED=false
|
|
130
|
+
test("SEED_AUTOMATIONS_ENABLED=false still seeds all schedules disabled", async () => {
|
|
112
131
|
process.env.SEED_AUTOMATIONS_ENABLED = "false";
|
|
113
|
-
const
|
|
132
|
+
const result = await runSeeder(createSchedulesSeeder(), { quiet: true });
|
|
133
|
+
expect(result).toMatchObject({ created: 11, failed: [] });
|
|
134
|
+
const schedules = await getScheduledTasks();
|
|
135
|
+
expect(schedules).toHaveLength(11);
|
|
114
136
|
expect(schedules.every((schedule) => schedule.enabled === false)).toBe(true);
|
|
115
137
|
});
|
|
116
138
|
|
|
139
|
+
test("seeds a disabled schedule whose timezone still needs setup", async () => {
|
|
140
|
+
const result = await runSeeder(createSchedulesSeeder(), { quiet: true });
|
|
141
|
+
expect(result).toMatchObject({ created: 11, failed: [] });
|
|
142
|
+
expect(await getScheduledTaskByName("weekly-dependabot-triage")).toMatchObject({
|
|
143
|
+
cronExpression: "40 3 * * 0",
|
|
144
|
+
timezone: "{{TIMEZONE}}",
|
|
145
|
+
enabled: false,
|
|
146
|
+
nextRunAt: undefined,
|
|
147
|
+
requiredParams: ["REPO_URL", "SLACK_CHANNEL_ID", "TIMEZONE"],
|
|
148
|
+
requires: ["github", "slack"],
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
|
|
117
152
|
test("switch on: a zero-config candidate auto-enables via createSchedulesSeeder/apply", async () => {
|
|
118
153
|
delete process.env.SEED_AUTOMATIONS_ENABLED;
|
|
119
154
|
const seeder = createSchedulesSeeder([zeroConfigScheduleSource()]);
|
|
@@ -66,6 +66,7 @@ async function getWorkflow(name = "test-seeded-workflow") {
|
|
|
66
66
|
const ORIGINAL_SEED_AUTOMATIONS_ENABLED = process.env.SEED_AUTOMATIONS_ENABLED;
|
|
67
67
|
|
|
68
68
|
beforeEach(async () => {
|
|
69
|
+
delete process.env.SEED_AUTOMATIONS_ENABLED;
|
|
69
70
|
await removeDbFiles();
|
|
70
71
|
initDb(TEST_DB_PATH);
|
|
71
72
|
});
|
|
@@ -81,24 +82,35 @@ afterEach(async () => {
|
|
|
81
82
|
});
|
|
82
83
|
|
|
83
84
|
describe("workflows seeder", () => {
|
|
84
|
-
test("loads
|
|
85
|
+
test("loads all ten workflow templates with their setup metadata", () => {
|
|
85
86
|
const workflows = loadSeedWorkflows();
|
|
86
|
-
expect(workflows).toHaveLength(
|
|
87
|
+
expect(workflows).toHaveLength(10);
|
|
87
88
|
expect(workflows.find((workflow) => workflow.name === "autopilot")).toMatchObject({
|
|
88
89
|
enabled: false,
|
|
89
90
|
requiredParams: ["REPO_URL"],
|
|
90
91
|
requires: ["github"],
|
|
91
92
|
});
|
|
92
|
-
expect(
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
93
|
+
expect(
|
|
94
|
+
workflows.find((workflow) => workflow.name === "claude-code-changelog-watch"),
|
|
95
|
+
).toMatchObject({
|
|
96
|
+
enabled: false,
|
|
97
|
+
requiredParams: [],
|
|
98
|
+
requires: [],
|
|
99
|
+
});
|
|
100
|
+
expect(workflows.find((workflow) => workflow.name === "gsc-topic-miner")).toMatchObject({
|
|
101
|
+
enabled: false,
|
|
102
|
+
requiredParams: ["GSC_PROPERTY"],
|
|
103
|
+
requires: ["gsc", "agentfs"],
|
|
104
|
+
});
|
|
105
|
+
expect(workflows.every((workflow) => !workflow.enabled)).toBe(true);
|
|
97
106
|
});
|
|
98
107
|
|
|
99
|
-
test("SEED_AUTOMATIONS_ENABLED=false
|
|
108
|
+
test("SEED_AUTOMATIONS_ENABLED=false still seeds all workflows disabled", async () => {
|
|
100
109
|
process.env.SEED_AUTOMATIONS_ENABLED = "false";
|
|
101
|
-
const
|
|
110
|
+
const result = await runSeeder(createWorkflowsSeeder(), { quiet: true });
|
|
111
|
+
expect(result).toMatchObject({ created: 10, failed: [] });
|
|
112
|
+
const workflows = await listWorkflows();
|
|
113
|
+
expect(workflows).toHaveLength(10);
|
|
102
114
|
expect(workflows.every((workflow) => workflow.enabled === false)).toBe(true);
|
|
103
115
|
});
|
|
104
116
|
|