@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
package/src/slack/assistant.ts
CHANGED
|
@@ -7,7 +7,6 @@ import { resolveSlackUserId, rewriteSlackMentions } from "./enrich";
|
|
|
7
7
|
import { wasEventSeen } from "./event-dedup";
|
|
8
8
|
import type { SlackFile } from "./files";
|
|
9
9
|
import {
|
|
10
|
-
bufferedFileFailures,
|
|
11
10
|
buildEffectiveText,
|
|
12
11
|
createSlackTaskWithFiles,
|
|
13
12
|
fetchSlackFiles,
|
|
@@ -128,21 +127,12 @@ export function createAssistant(): Assistant {
|
|
|
128
127
|
// 1. Check if an agent is already working in this thread
|
|
129
128
|
const workingAgent = await getAgentWorkingOnThread(channelId, threadTs);
|
|
130
129
|
|
|
131
|
-
// Follow-up message →
|
|
132
|
-
// carry the `[File: …]` lines only; their files are not attached.
|
|
130
|
+
// Follow-up message → buffer text and file metadata until the flush.
|
|
133
131
|
if (workingAgent && workingAgent.status !== "offline" && isAdditiveSlack()) {
|
|
134
|
-
|
|
135
|
-
bufferThreadMessage(
|
|
136
|
-
channelId,
|
|
137
|
-
threadTs,
|
|
138
|
-
buildEffectiveText(messageText, files, unattached),
|
|
139
|
-
userId,
|
|
140
|
-
message.ts,
|
|
141
|
-
);
|
|
132
|
+
bufferThreadMessage(channelId, threadTs, messageText, userId, message.ts, files);
|
|
142
133
|
const count = getBufferMessageCount(`${channelId}:${threadTs}`);
|
|
143
134
|
const event = count === 1 ? "accepted" : "buffered";
|
|
144
135
|
await ackSlackMessage(client, channelId, message.ts, reactionName(event), event);
|
|
145
|
-
await notifySlackFileFailures(client, channelId, threadTs, unattached);
|
|
146
136
|
await safeSetStatus("Queuing follow-up...");
|
|
147
137
|
return;
|
|
148
138
|
}
|
|
@@ -167,6 +157,7 @@ export function createAssistant(): Assistant {
|
|
|
167
157
|
{
|
|
168
158
|
agentId: workingAgent.id,
|
|
169
159
|
routingReason: "continuity",
|
|
160
|
+
routingSource: "engine_default",
|
|
170
161
|
source: "slack",
|
|
171
162
|
slackChannelId: channelId,
|
|
172
163
|
slackThreadTs: threadTs,
|
|
@@ -249,6 +240,7 @@ export function createAssistant(): Assistant {
|
|
|
249
240
|
{
|
|
250
241
|
agentId: lead.id,
|
|
251
242
|
routingReason: "skill",
|
|
243
|
+
routingSource: "engine_default",
|
|
252
244
|
source: "slack",
|
|
253
245
|
slackChannelId: channelId,
|
|
254
246
|
slackThreadTs: threadTs,
|
package/src/slack/blocks.ts
CHANGED
|
@@ -555,7 +555,7 @@ export function buildTreeBlocks(roots: TreeNode[]): SlackBlock[] {
|
|
|
555
555
|
);
|
|
556
556
|
|
|
557
557
|
const treeTexts = roots.map(renderTree);
|
|
558
|
-
const blocks: SlackBlock[] = [sectionBlock(treeTexts.join("\n\n"))];
|
|
558
|
+
const blocks: SlackBlock[] = treeTexts.length > 0 ? [sectionBlock(treeTexts.join("\n\n"))] : [];
|
|
559
559
|
|
|
560
560
|
// Attachment blocks for completed nodes, with per-tree-message cap.
|
|
561
561
|
const attachmentNodes = collectAttachmentNodes(roots);
|
package/src/slack/handlers.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { App } from "@slack/bolt";
|
|
2
2
|
import type { WebClient } from "@slack/web-api";
|
|
3
|
+
import { z } from "zod";
|
|
3
4
|
import {
|
|
4
5
|
getAgentById,
|
|
5
6
|
getAgentWorkingOnThread,
|
|
7
|
+
getAllAgents,
|
|
6
8
|
getLeadAgent,
|
|
7
9
|
getMostRecentTaskInThread,
|
|
8
10
|
getTasksByAgentId,
|
|
9
11
|
} from "../be/db";
|
|
12
|
+
import { dispatchPre } from "../extensions/dispatcher";
|
|
10
13
|
import { resolveTemplate } from "../prompts/resolver";
|
|
11
14
|
import { slackContextKey } from "../tasks/context-key";
|
|
15
|
+
import { TaskCreationBlockedError } from "../tasks/errors";
|
|
16
|
+
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
12
17
|
import { workflowEventBus } from "../workflows/event-bus";
|
|
13
18
|
import { ackSlackMessage, reactionName } from "./ack";
|
|
14
19
|
import { buildTreeBlocks, type TreeNode } from "./blocks";
|
|
@@ -16,14 +21,19 @@ import { enrichSlackUserEmail, resolveSlackUserId, rewriteSlackMentions } from "
|
|
|
16
21
|
import { wasEventSeen } from "./event-dedup";
|
|
17
22
|
import type { SlackFile } from "./files";
|
|
18
23
|
import {
|
|
19
|
-
bufferedFileFailures,
|
|
20
24
|
buildEffectiveText,
|
|
21
25
|
createSlackTaskWithFiles,
|
|
22
26
|
fetchSlackFiles,
|
|
23
27
|
notifySlackFileFailures,
|
|
24
28
|
type SlackFileFailure,
|
|
25
29
|
} from "./inbound-files";
|
|
26
|
-
import {
|
|
30
|
+
import {
|
|
31
|
+
broadcastMatches,
|
|
32
|
+
extractTaskFromMessage,
|
|
33
|
+
hasOtherUserMention,
|
|
34
|
+
routeMessage,
|
|
35
|
+
} from "./router";
|
|
36
|
+
import type { AgentMatch } from "./types";
|
|
27
37
|
// Side-effect import: registers all Slack event templates in the in-memory registry
|
|
28
38
|
import "./templates";
|
|
29
39
|
import { isEnvFlagEnabled } from "../utils/env-flag";
|
|
@@ -33,6 +43,17 @@ import { formatSlackSteeringAck, requestSlackThreadSteering } from "./steering";
|
|
|
33
43
|
import { bufferThreadMessage, getBufferMessageCount, instantFlush } from "./thread-buffer";
|
|
34
44
|
import { registerTreeMessage } from "./watcher";
|
|
35
45
|
|
|
46
|
+
/** Runtime check for `pre.slack.route` modifications (mirrors `SlackRouteModify`). */
|
|
47
|
+
const SlackRouteModifySchema = z
|
|
48
|
+
.object({
|
|
49
|
+
target: z.discriminatedUnion("kind", [
|
|
50
|
+
z.object({ kind: z.literal("agent"), agentId: z.string().min(1) }).strict(),
|
|
51
|
+
z.object({ kind: z.literal("lead") }).strict(),
|
|
52
|
+
z.object({ kind: z.literal("broadcast") }).strict(),
|
|
53
|
+
]),
|
|
54
|
+
})
|
|
55
|
+
.strict();
|
|
56
|
+
|
|
36
57
|
// User filtering configuration from environment variables
|
|
37
58
|
const allowedEmailDomains = (process.env.SLACK_ALLOWED_EMAIL_DOMAINS || "")
|
|
38
59
|
.split(",")
|
|
@@ -103,7 +124,7 @@ export function checkUserAccess(
|
|
|
103
124
|
* Check if a user is allowed to interact with the swarm.
|
|
104
125
|
* Returns true if filtering is disabled, user is in whitelist, or user's email domain is allowed.
|
|
105
126
|
*/
|
|
106
|
-
async function isUserAllowed(client: WebClient, userId: string): Promise<boolean> {
|
|
127
|
+
export async function isUserAllowed(client: WebClient, userId: string): Promise<boolean> {
|
|
107
128
|
// If no filtering configured, allow all users (backwards compatible)
|
|
108
129
|
if (!filteringEnabled) {
|
|
109
130
|
return true;
|
|
@@ -445,11 +466,13 @@ export function registerMessageHandler(app: App): void {
|
|
|
445
466
|
sampleContext: msg.text ?? "",
|
|
446
467
|
});
|
|
447
468
|
|
|
448
|
-
//
|
|
469
|
+
// Keep channel/user for legacy consumers and channelId/userId for the extension contract.
|
|
449
470
|
workflowEventBus.emit("slack.message", {
|
|
450
471
|
channel: msg.channel,
|
|
472
|
+
channelId: msg.channel,
|
|
451
473
|
text: msg.text,
|
|
452
474
|
user: msg.user,
|
|
475
|
+
userId: msg.user,
|
|
453
476
|
ts: msg.ts,
|
|
454
477
|
threadTs: msg.thread_ts,
|
|
455
478
|
});
|
|
@@ -487,11 +510,7 @@ export function registerMessageHandler(app: App): void {
|
|
|
487
510
|
false,
|
|
488
511
|
);
|
|
489
512
|
if (additiveSlack && msg.thread_ts) {
|
|
490
|
-
|
|
491
|
-
const unattached = bufferedFileFailures(msg.files);
|
|
492
|
-
const stripped = buildEffectiveText(msg.text, msg.files, unattached)
|
|
493
|
-
.replace(/<@[A-Z0-9]+>/g, "")
|
|
494
|
-
.trim();
|
|
513
|
+
const stripped = (msg.text ?? "").replace(/<@[A-Z0-9]+>/g, "").trim();
|
|
495
514
|
if (
|
|
496
515
|
stripped.startsWith("!now") &&
|
|
497
516
|
(await hasSwarmThreadActivity(client, msg.channel, msg.thread_ts))
|
|
@@ -503,15 +522,14 @@ export function registerMessageHandler(app: App): void {
|
|
|
503
522
|
`[Slack] !now command detected in thread ${threadKey}${nowMessage ? ` with message: "${nowMessage}"` : ""}`,
|
|
504
523
|
);
|
|
505
524
|
|
|
506
|
-
if (nowMessage) {
|
|
507
|
-
bufferThreadMessage(msg.channel, msg.thread_ts, nowMessage, msg.user, msg.ts);
|
|
525
|
+
if (nowMessage || msg.files?.length) {
|
|
526
|
+
bufferThreadMessage(msg.channel, msg.thread_ts, nowMessage, msg.user, msg.ts, msg.files);
|
|
508
527
|
}
|
|
509
528
|
|
|
510
529
|
// Instant flush — no dependency
|
|
511
530
|
await instantFlush(threadKey);
|
|
512
531
|
|
|
513
532
|
await ackSlackMessage(client, msg.channel, msg.ts, reactionName("now"), "now");
|
|
514
|
-
await notifySlackFileFailures(client, msg.channel, msg.thread_ts, unattached);
|
|
515
533
|
|
|
516
534
|
return;
|
|
517
535
|
}
|
|
@@ -538,14 +556,13 @@ export function registerMessageHandler(app: App): void {
|
|
|
538
556
|
|
|
539
557
|
if (hasSwarmActivity) {
|
|
540
558
|
const threadKey = `${msg.channel}:${msg.thread_ts}`;
|
|
541
|
-
// Buffered follow-ups carry the `[File: …]` lines only; their files are not attached.
|
|
542
|
-
const unattached = bufferedFileFailures(msg.files);
|
|
543
559
|
bufferThreadMessage(
|
|
544
560
|
msg.channel,
|
|
545
561
|
msg.thread_ts,
|
|
546
|
-
|
|
562
|
+
msg.text ?? "",
|
|
547
563
|
msg.user,
|
|
548
564
|
msg.ts,
|
|
565
|
+
msg.files,
|
|
549
566
|
);
|
|
550
567
|
|
|
551
568
|
// Slack feedback: react with the accepted reaction on first buffer, buffered on appends
|
|
@@ -554,7 +571,6 @@ export function registerMessageHandler(app: App): void {
|
|
|
554
571
|
const name = reactionName(event);
|
|
555
572
|
console.log(`[Slack] Additive buffer: ${threadKey} (message #${count}, reaction: ${name})`);
|
|
556
573
|
await ackSlackMessage(client, msg.channel, msg.ts, name, event);
|
|
557
|
-
await notifySlackFileFailures(client, msg.channel, msg.thread_ts, unattached);
|
|
558
574
|
|
|
559
575
|
return; // Don't process further — buffer will flush
|
|
560
576
|
}
|
|
@@ -565,7 +581,61 @@ export function registerMessageHandler(app: App): void {
|
|
|
565
581
|
const routingThreadContext = msg.thread_ts
|
|
566
582
|
? { channelId: msg.channel, threadTs: msg.thread_ts }
|
|
567
583
|
: undefined;
|
|
568
|
-
const
|
|
584
|
+
const routeResult = await dispatchPre(
|
|
585
|
+
"pre.slack.route",
|
|
586
|
+
{
|
|
587
|
+
channelId: msg.channel,
|
|
588
|
+
userId: msg.user,
|
|
589
|
+
text: routingText,
|
|
590
|
+
...(msg.thread_ts ? { threadTs: msg.thread_ts } : {}),
|
|
591
|
+
botMentioned: botMentioned || isImplicitMention,
|
|
592
|
+
...(routingThreadContext ? { threadContext: routingThreadContext } : {}),
|
|
593
|
+
},
|
|
594
|
+
{
|
|
595
|
+
// A runtime-invalid target (missing, null, unknown kind) is an extension
|
|
596
|
+
// failure, not a routing input; the built-in router keeps handling the message.
|
|
597
|
+
validateModify: (data) => {
|
|
598
|
+
const parsed = SlackRouteModifySchema.safeParse(data);
|
|
599
|
+
return parsed.success
|
|
600
|
+
? { success: true, data: parsed.data }
|
|
601
|
+
: { success: false, error: new Error(parsed.error.message) };
|
|
602
|
+
},
|
|
603
|
+
},
|
|
604
|
+
);
|
|
605
|
+
if (routeResult.action === "block") {
|
|
606
|
+
console.info("[Slack] Extension blocked message routing:", scrubSecrets(routeResult.reason));
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
let matches: AgentMatch[] | undefined;
|
|
611
|
+
if (routeResult.action === "modify") {
|
|
612
|
+
const { target } = routeResult.data;
|
|
613
|
+
if (target.kind === "agent") {
|
|
614
|
+
const agent = await getAgentById(target.agentId);
|
|
615
|
+
if (agent) {
|
|
616
|
+
matches = [{ agent, matchedText: "extension" }];
|
|
617
|
+
} else {
|
|
618
|
+
console.warn(
|
|
619
|
+
"[Slack] Extension selected an unknown agent. Using the built-in router:",
|
|
620
|
+
scrubSecrets(target.agentId),
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
} else if (target.kind === "lead") {
|
|
624
|
+
const leadAgent = await getLeadAgent();
|
|
625
|
+
if (leadAgent) {
|
|
626
|
+
matches = [{ agent: leadAgent, matchedText: "extension" }];
|
|
627
|
+
} else {
|
|
628
|
+
console.warn(
|
|
629
|
+
scrubSecrets(
|
|
630
|
+
"[Slack] Extension selected the lead, but no lead exists. Using the built-in router.",
|
|
631
|
+
),
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
} else {
|
|
635
|
+
matches = broadcastMatches(await getAllAgents());
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
matches ??= await routeMessage(
|
|
569
639
|
routingText,
|
|
570
640
|
botUserId,
|
|
571
641
|
botMentioned || isImplicitMention,
|
|
@@ -625,6 +695,7 @@ export function registerMessageHandler(app: App): void {
|
|
|
625
695
|
{
|
|
626
696
|
agentId: lead?.id,
|
|
627
697
|
routingReason: lead ? "skill" : undefined,
|
|
698
|
+
routingSource: lead ? "engine_default" : undefined,
|
|
628
699
|
source: "slack",
|
|
629
700
|
slackChannelId: msg.channel,
|
|
630
701
|
slackThreadTs: threadTs,
|
|
@@ -741,6 +812,7 @@ export function registerMessageHandler(app: App): void {
|
|
|
741
812
|
{
|
|
742
813
|
agentId: agent.id,
|
|
743
814
|
routingReason: "human_pinned",
|
|
815
|
+
routingSource: "engine_default",
|
|
744
816
|
source: "slack",
|
|
745
817
|
slackChannelId: msg.channel,
|
|
746
818
|
slackThreadTs: threadTs,
|
|
@@ -765,6 +837,7 @@ export function registerMessageHandler(app: App): void {
|
|
|
765
837
|
{
|
|
766
838
|
agentId: agent.id,
|
|
767
839
|
routingReason: "human_pinned",
|
|
840
|
+
routingSource: "engine_default",
|
|
768
841
|
source: "slack",
|
|
769
842
|
slackChannelId: msg.channel,
|
|
770
843
|
slackThreadTs: threadTs,
|
|
@@ -790,8 +863,11 @@ export function registerMessageHandler(app: App): void {
|
|
|
790
863
|
} else {
|
|
791
864
|
results.assigned.push({ agentName: agent.name, taskId: task.id });
|
|
792
865
|
}
|
|
793
|
-
} catch {
|
|
794
|
-
results.failed.push({
|
|
866
|
+
} catch (error) {
|
|
867
|
+
results.failed.push({
|
|
868
|
+
agentName: agent.name,
|
|
869
|
+
reason: error instanceof TaskCreationBlockedError ? error.reason : "error",
|
|
870
|
+
});
|
|
795
871
|
}
|
|
796
872
|
}
|
|
797
873
|
|
|
@@ -807,6 +883,18 @@ export function registerMessageHandler(app: App): void {
|
|
|
807
883
|
);
|
|
808
884
|
if (isSlackRenderV2Enabled()) {
|
|
809
885
|
if (successfulTaskIds.length > 0) await ensureSlackThreadTree(successfulTaskIds);
|
|
886
|
+
// The tree only renders tasks that exist. A blocked or failed assignment must
|
|
887
|
+
// still be answered, or the user gets silence for a policy block.
|
|
888
|
+
if (results.failed.length > 0) {
|
|
889
|
+
const failedLines = results.failed
|
|
890
|
+
.map((f) => `⚠️ Could not assign to: *${f.agentName}* — ${f.reason}`)
|
|
891
|
+
.join("\n");
|
|
892
|
+
await say({
|
|
893
|
+
text: `Could not assign to: ${results.failed.map((f) => f.agentName).join(", ")}`,
|
|
894
|
+
blocks: [{ type: "context", elements: [{ type: "mrkdwn", text: failedLines }] }],
|
|
895
|
+
thread_ts: msg.thread_ts || msg.ts,
|
|
896
|
+
});
|
|
897
|
+
}
|
|
810
898
|
} else {
|
|
811
899
|
// Build initial tree nodes from assignment results
|
|
812
900
|
const initialNodes: TreeNode[] = results.assigned.map(({ agentName, taskId }) => ({
|
|
@@ -134,9 +134,9 @@ export function buildEffectiveText(
|
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/**
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
137
|
+
* Fallback when a buffered follow-up cannot fetch its files (for example,
|
|
138
|
+
* the Slack app is unavailable at flush). Keep their names in the task and
|
|
139
|
+
* mark them unattached. Normal flushes report specific download/storage failures.
|
|
140
140
|
*/
|
|
141
141
|
export function bufferedFileFailures(files: SlackFile[] | undefined): SlackFileFailure[] {
|
|
142
142
|
return (files ?? []).map((file) => ({ file, reason: BUFFERED_REASON }));
|
|
@@ -288,11 +288,15 @@ export async function createSlackTaskWithFiles(
|
|
|
288
288
|
inbound: InboundSlackFiles,
|
|
289
289
|
): Promise<{ task: AgentTask; unattached: SlackFileFailure[] }> {
|
|
290
290
|
if (inbound.fetched.length === 0) {
|
|
291
|
-
const task = await createTaskWithSiblingAwareness(description, options);
|
|
291
|
+
const task = await createTaskWithSiblingAwareness(description, options, { origin: "slack" });
|
|
292
292
|
return { task, unattached: inbound.failed };
|
|
293
293
|
}
|
|
294
294
|
|
|
295
|
-
const task = await createTaskWithSiblingAwareness(
|
|
295
|
+
const task = await createTaskWithSiblingAwareness(
|
|
296
|
+
description,
|
|
297
|
+
{ ...options, status: "draft" },
|
|
298
|
+
{ origin: "slack" },
|
|
299
|
+
);
|
|
296
300
|
const unattached = [...inbound.failed];
|
|
297
301
|
// Uploads run one after another and can outlast the abandoned-draft sweep's
|
|
298
302
|
// window; renewing the lease keeps the sweep from promoting a live batch.
|