@cursor/july 0.1.108 → 0.1.109

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 (343) hide show
  1. package/AGENTS.md +2 -6
  2. package/README.md +3 -6
  3. package/dist/channels/bitbucket/api.d.ts +41 -0
  4. package/dist/channels/bitbucket/api.d.ts.map +1 -1
  5. package/dist/channels/bitbucket/api.js +260 -0
  6. package/dist/channels/bitbucket/binding.d.ts +4 -0
  7. package/dist/channels/bitbucket/binding.d.ts.map +1 -1
  8. package/dist/channels/bitbucket/binding.js +16 -0
  9. package/dist/channels/bitbucket/index.d.ts +1 -1
  10. package/dist/channels/bitbucket/index.d.ts.map +1 -1
  11. package/dist/channels/bitbucket/index.js +1 -1
  12. package/dist/channels/gitlab/api.d.ts +27 -0
  13. package/dist/channels/gitlab/api.d.ts.map +1 -1
  14. package/dist/channels/gitlab/api.js +88 -0
  15. package/dist/channels/gitlab/binding.d.ts +5 -0
  16. package/dist/channels/gitlab/binding.d.ts.map +1 -1
  17. package/dist/channels/gitlab/binding.js +10 -0
  18. package/dist/channels/gitlab/index.d.ts +1 -1
  19. package/dist/channels/gitlab/index.d.ts.map +1 -1
  20. package/dist/channels/gitlab/index.js +1 -1
  21. package/dist/channels/slack/dispatch.d.ts +10 -0
  22. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  23. package/dist/channels/slack/dispatch.js +20 -3
  24. package/dist/channels/slack/slack-channel.d.ts +12 -5
  25. package/dist/channels/slack/slack-channel.d.ts.map +1 -1
  26. package/dist/channels/slack/slack-channel.js +59 -8
  27. package/dist/docs/404.html +2 -2
  28. package/dist/docs/assets/{app.BASKM3M4.js → app.Cr-wVbnB.js} +1 -1
  29. package/dist/docs/assets/{building-with-agents.md.CUSWxlP_.js → building-with-agents.md.D0KbSkJn.js} +2 -2
  30. package/dist/docs/assets/{building-with-agents.md.CUSWxlP_.lean.js → building-with-agents.md.D0KbSkJn.lean.js} +1 -1
  31. package/dist/docs/assets/chunks/@localSearchIndexroot.CFVQ4S17.js +1 -0
  32. package/dist/docs/assets/chunks/{VPLocalSearchBox.BOKxlYGP.js → VPLocalSearchBox.CVQERt56.js} +1 -1
  33. package/dist/docs/assets/chunks/{theme.DbDZW-zb.js → theme.Dnsd3XOn.js} +2 -2
  34. package/dist/docs/assets/concepts.md.B4o63Gul.js +1 -0
  35. package/dist/docs/assets/evals.md.C7JLjoEP.js +211 -0
  36. package/dist/docs/assets/evals.md.C7JLjoEP.lean.js +1 -0
  37. package/dist/docs/assets/guides_bitbucket.md.DZPzmUjU.js +10 -0
  38. package/dist/docs/assets/guides_bitbucket.md.DZPzmUjU.lean.js +1 -0
  39. package/dist/docs/assets/{guides_github.md.BH33UEBJ.js → guides_github.md.TZaTZlfz.js} +13 -3
  40. package/dist/docs/assets/{guides_github.md.BH33UEBJ.lean.js → guides_github.md.TZaTZlfz.lean.js} +1 -1
  41. package/dist/docs/assets/guides_gitlab.md.BmqwQfdG.js +14 -0
  42. package/dist/docs/assets/guides_gitlab.md.BmqwQfdG.lean.js +1 -0
  43. package/dist/docs/assets/{guides_webhooks.md.DKdA43Qm.js → guides_webhooks.md.CJK484ex.js} +2 -2
  44. package/dist/docs/assets/{hillclimbing.md.CpTGTCle.js → hillclimbing.md.BOiVo1tf.js} +1 -1
  45. package/dist/docs/assets/index.md.DD9Q2XuJ.js +5 -0
  46. package/dist/docs/assets/{index.md.BjH1w2ZW.lean.js → index.md.DD9Q2XuJ.lean.js} +1 -1
  47. package/dist/docs/assets/{reference_channels.md.D-qTqwcq.js → reference_channels.md.CAo-iK4j.js} +2 -2
  48. package/dist/docs/assets/{reference_channels.md.D-qTqwcq.lean.js → reference_channels.md.CAo-iK4j.lean.js} +1 -1
  49. package/dist/docs/assets/{reference_cli.md.Ca26u0Es.js → reference_cli.md.Deg7849l.js} +1 -1
  50. package/dist/docs/assets/{reference_extensions.md.CPWt00ds.js → reference_extensions.md.ZAVUyuEX.js} +2 -2
  51. package/dist/docs/assets/{reference_hooks.md.Ddt5DdgJ.js → reference_hooks.md.BlM_bOg6.js} +3 -3
  52. package/dist/docs/assets/{reference_hooks.md.Ddt5DdgJ.lean.js → reference_hooks.md.BlM_bOg6.lean.js} +1 -1
  53. package/dist/docs/assets/{reference_http-api.md.oySXBO8o.js → reference_http-api.md.BwaCo-VO.js} +1 -1
  54. package/dist/docs/assets/{reference_playground.md.4myJPxrf.js → reference_playground.md.DLnoaczX.js} +1 -1
  55. package/dist/docs/assets/{reference_playground.md.4myJPxrf.lean.js → reference_playground.md.DLnoaczX.lean.js} +1 -1
  56. package/dist/docs/assets/{reference_project-layout.md.DuBu9a96.js → reference_project-layout.md.BEU8MtQV.js} +3 -3
  57. package/dist/docs/assets/{reference_project-layout.md.DuBu9a96.lean.js → reference_project-layout.md.BEU8MtQV.lean.js} +1 -1
  58. package/dist/docs/assets/reference_sessions.md.CyXV1MUw.js +1 -0
  59. package/dist/docs/assets/skills_deploy.md.CWqi_ZxW.js +35 -0
  60. package/dist/docs/assets/skills_deploy.md.CWqi_ZxW.lean.js +1 -0
  61. package/dist/docs/assets/{skills_evals.md.BhovOvrl.js → skills_evals.md.DFxYPErF.js} +3 -3
  62. package/dist/docs/assets/skills_evals.md.DFxYPErF.lean.js +1 -0
  63. package/dist/docs/assets/{skills_framework-map.md.D-tFZhFS.js → skills_framework-map.md.BxLSOhSY.js} +1 -1
  64. package/dist/docs/assets/skills_index.md.DL7EHaQ-.js +1 -0
  65. package/dist/docs/assets/skills_index.md.DL7EHaQ-.lean.js +1 -0
  66. package/dist/docs/assets/{storage.md.BOHeqk2M.js → storage.md.BUrhJ-Zz.js} +4 -4
  67. package/dist/docs/assets/{storage.md.BOHeqk2M.lean.js → storage.md.BUrhJ-Zz.lean.js} +1 -1
  68. package/dist/docs/building-with-agents.html +5 -5
  69. package/dist/docs/building-with-agents.md +3 -2
  70. package/dist/docs/concepts.html +5 -5
  71. package/dist/docs/concepts.md +2 -4
  72. package/dist/docs/deployment.html +4 -4
  73. package/dist/docs/evals.html +161 -35
  74. package/dist/docs/evals.md +612 -297
  75. package/dist/docs/guides/agent-to-agent.html +4 -4
  76. package/dist/docs/guides/bitbucket.html +36 -0
  77. package/dist/docs/guides/bitbucket.md +84 -0
  78. package/dist/docs/guides/cloud-agents.html +4 -4
  79. package/dist/docs/guides/convert-automation.html +4 -4
  80. package/dist/docs/guides/github.html +17 -7
  81. package/dist/docs/guides/github.md +31 -0
  82. package/dist/docs/guides/gitlab.html +40 -0
  83. package/dist/docs/guides/gitlab.md +92 -0
  84. package/dist/docs/guides/grokbot-agents.html +4 -4
  85. package/dist/docs/guides/human-in-the-loop.html +4 -4
  86. package/dist/docs/guides/improve.html +4 -4
  87. package/dist/docs/guides/mcp-oauth.html +4 -4
  88. package/dist/docs/guides/opentelemetry.html +4 -4
  89. package/dist/docs/guides/slack.html +5 -5
  90. package/dist/docs/guides/webhooks.html +6 -6
  91. package/dist/docs/guides/webhooks.md +4 -2
  92. package/dist/docs/hashmap.json +1 -1
  93. package/dist/docs/hillclimbing.html +6 -6
  94. package/dist/docs/hillclimbing.md +2 -2
  95. package/dist/docs/index.html +6 -6
  96. package/dist/docs/index.md +10 -6
  97. package/dist/docs/llms-full.txt +1113 -778
  98. package/dist/docs/llms.txt +6 -5
  99. package/dist/docs/quickstart.html +4 -4
  100. package/dist/docs/reference/agent-config.html +4 -4
  101. package/dist/docs/reference/artifacts.html +4 -4
  102. package/dist/docs/reference/channels.html +6 -6
  103. package/dist/docs/reference/channels.md +16 -3
  104. package/dist/docs/reference/cli.html +6 -6
  105. package/dist/docs/reference/cli.md +6 -4
  106. package/dist/docs/reference/connections.html +4 -4
  107. package/dist/docs/reference/extensions.html +7 -7
  108. package/dist/docs/reference/extensions.md +0 -3
  109. package/dist/docs/reference/hooks.html +7 -7
  110. package/dist/docs/reference/hooks.md +9 -12
  111. package/dist/docs/reference/http-api.html +6 -6
  112. package/dist/docs/reference/http-api.md +2 -3
  113. package/dist/docs/reference/instructions.html +4 -4
  114. package/dist/docs/reference/playground.html +5 -5
  115. package/dist/docs/reference/playground.md +0 -4
  116. package/dist/docs/reference/project-layout.html +7 -7
  117. package/dist/docs/reference/project-layout.md +1 -8
  118. package/dist/docs/reference/prompt.html +4 -4
  119. package/dist/docs/reference/result.html +4 -4
  120. package/dist/docs/reference/schedules.html +4 -4
  121. package/dist/docs/reference/sessions.html +5 -5
  122. package/dist/docs/reference/sessions.md +1 -2
  123. package/dist/docs/reference/skills.html +4 -4
  124. package/dist/docs/reference/subagents.html +4 -4
  125. package/dist/docs/reference/tools.html +4 -4
  126. package/dist/docs/scaffolding-agents.html +4 -4
  127. package/dist/docs/skills/create-agent.html +4 -4
  128. package/dist/docs/skills/debug.html +4 -4
  129. package/dist/docs/skills/deploy.html +61 -0
  130. package/dist/docs/skills/deploy.md +161 -0
  131. package/dist/docs/skills/evals.html +8 -8
  132. package/dist/docs/skills/evals.md +44 -6
  133. package/dist/docs/skills/framework-map.html +5 -5
  134. package/dist/docs/skills/framework-map.md +1 -2
  135. package/dist/docs/skills/github.html +4 -4
  136. package/dist/docs/skills/hillclimb.html +4 -4
  137. package/dist/docs/skills/index.html +6 -6
  138. package/dist/docs/skills/index.md +1 -1
  139. package/dist/docs/skills/mcp-auth.html +4 -4
  140. package/dist/docs/skills/otel.html +4 -4
  141. package/dist/docs/skills/setup-slack.html +4 -4
  142. package/dist/docs/storage.html +8 -8
  143. package/dist/docs/storage.md +15 -24
  144. package/dist/docs/templates/agentic-owners.html +4 -4
  145. package/dist/docs/templates/agents-md.html +4 -4
  146. package/dist/docs/templates/code-wiki.html +4 -4
  147. package/dist/docs/templates/demo.html +4 -4
  148. package/dist/docs/templates/grokbot-agents.html +4 -4
  149. package/dist/docs/templates/pr-autofixer.html +4 -4
  150. package/dist/docs/templates/security-help.html +4 -4
  151. package/dist/docs/templates/security-reviewer.html +4 -4
  152. package/dist/docs/templates/triage.html +4 -4
  153. package/dist/docs/troubleshooting.html +4 -4
  154. package/dist/extensions.d.ts +2 -3
  155. package/dist/extensions.d.ts.map +1 -1
  156. package/dist/extensions.js +2 -5
  157. package/dist/index.d.ts +2 -3
  158. package/dist/index.d.ts.map +1 -1
  159. package/dist/index.js +1 -2
  160. package/dist/internal/authored-alias-hooks.d.ts +5 -0
  161. package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
  162. package/dist/internal/authored-alias-hooks.js +17 -0
  163. package/dist/internal/authored-loaders.d.ts +4 -0
  164. package/dist/internal/authored-loaders.d.ts.map +1 -1
  165. package/dist/internal/authored-loaders.js +21 -2
  166. package/dist/internal/cli-ax.d.ts +1 -2
  167. package/dist/internal/cli-ax.d.ts.map +1 -1
  168. package/dist/internal/cli-ax.js +1 -2
  169. package/dist/internal/continuation-channel.d.ts.map +1 -1
  170. package/dist/internal/continuation-channel.js +2 -2
  171. package/dist/internal/continuation-identity.js +8 -3
  172. package/dist/internal/discovery/agent.d.ts +1 -1
  173. package/dist/internal/discovery/agent.d.ts.map +1 -1
  174. package/dist/internal/discovery/agent.js +0 -5
  175. package/dist/internal/discovery/extension-overlay.d.ts +1 -2
  176. package/dist/internal/discovery/extension-overlay.d.ts.map +1 -1
  177. package/dist/internal/discovery/extension-overlay.js +0 -14
  178. package/dist/internal/discovery/extensions.d.ts +1 -2
  179. package/dist/internal/discovery/extensions.d.ts.map +1 -1
  180. package/dist/internal/discovery/extensions.js +4 -22
  181. package/dist/internal/discovery/info.d.ts.map +1 -1
  182. package/dist/internal/discovery/info.js +42 -24
  183. package/dist/internal/discovery/modules.js +0 -1
  184. package/dist/internal/discovery/project.d.ts.map +1 -1
  185. package/dist/internal/discovery/project.js +0 -16
  186. package/dist/internal/eval-runner.js +0 -1
  187. package/dist/internal/framework-file-storage.d.ts +4 -5
  188. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  189. package/dist/internal/framework-file-storage.js +4 -5
  190. package/dist/internal/framework-storage-selection.d.ts +2 -2
  191. package/dist/internal/framework-storage-selection.js +2 -2
  192. package/dist/internal/init-scaffold.d.ts.map +1 -1
  193. package/dist/internal/init-scaffold.js +1 -2
  194. package/dist/internal/install-cursor-skills.d.ts +5 -2
  195. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  196. package/dist/internal/install-cursor-skills.js +25 -5
  197. package/dist/internal/run-client.d.ts +1 -1
  198. package/dist/internal/sdk-runner.js +1 -1
  199. package/dist/internal/server.js +0 -14
  200. package/dist/internal/session-engine.d.ts +5 -35
  201. package/dist/internal/session-engine.d.ts.map +1 -1
  202. package/dist/internal/session-engine.js +17 -162
  203. package/dist/internal/storage-coordinator.d.ts +5 -19
  204. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  205. package/dist/internal/storage-coordinator.js +3 -62
  206. package/dist/internal/storage-roles.d.ts +4 -9
  207. package/dist/internal/storage-roles.d.ts.map +1 -1
  208. package/dist/internal/storage-roles.js +2 -2
  209. package/dist/playground/assets/index-Bhxzrcf6.css +1 -0
  210. package/dist/playground/assets/index-CqLX5uF3.js +67 -0
  211. package/dist/playground/index.html +2 -2
  212. package/dist/storage-backends/cursor-hosted-v2.d.ts +4 -5
  213. package/dist/storage-backends/cursor-hosted-v2.d.ts.map +1 -1
  214. package/dist/storage-backends/cursor-hosted-v2.js +4 -5
  215. package/dist/storage-backends/cursor-hosted.d.ts +1 -2
  216. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  217. package/dist/storage-backends/cursor-hosted.js +0 -30
  218. package/dist/storage-backends/file-kv.d.ts +9 -12
  219. package/dist/storage-backends/file-kv.d.ts.map +1 -1
  220. package/dist/storage-backends/file-kv.js +11 -47
  221. package/dist/storage-protocol.d.ts +3 -11
  222. package/dist/storage-protocol.d.ts.map +1 -1
  223. package/dist/storage-protocol.js +3 -11
  224. package/dist/storage.d.ts +8 -36
  225. package/dist/storage.d.ts.map +1 -1
  226. package/dist/storage.js +8 -44
  227. package/dist/types.d.ts +20 -57
  228. package/dist/types.d.ts.map +1 -1
  229. package/docs/README.md +10 -6
  230. package/docs/building-with-agents.md +3 -2
  231. package/docs/concepts.md +2 -4
  232. package/docs/evals.md +613 -298
  233. package/docs/guides/bitbucket.md +89 -0
  234. package/docs/guides/github.md +31 -0
  235. package/docs/guides/gitlab.md +97 -0
  236. package/docs/guides/webhooks.md +4 -2
  237. package/docs/hillclimbing.md +2 -2
  238. package/docs/reference/channels.md +16 -3
  239. package/docs/reference/cli.md +6 -4
  240. package/docs/reference/extensions.md +0 -3
  241. package/docs/reference/hooks.md +9 -12
  242. package/docs/reference/http-api.md +2 -3
  243. package/docs/reference/playground.md +0 -4
  244. package/docs/reference/project-layout.md +1 -8
  245. package/docs/reference/sessions.md +1 -2
  246. package/docs/skills/index.md +2 -2
  247. package/docs/storage.md +15 -24
  248. package/package.json +1 -7
  249. package/skills/deploy/SKILL.md +169 -0
  250. package/skills/evals/SKILL.md +45 -8
  251. package/skills/framework-map/SKILL.md +1 -2
  252. package/src/channels/bitbucket/api.ts +341 -0
  253. package/src/channels/bitbucket/binding.ts +25 -0
  254. package/src/channels/bitbucket/index.ts +2 -0
  255. package/src/channels/gitlab/api.ts +123 -0
  256. package/src/channels/gitlab/binding.ts +12 -0
  257. package/src/channels/gitlab/index.ts +1 -0
  258. package/src/channels/slack/dispatch.ts +30 -0
  259. package/src/channels/slack/slack-channel.ts +69 -7
  260. package/src/extensions.ts +2 -6
  261. package/src/index.ts +0 -3
  262. package/src/internal/authored-alias-hooks.ts +32 -0
  263. package/src/internal/authored-loaders.ts +26 -2
  264. package/src/internal/cli-ax.ts +1 -2
  265. package/src/internal/continuation-channel.ts +2 -1
  266. package/src/internal/continuation-identity.ts +10 -2
  267. package/src/internal/discovery/agent.ts +1 -7
  268. package/src/internal/discovery/extension-overlay.ts +0 -18
  269. package/src/internal/discovery/extensions.ts +2 -26
  270. package/src/internal/discovery/info.ts +3 -13
  271. package/src/internal/discovery/modules.ts +0 -1
  272. package/src/internal/discovery/project.ts +0 -16
  273. package/src/internal/eval-runner.ts +0 -1
  274. package/src/internal/framework-file-storage.ts +4 -5
  275. package/src/internal/framework-storage-selection.ts +2 -2
  276. package/src/internal/init-scaffold.ts +1 -2
  277. package/src/internal/install-cursor-skills.ts +38 -5
  278. package/src/internal/run-client.ts +1 -1
  279. package/src/internal/sdk-runner.ts +1 -1
  280. package/src/internal/server.ts +0 -16
  281. package/src/internal/session-engine.ts +14 -202
  282. package/src/internal/storage-coordinator.ts +5 -76
  283. package/src/internal/storage-roles.ts +4 -9
  284. package/src/storage-backends/cursor-hosted-v2.ts +4 -7
  285. package/src/storage-backends/cursor-hosted.ts +0 -37
  286. package/src/storage-backends/file-kv.ts +10 -51
  287. package/src/storage-protocol.ts +3 -17
  288. package/src/storage.ts +10 -101
  289. package/src/types.ts +19 -56
  290. package/templates/demo/README.md +10 -6
  291. package/templates/demo/agent/channels/github.ts +2 -0
  292. package/templates/demo/agent/channels/queue.ts +6 -2
  293. package/templates/demo/agent/lib/repos.ts +5 -0
  294. package/templates/demo/init.json +25 -0
  295. package/dist/ab.d.ts +0 -209
  296. package/dist/ab.d.ts.map +0 -1
  297. package/dist/ab.js +0 -246
  298. package/dist/docs/ab.html +0 -80
  299. package/dist/docs/ab.md +0 -332
  300. package/dist/docs/assets/ab.md.mlVgqvSk.js +0 -54
  301. package/dist/docs/assets/ab.md.mlVgqvSk.lean.js +0 -1
  302. package/dist/docs/assets/chunks/@localSearchIndexroot.BHZYsNVi.js +0 -1
  303. package/dist/docs/assets/concepts.md.DgEcZOfT.js +0 -1
  304. package/dist/docs/assets/evals.md.C1ekS3k2.js +0 -85
  305. package/dist/docs/assets/evals.md.C1ekS3k2.lean.js +0 -1
  306. package/dist/docs/assets/index.md.BjH1w2ZW.js +0 -5
  307. package/dist/docs/assets/reference_sessions.md.CueyOHSL.js +0 -1
  308. package/dist/docs/assets/skills_ab.md.CsFNatVx.js +0 -26
  309. package/dist/docs/assets/skills_ab.md.CsFNatVx.lean.js +0 -1
  310. package/dist/docs/assets/skills_evals.md.BhovOvrl.lean.js +0 -1
  311. package/dist/docs/assets/skills_index.md.DKwIxzGg.js +0 -1
  312. package/dist/docs/assets/skills_index.md.DKwIxzGg.lean.js +0 -1
  313. package/dist/docs/skills/ab.html +0 -52
  314. package/dist/docs/skills/ab.md +0 -50
  315. package/dist/internal/ab-collector.d.ts +0 -44
  316. package/dist/internal/ab-collector.d.ts.map +0 -1
  317. package/dist/internal/ab-collector.js +0 -142
  318. package/dist/internal/ab-fold.d.ts +0 -36
  319. package/dist/internal/ab-fold.d.ts.map +0 -1
  320. package/dist/internal/ab-fold.js +0 -175
  321. package/dist/internal/ab-snapshot.d.ts +0 -68
  322. package/dist/internal/ab-snapshot.d.ts.map +0 -1
  323. package/dist/internal/ab-snapshot.js +0 -208
  324. package/dist/internal/discovery/ab.d.ts +0 -9
  325. package/dist/internal/discovery/ab.d.ts.map +0 -1
  326. package/dist/internal/discovery/ab.js +0 -113
  327. package/dist/playground/assets/index-BMDqAeXu.js +0 -67
  328. package/dist/playground/assets/index-LUgJoWdL.css +0 -1
  329. package/docs/ab.md +0 -337
  330. package/skills/ab/SKILL.md +0 -58
  331. package/src/ab.ts +0 -430
  332. package/src/internal/ab-collector.ts +0 -200
  333. package/src/internal/ab-fold.ts +0 -232
  334. package/src/internal/ab-snapshot.ts +0 -331
  335. package/src/internal/discovery/ab.ts +0 -131
  336. /package/dist/docs/assets/{concepts.md.DgEcZOfT.lean.js → concepts.md.B4o63Gul.lean.js} +0 -0
  337. /package/dist/docs/assets/{guides_webhooks.md.DKdA43Qm.lean.js → guides_webhooks.md.CJK484ex.lean.js} +0 -0
  338. /package/dist/docs/assets/{hillclimbing.md.CpTGTCle.lean.js → hillclimbing.md.BOiVo1tf.lean.js} +0 -0
  339. /package/dist/docs/assets/{reference_cli.md.Ca26u0Es.lean.js → reference_cli.md.Deg7849l.lean.js} +0 -0
  340. /package/dist/docs/assets/{reference_extensions.md.CPWt00ds.lean.js → reference_extensions.md.ZAVUyuEX.lean.js} +0 -0
  341. /package/dist/docs/assets/{reference_http-api.md.oySXBO8o.lean.js → reference_http-api.md.BwaCo-VO.lean.js} +0 -0
  342. /package/dist/docs/assets/{reference_sessions.md.CueyOHSL.lean.js → reference_sessions.md.CyXV1MUw.lean.js} +0 -0
  343. /package/dist/docs/assets/{skills_framework-map.md.D-tFZhFS.lean.js → skills_framework-map.md.BxLSOhSY.lean.js} +0 -0
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: agentsdk-deploy
3
+ description: >-
4
+ Deploy or redeploy an Agent SDK project to Cursor-managed hosting
5
+ with an attached service account. Use when asked to deploy,
6
+ redeploy, publish, or update a hosted Agent SDK agent.
7
+ ---
8
+
9
+ # Deploy an Agent SDK agent
10
+
11
+ Use this skill only after a person asks for a deployment. It deploys a
12
+ pushed Git ref to Cursor-managed hosting. Local files never upload.
13
+
14
+ Use the exact published `@cursor/july` release embedded in the installed
15
+ skill. Do not use a floating npm tag or a workspace build of the CLI.
16
+
17
+ ## Gather the target
18
+
19
+ Resolve these values from the request and checkout:
20
+
21
+ - Agent directory. Default to the current directory only when it contains
22
+ one Agent SDK project.
23
+ - Deployment slug. Default to the normalized directory name.
24
+ - Git ref. Default to the exact pushed `HEAD` commit.
25
+ - Team. Use the service account's team unless the request names another.
26
+ - Cursor-event repositories and CLI-only egress domains.
27
+
28
+ Ask one focused question when the target or requested ref is ambiguous.
29
+ Do not ask for values the checkout or existing deployment supplies.
30
+
31
+ ## Use the attached service account
32
+
33
+ Continue only when `CURSOR_SERVICE_ACCOUNT_KEY` is present. Never print
34
+ the value. Do not run `agent-sdk login`.
35
+
36
+ On Linux and macOS, run every Agent SDK command through this wrapper:
37
+
38
+ ```bash
39
+ CURSOR_JULY_VERSION="__CURSOR_JULY_VERSION__"
40
+ case "$CURSOR_JULY_VERSION" in
41
+ __CURSOR_JULY_*__)
42
+ echo "The Agent SDK deploy skill is not bound to a package version." >&2
43
+ exit 1
44
+ ;;
45
+ esac
46
+
47
+ run_agent_sdk() {
48
+ env -u NODE_OPTIONS -u CURSOR_API_KEY \
49
+ CURSOR_API_KEY_FILE=/dev/null \
50
+ npx --yes "@cursor/july@$CURSOR_JULY_VERSION" "$@"
51
+ }
52
+ ```
53
+
54
+ The installed copy pins the release it came from. The wrapper isolates that
55
+ published CLI and the attached service account. The presence check prevents a
56
+ stored personal login from being used when the attachment is missing.
57
+
58
+ Verify the principal before any write:
59
+
60
+ ```bash
61
+ test -n "${CURSOR_SERVICE_ACCOUNT_KEY:-}" || {
62
+ echo "No attached Cursor service account." >&2
63
+ exit 1
64
+ }
65
+ run_agent_sdk whoami --json
66
+ ```
67
+
68
+ Continue only when `credentialSource` is `service-account`. Record the
69
+ team and complete service-account ID for the final report. Stop on an
70
+ authentication, team-access, repository-scope, or hosting-entitlement
71
+ error.
72
+
73
+ ## Pin pushed source
74
+
75
+ Find the Git root and commit:
76
+
77
+ ```bash
78
+ GIT_ROOT="$(git -C "$AGENT_DIR" rev-parse --show-toplevel)"
79
+ SOURCE_REF="$(git -C "$GIT_ROOT" rev-parse HEAD)"
80
+ git -C "$GIT_ROOT" status --short
81
+ git -C "$GIT_ROOT" branch -r --contains "$SOURCE_REF"
82
+ ```
83
+
84
+ Use a ref from the request instead of `SOURCE_REF` when the person names
85
+ one. Confirm the selected commit exists on the remote. If intended
86
+ changes are uncommitted or unpushed, stop and explain they will not ship.
87
+ Do not commit or push unless the request includes that work.
88
+
89
+ The CLI infers the normalized HTTPS `origin`, agent path, and slug from
90
+ `--dir`. Pass `--repo`, `--path`, or `--slug` when the request overrides
91
+ the inferred value. Never print a remote URL that contains credentials.
92
+
93
+ ## Preserve deployment inputs
94
+
95
+ A redeploy replaces its source, Cursor-event repositories, and
96
+ CLI-supplied egress domains. Preserve the existing
97
+ `cursorEventRepos` and `egressAllowedDomains` unless the request or
98
+ project changes them. Reapply each value with:
99
+
100
+ ```text
101
+ --cursor-events-repo <owner/repo>
102
+ --allow-domain <hostname>
103
+ ```
104
+
105
+ Read existing settings through a filter that selects only those two
106
+ fields:
107
+
108
+ ```bash
109
+ run_agent_sdk deployment "$SLUG" --json |
110
+ node -e '
111
+ let raw = "";
112
+ process.stdin.setEncoding("utf8");
113
+ process.stdin.on("data", (chunk) => { raw += chunk; });
114
+ process.stdin.on("end", () => {
115
+ const value = JSON.parse(raw);
116
+ console.log(JSON.stringify({
117
+ cursorEventRepos: value.cursorEventRepos ?? [],
118
+ egressAllowedDomains: value.egressAllowedDomains ?? [],
119
+ }, null, 2));
120
+ });
121
+ '
122
+ ```
123
+
124
+ Never print or save the full response because it can contain short-lived
125
+ engine-access headers.
126
+
127
+ For a new SCM-channel deployment, ask which repositories should wake the
128
+ agent when the project does not declare the answer. The source repository
129
+ is not always the event repository.
130
+
131
+ ## Validate, deploy, and verify
132
+
133
+ Validate with the same published package and principal:
134
+
135
+ ```bash
136
+ run_agent_sdk validate --dir "$AGENT_DIR"
137
+ ```
138
+
139
+ Stop on validation errors. Review hosting warnings about secret names,
140
+ egress domains, and channel configuration before continuing.
141
+
142
+ Deploy the pinned source. Add the preserved or requested repeatable
143
+ flags:
144
+
145
+ ```bash
146
+ run_agent_sdk deploy \
147
+ --dir "$AGENT_DIR" \
148
+ --ref "$SOURCE_REF"
149
+ ```
150
+
151
+ The command waits for a terminal deployment state. Do not treat
152
+ `pending`, `accepted`, or `deploying` as success. If the command is
153
+ interrupted, resume inspection with:
154
+
155
+ ```bash
156
+ run_agent_sdk deployment "$SLUG"
157
+ ```
158
+
159
+ A first deployment prints a one-time alias token. Never paste it into
160
+ chat or expose it in an agent-captured terminal. Before a first deploy,
161
+ ask for a secure destination or ask the person to run the final command
162
+ in a private terminal. When writing the token, use mode `0600` and print
163
+ only the path. Redeploys do not print the token. JSON deployment output
164
+ can also contain credentials, so filter it before display.
165
+
166
+ Finish only when the deployment reports `running`. Report the slug,
167
+ team, generation, pinned ref, and complete service-account ID. On
168
+ failure, report the deployment status and sanitized error without
169
+ retrying a different ref or principal.
@@ -3,17 +3,17 @@ name: agentsdk-evals
3
3
  description: >-
