@desplega.ai/agent-swarm 1.173.0 → 2.1.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-ccm9xrep.js → acp-adapter-kr4abrsk.js} +17 -16
- package/dist/{actions-sgeyv08k.js → actions-eh4g6w2r.js} +39 -34
- package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-7h7wdt8q.js} +8 -7
- package/dist/{app-km9qnv2f.js → app-7k8s9w5p.js} +18 -14
- package/dist/{assistant-5r8tcvvd.js → assistant-wswt2y7p.js} +40 -35
- package/dist/{boot-reembed-16rv9843.js → boot-reembed-9apm9qw6.js} +10 -9
- package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-whzbdthj.js} +10 -9
- package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-ndzmvmgt.js} +11 -10
- package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-e9sta0yt.js} +16 -13
- package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-4mqd3r6r.js} +19 -18
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-9wswb52m.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-tpe1effx.js} +6 -4
- package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-q49ghmh9.js} +12402 -11850
- package/dist/{cli-ne7smj1b.js → cli-01xvj1rq.js} +10 -10
- package/dist/{cli-nwrdx840.js → cli-035vekcw.js} +3 -3
- package/dist/{cli-9xf7fdtp.js → cli-0pd8hzhc.js} +29 -6
- package/dist/{cli-tmhsxhb8.js → cli-0veb92a3.js} +28 -6
- package/dist/{cli-c3rk1v0x.js → cli-10jesr25.js} +3 -3
- package/dist/{cli-6thk4jz3.js → cli-1y7yywmj.js} +6 -6
- package/dist/{cli-6r2f7edk.js → cli-20krdhz5.js} +47 -19
- package/dist/{cli-rfs4vddv.js → cli-29rja109.js} +39 -20
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-na2pxe4f.js → cli-2pwa0q4d.js} +15 -4
- package/dist/{cli-7a93cv8c.js → cli-4mengw46.js} +441 -43
- package/dist/{cli-94b48jhk.js → cli-5twdke5x.js} +16 -14
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-w1apjecb.js → cli-711vwbxn.js} +2 -2
- package/dist/{cli-r4fqfpwf.js → cli-78vv7446.js} +50 -27
- package/dist/{cli-srqq3gc5.js → cli-7n6s5man.js} +5 -5
- package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
- package/dist/{cli-2bw3w47j.js → cli-8wwxw8a3.js} +1 -1
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-ywm1azg9.js → cli-9jzdj90z.js} +8 -4
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/cli-cvv9k0hh.js +10143 -0
- package/dist/{cli-anzdk0z4.js → cli-d9286m9h.js} +2 -2
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-gmdajfw5.js → cli-gxzkg1de.js} +5020 -1729
- package/dist/{cli-451ks6aw.js → cli-h1arqn31.js} +1 -1
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-jpc4r224.js → cli-hqr88ew6.js} +19 -3
- package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
- package/dist/{cli-cd0hv9nh.js → cli-j67mh2vg.js} +2 -2
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-d603qf86.js → cli-ksphgh48.js} +10 -8
- package/dist/{cli-3nxdmjrc.js → cli-mgz4nbgg.js} +4 -4
- package/dist/{cli-saqyage0.js → cli-mz5as5ha.js} +179 -27
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-ppy4nnnh.js → cli-n8ndw8j7.js} +2 -2
- package/dist/{cli-1w0vj3gw.js → cli-naqzr17j.js} +7 -7
- package/dist/{cli-0a7mm3zp.js → cli-nm1p8jfr.js} +25 -21
- package/dist/{cli-wrh08zjd.js → cli-p3zbc1rw.js} +5 -18
- package/dist/{cli-hsem16hb.js → cli-pe05f8yk.js} +29 -6
- package/dist/{cli-5wpw4rab.js → cli-qmzsbkvy.js} +5 -5
- package/dist/{cli-bv2etw2y.js → cli-qnm4e9e4.js} +99 -590
- package/dist/{cli-1x7da0de.js → cli-qqy4q48b.js} +8 -8
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-5er5gjbm.js → cli-r35rw5de.js} +15 -15
- package/dist/{cli-v3zhnxsb.js → cli-r610p9bs.js} +2 -2
- package/dist/{cli-7jykv7ef.js → cli-rc6pf5kv.js} +1 -1
- package/dist/{cli-x119kdba.js → cli-rdxm77k3.js} +1 -1
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-0p3enk35.js → cli-s69nfyeh.js} +9 -1
- package/dist/{cli-0kxf81jj.js → cli-sawv63e8.js} +2 -2
- package/dist/{cli-e3pmyt39.js → cli-sg19gbf0.js} +1 -1
- package/dist/{cli-d161g69q.js → cli-shk7r5cs.js} +57 -6
- package/dist/{cli-7pz3b7x5.js → cli-sksetb2q.js} +36 -1
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-db3m6zdt.js → cli-t02z59f2.js} +1 -1
- package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
- package/dist/{cli-s8z6x4b4.js → cli-v7g551te.js} +225 -113
- package/dist/{cli-rfz2ve55.js → cli-vgqzp4em.js} +3341 -955
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/cli-wfnemr1t.js +86 -0
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-qm1448f9.js → cli-wms6x9db.js} +8 -8
- package/dist/{cli-tadfgd0t.js → cli-x1r545x8.js} +33 -4
- package/dist/{cli-xc7p7s3g.js → cli-xczsgshn.js} +6 -6
- package/dist/{cli-fmhj1ehj.js → cli-y3167wt1.js} +882 -271
- package/dist/{cli-r0byd61h.js → cli-yjmqpxt3.js} +17 -16
- package/dist/{cli-81r1wjyv.js → cli-z780ec7c.js} +1 -1
- package/dist/{cli-phcqp1b9.js → cli-zm9t2vde.js} +2 -2
- package/dist/cli.js +34 -49
- package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-4z16v9n0.js} +15 -14
- package/dist/{codex-login-841kv5fk.js → codex-login-pkepy2j1.js} +3 -2
- package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-rvms9y2x.js} +15 -14
- package/dist/{commands-z8fq9qna.js → commands-2a9rtyat.js} +11 -10
- package/dist/{controller-hq5ggpcp.js → controller-3k3madbn.js} +5 -4
- package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-v9yn8zb9.js} +42 -37
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-98gbhyzn.js} +7 -6
- package/dist/{db-qfpq4bt7.js → db-eywwsnjw.js} +30 -9
- package/dist/{db-yyhqqrbf.js → db-ncypk9np.js} +12 -11
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-zeq8b9gz.js} +3 -2
- package/dist/{dispatcher-x0x7qfcq.js → dispatcher-w94kc575.js} +38 -33
- package/dist/{docker-f503k9p0.js → docker-b1e4cqab.js} +3 -2
- package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-47ztej36.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-bbt8ey45.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-dp804sen.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-j2jdg3qb.js} +3 -2
- package/dist/{external-channel-h1fjecwe.js → external-channel-zrkg8ar9.js} +11 -10
- package/dist/{google-generative-ai-szdxbpqg.js → google-generative-ai-g8db7x0f.js} +4 -2
- package/dist/{google-vertex-qzw3p36d.js → google-vertex-r2692q0r.js} +4 -2
- package/dist/{grok-adapter-e7mr287e.js → grok-adapter-s9ncp9vy.js} +18 -17
- package/dist/{handlers-znb9n7d4.js → handlers-kqftvjgw.js} +41 -36
- package/dist/{heartbeat-bm4qkn8d.js → heartbeat-9q96p8v9.js} +43 -38
- package/dist/{hook-254r4mza.js → hook-56qe10dp.js} +11 -23
- package/dist/{hook-xaa3q80s.js → hook-yy6rw42k.js} +12 -11
- package/dist/{http-3dgrgp8y.js → http-r2dnb8f8.js} +2411 -275
- package/dist/{index-fx3jqq1e.js → index-3gtmkhc6.js} +38 -33
- package/dist/{index-bdsqa799.js → index-3k5hkz7r.js} +43 -38
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-g2byveez.js → index-5e101240.js} +38 -33
- package/dist/{index-2ybk7khy.js → index-5wyfjc2c.js} +845 -683
- 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-jd7sejm2.js → index-vxvhxxbn.js} +10 -9
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{keepalive-6ywhpja1.js → keepalive-psj6j54c.js} +12 -11
- package/dist/{lead-cw45n21s.js → lead-hajz4688.js} +61 -56
- package/dist/{maintenance-ss1a1ge9.js → maintenance-ps02sb5m.js} +10 -9
- package/dist/{node-fkajaq96.js → node-mwb5r697.js} +2 -1
- package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-0284h93b.js} +11 -10
- package/dist/{onboard-8hzdhc1k.js → onboard-rbf6bg01.js} +11 -3
- package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-13dcatgq.js} +18 -13
- package/dist/{otel-impl-e6mnvc4v.js → otel-impl-zvqcbhp7.js} +242 -868
- package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-xxy47q4v.js} +244 -106
- package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-kefx9v3t.js} +12 -11
- package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-3m36rxm2.js} +11 -10
- package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-z76xv0hq.js} +12 -11
- package/dist/{render-v2-907cy6sa.js → render-v2-wz73bs25.js} +18 -14
- package/dist/{resume-42stcaz0.js → resume-k4wzge8w.js} +25 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-adbc1c10.js → setup-2fp2pypp.js} +2 -2
- package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
- package/dist/{work-objects-wpj8ck95.js → work-objects-6k0ywz3m.js} +41 -36
- package/dist/{worker-bzdra9rf.js → worker-5v3rxsdh.js} +61 -56
- package/dist/{x-qfmygqqv.js → x-4mtdeym1.js} +3 -2
- package/openapi.json +1279 -329
- package/package.json +15 -15
- package/src/agentmail/handlers.ts +21 -11
- package/src/apps/definition.ts +16 -0
- package/src/azure-devops/api.ts +52 -2
- package/src/azure-devops/boards-sync.ts +50 -20
- package/src/azure-devops/index.ts +1 -0
- package/src/azure-devops/outbound.ts +95 -0
- package/src/be/boot-seeds.ts +11 -0
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/model-profiles.ts +315 -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 +237 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +87 -36
- 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/migrations/219_relabel_pi_context_compactions.sql +22 -0
- package/src/be/migrations/220_model_profiles.sql +137 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +155 -10
- package/src/be/model-validation.ts +12 -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-credential-broker.ts +39 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +22 -8
- package/src/be/secret-registry.ts +6 -2
- 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-model-profiles.ts +41 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +368 -0
- 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-scripts/index.ts +9 -0
- package/src/be/seed-skills/bundled-files.generated.json +0 -18
- package/src/be/seed-skills/index.ts +104 -3
- 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/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +193 -71
- package/src/e2b/env.ts +5 -0
- package/src/extensions/catalog.generated.json +17 -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/loader.ts +10 -5
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/heartbeat.ts +2 -1
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/agents.ts +49 -2
- package/src/http/all-routes.ts +1 -1
- package/src/http/apps.ts +30 -3
- package/src/http/config.ts +62 -19
- package/src/http/core.ts +8 -0
- package/src/http/index.ts +25 -3
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp.ts +15 -5
- package/src/http/model-profiles.ts +303 -0
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +13 -7
- package/src/http/pages.ts +3 -13
- package/src/http/poll.ts +42 -71
- package/src/http/requested-by.ts +54 -0
- package/src/http/script-runs.ts +1 -1
- package/src/http/scripts.ts +26 -2
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +79 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +160 -3
- 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/{artifact-sdk → pages}/feedback-overlay.ts +65 -6
- 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 +1 -1
- package/src/providers/claude-flag-settings.ts +17 -5
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +243 -26
- package/src/providers/opencode-swarm-plugin.ts +31 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pi-mono-extension.ts +17 -3
- package/src/providers/pricing-sources.md +33 -2
- package/src/providers/reasoning-effort.ts +37 -0
- package/src/providers/types.ts +6 -2
- package/src/rbac/legacy-policy.ts +16 -2
- package/src/rbac/permissions.ts +26 -0
- package/src/scheduler/deferred-task-waits.ts +18 -5
- package/src/scheduler/scheduler.ts +11 -3
- package/src/scripts-runtime/executors/quickjs-prelude.ts +75 -6
- package/src/scripts-runtime/executors/quickjs-runner.ts +85 -8
- package/src/scripts-runtime/executors/quickjs-web-shims.ts +1041 -0
- package/src/scripts-runtime/extract-args-schema.ts +9 -8
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/quickjs-compat.ts +464 -0
- package/src/scripts-runtime/sdk-allowlist.ts +12 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +39 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +66 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +39 -15
- package/src/server.ts +62 -19
- package/src/slack/blocks.ts +4 -2
- package/src/slack/event-dedup.ts +1 -1
- package/src/slack/reaction-shortcode.ts +14 -0
- package/src/slack/render-v2.ts +12 -7
- package/src/slack/responses.ts +5 -4
- package/src/slack/thread-buffer.ts +41 -22
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +60 -1
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +15 -33
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/agentmail-filters.test.ts +47 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/apps-spike2.test.ts +35 -0
- package/src/tests/azure-devops-outbound.test.ts +420 -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 +9 -4
- package/src/tests/claude-flag-settings.test.ts +11 -3
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
- 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 +19 -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 +22 -0
- package/src/tests/db-task-write-contract.test.ts +11 -0
- package/src/tests/deferred-task-wake.test.ts +78 -1
- 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/env-flag.test.ts +1 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-catalog.test.ts +1 -0
- package/src/tests/extensions-example-comms-adherence-gate.test.ts +413 -0
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-loader.test.ts +15 -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/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-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/heartbeat-jev-gate-credentials.test.ts +168 -0
- package/src/tests/heartbeat-jev-gate.test.ts +385 -0
- 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-profile-backcompat.test.ts +327 -0
- package/src/tests/model-profile-providers.test.ts +302 -0
- package/src/tests/model-profile-runtime-secrets.test.ts +223 -0
- package/src/tests/model-profiles-api.test.ts +614 -0
- package/src/tests/model-tier-resolution.test.ts +93 -0
- package/src/tests/models-catalog.test.ts +42 -1
- 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 +216 -2
- 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-keys.test.ts +121 -0
- package/src/tests/pages-feedback.test.ts +4 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-context-compaction.test.ts +193 -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/profile-claim.test.ts +269 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/quickjs-compat.test.ts +213 -0
- package/src/tests/rbac-engine.test.ts +32 -3
- package/src/tests/runner-exit-after-tasks.test.ts +0 -4
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections.test.ts +6 -0
- package/src/tests/script-executor-conformance.test.ts +252 -1
- package/src/tests/script-executor-quickjs.test.ts +96 -0
- package/src/tests/script-runs-http.test.ts +89 -0
- package/src/tests/scripts-http.test.ts +217 -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 +96 -0
- package/src/tests/seed-model-profiles.test.ts +174 -0
- package/src/tests/seed-scripts.test.ts +2 -2
- 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 +46 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/skill-invocations.test.ts +4 -2
- package/src/tests/slack-blocks.test.ts +36 -0
- package/src/tests/slack-inline-output.test.ts +14 -0
- package/src/tests/slack-reaction-config.test.ts +20 -0
- package/src/tests/slack-render-v2.test.ts +37 -0
- package/src/tests/slack-thread-buffer.test.ts +98 -1
- package/src/tests/sonnet-5-5-registry.test.ts +9 -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/vercel-ai-gateway.test.ts +149 -0
- package/src/tests/workflow-llm.test.ts +61 -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/model-catalog/index.ts +2 -1
- package/src/tools/model-profiles/list-model-profiles.ts +54 -0
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/request-human-input.ts +11 -3
- package/src/tools/script-apis.ts +5 -1
- package/src/tools/script-upsert.ts +4 -1
- package/src/tools/send-task.ts +48 -1
- package/src/tools/skills/skill-get.ts +17 -9
- 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/system-one-decide.ts +104 -0
- package/src/tools/task-action.ts +22 -1
- package/src/tools/tool-config.ts +14 -6
- package/src/types.ts +48 -3
- 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/runtime-model-catalog.ts +11 -1
- package/src/utils/secret-scrubber.ts +86 -10
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/utils/vcs-repo-match.ts +29 -0
- package/src/workflows/executors/raw-llm.ts +8 -3
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/src/workflows/executors/system-one-decision.ts +21 -11
- package/src/workflows/executors/workflow-llm.ts +22 -0
- package/src/workflows/index.ts +21 -12
- package/templates/extensions/README.md +1 -0
- package/templates/extensions/comms-adherence-gate/README.md +88 -0
- package/templates/extensions/comms-adherence-gate/hooks.ts +489 -0
- package/templates/extensions/comms-adherence-gate/manifest.json +8 -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 +8 -1
- package/templates/skills/apps/content.md +8 -1
- 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/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-42qhyvwx.js +0 -33
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- package/dist/cli-tcc4wd5d.js +0 -56471
- 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/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Boot seed for the shipped model profiles: one `<harness>-<tier>` profile per
|
|
3
|
+
* harness and tier, a 1:1 copy of `DEFAULT_MODEL_TIER_MAP` (runbooks/model-tiers.md
|
|
4
|
+
* § Model profiles). A global `MODEL_TIER_<HARNESS>_<TIER>` row, when one exists,
|
|
5
|
+
* overrides the seed's model at seeding time. Seeds use the harness default
|
|
6
|
+
* route, no effort and no fallbacks.
|
|
7
|
+
*
|
|
8
|
+
* Idempotent: an existing name is never overwritten, so an operator's edit to a
|
|
9
|
+
* seed survives every boot. Harnesses with no portable tier mapping (acp) get
|
|
10
|
+
* no seeds.
|
|
11
|
+
*/
|
|
12
|
+
import { DEFAULT_MODEL_TIER_MAP, MODEL_TIERS, ProviderNameSchema } from "../types";
|
|
13
|
+
import { createModelProfile } from "./db/model-profiles";
|
|
14
|
+
import { getDbClient } from "./db/runtime";
|
|
15
|
+
import { tierConfigKey } from "./model-tier-keys";
|
|
16
|
+
|
|
17
|
+
export async function seedModelProfiles(): Promise<number> {
|
|
18
|
+
let inserted = 0;
|
|
19
|
+
for (const harness of ProviderNameSchema.options) {
|
|
20
|
+
for (const tier of MODEL_TIERS) {
|
|
21
|
+
const fallback = DEFAULT_MODEL_TIER_MAP[harness]?.[tier];
|
|
22
|
+
if (!fallback) continue;
|
|
23
|
+
const configured = await getDbClient().get<{ value: string }>(
|
|
24
|
+
"SELECT value FROM swarm_config WHERE scope = 'global' AND scopeId IS NULL AND key = ? AND isSecret = 0",
|
|
25
|
+
[tierConfigKey(harness, tier)],
|
|
26
|
+
);
|
|
27
|
+
const created = await createModelProfile({
|
|
28
|
+
name: `${harness}-${tier}`,
|
|
29
|
+
harness,
|
|
30
|
+
model: configured?.value.trim() || fallback,
|
|
31
|
+
effort: null,
|
|
32
|
+
// Tier values are free-form today (a `latest:` alias, a gateway id); keep that.
|
|
33
|
+
allowCustomModel: true,
|
|
34
|
+
description: `The ${tier} tier on ${harness}, seeded from the tier map.`,
|
|
35
|
+
seededFrom: `tier:${tier}`,
|
|
36
|
+
});
|
|
37
|
+
if (created) inserted++;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return inserted;
|
|
41
|
+
}
|
package/src/be/seed-pricing.ts
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
* admin route (`POST /api/pricing`) — we don't overwrite seed rows.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
import { openAICompatibleProviderIds } from "@desplega/model-catalog";
|
|
22
23
|
import type { PricingProvider, PricingTokenClass } from "../types";
|
|
23
24
|
import { getDb } from "./db";
|
|
24
25
|
import {
|
|
@@ -98,8 +99,9 @@ const ANTHROPIC_SHORTNAME_TO_MODELSDEV: Record<string, string> = {
|
|
|
98
99
|
const ANTHROPIC_SHORTNAME_PRICING_FALLBACKS: Record<string, ModelsDevCostBlock> = {
|
|
99
100
|
// https://platform.claude.com/docs/en/about-claude/pricing (verified 2026-09-22)
|
|
100
101
|
"claude-opus-5-5": { input: 4, output: 20, cache_read: 0.2, cache_write: 5 },
|
|
101
|
-
// https://platform.claude.com/docs/en/about-claude/pricing (verified 2026-
|
|
102
|
-
|
|
102
|
+
// https://platform.claude.com/docs/en/about-claude/pricing (verified 2026-10-15):
|
|
103
|
+
// cache hits on Sonnet 5.5 cost 0.05x input, not the usual 0.1x.
|
|
104
|
+
"claude-sonnet-5-5": { input: 2, output: 10, cache_read: 0.1, cache_write: 2.5 },
|
|
103
105
|
"claude-fable-5-1": { input: 10, output: 50, cache_read: 0.25, cache_write: 12.5 },
|
|
104
106
|
"claude-mythos-5-1": { input: 10, output: 50, cache_read: 0.25, cache_write: 12.5 },
|
|
105
107
|
};
|
|
@@ -367,6 +369,21 @@ export function buildModelsDevSeedRows(cache: ModelsDevCache): PricingSeedRow[]
|
|
|
367
369
|
}
|
|
368
370
|
}
|
|
369
371
|
|
|
372
|
+
// ---- OpenAI-compatible registry providers ($0 flat-rate subscriptions) --
|
|
373
|
+
// pi and opencode run these as `<provider>/<id>`. The models.dev `nan`
|
|
374
|
+
// section and the registry-synthesized `helmcode` section
|
|
375
|
+
// (`withRegistryCatalogSections`) carry cost {0, 0}, so the sessions price
|
|
376
|
+
// as `pricing-table` at $0 instead of `unpriced`. The provider prefix stays
|
|
377
|
+
// in the key: `nan/qwen3.6` and `helmcode/qwen3.6` are separate rows.
|
|
378
|
+
for (const provider of openAICompatibleProviderIds()) {
|
|
379
|
+
for (const [id, model] of Object.entries(cache[provider]?.models ?? {})) {
|
|
380
|
+
if (!model?.cost) continue;
|
|
381
|
+
const key = `${provider}/${id}`;
|
|
382
|
+
add(key, projectCostBlock("pi", key, model.cost));
|
|
383
|
+
add(key, projectCostBlock("opencode", key, model.cost));
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
370
387
|
return collapseNormalizedIds(sourced);
|
|
371
388
|
}
|
|
372
389
|
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const argsSchema = z.object({
|
|
4
|
+
leadAgentId: z.string().optional().describe("Lead agent id; the heartbeat passes it"),
|
|
5
|
+
dryRun: z
|
|
6
|
+
.boolean()
|
|
7
|
+
.optional()
|
|
8
|
+
.describe(
|
|
9
|
+
"Return the verdict, the compact state and the prompt it would create, without creating a prompt or writing KV",
|
|
10
|
+
),
|
|
11
|
+
threshold: z
|
|
12
|
+
.number()
|
|
13
|
+
.min(0)
|
|
14
|
+
.max(1)
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Quiet when Jev's p(needs action) is below this (default 0.5)"),
|
|
17
|
+
provider: z
|
|
18
|
+
.enum(["auto", "typesafe", "openrouter"])
|
|
19
|
+
.optional()
|
|
20
|
+
.describe("Jev host; auto prefers TypeSafe (default auto)"),
|
|
21
|
+
timeZone: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe("IANA time zone for the state's current time and dates (default UTC)"),
|
|
25
|
+
jevTimeoutMs: z
|
|
26
|
+
.number()
|
|
27
|
+
.int()
|
|
28
|
+
.min(1_000)
|
|
29
|
+
.max(45_000)
|
|
30
|
+
.optional()
|
|
31
|
+
.describe("Abandon the Jev call after this many ms (default 25000); the gate deadline is 60 s"),
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const KV_NAMESPACE = "heartbeat-jev-gate";
|
|
35
|
+
const KV_KEY = "setup";
|
|
36
|
+
// Measured per decision in the 2026-10-15 heartbeat replay (229 states).
|
|
37
|
+
const COST_PER_DECISION = "$0.00004";
|
|
38
|
+
|
|
39
|
+
// Jev is called through `ctx.swarm.systemOne_decide`: the API server reads the
|
|
40
|
+
// key and sends the request, so no key ever enters this script's realm. The
|
|
41
|
+
// server also refuses OpenRouter when the effective OPENROUTER_BASE_URL (stored
|
|
42
|
+
// config or deployment env) points at a gateway.
|
|
43
|
+
const PROVIDERS = {
|
|
44
|
+
typesafe: { keyName: "TYPESAFE_API_KEY", model: "jev-latest" },
|
|
45
|
+
openrouter: { keyName: "OPENROUTER_API_KEY", model: "~typesafe/jev-latest" },
|
|
46
|
+
} as const;
|
|
47
|
+
type ProviderId = keyof typeof PROVIDERS;
|
|
48
|
+
|
|
49
|
+
// Worded exactly as in the replay that set the 0.5 threshold; changing it voids that result.
|
|
50
|
+
const QUESTIONS = {
|
|
51
|
+
act: {
|
|
52
|
+
type: "noul",
|
|
53
|
+
instructions:
|
|
54
|
+
"This is a 30-minute heartbeat for the Lead agent of an AI agent swarm. Does this state require the Lead to take an action now: message a human, dispatch, resume or fix a task, or act on a tracked item that is due now? Answer false when nothing changed since the previous heartbeat and every failure is already triaged or owned.",
|
|
55
|
+
criteria: {
|
|
56
|
+
true: "A new untriaged failure, a tracked item or human ask due now and not yet done, or a problem with no owner",
|
|
57
|
+
false:
|
|
58
|
+
"Same state as the previous heartbeat, failures already triaged or owned, nothing due now",
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
type SetupState = {
|
|
64
|
+
status: "asked" | "approved" | "declined" | "expired";
|
|
65
|
+
requestId?: string;
|
|
66
|
+
url?: string;
|
|
67
|
+
askedAt?: string;
|
|
68
|
+
resolvedAt?: string;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
function rows(res: any): any[] {
|
|
72
|
+
const p = res?.data ?? res;
|
|
73
|
+
if (p?.error) throw new Error(`db_query: ${String(p.error).slice(0, 200)}`);
|
|
74
|
+
if (!Array.isArray(p?.rows)) throw new Error("db_query returned no rows array");
|
|
75
|
+
const cols: string[] = p.columns ?? [];
|
|
76
|
+
return p.rows.map((r: any) =>
|
|
77
|
+
Array.isArray(r) ? Object.fromEntries(cols.map((c, i) => [c, r[i]])) : r,
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const oneLine = (s: unknown) => String(s ?? "").replace(/\s+/g, " ");
|
|
82
|
+
|
|
83
|
+
/** `YYYY-MM-DD HH:MM` in the zone, falling back to UTC when the runtime has no Intl zone data. */
|
|
84
|
+
function localStamp(ms: number, timeZone: string): { stamp: string; zone: string } {
|
|
85
|
+
const utc = { stamp: new Date(ms).toISOString().slice(0, 16).replace("T", " "), zone: "UTC" };
|
|
86
|
+
if (timeZone === "UTC") return utc;
|
|
87
|
+
try {
|
|
88
|
+
const parts = new Intl.DateTimeFormat("en-CA", {
|
|
89
|
+
timeZone,
|
|
90
|
+
year: "numeric",
|
|
91
|
+
month: "2-digit",
|
|
92
|
+
day: "2-digit",
|
|
93
|
+
hour: "2-digit",
|
|
94
|
+
minute: "2-digit",
|
|
95
|
+
hourCycle: "h23",
|
|
96
|
+
}).formatToParts(new Date(ms));
|
|
97
|
+
const v = (t: string) => parts.find((p) => p.type === t)?.value ?? "";
|
|
98
|
+
return { stamp: `${v("year")}-${v("month")}-${v("day")} ${v("hour")}:${v("minute")}`, zone: timeZone };
|
|
99
|
+
} catch {
|
|
100
|
+
return utc;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// The checklist task renders failures as these lines (gatherSystemStatus in
|
|
105
|
+
// src/heartbeat/heartbeat.ts). The replay parsed them with this regex, so the
|
|
106
|
+
// gate renders and parses the same way to keep its fields identical.
|
|
107
|
+
const FAILURE_LINE_RE =
|
|
108
|
+
/- \[([0-9a-f]{8})\] "([\s\S]*?)" — agent: ([0-9a-f]{8}), reason: ([\s\S]*?), at: (\S+)/g;
|
|
109
|
+
|
|
110
|
+
function parseFailures(status: string): { id: string; what: string; reason: string }[] {
|
|
111
|
+
const out: { id: string; what: string; reason: string }[] = [];
|
|
112
|
+
for (const m of status.matchAll(FAILURE_LINE_RE)) {
|
|
113
|
+
out.push({
|
|
114
|
+
id: m[1] ?? "",
|
|
115
|
+
what: oneLine(m[2]).slice(0, 90),
|
|
116
|
+
reason: oneLine(m[4]).slice(0, 140),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
return out;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function renderFailureLine(t: any): string {
|
|
123
|
+
const agent = t.agentId ? String(t.agentId).slice(0, 8) : "unassigned";
|
|
124
|
+
const reason = t.failureReason ? String(t.failureReason).slice(0, 100) : "no reason";
|
|
125
|
+
return `- [${String(t.id).slice(0, 8)}] "${String(t.task ?? "").slice(0, 50)}" — agent: ${agent}, reason: ${reason}, at: ${t.finishedAt}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The compact state Jev scores: the fields of the 2026-10-15 replay, built from
|
|
130
|
+
* live data because the checklist task body does not exist yet at gate time.
|
|
131
|
+
*/
|
|
132
|
+
async function buildState(ctx: any, leadId: string, nowMs: number, timeZone: string) {
|
|
133
|
+
const q = async (sql: string, params: unknown[] = []) =>
|
|
134
|
+
rows(await ctx.swarm.db_query({ sql, params }));
|
|
135
|
+
const since6h = new Date(nowMs - 6 * 3600e3).toISOString();
|
|
136
|
+
const since24h = new Date(nowMs - 24 * 3600e3).toISOString();
|
|
137
|
+
// Sequential: db_query caps concurrent queries per caller, and parallel reads fail with
|
|
138
|
+
// db_query_concurrency_cap on a busy swarm.
|
|
139
|
+
const lead = await q("SELECT heartbeatMd FROM agents WHERE id = ?", [leadId]);
|
|
140
|
+
const prev = await q(
|
|
141
|
+
`SELECT id, substr(output, 1, 400) AS output,
|
|
142
|
+
substr(task, 1, instr(task, '## Your Standing Orders')) AS status
|
|
143
|
+
FROM agent_tasks
|
|
144
|
+
WHERE agentId = ? AND taskType = 'heartbeat-checklist' AND status = 'completed'
|
|
145
|
+
ORDER BY createdAt DESC LIMIT 1`,
|
|
146
|
+
[leadId],
|
|
147
|
+
);
|
|
148
|
+
const failed = await q(
|
|
149
|
+
`SELECT id, agentId, substr(task, 1, 60) AS task, substr(failureReason, 1, 120) AS failureReason, finishedAt
|
|
150
|
+
FROM agent_tasks WHERE status = 'failed' AND finishedAt > ?
|
|
151
|
+
ORDER BY finishedAt DESC LIMIT 10`,
|
|
152
|
+
[since6h],
|
|
153
|
+
);
|
|
154
|
+
const overview = await q(
|
|
155
|
+
`SELECT SUM(status = 'in_progress') AS inProgress, SUM(status = 'pending') AS pending,
|
|
156
|
+
SUM(status = 'unassigned') AS unassigned,
|
|
157
|
+
SUM(status = 'completed' AND finishedAt > ?) AS completed24,
|
|
158
|
+
SUM(status = 'failed' AND finishedAt > ?) AS failed24
|
|
159
|
+
FROM agent_tasks`,
|
|
160
|
+
[since24h, since24h],
|
|
161
|
+
);
|
|
162
|
+
const agents = await q(
|
|
163
|
+
"SELECT status, COUNT(*) AS n FROM agents WHERE COALESCE(role, '') != 'extension' GROUP BY status",
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
const fails = parseFailures(failed.map(renderFailureLine).join("\n"));
|
|
167
|
+
const prevIds = new Set(parseFailures(String(prev[0]?.status ?? "")).map((f) => f.id));
|
|
168
|
+
const newFails = fails.filter((f) => !prevIds.has(f.id));
|
|
169
|
+
|
|
170
|
+
const { stamp, zone } = localStamp(nowMs, timeZone);
|
|
171
|
+
const mmdd = new Date(nowMs).toISOString().slice(5, 10);
|
|
172
|
+
const mmddLocal = stamp.slice(5, 10);
|
|
173
|
+
const due: string[] = [];
|
|
174
|
+
for (const line of String(lead[0]?.heartbeatMd ?? "").split("\n")) {
|
|
175
|
+
const l = line.trim();
|
|
176
|
+
if (!l) continue;
|
|
177
|
+
const del = /DELETE <?(\d\d-\d\d)>?/.exec(l);
|
|
178
|
+
if (l.includes(mmdd) || l.includes(mmddLocal) || (del?.[1] && del[1] <= mmddLocal)) {
|
|
179
|
+
due.push(oneLine(l).slice(0, 200));
|
|
180
|
+
}
|
|
181
|
+
if (due.length >= 6) break;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const o = overview[0] ?? {};
|
|
185
|
+
const n = (v: unknown) => Number(v ?? 0) || 0;
|
|
186
|
+
const count = (s: string) => n(agents.find((a) => a.status === s)?.n);
|
|
187
|
+
const idle = count("idle");
|
|
188
|
+
const busy = count("busy");
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
now: `${stamp} ${zone}`,
|
|
192
|
+
new_failures_since_previous_heartbeat: newFails.length
|
|
193
|
+
? newFails.map((f) => `${f.id}: ${f.what} | ${f.reason}`)
|
|
194
|
+
: "none",
|
|
195
|
+
tracked_items_mentioning_today_or_past_delete_date: due.length ? due : "none",
|
|
196
|
+
previous_heartbeat_result: prev[0]?.output
|
|
197
|
+
? oneLine(prev[0].output).slice(0, 350)
|
|
198
|
+
: "unknown",
|
|
199
|
+
failures_last_6h_total: fails.length,
|
|
200
|
+
task_overview: `- In Progress: ${n(o.inProgress)} - Pending: ${n(o.pending)} - Unassigned: ${n(o.unassigned)} - Completed (24h): ${n(o.completed24)} - Failed (24h): ${n(o.failed24)}`,
|
|
201
|
+
agents: `- Online: ${idle + busy} (${idle} idle, ${busy} busy), Offline: ${count("offline")}`,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function setupPrompt(keys: string[]) {
|
|
206
|
+
return {
|
|
207
|
+
title: "Heartbeat Jev gate: add a Jev credential or decline",
|
|
208
|
+
detached: true,
|
|
209
|
+
questions: [
|
|
210
|
+
{
|
|
211
|
+
id: "enable",
|
|
212
|
+
type: "approval",
|
|
213
|
+
label: "Enable the Jev heartbeat gate?",
|
|
214
|
+
description: [
|
|
215
|
+
"Before each recurring heartbeat checklist, the `heartbeat-jev-gate` script sends a short summary of swarm state (about 1,500 characters: new failures, due tracked items, task and agent counts) to Jev, a small decision model by TypeSafe, and asks whether the Lead needs to act. With `HEARTBEAT_CHECKLIST_GATE_MODE=enforce`, quiet ticks skip the Lead's checklist task.",
|
|
216
|
+
"",
|
|
217
|
+
`Cost: about ${COST_PER_DECISION} per decision, one decision per checklist tick.`,
|
|
218
|
+
"",
|
|
219
|
+
`No Jev credential is configured. To enable, approve and add one of ${keys.map((k) => `\`${k}\``).join(" or ")} as a global secret on the Secrets page (Settings > Secrets). Do not paste the key here. The next tick picks it up.`,
|
|
220
|
+
"",
|
|
221
|
+
"Reject to decline. The gate then stays inactive, with no further prompts, until a key is added.",
|
|
222
|
+
].join("\n"),
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Heartbeat checklist gate backed by Jev: asks Jev whether a recurring checklist
|
|
230
|
+
* tick needs the Lead and returns { quiet, reason, summary }. With no Jev
|
|
231
|
+
* credential it asks a human once, then stays a no-op until a key is added.
|
|
232
|
+
*/
|
|
233
|
+
export default async function heartbeatJevGate(args: any, ctx: any) {
|
|
234
|
+
const parsed = argsSchema.safeParse(args ?? {});
|
|
235
|
+
if (!parsed.success) throw new Error(`invalid args: ${parsed.error.message.slice(0, 200)}`);
|
|
236
|
+
const a = parsed.data;
|
|
237
|
+
const dryRun = a.dryRun === true;
|
|
238
|
+
|
|
239
|
+
const agentInfo: any = a.leadAgentId ? null : await ctx.swarm.agent_info();
|
|
240
|
+
const leadId = String(a.leadAgentId ?? agentInfo?.data?.id ?? agentInfo?.id ?? "");
|
|
241
|
+
if (!leadId) throw new Error("no leadAgentId");
|
|
242
|
+
|
|
243
|
+
// Values of secret rows come back masked: presence is all this script reads.
|
|
244
|
+
const cfgRes: any = await ctx.swarm.config_get({ agentId: leadId });
|
|
245
|
+
const configs: any[] = cfgRes?.data?.configs ?? cfgRes?.configs ?? [];
|
|
246
|
+
const cfg = (key: string): string => {
|
|
247
|
+
const value = configs.find((c) => c?.key === key)?.value;
|
|
248
|
+
return typeof value === "string" ? value.trim() : "";
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const cfgThreshold = Number.parseFloat(cfg("HEARTBEAT_JEV_GATE_THRESHOLD"));
|
|
252
|
+
const threshold =
|
|
253
|
+
a.threshold ?? (cfgThreshold >= 0 && cfgThreshold <= 1 ? cfgThreshold : 0.5);
|
|
254
|
+
const providerPref = a.provider ?? (cfg("HEARTBEAT_JEV_GATE_PROVIDER").toLowerCase() || "auto");
|
|
255
|
+
const timeZone = a.timeZone ?? (cfg("HEARTBEAT_JEV_GATE_TIMEZONE") || "UTC");
|
|
256
|
+
|
|
257
|
+
const usable: Record<ProviderId, boolean> = {
|
|
258
|
+
typesafe: cfg(PROVIDERS.typesafe.keyName) !== "",
|
|
259
|
+
openrouter: cfg(PROVIDERS.openrouter.keyName) !== "",
|
|
260
|
+
};
|
|
261
|
+
const candidates: ProviderId[] =
|
|
262
|
+
providerPref === "typesafe"
|
|
263
|
+
? ["typesafe"]
|
|
264
|
+
: providerPref === "openrouter"
|
|
265
|
+
? ["openrouter"]
|
|
266
|
+
: ["typesafe", "openrouter"];
|
|
267
|
+
const provider = candidates.find((id) => usable[id]);
|
|
268
|
+
|
|
269
|
+
if (!provider) {
|
|
270
|
+
const keys = candidates.map((id) => PROVIDERS[id].keyName);
|
|
271
|
+
const inactive = (state: string, extra: Record<string, unknown> = {}) => ({
|
|
272
|
+
quiet: false,
|
|
273
|
+
reason: `jev-gate inactive: ${state}`.slice(0, 300),
|
|
274
|
+
...(dryRun ? { dryRun: true, ...extra } : {}),
|
|
275
|
+
});
|
|
276
|
+
const entry: any = await ctx.swarm.kv_getOrNull({ namespace: KV_NAMESPACE, key: KV_KEY });
|
|
277
|
+
const stored = entry?.value;
|
|
278
|
+
let setup: SetupState | null = typeof stored === "string" ? JSON.parse(stored) : (stored ?? null);
|
|
279
|
+
|
|
280
|
+
if (!setup) {
|
|
281
|
+
const prompt = setupPrompt(keys);
|
|
282
|
+
if (dryRun) {
|
|
283
|
+
const state = await buildState(ctx, leadId, Date.now(), timeZone);
|
|
284
|
+
return inactive("no credential, would ask a human", { prompt, state });
|
|
285
|
+
}
|
|
286
|
+
const res: any = await ctx.swarm.request_humanInput(prompt);
|
|
287
|
+
const requestId = res?.data?.requestId ?? res?.requestId;
|
|
288
|
+
if (!requestId) throw new Error("request_humanInput returned no requestId");
|
|
289
|
+
setup = {
|
|
290
|
+
status: "asked",
|
|
291
|
+
requestId,
|
|
292
|
+
url: res?.data?.url ?? res?.url,
|
|
293
|
+
askedAt: new Date().toISOString(),
|
|
294
|
+
};
|
|
295
|
+
await ctx.swarm.kv_set({ namespace: KV_NAMESPACE, key: KV_KEY, value: setup });
|
|
296
|
+
return inactive(`no credential, asked a human (approval request ${requestId})`);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
if (setup.status === "asked" && setup.requestId) {
|
|
300
|
+
const [req] = rows(
|
|
301
|
+
await ctx.swarm.db_query({
|
|
302
|
+
sql: "SELECT status FROM approval_requests WHERE id = ?",
|
|
303
|
+
params: [setup.requestId],
|
|
304
|
+
}),
|
|
305
|
+
);
|
|
306
|
+
const status = String(req?.status ?? "missing");
|
|
307
|
+
if (status === "pending") {
|
|
308
|
+
return inactive(`no credential, awaiting answer on approval request ${setup.requestId}`);
|
|
309
|
+
}
|
|
310
|
+
const next: SetupState["status"] =
|
|
311
|
+
status === "approved" ? "approved" : status === "rejected" ? "declined" : "expired";
|
|
312
|
+
setup = { ...setup, status: next, resolvedAt: new Date().toISOString() };
|
|
313
|
+
if (!dryRun) await ctx.swarm.kv_set({ namespace: KV_NAMESPACE, key: KV_KEY, value: setup });
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const why =
|
|
317
|
+
setup.status === "approved"
|
|
318
|
+
? `approved, waiting for ${keys.join(" or ")} on the Secrets page`
|
|
319
|
+
: setup.status === "declined"
|
|
320
|
+
? `declined; add ${keys.join(" or ")} to enable`
|
|
321
|
+
: `setup request expired unanswered; add ${keys.join(" or ")} to enable`;
|
|
322
|
+
return inactive(why, { setup });
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const target = PROVIDERS[provider];
|
|
326
|
+
const state = await buildState(ctx, leadId, Date.now(), timeZone);
|
|
327
|
+
|
|
328
|
+
// The server enforces the time budget. No retries, as in the replay.
|
|
329
|
+
const res: any = await ctx.swarm.systemOne_decide({
|
|
330
|
+
provider,
|
|
331
|
+
model: target.model,
|
|
332
|
+
state,
|
|
333
|
+
questions: QUESTIONS,
|
|
334
|
+
timeoutMs: a.jevTimeoutMs ?? 25_000,
|
|
335
|
+
maxRetries: 0,
|
|
336
|
+
});
|
|
337
|
+
const body: any = res?.data ?? res;
|
|
338
|
+
if (res?.success === false || body?.success === false) {
|
|
339
|
+
throw new Error(`jev ${provider}: ${String(body?.message ?? body?.error ?? `HTTP ${res?.status}`).slice(0, 250)}`);
|
|
340
|
+
}
|
|
341
|
+
const p = body?.answers?.act?.noul;
|
|
342
|
+
if (typeof p !== "number" || !Number.isFinite(p)) {
|
|
343
|
+
throw new Error(`jev ${provider}: response has no numeric answers.act.noul`);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const pText = p.toFixed(3);
|
|
347
|
+
const quiet = p < threshold;
|
|
348
|
+
const verdict: Record<string, unknown> = {
|
|
349
|
+
quiet,
|
|
350
|
+
reason: `jev p(needs action)=${pText} ${quiet ? "<" : ">="} ${threshold} via ${provider}`,
|
|
351
|
+
};
|
|
352
|
+
if (!quiet) {
|
|
353
|
+
const lines = [`Jev p(needs action) = ${pText} (threshold ${threshold}, ${provider}).`];
|
|
354
|
+
const failures = state.new_failures_since_previous_heartbeat;
|
|
355
|
+
const tracked = state.tracked_items_mentioning_today_or_past_delete_date;
|
|
356
|
+
if (Array.isArray(failures)) {
|
|
357
|
+
lines.push("", "New failures since the previous checklist:", ...failures.map((f) => `- ${f}`));
|
|
358
|
+
}
|
|
359
|
+
if (Array.isArray(tracked)) {
|
|
360
|
+
lines.push("", "Tracked items due today or past their DELETE date:", ...tracked.map((t) => `- ${t.replace(/^[-*] /, "")}`));
|
|
361
|
+
}
|
|
362
|
+
if (!Array.isArray(failures) && !Array.isArray(tracked)) {
|
|
363
|
+
lines.push("", "No new failures or due tracked items; Jev flagged the overall state.");
|
|
364
|
+
}
|
|
365
|
+
verdict.summary = lines.join("\n").slice(0, 4000);
|
|
366
|
+
}
|
|
367
|
+
return dryRun ? { ...verdict, dryRun: true, provider, p, threshold, state } : verdict;
|
|
368
|
+
}
|
|
@@ -38,7 +38,7 @@ const CONTRADICTORY_RE =
|
|
|
38
38
|
/\b(do not|don't|never)\b[\s\S]{0,240}\b(always|must|required)\b|\b(always|must|required)\b[\s\S]{0,240}\b(do not|don't|never)\b/i;
|
|
39
39
|
|
|
40
40
|
const CODE_REGISTRY_EVENTS =
|
|
41
|
-
"agentmail.email.followup agentmail.email.mapped_lead agentmail.email.mapped_worker agentmail.email.no_agent agentmail.email.unmapped common.command_suggestions.github_comment_issue common.command_suggestions.github_comment_pr common.command_suggestions.github_issue common.command_suggestions.github_pr common.command_suggestions.gitlab_issue common.command_suggestions.gitlab_mr common.delegation_instruction common.delegation_instruction.gitlab github.check_run.failed github.check_suite.failed github.comment.mentioned github.issue.assigned github.issue.labeled github.issue.mentioned github.pull_request.assigned github.pull_request.closed github.pull_request.labeled github.pull_request.mentioned github.pull_request.review_requested github.pull_request.review_submitted github.pull_request.synchronize github.workflow_run.failed gitlab.comment.mentioned gitlab.issue.assigned gitlab.merge_request.opened gitlab.pipeline.failed heartbeat.boot-triage heartbeat.checklist jira.issue.assigned jira.issue.commented jira.issue.followup kapso.message.received linear.issue.assigned linear.issue.followup linear.issue.reassigned slack.assistant.greeting slack.assistant.offline slack.assistant.suggested_prompts slack.message.attachment_failed slack.message.thread_context system.agent.communication system.agent.lead system.agent.memory system.agent.memory.remote system.agent.outputs system.agent.outputs.no_agent_fs system.agent.repository system.agent.role system.agent.secrets system.agent.slack system.agent.tools_skills system.agent.worker system.agent.worker.remote system.agent.workspace system.agent.workspace.remote system.session.lead system.session.lead.managed system.session.worker system.session.worker.managed system.session.worker.remote task.budget.refused task.requester.profile task.worker.completed task.worker.failed".split(
|
|
41
|
+
"agentmail.email.followup agentmail.email.mapped_lead agentmail.email.mapped_worker agentmail.email.no_agent agentmail.email.unmapped chat.message.thread_context common.command_suggestions.github_comment_issue common.command_suggestions.github_comment_pr common.command_suggestions.github_issue common.command_suggestions.github_pr common.command_suggestions.gitlab_issue common.command_suggestions.gitlab_mr common.delegation_instruction common.delegation_instruction.gitlab github.check_run.failed github.check_suite.failed github.comment.mentioned github.issue.assigned github.issue.labeled github.issue.mentioned github.pull_request.assigned github.pull_request.closed github.pull_request.labeled github.pull_request.mentioned github.pull_request.review_requested github.pull_request.review_submitted github.pull_request.synchronize github.workflow_run.failed gitlab.comment.mentioned gitlab.issue.assigned gitlab.merge_request.opened gitlab.pipeline.failed heartbeat.boot-triage heartbeat.checklist jira.issue.assigned jira.issue.commented jira.issue.followup kapso.message.received linear.issue.assigned linear.issue.followup linear.issue.reassigned slack.assistant.greeting slack.assistant.offline slack.assistant.suggested_prompts slack.message.attachment_failed slack.message.thread_context system.agent.communication system.agent.lead system.agent.memory system.agent.memory.remote system.agent.outputs system.agent.outputs.no_agent_fs system.agent.repository system.agent.role system.agent.secrets system.agent.slack system.agent.tools_skills system.agent.worker system.agent.worker.remote system.agent.workspace system.agent.workspace.remote system.session.lead system.session.lead.managed system.session.worker system.session.worker.managed system.session.worker.remote task.budget.refused task.requester.profile task.worker.completed task.worker.failed".split(
|
|
42
42
|
" ",
|
|
43
43
|
);
|
|
44
44
|
|
|
@@ -38,7 +38,7 @@ const CONTRADICTORY_RE =
|
|
|
38
38
|
/\b(do not|don't|never)\b[\s\S]{0,240}\b(always|must|required)\b|\b(always|must|required)\b[\s\S]{0,240}\b(do not|don't|never)\b/i;
|
|
39
39
|
|
|
40
40
|
const CODE_REGISTRY_EVENTS =
|
|
41
|
-
"agentmail.email.followup agentmail.email.mapped_lead agentmail.email.mapped_worker agentmail.email.no_agent agentmail.email.unmapped common.command_suggestions.github_comment_issue common.command_suggestions.github_comment_pr common.command_suggestions.github_issue common.command_suggestions.github_pr common.command_suggestions.gitlab_issue common.command_suggestions.gitlab_mr common.delegation_instruction common.delegation_instruction.gitlab github.check_run.failed github.check_suite.failed github.comment.mentioned github.issue.assigned github.issue.labeled github.issue.mentioned github.pull_request.assigned github.pull_request.closed github.pull_request.labeled github.pull_request.mentioned github.pull_request.review_requested github.pull_request.review_submitted github.pull_request.synchronize github.workflow_run.failed gitlab.comment.mentioned gitlab.issue.assigned gitlab.merge_request.opened gitlab.pipeline.failed heartbeat.boot-triage heartbeat.checklist jira.issue.assigned jira.issue.commented jira.issue.followup kapso.message.received linear.issue.assigned linear.issue.followup linear.issue.reassigned slack.assistant.greeting slack.assistant.offline slack.assistant.suggested_prompts slack.message.attachment_failed slack.message.thread_context system.agent.communication system.agent.lead system.agent.memory system.agent.memory.remote system.agent.outputs system.agent.outputs.no_agent_fs system.agent.repository system.agent.role system.agent.secrets system.agent.slack system.agent.tools_skills system.agent.worker system.agent.worker.remote system.agent.workspace system.agent.workspace.remote system.session.lead system.session.lead.managed system.session.worker system.session.worker.managed system.session.worker.remote task.budget.refused task.requester.profile task.worker.completed task.worker.failed".split(
|
|
41
|
+
"agentmail.email.followup agentmail.email.mapped_lead agentmail.email.mapped_worker agentmail.email.no_agent agentmail.email.unmapped chat.message.thread_context common.command_suggestions.github_comment_issue common.command_suggestions.github_comment_pr common.command_suggestions.github_issue common.command_suggestions.github_pr common.command_suggestions.gitlab_issue common.command_suggestions.gitlab_mr common.delegation_instruction common.delegation_instruction.gitlab github.check_run.failed github.check_suite.failed github.comment.mentioned github.issue.assigned github.issue.labeled github.issue.mentioned github.pull_request.assigned github.pull_request.closed github.pull_request.labeled github.pull_request.mentioned github.pull_request.review_requested github.pull_request.review_submitted github.pull_request.synchronize github.workflow_run.failed gitlab.comment.mentioned gitlab.issue.assigned gitlab.merge_request.opened gitlab.pipeline.failed heartbeat.boot-triage heartbeat.checklist jira.issue.assigned jira.issue.commented jira.issue.followup kapso.message.received linear.issue.assigned linear.issue.followup linear.issue.reassigned slack.assistant.greeting slack.assistant.offline slack.assistant.suggested_prompts slack.message.attachment_failed slack.message.thread_context system.agent.communication system.agent.lead system.agent.memory system.agent.memory.remote system.agent.outputs system.agent.outputs.no_agent_fs system.agent.repository system.agent.role system.agent.secrets system.agent.slack system.agent.tools_skills system.agent.worker system.agent.worker.remote system.agent.workspace system.agent.workspace.remote system.session.lead system.session.lead.managed system.session.worker system.session.worker.managed system.session.worker.remote task.budget.refused task.requester.profile task.worker.completed task.worker.failed".split(
|
|
42
42
|
" ",
|
|
43
43
|
);
|
|
44
44
|
|
|
@@ -35,6 +35,7 @@ import getChildOutputsSrc from "./catalog/get-child-outputs.ts" with { type: "te
|
|
|
35
35
|
import ghPrSnapshotSrc from "./catalog/gh-pr-snapshot.ts" with { type: "text" };
|
|
36
36
|
import githubIssuesPullSrc from "./catalog/github-issues-pull.ts" with { type: "text" };
|
|
37
37
|
import groupCountSrc from "./catalog/group-count.ts" with { type: "text" };
|
|
38
|
+
import heartbeatJevGateSrc from "./catalog/heartbeat-jev-gate.ts" with { type: "text" };
|
|
38
39
|
import jsonQuerySrc from "./catalog/json-query.ts" with { type: "text" };
|
|
39
40
|
import linearIssueSrc from "./catalog/linear-issue.ts" with { type: "text" };
|
|
40
41
|
import memoryDedupCheckSrc from "./catalog/memory-dedup-check.ts" with { type: "text" };
|
|
@@ -112,6 +113,14 @@ export const SEED_SCRIPTS: SeedScript[] = [
|
|
|
112
113
|
"Keep an app's synced rows fresh on a schedule or on demand; the script a targetType:'script' schedule points at to sync an app.",
|
|
113
114
|
source: asText(appSyncRunSrc),
|
|
114
115
|
},
|
|
116
|
+
{
|
|
117
|
+
name: "heartbeat-jev-gate",
|
|
118
|
+
description:
|
|
119
|
+
"Heartbeat checklist gate backed by Jev (TypeSafe or OpenRouter decisions API): scores a compact swarm state and returns {quiet, reason, summary} for HEARTBEAT_CHECKLIST_GATE_SCRIPT.",
|
|
120
|
+
intent:
|
|
121
|
+
"Skip quiet Lead heartbeat checklist ticks with a cheap Jev decision; with no Jev credential it asks a human once, then stays a no-op until a key is added.",
|
|
122
|
+
source: asText(heartbeatJevGateSrc),
|
|
123
|
+
},
|
|
115
124
|
{
|
|
116
125
|
name: "fetch-readable",
|
|
117
126
|
description:
|
|
@@ -1,22 +1,4 @@
|
|
|
1
1
|
{
|
|
2
|
-
"artifacts": [
|
|
3
|
-
{
|
|
4
|
-
"path": "examples/approval-flow.ts",
|
|
5
|
-
"content": "import { createArtifactServer } from \"../../src/artifact-sdk\";\nimport { Hono } from \"hono\";\n\nconst app = new Hono();\napp.get(\"/\", (c) =>\n c.html(`\n<!DOCTYPE html>\n<html>\n<head><title>Approval Required</title></head>\n<body>\n <h1>PR #42 — Review Required</h1>\n <p>Agent wants to merge this PR. Please review.</p>\n <button id=\"approve\">Approve</button>\n <button id=\"reject\">Reject</button>\n <script src=\"/@swarm/sdk.js\"></script>\n <script>\n const swarm = new SwarmSDK();\n document.getElementById('approve').onclick = async () => {\n await swarm.createTask({ task: 'Merge PR #42 — human approved' });\n document.body.innerHTML = '<h1>Approved! Task created.</h1>';\n };\n document.getElementById('reject').onclick = async () => {\n await swarm.createTask({ task: 'PR #42 rejected by human — needs changes' });\n document.body.innerHTML = '<h1>Rejected. Agent notified.</h1>';\n };\n </script>\n</body>\n</html>\n`),\n);\n\nconst server = createArtifactServer({ name: \"approval-pr-42\", app });\nawait server.start();\nconsole.log(`Approval artifact at: ${server.url}`);\n"
|
|
6
|
-
},
|
|
7
|
-
{
|
|
8
|
-
"path": "examples/hono-dashboard.ts",
|
|
9
|
-
"content": "import { createArtifactServer } from \"../../src/artifact-sdk\";\nimport { Hono } from \"hono\";\n\nconst app = new Hono();\n\napp.get(\"/\", (c) =>\n c.html(`\n<!DOCTYPE html>\n<html>\n<head><title>Dashboard</title></head>\n<body>\n <h1>Agent Dashboard</h1>\n <div id=\"agents\"></div>\n <script src=\"/@swarm/sdk.js\"></script>\n <script>\n const swarm = new SwarmSDK();\n swarm.getSwarm().then(agents => {\n document.getElementById('agents').innerHTML =\n '<ul>' + agents.map(a => '<li>' + a.name + ' (' + a.status + ')</li>').join('') + '</ul>';\n });\n </script>\n</body>\n</html>\n`),\n);\n\napp.get(\"/api/status\", (c) => c.json({ status: \"ok\", timestamp: Date.now() }));\n\nconst server = createArtifactServer({ name: \"dashboard\", app });\nawait server.start();\nconsole.log(`Dashboard live at: ${server.url}`);\n"
|
|
10
|
-
},
|
|
11
|
-
{
|
|
12
|
-
"path": "examples/multi-artifact.ts",
|
|
13
|
-
"content": "import { createArtifactServer } from \"../../src/artifact-sdk\";\nimport { Hono } from \"hono\";\n\n// Artifact 1: Status page\nconst statusApp = new Hono();\nstatusApp.get(\"/\", (c) => c.html(\"<h1>Status: All systems operational</h1>\"));\n\n// Artifact 2: Data viewer\nconst dataApp = new Hono();\ndataApp.get(\"/\", (c) => c.json({ items: [1, 2, 3], generated: new Date().toISOString() }));\n\nconst status = createArtifactServer({ name: \"status\", app: statusApp });\nconst data = createArtifactServer({ name: \"data\", app: dataApp });\n\nawait status.start();\nawait data.start();\n\nconsole.log(`Status page: ${status.url}`);\nconsole.log(`Data viewer: ${data.url}`);\nconsole.log(`Both artifacts running on different ports (${status.port}, ${data.port})`);\n"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"path": "examples/static-report.sh",
|
|
17
|
-
"content": "#!/bin/bash\n# Serve a static HTML report as an artifact\nARTIFACT_DIR=\"/workspace/personal/artifacts/my-report\"\nmkdir -p \"$ARTIFACT_DIR\"\n\ncat > \"$ARTIFACT_DIR/index.html\" << 'HTML'\n<!DOCTYPE html>\n<html>\n<head><title>Agent Report</title></head>\n<body>\n <h1>Analysis Report</h1>\n <p>Generated by agent</p>\n</body>\n</html>\nHTML\n\nagent-swarm artifact serve \"$ARTIFACT_DIR\" --name \"my-report\"\n"
|
|
18
|
-
}
|
|
19
|
-
],
|
|
20
2
|
"brainstorming": [
|
|
21
3
|
{
|
|
22
4
|
"path": "template.md",
|