@desplega.ai/agent-swarm 1.173.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{acp-adapter-ccm9xrep.js → acp-adapter-kr4abrsk.js} +17 -16
- package/dist/{actions-sgeyv08k.js → actions-eh4g6w2r.js} +39 -34
- package/dist/{amp-adapter-gpxp3kc9.js → amp-adapter-7h7wdt8q.js} +8 -7
- package/dist/{app-km9qnv2f.js → app-7k8s9w5p.js} +18 -14
- package/dist/{assistant-5r8tcvvd.js → assistant-wswt2y7p.js} +40 -35
- package/dist/{boot-reembed-16rv9843.js → boot-reembed-9apm9qw6.js} +10 -9
- package/dist/{boot-reembed-swwzdgd7.js → boot-reembed-whzbdthj.js} +10 -9
- package/dist/{boot-scrub-sweep-zkr6vkqb.js → boot-scrub-sweep-ndzmvmgt.js} +11 -10
- package/dist/{boot-seeds-d8sp49t2.js → boot-seeds-e9sta0yt.js} +16 -13
- package/dist/{claude-adapter-yzzzh8jp.js → claude-adapter-4mqd3r6r.js} +19 -18
- package/dist/{claude-managed-adapter-xgxhqrt2.js → claude-managed-adapter-9wswb52m.js} +7 -5
- package/dist/{claude-managed-setup-bnmjarjc.js → claude-managed-setup-tpe1effx.js} +6 -4
- package/dist/{claude-sdk-session-4whxere4.js → claude-sdk-session-q49ghmh9.js} +12402 -11850
- package/dist/{cli-ne7smj1b.js → cli-01xvj1rq.js} +10 -10
- package/dist/{cli-nwrdx840.js → cli-035vekcw.js} +3 -3
- package/dist/{cli-9xf7fdtp.js → cli-0pd8hzhc.js} +29 -6
- package/dist/{cli-tmhsxhb8.js → cli-0veb92a3.js} +28 -6
- package/dist/{cli-c3rk1v0x.js → cli-10jesr25.js} +3 -3
- package/dist/{cli-6thk4jz3.js → cli-1y7yywmj.js} +6 -6
- package/dist/{cli-6r2f7edk.js → cli-20krdhz5.js} +47 -19
- package/dist/{cli-rfs4vddv.js → cli-29rja109.js} +39 -20
- package/dist/cli-2m1ktfzz.js +17795 -0
- package/dist/{cli-na2pxe4f.js → cli-2pwa0q4d.js} +15 -4
- package/dist/{cli-7a93cv8c.js → cli-4mengw46.js} +441 -43
- package/dist/{cli-94b48jhk.js → cli-5twdke5x.js} +16 -14
- package/dist/{cli-7a0sde2x.js → cli-6cagzc96.js} +9 -0
- package/dist/cli-6cvfxs8r.js +47 -0
- package/dist/{cli-w1apjecb.js → cli-711vwbxn.js} +2 -2
- package/dist/{cli-r4fqfpwf.js → cli-78vv7446.js} +50 -27
- package/dist/{cli-srqq3gc5.js → cli-7n6s5man.js} +5 -5
- package/dist/{cli-m89t9jdf.js → cli-7x0g4sn1.js} +15416 -16024
- package/dist/{cli-2bw3w47j.js → cli-8wwxw8a3.js} +1 -1
- package/dist/{cli-yatxqynm.js → cli-9ha6hs2d.js} +1 -290
- package/dist/{cli-ywm1azg9.js → cli-9jzdj90z.js} +8 -4
- package/dist/cli-9traj3dn.js +638 -0
- package/dist/{cli-smcrrmhy.js → cli-agzebbd5.js} +9 -9
- package/dist/{cli-c5km5znr.js → cli-c8r3kzzb.js} +1 -1
- package/dist/cli-cvv9k0hh.js +10143 -0
- package/dist/{cli-anzdk0z4.js → cli-d9286m9h.js} +2 -2
- package/dist/cli-e3g5mbkz.js +776 -0
- package/dist/cli-f527ce74.js +781 -0
- package/dist/{cli-gmdajfw5.js → cli-gxzkg1de.js} +5020 -1729
- package/dist/{cli-451ks6aw.js → cli-h1arqn31.js} +1 -1
- package/dist/cli-hjwmhcg1.js +10622 -0
- package/dist/{cli-jpc4r224.js → cli-hqr88ew6.js} +19 -3
- package/dist/{cli-h7k0xtry.js → cli-hvqbtna4.js} +4 -1256
- package/dist/{cli-cd0hv9nh.js → cli-j67mh2vg.js} +2 -2
- package/dist/cli-jta2eyzc.js +619 -0
- package/dist/{cli-wd0hz6ah.js → cli-kbrt8gqa.js} +9 -91
- package/dist/cli-kceah1eh.js +92 -0
- package/dist/{cli-d603qf86.js → cli-ksphgh48.js} +10 -8
- package/dist/{cli-3nxdmjrc.js → cli-mgz4nbgg.js} +4 -4
- package/dist/{cli-saqyage0.js → cli-mz5as5ha.js} +179 -27
- package/dist/cli-n2wq4j7m.js +6985 -0
- package/dist/{cli-ppy4nnnh.js → cli-n8ndw8j7.js} +2 -2
- package/dist/{cli-1w0vj3gw.js → cli-naqzr17j.js} +7 -7
- package/dist/{cli-0a7mm3zp.js → cli-nm1p8jfr.js} +25 -21
- package/dist/{cli-wrh08zjd.js → cli-p3zbc1rw.js} +5 -18
- package/dist/{cli-hsem16hb.js → cli-pe05f8yk.js} +29 -6
- package/dist/{cli-5wpw4rab.js → cli-qmzsbkvy.js} +5 -5
- package/dist/{cli-bv2etw2y.js → cli-qnm4e9e4.js} +99 -590
- package/dist/{cli-1x7da0de.js → cli-qqy4q48b.js} +8 -8
- package/dist/{cli-r44t9wqc.js → cli-r106725k.js} +2 -2
- package/dist/{cli-5er5gjbm.js → cli-r35rw5de.js} +15 -15
- package/dist/{cli-v3zhnxsb.js → cli-r610p9bs.js} +2 -2
- package/dist/{cli-7jykv7ef.js → cli-rc6pf5kv.js} +1 -1
- package/dist/{cli-x119kdba.js → cli-rdxm77k3.js} +1 -1
- package/dist/cli-rhs9pz33.js +294 -0
- package/dist/{cli-0p3enk35.js → cli-s69nfyeh.js} +9 -1
- package/dist/{cli-0kxf81jj.js → cli-sawv63e8.js} +2 -2
- package/dist/{cli-e3pmyt39.js → cli-sg19gbf0.js} +1 -1
- package/dist/{cli-d161g69q.js → cli-shk7r5cs.js} +57 -6
- package/dist/{cli-7pz3b7x5.js → cli-sksetb2q.js} +36 -1
- package/dist/{cli-014vns2y.js → cli-stfs0k5s.js} +208 -525
- package/dist/{cli-db3m6zdt.js → cli-t02z59f2.js} +1 -1
- package/dist/{cli-b07hr3bt.js → cli-txqb9s38.js} +2 -2
- package/dist/{cli-s8z6x4b4.js → cli-v7g551te.js} +225 -113
- package/dist/{cli-rfz2ve55.js → cli-vgqzp4em.js} +3341 -955
- package/dist/{cli-7avy4v8w.js → cli-w1q7h2r2.js} +5 -3
- package/dist/{cli-rcp5aqdw.js → cli-w7m81tb7.js} +1 -1
- package/dist/cli-wfnemr1t.js +86 -0
- package/dist/cli-wmgrkscj.js +23254 -0
- package/dist/{cli-qm1448f9.js → cli-wms6x9db.js} +8 -8
- package/dist/{cli-tadfgd0t.js → cli-x1r545x8.js} +33 -4
- package/dist/{cli-xc7p7s3g.js → cli-xczsgshn.js} +6 -6
- package/dist/{cli-fmhj1ehj.js → cli-y3167wt1.js} +882 -271
- package/dist/{cli-r0byd61h.js → cli-yjmqpxt3.js} +17 -16
- package/dist/{cli-81r1wjyv.js → cli-z780ec7c.js} +1 -1
- package/dist/{cli-phcqp1b9.js → cli-zm9t2vde.js} +2 -2
- package/dist/cli.js +34 -49
- package/dist/{codex-adapter-r3dn4fp5.js → codex-adapter-4z16v9n0.js} +15 -14
- package/dist/{codex-login-841kv5fk.js → codex-login-pkepy2j1.js} +3 -2
- package/dist/{codex-session-runner-fwt793h4.js → codex-session-runner-rvms9y2x.js} +15 -14
- package/dist/{commands-z8fq9qna.js → commands-2a9rtyat.js} +11 -10
- package/dist/{controller-hq5ggpcp.js → controller-3k3madbn.js} +5 -4
- package/dist/{controllers-connect-3mf2btyj.js → controllers-connect-v9yn8zb9.js} +42 -37
- package/dist/{cursor-adapter-q8pgv5qa.js → cursor-adapter-98gbhyzn.js} +7 -6
- package/dist/{db-qfpq4bt7.js → db-eywwsnjw.js} +30 -9
- package/dist/{db-yyhqqrbf.js → db-ncypk9np.js} +12 -11
- package/dist/{devin-adapter-xgtj680j.js → devin-adapter-zeq8b9gz.js} +3 -2
- package/dist/{dispatcher-x0x7qfcq.js → dispatcher-w94kc575.js} +38 -33
- package/dist/{docker-f503k9p0.js → docker-b1e4cqab.js} +3 -2
- package/dist/{dsh-adapter-34etvb5m.js → dsh-adapter-47ztej36.js} +7 -6
- package/dist/{e2b-66xra4az.js → e2b-bbt8ey45.js} +4 -3
- package/dist/{e2b-xwhyj8cw.js → e2b-dp804sen.js} +4 -3
- package/dist/{event-bus-vjtv82gm.js → event-bus-j2jdg3qb.js} +3 -2
- package/dist/{external-channel-h1fjecwe.js → external-channel-zrkg8ar9.js} +11 -10
- package/dist/{google-generative-ai-szdxbpqg.js → google-generative-ai-g8db7x0f.js} +4 -2
- package/dist/{google-vertex-qzw3p36d.js → google-vertex-r2692q0r.js} +4 -2
- package/dist/{grok-adapter-e7mr287e.js → grok-adapter-s9ncp9vy.js} +18 -17
- package/dist/{handlers-znb9n7d4.js → handlers-kqftvjgw.js} +41 -36
- package/dist/{heartbeat-bm4qkn8d.js → heartbeat-9q96p8v9.js} +43 -38
- package/dist/{hook-254r4mza.js → hook-56qe10dp.js} +11 -23
- package/dist/{hook-xaa3q80s.js → hook-yy6rw42k.js} +12 -11
- package/dist/{http-3dgrgp8y.js → http-r2dnb8f8.js} +2411 -275
- package/dist/{index-fx3jqq1e.js → index-3gtmkhc6.js} +38 -33
- package/dist/{index-bdsqa799.js → index-3k5hkz7r.js} +43 -38
- package/dist/index-52j1aja4.js +3465 -0
- package/dist/{index-g2byveez.js → index-5e101240.js} +38 -33
- package/dist/{index-2ybk7khy.js → index-5wyfjc2c.js} +845 -683
- package/dist/index-9gw58n4k.js +193 -0
- package/dist/index-9j87mcm8.js +56305 -0
- package/dist/index-bsmcresk.js +79424 -0
- package/dist/index-mh85qhec.js +475 -0
- package/dist/{index-jd7sejm2.js → index-vxvhxxbn.js} +10 -9
- package/dist/index-we27kd31.js +12810 -0
- package/dist/{keepalive-6ywhpja1.js → keepalive-psj6j54c.js} +12 -11
- package/dist/{lead-cw45n21s.js → lead-hajz4688.js} +61 -56
- package/dist/{maintenance-ss1a1ge9.js → maintenance-ps02sb5m.js} +10 -9
- package/dist/{node-fkajaq96.js → node-mwb5r697.js} +2 -1
- package/dist/{oauth-refresh-sweep-3c6f8vyy.js → oauth-refresh-sweep-0284h93b.js} +11 -10
- package/dist/{onboard-8hzdhc1k.js → onboard-rbf6bg01.js} +11 -3
- package/dist/{opencode-adapter-qbchbcfz.js → opencode-adapter-13dcatgq.js} +18 -13
- package/dist/{otel-impl-e6mnvc4v.js → otel-impl-zvqcbhp7.js} +242 -868
- package/dist/{pi-mono-adapter-3c9g9snh.js → pi-mono-adapter-xxy47q4v.js} +244 -106
- package/dist/{pricing-refresh-gedkjdw0.js → pricing-refresh-kefx9v3t.js} +12 -11
- package/dist/{rbac-roles-dt4vh1yy.js → rbac-roles-3m36rxm2.js} +11 -10
- package/dist/{rbac-roles-eszdg6pm.js → rbac-roles-z76xv0hq.js} +12 -11
- package/dist/{render-v2-907cy6sa.js → render-v2-wz73bs25.js} +18 -14
- package/dist/{resume-42stcaz0.js → resume-k4wzge8w.js} +25 -21
- package/dist/{runtime-qfry88v2.js → runtime-sa2vr16g.js} +2 -2
- package/dist/{setup-adbc1c10.js → setup-2fp2pypp.js} +2 -2
- package/dist/{virtual-modules-rtmt494q.js → virtual-modules-9gkxqrap.js} +6 -5
- package/dist/{work-objects-wpj8ck95.js → work-objects-6k0ywz3m.js} +41 -36
- package/dist/{worker-bzdra9rf.js → worker-5v3rxsdh.js} +61 -56
- package/dist/{x-qfmygqqv.js → x-4mtdeym1.js} +3 -2
- package/openapi.json +1279 -329
- package/package.json +15 -15
- package/src/agentmail/handlers.ts +21 -11
- package/src/apps/definition.ts +16 -0
- package/src/azure-devops/api.ts +52 -2
- package/src/azure-devops/boards-sync.ts +50 -20
- package/src/azure-devops/index.ts +1 -0
- package/src/azure-devops/outbound.ts +95 -0
- package/src/be/boot-seeds.ts +11 -0
- package/src/be/config-refs.ts +60 -0
- package/src/be/db/model-profiles.ts +315 -0
- package/src/be/db/page-versions.ts +15 -0
- package/src/be/db/runtime.ts +35 -8
- package/src/be/db/skill-name-resolution.ts +36 -0
- package/src/be/db/tasks/read.ts +237 -0
- package/src/be/db/tasks/write.ts +7 -0
- package/src/be/db.ts +87 -36
- package/src/be/migrations/215_swarm_config_export_to_env.sql +34 -0
- package/src/be/migrations/216_task_resolved_effort.sql +5 -0
- package/src/be/migrations/217_chat_sdk_state.sql +104 -0
- package/src/be/migrations/219_relabel_pi_context_compactions.sql +22 -0
- package/src/be/migrations/220_model_profiles.sql +137 -0
- package/src/be/model-catalog-store.ts +5 -1
- package/src/be/model-tier-resolution.ts +155 -10
- package/src/be/model-validation.ts +12 -2
- package/src/be/models-catalog.ts +26 -1
- package/src/be/modelsdev-cache.json +198 -63
- package/src/be/modelsdev-cache.ts +9 -1
- package/src/be/script-credential-broker.ts +39 -2
- package/src/be/scripts/run-saved.ts +1 -0
- package/src/be/scripts/typecheck.ts +22 -8
- package/src/be/secret-registry.ts +6 -2
- package/src/be/seed/runner.ts +13 -1
- package/src/be/seed/state-db.ts +5 -0
- package/src/be/seed/types.ts +6 -0
- package/src/be/seed-model-profiles.ts +41 -0
- package/src/be/seed-pricing.ts +19 -2
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +368 -0
- package/src/be/seed-scripts/catalog/ops-catalog-audit.inline.ts +1 -1
- package/src/be/seed-scripts/catalog/ops-catalog-audit.ts +1 -1
- package/src/be/seed-scripts/index.ts +9 -0
- package/src/be/seed-skills/bundled-files.generated.json +0 -18
- package/src/be/seed-skills/index.ts +104 -3
- package/src/be/swarm-config-guard.ts +53 -0
- package/src/cli.tsx +0 -16
- package/src/commands/onboard/non-interactive.ts +4 -2
- package/src/commands/provider-credentials.ts +52 -6
- package/src/commands/runner.ts +193 -71
- package/src/e2b/env.ts +5 -0
- package/src/extensions/catalog.generated.json +17 -0
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +45 -0
- package/src/extensions/dispatcher.ts +7 -0
- package/src/extensions/loader.ts +10 -5
- package/src/extensions/post-bridge.ts +40 -0
- package/src/github/handlers.ts +11 -4
- package/src/heartbeat/heartbeat.ts +2 -1
- package/src/heartbeat/templates.ts +8 -5
- package/src/hooks/hook.ts +0 -26
- package/src/http/agents.ts +49 -2
- package/src/http/all-routes.ts +1 -1
- package/src/http/apps.ts +30 -3
- package/src/http/config.ts +62 -19
- package/src/http/core.ts +8 -0
- package/src/http/index.ts +25 -3
- package/src/http/integrations.ts +88 -1
- package/src/http/mcp.ts +15 -5
- package/src/http/model-profiles.ts +303 -0
- package/src/http/page-proxy.ts +2 -4
- package/src/http/pages-public.ts +13 -7
- package/src/http/pages.ts +3 -13
- package/src/http/poll.ts +42 -71
- package/src/http/requested-by.ts +54 -0
- package/src/http/script-runs.ts +1 -1
- package/src/http/scripts.ts +26 -2
- package/src/http/stats.ts +1 -30
- package/src/http/tasks.ts +79 -5
- package/src/http/utils.ts +14 -0
- package/src/http/webhooks.ts +160 -3
- package/src/http/x.ts +1 -0
- package/src/integrations/chat-sdk/adapters.ts +129 -0
- package/src/integrations/chat-sdk/attachments.ts +232 -0
- package/src/integrations/chat-sdk/background.ts +36 -0
- package/src/integrations/chat-sdk/commands.ts +194 -0
- package/src/integrations/chat-sdk/config.ts +198 -0
- package/src/integrations/chat-sdk/discord-api.ts +63 -0
- package/src/integrations/chat-sdk/discord-gateway.ts +185 -0
- package/src/integrations/chat-sdk/handlers.ts +28 -0
- package/src/integrations/chat-sdk/inbound.ts +426 -0
- package/src/integrations/chat-sdk/limits.ts +48 -0
- package/src/integrations/chat-sdk/logger.ts +81 -0
- package/src/integrations/chat-sdk/outbound.ts +123 -0
- package/src/integrations/chat-sdk/relay.ts +172 -0
- package/src/integrations/chat-sdk/router.ts +169 -0
- package/src/integrations/chat-sdk/runtime.ts +351 -0
- package/src/integrations/chat-sdk/schema.ts +245 -0
- package/src/integrations/chat-sdk/state.ts +243 -0
- package/src/integrations/chat-sdk/status.ts +244 -0
- package/src/integrations/chat-sdk/steering.ts +58 -0
- package/src/integrations/chat-sdk/teams-origin.ts +77 -0
- package/src/integrations/chat-sdk/telegram-api.ts +56 -0
- package/src/integrations/chat-sdk/templates.ts +16 -0
- package/src/integrations/chat-sdk/test-hooks.ts +37 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +100 -0
- package/src/integrations/chat-sdk/typing.ts +65 -0
- package/src/{artifact-sdk → pages}/feedback-overlay.ts +65 -6
- package/src/pages/version.ts +4 -5
- package/src/prompts/base-prompt.ts +111 -45
- package/src/providers/acp-target-catalog.ts +6 -0
- package/src/providers/acp-targets.ts +56 -3
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/claude-adapter.ts +1 -1
- package/src/providers/claude-flag-settings.ts +17 -5
- package/src/providers/claude-managed-adapter.ts +1 -1
- package/src/providers/claude-session-events.ts +6 -1
- package/src/providers/dsh-adapter.ts +1 -1
- package/src/providers/opencode-adapter.ts +243 -26
- package/src/providers/opencode-swarm-plugin.ts +31 -0
- package/src/providers/pi-mono-adapter.ts +398 -153
- package/src/providers/pi-mono-extension.ts +17 -3
- package/src/providers/pricing-sources.md +33 -2
- package/src/providers/reasoning-effort.ts +37 -0
- package/src/providers/types.ts +6 -2
- package/src/rbac/legacy-policy.ts +16 -2
- package/src/rbac/permissions.ts +26 -0
- package/src/scheduler/deferred-task-waits.ts +18 -5
- package/src/scheduler/scheduler.ts +11 -3
- package/src/scripts-runtime/executors/quickjs-prelude.ts +75 -6
- package/src/scripts-runtime/executors/quickjs-runner.ts +85 -8
- package/src/scripts-runtime/executors/quickjs-web-shims.ts +1041 -0
- package/src/scripts-runtime/extract-args-schema.ts +9 -8
- package/src/scripts-runtime/loader.ts +19 -7
- package/src/scripts-runtime/quickjs-compat.ts +464 -0
- package/src/scripts-runtime/sdk-allowlist.ts +12 -6
- package/src/scripts-runtime/swarm-sdk.ts +0 -11
- package/src/scripts-runtime/types/stdlib.d.ts +39 -15
- package/src/scripts-runtime/types/swarm-extension.d.ts +66 -1
- package/src/scripts-runtime/types/swarm-sdk.d.ts +39 -15
- package/src/server.ts +62 -19
- package/src/slack/blocks.ts +4 -2
- package/src/slack/event-dedup.ts +1 -1
- package/src/slack/reaction-shortcode.ts +14 -0
- package/src/slack/render-v2.ts +12 -7
- package/src/slack/responses.ts +5 -4
- package/src/slack/thread-buffer.ts +41 -22
- package/src/tasks/additive-buffer.ts +4 -2
- package/src/tasks/context-key.ts +60 -1
- package/src/tasks/model-pin.ts +67 -0
- package/src/tasks/worker-follow-up.ts +15 -33
- package/src/tests/acp-adapter.test.ts +42 -0
- package/src/tests/agentmail-filters.test.ts +47 -0
- package/src/tests/api-drain-worker-e2e.test.ts +1 -6
- package/src/tests/apps-spike2.test.ts +35 -0
- package/src/tests/azure-devops-outbound.test.ts +420 -0
- package/src/tests/base-prompt.test.ts +58 -54
- package/src/tests/chat-sdk-commands.test.ts +191 -0
- package/src/tests/chat-sdk-config.test.ts +334 -0
- package/src/tests/chat-sdk-discord-api.test.ts +68 -0
- package/src/tests/chat-sdk-discord-gateway.test.ts +252 -0
- package/src/tests/chat-sdk-discord-webhook.test.ts +126 -0
- package/src/tests/chat-sdk-fields-sync.test.ts +50 -0
- package/src/tests/chat-sdk-harness.ts +146 -0
- package/src/tests/chat-sdk-inbound.test.ts +363 -0
- package/src/tests/chat-sdk-relay.test.ts +470 -0
- package/src/tests/chat-sdk-reload.test.ts +128 -0
- package/src/tests/chat-sdk-shutdown.test.ts +220 -0
- package/src/tests/chat-sdk-slack.test.ts +268 -0
- package/src/tests/chat-sdk-state.test.ts +163 -0
- package/src/tests/chat-sdk-status-route.test.ts +382 -0
- package/src/tests/chat-sdk-teams.test.ts +277 -0
- package/src/tests/chat-sdk-tools.test.ts +520 -0
- package/src/tests/chat-sdk-typing.test.ts +120 -0
- package/src/tests/chat-sdk-webhook-telegram.test.ts +200 -0
- package/src/tests/claude-adapter-binary.test.ts +9 -4
- package/src/tests/claude-flag-settings.test.ts +11 -3
- package/src/tests/claude-managed-adapter.test.ts +1 -1
- package/src/tests/claude-sdk-lifecycle.test.ts +9 -3
- package/src/tests/claude-thinking-tokens.test.ts +57 -0
- package/src/tests/claude-worker-parity.test.ts +2 -7
- package/src/tests/config-env-export-chat-sdk.test.ts +11 -0
- package/src/tests/config-refs.test.ts +66 -0
- package/src/tests/context-key.test.ts +19 -0
- package/src/tests/cors-allowlist.test.ts +25 -0
- package/src/tests/create-page-tool.test.ts +18 -0
- package/src/tests/credential-check.test.ts +139 -0
- package/src/tests/credentials.test.ts +21 -0
- package/src/tests/db-runtime.test.ts +61 -0
- package/src/tests/db-task-read-contract.test.ts +22 -0
- package/src/tests/db-task-write-contract.test.ts +11 -0
- package/src/tests/deferred-task-wake.test.ts +78 -1
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/enabled-capabilities.test.ts +20 -0
- package/src/tests/entrypoint-api-readiness.test.ts +14 -8
- package/src/tests/entrypoint-config-env-export.test.ts +5 -2
- package/src/tests/entrypoint-export-to-env.test.ts +78 -0
- package/src/tests/env-flag.test.ts +1 -0
- package/src/tests/explicit-model-validation.test.ts +105 -1
- package/src/tests/extensions-catalog.test.ts +1 -0
- package/src/tests/extensions-example-comms-adherence-gate.test.ts +413 -0
- package/src/tests/extensions-example-route-chat-channel.test.ts +154 -0
- package/src/tests/extensions-loader.test.ts +15 -0
- package/src/tests/extensions-post-bridge.test.ts +51 -0
- package/src/tests/fetch-resolved-env.test.ts +128 -0
- package/src/tests/fixtures/chat-sdk/telegram-private-text.json +10 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/hooks.ts +27 -0
- package/src/tests/fixtures/extensions/route-chat-channel-to-agent/manifest.json +9 -0
- package/src/tests/fixtures/openai-compatible-registry-extension.child.ts +146 -0
- package/src/tests/fixtures/runner-legacy-resume-prompt.ts +122 -0
- package/src/tests/github-handlers.test.ts +35 -0
- package/src/tests/harness-provider-resolution.test.ts +12 -0
- package/src/tests/heartbeat-checklist.test.ts +3 -2
- package/src/tests/heartbeat-jev-gate-credentials.test.ts +168 -0
- package/src/tests/heartbeat-jev-gate.test.ts +385 -0
- package/src/tests/hook-runtime-close.test.ts +0 -2
- package/src/tests/http-api-integration.test.ts +0 -25
- package/src/tests/migration-046-budgets.test.ts +17 -16
- package/src/tests/migration-217-chat-sdk-state.test.ts +113 -0
- package/src/tests/model-profile-backcompat.test.ts +327 -0
- package/src/tests/model-profile-providers.test.ts +302 -0
- package/src/tests/model-profile-runtime-secrets.test.ts +223 -0
- package/src/tests/model-profiles-api.test.ts +614 -0
- package/src/tests/model-tier-resolution.test.ts +93 -0
- package/src/tests/models-catalog.test.ts +42 -1
- package/src/tests/openai-compatible-providers.test.ts +134 -0
- package/src/tests/openai-compatible-registry-extension.test.ts +42 -0
- package/src/tests/opencode-adapter.test.ts +216 -2
- package/src/tests/opencode-helmcode-sdk.test.ts +201 -0
- package/src/tests/opencode-shell-env.test.ts +145 -0
- package/src/tests/openrouter-base-url.test.ts +101 -151
- package/src/tests/page-proxy.test.ts +1 -1
- package/src/tests/pages-browser-sdk.test.ts +76 -0
- package/src/tests/pages-feedback-keys.test.ts +121 -0
- package/src/tests/pages-feedback.test.ts +4 -1
- package/src/tests/paused-tasks-requested-by.test.ts +102 -0
- package/src/tests/pi-context-compaction.test.ts +193 -0
- package/src/tests/pi-custom-provider-fake-server.test.ts +442 -0
- package/src/tests/pi-mono-adapter.test.ts +385 -5
- package/src/tests/pi-shell-env.test.ts +170 -0
- package/src/tests/profile-claim.test.ts +269 -0
- package/src/tests/prompt-template-remaining.test.ts +35 -0
- package/src/tests/quickjs-compat.test.ts +213 -0
- package/src/tests/rbac-engine.test.ts +32 -3
- package/src/tests/runner-exit-after-tasks.test.ts +0 -4
- package/src/tests/runner-legacy-resume-prompt.test.ts +64 -0
- package/src/tests/script-connections.test.ts +6 -0
- package/src/tests/script-executor-conformance.test.ts +252 -1
- package/src/tests/script-executor-quickjs.test.ts +96 -0
- package/src/tests/script-runs-http.test.ts +89 -0
- package/src/tests/scripts-http.test.ts +217 -1
- package/src/tests/scripts-only-gating.test.ts +2 -3
- package/src/tests/scripts-runtime.test.ts +58 -40
- package/src/tests/secret-scrubber.test.ts +96 -0
- package/src/tests/seed-model-profiles.test.ts +174 -0
- package/src/tests/seed-scripts.test.ts +2 -2
- package/src/tests/seed-skills-bundled-files.test.ts +45 -53
- package/src/tests/seed-skills-retire.test.ts +182 -0
- package/src/tests/send-task-requester-gate.test.ts +58 -0
- package/src/tests/session-cost-recompute-unit.test.ts +46 -0
- package/src/tests/skill-get-name-resolution.test.ts +137 -0
- package/src/tests/skill-invocations.test.ts +4 -2
- package/src/tests/slack-blocks.test.ts +36 -0
- package/src/tests/slack-inline-output.test.ts +14 -0
- package/src/tests/slack-reaction-config.test.ts +20 -0
- package/src/tests/slack-render-v2.test.ts +37 -0
- package/src/tests/slack-thread-buffer.test.ts +98 -1
- package/src/tests/sonnet-5-5-registry.test.ts +9 -1
- package/src/tests/swarm-config-export-to-env.test.ts +267 -0
- package/src/tests/swarm-config-reserved-keys.test.ts +16 -0
- package/src/tests/swarm-diff.test.ts +1 -1
- package/src/tests/task-model-effort-rerun.test.ts +164 -0
- package/src/tests/task-session-prompts.test.ts +132 -0
- package/src/tests/task-tool-manifest.test.ts +14 -0
- package/src/tests/task-tools-ctx.test.ts +2 -0
- package/src/tests/tool-annotations.test.ts +6 -6
- package/src/tests/ui-logs-parser.test.ts +43 -0
- package/src/tests/used-by-route.test.ts +6 -0
- package/src/tests/vercel-ai-gateway.test.ts +149 -0
- package/src/tests/workflow-llm.test.ts +61 -0
- package/src/tests/workflow-swarm-script.test.ts +38 -0
- package/src/tests/workflow-wait-filter.test.ts +5 -3
- package/src/tools/chat-access.ts +41 -0
- package/src/tools/chat-open-dm.ts +59 -0
- package/src/tools/chat-post.ts +74 -0
- package/src/tools/chat-read-thread.ts +100 -0
- package/src/tools/chat-reply.ts +75 -0
- package/src/tools/create-page.ts +3 -13
- package/src/tools/model-catalog/index.ts +2 -1
- package/src/tools/model-profiles/list-model-profiles.ts +54 -0
- package/src/tools/register-chat-channel.ts +139 -0
- package/src/tools/request-human-input.ts +11 -3
- package/src/tools/script-apis.ts +5 -1
- package/src/tools/script-upsert.ts +4 -1
- package/src/tools/send-task.ts +48 -1
- package/src/tools/skills/skill-get.ts +17 -9
- package/src/tools/swarm-config/get-config.ts +2 -1
- package/src/tools/swarm-config/list-config.ts +2 -1
- package/src/tools/swarm-config/set-config.ts +16 -3
- package/src/tools/system-one-decide.ts +104 -0
- package/src/tools/task-action.ts +22 -1
- package/src/tools/tool-config.ts +14 -6
- package/src/types.ts +48 -3
- package/src/utils/config-env-export.ts +74 -0
- package/src/utils/credentials.test.ts +92 -0
- package/src/utils/credentials.ts +52 -4
- package/src/utils/harness-provider.ts +15 -6
- package/src/utils/runtime-model-catalog.ts +11 -1
- package/src/utils/secret-scrubber.ts +86 -10
- package/src/utils/task-tool-manifest.ts +19 -2
- package/src/utils/vcs-repo-match.ts +29 -0
- package/src/workflows/executors/raw-llm.ts +8 -3
- package/src/workflows/executors/swarm-script.ts +1 -0
- package/src/workflows/executors/system-one-decision.ts +21 -11
- package/src/workflows/executors/workflow-llm.ts +22 -0
- package/src/workflows/index.ts +21 -12
- package/templates/extensions/README.md +1 -0
- package/templates/extensions/comms-adherence-gate/README.md +88 -0
- package/templates/extensions/comms-adherence-gate/hooks.ts +489 -0
- package/templates/extensions/comms-adherence-gate/manifest.json +8 -0
- package/templates/skills/agent-browser/SKILL.md +1 -1
- package/templates/skills/agent-browser/content.md +1 -1
- package/templates/skills/apps/SKILL.md +8 -1
- package/templates/skills/apps/content.md +8 -1
- package/templates/skills/chat-sdk/config.json +14 -0
- package/templates/skills/chat-sdk/content.md +84 -0
- package/templates/skills/composio-gmail/content.md +7 -0
- package/templates/skills/composio-google-docs/content.md +1 -1
- package/templates/skills/email-domain-health/config.json +14 -0
- package/templates/skills/email-domain-health/content.md +131 -0
- package/templates/skills/kv-storage/content.md +2 -2
- package/templates/skills/pages/content.md +8 -10
- package/templates/skills/swarm-extensions/content.md +2 -0
- package/templates/skills/swarm-scripts/SKILL.md +4 -2
- package/templates/skills/swarm-scripts/config.json +1 -1
- package/templates/skills/swarm-scripts/content.md +4 -2
- package/templates/skills/workflow-iterate/content.md +38 -0
- package/dist/artifact-eczsknc3.js +0 -3843
- package/dist/cli-42qhyvwx.js +0 -33
- package/dist/cli-bd957dgb.js +0 -153
- package/dist/cli-q51yprfq.js +0 -1104
- package/dist/cli-t1ze64h3.js +0 -811
- package/dist/cli-tcc4wd5d.js +0 -56471
- package/dist/index-9ch1n761.js +0 -1102
- package/src/artifact-sdk/index.ts +0 -2
- package/src/artifact-sdk/localtunnel.d.ts +0 -20
- package/src/artifact-sdk/port.ts +0 -12
- package/src/artifact-sdk/server.ts +0 -183
- package/src/artifact-sdk/tunnel.ts +0 -19
- package/src/commands/artifact.ts +0 -249
- package/src/http/ecosystem.ts +0 -77
- package/src/tests/artifact-commands.test.ts +0 -92
- package/src/tests/artifact-sdk.test.ts +0 -793
- package/src/tests/register-service-security.test.ts +0 -194
- package/src/tools/list-services.ts +0 -107
- package/src/tools/register-service.ts +0 -177
- package/src/tools/unregister-service.ts +0 -73
- package/src/tools/update-service-status.ts +0 -96
- package/templates/skills/artifacts/config.json +0 -14
- package/templates/skills/artifacts/content.md +0 -344
- package/templates/skills/artifacts/files/examples/approval-flow.ts +0 -34
- package/templates/skills/artifacts/files/examples/hono-dashboard.ts +0 -31
- package/templates/skills/artifacts/files/examples/multi-artifact.ts +0 -20
- package/templates/skills/artifacts/files/examples/static-report.sh +0 -17
- /package/src/{artifact-sdk → pages}/browser-sdk.ts +0 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
import { pathToFileURL } from "node:url";
|
|
11
11
|
import { toJSONSchema } from "zod";
|
|
12
12
|
|
|
13
|
-
async function createShims(
|
|
13
|
+
async function createShims(moduleDir: string): Promise<void> {
|
|
14
14
|
const runtimeDir = process.env.SCRIPT_RUNTIME_DIR;
|
|
15
15
|
const shims: [string, URL][] = [
|
|
16
16
|
[
|
|
@@ -35,7 +35,7 @@ async function createShims(tmpdir: string): Promise<void> {
|
|
|
35
35
|
]),
|
|
36
36
|
];
|
|
37
37
|
for (const [name, url] of shims) {
|
|
38
|
-
const dir = `${
|
|
38
|
+
const dir = `${moduleDir}/node_modules/${name}`;
|
|
39
39
|
await Bun.$`mkdir -p ${dir}`.quiet();
|
|
40
40
|
await Bun.write(`${dir}/package.json`, JSON.stringify({ type: "module", main: "index.ts" }));
|
|
41
41
|
await Bun.write(`${dir}/index.ts`, `export * from ${JSON.stringify(url.href)};\n`);
|
|
@@ -52,14 +52,15 @@ if (!sourceFile || !resultFile || !tmpdir) {
|
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
try {
|
|
55
|
-
|
|
55
|
+
// Subdirectory, not the tmpdir itself: this harness runs with cwd = tmpdir,
|
|
56
|
+
// and Bun (>= 1.3.12) snapshots the cwd listing at startup — a file or
|
|
57
|
+
// node_modules written into cwd after launch is invisible to the module
|
|
58
|
+
// resolver. See the same fix in eval-harness.ts.
|
|
59
|
+
const moduleDir = `${tmpdir}/user-module`;
|
|
60
|
+
await createShims(moduleDir);
|
|
56
61
|
|
|
57
62
|
const source = await Bun.file(sourceFile).text();
|
|
58
|
-
|
|
59
|
-
// and Bun (>= 1.3.12) snapshots the cwd listing at startup — a file written
|
|
60
|
-
// into cwd after launch is invisible to the module resolver. See the same
|
|
61
|
-
// fix in eval-harness.ts.
|
|
62
|
-
const userModulePath = `${tmpdir}/user-module/user-script.ts`;
|
|
63
|
+
const userModulePath = `${moduleDir}/user-script.ts`;
|
|
63
64
|
await Bun.write(userModulePath, source);
|
|
64
65
|
|
|
65
66
|
let mod: Record<string, unknown>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getApiKey } from "../utils/api-key";
|
|
2
|
-
import {
|
|
2
|
+
import { getMcpBaseUrl } from "../utils/constants";
|
|
3
|
+
import { createValueScrubber, scrubObject, scrubSecrets } from "../utils/secret-scrubber";
|
|
3
4
|
import type { ScriptApiConnectionDescriptor, ScriptMcpConnectionDescriptor } from "./api-types";
|
|
4
5
|
import type { FailedCredentialBinding } from "./credential-broker";
|
|
5
6
|
import { buildEgressSecrets } from "./egress-secrets";
|
|
@@ -66,7 +67,7 @@ async function buildConfigPayload(input: RunScriptInput): Promise<SwarmConfigPay
|
|
|
66
67
|
apiKey: { value: apiKey, isSecret: true },
|
|
67
68
|
agentId: { value: input.agentId, isSecret: false },
|
|
68
69
|
mcpBaseUrl: {
|
|
69
|
-
value: input.mcpBaseUrl ??
|
|
70
|
+
value: input.mcpBaseUrl ?? getMcpBaseUrl(),
|
|
70
71
|
isSecret: false,
|
|
71
72
|
},
|
|
72
73
|
...(input.runtimeInstanceId
|
|
@@ -94,12 +95,21 @@ export async function runScript(input: RunScriptInput): Promise<RunScriptOutput>
|
|
|
94
95
|
};
|
|
95
96
|
}
|
|
96
97
|
|
|
98
|
+
// The global scrubber skips values under its length floor, so this run's own
|
|
99
|
+
// secret config is redacted here at any length before the global pass. Built
|
|
100
|
+
// before the import check: its diagnostic quotes source, which can hold a value.
|
|
101
|
+
const runSecrets = createValueScrubber(
|
|
102
|
+
Object.entries(input.userConfig ?? {})
|
|
103
|
+
.filter(([, entry]) => entry.isSecret)
|
|
104
|
+
.map(([key, entry]) => ({ value: entry.value, name: `config:${key}` })),
|
|
105
|
+
);
|
|
106
|
+
|
|
97
107
|
const imports = validateScriptImports(input.source);
|
|
98
108
|
if (!imports.ok) {
|
|
99
109
|
return {
|
|
100
110
|
result: undefined,
|
|
101
111
|
stdout: "",
|
|
102
|
-
stderr: imports.diagnostic,
|
|
112
|
+
stderr: scrubSecrets(runSecrets.text(imports.diagnostic)),
|
|
103
113
|
truncated: { stdout: false, stderr: false },
|
|
104
114
|
durationMs: 0,
|
|
105
115
|
exitCode: 1,
|
|
@@ -133,9 +143,11 @@ export async function runScript(input: RunScriptInput): Promise<RunScriptOutput>
|
|
|
133
143
|
|
|
134
144
|
return {
|
|
135
145
|
...output,
|
|
136
|
-
result: scrubObject(output.result),
|
|
137
|
-
stdout: scrubSecrets(output.stdout),
|
|
138
|
-
stderr: scrubSecrets(output.stderr),
|
|
139
|
-
...(output.runtimeError
|
|
146
|
+
result: scrubObject(runSecrets.object(output.result)),
|
|
147
|
+
stdout: scrubSecrets(runSecrets.text(output.stdout)),
|
|
148
|
+
stderr: scrubSecrets(runSecrets.text(output.stderr)),
|
|
149
|
+
...(output.runtimeError
|
|
150
|
+
? { runtimeError: scrubObject(runSecrets.object(output.runtimeError)) }
|
|
151
|
+
: {}),
|
|
140
152
|
};
|
|
141
153
|
}
|
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
import ts from "typescript";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Flags script source that would fail, or silently differ, under the quickjs
|
|
5
|
+
* executor. It is advisory: callers attach the findings as warnings and never
|
|
6
|
+
* reject on them.
|
|
7
|
+
*/
|
|
8
|
+
export type QuickJSCompatRule =
|
|
9
|
+
| "bunGlobal"
|
|
10
|
+
| "process"
|
|
11
|
+
| "fsStdlib"
|
|
12
|
+
| "require"
|
|
13
|
+
| "workspaceRw"
|
|
14
|
+
| "unsupportedGlobal"
|
|
15
|
+
| "cryptoSubtle"
|
|
16
|
+
| "responseBody"
|
|
17
|
+
| "localeFormat"
|
|
18
|
+
| "hostCredential"
|
|
19
|
+
| "privateHost";
|
|
20
|
+
|
|
21
|
+
export type QuickJSCompatFinding = {
|
|
22
|
+
rule: QuickJSCompatRule;
|
|
23
|
+
message: string;
|
|
24
|
+
/** 1-based line in the script source, when the finding has one. */
|
|
25
|
+
line?: number;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type QuickJSCompatReport = {
|
|
29
|
+
compatible: boolean;
|
|
30
|
+
findings: QuickJSCompatFinding[];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Globals that Bun provides and the quickjs sandbox does not (measured against
|
|
34
|
+
// the QuickJS build plus quickjs-prelude.ts and quickjs-web-shims.ts).
|
|
35
|
+
const UNSUPPORTED_GLOBALS = new Set([
|
|
36
|
+
"AbortController",
|
|
37
|
+
"AbortSignal",
|
|
38
|
+
"Blob",
|
|
39
|
+
"Buffer",
|
|
40
|
+
"Event",
|
|
41
|
+
"EventTarget",
|
|
42
|
+
"File",
|
|
43
|
+
"FormData",
|
|
44
|
+
"Intl",
|
|
45
|
+
"ReadableStream",
|
|
46
|
+
"Request",
|
|
47
|
+
"TransformStream",
|
|
48
|
+
"WebSocket",
|
|
49
|
+
"WritableStream",
|
|
50
|
+
"clearImmediate",
|
|
51
|
+
"navigator",
|
|
52
|
+
"performance",
|
|
53
|
+
"queueMicrotask",
|
|
54
|
+
"setImmediate",
|
|
55
|
+
"structuredClone",
|
|
56
|
+
]);
|
|
57
|
+
const RESPONSE_BODY_METHODS = new Set(["arrayBuffer", "blob", "formData", "bytes"]);
|
|
58
|
+
const LOCALE_METHODS = new Set(["toLocaleString", "toLocaleDateString", "toLocaleTimeString"]);
|
|
59
|
+
const FS_STDLIB = new Set(["glob", "grep"]);
|
|
60
|
+
// ctx.swarm.config values that quickjs keeps host-side (see quickjs-runner.ts).
|
|
61
|
+
const HOST_ONLY_CONFIG = new Set(["apiKey", "runtimeInstanceId"]);
|
|
62
|
+
const MAX_FINDINGS = 20;
|
|
63
|
+
|
|
64
|
+
const SCRIPT_FILE = "user-script.ts";
|
|
65
|
+
|
|
66
|
+
/** The initializer of the `const` binding a name reads; null for anything else. */
|
|
67
|
+
type ConstInitializer = (node: ts.Identifier) => ts.Expression | null;
|
|
68
|
+
// Follows at most this many consts, as in `const API = "..."; const url = `${API}/x``.
|
|
69
|
+
const MAX_CONST_DEPTH = 4;
|
|
70
|
+
|
|
71
|
+
/** True inside a `declare` statement, namespace or global block. */
|
|
72
|
+
function isAmbient(node: ts.Node): boolean {
|
|
73
|
+
for (let current: ts.Node | undefined = node; current; current = current.parent) {
|
|
74
|
+
if (
|
|
75
|
+
ts.canHaveModifiers(current) &&
|
|
76
|
+
ts.getModifiers(current)?.some((modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword)
|
|
77
|
+
) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Parses and binds the script with the TypeScript checker (no lib, no imports),
|
|
86
|
+
* so a name resolves by lexical scope: a `Buffer` parameter in one function does
|
|
87
|
+
* not hide a global `Buffer` read in another. A name declared only with
|
|
88
|
+
* `declare` (ambient) still counts as a global, because nothing defines it at run time.
|
|
89
|
+
*/
|
|
90
|
+
function createScope(source: string): {
|
|
91
|
+
sourceFile: ts.SourceFile;
|
|
92
|
+
isLocal: (node: ts.Identifier) => boolean;
|
|
93
|
+
constInitializer: ConstInitializer;
|
|
94
|
+
} {
|
|
95
|
+
const sourceFile = ts.createSourceFile(SCRIPT_FILE, source, ts.ScriptTarget.Latest, true);
|
|
96
|
+
const host: ts.CompilerHost = {
|
|
97
|
+
getSourceFile: (name) => (name === SCRIPT_FILE ? sourceFile : undefined),
|
|
98
|
+
getDefaultLibFileName: () => "lib.d.ts",
|
|
99
|
+
writeFile: () => {},
|
|
100
|
+
getCurrentDirectory: () => "/",
|
|
101
|
+
getCanonicalFileName: (name) => name,
|
|
102
|
+
useCaseSensitiveFileNames: () => true,
|
|
103
|
+
getNewLine: () => "\n",
|
|
104
|
+
fileExists: (name) => name === SCRIPT_FILE,
|
|
105
|
+
readFile: () => undefined,
|
|
106
|
+
};
|
|
107
|
+
const program = ts.createProgram({
|
|
108
|
+
rootNames: [SCRIPT_FILE],
|
|
109
|
+
options: { noLib: true, noResolve: true, types: [], target: ts.ScriptTarget.Latest },
|
|
110
|
+
host,
|
|
111
|
+
});
|
|
112
|
+
const checker = program.getTypeChecker();
|
|
113
|
+
const isLocal = (node: ts.Identifier) => {
|
|
114
|
+
const symbol =
|
|
115
|
+
ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node
|
|
116
|
+
? checker.getShorthandAssignmentValueSymbol(node.parent)
|
|
117
|
+
: checker.getSymbolAtLocation(node);
|
|
118
|
+
return Boolean(
|
|
119
|
+
symbol?.declarations?.some(
|
|
120
|
+
(declaration) => declaration.getSourceFile() === sourceFile && !isAmbient(declaration),
|
|
121
|
+
),
|
|
122
|
+
);
|
|
123
|
+
};
|
|
124
|
+
const constInitializer: ConstInitializer = (node) => {
|
|
125
|
+
const declaration = checker.getSymbolAtLocation(node)?.valueDeclaration;
|
|
126
|
+
if (!declaration || !ts.isVariableDeclaration(declaration) || !declaration.initializer) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
return ts.getCombinedNodeFlags(declaration) & ts.NodeFlags.Const
|
|
130
|
+
? declaration.initializer
|
|
131
|
+
: null;
|
|
132
|
+
};
|
|
133
|
+
return { sourceFile, isLocal, constInitializer };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** True when `node` is read as a value, not as a property name or declaration. */
|
|
137
|
+
function isValueReference(node: ts.Identifier): boolean {
|
|
138
|
+
const parent = node.parent;
|
|
139
|
+
if (ts.isPropertyAccessExpression(parent) && parent.name === node) return false;
|
|
140
|
+
if (ts.isShorthandPropertyAssignment(parent)) return true;
|
|
141
|
+
if ("name" in parent && (parent as { name?: ts.Node }).name === node) return false;
|
|
142
|
+
if (ts.isTypeOfExpression(parent)) return false;
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function isTypeOnly(node: ts.Node): boolean {
|
|
147
|
+
return (
|
|
148
|
+
ts.isTypeNode(node) ||
|
|
149
|
+
ts.isInterfaceDeclaration(node) ||
|
|
150
|
+
ts.isTypeAliasDeclaration(node) ||
|
|
151
|
+
(ts.isImportDeclaration(node) && Boolean(node.importClause?.isTypeOnly))
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function stdlibImportNames(node: ts.ImportDeclaration): string[] {
|
|
156
|
+
if (!ts.isStringLiteral(node.moduleSpecifier) || node.moduleSpecifier.text !== "stdlib")
|
|
157
|
+
return [];
|
|
158
|
+
const bindings = node.importClause?.namedBindings;
|
|
159
|
+
if (!bindings || !ts.isNamedImports(bindings)) return [];
|
|
160
|
+
return bindings.elements
|
|
161
|
+
.map((element) => (element.propertyName ?? element.name).text)
|
|
162
|
+
.filter((name) => FS_STDLIB.has(name));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** Strips parentheses, `as`, `!` and `satisfies`: `(globalThis as any)` is `globalThis`. */
|
|
166
|
+
function unwrap(node: ts.Expression): ts.Expression {
|
|
167
|
+
let current = node;
|
|
168
|
+
while (
|
|
169
|
+
ts.isParenthesizedExpression(current) ||
|
|
170
|
+
ts.isAsExpression(current) ||
|
|
171
|
+
ts.isNonNullExpression(current) ||
|
|
172
|
+
ts.isTypeAssertionExpression(current) ||
|
|
173
|
+
ts.isSatisfiesExpression(current)
|
|
174
|
+
) {
|
|
175
|
+
current = current.expression;
|
|
176
|
+
}
|
|
177
|
+
return current;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function isGlobalThis(node: ts.Expression): boolean {
|
|
181
|
+
const inner = unwrap(node);
|
|
182
|
+
return ts.isIdentifier(inner) && inner.text === "globalThis";
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** `globalThis.X` or `X` (free), as the global's name; otherwise null. */
|
|
186
|
+
function globalName(node: ts.Expression, isLocal: (node: ts.Identifier) => boolean): string | null {
|
|
187
|
+
const inner = unwrap(node);
|
|
188
|
+
if (ts.isIdentifier(inner)) return isLocal(inner) ? null : inner.text;
|
|
189
|
+
if (ts.isPropertyAccessExpression(inner) && isGlobalThis(inner.expression)) {
|
|
190
|
+
return inner.name.text;
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function isPrivateIPv4([a = 0, b = 0, c = 0]: number[]): boolean {
|
|
196
|
+
return (
|
|
197
|
+
a === 0 ||
|
|
198
|
+
a === 10 ||
|
|
199
|
+
a === 127 ||
|
|
200
|
+
(a === 100 && b >= 64 && b <= 127) ||
|
|
201
|
+
(a === 169 && b === 254) ||
|
|
202
|
+
(a === 172 && b >= 16 && b <= 31) ||
|
|
203
|
+
(a === 192 && b === 168) ||
|
|
204
|
+
(a === 192 && b === 0 && c === 0) ||
|
|
205
|
+
(a === 198 && (b === 18 || b === 19)) ||
|
|
206
|
+
a >= 224
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// `text` is a WHATWG-serialized IPv6 address without brackets: hex groups, at most one "::".
|
|
211
|
+
function isPrivateIPv6(text: string): boolean {
|
|
212
|
+
const [head = "", tail = ""] = text.split("::");
|
|
213
|
+
const left = head ? head.split(":") : [];
|
|
214
|
+
const right = text.includes("::") && tail ? tail.split(":") : [];
|
|
215
|
+
const fill = text.includes("::") ? 8 - left.length - right.length : 0;
|
|
216
|
+
const g = [...left, ...Array<string>(fill).fill("0"), ...right].map((part) => parseInt(part, 16));
|
|
217
|
+
const g0 = g[0] ?? 0;
|
|
218
|
+
if (g.slice(0, 6).every((part) => part === 0)) return true; // ::/96: ::, ::1
|
|
219
|
+
if (g.slice(0, 5).every((part) => part === 0) && g[5] === 0xffff) {
|
|
220
|
+
const [g6 = 0, g7 = 0] = g.slice(6);
|
|
221
|
+
return isPrivateIPv4([g6 >> 8, g6 & 255, g7 >> 8]); // IPv4-mapped
|
|
222
|
+
}
|
|
223
|
+
return (
|
|
224
|
+
(g0 & 0xfe00) === 0xfc00 || // fc00::/7 unique local
|
|
225
|
+
(g0 & 0xffc0) === 0xfe80 || // fe80::/10 link-local
|
|
226
|
+
(g0 & 0xffc0) === 0xfec0 || // fec0::/10 site-local
|
|
227
|
+
(g0 & 0xff00) === 0xff00 // ff00::/8 multicast
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* How the default egress policy sees a parsed URL hostname, statically:
|
|
233
|
+
* "private" for loopback names and private, link-local or reserved IP literals,
|
|
234
|
+
* "single-label" for a name with no dot (usually an internal service name that
|
|
235
|
+
* resolves to a private address). Null for anything else, including public names
|
|
236
|
+
* that resolve privately: only the runtime check sees DNS.
|
|
237
|
+
*/
|
|
238
|
+
function staticHostClass(hostname: string): "private" | "single-label" | null {
|
|
239
|
+
const host = hostname.toLowerCase().replace(/\.$/, "");
|
|
240
|
+
if (host === "localhost" || host.endsWith(".localhost")) return "private";
|
|
241
|
+
if (host.startsWith("[")) return isPrivateIPv6(host.slice(1, -1)) ? "private" : null;
|
|
242
|
+
const v4 = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/.exec(host);
|
|
243
|
+
if (v4) return isPrivateIPv4(v4.slice(1).map(Number)) ? "private" : null;
|
|
244
|
+
return host !== "" && !host.includes(".") ? "single-label" : null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** The fetch-like call this callee names: fetch, globalThis.fetch, ctx.stdlib.fetch or fetchJson. */
|
|
248
|
+
function fetchCallName(callee: ts.Expression): string | null {
|
|
249
|
+
const inner = unwrap(callee);
|
|
250
|
+
if (ts.isIdentifier(inner)) {
|
|
251
|
+
return inner.text === "fetch" || inner.text === "fetchJson" ? inner.text : null;
|
|
252
|
+
}
|
|
253
|
+
if (!ts.isPropertyAccessExpression(inner)) return null;
|
|
254
|
+
const method = inner.name.text;
|
|
255
|
+
if (method !== "fetch" && method !== "fetchJson") return null;
|
|
256
|
+
const owner = unwrap(inner.expression);
|
|
257
|
+
if (method === "fetch" && isGlobalThis(owner)) return "fetch";
|
|
258
|
+
const ownerName = ts.isIdentifier(owner)
|
|
259
|
+
? owner.text
|
|
260
|
+
: ts.isPropertyAccessExpression(owner)
|
|
261
|
+
? owner.name.text
|
|
262
|
+
: null;
|
|
263
|
+
return ownerName === "stdlib" ? `ctx.stdlib.${method}` : null;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* The fixed start of a URL argument: a literal, a const holding one, or a
|
|
268
|
+
* template or `+` concatenation that starts with them, through up to
|
|
269
|
+
* MAX_CONST_DEPTH consts. `cut` is true when the
|
|
270
|
+
* text stops at a dynamic part that could still extend the host, as in
|
|
271
|
+
* `http://intra${suffix}`; a dynamic part right after a const value cannot.
|
|
272
|
+
*/
|
|
273
|
+
function staticPrefix(
|
|
274
|
+
node: ts.Expression,
|
|
275
|
+
resolve: ConstInitializer,
|
|
276
|
+
depth = 0,
|
|
277
|
+
): { text: string; cut: boolean } | null {
|
|
278
|
+
const inner = unwrap(node);
|
|
279
|
+
if (ts.isStringLiteral(inner) || ts.isNoSubstitutionTemplateLiteral(inner)) {
|
|
280
|
+
return { text: inner.text, cut: false };
|
|
281
|
+
}
|
|
282
|
+
if (ts.isIdentifier(inner)) {
|
|
283
|
+
const initializer = depth < MAX_CONST_DEPTH ? resolve(inner) : null;
|
|
284
|
+
return initializer ? staticPrefix(initializer, resolve, depth + 1) : null;
|
|
285
|
+
}
|
|
286
|
+
if (ts.isTemplateExpression(inner)) {
|
|
287
|
+
let text = inner.head.text;
|
|
288
|
+
let boundary = false;
|
|
289
|
+
for (const span of inner.templateSpans) {
|
|
290
|
+
const part = staticPrefix(span.expression, resolve, depth);
|
|
291
|
+
if (part === null) return { text, cut: !boundary || text === "" };
|
|
292
|
+
if (part.cut) return { text: text + part.text, cut: true };
|
|
293
|
+
text += part.text + span.literal.text;
|
|
294
|
+
boundary = span.literal.text === "";
|
|
295
|
+
}
|
|
296
|
+
return { text, cut: false };
|
|
297
|
+
}
|
|
298
|
+
if (ts.isBinaryExpression(inner) && inner.operatorToken.kind === ts.SyntaxKind.PlusToken) {
|
|
299
|
+
const left = staticPrefix(inner.left, resolve, depth);
|
|
300
|
+
if (left === null || left.cut) return left;
|
|
301
|
+
const right = staticPrefix(inner.right, resolve, depth);
|
|
302
|
+
if (right === null) return { text: left.text, cut: !ts.isIdentifier(unwrap(inner.left)) };
|
|
303
|
+
return { text: left.text + right.text, cut: right.cut };
|
|
304
|
+
}
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/** The URL argument's host when the source fixes it, parsed with the host URL parser. */
|
|
309
|
+
function literalUrl(arg: ts.Expression | undefined, resolve: ConstInitializer): URL | null {
|
|
310
|
+
if (!arg) return null;
|
|
311
|
+
const prefix = staticPrefix(arg, resolve);
|
|
312
|
+
if (!prefix) return null;
|
|
313
|
+
// A cut prefix fixes the host only once the authority has ended.
|
|
314
|
+
if (prefix.cut && !/^[a-z][a-z0-9+.-]*:\/\/[^/?#]*[/?#]/i.test(prefix.text)) return null;
|
|
315
|
+
try {
|
|
316
|
+
return new URL(prefix.text);
|
|
317
|
+
} catch {
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function checkQuickJSCompat(
|
|
323
|
+
source: string,
|
|
324
|
+
options: { fsMode?: string } = {},
|
|
325
|
+
): QuickJSCompatReport {
|
|
326
|
+
const findings: QuickJSCompatFinding[] = [];
|
|
327
|
+
const seen = new Set<string>();
|
|
328
|
+
const { sourceFile, isLocal, constInitializer } = createScope(source);
|
|
329
|
+
const add = (rule: QuickJSCompatRule, message: string, node?: ts.Node) => {
|
|
330
|
+
if (seen.has(`${rule}:${message}`)) return;
|
|
331
|
+
seen.add(`${rule}:${message}`);
|
|
332
|
+
const line = node
|
|
333
|
+
? sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1
|
|
334
|
+
: undefined;
|
|
335
|
+
findings.push(line === undefined ? { rule, message } : { rule, message, line });
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
if (options.fsMode === "workspace-rw") {
|
|
339
|
+
add("workspaceRw", "fsMode workspace-rw is not available under quickjs");
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const reportGlobal = (name: string, node: ts.Node) => {
|
|
343
|
+
if (name === "Bun") add("bunGlobal", "Bun.* is not available under quickjs", node);
|
|
344
|
+
else if (name === "process") add("process", "process is not available under quickjs", node);
|
|
345
|
+
else if (UNSUPPORTED_GLOBALS.has(name)) {
|
|
346
|
+
add("unsupportedGlobal", `${name} is not available under quickjs`, node);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
const visit = (node: ts.Node) => {
|
|
351
|
+
if (isTypeOnly(node)) return;
|
|
352
|
+
|
|
353
|
+
if (
|
|
354
|
+
ts.isIdentifier(node) &&
|
|
355
|
+
(node.text === "Bun" || node.text === "process" || UNSUPPORTED_GLOBALS.has(node.text)) &&
|
|
356
|
+
isValueReference(node) &&
|
|
357
|
+
!isLocal(node)
|
|
358
|
+
) {
|
|
359
|
+
reportGlobal(node.text, node);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
363
|
+
const member = node.name.text;
|
|
364
|
+
const owner = globalName(node.expression, isLocal);
|
|
365
|
+
if (isGlobalThis(node.expression) && !ts.isTypeOfExpression(node.parent)) {
|
|
366
|
+
reportGlobal(member, node);
|
|
367
|
+
}
|
|
368
|
+
const parent = unwrap(node.expression);
|
|
369
|
+
if (
|
|
370
|
+
HOST_ONLY_CONFIG.has(member) &&
|
|
371
|
+
ts.isPropertyAccessExpression(parent) &&
|
|
372
|
+
parent.name.text === "config"
|
|
373
|
+
) {
|
|
374
|
+
add(
|
|
375
|
+
"hostCredential",
|
|
376
|
+
`ctx.swarm.config.${member} is host-only under quickjs; ctx.swarm calls use it for you`,
|
|
377
|
+
node,
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
if (member === "subtle" && owner === "crypto") {
|
|
381
|
+
add("cryptoSubtle", "crypto.subtle is not available under quickjs", node);
|
|
382
|
+
}
|
|
383
|
+
if (
|
|
384
|
+
FS_STDLIB.has(member) &&
|
|
385
|
+
ts.isPropertyAccessExpression(unwrap(node.expression)) &&
|
|
386
|
+
(unwrap(node.expression) as ts.PropertyAccessExpression).name.text === "stdlib"
|
|
387
|
+
) {
|
|
388
|
+
add("fsStdlib", `ctx.stdlib.${member} needs filesystem access, which quickjs lacks`, node);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (ts.isImportDeclaration(node)) {
|
|
393
|
+
for (const name of stdlibImportNames(node)) {
|
|
394
|
+
add("fsStdlib", `stdlib ${name} needs filesystem access, which quickjs lacks`, node);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
if (
|
|
399
|
+
ts.isVariableDeclaration(node) &&
|
|
400
|
+
ts.isObjectBindingPattern(node.name) &&
|
|
401
|
+
node.initializer &&
|
|
402
|
+
ts.isPropertyAccessExpression(node.initializer) &&
|
|
403
|
+
node.initializer.name.text === "stdlib"
|
|
404
|
+
) {
|
|
405
|
+
for (const element of node.name.elements) {
|
|
406
|
+
const name = (element.propertyName ?? element.name).getText(sourceFile);
|
|
407
|
+
if (FS_STDLIB.has(name)) {
|
|
408
|
+
add("fsStdlib", `ctx.stdlib.${name} needs filesystem access, which quickjs lacks`, node);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
if (ts.isCallExpression(node)) {
|
|
414
|
+
const callee = node.expression;
|
|
415
|
+
const fetchName = fetchCallName(callee);
|
|
416
|
+
const url = fetchName ? literalUrl(node.arguments[0], constInitializer) : null;
|
|
417
|
+
const hostClass =
|
|
418
|
+
url && (url.protocol === "http:" || url.protocol === "https:")
|
|
419
|
+
? staticHostClass(url.hostname)
|
|
420
|
+
: null;
|
|
421
|
+
if (url && hostClass) {
|
|
422
|
+
add(
|
|
423
|
+
"privateHost",
|
|
424
|
+
`${fetchName} to ${url.host} (${hostClass} host) depends on the egress policy: quickjs refuses private hosts unless the operator allows them`,
|
|
425
|
+
node,
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
if (ts.isIdentifier(callee) && callee.text === "require" && !isLocal(callee)) {
|
|
429
|
+
add("require", "require() is not supported; use an import", node);
|
|
430
|
+
}
|
|
431
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
432
|
+
const method = callee.name.text;
|
|
433
|
+
if (RESPONSE_BODY_METHODS.has(method) && node.arguments.length === 0) {
|
|
434
|
+
add(
|
|
435
|
+
"responseBody",
|
|
436
|
+
`.${method}() on a fetch Response is not available under quickjs (text() and json() are)`,
|
|
437
|
+
node,
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
if (LOCALE_METHODS.has(method) && node.arguments.length > 0) {
|
|
441
|
+
add(
|
|
442
|
+
"localeFormat",
|
|
443
|
+
`${method}(locale, options) ignores its arguments under quickjs (no Intl)`,
|
|
444
|
+
node,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
ts.forEachChild(node, visit);
|
|
451
|
+
};
|
|
452
|
+
visit(sourceFile);
|
|
453
|
+
|
|
454
|
+
return { compatible: findings.length === 0, findings: findings.slice(0, MAX_FINDINGS) };
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/** One human-readable line per finding, for `warnings` arrays. */
|
|
458
|
+
export function quickJSCompatWarnings(report: QuickJSCompatReport, label?: string): string[] {
|
|
459
|
+
const prefix = label ? `${label}: ` : "";
|
|
460
|
+
return report.findings.map(
|
|
461
|
+
(finding) =>
|
|
462
|
+
`${prefix}quickjs compat (${finding.rule}${finding.line ? `, line ${finding.line}` : ""}): ${finding.message}`,
|
|
463
|
+
);
|
|
464
|
+
}
|
|
@@ -89,6 +89,7 @@ export const SDK_TOOL_NAME_MAP = {
|
|
|
89
89
|
// ── model catalog ──
|
|
90
90
|
modelCatalog_refresh: "model-catalog-refresh", // external: fetches models.dev
|
|
91
91
|
modelCatalog_overlayUpsert: "model-catalog-overlay-upsert",
|
|
92
|
+
modelProfile_list: "list-model-profiles",
|
|
92
93
|
|
|
93
94
|
// ── slack ──
|
|
94
95
|
slack_read: "slack-read",
|
|
@@ -104,6 +105,14 @@ export const SDK_TOOL_NAME_MAP = {
|
|
|
104
105
|
slack_delete: "slack-delete", // external: mutates Slack, destructive
|
|
105
106
|
slack_update: "slack-update", // external: mutates Slack
|
|
106
107
|
|
|
108
|
+
// ── chat sdk ──
|
|
109
|
+
chat_reply: "chat-reply", // external: sends to the task's chat thread
|
|
110
|
+
chat_post: "chat-post", // external: sends to a chat platform
|
|
111
|
+
chat_openDm: "chat-open-dm", // external: opens a platform DM
|
|
112
|
+
chat_readThread: "chat-read-thread",
|
|
113
|
+
chat_registerChannel: "register-chat-channel",
|
|
114
|
+
chat_unregisterChannel: "unregister-chat-channel", // destructive
|
|
115
|
+
|
|
107
116
|
// ── messaging (internal) ──
|
|
108
117
|
message_read: "read-messages",
|
|
109
118
|
message_post: "post-message",
|
|
@@ -115,12 +124,6 @@ export const SDK_TOOL_NAME_MAP = {
|
|
|
115
124
|
context_history: "context-history",
|
|
116
125
|
context_diff: "context-diff",
|
|
117
126
|
|
|
118
|
-
// ── services ──
|
|
119
|
-
service_list: "list-services",
|
|
120
|
-
service_register: "register-service",
|
|
121
|
-
service_unregister: "unregister-service", // destructive
|
|
122
|
-
service_updateStatus: "update-service-status",
|
|
123
|
-
|
|
124
127
|
// ── workflows ──
|
|
125
128
|
workflow_list: "list-workflows",
|
|
126
129
|
workflow_get: "get-workflow",
|
|
@@ -187,6 +190,9 @@ export const SDK_TOOL_NAME_MAP = {
|
|
|
187
190
|
// ── human input ──
|
|
188
191
|
request_humanInput: "request-human-input",
|
|
189
192
|
approval_cancel: "cancel-approval-request", // destructive
|
|
193
|
+
|
|
194
|
+
// ── decisions ──
|
|
195
|
+
systemOne_decide: "system-one-decide",
|
|
190
196
|
} as const;
|
|
191
197
|
|
|
192
198
|
export const SDK_ALLOWLIST = Object.keys(SDK_TOOL_NAME_MAP) as Array<
|
|
@@ -280,17 +280,6 @@ function bridgeRequestFor(name: string, args: unknown): BridgeRequest | null {
|
|
|
280
280
|
return { method: "DELETE", path: `/api/config/${encodeURIComponent(id)}` };
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
-
// ── services ──
|
|
284
|
-
case "service_list":
|
|
285
|
-
return {
|
|
286
|
-
method: "GET",
|
|
287
|
-
path: appendQuery("/api/services", {
|
|
288
|
-
agentId: body.agentId,
|
|
289
|
-
name: body.name,
|
|
290
|
-
status: body.status,
|
|
291
|
-
}),
|
|
292
|
-
};
|
|
293
|
-
|
|
294
283
|
// ── workflows ──
|
|
295
284
|
case "workflow_list":
|
|
296
285
|
return {
|