4
4
  Author and run defineEval cases. Use when writing, fixing, seeding,
5
5
  or hillclimbing evals. Ask whether to generate samples or take
6
- uploaded data. Materialize API-backed fixtures first. Live A/B is
7
- defineAB (skills/ab), not defineEval.
6
+ uploaded data. Materialize API-backed fixtures first.
8
7
  ---
9
8
 
10
9
  # Agent SDK evals
11
10
 
12
11
  Fixed input, model turn, gates on the trajectory. Files live at
13
12
  project-root `evals/**/*.eval.ts`. `agent/evals/` is ignored.
13
+ Guide: `docs/evals.md`.
14
14
 
15
- Live traffic variants: `skills/ab/SKILL.md`. That is not a test
16
- runner.
15
+ Observing production: hooks. Tool logic without a model:
16
+ `agent-sdk call <tool> --input '{...}'`.
17
17
 
18
18
  ```bash
19
19
  agent-sdk eval --dir . --list
@@ -27,9 +27,13 @@ agent-sdk eval --dir . --tag smoke
27
27
  | `evals/weather.eval.ts` + `test` | `weather` |
28
28
  | `evals/weather/nyc.eval.ts` + `test` | `weather/nyc` |
29
29
  | `evals/weather.eval.ts` + `{ id: "nyc" }` | `weather/nyc` |
30
+ | `evals/sql.eval.ts` exporting an array of `defineEval` calls | `sql/0000`, `sql/0001`, ... |
30
31
 
31
32
  `eval` boots an ephemeral server and a temp state root. `--url`
32
- points at a running agent. Model turns need a Cursor credential (`CURSOR_API_KEY`, then `CURSOR_API_KEY_FILE`, then `CURSOR_SERVICE_ACCOUNT_KEY`, then `agent-sdk login`).
33
+ points at a running agent. Model turns need a Cursor credential
34
+ (`CURSOR_API_KEY`, then `CURSOR_API_KEY_FILE`, then
35
+ `CURSOR_SERVICE_ACCOUNT_KEY`, then `agent-sdk login`); `--list` does
36
+ not. Node 22.13+, never Bun.
33
37
 
34
38
  ## Seeding
35
39
 
@@ -79,9 +83,30 @@ export default defineEvalConfig({
79
83
  });
80
84
  ```
