@desplega.ai/agent-swarm 2.3.0 → 2.4.1
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 -0
- package/dist/{acp-adapter-v85a2bqy.js → acp-adapter-zvzr538d.js} +9 -9
- package/dist/{actions-zgcxfspj.js → actions-jhtqdw69.js} +21 -19
- package/dist/{amp-adapter-jw9xfz42.js → amp-adapter-bd84rhs2.js} +4 -4
- package/dist/{app-4e1s4675.js → app-kreq1gwg.js} +3 -3
- package/dist/{assistant-v238n9dk.js → assistant-3k22sbsq.js} +23 -21
- package/dist/{boot-reembed-p666cw5n.js → boot-reembed-e53x6b9v.js} +1 -1
- package/dist/{boot-reembed-w6pm64j4.js → boot-reembed-f6z923ny.js} +1 -1
- package/dist/{boot-scrub-sweep-jcyjagn3.js → boot-scrub-sweep-0538vsb7.js} +4 -4
- package/dist/{boot-seeds-gbedmamp.js → boot-seeds-6wxqkfk2.js} +4 -4
- package/dist/{claude-adapter-q7wspzt8.js → claude-adapter-gfts5044.js} +9 -9
- package/dist/{claude-managed-adapter-n7ahjyx6.js → claude-managed-adapter-h2y889ge.js} +3 -3
- package/dist/{claude-managed-setup-wza784fb.js → claude-managed-setup-h00hsgtz.js} +2 -2
- package/dist/{claude-sdk-session-yf400ptr.js → claude-sdk-session-56besmfz.js} +13 -13
- package/dist/{cli-65q70v2v.js → cli-0bh477zn.js} +33 -6
- package/dist/{cli-4ync7m60.js → cli-0ebey9hg.js} +1 -1
- package/dist/{cli-665j3feb.js → cli-0xk505e8.js} +1 -1
- package/dist/{cli-7gh7020n.js → cli-1dmcq2eh.js} +1 -1
- package/dist/{cli-gzvb3d4a.js → cli-1jx0srjt.js} +3 -3
- package/dist/{cli-zj4d6afs.js → cli-1pa3rz69.js} +21 -6
- package/dist/{cli-7ayprxp7.js → cli-2dfbv8qr.js} +8 -0
- package/dist/{cli-30m5q8mc.js → cli-3kh4kpqy.js} +6 -6
- package/dist/{cli-qrwp40st.js → cli-3p8fqcnh.js} +2 -2
- package/dist/{cli-y3dvz6ge.js → cli-3r448dqn.js} +3 -3
- package/dist/{cli-a17tzmn0.js → cli-3tnpj2bh.js} +7 -7
- package/dist/{cli-ea7chd26.js → cli-471qk6s2.js} +93 -46
- package/dist/{cli-a49vpbf3.js → cli-5kqnemen.js} +1 -1
- package/dist/{cli-0rh20bp3.js → cli-6ncjvx55.js} +3 -3
- package/dist/{cli-fb6t92v8.js → cli-6x9ma5w5.js} +1 -1
- package/dist/{cli-k28p6xh7.js → cli-7225gwj7.js} +2 -2
- package/dist/{cli-8cvvytad.js → cli-8nyhf7za.js} +3 -3
- package/dist/{cli-e09hj50q.js → cli-8wkb09q5.js} +11 -11
- package/dist/{cli-j0v75y13.js → cli-a0kcty51.js} +4 -4
- package/dist/{cli-zes4tsbb.js → cli-a4gvwttf.js} +4 -4
- package/dist/{cli-jhp7w1fy.js → cli-a5ebc95n.js} +2 -2
- package/dist/{cli-5d1m1qca.js → cli-ash6xxk7.js} +2 -2
- package/dist/{cli-fp4xbw07.js → cli-axh29tyr.js} +14 -12
- package/dist/{cli-p22zdvnt.js → cli-bn0rewsy.js} +3 -3
- package/dist/{cli-hz64bcnj.js → cli-bn5kevnf.js} +11 -373
- package/dist/{cli-8jtrekpy.js → cli-d2mb5s8a.js} +7 -7
- package/dist/{cli-c5sbmw1v.js → cli-d82btycs.js} +94 -15
- package/dist/{cli-vjfpshn3.js → cli-ejs3m1sx.js} +1 -1
- package/dist/{cli-yv0vgscc.js → cli-fpmsqq59.js} +18 -2
- package/dist/cli-fz9kewbh.js +382 -0
- package/dist/{cli-4s1kqrqg.js → cli-g0hgtz4p.js} +6 -6
- package/dist/{cli-hn3pftj2.js → cli-gf0kfg81.js} +7 -7
- package/dist/{cli-d43xqzbe.js → cli-hqhzg1qq.js} +2 -2
- package/dist/{cli-azs9bhc5.js → cli-j4rqdf2n.js} +2 -2
- package/dist/{cli-wtg6edvd.js → cli-jh0qcrga.js} +1 -1
- package/dist/{cli-kqypty34.js → cli-k9z4zd4p.js} +6 -5
- package/dist/{cli-jhmjwqcg.js → cli-kmqgmcnb.js} +47 -14
- package/dist/{cli-8qsx817b.js → cli-kr2pmfqx.js} +583 -769
- package/dist/{cli-4g629sgr.js → cli-m2qgh5sv.js} +20 -1
- package/dist/{cli-9e9kjqsj.js → cli-mfe7f7b5.js} +2 -2
- package/dist/{cli-x3en6ct3.js → cli-nwyw3zhg.js} +1 -1
- package/dist/{cli-6vcyw6v7.js → cli-nx462e4v.js} +5 -3
- package/dist/{cli-tr24eeny.js → cli-p0rakbrk.js} +9 -9
- package/dist/{cli-4hmaheb6.js → cli-p6argxh9.js} +9 -9
- package/dist/{cli-3avfh5az.js → cli-pemywhfq.js} +2 -2
- package/dist/{cli-etvn5ej2.js → cli-pnp2j5zg.js} +2 -2
- package/dist/{cli-wk8ccrz6.js → cli-pw7v69vp.js} +2 -2
- package/dist/{cli-ka01m5rb.js → cli-rdq7tzwm.js} +17 -14
- package/dist/{cli-re4wkbzx.js → cli-rqqsfz30.js} +677 -104
- package/dist/{cli-xgn4rwyv.js → cli-s48yvzb8.js} +4 -4
- package/dist/{cli-zv4vy2b0.js → cli-s95dknxh.js} +1 -1
- package/dist/{cli-g6p7c2my.js → cli-sjyetj21.js} +2 -2
- package/dist/{cli-rdr166ht.js → cli-smvcw9z5.js} +1 -1
- package/dist/{cli-fhvqt2fp.js → cli-sv5gb0yb.js} +1 -1
- package/dist/{cli-yv3n83x8.js → cli-syhq378v.js} +2 -2
- package/dist/{cli-q1812jbw.js → cli-tbhwrxpt.js} +9 -9
- package/dist/{cli-w7z94e6c.js → cli-tx00c0h6.js} +4 -2
- package/dist/{cli-dxwh4j32.js → cli-vy0fay6k.js} +46 -37
- package/dist/{cli-ptkpaqfy.js → cli-wt645v7q.js} +1 -1
- package/dist/{cli-ppapy34w.js → cli-wxbn3yfx.js} +2 -2
- package/dist/{cli-cby329ny.js → cli-x5mq1fyq.js} +3 -3
- package/dist/{cli-rc3r0bnh.js → cli-xbzvet96.js} +6 -6
- package/dist/{cli-4mkvwgzr.js → cli-xf234ws8.js} +1 -1
- package/dist/{cli-6p7ddg72.js → cli-xftrvxag.js} +5 -5
- package/dist/cli-z071fb95.js +848 -0
- package/dist/{cli-1v8w782f.js → cli-z1ew8vbq.js} +14 -7
- package/dist/{cli-9td5ss65.js → cli-zfg9enh9.js} +3 -3
- package/dist/{cli-yxqag76b.js → cli-zw88zjba.js} +1 -1
- package/dist/cli.js +19 -19
- package/dist/{codex-adapter-nhjj2veb.js → codex-adapter-p6rmm7vv.js} +6 -6
- package/dist/{codex-hook-x6tm6y5m.js → codex-hook-x7nejyrr.js} +8 -5
- package/dist/{codex-login-35p4sk85.js → codex-login-m819c41r.js} +1 -1
- package/dist/{codex-session-runner-6hggrjbx.js → codex-session-runner-8vd5t9t0.js} +7 -7
- package/dist/{commands-mrw1ph2w.js → commands-7ems2p13.js} +2 -2
- package/dist/{controller-pt1zam5w.js → controller-m263fg43.js} +4 -4
- package/dist/{controllers-connect-ymw5541d.js → controllers-connect-bg33ae53.js} +28 -24
- package/dist/{cursor-adapter-cf4zh5x0.js → cursor-adapter-cz6nm6mj.js} +3 -3
- package/dist/{db-hy80219q.js → db-w505dwa8.js} +2 -2
- package/dist/{db-hhpy6m4x.js → db-ys2rbdft.js} +3 -2
- package/dist/{devin-adapter-7egzmt0k.js → devin-adapter-zgqadvnm.js} +1 -1
- package/dist/{dispatcher-6pdjtkr1.js → dispatcher-0s0mckqr.js} +20 -18
- package/dist/{docker-njavd3fb.js → docker-fkgtr75t.js} +2 -2
- package/dist/{dsh-adapter-fbx06re2.js → dsh-adapter-3n3net33.js} +3 -3
- package/dist/{e2b-5r6a5jeb.js → e2b-7am6tmq6.js} +2 -2
- package/dist/{e2b-pw1nvtmh.js → e2b-thdcxtjd.js} +2 -2
- package/dist/{easter-egg-3d-6hg2r942.js → easter-egg-3d-5cgynaja.js} +1 -1
- package/dist/{event-bus-101fenkh.js → event-bus-9vpk8gmq.js} +1 -1
- package/dist/{execute-bcqc69a5.js → execute-t4e6m3rw.js} +1 -1
- package/dist/{external-channel-j6vb6ya1.js → external-channel-5b23fv8z.js} +2 -2
- package/dist/{google-generative-ai-phpmwxvg.js → google-generative-ai-bmq8gkf3.js} +1 -1
- package/dist/{google-vertex-es9ybgdy.js → google-vertex-b1rvp52s.js} +1 -1
- package/dist/{grok-adapter-1193sprp.js → grok-adapter-q9fghe5q.js} +10 -10
- package/dist/handlers-mqrym347.js +39 -0
- package/dist/{heartbeat-h1w1ktce.js → heartbeat-tww6yx1w.js} +23 -21
- package/dist/{hook-ejja4bpe.js → hook-dx0pkvar.js} +16 -9
- package/dist/{hook-skrbja18.js → hook-pvmh9b6m.js} +6 -6
- package/dist/{http-mzh41mfj.js → http-k2ejbt05.js} +975 -292
- package/dist/{index-6rmnn89d.js → index-2z710v4x.js} +10 -10
- package/dist/{index-xmmkyx82.js → index-dgz61nff.js} +20 -18
- package/dist/{index-wgsw9xcz.js → index-g6tbb6ve.js} +1 -1
- package/dist/index-h2ek08d6.js +40 -0
- package/dist/index-pqfwh9nn.js +41 -0
- package/dist/{index-epr2gnbw.js → index-x5aktmp8.js} +1 -1
- package/dist/{index-x0q2a4f9.js → index-ysd45kgc.js} +1 -1
- package/dist/{index-g909y089.js → index-zgvqzjsw.js} +8 -8
- package/dist/{keepalive-4djvbm2j.js → keepalive-nhvpw10z.js} +4 -4
- package/dist/lead-jb6sf69z.js +78 -0
- package/dist/{maintenance-f3xhnjsm.js → maintenance-agakc519.js} +1 -1
- package/dist/{oauth-refresh-sweep-fpd6x6rw.js → oauth-refresh-sweep-4dcbhtn0.js} +3 -3
- package/dist/{onboard-196tjgyn.js → onboard-4n2kwa4v.js} +3 -3
- package/dist/{opencode-adapter-eeesgfqk.js → opencode-adapter-3s7ax02e.js} +7 -7
- package/dist/{otel-impl-g8fh4c21.js → otel-impl-tfa12080.js} +2 -2
- package/dist/{pi-mono-adapter-zasp3ze3.js → pi-mono-adapter-ytp7gz8b.js} +24 -13
- package/dist/{pricing-refresh-sdcf5yaz.js → pricing-refresh-3cqx3f3x.js} +3 -3
- package/dist/{rbac-roles-bsp5657v.js → rbac-roles-9fae5rnv.js} +5 -3
- package/dist/{rbac-roles-2x4g1wb5.js → rbac-roles-y6zbfzve.js} +2 -2
- package/dist/{render-v2-0pyb39bb.js → render-v2-emawjvc4.js} +3 -3
- package/dist/{resume-a86tkj6r.js → resume-zhgts7h7.js} +10 -8
- package/dist/{runtime-ar8310ba.js → runtime-xe3aqy4x.js} +1 -1
- package/dist/session-access-cm823e06.js +25 -0
- package/dist/{setup-ypbzcapd.js → setup-tkp99w1e.js} +1 -1
- package/dist/{virtual-modules-wzk6jf3a.js → virtual-modules-4r3zkc20.js} +2 -2
- package/dist/{work-objects-yjp8de12.js → work-objects-f722h263.js} +23 -21
- package/dist/worker-p7f336rq.js +78 -0
- package/dist/{x-8ewt8gxn.js → x-y45mthwn.js} +2 -2
- package/openapi.json +1086 -305
- package/package.json +2 -2
- package/src/apps/action-caller.ts +6 -0
- package/src/apps/action-runner.ts +146 -0
- package/src/apps/row-store.ts +4 -2
- package/src/apps/script-types.ts +17 -4
- package/src/be/db/active-sessions.ts +5 -0
- package/src/be/db/session-visibility.ts +29 -0
- package/src/be/db/tasks/read.ts +61 -3
- package/src/be/db/tasks/write.ts +15 -6
- package/src/be/db.ts +106 -37
- package/src/be/events.ts +11 -0
- package/src/be/fleet-benchmark-stats.ts +10 -5
- package/src/be/migrations/230_session_shares.sql +23 -0
- package/src/be/models-catalog.ts +4 -0
- package/src/be/onboarding.ts +6 -0
- package/src/be/rbac-roles.ts +2 -0
- package/src/be/scripts/typecheck.ts +13 -0
- package/src/be/session-shares.ts +244 -0
- package/src/be/swarm-config-guard.ts +33 -3
- package/src/be/telemetry-enable.ts +1 -1
- package/src/commands/provider-credentials.ts +12 -2
- package/src/commands/runner.ts +14 -0
- package/src/heartbeat/heartbeat.ts +2 -2
- package/src/hooks/codex-hook.ts +6 -2
- package/src/hooks/hook.ts +7 -0
- package/src/hooks/pr-body-guard.ts +38 -11
- package/src/hooks/pr-room-guard.ts +88 -0
- package/src/http/active-sessions.ts +13 -2
- package/src/http/agents.ts +11 -3
- package/src/http/all-routes.ts +1 -0
- package/src/http/api-keys.ts +3 -1
- package/src/http/approval-requests.ts +2 -1
- package/src/http/apps.ts +118 -190
- package/src/http/config.ts +3 -0
- package/src/http/context.ts +2 -0
- package/src/http/core.ts +39 -2
- package/src/http/events.ts +6 -2
- package/src/http/favorite-owner.ts +1 -1
- package/src/http/fleet-benchmark.ts +79 -30
- package/src/http/fs.ts +38 -3
- package/src/http/global-config.ts +7 -0
- package/src/http/index.ts +3 -1
- package/src/http/memory.ts +3 -1
- package/src/http/ranking.ts +351 -0
- package/src/http/realtime.ts +26 -21
- package/src/http/route-def.ts +77 -11
- package/src/http/script-runs.ts +2 -1
- package/src/http/scripts.ts +8 -0
- package/src/http/session-access.ts +179 -0
- package/src/http/session-data.ts +10 -2
- package/src/http/sessions.ts +212 -12
- package/src/http/stats.ts +7 -3
- package/src/http/tasks.ts +85 -8
- package/src/http/telemetry-ui.ts +1 -1
- package/src/http/used-by.ts +64 -20
- package/src/http/users.ts +2 -2
- package/src/prompts/session-templates.ts +3 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/pi-mono-adapter.ts +15 -0
- package/src/providers/reasoning-effort.ts +2 -1
- package/src/providers/types.ts +2 -0
- package/src/ranking/telemetry-ranking.ts +119 -0
- package/src/ranking/usage.ts +57 -0
- package/src/rbac/admission.ts +22 -7
- package/src/rbac/legacy-policy.ts +2 -0
- package/src/rbac/permissions.ts +9 -0
- package/src/realtime/auth.ts +69 -0
- package/src/realtime/tickets.ts +4 -1
- package/src/realtime/transport.ts +77 -9
- package/src/scripts-runtime/sdk-allowlist.ts +7 -0
- package/src/scripts-runtime/types/stdlib.d.ts +31 -0
- package/src/scripts-runtime/types/swarm-sdk.d.ts +31 -0
- package/src/server.ts +4 -0
- package/src/slack/blocks.ts +18 -0
- package/src/slack/dm.ts +29 -0
- package/src/telemetry-context.ts +19 -1
- package/src/telemetry-contract/EVENTS.md +45 -8
- package/src/telemetry-contract/SOURCE.json +38 -4
- package/src/telemetry-contract/catalog.json +294 -5
- package/src/telemetry-contract/ranking/fixtures/expected.json +30 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/bad-category.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/bad-claim.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/blank-description.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/blank-name.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/description-too-long.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/domain-uppercase.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/domain-with-scheme.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/domain-with-www.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/http-source-url.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/missing-description.json +10 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/missing-version.json +10 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/name-not-string.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/name-too-long.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/not-object.json +1 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/null.json +1 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/other-with-subcategory.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/oversize.json +1 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/short-claim.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/subcategory-other-category.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/trailing-data.json +1 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/unknown-field.json +12 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/unsupported-version.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/updated-at-not-date.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/updated-at-offset.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/invalid/wrong-case-field.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/valid/category-without-subcategory.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/valid/full.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/valid/minimal.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/valid/no-claim.json +10 -0
- package/src/telemetry-contract/ranking/fixtures/valid/padded-text.json +11 -0
- package/src/telemetry-contract/ranking/fixtures/valid/unicode-name.json +11 -0
- package/src/telemetry-contract/ranking/listing.v1.schema.json +61 -0
- package/src/telemetry-contract/ranking/taxonomy.json +8 -0
- package/src/telemetry-contract/ranking-taxonomy.gen.ts +11 -0
- package/src/telemetry-contract/types.gen.ts +963 -58
- package/src/telemetry-identity.ts +47 -9
- package/src/telemetry-snapshot.ts +9 -1
- package/src/telemetry-ui-events.ts +9 -2
- package/src/telemetry.ts +40 -5
- package/src/tests/app-action-run-tool.test.ts +178 -0
- package/src/tests/app-row-tools.test.ts +360 -0
- package/src/tests/apps-rbac.test.ts +189 -2
- package/src/tests/apps-script-types.test.ts +16 -3
- package/src/tests/credential-check.test.ts +38 -0
- package/src/tests/db-extraction-contract.test.ts +1 -0
- package/src/tests/db-task-read-contract.test.ts +1 -0
- package/src/tests/docs-index-footprint.test.js +2 -2
- package/src/tests/fleet-benchmark.test.ts +122 -2
- package/src/tests/http-users.test.ts +62 -1
- package/src/tests/model-catalog-table.test.ts +63 -0
- package/src/tests/model-profiles-api.test.ts +19 -7
- package/src/tests/models-catalog.test.ts +50 -0
- package/src/tests/onboarding.test.ts +21 -0
- package/src/tests/org-identity.test.ts +44 -0
- package/src/tests/org-website.test.ts +62 -0
- package/src/tests/pi-mono-adapter.test.ts +23 -0
- package/src/tests/pr-body-leaks.test.ts +4 -0
- package/src/tests/pr-room-guard.test.ts +242 -0
- package/src/tests/ranking-listing.test.ts +97 -0
- package/src/tests/ranking-route.test.ts +321 -0
- package/src/tests/ranking-usage.test.ts +50 -0
- package/src/tests/rbac-admission-e2e.test.ts +8 -0
- package/src/tests/rbac-admission.test.ts +38 -0
- package/src/tests/rbac-charact-http.test.ts +4 -3
- package/src/tests/rbac-engine.test.ts +2 -0
- package/src/tests/rbac-roles.test.ts +2 -0
- package/src/tests/realtime-room-surfaces.test.ts +3 -1
- package/src/tests/realtime-session-join-race.test.ts +142 -0
- package/src/tests/realtime-tickets.test.ts +24 -17
- package/src/tests/realtime-transport.test.ts +91 -0
- package/src/tests/reasoning-effort.test.ts +39 -3
- package/src/tests/runner-harness-telemetry-env.test.ts +56 -1
- package/src/tests/session-route-posture.test.ts +639 -0
- package/src/tests/session-sharing-routes.test.ts +282 -0
- package/src/tests/session-sharing.test.ts +526 -0
- package/src/tests/sessions-detail-batch.test.ts +7 -1
- package/src/tests/slack-tool-blocks.test.ts +101 -0
- package/src/tests/slack-update.test.ts +55 -0
- package/src/tests/slack-user-dm.test.ts +177 -0
- package/src/tests/swarm-tool-result-gate.test.ts +2 -4
- package/src/tests/telemetry-context.test.ts +128 -2
- package/src/tests/telemetry-ui-route.test.ts +123 -0
- package/src/tests/tool-annotations.test.ts +3 -2
- package/src/tests/used-by-route.test.ts +153 -9
- package/src/tests/workflow-agent-task-retry.test.ts +130 -4
- package/src/tests/workflow-wait-recovery.test.ts +116 -4
- package/src/tools/app-action-run.ts +63 -0
- package/src/tools/app-rows.ts +234 -0
- package/src/tools/model-catalog/index.ts +1 -1
- package/src/tools/slack-post.ts +18 -12
- package/src/tools/slack-read.ts +13 -1
- package/src/tools/slack-reply.ts +7 -10
- package/src/tools/slack-start-thread.ts +18 -11
- package/src/tools/slack-update.ts +2 -9
- package/src/tools/tool-config.ts +8 -0
- package/src/tools/utils.ts +1 -1
- package/src/tools/workflows/retry-workflow-run.ts +1 -1
- package/src/types.ts +52 -0
- package/src/utils/company-profile.ts +24 -0
- package/src/utils/org-identity.ts +33 -0
- package/src/utils/org-website.ts +58 -21
- package/src/workflows/recovery.ts +10 -22
- package/src/workflows/resume.ts +16 -0
- package/src/workflows/task-step-routing.ts +47 -7
- package/templates/skills/apps/SKILL.md +58 -2
- package/templates/skills/apps/content.md +58 -2
- package/dist/handlers-tb3xgjnm.js +0 -37
- package/dist/index-nyfcdpky.js +0 -39
- package/dist/index-vjn3wbzf.js +0 -38
- package/dist/lead-61kqp604.js +0 -76
- package/dist/worker-4ptnn1ge.js +0 -76
- package/dist/{cli-n5mrsg0f.js → cli-60cgh1rv.js} +3 -3
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import * as z from "zod";
|
|
3
|
+
import { AppNameSchema, type ModelDef, SYSTEM_COLUMN_KINDS } from "../apps/definition";
|
|
4
|
+
import {
|
|
5
|
+
type AppRow,
|
|
6
|
+
AppRowAppNotFoundError,
|
|
7
|
+
AppRowValidationError,
|
|
8
|
+
createAppRow,
|
|
9
|
+
createAppRows,
|
|
10
|
+
deleteAppRow,
|
|
11
|
+
getAppRow,
|
|
12
|
+
patchAppRow,
|
|
13
|
+
validValue,
|
|
14
|
+
} from "../apps/row-store";
|
|
15
|
+
import { appDefinitionNeedsRepair, getApp } from "../apps/store";
|
|
16
|
+
import { getAgentById } from "../be/db";
|
|
17
|
+
import {
|
|
18
|
+
MAX_APP_BULK_ROWS_BODY_BYTES,
|
|
19
|
+
MAX_APP_ROW_BODY_BYTES,
|
|
20
|
+
rowMatchesFilters,
|
|
21
|
+
selectAppRows,
|
|
22
|
+
} from "../http/apps";
|
|
23
|
+
import { can } from "../rbac";
|
|
24
|
+
import {
|
|
25
|
+
createToolRegistrar,
|
|
26
|
+
type SwarmToolResult,
|
|
27
|
+
swarmToolOutputSchema,
|
|
28
|
+
toolErr,
|
|
29
|
+
toolOk,
|
|
30
|
+
} from "./utils";
|
|
31
|
+
|
|
32
|
+
const base = { appId: z.string().min(1), model: AppNameSchema };
|
|
33
|
+
const rowId = z.string().min(1);
|
|
34
|
+
const values = z.record(z.string(), z.unknown());
|
|
35
|
+
const equals = z.record(z.string(), z.union([z.string(), z.number(), z.boolean()]));
|
|
36
|
+
const limit = z.number().int().min(1).max(1000);
|
|
37
|
+
const rowOutput = { row: z.looseObject({}).optional() };
|
|
38
|
+
const rowsOutput = { rows: z.array(z.looseObject({})).optional() };
|
|
39
|
+
|
|
40
|
+
function checkSize(value: unknown, max: number): void {
|
|
41
|
+
if (Buffer.byteLength(JSON.stringify(value), "utf8") > max) {
|
|
42
|
+
throw new AppRowValidationError([
|
|
43
|
+
{ path: "values", message: `Row input exceeds ${max} bytes.` },
|
|
44
|
+
]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function rowFilters(model: ModelDef, equals: Record<string, string | number | boolean> = {}) {
|
|
49
|
+
return Object.entries(equals).map(([column, value]) => {
|
|
50
|
+
const declared = Object.hasOwn(model.columns, column) ? model.columns[column] : undefined;
|
|
51
|
+
if ((!declared && !Object.hasOwn(SYSTEM_COLUMN_KINDS, column)) || declared?.hidden) {
|
|
52
|
+
throw new AppRowValidationError([
|
|
53
|
+
{ path: `equals.${column}`, message: "Unknown or hidden column." },
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
if (!validValue(declared ?? { kind: SYSTEM_COLUMN_KINDS[column]! }, value)) {
|
|
57
|
+
throw new AppRowValidationError([
|
|
58
|
+
{ path: `equals.${column}`, message: "Filter value must match the column kind." },
|
|
59
|
+
]);
|
|
60
|
+
}
|
|
61
|
+
return { column, value };
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function registerAppRowTools(server: McpServer) {
|
|
66
|
+
function register<Shape extends z.ZodRawShape>(
|
|
67
|
+
name: string,
|
|
68
|
+
description: string,
|
|
69
|
+
shape: Shape,
|
|
70
|
+
output: z.ZodRawShape,
|
|
71
|
+
operation: (
|
|
72
|
+
args: z.infer<z.ZodObject<typeof base & Shape>>,
|
|
73
|
+
model: ModelDef,
|
|
74
|
+
actor: string,
|
|
75
|
+
) => Promise<SwarmToolResult>,
|
|
76
|
+
readOnly = false,
|
|
77
|
+
) {
|
|
78
|
+
createToolRegistrar(server)(
|
|
79
|
+
name,
|
|
80
|
+
{
|
|
81
|
+
title: description,
|
|
82
|
+
description,
|
|
83
|
+
annotations: { readOnlyHint: readOnly },
|
|
84
|
+
rbac: { permission: "app.use" },
|
|
85
|
+
inputSchema: z.object({ ...base, ...shape }),
|
|
86
|
+
outputSchema: swarmToolOutputSchema(output),
|
|
87
|
+
},
|
|
88
|
+
async (args, info) => {
|
|
89
|
+
if (!info.agentId) return toolErr('Agent ID not found. Set the "X-Agent-ID" header.');
|
|
90
|
+
const { appId, model: modelName } = z.object(base).parse(args);
|
|
91
|
+
const agent = await getAgentById(info.agentId);
|
|
92
|
+
const decision = can({
|
|
93
|
+
principal: { kind: "agent", agentId: info.agentId, isLead: agent?.isLead ?? false },
|
|
94
|
+
verb: "app.use",
|
|
95
|
+
resource: { kind: "app", appId },
|
|
96
|
+
source: "mcp",
|
|
97
|
+
});
|
|
98
|
+
if (!decision.allow) return toolErr(decision.reason);
|
|
99
|
+
const app = await getApp(appId);
|
|
100
|
+
if (!app) return toolErr("App not found.");
|
|
101
|
+
if (appDefinitionNeedsRepair(app))
|
|
102
|
+
return toolErr("App definition needs repair.", { data: { issues: app.definitionError } });
|
|
103
|
+
if (!Object.hasOwn(app.definition.models, modelName)) return toolErr("Model not found.");
|
|
104
|
+
try {
|
|
105
|
+
return await operation(args, app.definition.models[modelName]!, `agent:${info.agentId}`);
|
|
106
|
+
} catch (error) {
|
|
107
|
+
if (error instanceof AppRowValidationError)
|
|
108
|
+
return toolErr(error.message, { data: { issues: error.issues } });
|
|
109
|
+
if (error instanceof AppRowAppNotFoundError) return toolErr(error.message);
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
register(
|
|
117
|
+
"app-rows-list",
|
|
118
|
+
"List app rows with equality filters, sorting, and a limit.",
|
|
119
|
+
{
|
|
120
|
+
equals: equals.optional(),
|
|
121
|
+
sort: z.string().optional(),
|
|
122
|
+
limit: limit.optional(),
|
|
123
|
+
},
|
|
124
|
+
{ ...rowsOutput, total: z.number().optional() },
|
|
125
|
+
async (args, model) => {
|
|
126
|
+
const data = await selectAppRows(
|
|
127
|
+
args.appId,
|
|
128
|
+
args.model,
|
|
129
|
+
model,
|
|
130
|
+
rowFilters(model, args.equals),
|
|
131
|
+
args.sort,
|
|
132
|
+
args.limit,
|
|
133
|
+
true,
|
|
134
|
+
);
|
|
135
|
+
return toolOk(`Found ${data.total} row(s).`, { data });
|
|
136
|
+
},
|
|
137
|
+
true,
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
register(
|
|
141
|
+
"app-row-get",
|
|
142
|
+
"Get an app row.",
|
|
143
|
+
{ rowId },
|
|
144
|
+
rowOutput,
|
|
145
|
+
async (args) => {
|
|
146
|
+
const row = await getAppRow(args.appId, args.model, args.rowId);
|
|
147
|
+
return row ? toolOk("Row retrieved.", { data: { row } }) : toolErr("Row not found.");
|
|
148
|
+
},
|
|
149
|
+
true,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
register(
|
|
153
|
+
"app-row-create",
|
|
154
|
+
"Create an app row.",
|
|
155
|
+
{ values },
|
|
156
|
+
rowOutput,
|
|
157
|
+
async (args, model, actor) => {
|
|
158
|
+
checkSize({ values: args.values }, MAX_APP_ROW_BODY_BYTES);
|
|
159
|
+
const row = await createAppRow(args.appId, args.model, model, args.values, { actor });
|
|
160
|
+
return toolOk("Row created.", { data: { row } });
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
register(
|
|
165
|
+
"app-rows-create",
|
|
166
|
+
"Create up to 500 app rows within 10 MiB.",
|
|
167
|
+
{
|
|
168
|
+
rows: z.array(values).min(1).max(500),
|
|
169
|
+
},
|
|
170
|
+
rowsOutput,
|
|
171
|
+
async (args, model, actor) => {
|
|
172
|
+
checkSize({ rows: args.rows }, MAX_APP_BULK_ROWS_BODY_BYTES);
|
|
173
|
+
for (const values of args.rows) checkSize({ values }, MAX_APP_ROW_BODY_BYTES);
|
|
174
|
+
const rows = await createAppRows(args.appId, args.model, model, args.rows, { actor });
|
|
175
|
+
return toolOk(`Created ${rows.length} row(s).`, { data: { rows } });
|
|
176
|
+
},
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
register(
|
|
180
|
+
"app-row-patch",
|
|
181
|
+
"Patch an app row.",
|
|
182
|
+
{ rowId, values },
|
|
183
|
+
rowOutput,
|
|
184
|
+
async (args, model, actor) => {
|
|
185
|
+
checkSize({ values: args.values }, MAX_APP_ROW_BODY_BYTES);
|
|
186
|
+
const row = await patchAppRow(args.appId, args.model, model, args.rowId, args.values, {
|
|
187
|
+
actor,
|
|
188
|
+
});
|
|
189
|
+
return row ? toolOk("Row updated.", { data: { row } }) : toolErr("Row not found.");
|
|
190
|
+
},
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
register(
|
|
194
|
+
"app-row-delete",
|
|
195
|
+
"Delete an app row.",
|
|
196
|
+
{ rowId },
|
|
197
|
+
{ ok: z.boolean().optional() },
|
|
198
|
+
async (args, model) => {
|
|
199
|
+
const deleted = await deleteAppRow(args.appId, args.model, model, args.rowId);
|
|
200
|
+
return deleted ? toolOk("Row deleted.", { data: { ok: true } }) : toolErr("Row not found.");
|
|
201
|
+
},
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
register(
|
|
205
|
+
"app-rows-delete",
|
|
206
|
+
"Delete matching app rows. Supply at least one equality filter.",
|
|
207
|
+
{
|
|
208
|
+
equals: equals.refine(
|
|
209
|
+
(value) => Object.keys(value).length > 0,
|
|
210
|
+
"Supply at least one equality filter.",
|
|
211
|
+
),
|
|
212
|
+
limit: limit.optional(),
|
|
213
|
+
},
|
|
214
|
+
{ deleted: z.number().optional() },
|
|
215
|
+
async (args, model) => {
|
|
216
|
+
const filters = rowFilters(model, args.equals);
|
|
217
|
+
const { rows } = await selectAppRows(
|
|
218
|
+
args.appId,
|
|
219
|
+
args.model,
|
|
220
|
+
model,
|
|
221
|
+
filters,
|
|
222
|
+
undefined,
|
|
223
|
+
args.limit ?? 1000,
|
|
224
|
+
true,
|
|
225
|
+
);
|
|
226
|
+
// Re-check under the row lock: a row patched out of the filter since the select is kept.
|
|
227
|
+
const matches = (row: AppRow) => rowMatchesFilters(row, filters);
|
|
228
|
+
let deleted = 0;
|
|
229
|
+
for (const row of rows)
|
|
230
|
+
if (await deleteAppRow(args.appId, args.model, model, row.id, matches)) deleted++;
|
|
231
|
+
return toolOk(`Deleted ${deleted} row(s).`, { data: { deleted } });
|
|
232
|
+
},
|
|
233
|
+
);
|
|
234
|
+
}
|
|
@@ -87,7 +87,7 @@ export const registerModelCatalogOverlayUpsertTool = (server: McpServer) => {
|
|
|
87
87
|
.string()
|
|
88
88
|
.min(1)
|
|
89
89
|
.describe(
|
|
90
|
-
`models.dev provider id: anthropic, openai, openrouter, amazon-bedrock, opencode, ${openAICompatibleProviderIds().join(", ")}.`,
|
|
90
|
+
`models.dev provider id: anthropic, openai, openrouter, amazon-bedrock, opencode, opencode-go, ${openAICompatibleProviderIds().join(", ")}.`,
|
|
91
91
|
),
|
|
92
92
|
modelId: z
|
|
93
93
|
.string()
|
package/src/tools/slack-post.ts
CHANGED
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
} from "@/be/db";
|
|
9
9
|
import { can } from "@/rbac";
|
|
10
10
|
import { getSlackApp } from "@/slack/app";
|
|
11
|
-
import { getTaskLink } from "@/slack/blocks";
|
|
11
|
+
import { buildMrkdwnSectionBlocks, getTaskLink } from "@/slack/blocks";
|
|
12
12
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
13
|
+
import { resolveSlackConversationId } from "@/slack/dm";
|
|
13
14
|
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
14
15
|
import { getAgentDisplayName, getAgentEmoji, markdownToSlack } from "@/slack/responses";
|
|
15
16
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
@@ -24,7 +25,12 @@ export const registerSlackPostTool = (server: McpServer) => {
|
|
|
24
25
|
annotations: { openWorldHint: true },
|
|
25
26
|
|
|
26
27
|
inputSchema: z.object({
|
|
27
|
-
channelId: z
|
|
28
|
+
channelId: z
|
|
29
|
+
.string()
|
|
30
|
+
.min(1)
|
|
31
|
+
.describe(
|
|
32
|
+
"The Slack channel ID to post to. A user ID (U…/W…) posts in the bot's DM with that user.",
|
|
33
|
+
),
|
|
28
34
|
message: z.string().min(1).max(4000).describe("The message content to post."),
|
|
29
35
|
blocks: z
|
|
30
36
|
.array(z.record(z.string(), z.unknown()))
|
|
@@ -42,7 +48,7 @@ export const registerSlackPostTool = (server: McpServer) => {
|
|
|
42
48
|
messageTs: z.string().optional(),
|
|
43
49
|
}),
|
|
44
50
|
},
|
|
45
|
-
async ({ channelId, message, threadTs, blocks }, requestInfo, _meta) => {
|
|
51
|
+
async ({ channelId: requestedChannelId, message, threadTs, blocks }, requestInfo, _meta) => {
|
|
46
52
|
if (!requestInfo.agentId) {
|
|
47
53
|
return toolErr("Agent ID not found.");
|
|
48
54
|
}
|
|
@@ -68,6 +74,14 @@ export const registerSlackPostTool = (server: McpServer) => {
|
|
|
68
74
|
return toolErr("Slack not configured.");
|
|
69
75
|
}
|
|
70
76
|
|
|
77
|
+
let channelId: string;
|
|
78
|
+
try {
|
|
79
|
+
channelId = await resolveSlackConversationId(app.client, requestedChannelId);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
82
|
+
return toolErr(`Failed to open a DM with ${requestedChannelId}: ${errorMsg}`);
|
|
83
|
+
}
|
|
84
|
+
|
|
71
85
|
const blockReason = await getChannelBlockReason(app.client, channelId);
|
|
72
86
|
if (blockReason) {
|
|
73
87
|
return toolErr(externalChannelToolError(channelId, blockReason));
|
|
@@ -82,15 +96,7 @@ export const registerSlackPostTool = (server: McpServer) => {
|
|
|
82
96
|
const contextKey = sourceTask?.contextKey;
|
|
83
97
|
const tree = threadTs ? await getSlackTreeMessageByThread(channelId, threadTs) : null;
|
|
84
98
|
const messageBlocks: Record<string, unknown>[] = [
|
|
85
|
-
...(blocks ??
|
|
86
|
-
{
|
|
87
|
-
type: "section",
|
|
88
|
-
text: {
|
|
89
|
-
type: "mrkdwn",
|
|
90
|
-
text: slackMessage,
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
]),
|
|
99
|
+
...(blocks ?? buildMrkdwnSectionBlocks(slackMessage)),
|
|
94
100
|
];
|
|
95
101
|
if (sourceTask && tree) {
|
|
96
102
|
if (messageBlocks.length >= 50) {
|
package/src/tools/slack-read.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { getAgentById, getInboxMessageById, getTaskById } from "@/be/db";
|
|
|
4
4
|
import { can } from "@/rbac";
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
6
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
7
|
+
import { resolveSlackConversationId } from "@/slack/dm";
|
|
7
8
|
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
8
9
|
import { downloadFile, type SlackFile } from "@/slack/files";
|
|
9
10
|
import { attachableTask, attachSlackFilesForAgent } from "@/slack/inbound-files";
|
|
@@ -59,7 +60,9 @@ export const registerSlackReadTool = (server: McpServer) => {
|
|
|
59
60
|
channelId: z
|
|
60
61
|
.string()
|
|
61
62
|
.optional()
|
|
62
|
-
.describe(
|
|
63
|
+
.describe(
|
|
64
|
+
"Slack channel ID to read from (requires lead privileges). A user ID (U…/W…) reads the bot's DM with that user.",
|
|
65
|
+
),
|
|
63
66
|
threadTs: z
|
|
64
67
|
.string()
|
|
65
68
|
.optional()
|
|
@@ -155,6 +158,15 @@ export const registerSlackReadTool = (server: McpServer) => {
|
|
|
155
158
|
return toolErr("Slack not configured.", { data: { messages: [] } });
|
|
156
159
|
}
|
|
157
160
|
|
|
161
|
+
try {
|
|
162
|
+
slackChannelId = await resolveSlackConversationId(app.client, slackChannelId);
|
|
163
|
+
} catch (error) {
|
|
164
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
165
|
+
return toolErr(`Failed to open a DM with ${slackChannelId}: ${errorMsg}`, {
|
|
166
|
+
data: { messages: [] },
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
|
|
158
170
|
const blockReason = await getChannelBlockReason(app.client, slackChannelId);
|
|
159
171
|
if (blockReason) {
|
|
160
172
|
return toolErr(externalChannelToolError(slackChannelId, blockReason), {
|
package/src/tools/slack-reply.ts
CHANGED
|
@@ -11,7 +11,12 @@ import {
|
|
|
11
11
|
} from "@/be/db";
|
|
12
12
|
import { getTaskCitations } from "@/be/task-citations";
|
|
13
13
|
import { getSlackApp } from "@/slack/app";
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
buildCaptionBlock,
|
|
16
|
+
buildMrkdwnSectionBlocks,
|
|
17
|
+
getTaskLink,
|
|
18
|
+
getTaskUrl,
|
|
19
|
+
} from "@/slack/blocks";
|
|
15
20
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
16
21
|
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
17
22
|
import { getAgentDisplayName, getAgentEmoji, markdownToSlack } from "@/slack/responses";
|
|
@@ -140,15 +145,7 @@ export const registerSlackReplyTool = (server: McpServer) => {
|
|
|
140
145
|
|
|
141
146
|
const tree = await getSlackTreeMessageByThread(slackChannelId, slackThreadTs);
|
|
142
147
|
const messageBlocks: Record<string, unknown>[] = [
|
|
143
|
-
...(renderedBlocks ??
|
|
144
|
-
{
|
|
145
|
-
type: "section",
|
|
146
|
-
text: {
|
|
147
|
-
type: "mrkdwn",
|
|
148
|
-
text: slackMessage,
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
]),
|
|
148
|
+
...(renderedBlocks ?? buildMrkdwnSectionBlocks(slackMessage)),
|
|
152
149
|
];
|
|
153
150
|
for (const group of taskCitationSourceGroups(
|
|
154
151
|
blocks ? JSON.stringify(blocks) : message,
|
|
@@ -3,7 +3,9 @@ import * as z from "zod";
|
|
|
3
3
|
import { getAgentById, getTaskById, recordSlackMessage } from "@/be/db";
|
|
4
4
|
import { can } from "@/rbac";
|
|
5
5
|
import { getSlackApp } from "@/slack/app";
|
|
6
|
+
import { buildMrkdwnSectionBlocks } from "@/slack/blocks";
|
|
6
7
|
import { withAutoJoin } from "@/slack/channel-join";
|
|
8
|
+
import { resolveSlackConversationId } from "@/slack/dm";
|
|
7
9
|
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
8
10
|
import { getAgentDisplayName, getAgentEmoji, markdownToSlack } from "@/slack/responses";
|
|
9
11
|
import { createToolRegistrar, swarmToolOutputSchema, toolErr, toolOk } from "@/tools/utils";
|
|
@@ -18,7 +20,12 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
18
20
|
annotations: { openWorldHint: true },
|
|
19
21
|
|
|
20
22
|
inputSchema: z.object({
|
|
21
|
-
channelId: z
|
|
23
|
+
channelId: z
|
|
24
|
+
.string()
|
|
25
|
+
.min(1)
|
|
26
|
+
.describe(
|
|
27
|
+
"The Slack channel ID to post to. A user ID (U…/W…) opens the bot's DM with that user; use the returned channelId afterwards.",
|
|
28
|
+
),
|
|
22
29
|
message: z.string().min(1).max(4000).describe("The message content to post."),
|
|
23
30
|
blocks: z
|
|
24
31
|
.array(z.record(z.string(), z.unknown()))
|
|
@@ -32,7 +39,7 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
32
39
|
messageTs: z.string().optional(),
|
|
33
40
|
}),
|
|
34
41
|
},
|
|
35
|
-
async ({ channelId, message, blocks }, requestInfo, _meta) => {
|
|
42
|
+
async ({ channelId: requestedChannelId, message, blocks }, requestInfo, _meta) => {
|
|
36
43
|
if (!requestInfo.agentId) {
|
|
37
44
|
return toolErr("Agent ID not found.");
|
|
38
45
|
}
|
|
@@ -57,6 +64,14 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
57
64
|
return toolErr("Slack not configured.");
|
|
58
65
|
}
|
|
59
66
|
|
|
67
|
+
let channelId: string;
|
|
68
|
+
try {
|
|
69
|
+
channelId = await resolveSlackConversationId(app.client, requestedChannelId);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
72
|
+
return toolErr(`Failed to open a DM with ${requestedChannelId}: ${errorMsg}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
60
75
|
const blockReason = await getChannelBlockReason(app.client, channelId);
|
|
61
76
|
if (blockReason) {
|
|
62
77
|
return toolErr(externalChannelToolError(channelId, blockReason));
|
|
@@ -64,15 +79,7 @@ export const registerSlackStartThreadTool = (server: McpServer) => {
|
|
|
64
79
|
|
|
65
80
|
try {
|
|
66
81
|
const slackMessage = markdownToSlack(message);
|
|
67
|
-
const messageBlocks = blocks ??
|
|
68
|
-
{
|
|
69
|
-
type: "section",
|
|
70
|
-
text: {
|
|
71
|
-
type: "mrkdwn",
|
|
72
|
-
text: slackMessage,
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
];
|
|
82
|
+
const messageBlocks = blocks ?? buildMrkdwnSectionBlocks(slackMessage);
|
|
76
83
|
|
|
77
84
|
const result = await withAutoJoin(app.client, channelId, () =>
|
|
78
85
|
app.client.chat.postMessage({
|
|
@@ -4,6 +4,7 @@ import * as z from "zod";
|
|
|
4
4
|
import { getAgentById } from "@/be/db";
|
|
5
5
|
import { can } from "@/rbac";
|
|
6
6
|
import { getSlackApp } from "@/slack/app";
|
|
7
|
+
import { buildMrkdwnSectionBlocks } from "@/slack/blocks";
|
|
7
8
|
import { externalChannelToolError, getChannelBlockReason } from "@/slack/external-channel";
|
|
8
9
|
import { parseSlackTs } from "@/slack/message-text";
|
|
9
10
|
import { markdownToSlack } from "@/slack/responses";
|
|
@@ -77,15 +78,7 @@ export const registerSlackUpdateTool = (server: McpServer) => {
|
|
|
77
78
|
text: slackMessage,
|
|
78
79
|
unfurl_links: false,
|
|
79
80
|
unfurl_media: false,
|
|
80
|
-
blocks:
|
|
81
|
-
{
|
|
82
|
-
type: "section",
|
|
83
|
-
text: {
|
|
84
|
-
type: "mrkdwn",
|
|
85
|
-
text: slackMessage,
|
|
86
|
-
},
|
|
87
|
-
},
|
|
88
|
-
],
|
|
81
|
+
blocks: buildMrkdwnSectionBlocks(slackMessage),
|
|
89
82
|
} satisfies ChatUpdatePayload;
|
|
90
83
|
const result = await app.client.chat.update(updatePayload);
|
|
91
84
|
|
package/src/tools/tool-config.ts
CHANGED
|
@@ -189,6 +189,14 @@ export const DEFERRED_TOOLS = new Set([
|
|
|
189
189
|
"app-list",
|
|
190
190
|
"app-patch",
|
|
191
191
|
"app-query",
|
|
192
|
+
"app-rows-list",
|
|
193
|
+
"app-row-get",
|
|
194
|
+
"app-row-create",
|
|
195
|
+
"app-rows-create",
|
|
196
|
+
"app-row-patch",
|
|
197
|
+
"app-row-delete",
|
|
198
|
+
"app-rows-delete",
|
|
199
|
+
"app-action-run",
|
|
192
200
|
"app-sync",
|
|
193
201
|
"app-upsert",
|
|
194
202
|
"app-history",
|
package/src/tools/utils.ts
CHANGED
|
@@ -347,7 +347,7 @@ export const NUDGES: Record<string, (result: SwarmToolResult) => string | undefi
|
|
|
347
347
|
const hasQueries = Object.keys(definition?.queries ?? {}).length > 0;
|
|
348
348
|
const hasActions = Object.keys(definition?.actions ?? {}).length > 0;
|
|
349
349
|
return hasQueries || hasActions
|
|
350
|
-
? "
|
|
350
|
+
? "Run `definition.queries` with `app-query` and supply each `$param` value. Invoke `definition.actions` with `app-action-run` through MCP or `POST /api/apps/<id>/actions/<name>` through REST. Sync actions refresh sources."
|
|
351
351
|
: undefined;
|
|
352
352
|
},
|
|
353
353
|
// kv-get is spill-exempt (retrieval path), so oversized values reach the
|
|
@@ -10,7 +10,7 @@ export const registerRetryWorkflowRunTool = (server: McpServer) => {
|
|
|
10
10
|
title: "Retry Workflow Run",
|
|
11
11
|
annotations: { destructiveHint: false },
|
|
12
12
|
description:
|
|
13
|
-
"
|
|
13
|
+
"Resume the same failed workflow run from its failed step(s); completed steps are not re-run. Retrying re-creates the failed node's side effects (e.g. an agent task), so check the target state first if that work was already done manually.",
|
|
14
14
|
inputSchema: z.object({
|
|
15
15
|
runId: z.string().uuid().describe("Workflow run ID to retry"),
|
|
16
16
|
}),
|
package/src/types.ts
CHANGED
|
@@ -453,6 +453,41 @@ export const ModelProfileSchema = z.object({
|
|
|
453
453
|
});
|
|
454
454
|
export type ModelProfile = z.infer<typeof ModelProfileSchema>;
|
|
455
455
|
|
|
456
|
+
// ============================================================================
|
|
457
|
+
// Session sharing
|
|
458
|
+
// ============================================================================
|
|
459
|
+
//
|
|
460
|
+
// `SessionShareAccessSchema` MUST stay in sync with the SQL CHECK constraint
|
|
461
|
+
// on session_shares.access (migration 230).
|
|
462
|
+
|
|
463
|
+
export const SessionShareAccessSchema = z.enum(["read", "write"]);
|
|
464
|
+
export type SessionShareAccess = z.infer<typeof SessionShareAccessSchema>;
|
|
465
|
+
|
|
466
|
+
/** The caller's access to a session. `none` is never returned; it is a 403. */
|
|
467
|
+
export const SessionAccessSchema = z.enum(["owner", "write", "read"]);
|
|
468
|
+
|
|
469
|
+
export const SessionOwnerSchema = z
|
|
470
|
+
.object({ id: z.string(), name: z.string() })
|
|
471
|
+
.openapi("SessionOwner");
|
|
472
|
+
|
|
473
|
+
export const SessionSharesSchema = z
|
|
474
|
+
.object({
|
|
475
|
+
/** What every user may do. `none` = private (owner and named users only). */
|
|
476
|
+
everyone: z.enum(["none", "read", "write"]),
|
|
477
|
+
users: z.array(
|
|
478
|
+
z.object({ userId: z.string(), access: SessionShareAccessSchema, createdAt: z.string() }),
|
|
479
|
+
),
|
|
480
|
+
})
|
|
481
|
+
.openapi("SessionShares");
|
|
482
|
+
export type SessionShares = z.infer<typeof SessionSharesSchema>;
|
|
483
|
+
|
|
484
|
+
export const SessionSharesUpdateSchema = z.object({
|
|
485
|
+
everyone: z.enum(["none", "read", "write"]),
|
|
486
|
+
users: z
|
|
487
|
+
.array(z.object({ userId: z.string().min(1), access: SessionShareAccessSchema }))
|
|
488
|
+
.max(500),
|
|
489
|
+
});
|
|
490
|
+
|
|
456
491
|
// ============================================================================
|
|
457
492
|
// Task Steering Messages
|
|
458
493
|
// ============================================================================
|
|
@@ -1327,6 +1362,14 @@ export const AgentBedrockStatusSchema = z
|
|
|
1327
1362
|
.openapi("AgentBedrockStatus");
|
|
1328
1363
|
export type AgentBedrockStatus = z.infer<typeof AgentBedrockStatusSchema>;
|
|
1329
1364
|
|
|
1365
|
+
export const AgentOpencodeGoStatusSchema = z
|
|
1366
|
+
.object({
|
|
1367
|
+
probedAt: z.number(), // unix ms
|
|
1368
|
+
models: z.array(z.string()).default([]),
|
|
1369
|
+
})
|
|
1370
|
+
.openapi("AgentOpencodeGoStatus");
|
|
1371
|
+
export type AgentOpencodeGoStatus = z.infer<typeof AgentOpencodeGoStatusSchema>;
|
|
1372
|
+
|
|
1330
1373
|
const AcpSessionConfigSelectValueSchema = z.object({
|
|
1331
1374
|
value: z.string(),
|
|
1332
1375
|
name: z.string(),
|
|
@@ -1386,6 +1429,8 @@ export const AgentCredStatusSchema = z
|
|
|
1386
1429
|
reportKind: z.enum(["boot", "post_task"]).default("boot"),
|
|
1387
1430
|
/** Pi-mono Bedrock enumeration block — null when not in Bedrock mode. */
|
|
1388
1431
|
bedrock: AgentBedrockStatusSchema.nullable().default(null),
|
|
1432
|
+
/** Pi-mono only: the `opencode-go` model ids the worker's pi-ai resolves. */
|
|
1433
|
+
opencodeGo: AgentOpencodeGoStatusSchema.nullable().default(null),
|
|
1389
1434
|
/** ACP options advertised by the most recently created session. */
|
|
1390
1435
|
acp: AgentAcpStatusSchema.nullable().default(null),
|
|
1391
1436
|
})
|
|
@@ -2175,6 +2220,13 @@ export const RetryPolicySchema = z
|
|
|
2175
2220
|
.openapi("RetryPolicy");
|
|
2176
2221
|
export type RetryPolicy = z.infer<typeof RetryPolicySchema>;
|
|
2177
2222
|
|
|
2223
|
+
/**
|
|
2224
|
+
* `failureReason` of a workflow-step task cut by a supersede (deploy drain,
|
|
2225
|
+
* heartbeat remediation). The workflow engine re-dispatches it once even
|
|
2226
|
+
* when the node declares no `retry` (see `scheduleTaskStepRetry`).
|
|
2227
|
+
*/
|
|
2228
|
+
export const SUPERSEDED_WORKFLOW_TASK_REASON = "superseded_workflow_task";
|
|
2229
|
+
|
|
2178
2230
|
// --- Executor Metadata ---
|
|
2179
2231
|
|
|
2180
2232
|
export const ExecutorMetaSchema = z
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const COMPANY_TEAM_SIZES = ["1", "2-10", "11-50", "51+"] as const;
|
|
2
|
+
|
|
3
|
+
export const COMPANY_USE_CASES = ["features", "bugs", "review", "ops", "docs", "data"] as const;
|
|
4
|
+
|
|
5
|
+
export const COMPANY_ACQUISITION_SOURCES = [
|
|
6
|
+
"search",
|
|
7
|
+
"github",
|
|
8
|
+
"social",
|
|
9
|
+
"colleague",
|
|
10
|
+
"newsletter",
|
|
11
|
+
"event",
|
|
12
|
+
"ai_assistant",
|
|
13
|
+
"hacker_news",
|
|
14
|
+
"other",
|
|
15
|
+
] as const;
|
|
16
|
+
|
|
17
|
+
export const USER_FUNCTIONS = [
|
|
18
|
+
"engineer",
|
|
19
|
+
"eng_lead",
|
|
20
|
+
"founder",
|
|
21
|
+
"product",
|
|
22
|
+
"ops",
|
|
23
|
+
"other",
|
|
24
|
+
] as const;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The "is the org identity set" rule, shared by every feature that needs a real
|
|
3
|
+
* organization name and website (the public ranking, the "used by" grant).
|
|
4
|
+
* Pure: the API passes global config values, workers pass `process.env`.
|
|
5
|
+
*/
|
|
6
|
+
import { normalizeOrgWebsite } from "./org-website";
|
|
7
|
+
|
|
8
|
+
export const ORG_IDENTITY_KEYS = ["SWARM_ORG_NAME", "SWARM_ORG_WEBSITE"] as const;
|
|
9
|
+
export type OrgIdentityKey = (typeof ORG_IDENTITY_KEYS)[number];
|
|
10
|
+
|
|
11
|
+
/** Names the product falls back to when none is set; they are not an org name. */
|
|
12
|
+
const PLACEHOLDER_NAMES = new Set(["swarm", "your swarm"]);
|
|
13
|
+
|
|
14
|
+
export interface OrgIdentityStatus {
|
|
15
|
+
/** The trimmed name, or null when blank. A placeholder is returned but listed as missing. */
|
|
16
|
+
name: string | null;
|
|
17
|
+
/** The website as a bare hostname, or null when blank or not a public hostname. */
|
|
18
|
+
website: string | null;
|
|
19
|
+
missing: OrgIdentityKey[];
|
|
20
|
+
ok: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function orgIdentityStatus(src: {
|
|
24
|
+
SWARM_ORG_NAME?: string | null;
|
|
25
|
+
SWARM_ORG_WEBSITE?: string | null;
|
|
26
|
+
}): OrgIdentityStatus {
|
|
27
|
+
const name = src.SWARM_ORG_NAME?.trim() || null;
|
|
28
|
+
const website = normalizeOrgWebsite(src.SWARM_ORG_WEBSITE) || null;
|
|
29
|
+
const missing: OrgIdentityKey[] = [];
|
|
30
|
+
if (!name || PLACEHOLDER_NAMES.has(name.toLowerCase())) missing.push("SWARM_ORG_NAME");
|
|
31
|
+
if (!website) missing.push("SWARM_ORG_WEBSITE");
|
|
32
|
+
return { name, website, missing, ok: missing.length === 0 };
|
|
33
|
+
}
|