@desplega.ai/agent-swarm 2.4.4 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/dist/{acp-adapter-thq04adh.js → acp-adapter-11gp67nr.js} +8 -6
- package/dist/{actions-j6ywh6x5.js → actions-8p2kze8j.js} +24 -22
- package/dist/{amp-adapter-k8b5xmj8.js → amp-adapter-z4qvhacj.js} +2 -2
- package/dist/{anthropic-messages-g6pqmqk4.js → anthropic-messages-txs190dd.js} +17 -20
- package/dist/{app-rb7vc02s.js → app-0qp0a2gk.js} +3 -3
- package/dist/{assistant-ftta1zjf.js → assistant-jedd3ktm.js} +27 -25
- package/dist/{azure-openai-responses-9dbmj346.js → azure-openai-responses-9kfwhmn7.js} +18 -13
- package/dist/{boot-reembed-xns7h5h9.js → boot-reembed-4xwq5tg0.js} +1 -1
- package/dist/{boot-reembed-srp6v6af.js → boot-reembed-n4wq5dd2.js} +1 -1
- package/dist/{boot-scrub-sweep-3qqrh2mz.js → boot-scrub-sweep-69h90xcq.js} +4 -4
- package/dist/{boot-seeds-9ks8hce7.js → boot-seeds-3vn0m9sg.js} +4 -4
- package/dist/{claude-adapter-k5ksyres.js → claude-adapter-221mvad5.js} +8 -6
- package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-gt6pa35d.js} +2 -2
- package/dist/{claude-managed-setup-n5a5eqks.js → claude-managed-setup-c3hp36ph.js} +4 -4
- package/dist/{claude-sdk-session-2j3j4kwn.js → claude-sdk-session-8thjsk5e.js} +9729 -9628
- package/dist/{cli-b9fcxxev.js → cli-007cnhm1.js} +50 -4
- package/dist/{cli-j4rqdf2n.js → cli-03vpq45j.js} +2 -2
- package/dist/{cli-amyhm3gj.js → cli-0y6f0ckq.js} +1 -1
- package/dist/{cli-4dg55wsk.js → cli-0z3vjrpm.js} +1 -1
- package/dist/{cli-pccfmtb5.js → cli-179xcyky.js} +11 -11
- package/dist/{cli-3r8samv3.js → cli-1f0gp9vz.js} +3 -2
- package/dist/{cli-hj3debgw.js → cli-1pr672hz.js} +3 -3
- package/dist/{cli-0bqteszy.js → cli-2nf3b08t.js} +328 -25
- package/dist/{cli-t7cyef5g.js → cli-36j4jnk3.js} +4 -4
- package/dist/{cli-er83cjbn.js → cli-3qv8naq8.js} +527 -231
- package/dist/cli-3zwye9sn.js +1193 -0
- package/dist/{cli-60cgh1rv.js → cli-459fk97x.js} +7 -7
- package/dist/{cli-xj0re5tm.js → cli-4w24f7z3.js} +1 -1
- package/dist/{cli-v3yr2gbg.js → cli-5kzk3472.js} +2198 -968
- package/dist/{cli-h7gc0b4r.js → cli-5m84zd2k.js} +55 -18
- package/dist/{cli-w6nadkh4.js → cli-5rvg1ddk.js} +5 -5
- package/dist/{cli-dvkmp9bt.js → cli-6ctwrf1z.js} +20 -10
- package/dist/{cli-9qtjfd60.js → cli-6rg2jn2y.js} +3 -2
- package/dist/{cli-2v045xyf.js → cli-7bwtc6yx.js} +3 -3
- package/dist/{cli-3cgngyd8.js → cli-7g40g8hq.js} +35 -17
- package/dist/{cli-q6r7t299.js → cli-92mqenkc.js} +2379 -154
- package/dist/{cli-cynvc9fj.js → cli-9ce2xw98.js} +8 -8
- package/dist/{cli-gqvh8d8a.js → cli-bgdtv62r.js} +36 -22
- package/dist/{cli-wxbn3yfx.js → cli-cz5nmdxt.js} +2 -2
- package/dist/{cli-wt645v7q.js → cli-dabehxhp.js} +1 -1
- package/dist/{cli-vfha21c9.js → cli-e5bxnjps.js} +2 -2
- package/dist/{cli-p20r8w42.js → cli-fcc5qe3f.js} +763 -268
- package/dist/{cli-1ephgwnq.js → cli-fes51ya2.js} +3 -3
- package/dist/{cli-1d70crsy.js → cli-ftmq4nvk.js} +2 -2
- package/dist/{cli-qkhc5aqy.js → cli-fy1jyyym.js} +13 -13
- package/dist/{cli-s95dknxh.js → cli-g1cw7xtt.js} +1 -1
- package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
- package/dist/{cli-74c1wpm0.js → cli-gpv60278.js} +1 -1
- package/dist/{cli-pemywhfq.js → cli-ha9rmwgq.js} +2 -1
- package/dist/{cli-bnz0r3kc.js → cli-j1eghqfm.js} +5 -5
- package/dist/{cli-2zqpkvtt.js → cli-jpxsrxcb.js} +1 -1
- package/dist/{cli-ejs3m1sx.js → cli-kxpfx2xr.js} +1 -1
- package/dist/{cli-37yb7307.js → cli-mbfj11fq.js} +1 -1
- package/dist/{cli-pnp2j5zg.js → cli-mmhj8vd7.js} +2 -2
- package/dist/{cli-xf234ws8.js → cli-n4c8e3s5.js} +2 -0
- package/dist/{cli-a0kcty51.js → cli-n6kmqngw.js} +2 -2
- package/dist/{cli-te6b5wvg.js → cli-nnvjb17s.js} +3 -3
- package/dist/{cli-1dmcq2eh.js → cli-nzfnt2gs.js} +1 -1
- package/dist/{cli-625tb7aq.js → cli-p859hcc8.js} +2 -2
- package/dist/{cli-smvcw9z5.js → cli-pasyvjmm.js} +1 -1
- package/dist/cli-pkaqk57w.js +128 -0
- package/dist/{cli-8nyhf7za.js → cli-qqzmjxkf.js} +129 -105
- package/dist/{cli-zrwpctp4.js → cli-r25qpaxt.js} +161 -63
- package/dist/{cli-nc35pxb7.js → cli-rh5smt8t.js} +19 -4
- package/dist/{cli-qwkcwjdn.js → cli-rycdaj0a.js} +1 -1
- package/dist/{cli-esxerzg7.js → cli-s4sntwt4.js} +2 -2
- package/dist/{cli-b8k7epj1.js → cli-segs7hx9.js} +8 -8
- package/dist/{cli-36ckw0wx.js → cli-stxdrqs2.js} +2 -2
- package/dist/{cli-vdm20wej.js → cli-sy8f9705.js} +4 -4
- package/dist/{cli-1m17dc9d.js → cli-ta8bd7th.js} +2 -2
- package/dist/{cli-2y91wnbh.js → cli-we0ra057.js} +222 -10
- package/dist/{cli-55qmbp6z.js → cli-x21dqn18.js} +5 -5
- package/dist/{cli-dqb4n629.js → cli-x6vf4sad.js} +11 -11
- package/dist/{cli-d2mb5s8a.js → cli-x77gen2p.js} +680 -440
- package/dist/{cli-vq97g1jq.js → cli-xawhpgc9.js} +95 -195
- package/dist/{cli-82d3nkc3.js → cli-xd4eqtr2.js} +2 -2
- package/dist/{cli-9fhkkpj5.js → cli-xt768r5m.js} +2 -2
- package/dist/{cli-zrk6jxv8.js → cli-y4x8ww6s.js} +2 -2
- package/dist/{cli-xc27fwzg.js → cli-y9jvxfhk.js} +3 -3
- package/dist/{cli-44159k28.js → cli-z63a269p.js} +2 -2
- package/dist/{cli-sm8rses9.js → cli-zfdp01hn.js} +8 -5
- package/dist/cli.js +31 -29
- package/dist/{cloudflare-workers-ai-system-one-ch2wxfcp.js → cloudflare-workers-ai-system-one-43v9qkjk.js} +7 -2
- package/dist/{codex-adapter-968xwfy7.js → codex-adapter-tcg1q3jk.js} +6 -4
- package/dist/{codex-login-m819c41r.js → codex-login-rn7c5gxt.js} +1 -1
- package/dist/{codex-session-runner-ht4z99fa.js → codex-session-runner-xfx4wd9x.js} +7 -5
- package/dist/{commands-pcymaeg9.js → commands-ew83nj70.js} +2 -2
- package/dist/{controller-fpjyk46r.js → controller-gnq1k1mf.js} +4 -4
- package/dist/{controllers-connect-mwzx1fh6.js → controllers-connect-tw1dan9r.js} +26 -24
- package/dist/{cursor-adapter-cp4s2e2f.js → cursor-adapter-yq5xgfcg.js} +1 -1
- package/dist/{db-xsjg9jqq.js → db-7gbc53fd.js} +14 -2
- package/dist/{db-sgd12bt9.js → db-t86xrnes.js} +3 -3
- package/dist/{devin-adapter-zgqadvnm.js → devin-adapter-4ycy4vrf.js} +1 -1
- package/dist/{dispatcher-x0jfw2c9.js → dispatcher-64bdyhps.js} +23 -21
- package/dist/{docker-fkgtr75t.js → docker-nfy2gc8t.js} +2 -2
- package/dist/{dsh-adapter-jrq7ma7h.js → dsh-adapter-tvhc4k2d.js} +1 -1
- package/dist/{e2b-16d6ch39.js → e2b-9gkdhm3c.js} +2 -2
- package/dist/{e2b-zn0b4w5w.js → e2b-cjtf8k1z.js} +2 -2
- package/dist/{easter-egg-3d-5cgynaja.js → easter-egg-3d-e4qv8dxj.js} +1 -1
- package/dist/{event-bus-9vpk8gmq.js → event-bus-3z78ep5n.js} +1 -1
- package/dist/{execute-t4e6m3rw.js → execute-0xpz8950.js} +85 -23
- package/dist/{external-channel-8njj4h3b.js → external-channel-e9nw24zv.js} +2 -2
- package/dist/{google-generative-ai-bmq8gkf3.js → google-generative-ai-mk9vcpe1.js} +15 -15
- package/dist/{google-vertex-b1rvp52s.js → google-vertex-q580kz8k.js} +20 -20
- package/dist/{grok-adapter-kkr97v2f.js → grok-adapter-v82srhrx.js} +9 -7
- package/dist/handlers-c9ajzhbn.js +41 -0
- package/dist/{heartbeat-wd03zhn0.js → heartbeat-2vqs1319.js} +26 -24
- package/dist/{hook-xzj2ts2p.js → hook-01nk13wx.js} +7 -5
- package/dist/{hook-f0vghj42.js → hook-jzpheegg.js} +9 -7
- package/dist/{http-4hwxv62p.js → http-fc1k6ec8.js} +859 -252
- package/dist/index-07ef7nkm.js +42 -0
- package/dist/{index-g6tbb6ve.js → index-31ceyf42.js} +1 -1
- package/dist/index-7yts8n9s.js +43 -0
- package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
- package/dist/index-q3t40ryv.js +46 -0
- package/dist/{index-ww2vznkp.js → index-sepja052.js} +1 -1
- package/dist/{index-97q4xn03.js → index-zdycv3ja.js} +135 -79
- package/dist/{index-g216q6jr.js → index-zsyx51ap.js} +1 -4
- package/dist/{keepalive-hrh7xnr9.js → keepalive-5nh2rhmr.js} +4 -4
- package/dist/lead-aayq64jn.js +79 -0
- package/dist/{llama-cpp-classify-vv43gswy.js → llama-cpp-classify-ee7vmd7q.js} +4 -1
- package/dist/{maintenance-e8wnwnqx.js → maintenance-hjhzdt3k.js} +1 -1
- package/dist/{mistral-conversations-1medfwv7.js → mistral-conversations-sd0xf1tn.js} +13 -13
- package/dist/{node-3v3f08f7.js → node-jzjj7r9x.js} +10 -9
- package/dist/{oauth-refresh-sweep-zm0yj4sj.js → oauth-refresh-sweep-y3n1knmd.js} +3 -3
- package/dist/{onboard-dtwcq603.js → onboard-1zq3m7db.js} +2 -2
- package/dist/{openai-codex-responses-de9pvs4d.js → openai-codex-responses-79s8xnbh.js} +29 -23
- package/dist/{openai-completions-mtqge3nf.js → openai-completions-tdbyts0x.js} +21 -20
- package/dist/{openai-decisions-ygk4kkxd.js → openai-decisions-bqhnjyfz.js} +2 -1
- package/dist/{openai-responses-dkyng71g.js → openai-responses-dm3t5vqp.js} +26 -17
- package/dist/{opencode-adapter-x4tqzhkh.js → opencode-adapter-e56086m1.js} +7 -5
- package/dist/{openrouter-images-wvv7camj.js → openrouter-images-ssttr1y4.js} +6 -3
- package/dist/{otel-impl-w3fbhpn0.js → otel-impl-h9yyza47.js} +2 -2
- package/dist/{pi-messages-nhh1pkz2.js → pi-messages-3nf8bq1a.js} +6 -4
- package/dist/{pi-mono-adapter-mcfkn9vf.js → pi-mono-adapter-tzps8f38.js} +9 -37
- package/dist/{pricing-refresh-j38dehfs.js → pricing-refresh-nevhat8h.js} +3 -3
- package/dist/{rbac-roles-ae8yttq4.js → rbac-roles-4y6ngvzq.js} +1 -1
- package/dist/{rbac-roles-ejxx9b35.js → rbac-roles-exbg8xb6.js} +2 -2
- package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
- package/dist/{render-v2-n16n0phe.js → render-v2-cfsh13z3.js} +3 -3
- package/dist/{resume-z0fgjc38.js → resume-5s2t0dbs.js} +10 -8
- package/dist/{runtime-xe3aqy4x.js → runtime-bt5pkpm1.js} +1 -1
- package/dist/{session-access-cv3mq6mc.js → session-access-dnbyp3cn.js} +6 -4
- package/dist/{setup-mafhj3yt.js → setup-1wj1y77j.js} +1 -1
- package/dist/{typesafe-system-one-2hgpayzy.js → typesafe-system-one-bre38hvs.js} +4 -2
- package/dist/{virtual-modules-4r3zkc20.js → virtual-modules-mnfbh5mr.js} +8 -2
- package/dist/{work-objects-8b86mgjp.js → work-objects-7mg6216g.js} +26 -24
- package/dist/worker-nwb789mg.js +79 -0
- package/dist/{x-y45mthwn.js → x-pbpezr0s.js} +2 -2
- package/openapi.json +793 -6
- package/package.json +11 -11
- package/src/apps/catalog.generated.json +206 -4
- package/src/apps/page-validator.ts +13 -1
- package/src/assets/key.ts +17 -0
- package/src/azure-devops/handlers.ts +1 -1
- package/src/be/chunking.ts +42 -9
- package/src/be/db/approvals.ts +18 -0
- package/src/be/db/session-moves.ts +164 -0
- package/src/be/db/session-tree.ts +384 -0
- package/src/be/db/tasks/draft-text.ts +15 -0
- package/src/be/db/tasks/read.ts +54 -5
- package/src/be/db/workflow-runs.ts +96 -0
- package/src/be/db.ts +85 -237
- package/src/be/memory/index-content.ts +36 -17
- package/src/be/memory/providers/openai-embedding.ts +115 -61
- package/src/be/memory/providers/sqlite-store.ts +69 -23
- package/src/be/memory/reranker.ts +31 -1
- package/src/be/memory/search-candidates.ts +47 -0
- package/src/be/memory/types.ts +14 -0
- package/src/be/onboarding.ts +3 -0
- package/src/be/scripts/typecheck.ts +2 -0
- package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +106 -54
- package/src/be/seed-scripts/index.ts +2 -2
- package/src/be/skill-sync.ts +43 -2
- package/src/be/swarm-config-guard.ts +25 -1
- package/src/be/task-attachment-store.ts +30 -0
- package/src/bitbucket/api.ts +81 -0
- package/src/bitbucket/auth.ts +64 -0
- package/src/bitbucket/handlers.ts +434 -0
- package/src/bitbucket/index.ts +28 -0
- package/src/bitbucket/templates.ts +134 -0
- package/src/bitbucket/types.ts +65 -0
- package/src/commands/runner.ts +55 -3
- package/src/e2b/env.ts +1 -0
- package/src/extensions/catalog.generated.json +4 -4
- package/src/extensions/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +9 -2
- package/src/extensions/post-bridge.ts +1 -0
- package/src/fs/provider.ts +13 -1
- package/src/github/handlers.ts +6 -6
- package/src/gitlab/handlers.ts +5 -5
- package/src/heartbeat/heartbeat.ts +31 -11
- package/src/http/assets.ts +14 -2
- package/src/http/core.ts +12 -0
- package/src/http/fs.ts +54 -34
- package/src/http/index.ts +4 -0
- package/src/http/mcp-body.ts +37 -0
- package/src/http/mcp-user.ts +3 -5
- package/src/http/mcp.ts +6 -7
- package/src/http/memory.ts +26 -15
- package/src/http/onboarding.ts +1 -0
- package/src/http/page-proxy.ts +61 -5
- package/src/http/pages-public.ts +27 -44
- package/src/http/pages.ts +4 -4
- package/src/http/script-runs.ts +2 -0
- package/src/http/sessions.ts +366 -12
- package/src/http/skills.ts +48 -1
- package/src/http/tasks.ts +1 -1
- package/src/http/users.ts +13 -1
- package/src/http/webhooks.ts +141 -0
- package/src/integrations/chat-sdk/adapters.ts +24 -4
- package/src/integrations/chat-sdk/attachments.ts +90 -12
- package/src/integrations/chat-sdk/facts.ts +138 -0
- package/src/integrations/chat-sdk/inbound.ts +156 -8
- package/src/integrations/chat-sdk/limits.ts +24 -0
- package/src/integrations/chat-sdk/outbound-files.ts +186 -0
- package/src/integrations/chat-sdk/outbound.ts +272 -5
- package/src/integrations/chat-sdk/relay.ts +4 -1
- package/src/integrations/chat-sdk/router.ts +28 -2
- package/src/integrations/chat-sdk/steering.ts +9 -0
- package/src/integrations/chat-sdk/templates.ts +14 -0
- package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
- package/src/mcp-limits.ts +20 -0
- package/src/pages/browser-sdk.ts +8 -3
- package/src/pages/feedback-overlay.ts +1 -1
- package/src/providers/acp-targets.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/codex-adapter.ts +106 -119
- package/src/providers/codex-agents-md.ts +35 -229
- package/src/providers/cursor-adapter.ts +1 -1
- package/src/providers/pi-mono-adapter.ts +5 -53
- package/src/realtime/transport.ts +1 -2
- package/src/script-workflows/workflow-ctx.ts +1 -0
- package/src/scripts-runtime/types/stdlib.d.ts +2 -0
- package/src/scripts-runtime/types/swarm-extension.d.ts +14 -4
- package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
- package/src/server-user.ts +2 -0
- package/src/server.ts +2 -0
- package/src/slack/assistant.ts +2 -2
- package/src/slack/files.ts +2 -0
- package/src/slack/handlers.test.ts +158 -0
- package/src/slack/handlers.ts +23 -32
- package/src/slack/inbound-files.ts +39 -6
- package/src/slack/thread-buffer.ts +2 -1
- package/src/tasks/context-key.ts +61 -1
- package/src/tasks/task-terminal-effects.ts +21 -17
- package/src/tests/apps-card-grid.test.ts +197 -0
- package/src/tests/apps-catalog-additions.test.ts +120 -0
- package/src/tests/apps-tree.test.ts +129 -0
- package/src/tests/bitbucket-auth.test.ts +156 -0
- package/src/tests/bitbucket-handlers.test.ts +425 -0
- package/src/tests/bitbucket-webhook.test.ts +220 -0
- package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
- package/src/tests/chat-sdk-config.test.ts +11 -0
- package/src/tests/chat-sdk-facts.test.ts +23 -0
- package/src/tests/chat-sdk-inbound.test.ts +597 -4
- package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
- package/src/tests/chat-sdk-telegram-markdown.test.ts +92 -0
- package/src/tests/codex-adapter.test.ts +167 -242
- package/src/tests/config-api-only-keys.test.ts +9 -0
- package/src/tests/context-key.test.ts +50 -0
- package/src/tests/core-auth.test.ts +5 -0
- package/src/tests/cors-allowlist.test.ts +1 -1
- package/src/tests/db-task-read-contract.test.ts +7 -0
- package/src/tests/db-task-write-contract.test.ts +6 -0
- package/src/tests/docs-index-footprint.test.js +3 -3
- package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
- package/src/tests/fixtures/bitbucket/pullrequest-comment-created-inline.json +174 -0
- package/src/tests/fixtures/bitbucket/pullrequest-comment-created.json +170 -0
- package/src/tests/fixtures/bitbucket/pullrequest-created-mention.json +132 -0
- package/src/tests/fixtures/bitbucket/pullrequest-created-reviewer.json +140 -0
- package/src/tests/fixtures/bitbucket/pullrequest-fulfilled.json +134 -0
- package/src/tests/fixtures/bitbucket/pullrequest-rejected.json +133 -0
- package/src/tests/generate-mcp-docs.test.ts +101 -0
- package/src/tests/gitlab-handlers.test.ts +3 -3
- package/src/tests/gitlab-vcs-db.test.ts +4 -4
- package/src/tests/heartbeat-checklist.test.ts +33 -0
- package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
- package/src/tests/heartbeat-jev-gate.test.ts +242 -1
- package/src/tests/integration-disable-flags.test.ts +36 -0
- package/src/tests/kv-page-proxy.test.ts +91 -5
- package/src/tests/launch-password-rejection.test.ts +2 -2
- package/src/tests/mcp-input-caps.test.ts +294 -0
- package/src/tests/mcp-tools.test.ts +1 -1
- package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
- package/src/tests/memory-embedding-input-cap.test.ts +114 -0
- package/src/tests/memory.test.ts +14 -0
- package/src/tests/onboarding.test.ts +12 -0
- package/src/tests/page-guest-session.test.ts +19 -8
- package/src/tests/page-proxy-authed.test.ts +1 -1
- package/src/tests/page-proxy.test.ts +17 -10
- package/src/tests/page-session.test.ts +102 -1
- package/src/tests/pages-authed-mode.test.ts +82 -12
- package/src/tests/pages-password-mode.test.ts +5 -5
- package/src/tests/pi-codemode.test.ts +8 -2
- package/src/tests/preload-env.test.ts +57 -0
- package/src/tests/preload.ts +21 -0
- package/src/tests/prompt-template-remaining.test.ts +38 -0
- package/src/tests/realtime-transport.test.ts +13 -7
- package/src/tests/run-root-coverage.test.ts +39 -0
- package/src/tests/runner-bitbucket-vcs.test.ts +191 -0
- package/src/tests/runner-skills-refresh.test.ts +58 -0
- package/src/tests/script-runs-http.test.ts +84 -0
- package/src/tests/scripts-http.test.ts +10 -1
- package/src/tests/secret-scrubber.test.ts +15 -0
- package/src/tests/sessions-move.test.ts +576 -0
- package/src/tests/sessions-tree.test.ts +493 -0
- package/src/tests/skill-files-http.test.ts +50 -0
- package/src/tests/skills-bundle.test.ts +99 -0
- package/src/tests/swarm-config-export-to-env.test.ts +23 -3
- package/src/tests/task-audio-transcription.test.ts +299 -0
- package/src/tests/task-completion-memory-chunking.test.ts +434 -0
- package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
- package/src/tests/transcription.test.ts +299 -0
- package/src/tests/vcs-bitbucket.test.ts +91 -0
- package/src/tests/vcs-provider-isolation.test.ts +123 -0
- package/src/tests/vcs-provider.test.ts +16 -1
- package/src/tests/vcs-tracking.test.ts +3 -3
- package/src/tests/workflow-foreach-bodies.test.ts +637 -0
- package/src/tests/workflow-foreach-concurrency.test.ts +342 -0
- package/src/tests/workflow-foreach-retry.test.ts +537 -0
- package/src/tests/workflow-foreach.test.ts +44 -23
- package/src/tests/workflow-step-claims.test.ts +6 -6
- package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
- package/src/tests/workflow-system-one-decision.test.ts +2 -1
- package/src/tests/workflow-tla-races.test.ts +2 -2
- package/src/tools/chat-access.ts +10 -0
- package/src/tools/chat-post.ts +31 -11
- package/src/tools/chat-reply.ts +32 -10
- package/src/tools/memory-search.ts +3 -1
- package/src/tools/script-delete.ts +1 -1
- package/src/tools/system-one-decide.ts +17 -4
- package/src/tools/workflows/create-workflow.ts +5 -3
- package/src/types.ts +9 -2
- package/src/utils/config-env-export.ts +4 -1
- package/src/utils/page-session.ts +133 -20
- package/src/utils/secret-scrubber.ts +4 -0
- package/src/utils/skills-refresh.ts +83 -43
- package/src/utils/transcription.ts +246 -0
- package/src/vcs/bitbucket.ts +58 -0
- package/src/vcs/index.ts +2 -0
- package/src/vcs/types.ts +2 -2
- package/src/workflows/approval-resolution.ts +4 -1
- package/src/workflows/checkpoint.ts +9 -1
- package/src/workflows/constants.ts +3 -0
- package/src/workflows/definition.ts +48 -17
- package/src/workflows/engine.ts +25 -15
- package/src/workflows/executors/foreach.ts +45 -99
- package/src/workflows/executors/system-one-decision.ts +28 -7
- package/src/workflows/executors/system-one-providers.ts +39 -4
- package/src/workflows/foreach-body.ts +146 -0
- package/src/workflows/foreach-driver.ts +552 -0
- package/src/workflows/foreach-join.ts +206 -7
- package/src/workflows/node-timeout.ts +21 -0
- package/src/workflows/recovery.ts +68 -3
- package/src/workflows/resume.ts +221 -43
- package/src/workflows/retry-poller.ts +39 -24
- package/src/workflows/step-input.ts +59 -0
- package/src/workflows/task-step-routing.ts +114 -56
- package/templates/extensions/slack-reply-gate/README.md +24 -22
- package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
- package/templates/extensions/slack-reply-gate/manifest.json +2 -2
- package/templates/skills/apps/SKILL.md +28 -6
- package/templates/skills/apps/content.md +28 -6
- package/templates/skills/chat-sdk/content.md +6 -2
- package/templates/skills/code-quality/content.md +2 -1
- package/templates/skills/heartbeat-runbook/content.md +5 -5
- package/templates/skills/pages/content.md +6 -4
- package/templates/skills/slack-interaction/content.md +5 -0
- package/templates/skills/swarm-scripts/SKILL.md +2 -2
- package/templates/skills/swarm-scripts/content.md +2 -2
- package/templates/skills/work-on-task/SKILL.md +1 -1
- package/templates/skills/work-on-task/content.md +1 -1
- package/dist/cli-51y09c6p.js +0 -2657
- package/dist/cli-yw91rnmw.js +0 -13
- package/dist/handlers-0pvee9nw.js +0 -39
- package/dist/index-gdh8jrdm.js +0 -43
- package/dist/index-hg0x2cdv.js +0 -40
- package/dist/index-thm0y6a8.js +0 -41
- package/dist/lead-ee8vazz2.js +0 -77
- package/dist/worker-16s75hm5.js +0 -77
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { WorkflowRunStatus } from "../../types";
|
|
2
2
|
import { scrubSecrets } from "../../utils/secret-scrubber";
|
|
3
|
+
import { scrubJsonValue } from "../scrub-json";
|
|
3
4
|
import { getDbClient } from "./runtime";
|
|
4
5
|
|
|
5
6
|
// Parent/child links between workflow runs (migration 203): a `sub-workflow`
|
|
@@ -115,3 +116,98 @@ function emitAfterCommit(childRunId: string, parentStepId: string): void {
|
|
|
115
116
|
);
|
|
116
117
|
});
|
|
117
118
|
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Insert a foreach parent's missing child step rows as `pending` (queued), all
|
|
122
|
+
* in one transaction, so a crash never leaves a partial child set and the join
|
|
123
|
+
* always sees every item. Children that already exist (any row for the child
|
|
124
|
+
* node id) are skipped inside the transaction, which makes a concurrent
|
|
125
|
+
* re-execution of the same parent insert nothing twice. Returns how many rows
|
|
126
|
+
* this call inserted.
|
|
127
|
+
*/
|
|
128
|
+
export async function createForeachChildSteps(
|
|
129
|
+
runId: string,
|
|
130
|
+
parentNodeId: string,
|
|
131
|
+
rows: Array<{
|
|
132
|
+
id: string;
|
|
133
|
+
nodeId: string;
|
|
134
|
+
nodeType: string;
|
|
135
|
+
input: unknown;
|
|
136
|
+
idempotencyKey: string;
|
|
137
|
+
}>,
|
|
138
|
+
): Promise<number> {
|
|
139
|
+
if (rows.length === 0) return 0;
|
|
140
|
+
const prefix = `${parentNodeId}#`;
|
|
141
|
+
return getDbClient().transaction(async (tx) => {
|
|
142
|
+
const existing = await tx.query<{ nodeId: string }>(
|
|
143
|
+
"SELECT DISTINCT nodeId FROM workflow_run_steps WHERE runId = ? AND substr(nodeId, 1, ?) = ?",
|
|
144
|
+
[runId, prefix.length, prefix],
|
|
145
|
+
);
|
|
146
|
+
const existingNodeIds = new Set(existing.map((row) => row.nodeId));
|
|
147
|
+
const now = new Date().toISOString();
|
|
148
|
+
let created = 0;
|
|
149
|
+
for (const row of rows) {
|
|
150
|
+
if (existingNodeIds.has(row.nodeId)) continue;
|
|
151
|
+
await tx.run(
|
|
152
|
+
`INSERT INTO workflow_run_steps (id, runId, nodeId, nodeType, status, startedAt, input, idempotencyKey)
|
|
153
|
+
VALUES (?, ?, ?, ?, 'pending', ?, ?, ?)`,
|
|
154
|
+
[
|
|
155
|
+
row.id,
|
|
156
|
+
runId,
|
|
157
|
+
row.nodeId,
|
|
158
|
+
row.nodeType,
|
|
159
|
+
now,
|
|
160
|
+
scrubJsonValue(row.input),
|
|
161
|
+
row.idempotencyKey,
|
|
162
|
+
],
|
|
163
|
+
);
|
|
164
|
+
existingNodeIds.add(row.nodeId);
|
|
165
|
+
created++;
|
|
166
|
+
}
|
|
167
|
+
return created;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Insert a new `pending` attempt row for each foreach item being retried. Each
|
|
173
|
+
* row reuses its item's child node id and gets a fresh step id, so the body
|
|
174
|
+
* starts a new invocation (a new task, child run, approval or wait) while the
|
|
175
|
+
* earlier attempt rows stay as history. `attempt` is the number of rows the
|
|
176
|
+
* item already has, and the idempotency key `<runId>:<childNodeId>:<attempt>`
|
|
177
|
+
* is UNIQUE, so a duplicated retry of the same attempt inserts nothing.
|
|
178
|
+
* Call it inside the retry's transaction. Returns how many rows it inserted.
|
|
179
|
+
*/
|
|
180
|
+
export async function createForeachAttemptSteps(
|
|
181
|
+
runId: string,
|
|
182
|
+
rows: Array<{ nodeId: string; nodeType: string; itemKey: string; index: number }>,
|
|
183
|
+
): Promise<number> {
|
|
184
|
+
if (rows.length === 0) return 0;
|
|
185
|
+
return getDbClient().transaction(async (tx) => {
|
|
186
|
+
const now = new Date().toISOString();
|
|
187
|
+
let created = 0;
|
|
188
|
+
for (const row of rows) {
|
|
189
|
+
const count = await tx.get<{ n: number }>(
|
|
190
|
+
"SELECT COUNT(*) AS n FROM workflow_run_steps WHERE runId = ? AND nodeId = ?",
|
|
191
|
+
[runId, row.nodeId],
|
|
192
|
+
);
|
|
193
|
+
const attempt = count?.n ?? 0;
|
|
194
|
+
const inserted = await tx.get<{ id: string }>(
|
|
195
|
+
`INSERT INTO workflow_run_steps (id, runId, nodeId, nodeType, status, startedAt, input, idempotencyKey)
|
|
196
|
+
VALUES (?, ?, ?, ?, 'pending', ?, ?, ?)
|
|
197
|
+
ON CONFLICT(idempotencyKey) DO NOTHING
|
|
198
|
+
RETURNING id`,
|
|
199
|
+
[
|
|
200
|
+
crypto.randomUUID(),
|
|
201
|
+
runId,
|
|
202
|
+
row.nodeId,
|
|
203
|
+
row.nodeType,
|
|
204
|
+
now,
|
|
205
|
+
scrubJsonValue({ itemKey: row.itemKey, index: row.index, attempt }),
|
|
206
|
+
`${runId}:${row.nodeId}:${attempt}`,
|
|
207
|
+
],
|
|
208
|
+
);
|
|
209
|
+
if (inserted) created++;
|
|
210
|
+
}
|
|
211
|
+
return created;
|
|
212
|
+
});
|
|
213
|
+
}
|
package/src/be/db.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Database } from "bun:sqlite";
|
|
2
2
|
import pkg from "../../package.json";
|
|
3
|
-
import { defaultAssetKey, normalizeAssetKey } from "../assets/key";
|
|
3
|
+
import { defaultAssetKey, normalizeAssetKey, sessionGroupKey } from "../assets/key";
|
|
4
4
|
import {
|
|
5
5
|
generateDefaultClaudeMd,
|
|
6
6
|
generateDefaultIdentityMd,
|
|
@@ -195,7 +195,19 @@ import {
|
|
|
195
195
|
} from "./db/context-versions";
|
|
196
196
|
import { clearAgentModelProfileOnOverrideChange } from "./db/model-profiles";
|
|
197
197
|
import { getDb, getDbClient } from "./db/runtime";
|
|
198
|
-
import {
|
|
198
|
+
import {
|
|
199
|
+
assertAssetKeyMovesAllowed,
|
|
200
|
+
configureSessionMoveDependencies,
|
|
201
|
+
moveTaskChainKeyInTx,
|
|
202
|
+
} from "./db/session-moves";
|
|
203
|
+
import {
|
|
204
|
+
type SessionFilters,
|
|
205
|
+
type SessionReadState,
|
|
206
|
+
type SessionRowFields,
|
|
207
|
+
sessionCountQuery,
|
|
208
|
+
sessionPageFields,
|
|
209
|
+
sessionSummaryQuery,
|
|
210
|
+
} from "./db/session-tree";
|
|
199
211
|
import { classifyTaskHumanFree, reclassifyTaskHumanFree } from "./db/tasks/human-free";
|
|
200
212
|
import {
|
|
201
213
|
type AgentTaskRow,
|
|
@@ -269,6 +281,7 @@ export { recordKeySeatMismatch } from "./db/api-keys";
|
|
|
269
281
|
export {
|
|
270
282
|
type ApprovalRequestSummary,
|
|
271
283
|
type ApprovalVote,
|
|
284
|
+
getPendingApprovalsForTasks,
|
|
272
285
|
getPendingApprovalVoteState,
|
|
273
286
|
listApprovalRequestSummaries,
|
|
274
287
|
recordApprovalVotes,
|
|
@@ -281,6 +294,11 @@ export {
|
|
|
281
294
|
getLatestContextVersion,
|
|
282
295
|
} from "./db/context-versions";
|
|
283
296
|
export { getScriptRunExecutionArgs } from "./db/script-runs";
|
|
297
|
+
export {
|
|
298
|
+
AssetKeyMovesBlockedError,
|
|
299
|
+
assertAssetKeyMovesAllowed,
|
|
300
|
+
moveTaskChainKeyInTx,
|
|
301
|
+
} from "./db/session-moves";
|
|
284
302
|
|
|
285
303
|
configureAgentDependencies({
|
|
286
304
|
createLogEntry: (entry) => createLogEntry(entry),
|
|
@@ -300,6 +318,7 @@ export {
|
|
|
300
318
|
export {
|
|
301
319
|
type ExistingTrackerContextWork,
|
|
302
320
|
type ExistingTrackerContextWorkReason,
|
|
321
|
+
findActiveTasksByVcs,
|
|
303
322
|
findCompletedTaskInThread,
|
|
304
323
|
findExistingLinearTrackerContextWork,
|
|
305
324
|
findRecentCancelledTaskInThread,
|
|
@@ -387,6 +406,11 @@ configureTaskWriteDependencies({
|
|
|
387
406
|
cascadeFailDependents: (...args) => cascadeFailDependents(...args),
|
|
388
407
|
});
|
|
389
408
|
|
|
409
|
+
configureSessionMoveDependencies({
|
|
410
|
+
auditAssetKeys: () => auditAssetKeys(getDb()),
|
|
411
|
+
insertAssetKeyHistory: (...args) => insertAssetKeyHistory(...args),
|
|
412
|
+
});
|
|
413
|
+
|
|
390
414
|
configureTaskReadDependencies({
|
|
391
415
|
checkDependencies: (taskId) => checkDependencies(taskId),
|
|
392
416
|
assetKeyPrefixPattern: (input) => assetKeyPrefixPattern(input),
|
|
@@ -400,7 +424,7 @@ type TaskTelemetryContext = {
|
|
|
400
424
|
};
|
|
401
425
|
|
|
402
426
|
/** LIKE pattern matching strings that start with `prefix` literally (use with `ESCAPE '\\'`). */
|
|
403
|
-
function literalPrefixPattern(prefix: string): string {
|
|
427
|
+
export function literalPrefixPattern(prefix: string): string {
|
|
404
428
|
return `${prefix.replace(/[\\%_]/g, "\\$&")}%`;
|
|
405
429
|
}
|
|
406
430
|
|
|
@@ -1060,7 +1084,7 @@ export async function setSlackMessageTracking(
|
|
|
1060
1084
|
export async function updateTaskVcs(
|
|
1061
1085
|
taskId: string,
|
|
1062
1086
|
vcs: {
|
|
1063
|
-
vcsProvider: "github" | "gitlab" | "azure-devops";
|
|
1087
|
+
vcsProvider: "github" | "gitlab" | "azure-devops" | "bitbucket";
|
|
1064
1088
|
vcsRepo: string;
|
|
1065
1089
|
vcsNumber: number;
|
|
1066
1090
|
vcsUrl: string;
|
|
@@ -1742,17 +1766,7 @@ export async function moveAssetKey(input: {
|
|
|
1742
1766
|
descendantTaskIds?: readonly string[];
|
|
1743
1767
|
}): Promise<false | { movedTaskIds?: string[] }> {
|
|
1744
1768
|
const key = normalizeAssetKey(input.key);
|
|
1745
|
-
|
|
1746
|
-
// client transaction so this request-path read cannot observe another
|
|
1747
|
-
// request's uncommitted writes on the shared connection.
|
|
1748
|
-
const audit = await getDbClient().transaction(async () => auditAssetKeys(getDb()), {
|
|
1749
|
-
readOnly: true,
|
|
1750
|
-
});
|
|
1751
|
-
if (!audit.ok) {
|
|
1752
|
-
throw new Error(
|
|
1753
|
-
"Asset namespace moves are blocked until structural errors, unknown personal users, or provider mapping drift are repaired.",
|
|
1754
|
-
);
|
|
1755
|
-
}
|
|
1769
|
+
await assertAssetKeyMovesAllowed();
|
|
1756
1770
|
const previousKey = await currentAssetKey(input.entityType, input.id);
|
|
1757
1771
|
if (!previousKey) return false;
|
|
1758
1772
|
if (previousKey === key && input.entityType !== "task") return {};
|
|
@@ -1769,60 +1783,13 @@ export async function moveAssetKey(input: {
|
|
|
1769
1783
|
return getDbClient().transaction(async (tx) => {
|
|
1770
1784
|
switch (input.entityType) {
|
|
1771
1785
|
case "task": {
|
|
1772
|
-
const
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
const movedTaskIds: string[] = [];
|
|
1780
|
-
for (const task of tasks) {
|
|
1781
|
-
if (task.key === key) continue;
|
|
1782
|
-
// A file shared with another task keeps the namespace of the task whose attachment
|
|
1783
|
-
// sources its mapping. Mappings with no attachment source follow any attaching task.
|
|
1784
|
-
const mappedFiles = await tx.query<{ id: string; key: string }>(
|
|
1785
|
-
`SELECT DISTINCT m.id, m."key" AS key
|
|
1786
|
-
FROM asset_key_mappings m
|
|
1787
|
-
JOIN task_attachments a
|
|
1788
|
-
ON m.provider_id = COALESCE(NULLIF(a.provider_id, ''), 'agent-fs')
|
|
1789
|
-
AND m.provider_org_id = COALESCE(a.agent_fs_org_id, '')
|
|
1790
|
-
AND m.provider_drive_id = COALESCE(a.agent_fs_drive_id, '')
|
|
1791
|
-
AND m.provider_key = COALESCE(NULLIF(a.provider_key, ''), a.path)
|
|
1792
|
-
WHERE a.task_id = ?
|
|
1793
|
-
AND (m.source_entity_type IS NOT 'task-attachment'
|
|
1794
|
-
OR m.source_entity_id IN (SELECT id FROM task_attachments WHERE task_id = ?))`,
|
|
1795
|
-
[task.id, task.id],
|
|
1796
|
-
);
|
|
1797
|
-
// The namespace is metadata, and lastUpdatedAt tracks task activity, as in updateTaskTitle.
|
|
1798
|
-
await tx.run('UPDATE agent_tasks SET "key" = ?, updated_by = ? WHERE id = ?', [
|
|
1799
|
-
key,
|
|
1800
|
-
input.changedBy ?? null,
|
|
1801
|
-
task.id,
|
|
1802
|
-
]);
|
|
1803
|
-
for (const mapping of mappedFiles) {
|
|
1804
|
-
if (mapping.key === key) continue;
|
|
1805
|
-
await tx.run(
|
|
1806
|
-
'UPDATE asset_key_mappings SET "key" = ?, updated_at = ?, updated_by = ? WHERE id = ?',
|
|
1807
|
-
[key, now, input.changedBy ?? null, mapping.id],
|
|
1808
|
-
);
|
|
1809
|
-
await insertAssetKeyHistory({
|
|
1810
|
-
entityType: "file",
|
|
1811
|
-
entityId: mapping.id,
|
|
1812
|
-
previousKey: mapping.key,
|
|
1813
|
-
newKey: key,
|
|
1814
|
-
changedBy: input.changedBy,
|
|
1815
|
-
});
|
|
1816
|
-
}
|
|
1817
|
-
await insertAssetKeyHistory({
|
|
1818
|
-
entityType: "task",
|
|
1819
|
-
entityId: task.id,
|
|
1820
|
-
previousKey: task.key,
|
|
1821
|
-
newKey: key,
|
|
1822
|
-
changedBy: input.changedBy,
|
|
1823
|
-
});
|
|
1824
|
-
movedTaskIds.push(task.id);
|
|
1825
|
-
}
|
|
1786
|
+
const movedTaskIds = await moveTaskChainKeyInTx(
|
|
1787
|
+
input.id,
|
|
1788
|
+
input.descendantTaskIds ?? [],
|
|
1789
|
+
key,
|
|
1790
|
+
input.changedBy,
|
|
1791
|
+
);
|
|
1792
|
+
if (movedTaskIds === false) return false;
|
|
1826
1793
|
return { movedTaskIds };
|
|
1827
1794
|
}
|
|
1828
1795
|
case "workflow":
|
|
@@ -2605,7 +2572,7 @@ export async function createTaskExtended(
|
|
|
2605
2572
|
}
|
|
2606
2573
|
|
|
2607
2574
|
// VCS identity (GitHub / GitLab issue / PR / MR + webhook routing)
|
|
2608
|
-
// Webhook handlers locate active work via `findTaskByVcs(repo, number)`,
|
|
2575
|
+
// Webhook handlers locate active work via `findTaskByVcs(repo, number, provider)`,
|
|
2609
2576
|
// so a resume / follow-up child MUST carry the full VCS identity or
|
|
2610
2577
|
// subsequent review/update events get dropped.
|
|
2611
2578
|
if (parent.vcsProvider && !options.vcsProvider) {
|
|
@@ -2676,7 +2643,11 @@ export async function createTaskExtended(
|
|
|
2676
2643
|
}
|
|
2677
2644
|
|
|
2678
2645
|
// Attribution
|
|
2679
|
-
if (
|
|
2646
|
+
if (
|
|
2647
|
+
parent.requestedByUserId &&
|
|
2648
|
+
!options.requestedByUserId &&
|
|
2649
|
+
options.inheritParentRequester !== false
|
|
2650
|
+
) {
|
|
2680
2651
|
options.requestedByUserId = parent.requestedByUserId;
|
|
2681
2652
|
requestedByUserIdInherited = true;
|
|
2682
2653
|
}
|
|
@@ -12917,7 +12888,7 @@ export async function getRootTaskChain(rootTaskId: string): Promise<AgentTask[]>
|
|
|
12917
12888
|
return rows.map(rowToAgentTask);
|
|
12918
12889
|
}
|
|
12919
12890
|
|
|
12920
|
-
export interface SessionListItem {
|
|
12891
|
+
export interface SessionListItem extends SessionRowFields {
|
|
12921
12892
|
root: AgentTask;
|
|
12922
12893
|
chainTaskCount: number;
|
|
12923
12894
|
lastActivityAt: string;
|
|
@@ -12930,42 +12901,18 @@ export interface SessionListItem {
|
|
|
12930
12901
|
* The session list only renders a brief of the root; the full root + chain are
|
|
12931
12902
|
* on `GET /api/sessions/{rootTaskId}`.
|
|
12932
12903
|
*/
|
|
12933
|
-
export interface SessionListItemSummary {
|
|
12904
|
+
export interface SessionListItemSummary extends SessionRowFields {
|
|
12934
12905
|
root: AgentTaskSummary;
|
|
12935
12906
|
chainTaskCount: number;
|
|
12936
12907
|
lastActivityAt: string;
|
|
12937
12908
|
latestStatus: AgentTaskStatus;
|
|
12938
12909
|
}
|
|
12939
12910
|
|
|
12940
|
-
|
|
12941
|
-
* List the most recent sessions ordered by chain-wide latest activity.
|
|
12942
|
-
* A "session" here is any task with `parentTaskId IS NULL` — its descendants
|
|
12943
|
-
* (children, grand-children, …) are summarized via the recursive CTE.
|
|
12944
|
-
*
|
|
12945
|
-
* Single-pass CTE: seeds with root tasks matching the filter, walks the full
|
|
12946
|
-
* descendant tree once, then aggregates chainCount / lastActivityAt /
|
|
12947
|
-
* latestStatus in two lightweight non-recursive CTEs — replacing the original
|
|
12948
|
-
* pattern of 3 correlated subqueries each re-running the recursion per row.
|
|
12949
|
-
*/
|
|
12950
|
-
interface ListRecentSessionsOpts {
|
|
12911
|
+
interface ListRecentSessionsOpts extends SessionFilters {
|
|
12951
12912
|
limit?: number;
|
|
12952
12913
|
offset?: number;
|
|
12953
|
-
/**
|
|
12954
|
-
source?: string[];
|
|
12955
|
-
/** Case-insensitive substring match against `r.task`. */
|
|
12956
|
-
q?: string;
|
|
12957
|
-
/** When set, restrict to root tasks where `requestedByUserId` equals this value. NULL rows are excluded. */
|
|
12958
|
-
requestedByUserId?: string;
|
|
12959
|
-
/**
|
|
12960
|
-
* When set, restrict to root tasks whose `contextKey` starts with this
|
|
12961
|
-
* literal prefix (`%`, `_` and `\` are escaped). Powers the UI contextual
|
|
12962
|
-
* session panel's per-page dropdown.
|
|
12963
|
-
*/
|
|
12964
|
-
contextKeyPrefix?: string;
|
|
12965
|
-
/** When true, return slim `SessionListItemSummary` rows (default: full). */
|
|
12914
|
+
/** Return a slim root task summary instead of the full task. */
|
|
12966
12915
|
slim?: boolean;
|
|
12967
|
-
/** Restrict to sessions this viewer may open (session sharing). */
|
|
12968
|
-
viewer?: SessionViewer;
|
|
12969
12916
|
}
|
|
12970
12917
|
|
|
12971
12918
|
export async function listRecentSessions(
|
|
@@ -12975,149 +12922,50 @@ export async function listRecentSessions(
|
|
|
12975
12922
|
opts: ListRecentSessionsOpts & { slim: true },
|
|
12976
12923
|
): Promise<SessionListItemSummary[]>;
|
|
12977
12924
|
export async function listRecentSessions(
|
|
12978
|
-
opts
|
|
12925
|
+
opts: ListRecentSessionsOpts = {},
|
|
12979
12926
|
): Promise<SessionListItem[] | SessionListItemSummary[]> {
|
|
12980
|
-
const
|
|
12981
|
-
const offset = opts?.offset ?? 0;
|
|
12982
|
-
const sources = opts?.source?.filter((s) => s.length > 0) ?? [];
|
|
12983
|
-
const q = opts?.q?.trim();
|
|
12984
|
-
const requestedByUserId = opts?.requestedByUserId?.trim() || undefined;
|
|
12985
|
-
|
|
12986
|
-
const conditions: string[] = ["r.parentTaskId IS NULL"];
|
|
12987
|
-
const params: (string | number | null)[] = [];
|
|
12988
|
-
|
|
12989
|
-
if (sources.length > 0) {
|
|
12990
|
-
conditions.push(`r.source IN (${sources.map(() => "?").join(", ")})`);
|
|
12991
|
-
params.push(...sources);
|
|
12992
|
-
}
|
|
12993
|
-
if (q && q.length > 0) {
|
|
12994
|
-
conditions.push("(lower(r.task) LIKE ? OR lower(COALESCE(r.title, '')) LIKE ?)");
|
|
12995
|
-
const like = `%${q.toLowerCase()}%`;
|
|
12996
|
-
params.push(like, like);
|
|
12997
|
-
}
|
|
12998
|
-
if (requestedByUserId) {
|
|
12999
|
-
conditions.push("r.requestedByUserId = ?");
|
|
13000
|
-
params.push(requestedByUserId);
|
|
13001
|
-
}
|
|
13002
|
-
if (opts?.contextKeyPrefix) {
|
|
13003
|
-
conditions.push(`r.contextKey LIKE ? ESCAPE '\\'`);
|
|
13004
|
-
params.push(literalPrefixPattern(opts.contextKeyPrefix));
|
|
13005
|
-
}
|
|
13006
|
-
if (opts?.viewer) {
|
|
13007
|
-
const viewer = sessionViewerCondition(opts.viewer);
|
|
13008
|
-
conditions.push(viewer.sql);
|
|
13009
|
-
params.push(...viewer.params);
|
|
13010
|
-
}
|
|
13011
|
-
params.push(limit, offset);
|
|
13012
|
-
|
|
12927
|
+
const query = sessionSummaryQuery(opts);
|
|
13013
12928
|
const rootRows = await getDbClient().query<
|
|
13014
|
-
AgentTaskRow & {
|
|
12929
|
+
AgentTaskRow & {
|
|
12930
|
+
__chainCount: number;
|
|
12931
|
+
__lastActivityAt: string;
|
|
12932
|
+
__latestStatus: AgentTaskStatus;
|
|
12933
|
+
__readState: SessionReadState | null;
|
|
12934
|
+
__snoozeUntil: string | null;
|
|
12935
|
+
__needsYou: number;
|
|
12936
|
+
}
|
|
13015
12937
|
>(
|
|
13016
|
-
`
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
|
|
13022
|
-
|
|
13023
|
-
|
|
13024
|
-
|
|
13025
|
-
|
|
13026
|
-
|
|
13027
|
-
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
|
|
13034
|
-
|
|
13035
|
-
|
|
13036
|
-
|
|
13037
|
-
|
|
13038
|
-
|
|
13039
|
-
|
|
13040
|
-
|
|
13041
|
-
a.chainCount AS __chainCount,
|
|
13042
|
-
a.lastActivityAt AS __lastActivityAt,
|
|
13043
|
-
COALESCE(ls.latestStatus, r.status) AS __latestStatus
|
|
13044
|
-
FROM agent_tasks r
|
|
13045
|
-
JOIN agg a ON a.root_id = r.id
|
|
13046
|
-
LEFT JOIN latest_status ls ON ls.root_id = r.id
|
|
13047
|
-
ORDER BY a.lastActivityAt DESC, r.createdAt DESC, r.id DESC
|
|
13048
|
-
LIMIT ? OFFSET ?`,
|
|
13049
|
-
params,
|
|
13050
|
-
);
|
|
13051
|
-
|
|
13052
|
-
if (opts?.slim) {
|
|
13053
|
-
return rootRows.map((row): SessionListItemSummary => {
|
|
13054
|
-
const { __chainCount, __lastActivityAt, __latestStatus, ...taskRow } = row;
|
|
13055
|
-
return {
|
|
13056
|
-
root: rowToAgentTaskSummary(taskRow as AgentTaskRow),
|
|
13057
|
-
chainTaskCount: __chainCount,
|
|
13058
|
-
lastActivityAt: __lastActivityAt ?? row.lastUpdatedAt,
|
|
13059
|
-
latestStatus: (__latestStatus as AgentTaskStatus) ?? row.status,
|
|
13060
|
-
};
|
|
13061
|
-
});
|
|
13062
|
-
}
|
|
13063
|
-
|
|
13064
|
-
return rootRows.map((row): SessionListItem => {
|
|
13065
|
-
const { __chainCount, __lastActivityAt, __latestStatus, ...taskRow } = row;
|
|
13066
|
-
return {
|
|
13067
|
-
root: rowToAgentTask(taskRow as AgentTaskRow),
|
|
13068
|
-
chainTaskCount: __chainCount,
|
|
13069
|
-
lastActivityAt: __lastActivityAt ?? row.lastUpdatedAt,
|
|
13070
|
-
latestStatus: (__latestStatus as AgentTaskStatus) ?? row.status,
|
|
13071
|
-
};
|
|
13072
|
-
});
|
|
12938
|
+
`SELECT r.*, a.chainCount AS __chainCount, a.lastActivityAt AS __lastActivityAt,
|
|
12939
|
+
a.latestStatus AS __latestStatus, a.readState AS __readState,
|
|
12940
|
+
a.snoozeUntil AS __snoozeUntil, a.needsYou AS __needsYou
|
|
12941
|
+
FROM (${query.sql}) a CROSS JOIN agent_tasks r ON r.id = a.root_id
|
|
12942
|
+
ORDER BY ${opts.triage === "later" ? "a.snoozeUntil ASC," : ""}
|
|
12943
|
+
a.lastActivityAt DESC, r.createdAt DESC, r.id DESC LIMIT ? OFFSET ?`,
|
|
12944
|
+
[...query.params, opts.limit ?? 25, opts.offset ?? 0],
|
|
12945
|
+
);
|
|
12946
|
+
const fields = await sessionPageFields(
|
|
12947
|
+
rootRows.map((row) => ({
|
|
12948
|
+
id: row.id,
|
|
12949
|
+
requestedByUserId: row.requestedByUserId ?? undefined,
|
|
12950
|
+
})),
|
|
12951
|
+
);
|
|
12952
|
+
return rootRows.map((row) => ({
|
|
12953
|
+
root: opts.slim ? rowToAgentTaskSummary(row) : rowToAgentTask(row),
|
|
12954
|
+
chainTaskCount: row.__chainCount,
|
|
12955
|
+
lastActivityAt: row.__lastActivityAt,
|
|
12956
|
+
latestStatus: row.__latestStatus,
|
|
12957
|
+
...(row.__readState ? { readState: row.__readState } : {}),
|
|
12958
|
+
snoozeUntil: row.__snoozeUntil,
|
|
12959
|
+
needsYou: !!row.__needsYou,
|
|
12960
|
+
groupKey: sessionGroupKey(row.key),
|
|
12961
|
+
...fields.get(row.id),
|
|
12962
|
+
}));
|
|
13073
12963
|
}
|
|
13074
12964
|
|
|
13075
|
-
/**
|
|
13076
|
-
|
|
13077
|
-
|
|
13078
|
-
|
|
13079
|
-
* a plain count, no recursive chain walk needed.
|
|
13080
|
-
*/
|
|
13081
|
-
export async function countSessions(
|
|
13082
|
-
opts?: Pick<
|
|
13083
|
-
ListRecentSessionsOpts,
|
|
13084
|
-
"source" | "q" | "requestedByUserId" | "contextKeyPrefix" | "viewer"
|
|
13085
|
-
>,
|
|
13086
|
-
): Promise<number> {
|
|
13087
|
-
const sources = opts?.source?.filter((s) => s.length > 0) ?? [];
|
|
13088
|
-
const q = opts?.q?.trim();
|
|
13089
|
-
const requestedByUserId = opts?.requestedByUserId?.trim() || undefined;
|
|
13090
|
-
|
|
13091
|
-
const conditions: string[] = ["r.parentTaskId IS NULL"];
|
|
13092
|
-
const params: (string | null)[] = [];
|
|
13093
|
-
|
|
13094
|
-
if (sources.length > 0) {
|
|
13095
|
-
conditions.push(`r.source IN (${sources.map(() => "?").join(", ")})`);
|
|
13096
|
-
params.push(...sources);
|
|
13097
|
-
}
|
|
13098
|
-
if (q && q.length > 0) {
|
|
13099
|
-
conditions.push("(lower(r.task) LIKE ? OR lower(COALESCE(r.title, '')) LIKE ?)");
|
|
13100
|
-
const like = `%${q.toLowerCase()}%`;
|
|
13101
|
-
params.push(like, like);
|
|
13102
|
-
}
|
|
13103
|
-
if (requestedByUserId) {
|
|
13104
|
-
conditions.push("r.requestedByUserId = ?");
|
|
13105
|
-
params.push(requestedByUserId);
|
|
13106
|
-
}
|
|
13107
|
-
if (opts?.contextKeyPrefix) {
|
|
13108
|
-
conditions.push(`r.contextKey LIKE ? ESCAPE '\\'`);
|
|
13109
|
-
params.push(literalPrefixPattern(opts.contextKeyPrefix));
|
|
13110
|
-
}
|
|
13111
|
-
if (opts?.viewer) {
|
|
13112
|
-
const viewer = sessionViewerCondition(opts.viewer);
|
|
13113
|
-
conditions.push(viewer.sql);
|
|
13114
|
-
params.push(...viewer.params);
|
|
13115
|
-
}
|
|
13116
|
-
|
|
13117
|
-
const row = await getDbClient().get<{ count: number }>(
|
|
13118
|
-
`SELECT COUNT(*) AS count FROM agent_tasks r WHERE ${conditions.join(" AND ")}`,
|
|
13119
|
-
params,
|
|
13120
|
-
);
|
|
12965
|
+
/** Count roots directly unless a filter needs chain activity or participants. */
|
|
12966
|
+
export async function countSessions(opts: SessionFilters = {}): Promise<number> {
|
|
12967
|
+
const query = sessionCountQuery(opts);
|
|
12968
|
+
const row = await getDbClient().get<{ count: number }>(query.sql, query.params);
|
|
13121
12969
|
return row?.count ?? 0;
|
|
13122
12970
|
}
|
|
13123
12971
|
|
|
@@ -37,6 +37,12 @@ export interface IndexMemoryContentParams {
|
|
|
37
37
|
* out, the writer has no authority. Throws `MemoryKeyError`.
|
|
38
38
|
*/
|
|
39
39
|
writer?: MemoryKeyWriter;
|
|
40
|
+
/**
|
|
41
|
+
* With `key`: replace this owner's existing document under the key (same
|
|
42
|
+
* scope and source) in the same transaction as the insert, instead of
|
|
43
|
+
* failing on the unique key index. A re-write may change the chunk count.
|
|
44
|
+
*/
|
|
45
|
+
replaceExisting?: boolean;
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
export interface IndexMemoryContentResult {
|
|
@@ -48,6 +54,14 @@ export interface IndexMemoryContentResult {
|
|
|
48
54
|
chunks: number;
|
|
49
55
|
}
|
|
50
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Key shared by every chunk of one task's completion memory, so the chunks
|
|
59
|
+
* group as one document (access counting, chunk listing, search collapse).
|
|
60
|
+
*/
|
|
61
|
+
export function taskCompletionMemoryKey(taskId: string): string {
|
|
62
|
+
return `/task-completions/${taskId.toLowerCase().replace(/[^a-z0-9._-]/g, "-")}`;
|
|
63
|
+
}
|
|
64
|
+
|
|
51
65
|
export async function indexMemoryContent(
|
|
52
66
|
params: IndexMemoryContentParams,
|
|
53
67
|
): Promise<IndexMemoryContentResult> {
|
|
@@ -111,23 +125,28 @@ export async function indexMemoryContent(
|
|
|
111
125
|
}
|
|
112
126
|
|
|
113
127
|
// Atomic batch insert: all chunks or none
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
128
|
+
const inputs = contentChunks.map((chunk) => ({
|
|
129
|
+
agentId: agentId || null,
|
|
130
|
+
content: chunk.content,
|
|
131
|
+
name,
|
|
132
|
+
scope,
|
|
133
|
+
source,
|
|
134
|
+
sourcePath: sourcePath || null,
|
|
135
|
+
sourceTaskId: sourceTaskId || null,
|
|
136
|
+
chunkIndex: chunk.chunkIndex,
|
|
137
|
+
totalChunks: chunk.totalChunks,
|
|
138
|
+
tags: tags || [],
|
|
139
|
+
contextKey: params.contextKey ?? null,
|
|
140
|
+
intent: params.intent ?? "index memory content",
|
|
141
|
+
key: rowKey,
|
|
142
|
+
}));
|
|
143
|
+
const memories =
|
|
144
|
+
params.replaceExisting && params.key
|
|
145
|
+
? await store.replaceDocument(
|
|
146
|
+
{ key: params.key, scope, agentId: agentId || null, source },
|
|
147
|
+
inputs,
|
|
148
|
+
)
|
|
149
|
+
: await store.storeBatch(inputs);
|
|
131
150
|
|
|
132
151
|
// Resolve and store deterministic links (wikilinks, PR refs, agent-fs paths)
|
|
133
152
|
if (agentId) {
|