@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/dist/cli-y3pq4v9g.js
DELETED
|
@@ -1,664 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isMultiRuntimeEnabled
|
|
3
|
-
} from "./cli-07jd68a1.js";
|
|
4
|
-
import {
|
|
5
|
-
init_task_attachment_links,
|
|
6
|
-
taskAttachmentDisplayUrl
|
|
7
|
-
} from "./cli-9d8ntetj.js";
|
|
8
|
-
import {
|
|
9
|
-
buildRoutingAffinityFromAgent,
|
|
10
|
-
createLogEntry,
|
|
11
|
-
createTaskExtended,
|
|
12
|
-
getActiveTaskCount,
|
|
13
|
-
getAgentById,
|
|
14
|
-
getDbClient,
|
|
15
|
-
getDependentTasks,
|
|
16
|
-
getLeadAgent,
|
|
17
|
-
getSwarmConfigs,
|
|
18
|
-
getTaskAttachments,
|
|
19
|
-
getTaskById,
|
|
20
|
-
hasNonTerminalRerouteDecisionChild,
|
|
21
|
-
init_date_utils,
|
|
22
|
-
init_db,
|
|
23
|
-
init_templates,
|
|
24
|
-
isAgentEligibleForTask,
|
|
25
|
-
normalizeDateRequired,
|
|
26
|
-
updateAgentMaxTasks,
|
|
27
|
-
updateAgentStatus,
|
|
28
|
-
upsertSwarmConfig
|
|
29
|
-
} from "./cli-qgd4sqz5.js";
|
|
30
|
-
import {
|
|
31
|
-
init_resolver,
|
|
32
|
-
resolveTemplate
|
|
33
|
-
} from "./cli-3apbzgyk.js";
|
|
34
|
-
import {
|
|
35
|
-
init_env_flag,
|
|
36
|
-
isEnvFlagEnabled
|
|
37
|
-
} from "./cli-ej6gbxfb.js";
|
|
38
|
-
|
|
39
|
-
// src/be/multi-runtime.ts
|
|
40
|
-
init_db();
|
|
41
|
-
var AGENT_MAX_TASKS_CONFIG_KEY = "AGENT_MAX_TASKS";
|
|
42
|
-
function parseAgentMaxTasksValue(raw) {
|
|
43
|
-
const str = raw.trim();
|
|
44
|
-
if (!/^\d+$/.test(str))
|
|
45
|
-
return null;
|
|
46
|
-
const value = Number(str);
|
|
47
|
-
return value >= 1 && value <= 100 ? value : null;
|
|
48
|
-
}
|
|
49
|
-
function defaultMaxTasksForAgent(agent) {
|
|
50
|
-
return agent.isLead ? 2 : 1;
|
|
51
|
-
}
|
|
52
|
-
async function getAgentMaxTasksConfig(agentId) {
|
|
53
|
-
return (await getSwarmConfigs({ scope: "agent", scopeId: agentId, key: AGENT_MAX_TASKS_CONFIG_KEY }))[0] ?? null;
|
|
54
|
-
}
|
|
55
|
-
async function reconcileAgentMaxTasksPolicy(agentId) {
|
|
56
|
-
const agent = await getAgentById(agentId);
|
|
57
|
-
if (!agent)
|
|
58
|
-
return;
|
|
59
|
-
const existing = await getAgentMaxTasksConfig(agentId);
|
|
60
|
-
if (existing) {
|
|
61
|
-
const authoritative = parseAgentMaxTasksValue(existing.value);
|
|
62
|
-
if (authoritative !== null && authoritative !== (agent.maxTasks ?? 1)) {
|
|
63
|
-
await updateAgentMaxTasks(agentId, authoritative);
|
|
64
|
-
}
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
await upsertSwarmConfig({
|
|
68
|
-
scope: "agent",
|
|
69
|
-
scopeId: agentId,
|
|
70
|
-
key: AGENT_MAX_TASKS_CONFIG_KEY,
|
|
71
|
-
value: String(agent.maxTasks ?? defaultMaxTasksForAgent(agent)),
|
|
72
|
-
description: "Logical agent max-tasks policy (seeded from agents.maxTasks)"
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
async function resetAgentMaxTasksMirror(agentId) {
|
|
76
|
-
const agent = await getAgentById(agentId);
|
|
77
|
-
if (!agent)
|
|
78
|
-
return;
|
|
79
|
-
await updateAgentMaxTasks(agentId, defaultMaxTasksForAgent(agent));
|
|
80
|
-
}
|
|
81
|
-
async function upsertSwarmConfigWithPolicyMirror(data) {
|
|
82
|
-
const scopeId = data.scope === "agent" ? data.scopeId : null;
|
|
83
|
-
if (!scopeId || data.key !== AGENT_MAX_TASKS_CONFIG_KEY) {
|
|
84
|
-
return upsertSwarmConfig(data);
|
|
85
|
-
}
|
|
86
|
-
return await getDbClient().transaction(async () => {
|
|
87
|
-
const row = await upsertSwarmConfig(data);
|
|
88
|
-
const value = parseAgentMaxTasksValue(data.value);
|
|
89
|
-
if (value !== null)
|
|
90
|
-
await updateAgentMaxTasks(scopeId, value);
|
|
91
|
-
return row;
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
function rowToRuntimeInstance(row) {
|
|
95
|
-
let metadata = null;
|
|
96
|
-
if (row.metadata) {
|
|
97
|
-
try {
|
|
98
|
-
metadata = JSON.parse(row.metadata);
|
|
99
|
-
} catch {
|
|
100
|
-
metadata = null;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
id: row.id,
|
|
105
|
-
agentId: row.agent_id,
|
|
106
|
-
status: row.status,
|
|
107
|
-
reportedSlots: row.reported_slots,
|
|
108
|
-
credentialReady: row.credential_ready === null ? null : row.credential_ready === 1,
|
|
109
|
-
metadata,
|
|
110
|
-
lastSeenAt: row.last_seen_at,
|
|
111
|
-
createdAt: row.created_at,
|
|
112
|
-
updatedAt: row.updated_at
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
function runtimeStaleThresholdMinutes() {
|
|
116
|
-
return Number(process.env.RUNTIME_STALE_THRESHOLD_MIN) || 5;
|
|
117
|
-
}
|
|
118
|
-
function runtimeLivenessCutoff() {
|
|
119
|
-
return new Date(Date.now() - runtimeStaleThresholdMinutes() * 60 * 1000).toISOString();
|
|
120
|
-
}
|
|
121
|
-
async function upsertRuntimeInstance(instance) {
|
|
122
|
-
const metadataJson = instance.metadata ? JSON.stringify(instance.metadata) : null;
|
|
123
|
-
const row = await getDbClient().get(`INSERT INTO runtime_instances (id, agent_id, status, reported_slots, metadata)
|
|
124
|
-
VALUES (?, ?, 'active', ?, ?)
|
|
125
|
-
ON CONFLICT(id) DO UPDATE SET
|
|
126
|
-
status = 'active',
|
|
127
|
-
reported_slots = excluded.reported_slots,
|
|
128
|
-
metadata = COALESCE(excluded.metadata, runtime_instances.metadata),
|
|
129
|
-
last_seen_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
|
|
130
|
-
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
131
|
-
WHERE runtime_instances.agent_id = excluded.agent_id
|
|
132
|
-
RETURNING *`, [instance.id, instance.agentId, instance.reportedSlots, metadataJson]);
|
|
133
|
-
return row ? rowToRuntimeInstance(row) : null;
|
|
134
|
-
}
|
|
135
|
-
async function getRuntimeInstanceById(id) {
|
|
136
|
-
const row = await getDbClient().get("SELECT * FROM runtime_instances WHERE id = ?", [id]);
|
|
137
|
-
return row ? rowToRuntimeInstance(row) : null;
|
|
138
|
-
}
|
|
139
|
-
async function touchRuntimeInstance(id, agentId) {
|
|
140
|
-
const result = await getDbClient().run(`UPDATE runtime_instances
|
|
141
|
-
SET last_seen_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),
|
|
142
|
-
updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
143
|
-
WHERE id = ? AND agent_id = ? AND status = 'active' AND last_seen_at >= ?`, [id, agentId, runtimeLivenessCutoff()]);
|
|
144
|
-
return result.changes > 0;
|
|
145
|
-
}
|
|
146
|
-
async function markRuntimeInstanceOffline(id, agentId) {
|
|
147
|
-
const row = await getDbClient().get(`UPDATE runtime_instances
|
|
148
|
-
SET status = 'offline', updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
149
|
-
WHERE id = ? AND agent_id = ? RETURNING *`, [id, agentId]);
|
|
150
|
-
return row ? rowToRuntimeInstance(row) : null;
|
|
151
|
-
}
|
|
152
|
-
async function countActiveRuntimeInstancesForAgent(agentId) {
|
|
153
|
-
const result = await getDbClient().get(`SELECT COUNT(*) as count FROM runtime_instances
|
|
154
|
-
WHERE agent_id = ? AND status = 'active' AND last_seen_at >= ?`, [agentId, runtimeLivenessCutoff()]);
|
|
155
|
-
return result?.count ?? 0;
|
|
156
|
-
}
|
|
157
|
-
async function listRuntimeInstancesForAgent(agentId) {
|
|
158
|
-
const rows = await getDbClient().query(`SELECT *, (status = 'active' AND last_seen_at >= ?) AS is_live
|
|
159
|
-
FROM runtime_instances
|
|
160
|
-
WHERE agent_id = ?
|
|
161
|
-
ORDER BY created_at ASC, id ASC`, [runtimeLivenessCutoff(), agentId]);
|
|
162
|
-
return rows.map((row) => ({ ...rowToRuntimeInstance(row), isLive: row.is_live === 1 }));
|
|
163
|
-
}
|
|
164
|
-
async function setRuntimeCredentialReady(id, agentId, ready) {
|
|
165
|
-
const result = await getDbClient().run(`UPDATE runtime_instances
|
|
166
|
-
SET credential_ready = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')
|
|
167
|
-
WHERE id = ? AND agent_id = ? AND status = 'active' AND last_seen_at >= ?`, [ready ? 1 : 0, id, agentId, runtimeLivenessCutoff()]);
|
|
168
|
-
return result.changes > 0;
|
|
169
|
-
}
|
|
170
|
-
async function hasReadyLiveRuntime(agentId) {
|
|
171
|
-
const row = await getDbClient().get(`SELECT COUNT(*) c FROM runtime_instances
|
|
172
|
-
WHERE agent_id = ? AND status = 'active' AND last_seen_at >= ?
|
|
173
|
-
AND (credential_ready IS NULL OR credential_ready = 1)`, [agentId, runtimeLivenessCutoff()]);
|
|
174
|
-
return (row?.c ?? 0) > 0;
|
|
175
|
-
}
|
|
176
|
-
async function reconcileAgentStatusFromRuntimes(agentId) {
|
|
177
|
-
await getDbClient().transaction(async () => {
|
|
178
|
-
const agent = await getAgentById(agentId);
|
|
179
|
-
if (!agent)
|
|
180
|
-
return;
|
|
181
|
-
if (await countActiveRuntimeInstancesForAgent(agentId) === 0) {
|
|
182
|
-
if (agent.status !== "offline")
|
|
183
|
-
await updateAgentStatus(agentId, "offline");
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
if (!await hasReadyLiveRuntime(agentId)) {
|
|
187
|
-
if (agent.status !== "waiting_for_credentials") {
|
|
188
|
-
await updateAgentStatus(agentId, "waiting_for_credentials");
|
|
189
|
-
}
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
const next = await getActiveTaskCount(agentId) > 0 ? "busy" : "idle";
|
|
193
|
-
if (agent.status !== next)
|
|
194
|
-
await updateAgentStatus(agentId, next);
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
async function agentsWithLiveRuntime() {
|
|
198
|
-
const rows = await getDbClient().query(`SELECT DISTINCT agent_id FROM runtime_instances
|
|
199
|
-
WHERE status = 'active' AND last_seen_at >= ?`, [runtimeLivenessCutoff()]);
|
|
200
|
-
return new Set(rows.map((r) => r.agent_id));
|
|
201
|
-
}
|
|
202
|
-
async function expireStaleRuntimeInstances() {
|
|
203
|
-
if (!isMultiRuntimeEnabled()) {
|
|
204
|
-
return { expired: 0, agentsOffline: 0, pruned: 0 };
|
|
205
|
-
}
|
|
206
|
-
return await getDbClient().transaction(async (tx) => {
|
|
207
|
-
const cutoff = runtimeLivenessCutoff();
|
|
208
|
-
const stale = await tx.query(`SELECT id, agent_id FROM runtime_instances
|
|
209
|
-
WHERE status = 'active' AND last_seen_at < ?`, [cutoff]);
|
|
210
|
-
const pruned = (await tx.run("DELETE FROM runtime_instances WHERE last_seen_at < ?", [cutoff])).changes;
|
|
211
|
-
let agentsOffline = 0;
|
|
212
|
-
for (const agentId of new Set(stale.map((r) => r.agent_id))) {
|
|
213
|
-
await reconcileAgentStatusFromRuntimes(agentId);
|
|
214
|
-
if ((await getAgentById(agentId))?.status === "offline")
|
|
215
|
-
agentsOffline++;
|
|
216
|
-
}
|
|
217
|
-
return { expired: stale.length, agentsOffline, pruned };
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// src/be/db-queries/tracker.ts
|
|
222
|
-
init_date_utils();
|
|
223
|
-
init_db();
|
|
224
|
-
function normalizeTrackerSync(row) {
|
|
225
|
-
return {
|
|
226
|
-
...row,
|
|
227
|
-
lastSyncedAt: normalizeDateRequired(row.lastSyncedAt),
|
|
228
|
-
createdAt: normalizeDateRequired(row.createdAt)
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
function normalizeTrackerAgentMapping(row) {
|
|
232
|
-
return {
|
|
233
|
-
...row,
|
|
234
|
-
createdAt: normalizeDateRequired(row.createdAt)
|
|
235
|
-
};
|
|
236
|
-
}
|
|
237
|
-
async function getTrackerSync(provider, entityType, swarmId) {
|
|
238
|
-
const row = await getDbClient().get("SELECT * FROM tracker_sync WHERE provider = ? AND entityType = ? AND swarmId = ?", [provider, entityType, swarmId]);
|
|
239
|
-
return row ? normalizeTrackerSync(row) : null;
|
|
240
|
-
}
|
|
241
|
-
async function getTrackerSyncByExternalId(provider, entityType, externalId) {
|
|
242
|
-
const row = await getDbClient().get("SELECT * FROM tracker_sync WHERE provider = ? AND entityType = ? AND externalId = ?", [provider, entityType, externalId]);
|
|
243
|
-
return row ? normalizeTrackerSync(row) : null;
|
|
244
|
-
}
|
|
245
|
-
async function createTrackerSyncIfAbsent(data) {
|
|
246
|
-
const insertResult = await getDbClient().get(`INSERT INTO tracker_sync (provider, entityType, providerEntityType, swarmId, externalId, externalIdentifier, externalUrl, lastSyncOrigin, lastDeliveryId, syncDirection)
|
|
247
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
248
|
-
ON CONFLICT (provider, entityType, externalId) DO NOTHING
|
|
249
|
-
RETURNING *`, [
|
|
250
|
-
data.provider,
|
|
251
|
-
data.entityType,
|
|
252
|
-
data.providerEntityType ?? null,
|
|
253
|
-
data.swarmId,
|
|
254
|
-
data.externalId,
|
|
255
|
-
data.externalIdentifier ?? null,
|
|
256
|
-
data.externalUrl ?? null,
|
|
257
|
-
data.lastSyncOrigin ?? null,
|
|
258
|
-
data.lastDeliveryId ?? null,
|
|
259
|
-
data.syncDirection ?? "inbound"
|
|
260
|
-
]);
|
|
261
|
-
if (insertResult) {
|
|
262
|
-
return { inserted: true, sync: normalizeTrackerSync(insertResult) };
|
|
263
|
-
}
|
|
264
|
-
const existing = await getTrackerSyncByExternalId(data.provider, data.entityType, data.externalId);
|
|
265
|
-
if (!existing) {
|
|
266
|
-
throw new Error(`[tracker] createTrackerSyncIfAbsent: ON CONFLICT fired but no existing row found for (${data.provider}, ${data.entityType}, ${data.externalId})`);
|
|
267
|
-
}
|
|
268
|
-
return { inserted: false, sync: existing };
|
|
269
|
-
}
|
|
270
|
-
async function updateTrackerSyncSwarmId(id, swarmId) {
|
|
271
|
-
await getDbClient().run("UPDATE tracker_sync SET swarmId = ? WHERE id = ?", [swarmId, id]);
|
|
272
|
-
}
|
|
273
|
-
async function repointTrackerSyncBySwarmId(oldSwarmId, newSwarmId) {
|
|
274
|
-
const result = await getDbClient().run("UPDATE tracker_sync SET swarmId = ? WHERE swarmId = ?", [
|
|
275
|
-
newSwarmId,
|
|
276
|
-
oldSwarmId
|
|
277
|
-
]);
|
|
278
|
-
return Number(result.changes ?? 0);
|
|
279
|
-
}
|
|
280
|
-
async function createTrackerSync(data) {
|
|
281
|
-
const result = await getDbClient().get(`INSERT INTO tracker_sync (provider, entityType, providerEntityType, swarmId, externalId, externalIdentifier, externalUrl, lastSyncOrigin, lastDeliveryId, syncDirection)
|
|
282
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
283
|
-
RETURNING *`, [
|
|
284
|
-
data.provider,
|
|
285
|
-
data.entityType,
|
|
286
|
-
data.providerEntityType ?? null,
|
|
287
|
-
data.swarmId,
|
|
288
|
-
data.externalId,
|
|
289
|
-
data.externalIdentifier ?? null,
|
|
290
|
-
data.externalUrl ?? null,
|
|
291
|
-
data.lastSyncOrigin ?? null,
|
|
292
|
-
data.lastDeliveryId ?? null,
|
|
293
|
-
data.syncDirection ?? "inbound"
|
|
294
|
-
]);
|
|
295
|
-
return normalizeTrackerSync(result);
|
|
296
|
-
}
|
|
297
|
-
async function updateTrackerSync(id, data) {
|
|
298
|
-
const sets = [];
|
|
299
|
-
const values = [];
|
|
300
|
-
if (data.lastSyncedAt !== undefined) {
|
|
301
|
-
sets.push("lastSyncedAt = ?");
|
|
302
|
-
values.push(data.lastSyncedAt);
|
|
303
|
-
}
|
|
304
|
-
if (data.lastSyncOrigin !== undefined) {
|
|
305
|
-
sets.push("lastSyncOrigin = ?");
|
|
306
|
-
values.push(data.lastSyncOrigin);
|
|
307
|
-
}
|
|
308
|
-
if (data.lastDeliveryId !== undefined) {
|
|
309
|
-
sets.push("lastDeliveryId = ?");
|
|
310
|
-
values.push(data.lastDeliveryId);
|
|
311
|
-
}
|
|
312
|
-
if (data.syncDirection !== undefined) {
|
|
313
|
-
sets.push("syncDirection = ?");
|
|
314
|
-
values.push(data.syncDirection);
|
|
315
|
-
}
|
|
316
|
-
if (data.externalUrl !== undefined) {
|
|
317
|
-
sets.push("externalUrl = ?");
|
|
318
|
-
values.push(data.externalUrl);
|
|
319
|
-
}
|
|
320
|
-
if (data.externalIdentifier !== undefined) {
|
|
321
|
-
sets.push("externalIdentifier = ?");
|
|
322
|
-
values.push(data.externalIdentifier);
|
|
323
|
-
}
|
|
324
|
-
if (sets.length === 0)
|
|
325
|
-
return;
|
|
326
|
-
values.push(id);
|
|
327
|
-
await getDbClient().run(`UPDATE tracker_sync SET ${sets.join(", ")} WHERE id = ?`, values);
|
|
328
|
-
}
|
|
329
|
-
async function deleteTrackerSync(id) {
|
|
330
|
-
await getDbClient().run("DELETE FROM tracker_sync WHERE id = ?", [id]);
|
|
331
|
-
}
|
|
332
|
-
async function hasTrackerDelivery(provider, deliveryId) {
|
|
333
|
-
if (!deliveryId)
|
|
334
|
-
return false;
|
|
335
|
-
const row = await getDbClient().get("SELECT 1 AS hit FROM tracker_sync WHERE provider = ? AND lastDeliveryId = ? LIMIT 1", [provider, deliveryId]);
|
|
336
|
-
return !!row;
|
|
337
|
-
}
|
|
338
|
-
async function markTrackerDelivery(provider, entityType, externalId, deliveryId) {
|
|
339
|
-
await getDbClient().run("UPDATE tracker_sync SET lastDeliveryId = ? WHERE provider = ? AND entityType = ? AND externalId = ?", [deliveryId, provider, entityType, externalId]);
|
|
340
|
-
}
|
|
341
|
-
async function getAllTrackerSyncs(provider, entityType) {
|
|
342
|
-
const conditions = [];
|
|
343
|
-
const values = [];
|
|
344
|
-
if (provider) {
|
|
345
|
-
conditions.push("provider = ?");
|
|
346
|
-
values.push(provider);
|
|
347
|
-
}
|
|
348
|
-
if (entityType) {
|
|
349
|
-
conditions.push("entityType = ?");
|
|
350
|
-
values.push(entityType);
|
|
351
|
-
}
|
|
352
|
-
const where = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";
|
|
353
|
-
const rows = await getDbClient().query(`SELECT * FROM tracker_sync ${where} ORDER BY createdAt DESC`, values);
|
|
354
|
-
return rows.map(normalizeTrackerSync);
|
|
355
|
-
}
|
|
356
|
-
async function createTrackerAgentMapping(data) {
|
|
357
|
-
const result = await getDbClient().get(`INSERT INTO tracker_agent_mapping (provider, agentId, externalUserId, agentName)
|
|
358
|
-
VALUES (?, ?, ?, ?)
|
|
359
|
-
RETURNING *`, [data.provider, data.agentId, data.externalUserId, data.agentName]);
|
|
360
|
-
return normalizeTrackerAgentMapping(result);
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// src/tasks/worker-follow-up.ts
|
|
364
|
-
init_db();
|
|
365
|
-
init_resolver();
|
|
366
|
-
init_env_flag();
|
|
367
|
-
init_task_attachment_links();
|
|
368
|
-
init_templates();
|
|
369
|
-
var WORKER_LIVENESS_WINDOW_SECONDS = Number(process.env.WORKER_LIVENESS_WINDOW_SECONDS || "30");
|
|
370
|
-
function isCrashResumePinEnabled() {
|
|
371
|
-
return isEnvFlagEnabled("HEARTBEAT_PIN_CRASH_RESUME", true);
|
|
372
|
-
}
|
|
373
|
-
function isGracefulResumePinEnabled() {
|
|
374
|
-
return process.env.HEARTBEAT_PIN_GRACEFUL_RESUME !== "0";
|
|
375
|
-
}
|
|
376
|
-
var RESUME_GENERATION_TAG_PREFIX = "resume-generation:";
|
|
377
|
-
var CRASH_RECOVERY_PIN_TAG = "crash-recovery-pin";
|
|
378
|
-
var GRACEFUL_SHUTDOWN_PIN_TAG = "graceful-shutdown-pin";
|
|
379
|
-
var REBOOT_RETRY_PIN_TAG = "reboot-retry-pin";
|
|
380
|
-
async function getPinCandidateAgent(agentId) {
|
|
381
|
-
const candidate = await getAgentById(agentId);
|
|
382
|
-
if (!candidate || candidate.status === "offline")
|
|
383
|
-
return null;
|
|
384
|
-
return candidate;
|
|
385
|
-
}
|
|
386
|
-
async function resolveLeadOnlyRecoveryAssignment(task, sourceCandidate) {
|
|
387
|
-
if (!task.routingAffinity?.leadOnly)
|
|
388
|
-
return {};
|
|
389
|
-
if (sourceCandidate?.isLead && isAgentEligibleForTask(sourceCandidate, task)) {
|
|
390
|
-
return { agentId: sourceCandidate.id, decision: "source_lead_pin" };
|
|
391
|
-
}
|
|
392
|
-
const lead = await getLeadAgent();
|
|
393
|
-
if (lead && lead.status !== "offline" && isAgentEligibleForTask(lead, task)) {
|
|
394
|
-
return { agentId: lead.id, decision: "rerouted_to_lead" };
|
|
395
|
-
}
|
|
396
|
-
return { decision: "escalated_unassigned" };
|
|
397
|
-
}
|
|
398
|
-
function getResumeGeneration(task) {
|
|
399
|
-
const tag = task.tags.find((value) => value.startsWith(RESUME_GENERATION_TAG_PREFIX));
|
|
400
|
-
if (!tag)
|
|
401
|
-
return 0;
|
|
402
|
-
const parsed = Number(tag.slice(RESUME_GENERATION_TAG_PREFIX.length));
|
|
403
|
-
return Number.isInteger(parsed) && parsed > 0 ? parsed : 0;
|
|
404
|
-
}
|
|
405
|
-
function getNextResumeGeneration(parent) {
|
|
406
|
-
return getResumeGeneration(parent) + 1;
|
|
407
|
-
}
|
|
408
|
-
function attachmentPointer(a) {
|
|
409
|
-
return taskAttachmentDisplayUrl(a);
|
|
410
|
-
}
|
|
411
|
-
function formatAttachmentsBlock(attachments) {
|
|
412
|
-
if (attachments.length === 0)
|
|
413
|
-
return "";
|
|
414
|
-
const lines = attachments.map((a) => {
|
|
415
|
-
const tag = a.isPrimary ? "[primary] " : "";
|
|
416
|
-
const intent = a.intent ? ` (intent: ${a.intent})` : "";
|
|
417
|
-
return `- ${tag}${a.name} - ${attachmentPointer(a)}${intent}`;
|
|
418
|
-
});
|
|
419
|
-
return `
|
|
420
|
-
|
|
421
|
-
Attachments (${attachments.length}):
|
|
422
|
-
${lines.join(`
|
|
423
|
-
`)}`;
|
|
424
|
-
}
|
|
425
|
-
async function createWorkerTaskFollowUp(args) {
|
|
426
|
-
const { task, status, output, failureReason } = args;
|
|
427
|
-
if (task.workflowRunId)
|
|
428
|
-
return null;
|
|
429
|
-
if (task.followUpConfig?.disabled === true)
|
|
430
|
-
return null;
|
|
431
|
-
const taskAgent = await getAgentById(task.agentId ?? "");
|
|
432
|
-
if (!taskAgent || taskAgent.isLead)
|
|
433
|
-
return null;
|
|
434
|
-
const leadAgent = await getLeadAgent();
|
|
435
|
-
if (!leadAgent)
|
|
436
|
-
return null;
|
|
437
|
-
const agentName = taskAgent.name || task.agentId?.slice(0, 8) || "Unknown";
|
|
438
|
-
const taskDesc = task.task.slice(0, 200);
|
|
439
|
-
const creatorAgent = task.creatorAgentId ? `${task.creatorAgentId}${task.creatorAgentId === leadAgent.id ? " (you)" : ""}` : "<none>";
|
|
440
|
-
const instructions = status === "completed" ? task.followUpConfig?.onCompleted ?? "" : task.followUpConfig?.onFailed ?? "";
|
|
441
|
-
const followUpInstructions = instructions ? `
|
|
442
|
-
Additional instructions from the task creator:
|
|
443
|
-
${instructions}
|
|
444
|
-
` : "";
|
|
445
|
-
let followUpDescription;
|
|
446
|
-
if (status === "completed") {
|
|
447
|
-
const attachmentsBlock = formatAttachmentsBlock(await getTaskAttachments(task.id));
|
|
448
|
-
const outputSummary = output ? `${output.slice(0, 500)}${output.length > 500 ? "..." : ""}${attachmentsBlock}` : `(no output)${attachmentsBlock}`;
|
|
449
|
-
const completedResult = resolveTemplate("task.worker.completed", {
|
|
450
|
-
agent_name: agentName,
|
|
451
|
-
task_desc: taskDesc,
|
|
452
|
-
creator_agent: creatorAgent,
|
|
453
|
-
output_summary: outputSummary,
|
|
454
|
-
follow_up_instructions: followUpInstructions,
|
|
455
|
-
task_id: task.id
|
|
456
|
-
});
|
|
457
|
-
followUpDescription = completedResult.text;
|
|
458
|
-
} else {
|
|
459
|
-
const reason = failureReason || "(no reason given)";
|
|
460
|
-
const failedResult = resolveTemplate("task.worker.failed", {
|
|
461
|
-
agent_name: agentName,
|
|
462
|
-
task_desc: taskDesc,
|
|
463
|
-
creator_agent: creatorAgent,
|
|
464
|
-
failure_reason: reason,
|
|
465
|
-
follow_up_instructions: followUpInstructions,
|
|
466
|
-
task_id: task.id
|
|
467
|
-
});
|
|
468
|
-
followUpDescription = failedResult.text;
|
|
469
|
-
const cascadedDeps = (await getDependentTasks(task.id, { includeTerminal: true })).filter((t) => t.status === "failed" && t.failureReason?.includes("Blocked dependency"));
|
|
470
|
-
if (cascadedDeps.length > 0) {
|
|
471
|
-
const depLines = cascadedDeps.map((d) => `- ${d.id.slice(0, 8)} — "${d.task.slice(0, 100)}" (${d.failureReason})`);
|
|
472
|
-
followUpDescription += `
|
|
473
|
-
|
|
474
|
-
⚠️ Cascade impact: ${cascadedDeps.length} dependent task(s) were also failed because they depend on this task:
|
|
475
|
-
${depLines.join(`
|
|
476
|
-
`)}`;
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
return await createTaskExtended(followUpDescription, {
|
|
480
|
-
agentId: leadAgent.id,
|
|
481
|
-
routingReason: "skill",
|
|
482
|
-
source: "system",
|
|
483
|
-
taskType: "follow-up",
|
|
484
|
-
parentTaskId: task.id,
|
|
485
|
-
slackChannelId: task.slackChannelId,
|
|
486
|
-
slackThreadTs: task.slackThreadTs,
|
|
487
|
-
slackUserId: task.slackUserId
|
|
488
|
-
});
|
|
489
|
-
}
|
|
490
|
-
async function createResumeFollowUp(args) {
|
|
491
|
-
const parent = await getTaskById(args.parentId);
|
|
492
|
-
if (!parent)
|
|
493
|
-
return { kind: "skipped", reason: "parent_not_found" };
|
|
494
|
-
if (parent.workflowRunStepId) {
|
|
495
|
-
return { kind: "workflow-skip", stepId: parent.workflowRunStepId };
|
|
496
|
-
}
|
|
497
|
-
let preferredAgentId;
|
|
498
|
-
let authorizationDecision;
|
|
499
|
-
const leadOnly = parent.routingAffinity?.leadOnly === true;
|
|
500
|
-
if (parent.agentId) {
|
|
501
|
-
const candidate = await getPinCandidateAgent(parent.agentId);
|
|
502
|
-
if (candidate) {
|
|
503
|
-
const lastActivity = candidate.lastActivityAt ? Date.parse(candidate.lastActivityAt) : 0;
|
|
504
|
-
const fresh = Number.isFinite(lastActivity) && Date.now() - lastActivity < WORKER_LIVENESS_WINDOW_SECONDS * 1000;
|
|
505
|
-
const activeCount = await getActiveTaskCount(candidate.id);
|
|
506
|
-
const hasCap = activeCount < (candidate.maxTasks ?? 1);
|
|
507
|
-
const isCrashRecovery = args.reason === "crash_recovery" && isCrashResumePinEnabled();
|
|
508
|
-
const isGracefulShutdown = args.reason === "graceful_shutdown";
|
|
509
|
-
const isGracefulPin = isGracefulShutdown && isGracefulResumePinEnabled();
|
|
510
|
-
const isFreshPinnedReason = !isGracefulShutdown && fresh;
|
|
511
|
-
if (hasCap && (isCrashRecovery || isGracefulPin || isFreshPinnedReason) && (!leadOnly || candidate.isLead)) {
|
|
512
|
-
preferredAgentId = candidate.id;
|
|
513
|
-
if (leadOnly)
|
|
514
|
-
authorizationDecision = "source_lead_pin";
|
|
515
|
-
} else if ((isCrashRecovery || isGracefulPin) && !hasCap) {
|
|
516
|
-
console.warn(`[Heartbeat] ${args.reason} resume for task ${parent.id.slice(0, 8)} NOT pinned: agent ${candidate.id.slice(0, 8)} at capacity (${activeCount}/${candidate.maxTasks ?? 1}); falling back to unassigned pool`);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
if (leadOnly) {
|
|
521
|
-
const source = preferredAgentId ? await getAgentById(preferredAgentId) : null;
|
|
522
|
-
const resolution = await resolveLeadOnlyRecoveryAssignment(parent, source);
|
|
523
|
-
preferredAgentId = resolution.agentId;
|
|
524
|
-
authorizationDecision = resolution.decision;
|
|
525
|
-
}
|
|
526
|
-
const parentDesc = parent.task.slice(0, 200);
|
|
527
|
-
const followUpDescription = [
|
|
528
|
-
"Resume interrupted task.",
|
|
529
|
-
"",
|
|
530
|
-
`Parent task: ${parentDesc}`,
|
|
531
|
-
"",
|
|
532
|
-
`Reason: ${args.reason}`,
|
|
533
|
-
"",
|
|
534
|
-
"The full prior context (description, recent tool calls, artifacts) is",
|
|
535
|
-
"prepended to this prompt at dispatch time via the resume context preamble.",
|
|
536
|
-
"Do NOT redo work already completed — extend it."
|
|
537
|
-
].join(`
|
|
538
|
-
`);
|
|
539
|
-
const priority = Math.min(100, (parent.priority ?? 50) + 10);
|
|
540
|
-
const tags = [
|
|
541
|
-
"auto-resume",
|
|
542
|
-
`reason:${args.reason}`,
|
|
543
|
-
`${RESUME_GENERATION_TAG_PREFIX}${getNextResumeGeneration(parent)}`
|
|
544
|
-
];
|
|
545
|
-
if (args.reason === "crash_recovery" && preferredAgentId === parent.agentId) {
|
|
546
|
-
tags.push(CRASH_RECOVERY_PIN_TAG);
|
|
547
|
-
}
|
|
548
|
-
if (args.reason === "graceful_shutdown" && preferredAgentId === parent.agentId) {
|
|
549
|
-
tags.push(GRACEFUL_SHUTDOWN_PIN_TAG);
|
|
550
|
-
}
|
|
551
|
-
const sourceAffinity = parent.agentId ? await buildRoutingAffinityFromAgent(parent.agentId) ?? undefined : undefined;
|
|
552
|
-
const routingAffinity = leadOnly ? {
|
|
553
|
-
...sourceAffinity ?? parent.routingAffinity,
|
|
554
|
-
capabilities: parent.routingAffinity?.capabilities ?? [],
|
|
555
|
-
leadOnly: true
|
|
556
|
-
} : sourceAffinity;
|
|
557
|
-
const created = await createTaskExtended(followUpDescription, {
|
|
558
|
-
agentId: preferredAgentId,
|
|
559
|
-
routingReason: preferredAgentId === undefined ? undefined : preferredAgentId === parent.agentId ? "continuity" : "reroute_fault",
|
|
560
|
-
creatorAgentId: parent.creatorAgentId,
|
|
561
|
-
source: "system",
|
|
562
|
-
taskType: "resume",
|
|
563
|
-
tags,
|
|
564
|
-
priority,
|
|
565
|
-
parentTaskId: parent.id,
|
|
566
|
-
routingAffinity
|
|
567
|
-
});
|
|
568
|
-
if (authorizationDecision) {
|
|
569
|
-
try {
|
|
570
|
-
await createLogEntry({
|
|
571
|
-
eventType: "task_recovery_authorization",
|
|
572
|
-
taskId: created.id,
|
|
573
|
-
agentId: preferredAgentId,
|
|
574
|
-
metadata: {
|
|
575
|
-
leadOnly: true,
|
|
576
|
-
parentTaskId: parent.id,
|
|
577
|
-
sourceAgentId: parent.agentId,
|
|
578
|
-
decision: authorizationDecision
|
|
579
|
-
}
|
|
580
|
-
});
|
|
581
|
-
} catch {}
|
|
582
|
-
}
|
|
583
|
-
const repointed = await repointTrackerSyncBySwarmId(parent.id, created.id);
|
|
584
|
-
if (repointed > 0) {
|
|
585
|
-
console.log(`[ResumeFollowUp] Repointed ${repointed} tracker_sync row(s) from ${parent.id.slice(0, 8)} → ${created.id.slice(0, 8)}`);
|
|
586
|
-
}
|
|
587
|
-
return { kind: "created", task: created };
|
|
588
|
-
}
|
|
589
|
-
async function createRerouteDecisionTask(args) {
|
|
590
|
-
const { original, staleResume, reason, maxGenerations } = args;
|
|
591
|
-
const leadAgent = await getLeadAgent();
|
|
592
|
-
if (!leadAgent)
|
|
593
|
-
return { kind: "skipped", reason: "lead_not_found" };
|
|
594
|
-
if (await hasNonTerminalRerouteDecisionChild(original.id)) {
|
|
595
|
-
return { kind: "skipped", reason: "duplicate_exists" };
|
|
596
|
-
}
|
|
597
|
-
const crashedAgent = original.agentId ? await getAgentById(original.agentId) : null;
|
|
598
|
-
const agentName = crashedAgent?.name || original.agentId?.slice(0, 8) || "unknown";
|
|
599
|
-
const identitySlice = crashedAgent?.identityMd ? `${crashedAgent.identityMd.slice(0, 500)}${crashedAgent.identityMd.length > 500 ? "..." : ""}` : "(no identity recorded)";
|
|
600
|
-
const attachmentsBlock = formatAttachmentsBlock(await getTaskAttachments(original.id));
|
|
601
|
-
const decision = resolveTemplate("task.reroute.decision", {
|
|
602
|
-
original_agent_name: agentName,
|
|
603
|
-
original_agent_identity: identitySlice,
|
|
604
|
-
original_task_id: original.id,
|
|
605
|
-
reason,
|
|
606
|
-
task_desc: original.task.slice(0, 200),
|
|
607
|
-
generation_next: getNextResumeGeneration(staleResume),
|
|
608
|
-
max_generations: maxGenerations,
|
|
609
|
-
artifacts_block: attachmentsBlock
|
|
610
|
-
});
|
|
611
|
-
const created = await createTaskExtended(decision.text, {
|
|
612
|
-
agentId: leadAgent.id,
|
|
613
|
-
routingReason: "reroute_fault",
|
|
614
|
-
creatorAgentId: original.creatorAgentId,
|
|
615
|
-
source: "system",
|
|
616
|
-
taskType: "reroute-decision",
|
|
617
|
-
tags: ["reroute-decision"],
|
|
618
|
-
priority: Math.min(100, (original.priority ?? 50) + 10),
|
|
619
|
-
parentTaskId: original.id,
|
|
620
|
-
inheritParentOutputSchema: false,
|
|
621
|
-
inheritParentRoutingAffinity: false,
|
|
622
|
-
routingAffinity: leadControlPlaneRoutingAffinity()
|
|
623
|
-
});
|
|
624
|
-
return { kind: "created", task: created };
|
|
625
|
-
}
|
|
626
|
-
function leadControlPlaneRoutingAffinity() {
|
|
627
|
-
return { leadOnly: true, capabilities: [] };
|
|
628
|
-
}
|
|
629
|
-
async function createPoolStarvationDecisionTask(args) {
|
|
630
|
-
const { original } = args;
|
|
631
|
-
const leadAgent = await getLeadAgent();
|
|
632
|
-
if (!leadAgent)
|
|
633
|
-
return { kind: "skipped", reason: "lead_not_found" };
|
|
634
|
-
if (await hasNonTerminalRerouteDecisionChild(original.id)) {
|
|
635
|
-
return { kind: "skipped", reason: "duplicate_exists" };
|
|
636
|
-
}
|
|
637
|
-
const affinity = original.routingAffinity;
|
|
638
|
-
const requiredRole = affinity?.role ?? "(none declared)";
|
|
639
|
-
const requiredCapabilities = affinity?.capabilities && affinity.capabilities.length > 0 ? affinity.capabilities.join(", ") : "(none declared)";
|
|
640
|
-
const attachmentsBlock = formatAttachmentsBlock(await getTaskAttachments(original.id));
|
|
641
|
-
const decision = resolveTemplate("task.pool.starved.decision", {
|
|
642
|
-
original_task_id: original.id,
|
|
643
|
-
task_desc: original.task.slice(0, 200),
|
|
644
|
-
required_role: requiredRole,
|
|
645
|
-
required_capabilities: requiredCapabilities,
|
|
646
|
-
artifacts_block: attachmentsBlock
|
|
647
|
-
});
|
|
648
|
-
const created = await createTaskExtended(decision.text, {
|
|
649
|
-
agentId: leadAgent.id,
|
|
650
|
-
routingReason: "overflow",
|
|
651
|
-
creatorAgentId: original.creatorAgentId,
|
|
652
|
-
source: "system",
|
|
653
|
-
taskType: "reroute-decision",
|
|
654
|
-
tags: ["reroute-decision", "pool-starvation"],
|
|
655
|
-
priority: Math.min(100, (original.priority ?? 50) + 10),
|
|
656
|
-
parentTaskId: original.id,
|
|
657
|
-
inheritParentOutputSchema: false,
|
|
658
|
-
inheritParentRoutingAffinity: false,
|
|
659
|
-
routingAffinity: leadControlPlaneRoutingAffinity()
|
|
660
|
-
});
|
|
661
|
-
return { kind: "created", task: created };
|
|
662
|
-
}
|
|
663
|
-
|
|
664
|
-
export { AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, touchRuntimeInstance, markRuntimeInstanceOffline, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, getTrackerSync, getTrackerSyncByExternalId, createTrackerSyncIfAbsent, updateTrackerSyncSwarmId, repointTrackerSyncBySwarmId, createTrackerSync, updateTrackerSync, deleteTrackerSync, hasTrackerDelivery, markTrackerDelivery, getAllTrackerSyncs, createTrackerAgentMapping, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask };
|