@desplega.ai/agent-swarm 1.158.0 → 1.160.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-xaq4n6pc.js → acp-adapter-2mjwcsfh.js} +124 -27
- package/dist/{actions-p9hz5yat.js → actions-e43rxskr.js} +35 -30
- package/dist/{anthropic-messages-51pz26qe.js → anthropic-messages-5qx80j9k.js} +106 -16
- package/dist/{app-g26wdcz6.js → app-mc7xfagn.js} +12 -10
- package/dist/{assistant-wydfqkb3.js → assistant-sedkzv3b.js} +42 -31
- package/dist/{azure-openai-responses-8gksqtmz.js → azure-openai-responses-nfb21z9a.js} +13 -14
- package/dist/{boot-reembed-se8zmdcp.js → boot-reembed-cqz9swn5.js} +13 -12
- package/dist/{boot-reembed-g5ckg9yb.js → boot-reembed-m3656j2n.js} +14 -13
- package/dist/{boot-scrub-logs-wfxqan61.js → boot-scrub-logs-xbxf5d7w.js} +11 -9
- package/dist/boot-seeds-gsetbs5y.js +28 -0
- package/dist/{claude-adapter-tv2x4f36.js → claude-adapter-dc6289mc.js} +28 -23
- package/dist/{claude-managed-adapter-41b2s7fd.js → claude-managed-adapter-naaw51me.js} +4 -3
- package/dist/{claude-managed-setup-60g8aazx.js → claude-managed-setup-eacvchx0.js} +12 -3
- package/dist/claude-sdk-session-bqp2xvym.js +29722 -0
- package/dist/{cli-987hg0aa.js → cli-0jwe9034.js} +2 -2
- package/dist/{cli-vj6h9kc2.js → cli-0m7wct0d.js} +59 -1
- package/dist/{cli-c07r9a2m.js → cli-0q3avq3s.js} +12 -11
- package/dist/{cli-19jenss3.js → cli-0wgxmwf6.js} +31 -10
- package/dist/cli-0x01kwrd.js +491 -0
- package/dist/cli-0xqde53b.js +176 -0
- package/dist/cli-10nhj6xq.js +8355 -0
- package/dist/{cli-tt9k8r35.js → cli-12tszpk9.js} +479 -910
- package/dist/{cli-5b6b62tz.js → cli-13hw4z91.js} +1 -1
- package/dist/{cli-cqt19wg6.js → cli-1a2j50m0.js} +11 -2
- package/dist/{cli-xberxa1r.js → cli-25fcq4b4.js} +2 -2
- package/dist/{cli-npssxgaz.js → cli-2pdaysab.js} +52 -2
- package/dist/cli-3qhyh31j.js +166 -0
- package/dist/cli-447dt1h3.js +3828 -0
- package/dist/cli-4derpgyk.js +115 -0
- package/dist/{cli-00w2c66p.js → cli-523679eh.js} +13 -2
- package/dist/{cli-y95wp3tg.js → cli-58e8yr0d.js} +1 -1
- package/dist/{cli-24k806sc.js → cli-5nbmpy8w.js} +3 -3
- package/dist/{cli-53sz8gkz.js → cli-6cs6wzxt.js} +1 -1
- package/dist/cli-741yb0xx.js +1027 -0
- package/dist/cli-74h9hscv.js +69 -0
- package/dist/cli-7cxw8b60.js +14910 -0
- package/dist/{cli-xhaeg2nc.js → cli-7e398j1h.js} +1 -1
- package/dist/cli-7kyk9jr3.js +22 -0
- package/dist/cli-89s4ngw3.js +183 -0
- package/dist/{cli-9b13ggd1.js → cli-89v6kyq7.js} +1 -0
- package/dist/{cli-ftfvggzx.js → cli-9hsgwz4w.js} +1045 -581
- package/dist/{cli-rqz8qbw7.js → cli-a8dvhzrt.js} +59 -20
- package/dist/{cli-j57qkrpq.js → cli-azhgzetg.js} +395 -56
- package/dist/cli-br0qdrnp.js +2150 -0
- package/dist/{cli-rj19hc34.js → cli-btfv8y88.js} +1 -1
- package/dist/{cli-8qmme6vd.js → cli-c8a36vcc.js} +2 -2
- package/dist/cli-cpvsaqsw.js +333 -0
- package/dist/cli-d5czme6m.js +17805 -0
- package/dist/{cli-h38x0qhg.js → cli-et8m9xsv.js} +4 -3
- package/dist/{cli-x24pshtq.js → cli-evvtk35y.js} +6 -6
- package/dist/{cli-7s3syk22.js → cli-f8gy6r2r.js} +5 -5
- package/dist/{cli-zt1227k1.js → cli-fkqhbg8g.js} +5 -3
- package/dist/{cli-9httdpyq.js → cli-g2whhdrf.js} +1 -1
- package/dist/cli-gt4hxb8p.js +99 -0
- package/dist/{cli-s8eet254.js → cli-jajnsm8q.js} +37184 -53838
- package/dist/{cli-7gtvvpbh.js → cli-jayjpjmb.js} +21 -12
- package/dist/{cli-68w09sjw.js → cli-jyk0ynw2.js} +27 -89
- package/dist/{cli-aehm1rbq.js → cli-jz4w45qt.js} +1152 -61
- package/dist/cli-kmcpfwn2.js +333856 -0
- package/dist/{cli-4198qc9v.js → cli-ktmyrtpn.js} +19 -3
- package/dist/{cli-j55n64b6.js → cli-mfe5btp9.js} +505 -189
- package/dist/{cli-q67y4wzm.js → cli-phsaj4xq.js} +24 -2
- package/dist/{cli-1hkrch3k.js → cli-pm1rst0h.js} +46 -7
- package/dist/{cli-pw9rj5t9.js → cli-pqetb83f.js} +1 -176
- package/dist/{cli-ggm92wcn.js → cli-ptr8h7kp.js} +20 -1
- package/dist/{cli-s8s499xy.js → cli-qbksc292.js} +3 -2
- package/dist/{cli-47m6dkd3.js → cli-qydf22qq.js} +597 -346
- package/dist/{cli-3gmcwfyx.js → cli-r1mxd1xh.js} +13 -6
- package/dist/cli-rb9m6rpe.js +4980 -0
- package/dist/cli-rykfmgwg.js +102 -0
- package/dist/{cli-5d10vd2m.js → cli-shkxm1vn.js} +6 -5
- package/dist/{cli-eetrvv91.js → cli-t3p77qk1.js} +1 -1
- package/dist/cli-tfky2838.js +756 -0
- package/dist/{cli-g8djp6qe.js → cli-tmqt7dpj.js} +40 -0
- package/dist/{cli-fgqxwrpv.js → cli-tpq83z89.js} +1631 -127
- package/dist/cli-trc24wk2.js +143 -0
- package/dist/{cli-aky8tctm.js → cli-tzx2ke1v.js} +3 -3
- package/dist/cli-v7fn5gms.js +1425 -0
- package/dist/{cli-wscdvcqz.js → cli-vctdqs5h.js} +1 -1
- package/dist/{cli-cw9zck8j.js → cli-xjcywfsf.js} +8 -4
- package/dist/{cli-k0g1sjzm.js → cli-ybgv4kw2.js} +18 -11
- package/dist/{cli-rjehvrts.js → cli-ydmcgve1.js} +8 -8
- package/dist/{cli-vhjwh6cz.js → cli-ygwm91nt.js} +1 -1
- package/dist/{cli-mcnhgnn1.js → cli-ykk5jaax.js} +184 -26
- package/dist/{cli-de1396j2.js → cli-ywybs5as.js} +7 -1
- package/dist/cli-zpep9q5e.js +491 -0
- package/dist/cli.js +41 -32
- package/dist/cloudflare-workers-ai-system-one-k6fbxw9d.js +46 -0
- package/dist/{codex-adapter-cnm8wk11.js → codex-adapter-nmxcatww.js} +26 -17
- package/dist/{codex-hook-9hptmdhj.js → codex-hook-20me6byw.js} +2 -2
- package/dist/{codex-login-x3jk4etn.js → codex-login-w6fz4xbz.js} +50 -5
- package/dist/{codex-session-runner-gfg547zj.js → codex-session-runner-90aa80ev.js} +24 -17
- package/dist/{commands-e3bn0p75.js → commands-8wcq1kn7.js} +11 -9
- package/dist/{db-03v9kzr2.js → db-j40kc4se.js} +25 -11
- package/dist/{devin-adapter-8vgkwh29.js → devin-adapter-dpsv6hd9.js} +1 -1
- package/dist/{dispatcher-nrmg8yht.js → dispatcher-4zqy768d.js} +34 -29
- package/dist/{dsh-adapter-k03nfqa6.js → dsh-adapter-mpnzgztj.js} +3 -3
- package/dist/{e2b-93x1k0j5.js → e2b-ez07znam.js} +4 -3
- package/dist/execute-6e7qeyk4.js +1017 -0
- package/dist/{google-generative-ai-bxmv50nc.js → google-generative-ai-k6n5nbpp.js} +6 -5
- package/dist/{google-vertex-809af514.js → google-vertex-44xxtcvp.js} +6 -5
- package/dist/{handlers-aqcedbyb.js → handlers-kjdce1w5.js} +37 -32
- package/dist/{hook-ybvmrmhq.js → hook-czx13n12.js} +19 -15
- package/dist/{hook-7vkskkre.js → hook-r2t4bqfg.js} +18 -14
- package/dist/{http-2eqa8t24.js → http-3bbb19be.js} +900 -145
- package/dist/{index-f6cryxwe.js → index-4a5njnm1.js} +2 -59
- package/dist/{index-x71bvq0p.js → index-668me3f0.js} +35 -30
- package/dist/{index-c6zsv1bd.js → index-7aj368tw.js} +13 -12
- package/dist/{index-1yks3qcr.js → index-fg0dsp6c.js} +34 -29
- package/dist/{index-chgdkq36.js → index-kkv84jq9.js} +34 -29
- package/dist/{index-a3vn96n8.js → index-zg7vp46x.js} +198 -54
- package/dist/{keepalive-vtkf5n99.js → keepalive-yra8dy57.js} +13 -11
- package/dist/{lead-h3sp357x.js → lead-va0pad2c.js} +54 -49
- package/dist/llama-cpp-classify-tgj35k8d.js +335 -0
- package/dist/{maintenance-jzeqtk3q.js → maintenance-hqewtmyg.js} +14 -13
- package/dist/{mistral-conversations-zx0kn554.js → mistral-conversations-pc3ntnxt.js} +14 -17
- package/dist/{oauth-refresh-sweep-qp3dzmdp.js → oauth-refresh-sweep-7rdt1m9n.js} +12 -10
- package/dist/{onboard-tmsp0qbz.js → onboard-j6ms6d0x.js} +6 -5
- package/dist/{openai-codex-responses-4vjqzvjp.js → openai-codex-responses-bbancrr0.js} +21 -8
- package/dist/{openai-completions-9hjrqbw8.js → openai-completions-jpaj5g2b.js} +9 -12
- package/dist/{openai-responses-7b1pn0xt.js → openai-responses-200k1wx4.js} +23 -18
- package/dist/{opencode-adapter-x6x2da1z.js → opencode-adapter-89rabkw2.js} +8 -7
- package/dist/{openrouter-images-9f9ek4rw.js → openrouter-images-8yx3487g.js} +5 -7
- package/dist/{otel-impl-9mz73q65.js → otel-impl-a792rjz0.js} +1 -1
- package/dist/{pi-messages-txpjj39q.js → pi-messages-vxdt8v7j.js} +2 -1
- package/dist/{pi-mono-adapter-m6dvv0dz.js → pi-mono-adapter-g7qzvr3v.js} +295 -70
- package/dist/pricing-refresh-wx0tp7cb.js +39 -0
- package/dist/quickjs-r1pq2107.wasm +0 -0
- package/dist/{rbac-roles-c9wqz83x.js → rbac-roles-8tzawacv.js} +12 -10
- package/dist/{render-v2-gryrh9h8.js → render-v2-mm7zswb8.js} +12 -10
- package/dist/runtime-zyssgse0.js +24 -0
- package/dist/{setup-q9720bt6.js → setup-8y70ys6t.js} +6 -5
- package/dist/typesafe-system-one-2ef30pec.js +27 -0
- package/dist/{virtual-modules-3htpgn8x.js → virtual-modules-6nmk7h3n.js} +22 -13
- package/dist/{work-objects-b76x7deb.js → work-objects-fg6xkb0n.js} +37 -32
- package/dist/{worker-6vrxbv41.js → worker-wmwhxsph.js} +54 -49
- package/openapi.json +1314 -91
- package/package.json +12 -11
- package/src/be/db/agents.ts +20 -0
- package/src/be/db/api-keys.ts +70 -0
- package/src/be/db/tasks/human-free.ts +442 -0
- package/src/be/db/tasks/read.ts +56 -1
- package/src/be/db/tasks/write.ts +107 -11
- package/src/be/db.ts +274 -188
- package/src/be/harness-model-support.ts +182 -0
- package/src/be/human-free-drain.ts +67 -0
- package/src/be/memory/providers/sqlite-store.ts +51 -15
- package/src/be/migrations/182_task_human_free_flag.sql +63 -0
- package/src/be/migrations/183_human_free_reclassify_queue.sql +25 -0
- package/src/be/migrations/184_model_catalog.sql +120 -0
- package/src/be/migrations/185_api_key_auth_failures.sql +6 -0
- package/src/be/migrations/186_api_key_seat_mismatch.sql +8 -0
- package/src/be/model-catalog-store.ts +644 -0
- package/src/be/model-tier-keys.ts +46 -0
- package/src/be/model-tier-resolution.ts +534 -0
- package/src/be/model-validation.ts +188 -0
- package/src/be/models-catalog.ts +61 -7
- package/src/be/modelsdev-cache.json +82 -0
- package/src/be/modelsdev-cache.ts +2 -0
- package/src/be/pricing-refresh.ts +154 -12
- package/src/be/scripts/typecheck.ts +15 -0
- package/src/be/seed/runner.ts +18 -12
- package/src/be/seed/types.ts +1 -0
- package/src/be/seed-scripts/catalog/task-failure-audit.ts +61 -9
- package/src/be/swarm-config-guard.ts +8 -0
- package/src/cli.tsx +10 -0
- package/src/commands/claude-managed-setup.ts +3 -1
- package/src/commands/codex-login.ts +67 -0
- package/src/commands/credential-outcome-report.ts +191 -0
- package/src/commands/rate-limit-outcome.ts +34 -4
- package/src/commands/runner.ts +357 -186
- package/src/commands/seat-mismatch-report.ts +46 -0
- package/src/extensions/apply-task-create.ts +27 -1
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/heartbeat/heartbeat.ts +79 -17
- package/src/heartbeat/templates.ts +2 -2
- package/src/http/agents.ts +62 -1
- package/src/http/api-keys.ts +140 -2
- package/src/http/codex-oauth-keep-warm.ts +3 -5
- package/src/http/index.ts +8 -0
- package/src/http/memory.ts +12 -5
- package/src/http/models-catalog.ts +357 -8
- package/src/http/poll.ts +54 -3
- package/src/http/schedules.ts +51 -6
- package/src/http/script-runs.ts +12 -0
- package/src/http/session-data.ts +2 -5
- package/src/http/stats.ts +6 -8
- package/src/http/status.ts +15 -1
- package/src/http/tasks.ts +90 -7
- package/src/http/usage-cache.ts +56 -15
- package/src/http/workflows.ts +46 -8
- package/src/mcp-client/http-client.ts +5 -0
- package/src/memory/recall-query.ts +74 -0
- package/src/prompts/base-prompt.ts +15 -4
- package/src/prompts/session-templates.ts +23 -1
- package/src/providers/acp-adapter.ts +1 -0
- package/src/providers/claude-adapter.ts +14 -5
- package/src/providers/claude-managed-adapter.ts +1 -0
- package/src/providers/claude-managed-models.ts +47 -161
- package/src/providers/claude-sdk-session.ts +3 -1
- package/src/providers/codex-adapter.ts +14 -14
- package/src/providers/codex-models.ts +65 -198
- package/src/providers/devin-adapter.ts +1 -0
- package/src/providers/dsh-adapter.ts +2 -1
- package/src/providers/harness-version.ts +83 -7
- package/src/providers/opencode-adapter.ts +53 -1
- package/src/providers/pi-binary-root/src/extensions/codemode/worker.ts +11 -0
- package/src/providers/pi-codemode-runtime.ts +17 -0
- package/src/providers/pi-mono-adapter.ts +361 -83
- package/src/providers/pi-mono-extension.ts +16 -1
- package/src/providers/reasoning-effort.ts +44 -140
- package/src/providers/types.ts +8 -0
- package/src/rbac/legacy-policy.ts +43 -0
- package/src/rbac/permissions.ts +15 -0
- package/src/scripts-runtime/sdk-allowlist.ts +4 -0
- package/src/scripts-runtime/types/stdlib.d.ts +15 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +3 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +15 -0
- package/src/server.ts +6 -0
- package/src/slack/assistant.ts +13 -0
- package/src/slack/message-text.ts +56 -2
- package/src/slack/render-v2.ts +87 -37
- package/src/slack/session-status.ts +541 -0
- package/src/slack/thread-buffer.ts +10 -2
- package/src/tasks/sibling-awareness.ts +3 -2
- package/src/telemetry.ts +5 -4
- package/src/templates.d.ts +6 -0
- package/src/tests/agents-list-model-display.test.ts +4 -6
- package/src/tests/api-key-auth-failure-route.test.ts +142 -0
- package/src/tests/api-key-tracking.test.ts +368 -1
- package/src/tests/base-prompt.test.ts +43 -2
- package/src/tests/claude-adapter.test.ts +68 -0
- package/src/tests/claude-managed-adapter.test.ts +12 -18
- package/src/tests/codex-adapter.test.ts +2 -1
- package/src/tests/codex-auth-failure.test.ts +52 -0
- package/src/tests/codex-gpt6-release.test.ts +66 -5
- package/src/tests/codex-login.test.ts +116 -0
- package/src/tests/context-window.test.ts +7 -5
- package/src/tests/credential-exhaustion-policy.test.ts +118 -3
- package/src/tests/credential-outcome-report.test.ts +171 -0
- package/src/tests/credential-status-api.test.ts +103 -2
- package/src/tests/db-extraction-contract.test.ts +1 -0
- package/src/tests/db-task-read-contract.test.ts +10 -1
- package/src/tests/db-task-write-contract.test.ts +535 -2
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/dokploy-deploy.test.ts +315 -0
- package/src/tests/dsh-adapter.test.ts +1 -1
- package/src/tests/explicit-model-validation.test.ts +583 -0
- package/src/tests/extensions-pre-task.test.ts +73 -0
- package/src/tests/fetch-resolved-env.test.ts +46 -0
- package/src/tests/hang-watchdog-worker.ts +47 -0
- package/src/tests/hang-watchdog.test.ts +45 -0
- package/src/tests/hang-watchdog.ts +30 -0
- package/src/tests/harness-model-guard.test.ts +123 -0
- package/src/tests/harness-model-support.test.ts +374 -0
- package/src/tests/harness-version.test.ts +70 -3
- package/src/tests/heartbeat-checklist-config.test.ts +71 -0
- package/src/tests/heartbeat-checklist.test.ts +4 -2
- package/src/tests/heartbeat-orphan-resume.test.ts +48 -0
- package/src/tests/http-task-write-ownership.test.ts +172 -0
- package/src/tests/human-free-flag.test.ts +279 -0
- package/src/tests/human-free-oracle.ts +57 -0
- package/src/tests/human-free-reclassify.test.ts +669 -0
- package/src/tests/memory-fts-populate.test.ts +139 -0
- package/src/tests/memory-http-recall-gating.test.ts +125 -1
- package/src/tests/migration-046-budgets.test.ts +3 -3
- package/src/tests/model-catalog-migration.test.ts +134 -0
- package/src/tests/model-catalog-table.test.ts +249 -0
- package/src/tests/model-catalog-write-access.test.ts +387 -0
- package/src/tests/model-rate-limit-windows.test.ts +19 -0
- package/src/tests/model-tier-resolution.test.ts +611 -0
- package/src/tests/models-catalog.test.ts +1 -1
- package/src/tests/multi-runtime-enabled-stats.test.ts +65 -1
- package/src/tests/opencode-adapter.test.ts +157 -2
- package/src/tests/package-publish.test.ts +137 -36
- package/src/tests/pi-codemode.test.ts +246 -0
- package/src/tests/pi-mono-adapter.test.ts +3 -0
- package/src/tests/pi-native-mcp.test.ts +193 -0
- package/src/tests/pi-tool-exposure.test.ts +374 -0
- package/src/tests/preload.ts +3 -0
- package/src/tests/pricing-routes.test.ts +2 -2
- package/src/tests/prompt-template-session.test.ts +5 -3
- package/src/tests/rate-limit-event.test.ts +65 -0
- package/src/tests/rate-limit-outcome.test.ts +90 -0
- package/src/tests/rbac-engine.test.ts +77 -3
- package/src/tests/reasoning-effort.test.ts +109 -0
- package/src/tests/refresh-modelsdev-carryforward.test.ts +5 -5
- package/src/tests/runner-key-completion-outcome.test.ts +112 -0
- package/src/tests/runner-key-outcome-late-reset.test.ts +224 -0
- package/src/tests/runner-registration-retry.test.ts +149 -0
- package/src/tests/runtime-model-catalog.test.ts +86 -0
- package/src/tests/script-connections.test.ts +9 -0
- package/src/tests/seat-mismatch-report.test.ts +85 -0
- package/src/tests/seed-scripts.test.ts +138 -0
- package/src/tests/seed.test.ts +25 -0
- package/src/tests/session-costs.test.ts +14 -11
- package/src/tests/slack-message-text.test.ts +101 -0
- package/src/tests/slack-render-v2.test.ts +96 -0
- package/src/tests/slack-session-status.test.ts +626 -0
- package/src/tests/slack-thread-buffer-context.test.ts +93 -0
- package/src/tests/status.test.ts +29 -0
- package/src/tests/steering-promotion.test.ts +51 -0
- package/src/tests/store-progress-ownership.test.ts +136 -0
- package/src/tests/subscription-plans.test.ts +28 -0
- package/src/tests/task-cascade-fail.test.ts +148 -2
- package/src/tests/task-citations.test.ts +3 -2
- package/src/tests/tool-annotations.test.ts +1 -1
- package/src/tests/usage-cache.test.ts +166 -0
- package/src/tests/workflow-agent-task.test.ts +30 -0
- package/src/tests/workflow-executors.test.ts +5 -2
- package/src/tests/workflow-system-one-decision-review.test.ts +1021 -0
- package/src/tests/workflow-system-one-decision-save-warnings.test.ts +365 -0
- package/src/tests/workflow-system-one-decision.test.ts +2063 -0
- package/src/tests/workflow-triggers-v2.test.ts +320 -0
- package/src/tools/model-catalog/index.ts +137 -0
- package/src/tools/schedules/create-schedule.ts +17 -2
- package/src/tools/schedules/patch-schedule.ts +31 -1
- package/src/tools/schedules/update-schedule.ts +31 -1
- package/src/tools/send-task.ts +18 -1
- package/src/tools/store-progress.ts +49 -4
- package/src/tools/task-action.ts +14 -1
- package/src/tools/tool-config.ts +3 -1
- package/src/tools/workflows/create-workflow.ts +17 -4
- package/src/tools/workflows/patch-workflow-node.ts +17 -7
- package/src/tools/workflows/patch-workflow.ts +9 -2
- package/src/tools/workflows/update-workflow.ts +17 -4
- package/src/types.ts +41 -1
- package/src/utils/codex-auth-failure.ts +34 -0
- package/src/utils/context-window.ts +47 -53
- package/src/utils/credentials.ts +72 -30
- package/src/utils/error-tracker.ts +80 -0
- package/src/utils/harness-cli-version.ts +115 -0
- package/src/utils/harness-model-error.ts +33 -0
- package/src/utils/model-rate-limit-windows.ts +12 -0
- package/src/utils/runtime-model-catalog.ts +152 -0
- package/src/utils/spawn-model-guard.ts +43 -0
- package/src/utils/subscription-plans.ts +22 -0
- package/src/workflows/approval-resolution.ts +39 -0
- package/src/workflows/definition.ts +7 -0
- package/src/workflows/engine.ts +69 -1
- package/src/workflows/executors/agent-task.ts +16 -6
- package/src/workflows/executors/base.ts +53 -0
- package/src/workflows/executors/human-in-the-loop.ts +8 -8
- package/src/workflows/executors/index.ts +1 -0
- package/src/workflows/executors/registry.ts +2 -0
- package/src/workflows/executors/system-one-decision.ts +1232 -0
- package/src/workflows/executors/system-one-providers.ts +301 -0
- package/src/workflows/executors/workflow-llm.ts +13 -1
- package/src/workflows/model-validation.ts +45 -0
- package/src/workflows/patch-definition.ts +5 -0
- package/src/workflows/readiness.ts +86 -0
- package/src/workflows/recovery.ts +12 -12
- package/src/workflows/resume.ts +23 -9
- package/src/workflows/triggers.ts +85 -0
- package/templates/schedules/daily-blocker-digest/content.md +4 -5
- package/templates/skills/agent-browser/SKILL.md +6 -5
- package/templates/skills/agent-browser/content.md +6 -5
- package/templates/skills/heartbeat-runbook/config.json +1 -1
- package/templates/skills/heartbeat-runbook/content.md +2 -2
- package/templates/skills/swarm-scripts/SKILL.md +1 -1
- package/templates/skills/swarm-scripts/content.md +1 -1
- package/templates/skills/workflow-iterate/content.md +82 -1
- package/templates/workflows/claude-code-changelog-watch/content.md +2 -0
- package/templates/workflows/pr-review-status-sweep/content.md +2 -0
- package/dist/boot-seeds-s3q01xj3.js +0 -26
- package/dist/claude-sdk-session-t442qz6f.js +0 -39108
- package/dist/cli-0xjkj1j7.js +0 -61
- package/dist/cli-20cj37vt.js +0 -335561
- package/dist/cli-2djtr51b.js +0 -48
- package/dist/cli-65hjmev5.js +0 -1141
- package/dist/cli-aw1jwp1r.js +0 -14075
- package/dist/cli-h967nb6r.js +0 -6603
- package/dist/cli-vapyk8sw.js +0 -20
- package/dist/cli-ws6rqycm.js +0 -247
- package/dist/pricing-refresh-v1cbr9te.js +0 -27
- package/src/providers/modelsdev-reasoning.json +0 -6453
- package/dist/{index-f24115ge.js → index-2wsdsnmm.js} +3 -3
|
@@ -2,21 +2,28 @@
|
|
|
2
2
|
* Normalized per-agent reasoning/effort control, shared across the four
|
|
3
3
|
* local harnesses (`claude`, `codex`, `pi`, `opencode`).
|
|
4
4
|
*
|
|
5
|
-
* Pure module — no DB import, no network I/O
|
|
6
|
-
* read from the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
5
|
+
* Pure module — no DB import, no network I/O of its own. Capability data is
|
|
6
|
+
* read from the model catalog (`src/utils/runtime-model-catalog.ts`: live
|
|
7
|
+
* `model_catalog` + overlay rows, vendored models.dev snapshot offline),
|
|
8
|
+
* layered with a small harness-specific override table for quirks the
|
|
9
|
+
* catalog can't encode. A new model's reasoning levels arrive with its
|
|
10
|
+
* catalog row (model-catalog phase 4). See
|
|
10
11
|
* `thoughts/taras/plans/2026-07-01-agent-reasoning-effort-runtime-control.md`
|
|
11
12
|
* (Phase 1) and `thoughts/taras/research/2026-05-26-agent-reasoning-effort-runtime-control.md`
|
|
12
13
|
* for the design rationale.
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
|
-
import
|
|
16
|
+
import {
|
|
17
|
+
claudeCatalogModelId,
|
|
18
|
+
REASONING_EFFORT_LEVELS,
|
|
19
|
+
type ReasoningEffortLevel,
|
|
20
|
+
reasoningLevelsFor,
|
|
21
|
+
} from "@desplega/model-catalog";
|
|
22
|
+
import { runtimeCatalogModel, runtimeCatalogSection } from "../utils/runtime-model-catalog";
|
|
16
23
|
|
|
17
24
|
/** Closed, normalized enum. `minimal` remains out of scope; GPT-5.6 Codex adds `max`. */
|
|
18
|
-
export
|
|
19
|
-
export type ReasoningEffort =
|
|
25
|
+
export { REASONING_EFFORT_LEVELS };
|
|
26
|
+
export type ReasoningEffort = ReasoningEffortLevel;
|
|
20
27
|
|
|
21
28
|
/** The four local harnesses this feature covers (Devin / claude-managed are out of scope). */
|
|
22
29
|
export type ReasoningHarness = "claude" | "codex" | "pi" | "opencode";
|
|
@@ -45,44 +52,7 @@ export type ReasoningEffortApplication =
|
|
|
45
52
|
}
|
|
46
53
|
| { kind: "noop" };
|
|
47
54
|
|
|
48
|
-
// ---
|
|
49
|
-
|
|
50
|
-
interface SlimReasoningOption {
|
|
51
|
-
type: string;
|
|
52
|
-
values?: string[];
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
interface SlimModelEntry {
|
|
56
|
-
id: string;
|
|
57
|
-
reasoning: boolean;
|
|
58
|
-
reasoningOptions?: SlimReasoningOption[];
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Providers the snapshot covers — mirrors `SNAPSHOT_ORDER` +
|
|
63
|
-
* `BEDROCK_SNAPSHOT_ID` in `apps/ui/src/lib/agent-runtime-models.ts`. Direct
|
|
64
|
-
* `claude`/`codex` model strings (no provider prefix) resolve against
|
|
65
|
-
* `anthropic`/`openai` respectively; `pi`/`opencode` model strings are always
|
|
66
|
-
* `<providerId>/<model-id>` (see `splitProviderModel`).
|
|
67
|
-
*/
|
|
68
|
-
type SnapshotProviderId = "anthropic" | "openai" | "openrouter" | "amazon-bedrock";
|
|
69
|
-
|
|
70
|
-
type ReasoningSnapshot = Partial<Record<SnapshotProviderId, Record<string, SlimModelEntry>>>;
|
|
71
|
-
|
|
72
|
-
const SNAPSHOT = reasoningSnapshotJson as ReasoningSnapshot;
|
|
73
|
-
|
|
74
|
-
/** Shared-safe subset accepted by all four harnesses on at least their default models (see research doc). */
|
|
75
|
-
const FALLBACK_LEVELS: ReasoningEffort[] = ["low", "medium", "high"];
|
|
76
|
-
|
|
77
|
-
/** models.dev `reasoning_options[].type === "effort"` value → our normalized enum. `minimal` intentionally dropped. */
|
|
78
|
-
const EFFORT_VALUE_MAP: Partial<Record<string, ReasoningEffort>> = {
|
|
79
|
-
none: "off",
|
|
80
|
-
low: "low",
|
|
81
|
-
medium: "medium",
|
|
82
|
-
high: "high",
|
|
83
|
-
xhigh: "xhigh",
|
|
84
|
-
max: "max",
|
|
85
|
-
};
|
|
55
|
+
// --- Capability lookup --------------------------------------------------------
|
|
86
56
|
|
|
87
57
|
function splitProviderModel(model: string): { providerId: string; modelId: string } {
|
|
88
58
|
const slash = model.indexOf("/");
|
|
@@ -90,81 +60,33 @@ function splitProviderModel(model: string): { providerId: string; modelId: strin
|
|
|
90
60
|
return { providerId: model.slice(0, slash), modelId: model.slice(slash + 1) };
|
|
91
61
|
}
|
|
92
62
|
|
|
93
|
-
function lookupModelEntry(harness: ReasoningHarness, model: string): SlimModelEntry | undefined {
|
|
94
|
-
if (!model) return undefined;
|
|
95
|
-
if (harness === "claude") return SNAPSHOT.anthropic?.[model];
|
|
96
|
-
if (harness === "codex") return SNAPSHOT.openai?.[model];
|
|
97
|
-
// pi / opencode model strings are always "<provider>/<model-id...>" — the
|
|
98
|
-
// model id itself may contain further slashes (e.g. openrouter's
|
|
99
|
-
// "google/gemini-3-flash-preview"), so split on the FIRST slash only.
|
|
100
|
-
const { providerId, modelId } = splitProviderModel(model);
|
|
101
|
-
if (!providerId) return undefined;
|
|
102
|
-
return SNAPSHOT[providerId as SnapshotProviderId]?.[modelId];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function levelsFromReasoningOptions(options: SlimReasoningOption[] | undefined): ReasoningEffort[] {
|
|
106
|
-
const effortEntry = options?.find((o) => o.type === "effort");
|
|
107
|
-
if (!effortEntry?.values?.length) return [];
|
|
108
|
-
const mapped = new Set(
|
|
109
|
-
effortEntry.values
|
|
110
|
-
.map((v) => EFFORT_VALUE_MAP[v])
|
|
111
|
-
.filter((v): v is ReasoningEffort => v !== undefined),
|
|
112
|
-
);
|
|
113
|
-
// Preserve canonical ordering rather than whatever order models.dev lists them in.
|
|
114
|
-
return REASONING_EFFORT_LEVELS.filter((level) => mapped.has(level));
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
function hasBudgetTokensOption(entry: SlimModelEntry): boolean {
|
|
118
|
-
return Boolean(entry.reasoningOptions?.some((o) => o.type === "budget_tokens"));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
63
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
64
|
+
* The (catalog id, catalog facts) a harness's model string names. Direct
|
|
65
|
+
* `claude`/`codex` strings (no provider prefix) resolve against
|
|
66
|
+
* `anthropic`/`openai`; a Claude CLI shortname (`opus`, the tier default)
|
|
67
|
+
* resolves to the newest model of its family. `pi`/`opencode` strings are
|
|
68
|
+
* always `<providerId>/<model-id>`, and the id may hold more slashes (openrouter's
|
|
69
|
+
* `google/gemini-3-flash-preview`), so split on the FIRST slash only.
|
|
125
70
|
*/
|
|
126
|
-
function
|
|
71
|
+
function lookupModel(
|
|
127
72
|
harness: ReasoningHarness,
|
|
128
73
|
model: string,
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
let
|
|
133
|
-
|
|
74
|
+
): { id: string; facts: ReturnType<typeof runtimeCatalogModel> } | undefined {
|
|
75
|
+
if (!model) return undefined;
|
|
76
|
+
let providerId: string;
|
|
77
|
+
let modelId: string;
|
|
134
78
|
if (harness === "claude") {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
if (
|
|
143
|
-
result = ["off", ...result];
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (harness !== "codex") {
|
|
148
|
-
result = result.filter((l) => l !== "max");
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (harness === "codex") {
|
|
152
|
-
// The cache already tends to encode this correctly per model (verified:
|
|
153
|
-
// `gpt-5.1-codex` excludes xhigh, `gpt-5.1-codex-max` includes it). This
|
|
154
|
-
// rule is defense-in-depth for models missing from the snapshot (the
|
|
155
|
-
// {low,medium,high} fallback path), where naming alone should still
|
|
156
|
-
// decide xhigh eligibility for `*-codex` family models.
|
|
157
|
-
const isCodexMax = /-codex-max$/.test(model);
|
|
158
|
-
const isCodexNonMax = /-codex$/.test(model) && !isCodexMax;
|
|
159
|
-
if (isCodexMax && !result.includes("xhigh")) {
|
|
160
|
-
result = [...result, "xhigh"];
|
|
161
|
-
}
|
|
162
|
-
if (isCodexNonMax) {
|
|
163
|
-
result = result.filter((l) => l !== "xhigh");
|
|
164
|
-
}
|
|
79
|
+
providerId = "anthropic";
|
|
80
|
+
modelId = claudeCatalogModelId(model, runtimeCatalogSection("anthropic"));
|
|
81
|
+
} else if (harness === "codex") {
|
|
82
|
+
providerId = "openai";
|
|
83
|
+
modelId = model;
|
|
84
|
+
} else {
|
|
85
|
+
({ providerId, modelId } = splitProviderModel(model));
|
|
86
|
+
if (!providerId) return undefined;
|
|
165
87
|
}
|
|
166
|
-
|
|
167
|
-
return
|
|
88
|
+
const facts = runtimeCatalogModel(providerId, modelId);
|
|
89
|
+
return facts ? { id: modelId, facts } : undefined;
|
|
168
90
|
}
|
|
169
91
|
|
|
170
92
|
function pickDefault(levels: ReasoningEffort[]): ReasoningEffort | null {
|
|
@@ -173,33 +95,15 @@ function pickDefault(levels: ReasoningEffort[]): ReasoningEffort | null {
|
|
|
173
95
|
}
|
|
174
96
|
|
|
175
97
|
/**
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
* 3. `reasoning_options` has a usable `type: "effort"` entry → levels come
|
|
181
|
-
* from its `values` (mapped/filtered — `none`→`off`, `minimal` dropped).
|
|
182
|
-
* 4. Otherwise (`reasoning: true`, no usable effort entry) → the shared-safe
|
|
183
|
-
* fallback subset `{low, medium, high}`.
|
|
184
|
-
* 5. Harness-specific override table applied on top for known quirks.
|
|
98
|
+
* The levels `(harness, model)` accepts, from the catalog facts
|
|
99
|
+
* (`reasoningLevelsFor`, shared with the swarm app's effort pickers). Unknown
|
|
100
|
+
* models (custom strings, ids the catalog lacks) and non-reasoning models are
|
|
101
|
+
* unsupported.
|
|
185
102
|
*/
|
|
186
103
|
export function reasoningCapability(harness: ReasoningHarness, model: string): ReasoningCapability {
|
|
187
|
-
const entry =
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
let levels = levelsFromReasoningOptions(entry.reasoningOptions);
|
|
193
|
-
if (levels.length === 0) {
|
|
194
|
-
levels = [...FALLBACK_LEVELS];
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
levels = applyHarnessOverrides(harness, model, entry, levels);
|
|
198
|
-
|
|
199
|
-
if (levels.length === 0) {
|
|
200
|
-
return { supported: false, levels: [], default: null };
|
|
201
|
-
}
|
|
202
|
-
|
|
104
|
+
const entry = lookupModel(harness, model);
|
|
105
|
+
const levels = entry ? reasoningLevelsFor(harness, entry.id, entry.facts) : [];
|
|
106
|
+
if (levels.length === 0) return { supported: false, levels: [], default: null };
|
|
203
107
|
return { supported: true, levels, default: pickDefault(levels) };
|
|
204
108
|
}
|
|
205
109
|
|
package/src/providers/types.ts
CHANGED
|
@@ -203,6 +203,12 @@ export interface ProviderResult {
|
|
|
203
203
|
* rejection event arrived; it orders the report against other workers'.
|
|
204
204
|
*/
|
|
205
205
|
modelRateLimit?: { window: string; model: ModelFamily; resetAt: string; observedAt?: string };
|
|
206
|
+
/**
|
|
207
|
+
* Set when the Claude CLI sent a rejected `rate_limit_event` with
|
|
208
|
+
* `errorCode: "credits_required"`: the key's seat cannot run the model. Not
|
|
209
|
+
* a rate limit, so `rateLimitResetAt` is never set from that event.
|
|
210
|
+
*/
|
|
211
|
+
creditsRequired?: { observedAt: string; overageDisabledReason?: string };
|
|
206
212
|
/**
|
|
207
213
|
* Reasoning/effort level the adapter actually applied (Phase 4). `null`
|
|
208
214
|
* means `applyReasoningEffort()` returned `noop` (capability rejected the
|
|
@@ -216,6 +222,8 @@ export interface ProviderResult {
|
|
|
216
222
|
export interface ProviderTraits {
|
|
217
223
|
/** Provider can call MCP tools (store-progress, task-action, skills, slack-reply, etc.) */
|
|
218
224
|
hasMcp: boolean;
|
|
225
|
+
/** Provider hides MCP tools behind a native tool search. Defaults to false. */
|
|
226
|
+
hasToolSearch?: boolean;
|
|
219
227
|
/**
|
|
220
228
|
* Provider discovers installed skills on its own — it reads the local skills
|
|
221
229
|
* tree and ambient-injects each skill's name + description into the session
|
|
@@ -56,6 +56,27 @@ const leadOrOperatorOrUser: LegacyRule = {
|
|
|
56
56
|
principal.kind === "operator" || principal.kind === "user" || actsAsLead(principal),
|
|
57
57
|
};
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Lead agents and the operator (shared API key with no agent identity). Plain dashboard users are
|
|
61
|
+
* left out: nothing in the UI writes through a verb with this rule yet.
|
|
62
|
+
*/
|
|
63
|
+
const leadOrOperator: LegacyRule = {
|
|
64
|
+
name: "lead-or-operator",
|
|
65
|
+
denyReason: "requires lead agent or operator authentication",
|
|
66
|
+
evaluate: (principal) => principal.kind === "operator" || actsAsLead(principal),
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Registered agents and the operator. Dashboard users are left out: a support row is a worker's
|
|
71
|
+
* report about its own CLI (or an operator correction), and no UI writes one.
|
|
72
|
+
*/
|
|
73
|
+
const agentOrOperator: LegacyRule = {
|
|
74
|
+
name: "agent-or-operator",
|
|
75
|
+
denyReason: "requires a registered agent or operator authentication",
|
|
76
|
+
evaluate: (principal) =>
|
|
77
|
+
principal.kind === "operator" || (principal.kind === "agent" && principal.agentId !== ""),
|
|
78
|
+
};
|
|
79
|
+
|
|
59
80
|
const extensionWrite: LegacyRule = {
|
|
60
81
|
name: "extension-owner-or-elevated",
|
|
61
82
|
denyReason: "requires extension owner, lead agent, operator, or user authentication",
|
|
@@ -195,10 +216,29 @@ const taskFsMutate: LegacyRule = {
|
|
|
195
216
|
},
|
|
196
217
|
};
|
|
197
218
|
|
|
219
|
+
/**
|
|
220
|
+
* task.progress.write — operator OR user OR lead OR task-assignee OR unassigned
|
|
221
|
+
* task (store-progress, POST /api/tasks/{id}/progress). A worker once completed
|
|
222
|
+
* a workflow sibling's task with its own report; the creator gets no write
|
|
223
|
+
* here, unlike task.fs.mutate. Leads may write, unlike HTTP finish.
|
|
224
|
+
*/
|
|
225
|
+
const taskProgressWrite: LegacyRule = {
|
|
226
|
+
name: "operator-or-user-or-lead-or-task-assignee",
|
|
227
|
+
denyReason: "requires operator, user, lead agent, or task assignee",
|
|
228
|
+
evaluate: (principal, resource) => {
|
|
229
|
+
if (principal.kind === "operator" || principal.kind === "user") return true;
|
|
230
|
+
if (actsAsLead(principal)) return true;
|
|
231
|
+
if (resource?.kind !== "task") return false;
|
|
232
|
+
return resource.agentId == null || resource.agentId === principal.agentId;
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
|
|
198
236
|
/** All named (non-composite) rule kinds, keyed by identifier. */
|
|
199
237
|
export const LEGACY_RULES = {
|
|
200
238
|
"operator-or-user": operatorOrUser,
|
|
201
239
|
"lead-or-operator-or-user": leadOrOperatorOrUser,
|
|
240
|
+
"lead-or-operator": leadOrOperator,
|
|
241
|
+
"agent-or-operator": agentOrOperator,
|
|
202
242
|
"lead-only": leadOnly,
|
|
203
243
|
"lead-or-task-creator": leadOrTaskCreator,
|
|
204
244
|
"lead-or-resource-owner": leadOrResourceOwner,
|
|
@@ -223,6 +263,7 @@ export const LEGACY_POLICY = {
|
|
|
223
263
|
"task.steer.own": requesterOwnsTask,
|
|
224
264
|
"task.action.own": requesterOwnsTask,
|
|
225
265
|
"task.fs.mutate": taskFsMutate,
|
|
266
|
+
"task.progress.write": taskProgressWrite,
|
|
226
267
|
"favorite.write.own": anyAuthenticated,
|
|
227
268
|
"memory.learning.inject": leadOnly,
|
|
228
269
|
"memory.edit.any": leadOrResourceOwner,
|
|
@@ -246,6 +287,8 @@ export const LEGACY_POLICY = {
|
|
|
246
287
|
"config.write.any": leadOnly,
|
|
247
288
|
"config.delete.any": leadOnly,
|
|
248
289
|
"config.read.secrets": leadOnly,
|
|
290
|
+
"models.catalog.write": leadOrOperator,
|
|
291
|
+
"models.harness-support.write": agentOrOperator,
|
|
249
292
|
"skill.create.swarm": leadOnly,
|
|
250
293
|
"skill.install.any": leadOnly,
|
|
251
294
|
"skill.install.global": leadOnly,
|
package/src/rbac/permissions.ts
CHANGED
|
@@ -65,6 +65,11 @@ export const PERMISSIONS = {
|
|
|
65
65
|
description: "Mutate a task's filesystem artifacts and attachments.",
|
|
66
66
|
namespace: "task",
|
|
67
67
|
},
|
|
68
|
+
"task.progress.write": {
|
|
69
|
+
description:
|
|
70
|
+
"Write a task's progress, status, or output (its assignee, a lead, a human, or anyone while unassigned).",
|
|
71
|
+
namespace: "task",
|
|
72
|
+
},
|
|
68
73
|
"favorite.write.own": {
|
|
69
74
|
description: "Set a favorite the caller owns.",
|
|
70
75
|
namespace: "favorite",
|
|
@@ -153,6 +158,16 @@ export const PERMISSIONS = {
|
|
|
153
158
|
description: "Delete any swarm-config entry.",
|
|
154
159
|
namespace: "config",
|
|
155
160
|
},
|
|
161
|
+
"models.catalog.write": {
|
|
162
|
+
description:
|
|
163
|
+
"Force a model-catalog refresh from models.dev or write/delete model-catalog overlay rows.",
|
|
164
|
+
namespace: "models",
|
|
165
|
+
},
|
|
166
|
+
"models.harness-support.write": {
|
|
167
|
+
description:
|
|
168
|
+
"Record whether a pinned harness CLI version accepts a model (a worker reports its own probe results; the operator may correct any row).",
|
|
169
|
+
namespace: "models",
|
|
170
|
+
},
|
|
156
171
|
"config.read.secrets": {
|
|
157
172
|
description: "Read unmasked secret config values.",
|
|
158
173
|
namespace: "config",
|
|
@@ -80,6 +80,10 @@ export const SDK_TOOL_NAME_MAP = {
|
|
|
80
80
|
config_set: "set-config",
|
|
81
81
|
config_delete: "delete-config", // destructive
|
|
82
82
|
|
|
83
|
+
// ── model catalog ──
|
|
84
|
+
modelCatalog_refresh: "model-catalog-refresh", // external: fetches models.dev
|
|
85
|
+
modelCatalog_overlayUpsert: "model-catalog-overlay-upsert",
|
|
86
|
+
|
|
83
87
|
// ── slack ──
|
|
84
88
|
slack_read: "slack-read",
|
|
85
89
|
slack_listChannels: "slack-list-channels",
|
|
@@ -433,6 +433,21 @@ declare module "swarm-sdk" {
|
|
|
433
433
|
}): Promise<unknown>;
|
|
434
434
|
config_delete(args: { id: string }): Promise<unknown>;
|
|
435
435
|
|
|
436
|
+
// --- write: model catalog ---
|
|
437
|
+
modelCatalog_refresh(args?: { force?: boolean }): Promise<unknown>;
|
|
438
|
+
modelCatalog_overlayUpsert(args: {
|
|
439
|
+
provider: string;
|
|
440
|
+
modelId: string;
|
|
441
|
+
name?: string;
|
|
442
|
+
releaseDate?: string;
|
|
443
|
+
contextWindow?: number;
|
|
444
|
+
maxOutput?: number;
|
|
445
|
+
reasoningOptions?: Array<{ type: string; values?: string[] }>;
|
|
446
|
+
pricing?: { input?: number; output?: number; cache_read?: number; cache_write?: number };
|
|
447
|
+
reason: string;
|
|
448
|
+
verifiedBy?: string;
|
|
449
|
+
}): Promise<unknown>;
|
|
450
|
+
|
|
436
451
|
// --- write: slack ---
|
|
437
452
|
slack_post(args: { channelId: string; message: string; blocks?: unknown }): Promise<unknown>;
|
|
438
453
|
slack_reply(args: {
|
|
@@ -180,6 +180,9 @@ declare module "swarm-extension" {
|
|
|
180
180
|
model?: string | undefined;
|
|
181
181
|
modelTier?: "smol" | "regular" | "smart" | "ultra" | undefined;
|
|
182
182
|
effort?: "off" | "low" | "medium" | "high" | "xhigh" | "max" | undefined;
|
|
183
|
+
resolvedModel?: string | undefined;
|
|
184
|
+
modelSource?: string | undefined;
|
|
185
|
+
modelAlias?: string | undefined;
|
|
183
186
|
scheduleId?: string | undefined;
|
|
184
187
|
workflowRunId?: string | null | undefined;
|
|
185
188
|
workflowRunStepId?: string | null | undefined;
|
|
@@ -415,6 +415,21 @@ declare module "swarm-sdk" {
|
|
|
415
415
|
}): Promise<unknown>;
|
|
416
416
|
config_delete(args: { id: string }): Promise<unknown>;
|
|
417
417
|
|
|
418
|
+
// --- write: model catalog ---
|
|
419
|
+
modelCatalog_refresh(args?: { force?: boolean }): Promise<unknown>;
|
|
420
|
+
modelCatalog_overlayUpsert(args: {
|
|
421
|
+
provider: string;
|
|
422
|
+
modelId: string;
|
|
423
|
+
name?: string;
|
|
424
|
+
releaseDate?: string;
|
|
425
|
+
contextWindow?: number;
|
|
426
|
+
maxOutput?: number;
|
|
427
|
+
reasoningOptions?: Array<{ type: string; values?: string[] }>;
|
|
428
|
+
pricing?: { input?: number; output?: number; cache_read?: number; cache_write?: number };
|
|
429
|
+
reason: string;
|
|
430
|
+
verifiedBy?: string;
|
|
431
|
+
}): Promise<unknown>;
|
|
432
|
+
|
|
418
433
|
// --- write: slack ---
|
|
419
434
|
slack_post(args: { channelId: string; message: string; blocks?: unknown }): Promise<unknown>;
|
|
420
435
|
slack_reply(args: {
|
package/src/server.ts
CHANGED
|
@@ -73,6 +73,10 @@ import { registerMemoryGetTool } from "./tools/memory-get";
|
|
|
73
73
|
import { registerMemoryRateTool } from "./tools/memory-rate";
|
|
74
74
|
import { registerMemorySearchTool } from "./tools/memory-search";
|
|
75
75
|
import { registerMemoryStoreTool } from "./tools/memory-store";
|
|
76
|
+
import {
|
|
77
|
+
registerModelCatalogOverlayUpsertTool,
|
|
78
|
+
registerModelCatalogRefreshTool,
|
|
79
|
+
} from "./tools/model-catalog";
|
|
76
80
|
import { registerMyAgentInfoTool } from "./tools/my-agent-info";
|
|
77
81
|
import { registerGetOauthAccessTokenTool } from "./tools/oauth-access-token";
|
|
78
82
|
import { registerPollTaskTool } from "./tools/poll-task";
|
|
@@ -413,6 +417,8 @@ export async function createServer(
|
|
|
413
417
|
registerListConfigTool(server);
|
|
414
418
|
registerDeleteConfigTool(server);
|
|
415
419
|
registerCredentialBindingsTool(server);
|
|
420
|
+
registerModelCatalogRefreshTool(server);
|
|
421
|
+
registerModelCatalogOverlayUpsertTool(server);
|
|
416
422
|
}
|
|
417
423
|
|
|
418
424
|
// Scripts capability - reusable script catalog (HTTP MCP only in v1)
|
package/src/slack/assistant.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "./inbound-files";
|
|
15
15
|
import { ensureSlackThreadTree, isSlackRenderV2Enabled } from "./render-v2";
|
|
16
16
|
import { hasOtherUserMention } from "./router";
|
|
17
|
+
import { markSlackSessionProcessing } from "./session-status";
|
|
17
18
|
import { bufferThreadMessage, getBufferMessageCount } from "./thread-buffer";
|
|
18
19
|
// Side-effect import: registers all Slack event templates in the in-memory registry
|
|
19
20
|
import "./templates";
|
|
@@ -65,7 +66,18 @@ export function createAssistant(): Assistant {
|
|
|
65
66
|
// Wrap setStatus/setTitle to swallow all errors gracefully.
|
|
66
67
|
// These calls can fail for various reasons (no_permission when the thread
|
|
67
68
|
// wasn't started by the assistant, network errors, etc.), so we log and continue.
|
|
69
|
+
// With the v2 renderer Slack's native session status carries the "working"
|
|
70
|
+
// state for the whole ask (see session-status.ts), so the legacy free-text
|
|
71
|
+
// status below is only the fallback when the native call is unavailable.
|
|
72
|
+
let statusThread: { channelId: string; threadTs: string } | undefined;
|
|
68
73
|
const safeSetStatus = async (status: string) => {
|
|
74
|
+
if (
|
|
75
|
+
statusThread &&
|
|
76
|
+
isSlackRenderV2Enabled() &&
|
|
77
|
+
(await markSlackSessionProcessing({ ...statusThread, client }))
|
|
78
|
+
) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
69
81
|
try {
|
|
70
82
|
await setStatus(status);
|
|
71
83
|
} catch (error) {
|
|
@@ -85,6 +97,7 @@ export function createAssistant(): Assistant {
|
|
|
85
97
|
const msg = message as unknown as Record<string, unknown>;
|
|
86
98
|
const threadTs = (msg.thread_ts as string) || message.ts;
|
|
87
99
|
const channelId = message.channel;
|
|
100
|
+
statusThread = { channelId, threadTs };
|
|
88
101
|
const messageText = (msg.text as string) || "";
|
|
89
102
|
// `file_share` messages land here too: an image sent with no caption
|
|
90
103
|
// arrives with empty `text` and everything in `files`.
|
|
@@ -52,6 +52,34 @@ function collectRichTextParts(node: unknown, parts: string[]): void {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* Turn top-level mrkdwn `text` into the plain text a rich_text block flattens
|
|
57
|
+
* to: drop `<…>` tokens (user/channel mentions, links, `<!here>`), which
|
|
58
|
+
* collectRichTextParts does not emit, then decode Slack's HTML escapes.
|
|
59
|
+
*/
|
|
60
|
+
function decodeMrkdwn(text: string): string {
|
|
61
|
+
return text
|
|
62
|
+
.replace(/<[^<>]*>/g, "")
|
|
63
|
+
.replace(/</g, "<")
|
|
64
|
+
.replace(/>/g, ">")
|
|
65
|
+
.replace(/&/g, "&");
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Normalize text for the text-vs-rich_text equality check only (never for
|
|
70
|
+
* output): drop emoji shortcodes, quote and list markers, and mrkdwn style
|
|
71
|
+
* characters, which rich_text carries as element types or style flags rather
|
|
72
|
+
* than characters, then all whitespace, since flattening joins styled runs
|
|
73
|
+
* with newlines.
|
|
74
|
+
*/
|
|
75
|
+
function normalizeForDedupe(text: string): string {
|
|
76
|
+
return text
|
|
77
|
+
.replace(/:[a-z0-9_+'-]+:/gi, "")
|
|
78
|
+
.replace(/^[ \t]*(?:>|[•◦▪‣-]|\d+\.)[ \t]*/gm, "")
|
|
79
|
+
.replace(/[*_~`]/g, "")
|
|
80
|
+
.replace(/\s+/g, "");
|
|
81
|
+
}
|
|
82
|
+
|
|
55
83
|
/**
|
|
56
84
|
* Return displayable text for a Slack message, combining ALL content layers.
|
|
57
85
|
*
|
|
@@ -64,7 +92,8 @@ function collectRichTextParts(node: unknown, parts: string[]): void {
|
|
|
64
92
|
*
|
|
65
93
|
* Dedup: if `msg.text` is already contained verbatim in the combined
|
|
66
94
|
* attachments+blocks body (fallback echoed in a block), it is omitted to avoid
|
|
67
|
-
* printing it twice.
|
|
95
|
+
* printing it twice. A rich_text block whose content equals `msg.text` after
|
|
96
|
+
* normalization is omitted instead (see below).
|
|
68
97
|
*
|
|
69
98
|
* Block types extracted: section (text + fields), rich_text, header, context,
|
|
70
99
|
* actions (button label + url as mrkdwn link).
|
|
@@ -123,6 +152,9 @@ export function extractSlackMessageText(msg: SlackMessageLike): string {
|
|
|
123
152
|
|
|
124
153
|
// Block Kit blocks
|
|
125
154
|
const blockParts: string[] = [];
|
|
155
|
+
// Index range of each rich_text block's parts inside blockParts, so a
|
|
156
|
+
// rich_text block that merely re-renders `msg.text` can be dropped below.
|
|
157
|
+
const richTextRanges: Array<[number, number]> = [];
|
|
126
158
|
if (Array.isArray(msg.blocks) && msg.blocks.length > 0) {
|
|
127
159
|
for (const rawBlock of msg.blocks) {
|
|
128
160
|
if (rawBlock == null || typeof rawBlock !== "object") continue;
|
|
@@ -137,9 +169,11 @@ export function extractSlackMessageText(msg: SlackMessageLike): string {
|
|
|
137
169
|
}
|
|
138
170
|
}
|
|
139
171
|
} else if (block.type === "rich_text" && Array.isArray(block.elements)) {
|
|
172
|
+
const start = blockParts.length;
|
|
140
173
|
for (const el of block.elements) {
|
|
141
174
|
collectRichTextParts(el, blockParts);
|
|
142
175
|
}
|
|
176
|
+
if (blockParts.length > start) richTextRanges.push([start, blockParts.length]);
|
|
143
177
|
} else if (block.type === "header") {
|
|
144
178
|
if (block.text?.text) blockParts.push(block.text.text);
|
|
145
179
|
} else if (block.type === "context" && Array.isArray(block.elements)) {
|
|
@@ -162,7 +196,27 @@ export function extractSlackMessageText(msg: SlackMessageLike): string {
|
|
|
162
196
|
}
|
|
163
197
|
}
|
|
164
198
|
|
|
165
|
-
|
|
199
|
+
// A human message carries the same content twice: `text` (mrkdwn) and a
|
|
200
|
+
// rich_text block. The block flattens to one part per styled run, so the
|
|
201
|
+
// per-line check below never matches a multi-line or formatted message and
|
|
202
|
+
// the whole message would render twice. When the rich_text content equals
|
|
203
|
+
// `text` after normalization, keep `text` (it also carries the mentions,
|
|
204
|
+
// links and emoji the rich_text flattening drops) and skip the blocks.
|
|
205
|
+
let bodyBlockParts = blockParts;
|
|
206
|
+
if (topText && richTextRanges.length > 0) {
|
|
207
|
+
const richText = richTextRanges
|
|
208
|
+
.map(([start, end]) => blockParts.slice(start, end).join("\n"))
|
|
209
|
+
.join("\n");
|
|
210
|
+
if (normalizeForDedupe(richText) === normalizeForDedupe(decodeMrkdwn(topText))) {
|
|
211
|
+
const dropped = new Set<number>();
|
|
212
|
+
for (const [start, end] of richTextRanges) {
|
|
213
|
+
for (let i = start; i < end; i++) dropped.add(i);
|
|
214
|
+
}
|
|
215
|
+
bodyBlockParts = blockParts.filter((_, i) => !dropped.has(i));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const bodyText = [...attachmentParts, ...bodyBlockParts].filter(Boolean).join("\n");
|
|
166
220
|
|
|
167
221
|
// Include the top-level text unless it already appears as a complete line in the body.
|
|
168
222
|
// Boundary-aware check: "hi".includes check would silently drop "hi" when the body
|