81
85
 
82
- Either `test(t)` or `cases`, not both. `t.send` waits for park/fail.
83
- `workspaceFiles` seeds the first turn. Assert with `t.succeeded()`,
84
- `calledTool` / `notCalledTool`, `t.check(t.reply, …)`, `t.metric`.
86
+ Either `test(t)` or `cases`, not both. `t.send` waits for the turn to
87
+ settle (complete, park, or fail) and returns it; `turn.calledTool(...)`
88
+ reads only that turn, `t.*` reads the whole run. First-send options:
89
+ `workspaceFiles`, `workspaceDir`, `cloud`.
90
+
91
+ Gates: `t.succeeded()` / `t.parked()`,
92
+ `calledTool(name, { input, output, status, count })` / `notCalledTool`,
93
+ `toolOrder`, `maxToolCalls`, `taggedArtifact`, `event` / `notEvent`,
94
+ `t.check(value, includes | equals | matches | similarity | satisfies)`.
95
+ Records: `t.metric`, `t.log`, `t.score` (soft 0-1).
96
+
97
+ Severity is on the handle: default gate; `.soft()` tracked;
98
+ `.atLeast(0.8)` soft with a bar (verdict `scored`, exit 1 only under
99
+ `--strict`); `.gate(0.8)` hard. `t.judge.factuality`, `summarizes`,
100
+ `closedQA`, and `sql` are soft by default and need a judge model
101
+ (`judge` in `evals.config.ts`, on the eval or case, or per-call
102
+ `{ model }`).
103
+
104
+ ## Side effects
105
+
106
+ Eval sessions run real tools. Guard actuation with
107
+ `ctx.session.purpose === "eval"` in the tool, hook, or `defineResult`
108
+ and return a shaped result so `calledTool` can still assert the
109
+ decision.
85
110
 
