@desplega.ai/agent-swarm 2.4.4 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (382) hide show
  1. package/README.md +4 -2
  2. package/dist/{acp-adapter-thq04adh.js → acp-adapter-11gp67nr.js} +8 -6
  3. package/dist/{actions-j6ywh6x5.js → actions-8p2kze8j.js} +24 -22
  4. package/dist/{amp-adapter-k8b5xmj8.js → amp-adapter-z4qvhacj.js} +2 -2
  5. package/dist/{anthropic-messages-g6pqmqk4.js → anthropic-messages-txs190dd.js} +17 -20
  6. package/dist/{app-rb7vc02s.js → app-0qp0a2gk.js} +3 -3
  7. package/dist/{assistant-ftta1zjf.js → assistant-jedd3ktm.js} +27 -25
  8. package/dist/{azure-openai-responses-9dbmj346.js → azure-openai-responses-9kfwhmn7.js} +18 -13
  9. package/dist/{boot-reembed-xns7h5h9.js → boot-reembed-4xwq5tg0.js} +1 -1
  10. package/dist/{boot-reembed-srp6v6af.js → boot-reembed-n4wq5dd2.js} +1 -1
  11. package/dist/{boot-scrub-sweep-3qqrh2mz.js → boot-scrub-sweep-69h90xcq.js} +4 -4
  12. package/dist/{boot-seeds-9ks8hce7.js → boot-seeds-3vn0m9sg.js} +4 -4
  13. package/dist/{claude-adapter-k5ksyres.js → claude-adapter-221mvad5.js} +8 -6
  14. package/dist/{claude-managed-adapter-h2y889ge.js → claude-managed-adapter-gt6pa35d.js} +2 -2
  15. package/dist/{claude-managed-setup-n5a5eqks.js → claude-managed-setup-c3hp36ph.js} +4 -4
  16. package/dist/{claude-sdk-session-2j3j4kwn.js → claude-sdk-session-8thjsk5e.js} +9729 -9628
  17. package/dist/{cli-b9fcxxev.js → cli-007cnhm1.js} +50 -4
  18. package/dist/{cli-j4rqdf2n.js → cli-03vpq45j.js} +2 -2
  19. package/dist/{cli-amyhm3gj.js → cli-0y6f0ckq.js} +1 -1
  20. package/dist/{cli-4dg55wsk.js → cli-0z3vjrpm.js} +1 -1
  21. package/dist/{cli-pccfmtb5.js → cli-179xcyky.js} +11 -11
  22. package/dist/{cli-3r8samv3.js → cli-1f0gp9vz.js} +3 -2
  23. package/dist/{cli-hj3debgw.js → cli-1pr672hz.js} +3 -3
  24. package/dist/{cli-0bqteszy.js → cli-2nf3b08t.js} +328 -25
  25. package/dist/{cli-t7cyef5g.js → cli-36j4jnk3.js} +4 -4
  26. package/dist/{cli-er83cjbn.js → cli-3qv8naq8.js} +527 -231
  27. package/dist/cli-3zwye9sn.js +1193 -0
  28. package/dist/{cli-60cgh1rv.js → cli-459fk97x.js} +7 -7
  29. package/dist/{cli-xj0re5tm.js → cli-4w24f7z3.js} +1 -1
  30. package/dist/{cli-v3yr2gbg.js → cli-5kzk3472.js} +2198 -968
  31. package/dist/{cli-h7gc0b4r.js → cli-5m84zd2k.js} +55 -18
  32. package/dist/{cli-w6nadkh4.js → cli-5rvg1ddk.js} +5 -5
  33. package/dist/{cli-dvkmp9bt.js → cli-6ctwrf1z.js} +20 -10
  34. package/dist/{cli-9qtjfd60.js → cli-6rg2jn2y.js} +3 -2
  35. package/dist/{cli-2v045xyf.js → cli-7bwtc6yx.js} +3 -3
  36. package/dist/{cli-3cgngyd8.js → cli-7g40g8hq.js} +35 -17
  37. package/dist/{cli-q6r7t299.js → cli-92mqenkc.js} +2379 -154
  38. package/dist/{cli-cynvc9fj.js → cli-9ce2xw98.js} +8 -8
  39. package/dist/{cli-gqvh8d8a.js → cli-bgdtv62r.js} +36 -22
  40. package/dist/{cli-wxbn3yfx.js → cli-cz5nmdxt.js} +2 -2
  41. package/dist/{cli-wt645v7q.js → cli-dabehxhp.js} +1 -1
  42. package/dist/{cli-vfha21c9.js → cli-e5bxnjps.js} +2 -2
  43. package/dist/{cli-p20r8w42.js → cli-fcc5qe3f.js} +763 -268
  44. package/dist/{cli-1ephgwnq.js → cli-fes51ya2.js} +3 -3
  45. package/dist/{cli-1d70crsy.js → cli-ftmq4nvk.js} +2 -2
  46. package/dist/{cli-qkhc5aqy.js → cli-fy1jyyym.js} +13 -13
  47. package/dist/{cli-s95dknxh.js → cli-g1cw7xtt.js} +1 -1
  48. package/dist/{cli-qje9k2nh.js → cli-g9ypd5en.js} +12 -2
  49. package/dist/{cli-74c1wpm0.js → cli-gpv60278.js} +1 -1
  50. package/dist/{cli-pemywhfq.js → cli-ha9rmwgq.js} +2 -1
  51. package/dist/{cli-bnz0r3kc.js → cli-j1eghqfm.js} +5 -5
  52. package/dist/{cli-2zqpkvtt.js → cli-jpxsrxcb.js} +1 -1
  53. package/dist/{cli-ejs3m1sx.js → cli-kxpfx2xr.js} +1 -1
  54. package/dist/{cli-37yb7307.js → cli-mbfj11fq.js} +1 -1
  55. package/dist/{cli-pnp2j5zg.js → cli-mmhj8vd7.js} +2 -2
  56. package/dist/{cli-xf234ws8.js → cli-n4c8e3s5.js} +2 -0
  57. package/dist/{cli-a0kcty51.js → cli-n6kmqngw.js} +2 -2
  58. package/dist/{cli-te6b5wvg.js → cli-nnvjb17s.js} +3 -3
  59. package/dist/{cli-1dmcq2eh.js → cli-nzfnt2gs.js} +1 -1
  60. package/dist/{cli-625tb7aq.js → cli-p859hcc8.js} +2 -2
  61. package/dist/{cli-smvcw9z5.js → cli-pasyvjmm.js} +1 -1
  62. package/dist/cli-pkaqk57w.js +128 -0
  63. package/dist/{cli-8nyhf7za.js → cli-qqzmjxkf.js} +129 -105
  64. package/dist/{cli-zrwpctp4.js → cli-r25qpaxt.js} +161 -63
  65. package/dist/{cli-nc35pxb7.js → cli-rh5smt8t.js} +19 -4
  66. package/dist/{cli-qwkcwjdn.js → cli-rycdaj0a.js} +1 -1
  67. package/dist/{cli-esxerzg7.js → cli-s4sntwt4.js} +2 -2
  68. package/dist/{cli-b8k7epj1.js → cli-segs7hx9.js} +8 -8
  69. package/dist/{cli-36ckw0wx.js → cli-stxdrqs2.js} +2 -2
  70. package/dist/{cli-vdm20wej.js → cli-sy8f9705.js} +4 -4
  71. package/dist/{cli-1m17dc9d.js → cli-ta8bd7th.js} +2 -2
  72. package/dist/{cli-2y91wnbh.js → cli-we0ra057.js} +222 -10
  73. package/dist/{cli-55qmbp6z.js → cli-x21dqn18.js} +5 -5
  74. package/dist/{cli-dqb4n629.js → cli-x6vf4sad.js} +11 -11
  75. package/dist/{cli-d2mb5s8a.js → cli-x77gen2p.js} +680 -440
  76. package/dist/{cli-vq97g1jq.js → cli-xawhpgc9.js} +95 -195
  77. package/dist/{cli-82d3nkc3.js → cli-xd4eqtr2.js} +2 -2
  78. package/dist/{cli-9fhkkpj5.js → cli-xt768r5m.js} +2 -2
  79. package/dist/{cli-zrk6jxv8.js → cli-y4x8ww6s.js} +2 -2
  80. package/dist/{cli-xc27fwzg.js → cli-y9jvxfhk.js} +3 -3
  81. package/dist/{cli-44159k28.js → cli-z63a269p.js} +2 -2
  82. package/dist/{cli-sm8rses9.js → cli-zfdp01hn.js} +8 -5
  83. package/dist/cli.js +31 -29
  84. package/dist/{cloudflare-workers-ai-system-one-ch2wxfcp.js → cloudflare-workers-ai-system-one-43v9qkjk.js} +7 -2
  85. package/dist/{codex-adapter-968xwfy7.js → codex-adapter-tcg1q3jk.js} +6 -4
  86. package/dist/{codex-login-m819c41r.js → codex-login-rn7c5gxt.js} +1 -1
  87. package/dist/{codex-session-runner-ht4z99fa.js → codex-session-runner-xfx4wd9x.js} +7 -5
  88. package/dist/{commands-pcymaeg9.js → commands-ew83nj70.js} +2 -2
  89. package/dist/{controller-fpjyk46r.js → controller-gnq1k1mf.js} +4 -4
  90. package/dist/{controllers-connect-mwzx1fh6.js → controllers-connect-tw1dan9r.js} +26 -24
  91. package/dist/{cursor-adapter-cp4s2e2f.js → cursor-adapter-yq5xgfcg.js} +1 -1
  92. package/dist/{db-xsjg9jqq.js → db-7gbc53fd.js} +14 -2
  93. package/dist/{db-sgd12bt9.js → db-t86xrnes.js} +3 -3
  94. package/dist/{devin-adapter-zgqadvnm.js → devin-adapter-4ycy4vrf.js} +1 -1
  95. package/dist/{dispatcher-x0jfw2c9.js → dispatcher-64bdyhps.js} +23 -21
  96. package/dist/{docker-fkgtr75t.js → docker-nfy2gc8t.js} +2 -2
  97. package/dist/{dsh-adapter-jrq7ma7h.js → dsh-adapter-tvhc4k2d.js} +1 -1
  98. package/dist/{e2b-16d6ch39.js → e2b-9gkdhm3c.js} +2 -2
  99. package/dist/{e2b-zn0b4w5w.js → e2b-cjtf8k1z.js} +2 -2
  100. package/dist/{easter-egg-3d-5cgynaja.js → easter-egg-3d-e4qv8dxj.js} +1 -1
  101. package/dist/{event-bus-9vpk8gmq.js → event-bus-3z78ep5n.js} +1 -1
  102. package/dist/{execute-t4e6m3rw.js → execute-0xpz8950.js} +85 -23
  103. package/dist/{external-channel-8njj4h3b.js → external-channel-e9nw24zv.js} +2 -2
  104. package/dist/{google-generative-ai-bmq8gkf3.js → google-generative-ai-mk9vcpe1.js} +15 -15
  105. package/dist/{google-vertex-b1rvp52s.js → google-vertex-q580kz8k.js} +20 -20
  106. package/dist/{grok-adapter-kkr97v2f.js → grok-adapter-v82srhrx.js} +9 -7
  107. package/dist/handlers-c9ajzhbn.js +41 -0
  108. package/dist/{heartbeat-wd03zhn0.js → heartbeat-2vqs1319.js} +26 -24
  109. package/dist/{hook-xzj2ts2p.js → hook-01nk13wx.js} +7 -5
  110. package/dist/{hook-f0vghj42.js → hook-jzpheegg.js} +9 -7
  111. package/dist/{http-4hwxv62p.js → http-fc1k6ec8.js} +859 -252
  112. package/dist/index-07ef7nkm.js +42 -0
  113. package/dist/{index-g6tbb6ve.js → index-31ceyf42.js} +1 -1
  114. package/dist/index-7yts8n9s.js +43 -0
  115. package/dist/{index-c4ykd0f1.js → index-dr94zbnh.js} +13348 -11611
  116. package/dist/index-q3t40ryv.js +46 -0
  117. package/dist/{index-ww2vznkp.js → index-sepja052.js} +1 -1
  118. package/dist/{index-97q4xn03.js → index-zdycv3ja.js} +135 -79
  119. package/dist/{index-g216q6jr.js → index-zsyx51ap.js} +1 -4
  120. package/dist/{keepalive-hrh7xnr9.js → keepalive-5nh2rhmr.js} +4 -4
  121. package/dist/lead-aayq64jn.js +79 -0
  122. package/dist/{llama-cpp-classify-vv43gswy.js → llama-cpp-classify-ee7vmd7q.js} +4 -1
  123. package/dist/{maintenance-e8wnwnqx.js → maintenance-hjhzdt3k.js} +1 -1
  124. package/dist/{mistral-conversations-1medfwv7.js → mistral-conversations-sd0xf1tn.js} +13 -13
  125. package/dist/{node-3v3f08f7.js → node-jzjj7r9x.js} +10 -9
  126. package/dist/{oauth-refresh-sweep-zm0yj4sj.js → oauth-refresh-sweep-y3n1knmd.js} +3 -3
  127. package/dist/{onboard-dtwcq603.js → onboard-1zq3m7db.js} +2 -2
  128. package/dist/{openai-codex-responses-de9pvs4d.js → openai-codex-responses-79s8xnbh.js} +29 -23
  129. package/dist/{openai-completions-mtqge3nf.js → openai-completions-tdbyts0x.js} +21 -20
  130. package/dist/{openai-decisions-ygk4kkxd.js → openai-decisions-bqhnjyfz.js} +2 -1
  131. package/dist/{openai-responses-dkyng71g.js → openai-responses-dm3t5vqp.js} +26 -17
  132. package/dist/{opencode-adapter-x4tqzhkh.js → opencode-adapter-e56086m1.js} +7 -5
  133. package/dist/{openrouter-images-wvv7camj.js → openrouter-images-ssttr1y4.js} +6 -3
  134. package/dist/{otel-impl-w3fbhpn0.js → otel-impl-h9yyza47.js} +2 -2
  135. package/dist/{pi-messages-nhh1pkz2.js → pi-messages-3nf8bq1a.js} +6 -4
  136. package/dist/{pi-mono-adapter-mcfkn9vf.js → pi-mono-adapter-tzps8f38.js} +9 -37
  137. package/dist/{pricing-refresh-j38dehfs.js → pricing-refresh-nevhat8h.js} +3 -3
  138. package/dist/{rbac-roles-ae8yttq4.js → rbac-roles-4y6ngvzq.js} +1 -1
  139. package/dist/{rbac-roles-ejxx9b35.js → rbac-roles-exbg8xb6.js} +2 -2
  140. package/dist/{registry-rxw10xzg.js → registry-ajhexe44.js} +1 -1
  141. package/dist/{render-v2-n16n0phe.js → render-v2-cfsh13z3.js} +3 -3
  142. package/dist/{resume-z0fgjc38.js → resume-5s2t0dbs.js} +10 -8
  143. package/dist/{runtime-xe3aqy4x.js → runtime-bt5pkpm1.js} +1 -1
  144. package/dist/{session-access-cv3mq6mc.js → session-access-dnbyp3cn.js} +6 -4
  145. package/dist/{setup-mafhj3yt.js → setup-1wj1y77j.js} +1 -1
  146. package/dist/{typesafe-system-one-2hgpayzy.js → typesafe-system-one-bre38hvs.js} +4 -2
  147. package/dist/{virtual-modules-4r3zkc20.js → virtual-modules-mnfbh5mr.js} +8 -2
  148. package/dist/{work-objects-8b86mgjp.js → work-objects-7mg6216g.js} +26 -24
  149. package/dist/worker-nwb789mg.js +79 -0
  150. package/dist/{x-y45mthwn.js → x-pbpezr0s.js} +2 -2
  151. package/openapi.json +793 -6
  152. package/package.json +11 -11
  153. package/src/apps/catalog.generated.json +206 -4
  154. package/src/apps/page-validator.ts +13 -1
  155. package/src/assets/key.ts +17 -0
  156. package/src/azure-devops/handlers.ts +1 -1
  157. package/src/be/chunking.ts +42 -9
  158. package/src/be/db/approvals.ts +18 -0
  159. package/src/be/db/session-moves.ts +164 -0
  160. package/src/be/db/session-tree.ts +384 -0
  161. package/src/be/db/tasks/draft-text.ts +15 -0
  162. package/src/be/db/tasks/read.ts +54 -5
  163. package/src/be/db/workflow-runs.ts +96 -0
  164. package/src/be/db.ts +85 -237
  165. package/src/be/memory/index-content.ts +36 -17
  166. package/src/be/memory/providers/openai-embedding.ts +115 -61
  167. package/src/be/memory/providers/sqlite-store.ts +69 -23
  168. package/src/be/memory/reranker.ts +31 -1
  169. package/src/be/memory/search-candidates.ts +47 -0
  170. package/src/be/memory/types.ts +14 -0
  171. package/src/be/onboarding.ts +3 -0
  172. package/src/be/scripts/typecheck.ts +2 -0
  173. package/src/be/seed-scripts/catalog/heartbeat-jev-gate.ts +106 -54
  174. package/src/be/seed-scripts/index.ts +2 -2
  175. package/src/be/skill-sync.ts +43 -2
  176. package/src/be/swarm-config-guard.ts +25 -1
  177. package/src/be/task-attachment-store.ts +30 -0
  178. package/src/bitbucket/api.ts +81 -0
  179. package/src/bitbucket/auth.ts +64 -0
  180. package/src/bitbucket/handlers.ts +434 -0
  181. package/src/bitbucket/index.ts +28 -0
  182. package/src/bitbucket/templates.ts +134 -0
  183. package/src/bitbucket/types.ts +65 -0
  184. package/src/commands/runner.ts +55 -3
  185. package/src/e2b/env.ts +1 -0
  186. package/src/extensions/catalog.generated.json +4 -4
  187. package/src/extensions/contract-types.generated.ts +1 -1
  188. package/src/extensions/contract.ts +9 -2
  189. package/src/extensions/post-bridge.ts +1 -0
  190. package/src/fs/provider.ts +13 -1
  191. package/src/github/handlers.ts +6 -6
  192. package/src/gitlab/handlers.ts +5 -5
  193. package/src/heartbeat/heartbeat.ts +31 -11
  194. package/src/http/assets.ts +14 -2
  195. package/src/http/core.ts +12 -0
  196. package/src/http/fs.ts +54 -34
  197. package/src/http/index.ts +4 -0
  198. package/src/http/mcp-body.ts +37 -0
  199. package/src/http/mcp-user.ts +3 -5
  200. package/src/http/mcp.ts +6 -7
  201. package/src/http/memory.ts +26 -15
  202. package/src/http/onboarding.ts +1 -0
  203. package/src/http/page-proxy.ts +61 -5
  204. package/src/http/pages-public.ts +27 -44
  205. package/src/http/pages.ts +4 -4
  206. package/src/http/script-runs.ts +2 -0
  207. package/src/http/sessions.ts +366 -12
  208. package/src/http/skills.ts +48 -1
  209. package/src/http/tasks.ts +1 -1
  210. package/src/http/users.ts +13 -1
  211. package/src/http/webhooks.ts +141 -0
  212. package/src/integrations/chat-sdk/adapters.ts +24 -4
  213. package/src/integrations/chat-sdk/attachments.ts +90 -12
  214. package/src/integrations/chat-sdk/facts.ts +138 -0
  215. package/src/integrations/chat-sdk/inbound.ts +156 -8
  216. package/src/integrations/chat-sdk/limits.ts +24 -0
  217. package/src/integrations/chat-sdk/outbound-files.ts +186 -0
  218. package/src/integrations/chat-sdk/outbound.ts +272 -5
  219. package/src/integrations/chat-sdk/relay.ts +4 -1
  220. package/src/integrations/chat-sdk/router.ts +28 -2
  221. package/src/integrations/chat-sdk/steering.ts +9 -0
  222. package/src/integrations/chat-sdk/templates.ts +14 -0
  223. package/src/integrations/chat-sdk/thread-buffer.ts +4 -0
  224. package/src/mcp-limits.ts +20 -0
  225. package/src/pages/browser-sdk.ts +8 -3
  226. package/src/pages/feedback-overlay.ts +1 -1
  227. package/src/providers/acp-targets.ts +1 -1
  228. package/src/providers/amp-adapter.ts +1 -1
  229. package/src/providers/codex-adapter.ts +106 -119
  230. package/src/providers/codex-agents-md.ts +35 -229
  231. package/src/providers/cursor-adapter.ts +1 -1
  232. package/src/providers/pi-mono-adapter.ts +5 -53
  233. package/src/realtime/transport.ts +1 -2
  234. package/src/script-workflows/workflow-ctx.ts +1 -0
  235. package/src/scripts-runtime/types/stdlib.d.ts +2 -0
  236. package/src/scripts-runtime/types/swarm-extension.d.ts +14 -4
  237. package/src/scripts-runtime/types/swarm-sdk.d.ts +2 -0
  238. package/src/server-user.ts +2 -0
  239. package/src/server.ts +2 -0
  240. package/src/slack/assistant.ts +2 -2
  241. package/src/slack/files.ts +2 -0
  242. package/src/slack/handlers.test.ts +158 -0
  243. package/src/slack/handlers.ts +23 -32
  244. package/src/slack/inbound-files.ts +39 -6
  245. package/src/slack/thread-buffer.ts +2 -1
  246. package/src/tasks/context-key.ts +61 -1
  247. package/src/tasks/task-terminal-effects.ts +21 -17
  248. package/src/tests/apps-card-grid.test.ts +197 -0
  249. package/src/tests/apps-catalog-additions.test.ts +120 -0
  250. package/src/tests/apps-tree.test.ts +129 -0
  251. package/src/tests/bitbucket-auth.test.ts +156 -0
  252. package/src/tests/bitbucket-handlers.test.ts +425 -0
  253. package/src/tests/bitbucket-webhook.test.ts +220 -0
  254. package/src/tests/chat-sdk-attachments-reply.test.ts +52 -0
  255. package/src/tests/chat-sdk-config.test.ts +11 -0
  256. package/src/tests/chat-sdk-facts.test.ts +23 -0
  257. package/src/tests/chat-sdk-inbound.test.ts +597 -4
  258. package/src/tests/chat-sdk-outbound-files.test.ts +652 -0
  259. package/src/tests/chat-sdk-telegram-markdown.test.ts +92 -0
  260. package/src/tests/codex-adapter.test.ts +167 -242
  261. package/src/tests/config-api-only-keys.test.ts +9 -0
  262. package/src/tests/context-key.test.ts +50 -0
  263. package/src/tests/core-auth.test.ts +5 -0
  264. package/src/tests/cors-allowlist.test.ts +1 -1
  265. package/src/tests/db-task-read-contract.test.ts +7 -0
  266. package/src/tests/db-task-write-contract.test.ts +6 -0
  267. package/src/tests/docs-index-footprint.test.js +3 -3
  268. package/src/tests/extensions-example-slack-reply-gate.test.ts +262 -91
  269. package/src/tests/fixtures/bitbucket/pullrequest-comment-created-inline.json +174 -0
  270. package/src/tests/fixtures/bitbucket/pullrequest-comment-created.json +170 -0
  271. package/src/tests/fixtures/bitbucket/pullrequest-created-mention.json +132 -0
  272. package/src/tests/fixtures/bitbucket/pullrequest-created-reviewer.json +140 -0
  273. package/src/tests/fixtures/bitbucket/pullrequest-fulfilled.json +134 -0
  274. package/src/tests/fixtures/bitbucket/pullrequest-rejected.json +133 -0
  275. package/src/tests/generate-mcp-docs.test.ts +101 -0
  276. package/src/tests/gitlab-handlers.test.ts +3 -3
  277. package/src/tests/gitlab-vcs-db.test.ts +4 -4
  278. package/src/tests/heartbeat-checklist.test.ts +33 -0
  279. package/src/tests/heartbeat-jev-gate-credentials.test.ts +44 -0
  280. package/src/tests/heartbeat-jev-gate.test.ts +242 -1
  281. package/src/tests/integration-disable-flags.test.ts +36 -0
  282. package/src/tests/kv-page-proxy.test.ts +91 -5
  283. package/src/tests/launch-password-rejection.test.ts +2 -2
  284. package/src/tests/mcp-input-caps.test.ts +294 -0
  285. package/src/tests/mcp-tools.test.ts +1 -1
  286. package/src/tests/memory-chunked-search-starvation.test.ts +200 -0
  287. package/src/tests/memory-embedding-input-cap.test.ts +114 -0
  288. package/src/tests/memory.test.ts +14 -0
  289. package/src/tests/onboarding.test.ts +12 -0
  290. package/src/tests/page-guest-session.test.ts +19 -8
  291. package/src/tests/page-proxy-authed.test.ts +1 -1
  292. package/src/tests/page-proxy.test.ts +17 -10
  293. package/src/tests/page-session.test.ts +102 -1
  294. package/src/tests/pages-authed-mode.test.ts +82 -12
  295. package/src/tests/pages-password-mode.test.ts +5 -5
  296. package/src/tests/pi-codemode.test.ts +8 -2
  297. package/src/tests/preload-env.test.ts +57 -0
  298. package/src/tests/preload.ts +21 -0
  299. package/src/tests/prompt-template-remaining.test.ts +38 -0
  300. package/src/tests/realtime-transport.test.ts +13 -7
  301. package/src/tests/run-root-coverage.test.ts +39 -0
  302. package/src/tests/runner-bitbucket-vcs.test.ts +191 -0
  303. package/src/tests/runner-skills-refresh.test.ts +58 -0
  304. package/src/tests/script-runs-http.test.ts +84 -0
  305. package/src/tests/scripts-http.test.ts +10 -1
  306. package/src/tests/secret-scrubber.test.ts +15 -0
  307. package/src/tests/sessions-move.test.ts +576 -0
  308. package/src/tests/sessions-tree.test.ts +493 -0
  309. package/src/tests/skill-files-http.test.ts +50 -0
  310. package/src/tests/skills-bundle.test.ts +99 -0
  311. package/src/tests/swarm-config-export-to-env.test.ts +23 -3
  312. package/src/tests/task-audio-transcription.test.ts +299 -0
  313. package/src/tests/task-completion-memory-chunking.test.ts +434 -0
  314. package/src/tests/task-terminal-secret-scrub.test.ts +6 -1
  315. package/src/tests/transcription.test.ts +299 -0
  316. package/src/tests/vcs-bitbucket.test.ts +91 -0
  317. package/src/tests/vcs-provider-isolation.test.ts +123 -0
  318. package/src/tests/vcs-provider.test.ts +16 -1
  319. package/src/tests/vcs-tracking.test.ts +3 -3
  320. package/src/tests/workflow-foreach-bodies.test.ts +637 -0
  321. package/src/tests/workflow-foreach-concurrency.test.ts +342 -0
  322. package/src/tests/workflow-foreach-retry.test.ts +537 -0
  323. package/src/tests/workflow-foreach.test.ts +44 -23
  324. package/src/tests/workflow-step-claims.test.ts +6 -6
  325. package/src/tests/workflow-system-one-decision-providers.test.ts +98 -1
  326. package/src/tests/workflow-system-one-decision.test.ts +2 -1
  327. package/src/tests/workflow-tla-races.test.ts +2 -2
  328. package/src/tools/chat-access.ts +10 -0
  329. package/src/tools/chat-post.ts +31 -11
  330. package/src/tools/chat-reply.ts +32 -10
  331. package/src/tools/memory-search.ts +3 -1
  332. package/src/tools/script-delete.ts +1 -1
  333. package/src/tools/system-one-decide.ts +17 -4
  334. package/src/tools/workflows/create-workflow.ts +5 -3
  335. package/src/types.ts +9 -2
  336. package/src/utils/config-env-export.ts +4 -1
  337. package/src/utils/page-session.ts +133 -20
  338. package/src/utils/secret-scrubber.ts +4 -0
  339. package/src/utils/skills-refresh.ts +83 -43
  340. package/src/utils/transcription.ts +246 -0
  341. package/src/vcs/bitbucket.ts +58 -0
  342. package/src/vcs/index.ts +2 -0
  343. package/src/vcs/types.ts +2 -2
  344. package/src/workflows/approval-resolution.ts +4 -1
  345. package/src/workflows/checkpoint.ts +9 -1
  346. package/src/workflows/constants.ts +3 -0
  347. package/src/workflows/definition.ts +48 -17
  348. package/src/workflows/engine.ts +25 -15
  349. package/src/workflows/executors/foreach.ts +45 -99
  350. package/src/workflows/executors/system-one-decision.ts +28 -7
  351. package/src/workflows/executors/system-one-providers.ts +39 -4
  352. package/src/workflows/foreach-body.ts +146 -0
  353. package/src/workflows/foreach-driver.ts +552 -0
  354. package/src/workflows/foreach-join.ts +206 -7
  355. package/src/workflows/node-timeout.ts +21 -0
  356. package/src/workflows/recovery.ts +68 -3
  357. package/src/workflows/resume.ts +221 -43
  358. package/src/workflows/retry-poller.ts +39 -24
  359. package/src/workflows/step-input.ts +59 -0
  360. package/src/workflows/task-step-routing.ts +114 -56
  361. package/templates/extensions/slack-reply-gate/README.md +24 -22
  362. package/templates/extensions/slack-reply-gate/hooks.ts +146 -95
  363. package/templates/extensions/slack-reply-gate/manifest.json +2 -2
  364. package/templates/skills/apps/SKILL.md +28 -6
  365. package/templates/skills/apps/content.md +28 -6
  366. package/templates/skills/chat-sdk/content.md +6 -2
  367. package/templates/skills/code-quality/content.md +2 -1
  368. package/templates/skills/heartbeat-runbook/content.md +5 -5
  369. package/templates/skills/pages/content.md +6 -4
  370. package/templates/skills/slack-interaction/content.md +5 -0
  371. package/templates/skills/swarm-scripts/SKILL.md +2 -2
  372. package/templates/skills/swarm-scripts/content.md +2 -2
  373. package/templates/skills/work-on-task/SKILL.md +1 -1
  374. package/templates/skills/work-on-task/content.md +1 -1
  375. package/dist/cli-51y09c6p.js +0 -2657
  376. package/dist/cli-yw91rnmw.js +0 -13
  377. package/dist/handlers-0pvee9nw.js +0 -39
  378. package/dist/index-gdh8jrdm.js +0 -43
  379. package/dist/index-hg0x2cdv.js +0 -40
  380. package/dist/index-thm0y6a8.js +0 -41
  381. package/dist/lead-ee8vazz2.js +0 -77
  382. package/dist/worker-16s75hm5.js +0 -77
