@desplega.ai/agent-swarm 2.4.5 → 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-2wdkktv6.js → acp-adapter-11gp67nr.js} +8 -6
- package/dist/{actions-c40ebcm4.js → actions-8p2kze8j.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-0qp0a2gk.js} +3 -3
- package/dist/{assistant-sj1njh23.js → assistant-jedd3ktm.js} +24 -22
- package/dist/{azure-openai-responses-9dbmj346.js → azure-openai-responses-9kfwhmn7.js} +18 -13
- package/dist/{boot-reembed-qdkvxeem.js → boot-reembed-4xwq5tg0.js} +1 -1
- package/dist/{boot-reembed-b9c3az3c.js → boot-reembed-n4wq5dd2.js} +1 -1
- package/dist/{boot-scrub-sweep-m3wh8eks.js → boot-scrub-sweep-69h90xcq.js} +4 -4
- package/dist/{boot-seeds-j2273s54.js → boot-seeds-3vn0m9sg.js} +4 -4
- package/dist/{claude-adapter-m7q0a085.js → claude-adapter-221mvad5.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-8thjsk5e.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-dk44dxec.js → cli-0y6f0ckq.js} +1 -1
- package/dist/{cli-kpw04va0.js → cli-0z3vjrpm.js} +1 -1
- package/dist/{cli-94gwyg7m.js → cli-179xcyky.js} +9 -9
- package/dist/{cli-3r8samv3.js → cli-1f0gp9vz.js} +3 -2
- package/dist/{cli-4zfqgjc5.js → cli-1pr672hz.js} +2 -2
- package/dist/{cli-0bqteszy.js → cli-2nf3b08t.js} +328 -25
- package/dist/{cli-43x64hv3.js → cli-36j4jnk3.js} +4 -4
- package/dist/{cli-k8g16gz3.js → cli-3qv8naq8.js} +115 -119
- package/dist/cli-3zwye9sn.js +1193 -0
- package/dist/{cli-60cgh1rv.js → cli-459fk97x.js} +7 -7
- package/dist/{cli-v8fjakwf.js → cli-4w24f7z3.js} +1 -1
- package/dist/{cli-n72rg53p.js → cli-5kzk3472.js} +812 -418
- package/dist/{cli-h7gc0b4r.js → cli-5m84zd2k.js} +55 -18
- package/dist/{cli-j99azg3g.js → cli-5rvg1ddk.js} +5 -5
- package/dist/{cli-dvkmp9bt.js → cli-6ctwrf1z.js} +20 -10
- package/dist/{cli-848hxdwj.js → cli-6rg2jn2y.js} +2 -1
- package/dist/{cli-fv5hepyy.js → cli-7bwtc6yx.js} +3 -3
- package/dist/{cli-ms85309d.js → cli-7g40g8hq.js} +11 -11
- package/dist/{cli-xpa64rek.js → cli-92mqenkc.js} +2362 -159
- package/dist/{cli-018r4jq6.js → cli-9ce2xw98.js} +8 -8
- package/dist/{cli-1syn2xy1.js → cli-bgdtv62r.js} +32 -18
- 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-wt0jf9hm.js → cli-fcc5qe3f.js} +553 -193
- package/dist/{cli-ftc1g5tj.js → cli-fes51ya2.js} +3 -3
- package/dist/{cli-3a45zcgm.js → cli-ftmq4nvk.js} +2 -2
- package/dist/{cli-37j04k05.js → cli-fy1jyyym.js} +13 -13
- package/dist/{cli-s95dknxh.js → cli-g1cw7xtt.js} +1 -1
- package/dist/{cli-74c1wpm0.js → cli-gpv60278.js} +1 -1
- package/dist/{cli-pemywhfq.js → cli-ha9rmwgq.js} +2 -1
- package/dist/{cli-g35m2xwm.js → cli-j1eghqfm.js} +2 -2
- package/dist/{cli-qfxc84gh.js → cli-jpxsrxcb.js} +1 -1
- package/dist/{cli-ejs3m1sx.js → cli-kxpfx2xr.js} +1 -1
- package/dist/{cli-p14m2cnp.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-f01h25yt.js → cli-n6kmqngw.js} +2 -2
- package/dist/{cli-v0yrfmdh.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-9yqgm9nd.js → cli-r25qpaxt.js} +161 -63
- package/dist/{cli-eww120g8.js → cli-rh5smt8t.js} +18 -4
- package/dist/{cli-qwkcwjdn.js → cli-rycdaj0a.js} +1 -1
- package/dist/{cli-a92r1127.js → cli-s4sntwt4.js} +2 -2
- package/dist/{cli-be2161h1.js → cli-segs7hx9.js} +6 -6
- package/dist/{cli-36ckw0wx.js → cli-stxdrqs2.js} +2 -2
- package/dist/{cli-z7d29rw9.js → cli-sy8f9705.js} +4 -4
- package/dist/{cli-1m17dc9d.js → cli-ta8bd7th.js} +2 -2
- package/dist/{cli-st8aw1m6.js → cli-we0ra057.js} +4 -4
- package/dist/{cli-7c9qs530.js → cli-x21dqn18.js} +5 -5
- package/dist/{cli-1sp861s4.js → cli-x6vf4sad.js} +11 -11
- package/dist/{cli-d2mb5s8a.js → cli-x77gen2p.js} +680 -440
- package/dist/{cli-tw4p90jb.js → cli-xawhpgc9.js} +5 -5
- package/dist/{cli-f0g3pgvf.js → cli-xd4eqtr2.js} +2 -2
- package/dist/{cli-1f3qzw6y.js → cli-xt768r5m.js} +2 -2
- package/dist/{cli-cxxe61f6.js → cli-y4x8ww6s.js} +2 -2
- package/dist/{cli-bnes4z6b.js → cli-y9jvxfhk.js} +3 -3
- package/dist/{cli-qwhy2qma.js → cli-z63a269p.js} +2 -2
- package/dist/{cli-sm8rses9.js → cli-zfdp01hn.js} +8 -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-tcg1q3jk.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-xfx4wd9x.js} +7 -5
- package/dist/{commands-t7rz9146.js → commands-ew83nj70.js} +2 -2
- package/dist/{controller-m2jasma5.js → controller-gnq1k1mf.js} +4 -4
- package/dist/{controllers-connect-9ftpex99.js → controllers-connect-tw1dan9r.js} +25 -23
- package/dist/{cursor-adapter-mjv79e4z.js → cursor-adapter-yq5xgfcg.js} +1 -1
- package/dist/{db-6sfrn9g3.js → db-7gbc53fd.js} +14 -2
- package/dist/{db-rn673r06.js → db-t86xrnes.js} +3 -3
- package/dist/{devin-adapter-zgqadvnm.js → devin-adapter-4ycy4vrf.js} +1 -1
- package/dist/{dispatcher-c155xz0p.js → dispatcher-64bdyhps.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-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-tfrq7tg1.js → grok-adapter-v82srhrx.js} +9 -7
- package/dist/handlers-c9ajzhbn.js +41 -0
- package/dist/{heartbeat-dyg4npkp.js → heartbeat-2vqs1319.js} +25 -23
- package/dist/{hook-x26b31bg.js → hook-01nk13wx.js} +7 -5
- package/dist/{hook-drspbwpe.js → hook-jzpheegg.js} +9 -7
- package/dist/{http-pk972xyw.js → http-fc1k6ec8.js} +544 -76
- 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-q3t40ryv.js +46 -0
- package/dist/{index-arytgj5q.js → index-sepja052.js} +1 -1
- package/dist/{index-jwxkkex2.js → index-zdycv3ja.js} +13 -11
- package/dist/{index-g216q6jr.js → index-zsyx51ap.js} +1 -4
- package/dist/{keepalive-7yrng7px.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-e6cemdqt.js → maintenance-hjhzdt3k.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-y3n1knmd.js} +3 -3
- package/dist/{onboard-0a9y5yrc.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-trjpkfb7.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-d2b5my0y.js → pricing-refresh-nevhat8h.js} +3 -3
- package/dist/{rbac-roles-nxh5ahwk.js → rbac-roles-4y6ngvzq.js} +1 -1
- package/dist/{rbac-roles-hey3yv9d.js → rbac-roles-exbg8xb6.js} +2 -2
- package/dist/{render-v2-rr3p2atg.js → render-v2-cfsh13z3.js} +3 -3
- package/dist/{resume-2efkf1s1.js → resume-5s2t0dbs.js} +10 -8
- package/dist/{runtime-xe3aqy4x.js → runtime-bt5pkpm1.js} +1 -1
- package/dist/{session-access-s2mttxpw.js → session-access-dnbyp3cn.js} +6 -4
- package/dist/{setup-vypma5yt.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-rvhckdkp.js → work-objects-7mg6216g.js} +25 -23
- package/dist/worker-nwb789mg.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/handlers.ts +5 -5
- 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-handlers.test.ts +3 -3
- 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
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
gitlabContextKey,
|
|
10
10
|
azureDevOpsContextKey,
|
|
11
11
|
azureDevOpsWorkItemContextKey,
|
|
12
|
+
bitbucketContextKey,
|
|
12
13
|
linearContextKey,
|
|
13
14
|
buildJiraContextKey,
|
|
14
15
|
scheduleContextKey,
|
|
@@ -72,6 +73,7 @@ import {
|
|
|
72
73
|
hasNonTerminalRerouteDecisionChild2,
|
|
73
74
|
getAgentCurrentTask2,
|
|
74
75
|
findTaskByVcs2,
|
|
76
|
+
findActiveTasksByVcs2,
|
|
75
77
|
readableSessionCondition,
|
|
76
78
|
getAllTasks2,
|
|
77
79
|
getPendingChatRelayTasks2,
|
|
@@ -334,19 +336,19 @@ import {
|
|
|
334
336
|
recordInlineScriptRun2,
|
|
335
337
|
exports_db,
|
|
336
338
|
init_db3
|
|
337
|
-
} from "./cli-
|
|
339
|
+
} from "./cli-fcc5qe3f.js";
|
|
338
340
|
import {
|
|
339
341
|
getUserGrant2,
|
|
340
342
|
init_rbac_roles
|
|
341
|
-
} from "./cli-
|
|
343
|
+
} from "./cli-0z3vjrpm.js";
|
|
342
344
|
import {
|
|
343
345
|
ensurePricingSeeded2,
|
|
344
346
|
ensureRbacSeeded2,
|
|
345
347
|
ensureModelProfilesSeeded2
|
|
346
|
-
} from "./cli-
|
|
348
|
+
} from "./cli-36j4jnk3.js";
|
|
347
349
|
import {
|
|
348
350
|
loadModelsDevCache
|
|
349
|
-
} from "./cli-
|
|
351
|
+
} from "./cli-0y6f0ckq.js";
|
|
350
352
|
import {
|
|
351
353
|
buildCatalogEntries,
|
|
352
354
|
listModelCatalog,
|
|
@@ -356,12 +358,12 @@ import {
|
|
|
356
358
|
loadModelsCatalog,
|
|
357
359
|
requestModelCatalogRefresh2,
|
|
358
360
|
startPricingRefreshLoop2
|
|
359
|
-
} from "./cli-
|
|
361
|
+
} from "./cli-y9jvxfhk.js";
|
|
360
362
|
import {
|
|
361
363
|
ampPinProviderError,
|
|
362
364
|
ampPinCatalogError,
|
|
363
365
|
ampModelError
|
|
364
|
-
} from "./cli-
|
|
366
|
+
} from "./cli-jpxsrxcb.js";
|
|
365
367
|
import {
|
|
366
368
|
notifyAutomationPreflightFailure,
|
|
367
369
|
isNeedsSetupFailure,
|
|
@@ -370,50 +372,50 @@ import {
|
|
|
370
372
|
getAutomationSetupStates,
|
|
371
373
|
schedulePreflightInput,
|
|
372
374
|
recordSchedulePreflightFailure,
|
|
375
|
+
BaseExecutor,
|
|
376
|
+
postApprovalCancellationUpdates,
|
|
377
|
+
createApprovalFollowUpTask,
|
|
378
|
+
HumanInTheLoopExecutor,
|
|
379
|
+
resolveWorkflowLlmConfig,
|
|
380
|
+
SYSTEM_ONE_PROVIDER_IDS,
|
|
381
|
+
SystemOneExtractionExecutor,
|
|
382
|
+
SYSTEM_ONE_DECISION_NODE_TYPE,
|
|
383
|
+
SystemOneDecisionConfigSchema,
|
|
384
|
+
SystemOneDecisionExecutor,
|
|
373
385
|
checkpointStep,
|
|
374
386
|
checkpointStepFailure,
|
|
375
387
|
checkpointStepWaiting,
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
buildForeachAggregate,
|
|
388
|
+
FAILED_TASK_OUTPUT_PREFIX,
|
|
389
|
+
FOREACH_ITEMS_WAIT_FOR,
|
|
379
390
|
loadCompletedStepRouting,
|
|
380
391
|
resolveInputValue,
|
|
381
392
|
getSecretInputKeys,
|
|
382
393
|
validateJsonSchema,
|
|
383
394
|
findJsonSchemaShapeErrors,
|
|
384
|
-
getMaxWorkflowStepsPerRun,
|
|
385
395
|
workflowSaveWarnings,
|
|
386
396
|
withSaveWarnings,
|
|
387
397
|
runStepValidation,
|
|
388
|
-
shapeApprovalResolution,
|
|
389
|
-
FAILED_TASK_OUTPUT_PREFIX,
|
|
390
|
-
SubWorkflowExecutor,
|
|
391
|
-
WaitExecutor,
|
|
392
|
-
failStepAndRunIfWaiting,
|
|
393
|
-
checkpointPortStepAndResolveSuccessors,
|
|
394
|
-
scheduleTaskStepRetry,
|
|
395
|
-
completeTaskStepAndResolveSuccessors,
|
|
396
|
-
setupWorkflowResumeListener2,
|
|
397
|
-
finalizeOrWait2,
|
|
398
|
-
retryFailedRun2,
|
|
399
|
-
cancelWorkflowRunRows2,
|
|
400
|
-
cancelWorkflowRun2,
|
|
401
|
-
resumeWaitState2,
|
|
402
|
-
recoverResolvedWaitState2,
|
|
403
|
-
resumeFromChildRun2,
|
|
404
|
-
initWaitBusSubscriptions2,
|
|
405
398
|
TriggerSchemaError,
|
|
406
399
|
startWorkflowExecution2,
|
|
407
400
|
failRunOnUnreadableReplay,
|
|
408
401
|
isWorkflowRunActive,
|
|
409
402
|
holdWorkflowRun,
|
|
410
403
|
walkGraph,
|
|
411
|
-
rehydrateCompletedStepOutputs,
|
|
412
404
|
findReadyNodes,
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
405
|
+
scriptBodyInterpolationError,
|
|
406
|
+
ForeachExecutor,
|
|
407
|
+
rebuildNodeExecutionInput,
|
|
408
|
+
isForeachChildOwned,
|
|
409
|
+
parkAndDriveForeach,
|
|
410
|
+
runForeachDrive,
|
|
411
|
+
stepFailureMode,
|
|
412
|
+
generateEdges,
|
|
413
|
+
resolveValidationPort,
|
|
414
|
+
getSuccessors,
|
|
415
|
+
definitionNodeIds,
|
|
416
|
+
validateDefinition,
|
|
417
|
+
applyDefinitionPatch
|
|
418
|
+
} from "./cli-92mqenkc.js";
|
|
417
419
|
import {
|
|
418
420
|
require_dist2,
|
|
419
421
|
publicEndpointSsrfOptions,
|
|
@@ -473,14 +475,14 @@ import {
|
|
|
473
475
|
deleteApp,
|
|
474
476
|
typecheckScript,
|
|
475
477
|
parseSkillContent
|
|
476
|
-
} from "./cli-
|
|
478
|
+
} from "./cli-we0ra057.js";
|
|
477
479
|
import {
|
|
478
480
|
buildAuthorizationUrl,
|
|
479
481
|
onAuthorizationRefreshed,
|
|
480
482
|
ensureAuthorizationTokenOrThrow,
|
|
481
483
|
ensureToken,
|
|
482
484
|
ensureTokenOrThrow
|
|
483
|
-
} from "./cli-
|
|
485
|
+
} from "./cli-s4sntwt4.js";
|
|
484
486
|
import {
|
|
485
487
|
detachedProcessGroup,
|
|
486
488
|
registerProcessGroup,
|
|
@@ -510,36 +512,36 @@ import {
|
|
|
510
512
|
getSlackApp2,
|
|
511
513
|
startSlackApp2,
|
|
512
514
|
stopSlackApp2
|
|
513
|
-
} from "./cli-
|
|
515
|
+
} from "./cli-fy1jyyym.js";
|
|
514
516
|
import {
|
|
515
517
|
slackCode,
|
|
516
518
|
slackMissingScopeMessage,
|
|
517
519
|
withAutoJoin,
|
|
518
520
|
externalChannelToolError2,
|
|
519
521
|
getChannelBlockReason2
|
|
520
|
-
} from "./cli-
|
|
521
|
-
import {
|
|
522
|
-
BaseExecutor,
|
|
523
|
-
postApprovalCancellationUpdates,
|
|
524
|
-
createApprovalFollowUpTask,
|
|
525
|
-
HumanInTheLoopExecutor,
|
|
526
|
-
resolveWorkflowLlmConfig,
|
|
527
|
-
SYSTEM_ONE_PROVIDER_IDS,
|
|
528
|
-
SystemOneExtractionExecutor,
|
|
529
|
-
SYSTEM_ONE_DECISION_NODE_TYPE,
|
|
530
|
-
SystemOneDecisionConfigSchema,
|
|
531
|
-
SystemOneDecisionExecutor,
|
|
532
|
-
generateEdges,
|
|
533
|
-
resolveValidationPort,
|
|
534
|
-
getSuccessors,
|
|
535
|
-
definitionNodeIds,
|
|
536
|
-
validateDefinition,
|
|
537
|
-
applyDefinitionPatch
|
|
538
|
-
} from "./cli-xpa64rek.js";
|
|
522
|
+
} from "./cli-ftmq4nvk.js";
|
|
539
523
|
import {
|
|
540
524
|
workflowEventBus2,
|
|
541
525
|
init_event_bus
|
|
542
|
-
} from "./cli-
|
|
526
|
+
} from "./cli-dabehxhp.js";
|
|
527
|
+
import {
|
|
528
|
+
shapeApprovalResolution,
|
|
529
|
+
SubWorkflowExecutor,
|
|
530
|
+
WaitExecutor,
|
|
531
|
+
failStepAndRunIfWaiting,
|
|
532
|
+
checkpointPortStepAndResolveSuccessors,
|
|
533
|
+
scheduleTaskStepRetry,
|
|
534
|
+
completeTaskStepAndResolveSuccessors,
|
|
535
|
+
setupWorkflowResumeListener2,
|
|
536
|
+
finalizeOrWait2,
|
|
537
|
+
retryFailedRun2,
|
|
538
|
+
cancelWorkflowRunRows2,
|
|
539
|
+
cancelWorkflowRun2,
|
|
540
|
+
resumeWaitState2,
|
|
541
|
+
recoverResolvedWaitState2,
|
|
542
|
+
resumeFromChildRun2,
|
|
543
|
+
initWaitBusSubscriptions2
|
|
544
|
+
} from "./cli-3zwye9sn.js";
|
|
543
545
|
import {
|
|
544
546
|
duplicateGuardedQueryKey,
|
|
545
547
|
parseQueryParams,
|
|
@@ -566,7 +568,7 @@ import {
|
|
|
566
568
|
isPublicRoute,
|
|
567
569
|
findRoute,
|
|
568
570
|
route
|
|
569
|
-
} from "./cli-
|
|
571
|
+
} from "./cli-9ce2xw98.js";
|
|
570
572
|
import {
|
|
571
573
|
isMultiRuntimeEnabled
|
|
572
574
|
} from "./cli-e8xyjvfc.js";
|
|
@@ -580,7 +582,7 @@ import {
|
|
|
580
582
|
import {
|
|
581
583
|
getRuntimePool2,
|
|
582
584
|
init_db
|
|
583
|
-
} from "./cli-
|
|
585
|
+
} from "./cli-5rvg1ddk.js";
|
|
584
586
|
import {
|
|
585
587
|
getMemoryRaterNames,
|
|
586
588
|
REFERENCES_SOURCE_MAX_LENGTH,
|
|
@@ -591,7 +593,7 @@ import {
|
|
|
591
593
|
COMPOSIO_HTTP_METHODS,
|
|
592
594
|
executeComposioRequest,
|
|
593
595
|
composioArgsFromParts
|
|
594
|
-
} from "./cli-
|
|
596
|
+
} from "./cli-pasyvjmm.js";
|
|
595
597
|
import {
|
|
596
598
|
require_fast_deep_equal
|
|
597
599
|
} from "./cli-bhp11egn.js";
|
|
@@ -605,7 +607,7 @@ import {
|
|
|
605
607
|
import {
|
|
606
608
|
canProvisionKind,
|
|
607
609
|
init_runtime_providers
|
|
608
|
-
} from "./cli-
|
|
610
|
+
} from "./cli-p859hcc8.js";
|
|
609
611
|
import {
|
|
610
612
|
findUserById,
|
|
611
613
|
findUserByExternalId,
|
|
@@ -621,7 +623,7 @@ import {
|
|
|
621
623
|
resolveSessionToken,
|
|
622
624
|
fingerprintApiKey,
|
|
623
625
|
init_users
|
|
624
|
-
} from "./cli-
|
|
626
|
+
} from "./cli-xt768r5m.js";
|
|
625
627
|
import {
|
|
626
628
|
isRbacEnabled,
|
|
627
629
|
decideAdmission,
|
|
@@ -690,7 +692,7 @@ import {
|
|
|
690
692
|
KvNamespaceSchema,
|
|
691
693
|
KvKeySchema,
|
|
692
694
|
init_types
|
|
693
|
-
} from "./cli-
|
|
695
|
+
} from "./cli-rh5smt8t.js";
|
|
694
696
|
import {
|
|
695
697
|
generateDefaultClaudeMd2,
|
|
696
698
|
generateDefaultSoulMd2,
|
|
@@ -699,7 +701,7 @@ import {
|
|
|
699
701
|
taskAttachmentFetchCommand,
|
|
700
702
|
taskAttachmentDisplayUrl,
|
|
701
703
|
init_task_attachment_links
|
|
702
|
-
} from "./cli-
|
|
704
|
+
} from "./cli-gpv60278.js";
|
|
703
705
|
import {
|
|
704
706
|
getSlackConfiguration,
|
|
705
707
|
init_config
|
|
@@ -711,7 +713,6 @@ import {
|
|
|
711
713
|
import {
|
|
712
714
|
findInterpolationTokens,
|
|
713
715
|
interpolate,
|
|
714
|
-
deepInterpolate,
|
|
715
716
|
init_template,
|
|
716
717
|
registerTemplate,
|
|
717
718
|
getTemplateDefinition,
|
|
@@ -737,7 +738,6 @@ import {
|
|
|
737
738
|
_null,
|
|
738
739
|
any,
|
|
739
740
|
unknown,
|
|
740
|
-
never,
|
|
741
741
|
array2,
|
|
742
742
|
object2,
|
|
743
743
|
looseObject,
|
|
@@ -761,7 +761,7 @@ import {
|
|
|
761
761
|
import {
|
|
762
762
|
init_package,
|
|
763
763
|
package_default
|
|
764
|
-
} from "./cli-
|
|
764
|
+
} from "./cli-179xcyky.js";
|
|
765
765
|
import {
|
|
766
766
|
realtimeBus,
|
|
767
767
|
init_bus
|
|
@@ -795,7 +795,7 @@ import {
|
|
|
795
795
|
registerVolatileSecret,
|
|
796
796
|
registerSensitiveKeyName,
|
|
797
797
|
init_secret_scrubber
|
|
798
|
-
} from "./cli-
|
|
798
|
+
} from "./cli-n4c8e3s5.js";
|
|
799
799
|
import {
|
|
800
800
|
isAlias,
|
|
801
801
|
parseAlias,
|
|
@@ -20137,6 +20137,7 @@ async function recoverIncompleteRuns(registry) {
|
|
|
20137
20137
|
console.error(`[workflows] Failed to resume sub-workflow step ${parentStepId}:`, err);
|
|
20138
20138
|
}
|
|
20139
20139
|
}
|
|
20140
|
+
recovered += await recoverForeachFanouts(registry);
|
|
20140
20141
|
if (recovered > 0) {
|
|
20141
20142
|
console.log(`[workflows] Recovered ${recovered} incomplete run(s)`);
|
|
20142
20143
|
}
|
|
@@ -20230,10 +20231,10 @@ async function recoverWaitingRuns(registry) {
|
|
|
20230
20231
|
if (retry !== "not-eligible")
|
|
20231
20232
|
continue;
|
|
20232
20233
|
}
|
|
20233
|
-
if (!taskCompleted && (workflow.definition.
|
|
20234
|
+
if (!taskCompleted && stepFailureMode(workflow.definition, stuck.nodeId) === "fail") {
|
|
20234
20235
|
const reason = stuck.taskStatus === "failed" ? "Task failed (recovered)" : "Task cancelled (recovered)";
|
|
20235
|
-
const
|
|
20236
|
-
if (!claimed)
|
|
20236
|
+
const failed = await failStepAndRunIfWaiting(workflow.definition, stuck.stepId, stuck.runId, reason, stuck.taskId, { registry });
|
|
20237
|
+
if (!failed.claimed)
|
|
20237
20238
|
continue;
|
|
20238
20239
|
recovered++;
|
|
20239
20240
|
continue;
|
|
@@ -20247,7 +20248,7 @@ async function recoverWaitingRuns(registry) {
|
|
|
20247
20248
|
const step = await getWorkflowRunStep2(stuck.stepId);
|
|
20248
20249
|
if (!step)
|
|
20249
20250
|
continue;
|
|
20250
|
-
const routing = await completeTaskStepAndResolveSuccessors(workflow.definition, stuck.runId, step, stepOutput, ctx, taskCompleted ? undefined : reason, stuck.taskId);
|
|
20251
|
+
const routing = await completeTaskStepAndResolveSuccessors(workflow.definition, stuck.runId, step, stepOutput, ctx, taskCompleted ? undefined : reason, stuck.taskId, registry);
|
|
20251
20252
|
if (!routing.claimed)
|
|
20252
20253
|
continue;
|
|
20253
20254
|
if (routing.foreachChild && !routing.joined) {
|
|
@@ -20302,7 +20303,7 @@ async function recoverApprovalWaitingRuns(registry) {
|
|
|
20302
20303
|
status: approvalStatus,
|
|
20303
20304
|
responses: approval?.responses ?? null
|
|
20304
20305
|
});
|
|
20305
|
-
return await checkpointPortStepAndResolveSuccessors(workflow.definition, stuck.runId, stuck.stepId, stuck.nodeId, stepOutput, nextPort, ctx);
|
|
20306
|
+
return await checkpointPortStepAndResolveSuccessors(workflow.definition, stuck.runId, stuck.stepId, stuck.nodeId, stepOutput, nextPort, ctx, registry);
|
|
20306
20307
|
});
|
|
20307
20308
|
if (!routing?.claimed)
|
|
20308
20309
|
continue;
|
|
@@ -20341,6 +20342,42 @@ async function recoverWaitStates(registry) {
|
|
|
20341
20342
|
}
|
|
20342
20343
|
return recovered;
|
|
20343
20344
|
}
|
|
20345
|
+
async function recoverForeachFanouts(registry) {
|
|
20346
|
+
const rows = await getDbClient2().query(`SELECT s.runId AS runId, r.workflowId AS workflowId, s.id AS stepId, s.nodeId AS nodeId, s.status AS status
|
|
20347
|
+
FROM workflow_run_steps s
|
|
20348
|
+
JOIN workflow_runs r ON r.id = s.runId
|
|
20349
|
+
WHERE r.status IN ('running', 'waiting')
|
|
20350
|
+
AND s.status IN ('pending', 'running')
|
|
20351
|
+
AND instr(s.nodeId, '#') > 1`);
|
|
20352
|
+
const fanouts = new Map;
|
|
20353
|
+
for (const row of rows) {
|
|
20354
|
+
if (row.status === "running" && isForeachChildOwned(row.stepId))
|
|
20355
|
+
continue;
|
|
20356
|
+
const parentNodeId = row.nodeId.slice(0, row.nodeId.indexOf("#"));
|
|
20357
|
+
fanouts.set(`${row.runId}\x00${parentNodeId}`, {
|
|
20358
|
+
runId: row.runId,
|
|
20359
|
+
workflowId: row.workflowId,
|
|
20360
|
+
parentNodeId
|
|
20361
|
+
});
|
|
20362
|
+
}
|
|
20363
|
+
let recovered = 0;
|
|
20364
|
+
for (const fanout of fanouts.values()) {
|
|
20365
|
+
try {
|
|
20366
|
+
const workflow = await getWorkflow2(fanout.workflowId);
|
|
20367
|
+
const parent = workflow?.definition.nodes.find((node) => node.id === fanout.parentNodeId);
|
|
20368
|
+
if (parent?.type !== "foreach")
|
|
20369
|
+
continue;
|
|
20370
|
+
const drive = await runForeachDrive(fanout.runId, fanout.parentNodeId, registry);
|
|
20371
|
+
if (drive.claimed > 0)
|
|
20372
|
+
recovered++;
|
|
20373
|
+
} catch (err) {
|
|
20374
|
+
if (await failRunOnUnreadableReplay(fanout.runId, err))
|
|
20375
|
+
continue;
|
|
20376
|
+
console.error(`[workflows] Failed to re-drive foreach ${fanout.parentNodeId} of run ${fanout.runId}:`, err);
|
|
20377
|
+
}
|
|
20378
|
+
}
|
|
20379
|
+
return recovered;
|
|
20380
|
+
}
|
|
20344
20381
|
async function getRunIdsByStatus(status) {
|
|
20345
20382
|
const rows = await getDbClient2().query("SELECT id FROM workflow_runs WHERE status = ?", [status]);
|
|
20346
20383
|
return rows.map((r) => r.id);
|
|
@@ -20370,17 +20407,16 @@ function startRetryPoller(registry, intervalMs = 5000) {
|
|
|
20370
20407
|
release = holdWorkflowRun(run.id);
|
|
20371
20408
|
if (!await claimRetry(run.id, step.id))
|
|
20372
20409
|
continue;
|
|
20373
|
-
const
|
|
20374
|
-
|
|
20375
|
-
|
|
20376
|
-
|
|
20377
|
-
|
|
20378
|
-
|
|
20410
|
+
const {
|
|
20411
|
+
ctx,
|
|
20412
|
+
inputCtx,
|
|
20413
|
+
config: interpolatedConfig,
|
|
20414
|
+
scriptBodyUnresolved
|
|
20415
|
+
} = await rebuildNodeExecutionInput(workflow.definition, run, node, registry);
|
|
20379
20416
|
if (scriptBodyUnresolved && scriptBodyUnresolved.length > 0) {
|
|
20380
20417
|
await checkpointStepFailure(run.id, step.id, scriptBodyInterpolationError(node.id, scriptBodyUnresolved), step.retryCount);
|
|
20381
20418
|
continue;
|
|
20382
20419
|
}
|
|
20383
|
-
const interpolatedConfig = interpolatedValue;
|
|
20384
20420
|
const executor = registry.get(node.type);
|
|
20385
20421
|
const meta = {
|
|
20386
20422
|
runId: run.id,
|
|
@@ -20400,6 +20436,21 @@ function startRetryPoller(registry, intervalMs = 5000) {
|
|
|
20400
20436
|
if (result.status === "failed") {
|
|
20401
20437
|
const retryPolicy = node.retry || executor.retryPolicy;
|
|
20402
20438
|
await checkpointStepFailure(run.id, step.id, result.error || "Retry failed", step.retryCount, retryPolicy);
|
|
20439
|
+
} else if ("async" in result && result.async && result.waitFor === FOREACH_ITEMS_WAIT_FOR) {
|
|
20440
|
+
const drive = await parkAndDriveForeach({
|
|
20441
|
+
runId: run.id,
|
|
20442
|
+
stepId: step.id,
|
|
20443
|
+
parentNodeId: node.id,
|
|
20444
|
+
ctx,
|
|
20445
|
+
registry
|
|
20446
|
+
});
|
|
20447
|
+
if (!drive.joined)
|
|
20448
|
+
continue;
|
|
20449
|
+
if (drive.successors.length > 0) {
|
|
20450
|
+
await walkGraph(workflow.definition, run.id, ctx, drive.successors, registry, workflow.id);
|
|
20451
|
+
} else {
|
|
20452
|
+
await completeRunIfSettled(run.id, ctx);
|
|
20453
|
+
}
|
|
20403
20454
|
} else if ("async" in result && result.async) {
|
|
20404
20455
|
const waiting = await checkpointStepWaiting(run.id, step.id, ctx);
|
|
20405
20456
|
if (!waiting)
|
|
@@ -21025,154 +21076,6 @@ class CodeMatchExecutor extends BaseExecutor {
|
|
|
21025
21076
|
}
|
|
21026
21077
|
}
|
|
21027
21078
|
|
|
21028
|
-
// src/workflows/executors/foreach.ts
|
|
21029
|
-
init_zod();
|
|
21030
|
-
init_template();
|
|
21031
|
-
var ForeachBodySchema = object2({
|
|
21032
|
-
type: literal2("agent-task"),
|
|
21033
|
-
config: record2(string2(), unknown())
|
|
21034
|
-
});
|
|
21035
|
-
var ForeachConfigSchema = object2({
|
|
21036
|
-
over: array2(record2(string2(), unknown())),
|
|
21037
|
-
itemKey: string2().min(1),
|
|
21038
|
-
body: ForeachBodySchema,
|
|
21039
|
-
concurrency: never().optional()
|
|
21040
|
-
});
|
|
21041
|
-
var ForeachResultSchema = object2({
|
|
21042
|
-
itemKey: string2(),
|
|
21043
|
-
status: _enum2(["completed", "failed", "cancelled", "skipped"]),
|
|
21044
|
-
output: unknown().optional()
|
|
21045
|
-
});
|
|
21046
|
-
var ForeachOutputSchema = object2({
|
|
21047
|
-
results: array2(ForeachResultSchema),
|
|
21048
|
-
okCount: number2().int().nonnegative(),
|
|
21049
|
-
failedCount: number2().int().nonnegative()
|
|
21050
|
-
});
|
|
21051
|
-
|
|
21052
|
-
class ForeachExecutor extends BaseExecutor {
|
|
21053
|
-
type = "foreach";
|
|
21054
|
-
mode = "async";
|
|
21055
|
-
configSchema = ForeachConfigSchema;
|
|
21056
|
-
outputSchema = ForeachOutputSchema;
|
|
21057
|
-
async execute(config, context, meta) {
|
|
21058
|
-
if (config.over.length === 0) {
|
|
21059
|
-
return {
|
|
21060
|
-
status: "success",
|
|
21061
|
-
output: { results: [], okCount: 0, failedCount: 0 }
|
|
21062
|
-
};
|
|
21063
|
-
}
|
|
21064
|
-
const items = config.over.map((item, index) => {
|
|
21065
|
-
const rawItemKey = item[config.itemKey];
|
|
21066
|
-
if (typeof rawItemKey !== "string" || rawItemKey.length === 0) {
|
|
21067
|
-
throw new Error(`foreach item at index ${index} is missing non-empty string itemKey property "${config.itemKey}"`);
|
|
21068
|
-
}
|
|
21069
|
-
return { item, index, itemKey: rawItemKey };
|
|
21070
|
-
});
|
|
21071
|
-
const seenItemKeys = new Set;
|
|
21072
|
-
for (const { itemKey } of items) {
|
|
21073
|
-
if (seenItemKeys.has(itemKey)) {
|
|
21074
|
-
throw new Error(`foreach itemKey "${itemKey}" is duplicated`);
|
|
21075
|
-
}
|
|
21076
|
-
seenItemKeys.add(itemKey);
|
|
21077
|
-
}
|
|
21078
|
-
const agentTaskExecutor = new AgentTaskExecutor(this.deps);
|
|
21079
|
-
const runSteps = await this.deps.db.getWorkflowRunStepsByRunId(meta.runId);
|
|
21080
|
-
const childStepsByNodeId = new Map(runSteps.filter((step) => parseSyntheticNodeId(step.nodeId)?.parentNodeId === meta.nodeId).map((step) => [step.nodeId, step]));
|
|
21081
|
-
const childCountToCreate = items.filter(({ itemKey }) => !childStepsByNodeId.has(`${meta.nodeId}#${itemKey}`)).length;
|
|
21082
|
-
const maxSteps = getMaxWorkflowStepsPerRun();
|
|
21083
|
-
const workflow = await this.deps.db.getWorkflow(meta.workflowId);
|
|
21084
|
-
const hasSuccessors = workflow ? getSuccessors(workflow.definition, meta.nodeId).length > 0 : true;
|
|
21085
|
-
const totalSteps = runSteps.length + childCountToCreate;
|
|
21086
|
-
const capBreached = hasSuccessors ? totalSteps >= maxSteps : totalSteps > maxSteps;
|
|
21087
|
-
if (childCountToCreate > 0 && capBreached) {
|
|
21088
|
-
return {
|
|
21089
|
-
status: "failed",
|
|
21090
|
-
error: `foreach would reach ${maxSteps} total steps (WORKFLOW_MAX_STEPS_PER_RUN): ${runSteps.length} existing + ${childCountToCreate} children${hasSuccessors ? " leaves no room for the post-join walk" : " exceeds the per-run cap"}`
|
|
21091
|
-
};
|
|
21092
|
-
}
|
|
21093
|
-
for (const { index, itemKey } of items) {
|
|
21094
|
-
const childNodeId = `${meta.nodeId}#${itemKey}`;
|
|
21095
|
-
if (childStepsByNodeId.has(childNodeId))
|
|
21096
|
-
continue;
|
|
21097
|
-
const childStepId = crypto.randomUUID();
|
|
21098
|
-
const childStep = await this.deps.db.createWorkflowRunStep({
|
|
21099
|
-
id: childStepId,
|
|
21100
|
-
runId: meta.runId,
|
|
21101
|
-
nodeId: childNodeId,
|
|
21102
|
-
nodeType: "agent-task",
|
|
21103
|
-
input: { itemKey, index }
|
|
21104
|
-
});
|
|
21105
|
-
await this.deps.db.updateWorkflowRunStep(childStepId, {
|
|
21106
|
-
idempotencyKey: `${meta.runId}:${childNodeId}:0`
|
|
21107
|
-
});
|
|
21108
|
-
childStepsByNodeId.set(childNodeId, childStep);
|
|
21109
|
-
}
|
|
21110
|
-
for (const { item, index, itemKey } of items) {
|
|
21111
|
-
const childNodeId = `${meta.nodeId}#${itemKey}`;
|
|
21112
|
-
const childStep = childStepsByNodeId.get(childNodeId);
|
|
21113
|
-
if (FOREACH_TERMINAL_STEP_STATUSES.has(childStep.status))
|
|
21114
|
-
continue;
|
|
21115
|
-
const bodyCtx = { ...meta.inputCtx ?? context, item, index };
|
|
21116
|
-
const childInterpolation = deepInterpolate(config.body.config, bodyCtx);
|
|
21117
|
-
if (childInterpolation.unresolved.length > 0) {
|
|
21118
|
-
console.warn(`[workflow] Step ${childNodeId}: unresolved interpolation tokens: ${childInterpolation.unresolved.join(", ")}`);
|
|
21119
|
-
await this.deps.db.updateWorkflowRunStep(childStep.id, {
|
|
21120
|
-
diagnostics: JSON.stringify({ unresolvedTokens: childInterpolation.unresolved })
|
|
21121
|
-
});
|
|
21122
|
-
}
|
|
21123
|
-
const linkedTask = await this.deps.db.getTaskByWorkflowRunStepId(childStep.id);
|
|
21124
|
-
if (linkedTask?.status === "failed" || linkedTask?.status === "cancelled") {
|
|
21125
|
-
await this.deps.db.detachTaskFromWorkflowRunStep(linkedTask.id);
|
|
21126
|
-
}
|
|
21127
|
-
const childResult = await agentTaskExecutor.run({
|
|
21128
|
-
config: childInterpolation.value,
|
|
21129
|
-
context,
|
|
21130
|
-
meta: {
|
|
21131
|
-
...meta,
|
|
21132
|
-
stepId: childStep.id,
|
|
21133
|
-
nodeId: childNodeId
|
|
21134
|
-
}
|
|
21135
|
-
});
|
|
21136
|
-
if (childResult.status !== "success") {
|
|
21137
|
-
throw new Error(childResult.error ?? `foreach child "${itemKey}" failed to start`);
|
|
21138
|
-
}
|
|
21139
|
-
if ("async" in childResult) {
|
|
21140
|
-
await this.deps.db.updateWorkflowRunStep(childStep.id, { status: "waiting" });
|
|
21141
|
-
} else {
|
|
21142
|
-
await this.deps.db.updateWorkflowRunStep(childStep.id, {
|
|
21143
|
-
status: "completed",
|
|
21144
|
-
output: normalizeExistingTaskOutput(childResult.output),
|
|
21145
|
-
finishedAt: new Date().toISOString()
|
|
21146
|
-
});
|
|
21147
|
-
}
|
|
21148
|
-
}
|
|
21149
|
-
const childSteps = (await this.deps.db.getWorkflowRunStepsByRunId(meta.runId)).filter((step) => parseSyntheticNodeId(step.nodeId)?.parentNodeId === meta.nodeId);
|
|
21150
|
-
if (childSteps.every((step) => FOREACH_TERMINAL_STEP_STATUSES.has(step.status))) {
|
|
21151
|
-
return { status: "success", output: buildForeachAggregate(childSteps) };
|
|
21152
|
-
}
|
|
21153
|
-
return {
|
|
21154
|
-
status: "success",
|
|
21155
|
-
async: true,
|
|
21156
|
-
waitFor: "task.completed",
|
|
21157
|
-
correlationId: meta.stepId
|
|
21158
|
-
};
|
|
21159
|
-
}
|
|
21160
|
-
}
|
|
21161
|
-
function normalizeExistingTaskOutput(output) {
|
|
21162
|
-
if (typeof output !== "object" || output === null)
|
|
21163
|
-
return output;
|
|
21164
|
-
const record = output;
|
|
21165
|
-
if (typeof record.taskOutput !== "string")
|
|
21166
|
-
return output;
|
|
21167
|
-
try {
|
|
21168
|
-
const parsed = JSON.parse(record.taskOutput);
|
|
21169
|
-
if (typeof parsed === "object" && parsed !== null) {
|
|
21170
|
-
return { ...record, taskOutput: parsed };
|
|
21171
|
-
}
|
|
21172
|
-
} catch {}
|
|
21173
|
-
return output;
|
|
21174
|
-
}
|
|
21175
|
-
|
|
21176
21079
|
// src/workflows/executors/notify.ts
|
|
21177
21080
|
init_zod();
|
|
21178
21081
|
init_secret_scrubber();
|
|
@@ -21216,7 +21119,7 @@ class NotifyExecutor extends BaseExecutor {
|
|
|
21216
21119
|
}
|
|
21217
21120
|
}
|
|
21218
21121
|
case "slack": {
|
|
21219
|
-
const { getSlackApp } = await import("./app-
|
|
21122
|
+
const { getSlackApp } = await import("./app-0qp0a2gk.js");
|
|
21220
21123
|
const app = getSlackApp();
|
|
21221
21124
|
if (!app) {
|
|
21222
21125
|
return {
|
|
@@ -24579,7 +24482,7 @@ function setPreloadedTools(server, names) {
|
|
|
24579
24482
|
async function applyPreToolCall(name, args, requestInfo, inputSchema) {
|
|
24580
24483
|
if (requestInfo.callOrigin !== "mcp")
|
|
24581
24484
|
return { args };
|
|
24582
|
-
const dispatcher = await import("./dispatcher-
|
|
24485
|
+
const dispatcher = await import("./dispatcher-64bdyhps.js");
|
|
24583
24486
|
const result = await dispatcher.dispatchPre("pre.tool.call", { tool: name, args, requestInfo }, inputSchema ? {
|
|
24584
24487
|
validateModify: async (data) => {
|
|
24585
24488
|
const schema = normalizeObjectSchema(inputSchema) ?? inputSchema;
|
|
@@ -25789,7 +25692,8 @@ var onChatMessageSent = chatMessageBridge("chat.message.sent", "outbound");
|
|
|
25789
25692
|
var VCS_PROVIDERS = new Set([
|
|
25790
25693
|
"github",
|
|
25791
25694
|
"gitlab",
|
|
25792
|
-
"azure-devops"
|
|
25695
|
+
"azure-devops",
|
|
25696
|
+
"bitbucket"
|
|
25793
25697
|
]);
|
|
25794
25698
|
var VCS_KINDS = new Set([
|
|
25795
25699
|
"pull_request",
|
|
@@ -28080,7 +27984,7 @@ async function handlePullRequestCommented(event) {
|
|
|
28080
27984
|
return { created: false };
|
|
28081
27985
|
}
|
|
28082
27986
|
const requestedByUserId = await resolveAzureDevOpsSender(comment.author, "pull_request_comment", comment.content);
|
|
28083
|
-
const existingTask = await findTaskByVcs2(repo, pr.pullRequestId);
|
|
27987
|
+
const existingTask = await findTaskByVcs2(repo, pr.pullRequestId, "azure-devops");
|
|
28084
27988
|
const existingTaskNote = existingTask ? `
|
|
28085
27989
|
|
|
28086
27990
|
_Note: There's an active task (${existingTask.id}) for this PR #${pr.pullRequestId}._` : "";
|
|
@@ -29194,6 +29098,456 @@ async function syncTelemetryEnabled(via) {
|
|
|
29194
29098
|
track({ event: "telemetry.enabled", properties: { via } });
|
|
29195
29099
|
return true;
|
|
29196
29100
|
}
|
|
29101
|
+
|
|
29102
|
+
// src/bitbucket/api.ts
|
|
29103
|
+
init_secret_scrubber();
|
|
29104
|
+
|
|
29105
|
+
// src/bitbucket/auth.ts
|
|
29106
|
+
init_env_flag();
|
|
29107
|
+
var initialized4 = false;
|
|
29108
|
+
var webhookSecret4 = null;
|
|
29109
|
+
var apiToken2 = null;
|
|
29110
|
+
function isBitbucketEnabled() {
|
|
29111
|
+
return !!process.env.BITBUCKET_WEBHOOK_SECRET && !isEnvFlagEnabled("BITBUCKET_DISABLE", false);
|
|
29112
|
+
}
|
|
29113
|
+
function initBitbucket() {
|
|
29114
|
+
if (initialized4)
|
|
29115
|
+
return;
|
|
29116
|
+
if (!isBitbucketEnabled()) {
|
|
29117
|
+
console.log("[Bitbucket] Integration disabled (BITBUCKET_WEBHOOK_SECRET not set)");
|
|
29118
|
+
return;
|
|
29119
|
+
}
|
|
29120
|
+
webhookSecret4 = process.env.BITBUCKET_WEBHOOK_SECRET;
|
|
29121
|
+
apiToken2 = process.env.BITBUCKET_TOKEN ?? null;
|
|
29122
|
+
initialized4 = true;
|
|
29123
|
+
console.log(`[Bitbucket] Integration initialized (API token: ${apiToken2 ? "set" : "not set"})`);
|
|
29124
|
+
}
|
|
29125
|
+
function verifyBitbucketWebhook(rawBody, signatureHeader) {
|
|
29126
|
+
if (!webhookSecret4)
|
|
29127
|
+
return false;
|
|
29128
|
+
if (!signatureHeader?.startsWith("sha256="))
|
|
29129
|
+
return false;
|
|
29130
|
+
return verifyHmacSignature(webhookSecret4, rawBody, signatureHeader);
|
|
29131
|
+
}
|
|
29132
|
+
function getBitbucketToken() {
|
|
29133
|
+
return apiToken2;
|
|
29134
|
+
}
|
|
29135
|
+
function getBitbucketBotName() {
|
|
29136
|
+
return process.env.BITBUCKET_BOT_NAME || "agent-swarm-bot";
|
|
29137
|
+
}
|
|
29138
|
+
function resetBitbucket() {
|
|
29139
|
+
initialized4 = false;
|
|
29140
|
+
webhookSecret4 = null;
|
|
29141
|
+
apiToken2 = null;
|
|
29142
|
+
}
|
|
29143
|
+
|
|
29144
|
+
// src/bitbucket/api.ts
|
|
29145
|
+
var BITBUCKET_API = "https://api.bitbucket.org/2.0";
|
|
29146
|
+
function headers3() {
|
|
29147
|
+
const token = getBitbucketToken();
|
|
29148
|
+
if (!token)
|
|
29149
|
+
throw new Error("[Bitbucket] No API token configured");
|
|
29150
|
+
return {
|
|
29151
|
+
Authorization: `Bearer ${token}`,
|
|
29152
|
+
"Content-Type": "application/json",
|
|
29153
|
+
Accept: "application/json"
|
|
29154
|
+
};
|
|
29155
|
+
}
|
|
29156
|
+
var cachedBotAccountId = null;
|
|
29157
|
+
async function resolveBitbucketBotAccountId() {
|
|
29158
|
+
const fromEnv = process.env.BITBUCKET_BOT_ACCOUNT_ID?.trim();
|
|
29159
|
+
if (fromEnv)
|
|
29160
|
+
return fromEnv;
|
|
29161
|
+
if (cachedBotAccountId)
|
|
29162
|
+
return cachedBotAccountId;
|
|
29163
|
+
if (!getBitbucketToken())
|
|
29164
|
+
return null;
|
|
29165
|
+
try {
|
|
29166
|
+
const resp = await fetch(`${BITBUCKET_API}/user`, { headers: headers3(), redirect: "error" });
|
|
29167
|
+
if (!resp.ok) {
|
|
29168
|
+
console.error(`[Bitbucket] GET /user returned ${resp.status}`);
|
|
29169
|
+
return null;
|
|
29170
|
+
}
|
|
29171
|
+
const data = await resp.json();
|
|
29172
|
+
cachedBotAccountId = data.account_id?.trim() || null;
|
|
29173
|
+
return cachedBotAccountId;
|
|
29174
|
+
} catch (err) {
|
|
29175
|
+
console.error(`[Bitbucket] Failed to resolve bot identity: ${scrubSecrets(String(err))}`);
|
|
29176
|
+
return null;
|
|
29177
|
+
}
|
|
29178
|
+
}
|
|
29179
|
+
function resetBitbucketBotCache() {
|
|
29180
|
+
cachedBotAccountId = null;
|
|
29181
|
+
}
|
|
29182
|
+
// src/bitbucket/handlers.ts
|
|
29183
|
+
init_db3();
|
|
29184
|
+
init_users();
|
|
29185
|
+
init_resolver();
|
|
29186
|
+
init_context_key();
|
|
29187
|
+
|
|
29188
|
+
// src/bitbucket/templates.ts
|
|
29189
|
+
init_registry();
|
|
29190
|
+
registerTemplate({
|
|
29191
|
+
eventType: "common.delegation_instruction.bitbucket",
|
|
29192
|
+
header: "",
|
|
29193
|
+
defaultBody: "\n\n**Delegation instruction:** As the lead agent, analyze this and decide whether to handle it yourself or delegate to a worker agent. Use `send-task` to delegate with clear instructions.",
|
|
29194
|
+
variables: [],
|
|
29195
|
+
category: "common"
|
|
29196
|
+
});
|
|
29197
|
+
registerTemplate({
|
|
29198
|
+
eventType: "common.command_suggestions.bitbucket_pr",
|
|
29199
|
+
header: "",
|
|
29200
|
+
defaultBody: 'Workers have `git` authenticated for bitbucket.org and `BITBUCKET_TOKEN` in env; there is no Bitbucket CLI, so use curl against `https://api.bitbucket.org/2.0/repositories/{{repo}}` with `-H "Authorization: Bearer $BITBUCKET_TOKEN"`. Inspect the PR with `GET .../pullrequests/{{pr_id}}` and its diff with `GET .../pullrequests/{{pr_id}}/diff`. Reply with `POST .../pullrequests/{{pr_id}}/comments` and JSON body `{"content":{"raw":"<reply>"}}`. Find a PR by branch with `GET .../pullrequests?q=source.branch.name="<branch>"`. Open a PR with `POST .../pullrequests` and JSON body `{"title":"<title>","source":{"branch":{"name":"<branch>"}},"destination":{"branch":{"name":"<base>"}}}`.',
|
|
29201
|
+
variables: [
|
|
29202
|
+
{ name: "repo", description: "Repository full name (<workspace>/<repo_slug>)" },
|
|
29203
|
+
{ name: "pr_id", description: "Pull request ID" }
|
|
29204
|
+
],
|
|
29205
|
+
category: "common"
|
|
29206
|
+
});
|
|
29207
|
+
var SHARED_VARIABLES2 = [
|
|
29208
|
+
{ name: "pr_id", description: "Pull request ID" },
|
|
29209
|
+
{ name: "pr_title", description: "Pull request title" },
|
|
29210
|
+
{ name: "repo", description: "Repository full name (<workspace>/<repo_slug>)" },
|
|
29211
|
+
{ name: "pr_url", description: "Pull request web URL" }
|
|
29212
|
+
];
|
|
29213
|
+
var PR_BRANCH_VARIABLES = [
|
|
29214
|
+
{ name: "source_branch", description: "Source branch name" },
|
|
29215
|
+
{ name: "target_branch", description: "Target branch name" },
|
|
29216
|
+
{ name: "context_section", description: "Context section with description or empty string" }
|
|
29217
|
+
];
|
|
29218
|
+
registerTemplate({
|
|
29219
|
+
eventType: "bitbucket.pull_request.opened",
|
|
29220
|
+
header: "[Bitbucket PR #{{pr_id}}] {{pr_title}}",
|
|
29221
|
+
defaultBody: `Repo: {{repo}}
|
|
29222
|
+
Author: {{username}}
|
|
29223
|
+
Branch: {{source_branch}} → {{target_branch}}
|
|
29224
|
+
URL: {{pr_url}}
|
|
29225
|
+
|
|
29226
|
+
{{context_section}}{{@template[common.command_suggestions.bitbucket_pr]}}{{@template[common.delegation_instruction.bitbucket]}}`,
|
|
29227
|
+
variables: [
|
|
29228
|
+
...SHARED_VARIABLES2,
|
|
29229
|
+
{
|
|
29230
|
+
name: "username",
|
|
29231
|
+
description: "Author identity — resolved canonical name (e.g. 'Luis (bitbucket:557058:…)') or the UNKNOWN sentinel"
|
|
29232
|
+
},
|
|
29233
|
+
...PR_BRANCH_VARIABLES
|
|
29234
|
+
],
|
|
29235
|
+
category: "event"
|
|
29236
|
+
});
|
|
29237
|
+
registerTemplate({
|
|
29238
|
+
eventType: "bitbucket.pull_request.review_requested",
|
|
29239
|
+
header: "[Bitbucket PR #{{pr_id}}] Review requested: {{pr_title}}",
|
|
29240
|
+
defaultBody: `Repo: {{repo}}
|
|
29241
|
+
Author: {{username}}
|
|
29242
|
+
Branch: {{source_branch}} → {{target_branch}}
|
|
29243
|
+
URL: {{pr_url}}
|
|
29244
|
+
|
|
29245
|
+
You were added as a reviewer on this pull request.
|
|
29246
|
+
|
|
29247
|
+
{{context_section}}{{@template[common.command_suggestions.bitbucket_pr]}}{{@template[common.delegation_instruction.bitbucket]}}`,
|
|
29248
|
+
variables: [
|
|
29249
|
+
...SHARED_VARIABLES2,
|
|
29250
|
+
{
|
|
29251
|
+
name: "username",
|
|
29252
|
+
description: "Author identity — resolved canonical name (e.g. 'Luis (bitbucket:557058:…)') or the UNKNOWN sentinel"
|
|
29253
|
+
},
|
|
29254
|
+
...PR_BRANCH_VARIABLES
|
|
29255
|
+
],
|
|
29256
|
+
category: "event"
|
|
29257
|
+
});
|
|
29258
|
+
registerTemplate({
|
|
29259
|
+
eventType: "bitbucket.comment.mentioned",
|
|
29260
|
+
header: "[Bitbucket Comment on PR #{{pr_id}}] {{username}} mentioned bot",
|
|
29261
|
+
defaultBody: `Repo: {{repo}}
|
|
29262
|
+
PR: {{pr_title}}
|
|
29263
|
+
URL: {{pr_url}}
|
|
29264
|
+
{{location_section}}
|
|
29265
|
+
Comment:
|
|
29266
|
+
{{context}}{{existing_task_note}}
|
|
29267
|
+
|
|
29268
|
+
{{@template[common.command_suggestions.bitbucket_pr]}}{{@template[common.delegation_instruction.bitbucket]}}`,
|
|
29269
|
+
variables: [
|
|
29270
|
+
...SHARED_VARIABLES2,
|
|
29271
|
+
{
|
|
29272
|
+
name: "username",
|
|
29273
|
+
description: "Comment author identity — resolved canonical name (e.g. 'Luis (bitbucket:557058:…)') or the UNKNOWN sentinel"
|
|
29274
|
+
},
|
|
29275
|
+
{
|
|
29276
|
+
name: "location_section",
|
|
29277
|
+
description: "`File: <path>:<line>` line for inline comments, or empty string"
|
|
29278
|
+
},
|
|
29279
|
+
{ name: "context", description: "Extracted mention context from comment" },
|
|
29280
|
+
{
|
|
29281
|
+
name: "existing_task_note",
|
|
29282
|
+
description: "Note about existing active task, or empty string"
|
|
29283
|
+
}
|
|
29284
|
+
],
|
|
29285
|
+
category: "event"
|
|
29286
|
+
});
|
|
29287
|
+
|
|
29288
|
+
// src/bitbucket/handlers.ts
|
|
29289
|
+
var DEDUP_TTL_MS2 = 60000;
|
|
29290
|
+
var processedEvents3 = new Map;
|
|
29291
|
+
var processedDeliveries = new Map;
|
|
29292
|
+
function sweep(cache, now) {
|
|
29293
|
+
for (const [k, ts] of cache) {
|
|
29294
|
+
if (now - ts > DEDUP_TTL_MS2)
|
|
29295
|
+
cache.delete(k);
|
|
29296
|
+
}
|
|
29297
|
+
}
|
|
29298
|
+
function isDuplicate3(key) {
|
|
29299
|
+
const now = Date.now();
|
|
29300
|
+
sweep(processedEvents3, now);
|
|
29301
|
+
if (processedEvents3.has(key))
|
|
29302
|
+
return true;
|
|
29303
|
+
processedEvents3.set(key, now);
|
|
29304
|
+
return false;
|
|
29305
|
+
}
|
|
29306
|
+
async function withDedupReservation(key, fn) {
|
|
29307
|
+
if (isDuplicate3(key))
|
|
29308
|
+
return null;
|
|
29309
|
+
try {
|
|
29310
|
+
return await fn();
|
|
29311
|
+
} catch (err) {
|
|
29312
|
+
processedEvents3.delete(key);
|
|
29313
|
+
throw err;
|
|
29314
|
+
}
|
|
29315
|
+
}
|
|
29316
|
+
function isDuplicateDelivery(requestUuid) {
|
|
29317
|
+
if (!requestUuid)
|
|
29318
|
+
return false;
|
|
29319
|
+
sweep(processedDeliveries, Date.now());
|
|
29320
|
+
return processedDeliveries.has(requestUuid);
|
|
29321
|
+
}
|
|
29322
|
+
function markDeliveryProcessed(requestUuid) {
|
|
29323
|
+
if (requestUuid)
|
|
29324
|
+
processedDeliveries.set(requestUuid, Date.now());
|
|
29325
|
+
}
|
|
29326
|
+
function escapeRegExp2(value) {
|
|
29327
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
29328
|
+
}
|
|
29329
|
+
function mentionPatterns2(botAccountId) {
|
|
29330
|
+
const patterns = [new RegExp(`@${escapeRegExp2(getBitbucketBotName())}(?![\\w-])`, "gi")];
|
|
29331
|
+
if (botAccountId)
|
|
29332
|
+
patterns.push(new RegExp(`@\\{${escapeRegExp2(botAccountId)}\\}`, "gi"));
|
|
29333
|
+
return patterns;
|
|
29334
|
+
}
|
|
29335
|
+
function detectMention2(text, botAccountId) {
|
|
29336
|
+
if (!text)
|
|
29337
|
+
return false;
|
|
29338
|
+
return mentionPatterns2(botAccountId).some((re) => {
|
|
29339
|
+
re.lastIndex = 0;
|
|
29340
|
+
return re.test(text);
|
|
29341
|
+
});
|
|
29342
|
+
}
|
|
29343
|
+
function extractMentionContext2(text, botAccountId) {
|
|
29344
|
+
return mentionPatterns2(botAccountId).reduce((acc, re) => acc.replace(re, ""), text).trim();
|
|
29345
|
+
}
|
|
29346
|
+
function isBot2(account, botAccountId) {
|
|
29347
|
+
return !!botAccountId && account?.account_id === botAccountId;
|
|
29348
|
+
}
|
|
29349
|
+
function pullRequestWebUrl2(repo, pr) {
|
|
29350
|
+
return pr.links?.html?.href ?? `https://bitbucket.org/${repo}/pull-requests/${pr.id}`;
|
|
29351
|
+
}
|
|
29352
|
+
function contextKeyOf(event) {
|
|
29353
|
+
return bitbucketContextKey({
|
|
29354
|
+
repoUuid: event.repository.uuid,
|
|
29355
|
+
pullRequestId: event.pullrequest.id
|
|
29356
|
+
});
|
|
29357
|
+
}
|
|
29358
|
+
function pullRequestEventOf(body) {
|
|
29359
|
+
const event = body;
|
|
29360
|
+
const pr = event?.pullrequest;
|
|
29361
|
+
const repo = event?.repository;
|
|
29362
|
+
if (typeof pr?.id !== "number" || typeof pr.title !== "string" || typeof repo?.uuid !== "string" || typeof repo.full_name !== "string" || !event?.actor) {
|
|
29363
|
+
return null;
|
|
29364
|
+
}
|
|
29365
|
+
return event;
|
|
29366
|
+
}
|
|
29367
|
+
function pullRequestCommentEventOf(body) {
|
|
29368
|
+
const event = pullRequestEventOf(body);
|
|
29369
|
+
const comment = event?.comment;
|
|
29370
|
+
if (!event || typeof comment?.id !== "number" || typeof comment.content?.raw !== "string") {
|
|
29371
|
+
return null;
|
|
29372
|
+
}
|
|
29373
|
+
return event;
|
|
29374
|
+
}
|
|
29375
|
+
function warnMalformed2(eventKey) {
|
|
29376
|
+
console.warn(`[Bitbucket] Ignoring ${eventKey} event: required payload fields are missing`);
|
|
29377
|
+
}
|
|
29378
|
+
async function findLeadAgent3() {
|
|
29379
|
+
const agents = await getAllAgents2();
|
|
29380
|
+
return agents.find((a) => a.role === "lead" && a.status === "idle") ?? agents.find((a) => a.role === "lead") ?? null;
|
|
29381
|
+
}
|
|
29382
|
+
var UNMAPPED_NAMESPACE2 = "integration:unmapped:bitbucket";
|
|
29383
|
+
var UNMAPPED_TTL_MS2 = 30 * 24 * 60 * 60 * 1000;
|
|
29384
|
+
function externalIdOf2(account) {
|
|
29385
|
+
return account?.account_id?.trim() || account?.uuid?.trim() || null;
|
|
29386
|
+
}
|
|
29387
|
+
async function resolveBitbucketSender(account, sampleEventType, sampleContext) {
|
|
29388
|
+
const externalId = externalIdOf2(account);
|
|
29389
|
+
if (!externalId)
|
|
29390
|
+
return;
|
|
29391
|
+
const existing = await findUserByExternalId("bitbucket", externalId);
|
|
29392
|
+
if (existing)
|
|
29393
|
+
return existing.id;
|
|
29394
|
+
await upsertKv2({
|
|
29395
|
+
namespace: UNMAPPED_NAMESPACE2,
|
|
29396
|
+
key: `${externalId}:meta`,
|
|
29397
|
+
value: {
|
|
29398
|
+
lastSeenAt: new Date().toISOString(),
|
|
29399
|
+
displayName: account?.display_name,
|
|
29400
|
+
sampleEventType,
|
|
29401
|
+
sampleContext: sampleContext.slice(0, 100)
|
|
29402
|
+
},
|
|
29403
|
+
valueType: "json",
|
|
29404
|
+
expiresAt: Date.now() + UNMAPPED_TTL_MS2
|
|
29405
|
+
});
|
|
29406
|
+
await incrKv2(UNMAPPED_NAMESPACE2, `${externalId}:count`, 1);
|
|
29407
|
+
return;
|
|
29408
|
+
}
|
|
29409
|
+
async function renderBitbucketIdentity(account) {
|
|
29410
|
+
return renderIdentity(await resolveIdentity("bitbucket", externalIdOf2(account) ?? ""));
|
|
29411
|
+
}
|
|
29412
|
+
async function createBitbucketTask(text, event, fields) {
|
|
29413
|
+
const { pullrequest: pr, repository } = event;
|
|
29414
|
+
const lead = await findLeadAgent3();
|
|
29415
|
+
const task = await createTaskWithSiblingAwareness(text, {
|
|
29416
|
+
agentId: lead?.id ?? null,
|
|
29417
|
+
routingReason: lead ? "skill" : undefined,
|
|
29418
|
+
routingSource: lead ? "engine_default" : undefined,
|
|
29419
|
+
source: "bitbucket",
|
|
29420
|
+
vcsProvider: "bitbucket",
|
|
29421
|
+
taskType: fields.taskType,
|
|
29422
|
+
vcsRepo: repository.full_name,
|
|
29423
|
+
vcsEventType: fields.vcsEventType,
|
|
29424
|
+
vcsNumber: pr.id,
|
|
29425
|
+
vcsCommentId: fields.vcsCommentId,
|
|
29426
|
+
vcsAuthor: externalIdOf2(fields.author) ?? undefined,
|
|
29427
|
+
requestedByUserId: fields.requestedByUserId,
|
|
29428
|
+
vcsUrl: pullRequestWebUrl2(repository.full_name, pr),
|
|
29429
|
+
parentTaskId: fields.parentTaskId,
|
|
29430
|
+
contextKey: contextKeyOf(event)
|
|
29431
|
+
}, { origin: "webhook" });
|
|
29432
|
+
return { created: true, taskId: task.id };
|
|
29433
|
+
}
|
|
29434
|
+
async function handlePullRequestCreated2(body) {
|
|
29435
|
+
const event = pullRequestEventOf(body);
|
|
29436
|
+
if (!event) {
|
|
29437
|
+
warnMalformed2("pullrequest:created");
|
|
29438
|
+
return { created: false };
|
|
29439
|
+
}
|
|
29440
|
+
const { pullrequest: pr, repository } = event;
|
|
29441
|
+
const repo = repository.full_name;
|
|
29442
|
+
const author = pr.author ?? event.actor;
|
|
29443
|
+
console.log(`[Bitbucket] PR #${pr.id} created by ${author.display_name} in ${repo}`);
|
|
29444
|
+
const botAccountId = await resolveBitbucketBotAccountId();
|
|
29445
|
+
if (isBot2(author, botAccountId)) {
|
|
29446
|
+
console.log(`[Bitbucket] PR opened by the bot itself, skipping`);
|
|
29447
|
+
return { created: false };
|
|
29448
|
+
}
|
|
29449
|
+
const mentioned = detectMention2(pr.description, botAccountId);
|
|
29450
|
+
const reviewRequested = !!botAccountId && (pr.reviewers ?? []).some((r) => r.account_id === botAccountId);
|
|
29451
|
+
if (!mentioned && !reviewRequested) {
|
|
29452
|
+
console.log(`[Bitbucket] PR opened without bot mention or review request, skipping`);
|
|
29453
|
+
return { created: false };
|
|
29454
|
+
}
|
|
29455
|
+
const dedupKey = `bitbucket-pr-${repository.uuid}-${pr.id}-created`;
|
|
29456
|
+
const outcome = await withDedupReservation(dedupKey, async () => {
|
|
29457
|
+
const requestedByUserId = await resolveBitbucketSender(author, "pull_request", `PR #${pr.id}: ${pr.title}`);
|
|
29458
|
+
const context = pr.description ? extractMentionContext2(pr.description, botAccountId) : "";
|
|
29459
|
+
const templateId = mentioned ? "bitbucket.pull_request.opened" : "bitbucket.pull_request.review_requested";
|
|
29460
|
+
const result = resolveTemplate(templateId, {
|
|
29461
|
+
pr_id: pr.id,
|
|
29462
|
+
pr_title: pr.title,
|
|
29463
|
+
repo,
|
|
29464
|
+
username: await renderBitbucketIdentity(author),
|
|
29465
|
+
source_branch: pr.source?.branch?.name ?? "",
|
|
29466
|
+
target_branch: pr.destination?.branch?.name ?? "",
|
|
29467
|
+
pr_url: pullRequestWebUrl2(repo, pr),
|
|
29468
|
+
context_section: context ? `Context: ${context}
|
|
29469
|
+
|
|
29470
|
+
` : ""
|
|
29471
|
+
});
|
|
29472
|
+
if (result.skipped) {
|
|
29473
|
+
return { created: false };
|
|
29474
|
+
}
|
|
29475
|
+
return createBitbucketTask(result.text, event, {
|
|
29476
|
+
taskType: "bitbucket-pr",
|
|
29477
|
+
vcsEventType: "pull_request",
|
|
29478
|
+
author,
|
|
29479
|
+
requestedByUserId
|
|
29480
|
+
});
|
|
29481
|
+
});
|
|
29482
|
+
if (!outcome)
|
|
29483
|
+
console.log(`[Bitbucket] Skipping duplicate PR event`);
|
|
29484
|
+
return outcome ?? { created: false };
|
|
29485
|
+
}
|
|
29486
|
+
async function handlePullRequestCommentCreated(body) {
|
|
29487
|
+
const event = pullRequestCommentEventOf(body);
|
|
29488
|
+
if (!event) {
|
|
29489
|
+
warnMalformed2("pullrequest:comment_created");
|
|
29490
|
+
return { created: false };
|
|
29491
|
+
}
|
|
29492
|
+
const { pullrequest: pr, repository, comment } = event;
|
|
29493
|
+
const repo = repository.full_name;
|
|
29494
|
+
const author = comment.user ?? event.actor;
|
|
29495
|
+
const botAccountId = await resolveBitbucketBotAccountId();
|
|
29496
|
+
if (isBot2(author, botAccountId)) {
|
|
29497
|
+
return { created: false };
|
|
29498
|
+
}
|
|
29499
|
+
if (!detectMention2(comment.content.raw, botAccountId)) {
|
|
29500
|
+
return { created: false };
|
|
29501
|
+
}
|
|
29502
|
+
console.log(`[Bitbucket] Comment by ${author.display_name} on PR #${pr.id} in ${repo}`);
|
|
29503
|
+
const dedupKey = `bitbucket-comment-${repository.uuid}-${pr.id}-${comment.id}`;
|
|
29504
|
+
const outcome = await withDedupReservation(dedupKey, async () => {
|
|
29505
|
+
const requestedByUserId = await resolveBitbucketSender(author, "pull_request_comment", comment.content.raw);
|
|
29506
|
+
const existingTask = await findTaskByVcs2(repo, pr.id, "bitbucket");
|
|
29507
|
+
const existingTaskNote = existingTask ? `
|
|
29508
|
+
|
|
29509
|
+
_Note: There's an active task (${existingTask.id}) for this PR #${pr.id}._` : "";
|
|
29510
|
+
const line = comment.inline?.to ?? comment.inline?.from;
|
|
29511
|
+
const locationSection = comment.inline ? `File: ${comment.inline.path}${line != null ? `:${line}` : ""}
|
|
29512
|
+
` : "";
|
|
29513
|
+
const result = resolveTemplate("bitbucket.comment.mentioned", {
|
|
29514
|
+
pr_id: pr.id,
|
|
29515
|
+
pr_title: pr.title,
|
|
29516
|
+
username: await renderBitbucketIdentity(author),
|
|
29517
|
+
repo,
|
|
29518
|
+
pr_url: comment.links?.html?.href ?? pullRequestWebUrl2(repo, pr),
|
|
29519
|
+
location_section: locationSection,
|
|
29520
|
+
context: extractMentionContext2(comment.content.raw, botAccountId),
|
|
29521
|
+
existing_task_note: existingTaskNote
|
|
29522
|
+
});
|
|
29523
|
+
if (result.skipped) {
|
|
29524
|
+
return { created: false };
|
|
29525
|
+
}
|
|
29526
|
+
return createBitbucketTask(result.text, event, {
|
|
29527
|
+
taskType: "bitbucket-comment",
|
|
29528
|
+
vcsEventType: "pull_request_comment",
|
|
29529
|
+
author,
|
|
29530
|
+
requestedByUserId,
|
|
29531
|
+
vcsCommentId: comment.id,
|
|
29532
|
+
parentTaskId: existingTask?.id
|
|
29533
|
+
});
|
|
29534
|
+
});
|
|
29535
|
+
return outcome ?? { created: false };
|
|
29536
|
+
}
|
|
29537
|
+
async function handlePullRequestClosed(body, outcome) {
|
|
29538
|
+
const event = pullRequestEventOf(body);
|
|
29539
|
+
if (!event) {
|
|
29540
|
+
warnMalformed2(outcome === "merged" ? "pullrequest:fulfilled" : "pullrequest:rejected");
|
|
29541
|
+
return { created: false };
|
|
29542
|
+
}
|
|
29543
|
+
const { pullrequest: pr, repository } = event;
|
|
29544
|
+
const reason = outcome === "merged" ? "PR was merged" : "PR was declined";
|
|
29545
|
+
for (const task of await findActiveTasksByVcs2(repository.full_name, pr.id, "bitbucket")) {
|
|
29546
|
+
console.log(`[Bitbucket] Cancelling task ${task.id} — ${reason}`);
|
|
29547
|
+
await failTask2(task.id, reason);
|
|
29548
|
+
}
|
|
29549
|
+
return { created: false };
|
|
29550
|
+
}
|
|
29197
29551
|
// src/github/handlers.ts
|
|
29198
29552
|
init_db3();
|
|
29199
29553
|
init_users();
|
|
@@ -29218,12 +29572,12 @@ function computeMentionPattern(names) {
|
|
|
29218
29572
|
}
|
|
29219
29573
|
var BOT_NAMES = computeBotNames();
|
|
29220
29574
|
var MENTION_PATTERN = computeMentionPattern(BOT_NAMES);
|
|
29221
|
-
function
|
|
29575
|
+
function detectMention3(text) {
|
|
29222
29576
|
if (!text)
|
|
29223
29577
|
return false;
|
|
29224
29578
|
return MENTION_PATTERN.test(text);
|
|
29225
29579
|
}
|
|
29226
|
-
function
|
|
29580
|
+
function extractMentionContext3(text) {
|
|
29227
29581
|
if (!text)
|
|
29228
29582
|
return "";
|
|
29229
29583
|
return text.replace(MENTION_PATTERN, "").trim();
|
|
@@ -29666,7 +30020,7 @@ Related task: {{related_task_id}}
|
|
|
29666
30020
|
});
|
|
29667
30021
|
|
|
29668
30022
|
// src/github/handlers.ts
|
|
29669
|
-
var
|
|
30023
|
+
var processedEvents4 = new Map;
|
|
29670
30024
|
var EVENT_TTL2 = 60000;
|
|
29671
30025
|
function buildGithubContextKey(fullName, kind, number) {
|
|
29672
30026
|
const [owner, repo] = fullName.split("/");
|
|
@@ -29710,34 +30064,34 @@ function getCommandSuggestions(taskType, targetType) {
|
|
|
29710
30064
|
return "";
|
|
29711
30065
|
}
|
|
29712
30066
|
}
|
|
29713
|
-
function
|
|
30067
|
+
function isDuplicate4(eventKey) {
|
|
29714
30068
|
const now = Date.now();
|
|
29715
|
-
for (const [key, timestamp] of
|
|
30069
|
+
for (const [key, timestamp] of processedEvents4) {
|
|
29716
30070
|
if (now - timestamp > EVENT_TTL2) {
|
|
29717
|
-
|
|
30071
|
+
processedEvents4.delete(key);
|
|
29718
30072
|
}
|
|
29719
30073
|
}
|
|
29720
|
-
if (
|
|
30074
|
+
if (processedEvents4.has(eventKey)) {
|
|
29721
30075
|
return true;
|
|
29722
30076
|
}
|
|
29723
|
-
|
|
30077
|
+
processedEvents4.set(eventKey, now);
|
|
29724
30078
|
return false;
|
|
29725
30079
|
}
|
|
29726
|
-
async function
|
|
30080
|
+
async function findLeadAgent4() {
|
|
29727
30081
|
const agents = await getAllAgents2();
|
|
29728
30082
|
const onlineLead = agents.find((a) => a.isLead && a.status !== "offline");
|
|
29729
30083
|
if (onlineLead)
|
|
29730
30084
|
return onlineLead;
|
|
29731
30085
|
return agents.find((a) => a.isLead) ?? null;
|
|
29732
30086
|
}
|
|
29733
|
-
var
|
|
29734
|
-
var
|
|
30087
|
+
var UNMAPPED_NAMESPACE3 = "integration:unmapped:github";
|
|
30088
|
+
var UNMAPPED_TTL_MS3 = 30 * 24 * 60 * 60 * 1000;
|
|
29735
30089
|
async function resolveGitHubSender(login, sampleEventType, sampleContext) {
|
|
29736
30090
|
const existing = await findUserByExternalId("github", login);
|
|
29737
30091
|
if (existing)
|
|
29738
30092
|
return existing.id;
|
|
29739
30093
|
await upsertKv2({
|
|
29740
|
-
namespace:
|
|
30094
|
+
namespace: UNMAPPED_NAMESPACE3,
|
|
29741
30095
|
key: `${login}:meta`,
|
|
29742
30096
|
value: {
|
|
29743
30097
|
lastSeenAt: new Date().toISOString(),
|
|
@@ -29745,9 +30099,9 @@ async function resolveGitHubSender(login, sampleEventType, sampleContext) {
|
|
|
29745
30099
|
sampleContext: sampleContext.slice(0, 100)
|
|
29746
30100
|
},
|
|
29747
30101
|
valueType: "json",
|
|
29748
|
-
expiresAt: Date.now() +
|
|
30102
|
+
expiresAt: Date.now() + UNMAPPED_TTL_MS3
|
|
29749
30103
|
});
|
|
29750
|
-
await incrKv2(
|
|
30104
|
+
await incrKv2(UNMAPPED_NAMESPACE3, `${login}:count`, 1);
|
|
29751
30105
|
return;
|
|
29752
30106
|
}
|
|
29753
30107
|
async function handlePullRequest(event) {
|
|
@@ -29766,10 +30120,10 @@ async function handlePullRequest(event) {
|
|
|
29766
30120
|
return { created: false };
|
|
29767
30121
|
}
|
|
29768
30122
|
const eventKey = `pr-assigned:${repository.full_name}:${pr.number}`;
|
|
29769
|
-
if (
|
|
30123
|
+
if (isDuplicate4(eventKey)) {
|
|
29770
30124
|
return { created: false };
|
|
29771
30125
|
}
|
|
29772
|
-
const lead = await
|
|
30126
|
+
const lead = await findLeadAgent4();
|
|
29773
30127
|
const result = resolveTemplate("github.pull_request.assigned", {
|
|
29774
30128
|
pr_number: pr.number,
|
|
29775
30129
|
pr_title: pr.title,
|
|
@@ -29816,7 +30170,7 @@ async function handlePullRequest(event) {
|
|
|
29816
30170
|
console.log(`[GitHub] unassign cancel disabled by config — leaving task untouched (PR #${pr.number})`);
|
|
29817
30171
|
return { created: false };
|
|
29818
30172
|
}
|
|
29819
|
-
const task = await findTaskByVcs2(repository.full_name, pr.number);
|
|
30173
|
+
const task = await findTaskByVcs2(repository.full_name, pr.number, "github");
|
|
29820
30174
|
if (!task) {
|
|
29821
30175
|
console.log(`[GitHub] No active task found for PR #${pr.number} to cancel`);
|
|
29822
30176
|
return { created: false };
|
|
@@ -29833,15 +30187,15 @@ async function handlePullRequest(event) {
|
|
|
29833
30187
|
return { created: false };
|
|
29834
30188
|
}
|
|
29835
30189
|
const eventKey = `pr-review-requested:${repository.full_name}:${pr.number}`;
|
|
29836
|
-
if (
|
|
30190
|
+
if (isDuplicate4(eventKey)) {
|
|
29837
30191
|
return { created: false };
|
|
29838
30192
|
}
|
|
29839
|
-
const existingTask = await findTaskByVcs2(repository.full_name, pr.number);
|
|
30193
|
+
const existingTask = await findTaskByVcs2(repository.full_name, pr.number, "github");
|
|
29840
30194
|
if (existingTask) {
|
|
29841
30195
|
console.log(`[GitHub] Skipping review task for PR #${pr.number} — active task ${existingTask.id} already exists`);
|
|
29842
30196
|
return { created: false };
|
|
29843
30197
|
}
|
|
29844
|
-
const lead = await
|
|
30198
|
+
const lead = await findLeadAgent4();
|
|
29845
30199
|
const result = resolveTemplate("github.pull_request.review_requested", {
|
|
29846
30200
|
pr_number: pr.number,
|
|
29847
30201
|
pr_title: pr.title,
|
|
@@ -29888,7 +30242,7 @@ async function handlePullRequest(event) {
|
|
|
29888
30242
|
console.log(`[GitHub] review-request-removed cancel disabled by config — leaving task untouched (PR #${pr.number})`);
|
|
29889
30243
|
return { created: false };
|
|
29890
30244
|
}
|
|
29891
|
-
const task = await findTaskByVcs2(repository.full_name, pr.number);
|
|
30245
|
+
const task = await findTaskByVcs2(repository.full_name, pr.number, "github");
|
|
29892
30246
|
if (!task) {
|
|
29893
30247
|
console.log(`[GitHub] No active task found for PR #${pr.number} to cancel`);
|
|
29894
30248
|
return { created: false };
|
|
@@ -29906,10 +30260,10 @@ async function handlePullRequest(event) {
|
|
|
29906
30260
|
return { created: false };
|
|
29907
30261
|
}
|
|
29908
30262
|
const eventKey = `pr-labeled:${repository.full_name}:${pr.number}:${labelName}`;
|
|
29909
|
-
if (
|
|
30263
|
+
if (isDuplicate4(eventKey)) {
|
|
29910
30264
|
return { created: false };
|
|
29911
30265
|
}
|
|
29912
|
-
const lead = await
|
|
30266
|
+
const lead = await findLeadAgent4();
|
|
29913
30267
|
const result = resolveTemplate("github.pull_request.labeled", {
|
|
29914
30268
|
pr_number: pr.number,
|
|
29915
30269
|
pr_title: pr.title,
|
|
@@ -29959,16 +30313,16 @@ async function handlePullRequest(event) {
|
|
|
29959
30313
|
if (action !== "opened" && action !== "edited") {
|
|
29960
30314
|
return { created: false };
|
|
29961
30315
|
}
|
|
29962
|
-
const hasMention =
|
|
30316
|
+
const hasMention = detectMention3(pr.title) || detectMention3(pr.body);
|
|
29963
30317
|
if (!hasMention) {
|
|
29964
30318
|
return { created: false };
|
|
29965
30319
|
}
|
|
29966
30320
|
const eventKey = `pr:${repository.full_name}:${pr.number}:${action}`;
|
|
29967
|
-
if (
|
|
30321
|
+
if (isDuplicate4(eventKey)) {
|
|
29968
30322
|
return { created: false };
|
|
29969
30323
|
}
|
|
29970
|
-
const lead = await
|
|
29971
|
-
const context =
|
|
30324
|
+
const lead = await findLeadAgent4();
|
|
30325
|
+
const context = extractMentionContext3(pr.body) || pr.title;
|
|
29972
30326
|
const result = resolveTemplate("github.pull_request.mentioned", {
|
|
29973
30327
|
pr_number: pr.number,
|
|
29974
30328
|
pr_title: pr.title,
|
|
@@ -30014,10 +30368,10 @@ async function handleIssue(event) {
|
|
|
30014
30368
|
return { created: false };
|
|
30015
30369
|
}
|
|
30016
30370
|
const eventKey = `issue-assigned:${repository.full_name}:${issue.number}`;
|
|
30017
|
-
if (
|
|
30371
|
+
if (isDuplicate4(eventKey)) {
|
|
30018
30372
|
return { created: false };
|
|
30019
30373
|
}
|
|
30020
|
-
const lead = await
|
|
30374
|
+
const lead = await findLeadAgent4();
|
|
30021
30375
|
const result = resolveTemplate("github.issue.assigned", {
|
|
30022
30376
|
issue_number: issue.number,
|
|
30023
30377
|
issue_title: issue.title,
|
|
@@ -30062,7 +30416,7 @@ async function handleIssue(event) {
|
|
|
30062
30416
|
console.log(`[GitHub] unassign cancel disabled by config — leaving task untouched (issue #${issue.number})`);
|
|
30063
30417
|
return { created: false };
|
|
30064
30418
|
}
|
|
30065
|
-
const task = await findTaskByVcs2(repository.full_name, issue.number);
|
|
30419
|
+
const task = await findTaskByVcs2(repository.full_name, issue.number, "github");
|
|
30066
30420
|
if (!task) {
|
|
30067
30421
|
console.log(`[GitHub] No active task found for issue #${issue.number} to cancel`);
|
|
30068
30422
|
return { created: false };
|
|
@@ -30080,10 +30434,10 @@ async function handleIssue(event) {
|
|
|
30080
30434
|
return { created: false };
|
|
30081
30435
|
}
|
|
30082
30436
|
const eventKey = `issue-labeled:${repository.full_name}:${issue.number}:${labelName}`;
|
|
30083
|
-
if (
|
|
30437
|
+
if (isDuplicate4(eventKey)) {
|
|
30084
30438
|
return { created: false };
|
|
30085
30439
|
}
|
|
30086
|
-
const lead = await
|
|
30440
|
+
const lead = await findLeadAgent4();
|
|
30087
30441
|
const result = resolveTemplate("github.issue.labeled", {
|
|
30088
30442
|
issue_number: issue.number,
|
|
30089
30443
|
issue_title: issue.title,
|
|
@@ -30123,16 +30477,16 @@ async function handleIssue(event) {
|
|
|
30123
30477
|
if (action !== "opened" && action !== "edited") {
|
|
30124
30478
|
return { created: false };
|
|
30125
30479
|
}
|
|
30126
|
-
const hasMention =
|
|
30480
|
+
const hasMention = detectMention3(issue.title) || detectMention3(issue.body);
|
|
30127
30481
|
if (!hasMention) {
|
|
30128
30482
|
return { created: false };
|
|
30129
30483
|
}
|
|
30130
30484
|
const eventKey = `issue:${repository.full_name}:${issue.number}:${action}`;
|
|
30131
|
-
if (
|
|
30485
|
+
if (isDuplicate4(eventKey)) {
|
|
30132
30486
|
return { created: false };
|
|
30133
30487
|
}
|
|
30134
|
-
const lead = await
|
|
30135
|
-
const context =
|
|
30488
|
+
const lead = await findLeadAgent4();
|
|
30489
|
+
const context = extractMentionContext3(issue.body) || issue.title;
|
|
30136
30490
|
const result = resolveTemplate("github.issue.mentioned", {
|
|
30137
30491
|
issue_number: issue.number,
|
|
30138
30492
|
issue_title: issue.title,
|
|
@@ -30178,21 +30532,21 @@ async function handleComment(event, eventType) {
|
|
|
30178
30532
|
if (action !== "created") {
|
|
30179
30533
|
return skip("action is not created");
|
|
30180
30534
|
}
|
|
30181
|
-
if (!
|
|
30535
|
+
if (!detectMention3(comment.body)) {
|
|
30182
30536
|
return skip("no bot mention");
|
|
30183
30537
|
}
|
|
30184
30538
|
const eventKey = `comment:${repository.full_name}:${comment.id}`;
|
|
30185
|
-
if (
|
|
30539
|
+
if (isDuplicate4(eventKey)) {
|
|
30186
30540
|
return skip("duplicate delivery");
|
|
30187
30541
|
}
|
|
30188
|
-
const lead = await
|
|
30542
|
+
const lead = await findLeadAgent4();
|
|
30189
30543
|
const target = pull_request || issue;
|
|
30190
30544
|
const targetType = pull_request ? "PR" : "Issue";
|
|
30191
30545
|
const targetNumber = target?.number ?? 0;
|
|
30192
30546
|
const targetTitle = target?.title ?? "Unknown";
|
|
30193
30547
|
const targetUrl = target?.html_url ?? comment.html_url;
|
|
30194
|
-
const existingTask = targetNumber ? await findTaskByVcs2(repository.full_name, targetNumber) : null;
|
|
30195
|
-
const context =
|
|
30548
|
+
const existingTask = targetNumber ? await findTaskByVcs2(repository.full_name, targetNumber, "github") : null;
|
|
30549
|
+
const context = extractMentionContext3(comment.body);
|
|
30196
30550
|
const suggestions = getCommandSuggestions("github-comment", targetType);
|
|
30197
30551
|
const relatedTaskSection = existingTask ? `Related task: ${existingTask.id}
|
|
30198
30552
|
\uD83D\uDD00 Consider routing to the same agent working on the related task.
|
|
@@ -30426,7 +30780,7 @@ async function handlePullRequestReview(event) {
|
|
|
30426
30780
|
return { created: false };
|
|
30427
30781
|
}
|
|
30428
30782
|
const eventKey = `pr-review:${repository.full_name}:${pr.number}:${review.id}`;
|
|
30429
|
-
if (
|
|
30783
|
+
if (isDuplicate4(eventKey)) {
|
|
30430
30784
|
return { created: false };
|
|
30431
30785
|
}
|
|
30432
30786
|
const { comments: inlineComments, degraded } = await fetchReviewComments(repository.full_name, pr.number, review.id, installation?.id);
|
|
@@ -30441,12 +30795,12 @@ async function handlePullRequestReview(event) {
|
|
|
30441
30795
|
return { created: false };
|
|
30442
30796
|
}
|
|
30443
30797
|
}
|
|
30444
|
-
const existingTask = await findTaskByVcs2(repository.full_name, pr.number);
|
|
30798
|
+
const existingTask = await findTaskByVcs2(repository.full_name, pr.number, "github");
|
|
30445
30799
|
const isBotCreator = isBotAssignee(pr.user.login);
|
|
30446
30800
|
if (!isBotCreator && !existingTask) {
|
|
30447
30801
|
return { created: false };
|
|
30448
30802
|
}
|
|
30449
|
-
const lead = await
|
|
30803
|
+
const lead = await findLeadAgent4();
|
|
30450
30804
|
const { emoji, label } = getReviewStateInfo(review.state);
|
|
30451
30805
|
const reviewBodySection = review.body ? `
|
|
30452
30806
|
|
|
@@ -30523,46 +30877,46 @@ async function handleWorkflowRun(event) {
|
|
|
30523
30877
|
}
|
|
30524
30878
|
// src/gitlab/auth.ts
|
|
30525
30879
|
init_env_flag();
|
|
30526
|
-
var
|
|
30527
|
-
var
|
|
30528
|
-
var
|
|
30880
|
+
var initialized5 = false;
|
|
30881
|
+
var webhookSecret5 = null;
|
|
30882
|
+
var apiToken3 = null;
|
|
30529
30883
|
var gitlabUrl = "https://gitlab.com";
|
|
30530
30884
|
function isGitLabEnabled() {
|
|
30531
30885
|
return !!process.env.GITLAB_WEBHOOK_SECRET && !isEnvFlagEnabled("GITLAB_DISABLE", false);
|
|
30532
30886
|
}
|
|
30533
30887
|
function initGitLab() {
|
|
30534
|
-
if (
|
|
30888
|
+
if (initialized5)
|
|
30535
30889
|
return;
|
|
30536
30890
|
if (!isGitLabEnabled()) {
|
|
30537
30891
|
console.log("[GitLab] Integration disabled (GITLAB_WEBHOOK_SECRET not set)");
|
|
30538
30892
|
return;
|
|
30539
30893
|
}
|
|
30540
|
-
|
|
30541
|
-
|
|
30894
|
+
webhookSecret5 = process.env.GITLAB_WEBHOOK_SECRET;
|
|
30895
|
+
apiToken3 = process.env.GITLAB_TOKEN ?? null;
|
|
30542
30896
|
gitlabUrl = process.env.GITLAB_URL ?? "https://gitlab.com";
|
|
30543
|
-
|
|
30897
|
+
initialized5 = true;
|
|
30544
30898
|
console.log(`[GitLab] Integration initialized (url: ${gitlabUrl})`);
|
|
30545
30899
|
}
|
|
30546
30900
|
function verifyGitLabWebhook(tokenHeader) {
|
|
30547
|
-
if (!
|
|
30901
|
+
if (!webhookSecret5)
|
|
30548
30902
|
return false;
|
|
30549
30903
|
if (!tokenHeader)
|
|
30550
30904
|
return false;
|
|
30551
|
-
if (tokenHeader.length !==
|
|
30905
|
+
if (tokenHeader.length !== webhookSecret5.length)
|
|
30552
30906
|
return false;
|
|
30553
|
-
return crypto.timingSafeEqual(Buffer.from(tokenHeader), Buffer.from(
|
|
30907
|
+
return crypto.timingSafeEqual(Buffer.from(tokenHeader), Buffer.from(webhookSecret5));
|
|
30554
30908
|
}
|
|
30555
30909
|
function getGitLabToken() {
|
|
30556
|
-
return
|
|
30910
|
+
return apiToken3;
|
|
30557
30911
|
}
|
|
30558
30912
|
function getGitLabUrl() {
|
|
30559
30913
|
return gitlabUrl;
|
|
30560
30914
|
}
|
|
30561
30915
|
var GITLAB_BOT_NAME = process.env.GITLAB_BOT_NAME ?? "agent-swarm-bot";
|
|
30562
30916
|
function resetGitLab() {
|
|
30563
|
-
|
|
30564
|
-
|
|
30565
|
-
|
|
30917
|
+
initialized5 = false;
|
|
30918
|
+
webhookSecret5 = null;
|
|
30919
|
+
apiToken3 = null;
|
|
30566
30920
|
gitlabUrl = "https://gitlab.com";
|
|
30567
30921
|
}
|
|
30568
30922
|
// src/gitlab/handlers.ts
|
|
@@ -30572,7 +30926,7 @@ init_resolver();
|
|
|
30572
30926
|
init_context_key();
|
|
30573
30927
|
|
|
30574
30928
|
// src/gitlab/reactions.ts
|
|
30575
|
-
function
|
|
30929
|
+
function headers4() {
|
|
30576
30930
|
const token = getGitLabToken();
|
|
30577
30931
|
if (!token)
|
|
30578
30932
|
throw new Error("[GitLab] No API token configured");
|
|
@@ -30593,7 +30947,7 @@ async function addGitLabReaction(project, entityType, iid, emojiName) {
|
|
|
30593
30947
|
try {
|
|
30594
30948
|
const resp = await fetch(url, {
|
|
30595
30949
|
method: "POST",
|
|
30596
|
-
headers:
|
|
30950
|
+
headers: headers4(),
|
|
30597
30951
|
body: JSON.stringify({ name: emojiName })
|
|
30598
30952
|
});
|
|
30599
30953
|
if (!resp.ok) {
|
|
@@ -30609,7 +30963,7 @@ async function addGitLabNoteReaction(project, entityType, iid, noteId, emojiName
|
|
|
30609
30963
|
try {
|
|
30610
30964
|
const resp = await fetch(url, {
|
|
30611
30965
|
method: "POST",
|
|
30612
|
-
headers:
|
|
30966
|
+
headers: headers4(),
|
|
30613
30967
|
body: JSON.stringify({ name: emojiName })
|
|
30614
30968
|
});
|
|
30615
30969
|
if (!resp.ok) {
|
|
@@ -30733,33 +31087,33 @@ The CI pipeline has failed. Please investigate and fix the issues.{{@template[co
|
|
|
30733
31087
|
});
|
|
30734
31088
|
|
|
30735
31089
|
// src/gitlab/handlers.ts
|
|
30736
|
-
var
|
|
30737
|
-
var
|
|
30738
|
-
function
|
|
31090
|
+
var processedEvents5 = new Map;
|
|
31091
|
+
var DEDUP_TTL_MS3 = 60000;
|
|
31092
|
+
function isDuplicate5(key) {
|
|
30739
31093
|
const now = Date.now();
|
|
30740
|
-
for (const [k, ts] of
|
|
30741
|
-
if (now - ts >
|
|
30742
|
-
|
|
31094
|
+
for (const [k, ts] of processedEvents5) {
|
|
31095
|
+
if (now - ts > DEDUP_TTL_MS3)
|
|
31096
|
+
processedEvents5.delete(k);
|
|
30743
31097
|
}
|
|
30744
|
-
if (
|
|
31098
|
+
if (processedEvents5.has(key))
|
|
30745
31099
|
return true;
|
|
30746
|
-
|
|
31100
|
+
processedEvents5.set(key, now);
|
|
30747
31101
|
return false;
|
|
30748
31102
|
}
|
|
30749
|
-
function
|
|
31103
|
+
function detectMention4(text) {
|
|
30750
31104
|
if (!text)
|
|
30751
31105
|
return false;
|
|
30752
31106
|
return new RegExp(`@${GITLAB_BOT_NAME}\\b`, "i").test(text);
|
|
30753
31107
|
}
|
|
30754
|
-
function
|
|
31108
|
+
function extractMentionContext4(text) {
|
|
30755
31109
|
return text.replace(new RegExp(`@${GITLAB_BOT_NAME}\\b`, "gi"), "").trim();
|
|
30756
31110
|
}
|
|
30757
|
-
async function
|
|
31111
|
+
async function findLeadAgent5() {
|
|
30758
31112
|
const agents = await getAllAgents2();
|
|
30759
31113
|
return agents.find((a) => a.role === "lead" && a.status === "idle") ?? agents.find((a) => a.role === "lead") ?? null;
|
|
30760
31114
|
}
|
|
30761
|
-
var
|
|
30762
|
-
var
|
|
31115
|
+
var UNMAPPED_NAMESPACE4 = "integration:unmapped:gitlab";
|
|
31116
|
+
var UNMAPPED_TTL_MS4 = 30 * 24 * 60 * 60 * 1000;
|
|
30763
31117
|
var GITLAB_WEBHOOK_ACTOR = { kind: "system", id: "webhook:gitlab" };
|
|
30764
31118
|
async function resolveGitLabSender(user, sampleEventType, sampleContext) {
|
|
30765
31119
|
const existing = await findUserByExternalId("gitlab", user.username);
|
|
@@ -30772,7 +31126,7 @@ async function resolveGitLabSender(user, sampleEventType, sampleContext) {
|
|
|
30772
31126
|
return linked.id;
|
|
30773
31127
|
}
|
|
30774
31128
|
await upsertKv2({
|
|
30775
|
-
namespace:
|
|
31129
|
+
namespace: UNMAPPED_NAMESPACE4,
|
|
30776
31130
|
key: `${user.username}:meta`,
|
|
30777
31131
|
value: {
|
|
30778
31132
|
lastSeenAt: new Date().toISOString(),
|
|
@@ -30780,9 +31134,9 @@ async function resolveGitLabSender(user, sampleEventType, sampleContext) {
|
|
|
30780
31134
|
sampleContext: sampleContext.slice(0, 100)
|
|
30781
31135
|
},
|
|
30782
31136
|
valueType: "json",
|
|
30783
|
-
expiresAt: Date.now() +
|
|
31137
|
+
expiresAt: Date.now() + UNMAPPED_TTL_MS4
|
|
30784
31138
|
});
|
|
30785
|
-
await incrKv2(
|
|
31139
|
+
await incrKv2(UNMAPPED_NAMESPACE4, `${user.username}:count`, 1);
|
|
30786
31140
|
return;
|
|
30787
31141
|
}
|
|
30788
31142
|
async function renderGitLabIdentity(username) {
|
|
@@ -30795,19 +31149,19 @@ async function handleMergeRequest(event) {
|
|
|
30795
31149
|
const requestedByUserId = await resolveGitLabSender(user, "merge_request", `MR !${mr.iid}: ${mr.title}`);
|
|
30796
31150
|
console.log(`[GitLab] MR #${mr.iid} ${action} by ${user.username} in ${repo}`);
|
|
30797
31151
|
const dedupKey = `gitlab-mr-${repo}-${mr.iid}-${action}-${user.username}`;
|
|
30798
|
-
if (
|
|
31152
|
+
if (isDuplicate5(dedupKey)) {
|
|
30799
31153
|
console.log(`[GitLab] Skipping duplicate MR event`);
|
|
30800
31154
|
return { created: false };
|
|
30801
31155
|
}
|
|
30802
|
-
const lead = await
|
|
31156
|
+
const lead = await findLeadAgent5();
|
|
30803
31157
|
switch (action) {
|
|
30804
31158
|
case "open": {
|
|
30805
|
-
const hasMention =
|
|
31159
|
+
const hasMention = detectMention4(mr.description);
|
|
30806
31160
|
if (!hasMention) {
|
|
30807
31161
|
console.log(`[GitLab] MR opened without bot mention, skipping`);
|
|
30808
31162
|
return { created: false };
|
|
30809
31163
|
}
|
|
30810
|
-
const context = mr.description ?
|
|
31164
|
+
const context = mr.description ? extractMentionContext4(mr.description) : "";
|
|
30811
31165
|
const contextSection = context ? `Context: ${context}
|
|
30812
31166
|
|
|
30813
31167
|
` : "";
|
|
@@ -30851,7 +31205,7 @@ async function handleMergeRequest(event) {
|
|
|
30851
31205
|
}
|
|
30852
31206
|
case "close":
|
|
30853
31207
|
case "merge": {
|
|
30854
|
-
const existingTask = await findTaskByVcs2(repo, mr.iid);
|
|
31208
|
+
const existingTask = await findTaskByVcs2(repo, mr.iid, "gitlab");
|
|
30855
31209
|
if (existingTask) {
|
|
30856
31210
|
const reason = action === "merge" ? "MR was merged" : "MR was closed";
|
|
30857
31211
|
console.log(`[GitLab] Cancelling task ${existingTask.id} — ${reason}`);
|
|
@@ -30860,7 +31214,7 @@ async function handleMergeRequest(event) {
|
|
|
30860
31214
|
return { created: false };
|
|
30861
31215
|
}
|
|
30862
31216
|
case "update": {
|
|
30863
|
-
const task = await findTaskByVcs2(repo, mr.iid);
|
|
31217
|
+
const task = await findTaskByVcs2(repo, mr.iid, "gitlab");
|
|
30864
31218
|
if (task) {
|
|
30865
31219
|
console.log(`[GitLab] MR #${mr.iid} updated, active task exists: ${task.id}`);
|
|
30866
31220
|
return { created: false };
|
|
@@ -30879,13 +31233,13 @@ async function handleIssue2(event) {
|
|
|
30879
31233
|
const requestedByUserId = await resolveGitLabSender(user, "issue", `Issue #${issue.iid}: ${issue.title}`);
|
|
30880
31234
|
console.log(`[GitLab] Issue #${issue.iid} ${action} by ${user.username} in ${repo}`);
|
|
30881
31235
|
const dedupKey = `gitlab-issue-${repo}-${issue.iid}-${action}-${user.username}`;
|
|
30882
|
-
if (
|
|
31236
|
+
if (isDuplicate5(dedupKey)) {
|
|
30883
31237
|
return { created: false };
|
|
30884
31238
|
}
|
|
30885
|
-
const lead = await
|
|
31239
|
+
const lead = await findLeadAgent5();
|
|
30886
31240
|
switch (action) {
|
|
30887
31241
|
case "open": {
|
|
30888
|
-
const hasMention =
|
|
31242
|
+
const hasMention = detectMention4(issue.description);
|
|
30889
31243
|
if (!hasMention) {
|
|
30890
31244
|
const isBotAssigned = event.assignees?.some((a) => a.username.toLowerCase() === GITLAB_BOT_NAME.toLowerCase());
|
|
30891
31245
|
if (!isBotAssigned) {
|
|
@@ -30893,7 +31247,7 @@ async function handleIssue2(event) {
|
|
|
30893
31247
|
return { created: false };
|
|
30894
31248
|
}
|
|
30895
31249
|
}
|
|
30896
|
-
const context = issue.description ?
|
|
31250
|
+
const context = issue.description ? extractMentionContext4(issue.description) : "";
|
|
30897
31251
|
const contextSection = context ? `Context: ${context}
|
|
30898
31252
|
|
|
30899
31253
|
` : "";
|
|
@@ -30934,7 +31288,7 @@ async function handleIssue2(event) {
|
|
|
30934
31288
|
return { created: true, taskId: task.id };
|
|
30935
31289
|
}
|
|
30936
31290
|
case "close": {
|
|
30937
|
-
const existingTask = await findTaskByVcs2(repo, issue.iid);
|
|
31291
|
+
const existingTask = await findTaskByVcs2(repo, issue.iid, "gitlab");
|
|
30938
31292
|
if (existingTask) {
|
|
30939
31293
|
console.log(`[GitLab] Cancelling task ${existingTask.id} — issue closed`);
|
|
30940
31294
|
await failTask2(existingTask.id, "Issue was closed");
|
|
@@ -30949,16 +31303,16 @@ async function handleNote(event) {
|
|
|
30949
31303
|
const { user, project, object_attributes: note } = event;
|
|
30950
31304
|
const repo = project.path_with_namespace;
|
|
30951
31305
|
const requestedByUserId = await resolveGitLabSender(user, "note", note.note);
|
|
30952
|
-
if (!
|
|
31306
|
+
if (!detectMention4(note.note)) {
|
|
30953
31307
|
return { created: false };
|
|
30954
31308
|
}
|
|
30955
31309
|
console.log(`[GitLab] Note by ${user.username} in ${repo} (${note.noteable_type})`);
|
|
30956
31310
|
const dedupKey = `gitlab-note-${note.id}`;
|
|
30957
|
-
if (
|
|
31311
|
+
if (isDuplicate5(dedupKey)) {
|
|
30958
31312
|
return { created: false };
|
|
30959
31313
|
}
|
|
30960
|
-
const lead = await
|
|
30961
|
-
const context =
|
|
31314
|
+
const lead = await findLeadAgent5();
|
|
31315
|
+
const context = extractMentionContext4(note.note);
|
|
30962
31316
|
let targetNumber;
|
|
30963
31317
|
let targetUrl;
|
|
30964
31318
|
let eventType;
|
|
@@ -30977,7 +31331,7 @@ async function handleNote(event) {
|
|
|
30977
31331
|
console.log(`[GitLab] Ignoring note on ${note.noteable_type}`);
|
|
30978
31332
|
return { created: false };
|
|
30979
31333
|
}
|
|
30980
|
-
const existingTask = targetNumber ? await findTaskByVcs2(repo, targetNumber) : null;
|
|
31334
|
+
const existingTask = targetNumber ? await findTaskByVcs2(repo, targetNumber, "gitlab") : null;
|
|
30981
31335
|
const existingTaskNote = existingTask ? `
|
|
30982
31336
|
|
|
30983
31337
|
_Note: There's an active task (${existingTask.id}) for this ${entityLabel}._` : "";
|
|
@@ -31032,14 +31386,14 @@ async function handlePipeline(event) {
|
|
|
31032
31386
|
}
|
|
31033
31387
|
const mrIid = event.merge_request.iid;
|
|
31034
31388
|
const dedupKey = `gitlab-pipeline-${pipeline.id}`;
|
|
31035
|
-
if (
|
|
31389
|
+
if (isDuplicate5(dedupKey)) {
|
|
31036
31390
|
return { created: false };
|
|
31037
31391
|
}
|
|
31038
|
-
const existingTask = await findTaskByVcs2(repo, mrIid);
|
|
31392
|
+
const existingTask = await findTaskByVcs2(repo, mrIid, "gitlab");
|
|
31039
31393
|
if (!existingTask) {
|
|
31040
31394
|
return { created: false };
|
|
31041
31395
|
}
|
|
31042
|
-
const lead = await
|
|
31396
|
+
const lead = await findLeadAgent5();
|
|
31043
31397
|
const pipelineResult = resolveTemplate("gitlab.pipeline.failed", {
|
|
31044
31398
|
pipeline_id: pipeline.id,
|
|
31045
31399
|
mr_iid: mrIid,
|
|
@@ -31243,6 +31597,71 @@ function readApiUrlOverrides() {
|
|
|
31243
31597
|
}
|
|
31244
31598
|
}
|
|
31245
31599
|
|
|
31600
|
+
// src/integrations/chat-sdk/facts.ts
|
|
31601
|
+
var SNIPPET_MAX = 80;
|
|
31602
|
+
function snippet2(text) {
|
|
31603
|
+
const flat = text?.replace(/\s+/g, " ").trim();
|
|
31604
|
+
if (!flat)
|
|
31605
|
+
return;
|
|
31606
|
+
return flat.length > SNIPPET_MAX ? `${flat.slice(0, SNIPPET_MAX)}...` : flat;
|
|
31607
|
+
}
|
|
31608
|
+
function personLabel(name, username, fallback) {
|
|
31609
|
+
if (name && username && name !== username)
|
|
31610
|
+
return `${name} (@${username})`;
|
|
31611
|
+
if (username)
|
|
31612
|
+
return `@${username}`;
|
|
31613
|
+
return name || fallback;
|
|
31614
|
+
}
|
|
31615
|
+
function replyIsTopicRoot(raw) {
|
|
31616
|
+
const reply = raw.reply_to_message;
|
|
31617
|
+
return reply !== undefined && (reply.forum_topic_created !== undefined || raw.is_topic_message === true && reply.message_id === raw.message_thread_id);
|
|
31618
|
+
}
|
|
31619
|
+
function isTelegramReplyToBot(raw, botUserId) {
|
|
31620
|
+
const fromId = raw.reply_to_message?.from?.id;
|
|
31621
|
+
return !replyIsTopicRoot(raw) && fromId !== undefined && botUserId !== undefined && String(fromId) === botUserId;
|
|
31622
|
+
}
|
|
31623
|
+
function telegramFacts(raw, message, botUserId) {
|
|
31624
|
+
const reply = raw.reply_to_message;
|
|
31625
|
+
const topicRoot = replyIsTopicRoot(raw);
|
|
31626
|
+
const realReply = reply && !topicRoot ? reply : undefined;
|
|
31627
|
+
const topicName = topicRoot ? reply?.forum_topic_created?.name : undefined;
|
|
31628
|
+
const name = [raw.from?.first_name, raw.from?.last_name].filter(Boolean).join(" ").trim();
|
|
31629
|
+
return {
|
|
31630
|
+
chatType: raw.chat?.type,
|
|
31631
|
+
isForum: raw.chat?.is_forum === true ? true : undefined,
|
|
31632
|
+
title: raw.chat?.title,
|
|
31633
|
+
topic: raw.is_topic_message === true && raw.message_thread_id !== undefined ? topicName ? `"${topicName}"` : `#${raw.message_thread_id}` : undefined,
|
|
31634
|
+
from: personLabel(name || undefined, raw.from?.username, message.author.userId),
|
|
31635
|
+
replyToBot: isTelegramReplyToBot(raw, botUserId),
|
|
31636
|
+
replyToSnippet: snippet2(realReply?.text ?? realReply?.caption)
|
|
31637
|
+
};
|
|
31638
|
+
}
|
|
31639
|
+
function readChatMessageFacts(thread, message) {
|
|
31640
|
+
const raw = message.raw;
|
|
31641
|
+
if (thread.adapter.name === "telegram" && raw && typeof raw === "object") {
|
|
31642
|
+
return telegramFacts(raw, message, thread.adapter.botUserId);
|
|
31643
|
+
}
|
|
31644
|
+
const { fullName, userName, userId } = message.author;
|
|
31645
|
+
return {
|
|
31646
|
+
chatType: thread.isDM ? "dm" : undefined,
|
|
31647
|
+
from: personLabel(fullName || undefined, userName || undefined, userId),
|
|
31648
|
+
replyToBot: message.replyTo?.author.isMe === true,
|
|
31649
|
+
replyToSnippet: snippet2(message.replyTo?.text)
|
|
31650
|
+
};
|
|
31651
|
+
}
|
|
31652
|
+
function formatChatHeaderFacts(adapter, facts, addressed) {
|
|
31653
|
+
const oneLine = (text) => text.replace(/\s+/g, " ").trim();
|
|
31654
|
+
const parts = [adapter];
|
|
31655
|
+
if (facts.chatType)
|
|
31656
|
+
parts.push(facts.title ? `${facts.chatType} "${oneLine(facts.title)}"` : facts.chatType);
|
|
31657
|
+
if (facts.isForum)
|
|
31658
|
+
parts.push(facts.topic ? `forum topic ${oneLine(facts.topic)}` : "forum");
|
|
31659
|
+
parts.push(`from: ${oneLine(facts.from)}`, `addressed: ${addressed}`);
|
|
31660
|
+
if (facts.replyToSnippet)
|
|
31661
|
+
parts.push(`reply-to: "${facts.replyToSnippet}"`);
|
|
31662
|
+
return parts.join(" · ");
|
|
31663
|
+
}
|
|
31664
|
+
|
|
31246
31665
|
// src/integrations/chat-sdk/logger.ts
|
|
31247
31666
|
init_secret_scrubber();
|
|
31248
31667
|
var MAX_ISSUE_CHARS = 300;
|
|
@@ -31334,8 +31753,14 @@ async function loadAdapter(name, config, logger) {
|
|
|
31334
31753
|
const base = { ...config, apiUrl, logger };
|
|
31335
31754
|
switch (name) {
|
|
31336
31755
|
case "telegram": {
|
|
31337
|
-
const {
|
|
31338
|
-
|
|
31756
|
+
const { TelegramAdapter } = await import("./index-zsyx51ap.js");
|
|
31757
|
+
|
|
31758
|
+
class SwarmTelegramAdapter extends TelegramAdapter {
|
|
31759
|
+
isBotMentioned(message, text) {
|
|
31760
|
+
return super.isBotMentioned(message, text) || String(message.from?.id) !== this.botUserId && isTelegramReplyToBot(message, this.botUserId);
|
|
31761
|
+
}
|
|
31762
|
+
}
|
|
31763
|
+
return new SwarmTelegramAdapter({
|
|
31339
31764
|
...base,
|
|
31340
31765
|
allowUnverifiedWebhooks: false,
|
|
31341
31766
|
mentionOnReply: true
|
|
@@ -32383,63 +32808,6 @@ async function attachChatFilesToTask(taskId, fetched) {
|
|
|
32383
32808
|
return unattached;
|
|
32384
32809
|
}
|
|
32385
32810
|
|
|
32386
|
-
// src/integrations/chat-sdk/facts.ts
|
|
32387
|
-
var SNIPPET_MAX = 80;
|
|
32388
|
-
function snippet2(text) {
|
|
32389
|
-
const flat = text?.replace(/\s+/g, " ").trim();
|
|
32390
|
-
if (!flat)
|
|
32391
|
-
return;
|
|
32392
|
-
return flat.length > SNIPPET_MAX ? `${flat.slice(0, SNIPPET_MAX)}...` : flat;
|
|
32393
|
-
}
|
|
32394
|
-
function personLabel(name, username, fallback) {
|
|
32395
|
-
if (name && username && name !== username)
|
|
32396
|
-
return `${name} (@${username})`;
|
|
32397
|
-
if (username)
|
|
32398
|
-
return `@${username}`;
|
|
32399
|
-
return name || fallback;
|
|
32400
|
-
}
|
|
32401
|
-
function telegramFacts(raw, message, botUserId) {
|
|
32402
|
-
const reply = raw.reply_to_message;
|
|
32403
|
-
const replyIsTopicRoot = reply !== undefined && (reply.forum_topic_created !== undefined || raw.is_topic_message === true && reply.message_id === raw.message_thread_id);
|
|
32404
|
-
const realReply = reply && !replyIsTopicRoot ? reply : undefined;
|
|
32405
|
-
const topicName = replyIsTopicRoot ? reply?.forum_topic_created?.name : undefined;
|
|
32406
|
-
const name = [raw.from?.first_name, raw.from?.last_name].filter(Boolean).join(" ").trim();
|
|
32407
|
-
return {
|
|
32408
|
-
chatType: raw.chat?.type,
|
|
32409
|
-
isForum: raw.chat?.is_forum === true ? true : undefined,
|
|
32410
|
-
title: raw.chat?.title,
|
|
32411
|
-
topic: raw.is_topic_message === true && raw.message_thread_id !== undefined ? topicName ? `"${topicName}"` : `#${raw.message_thread_id}` : undefined,
|
|
32412
|
-
from: personLabel(name || undefined, raw.from?.username, message.author.userId),
|
|
32413
|
-
replyToBot: realReply?.from?.id !== undefined && botUserId !== undefined && String(realReply.from.id) === botUserId,
|
|
32414
|
-
replyToSnippet: snippet2(realReply?.text ?? realReply?.caption)
|
|
32415
|
-
};
|
|
32416
|
-
}
|
|
32417
|
-
function readChatMessageFacts(thread, message) {
|
|
32418
|
-
const raw = message.raw;
|
|
32419
|
-
if (thread.adapter.name === "telegram" && raw && typeof raw === "object") {
|
|
32420
|
-
return telegramFacts(raw, message, thread.adapter.botUserId);
|
|
32421
|
-
}
|
|
32422
|
-
const { fullName, userName, userId } = message.author;
|
|
32423
|
-
return {
|
|
32424
|
-
chatType: thread.isDM ? "dm" : undefined,
|
|
32425
|
-
from: personLabel(fullName || undefined, userName || undefined, userId),
|
|
32426
|
-
replyToBot: message.replyTo?.author.isMe === true,
|
|
32427
|
-
replyToSnippet: snippet2(message.replyTo?.text)
|
|
32428
|
-
};
|
|
32429
|
-
}
|
|
32430
|
-
function formatChatHeaderFacts(adapter, facts, addressed) {
|
|
32431
|
-
const oneLine = (text) => text.replace(/\s+/g, " ").trim();
|
|
32432
|
-
const parts = [adapter];
|
|
32433
|
-
if (facts.chatType)
|
|
32434
|
-
parts.push(facts.title ? `${facts.chatType} "${oneLine(facts.title)}"` : facts.chatType);
|
|
32435
|
-
if (facts.isForum)
|
|
32436
|
-
parts.push(facts.topic ? `forum topic ${oneLine(facts.topic)}` : "forum");
|
|
32437
|
-
parts.push(`from: ${oneLine(facts.from)}`, `addressed: ${addressed}`);
|
|
32438
|
-
if (facts.replyToSnippet)
|
|
32439
|
-
parts.push(`reply-to: "${facts.replyToSnippet}"`);
|
|
32440
|
-
return parts.join(" · ");
|
|
32441
|
-
}
|
|
32442
|
-
|
|
32443
32811
|
// src/integrations/chat-sdk/outbound.ts
|
|
32444
32812
|
init_secret_scrubber();
|
|
32445
32813
|
init_event_bus();
|
|
@@ -32515,11 +32883,32 @@ class ChatFileTooLargeError extends Error {
|
|
|
32515
32883
|
this.name = "ChatFileTooLargeError";
|
|
32516
32884
|
}
|
|
32517
32885
|
}
|
|
32886
|
+
var FENCE_LINE = /^ {0,3}(`{3,}|~{3,})/;
|
|
32887
|
+
var NON_HEADING_HASH = /^( {0,3}(?:>[ \t]?)*[ \t]*(?:(?:[-*+]|\d{1,9}[.)])[ \t]+(?:\[[ xX]\][ \t]+)?)?)(#{7,}|#{1,6}(?=[^\s#]))/;
|
|
32888
|
+
function escapeTelegramHashLines(markdown) {
|
|
32889
|
+
let fence;
|
|
32890
|
+
return markdown.split(`
|
|
32891
|
+
`).map((line) => {
|
|
32892
|
+
const marker = FENCE_LINE.exec(line)?.[1];
|
|
32893
|
+
if (fence) {
|
|
32894
|
+
if (marker && marker[0] === fence[0] && marker.length >= fence.length)
|
|
32895
|
+
fence = undefined;
|
|
32896
|
+
return line;
|
|
32897
|
+
}
|
|
32898
|
+
if (marker) {
|
|
32899
|
+
fence = marker;
|
|
32900
|
+
return line;
|
|
32901
|
+
}
|
|
32902
|
+
return line.replace(NON_HEADING_HASH, "$1\\$2");
|
|
32903
|
+
}).join(`
|
|
32904
|
+
`);
|
|
32905
|
+
}
|
|
32518
32906
|
async function postChunks(adapter, target, text) {
|
|
32519
32907
|
const messageIds = [];
|
|
32520
32908
|
let threadId;
|
|
32521
32909
|
for (const chunk of splitChatMessage(text, chatMessageLimit(adapter))) {
|
|
32522
|
-
const
|
|
32910
|
+
const markdown = adapter === "telegram" ? escapeTelegramHashLines(chunk) : chunk;
|
|
32911
|
+
const sent = await target.post({ markdown });
|
|
32523
32912
|
messageIds.push(sent.id);
|
|
32524
32913
|
threadId ??= sent.threadId;
|
|
32525
32914
|
}
|
|
@@ -34251,7 +34640,7 @@ async function resolveBotAccountId() {
|
|
|
34251
34640
|
function resetBotAccountIdCache() {
|
|
34252
34641
|
setCachedBotAccountId(null);
|
|
34253
34642
|
}
|
|
34254
|
-
async function
|
|
34643
|
+
async function findLeadAgent6() {
|
|
34255
34644
|
const agents = await getAllAgents2();
|
|
34256
34645
|
const onlineLead = agents.find((a) => a.isLead && a.status !== "offline");
|
|
34257
34646
|
if (onlineLead)
|
|
@@ -34455,7 +34844,7 @@ async function handleIssueDeleteEvent(event) {
|
|
|
34455
34844
|
}
|
|
34456
34845
|
}
|
|
34457
34846
|
async function createInitialJiraTask(input) {
|
|
34458
|
-
const lead = await
|
|
34847
|
+
const lead = await findLeadAgent6();
|
|
34459
34848
|
const descriptionSection = input.descriptionText ? `
|
|
34460
34849
|
Description:
|
|
34461
34850
|
${input.descriptionText}
|
|
@@ -34493,7 +34882,7 @@ ${input.descriptionText}
|
|
|
34493
34882
|
console.log(`[Jira Sync] Created ${action} task ${task.id} for ${input.issueKey} -> ${lead?.name ?? "unassigned"}`);
|
|
34494
34883
|
}
|
|
34495
34884
|
async function createCommentMentionTask(input) {
|
|
34496
|
-
const lead = await
|
|
34885
|
+
const lead = await findLeadAgent6();
|
|
34497
34886
|
const descriptionSection = input.descriptionText ? `
|
|
34498
34887
|
Description:
|
|
34499
34888
|
${input.descriptionText}
|
|
@@ -34553,7 +34942,7 @@ async function notifySlack(text) {
|
|
|
34553
34942
|
return;
|
|
34554
34943
|
}
|
|
34555
34944
|
try {
|
|
34556
|
-
const { getSlackApp } = await import("./app-
|
|
34945
|
+
const { getSlackApp } = await import("./app-0qp0a2gk.js");
|
|
34557
34946
|
const app = getSlackApp();
|
|
34558
34947
|
if (!app) {
|
|
34559
34948
|
console.warn("[Jira webhook keepalive] Slack not available, cannot send notification");
|
|
@@ -34624,7 +35013,7 @@ async function deleteJiraWebhook(webhookId) {
|
|
|
34624
35013
|
console.log(`[Jira webhook keepalive] Deleted webhook id=${webhookId}`);
|
|
34625
35014
|
}
|
|
34626
35015
|
async function overwriteWebhookIds(next) {
|
|
34627
|
-
const { getDbClient } = await import("./db-
|
|
35016
|
+
const { getDbClient } = await import("./db-7gbc53fd.js");
|
|
34628
35017
|
await getDbClient().transaction(async (tx) => {
|
|
34629
35018
|
const row = await tx.get("SELECT metadata FROM oauth_apps WHERE provider = 'jira'");
|
|
34630
35019
|
if (!row) {
|
|
@@ -34731,7 +35120,7 @@ function stopJiraWebhookKeepalive() {
|
|
|
34731
35120
|
}
|
|
34732
35121
|
|
|
34733
35122
|
// src/jira/app.ts
|
|
34734
|
-
var
|
|
35123
|
+
var initialized6 = false;
|
|
34735
35124
|
function isJiraEnabled() {
|
|
34736
35125
|
if (isEnvFlagEnabled("JIRA_DISABLE", false))
|
|
34737
35126
|
return false;
|
|
@@ -34743,12 +35132,12 @@ function resetJira() {
|
|
|
34743
35132
|
resetBotAccountIdCache();
|
|
34744
35133
|
teardownJiraOutboundSync();
|
|
34745
35134
|
stopJiraWebhookKeepalive();
|
|
34746
|
-
|
|
35135
|
+
initialized6 = false;
|
|
34747
35136
|
}
|
|
34748
35137
|
async function initJira() {
|
|
34749
|
-
if (
|
|
35138
|
+
if (initialized6)
|
|
34750
35139
|
return isJiraEnabled();
|
|
34751
|
-
|
|
35140
|
+
initialized6 = true;
|
|
34752
35141
|
if (!isJiraEnabled()) {
|
|
34753
35142
|
console.log("[Jira] Integration disabled or JIRA_CLIENT_ID not set");
|
|
34754
35143
|
return false;
|
|
@@ -34805,7 +35194,7 @@ function synthesizeDeliveryId(body, rawBody) {
|
|
|
34805
35194
|
const hash = createHash2("sha256").update(rawBody).digest("hex").slice(0, 16);
|
|
34806
35195
|
return `${event}:${ts}:${entityId}:${hash}`;
|
|
34807
35196
|
}
|
|
34808
|
-
async function
|
|
35197
|
+
async function isDuplicateDelivery2(deliveryId) {
|
|
34809
35198
|
return await hasTrackerDelivery("jira", deliveryId);
|
|
34810
35199
|
}
|
|
34811
35200
|
async function markDelivery(externalId, deliveryId) {
|
|
@@ -34828,7 +35217,7 @@ async function handleJiraWebhook(pathToken, rawBody) {
|
|
|
34828
35217
|
return { status: 200, body: { status: "ignored", reason: "invalid-json" } };
|
|
34829
35218
|
}
|
|
34830
35219
|
const deliveryId = synthesizeDeliveryId(parsed, rawBody);
|
|
34831
|
-
if (await
|
|
35220
|
+
if (await isDuplicateDelivery2(deliveryId)) {
|
|
34832
35221
|
return { status: 200, body: { status: "duplicate" } };
|
|
34833
35222
|
}
|
|
34834
35223
|
const event = String(parsed.webhookEvent ?? "");
|
|
@@ -106647,15 +107036,15 @@ async function _fetchIssueGatingInfo(issueId) {
|
|
|
106647
107036
|
const labelNames = (json.data?.issue?.labels?.nodes ?? []).map((n) => n?.name ?? "").filter((n) => n.length > 0);
|
|
106648
107037
|
return { stateType, labelNames };
|
|
106649
107038
|
}
|
|
106650
|
-
async function
|
|
107039
|
+
async function findLeadAgent7() {
|
|
106651
107040
|
const agents = await getAllAgents2();
|
|
106652
107041
|
const onlineLead = agents.find((a) => a.isLead && a.status !== "offline");
|
|
106653
107042
|
if (onlineLead)
|
|
106654
107043
|
return onlineLead;
|
|
106655
107044
|
return agents.find((a) => a.isLead) ?? null;
|
|
106656
107045
|
}
|
|
106657
|
-
var
|
|
106658
|
-
var
|
|
107046
|
+
var UNMAPPED_NAMESPACE5 = "integration:unmapped:linear";
|
|
107047
|
+
var UNMAPPED_TTL_MS5 = 30 * 24 * 60 * 60 * 1000;
|
|
106659
107048
|
var LINEAR_WEBHOOK_ACTOR = { kind: "system", id: "webhook:linear" };
|
|
106660
107049
|
var APP_USER_ID_NAMESPACE = "integration:linear:bot-app-user-id";
|
|
106661
107050
|
async function getStoredAppUserId(workspaceId) {
|
|
@@ -106686,7 +107075,7 @@ async function resolveLinearActor(linearUserId, email, name, workspaceId, sample
|
|
|
106686
107075
|
return linked.id;
|
|
106687
107076
|
}
|
|
106688
107077
|
await upsertKv2({
|
|
106689
|
-
namespace:
|
|
107078
|
+
namespace: UNMAPPED_NAMESPACE5,
|
|
106690
107079
|
key: `${linearUserId}:meta`,
|
|
106691
107080
|
value: {
|
|
106692
107081
|
lastSeenAt: new Date().toISOString(),
|
|
@@ -106694,9 +107083,9 @@ async function resolveLinearActor(linearUserId, email, name, workspaceId, sample
|
|
|
106694
107083
|
sampleContext: sampleContext ? sampleContext.slice(0, 100) : null
|
|
106695
107084
|
},
|
|
106696
107085
|
valueType: "json",
|
|
106697
|
-
expiresAt: Date.now() +
|
|
107086
|
+
expiresAt: Date.now() + UNMAPPED_TTL_MS5
|
|
106698
107087
|
});
|
|
106699
|
-
await incrKv2(
|
|
107088
|
+
await incrKv2(UNMAPPED_NAMESPACE5, `${linearUserId}:count`, 1);
|
|
106700
107089
|
return;
|
|
106701
107090
|
}
|
|
106702
107091
|
var REQUEST_SECTION_LABEL = "Request (comment that opened this session)";
|
|
@@ -106808,7 +107197,7 @@ async function handleAgentSessionEvent(event) {
|
|
|
106808
107197
|
}
|
|
106809
107198
|
return;
|
|
106810
107199
|
}
|
|
106811
|
-
const lead = await
|
|
107200
|
+
const lead = await findLeadAgent7();
|
|
106812
107201
|
const sessionSection = sessionUrl ? `
|
|
106813
107202
|
Session: ${sessionUrl}` : "";
|
|
106814
107203
|
const requestSection = buildSessionRequestSection(event, actorName);
|
|
@@ -107012,7 +107401,7 @@ async function handleAgentSessionPrompted(event) {
|
|
|
107012
107401
|
return;
|
|
107013
107402
|
}
|
|
107014
107403
|
}
|
|
107015
|
-
const lead = await
|
|
107404
|
+
const lead = await findLeadAgent7();
|
|
107016
107405
|
const activity = event.agentActivity;
|
|
107017
107406
|
const promptUser = activity?.user;
|
|
107018
107407
|
const promptedActorLinearId = promptUser ? String(promptUser.id ?? "") : "";
|
|
@@ -107294,7 +107683,7 @@ function shouldSkipForLoopPrevention2(sync) {
|
|
|
107294
107683
|
}
|
|
107295
107684
|
|
|
107296
107685
|
// src/linear/app.ts
|
|
107297
|
-
var
|
|
107686
|
+
var initialized7 = false;
|
|
107298
107687
|
var unsubscribeRefresh = null;
|
|
107299
107688
|
function isLinearEnabled() {
|
|
107300
107689
|
if (isEnvFlagEnabled("LINEAR_DISABLE", false))
|
|
@@ -107309,12 +107698,12 @@ function resetLinear() {
|
|
|
107309
107698
|
unsubscribeRefresh();
|
|
107310
107699
|
unsubscribeRefresh = null;
|
|
107311
107700
|
}
|
|
107312
|
-
|
|
107701
|
+
initialized7 = false;
|
|
107313
107702
|
}
|
|
107314
107703
|
async function initLinear() {
|
|
107315
|
-
if (
|
|
107704
|
+
if (initialized7)
|
|
107316
107705
|
return isLinearEnabled();
|
|
107317
|
-
|
|
107706
|
+
initialized7 = true;
|
|
107318
107707
|
if (!isLinearEnabled()) {
|
|
107319
107708
|
console.log("[Linear] Integration disabled or LINEAR_CLIENT_ID not set");
|
|
107320
107709
|
return false;
|
|
@@ -108019,7 +108408,7 @@ async function reloadGlobalConfigsAndIntegrations() {
|
|
|
108019
108408
|
return runWithoutRequestAuth(() => reloadGlobalConfigsAndIntegrationsInner());
|
|
108020
108409
|
}
|
|
108021
108410
|
async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
108022
|
-
const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-
|
|
108411
|
+
const { getEmbeddingProvider, resetEmbeddingProvider } = await import("./index-sepja052.js");
|
|
108023
108412
|
const wasEmbeddingsConfigured = getEmbeddingProvider().isConfigured();
|
|
108024
108413
|
const updated = await loadGlobalConfigsIntoEnv(true);
|
|
108025
108414
|
await syncTelemetryEnabled("settings").catch((err) => {
|
|
@@ -108035,10 +108424,10 @@ async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
|
108035
108424
|
integrations.push("embeddings");
|
|
108036
108425
|
}
|
|
108037
108426
|
if (!wasEmbeddingsConfigured && isEmbeddingsConfigured) {
|
|
108038
|
-
import("./boot-reembed-
|
|
108427
|
+
import("./boot-reembed-n4wq5dd2.js").then(({ runBootReembed }) => runBootReembed()).catch((err) => {
|
|
108039
108428
|
console.error("[config-reload] memory backfill failed (non-fatal):", err);
|
|
108040
108429
|
});
|
|
108041
|
-
import("./boot-reembed-
|
|
108430
|
+
import("./boot-reembed-4xwq5tg0.js").then(({ runBootReembedScripts }) => runBootReembedScripts()).catch((err) => {
|
|
108042
108431
|
console.error("[config-reload] script backfill failed (non-fatal):", err);
|
|
108043
108432
|
});
|
|
108044
108433
|
}
|
|
@@ -108060,6 +108449,11 @@ async function reloadGlobalConfigsAndIntegrationsInner() {
|
|
|
108060
108449
|
teardownAzureDevOpsOutbound();
|
|
108061
108450
|
if (isAzureDevOpsEnabled())
|
|
108062
108451
|
initAzureDevOpsOutbound();
|
|
108452
|
+
resetBitbucket();
|
|
108453
|
+
resetBitbucketBotCache();
|
|
108454
|
+
initBitbucket();
|
|
108455
|
+
if (isBitbucketEnabled())
|
|
108456
|
+
integrations.push("bitbucket");
|
|
108063
108457
|
resetLinear();
|
|
108064
108458
|
if (await initLinear())
|
|
108065
108459
|
integrations.push("linear");
|
|
@@ -115538,14 +115932,14 @@ var prMatcher = (content) => {
|
|
|
115538
115932
|
}
|
|
115539
115933
|
return results;
|
|
115540
115934
|
};
|
|
115541
|
-
function
|
|
115935
|
+
function escapeRegExp3(value) {
|
|
115542
115936
|
return value.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&");
|
|
115543
115937
|
}
|
|
115544
115938
|
function agentFsPathRegex() {
|
|
115545
115939
|
const appHosts = getConfiguredAppUrls().flatMap((value) => {
|
|
115546
115940
|
try {
|
|
115547
115941
|
const url = new URL(value);
|
|
115548
|
-
return [
|
|
115942
|
+
return [escapeRegExp3(`${url.host}${url.pathname.replace(/\/+$/, "")}`)];
|
|
115549
115943
|
} catch {
|
|
115550
115944
|
return [];
|
|
115551
115945
|
}
|
|
@@ -130365,7 +130759,7 @@ var registerScriptConnectionsTool = (server) => {
|
|
|
130365
130759
|
};
|
|
130366
130760
|
// src/tools/script-delete.ts
|
|
130367
130761
|
init_zod();
|
|
130368
|
-
var SCRIPT_DELETE_DESCRIPTION = "
|
|
130762
|
+
var SCRIPT_DELETE_DESCRIPTION = "Permanently remove a swarm-shared script and all its versions from the catalog. This cannot be undone.";
|
|
130369
130763
|
var registerScriptDeleteTool = (server) => {
|
|
130370
130764
|
createToolRegistrar(server)("script-delete", {
|
|
130371
130765
|
title: "Script Delete",
|
|
@@ -134934,7 +135328,7 @@ async function emitBudgetRefusalSideEffects(ctx, inserted) {
|
|
|
134934
135328
|
console.warn(`[budget-refusal-notify] Failed to create follow-up task for budget refusal (task=${ctx.task.id.slice(0, 8)}): ${err}`);
|
|
134935
135329
|
}
|
|
134936
135330
|
}
|
|
134937
|
-
import("./event-bus-
|
|
135331
|
+
import("./event-bus-3z78ep5n.js").then(({ workflowEventBus }) => {
|
|
134938
135332
|
workflowEventBus.emit("task.budget_refused", {
|
|
134939
135333
|
taskId: ctx.task.id,
|
|
134940
135334
|
agentId: ctx.agentId,
|
|
@@ -135985,7 +136379,7 @@ var registerCreateWorkflowTool = (server) => {
|
|
|
135985
136379
|
` + "- CROSS-NODE DATA: To use output from an upstream node, you MUST declare an 'inputs' mapping on the downstream node. " + 'Example: inputs: { "cityData": "generate-city" } → then use {{cityData.taskOutput.field}} in config templates. ' + "Without 'inputs', built-in trigger/input/workflow/swarm/run context remains available, but upstream outputs do not. " + "Agent-task templates may interpolate trigger and declared upstream aliases. SECURITY: executable source for script/swarm-script nodes does not: " + "inline script source allows only input/workflow/swarm/run values, while named swarm-script source is not workflow-interpolated. " + `Pass dynamic trigger or upstream values through config.args (argv for inline scripts; the args object for swarm-script).
|
|
135986
136380
|
` + "- STRUCTURED OUTPUT: For agent-task nodes, put outputSchema inside 'config' to validate the agent's raw JSON output. " + `Node-level outputSchema validates the executor's return ({taskId, taskOutput}), which is different.
|
|
135987
136381
|
` + `- Agent-task config: { template, outputSchema?, agentId?, tags?, priority?, dir?, vcsRepo?, model? }.
|
|
135988
|
-
` + "- FOREACH NODE: type 'foreach'
|
|
136382
|
+
` + "- FOREACH NODE: type 'foreach' runs its body once per item. Config: " + "{ over: <array or exact {{input}} token>, itemKey: <property name>, body: { type: <any executor except foreach>, config: {...} }, " + "concurrency?: <integer >= 1, items in flight; unbounded when absent>, failurePolicy?: 'fail-fast' | 'collect-outcomes' }. " + "The body config is interpolated once per item with {{item.*}} and {{index}}. Child steps use synthetic IDs " + "'<foreachNodeId>#<itemKey>'; the parent waits for every child and exposes one aggregate result to successors. " + "failurePolicy defaults from onNodeFailure ('continue' = collect-outcomes, else fail-fast); fail-fast cancels queued items. " + `retry-workflow-run on a failed fan-out reruns only failed and cancelled items.
|
|
135989
136383
|
` + "- TRIGGER SCHEMA: Optional 'triggerSchema' is a JSON-Schema object that validates incoming trigger payloads. " + "Supported keywords: type, required, properties, enum, const, items (recursive into arrays). " + `Other JSON-Schema keywords (oneOf/anyOf/$ref/pattern/format/additionalProperties) are silently ignored.
|
|
135990
136384
|
` + "- WEBHOOK VERIFICATION: Webhook triggers use hmacSecret for all verification formats. " + "Omit verification for legacy HMAC-SHA256 over the raw body with fallback header scanning; " + "or set verification to { format: 'hmac-sha256', header }, { format: 'timestamped-hmac-sha256', header, toleranceSeconds? }, " + "{ format: 'token-equality', header }, or { format: 'standard-webhooks', toleranceSeconds? } " + "(standardwebhooks.com: webhook-id/webhook-timestamp/webhook-signature headers, hmacSecret is the whsec_ signing secret). Example: { type: 'webhook', hmacSecret: 'secret.SUPERAGENT_WEBHOOK_SECRET', " + `verification: { format: 'timestamped-hmac-sha256', header: 'X-Superagent-Signature', toleranceSeconds: 300 } }.
|
|
135991
136385
|
` + "- WAIT NODE: type 'wait' pauses a workflow for a duration or until a named workflowEventBus event arrives. " + "See runbooks/workflows.md#wait-nodes for config shapes, ordering caveats, and built-in event names.",
|
|
@@ -137032,4 +137426,4 @@ async function createServer(opts = {}) {
|
|
|
137032
137426
|
return server;
|
|
137033
137427
|
}
|
|
137034
137428
|
|
|
137035
|
-
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, scopeFromAttachment, backingProviderId, transcribeAudioNotes, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, isCookieSafePageId, extractPageSession, extractLegacyPageSession, extractAndVerifyCookie, pageSessionSetCookies, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, MCP_MAX_TOOL_INPUT_ELEMENTS, MCP_MAX_REQUEST_BODY_BYTES, userCtx, requestPrincipal, agentFirstPrincipal, rejectGuest, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, MemoryKeyError, refreshLinks, indexMemoryContent, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, sessionAccessTopic, sessionPresenceRoot, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };
|
|
137429
|
+
export { DEFAULT_NEGOTIATED_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, isJSONRPCRequest, isJSONRPCResultResponse, isJSONRPCErrorResponse, JSONRPCMessageSchema, isInitializeRequest, McpServer, isGitHubEnabled, initGitHub, verifyWebhookSignature, isAgentMailEnabled, initAgentMail, verifyAgentMailWebhook, resolveIdentity, renderIdentity, createAdditiveBuffer, taskModelPin, resumedTaskModelSelection, listHarnessModelSupport, recordHarnessModelSupport, agentRanModel, getAgentHarnessCliVersion, setAgentHarnessCliVersion, sanitizeModelTierOverrides, parseModelTierOverridesHeader, setAgentModelTierOverrides, previewModelTiers, recordClaimModelResolution, harnessModelErrorFor, poolTaskRunsOnHarness, explicitModelError, explicitModelErrorForAgent, referencedBundlePaths, skillDirs, TaskCreationBlockedError, recordUnmappedIdentity, MAX_TASK_ATTACHMENT_BYTES, recordTaskAttachmentUpload, scopeFromAttachment, backingProviderId, transcribeAudioNotes, buildEffectiveText, bufferedFileFailures, fetchSlackFiles, createSlackTaskWithFiles, notifySlackFileFailures, isRuntimePoolWakeable, isAgentReachable, hasOtherUserMention, broadcastMatches, routeMessage, extractTaskFromMessage, extractSlackMessageText, recoverIncompleteRuns, handleWebhookTrigger, verifyHmacSignature, WebhookError, snapshotAndUpdateWorkflow, RawLlmConfigSchema, RawLlmOutputSchema, executeRawLlm, getExecutorRegistry2, initWorkflows2, dispatchScheduleTarget, calculateNextRun2, startScheduler2, stopScheduler2, runScheduleNow2, ExtensionAssetConflictError, ExtensionOwnershipError, getExtensionFiles, getExtensionById, getExtensionByName, listExtensions, listExtensionVersions, updateExtensionMeta, listExtensionRuns, SDK_ALLOWLIST, mcpToolNameForSdkMethod, mcpOverflowAuthError, hasKvViewArgs, resolveKvView, toolErr, createToolRegistrar, handleMcpBridge, Redacted, SCRIPT_SDK_RESPONSE_LIMIT_BYTES, readScriptSdkJsonResponse, ExtensionConfigError, ExtensionLifecycleError, setExtensionLoopbackBaseUrl, enableExtension, disableExtension, activateVersion, ExtensionAssetsInvalidError, installExtensionWithAssets, uninstallExtension, reloadExtension, loadEnabledExtensions, stopExtensionRuntime, ExtensionAbortedError2, isRegistered2, isExtensionAgentId2, getExtensionBridgeToken2, resolveBridgeCallOrigin2, extensionIdForAgent2, runContext2, registerLoaded2, unregister2, listRegistered2, dispatchPre2, dispatchPost2, stripSiblingBlock, createTaskWithSiblingAwareness, isInboxAllowed, isSenderAllowed, handleMessageReceived, isAzureDevOpsEnabled, initAzureDevOps, verifyAzureDevOpsWebhook, repointTrackerSyncBySwarmId, isAzureDevOpsUrl, canonicalAzureDevOpsRepoUrl, parseAzureDevOpsRepoUrl, createdPullRequestOf, commentedPayloadOf, handlePullRequestCreated, handlePullRequestCommented, handleWorkItemCreated, handleWorkItemUpdated, handleWorkItemCommented, handleWorkItemDeleted, handleWorkItemRestored, initAzureDevOpsOutbound, AGENT_MAX_TASKS_CONFIG_KEY, reconcileAgentMaxTasksPolicy, resetAgentMaxTasksMirror, upsertSwarmConfigWithPolicyMirror, runtimeStaleThresholdMinutes, upsertRuntimeInstance, getRuntimeInstanceById, insertProvisioningRuntime, markRuntimeTerminated, touchRuntimeInstance, countActiveRuntimeInstancesForAgent, listRuntimeInstancesForAgent, setRuntimeCredentialReady, reconcileAgentStatusFromRuntimes, agentsWithLiveRuntime, expireStaleRuntimeInstances, listRuntimeInstancesForPool, enqueueAuditRow, enqueueAdmissionRow, flushAuditBuffer, startAuditWriter, stopAuditWriter, startAuditGc, stopAuditGc, getTelemetryIngestAnchor, initApiTelemetry, syncTelemetryEnabled, isBitbucketEnabled, initBitbucket, verifyBitbucketWebhook, isDuplicateDelivery, markDeliveryProcessed, pullRequestEventOf, pullRequestCommentEventOf, handlePullRequestCreated2, handlePullRequestCommentCreated, handlePullRequestClosed, handlePullRequest, handleIssue, handleComment, handlePullRequestReview, handleCheckRun, handleCheckSuite, handleWorkflowRun, isGitLabEnabled, initGitLab, verifyGitLabWebhook, handleMergeRequest, handleIssue2, handleNote, handlePipeline, isChatSdkEnabled, getChatSdkConfig, errorMessage, resolveAdapterApiUrl, trackBackground, TelegramBotApiError, callTelegramBotApi, isTrustedTeamsServiceUrl, isChatSdkStopping, startChatSdk, getChatInstance, isChatAdapterConfigured, getChatSdkHealth, stopChatSdk, getJiraMetadata, updateJiraMetadata, clearJiraMetadata, registerJiraWebhook, deleteJiraWebhook, isJiraEnabled, initJira, handleJiraWebhook, handleAgentSessionEvent, handleIssueUpdate, handleIssueDelete, handleAgentSessionPrompted, isLinearEnabled, initLinear, isCookieSafePageId, extractPageSession, extractLegacyPageSession, extractAndVerifyCookie, pageSessionSetCookies, resolveHttpRequestAuth, loadGlobalConfigsIntoEnv, reloadGlobalConfigsAndIntegrations, scheduleIntegrationsReload, handleCore, MCP_MAX_TOOL_INPUT_ELEMENTS, MCP_MAX_REQUEST_BODY_BYTES, userCtx, requestPrincipal, agentFirstPrincipal, rejectGuest, handleApps, cancelApprovalRequest, cancelApprovalRequestAndRun, getUserCommsPrefs, getTaskDetailsInputSchema, getTaskDetailsOutputSchema, getTaskDetailsHandler, cancelTaskInputSchema, cancelTaskOutputSchema, cancelTaskHandler, executeReadOnlyQuery, assertSelectOnlyQuery, handleDbQuery, snapshotMetric, AssetKeyAuthorizationError, authorizeAssetKeyWrite, getPageEditCounter, snapshotPage, assertOAuthAppUrlsSafe, assertOAuthEgressUrlSafe, listOAuthPresets, listOAuthPresetIds, getOAuthPreset, hydrateOAuthAppFromPreset, scopedResourceScopeIdSchema, resolveScopedResourceId, MemoryKeyError, refreshLinks, indexMemoryContent, dedupeMemoryDocumentIds, recordMemoryAccesses, recordRetrievals, ExplicitSelfDuplicateError, applyRating, shouldPersistAutomaticTaskMemory, REBOOT_RETRY_PIN_TAG, getPinCandidateAgent, resolveLeadOnlyRecoveryAssignment, getResumeGeneration, getNextResumeGeneration, inheritedModelSelection, createWorkerTaskFollowUp, createResumeFollowUp, createRerouteDecisionTask, createPoolStarvationDecisionTask, guardTerminalTaskResultWrite, getTasksInputSchema, getTasksOutputSchema, getTasksHandler, reservedNamespaceError, reservedRoomKeyError, updateMcpServerChecked, updateTouchesStdioExecution, canReadMemory, getLinksForMemory, expandCandidatesWithGraph, isApiDraining, drainApi, markKapsoMessageRead, sendKapsoReaction, getKapsoConfig, getKapsoNumberMapping, markKapsoMessageSeen, changesAllowMerge, updateSwarmRepoChecked, getCombConfig, resolveRoomNamespace, roomRequestInfo, authorizeRoomNamespace, sessionAccessTopic, sessionPresenceRoot, RoomOperationSchema, removeAwarenessStates, roomTopic, decodeRoomSnapshot, roomView, getRoom, changeRoom, applyRoomUpdate, resetRoom, sweepRooms, closeRooms, removeNamespaceRooms, MEMORY_KEYS_DEFAULT_PREFIX, MEMORY_KEYS_MAX_LIMIT, estimateTokens, posteriorMean, listMemoryKeys, checkChunkIntegrity, getMemoryChunks, getPosteriorsByIds, createEvent, createEventsBatch, getEventCountsFiltered, getEventsFiltered, mergeScheduleTiming, validateRecurringTiming, checkOutputSchemaShape, sendTaskOutputSchema, sendTaskHandler, steerTaskUserInputSchema, steerTaskOutputSchema, steerTaskHandler, canClaim, emitBudgetRefusalSideEffects, workflowModelErrors, patchWorkflowDefinition, resolveScriptsOnlyMode, ALL_CAPABILITIES, hasCapability, getEnabledCapabilities, createServer };
|