86
111
  ## What to gate
87
112
 
@@ -103,6 +128,18 @@ drifting inputs (pin them).
103
128
  | GitHub | `github replay … --dry-run --out fixtures/github` |
104
129
  | Host-prep PR review | A team-owned PR; gate findings shape, not counts |
105
130
  | Workspace | `workspaceFiles` in `t.send` |
131
+ | Dataset | `loadJson` / `loadJsonl` / `loadYaml` from `@cursor/july/evals/loaders`, paths from the project root |
132
+
133
+ ## Debug and CI
134
+
135
+ A failed local run leaves `evals/<case-id>.json` (assertions, inputs,
136
+ tool I/O, final text, logs) under `evals/<stamp>/` in the project state
137
+ directory (the CLI prints the path); read it before editing the eval.
138
+ `--state-root <path>` keeps the raw session events too.
139
+
140
+ CI: `agent-sdk eval --dir . --json --no-stream --junit reports/evals.xml`.
141
+ Exit `1` on a failed gate, `2` when nothing matched, `--strict` to fail
142
+ on `scored`.
106
143
 
107
144
  Every kept hillclimb change lands an eval that would have failed
108
145
  before it. Never weaken a gate to pass a round.
@@ -51,7 +51,6 @@ Path is identity. Full list: README "Folder structure".
51
51
  | `agent/hooks/*.ts` | Observe-only |
