@desplega.ai/agent-swarm 2.5.4 → 2.7.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 +4 -2
- package/dist/{acp-adapter-ek38cwsv.js → acp-adapter-ma1js5n7.js} +9 -9
- package/dist/{actions-92mepq03.js → actions-1vhmtvg9.js} +21 -21
- package/dist/{amp-adapter-9gaxg015.js → amp-adapter-sxqqvmdk.js} +4 -4
- package/dist/{app-ctn8gsgx.js → app-mwx1d5a9.js} +3 -3
- package/dist/{assistant-zyr5kz47.js → assistant-yx1p6g82.js} +30 -26
- package/dist/{boot-reembed-w75maga2.js → boot-reembed-5h37a2c2.js} +1 -1
- package/dist/{boot-reembed-dwzfttdr.js → boot-reembed-7h78vmvv.js} +2 -1
- package/dist/{boot-scrub-sweep-e9kq43kf.js → boot-scrub-sweep-8mawd4gw.js} +4 -4
- package/dist/{boot-seeds-x28v3fhb.js → boot-seeds-ca84dhnn.js} +4 -4
- package/dist/{claude-adapter-f0afqnne.js → claude-adapter-wqt4hfkq.js} +9 -9
- package/dist/{claude-managed-adapter-x81a7r65.js → claude-managed-adapter-6fjqtr2z.js} +2 -2
- package/dist/{claude-managed-setup-bqzwjd9x.js → claude-managed-setup-rqv98sea.js} +10 -3
- package/dist/{claude-sdk-session-7b7whkaq.js → claude-sdk-session-f29f3b2x.js} +11 -11
- package/dist/{cli-sxgtf5fw.js → cli-07q03xm2.js} +1 -1
- package/dist/{cli-kxpfx2xr.js → cli-0z1xjzwa.js} +2 -2
- package/dist/{cli-g9vd9ece.js → cli-1hhbzkbb.js} +14 -16
- package/dist/{cli-qqzmjxkf.js → cli-1m9x8dr5.js} +11 -6
- package/dist/{cli-jbnn4vxb.js → cli-2pvzmas1.js} +3 -3
- package/dist/{cli-x77gen2p.js → cli-2y7v133v.js} +7 -7
- package/dist/{cli-dew6x255.js → cli-39aet655.js} +2 -2
- package/dist/{cli-g1cw7xtt.js → cli-39rrw8yp.js} +1 -1
- package/dist/{cli-jb30dzvk.js → cli-48gxjmcz.js} +530 -190
- package/dist/{cli-pzatvw94.js → cli-54sj64fc.js} +2 -2
- package/dist/{cli-bvpgr9ny.js → cli-60sty27p.js} +5 -5
- package/dist/{cli-asq5ydm4.js → cli-6a9qfa8b.js} +411 -69
- package/dist/{cli-277c31dw.js → cli-6mgdba42.js} +225 -3
- package/dist/{cli-19202kew.js → cli-6srv653c.js} +5 -5
- package/dist/{cli-n4c8e3s5.js → cli-708wdy32.js} +1 -1
- package/dist/{cli-pasyvjmm.js → cli-737pyqxr.js} +1 -1
- package/dist/{cli-6x9ma5w5.js → cli-803188pb.js} +1 -1
- package/dist/{cli-hh5we352.js → cli-86ehn4s5.js} +7 -7
- package/dist/{cli-9s05422w.js → cli-8mbc9za9.js} +1 -1
- package/dist/{cli-ff1tm9n9.js → cli-8wmj18cz.js} +1 -1
- package/dist/{cli-1r5ad7j5.js → cli-9gsm2rzp.js} +12 -12
- package/dist/{cli-mz9afxxf.js → cli-9pshx6rd.js} +17 -3
- package/dist/{cli-s682zgqz.js → cli-a6ds2epe.js} +1 -1
- package/dist/{cli-6a1xg1p7.js → cli-a89zdqz9.js} +2 -2
- package/dist/{cli-03vpq45j.js → cli-ay40dnj3.js} +2 -2
- package/dist/{cli-tsma7p8v.js → cli-aypd09nf.js} +2 -2
- package/dist/{cli-ethgy7ha.js → cli-b3yzyc57.js} +2 -2
- package/dist/{cli-bn0rewsy.js → cli-c081bj3b.js} +2 -2
- package/dist/{cli-mmhj8vd7.js → cli-c668vvcf.js} +11 -2
- package/dist/{cli-sbwsxvtd.js → cli-d20qvpr2.js} +2 -2
- package/dist/{cli-c952c7ac.js → cli-e1595bgx.js} +3 -3
- package/dist/{cli-621ce7kw.js → cli-f12mr20z.js} +3 -3
- package/dist/{cli-dqygeeh5.js → cli-f1e0ptjj.js} +10 -1
- package/dist/{cli-xzfq4at3.js → cli-f4dbh7a5.js} +16 -12
- package/dist/{cli-ha9rmwgq.js → cli-fb8m699c.js} +2 -2
- package/dist/{cli-5bnsc0e1.js → cli-gsfk58nw.js} +5 -5
- package/dist/cli-gt4h8cxw.js +895 -0
- package/dist/{cli-nwyw3zhg.js → cli-gxee0bqa.js} +1 -1
- package/dist/{cli-25n3mv5d.js → cli-h5jeg46p.js} +6 -6
- package/dist/{cli-gn5af0x5.js → cli-he9gbdx0.js} +62 -12
- package/dist/{cli-gbfxp48k.js → cli-j0ppywdr.js} +42 -35
- package/dist/{cli-k4tjsdx9.js → cli-j3y0x2n4.js} +277 -199
- package/dist/{cli-7p4jxgtt.js → cli-j9bpmykh.js} +75 -27
- package/dist/{cli-dabehxhp.js → cli-kt907da6.js} +1 -1
- package/dist/{cli-wx2nj19m.js → cli-kv7sbc2c.js} +6 -6
- package/dist/{cli-abs8ndtr.js → cli-m30k9777.js} +26 -26
- package/dist/{cli-cz5nmdxt.js → cli-m5e802r7.js} +2 -2
- package/dist/{cli-0shx9j93.js → cli-pfk92eqz.js} +2 -2
- package/dist/{cli-xtrz6bzs.js → cli-ptfq202x.js} +5 -3
- package/dist/{cli-6n8axjv1.js → cli-qj442fws.js} +2 -2
- package/dist/{cli-c61mbdds.js → cli-rd5m70gj.js} +4 -4
- package/dist/{cli-eftzyh9y.js → cli-s09j9vp5.js} +2 -2
- package/dist/{cli-m4ecdxvz.js → cli-s0mgx214.js} +7 -7
- package/dist/{cli-wghjkr0e.js → cli-sgqm2582.js} +10 -7
- package/dist/{cli-2655k16q.js → cli-sjctjr48.js} +2 -2
- package/dist/{cli-nzfnt2gs.js → cli-tf1n0r0b.js} +1 -1
- package/dist/{cli-x0f2v69c.js → cli-twctnkng.js} +12 -7
- package/dist/{cli-j6rktc91.js → cli-v6shg7na.js} +1 -1
- package/dist/{cli-gx4rm0qx.js → cli-vz78s5wm.js} +1 -1
- package/dist/{cli-gwhjmh8g.js → cli-wqr7cea4.js} +5 -5
- package/dist/{cli-e42vss7b.js → cli-x37r7qwf.js} +16 -8
- package/dist/{cli-4b2z6n0m.js → cli-yd2nreqw.js} +17 -8
- package/dist/{cli-64mh9mf3.js → cli-ymjpkxgn.js} +69 -17
- package/dist/{cli-5kqnemen.js → cli-yvy48785.js} +1 -1
- package/dist/{cli-9j129brq.js → cli-yxbsmx56.js} +6 -6
- package/dist/cli.js +22 -20
- package/dist/{codex-adapter-wch12q99.js → codex-adapter-zk59x2zh.js} +7 -7
- package/dist/{codex-hook-brpnycn5.js → codex-hook-xyjhvxwd.js} +1 -1
- package/dist/{codex-login-rn7c5gxt.js → codex-login-8cg0vhf2.js} +1 -1
- package/dist/{codex-session-runner-41pfcr95.js → codex-session-runner-kh6s4j3n.js} +8 -8
- package/dist/{commands-9849dkj6.js → commands-68et1qv2.js} +2 -2
- package/dist/{controller-ja0sd95p.js → controller-fyrbnzg4.js} +4 -4
- package/dist/{controllers-connect-xp05dj6x.js → controllers-connect-nep9h2xv.js} +23 -23
- package/dist/{cursor-adapter-623qxqew.js → cursor-adapter-yss3pg7t.js} +2 -2
- package/dist/{db-w759qmx0.js → db-28gjyvxj.js} +4 -2
- package/dist/{db-47vj40dy.js → db-8ftwvzba.js} +3 -3
- package/dist/{devin-adapter-4ycy4vrf.js → devin-adapter-byen2cxt.js} +1 -1
- package/dist/{dispatcher-7b8e4z2j.js → dispatcher-hayexmkr.js} +20 -20
- package/dist/{docker-s84hjs91.js → docker-fdzyewpz.js} +2 -2
- package/dist/{dsh-adapter-2ezw3xea.js → dsh-adapter-46wawff9.js} +2 -2
- package/dist/{e2b-9gkdhm3c.js → e2b-222hsajc.js} +2 -2
- package/dist/{e2b-cjtf8k1z.js → e2b-fn3zacvt.js} +2 -2
- package/dist/{easter-egg-3d-e4qv8dxj.js → easter-egg-3d-8d1e0h4m.js} +1 -1
- package/dist/{event-bus-3z78ep5n.js → event-bus-pghg8hqy.js} +1 -1
- package/dist/{execute-0xpz8950.js → execute-cjrfxfnm.js} +1 -1
- package/dist/{external-channel-e2s028da.js → external-channel-xbmxcg09.js} +2 -2
- package/dist/{grok-adapter-ys7gaqee.js → grok-adapter-ag4wks2a.js} +10 -10
- package/dist/handlers-tzmevqb5.js +41 -0
- package/dist/{heartbeat-w3mntghj.js → heartbeat-psfvcgwp.js} +23 -23
- package/dist/{hook-g7kvv6x9.js → hook-8pz04697.js} +6 -6
- package/dist/{hook-3jjywnpb.js → hook-cyq4mryn.js} +8 -8
- package/dist/{http-tkp7d4kb.js → http-haj1nd6k.js} +921 -169
- package/dist/{index-q7m26kvs.js → index-jwt2bj6f.js} +265 -97
- package/dist/{index-3n8m9ea2.js → index-q52f47pe.js} +1 -1
- package/dist/{index-31ceyf42.js → index-syvhnvtw.js} +1 -1
- package/dist/index-y1ajx04a.js +43 -0
- package/dist/{index-1ef1myq2.js → index-z5h22pes.js} +20 -20
- package/dist/{index-xdaahthb.js → index-zyq8ct52.js} +20 -20
- package/dist/{keepalive-v4ta8wgg.js → keepalive-xdvsamvj.js} +4 -4
- package/dist/lead-hqg57kdp.js +79 -0
- package/dist/{maintenance-84n1ex21.js → maintenance-4y2xzh3a.js} +1 -1
- package/dist/{oauth-refresh-sweep-vjnnandw.js → oauth-refresh-sweep-jd4r7zbs.js} +9 -4
- package/dist/{onboard-sfmpe4np.js → onboard-18447q9q.js} +6 -6
- package/dist/{opencode-adapter-jmpst4q4.js → opencode-adapter-26b2frdf.js} +7 -7
- package/dist/{otel-impl-v6cc0zve.js → otel-impl-f9tgr8yw.js} +2 -2
- package/dist/{pi-mono-adapter-fk8fkcf6.js → pi-mono-adapter-qn6qbga1.js} +38 -17
- package/dist/{pricing-refresh-fsk1e1zc.js → pricing-refresh-dw2tgb53.js} +3 -3
- package/dist/{rbac-roles-prmkdnkw.js → rbac-roles-aygm2760.js} +2 -2
- package/dist/{rbac-roles-zxmxqa39.js → rbac-roles-s4nwj2m3.js} +1 -1
- package/dist/render-v2-yfvdfr0x.js +16 -0
- package/dist/{resume-frdtgfa0.js → resume-1bmvjbf3.js} +9 -9
- package/dist/{runtime-bt5pkpm1.js → runtime-f7tpzedy.js} +1 -1
- package/dist/{session-access-fpez4y5q.js → session-access-r5garej6.js} +4 -4
- package/dist/session-source-backfill-424wzv0r.js +110 -0
- package/dist/{setup-mq6m3m8q.js → setup-8tygvxkq.js} +1 -1
- package/dist/{virtual-modules-mnfbh5mr.js → virtual-modules-xsw323b3.js} +2 -2
- package/dist/{work-objects-kfahhjsq.js → work-objects-ggnghpgf.js} +23 -23
- package/dist/worker-sqjd1nqf.js +79 -0
- package/dist/{x-pbpezr0s.js → x-wxrzvzx8.js} +2 -2
- package/openapi.json +1324 -14
- package/package.json +5 -3
- package/src/assets/source-key.ts +95 -0
- package/src/be/automation-preflight.ts +2 -0
- package/src/be/db/api-keys.ts +89 -0
- package/src/be/db/session-labels.ts +28 -0
- package/src/be/db/session-moves.ts +5 -6
- package/src/be/db/session-tree.ts +153 -14
- package/src/be/db/tasks/read.ts +11 -0
- package/src/be/db/tasks/write.ts +6 -1
- package/src/be/db/workflow-runs.ts +219 -6
- package/src/be/db-retention.ts +61 -6
- package/src/be/db.ts +135 -132
- package/src/be/memory/providers/openai-embedding.ts +5 -1
- package/src/be/memory/task-learning.ts +155 -0
- package/src/be/migrations/244_api_key_validation.sql +4 -0
- package/src/be/migrations/245_script_executor.sql +3 -0
- package/src/be/oauth-refresh-sweep.ts +2 -1
- package/src/be/onboarding.ts +4 -0
- package/src/be/scripts/boot-reembed.ts +2 -0
- package/src/be/scripts/db.ts +14 -4
- package/src/be/scripts/embeddings.ts +2 -0
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +10 -4
- package/src/be/seed-skills/index.ts +7 -0
- package/src/be/session-source-backfill.ts +163 -0
- package/src/be/swarm-config-guard.ts +1 -0
- package/src/comb/review-batch.ts +28 -1
- package/src/comb/templates.ts +7 -2
- package/src/commands/claude-managed-setup.ts +7 -1
- package/src/commands/credential-refresh.ts +76 -1
- package/src/commands/credential-wait.ts +2 -2
- package/src/commands/onboard/compose-generator.ts +5 -3
- package/src/commands/provider-credentials.ts +212 -171
- package/src/commands/runner.ts +25 -4
- package/src/extensions/apply-task-create.ts +8 -1
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +5 -0
- package/src/heartbeat/heartbeat.ts +14 -1
- package/src/heartbeat/script-runner-probe.ts +47 -0
- package/src/http/all-routes.ts +2 -0
- package/src/http/api-keys.ts +77 -9
- package/src/http/assets.ts +15 -0
- package/src/http/codex-oauth-accounts.ts +191 -0
- package/src/http/comb.ts +15 -2
- package/src/http/config.ts +1 -1
- package/src/http/core.ts +6 -0
- package/src/http/fleet-benchmark.ts +5 -2
- package/src/http/idempotency-key.ts +1 -1
- package/src/http/index.ts +14 -3
- package/src/http/integrations.ts +5 -1
- package/src/http/kv.ts +8 -3
- package/src/http/onboarding.ts +6 -1
- package/src/http/pages-public.ts +38 -5
- package/src/http/pool-keys.ts +354 -0
- package/src/http/scripts.ts +27 -0
- package/src/http/sessions.ts +37 -12
- package/src/http/stats.ts +1 -0
- package/src/http/status.ts +26 -12
- package/src/http/tasks.ts +3 -0
- package/src/http/used-by.ts +7 -2
- package/src/http/workflows.ts +88 -9
- package/src/http/x.ts +5 -0
- package/src/integrations/chat-sdk/inbound.ts +27 -0
- package/src/kv-reserved-namespaces.ts +19 -0
- package/src/prompts/base-prompt.ts +21 -1
- package/src/prompts/session-templates.ts +17 -3
- package/src/providers/acp-targets.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +5 -1
- package/src/providers/claude-managed-adapter.ts +16 -9
- package/src/providers/codex-adapter.ts +71 -11
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/pi-mono-adapter.ts +41 -11
- package/src/scheduler/scheduler.ts +5 -3
- package/src/scripts-runtime/eval-harness.ts +8 -1
- package/src/scripts-runtime/executors/native.ts +22 -16
- package/src/scripts-runtime/executors/quickjs-prelude.ts +103 -1
- package/src/scripts-runtime/executors/quickjs-runner.ts +2 -1
- package/src/scripts-runtime/executors/quickjs.ts +7 -0
- package/src/scripts-runtime/executors/registry.ts +32 -0
- package/src/scripts-runtime/executors/types.ts +7 -0
- package/src/scripts-runtime/host-validated-args.ts +133 -0
- package/src/scripts-runtime/loader.ts +30 -3
- package/src/scripts-runtime/swarm-sdk.ts +16 -3
- package/src/scripts-runtime/types/stdlib.d.ts +10 -2
- package/src/scripts-runtime/types/swarm-extension.d.ts +17 -8
- package/src/scripts-runtime/types/swarm-sdk.d.ts +10 -2
- package/src/slack/assistant.ts +7 -0
- package/src/slack/channel-labels.ts +74 -0
- package/src/slack/handlers.ts +8 -0
- package/src/slack/inbound-files.ts +5 -2
- package/src/slack/thread-buffer.ts +4 -0
- package/src/tasks/sibling-awareness.ts +12 -3
- package/src/telemetry-context.ts +5 -6
- package/src/telemetry-identity.ts +3 -3
- package/src/tests/api-key-status-by-suffix.test.ts +242 -0
- package/src/tests/api-keys-validation.test.ts +170 -0
- package/src/tests/base-prompt.test.ts +70 -2
- package/src/tests/claude-managed-adapter.test.ts +46 -0
- package/src/tests/claude-routes-e2e.test.ts +7 -2
- package/src/tests/codex-credential-pools.test.ts +120 -0
- package/src/tests/codex-gateway-route.test.ts +165 -0
- package/src/tests/codex-oauth-accounts.test.ts +357 -0
- package/src/tests/comb-review-batch.test.ts +63 -2
- package/src/tests/community-linear-delivery-loop.test.ts +2099 -0
- package/src/tests/config-pool-keys.test.ts +533 -0
- package/src/tests/credential-check.test.ts +294 -4
- package/src/tests/credential-refresh.test.ts +172 -1
- package/src/tests/db-retention.test.ts +9 -3
- package/src/tests/db-task-read-contract.test.ts +1 -0
- package/src/tests/db-task-write-contract.test.ts +1 -3
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/docs-index.test.ts +135 -0
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/extensions-pre-task.test.ts +53 -1
- package/src/tests/fetch-resolved-env.test.ts +16 -2
- package/src/tests/fixtures/extensions/record-task-create/hooks.ts +9 -0
- package/src/tests/fixtures/extensions/record-task-create/manifest.json +7 -0
- package/src/tests/fleet-benchmark.test.ts +8 -0
- package/src/tests/get-workflow-run-tool.test.ts +98 -0
- package/src/tests/heartbeat-checklist.test.ts +89 -0
- package/src/tests/heartbeat-script-runner-probe.test.ts +83 -0
- package/src/tests/integrations-http.test.ts +32 -2
- package/src/tests/internal-ai/complete-structured.test.ts +37 -1
- package/src/tests/internal-ai/credentials.test.ts +23 -0
- package/src/tests/kv-http.test.ts +32 -0
- package/src/tests/kv-tool.test.ts +25 -0
- package/src/tests/multi-runtime-registration.test.ts +12 -12
- package/src/tests/oauth-refresh-sweep.test.ts +34 -1
- package/src/tests/onboard-compose.test.ts +20 -0
- package/src/tests/onboarding.test.ts +108 -1
- package/src/tests/openai-embedding-credentials.test.ts +35 -0
- package/src/tests/opencode-adapter.test.ts +2 -1
- package/src/tests/openrouter-attribution-call-sites.test.ts +2 -2
- package/src/tests/org-website.test.ts +36 -0
- package/src/tests/pages-frame-ancestors.test.ts +162 -0
- package/src/tests/pi-codemode.test.ts +2 -1
- package/src/tests/pi-mono-adapter.test.ts +54 -0
- package/src/tests/pi-native-mcp.test.ts +13 -1
- package/src/tests/pi-tool-exposure.test.ts +8 -8
- package/src/tests/probe-tool-schema-tokens.test.ts +144 -0
- package/src/tests/prompt-template-session.test.ts +4 -3
- package/src/tests/provider-key-probes.test.ts +181 -0
- package/src/tests/rbac-e2e-helpers.test.ts +88 -1
- package/src/tests/rbac-e2e-helpers.ts +36 -11
- package/src/tests/request-composition-derive.test.ts +329 -0
- package/src/tests/script-connections.test.ts +4 -0
- package/src/tests/script-executor-conformance.test.ts +36 -1
- package/src/tests/script-executor-quickjs-pool.test.ts +50 -0
- package/src/tests/script-executor-quickjs.test.ts +140 -0
- package/src/tests/script-host-validated-args-native.test.ts +196 -0
- package/src/tests/script-per-script-executor.test.ts +415 -0
- package/src/tests/script-runs-retention.test.ts +212 -0
- package/src/tests/scripts-external-api.test.ts +45 -0
- package/src/tests/sdk-allowlist.test.ts +42 -2
- package/src/tests/self-improvement.test.ts +4 -4
- package/src/tests/session-source-backfill.test.ts +429 -0
- package/src/tests/session-source-keys.test.ts +236 -0
- package/src/tests/session-source-labels.test.ts +419 -0
- package/src/tests/sessions-detail-batch.test.ts +2 -0
- package/src/tests/sessions-move.test.ts +131 -0
- package/src/tests/sessions-tree.test.ts +299 -2
- package/src/tests/slack-inbound-files.test.ts +103 -23
- package/src/tests/status.test.ts +101 -18
- package/src/tests/store-progress-learning.test.ts +288 -0
- package/src/tests/tasks-workflow-run-filter.test.ts +146 -0
- package/src/tests/test-net.ts +31 -0
- package/src/tests/transcription.test.ts +8 -0
- package/src/tests/ui-logs-parser.test.ts +180 -0
- package/src/tests/used-by-route.test.ts +11 -0
- package/src/tests/workflow-cascade-cancel.test.ts +172 -0
- package/src/tests/workflow-engine-v2.test.ts +116 -1
- package/src/tests/workflow-http-v2.test.ts +131 -0
- package/src/tests/workflow-mcp-trigger-schema.test.ts +209 -0
- package/src/tests/workflow-run-finished-event.test.ts +263 -0
- package/src/tests/workflow-step-order.test.ts +92 -0
- package/src/tests/workflow-sub-workflow.test.ts +30 -0
- package/src/tests/workflow-swarm-script.test.ts +34 -0
- package/src/tools/get-tasks.ts +8 -0
- package/src/tools/kv/kv-read-auth.ts +4 -2
- package/src/tools/script-common.ts +1 -0
- package/src/tools/script-run.ts +7 -0
- package/src/tools/script-upsert.ts +7 -0
- package/src/tools/store-progress.ts +67 -1
- package/src/tools/task-action.ts +1 -1
- package/src/tools/workflows/get-workflow-run.ts +14 -4
- package/src/tools/workflows/trigger-workflow.ts +104 -10
- package/src/types.ts +36 -1
- package/src/utils/company-profile.ts +51 -1
- package/src/utils/credentials.ts +10 -4
- package/src/utils/internal-ai/complete-structured.ts +5 -0
- package/src/utils/internal-ai/credentials.ts +4 -3
- package/src/utils/provider-key-probes.ts +328 -0
- package/src/utils/transcription.ts +4 -1
- package/src/workflows/engine.ts +18 -16
- package/src/workflows/executors/sub-workflow.ts +8 -1
- package/src/workflows/executors/swarm-script.ts +5 -0
- package/src/workflows/foreach-driver.ts +5 -11
- package/src/workflows/node-timeout.ts +30 -0
- package/templates/ai-toolbox.manifest.json +2 -2
- package/templates/community/linear-delivery-loop/PLAYBOOK.md +323 -0
- package/templates/community/linear-delivery-loop/README.md +38 -0
- package/templates/community/linear-delivery-loop/config.example.json +31 -0
- package/templates/community/linear-delivery-loop/lead-prompt.md +34 -0
- package/templates/community/linear-delivery-loop/schedule.json +10 -0
- package/templates/community/linear-delivery-loop/scripts/linear-delivery-setup.ts +148 -0
- package/templates/community/linear-delivery-loop/scripts/linear-delivery-tick.ts +1781 -0
- package/templates/skills/researching/content.md +2 -0
- package/templates/skills/swarm-docs/config.json +14 -0
- package/templates/skills/swarm-docs/content.md +144 -0
- package/templates/skills/swarm-scripts/SKILL.md +1 -0
- package/templates/skills/swarm-scripts/content.md +1 -0
- package/dist/cli-7421jzsw.js +0 -84
- package/dist/cli-e45e4m6b.js +0 -413
- package/dist/cli-zw88zjba.js +0 -307
- package/dist/handlers-wy1dr6ja.js +0 -41
- package/dist/index-nmm79qgr.js +0 -43
- package/dist/lead-sawnyqxk.js +0 -79
- package/dist/render-v2-pjwxvnkw.js +0 -12
- package/dist/worker-v5e5rxj3.js +0 -79
package/src/http/status.ts
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
getDbClient,
|
|
30
30
|
getInstanceActivity,
|
|
31
31
|
getLiveAgentCounts,
|
|
32
|
+
getReadyAgentCounts,
|
|
32
33
|
hasFirstCompletedTask,
|
|
33
34
|
listAgentsWithCredStatusByProvider,
|
|
34
35
|
NOT_EXTENSION_AGENT_SQL,
|
|
@@ -121,6 +122,12 @@ export type StatusIdentity = z.infer<typeof StatusIdentitySchema>;
|
|
|
121
122
|
export const StatusActivitySchema = z.object({
|
|
122
123
|
agents_online: z.number().int().nonnegative(),
|
|
123
124
|
leads_online: z.number().int().nonnegative(),
|
|
125
|
+
/**
|
|
126
|
+
* Leads that can take work now (status `idle` or `busy`). Unlike
|
|
127
|
+
* `leads_online`, this does not depend on a recent heartbeat: an idle lead
|
|
128
|
+
* stops updating its activity time.
|
|
129
|
+
*/
|
|
130
|
+
leads_ready: z.number().int().nonnegative(),
|
|
124
131
|
recent_tasks_count: z.number().int().nonnegative(),
|
|
125
132
|
});
|
|
126
133
|
export type StatusActivity = z.infer<typeof StatusActivitySchema>;
|
|
@@ -194,12 +201,13 @@ export type AutomationStatus = z.infer<typeof AutomationStatusSchema>;
|
|
|
194
201
|
/**
|
|
195
202
|
* Phase 2: Aggregate health derived from setup milestones.
|
|
196
203
|
*
|
|
197
|
-
* - `broken
|
|
198
|
-
* - `degraded
|
|
199
|
-
*
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
204
|
+
* - `broken`: harness or workers blocking (creds missing, no live workers ever).
|
|
205
|
+
* - `degraded`: no lead can take work (none is `idle` or `busy`), OR at
|
|
206
|
+
* least one optional integration `unverified`/`configured` while another
|
|
207
|
+
* is configured, OR harness creds present but the latest live test failed
|
|
208
|
+
* or never ran (`configured`).
|
|
209
|
+
* - `ok`: harness + workers `verified`, a lead can take work, and no
|
|
210
|
+
* integration left in `configured` state.
|
|
203
211
|
*/
|
|
204
212
|
export const StatusHealthSchema = z.enum(["ok", "degraded", "broken"]);
|
|
205
213
|
export type StatusHealth = z.infer<typeof StatusHealthSchema>;
|
|
@@ -692,19 +700,23 @@ export async function buildSetup(
|
|
|
692
700
|
* Decision matrix:
|
|
693
701
|
* - Harness `unverified` (no creds at all) → `broken` — the swarm cannot run a task.
|
|
694
702
|
* - Workers `unverified` (no agents ever) → `broken` — same reason.
|
|
703
|
+
* - No lead can take work (`readyLeads` is 0) → `degraded`. Tasks wait until a lead is online.
|
|
695
704
|
* - Harness `configured` (creds present, never live-tested) → `degraded`.
|
|
696
705
|
* - Any of {slack, github, linear, jira} `configured` (i.e. half-set-up) → `degraded`.
|
|
697
706
|
* - Otherwise → `ok`.
|
|
698
707
|
*
|
|
699
708
|
* Notes:
|
|
709
|
+
* - `readyLeads` counts leads with status `idle` or `busy`
|
|
710
|
+
* (`getReadyAgentCounts`). It does not use the heartbeat time: an agent
|
|
711
|
+
* updates `lastActivityAt` only while a session runs, so an idle, healthy
|
|
712
|
+
* lead looks stale.
|
|
700
713
|
* - Worker `configured` (fleet exists but missed recent heartbeats) does NOT
|
|
701
|
-
* degrade the rollup
|
|
702
|
-
* /agents page and the dashboard canvas — not a setup health signal.
|
|
714
|
+
* degrade the rollup on its own, for the same reason.
|
|
703
715
|
* - Integrations in `unverified` are NOT degrading on their own — most
|
|
704
716
|
* deployments don't connect every integration. They only nudge the rollup if
|
|
705
717
|
* paired with another integration in `configured` (the brainstorm contract).
|
|
706
718
|
*/
|
|
707
|
-
export function computeHealth(setup: SetupMilestone[]): StatusHealth {
|
|
719
|
+
export function computeHealth(setup: SetupMilestone[], readyLeads: number): StatusHealth {
|
|
708
720
|
const byId = new Map(setup.map((m) => [m.id, m] as const));
|
|
709
721
|
const harness = byId.get("harness");
|
|
710
722
|
const workers = byId.get("workers");
|
|
@@ -714,6 +726,7 @@ export function computeHealth(setup: SetupMilestone[]): StatusHealth {
|
|
|
714
726
|
if (!workers || workers.state === "unverified") return "broken";
|
|
715
727
|
|
|
716
728
|
// `degraded` rules.
|
|
729
|
+
if (readyLeads === 0) return "degraded";
|
|
717
730
|
if (harness.state === "configured") return "degraded";
|
|
718
731
|
|
|
719
732
|
for (const id of ["slack", "github", "linear", "jira"] as const) {
|
|
@@ -740,12 +753,13 @@ export async function buildStatusPayload(): Promise<StatusResponse> {
|
|
|
740
753
|
.map((automation) => toStatus(preflightAutomation(automation, automationSetup)))
|
|
741
754
|
.sort((a, b) => a.name.localeCompare(b.name) || a.kind.localeCompare(b.kind));
|
|
742
755
|
const activity = await getInstanceActivity();
|
|
756
|
+
const readyLeads = (await getReadyAgentCounts()).leads;
|
|
743
757
|
const instance = await getInstanceFeedbackSignals();
|
|
744
758
|
return {
|
|
745
759
|
runtime_pools: { enabled: isRuntimePoolsEnabled(), supervisor: runtimeSupervisorStatus() },
|
|
746
760
|
identity: buildIdentity(),
|
|
747
761
|
setup,
|
|
748
|
-
activity,
|
|
762
|
+
activity: { ...activity, leads_ready: readyLeads },
|
|
749
763
|
agent_fs: {
|
|
750
764
|
configured: !!process.env.AGENT_FS_API_URL,
|
|
751
765
|
base_url: process.env.AGENT_FS_API_URL ?? null,
|
|
@@ -753,7 +767,7 @@ export async function buildStatusPayload(): Promise<StatusResponse> {
|
|
|
753
767
|
comb: getCombStatus(await combServiceUserId),
|
|
754
768
|
},
|
|
755
769
|
automations,
|
|
756
|
-
health: computeHealth(setup),
|
|
770
|
+
health: computeHealth(setup, readyLeads),
|
|
757
771
|
telemetry: { enabled: isTelemetryEnabled() },
|
|
758
772
|
instance,
|
|
759
773
|
};
|
|
@@ -797,7 +811,7 @@ const getStatus = route({
|
|
|
797
811
|
pattern: ["status"],
|
|
798
812
|
summary: "Identity + setup readiness + live activity for the swarm dashboard",
|
|
799
813
|
description:
|
|
800
|
-
"Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; setup milestones each emit `unverified | configured | verified`; automations report `running | needs_setup` from the same runtime preflight used at dispatch; activity counts agents alive in the last 5 min and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set, plus the Comb settings (COMB_ENABLED, the browser-facing agent-fs URL, the shared org and drive ids, and the agent-fs user id of the swarm service account); telemetry reports the effective ANONYMIZED_TELEMETRY opt-out state.",
|
|
814
|
+
"Single source of truth consumed by the UI home page. Identity comes from SWARM_* envs; setup milestones each emit `unverified | configured | verified`; automations report `running | needs_setup` from the same runtime preflight used at dispatch; activity counts agents alive in the last 5 min, leads that can take work (status idle or busy), and tasks created in the last 24h; agent_fs reports whether AGENT_FS_API_URL is set, plus the Comb settings (COMB_ENABLED, the browser-facing agent-fs URL, the shared org and drive ids, and the agent-fs user id of the swarm service account); telemetry reports the effective ANONYMIZED_TELEMETRY opt-out state.",
|
|
801
815
|
tags: ["Status"],
|
|
802
816
|
responses: {
|
|
803
817
|
200: { description: "Status payload", schema: StatusResponseSchema },
|
package/src/http/tasks.ts
CHANGED
|
@@ -227,6 +227,8 @@ const listTasks = route({
|
|
|
227
227
|
status: z.string().optional(),
|
|
228
228
|
agentId: z.string().optional(),
|
|
229
229
|
scheduleId: z.string().optional(),
|
|
230
|
+
/** Only tasks of this workflow run (indexed; independent of fleet size). */
|
|
231
|
+
workflowRunId: z.string().uuid().optional(),
|
|
230
232
|
key: AssetKeySchema.optional(),
|
|
231
233
|
keyPrefix: AssetKeySchema.optional(),
|
|
232
234
|
search: z.string().optional(),
|
|
@@ -976,6 +978,7 @@ export async function handleTasks(
|
|
|
976
978
|
status,
|
|
977
979
|
agentId: parsed.query.agentId || undefined,
|
|
978
980
|
scheduleId: parsed.query.scheduleId || undefined,
|
|
981
|
+
workflowRunId: parsed.query.workflowRunId,
|
|
979
982
|
key: parsed.query.key,
|
|
980
983
|
keyPrefix: parsed.query.keyPrefix,
|
|
981
984
|
search: parsed.query.search || undefined,
|
package/src/http/used-by.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { IncomingMessage, ServerResponse } from "node:http";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { getDbClient, upsertSwarmConfig } from "../be/db";
|
|
4
4
|
import { isTelemetryEnabled, trackRelayed } from "../telemetry";
|
|
5
|
-
import { USER_FUNCTIONS } from "../utils/company-profile";
|
|
5
|
+
import { reportedUserFunction, USER_FUNCTIONS } from "../utils/company-profile";
|
|
6
6
|
import { orgIdentityStatus } from "../utils/org-identity";
|
|
7
7
|
import { normalizeOrgWebsite, TELEMETRY_PROXY_ORIGIN } from "../utils/org-website";
|
|
8
8
|
import { ensureConfigAdmin } from "./config";
|
|
@@ -129,7 +129,12 @@ export async function handleUsedBy(
|
|
|
129
129
|
...(orgDomain ? { org_domain: orgDomain } : {}),
|
|
130
130
|
granted,
|
|
131
131
|
...(granted
|
|
132
|
-
? {
|
|
132
|
+
? {
|
|
133
|
+
contact_email: contactEmail,
|
|
134
|
+
// The proxy rejects a job function its catalog does not list yet.
|
|
135
|
+
contact_function: reportedUserFunction(contactFunction),
|
|
136
|
+
quote,
|
|
137
|
+
}
|
|
133
138
|
: {}),
|
|
134
139
|
changed_at: changedAt,
|
|
135
140
|
}),
|
package/src/http/workflows.ts
CHANGED
|
@@ -23,7 +23,14 @@ import {
|
|
|
23
23
|
type WorkflowIdempotencyClaim,
|
|
24
24
|
workflowRequestFingerprint,
|
|
25
25
|
} from "../be/db/workflow-idempotency";
|
|
26
|
-
import {
|
|
26
|
+
import {
|
|
27
|
+
getWorkflowRunParent,
|
|
28
|
+
getWorkflowRunStepsSlimByRunId,
|
|
29
|
+
getWorkflowRunSummary,
|
|
30
|
+
getWorkflowRunTree,
|
|
31
|
+
WORKFLOW_RUN_TREE_MAX_DEPTH,
|
|
32
|
+
WorkflowRunTreeError,
|
|
33
|
+
} from "../be/db/workflow-runs";
|
|
27
34
|
import {
|
|
28
35
|
AssetKeySchema,
|
|
29
36
|
AutomationIntegrationIdSchema,
|
|
@@ -39,6 +46,7 @@ import {
|
|
|
39
46
|
WorkflowRunSchema,
|
|
40
47
|
WorkflowRunStatusSchema,
|
|
41
48
|
WorkflowRunStepSchema,
|
|
49
|
+
WorkflowRunStepSlimSchema,
|
|
42
50
|
WorkflowRunSummarySchema,
|
|
43
51
|
WorkflowSchema,
|
|
44
52
|
WorkflowVersionSchema,
|
|
@@ -109,6 +117,13 @@ const WorkflowRunPageSchema = z.object({
|
|
|
109
117
|
}),
|
|
110
118
|
});
|
|
111
119
|
|
|
120
|
+
/** Mirrors `WorkflowRunTree` in src/be/db/workflow-runs.ts. */
|
|
121
|
+
const WorkflowRunTreeSchema = z.object({
|
|
122
|
+
rootRunId: z.string(),
|
|
123
|
+
runs: z.array(WorkflowRunSummarySchema),
|
|
124
|
+
hasOpenWork: z.boolean(),
|
|
125
|
+
});
|
|
126
|
+
|
|
112
127
|
const SuccessResponseSchema = z.object({ success: z.literal(true) });
|
|
113
128
|
|
|
114
129
|
/** Adds `warnings` to a just-saved workflow when a node in it cannot run yet. */
|
|
@@ -292,6 +307,15 @@ const triggerWorkflowRoute = route({
|
|
|
292
307
|
"With an `Idempotency-Key`, a retry returns the accepted run's `runId` and `skipped` without starting, resuming or waiting for anything, even after the workflow was disabled or edited and whatever state the run is in now.",
|
|
293
308
|
tags: ["Workflows"],
|
|
294
309
|
params: z.object({ id: z.string() }),
|
|
310
|
+
query: z.object({
|
|
311
|
+
wait: z
|
|
312
|
+
.enum(["true", "false"])
|
|
313
|
+
.optional()
|
|
314
|
+
.describe(
|
|
315
|
+
"Default true: respond after the run's instant steps ran, when it finishes or parks at its first async step. " +
|
|
316
|
+
"false: respond as soon as the run is committed and walk it in the background.",
|
|
317
|
+
),
|
|
318
|
+
}),
|
|
295
319
|
headers: idempotencyKeyHeader("starts one run"),
|
|
296
320
|
responses: {
|
|
297
321
|
201: {
|
|
@@ -349,22 +373,50 @@ const getWorkflowRunRoute = route({
|
|
|
349
373
|
path: "/api/workflow-runs/{id}",
|
|
350
374
|
pattern: ["api", "workflow-runs", null],
|
|
351
375
|
summary: "Get a workflow run with steps (includes retry columns)",
|
|
376
|
+
description:
|
|
377
|
+
"Returns the run with its `context` and every step with its `input` by default. A step's `input` is a snapshot of the context when the step started, so in runs with loops (polling, `wait`, iterations) the response grows with steps × context size. Pass `fields=slim` to drop `run.context` and `steps[].input`; outputs, errors, diagnostics, retry fields and `parent` stay.",
|
|
352
378
|
tags: ["Workflows"],
|
|
353
379
|
params: z.object({ id: z.string() }),
|
|
380
|
+
query: z.object({
|
|
381
|
+
/** `slim` omits `run.context` and `steps[].input`; default is full. */
|
|
382
|
+
fields: z.enum(["full", "slim"]).optional(),
|
|
383
|
+
}),
|
|
354
384
|
responses: {
|
|
355
385
|
200: {
|
|
356
386
|
description: "Workflow run details with steps including retry info",
|
|
357
|
-
schema: z.
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
387
|
+
schema: z.union([
|
|
388
|
+
z.object({
|
|
389
|
+
run: WorkflowRunSchema,
|
|
390
|
+
steps: z.array(WorkflowRunStepSchema),
|
|
391
|
+
/** Set on a child run: the run and `sub-workflow` step that started it. */
|
|
392
|
+
parent: WorkflowRunParentSchema.optional(),
|
|
393
|
+
}),
|
|
394
|
+
z.object({
|
|
395
|
+
run: WorkflowRunSummarySchema,
|
|
396
|
+
steps: z.array(WorkflowRunStepSlimSchema),
|
|
397
|
+
parent: WorkflowRunParentSchema.optional(),
|
|
398
|
+
}),
|
|
399
|
+
]),
|
|
363
400
|
},
|
|
364
401
|
404: { description: "Run not found" },
|
|
365
402
|
},
|
|
366
403
|
});
|
|
367
404
|
|
|
405
|
+
const getWorkflowRunTreeRoute = route({
|
|
406
|
+
method: "get",
|
|
407
|
+
path: "/api/workflow-runs/{id}/tree",
|
|
408
|
+
pattern: ["api", "workflow-runs", null, "tree"],
|
|
409
|
+
summary: "Get a workflow run and every sub-workflow run below it",
|
|
410
|
+
description: `Follows stored parent links (\`parentStepId\` → step → run) through every attempt of every step, terminal runs included. \`runs\` holds list rows without \`context\`, root first. \`hasOpenWork\` is true while any run in the tree is live, has a pending, running or waiting step, a queued retry, an open task or a pending approval; after a cancel it turns false once the tree has settled. Both come from one read snapshot. The tree is not paginated. Links that form a cycle or nest deeper than ${WORKFLOW_RUN_TREE_MAX_DEPTH} levels return 409.`,
|
|
411
|
+
tags: ["Workflows"],
|
|
412
|
+
params: z.object({ id: z.string() }),
|
|
413
|
+
responses: {
|
|
414
|
+
200: { description: "The run tree", schema: WorkflowRunTreeSchema },
|
|
415
|
+
404: { description: "Run not found" },
|
|
416
|
+
409: { description: "Stored parent links form a cycle or nest past the depth bound" },
|
|
417
|
+
},
|
|
418
|
+
});
|
|
419
|
+
|
|
368
420
|
const retryWorkflowRunRoute = route({
|
|
369
421
|
method: "post",
|
|
370
422
|
path: "/api/workflow-runs/{id}/retry",
|
|
@@ -959,6 +1011,7 @@ export async function handleWorkflows(
|
|
|
959
1011
|
runId = await startWorkflowExecution(workflow, body, getExecutorRegistry(), {
|
|
960
1012
|
triggerType: "api",
|
|
961
1013
|
requestedByUserId: (await resolveHttpAuditUserId(req, myAgentId)) ?? undefined,
|
|
1014
|
+
detach: parsed.query.wait === "false",
|
|
962
1015
|
// Recorded in the run's own transaction, before the walk starts.
|
|
963
1016
|
accept: claim
|
|
964
1017
|
? async (run) => {
|
|
@@ -1014,18 +1067,44 @@ export async function handleWorkflows(
|
|
|
1014
1067
|
const parsed = await getWorkflowRunRoute.parse(req, res, pathSegments, queryParams);
|
|
1015
1068
|
if (!parsed) return true;
|
|
1016
1069
|
// Display view: the scrubbed context and step outputs, never replay state.
|
|
1017
|
-
|
|
1070
|
+
// `fields=slim` skips the context and step-input columns in SQL too.
|
|
1071
|
+
const slim = parsed.query.fields === "slim";
|
|
1072
|
+
const run = slim
|
|
1073
|
+
? await getWorkflowRunSummary(parsed.params.id)
|
|
1074
|
+
: await getWorkflowRun(parsed.params.id, "display");
|
|
1018
1075
|
if (!run) {
|
|
1019
1076
|
res.writeHead(404);
|
|
1020
1077
|
res.end();
|
|
1021
1078
|
return true;
|
|
1022
1079
|
}
|
|
1023
|
-
const steps =
|
|
1080
|
+
const steps = slim
|
|
1081
|
+
? await getWorkflowRunStepsSlimByRunId(parsed.params.id)
|
|
1082
|
+
: await getWorkflowRunStepsByRunId(parsed.params.id, "display");
|
|
1024
1083
|
const parent = run.parentStepId ? await getWorkflowRunParent(run.parentStepId) : null;
|
|
1025
1084
|
getWorkflowRunRoute.respond(res, 200, { run, steps, ...(parent ? { parent } : {}) });
|
|
1026
1085
|
return true;
|
|
1027
1086
|
}
|
|
1028
1087
|
|
|
1088
|
+
if (getWorkflowRunTreeRoute.match(req.method, pathSegments)) {
|
|
1089
|
+
const parsed = await getWorkflowRunTreeRoute.parse(req, res, pathSegments, queryParams);
|
|
1090
|
+
if (!parsed) return true;
|
|
1091
|
+
let tree: Awaited<ReturnType<typeof getWorkflowRunTree>>;
|
|
1092
|
+
try {
|
|
1093
|
+
tree = await getWorkflowRunTree(parsed.params.id);
|
|
1094
|
+
} catch (err) {
|
|
1095
|
+
if (!(err instanceof WorkflowRunTreeError)) throw err;
|
|
1096
|
+
jsonError(res, err.message, 409);
|
|
1097
|
+
return true;
|
|
1098
|
+
}
|
|
1099
|
+
if (!tree) {
|
|
1100
|
+
res.writeHead(404);
|
|
1101
|
+
res.end();
|
|
1102
|
+
return true;
|
|
1103
|
+
}
|
|
1104
|
+
getWorkflowRunTreeRoute.respond(res, 200, tree);
|
|
1105
|
+
return true;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1029
1108
|
if (retryWorkflowRunRoute.match(req.method, pathSegments)) {
|
|
1030
1109
|
const parsed = await retryWorkflowRunRoute.parse(req, res, pathSegments, queryParams);
|
|
1031
1110
|
if (!parsed) return true;
|
package/src/http/x.ts
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
MAX_SCRIPT_WALL_CLOCK_MS,
|
|
21
21
|
MIN_SCRIPT_WALL_CLOCK_MS,
|
|
22
22
|
} from "../scripts-runtime/executors/types";
|
|
23
|
+
import { HOST_VALIDATED_ARGS } from "../scripts-runtime/host-validated-args";
|
|
23
24
|
import type { RunScriptOutput } from "../scripts-runtime/loader";
|
|
24
25
|
import { scrubObject, scrubSecrets } from "../utils/secret-scrubber";
|
|
25
26
|
import { validateJsonSchema } from "../workflows/json-schema-validator";
|
|
@@ -214,6 +215,7 @@ export async function handleX(
|
|
|
214
215
|
// Scripts predating the schema column, or where extraction failed, have a
|
|
215
216
|
// null schema — we skip and let the in-subprocess Zod check surface as a
|
|
216
217
|
// runtime_error instead.
|
|
218
|
+
let hostValidatedArgs = false;
|
|
217
219
|
if (script.argsJsonSchema) {
|
|
218
220
|
try {
|
|
219
221
|
const schema = JSON.parse(script.argsJsonSchema) as Record<string, unknown>;
|
|
@@ -227,6 +229,7 @@ export async function handleX(
|
|
|
227
229
|
});
|
|
228
230
|
return true;
|
|
229
231
|
}
|
|
232
|
+
hostValidatedArgs = true;
|
|
230
233
|
} catch {
|
|
231
234
|
// Malformed stored schema — don't block execution on it.
|
|
232
235
|
}
|
|
@@ -245,7 +248,9 @@ export async function handleX(
|
|
|
245
248
|
const output = await runScriptWithRunCredential({
|
|
246
249
|
source: script.source,
|
|
247
250
|
args: args ?? null,
|
|
251
|
+
[HOST_VALIDATED_ARGS]: hostValidatedArgs,
|
|
248
252
|
fsMode: "none",
|
|
253
|
+
executor: script.executor,
|
|
249
254
|
agentId: endpoint.agentId,
|
|
250
255
|
// timeoutMs only raises the wall-clock limit (network-bound scripts can use
|
|
251
256
|
// the full window); the CPU ulimit (`ulimit -t`) is intentionally left at
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Adapter, Message, Thread } from "chat";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { sessionGroupKey } from "@/assets/key";
|
|
4
|
+
import { sessionSourceKey } from "@/assets/source-key";
|
|
3
5
|
import {
|
|
4
6
|
getAgentById,
|
|
5
7
|
getAgentWorkingOnContextKey,
|
|
@@ -9,6 +11,7 @@ import {
|
|
|
9
11
|
getLeadAgent,
|
|
10
12
|
isExtensionAgent,
|
|
11
13
|
} from "@/be/db";
|
|
14
|
+
import { rememberSessionLabel } from "@/be/db/session-labels";
|
|
12
15
|
import { resolveIdentity } from "@/be/identity";
|
|
13
16
|
import { recordUnmappedIdentity } from "@/be/unmapped-identities";
|
|
14
17
|
import { dispatchPre } from "@/extensions/dispatcher";
|
|
@@ -373,6 +376,20 @@ async function targetFromExtension(
|
|
|
373
376
|
* Runs outside any transaction, so `pre.chat.route` is dispatched here, after
|
|
374
377
|
* the flush and before any task exists.
|
|
375
378
|
*/
|
|
379
|
+
/**
|
|
380
|
+
* The source group label a Telegram or Discord message gives: the DM sender,
|
|
381
|
+
* or a Telegram group title. Slack labels come from the Slack lookup instead.
|
|
382
|
+
*/
|
|
383
|
+
function chatSourceLabel(adapter: string, item: ChatBufferedMessage): string | undefined {
|
|
384
|
+
if (adapter !== "telegram" && adapter !== "discord") return undefined;
|
|
385
|
+
const { facts } = item;
|
|
386
|
+
if (facts.chatType === "dm" || item.isDirectMessage)
|
|
387
|
+
return facts.from ? `DM · ${facts.from}` : undefined;
|
|
388
|
+
if (adapter === "telegram" && (facts.chatType === "group" || facts.chatType === "supergroup"))
|
|
389
|
+
return facts.title || undefined;
|
|
390
|
+
return undefined;
|
|
391
|
+
}
|
|
392
|
+
|
|
376
393
|
export async function flushChatThread(
|
|
377
394
|
threadId: string,
|
|
378
395
|
items: ChatBufferedMessage[],
|
|
@@ -538,6 +555,7 @@ export async function flushChatThread(
|
|
|
538
555
|
const latestActive = await getLatestActiveTaskByContextKey(contextKey, "chat");
|
|
539
556
|
const dependsOn = !immediate && latestActive ? [latestActive.id] : undefined;
|
|
540
557
|
let created = 0;
|
|
558
|
+
let sourceKey: string | null = null;
|
|
541
559
|
for (const match of target.matches) {
|
|
542
560
|
const options: CreateTaskOptions = {
|
|
543
561
|
agentId: match.agent?.id ?? null,
|
|
@@ -564,6 +582,7 @@ export async function flushChatThread(
|
|
|
564
582
|
};
|
|
565
583
|
try {
|
|
566
584
|
const { task, unattached } = await createChatTaskWithFiles(description, options, inbound);
|
|
585
|
+
sourceKey ??= sessionSourceKey(task);
|
|
567
586
|
created++;
|
|
568
587
|
console.log(
|
|
569
588
|
`[chat-sdk] ${threadId}: task ${task.id} for ${match.agent ? `agent ${match.agent.id}` : "no agent (queued)"} (${match.matchedText}, dependsOn: ${dependsOn?.join(", ") ?? "none"}${unattached.length ? `, ${unattached.length} file(s) not attached` : ""})`,
|
|
@@ -578,6 +597,14 @@ export async function flushChatThread(
|
|
|
578
597
|
}
|
|
579
598
|
}
|
|
580
599
|
}
|
|
600
|
+
const label = chatSourceLabel(adapter, requester);
|
|
601
|
+
if (sourceKey && label) {
|
|
602
|
+
// Every message refreshes the label, so a renamed group shows its new title.
|
|
603
|
+
// The error may echo the label, which can hold a person's name: do not log it.
|
|
604
|
+
await rememberSessionLabel(sessionGroupKey(sourceKey), label).catch(() => {
|
|
605
|
+
console.warn("[chat-sdk] Could not save a session source label");
|
|
606
|
+
});
|
|
607
|
+
}
|
|
581
608
|
if (created > 0) {
|
|
582
609
|
await rememberChatThreadRequester(threadId, requester.userId);
|
|
583
610
|
await subscribe(thread);
|
|
@@ -12,8 +12,20 @@ const RESERVED_FAMILIES = new Map([
|
|
|
12
12
|
["worker", "namespace is reserved for worker nudges"],
|
|
13
13
|
// Durable dedupe for SLACK_BLOCK_EXTERNAL_CHANNELS alerts (src/slack/external-channel.ts).
|
|
14
14
|
["slack-external-alert", "namespace is reserved for Slack external channel alerts"],
|
|
15
|
+
// Source group labels (src/be/db/session-labels.ts). Private, see PRIVATE_FAMILIES.
|
|
16
|
+
[
|
|
17
|
+
"session-labels",
|
|
18
|
+
"namespace is reserved for session source labels; GET /api/session-tree returns them",
|
|
19
|
+
],
|
|
15
20
|
]);
|
|
16
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Reserved families that generic KV callers may not read either. Their rows
|
|
24
|
+
* hold data that another route returns only to callers with access (a
|
|
25
|
+
* source label names a private channel or a DM partner).
|
|
26
|
+
*/
|
|
27
|
+
const PRIVATE_FAMILIES = new Set(["session-labels"]);
|
|
28
|
+
|
|
17
29
|
export function isReservedNamespace(namespace: string): boolean {
|
|
18
30
|
return reservedNamespaceError(namespace) !== null;
|
|
19
31
|
}
|
|
@@ -22,6 +34,13 @@ export function reservedNamespaceError(namespace: string): string | null {
|
|
|
22
34
|
return RESERVED_FAMILIES.get(namespace.split(":", 1)[0] ?? "") ?? null;
|
|
23
35
|
}
|
|
24
36
|
|
|
37
|
+
/** The error a generic KV read of a private family gets, or null. */
|
|
38
|
+
export function privateNamespaceError(namespace: string): string | null {
|
|
39
|
+
return PRIVATE_FAMILIES.has(namespace.split(":", 1)[0] ?? "")
|
|
40
|
+
? reservedNamespaceError(namespace)
|
|
41
|
+
: null;
|
|
42
|
+
}
|
|
43
|
+
|
|
25
44
|
export function reservedRoomKeyError(key: string): string | null {
|
|
26
45
|
return key.startsWith("_room/")
|
|
27
46
|
? "room snapshot keys are reserved; use the room endpoints"
|
|
@@ -271,12 +271,22 @@ export const getBasePrompt = async (args: BasePromptArgs): Promise<string> => {
|
|
|
271
271
|
renderToolsAndSkillsVars({
|
|
272
272
|
skillsSummary: args.skillsSummary,
|
|
273
273
|
mcpServers: args.mcpServers,
|
|
274
|
+
// pi defers installed MCP servers together with swarm tools.
|
|
275
|
+
mcpToolsDeferred: provider === "pi" && hasToolSearch,
|
|
274
276
|
nativeSkillDiscovery,
|
|
275
277
|
toolDiscovery: discoveryResult.text,
|
|
276
278
|
hasLocalEnv,
|
|
277
279
|
}),
|
|
278
280
|
);
|
|
279
281
|
prompt += toolsResult.text;
|
|
282
|
+
|
|
283
|
+
// Lead docs pointer: only when the lead has the `swarm-docs` skill. The
|
|
284
|
+
// skill list is unknown on claude-managed (the cloud sandbox owns skill
|
|
285
|
+
// delivery) and before the first skill load, so render it then.
|
|
286
|
+
if (role === "lead" && hasSwarmDocsSkill(args.skillsSummary)) {
|
|
287
|
+
const docsResult = await resolveTemplateAsync("system.agent.lead.docs", {});
|
|
288
|
+
prompt += docsResult.text;
|
|
289
|
+
}
|
|
280
290
|
}
|
|
281
291
|
|
|
282
292
|
// J. Agent notes (CLAUDE.md), only when it differs from the generated
|
|
@@ -339,6 +349,11 @@ export const getTaskContextPrompt = async (args: TaskContextPromptArgs): Promise
|
|
|
339
349
|
return prompt.replace(/\n{3,}/g, "\n\n").trim();
|
|
340
350
|
};
|
|
341
351
|
|
|
352
|
+
/** True when the skill list includes `swarm-docs`, or when the list is unknown. */
|
|
353
|
+
function hasSwarmDocsSkill(skills: { name: string }[] | undefined): boolean {
|
|
354
|
+
return skills === undefined || skills.some((skill) => skill.name === "swarm-docs");
|
|
355
|
+
}
|
|
356
|
+
|
|
342
357
|
/**
|
|
343
358
|
* Dynamic lines for `system.agent.tools_skills`. The static text lives in the
|
|
344
359
|
* template so operators can override or skip the section; only the lists that
|
|
@@ -347,6 +362,7 @@ export const getTaskContextPrompt = async (args: TaskContextPromptArgs): Promise
|
|
|
347
362
|
function renderToolsAndSkillsVars(input: {
|
|
348
363
|
skillsSummary?: { name: string; description: string }[];
|
|
349
364
|
mcpServers?: string[];
|
|
365
|
+
mcpToolsDeferred?: boolean;
|
|
350
366
|
nativeSkillDiscovery: boolean;
|
|
351
367
|
hasLocalEnv: boolean;
|
|
352
368
|
toolDiscovery: string;
|
|
@@ -382,7 +398,11 @@ function renderToolsAndSkillsVars(input: {
|
|
|
382
398
|
const servers = (input.mcpServers ?? []).filter((name) => name.trim().length > 0);
|
|
383
399
|
const mcpLine =
|
|
384
400
|
servers.length > 0
|
|
385
|
-
? `Connected MCP servers: ${servers.join(", ")}.
|
|
401
|
+
? `Connected MCP servers: ${servers.join(", ")}. ${
|
|
402
|
+
input.mcpToolsDeferred
|
|
403
|
+
? "Load their tools with your harness tool search."
|
|
404
|
+
: "Their tools are in your tool list."
|
|
405
|
+
}\n`
|
|
386
406
|
: "";
|
|
387
407
|
|
|
388
408
|
return {
|
|
@@ -15,8 +15,9 @@
|
|
|
15
15
|
* G secrets system.agent.secrets
|
|
16
16
|
*
|
|
17
17
|
* Deployment-gated blocks (E outputs, H slack, steering) and the per-agent and
|
|
18
|
-
* per-task sections (tools and skills, agent notes,
|
|
19
|
-
* profile) are appended by base-prompt.ts after the
|
|
18
|
+
* per-task sections (tools and skills, the lead docs pointer, agent notes,
|
|
19
|
+
* repository, requester profile) are appended by base-prompt.ts after the
|
|
20
|
+
* composite.
|
|
20
21
|
*
|
|
21
22
|
* Writing rules for every body: sentence case headings, one idea per sentence,
|
|
22
23
|
* active voice, plain words, no em dashes, a prohibition only where no positive
|
|
@@ -109,6 +110,19 @@ Your heartbeat runbook is the \`heartbeatMd\` profile field. Edit it with \`upda
|
|
|
109
110
|
category: "system",
|
|
110
111
|
});
|
|
111
112
|
|
|
113
|
+
// Lead docs pointer. base-prompt.ts appends it after the tools and skills
|
|
114
|
+
// section when the lead has the `swarm-docs` skill (or when the skill list is
|
|
115
|
+
// unknown). An operator override with an empty body switches it off.
|
|
116
|
+
registerTemplate({
|
|
117
|
+
eventType: "system.agent.lead.docs",
|
|
118
|
+
header: "",
|
|
119
|
+
defaultBody: `
|
|
120
|
+
Load the \`swarm-docs\` skill only when a person asks for something no skill, workflow, schedule or memory of yours covers, or asks where something is documented. Then follow its offer rules.
|
|
121
|
+
`,
|
|
122
|
+
variables: [],
|
|
123
|
+
category: "system",
|
|
124
|
+
});
|
|
125
|
+
|
|
112
126
|
// Remote providers (no MCP, no container): the task arrives in the session
|
|
113
127
|
// prompt and the final message is the output. No tools to name.
|
|
114
128
|
registerTemplate({
|
|
@@ -168,7 +182,7 @@ registerTemplate({
|
|
|
168
182
|
## Memory
|
|
169
183
|
|
|
170
184
|
Memories from past sessions are in your task message. Read them before you start. For a wider search, run the \`task-context-gathering\` script with the task ID and two to four queries.
|
|
171
|
-
|
|
185
|
+
When you learn something that would change how the next agent works (a fix, a pattern, a gotcha), pass it as \`learning\` on a \`store-progress\` call before the task ends. Completed task outputs are stored for you.
|
|
172
186
|
You MUST use the \`memory\` skill before you store, edit, or delete a memory.
|
|
173
187
|
`,
|
|
174
188
|
variables: [],
|
|
@@ -359,7 +359,7 @@ const copilotTargetProfile: AcpTargetProfile = {
|
|
|
359
359
|
},
|
|
360
360
|
};
|
|
361
361
|
|
|
362
|
-
/** Qwen Code's `--auth-type` choices (0.26.
|
|
362
|
+
/** Qwen Code's `--auth-type` choices (0.26.1). `qwen-oauth` needs a browser, so it is left out. */
|
|
363
363
|
const QWEN_AUTH_TYPES = ["openai", "openai-responses", "anthropic", "gemini", "vertex-ai"] as const;
|
|
364
364
|
|
|
365
365
|
// Qwen Code is a Gemini CLI fork: QWEN_SYSTEM_MD replaces its built-in prompt
|
|
@@ -45,7 +45,7 @@ import type {
|
|
|
45
45
|
* default; the image installs exactly this version and the per-task settings
|
|
46
46
|
* set `amp.updates.mode: "disabled"`. Bump it deliberately, with a live run.
|
|
47
47
|
*/
|
|
48
|
-
export const AMP_PACKAGE = "@ampcode/cli@0.0.
|
|
48
|
+
export const AMP_PACKAGE = "@ampcode/cli@0.0.1793025586-g9211b5";
|
|
49
49
|
|
|
50
50
|
/** MCP server name. Amp exposes its tools as `agent_swarm` / `store_progress` (dashes become underscores). */
|
|
51
51
|
const AMP_MCP_SERVER_NAME = "agent-swarm";
|
|
@@ -1445,7 +1445,11 @@ export class ClaudeAdapter implements ProviderAdapter {
|
|
|
1445
1445
|
// (headless) or block on the trust dialog (tmux), so seed trust for every session.
|
|
1446
1446
|
if (isEnvFlagEnabled("CLAUDE_TRUST_PRESEED", true, sourceEnv)) {
|
|
1447
1447
|
try {
|
|
1448
|
-
|
|
1448
|
+
// Seed the ~/.claude.json the CLI reads: its HOME comes from the session env.
|
|
1449
|
+
await preseedClaudeTrustDialog(
|
|
1450
|
+
await resolveClaudeTrustDirs(config.cwd),
|
|
1451
|
+
sourceEnv.HOME || undefined,
|
|
1452
|
+
);
|
|
1449
1453
|
} catch (err) {
|
|
1450
1454
|
console.warn(
|
|
1451
1455
|
`\x1b[33m[claude]\x1b[0m ${scrubSecrets(`Failed to pre-seed trust for ${config.cwd}: ${err}`)}`,
|
|
@@ -64,6 +64,7 @@ import {
|
|
|
64
64
|
computeContextUsedUnified,
|
|
65
65
|
getContextWindowSize,
|
|
66
66
|
} from "../utils/context-window";
|
|
67
|
+
import { selectCredential } from "../utils/credentials";
|
|
67
68
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
68
69
|
import { computeClaudeManagedCostUsd } from "./claude-managed-models";
|
|
69
70
|
import { getRuntimeFeePerHour } from "./claude-managed-pricing";
|
|
@@ -862,7 +863,11 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
|
|
|
862
863
|
);
|
|
863
864
|
}
|
|
864
865
|
|
|
865
|
-
this.apiKey =
|
|
866
|
+
this.apiKey = selectCredential(
|
|
867
|
+
process.env.ANTHROPIC_API_KEY as string,
|
|
868
|
+
undefined,
|
|
869
|
+
"ANTHROPIC_API_KEY",
|
|
870
|
+
).selected;
|
|
866
871
|
this.agentId = process.env.MANAGED_AGENT_ID as string;
|
|
867
872
|
this.environmentId = process.env.MANAGED_ENVIRONMENT_ID as string;
|
|
868
873
|
|
|
@@ -879,6 +884,14 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
|
|
|
879
884
|
}
|
|
880
885
|
|
|
881
886
|
async createSession(config: ProviderSessionConfig): Promise<ProviderSession> {
|
|
887
|
+
// Keep the runner's task selection instead of the container's pool.
|
|
888
|
+
const taskKey = config.env?.ANTHROPIC_API_KEY;
|
|
889
|
+
const client =
|
|
890
|
+
taskKey && this.client instanceof Anthropic
|
|
891
|
+
? this.client.withOptions({
|
|
892
|
+
apiKey: selectCredential(taskKey, undefined, "ANTHROPIC_API_KEY").selected,
|
|
893
|
+
})
|
|
894
|
+
: this.client;
|
|
882
895
|
// Native resume is deprecated. Follow-up continuity is delivered via the
|
|
883
896
|
// context preamble (see src/commands/context-preamble.ts). Any stray
|
|
884
897
|
// resumeSessionId is logged and ignored — we always create a fresh session.
|
|
@@ -942,16 +955,10 @@ export class ClaudeManagedAdapter implements ProviderAdapter {
|
|
|
942
955
|
if (vaultIds.length > 0) {
|
|
943
956
|
createParams.vault_ids = Array.from(new Set(vaultIds));
|
|
944
957
|
}
|
|
945
|
-
const created = await Promise.resolve(
|
|
958
|
+
const created = await Promise.resolve(client.beta.sessions.create(createParams));
|
|
946
959
|
const sessionId = created.id;
|
|
947
960
|
|
|
948
|
-
return new ClaudeManagedSession(
|
|
949
|
-
this.client,
|
|
950
|
-
sessionId,
|
|
951
|
-
config,
|
|
952
|
-
userMessageContent,
|
|
953
|
-
seenEventIds,
|
|
954
|
-
);
|
|
961
|
+
return new ClaudeManagedSession(client, sessionId, config, userMessageContent, seenEventIds);
|
|
955
962
|
}
|
|
956
963
|
|
|
957
964
|
/**
|