@desplega.ai/agent-swarm 2.7.4 → 2.7.6
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-bp91d37f.js +15 -0
- package/dist/{actions-gfrr9vb7.js → actions-yj0eeaqh.js} +19 -18
- package/dist/{amp-adapter-0s58gm46.js → amp-adapter-4pg9h34q.js} +3 -3
- package/dist/{app-stvq692g.js → app-909e97cr.js} +3 -3
- package/dist/{assistant-5s37fr9n.js → assistant-qdyb5fyy.js} +32 -23
- package/dist/{boot-reembed-yzy1841n.js → boot-reembed-fk0s9z18.js} +1 -1
- package/dist/{boot-reembed-cv82gz7y.js → boot-reembed-gs1rzrnh.js} +1 -1
- package/dist/{boot-scrub-sweep-8k4q95ap.js → boot-scrub-sweep-4qfd4kfx.js} +4 -4
- package/dist/{boot-seeds-ftt9htah.js → boot-seeds-yr00k13d.js} +4 -4
- package/dist/{boxd-515v1t8z.js → boxd-vdmfssd9.js} +5 -5
- package/dist/{claude-adapter-t00wrzeh.js → claude-adapter-qta1f1xn.js} +7 -7
- package/dist/{claude-managed-adapter-g6vmjccb.js → claude-managed-adapter-dvs2xw5n.js} +2 -2
- package/dist/{claude-managed-setup-afpa82f7.js → claude-managed-setup-sc6j4dm0.js} +3 -3
- package/dist/{claude-sdk-session-vj0c2azx.js → claude-sdk-session-zgrz6yvc.js} +9175 -9076
- package/dist/{cli-gjr2y2xk.js → cli-0agcv1v5.js} +4 -1
- package/dist/{cli-edmm9d9y.js → cli-0at8w34w.js} +7 -7
- package/dist/{cli-a81qevyg.js → cli-0qatpy8q.js} +20 -36
- package/dist/{cli-bcz074zx.js → cli-0yv5z2pg.js} +1 -1
- package/dist/{cli-a4btqqft.js → cli-1b7btd38.js} +1 -1
- package/dist/{cli-a2jw6ee5.js → cli-1p89xny0.js} +1 -1
- package/dist/{cli-v726afdm.js → cli-2pnswgh8.js} +1 -1
- package/dist/{cli-jkt52mgt.js → cli-386tyxxg.js} +2 -2
- package/dist/{cli-az0bpf8p.js → cli-3ypk9vk1.js} +3 -3
- package/dist/{cli-wk9md5px.js → cli-436532ck.js} +4 -4
- package/dist/{cli-7n5sbw0z.js → cli-4necwtsv.js} +5 -5
- package/dist/cli-54t00gt8.js +151 -0
- package/dist/{cli-655xm9ms.js → cli-583frbyr.js} +1 -1
- package/dist/{cli-4r12t6w6.js → cli-5c4hjzne.js} +101 -4
- package/dist/{cli-hf6zt5m6.js → cli-69szn7w7.js} +17 -1
- package/dist/{cli-rtk9g7av.js → cli-73jzwksr.js} +6 -2
- package/dist/{cli-jg0nfda6.js → cli-75gkpjvw.js} +52 -21
- package/dist/{cli-wcmnan2g.js → cli-89knwags.js} +5 -5
- package/dist/{cli-pwyevs29.js → cli-8bc1w0tw.js} +22 -21
- package/dist/{cli-t282jgab.js → cli-8snvgs5r.js} +41 -16
- package/dist/{cli-vqgnyh76.js → cli-98rw5dt5.js} +15 -3
- package/dist/{cli-9cctx1tn.js → cli-a22h291q.js} +1 -1
- package/dist/{cli-ycm6180s.js → cli-a7v854rf.js} +5 -3
- package/dist/{cli-98pke4vk.js → cli-ae7mrdf9.js} +2 -2
- package/dist/{cli-je8yeyc5.js → cli-bjb3z51z.js} +5 -5
- package/dist/{cli-mc97xy2s.js → cli-c60vetmm.js} +16 -4
- package/dist/{cli-j4kw3rsx.js → cli-cm5yqn35.js} +18 -0
- package/dist/{cli-wndv9p7g.js → cli-decfb6v8.js} +6 -6
- package/dist/{cli-h55y2bjc.js → cli-dhar9qay.js} +2 -2
- package/dist/{cli-8yy525ad.js → cli-drr5v6av.js} +2 -2
- package/dist/{cli-5gr1g711.js → cli-dxae2yg7.js} +2 -2
- package/dist/{cli-pe09p6dv.js → cli-e3r2neck.js} +8 -7
- package/dist/{cli-13jvmew3.js → cli-ekwks2vs.js} +7 -7
- package/dist/{cli-jg4p5t36.js → cli-es6va8jk.js} +121 -51
- package/dist/{cli-j4kt1mpb.js → cli-faxe6thg.js} +3 -3
- package/dist/{cli-tzrpv5sc.js → cli-ftyxyspd.js} +1 -1
- package/dist/cli-fw2w0kva.js +47 -0
- package/dist/{cli-2dfbv8qr.js → cli-fy6x31ps.js} +1 -0
- package/dist/{cli-aq58fk5m.js → cli-g83s9ewh.js} +7 -1
- package/dist/cli-gdhpcbhf.js +55 -0
- package/dist/{cli-82jg7fp9.js → cli-he5nxaa8.js} +1 -1
- package/dist/{cli-8veytvbh.js → cli-he9wchme.js} +1 -1
- package/dist/{cli-k76tgq03.js → cli-hgaazk69.js} +2 -2
- package/dist/{cli-d2pzqej1.js → cli-hr2e2fft.js} +741 -7
- package/dist/{cli-dae4sbgy.js → cli-jm2vfpfd.js} +2 -2
- package/dist/{cli-1s1dqn1j.js → cli-k2gzwsj2.js} +297 -140
- package/dist/{cli-b1afgtj3.js → cli-kqdg1bsb.js} +3 -3
- package/dist/cli-m2z8jagn.js +12078 -0
- package/dist/{cli-mvckssyq.js → cli-m48g6p95.js} +5 -5
- package/dist/{cli-bwty35gx.js → cli-mthwvjre.js} +1 -1
- package/dist/{cli-41z8xwj0.js → cli-nhrvpaj7.js} +34 -8
- package/dist/{cli-ahd90bwt.js → cli-nwj0ee2w.js} +6 -6
- package/dist/{cli-kvtc7aez.js → cli-p5gp8pcx.js} +44 -14
- package/dist/{cli-avgcz4ra.js → cli-pd7vagab.js} +436 -171
- package/dist/{cli-zn15c46z.js → cli-q0k1w5zd.js} +1 -1
- package/dist/{cli-bq2pcphn.js → cli-rmmmrjkd.js} +1 -1
- package/dist/{cli-2qpvmmkw.js → cli-s0qnd4wv.js} +1 -1
- package/dist/{cli-kg8hchyg.js → cli-sa02jsqt.js} +1 -1
- package/dist/{cli-1yekbyqm.js → cli-shpbx5ee.js} +283 -82
- package/dist/{cli-9y354g3j.js → cli-srye3vdt.js} +1 -1
- package/dist/{cli-byqfbnjw.js → cli-svj5090z.js} +9 -9
- package/dist/{cli-gcbdjt47.js → cli-vfym7wmz.js} +6 -6
- package/dist/{cli-v1yw3wha.js → cli-vvpx3gsx.js} +4 -4
- package/dist/{cli-a1fhj4n9.js → cli-w6dt9ged.js} +2 -2
- package/dist/{cli-1gm8jcyr.js → cli-waqbxg08.js} +5232 -68
- package/dist/{cli-5hjced2v.js → cli-wp9sp1qb.js} +6 -6
- package/dist/{cli-eny54typ.js → cli-wx3rhnm0.js} +1 -1
- package/dist/{cli-s0exq74r.js → cli-xbbndvjy.js} +3 -3
- package/dist/{cli-f255yaqn.js → cli-xds5f77d.js} +3 -3
- package/dist/{cli-0sbkss7h.js → cli-xnqgpshy.js} +2 -2
- package/dist/{cli-0fgr1w9b.js → cli-xnrwazav.js} +20 -3
- package/dist/{cli-gf5hbmdr.js → cli-yjdgea32.js} +3 -3
- package/dist/{cli-cq1pf336.js → cli-yn4kxs06.js} +124 -11
- package/dist/{cli-224epwwf.js → cli-yx4kfngt.js} +3 -3
- package/dist/{cli-eqx6k993.js → cli-yy3rhsdw.js} +47 -13
- package/dist/{cli-36g23z21.js → cli-zbbwez0r.js} +4 -4
- package/dist/{cli-ktmvb20s.js → cli-zm72anhg.js} +12 -12
- package/dist/cli.js +26 -25
- package/dist/{codex-adapter-g0gctw29.js → codex-adapter-ayd1fb6h.js} +5 -5
- package/dist/{codex-hook-vrzz2xhr.js → codex-hook-9efm2x1m.js} +1 -1
- package/dist/{codex-login-0gg46ygn.js → codex-login-y0pmff1c.js} +1 -1
- package/dist/{codex-session-runner-dr2cxe1c.js → codex-session-runner-jesa32xc.js} +6 -6
- package/dist/{commands-1p07cvff.js → commands-hanewgf2.js} +9 -3
- package/dist/{controller-z0s7sv6r.js → controller-dt1n3c1q.js} +9 -4
- package/dist/{controllers-connect-x9kvvhyk.js → controllers-connect-xx8x64n5.js} +22 -21
- package/dist/{cursor-adapter-m5b98pvk.js → cursor-adapter-9s4dwwdw.js} +2 -2
- package/dist/{db-capk2raj.js → db-3vttcbv4.js} +3 -3
- package/dist/{db-rsh04kh3.js → db-9dv0g1ab.js} +12 -4
- package/dist/{devin-adapter-yxm87fe9.js → devin-adapter-r9phbnc9.js} +1 -1
- package/dist/{devtools-82fzqra8.js → devtools-qxfgbsqz.js} +1 -1
- package/dist/{dispatcher-304q6fwa.js → dispatcher-tx9hd1sv.js} +18 -17
- package/dist/{docker-7rxt0rry.js → docker-c1a3gqmf.js} +91 -24
- package/dist/{dsh-adapter-btewem0y.js → dsh-adapter-007y4ejs.js} +2 -2
- package/dist/{e2b-renc0k8q.js → e2b-a19d28rz.js} +4 -4
- package/dist/{e2b-7fc9b9bd.js → e2b-we6hs6q5.js} +6 -6
- package/dist/{easter-egg-3d-fm1p3n4d.js → easter-egg-3d-rgbrqb8s.js} +1 -1
- package/dist/{embedding-space-s68v49ct.js → embedding-space-ny1e2940.js} +6 -6
- package/dist/{embeddings-4ms3604w.js → embeddings-2t386t13.js} +1 -1
- package/dist/{event-bus-dfjx2qdh.js → event-bus-g0ka3pbw.js} +1 -1
- package/dist/{execute-mcdgccjs.js → execute-pksh0ceh.js} +1 -1
- package/dist/{external-channel-9dxwfztn.js → external-channel-phgmhmd7.js} +2 -2
- package/dist/fx-adapter-fy8rr921.js +18 -0
- package/dist/{google-generative-ai-yvmdxyxa.js → google-generative-ai-8y3m3k4b.js} +1 -1
- package/dist/{google-vertex-jrtdh9gs.js → google-vertex-w3v98n7b.js} +1 -1
- package/dist/{grok-adapter-05ecv4h0.js → grok-adapter-q0abvpaj.js} +8 -8
- package/dist/handlers-by3sfxyx.js +32 -0
- package/dist/{heartbeat-3n94heh3.js → heartbeat-kadyek8p.js} +21 -20
- package/dist/{hook-aadrn69x.js → hook-5zs3msf6.js} +6 -6
- package/dist/{hook-zxwje86c.js → hook-9k551xnj.js} +4 -4
- package/dist/{http-xzxk9mst.js → http-mhz9vw1f.js} +272 -103
- package/dist/index-4f2pvxae.js +37 -0
- package/dist/index-98gz7tmp.js +30 -0
- package/dist/{index-5rk6rfzr.js → index-fvzke5kx.js} +1 -1
- package/dist/index-k08z2cak.js +33 -0
- package/dist/{index-yqhz88yy.js → index-pxn30mse.js} +8 -8
- package/dist/{index-d34f6r87.js → index-q361cg2f.js} +1 -1
- package/dist/{index-9j4zwcht.js → index-rvr00sg7.js} +168 -675
- package/dist/{index-qeb82z37.js → index-vdygbq10.js} +1 -1
- package/dist/{keepalive-w4aakbyk.js → keepalive-w56f32cg.js} +4 -4
- package/dist/lead-enq35nqp.js +70 -0
- package/dist/{maintenance-hbptpk6p.js → maintenance-7mdgxcea.js} +1 -1
- package/dist/{oauth-refresh-sweep-217semrv.js → oauth-refresh-sweep-29txy9vk.js} +3 -3
- package/dist/{onboard-vz2s5df3.js → onboard-kpsrkarj.js} +5 -5
- package/dist/{opencode-adapter-gtfd7d7v.js → opencode-adapter-j25vm3rr.js} +5 -5
- package/dist/{otel-impl-aefave37.js → otel-impl-6kkct7a8.js} +2 -2
- package/dist/{pi-mono-adapter-f8h5yseh.js → pi-mono-adapter-exhkzhn2.js} +117 -23
- package/dist/{pricing-refresh-m1yhh9ya.js → pricing-refresh-n2x7jh6k.js} +3 -3
- package/dist/{rbac-roles-rrw8twdz.js → rbac-roles-81ypx6es.js} +1 -1
- package/dist/{rbac-roles-svj72cdf.js → rbac-roles-b5htkjby.js} +2 -2
- package/dist/{render-v2-amwbnfxh.js → render-v2-qn6jmpk4.js} +3 -3
- package/dist/{resume-9cd6wf6z.js → resume-wd30wx23.js} +7 -7
- package/dist/{runtime-fp4vrx7m.js → runtime-4hsg7h60.js} +1 -1
- package/dist/{session-access-21t6yjyg.js → session-access-5qvfevhk.js} +4 -4
- package/dist/{session-source-backfill-pxbzcsc6.js → session-source-backfill-n1czavbr.js} +3 -3
- package/dist/{setup-4592tqz4.js → setup-dnb56qy5.js} +3 -3
- package/dist/{virtual-modules-gzfnpmnz.js → virtual-modules-76xxv9fs.js} +2 -2
- package/dist/{work-objects-t9tcf174.js → work-objects-4n21tfkm.js} +21 -20
- package/dist/{worker-follow-up-q32jh4yk.js → worker-follow-up-77hvzxww.js} +18 -17
- package/dist/worker-gg1576j3.js +70 -0
- package/dist/{x-b6wxntdt.js → x-vmmye1kb.js} +2 -2
- package/openapi.json +189 -32
- package/package.json +8 -7
- package/src/be/db/script-runs.ts +23 -0
- package/src/be/db/session-summaries.ts +8 -2
- package/src/be/db/session-tree.ts +174 -61
- package/src/be/db/session-visibility.ts +5 -4
- package/src/be/db/tasks/read.ts +122 -3
- package/src/be/db-client.ts +8 -5
- package/src/be/db.ts +23 -8
- package/src/be/memory/providers/sqlite-store.ts +49 -12
- package/src/be/migrations/259_session_summaries_open_tasks.sql +111 -0
- package/src/be/migrations/260_runtime_pool_cache.sql +20 -0
- package/src/be/migrations/262_session_visibility_indexes.sql +18 -0
- package/src/be/migrations/263_task_list_filter_index.sql +11 -0
- package/src/be/migrations/264_slack_thread_cover_index.sql +9 -0
- package/src/be/migrations/266_script_runs_source_task.sql +11 -0
- package/src/be/model-validation.ts +5 -1
- package/src/be/pricing-normalize.ts +7 -2
- package/src/be/runtime-pools/cache-cleanup.ts +109 -0
- package/src/be/runtime-pools/db.ts +65 -6
- package/src/be/runtime-pools/remote-controller.ts +5 -0
- package/src/be/runtime-pools/supervisor.ts +33 -2
- package/src/be/scripts/typecheck.ts +23 -0
- package/src/be/seed/schedules-seeder.ts +135 -9
- package/src/be/seed/workflows-seeder.ts +65 -1
- package/src/be/seed-pricing.ts +23 -0
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +5 -1
- package/src/be/steering.ts +50 -3
- package/src/be/swarm-config-guard.ts +1 -0
- package/src/commands/controller.ts +4 -0
- package/src/commands/entrypoint-api-readiness.ts +74 -0
- package/src/commands/provider-credentials.ts +29 -2
- package/src/commands/runner.ts +86 -5
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +27 -1
- package/src/extensions/dispatcher.ts +4 -0
- package/src/http/agents.ts +1 -0
- package/src/http/index.ts +1 -1
- package/src/http/list-total-cache.ts +14 -7
- package/src/http/mcp-bridge.ts +4 -0
- package/src/http/memory.ts +38 -9
- package/src/http/script-runs.ts +174 -5
- package/src/http/status.ts +10 -2
- package/src/http/tasks.ts +4 -2
- package/src/integrations/chat-sdk/inbound.ts +15 -5
- package/src/integrations/chat-sdk/steering.ts +3 -1
- package/src/kv-reserved-namespaces.ts +2 -0
- package/src/prompts/base-prompt.ts +4 -1
- package/src/prompts/session-templates.ts +26 -0
- package/src/providers/acp-adapter.ts +190 -26
- package/src/providers/acp-targets.ts +306 -6
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/codex-adapter.ts +9 -44
- package/src/providers/codex-oauth/flow.ts +24 -3
- package/src/providers/codex-oauth/storage.ts +56 -17
- package/src/providers/codex-oauth/subscription.ts +67 -0
- package/src/providers/fx-adapter.ts +211 -0
- package/src/providers/index.ts +5 -1
- package/src/providers/mcp-loopback-proxy.ts +94 -0
- package/src/providers/pi-mono-adapter.ts +98 -13
- package/src/providers/pricing-sources.md +8 -0
- package/src/providers/reasoning-effort.ts +17 -1
- package/src/providers/types.ts +2 -1
- package/src/runtime-providers/controller-protocol.ts +14 -1
- package/src/runtime-providers/controller.ts +5 -0
- package/src/runtime-providers/docker.ts +108 -23
- package/src/runtime-providers/types.ts +16 -0
- package/src/scheduler/scheduler.ts +36 -3
- package/src/script-workflows/workflow-ctx.ts +8 -0
- package/src/scripts-runtime/sdk-allowlist.ts +1 -0
- package/src/scripts-runtime/types/stdlib.d.ts +27 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +33 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +27 -0
- package/src/server-user.ts +1 -0
- package/src/server.ts +7 -0
- package/src/slack/assistant.ts +17 -1
- package/src/slack/commands.ts +5 -1
- package/src/slack/handlers.ts +53 -5
- package/src/slack/left-threads.ts +88 -0
- package/src/slack/steering.ts +3 -0
- package/src/slack/thread-buffer.ts +40 -16
- package/src/tasks/follow-up-redelegation-guard.ts +155 -0
- package/src/tests/acp-adapter.test.ts +79 -0
- package/src/tests/base-prompt.test.ts +12 -0
- package/src/tests/chat-sdk-inbound.test.ts +30 -0
- package/src/tests/chatgpt-subscription-model-groups.test.ts +62 -0
- package/src/tests/chatgpt-subscription-pi.test.ts +170 -0
- package/src/tests/chatgpt-subscription-session-bench.test.ts +198 -0
- package/src/tests/claude-artifacts-read-script.test.ts +209 -0
- package/src/tests/codex-oauth-credential-info.test.ts +40 -0
- package/src/tests/codex-oauth-refresh-egress.test.ts +194 -0
- package/src/tests/context-window.test.ts +7 -0
- package/src/tests/db-client.test.ts +21 -0
- package/src/tests/db-task-read-contract.test.ts +8 -2
- package/src/tests/db-task-write-contract.test.ts +5 -1
- package/src/tests/entrypoint-api-readiness.test.ts +416 -210
- package/src/tests/explicit-model-validation.test.ts +113 -8
- package/src/tests/extensions-run-context.test.ts +11 -0
- package/src/tests/extensions-steering.test.ts +353 -0
- package/src/tests/extensions-validate.test.ts +5 -0
- package/src/tests/fixtures/extensions/steering-policy/hooks.ts +39 -0
- package/src/tests/fixtures/extensions/steering-policy/manifest.json +7 -0
- package/src/tests/fixtures/fake-fx.ts +167 -0
- package/src/tests/fixtures/fx/acp-responses-recorded.json +157 -0
- package/src/tests/fixtures/fx/acp-updates-recorded.jsonl +15 -0
- package/src/tests/follow-up-redelivery-guard.test.ts +432 -202
- package/src/tests/fx-adapter.test.ts +771 -0
- package/src/tests/grok-adapter.test.ts +36 -0
- package/src/tests/list-total-cache.test.ts +27 -2
- package/src/tests/mcp-loopback-proxy.test.ts +193 -0
- package/src/tests/memory-fts-populate.test.ts +11 -9
- package/src/tests/memory-retrieval-purge.test.ts +80 -0
- package/src/tests/migration-260-runtime-pool-cache.test.ts +118 -0
- package/src/tests/model-tier-resolution.test.ts +3 -3
- package/src/tests/pricing-refresh.test.ts +5 -5
- package/src/tests/prompt-template-session.test.ts +5 -3
- package/src/tests/provider-registration.test.ts +2 -1
- package/src/tests/query-audit-plans.test.ts +30 -2
- package/src/tests/runtime-cache-cleanup.test.ts +367 -0
- package/src/tests/runtime-e2b-pools.test.ts +41 -0
- package/src/tests/runtime-pools-db.test.ts +98 -0
- package/src/tests/runtime-pools-http.test.ts +29 -0
- package/src/tests/runtime-providers-docker.test.ts +253 -0
- package/src/tests/runtime-remote-controller.test.ts +66 -2
- package/src/tests/runtime-supervisor.test.ts +66 -2
- package/src/tests/script-connections.test.ts +13 -0
- package/src/tests/script-runs-http.test.ts +684 -2
- package/src/tests/seed-model-profiles.test.ts +2 -2
- package/src/tests/seed-schedules.test.ts +138 -0
- package/src/tests/seed-scripts.test.ts +26 -0
- package/src/tests/session-cost-recompute-unit.test.ts +39 -0
- package/src/tests/session-costs-golden.test.ts +26 -0
- package/src/tests/session-summaries-plans.test.ts +120 -0
- package/src/tests/session-summaries.test.ts +72 -12
- package/src/tests/sessions-tree.test.ts +11 -3
- package/src/tests/slack-leave-thread.test.ts +571 -0
- package/src/tests/slack-render-v2-query-plans.test.ts +24 -2
- package/src/tests/status.test.ts +11 -0
- package/src/tests/tasks-readable-row.test.ts +155 -0
- package/src/tests/tool-annotations.test.ts +2 -1
- package/src/tests/workflow-engine-v2.test.ts +42 -0
- package/src/tests/workflow-script-principal.test.ts +207 -7
- package/src/tools/send-task.ts +35 -47
- package/src/tools/slack-leave-thread.ts +104 -0
- package/src/tools/steer-task.ts +3 -2
- package/src/tools/task-dedup.ts +45 -21
- package/src/tools/tool-config.ts +2 -1
- package/src/types.ts +57 -0
- package/src/utils/codex-auth-failure.ts +30 -0
- package/src/utils/context-window.ts +4 -1
- package/src/utils/credentials.ts +7 -0
- package/src/utils/fx-models.ts +43 -0
- package/src/workflows/cooldown.ts +3 -2
- package/src/workflows/engine.ts +24 -9
- package/templates/schedules/dreaming-daily/config.json +1 -1
- package/templates/schedules/dreaming-daily/content.md +6 -14
- package/templates/skills/composio-google-docs/content.md +10 -0
- package/templates/skills/script-workflows/content.md +19 -1
- package/templates/skills/swarm-docs/content.md +2 -0
- package/templates/skills/swarm-scripts/SKILL.md +2 -0
- package/templates/skills/swarm-scripts/content.md +2 -0
- package/templates/workflows/dreaming/content.md +5 -1
- package/dist/acp-adapter-96dc64m2.js +0 -15
- package/dist/cli-dznrgaep.js +0 -30
- package/dist/cli-w3hcrxht.js +0 -6985
- package/dist/handlers-jg7v74ty.js +0 -31
- package/dist/index-8c1zbz59.js +0 -29
- package/dist/index-8k8tmfxd.js +0 -32
- package/dist/index-hq617xdj.js +0 -36
- package/dist/lead-567kw7x3.js +0 -68
- package/dist/worker-fjdqra6q.js +0 -68
|
@@ -14,9 +14,11 @@
|
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
16
|
import {
|
|
17
|
+
CHATGPT_SUBSCRIPTION_PROVIDER,
|
|
17
18
|
claudeCatalogModelId,
|
|
18
19
|
cursorCatalogRef,
|
|
19
20
|
dshCatalogRef,
|
|
21
|
+
fxCatalogRef,
|
|
20
22
|
grokCatalogRef,
|
|
21
23
|
REASONING_EFFORT_LEVELS,
|
|
22
24
|
type ReasoningEffortLevel,
|
|
@@ -37,7 +39,8 @@ export type ReasoningHarness =
|
|
|
37
39
|
| "dsh"
|
|
38
40
|
| "cursor"
|
|
39
41
|
| "amp"
|
|
40
|
-
| "grok"
|
|
42
|
+
| "grok"
|
|
43
|
+
| "fx";
|
|
41
44
|
|
|
42
45
|
export interface ReasoningCapability {
|
|
43
46
|
supported: boolean;
|
|
@@ -65,6 +68,7 @@ export type ReasoningEffortApplication =
|
|
|
65
68
|
| { kind: "amp-effort"; reasoningEffort: ReasoningEffort }
|
|
66
69
|
| { kind: "cursor-effort"; reasoningEffort: ReasoningEffort }
|
|
67
70
|
| { kind: "grok-effort"; reasoningEffort: ReasoningEffort }
|
|
71
|
+
| { kind: "fx-effort"; reasoningEffort: ReasoningEffort }
|
|
68
72
|
| { kind: "noop" };
|
|
69
73
|
|
|
70
74
|
// --- Capability lookup --------------------------------------------------------
|
|
@@ -102,9 +106,16 @@ function lookupModel(
|
|
|
102
106
|
({ providerId, modelId } = cursorCatalogRef(model));
|
|
103
107
|
} else if (harness === "grok") {
|
|
104
108
|
({ providerId, modelId } = grokCatalogRef(model));
|
|
109
|
+
} else if (harness === "fx") {
|
|
110
|
+
// Only the AI Gateway route (`vercel/…`) has an effort control.
|
|
111
|
+
const ref = fxCatalogRef(model);
|
|
112
|
+
if (!ref) return undefined;
|
|
113
|
+
({ providerId, modelId } = ref);
|
|
105
114
|
} else {
|
|
106
115
|
({ providerId, modelId } = splitProviderModel(model));
|
|
107
116
|
if (!providerId) return undefined;
|
|
117
|
+
// A ChatGPT subscription id names an OpenAI catalog model.
|
|
118
|
+
if (providerId.toLowerCase() === CHATGPT_SUBSCRIPTION_PROVIDER) providerId = "openai";
|
|
108
119
|
}
|
|
109
120
|
const facts = runtimeCatalogModel(providerId, modelId);
|
|
110
121
|
return facts ? { id: modelId, facts } : undefined;
|
|
@@ -240,6 +251,10 @@ export function applyReasoningEffort(
|
|
|
240
251
|
// Grok's `--reasoning-effort` takes the normalized names as-is; see
|
|
241
252
|
// `src/providers/grok-adapter.ts`.
|
|
242
253
|
return { kind: "grok-effort", reasoningEffort: level };
|
|
254
|
+
case "fx":
|
|
255
|
+
// fx's `effort` config option takes the normalized names; the adapter
|
|
256
|
+
// sets it on the AI Gateway route only (see `fxTargetProfile`).
|
|
257
|
+
return { kind: "fx-effort", reasoningEffort: level };
|
|
243
258
|
default: {
|
|
244
259
|
const _exhaustive: never = harness;
|
|
245
260
|
return _exhaustive;
|
|
@@ -256,6 +271,7 @@ const REASONING_HARNESSES: ReadonlySet<string> = new Set<ReasoningHarness>([
|
|
|
256
271
|
"cursor",
|
|
257
272
|
"amp",
|
|
258
273
|
"grok",
|
|
274
|
+
"fx",
|
|
259
275
|
]);
|
|
260
276
|
|
|
261
277
|
/**
|
package/src/providers/types.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { RuntimeProviderKindSchema } from "../types";
|
|
2
|
+
import { RuntimePoolCacheSchema, RuntimeProviderKindSchema } from "../types";
|
|
3
3
|
|
|
4
4
|
export const CONTROLLER_PROTOCOL_VERSION = 1;
|
|
5
5
|
export const CONTROLLER_COMMAND_TIMEOUT_MS = 60_000;
|
|
@@ -16,6 +16,7 @@ const traitsSchema = z.object({
|
|
|
16
16
|
canProvision: z.boolean(),
|
|
17
17
|
ephemeralDisk: z.boolean(),
|
|
18
18
|
supportsPause: z.boolean(),
|
|
19
|
+
persistentCache: z.boolean().optional(),
|
|
19
20
|
maxTtlSec: z.number().positive().optional(),
|
|
20
21
|
maxContinuousSec: z.number().positive().optional(),
|
|
21
22
|
});
|
|
@@ -31,9 +32,21 @@ const provisionSchema = z.object({
|
|
|
31
32
|
.object({ cpu: z.number().positive().optional(), memoryMb: z.number().positive().optional() })
|
|
32
33
|
.optional(),
|
|
33
34
|
ttlSec: z.number().positive().optional(),
|
|
35
|
+
cache: RuntimePoolCacheSchema.extend({
|
|
36
|
+
key: z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_.-]+$/),
|
|
37
|
+
}).optional(),
|
|
34
38
|
});
|
|
35
39
|
const command = { type: z.literal("cmd"), id: z.string().min(1) };
|
|
36
40
|
export const ControllerCommandSchema = z.discriminatedUnion("op", [
|
|
41
|
+
z.object({
|
|
42
|
+
...command,
|
|
43
|
+
op: z.literal("release-cache"),
|
|
44
|
+
payload: z.object({
|
|
45
|
+
key: z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_.-]+$/),
|
|
46
|
+
poolId: z.string().min(1),
|
|
47
|
+
ownerId: z.string().min(1),
|
|
48
|
+
}),
|
|
49
|
+
}),
|
|
37
50
|
z.object({ ...command, op: z.literal("provision"), payload: provisionSchema }),
|
|
38
51
|
z.object({
|
|
39
52
|
...command,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { scrubSecrets } from "../utils/secret-scrubber";
|
|
2
2
|
import type {
|
|
3
3
|
ProvisionRequest,
|
|
4
|
+
RuntimeCacheReference,
|
|
4
5
|
RuntimeHandle,
|
|
5
6
|
RuntimeProvider,
|
|
6
7
|
RuntimeProviderTraits,
|
|
@@ -25,6 +26,7 @@ export interface ControllerCommands {
|
|
|
25
26
|
terminate(handle: RuntimeHandle, reason: string): Promise<void>;
|
|
26
27
|
status(handles: RuntimeHandle[]): Promise<Record<string, RuntimeStatus>>;
|
|
27
28
|
list(ownerId: string): Promise<RuntimeHandle[]>;
|
|
29
|
+
releaseCache?(cache: RuntimeCacheReference): Promise<void>;
|
|
28
30
|
renew?(handle: RuntimeHandle, ttlSec: number): Promise<{ endAt: string }>;
|
|
29
31
|
pause?(handle: RuntimeHandle): Promise<void>;
|
|
30
32
|
resume?(handle: RuntimeHandle): Promise<void>;
|
|
@@ -36,6 +38,7 @@ export class BuiltinController implements ControllerCommands {
|
|
|
36
38
|
readonly renew?: ControllerCommands["renew"];
|
|
37
39
|
readonly pause?: ControllerCommands["pause"];
|
|
38
40
|
readonly resume?: ControllerCommands["resume"];
|
|
41
|
+
readonly releaseCache?: ControllerCommands["releaseCache"];
|
|
39
42
|
|
|
40
43
|
constructor(
|
|
41
44
|
readonly id: string,
|
|
@@ -47,6 +50,8 @@ export class BuiltinController implements ControllerCommands {
|
|
|
47
50
|
this.workerApiUrl = workerApiUrl;
|
|
48
51
|
if (provider.renew)
|
|
49
52
|
this.renew = (handle, ttlSec) => this.call(() => provider.renew!(target, handle, ttlSec));
|
|
53
|
+
if (provider.releaseCache)
|
|
54
|
+
this.releaseCache = (cache) => this.call(() => provider.releaseCache!(target, cache));
|
|
50
55
|
if (provider.pause) this.pause = (handle) => this.call(() => provider.pause!(target, handle));
|
|
51
56
|
if (provider.resume)
|
|
52
57
|
this.resume = (handle) => this.call(() => provider.resume!(target, handle));
|
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
type ConfigStatus,
|
|
5
5
|
type ProvisionRequest,
|
|
6
6
|
RUNTIME_LABELS,
|
|
7
|
+
type RuntimeCacheReference,
|
|
7
8
|
type RuntimeHandle,
|
|
8
9
|
type RuntimeProvider,
|
|
9
10
|
type RuntimeStatus,
|
|
@@ -63,6 +64,22 @@ class DockerApiError extends Error {
|
|
|
63
64
|
}
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
function isCacheMountError(error: unknown): boolean {
|
|
68
|
+
return error instanceof DockerApiError && /\b(?:mount\w*|volume\w*)\b/i.test(error.message);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
type CacheVolume = { Name: string; Labels?: Record<string, string> };
|
|
72
|
+
|
|
73
|
+
function assertCacheOwner(volume: CacheVolume, cache: RuntimeCacheReference): void {
|
|
74
|
+
if (
|
|
75
|
+
volume.Name !== cache.key ||
|
|
76
|
+
volume.Labels?.[RUNTIME_LABELS.owner] !== cache.ownerId ||
|
|
77
|
+
volume.Labels?.[RUNTIME_LABELS.poolId] !== cache.poolId ||
|
|
78
|
+
volume.Labels?.["swarm.cache"] !== "true"
|
|
79
|
+
)
|
|
80
|
+
throw new Error(`Cache volume ${cache.key} is not owned by this swarm and pool`);
|
|
81
|
+
}
|
|
82
|
+
|
|
66
83
|
async function dockerApi<T>(
|
|
67
84
|
target: RuntimeTargetConfig,
|
|
68
85
|
method: string,
|
|
@@ -119,7 +136,12 @@ async function dockerApi<T>(
|
|
|
119
136
|
|
|
120
137
|
export class DockerRuntimeProvider implements RuntimeProvider {
|
|
121
138
|
readonly kind = "docker" as const;
|
|
122
|
-
readonly traits = {
|
|
139
|
+
readonly traits = {
|
|
140
|
+
canProvision: true,
|
|
141
|
+
ephemeralDisk: true,
|
|
142
|
+
supportsPause: false,
|
|
143
|
+
persistentCache: true,
|
|
144
|
+
};
|
|
123
145
|
|
|
124
146
|
checkConfig(target: RuntimeTargetConfig): ConfigStatus {
|
|
125
147
|
try {
|
|
@@ -132,6 +154,29 @@ export class DockerRuntimeProvider implements RuntimeProvider {
|
|
|
132
154
|
|
|
133
155
|
async provision(target: RuntimeTargetConfig, req: ProvisionRequest): Promise<RuntimeHandle> {
|
|
134
156
|
try {
|
|
157
|
+
let cacheWarning: string | undefined;
|
|
158
|
+
let cacheMount: { Type: "volume"; Source: string; Target: string } | undefined;
|
|
159
|
+
if (req.cache) {
|
|
160
|
+
try {
|
|
161
|
+
const volume = await dockerApi<CacheVolume>(target, "POST", "/volumes/create", {
|
|
162
|
+
Name: req.cache.key,
|
|
163
|
+
Labels: {
|
|
164
|
+
[RUNTIME_LABELS.owner]: req.ownerId,
|
|
165
|
+
[RUNTIME_LABELS.poolId]: req.poolId,
|
|
166
|
+
"swarm.cache": "true",
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
// Docker reuses an existing name without replacing its labels.
|
|
170
|
+
assertCacheOwner(volume, {
|
|
171
|
+
key: req.cache.key,
|
|
172
|
+
poolId: req.poolId,
|
|
173
|
+
ownerId: req.ownerId,
|
|
174
|
+
});
|
|
175
|
+
cacheMount = { Type: "volume", Source: req.cache.key, Target: req.cache.mountPath };
|
|
176
|
+
} catch (error) {
|
|
177
|
+
cacheWarning = redactWithEnv(scrubSecrets(String(error)), req.env);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
135
180
|
const path = `/containers/create?name=${encodeURIComponent(`swarm-rt-${req.runtimeId}`)}`;
|
|
136
181
|
const body = {
|
|
137
182
|
Image: req.image,
|
|
@@ -154,40 +199,80 @@ export class DockerRuntimeProvider implements RuntimeProvider {
|
|
|
154
199
|
NetworkMode: target.DOCKER_NETWORK,
|
|
155
200
|
Memory: req.resources?.memoryMb ? req.resources.memoryMb * 1024 * 1024 : undefined,
|
|
156
201
|
NanoCpus: req.resources?.cpu ? Math.round(req.resources.cpu * 1e9) : undefined,
|
|
202
|
+
...(cacheMount ? { Mounts: [cacheMount] } : {}),
|
|
157
203
|
},
|
|
158
204
|
};
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
205
|
+
const createAndStart = async (): Promise<string> => {
|
|
206
|
+
let created: { Id: string };
|
|
207
|
+
try {
|
|
208
|
+
created = await dockerApi(target, "POST", path, body);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
if (
|
|
211
|
+
!(err instanceof DockerApiError) ||
|
|
212
|
+
err.statusCode !== 404 ||
|
|
213
|
+
!err.message.includes("No such image")
|
|
214
|
+
)
|
|
215
|
+
throw err;
|
|
216
|
+
const pullParams = new URLSearchParams({ fromImage: req.image });
|
|
217
|
+
if (
|
|
218
|
+
!req.image.includes("@") &&
|
|
219
|
+
req.image.lastIndexOf(":") <= req.image.lastIndexOf("/")
|
|
220
|
+
) {
|
|
221
|
+
pullParams.set("tag", "latest");
|
|
222
|
+
}
|
|
223
|
+
await dockerApi(target, "POST", `/images/create?${pullParams}`, undefined, true);
|
|
224
|
+
created = await dockerApi(target, "POST", path, body);
|
|
169
225
|
}
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
226
|
+
try {
|
|
227
|
+
await dockerApi(target, "POST", `/containers/${created.Id}/start`);
|
|
228
|
+
} catch (err) {
|
|
229
|
+
try {
|
|
230
|
+
await dockerApi(target, "DELETE", `/containers/${created.Id}?force=true&v=true`);
|
|
231
|
+
} catch (cleanupError) {
|
|
232
|
+
if (
|
|
233
|
+
cacheMount &&
|
|
234
|
+
isCacheMountError(err) &&
|
|
235
|
+
!(cleanupError instanceof DockerApiError && cleanupError.statusCode === 404)
|
|
236
|
+
)
|
|
237
|
+
throw new Error(
|
|
238
|
+
`${String(err)}; failed-start cleanup failed: ${String(cleanupError)}`,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
throw err;
|
|
173
242
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
243
|
+
return created.Id;
|
|
244
|
+
};
|
|
245
|
+
let externalId: string;
|
|
177
246
|
try {
|
|
178
|
-
await
|
|
247
|
+
externalId = await createAndStart();
|
|
179
248
|
} catch (err) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
249
|
+
if (!cacheMount || !isCacheMountError(err)) throw err;
|
|
250
|
+
cacheWarning = redactWithEnv(scrubSecrets(String(err)), req.env);
|
|
251
|
+
delete body.HostConfig.Mounts;
|
|
252
|
+
externalId = await createAndStart();
|
|
184
253
|
}
|
|
185
|
-
return {
|
|
254
|
+
return {
|
|
255
|
+
kind: "docker",
|
|
256
|
+
externalId,
|
|
257
|
+
...(cacheWarning ? { meta: { cacheWarning } } : {}),
|
|
258
|
+
};
|
|
186
259
|
} catch (err) {
|
|
187
260
|
throw new Error(redactWithEnv(String(err), req.env));
|
|
188
261
|
}
|
|
189
262
|
}
|
|
190
263
|
|
|
264
|
+
async releaseCache(target: RuntimeTargetConfig, cache: RuntimeCacheReference): Promise<void> {
|
|
265
|
+
const path = `/volumes/${encodeURIComponent(cache.key)}`;
|
|
266
|
+
try {
|
|
267
|
+
const volume = await dockerApi<CacheVolume>(target, "GET", path);
|
|
268
|
+
assertCacheOwner(volume, cache);
|
|
269
|
+
// A volume still attached to any container must remain intact (Docker returns 409).
|
|
270
|
+
await dockerApi(target, "DELETE", path);
|
|
271
|
+
} catch (error) {
|
|
272
|
+
if (!(error instanceof DockerApiError && error.statusCode === 404)) throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
191
276
|
async terminate(target: RuntimeTargetConfig, handle: RuntimeHandle): Promise<void> {
|
|
192
277
|
try {
|
|
193
278
|
// v=true also removes the container's anonymous volumes (the worker image declares
|
|
@@ -19,6 +19,8 @@ export interface RuntimeProviderTraits {
|
|
|
19
19
|
ephemeralDisk: boolean;
|
|
20
20
|
/** Provider can pause and resume a runtime. */
|
|
21
21
|
supportsPause: boolean;
|
|
22
|
+
/** Can mount a persistent cache shared by all runtimes of one pool. */
|
|
23
|
+
persistentCache?: boolean;
|
|
22
24
|
/** Provider hard cap on runtime lifetime, if any. */
|
|
23
25
|
maxTtlSec?: number;
|
|
24
26
|
/** Continuous runtime limit for the configured infrastructure tier. */
|
|
@@ -45,11 +47,23 @@ export interface ProvisionRequest {
|
|
|
45
47
|
/** Worker env: MCP_BASE_URL, AGENT_ID, API key or scoped token, pool env. */
|
|
46
48
|
env: Record<string, string>;
|
|
47
49
|
resources?: { cpu?: number; memoryMb?: number };
|
|
50
|
+
/** Provider-neutral cache identity, allocated by the API rather than the operator. */
|
|
51
|
+
cache?: { key: string; mountPath: string };
|
|
48
52
|
ttlSec?: number;
|
|
49
53
|
/** Ownership labels, used by list() to find runtimes this swarm started. */
|
|
50
54
|
labels: Record<string, string>;
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
export interface RuntimeCacheReference {
|
|
58
|
+
key: string;
|
|
59
|
+
poolId: string;
|
|
60
|
+
ownerId: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function poolCacheKey(poolId: string, generation?: string): string {
|
|
64
|
+
return `swarm-cache-${poolId}${generation ? `-${generation}` : ""}`;
|
|
65
|
+
}
|
|
66
|
+
|
|
53
67
|
export interface RuntimeHandle {
|
|
54
68
|
kind: RuntimeProviderKind;
|
|
55
69
|
/** Container id, sandbox id, or pod name. */
|
|
@@ -74,6 +88,8 @@ export interface RuntimeProvider {
|
|
|
74
88
|
status(target: RuntimeTargetConfig, handle: RuntimeHandle): Promise<RuntimeStatus>;
|
|
75
89
|
/** Every runtime this swarm owns on the target, found by labels. Used to reap orphans. */
|
|
76
90
|
list(target: RuntimeTargetConfig, ownerId: string): Promise<RuntimeHandle[]>;
|
|
91
|
+
/** Remove an owned pool cache after its runtimes stop; never force detach. */
|
|
92
|
+
releaseCache?(target: RuntimeTargetConfig, cache: RuntimeCacheReference): Promise<void>;
|
|
77
93
|
renew?(
|
|
78
94
|
target: RuntimeTargetConfig,
|
|
79
95
|
handle: RuntimeHandle,
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
import {
|
|
12
12
|
getDbClient,
|
|
13
13
|
getDueScheduledTasks,
|
|
14
|
+
getLeadAgent,
|
|
14
15
|
getScheduledTaskById,
|
|
15
16
|
getUserById,
|
|
16
17
|
getWorkflow,
|
|
@@ -26,8 +27,9 @@ import {
|
|
|
26
27
|
import { buildScriptCredentialBindingsWithFailures } from "@/be/script-credential-broker";
|
|
27
28
|
import { getScript } from "@/be/scripts/db";
|
|
28
29
|
import { runScriptWithRunCredential } from "@/be/scripts/run-credential";
|
|
30
|
+
import { seededWorkflowState } from "@/be/seed/workflows-seeder";
|
|
29
31
|
import { telemetry } from "@/telemetry";
|
|
30
|
-
import type { AgentTask, ScheduledTask } from "@/types";
|
|
32
|
+
import type { AgentTask, ScheduledTask, Workflow } from "@/types";
|
|
31
33
|
import { getExecutorRegistry as getWorkflowExecutorRegistry } from "@/workflows";
|
|
32
34
|
import { startWorkflowExecution } from "@/workflows/engine";
|
|
33
35
|
import type { ExecutorRegistry } from "@/workflows/executors/registry";
|
|
@@ -252,8 +254,7 @@ export async function dispatchScheduleTarget(
|
|
|
252
254
|
};
|
|
253
255
|
const runId = await startWorkflowExecution(workflow, triggerData, registry, {
|
|
254
256
|
triggerType: "schedule",
|
|
255
|
-
|
|
256
|
-
triggeredByAgentId: schedule.createdByAgentId,
|
|
257
|
+
triggeredByAgentId: await scheduledWorkflowPrincipal(schedule, workflow),
|
|
257
258
|
requestedByUserId: schedule.createdBy,
|
|
258
259
|
});
|
|
259
260
|
await throwIfWorkflowNeedsSetup(schedule.id, [runId]);
|
|
@@ -295,6 +296,38 @@ export async function dispatchScheduleTarget(
|
|
|
295
296
|
}
|
|
296
297
|
}
|
|
297
298
|
|
|
299
|
+
/**
|
|
300
|
+
* The agent a scheduled workflow run acts as: the schedule's creator, as for
|
|
301
|
+
* script schedules (`targetAgentId` and trigger data are caller-chosen, so
|
|
302
|
+
* neither is ever the principal). A creator-less (seeded) schedule that fires
|
|
303
|
+
* a seeded workflow runs as the lead, resolved at fire time; with no lead the
|
|
304
|
+
* fire fails instead of running agentless. Operator settings such as inputs
|
|
305
|
+
* or on/off keep that. Any agent can edit a workflow, so one whose nodes or
|
|
306
|
+
* params changed never inherits the lead and its fire fails. Workflows the
|
|
307
|
+
* seeder never wrote keep their previous principal.
|
|
308
|
+
*/
|
|
309
|
+
async function scheduledWorkflowPrincipal(
|
|
310
|
+
schedule: ScheduledTask,
|
|
311
|
+
workflow: Workflow,
|
|
312
|
+
): Promise<string | undefined> {
|
|
313
|
+
if (schedule.createdByAgentId) return schedule.createdByAgentId;
|
|
314
|
+
if (workflow.createdByAgentId) return undefined;
|
|
315
|
+
const seeded = await seededWorkflowState(workflow);
|
|
316
|
+
if (seeded === "unseeded") return undefined;
|
|
317
|
+
if (seeded === "edited") {
|
|
318
|
+
throw new Error(
|
|
319
|
+
`Schedule "${schedule.name}" has no creator and the nodes or params of seeded workflow "${workflow.name}" were edited, so it will not run as the lead. Re-create the schedule as the agent it should run as.`,
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
const lead = await getLeadAgent();
|
|
323
|
+
if (!lead) {
|
|
324
|
+
throw new Error(
|
|
325
|
+
`Schedule "${schedule.name}" has no creator and the swarm has no lead to run its workflow as`,
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
return lead.id;
|
|
329
|
+
}
|
|
330
|
+
|
|
298
331
|
async function throwIfWorkflowNeedsSetup(scheduleId: string, runIds: string[]): Promise<void> {
|
|
299
332
|
for (const runId of runIds) {
|
|
300
333
|
const run = await getWorkflowRun(runId);
|
|
@@ -44,6 +44,14 @@ type AgentTaskConfig = {
|
|
|
44
44
|
parentTaskId?: string;
|
|
45
45
|
requestedByUserId?: string;
|
|
46
46
|
outputSchema?: Record<string, unknown>;
|
|
47
|
+
/**
|
|
48
|
+
* Dispatch even when the follow-up re-delegation guard blocks this step.
|
|
49
|
+
* The guard applies only to a run launched from a follow-up task in a Slack
|
|
50
|
+
* thread, and decides once for the whole run at its first new step: it
|
|
51
|
+
* blocks a repeat of work already completed in the thread, or a run past the
|
|
52
|
+
* thread's dispatch cap. A blocked run's later new steps are blocked too.
|
|
53
|
+
*/
|
|
54
|
+
allowRedelegation?: boolean;
|
|
47
55
|
/**
|
|
48
56
|
* Block until the dispatched task reaches a terminal status and journal
|
|
49
57
|
* its real output. Defaults to `true` — this is the natural semantic for
|
|
@@ -104,6 +104,7 @@ export const SDK_TOOL_NAME_MAP = {
|
|
|
104
104
|
slack_downloadFile: "slack-download-file",
|
|
105
105
|
slack_delete: "slack-delete", // external: mutates Slack, destructive
|
|
106
106
|
slack_update: "slack-update", // external: mutates Slack
|
|
107
|
+
slack_leaveThread: "slack-leave-thread",
|
|
107
108
|
|
|
108
109
|
// ── chat sdk ──
|
|
109
110
|
chat_reply: "chat-reply", // external: sends to the task's chat thread
|
|
@@ -63,6 +63,8 @@ declare module "swarm-sdk" {
|
|
|
63
63
|
parentTaskId?: string;
|
|
64
64
|
requestedByUserId?: string;
|
|
65
65
|
outputSchema?: Record<string, unknown>;
|
|
66
|
+
/** Dispatch even when the follow-up re-delegation guard blocks this step (a run launched from a follow-up task in a Slack thread, checked at its first new step). */
|
|
67
|
+
allowRedelegation?: boolean;
|
|
66
68
|
/** Wait for the dispatched task to reach a terminal status before resolving. Default: true. */
|
|
67
69
|
waitForCompletion?: boolean;
|
|
68
70
|
/** Max ms to wait for a terminal status before throwing. Default: 2h. Only used when waitForCompletion is true. */
|
|
@@ -493,6 +495,11 @@ declare module "swarm-sdk" {
|
|
|
493
495
|
slack_downloadFile(args: { url: string }): Promise<unknown>;
|
|
494
496
|
slack_delete(args: { channelId: string; messageTs: string }): Promise<unknown>;
|
|
495
497
|
slack_update(args: { channelId: string; messageTs: string; message: string }): Promise<unknown>;
|
|
498
|
+
slack_leaveThread(args: {
|
|
499
|
+
taskId?: string;
|
|
500
|
+
channelId?: string;
|
|
501
|
+
threadTs?: string;
|
|
502
|
+
}): Promise<unknown>;
|
|
496
503
|
|
|
497
504
|
// --- write: chat sdk ---
|
|
498
505
|
chat_reply(args: { text: string }): Promise<unknown>;
|
|
@@ -755,6 +762,26 @@ declare module "swarm-sdk" {
|
|
|
755
762
|
label: string,
|
|
756
763
|
config: { prompt: string; model?: string; schema?: Record<string, unknown> },
|
|
757
764
|
): Promise<unknown>;
|
|
765
|
+
/**
|
|
766
|
+
* Dispatch a task and journal its result under `label`.
|
|
767
|
+
*
|
|
768
|
+
* Resolves to the task's OUTPUT on success: the stored output string (JSON
|
|
769
|
+
* text under `outputSchema`, so parse it yourself), or `null` when the task
|
|
770
|
+
* stored none. It is never a task record: on a string, `result.taskId` and
|
|
771
|
+
* `result.status` are undefined; on `null`, reading them throws a TypeError.
|
|
772
|
+
* Other shapes:
|
|
773
|
+
* - `failOnTaskFailure: false` and the task ends failed/cancelled/superseded:
|
|
774
|
+
* `{ taskId, status: "failed", error }`.
|
|
775
|
+
* - `waitForCompletion: false`: the first call still waits up to ~30s while
|
|
776
|
+
* the server polls the task. Done in that window: the output, as on
|
|
777
|
+
* success. Failed or cancelled in that window: throws, or
|
|
778
|
+
* `{ taskId, status: "failed", error }` with `failOnTaskFailure: false`.
|
|
779
|
+
* Still running: `{ taskId, status }`.
|
|
780
|
+
*
|
|
781
|
+
* To get a step's task id, query by its context key:
|
|
782
|
+
* `SELECT id, status, output FROM agent_tasks WHERE contextKey = 'script-run:<runId>:<label>'
|
|
783
|
+
* AND taskType = 'script-run-step' ORDER BY createdAt DESC, rowid DESC LIMIT 1`.
|
|
784
|
+
*/
|
|
758
785
|
agentTask(label: string, config: AgentTaskStepConfig): Promise<unknown>;
|
|
759
786
|
swarmScript(
|
|
760
787
|
label: string,
|
|
@@ -98,6 +98,7 @@ declare module "swarm-extension" {
|
|
|
98
98
|
| "amp"
|
|
99
99
|
| "cursor"
|
|
100
100
|
| "grok"
|
|
101
|
+
| "fx"
|
|
101
102
|
| undefined;
|
|
102
103
|
leadOnly?: boolean | undefined;
|
|
103
104
|
}
|
|
@@ -233,6 +234,7 @@ declare module "swarm-extension" {
|
|
|
233
234
|
| "amp"
|
|
234
235
|
| "cursor"
|
|
235
236
|
| "grok"
|
|
237
|
+
| "fx"
|
|
236
238
|
| undefined;
|
|
237
239
|
providerMeta?: Record<string, unknown> | undefined;
|
|
238
240
|
harnessVariant?: string | undefined;
|
|
@@ -255,6 +257,7 @@ declare module "swarm-extension" {
|
|
|
255
257
|
| "amp"
|
|
256
258
|
| "cursor"
|
|
257
259
|
| "grok"
|
|
260
|
+
| "fx"
|
|
258
261
|
| undefined;
|
|
259
262
|
leadOnly?: boolean | undefined;
|
|
260
263
|
}
|
|
@@ -276,6 +279,10 @@ declare module "swarm-extension" {
|
|
|
276
279
|
runtimeInstanceId?: string | null | undefined;
|
|
277
280
|
};
|
|
278
281
|
|
|
282
|
+
export type SteerMode = "steer" | "queue";
|
|
283
|
+
|
|
284
|
+
export type SteeringSource = "script" | "slack" | "mcp" | "api" | "ui" | "chat";
|
|
285
|
+
|
|
279
286
|
export type RequestInfo = {
|
|
280
287
|
sessionId: string | undefined;
|
|
281
288
|
agentId: string | undefined;
|
|
@@ -486,6 +493,27 @@ declare module "swarm-extension" {
|
|
|
486
493
|
leadAgentId: string;
|
|
487
494
|
summary: string;
|
|
488
495
|
}
|
|
496
|
+
export interface TaskSteerEvent {
|
|
497
|
+
task: AgentTask;
|
|
498
|
+
message: string;
|
|
499
|
+
mode: SteerMode;
|
|
500
|
+
source: SteeringSource;
|
|
501
|
+
sender: {
|
|
502
|
+
kind: "user" | "agent" | "system";
|
|
503
|
+
userId?: string;
|
|
504
|
+
agentId?: string;
|
|
505
|
+
};
|
|
506
|
+
messageTimestamps?: string[];
|
|
507
|
+
/** Slack ingress metadata; not persisted or writable through modify. */
|
|
508
|
+
slack?: {
|
|
509
|
+
channelId: string;
|
|
510
|
+
threadTs: string;
|
|
511
|
+
userId?: string;
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
export interface TaskSteerModify {
|
|
515
|
+
message: string;
|
|
516
|
+
}
|
|
489
517
|
export type TaskFollowUpModify = Partial<
|
|
490
518
|
Pick<CreateTaskOptions, "agentId" | "priority" | "followUpConfig">
|
|
491
519
|
> & {
|
|
@@ -718,6 +746,11 @@ declare module "swarm-extension" {
|
|
|
718
746
|
modify: TaskFollowUpModify;
|
|
719
747
|
result: PreResult<TaskFollowUpModify>;
|
|
720
748
|
};
|
|
749
|
+
"pre.task.steer": {
|
|
750
|
+
event: TaskSteerEvent;
|
|
751
|
+
modify: TaskSteerModify;
|
|
752
|
+
result: PreResult<TaskSteerModify>;
|
|
753
|
+
};
|
|
721
754
|
"pre.slack.route": {
|
|
722
755
|
event: SlackRouteEvent;
|
|
723
756
|
modify: SlackRouteModify;
|
|
@@ -45,6 +45,8 @@ declare module "swarm-sdk" {
|
|
|
45
45
|
parentTaskId?: string;
|
|
46
46
|
requestedByUserId?: string;
|
|
47
47
|
outputSchema?: Record<string, unknown>;
|
|
48
|
+
/** Dispatch even when the follow-up re-delegation guard blocks this step (a run launched from a follow-up task in a Slack thread, checked at its first new step). */
|
|
49
|
+
allowRedelegation?: boolean;
|
|
48
50
|
/** Wait for the dispatched task to reach a terminal status before resolving. Default: true. */
|
|
49
51
|
waitForCompletion?: boolean;
|
|
50
52
|
/** Max ms to wait for a terminal status before throwing. Default: 2h. Only used when waitForCompletion is true. */
|
|
@@ -475,6 +477,11 @@ declare module "swarm-sdk" {
|
|
|
475
477
|
slack_downloadFile(args: { url: string }): Promise<unknown>;
|
|
476
478
|
slack_delete(args: { channelId: string; messageTs: string }): Promise<unknown>;
|
|
477
479
|
slack_update(args: { channelId: string; messageTs: string; message: string }): Promise<unknown>;
|
|
480
|
+
slack_leaveThread(args: {
|
|
481
|
+
taskId?: string;
|
|
482
|
+
channelId?: string;
|
|
483
|
+
threadTs?: string;
|
|
484
|
+
}): Promise<unknown>;
|
|
478
485
|
|
|
479
486
|
// --- write: chat sdk ---
|
|
480
487
|
chat_reply(args: { text: string }): Promise<unknown>;
|
|
@@ -737,6 +744,26 @@ declare module "swarm-sdk" {
|
|
|
737
744
|
label: string,
|
|
738
745
|
config: { prompt: string; model?: string; schema?: Record<string, unknown> },
|
|
739
746
|
): Promise<unknown>;
|
|
747
|
+
/**
|
|
748
|
+
* Dispatch a task and journal its result under `label`.
|
|
749
|
+
*
|
|
750
|
+
* Resolves to the task's OUTPUT on success: the stored output string (JSON
|
|
751
|
+
* text under `outputSchema`, so parse it yourself), or `null` when the task
|
|
752
|
+
* stored none. It is never a task record: on a string, `result.taskId` and
|
|
753
|
+
* `result.status` are undefined; on `null`, reading them throws a TypeError.
|
|
754
|
+
* Other shapes:
|
|
755
|
+
* - `failOnTaskFailure: false` and the task ends failed/cancelled/superseded:
|
|
756
|
+
* `{ taskId, status: "failed", error }`.
|
|
757
|
+
* - `waitForCompletion: false`: the first call still waits up to ~30s while
|
|
758
|
+
* the server polls the task. Done in that window: the output, as on
|
|
759
|
+
* success. Failed or cancelled in that window: throws, or
|
|
760
|
+
* `{ taskId, status: "failed", error }` with `failOnTaskFailure: false`.
|
|
761
|
+
* Still running: `{ taskId, status }`.
|
|
762
|
+
*
|
|
763
|
+
* To get a step's task id, query by its context key:
|
|
764
|
+
* `SELECT id, status, output FROM agent_tasks WHERE contextKey = 'script-run:<runId>:<label>'
|
|
765
|
+
* AND taskType = 'script-run-step' ORDER BY createdAt DESC, rowid DESC LIMIT 1`.
|
|
766
|
+
*/
|
|
740
767
|
agentTask(label: string, config: AgentTaskStepConfig): Promise<unknown>;
|
|
741
768
|
swarmScript(
|
|
742
769
|
label: string,
|
package/src/server-user.ts
CHANGED
package/src/server.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { MCP_MAX_TOOL_INPUT_ELEMENTS } from "./mcp-limits";
|
|
|
11
11
|
import { resolveTemplate } from "./prompts/resolver";
|
|
12
12
|
import { isRbacEnabled } from "./rbac";
|
|
13
13
|
import { getSlackConfiguration } from "./slack/config";
|
|
14
|
+
import { isSlackLeaveThreadDisabled } from "./slack/left-threads";
|
|
14
15
|
import { registerAcceptSteerTool } from "./tools/accept-steer";
|
|
15
16
|
import { registerAppActionRunTool } from "./tools/app-action-run";
|
|
16
17
|
import { registerAppDiffTool } from "./tools/app-diff";
|
|
@@ -162,6 +163,7 @@ import { registerSlackCreateChannelTool } from "./tools/slack-create-channel";
|
|
|
162
163
|
import { registerSlackDeleteTool } from "./tools/slack-delete";
|
|
163
164
|
import { registerSlackDownloadFileTool } from "./tools/slack-download-file";
|
|
164
165
|
import { registerSlackInviteToChannelTool } from "./tools/slack-invite-to-channel";
|
|
166
|
+
import { registerSlackLeaveThreadTool } from "./tools/slack-leave-thread";
|
|
165
167
|
import { registerSlackListChannelsTool } from "./tools/slack-list-channels";
|
|
166
168
|
import { registerSlackPostTool } from "./tools/slack-post";
|
|
167
169
|
import { registerSlackReadTool } from "./tools/slack-read";
|
|
@@ -693,6 +695,11 @@ export async function createServer(
|
|
|
693
695
|
registerSlackDownloadFileTool(server);
|
|
694
696
|
registerSlackDeleteTool(server);
|
|
695
697
|
registerSlackUpdateTool(server);
|
|
698
|
+
// The scripts bridge builds its full-surface server once and caches it, so
|
|
699
|
+
// it always registers the tool; the handler refuses while the flag is set.
|
|
700
|
+
if (opts.fullSurface === true || !isSlackLeaveThreadDisabled()) {
|
|
701
|
+
registerSlackLeaveThreadTool(server);
|
|
702
|
+
}
|
|
696
703
|
}
|
|
697
704
|
|
|
698
705
|
// End of default-enabled capabilities
|