@desplega.ai/agent-swarm 2.4.5 → 2.5.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 +4 -2
- package/dist/{acp-adapter-2wdkktv6.js → acp-adapter-7g6bpwbk.js} +8 -6
- package/dist/{actions-c40ebcm4.js → actions-w8xd014k.js} +23 -21
- package/dist/{amp-adapter-wb67m95z.js → amp-adapter-z4qvhacj.js} +2 -2
- package/dist/{anthropic-messages-g6pqmqk4.js → anthropic-messages-txs190dd.js} +17 -20
- package/dist/{app-353vre8g.js → app-nndcvftq.js} +3 -3
- package/dist/{assistant-sj1njh23.js → assistant-hjmqyscx.js} +24 -22
- package/dist/{azure-openai-responses-9dbmj346.js → azure-openai-responses-9kfwhmn7.js} +18 -13
- package/dist/{boot-reembed-b9c3az3c.js → boot-reembed-r8rhf9h8.js} +1 -1
- package/dist/{boot-reembed-qdkvxeem.js → boot-reembed-vwcj2y5d.js} +1 -1
- package/dist/{boot-scrub-sweep-m3wh8eks.js → boot-scrub-sweep-fr9q36ne.js} +4 -4
- package/dist/{boot-seeds-j2273s54.js → boot-seeds-9jqwnegq.js} +4 -4
- package/dist/{claude-adapter-m7q0a085.js → claude-adapter-2f8b85df.js} +8 -6
- package/dist/{claude-managed-adapter-5ptb6tzs.js → claude-managed-adapter-gt6pa35d.js} +2 -2
- package/dist/{claude-managed-setup-smrqk5j5.js → claude-managed-setup-c3hp36ph.js} +4 -4
- package/dist/{claude-sdk-session-38xnz21e.js → claude-sdk-session-05kat8rv.js} +9012 -8928
- package/dist/{cli-b9fcxxev.js → cli-007cnhm1.js} +50 -4
- package/dist/{cli-j4rqdf2n.js → cli-03vpq45j.js} +2 -2
- package/dist/{cli-1sp861s4.js → cli-0jy85zz4.js} +11 -11
- package/dist/{cli-j99azg3g.js → cli-1dp1zj04.js} +5 -5
- package/dist/{cli-3r8samv3.js → cli-1f0gp9vz.js} +3 -2
- package/dist/{cli-94gwyg7m.js → cli-22rmcjkg.js} +9 -9
- package/dist/{cli-ms85309d.js → cli-2jg61wab.js} +11 -11
- package/dist/{cli-0bqteszy.js → cli-2nf3b08t.js} +328 -25
- package/dist/{cli-9yqgm9nd.js → cli-2wba1ac9.js} +161 -63
- package/dist/{cli-cxxe61f6.js → cli-3ee5z0q0.js} +2 -2
- package/dist/{cli-k8g16gz3.js → cli-3qv8naq8.js} +115 -119
- package/dist/{cli-60cgh1rv.js → cli-459fk97x.js} +7 -7
- package/dist/{cli-h7gc0b4r.js → cli-5m84zd2k.js} +55 -18
- package/dist/{cli-dvkmp9bt.js → cli-6ctwrf1z.js} +20 -10
- package/dist/{cli-848hxdwj.js → cli-6rg2jn2y.js} +2 -1
- package/dist/{cli-dk44dxec.js → cli-9mm5ade4.js} +1 -1
- package/dist/{cli-7c9qs530.js → cli-ajqhxtnz.js} +5 -5
- package/dist/{cli-be2161h1.js → cli-cah5detr.js} +6 -6
- package/dist/{cli-v8fjakwf.js → cli-cwyafhw1.js} +1 -1
- 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-37j04k05.js → cli-e9btqw4y.js} +13 -13
- package/dist/{cli-1syn2xy1.js → cli-eym3jg7w.js} +32 -18
- package/dist/{cli-ftc1g5tj.js → cli-fes51ya2.js} +3 -3
- package/dist/{cli-s95dknxh.js → cli-g1cw7xtt.js} +1 -1
- package/dist/{cli-74c1wpm0.js → cli-gpv60278.js} +1 -1
- package/dist/{cli-1f3qzw6y.js → cli-gwcf52gz.js} +2 -2
- package/dist/{cli-pemywhfq.js → cli-ha9rmwgq.js} +2 -1
- package/dist/{cli-v0yrfmdh.js → cli-hadv0725.js} +3 -3
- package/dist/{cli-g35m2xwm.js → cli-j1eghqfm.js} +2 -2
- package/dist/{cli-qfxc84gh.js → cli-jpxsrxcb.js} +1 -1
- package/dist/{cli-n72rg53p.js → cli-kcsd1ez8.js} +848 -426
- package/dist/{cli-ejs3m1sx.js → cli-kxpfx2xr.js} +1 -1
- package/dist/{cli-pnp2j5zg.js → cli-mmhj8vd7.js} +2 -2
- package/dist/{cli-st8aw1m6.js → cli-mq7kg1b1.js} +4 -4
- package/dist/{cli-bnes4z6b.js → cli-mz2ygeyq.js} +3 -3
- package/dist/{cli-xf234ws8.js → cli-n4c8e3s5.js} +2 -0
- package/dist/{cli-f01h25yt.js → cli-n6kmqngw.js} +2 -2
- package/dist/cli-nj12tn2c.js +1193 -0
- 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-xpa64rek.js → cli-pyy4c9ch.js} +2362 -159
- package/dist/{cli-wt0jf9hm.js → cli-q9pzwxvk.js} +553 -193
- package/dist/{cli-z7d29rw9.js → cli-qfjm4gvt.js} +4 -4
- package/dist/{cli-p14m2cnp.js → cli-qfm6my86.js} +1 -1
- package/dist/{cli-8nyhf7za.js → cli-qqzmjxkf.js} +129 -105
- package/dist/{cli-4zfqgjc5.js → cli-r9fy0ddc.js} +2 -2
- package/dist/{cli-eww120g8.js → cli-rh5smt8t.js} +18 -4
- package/dist/{cli-a92r1127.js → cli-rngde2jv.js} +2 -2
- package/dist/{cli-qwkcwjdn.js → cli-rycdaj0a.js} +1 -1
- package/dist/{cli-fv5hepyy.js → cli-sn1vbtg2.js} +3 -3
- package/dist/{cli-36ckw0wx.js → cli-stxdrqs2.js} +2 -2
- package/dist/{cli-1m17dc9d.js → cli-ta8bd7th.js} +2 -2
- package/dist/{cli-43x64hv3.js → cli-v2g93k4v.js} +4 -4
- package/dist/{cli-d2mb5s8a.js → cli-x77gen2p.js} +680 -440
- package/dist/{cli-3a45zcgm.js → cli-xc65x52q.js} +2 -2
- package/dist/{cli-f0g3pgvf.js → cli-xd4eqtr2.js} +2 -2
- package/dist/{cli-018r4jq6.js → cli-y3zyaee5.js} +8 -8
- package/dist/{cli-kpw04va0.js → cli-z2dv25mf.js} +1 -1
- package/dist/{cli-qwhy2qma.js → cli-z63a269p.js} +2 -2
- package/dist/{cli-sm8rses9.js → cli-zfdp01hn.js} +8 -5
- package/dist/{cli-tw4p90jb.js → cli-znvq0k3t.js} +5 -5
- package/dist/cli.js +29 -27
- package/dist/{cloudflare-workers-ai-system-one-ch2wxfcp.js → cloudflare-workers-ai-system-one-43v9qkjk.js} +7 -2
- package/dist/{codex-adapter-tn6k5mkg.js → codex-adapter-p4ptwar5.js} +6 -4
- package/dist/{codex-login-m819c41r.js → codex-login-rn7c5gxt.js} +1 -1
- package/dist/{codex-session-runner-7vjt7jbw.js → codex-session-runner-964c7dnk.js} +7 -5
- package/dist/{commands-t7rz9146.js → commands-mbvhbrcy.js} +2 -2
- package/dist/{controller-m2jasma5.js → controller-gnq1k1mf.js} +4 -4
- package/dist/{controllers-connect-9ftpex99.js → controllers-connect-6dkm71tg.js} +25 -23
- package/dist/{cursor-adapter-mjv79e4z.js → cursor-adapter-yq5xgfcg.js} +1 -1
- package/dist/{db-6sfrn9g3.js → db-88wcymxt.js} +14 -2
- package/dist/{db-rn673r06.js → db-af9y8nkf.js} +3 -3
- package/dist/{devin-adapter-zgqadvnm.js → devin-adapter-4ycy4vrf.js} +1 -1
- package/dist/{dispatcher-c155xz0p.js → dispatcher-606ydx5v.js} +22 -20
- package/dist/{docker-fkgtr75t.js → docker-nfy2gc8t.js} +2 -2
- package/dist/{dsh-adapter-3mmszc1x.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-35k6tkv8.js → external-channel-y8q5z8z2.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-tfrq7tg1.js → grok-adapter-39aha52t.js} +9 -7
- package/dist/handlers-rk9dqech.js +41 -0
- package/dist/{heartbeat-dyg4npkp.js → heartbeat-jfe9zfjr.js} +25 -23
- package/dist/{hook-drspbwpe.js → hook-b1mez1m8.js} +9 -7
- package/dist/{hook-x26b31bg.js → hook-ffevzed1.js} +7 -5
- package/dist/{http-pk972xyw.js → http-d5b44f1r.js} +544 -76
- package/dist/{index-g6tbb6ve.js → index-31ceyf42.js} +1 -1
- package/dist/index-4q3vj1yr.js +46 -0
- package/dist/{index-arytgj5q.js → index-5en23s5z.js} +1 -1
- package/dist/index-d2qeem97.js +42 -0
- package/dist/index-mj46rk9k.js +43 -0
- package/dist/{index-jwxkkex2.js → index-nq8hhv28.js} +13 -11
- package/dist/{index-g216q6jr.js → index-zsyx51ap.js} +1 -4
- package/dist/{keepalive-7yrng7px.js → keepalive-wsby1btq.js} +4 -4
- package/dist/lead-paa141j6.js +79 -0
- package/dist/{llama-cpp-classify-vv43gswy.js → llama-cpp-classify-ee7vmd7q.js} +4 -1
- package/dist/{maintenance-e6cemdqt.js → maintenance-vnshcyv9.js} +1 -1
- package/dist/{mistral-conversations-1medfwv7.js → mistral-conversations-sd0xf1tn.js} +13 -13
- package/dist/{node-de6akczr.js → node-jzjj7r9x.js} +1 -1
- package/dist/{oauth-refresh-sweep-yw3xdbcj.js → oauth-refresh-sweep-d6sqn5np.js} +3 -3
- package/dist/{onboard-0a9y5yrc.js → onboard-nr4xhpzy.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-trjpkfb7.js → otel-impl-ytn9wyv9.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-d2b5my0y.js → pricing-refresh-pva04zee.js} +3 -3
- package/dist/{rbac-roles-nxh5ahwk.js → rbac-roles-7rc1q3g4.js} +1 -1
- package/dist/{rbac-roles-hey3yv9d.js → rbac-roles-ff1ffmec.js} +2 -2
- package/dist/{render-v2-rr3p2atg.js → render-v2-pyfsg9zk.js} +3 -3
- package/dist/{resume-2efkf1s1.js → resume-phj8xhqr.js} +10 -8
- package/dist/{runtime-xe3aqy4x.js → runtime-bt5pkpm1.js} +1 -1
- package/dist/{session-access-s2mttxpw.js → session-access-jzx2z9h5.js} +6 -4
- package/dist/{setup-vypma5yt.js → setup-rfg0f0sg.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-rvhckdkp.js → work-objects-44z2yjg8.js} +25 -23
- package/dist/worker-zsfqzxhm.js +79 -0
- package/dist/{x-y45mthwn.js → x-pbpezr0s.js} +2 -2
- package/openapi.json +785 -5
- package/package.json +9 -9
- package/src/assets/key.ts +17 -0
- package/src/azure-devops/handlers.ts +1 -1
- 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/read.ts +40 -4
- package/src/be/db/workflow-runs.ts +96 -0
- package/src/be/db.ts +80 -236
- package/src/be/onboarding.ts +3 -0
- package/src/be/skill-sync.ts +43 -2
- package/src/be/swarm-config-guard.ts +1 -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/contract-types.generated.ts +1 -1
- package/src/extensions/contract.ts +2 -2
- package/src/extensions/post-bridge.ts +1 -0
- package/src/github/handlers.ts +6 -6
- package/src/gitlab/auth.ts +8 -2
- package/src/gitlab/handlers.ts +63 -15
- package/src/gitlab/index.ts +1 -1
- package/src/http/assets.ts +14 -2
- package/src/http/core.ts +12 -0
- package/src/http/index.ts +4 -0
- package/src/http/onboarding.ts +1 -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 +1 -0
- package/src/http/webhooks.ts +141 -0
- package/src/integrations/chat-sdk/adapters.ts +19 -3
- package/src/integrations/chat-sdk/facts.ts +30 -12
- package/src/integrations/chat-sdk/outbound.ts +38 -1
- package/src/providers/acp-targets.ts +1 -1
- package/src/providers/amp-adapter.ts +1 -1
- package/src/providers/pi-mono-adapter.ts +5 -53
- package/src/scripts-runtime/types/swarm-extension.d.ts +6 -4
- package/src/slack/handlers.test.ts +158 -0
- package/src/slack/handlers.ts +19 -28
- package/src/tasks/context-key.ts +61 -1
- 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-inbound.test.ts +39 -0
- package/src/tests/chat-sdk-telegram-markdown.test.ts +92 -0
- package/src/tests/context-key.test.ts +50 -0
- package/src/tests/core-auth.test.ts +5 -0
- 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/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-auth.test.ts +13 -5
- package/src/tests/gitlab-handlers.test.ts +273 -25
- package/src/tests/gitlab-vcs-db.test.ts +4 -4
- package/src/tests/integration-disable-flags.test.ts +36 -0
- package/src/tests/mcp-tools.test.ts +1 -1
- package/src/tests/onboarding.test.ts +12 -0
- 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/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/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 +2 -1
- 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-tla-races.test.ts +2 -2
- package/src/tools/script-delete.ts +1 -1
- package/src/tools/workflows/create-workflow.ts +5 -3
- package/src/types.ts +3 -2
- package/src/utils/config-env-export.ts +1 -0
- package/src/utils/secret-scrubber.ts +4 -0
- package/src/utils/skills-refresh.ts +83 -43
- 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/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/skills/slack-interaction/content.md +5 -0
- package/templates/skills/work-on-task/SKILL.md +1 -1
- package/templates/skills/work-on-task/content.md +1 -1
- package/dist/cli-9hstj09h.js +0 -2657
- package/dist/cli-yw91rnmw.js +0 -13
- package/dist/handlers-7gw64dxw.js +0 -39
- package/dist/index-bgdyvcnv.js +0 -40
- package/dist/index-gabbcdn2.js +0 -43
- package/dist/index-tfb26zhy.js +0 -41
- package/dist/lead-7e02z839.js +0 -77
- package/dist/worker-5snytpbd.js +0 -77
package/src/gitlab/handlers.ts
CHANGED
|
@@ -8,13 +8,21 @@
|
|
|
8
8
|
* - Detects bot mentions
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
failTask,
|
|
13
|
+
findActiveTasksByVcs,
|
|
14
|
+
findTaskByVcs,
|
|
15
|
+
getAllAgents,
|
|
16
|
+
incrKv,
|
|
17
|
+
upsertKv,
|
|
18
|
+
} from "../be/db";
|
|
12
19
|
import { renderIdentity, resolveIdentity } from "../be/identity";
|
|
13
20
|
import { findOrCreateUserByEmail, findUserByExternalId, linkIdentity } from "../be/users";
|
|
14
21
|
import { resolveTemplate } from "../prompts/resolver";
|
|
15
22
|
import { gitlabContextKey } from "../tasks/context-key";
|
|
16
23
|
import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
|
|
17
|
-
import {
|
|
24
|
+
import type { AgentTask } from "../types";
|
|
25
|
+
import { getGitLabBotName } from "./auth";
|
|
18
26
|
import { addGitLabNoteReaction, addGitLabReaction } from "./reactions";
|
|
19
27
|
import type { GitLabUser } from "./types";
|
|
20
28
|
// Side-effect import: registers all GitLab event templates in the in-memory registry
|
|
@@ -40,11 +48,37 @@ function isDuplicate(key: string): boolean {
|
|
|
40
48
|
|
|
41
49
|
function detectMention(text: string | null | undefined): boolean {
|
|
42
50
|
if (!text) return false;
|
|
43
|
-
return new RegExp(`@${
|
|
51
|
+
return new RegExp(`@${getGitLabBotName()}\\b`, "i").test(text);
|
|
44
52
|
}
|
|
45
53
|
|
|
46
54
|
function extractMentionContext(text: string): string {
|
|
47
|
-
return text.replace(new RegExp(`@${
|
|
55
|
+
return text.replace(new RegExp(`@${getGitLabBotName()}\\b`, "gi"), "").trim();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Legacy rows written before contextKey existed: scoped only on positive evidence.
|
|
59
|
+
const LEGACY_SCOPE = {
|
|
60
|
+
mr: {
|
|
61
|
+
taskTypes: new Set(["gitlab-mr", "gitlab-ci"]),
|
|
62
|
+
eventTypes: new Set(["merge_request", "note_on_mr", "pipeline"]),
|
|
63
|
+
},
|
|
64
|
+
issue: {
|
|
65
|
+
taskTypes: new Set(["gitlab-issue"]),
|
|
66
|
+
eventTypes: new Set(["issue", "note_on_issue"]),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* GitLab issue and MR iids are separate per-project sequences, so a vcsNumber
|
|
72
|
+
* match alone hits both issue #N and MR !N. Match on the contextKey instead; a
|
|
73
|
+
* row without one counts only when its taskType or vcsEventType names the kind.
|
|
74
|
+
*/
|
|
75
|
+
function isScopedTask(task: AgentTask, kind: "mr" | "issue", contextKey: string): boolean {
|
|
76
|
+
if (task.contextKey) return task.contextKey === contextKey;
|
|
77
|
+
const legacy = LEGACY_SCOPE[kind];
|
|
78
|
+
return (
|
|
79
|
+
(task.taskType !== undefined && legacy.taskTypes.has(task.taskType)) ||
|
|
80
|
+
(task.vcsEventType !== undefined && legacy.eventTypes.has(task.vcsEventType))
|
|
81
|
+
);
|
|
48
82
|
}
|
|
49
83
|
|
|
50
84
|
async function findLeadAgent() {
|
|
@@ -206,19 +240,25 @@ export async function handleMergeRequest(
|
|
|
206
240
|
|
|
207
241
|
case "close":
|
|
208
242
|
case "merge": {
|
|
209
|
-
//
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
243
|
+
// Every active task, not only the newest: a note task is a child of the
|
|
244
|
+
// MR task, and failTask does not cascade up to the parent.
|
|
245
|
+
const reason = action === "merge" ? "MR was merged" : "MR was closed";
|
|
246
|
+
const mrContextKey = gitlabContextKey({
|
|
247
|
+
projectId: String(project.id),
|
|
248
|
+
kind: "mr",
|
|
249
|
+
iid: mr.iid,
|
|
250
|
+
});
|
|
251
|
+
const tasks = await findActiveTasksByVcs(repo, mr.iid, "gitlab");
|
|
252
|
+
for (const task of tasks.filter((t) => isScopedTask(t, "mr", mrContextKey))) {
|
|
253
|
+
console.log(`[GitLab] Cancelling task ${task.id} — ${reason}`);
|
|
254
|
+
await failTask(task.id, reason);
|
|
215
255
|
}
|
|
216
256
|
return { created: false };
|
|
217
257
|
}
|
|
218
258
|
|
|
219
259
|
case "update": {
|
|
220
260
|
// Check if there's an active task for this MR — if so, notify about the update
|
|
221
|
-
const task = await findTaskByVcs(repo, mr.iid);
|
|
261
|
+
const task = await findTaskByVcs(repo, mr.iid, "gitlab");
|
|
222
262
|
if (task) {
|
|
223
263
|
console.log(`[GitLab] MR #${mr.iid} updated, active task exists: ${task.id}`);
|
|
224
264
|
// Don't create a new task — the worker will see the changes
|
|
@@ -262,7 +302,7 @@ export async function handleIssue(
|
|
|
262
302
|
if (!hasMention) {
|
|
263
303
|
// Check if bot is in assignees
|
|
264
304
|
const isBotAssigned = event.assignees?.some(
|
|
265
|
-
(a) => a.username.toLowerCase() ===
|
|
305
|
+
(a) => a.username.toLowerCase() === getGitLabBotName().toLowerCase(),
|
|
266
306
|
);
|
|
267
307
|
if (!isBotAssigned) {
|
|
268
308
|
console.log(`[GitLab] Issue opened without bot mention/assignment, skipping`);
|
|
@@ -318,7 +358,15 @@ export async function handleIssue(
|
|
|
318
358
|
}
|
|
319
359
|
|
|
320
360
|
case "close": {
|
|
321
|
-
const
|
|
361
|
+
const issueContextKey = gitlabContextKey({
|
|
362
|
+
projectId: String(project.id),
|
|
363
|
+
kind: "issue",
|
|
364
|
+
iid: issue.iid,
|
|
365
|
+
});
|
|
366
|
+
// Newest issue-scoped task only; MR !N shares the iid but not the issue.
|
|
367
|
+
const existingTask = (await findActiveTasksByVcs(repo, issue.iid, "gitlab")).find((t) =>
|
|
368
|
+
isScopedTask(t, "issue", issueContextKey),
|
|
369
|
+
);
|
|
322
370
|
if (existingTask) {
|
|
323
371
|
console.log(`[GitLab] Cancelling task ${existingTask.id} — issue closed`);
|
|
324
372
|
await failTask(existingTask.id, "Issue was closed");
|
|
@@ -375,7 +423,7 @@ export async function handleNote(event: NoteEvent): Promise<{ created: boolean;
|
|
|
375
423
|
}
|
|
376
424
|
|
|
377
425
|
// Check if there's already an active task for this entity
|
|
378
|
-
const existingTask = targetNumber ? await findTaskByVcs(repo, targetNumber) : null;
|
|
426
|
+
const existingTask = targetNumber ? await findTaskByVcs(repo, targetNumber, "gitlab") : null;
|
|
379
427
|
|
|
380
428
|
const existingTaskNote = existingTask
|
|
381
429
|
? `\n\n_Note: There's an active task (${existingTask.id}) for this ${entityLabel}._`
|
|
@@ -462,7 +510,7 @@ export async function handlePipeline(
|
|
|
462
510
|
}
|
|
463
511
|
|
|
464
512
|
// Only create task if there's already an active task for this MR
|
|
465
|
-
const existingTask = await findTaskByVcs(repo, mrIid);
|
|
513
|
+
const existingTask = await findTaskByVcs(repo, mrIid, "gitlab");
|
|
466
514
|
if (!existingTask) {
|
|
467
515
|
return { created: false };
|
|
468
516
|
}
|
package/src/gitlab/index.ts
CHANGED
package/src/http/assets.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { auditAssetKeys } from "../be/asset-key-audit";
|
|
|
5
5
|
import { AssetKeyAuthorizationError, authorizeAssetKeyWrite } from "../be/asset-key-auth";
|
|
6
6
|
import { resolveHttpAuditUserId } from "../be/audit-user";
|
|
7
7
|
import {
|
|
8
|
+
AssetKeyMovesBlockedError,
|
|
8
9
|
getDb,
|
|
9
10
|
getDbClient,
|
|
10
11
|
getRootTaskChain,
|
|
@@ -25,6 +26,7 @@ import {
|
|
|
25
26
|
import { getRequestAuth } from "../utils/request-auth-context";
|
|
26
27
|
import { requestPrincipal } from "./request-principal";
|
|
27
28
|
import { route } from "./route-def";
|
|
29
|
+
import { canReadSession, hasSessionWrite, SESSION_READ_DENIED } from "./session-access";
|
|
28
30
|
import { jsonError } from "./utils";
|
|
29
31
|
|
|
30
32
|
const AssetKeyAuditIssueSchema = z.object({
|
|
@@ -184,7 +186,7 @@ const moveAssetRoute = route({
|
|
|
184
186
|
},
|
|
185
187
|
});
|
|
186
188
|
|
|
187
|
-
async function canMutateTaskNamespace(
|
|
189
|
+
export async function canMutateTaskNamespace(
|
|
188
190
|
task: { id: string; agentId: string | null; creatorAgentId?: string },
|
|
189
191
|
myAgentId: string | undefined,
|
|
190
192
|
req: IncomingMessage,
|
|
@@ -322,6 +324,16 @@ export async function handleAssets(
|
|
|
322
324
|
jsonError(res, "Asset not found", 404);
|
|
323
325
|
return true;
|
|
324
326
|
}
|
|
327
|
+
if (!(await hasSessionWrite(req, myAgentId, task.id))) {
|
|
328
|
+
jsonError(
|
|
329
|
+
res,
|
|
330
|
+
(await canReadSession(req, myAgentId, task.id))
|
|
331
|
+
? "You can view this session but not move it."
|
|
332
|
+
: SESSION_READ_DENIED,
|
|
333
|
+
403,
|
|
334
|
+
);
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
325
337
|
// Only the tasks checked here move: a subtask created after this read stays put.
|
|
326
338
|
const tasks = parsed.body.cascade ? await getRootTaskChain(task.id) : [task];
|
|
327
339
|
for (const target of tasks) {
|
|
@@ -382,7 +394,7 @@ export async function handleAssets(
|
|
|
382
394
|
return true;
|
|
383
395
|
}
|
|
384
396
|
const message = error instanceof Error ? error.message : String(error);
|
|
385
|
-
jsonError(res, message,
|
|
397
|
+
jsonError(res, message, error instanceof AssetKeyMovesBlockedError ? 409 : 400);
|
|
386
398
|
}
|
|
387
399
|
return true;
|
|
388
400
|
}
|
package/src/http/core.ts
CHANGED
|
@@ -29,6 +29,12 @@ import {
|
|
|
29
29
|
import { enqueueAdmissionRow } from "../be/rbac-audit";
|
|
30
30
|
import { getUserGrant } from "../be/rbac-roles";
|
|
31
31
|
import { syncTelemetryEnabled } from "../be/telemetry-enable";
|
|
32
|
+
import {
|
|
33
|
+
initBitbucket,
|
|
34
|
+
isBitbucketEnabled,
|
|
35
|
+
resetBitbucket,
|
|
36
|
+
resetBitbucketBotCache,
|
|
37
|
+
} from "../bitbucket";
|
|
32
38
|
import { initGitHub, resetGitHub } from "../github";
|
|
33
39
|
import { initGitLab, isGitLabEnabled, resetGitLab } from "../gitlab";
|
|
34
40
|
import { restartChatSdkIfConfigChanged } from "../integrations/chat-sdk/runtime";
|
|
@@ -248,6 +254,12 @@ async function reloadGlobalConfigsAndIntegrationsInner(): Promise<ReloadConfigRe
|
|
|
248
254
|
teardownAzureDevOpsOutbound();
|
|
249
255
|
if (isAzureDevOpsEnabled()) initAzureDevOpsOutbound();
|
|
250
256
|
|
|
257
|
+
// Same reset-then-init: the webhook secret and bot account id are cached.
|
|
258
|
+
resetBitbucket();
|
|
259
|
+
resetBitbucketBotCache();
|
|
260
|
+
initBitbucket();
|
|
261
|
+
if (isBitbucketEnabled()) integrations.push("bitbucket");
|
|
262
|
+
|
|
251
263
|
resetLinear();
|
|
252
264
|
if (await initLinear()) integrations.push("linear");
|
|
253
265
|
|
package/src/http/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ import { loadSecretRegistry } from "../be/secret-registry";
|
|
|
33
33
|
import { seedLegacyCapabilitiesConfig } from "../be/seed-capabilities";
|
|
34
34
|
import { initApiTelemetry } from "../be/telemetry-enable";
|
|
35
35
|
import { startWorkerNudgeListener } from "../be/worker-nudge-listener";
|
|
36
|
+
import { initBitbucket } from "../bitbucket";
|
|
36
37
|
import {
|
|
37
38
|
loadEnabledExtensions,
|
|
38
39
|
setExtensionLoopbackBaseUrl,
|
|
@@ -798,6 +799,9 @@ httpServer
|
|
|
798
799
|
initAzureDevOps();
|
|
799
800
|
initAzureDevOpsOutbound();
|
|
800
801
|
|
|
802
|
+
// Initialize Bitbucket Cloud webhook handler (if configured)
|
|
803
|
+
initBitbucket();
|
|
804
|
+
|
|
801
805
|
// Initialize AgentMail webhook handler (if configured)
|
|
802
806
|
initAgentMail();
|
|
803
807
|
|
package/src/http/onboarding.ts
CHANGED
|
@@ -58,6 +58,7 @@ async function buildSignals(state: OnboardingState): Promise<OnboardingSignals>
|
|
|
58
58
|
slack: integrations.slack === "configured",
|
|
59
59
|
github: Boolean(process.env.GITHUB_TOKEN?.trim()) || integrations.github === "verified",
|
|
60
60
|
gitlab: Boolean(process.env.GITLAB_TOKEN?.trim()),
|
|
61
|
+
bitbucket: Boolean(process.env.BITBUCKET_TOKEN?.trim()),
|
|
61
62
|
linear: integrations.linear === "verified",
|
|
62
63
|
jira: integrations.jira === "verified",
|
|
63
64
|
},
|