@desplega.ai/agent-swarm 1.172.0 → 2.0.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 +1 -1
- package/dist/{acp-adapter-fpecx1g1.js → acp-adapter-sj2g0m84.js} +18 -17
- package/dist/{actions-pw87a1a8.js → actions-fegk44gr.js} +65 -35
- package/dist/{amp-adapter-8jem2bc0.js → amp-adapter-ad8ft89x.js} +8 -7
- package/dist/{anthropic-messages-8ee2f22q.js → anthropic-messages-r6czkjv1.js} +7 -7
- package/dist/{app-wmf0m843.js → app-kfvgbvzy.js} +19 -13
- package/dist/{assistant-emp1e108.js → assistant-z7zdy9ja.js} +65 -38
- package/dist/{boot-reembed-1de4f4aj.js → boot-reembed-5c2z0mbe.js} +11 -9
- package/dist/{boot-reembed-4ymn9atn.js → boot-reembed-j8xa181e.js} +11 -9
- package/dist/{boot-scrub-sweep-adhk1s8c.js → boot-scrub-sweep-hnkn3rgt.js} +12 -10
- package/dist/{boot-seeds-8q637aew.js → boot-seeds-kwjq4d2z.js} +15 -13
- package/dist/{claude-adapter-t26cv8a4.js → claude-adapter-9vmvpvgd.js} +20 -19
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-k9qae05j.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-q54zx5q2.js} +6 -4
- package/dist/{claude-sdk-session-gsfsh662.js → claude-sdk-session-9jye6cxr.js} +12698 -11995
- package/dist/{cli-k46r9hmk.js → cli-03gedhng.js} +16 -14
- package/dist/{cli-kb4ehzx5.js → cli-1e4b6bzh.js} +7 -7
- package/dist/{cli-d603qf86.js → cli-29jc5q7w.js} +10 -8
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-8vs9trd4.js → cli-3dj8k4vy.js} +1 -1
- package/dist/{cli-zxm9p3x4.js → cli-3fbmmawm.js} +5 -5
- package/dist/{cli-gmdajfw5.js → cli-4jxm2qtz.js} +4987 -1708
- package/dist/{cli-tadfgd0t.js → cli-5hkm7whv.js} +33 -4
- package/dist/{cli-6jb2rf77.js → cli-5t4f29ez.js} +3 -3
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-pj6x9qce.js → cli-6jyj59nb.js} +2 -2
- package/dist/{cli-388egyf6.js → cli-6razj6t4.js} +2 -2
- package/dist/{cli-qsztpfry.js → cli-74ahz61x.js} +2 -2
- package/dist/{cli-4nz8p1p5.js → cli-7x0g4sn1.js} +15474 -16082
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-81r1wjyv.js → cli-9nfx44eh.js} +1 -1
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-bf7485pm.js → cli-apx87jne.js} +2 -2
- package/dist/{cli-ztrv9y21.js → cli-bzszjf2p.js} +3689 -1081
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/{cli-hsem16hb.js → cli-cgtksawx.js} +7 -4
- package/dist/{cli-db3m6zdt.js → cli-d2qr7aj4.js} +1 -1
- package/dist/{cli-1hgat6pa.js → cli-d5f9ed5c.js} +5 -5
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/{cli-7jykv7ef.js → cli-e6mpjhed.js} +1 -1
- package/dist/{cli-j6kpj9az.js → cli-ee9gtz70.js} +1553 -68
- package/dist/{cli-e0a9sk00.js → cli-eejsgvm4.js} +4 -4
- package/dist/{cli-tgpfnm6r.js → cli-ef1hg1wv.js} +518 -59
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-ppy4nnnh.js → cli-f7kr7svz.js} +2 -2
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-2bw3w47j.js → cli-hnhtk6cj.js} +1 -1
- package/dist/{cli-ywm1azg9.js → cli-hnmhtzvh.js} +6 -4
- package/dist/{cli-4fnb6884.js → cli-hvqbtna4.js} +7 -1259
- package/dist/{cli-pstq9888.js → cli-j0pfptdp.js} +220 -103
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-esnpehf5.js → cli-k382tshb.js} +12 -13
- package/dist/cli-k3dp5tpf.js +263 -0
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-prrt9fa0.js → cli-ke896fcf.js} +10 -10
- package/dist/{cli-nv4zd0b9.js → cli-kt6zqg0e.js} +6 -6
- package/dist/{cli-g6t9texm.js → cli-m50t4309.js} +5 -18
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-c2pq2rjb.js → cli-n3hzg89b.js} +46 -15
- package/dist/{cli-tmhsxhb8.js → cli-n5vwg842.js} +23 -6
- package/dist/{cli-5rv1j9ga.js → cli-ne236afy.js} +53 -7
- package/dist/cli-p0sg24zp.js +16 -0
- package/dist/{cli-d161g69q.js → cli-p1x85d2t.js} +50 -2
- package/dist/{cli-7pz3b7x5.js → cli-przpmdgr.js} +25 -0
- package/dist/{cli-g4f5pj26.js → cli-q0ke1yww.js} +111 -25
- package/dist/{cli-e3pmyt39.js → cli-q50942rs.js} +1 -1
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-gj81e47t.js → cli-r2pnvj8g.js} +2 -2
- package/dist/{cli-r8smj8b8.js → cli-r62a35ea.js} +19 -3
- package/dist/{cli-cd0hv9nh.js → cli-ra0xzggj.js} +2 -2
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-nyhb1r6x.js → cli-s2sp957d.js} +52 -29
- package/dist/{cli-1x7da0de.js → cli-s4setq91.js} +8 -8
- package/dist/{cli-xczpdp9e.js → cli-se8w6wny.js} +6 -6
- package/dist/cli-skxvvpap.js +10140 -0
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-0p3enk35.js → cli-tqaazemc.js} +9 -1
- package/dist/{cli-cf69s3ew.js → cli-tr4sxp68.js} +3 -3
- package/dist/{cli-8hzfb6xz.js → cli-tsde1hdr.js} +15 -15
- package/dist/{cli-cceskcvt.js → cli-txqb9s38.js} +8 -8
- package/dist/{cli-aspcaef3.js → cli-v1yb0rqb.js} +6 -6
- package/dist/{cli-j1pmc07z.js → cli-vatyhshy.js} +268 -40
- package/dist/{cli-04emfe2q.js → cli-vdach5a9.js} +5 -5
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/{cli-hwwvy36w.js → cli-wayw93nt.js} +3 -3
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-gp1rtyvk.js → cli-z5jjpaxw.js} +29 -6
- package/dist/{cli-451ks6aw.js → cli-zkpks3r3.js} +1 -1
- package/dist/cli.js +32 -48
- package/dist/{codex-adapter-m4tgdysy.js → codex-adapter-y81sssk0.js} +16 -15
- package/dist/{codex-login-841kv5fk.js → codex-login-f2rcfpp9.js} +3 -2
- package/dist/{codex-session-runner-ymwzm6ea.js → codex-session-runner-8vx4j6a9.js} +16 -15
- package/dist/{commands-n0hshcvs.js → commands-kcpvpcrr.js} +21 -10
- package/dist/{controller-hq5ggpcp.js → controller-ywrmt6yd.js} +5 -4
- package/dist/{controllers-connect-y07cqcvy.js → controllers-connect-kwpvj3rf.js} +45 -38
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-cehv1qns.js} +7 -6
- package/dist/{db-hkqvrdcb.js → db-k8ankj20.js} +13 -11
- package/dist/{db-4w7tmt1g.js → db-ww5d7jq3.js} +29 -9
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-x1022qb1.js} +3 -2
- package/dist/{dispatcher-5sd69y14.js → dispatcher-e8gq5m68.js} +41 -34
- package/dist/{docker-f503k9p0.js → docker-ff6y1190.js} +3 -2
- package/dist/{dsh-adapter-2h8m4cab.js → dsh-adapter-3epjm3af.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-8ygwhg0f.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-swhnpw3n.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-6axnngdj.js} +3 -2
- package/dist/external-channel-h3359cwn.js +52 -0
- package/dist/{google-generative-ai-7pavrbv7.js → google-generative-ai-g8db7x0f.js} +5 -3
- package/dist/{google-vertex-3f1jk41f.js → google-vertex-r2692q0r.js} +5 -3
- package/dist/{grok-adapter-8m9yqzbq.js → grok-adapter-0d4x7gkx.js} +19 -18
- package/dist/{handlers-s20xr10r.js → handlers-an1gzv21.js} +44 -37
- package/dist/{heartbeat-3k31q4g2.js → heartbeat-6dakeb61.js} +46 -39
- package/dist/{hook-gdn6a2fn.js → hook-6v6cv6d5.js} +12 -24
- package/dist/{hook-ygwerrdh.js → hook-sa5xye4y.js} +13 -12
- package/dist/{http-jdteeg81.js → http-r7f3eky0.js} +1598 -279
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-e0snym4t.js → index-7ep4gzdk.js} +41 -34
- package/dist/index-9gw58n4k.js +193 -0
- package/dist/index-9j87mcm8.js +56305 -0
- package/dist/index-bsmcresk.js +79424 -0
- package/dist/index-mh85qhec.js +475 -0
- package/dist/{index-vm3bm9t7.js → index-rmpw9a8q.js} +41 -34
- package/dist/{index-6ksewd5y.js → index-s2wxgzr0.js} +1015 -732
- package/dist/{index-tsszt7g9.js → index-v1v6n7hg.js} +46 -39
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{index-ffqzqgwb.js → index-zk96aq1k.js} +11 -9
- package/dist/{keepalive-jekc896t.js → keepalive-be9vwy5h.js} +13 -11
- package/dist/{lead-4k9s9szx.js → lead-0861cwrf.js} +64 -57
- package/dist/{maintenance-shazch4n.js → maintenance-mzzgc8bn.js} +11 -9
- package/dist/node-c9we95xf.js +1 -1
- package/dist/{node-fkajaq96.js → node-mn1zs7an.js} +2 -1
- package/dist/{oauth-refresh-sweep-5gb36kn8.js → oauth-refresh-sweep-cpdnfwdj.js} +12 -10
- package/dist/{onboard-ydrbnvww.js → onboard-fh8qs4r3.js} +11 -3
- package/dist/{opencode-adapter-5zh0he20.js → opencode-adapter-nm42wwj8.js} +19 -14
- package/dist/{otel-impl-6pf5cv86.js → otel-impl-x6c1c9g4.js} +248 -869
- package/dist/{pi-mono-adapter-ef9wwx9m.js → pi-mono-adapter-9n2ya240.js} +245 -107
- package/dist/{pricing-refresh-s52nsa5q.js → pricing-refresh-qb0rv0ap.js} +13 -11
- package/dist/{rbac-roles-aq3msh4e.js → rbac-roles-1gzdwbh1.js} +12 -10
- package/dist/{rbac-roles-q5gb5e8v.js → rbac-roles-3mraey52.js} +13 -11
- package/dist/{render-v2-pd1rg54q.js → render-v2-agpa45zz.js} +19 -13
- package/dist/{resume-gw4a2c6v.js → resume-x0ydy9s9.js} +27 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-jda1ksdh.js → setup-as9ga0d6.js} +2 -2
- package/dist/{virtual-modules-b3ga2m65.js → virtual-modules-9gkxqrap.js} +7 -6
- package/dist/{work-objects-tb7ycye8.js → work-objects-y5g1y7ev.js} +49 -37
- package/dist/{worker-njjccz5d.js → worker-860c3e38.js} +64 -57
- package/dist/{x-qfmygqqv.js → x-m477fr0h.js} +3 -2
- package/openapi.json +951 -356
- package/package.json +12 -13
- package/src/apps/catalog.generated.json +1309 -53
- package/src/apps/page-validator.ts +93 -31
- package/src/azure-devops/api.ts +94 -18
- package/src/azure-devops/auth.ts +32 -0
- package/src/azure-devops/boards-sync.ts +708 -0
- package/src/azure-devops/handlers.ts +52 -8
- package/src/azure-devops/html.ts +26 -0
- package/src/azure-devops/index.ts +15 -0
- package/src/azure-devops/templates.ts +86 -0
- package/src/azure-devops/types.ts +65 -1
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/page-versions.ts +15 -0
- package/src/be/db/runtime.ts +35 -8
- package/src/be/db/skill-name-resolution.ts +36 -0
- package/src/be/db/tasks/read.ts +230 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +74 -13
- package/src/be/migrations/213_script_connections_sql.sql +79 -0
- package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
- package/src/be/migrations/216_task_resolved_effort.sql +5 -0
- package/src/be/migrations/217_chat_sdk_state.sql +104 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +12 -1
- package/src/be/model-validation.ts +5 -2
- package/src/be/models-catalog.ts +26 -1
- package/src/be/modelsdev-cache.json +198 -63
- package/src/be/modelsdev-cache.ts +9 -1
- package/src/be/script-connections.ts +47 -8
- package/src/be/script-credential-broker.ts +39 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +10 -8
- package/src/be/seed/runner.ts +13 -1
- package/src/be/seed/state-db.ts +5 -0
- package/src/be/seed/types.ts +6 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/seed-skills/bundled-files.generated.json +10 -18
- package/src/be/seed-skills/index.ts +107 -3
- package/src/be/sql-connections.ts +118 -0
- package/src/be/swarm-config-guard.ts +53 -0
- package/src/cli.tsx +0 -16
- package/src/commands/onboard/non-interactive.ts +4 -2
- package/src/commands/profile-sync.ts +5 -3
- package/src/commands/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +196 -56
- package/src/e2b/env.ts +5 -0
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +45 -0
- package/src/extensions/dispatcher.ts +7 -0
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/all-routes.ts +0 -1
- package/src/http/config.ts +36 -17
- package/src/http/core.ts +4 -0
- package/src/http/index.ts +14 -2
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp-oauth.ts +6 -13
- package/src/http/mcp.ts +15 -5
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +6 -5
- package/src/http/pages.ts +5 -14
- package/src/http/poll.ts +28 -68
- package/src/http/requested-by.ts +54 -0
- package/src/http/route-def.ts +7 -6
- package/src/http/script-connection-proxy.ts +51 -4
- package/src/http/script-connections.ts +5 -2
- package/src/http/scripts.ts +1 -0
- package/src/http/session-cost-recompute.ts +12 -2
- package/src/http/session-data.ts +4 -0
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +61 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +183 -2
- package/src/http/x.ts +1 -0
- package/src/integrations/chat-sdk/adapters.ts +129 -0
- package/src/integrations/chat-sdk/attachments.ts +232 -0
- package/src/integrations/chat-sdk/background.ts +36 -0
- package/src/integrations/chat-sdk/commands.ts +194 -0
- package/src/integrations/chat-sdk/config.ts +198 -0
- package/src/integrations/chat-sdk/discord-api.ts +63 -0
- package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
- package/src/integrations/chat-sdk/handlers.ts +28 -0
- package/src/integrations/chat-sdk/inbound.ts +426 -0
- package/src/integrations/chat-sdk/limits.ts +48 -0
- package/src/integrations/chat-sdk/logger.ts +81 -0
- package/src/integrations/chat-sdk/outbound.ts +123 -0
- package/src/integrations/chat-sdk/relay.ts +172 -0
- package/src/integrations/chat-sdk/router.ts +169 -0
- package/src/integrations/chat-sdk/runtime.ts +351 -0
- package/src/integrations/chat-sdk/schema.ts +245 -0
- package/src/integrations/chat-sdk/state.ts +243 -0
- package/src/integrations/chat-sdk/status.ts +244 -0
- package/src/integrations/chat-sdk/steering.ts +58 -0
- package/src/integrations/chat-sdk/teams-origin.ts +77 -0
- package/src/integrations/chat-sdk/telegram-api.ts +56 -0
- package/src/integrations/chat-sdk/templates.ts +16 -0
- package/src/integrations/chat-sdk/test-hooks.ts +37 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
- package/src/integrations/chat-sdk/typing.ts +65 -0
- package/src/jira/adf.ts +3 -1
- package/src/kv-reserved-namespaces.ts +2 -0
- package/src/oauth/mcp-wrapper.ts +10 -6
- package/src/otel-impl.ts +2 -1
- package/src/pages/version.ts +4 -5
- package/src/prompts/base-prompt.ts +111 -45
- package/src/providers/acp-target-catalog.ts +6 -0
- package/src/providers/acp-targets.ts +56 -3
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +27 -2
- package/src/providers/claude-flag-settings.ts +133 -0
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-sdk-session.ts +7 -0
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +268 -37
- package/src/providers/opencode-billing.ts +86 -0
- package/src/providers/opencode-swarm-plugin.ts +51 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pricing-sources.md +37 -3
- package/src/providers/reasoning-effort.ts +27 -0
- package/src/providers/types.ts +11 -2
- package/src/rbac/legacy-policy.ts +8 -2
- package/src/rbac/permissions.ts +21 -0
- package/src/scheduler/scheduler.ts +4 -2
- package/src/scripts-runtime/api-client.ts +15 -1
- package/src/scripts-runtime/api-types.ts +9 -1
- package/src/scripts-runtime/ctx.ts +1 -1
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/mcp-client.ts +30 -19
- package/src/scripts-runtime/sdk-allowlist.ts +8 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +27 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +63 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -15
- package/src/server.ts +52 -18
- package/src/slack/actions.ts +29 -1
- package/src/slack/app.ts +14 -2
- package/src/slack/assistant.ts +36 -2
- package/src/slack/channel-join.ts +3 -16
- package/src/slack/commands.ts +9 -1
- package/src/slack/event-dedup.ts +1 -1
- package/src/slack/external-channel-egress.ts +113 -0
- package/src/slack/external-channel.ts +309 -0
- package/src/slack/handlers.ts +61 -0
- package/src/slack/render-v2.ts +40 -47
- package/src/slack/work-objects.ts +5 -0
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +94 -2
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +4 -31
- package/src/telemetry.ts +2 -1
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/apps-catalog-feedback.test.ts +310 -0
- package/src/tests/apps-catalog-inputs.test.ts +70 -0
- package/src/tests/apps-catalog-table.test.ts +113 -0
- package/src/tests/azure-devops-boards-sync.test.ts +584 -0
- package/src/tests/azure-devops-html.test.ts +13 -0
- package/src/tests/azure-devops-webhook-malformed.test.ts +4 -0
- package/src/tests/base-prompt.test.ts +58 -54
- package/src/tests/chat-sdk-commands.test.ts +191 -0
- package/src/tests/chat-sdk-config.test.ts +334 -0
- package/src/tests/chat-sdk-discord-api.test.ts +68 -0
- package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
- package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
- package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
- package/src/tests/chat-sdk-harness.ts +146 -0
- package/src/tests/chat-sdk-inbound.test.ts +363 -0
- package/src/tests/chat-sdk-relay.test.ts +470 -0
- package/src/tests/chat-sdk-reload.test.ts +128 -0
- package/src/tests/chat-sdk-shutdown.test.ts +220 -0
- package/src/tests/chat-sdk-slack.test.ts +268 -0
- package/src/tests/chat-sdk-state.test.ts +163 -0
- package/src/tests/chat-sdk-status-route.test.ts +382 -0
- package/src/tests/chat-sdk-teams.test.ts +277 -0
- package/src/tests/chat-sdk-tools.test.ts +520 -0
- package/src/tests/chat-sdk-typing.test.ts +120 -0
- package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
- package/src/tests/claude-adapter-binary.test.ts +144 -0
- package/src/tests/claude-flag-settings.test.ts +114 -0
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +148 -1
- package/src/tests/claude-sdk-process.fixture.ts +7 -0
- package/src/tests/claude-thinking-tokens.test.ts +57 -0
- package/src/tests/claude-worker-parity.test.ts +2 -7
- package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
- package/src/tests/config-refs.test.ts +66 -0
- package/src/tests/context-key.test.ts +51 -0
- package/src/tests/cors-allowlist.test.ts +25 -0
- package/src/tests/create-page-tool.test.ts +18 -0
- package/src/tests/credential-check.test.ts +139 -0
- package/src/tests/credentials.test.ts +21 -0
- package/src/tests/db-runtime.test.ts +61 -0
- package/src/tests/db-task-read-contract.test.ts +20 -0
- package/src/tests/db-task-write-contract.test.ts +10 -0
- package/src/tests/deferred-task-wake.test.ts +52 -4
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/enabled-capabilities.test.ts +20 -0
- package/src/tests/entrypoint-api-readiness.test.ts +14 -8
- package/src/tests/entrypoint-config-env-export.test.ts +5 -2
- package/src/tests/entrypoint-export-to-env.test.ts +78 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-post-bridge.test.ts +51 -0
- package/src/tests/fetch-resolved-env.test.ts +128 -0
- package/src/tests/fixtures/azure-boards/workitem.commented.json +89 -0
- package/src/tests/fixtures/azure-boards/workitem.created.json +81 -0
- package/src/tests/fixtures/azure-boards/workitem.deleted.json +70 -0
- package/src/tests/fixtures/azure-boards/workitem.restored.json +82 -0
- package/src/tests/fixtures/azure-boards/workitem.updated.json +130 -0
- package/src/tests/fixtures/catalog-feedback-definition.json.txt +860 -0
- package/src/tests/fixtures/catalog-inputs-definition.json.txt +910 -0
- package/src/tests/fixtures/catalog-table-definition.json.txt +468 -0
- package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
- package/src/tests/fixtures/runner-identity-refresh.ts +3 -0
- package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
- package/src/tests/github-handlers.test.ts +35 -0
- package/src/tests/harness-provider-resolution.test.ts +12 -0
- package/src/tests/heartbeat-checklist.test.ts +3 -2
- package/src/tests/hook-runtime-close.test.ts +0 -2
- package/src/tests/http-api-integration.test.ts +0 -25
- package/src/tests/migration-046-budgets.test.ts +17 -16
- package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
- package/src/tests/model-tier-resolution.test.ts +93 -0
- package/src/tests/models-catalog.test.ts +42 -1
- package/src/tests/node-env-runtime.test.ts +98 -0
- package/src/tests/openai-compatible-providers.test.ts +134 -0
- package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
- package/src/tests/opencode-adapter.test.ts +348 -3
- package/src/tests/opencode-billing.test.ts +28 -0
- package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
- package/src/tests/opencode-shell-env.test.ts +145 -0
- package/src/tests/openrouter-base-url.test.ts +101 -151
- package/src/tests/page-proxy.test.ts +1 -1
- package/src/tests/pages-browser-sdk.test.ts +76 -0
- package/src/tests/pages-feedback.test.ts +1 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
- package/src/tests/pi-mono-adapter.test.ts +385 -5
- package/src/tests/pi-shell-env.test.ts +170 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/rbac-engine.test.ts +11 -3
- package/src/tests/runner-exit-after-tasks.test.ts +0 -4
- package/src/tests/runner-identity-refresh.test.ts +3 -0
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections-sql.test.ts +675 -0
- package/src/tests/script-connections.test.ts +7 -1
- package/src/tests/scripts-http.test.ts +201 -1
- package/src/tests/scripts-only-gating.test.ts +2 -3
- package/src/tests/scripts-runtime.test.ts +58 -40
- package/src/tests/secret-scrubber.test.ts +86 -0
- package/src/tests/seed-skills-bundled-files.test.ts +45 -53
- package/src/tests/seed-skills-retire.test.ts +182 -0
- package/src/tests/send-task-requester-gate.test.ts +58 -0
- package/src/tests/session-cost-recompute-unit.test.ts +94 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/slack-channel-join.test.ts +4 -1
- package/src/tests/slack-external-channel-config.test.ts +65 -0
- package/src/tests/slack-external-channel-egress.test.ts +237 -0
- package/src/tests/slack-external-channel-guard.test.ts +280 -0
- package/src/tests/slack-external-channel-tools.test.ts +173 -0
- package/src/tests/slack-external-channel.test.ts +370 -0
- package/src/tests/slack-render-v2.test.ts +86 -10
- package/src/tests/sonnet-5-5-registry.test.ts +9 -1
- package/src/tests/spec-base-url.test.ts +16 -1
- package/src/tests/swarm-config-export-to-env.test.ts +267 -0
- package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
- package/src/tests/swarm-diff.test.ts +1 -1
- package/src/tests/task-model-effort-rerun.test.ts +164 -0
- package/src/tests/task-session-prompts.test.ts +132 -0
- package/src/tests/task-tool-manifest.test.ts +14 -0
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tool-annotations.test.ts +6 -6
- package/src/tests/ui-logs-parser.test.ts +43 -0
- package/src/tests/used-by-route.test.ts +6 -0
- package/src/tests/vendored-openapi.test.ts +16 -1
- package/src/tests/vercel-ai-gateway.test.ts +149 -0
- package/src/tests/workflow-swarm-script.test.ts +38 -0
- package/src/tests/workflow-wait-filter.test.ts +5 -3
- package/src/tools/chat-access.ts +41 -0
- package/src/tools/chat-open-dm.ts +59 -0
- package/src/tools/chat-post.ts +74 -0
- package/src/tools/chat-read-thread.ts +100 -0
- package/src/tools/chat-reply.ts +75 -0
- package/src/tools/create-page.ts +3 -13
- package/src/tools/defer-task.ts +17 -0
- package/src/tools/model-catalog/index.ts +2 -1
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/send-task.ts +24 -0
- package/src/tools/skills/skill-get.ts +17 -9
- package/src/tools/slack-post.ts +6 -0
- package/src/tools/slack-read.ts +8 -0
- package/src/tools/slack-reply.ts +6 -0
- package/src/tools/slack-start-thread.ts +6 -0
- package/src/tools/slack-update.ts +6 -0
- package/src/tools/slack-upload-file.ts +6 -0
- package/src/tools/swarm-config/get-config.ts +2 -1
- package/src/tools/swarm-config/list-config.ts +2 -1
- package/src/tools/swarm-config/set-config.ts +16 -3
- package/src/tools/tool-config.ts +8 -6
- package/src/types.ts +12 -2
- package/src/utils/config-env-export.ts +74 -0
- package/src/utils/credentials.test.ts +92 -0
- package/src/utils/credentials.ts +52 -4
- package/src/utils/harness-provider.ts +15 -6
- package/src/utils/node-env.ts +24 -0
- package/src/utils/runtime-model-catalog.ts +11 -1
- package/src/utils/secret-scrubber.ts +71 -2
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/templates/skills/agent-browser/SKILL.md +1 -1
- package/templates/skills/agent-browser/content.md +1 -1
- package/templates/skills/apps/SKILL.md +749 -0
- package/templates/skills/apps/content.md +60 -22
- package/templates/skills/chat-sdk/config.json +14 -0
- package/templates/skills/chat-sdk/content.md +84 -0
- package/templates/skills/composio-gmail/content.md +7 -0
- package/templates/skills/composio-google-docs/content.md +1 -1
- package/templates/skills/email-domain-health/config.json +14 -0
- package/templates/skills/email-domain-health/content.md +131 -0
- package/templates/skills/kv-storage/content.md +2 -2
- package/templates/skills/pages/content.md +8 -10
- package/templates/skills/qa-loom/config.json +14 -0
- package/templates/skills/qa-loom/content.md +187 -0
- package/templates/skills/qa-loom/files/build-loom.mjs +221 -0
- package/templates/skills/qa-loom/files/run-qa.sh +57 -0
- package/templates/skills/slack-interaction/content.md +4 -0
- package/templates/skills/swarm-extensions/content.md +2 -0
- package/templates/skills/swarm-scripts/SKILL.md +4 -2
- package/templates/skills/swarm-scripts/config.json +1 -1
- package/templates/skills/swarm-scripts/content.md +4 -2
- package/templates/skills/workflow-iterate/content.md +38 -0
- package/dist/artifact-eczsknc3.js +0 -3843
- package/dist/cli-9xsmdpdt.js +0 -56377
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- package/dist/index-9ch1n761.js +0 -1102
- package/src/artifact-sdk/index.ts +0 -2
- package/src/artifact-sdk/localtunnel.d.ts +0 -20
- package/src/artifact-sdk/port.ts +0 -12
- package/src/artifact-sdk/server.ts +0 -183
- package/src/artifact-sdk/tunnel.ts +0 -19
- package/src/commands/artifact.ts +0 -249
- package/src/http/ecosystem.ts +0 -77
- package/src/tests/artifact-commands.test.ts +0 -92
- package/src/tests/artifact-sdk.test.ts +0 -793
- package/src/tests/register-service-security.test.ts +0 -194
- package/src/tools/list-services.ts +0 -107
- package/src/tools/register-service.ts +0 -177
- package/src/tools/unregister-service.ts +0 -73
- package/src/tools/update-service-status.ts +0 -96
- package/templates/skills/artifacts/config.json +0 -14
- package/templates/skills/artifacts/content.md +0 -344
- package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
- package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
- package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
- package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
- package/dist/{azure-openai-responses-ap1gwxgr.js → azure-openai-responses-ygfreq4t.js} +5 -5
- package/dist/{cli-5rqrj7q0.js → cli-pw7ebjdt.js} +0 -0
- package/dist/{openai-codex-responses-33qhkkdy.js → openai-codex-responses-3bk0grnr.js} +4 -4
- package/dist/{openai-completions-s88xm3ns.js → openai-completions-5d4jpakc.js} +9 -9
- package/dist/{openai-responses-7xd2f2e2.js → openai-responses-krb51f59.js} +5 -5
- package/dist/{pi-messages-xszk613n.js → pi-messages-x9gzynm1.js} +3 -3
- /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
- /package/src/{artifact-sdk → pages}/feedback-overlay.ts +0 -0
|
@@ -10,7 +10,12 @@
|
|
|
10
10
|
|
|
11
11
|
import { findTaskByVcs, getAllAgents, incrKv, upsertKv } from "../be/db";
|
|
12
12
|
import { renderIdentity, resolveIdentity } from "../be/identity";
|
|
13
|
-
import {
|
|
13
|
+
import {
|
|
14
|
+
findOrCreateUserByEmail,
|
|
15
|
+
findUserByEmail,
|
|
16
|
+
findUserByExternalId,
|
|
17
|
+
linkIdentity,
|
|
18
|
+
} from "../be/users";
|
|
14
19
|
import { resolveTemplate } from "../prompts/resolver";
|
|
15
20
|
import { azureDevOpsContextKey } from "../tasks/context-key";
|
|
16
21
|
import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
|
|
@@ -36,7 +41,7 @@ type HandlerResult = { created: boolean; taskId?: string };
|
|
|
36
41
|
const processedEvents = new Map<string, number>();
|
|
37
42
|
const DEDUP_TTL_MS = 60_000;
|
|
38
43
|
|
|
39
|
-
function isDuplicate(key: string): boolean {
|
|
44
|
+
export function isDuplicate(key: string): boolean {
|
|
40
45
|
const now = Date.now();
|
|
41
46
|
// Cleanup expired
|
|
42
47
|
for (const [k, ts] of processedEvents) {
|
|
@@ -49,7 +54,7 @@ function isDuplicate(key: string): boolean {
|
|
|
49
54
|
|
|
50
55
|
// ── Helpers ──
|
|
51
56
|
|
|
52
|
-
function escapeRegExp(value: string): string {
|
|
57
|
+
export function escapeRegExp(value: string): string {
|
|
53
58
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
54
59
|
}
|
|
55
60
|
|
|
@@ -143,13 +148,15 @@ export function commentedPayloadOf(
|
|
|
143
148
|
return { comment, pullRequest };
|
|
144
149
|
}
|
|
145
150
|
|
|
146
|
-
function warnMalformed(
|
|
151
|
+
export function warnMalformed(
|
|
152
|
+
event: { eventType?: string; resourceVersion?: string } | null | undefined,
|
|
153
|
+
) {
|
|
147
154
|
console.warn(
|
|
148
155
|
`[AzureDevOps] Ignoring ${event?.eventType} event with resourceVersion ${event?.resourceVersion ?? "unknown"}: required resource fields are missing`,
|
|
149
156
|
);
|
|
150
157
|
}
|
|
151
158
|
|
|
152
|
-
async function findLeadAgent() {
|
|
159
|
+
export async function findLeadAgent() {
|
|
153
160
|
const agents = await getAllAgents();
|
|
154
161
|
return (
|
|
155
162
|
agents.find((a) => a.role === "lead" && a.status === "idle") ??
|
|
@@ -173,7 +180,7 @@ function externalIdOf(identity: AzureDevOpsIdentityRef): string {
|
|
|
173
180
|
* linked identity (`uniqueName`) → email when `uniqueName` is one → unmapped
|
|
174
181
|
* tracker entry for operator triage.
|
|
175
182
|
*/
|
|
176
|
-
async function resolveAzureDevOpsSender(
|
|
183
|
+
export async function resolveAzureDevOpsSender(
|
|
177
184
|
identity: AzureDevOpsIdentityRef,
|
|
178
185
|
sampleEventType: string,
|
|
179
186
|
sampleContext: string,
|
|
@@ -192,6 +199,15 @@ async function resolveAzureDevOpsSender(
|
|
|
192
199
|
return linked.id;
|
|
193
200
|
}
|
|
194
201
|
|
|
202
|
+
await recordUnmappedIdentity(externalId, sampleEventType, sampleContext);
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function recordUnmappedIdentity(
|
|
207
|
+
externalId: string,
|
|
208
|
+
sampleEventType: string,
|
|
209
|
+
sampleContext: string,
|
|
210
|
+
): Promise<void> {
|
|
195
211
|
await upsertKv({
|
|
196
212
|
namespace: UNMAPPED_NAMESPACE,
|
|
197
213
|
key: `${externalId}:meta`,
|
|
@@ -204,14 +220,42 @@ async function resolveAzureDevOpsSender(
|
|
|
204
220
|
expiresAt: Date.now() + UNMAPPED_TTL_MS,
|
|
205
221
|
});
|
|
206
222
|
await incrKv(UNMAPPED_NAMESPACE, `${externalId}:count`, 1);
|
|
207
|
-
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Authorize an actor to trigger a task: a swarm user already linked to the
|
|
227
|
+
* identity (or owning its sign-in email), or a sign-in name listed in
|
|
228
|
+
* AZURE_DEVOPS_ALLOWED_ACTORS (comma-separated). Unlike
|
|
229
|
+
* `resolveAzureDevOpsSender` this never creates users for strangers. Returns
|
|
230
|
+
* the `users.id`, or null after recording the actor for operator triage.
|
|
231
|
+
*/
|
|
232
|
+
export async function authorizeAzureDevOpsActor(
|
|
233
|
+
identity: AzureDevOpsIdentityRef,
|
|
234
|
+
sampleEventType: string,
|
|
235
|
+
sampleContext: string,
|
|
236
|
+
): Promise<string | null> {
|
|
237
|
+
const externalId = externalIdOf(identity);
|
|
238
|
+
const known =
|
|
239
|
+
(await findUserByExternalId("azure-devops", externalId)) ??
|
|
240
|
+
(externalId.includes("@") ? await findUserByEmail(externalId) : null);
|
|
241
|
+
if (known) return known.id;
|
|
242
|
+
|
|
243
|
+
const allowed = (process.env.AZURE_DEVOPS_ALLOWED_ACTORS ?? "")
|
|
244
|
+
.split(",")
|
|
245
|
+
.map((name) => name.trim().toLowerCase())
|
|
246
|
+
.filter(Boolean);
|
|
247
|
+
if (allowed.includes(externalId.toLowerCase())) {
|
|
248
|
+
return (await resolveAzureDevOpsSender(identity, sampleEventType, sampleContext)) ?? null;
|
|
249
|
+
}
|
|
250
|
+
await recordUnmappedIdentity(externalId, sampleEventType, sampleContext);
|
|
251
|
+
return null;
|
|
208
252
|
}
|
|
209
253
|
|
|
210
254
|
/**
|
|
211
255
|
* Render an Azure DevOps identity for agent-visible text: the resolved
|
|
212
256
|
* canonical name or the explicit UNKNOWN sentinel.
|
|
213
257
|
*/
|
|
214
|
-
async function renderAzureDevOpsIdentity(identity: AzureDevOpsIdentityRef): Promise<string> {
|
|
258
|
+
export async function renderAzureDevOpsIdentity(identity: AzureDevOpsIdentityRef): Promise<string> {
|
|
215
259
|
return renderIdentity(await resolveIdentity("azure-devops", externalIdOf(identity)));
|
|
216
260
|
}
|
|
217
261
|
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal HTML helpers for Azure Boards text. Work-item descriptions and
|
|
3
|
+
* comments are HTML; prompts want plain text.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const ENTITIES: Record<string, string> = {
|
|
7
|
+
"&": "&",
|
|
8
|
+
"<": "<",
|
|
9
|
+
">": ">",
|
|
10
|
+
""": '"',
|
|
11
|
+
"'": "'",
|
|
12
|
+
" ": " ",
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/** Strip tags, decode the common entities, and collapse whitespace. */
|
|
16
|
+
export function htmlToText(html: string | null | undefined): string {
|
|
17
|
+
if (!html) return "";
|
|
18
|
+
return html
|
|
19
|
+
.replace(/<br\s*\/?>|<\/(?:div|p|li|h[1-6])>/gi, "\n")
|
|
20
|
+
.replace(/<[^>]*>/g, "")
|
|
21
|
+
.replace(/&(?:amp|lt|gt|quot|#39|nbsp);/g, (entity) => ENTITIES[entity] ?? entity)
|
|
22
|
+
.replace(/[ \t]+/g, " ")
|
|
23
|
+
.replace(/ ?\n ?/g, "\n")
|
|
24
|
+
.replace(/\n{3,}/g, "\n\n")
|
|
25
|
+
.trim();
|
|
26
|
+
}
|
|
@@ -4,6 +4,7 @@ export {
|
|
|
4
4
|
postAzureDevOpsPullRequestComment,
|
|
5
5
|
resetAzureDevOpsBotIdCache,
|
|
6
6
|
resolveAzureDevOpsBotId,
|
|
7
|
+
resolveAzureDevOpsBotUniqueName,
|
|
7
8
|
} from "./api";
|
|
8
9
|
export {
|
|
9
10
|
AZURE_DEVOPS_BOT_NAME,
|
|
@@ -14,6 +15,15 @@ export {
|
|
|
14
15
|
resetAzureDevOps,
|
|
15
16
|
verifyAzureDevOpsWebhook,
|
|
16
17
|
} from "./auth";
|
|
18
|
+
export {
|
|
19
|
+
handleWorkItemCommented,
|
|
20
|
+
handleWorkItemCreated,
|
|
21
|
+
handleWorkItemDeleted,
|
|
22
|
+
handleWorkItemRestored,
|
|
23
|
+
handleWorkItemUpdated,
|
|
24
|
+
updatedPayloadOf,
|
|
25
|
+
workItemOf,
|
|
26
|
+
} from "./boards-sync";
|
|
17
27
|
export {
|
|
18
28
|
commentedPayloadOf,
|
|
19
29
|
createdPullRequestOf,
|
|
@@ -24,4 +34,9 @@ export type {
|
|
|
24
34
|
AzureDevOpsWebhookEvent,
|
|
25
35
|
PullRequestCommentedEvent,
|
|
26
36
|
PullRequestCreatedEvent,
|
|
37
|
+
WorkItemCommentedEvent,
|
|
38
|
+
WorkItemCreatedEvent,
|
|
39
|
+
WorkItemDeletedEvent,
|
|
40
|
+
WorkItemRestoredEvent,
|
|
41
|
+
WorkItemUpdatedEvent,
|
|
27
42
|
} from "./types";
|
|
@@ -106,3 +106,89 @@ Comment:
|
|
|
106
106
|
],
|
|
107
107
|
category: "event",
|
|
108
108
|
});
|
|
109
|
+
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Azure Boards work-item events
|
|
112
|
+
// ============================================================================
|
|
113
|
+
|
|
114
|
+
registerTemplate({
|
|
115
|
+
eventType: "common.command_suggestions.azure_devops_work_item",
|
|
116
|
+
header: "",
|
|
117
|
+
defaultBody:
|
|
118
|
+
'Workers have the `az` CLI with the azure-devops extension, authenticated with the swarm PAT. Inspect the work item with `az boards work-item show --id {{work_item_id}}`. To reply on it, run `az boards work-item update --id {{work_item_id}} --discussion "<reply>"`.',
|
|
119
|
+
variables: [{ name: "work_item_id", description: "Work item ID" }],
|
|
120
|
+
category: "common",
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
const WORK_ITEM_VARIABLES = [
|
|
124
|
+
{ name: "work_item_id", description: "Work item ID" },
|
|
125
|
+
{ name: "work_item_type", description: "Work item type (Task, Bug, Issue, ...)" },
|
|
126
|
+
{ name: "title", description: "Work item title" },
|
|
127
|
+
{ name: "state", description: "Work item state" },
|
|
128
|
+
{ name: "project", description: "Azure DevOps project name" },
|
|
129
|
+
{ name: "work_item_url", description: "Work item web URL" },
|
|
130
|
+
{
|
|
131
|
+
name: "username",
|
|
132
|
+
description:
|
|
133
|
+
"Actor identity — resolved canonical name (e.g. 'Luis (azure-devops:luis@example.com)') or the UNKNOWN sentinel",
|
|
134
|
+
},
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
registerTemplate({
|
|
138
|
+
eventType: "azure-devops.work_item.assigned",
|
|
139
|
+
header: "[Azure DevOps {{work_item_type}} #{{work_item_id}}] {{title}}",
|
|
140
|
+
defaultBody: `Project: {{project}}
|
|
141
|
+
State: {{state}}
|
|
142
|
+
Triggered by: {{username}} ({{trigger}})
|
|
143
|
+
URL: {{work_item_url}}
|
|
144
|
+
|
|
145
|
+
{{description_section}}{{@template[common.command_suggestions.azure_devops_work_item]}}{{@template[common.delegation_instruction.azure_devops]}}`,
|
|
146
|
+
variables: [
|
|
147
|
+
...WORK_ITEM_VARIABLES,
|
|
148
|
+
{ name: "trigger", description: "Why the task was created (assigned to the bot, mentioned)" },
|
|
149
|
+
{
|
|
150
|
+
name: "description_section",
|
|
151
|
+
description: "Description section (HTML stripped) or empty string",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
category: "event",
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
registerTemplate({
|
|
158
|
+
eventType: "azure-devops.work_item.commented",
|
|
159
|
+
header: "[Azure DevOps {{work_item_type}} #{{work_item_id}}] {{username}} mentioned bot",
|
|
160
|
+
defaultBody: `Project: {{project}}
|
|
161
|
+
Title: {{title}}
|
|
162
|
+
State: {{state}}
|
|
163
|
+
URL: {{work_item_url}}
|
|
164
|
+
|
|
165
|
+
Comment:
|
|
166
|
+
{{context}}{{existing_task_note}}
|
|
167
|
+
|
|
168
|
+
{{@template[common.command_suggestions.azure_devops_work_item]}}{{@template[common.delegation_instruction.azure_devops]}}`,
|
|
169
|
+
variables: [
|
|
170
|
+
...WORK_ITEM_VARIABLES,
|
|
171
|
+
{ name: "context", description: "Comment text with the bot mention removed" },
|
|
172
|
+
{ name: "existing_task_note", description: "Note about an active task, or empty string" },
|
|
173
|
+
],
|
|
174
|
+
category: "event",
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
registerTemplate({
|
|
178
|
+
eventType: "azure-devops.work_item.followup",
|
|
179
|
+
header: "[Azure DevOps {{work_item_type}} #{{work_item_id}}] Follow-up: {{title}}",
|
|
180
|
+
defaultBody: `Project: {{project}}
|
|
181
|
+
State: {{state}}
|
|
182
|
+
Trigger: {{trigger}} by {{username}}
|
|
183
|
+
URL: {{work_item_url}}
|
|
184
|
+
|
|
185
|
+
{{user_message}}
|
|
186
|
+
|
|
187
|
+
{{@template[common.command_suggestions.azure_devops_work_item]}}{{@template[common.delegation_instruction.azure_devops]}}`,
|
|
188
|
+
variables: [
|
|
189
|
+
...WORK_ITEM_VARIABLES,
|
|
190
|
+
{ name: "trigger", description: "What re-engaged the swarm" },
|
|
191
|
+
{ name: "user_message", description: "Comment text, or empty string" },
|
|
192
|
+
],
|
|
193
|
+
category: "event",
|
|
194
|
+
});
|
|
@@ -87,4 +87,68 @@ export type PullRequestCommentedEvent = ServiceHookEvent<
|
|
|
87
87
|
{ comment: AzureDevOpsComment; pullRequest: AzureDevOpsPullRequest }
|
|
88
88
|
>;
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
/**
|
|
91
|
+
* Azure Boards work-item fields (`resource.fields` on created / commented /
|
|
92
|
+
* deleted / restored, `resource.revision.fields` on updated). Identities are
|
|
93
|
+
* strings of the form `"Display Name <unique@name>"`, not identity objects.
|
|
94
|
+
*/
|
|
95
|
+
export interface AzureDevOpsWorkItemFields {
|
|
96
|
+
"System.TeamProject"?: string;
|
|
97
|
+
"System.WorkItemType"?: string;
|
|
98
|
+
"System.State"?: string;
|
|
99
|
+
"System.Title"?: string;
|
|
100
|
+
"System.Description"?: string; // HTML
|
|
101
|
+
"System.AssignedTo"?: string;
|
|
102
|
+
"System.ChangedBy"?: string;
|
|
103
|
+
"System.History"?: string; // HTML of the latest comment (commented events only)
|
|
104
|
+
[field: string]: unknown;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** `resource` of created / commented / deleted / restored events. */
|
|
108
|
+
export interface AzureDevOpsWorkItem {
|
|
109
|
+
id: number;
|
|
110
|
+
rev: number;
|
|
111
|
+
fields: AzureDevOpsWorkItemFields;
|
|
112
|
+
url?: string;
|
|
113
|
+
/** Present on `workitem.commented`: identifies the comment and its edit version. */
|
|
114
|
+
commentVersionRef?: { commentId: number; version: number };
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* `resource` of `workitem.updated`. `id` is the update id; the work item is
|
|
119
|
+
* `workItemId`. `fields` holds only the changed fields; the full state is in
|
|
120
|
+
* `revision.fields`.
|
|
121
|
+
*/
|
|
122
|
+
export interface AzureDevOpsWorkItemUpdate {
|
|
123
|
+
id: number;
|
|
124
|
+
workItemId: number;
|
|
125
|
+
rev: number;
|
|
126
|
+
url?: string;
|
|
127
|
+
revisedBy: AzureDevOpsIdentityRef;
|
|
128
|
+
fields?: Record<string, { oldValue?: unknown; newValue?: unknown }>;
|
|
129
|
+
revision: { id: number; rev: number; fields: AzureDevOpsWorkItemFields };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** `workitem.created` */
|
|
133
|
+
export type WorkItemCreatedEvent = ServiceHookEvent<"workitem.created", AzureDevOpsWorkItem>;
|
|
134
|
+
|
|
135
|
+
/** `workitem.updated` */
|
|
136
|
+
export type WorkItemUpdatedEvent = ServiceHookEvent<"workitem.updated", AzureDevOpsWorkItemUpdate>;
|
|
137
|
+
|
|
138
|
+
/** `workitem.commented`: `commentVersionRef.commentId` identifies the comment. */
|
|
139
|
+
export type WorkItemCommentedEvent = ServiceHookEvent<"workitem.commented", AzureDevOpsWorkItem>;
|
|
140
|
+
|
|
141
|
+
/** `workitem.deleted`: `resource.url` points at the recycle bin. */
|
|
142
|
+
export type WorkItemDeletedEvent = ServiceHookEvent<"workitem.deleted", AzureDevOpsWorkItem>;
|
|
143
|
+
|
|
144
|
+
/** `workitem.restored` */
|
|
145
|
+
export type WorkItemRestoredEvent = ServiceHookEvent<"workitem.restored", AzureDevOpsWorkItem>;
|
|
146
|
+
|
|
147
|
+
export type AzureDevOpsWebhookEvent =
|
|
148
|
+
| PullRequestCreatedEvent
|
|
149
|
+
| PullRequestCommentedEvent
|
|
150
|
+
| WorkItemCreatedEvent
|
|
151
|
+
| WorkItemUpdatedEvent
|
|
152
|
+
| WorkItemCommentedEvent
|
|
153
|
+
| WorkItemDeletedEvent
|
|
154
|
+
| WorkItemRestoredEvent;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config references: `{ "$config": "KEY" }` leaves inside a JSON config value
|
|
3
|
+
* that point at another config key (usually a secret). Pure, no DB access: the
|
|
4
|
+
* caller supplies the lookup and decides which keys are allowed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export interface ConfigRef {
|
|
8
|
+
$config: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** True when `value` is exactly `{ "$config": "<non-empty string>" }`. */
|
|
12
|
+
export function isConfigRef(value: unknown): value is ConfigRef {
|
|
13
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) return false;
|
|
14
|
+
const keys = Object.keys(value);
|
|
15
|
+
const ref = (value as { $config?: unknown }).$config;
|
|
16
|
+
return keys.length === 1 && keys[0] === "$config" && typeof ref === "string" && ref.length > 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class ConfigRefError extends Error {
|
|
20
|
+
constructor(
|
|
21
|
+
message: string,
|
|
22
|
+
readonly missingKeys: string[],
|
|
23
|
+
) {
|
|
24
|
+
super(message);
|
|
25
|
+
this.name = "ConfigRefError";
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Replace every `{ "$config": "KEY" }` leaf in `value` with `lookup(KEY)`.
|
|
31
|
+
* Walks arrays and plain objects. Missing keys (lookup returns undefined) are
|
|
32
|
+
* collected and reported in one error. A lookup that throws (for example on a
|
|
33
|
+
* forbidden key) propagates as-is.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveConfigRefs<T>(
|
|
36
|
+
value: unknown,
|
|
37
|
+
lookup: (key: string) => string | undefined,
|
|
38
|
+
): T {
|
|
39
|
+
const missing = new Set<string>();
|
|
40
|
+
|
|
41
|
+
const walk = (node: unknown): unknown => {
|
|
42
|
+
if (isConfigRef(node)) {
|
|
43
|
+
const resolved = lookup(node.$config);
|
|
44
|
+
if (resolved === undefined) missing.add(node.$config);
|
|
45
|
+
return resolved;
|
|
46
|
+
}
|
|
47
|
+
if (Array.isArray(node)) return node.map(walk);
|
|
48
|
+
if (node !== null && typeof node === "object") {
|
|
49
|
+
return Object.fromEntries(Object.entries(node).map(([k, v]) => [k, walk(v)]));
|
|
50
|
+
}
|
|
51
|
+
return node;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const result = walk(value);
|
|
55
|
+
if (missing.size > 0) {
|
|
56
|
+
const keys = [...missing].sort();
|
|
57
|
+
throw new ConfigRefError(`Unresolved config reference(s): ${keys.join(", ")}`, keys);
|
|
58
|
+
}
|
|
59
|
+
return result as T;
|
|
60
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getDbClient } from "./runtime";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The page's edit counter, `MAX(page_versions.version) + 1`, or 1 before the
|
|
5
|
+
* first snapshot. Reads one indexed aggregate instead of every snapshot body:
|
|
6
|
+
* loading all versions of a large, often-edited page blocked the event loop
|
|
7
|
+
* for seconds per call.
|
|
8
|
+
*/
|
|
9
|
+
export async function getPageEditCounter(pageId: string): Promise<number> {
|
|
10
|
+
const row = await getDbClient().get<{ latest: number | null }>(
|
|
11
|
+
"SELECT MAX(version) AS latest FROM page_versions WHERE pageId = ?",
|
|
12
|
+
[pageId],
|
|
13
|
+
);
|
|
14
|
+
return (row?.latest ?? 0) + 1;
|
|
15
|
+
}
|
package/src/be/db/runtime.ts
CHANGED
|
@@ -104,7 +104,34 @@ export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
|
104
104
|
db = new Database(dbPath, { create: true });
|
|
105
105
|
console.log(`Database initialized at ${dbPath}`);
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
// Boot must finish before getDb() hands this handle out. A step below can
|
|
108
|
+
// throw SQLITE_BUSY while another connection holds the file, and the
|
|
109
|
+
// db-client retries BUSY by calling getDb() again. With `db` still assigned,
|
|
110
|
+
// that retry got a connection whose encryption key was never resolved, and
|
|
111
|
+
// the server died on "Encryption key not resolved yet". Drop the handle so
|
|
112
|
+
// the retry runs boot again.
|
|
113
|
+
const opened = db;
|
|
114
|
+
try {
|
|
115
|
+
return bootOpenedDb(opened, dbPath, resolvePromptTemplate, autoEncryptLegacyPlaintextSecrets);
|
|
116
|
+
} catch (error) {
|
|
117
|
+
if (db === opened) {
|
|
118
|
+
db = null;
|
|
119
|
+
try {
|
|
120
|
+
opened.close();
|
|
121
|
+
} catch {
|
|
122
|
+
// Already closed by the step that failed.
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function bootOpenedDb(
|
|
130
|
+
database: Database,
|
|
131
|
+
dbPath: string,
|
|
132
|
+
resolvePromptTemplate: typeof import("../db").resolvePromptTemplate,
|
|
133
|
+
autoEncryptLegacyPlaintextSecrets: typeof import("../db").autoEncryptLegacyPlaintextSecrets,
|
|
134
|
+
): Database {
|
|
108
135
|
database.run("PRAGMA journal_mode = WAL;");
|
|
109
136
|
database.run("PRAGMA busy_timeout = 5000;");
|
|
110
137
|
database.run("PRAGMA foreign_keys = ON;");
|
|
@@ -140,7 +167,7 @@ export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
|
140
167
|
// Old databases have CHECK(status IN ('pending','in_progress','completed','failed'))
|
|
141
168
|
// which blocks 'cancelled', 'paused', 'offered', 'unassigned' statuses
|
|
142
169
|
try {
|
|
143
|
-
const taskSchemaInfo =
|
|
170
|
+
const taskSchemaInfo = database
|
|
144
171
|
.prepare<{ sql: string | null }, []>(
|
|
145
172
|
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'agent_tasks'",
|
|
146
173
|
)
|
|
@@ -153,7 +180,7 @@ export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
|
153
180
|
|
|
154
181
|
if (needsStatusMigration) {
|
|
155
182
|
console.log("[Migration] Removing restrictive CHECK constraint on agent_tasks.status");
|
|
156
|
-
|
|
183
|
+
database.run("PRAGMA foreign_keys=off");
|
|
157
184
|
|
|
158
185
|
// Migrations run before this compatibility guard, so a legacy table now
|
|
159
186
|
// carries every current column. Rebuilding from an old hard-coded column
|
|
@@ -169,12 +196,12 @@ export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
|
169
196
|
if (rebuiltSchemaSql === schemaSql || !/agent_tasks_new/i.test(rebuiltSchemaSql)) {
|
|
170
197
|
throw new Error("Could not derive agent_tasks schema without legacy status CHECK");
|
|
171
198
|
}
|
|
172
|
-
const columns =
|
|
199
|
+
const columns = database
|
|
173
200
|
.prepare<{ name: string }, []>('PRAGMA table_info("agent_tasks")')
|
|
174
201
|
.all()
|
|
175
202
|
.map((column) => `"${column.name.replaceAll('"', '""')}"`)
|
|
176
203
|
.join(", ");
|
|
177
|
-
const schemaObjects =
|
|
204
|
+
const schemaObjects = database
|
|
178
205
|
.prepare<{ sql: string }, []>(
|
|
179
206
|
`SELECT sql FROM sqlite_master
|
|
180
207
|
WHERE tbl_name = 'agent_tasks'
|
|
@@ -194,13 +221,13 @@ export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
|
194
221
|
for (const sql of schemaObjects) database.run(sql);
|
|
195
222
|
})();
|
|
196
223
|
|
|
197
|
-
|
|
224
|
+
database.run("PRAGMA foreign_keys=on");
|
|
198
225
|
console.log("[Migration] Successfully removed CHECK constraint on agent_tasks.status");
|
|
199
226
|
}
|
|
200
227
|
} catch (e) {
|
|
201
228
|
console.error("[Migration] Failed to update agent_tasks CHECK constraint:", e);
|
|
202
229
|
try {
|
|
203
|
-
|
|
230
|
+
database.run("PRAGMA foreign_keys=on");
|
|
204
231
|
} catch (cleanupError) {
|
|
205
232
|
console.error("[Migration] Failed to re-enable SQLite foreign_keys pragma:", cleanupError);
|
|
206
233
|
}
|
|
@@ -291,7 +318,7 @@ export function initDb(dbPath = "./agent-swarm-db.sqlite"): Database {
|
|
|
291
318
|
throw err;
|
|
292
319
|
}
|
|
293
320
|
|
|
294
|
-
return
|
|
321
|
+
return database;
|
|
295
322
|
}
|
|
296
323
|
|
|
297
324
|
export function getDb(path?: string): Database {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getDbClient } from "./runtime";
|
|
2
|
+
|
|
3
|
+
export type SwarmSkillNameResolution =
|
|
4
|
+
| { kind: "found"; skillId: string }
|
|
5
|
+
| { kind: "ambiguous"; skillIds: string[] }
|
|
6
|
+
| { kind: "none" };
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a swarm-scope skill name for `skill-get`.
|
|
10
|
+
*
|
|
11
|
+
* Migration 019 makes a name unique only per scope + owner, so a swarm name can
|
|
12
|
+
* match one ownerless row plus any number of agent-owned rows. Precedence:
|
|
13
|
+
* the ownerless row, then the caller's own row, then a single owned row.
|
|
14
|
+
* Several foreign-owned rows are ambiguous; the caller must pass a skillId.
|
|
15
|
+
*
|
|
16
|
+
* `getSkillByName(name, "swarm")` stays ownerless-only: the seeder relies on it.
|
|
17
|
+
*/
|
|
18
|
+
export async function resolveSwarmSkillByName(
|
|
19
|
+
name: string,
|
|
20
|
+
callerAgentId?: string,
|
|
21
|
+
): Promise<SwarmSkillNameResolution> {
|
|
22
|
+
const rows = await getDbClient().query<{ id: string; ownerAgentId: string | null }>(
|
|
23
|
+
"SELECT id, ownerAgentId FROM skills WHERE name = ? AND scope = 'swarm' ORDER BY createdAt, id",
|
|
24
|
+
[name],
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const ownerless = rows.find((row) => !row.ownerAgentId);
|
|
28
|
+
if (ownerless) return { kind: "found", skillId: ownerless.id };
|
|
29
|
+
|
|
30
|
+
const own = callerAgentId ? rows.find((row) => row.ownerAgentId === callerAgentId) : undefined;
|
|
31
|
+
if (own) return { kind: "found", skillId: own.id };
|
|
32
|
+
|
|
33
|
+
if (rows.length === 1) return { kind: "found", skillId: rows[0]!.id };
|
|
34
|
+
if (rows.length > 1) return { kind: "ambiguous", skillIds: rows.map((row) => row.id) };
|
|
35
|
+
return { kind: "none" };
|
|
36
|
+
}
|