52
52
  | `agent/artifacts.ts` | Durable tagged outputs (`defineArtifacts`) |
53
53
  | `agent/result.ts` | Host `commit` on the final assistant text (`defineResult`) |
54
- | `agent/ab.ts` or `agent/ab/*.ts` | Live A/B (`defineAB`) |
55
54
  | `agent/otel.ts` | OpenTelemetry (`defineOtel`) |
56
55
  | `agent/schedules/*` | Cron. Never auto-fire under `--dev` |
57
56
  | `agent/sandbox/workspace/` | Session seed files (local only) |
@@ -99,10 +98,10 @@ only this agent's directory.
99
98
  | --- | --- |
100
99
  | Scaffold | `skills/create-agent/SKILL.md` |
101
100
  | Evals | `skills/evals/SKILL.md` |
102
- | Live A/B | `skills/ab/SKILL.md` |
103
101
  | OpenTelemetry | `skills/otel/SKILL.md` |
104
102
  | GitHub | `skills/github/SKILL.md` |
105
103
  | Slack | `skills/setup-slack/SKILL.md` |
106
104
  | Host MCP OAuth | `skills/mcp-auth/SKILL.md` |
105
+ | Managed deployment | `skills/deploy/SKILL.md` |
107
106
  | Local triage | `skills/debug/SKILL.md` |