@@ -0,0 +1,434 @@
1
+ /**
2
+ * Bitbucket Cloud webhook event handlers.
3
+ *
4
+ * Mirrors src/azure-devops/handlers.ts and src/gitlab/handlers.ts:
5
+ * - Parses webhook payloads (pull request created / commented / merged / declined)
6
+ * - Creates agent tasks via createTaskWithSiblingAwareness()
7
+ * - Deduplicates deliveries (X-Request-UUID) and events via in-memory TTL maps
8
+ * - Detects bot mentions and reviewer requests
9
+ */
10
+
11
+ import {
12
+ failTask,
13
+ findActiveTasksByVcs,
14
+ findTaskByVcs,
15
+ getAllAgents,
16
+ incrKv,
17
+ upsertKv,
18
+ } from "../be/db";
19
+ import { renderIdentity, resolveIdentity } from "../be/identity";
20
+ import { findUserByExternalId } from "../be/users";
21
+ import { resolveTemplate } from "../prompts/resolver";
22
+ import { bitbucketContextKey } from "../tasks/context-key";
23
+ import { createTaskWithSiblingAwareness } from "../tasks/sibling-awareness";
24
+ import { resolveBitbucketBotAccountId } from "./api";
25
+ import { getBitbucketBotName } from "./auth";
26
+ // Side-effect import: registers all Bitbucket event templates in the in-memory registry
27
+ import "./templates";
28
+ import type {
29
+ BitbucketAccount,
30
+ BitbucketPullRequest,
31
+ PullRequestCommentEvent,
32
+ PullRequestEvent,
33
+ } from "./types";
34
+
35
+ type HandlerResult = { created: boolean; taskId?: string };
36
+
37
+ // ── Dedup caches (same pattern as GitHub/GitLab) ──
38
+ const DEDUP_TTL_MS = 60_000;
39
+ const processedEvents = new Map<string, number>();
40
+ const processedDeliveries = new Map<string, number>();
41
+
42
+ function sweep(cache: Map<string, number>, now: number): void {
43
+ for (const [k, ts] of cache) {
44
+ if (now - ts > DEDUP_TTL_MS) cache.delete(k);
45
+ }
46
+ }
47
+
48
+ /** Content-key dedup: true when the same event was handled in the last 60s. */
49
+ export function isDuplicate(key: string): boolean {
50
+ const now = Date.now();
51
+ sweep(processedEvents, now);
52
+ if (processedEvents.has(key)) return true;
53
+ processedEvents.set(key, now);
54
+ return false;
55
+ }
56
+
57
+ /**
58
+ * Hold the content-key reservation for `key` while `fn` runs. A throw releases
59
+ * it, so Bitbucket's retry of a delivery that failed with a 5xx is not taken
60
+ * for a duplicate. Returns null when the key is already held.
61
+ */
62
+ async function withDedupReservation(
63
+ key: string,
64
+ fn: () => Promise<HandlerResult>,
65
+ ): Promise<HandlerResult | null> {
66
+ if (isDuplicate(key)) return null;
67
+ try {
68
+ return await fn();
69
+ } catch (err) {
70
+ processedEvents.delete(key);
71
+ throw err;
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Delivery dedup on `X-Request-UUID`. Bitbucket retries a delivery (same
77
+ * UUID) when it gets a 5xx or times out, so only a delivery that was acked
78
+ * is recorded — see `markDeliveryProcessed`.
79
+ */
80
+ export function isDuplicateDelivery(requestUuid: string | undefined): boolean {
81
+ if (!requestUuid) return false;
82
+ sweep(processedDeliveries, Date.now());
83
+ return processedDeliveries.has(requestUuid);
84
+ }
85
+
86
+ export function markDeliveryProcessed(requestUuid: string | undefined): void {
87
+ if (requestUuid) processedDeliveries.set(requestUuid, Date.now());
88
+ }
89
+
90
+ /** Reset dedup state (tests). */
91
+ export function resetBitbucketDedup(): void {
92
+ processedEvents.clear();
93
+ processedDeliveries.clear();
94
+ }
95
+
96
+ // ── Helpers ──
97
+
98
+ export function escapeRegExp(value: string): string {
99
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
100
+ }
101
+
102
+ /**
103
+ * Mention patterns: the mention picker stores `@{<account_id>}` in the
104
+ * comment's raw content; a typed mention stays plain `@name`.
105
+ */
106
+ function mentionPatterns(botAccountId: string | null): RegExp[] {
107
+ // `(?![\w-])` rather than `\b`, so `@agent-swarm-bot-two` is not the bot.
108
+ const patterns = [new RegExp(`@${escapeRegExp(getBitbucketBotName())}(?![\\w-])`, "gi")];
109
+ if (botAccountId) patterns.push(new RegExp(`@\\{${escapeRegExp(botAccountId)}\\}`, "gi"));
110
+ return patterns;
111
+ }
112
+
113
+ export function detectMention(
114
+ text: string | null | undefined,
115
+ botAccountId: string | null,
116
+ ): boolean {
117
+ if (!text) return false;
118
+ return mentionPatterns(botAccountId).some((re) => {
119
+ re.lastIndex = 0;
120
+ return re.test(text);
121
+ });
122
+ }
123
+
124
+ function extractMentionContext(text: string, botAccountId: string | null): string {
125
+ return mentionPatterns(botAccountId)
126
+ .reduce((acc, re) => acc.replace(re, ""), text)
127
+ .trim();
128
+ }
129
+
130
+ function isBot(account: BitbucketAccount | undefined, botAccountId: string | null): boolean {
131
+ return !!botAccountId && account?.account_id === botAccountId;
132
+ }
133
+
134
+ function pullRequestWebUrl(repo: string, pr: BitbucketPullRequest): string {
135
+ return pr.links?.html?.href ?? `https://bitbucket.org/${repo}/pull-requests/${pr.id}`;
136
+ }
137
+
138
+ function contextKeyOf(event: PullRequestEvent): string {
139
+ return bitbucketContextKey({
140
+ repoUuid: event.repository.uuid,
141
+ pullRequestId: event.pullrequest.id,
142
+ });
143
+ }
144
+
145
+ // ── Payload shape ──
146
+
147
+ /** The pull request event, or null when the payload lacks the fields we read. */
148
+ export function pullRequestEventOf(body: unknown): PullRequestEvent | null {
149
+ const event = body as Partial<PullRequestEvent> | null | undefined;
150
+ const pr = event?.pullrequest;
151
+ const repo = event?.repository;
152
+ if (
153
+ typeof pr?.id !== "number" ||
154
+ typeof pr.title !== "string" ||
155
+ typeof repo?.uuid !== "string" ||
156
+ typeof repo.full_name !== "string" ||
157
+ !event?.actor
158
+ ) {
159
+ return null;
160
+ }
161
+ return event as PullRequestEvent;
162
+ }
163
+
164
+ /** The comment event, or null when the pull request or comment is missing. */
165
+ export function pullRequestCommentEventOf(body: unknown): PullRequestCommentEvent | null {
166
+ const event = pullRequestEventOf(body) as PullRequestCommentEvent | null;
167
+ const comment = event?.comment;
168
+ if (!event || typeof comment?.id !== "number" || typeof comment.content?.raw !== "string") {
169
+ return null;
170
+ }
171
+ return event;
172
+ }
173
+
174
+ function warnMalformed(eventKey: string) {
175
+ console.warn(`[Bitbucket] Ignoring ${eventKey} event: required payload fields are missing`);
176
+ }
177
+
178
+ export async function findLeadAgent() {
179
+ const agents = await getAllAgents();
180
+ return (
181
+ agents.find((a) => a.role === "lead" && a.status === "idle") ??
182
+ agents.find((a) => a.role === "lead") ??
183
+ null
184
+ );
185
+ }
186
+
187
+ // ── Identity resolution ──
188
+
189
+ const UNMAPPED_NAMESPACE = "integration:unmapped:bitbucket";
190
+ const UNMAPPED_TTL_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
191
+
192
+ function externalIdOf(account: BitbucketAccount | undefined): string | null {
193
+ return account?.account_id?.trim() || account?.uuid?.trim() || null;
194
+ }
195
+
196
+ /**
197
+ * Resolve a Bitbucket account to a `users.id` via its linked `bitbucket`
198
+ * identity (Atlassian `account_id`). Webhook payloads carry no email, so an
199
+ * unknown sender is recorded as an unmapped tracker entry for operator triage.
200
+ */
201
+ export async function resolveBitbucketSender(
202
+ account: BitbucketAccount | undefined,
203
+ sampleEventType: string,
204
+ sampleContext: string,
205
+ ): Promise<string | undefined> {
206
+ const externalId = externalIdOf(account);
207
+ if (!externalId) return undefined;
208
+ const existing = await findUserByExternalId("bitbucket", externalId);
209
+ if (existing) return existing.id;
210
+
211
+ await upsertKv({
212
+ namespace: UNMAPPED_NAMESPACE,
213
+ key: `${externalId}:meta`,
214
+ value: {
215
+ lastSeenAt: new Date().toISOString(),
216
+ displayName: account?.display_name,
217
+ sampleEventType,
218
+ sampleContext: sampleContext.slice(0, 100),
219
+ },
220
+ valueType: "json",
221
+ expiresAt: Date.now() + UNMAPPED_TTL_MS,
222
+ });
223
+ await incrKv(UNMAPPED_NAMESPACE, `${externalId}:count`, 1);
224
+ return undefined;
225
+ }
226
+
227
+ /**
228
+ * Render a Bitbucket account for agent-visible text: the resolved canonical
229
+ * name or the explicit UNKNOWN sentinel.
230
+ */
231
+ export async function renderBitbucketIdentity(
232
+ account: BitbucketAccount | undefined,
233
+ ): Promise<string> {
234
+ return renderIdentity(await resolveIdentity("bitbucket", externalIdOf(account) ?? ""));
235
+ }
236
+
237
+ async function createBitbucketTask(
238
+ text: string,
239
+ event: PullRequestEvent,
240
+ fields: {
241
+ taskType: "bitbucket-pr" | "bitbucket-comment";
242
+ vcsEventType: string;
243
+ author: BitbucketAccount | undefined;
244
+ requestedByUserId: string | undefined;
245
+ vcsCommentId?: number;
246
+ parentTaskId?: string;
247
+ },
248
+ ): Promise<HandlerResult> {
249
+ const { pullrequest: pr, repository } = event;
250
+ const lead = await findLeadAgent();
251
+ const task = await createTaskWithSiblingAwareness(
252
+ text,
253
+ {
254
+ agentId: lead?.id ?? null,
255
+ routingReason: lead ? "skill" : undefined,
256
+ routingSource: lead ? "engine_default" : undefined,
257
+ source: "bitbucket",
258
+ vcsProvider: "bitbucket",
259
+ taskType: fields.taskType,
260
+ vcsRepo: repository.full_name,
261
+ vcsEventType: fields.vcsEventType,
262
+ vcsNumber: pr.id,
263
+ vcsCommentId: fields.vcsCommentId,
264
+ vcsAuthor: externalIdOf(fields.author) ?? undefined,
265
+ requestedByUserId: fields.requestedByUserId,
266
+ vcsUrl: pullRequestWebUrl(repository.full_name, pr),
267
+ parentTaskId: fields.parentTaskId,
268
+ contextKey: contextKeyOf(event),
269
+ },
270
+ { origin: "webhook" },
271
+ );
272
+ return { created: true, taskId: task.id };
273
+ }
274
+
275
+ // ── Event Handlers ──
276
+
277
+ /**
278
+ * `pullrequest:created`: a bot mention in the description, or the bot listed
279
+ * as a reviewer, creates one task.
280
+ */
281
+ export async function handlePullRequestCreated(body: unknown): Promise<HandlerResult> {
282
+ const event = pullRequestEventOf(body);
283
+ if (!event) {
284
+ warnMalformed("pullrequest:created");
285
+ return { created: false };
286
+ }
287
+ const { pullrequest: pr, repository } = event;
288
+ const repo = repository.full_name;
289
+ const author = pr.author ?? event.actor;
290
+ console.log(`[Bitbucket] PR #${pr.id} created by ${author.display_name} in ${repo}`);
291
+
292
+ const botAccountId = await resolveBitbucketBotAccountId();
293
+ if (isBot(author, botAccountId)) {
294
+ console.log(`[Bitbucket] PR opened by the bot itself, skipping`);
295
+ return { created: false };
296
+ }
297
+
298
+ const mentioned = detectMention(pr.description, botAccountId);
299
+ const reviewRequested =
300
+ !!botAccountId && (pr.reviewers ?? []).some((r) => r.account_id === botAccountId);
301
+ if (!mentioned && !reviewRequested) {
302
+ console.log(`[Bitbucket] PR opened without bot mention or review request, skipping`);
303
+ return { created: false };
304
+ }
305
+
306
+ const dedupKey = `bitbucket-pr-${repository.uuid}-${pr.id}-created`;
307
+ const outcome = await withDedupReservation(dedupKey, async () => {
308
+ const requestedByUserId = await resolveBitbucketSender(
309
+ author,
310
+ "pull_request",
311
+ `PR #${pr.id}: ${pr.title}`,
312
+ );
313
+
314
+ const context = pr.description ? extractMentionContext(pr.description, botAccountId) : "";
315
+ // A mention is the explicit ask; the reviewer template is for a bare review request.
316
+ const templateId = mentioned
317
+ ? "bitbucket.pull_request.opened"
318
+ : "bitbucket.pull_request.review_requested";
319
+ const result = resolveTemplate(templateId, {
320
+ pr_id: pr.id,
321
+ pr_title: pr.title,
322
+ repo,
323
+ username: await renderBitbucketIdentity(author),
324
+ source_branch: pr.source?.branch?.name ?? "",
325
+ target_branch: pr.destination?.branch?.name ?? "",
326
+ pr_url: pullRequestWebUrl(repo, pr),
327
+ context_section: context ? `Context: ${context}\n\n` : "",
328
+ });
329
+ if (result.skipped) {
330
+ return { created: false };
331
+ }
332
+
333
+ return createBitbucketTask(result.text, event, {
334
+ taskType: "bitbucket-pr",
335
+ vcsEventType: "pull_request",
336
+ author,
337
+ requestedByUserId,
338
+ });
339
+ });
340
+ if (!outcome) console.log(`[Bitbucket] Skipping duplicate PR event`);
341
+ return outcome ?? { created: false };
342
+ }
343
+
344
+ /**
345
+ * `pullrequest:comment_created`: a bot mention in a new PR comment (general or
346
+ * inline) creates a task, linked to any active task for the same PR.
347
+ */
348
+ export async function handlePullRequestCommentCreated(body: unknown): Promise<HandlerResult> {
349
+ const event = pullRequestCommentEventOf(body);
350
+ if (!event) {
351
+ warnMalformed("pullrequest:comment_created");
352
+ return { created: false };
353
+ }
354
+ const { pullrequest: pr, repository, comment } = event;
355
+ const repo = repository.full_name;
356
+ const author = comment.user ?? event.actor;
357
+
358
+ const botAccountId = await resolveBitbucketBotAccountId();
359
+ if (isBot(author, botAccountId)) {
360
+ return { created: false };
361
+ }
362
+ if (!detectMention(comment.content.raw, botAccountId)) {
363
+ return { created: false };
364
+ }
365
+
366
+ console.log(`[Bitbucket] Comment by ${author.display_name} on PR #${pr.id} in ${repo}`);
367
+
368
+ const dedupKey = `bitbucket-comment-${repository.uuid}-${pr.id}-${comment.id}`;
369
+ const outcome = await withDedupReservation(dedupKey, async () => {
370
+ const requestedByUserId = await resolveBitbucketSender(
371
+ author,
372
+ "pull_request_comment",
373
+ comment.content.raw,
374
+ );
375
+
376
+ const existingTask = await findTaskByVcs(repo, pr.id, "bitbucket");
377
+ const existingTaskNote = existingTask
378
+ ? `\n\n_Note: There's an active task (${existingTask.id}) for this PR #${pr.id}._`
379
+ : "";
380
+
381
+ const line = comment.inline?.to ?? comment.inline?.from;
382
+ const locationSection = comment.inline
383
+ ? `File: ${comment.inline.path}${line != null ? `:${line}` : ""}\n`
384
+ : "";
385
+
386
+ const result = resolveTemplate("bitbucket.comment.mentioned", {
387
+ pr_id: pr.id,
388
+ pr_title: pr.title,
389
+ username: await renderBitbucketIdentity(author),
390
+ repo,
391
+ pr_url: comment.links?.html?.href ?? pullRequestWebUrl(repo, pr),
392
+ location_section: locationSection,
393
+ context: extractMentionContext(comment.content.raw, botAccountId),
394
+ existing_task_note: existingTaskNote,
395
+ });
396
+ if (result.skipped) {
397
+ return { created: false };
398
+ }
399
+
400
+ return createBitbucketTask(result.text, event, {
401
+ taskType: "bitbucket-comment",
402
+ vcsEventType: "pull_request_comment",
403
+ author,
404
+ requestedByUserId,
405
+ vcsCommentId: comment.id,
406
+ parentTaskId: existingTask?.id,
407
+ });
408
+ });
409
+ return outcome ?? { created: false };
410
+ }
411
+
412
+ /**
413
+ * `pullrequest:fulfilled` / `pullrequest:rejected`: cancel every active task
414
+ * for the PR.
415
+ */
416
+ export async function handlePullRequestClosed(
417
+ body: unknown,
418
+ outcome: "merged" | "declined",
419
+ ): Promise<HandlerResult> {
420
+ const event = pullRequestEventOf(body);
421
+ if (!event) {
422
+ warnMalformed(outcome === "merged" ? "pullrequest:fulfilled" : "pullrequest:rejected");
423
+ return { created: false };
424
+ }
425
+ const { pullrequest: pr, repository } = event;
426
+ // Every active task, not only the newest: a comment task is a child of the
427
+ // PR task, and failTask does not cascade up to the parent.
428
+ const reason = outcome === "merged" ? "PR was merged" : "PR was declined";
429
+ for (const task of await findActiveTasksByVcs(repository.full_name, pr.id, "bitbucket")) {
430
+ console.log(`[Bitbucket] Cancelling task ${task.id} — ${reason}`);
431
+ await failTask(task.id, reason);
432
+ }
433
+ return { created: false };
434
+ }
@@ -0,0 +1,28 @@
1
+ // Bitbucket Cloud Integration
2
+ export {
3
+ postBitbucketPullRequestComment,
4
+ resetBitbucketBotCache,
5
+ resolveBitbucketBotAccountId,
6
+ } from "./api";
7
+ export {
8
+ getBitbucketBotName,
9
+ getBitbucketToken,
10
+ initBitbucket,
11
+ isBitbucketEnabled,
12
+ resetBitbucket,
13
+ verifyBitbucketWebhook,
14
+ } from "./auth";
15
+ export {
16
+ handlePullRequestClosed,
17
+ handlePullRequestCommentCreated,
18
+ handlePullRequestCreated,
19
+ isDuplicateDelivery,
20
+ markDeliveryProcessed,
21
+ pullRequestCommentEventOf,
22
+ pullRequestEventOf,
23
+ } from "./handlers";
24
+ export type {
25
+ BitbucketWebhookEvent,
26
+ PullRequestCommentEvent,
27
+ PullRequestEvent,
28
+ } from "./types";
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Bitbucket Cloud event prompt template definitions.
3
+ *
4
+ * Each template is registered at module load time via registerTemplate().
5
+ * Handlers import this module for the side-effect of registration.
6
+ *
7
+ * Template text uses {{variable}} syntax. The resolver interpolates variables
8
+ * and expands {{@template[id]}} references before returning the final text.
9
+ */
10
+
11
+ import { registerTemplate } from "../prompts/registry";
12
+
13
+ // ============================================================================
14
+ // Common building blocks (Bitbucket-specific)
15
+ // ============================================================================
16
+
17
+ registerTemplate({
18
+ eventType: "common.delegation_instruction.bitbucket",
19
+ header: "",
20
+ defaultBody:
21
+ "\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.",
22
+ variables: [],
23
+ category: "common",
24
+ });
25
+
26
+ // There is no Bitbucket CLI in the worker image, so the recipes are curl calls
27
+ // against the REST API with the worker's BITBUCKET_TOKEN.
28
+ registerTemplate({
29
+ eventType: "common.command_suggestions.bitbucket_pr",
30
+ header: "",
31
+ defaultBody:
32
+ '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>"}}}`.',
33
+ variables: [
34
+ { name: "repo", description: "Repository full name (<workspace>/<repo_slug>)" },
35
+ { name: "pr_id", description: "Pull request ID" },
36
+ ],
37
+ category: "common",
38
+ });
39
+
40
+ const SHARED_VARIABLES = [
41
+ { name: "pr_id", description: "Pull request ID" },
42
+ { name: "pr_title", description: "Pull request title" },
43
+ { name: "repo", description: "Repository full name (<workspace>/<repo_slug>)" },
44
+ { name: "pr_url", description: "Pull request web URL" },
45
+ ];
46
+
47
+ const PR_BRANCH_VARIABLES = [
48
+ { name: "source_branch", description: "Source branch name" },
49
+ { name: "target_branch", description: "Target branch name" },
50
+ { name: "context_section", description: "Context section with description or empty string" },
51
+ ];
52
+
53
+ // ============================================================================
54
+ // Pull request events
55
+ // ============================================================================
56
+
57
+ registerTemplate({
58
+ eventType: "bitbucket.pull_request.opened",
59
+ header: "[Bitbucket PR #{{pr_id}}] {{pr_title}}",
60
+ defaultBody: `Repo: {{repo}}
61
+ Author: {{username}}
62
+ Branch: {{source_branch}} → {{target_branch}}
63
+ URL: {{pr_url}}
64
+
65
+ {{context_section}}{{@template[common.command_suggestions.bitbucket_pr]}}{{@template[common.delegation_instruction.bitbucket]}}`,
66
+ variables: [
67
+ ...SHARED_VARIABLES,
68
+ {
69
+ name: "username",
70
+ description:
71
+ "Author identity — resolved canonical name (e.g. 'Luis (bitbucket:557058:…)') or the UNKNOWN sentinel",
72
+ },
73
+ ...PR_BRANCH_VARIABLES,
74
+ ],
75
+ category: "event",
76
+ });
77
+
78
+ registerTemplate({
79
+ eventType: "bitbucket.pull_request.review_requested",
80
+ header: "[Bitbucket PR #{{pr_id}}] Review requested: {{pr_title}}",
81
+ defaultBody: `Repo: {{repo}}
82
+ Author: {{username}}
83
+ Branch: {{source_branch}} → {{target_branch}}
84
+ URL: {{pr_url}}
85
+
86
+ You were added as a reviewer on this pull request.
87
+
88
+ {{context_section}}{{@template[common.command_suggestions.bitbucket_pr]}}{{@template[common.delegation_instruction.bitbucket]}}`,
89
+ variables: [
90
+ ...SHARED_VARIABLES,
91
+ {
92
+ name: "username",
93
+ description:
94
+ "Author identity — resolved canonical name (e.g. 'Luis (bitbucket:557058:…)') or the UNKNOWN sentinel",
95
+ },
96
+ ...PR_BRANCH_VARIABLES,
97
+ ],
98
+ category: "event",
99
+ });
100
+
101
+ // ============================================================================
102
+ // Pull request comment events
103
+ // ============================================================================
104
+
105
+ registerTemplate({
106
+ eventType: "bitbucket.comment.mentioned",
107
+ header: "[Bitbucket Comment on PR #{{pr_id}}] {{username}} mentioned bot",
108
+ defaultBody: `Repo: {{repo}}
109
+ PR: {{pr_title}}
110
+ URL: {{pr_url}}
111
+ {{location_section}}
112
+ Comment:
113
+ {{context}}{{existing_task_note}}
114
+
115
+ {{@template[common.command_suggestions.bitbucket_pr]}}{{@template[common.delegation_instruction.bitbucket]}}`,
116
+ variables: [
117
+ ...SHARED_VARIABLES,
118
+ {
119
+ name: "username",
120
+ description:
121
+ "Comment author identity — resolved canonical name (e.g. 'Luis (bitbucket:557058:…)') or the UNKNOWN sentinel",
122
+ },
123
+ {
124
+ name: "location_section",
125
+ description: "`File: <path>:<line>` line for inline comments, or empty string",
126
+ },
127
+ { name: "context", description: "Extracted mention context from comment" },
128
+ {
129
+ name: "existing_task_note",
130
+ description: "Note about existing active task, or empty string",
131
+ },
132
+ ],
133
+ category: "event",
134
+ });
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Bitbucket Cloud webhook payload types (subsets of the documented event
3
+ * payloads; only the fields the handlers read).
4
+ * https://support.atlassian.com/bitbucket-cloud/docs/event-payloads/
5
+ */
6
+
7
+ export interface BitbucketAccount {
8
+ type?: string;
9
+ /** Atlassian account id, e.g. `557058:<uuid>`. Absent for some app/team actors. */
10
+ account_id?: string;
11
+ /** Bitbucket user UUID, wrapped in braces: `{…}`. */
12
+ uuid?: string;
13
+ display_name?: string;
14
+ nickname?: string;
15
+ }
16
+
17
+ export interface BitbucketRepository {
18
+ /** Repository UUID, wrapped in braces: `{…}`. Stable across renames. */
19
+ uuid: string;
20
+ /** `<workspace>/<repo_slug>` */
21
+ full_name: string;
22
+ name?: string;
23
+ links?: { html?: { href: string } };
24
+ }
25
+
26
+ export interface BitbucketBranchRef {
27
+ branch?: { name: string };
28
+ commit?: { hash: string };
29
+ repository?: BitbucketRepository;
30
+ }
31
+
32
+ export interface BitbucketPullRequest {
33
+ id: number;
34
+ title: string;
35
+ description?: string | null;
36
+ state?: "OPEN" | "MERGED" | "DECLINED" | "SUPERSEDED";
37
+ author?: BitbucketAccount;
38
+ source?: BitbucketBranchRef;
39
+ destination?: BitbucketBranchRef;
40
+ reviewers?: BitbucketAccount[];
41
+ links?: { html?: { href: string } };
42
+ }
43
+
44
+ export interface BitbucketComment {
45
+ id: number;
46
+ content: { raw: string; markup?: string; html?: string };
47
+ user?: BitbucketAccount;
48
+ inline?: { path: string; from?: number | null; to?: number | null } | null;
49
+ parent?: { id: number } | null;
50
+ links?: { html?: { href: string } };
51
+ }
52
+
53
+ /** `pullrequest:created`, `pullrequest:fulfilled`, `pullrequest:rejected` */
54
+ export interface PullRequestEvent {
55
+ actor: BitbucketAccount;
56
+ pullrequest: BitbucketPullRequest;
57
+ repository: BitbucketRepository;
58
+ }
59
+
60
+ /** `pullrequest:comment_created` */
61
+ export interface PullRequestCommentEvent extends PullRequestEvent {
62
+ comment: BitbucketComment;
63
+ }
64
+
65
+ export type BitbucketWebhookEvent = PullRequestEvent | PullRequestCommentEvent;