108
107
  | Measured improvement | `skills/hillclimb/SKILL.md` |
@@ -290,6 +290,8 @@ export interface BitbucketApiPullRequest {
290
290
  title?: string;
291
291
  description?: string;
292
292
  state?: string;
293
+ draft?: boolean;
294
+ authorUsername?: string;
293
295
  sourceBranch?: string;
294
296
  targetBranch?: string;
295
297
  headSha?: string;
@@ -298,6 +300,20 @@ export interface BitbucketApiPullRequest {
298
300
  raw: unknown;
299
301
  }
300
302
 
303
+ export interface BitbucketApiChangedFile {
304
+ path: string;
305
+ previousPath?: string;
306
+ status: "added" | "modified" | "removed" | "renamed";
307
+ patch?: string;
308
+ }
309
+
310
+ export interface BitbucketPullRequestDiffInput {
311
+ headSha?: string;
312
+ baseSha?: string;
313
+ mergeBaseSha?: string;
314
+ mergeBaseResolved?: boolean;
315
+ }
316
+
301
317
  /**
302
318
  * The handful of operations review products need, implemented once per
303
319
  * dialect. `ctx.bitbucket.api` is the repo-bound instance.
@@ -318,6 +334,30 @@ export interface BitbucketApi {
318
334
  getFileAtRef(path: string, ref: string): Promise<string>;
319
335
  }
320
336
 
337
+ export interface BitbucketPullRequestReadApi {
338
+ getPullRequest(id: number): Promise<BitbucketApiPullRequest>;
339
+ getMergeBaseSha(
340
+ id: number,
341
+ base: string,
342
+ headSha: string
343
+ ): Promise<string | undefined>;
344
+ listChangedFiles(
345
+ id: number,
346
+ input?: BitbucketPullRequestDiffInput
347
+ ): Promise<BitbucketApiChangedFile[]>;
348
+ }
349
+
350
+ export interface BitbucketPullRequestReadClient {
351
+ readonly repository: BitbucketRepositoryRef;
352
+ readonly api: Pick<BitbucketApi, "getPullRequest" | "getPullRequestDiff">;
353
+ request<T = unknown>(input: BitbucketRequestInput): Promise<T>;
354
+ }
355
+
356
+ export type BitbucketPullRequestReadDiagnostic =
357
+ | { kind: "commit-expansion-failed"; sha: string; error: unknown }
358
+ | { kind: "diff-fallback"; status: number }
359
+ | { kind: "metadata-fallback"; status: number };
360
+
321
361
  function asRecord(value: unknown): Record<string, unknown> | undefined {
322
362
  return typeof value === "object" && value !== null && !Array.isArray(value)
323
363
  ? (value as Record<string, unknown>)
@@ -334,6 +374,111 @@ function num(value: unknown): number | undefined {
334
374
  : undefined;
335
375
  }
336
376
 
377
+ function errorStatus(error: unknown): number | undefined {
378
+ return num(asRecord(error)?.status);
379
+ }
380
+
381
+ function bitbucketAuthorUsername(raw: unknown): string | undefined {
382
+ const author = asRecord(asRecord(raw)?.author);
383
+ const user = asRecord(author?.user);
384
+ return (
385
+ str(author?.nickname) ??
386
+ str(user?.name) ??
387
+ str(user?.slug) ??
388
+ str(author?.display_name) ??
389
+ str(user?.displayName)
390
+ );
391
+ }
392
+
393
+ const GIT_PATH_ESCAPES: Readonly<Record<string, string>> = {
394
+ a: "\u0007",
395
+ b: "\b",
396
+ f: "\f",
397
+ n: "\n",
398
+ r: "\r",
399
+ t: "\t",
400
+ v: "\v",
401
+ "\\": "\\",
402
+ '"': '"',
403
+ };
404
+
405
+ function unescapeGitPath(path: string, quoted: boolean): string {
406
+ if (!quoted) {
407
+ return path;
408
+ }
409
+ const bytes: number[] = [];
410
+ let output = "";
411
+ const flush = () => {
412
+ if (bytes.length > 0) {
413
+ output += Buffer.from(bytes).toString("utf8");
414
+ bytes.length = 0;
415
+ }
416
+ };
417
+ for (let index = 0; index < path.length; index += 1) {
418
+ const character = path[index] as string;
419
+ if (character !== "\\") {
420
+ flush();
421
+ output += character;
422
+ continue;
423
+ }
424
+ const octal = /^[0-7]{1,3}/.exec(path.slice(index + 1));
425
+ if (octal !== null) {
426
+ bytes.push(Number.parseInt(octal[0], 8));
427
+ index += octal[0].length;
428
+ continue;
429
+ }
430
+ flush();
431
+ const next = path[index + 1] ?? "";
432
+ output += GIT_PATH_ESCAPES[next] ?? next;
433
+ index += 1;
434
+ }
435
+ flush();
436
+ return output;
437
+ }
438
+
439
+ /** Split a Git-style unified diff into normalized changed files. */
440
+ export function splitBitbucketUnifiedDiff(
441
+ diff: string
442
+ ): BitbucketApiChangedFile[] {
443
+ const files: BitbucketApiChangedFile[] = [];
444
+ const sections = diff.split(/^(?=diff --git )/m).filter(Boolean);
445
+ for (const section of sections) {
446
+ const lines = section.replace(/\n$/, "").split("\n");
447
+ const header = /^diff --git ("?)a\/(.+?)\1 ("?)b\/(.+?)\3$/.exec(
448
+ lines[0] ?? ""
449
+ );
450
+ if (header === null) {
451
+ continue;
452
+ }
453
+ const oldPath = unescapeGitPath(header[2] ?? "", header[1] !== "");
454
+ const newPath = unescapeGitPath(header[4] ?? "", header[3] !== "");
455
+ let status: BitbucketApiChangedFile["status"] = "modified";
456
+ let bodyStart = 1;
457
+ for (; bodyStart < lines.length; bodyStart += 1) {
458
+ const line = lines[bodyStart] ?? "";
459
+ if (line.startsWith("@@")) {
460
+ break;
461
+ }
462
+ if (line === "--- /dev/null") {
463
+ status = "added";
464
+ } else if (line === "+++ /dev/null") {
465
+ status = "removed";
466
+ }
467
+ }
468
+ if (status === "modified" && oldPath !== newPath) {
469
+ status = "renamed";
470
+ }
471
+ const patch = lines.slice(bodyStart).join("\n");
472
+ files.push({
473
+ path: newPath,
474
+ previousPath: status === "renamed" ? oldPath : undefined,
475
+ status,
476
+ patch: patch === "" ? undefined : patch,
477
+ });
478
+ }
479
+ return files;
480
+ }
481
+
337
482
  function encodePath(path: string): string {
338
483
  return path
339
484
  .split("/")
@@ -367,6 +512,202 @@ export function bitbucketDataCenterRepoPath(repository: {
367
512
  return `/projects/${encodeURIComponent(repository.owner)}/repos/${encodeURIComponent(repository.slug)}`;
368
513
  }
369
514
 
515
+ export async function expandBitbucketCloudCommitSha(
516
+ bitbucket: Pick<BitbucketClient, "request">,
517
+ repository: Pick<BitbucketRepositoryRef, "owner" | "slug">,
518
+ sha: string | undefined,
519
+ onError?: (error: unknown) => void
520
+ ): Promise<string | undefined> {
521
+ if (sha === undefined || !/^[0-9a-f]{7,39}$/i.test(sha)) {
522
+ return sha;
523
+ }
524
+ try {
525
+ const commit = await bitbucket.request<{ hash?: string }>({
526
+ method: "GET",
527
+ path: `${bitbucketCloudRepoPath(repository)}/commit/${encodeURIComponent(sha)}`,
528
+ });
529
+ return /^[0-9a-f]{40}$/i.test(commit.hash ?? "") ? commit.hash : sha;
530
+ } catch (error) {
531
+ onError?.(error);
532
+ return sha;
533
+ }
534
+ }
535
+
536
+ function bitbucketPullRequestFromRaw(
537
+ raw: Record<string, unknown>,
538
+ id: number,
539
+ htmlUrl?: string
540
+ ): BitbucketApiPullRequest {
541
+ const source = asRecord(raw.source);
542
+ const destination = asRecord(raw.destination);
543
+ return {
544
+ id,
545
+ title: str(raw.title),
546
+ description: str(raw.description),
547
+ state: str(raw.state),
548
+ draft: typeof raw.draft === "boolean" ? raw.draft : undefined,
549
+ authorUsername: bitbucketAuthorUsername(raw),
550
+ sourceBranch:
551
+ str(asRecord(source?.branch)?.name) ??
552
+ str(asRecord(raw.fromRef)?.displayId),
553
+ targetBranch:
554
+ str(asRecord(destination?.branch)?.name) ??
555
+ str(asRecord(raw.toRef)?.displayId),
556
+ headSha:
557
+ str(asRecord(source?.commit)?.hash) ??
558
+ str(asRecord(raw.fromRef)?.latestCommit),
559
+ baseSha:
560
+ str(asRecord(destination?.commit)?.hash) ??
561
+ str(asRecord(raw.toRef)?.latestCommit),
562
+ htmlUrl,
563
+ raw,
564
+ };
565
+ }
566
+
567
+ export function createBitbucketPullRequestReadApi(
568
+ bitbucket: BitbucketPullRequestReadClient,
569
+ options: {
570
+ onDiagnostic?: (diagnostic: BitbucketPullRequestReadDiagnostic) => void;
571
+ } = {}
572
+ ): BitbucketPullRequestReadApi {
573
+ const { repository } = bitbucket;
574
+ const repo =
575
+ repository.dialect === "cloud"
576
+ ? bitbucketCloudRepoPath(repository)
577
+ : bitbucketDataCenterRepoPath(repository);
578
+ const cloudPullRequestFromActivity = async (
579
+ id: number
580
+ ): Promise<BitbucketApiPullRequest | undefined> => {
581
+ let path = `${repo}/pullrequests/${id}/activity`;
582
+ let query: Record<string, string | number> | undefined = { pagelen: 50 };
583
+ for (let page = 0; page < 20; page += 1) {
584
+ const response = await bitbucket.request<Record<string, unknown>>({
585
+ method: "GET",
586
+ path,
587
+ query,
588
+ });
589
+ for (const value of Array.isArray(response.values)
590
+ ? response.values
591
+ : []) {
592
+ const update = asRecord(asRecord(value)?.update);
593
+ if (update !== undefined) {
594
+ return bitbucketPullRequestFromRaw(update, id);
595
+ }
596
+ }
597
+ const next = str(response.next);
598
+ if (next === undefined) {
599
+ return undefined;
600
+ }
601
+ const nextUrl = new URL(next);
602
+ const marker = nextUrl.pathname.indexOf("/repositories/");
603
+ path = marker === -1 ? nextUrl.pathname : nextUrl.pathname.slice(marker);
604
+ query = Object.fromEntries(nextUrl.searchParams.entries());
605
+ }
606
+ return undefined;
607
+ };
608
+ return {
609
+ async getPullRequest(id) {
610
+ let pullRequest: BitbucketApiPullRequest;
611
+ try {
612
+ pullRequest = await bitbucket.api.getPullRequest(id);
613
+ } catch (error) {
614
+ const status = errorStatus(error);
615
+ if (
616
+ repository.dialect !== "cloud" ||
617
+ status === undefined ||
618
+ status < 500
619
+ ) {
620
+ throw error;
621
+ }
622
+ options.onDiagnostic?.({ kind: "metadata-fallback", status });
623
+ const fallback = await cloudPullRequestFromActivity(id);
624
+ if (fallback === undefined) {
625
+ throw error;
626
+ }
627
+ pullRequest = fallback;
628
+ }
629
+ const normalized = {
630
+ ...pullRequest,
631
+ draft: asRecord(pullRequest.raw)?.draft === true,
632
+ authorUsername: bitbucketAuthorUsername(pullRequest.raw),
633
+ };
634
+ if (repository.dialect !== "cloud") {
635
+ return normalized;
636
+ }
637
+ const [headSha, baseSha] = await Promise.all([
638
+ expandBitbucketCloudCommitSha(
639
+ bitbucket,
640
+ repository,
641
+ pullRequest.headSha,
642
+ (error) =>
643
+ pullRequest.headSha === undefined
644
+ ? undefined
645
+ : options.onDiagnostic?.({
646
+ kind: "commit-expansion-failed",
647
+ sha: pullRequest.headSha,
648
+ error,
649
+ })
650
+ ),
651
+ expandBitbucketCloudCommitSha(
652
+ bitbucket,
653
+ repository,
654
+ pullRequest.baseSha,
655
+ (error) =>
656
+ pullRequest.baseSha === undefined
657
+ ? undefined
658
+ : options.onDiagnostic?.({
659
+ kind: "commit-expansion-failed",
660
+ sha: pullRequest.baseSha,
661
+ error,
662
+ })
663
+ ),
664
+ ]);
665
+ return { ...normalized, headSha, baseSha };
666
+ },
667
+ async getMergeBaseSha(id, base, headSha) {
668
+ if (repository.dialect === "cloud") {
669
+ const commit = await bitbucket.request<{ hash?: string }>({
670
+ method: "GET",
671
+ path: `${repo}/merge-base/${encodeURIComponent(headSha)}..${encodeURIComponent(base)}`,
672
+ });
673
+ return str(commit.hash);
674
+ }
675
+ const commit = await bitbucket.request<{ id?: string }>({
676
+ method: "GET",
677
+ path: `${repo}/pull-requests/${id}/merge-base`,
678
+ });
679
+ return str(commit.id);
680
+ },
681
+ async listChangedFiles(id, input) {
682
+ try {
683
+ return splitBitbucketUnifiedDiff(
684
+ await bitbucket.api.getPullRequestDiff(id)
685
+ );
686
+ } catch (error) {
687
+ const status = errorStatus(error);
688
+ const comparisonBase = input?.mergeBaseSha ?? input?.baseSha;
689
+ if (
690
+ repository.dialect !== "cloud" ||
691
+ status === undefined ||
692
+ status < 500 ||
693
+ input?.headSha === undefined ||
694
+ comparisonBase === undefined
695
+ ) {
696
+ throw error;
697
+ }
698
+ options.onDiagnostic?.({ kind: "diff-fallback", status });
699
+ const diff = await bitbucket.request<string>({
700
+ method: "GET",
701
+ path: `${repo}/diff/${encodeURIComponent(input.headSha)}..${encodeURIComponent(comparisonBase)}`,
702
+ query: { topic: input.mergeBaseResolved === true ? "false" : "true" },
703
+ accept: "text/plain",
704
+ });
705
+ return splitBitbucketUnifiedDiff(diff);
706
+ }
707
+ },
708
+ };
709
+ }
710
+
370
711
  export function cloudBitbucketApi(
371
712
  client: BitbucketClient,
372
713
  repository: BitbucketRepositoryRef
@@ -265,6 +265,31 @@ export function bitbucketPullRequestUrl(
265
265
  : `${repository.htmlUrl.replace(/\/browse\/?$/, "")}/pull-requests/${id}`;
266
266
  }
267
267
 
268
+ /** Absolute PR URL, or undefined when a Data Center payload has no repo URL. */
269
+ export function bitbucketAbsolutePullRequestUrl(
270
+ repository: BitbucketRepositoryRef,
271
+ id: number,
272
+ explicit?: string
273
+ ): string | undefined {
274
+ if (explicit !== undefined) {
275
+ return explicit;
276
+ }
277
+ if (repository.dialect === "cloud") {
278
+ return `https://bitbucket.org/${repository.fullName}/pull-requests/${id}`;
279
+ }
280
+ return repository.htmlUrl === undefined
281
+ ? undefined
282
+ : `${repository.htmlUrl.replace(/\/+$/, "").replace(/\/browse$/, "")}/pull-requests/${id}`;
283
+ }
284
+
285
+ /** Whether a Data Center `updated` payload publishes a draft pull request. */
286
+ export function bitbucketDraftMarkedReady(
287
+ payload: Record<string, unknown>,
288
+ draft: boolean | undefined
289
+ ): boolean {
290
+ return payload.previousDraft === true && draft === false;
291
+ }
292
+
268
293
  /**
269
294
  * Normalize the pull request from either dialect. `action` is the suffix of
270
295
  * the Cloud-normalized event key (`pullrequest:created` → `created`).
@@ -24,8 +24,10 @@
24
24
  export * from "./api.js";
25
25
  export {
26
26
  type BitbucketHandle,
27
+ bitbucketAbsolutePullRequestUrl,
27
28
  bitbucketCommentFromPayload,
28
29
  bitbucketDialectOf,
30
+ bitbucketDraftMarkedReady,
29
31
  bitbucketPullRequestFromPayload,
30
32
  bitbucketPullRequestUrl,
31
33
  bitbucketPushFromPayload,