@cursor/july 0.1.101 → 0.1.103

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 (862) hide show
  1. package/AGENTS.md +34 -32
  2. package/README.md +28 -3
  3. package/dist/ab.d.ts +1 -1
  4. package/dist/ab.js +1 -1
  5. package/dist/bin/agent-serve.d.ts +12 -12
  6. package/dist/bin/agent-serve.js +114 -36
  7. package/dist/channels/bitbucket/api.d.ts +176 -0
  8. package/dist/channels/bitbucket/api.d.ts.map +1 -0
  9. package/dist/channels/bitbucket/api.js +419 -0
  10. package/dist/channels/bitbucket/binding.d.ts +71 -0
  11. package/dist/channels/bitbucket/binding.d.ts.map +1 -0
  12. package/dist/channels/bitbucket/binding.js +269 -0
  13. package/dist/channels/bitbucket/bitbucket-channel.d.ts +33 -0
  14. package/dist/channels/bitbucket/bitbucket-channel.d.ts.map +1 -0
  15. package/dist/channels/bitbucket/bitbucket-channel.js +120 -0
  16. package/dist/channels/bitbucket/bitbucket-webhook.d.ts +61 -0
  17. package/dist/channels/bitbucket/bitbucket-webhook.d.ts.map +1 -0
  18. package/dist/channels/bitbucket/bitbucket-webhook.js +394 -0
  19. package/dist/channels/bitbucket/checks.d.ts +67 -0
  20. package/dist/channels/bitbucket/checks.d.ts.map +1 -0
  21. package/dist/channels/bitbucket/checks.js +102 -0
  22. package/dist/channels/bitbucket/cursor-account.d.ts +37 -0
  23. package/dist/channels/bitbucket/cursor-account.d.ts.map +1 -0
  24. package/dist/channels/bitbucket/cursor-account.js +65 -0
  25. package/dist/channels/bitbucket/defaults.d.ts +26 -0
  26. package/dist/channels/bitbucket/defaults.d.ts.map +1 -0
  27. package/dist/channels/bitbucket/defaults.js +73 -0
  28. package/dist/channels/bitbucket/events.d.ts +22 -0
  29. package/dist/channels/bitbucket/events.d.ts.map +1 -0
  30. package/dist/channels/bitbucket/events.js +64 -0
  31. package/dist/channels/bitbucket/index.d.ts +34 -0
  32. package/dist/channels/bitbucket/index.d.ts.map +1 -0
  33. package/dist/channels/bitbucket/index.js +33 -0
  34. package/dist/channels/bitbucket/replay.d.ts +63 -0
  35. package/dist/channels/bitbucket/replay.d.ts.map +1 -0
  36. package/dist/channels/bitbucket/replay.js +304 -0
  37. package/dist/channels/bitbucket/state.d.ts +35 -0
  38. package/dist/channels/bitbucket/state.d.ts.map +1 -0
  39. package/dist/channels/bitbucket/state.js +21 -0
  40. package/dist/channels/bitbucket/types.d.ts +229 -0
  41. package/dist/channels/bitbucket/types.d.ts.map +1 -0
  42. package/dist/channels/bitbucket/types.js +1 -0
  43. package/dist/channels/deployments/deployments-channel.d.ts +22 -14
  44. package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
  45. package/dist/channels/deployments/deployments-channel.js +25 -27
  46. package/dist/channels/deployments/types.d.ts +12 -6
  47. package/dist/channels/deployments/types.d.ts.map +1 -1
  48. package/dist/channels/github/binding.d.ts +6 -0
  49. package/dist/channels/github/binding.d.ts.map +1 -1
  50. package/dist/channels/github/binding.js +3 -3
  51. package/dist/channels/github/cursor-account.d.ts +7 -3
  52. package/dist/channels/github/cursor-account.d.ts.map +1 -1
  53. package/dist/channels/github/cursor-account.js +10 -6
  54. package/dist/channels/github/events.d.ts +1 -1
  55. package/dist/channels/github/events.js +1 -1
  56. package/dist/channels/github/forward.d.ts +1 -1
  57. package/dist/channels/github/forward.d.ts.map +1 -1
  58. package/dist/channels/github/forward.js +3 -2
  59. package/dist/channels/github/github-channel.d.ts +29 -39
  60. package/dist/channels/github/github-channel.d.ts.map +1 -1
  61. package/dist/channels/github/github-channel.js +68 -101
  62. package/dist/channels/github/replay.d.ts +1 -1
  63. package/dist/channels/github/replay.js +1 -1
  64. package/dist/channels/github/state.d.ts +2 -0
  65. package/dist/channels/github/state.d.ts.map +1 -1
  66. package/dist/channels/github/state.js +14 -11
  67. package/dist/channels/github/types.d.ts +2 -4
  68. package/dist/channels/github/types.d.ts.map +1 -1
  69. package/dist/channels/gitlab/api.d.ts +91 -0
  70. package/dist/channels/gitlab/api.d.ts.map +1 -0
  71. package/dist/channels/gitlab/api.js +150 -0
  72. package/dist/channels/gitlab/binding.d.ts +58 -0
  73. package/dist/channels/gitlab/binding.d.ts.map +1 -0
  74. package/dist/channels/gitlab/binding.js +139 -0
  75. package/dist/channels/gitlab/checks.d.ts +110 -0
  76. package/dist/channels/gitlab/checks.d.ts.map +1 -0
  77. package/dist/channels/gitlab/checks.js +126 -0
  78. package/dist/channels/gitlab/cursor-account.d.ts +36 -0
  79. package/dist/channels/gitlab/cursor-account.d.ts.map +1 -0
  80. package/dist/channels/gitlab/cursor-account.js +65 -0
  81. package/dist/channels/gitlab/defaults.d.ts +25 -0
  82. package/dist/channels/gitlab/defaults.d.ts.map +1 -0
  83. package/dist/channels/gitlab/defaults.js +60 -0
  84. package/dist/channels/gitlab/events.d.ts +12 -0
  85. package/dist/channels/gitlab/events.d.ts.map +1 -0
  86. package/dist/channels/gitlab/events.js +28 -0
  87. package/dist/channels/gitlab/gitlab-channel.d.ts +33 -0
  88. package/dist/channels/gitlab/gitlab-channel.d.ts.map +1 -0
  89. package/dist/channels/gitlab/gitlab-channel.js +120 -0
  90. package/dist/channels/gitlab/gitlab-webhook.d.ts +45 -0
  91. package/dist/channels/gitlab/gitlab-webhook.d.ts.map +1 -0
  92. package/dist/channels/gitlab/gitlab-webhook.js +397 -0
  93. package/dist/channels/gitlab/index.d.ts +31 -0
  94. package/dist/channels/gitlab/index.d.ts.map +1 -0
  95. package/dist/channels/gitlab/index.js +30 -0
  96. package/dist/channels/gitlab/replay.d.ts +105 -0
  97. package/dist/channels/gitlab/replay.d.ts.map +1 -0
  98. package/dist/channels/gitlab/replay.js +206 -0
  99. package/dist/channels/gitlab/state.d.ts +33 -0
  100. package/dist/channels/gitlab/state.d.ts.map +1 -0
  101. package/dist/channels/gitlab/state.js +23 -0
  102. package/dist/channels/gitlab/types.d.ts +214 -0
  103. package/dist/channels/gitlab/types.d.ts.map +1 -0
  104. package/dist/channels/gitlab/types.js +1 -0
  105. package/dist/channels/origin/api.d.ts.map +1 -1
  106. package/dist/channels/origin/api.js +4 -2
  107. package/dist/channels/origin/origin-channel.d.ts +4 -9
  108. package/dist/channels/origin/origin-channel.d.ts.map +1 -1
  109. package/dist/channels/origin/origin-channel.js +8 -48
  110. package/dist/channels/origin/types.d.ts +20 -2
  111. package/dist/channels/origin/types.d.ts.map +1 -1
  112. package/dist/channels/slack/api.d.ts +1 -1
  113. package/dist/channels/slack/api.d.ts.map +1 -1
  114. package/dist/channels/slack/api.js +3 -1
  115. package/dist/channels/slack/assistant.d.ts +1 -1
  116. package/dist/channels/slack/assistant.d.ts.map +1 -1
  117. package/dist/channels/slack/dispatch.d.ts +3 -2
  118. package/dist/channels/slack/dispatch.d.ts.map +1 -1
  119. package/dist/channels/slack/dispatch.js +28 -8
  120. package/dist/channels/slack/eval-directive.d.ts.map +1 -1
  121. package/dist/channels/slack/eval-directive.js +1 -7
  122. package/dist/channels/slack/inbound.d.ts +8 -0
  123. package/dist/channels/slack/inbound.d.ts.map +1 -1
  124. package/dist/channels/slack/inbound.js +28 -0
  125. package/dist/channels/slack/init.d.ts.map +1 -1
  126. package/dist/channels/slack/init.js +3 -3
  127. package/dist/channels/slack/manifest.d.ts.map +1 -1
  128. package/dist/channels/slack/manifest.js +2 -1
  129. package/dist/channels/slack/setup.d.ts +1 -1
  130. package/dist/channels/slack/setup.d.ts.map +1 -1
  131. package/dist/channels/slack/setup.js +6 -13
  132. package/dist/channels/slack/types.d.ts +1 -1
  133. package/dist/channels/slack/types.d.ts.map +1 -1
  134. package/dist/channels.d.ts +1 -1
  135. package/dist/channels.d.ts.map +1 -1
  136. package/dist/client.d.ts +1 -1
  137. package/dist/client.js +1 -1
  138. package/dist/connections.d.ts +1 -1
  139. package/dist/connections.js +1 -1
  140. package/dist/docs/404.html +2 -2
  141. package/dist/docs/ab.html +4 -4
  142. package/dist/docs/assets/{app.BASO9Kih.js → app.DW9pXkpL.js} +1 -1
  143. package/dist/docs/assets/chunks/@localSearchIndexroot.nrl1ifBq.js +1 -0
  144. package/dist/docs/assets/chunks/{VPLocalSearchBox.DwkqxoE0.js → VPLocalSearchBox.CdEIUwDg.js} +1 -1
  145. package/dist/docs/assets/chunks/{theme.CCil_13e.js → theme.YZMHgPgg.js} +2 -2
  146. package/dist/docs/assets/{concepts.md.lwAgBIMI.js → concepts.md.DgEcZOfT.js} +1 -1
  147. package/dist/docs/assets/{concepts.md.lwAgBIMI.lean.js → concepts.md.DgEcZOfT.lean.js} +1 -1
  148. package/dist/docs/assets/{evals.md.CPzDAwoH.js → evals.md.CbMoebP1.js} +1 -1
  149. package/dist/docs/assets/guides_cloud-agents.md.DS8RIjwx.js +9 -0
  150. package/dist/docs/assets/guides_cloud-agents.md.DS8RIjwx.lean.js +1 -0
  151. package/dist/docs/assets/{guides_github.md.BtPr9GaP.js → guides_github.md.DKYiT9do.js} +1 -1
  152. package/dist/docs/assets/{guides_opentelemetry.md.BVTXDCRg.js → guides_opentelemetry.md.COh9jFVg.js} +7 -8
  153. package/dist/docs/assets/{guides_opentelemetry.md.BVTXDCRg.lean.js → guides_opentelemetry.md.COh9jFVg.lean.js} +1 -1
  154. package/dist/docs/assets/index.md.D75GWhPl.js +5 -0
  155. package/dist/docs/assets/{index.md.Bb4k8kUm.lean.js → index.md.D75GWhPl.lean.js} +1 -1
  156. package/dist/docs/assets/{reference_agent-config.md.BHeYMgme.js → reference_agent-config.md.CHNpiyp4.js} +3 -3
  157. package/dist/docs/assets/{reference_channels.md.Cd2f2iyV.js → reference_channels.md.Dz8Cnudp.js} +2 -2
  158. package/dist/docs/assets/{reference_channels.md.Cd2f2iyV.lean.js → reference_channels.md.Dz8Cnudp.lean.js} +1 -1
  159. package/dist/docs/assets/{reference_cli.md.DfoeyvL0.js → reference_cli.md.CJNc_xYK.js} +1 -1
  160. package/dist/docs/assets/reference_extensions.md.DykHW3qL.js +62 -0
  161. package/dist/docs/assets/reference_extensions.md.DykHW3qL.lean.js +1 -0
  162. package/dist/docs/assets/reference_hooks.md.Ddt5DdgJ.js +73 -0
  163. package/dist/docs/assets/{reference_hooks.md.a8BJxMR5.lean.js → reference_hooks.md.Ddt5DdgJ.lean.js} +1 -1
  164. package/dist/docs/assets/{reference_playground.md.DnX5nL-B.js → reference_playground.md.4myJPxrf.js} +1 -1
  165. package/dist/docs/assets/{reference_project-layout.md.Bv4KOtlB.js → reference_project-layout.md.DuBu9a96.js} +2 -2
  166. package/dist/docs/assets/{reference_project-layout.md.Bv4KOtlB.lean.js → reference_project-layout.md.DuBu9a96.lean.js} +1 -1
  167. package/dist/docs/assets/reference_result.md.BK5SxDrf.js +19 -0
  168. package/dist/docs/assets/reference_result.md.BK5SxDrf.lean.js +1 -0
  169. package/dist/docs/assets/{reference_sessions.md.NxFP_CAC.js → reference_sessions.md.CueyOHSL.js} +1 -1
  170. package/dist/docs/assets/{reference_sessions.md.NxFP_CAC.lean.js → reference_sessions.md.CueyOHSL.lean.js} +1 -1
  171. package/dist/docs/assets/{reference_skills.md.BFW9retM.js → reference_skills.md.l2ezAcaN.js} +1 -1
  172. package/dist/docs/assets/{reference_tools.md.CvAHsdSp.js → reference_tools.md.aGrn99hP.js} +2 -2
  173. package/dist/docs/assets/skills_framework-map.md.haibFyoB.js +1 -0
  174. package/dist/docs/assets/{skills_framework-map.md.BTi817yv.lean.js → skills_framework-map.md.haibFyoB.lean.js} +1 -1
  175. package/dist/docs/assets/{skills_otel.md.CgiZryR3.js → skills_otel.md.CqhobH3B.js} +3 -3
  176. package/dist/docs/assets/{skills_otel.md.CgiZryR3.lean.js → skills_otel.md.CqhobH3B.lean.js} +1 -1
  177. package/dist/docs/assets/{templates_pr-autofixer.md.x5zl6-GT.js → templates_pr-autofixer.md.Bds_XWcV.js} +2 -2
  178. package/dist/docs/assets/{templates_pr-autofixer.md.x5zl6-GT.lean.js → templates_pr-autofixer.md.Bds_XWcV.lean.js} +1 -1
  179. package/dist/docs/building-with-agents.html +4 -4
  180. package/dist/docs/concepts.html +5 -5
  181. package/dist/docs/concepts.md +5 -7
  182. package/dist/docs/deployment.html +4 -4
  183. package/dist/docs/design/runtime-abstraction.md +2 -3
  184. package/dist/docs/evals.html +6 -6
  185. package/dist/docs/evals.md +9 -7
  186. package/dist/docs/guides/agent-to-agent.html +4 -4
  187. package/dist/docs/guides/cloud-agents.html +35 -0
  188. package/dist/docs/guides/cloud-agents.md +91 -0
  189. package/dist/docs/guides/convert-automation.html +4 -4
  190. package/dist/docs/guides/github.html +6 -6
  191. package/dist/docs/guides/github.md +0 -1
  192. package/dist/docs/guides/human-in-the-loop.html +4 -4
  193. package/dist/docs/guides/mcp-oauth.html +5 -5
  194. package/dist/docs/guides/opentelemetry.html +11 -12
  195. package/dist/docs/guides/opentelemetry.md +41 -17
  196. package/dist/docs/guides/slack.html +4 -4
  197. package/dist/docs/guides/webhooks.html +4 -4
  198. package/dist/docs/hashmap.json +1 -1
  199. package/dist/docs/hillclimbing.html +4 -4
  200. package/dist/docs/index.html +6 -6
  201. package/dist/docs/index.md +7 -3
  202. package/dist/docs/llms-full.txt +765 -209
  203. package/dist/docs/llms.txt +3 -1
  204. package/dist/docs/quickstart.html +4 -4
  205. package/dist/docs/reference/agent-config.html +8 -8
  206. package/dist/docs/reference/agent-config.md +6 -10
  207. package/dist/docs/reference/artifacts.html +5 -5
  208. package/dist/docs/reference/channels.html +6 -6
  209. package/dist/docs/reference/channels.md +18 -8
  210. package/dist/docs/reference/cli.html +5 -5
  211. package/dist/docs/reference/cli.md +3 -4
  212. package/dist/docs/reference/connections.html +4 -4
  213. package/dist/docs/reference/extensions.html +88 -0
  214. package/dist/docs/reference/extensions.md +264 -0
  215. package/dist/docs/reference/hooks.html +69 -10
  216. package/dist/docs/reference/hooks.md +215 -46
  217. package/dist/docs/reference/http-api.html +4 -4
  218. package/dist/docs/reference/instructions.html +4 -4
  219. package/dist/docs/reference/playground.html +5 -5
  220. package/dist/docs/reference/playground.md +3 -0
  221. package/dist/docs/reference/project-layout.html +6 -6
  222. package/dist/docs/reference/project-layout.md +4 -0
  223. package/dist/docs/reference/prompt.html +4 -4
  224. package/dist/docs/reference/result.html +45 -0
  225. package/dist/docs/reference/result.md +89 -0
  226. package/dist/docs/reference/schedules.html +4 -4
  227. package/dist/docs/reference/sessions.html +5 -5
  228. package/dist/docs/reference/sessions.md +3 -1
  229. package/dist/docs/reference/skills.html +6 -6
  230. package/dist/docs/reference/skills.md +2 -0
  231. package/dist/docs/reference/subagents.html +5 -5
  232. package/dist/docs/reference/tools.html +6 -6
  233. package/dist/docs/reference/tools.md +3 -2
  234. package/dist/docs/scaffolding-agents.html +4 -4
  235. package/dist/docs/skills/ab.html +4 -4
  236. package/dist/docs/skills/create-agent.html +4 -4
  237. package/dist/docs/skills/debug.html +4 -4
  238. package/dist/docs/skills/evals.html +4 -4
  239. package/dist/docs/skills/framework-map.html +5 -5
  240. package/dist/docs/skills/framework-map.md +3 -0
  241. package/dist/docs/skills/github.html +4 -4
  242. package/dist/docs/skills/hillclimb.html +4 -4
  243. package/dist/docs/skills/index.html +4 -4
  244. package/dist/docs/skills/mcp-auth.html +4 -4
  245. package/dist/docs/skills/otel.html +7 -7
  246. package/dist/docs/skills/otel.md +8 -3
  247. package/dist/docs/skills/setup-slack.html +4 -4
  248. package/dist/docs/storage.html +4 -4
  249. package/dist/docs/templates/agentic-owners.html +4 -4
  250. package/dist/docs/templates/agents-md.html +4 -4
  251. package/dist/docs/templates/code-wiki.html +4 -4
  252. package/dist/docs/templates/demo.html +4 -4
  253. package/dist/docs/templates/pr-autofixer.html +6 -6
  254. package/dist/docs/templates/pr-autofixer.md +0 -3
  255. package/dist/docs/templates/security-help.html +4 -4
  256. package/dist/docs/templates/security-reviewer.html +4 -4
  257. package/dist/docs/templates/triage.html +4 -4
  258. package/dist/docs/troubleshooting.html +4 -4
  259. package/dist/evals.d.ts +1 -1
  260. package/dist/evals.d.ts.map +1 -1
  261. package/dist/extensions/cursor-cloud-agents/extension.d.ts +9 -7
  262. package/dist/extensions/cursor-cloud-agents/extension.d.ts.map +1 -1
  263. package/dist/extensions/cursor-cloud-agents/extension.js +9 -7
  264. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts +78 -0
  265. package/dist/extensions/cursor-cloud-agents/lib/backend.d.ts.map +1 -0
  266. package/dist/extensions/cursor-cloud-agents/lib/backend.js +286 -0
  267. package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts +5 -0
  268. package/dist/extensions/cursor-cloud-agents/lib/inputs.d.ts.map +1 -0
  269. package/dist/extensions/cursor-cloud-agents/lib/inputs.js +4 -0
  270. package/dist/extensions/cursor-cloud-agents/lib/transcript.d.ts +8 -0
  271. package/dist/extensions/cursor-cloud-agents/lib/transcript.d.ts.map +1 -0
  272. package/dist/extensions/cursor-cloud-agents/lib/transcript.js +15 -0
  273. package/dist/extensions/cursor-cloud-agents/skills/handoff.md +21 -7
  274. package/dist/extensions/cursor-cloud-agents/tools/cancel.d.ts +4 -0
  275. package/dist/extensions/cursor-cloud-agents/tools/cancel.d.ts.map +1 -0
  276. package/dist/extensions/cursor-cloud-agents/tools/cancel.js +26 -0
  277. package/dist/extensions/cursor-cloud-agents/tools/dump.d.ts +4 -0
  278. package/dist/extensions/cursor-cloud-agents/tools/dump.d.ts.map +1 -0
  279. package/dist/extensions/cursor-cloud-agents/tools/dump.js +54 -0
  280. package/dist/extensions/cursor-cloud-agents/tools/get.d.ts +4 -0
  281. package/dist/extensions/cursor-cloud-agents/tools/get.d.ts.map +1 -0
  282. package/dist/extensions/cursor-cloud-agents/tools/get.js +25 -0
  283. package/dist/extensions/cursor-cloud-agents/tools/launch.d.ts.map +1 -1
  284. package/dist/extensions/cursor-cloud-agents/tools/launch.js +14 -38
  285. package/dist/extensions/cursor-cloud-agents/tools/list.js +1 -1
  286. package/dist/extensions/cursor-cloud-agents/tools/reply.d.ts +4 -0
  287. package/dist/extensions/cursor-cloud-agents/tools/reply.d.ts.map +1 -0
  288. package/dist/extensions/cursor-cloud-agents/tools/{follow_up.js → reply.js} +12 -14
  289. package/dist/extensions.d.ts +54 -17
  290. package/dist/extensions.d.ts.map +1 -1
  291. package/dist/extensions.js +83 -15
  292. package/dist/files-backends/cursor-hosted.d.ts +0 -8
  293. package/dist/files-backends/cursor-hosted.d.ts.map +1 -1
  294. package/dist/files-backends/cursor-hosted.js +1 -11
  295. package/dist/files.d.ts +21 -4
  296. package/dist/files.d.ts.map +1 -1
  297. package/dist/files.js +38 -21
  298. package/dist/index.d.ts +6 -6
  299. package/dist/index.d.ts.map +1 -1
  300. package/dist/index.js +4 -4
  301. package/dist/internal/ab-snapshot.d.ts.map +1 -1
  302. package/dist/internal/ab-snapshot.js +0 -1
  303. package/dist/internal/advertise-tools.d.ts.map +1 -1
  304. package/dist/internal/advertise-tools.js +1 -3
  305. package/dist/internal/authored-alias-hooks.d.ts +4 -13
  306. package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
  307. package/dist/internal/authored-alias-hooks.js +4 -20
  308. package/dist/internal/authored-loaders.d.ts +2 -3
  309. package/dist/internal/authored-loaders.d.ts.map +1 -1
  310. package/dist/internal/authored-loaders.js +6 -20
  311. package/dist/internal/channel-dispatch.d.ts +43 -0
  312. package/dist/internal/channel-dispatch.d.ts.map +1 -0
  313. package/dist/internal/channel-dispatch.js +77 -0
  314. package/dist/internal/chat-client.d.ts +1 -1
  315. package/dist/internal/chat-client.js +1 -1
  316. package/dist/internal/cli-ax.d.ts +5 -5
  317. package/dist/internal/cli-ax.d.ts.map +1 -1
  318. package/dist/internal/cli-ax.js +5 -5
  319. package/dist/internal/cli-bitbucket.d.ts +33 -0
  320. package/dist/internal/cli-bitbucket.d.ts.map +1 -0
  321. package/dist/internal/cli-bitbucket.js +359 -0
  322. package/dist/internal/cli-convert-automation.d.ts +1 -1
  323. package/dist/internal/cli-convert-automation.js +2 -2
  324. package/dist/internal/cli-cursor.d.ts +1 -1
  325. package/dist/internal/cli-cursor.d.ts.map +1 -1
  326. package/dist/internal/cli-cursor.js +2 -4
  327. package/dist/internal/cli-deploy.d.ts.map +1 -1
  328. package/dist/internal/cli-deploy.js +2 -6
  329. package/dist/internal/cli-github.d.ts +1 -1
  330. package/dist/internal/cli-github.js +3 -3
  331. package/dist/internal/cli-gitlab.d.ts +37 -0
  332. package/dist/internal/cli-gitlab.d.ts.map +1 -0
  333. package/dist/internal/cli-gitlab.js +380 -0
  334. package/dist/internal/cli-mcp.d.ts.map +1 -1
  335. package/dist/internal/cli-mcp.js +2 -6
  336. package/dist/internal/cli-slack.d.ts +1 -1
  337. package/dist/internal/cli-slack.d.ts.map +1 -1
  338. package/dist/internal/cli-slack.js +2 -4
  339. package/dist/internal/continuation-channel.d.ts +14 -0
  340. package/dist/internal/continuation-channel.d.ts.map +1 -1
  341. package/dist/internal/continuation-channel.js +56 -3
  342. package/dist/internal/continuation-identity.d.ts +14 -15
  343. package/dist/internal/continuation-identity.d.ts.map +1 -1
  344. package/dist/internal/continuation-identity.js +182 -7
  345. package/dist/internal/conversation-mirror.d.ts.map +1 -1
  346. package/dist/internal/conversation-mirror.js +17 -18
  347. package/dist/internal/convert-automation/types.d.ts +1 -1
  348. package/dist/internal/convert-automation/types.js +1 -1
  349. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  350. package/dist/internal/cursor/account-mcp.js +1 -3
  351. package/dist/internal/cursor/backend-client.d.ts +13 -5
  352. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  353. package/dist/internal/cursor/backend-client.js +30 -15
  354. package/dist/internal/cursor/bound-secret-file.d.ts +56 -0
  355. package/dist/internal/cursor/bound-secret-file.d.ts.map +1 -0
  356. package/dist/internal/cursor/bound-secret-file.js +88 -0
  357. package/dist/internal/cursor/credentials.d.ts +39 -5
  358. package/dist/internal/cursor/credentials.d.ts.map +1 -1
  359. package/dist/internal/cursor/credentials.js +58 -8
  360. package/dist/internal/cursor/hosted-bound-secrets.d.ts +41 -0
  361. package/dist/internal/cursor/hosted-bound-secrets.d.ts.map +1 -0
  362. package/dist/internal/cursor/hosted-bound-secrets.js +54 -0
  363. package/dist/internal/cursor/hosted-deployment-secrets.d.ts +19 -5
  364. package/dist/internal/cursor/hosted-deployment-secrets.d.ts.map +1 -1
  365. package/dist/internal/cursor/hosted-deployment-secrets.js +29 -9
  366. package/dist/internal/cursor/hosted-store-secrets.d.ts +12 -1
  367. package/dist/internal/cursor/hosted-store-secrets.d.ts.map +1 -1
  368. package/dist/internal/cursor/hosted-store-secrets.js +16 -1
  369. package/dist/internal/cursor-account-mcp-auth.d.ts.map +1 -1
  370. package/dist/internal/cursor-account-mcp-auth.js +2 -4
  371. package/dist/internal/cursor-deployment-relay.d.ts +6 -2
  372. package/dist/internal/cursor-deployment-relay.d.ts.map +1 -1
  373. package/dist/internal/cursor-deployment-relay.js +13 -9
  374. package/dist/internal/deploy-manifest.d.ts +1 -1
  375. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  376. package/dist/internal/deploy-manifest.js +1 -1
  377. package/dist/internal/discovery/ab.d.ts +9 -0
  378. package/dist/internal/discovery/ab.d.ts.map +1 -0
  379. package/dist/internal/discovery/ab.js +113 -0
  380. package/dist/internal/discovery/agent-config.d.ts +35 -0
  381. package/dist/internal/discovery/agent-config.d.ts.map +1 -0
  382. package/dist/internal/discovery/agent-config.js +173 -0
  383. package/dist/internal/discovery/agent.d.ts +16 -0
  384. package/dist/internal/discovery/agent.d.ts.map +1 -0
  385. package/dist/internal/discovery/agent.js +255 -0
  386. package/dist/internal/discovery/channels.d.ts +10 -0
  387. package/dist/internal/discovery/channels.d.ts.map +1 -0
  388. package/dist/internal/discovery/channels.js +97 -0
  389. package/dist/internal/discovery/connections.d.ts +13 -0
  390. package/dist/internal/discovery/connections.d.ts.map +1 -0
  391. package/dist/internal/discovery/connections.js +422 -0
  392. package/dist/internal/discovery/context.d.ts +20 -0
  393. package/dist/internal/discovery/context.d.ts.map +1 -0
  394. package/dist/internal/discovery/context.js +30 -0
  395. package/dist/internal/discovery/cursor-plugin.d.ts +25 -0
  396. package/dist/internal/discovery/cursor-plugin.d.ts.map +1 -0
  397. package/dist/internal/discovery/cursor-plugin.js +568 -0
  398. package/dist/internal/discovery/extension-overlay.d.ts +32 -0
  399. package/dist/internal/discovery/extension-overlay.d.ts.map +1 -0
  400. package/dist/internal/discovery/extension-overlay.js +191 -0
  401. package/dist/internal/discovery/extensions.d.ts +28 -0
  402. package/dist/internal/discovery/extensions.d.ts.map +1 -0
  403. package/dist/internal/discovery/extensions.js +375 -0
  404. package/dist/internal/discovery/fs.d.ts +15 -0
  405. package/dist/internal/discovery/fs.d.ts.map +1 -0
  406. package/dist/internal/discovery/fs.js +115 -0
  407. package/dist/internal/discovery/hooks.d.ts +7 -0
  408. package/dist/internal/discovery/hooks.d.ts.map +1 -0
  409. package/dist/internal/discovery/hooks.js +61 -0
  410. package/dist/internal/discovery/info.d.ts +6 -0
  411. package/dist/internal/discovery/info.d.ts.map +1 -0
  412. package/dist/internal/discovery/info.js +147 -0
  413. package/dist/internal/discovery/instructions.d.ts +7 -0
  414. package/dist/internal/discovery/instructions.d.ts.map +1 -0
  415. package/dist/internal/discovery/instructions.js +95 -0
  416. package/dist/internal/discovery/modules.d.ts +20 -0
  417. package/dist/internal/discovery/modules.d.ts.map +1 -0
  418. package/dist/internal/discovery/modules.js +107 -0
  419. package/dist/internal/discovery/names.d.ts +12 -0
  420. package/dist/internal/discovery/names.d.ts.map +1 -0
  421. package/dist/internal/discovery/names.js +37 -0
  422. package/dist/internal/discovery/project.d.ts +51 -0
  423. package/dist/internal/discovery/project.d.ts.map +1 -0
  424. package/dist/internal/discovery/project.js +293 -0
  425. package/dist/internal/discovery/runtime.d.ts +34 -0
  426. package/dist/internal/discovery/runtime.d.ts.map +1 -0
  427. package/dist/internal/discovery/runtime.js +97 -0
  428. package/dist/internal/discovery/schedules.d.ts +7 -0
  429. package/dist/internal/discovery/schedules.d.ts.map +1 -0
  430. package/dist/internal/discovery/schedules.js +118 -0
  431. package/dist/internal/discovery/seed-files.d.ts +7 -0
  432. package/dist/internal/discovery/seed-files.d.ts.map +1 -0
  433. package/dist/internal/discovery/seed-files.js +41 -0
  434. package/dist/internal/discovery/services.d.ts +21 -0
  435. package/dist/internal/discovery/services.d.ts.map +1 -0
  436. package/dist/internal/discovery/services.js +134 -0
  437. package/dist/internal/discovery/skills.d.ts +11 -0
  438. package/dist/internal/discovery/skills.d.ts.map +1 -0
  439. package/dist/internal/discovery/skills.js +156 -0
  440. package/dist/internal/discovery/subagent.d.ts +16 -0
  441. package/dist/internal/discovery/subagent.d.ts.map +1 -0
  442. package/dist/internal/discovery/subagent.js +128 -0
  443. package/dist/internal/discovery/tools.d.ts +18 -0
  444. package/dist/internal/discovery/tools.d.ts.map +1 -0
  445. package/dist/internal/discovery/tools.js +159 -0
  446. package/dist/internal/discovery.d.ts +8 -63
  447. package/dist/internal/discovery.d.ts.map +1 -1
  448. package/dist/internal/discovery.js +6 -2504
  449. package/dist/internal/distribution.d.ts +10 -27
  450. package/dist/internal/distribution.d.ts.map +1 -1
  451. package/dist/internal/distribution.js +25 -73
  452. package/dist/internal/docs-site.js +1 -1
  453. package/dist/internal/eval-run-store.d.ts +0 -1
  454. package/dist/internal/eval-run-store.d.ts.map +1 -1
  455. package/dist/internal/eval-runner.d.ts.map +1 -1
  456. package/dist/internal/framework-file-storage.d.ts +8 -0
  457. package/dist/internal/framework-file-storage.d.ts.map +1 -1
  458. package/dist/internal/framework-file-storage.js +14 -14
  459. package/dist/internal/framework-storage-selection.d.ts.map +1 -1
  460. package/dist/internal/framework-storage-selection.js +8 -7
  461. package/dist/internal/frontmatter.d.ts +11 -3
  462. package/dist/internal/frontmatter.d.ts.map +1 -1
  463. package/dist/internal/frontmatter.js +29 -3
  464. package/dist/internal/github-fanout.d.ts +1 -1
  465. package/dist/internal/github-fanout.js +1 -1
  466. package/dist/internal/guest-network.d.ts +101 -0
  467. package/dist/internal/guest-network.d.ts.map +1 -0
  468. package/dist/internal/guest-network.js +304 -0
  469. package/dist/internal/host-otel.d.ts +3 -3
  470. package/dist/internal/host-otel.d.ts.map +1 -1
  471. package/dist/internal/host-otel.js +8 -4
  472. package/dist/internal/hosted-admission-adapter.d.ts +8 -7
  473. package/dist/internal/hosted-admission-adapter.d.ts.map +1 -1
  474. package/dist/internal/hosted-delivery-protocol.d.ts +6 -0
  475. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -1
  476. package/dist/internal/hosted-delivery-protocol.js +18 -5
  477. package/dist/internal/hosted-delivery.d.ts +18 -0
  478. package/dist/internal/hosted-delivery.d.ts.map +1 -1
  479. package/dist/internal/hosted-delivery.js +248 -118
  480. package/dist/internal/http-channel.d.ts.map +1 -1
  481. package/dist/internal/http-channel.js +1 -3
  482. package/dist/internal/init-interview.d.ts.map +1 -1
  483. package/dist/internal/init-interview.js +1 -3
  484. package/dist/internal/init-project.d.ts +2 -2
  485. package/dist/internal/init-project.js +2 -2
  486. package/dist/internal/inline-stdio-define-stub.d.ts +1 -1
  487. package/dist/internal/inline-stdio-define-stub.d.ts.map +1 -1
  488. package/dist/internal/inline-stdio-define-stub.js +1 -1
  489. package/dist/internal/is-record.d.ts +2 -0
  490. package/dist/internal/is-record.d.ts.map +1 -0
  491. package/dist/internal/is-record.js +3 -0
  492. package/dist/internal/json-schema.d.ts.map +1 -1
  493. package/dist/internal/json-schema.js +18 -10
  494. package/dist/internal/local-control-plane.d.ts +1 -2
  495. package/dist/internal/local-control-plane.d.ts.map +1 -1
  496. package/dist/internal/local-control-plane.js +3 -20
  497. package/dist/internal/mcp-endpoint.d.ts.map +1 -1
  498. package/dist/internal/mcp-endpoint.js +1 -3
  499. package/dist/internal/mcp-host.d.ts.map +1 -1
  500. package/dist/internal/mcp-host.js +37 -20
  501. package/dist/internal/otel/collector.d.ts +22 -0
  502. package/dist/internal/otel/collector.d.ts.map +1 -1
  503. package/dist/internal/otel/collector.js +145 -126
  504. package/dist/internal/otel/config.d.ts +0 -2
  505. package/dist/internal/otel/config.d.ts.map +1 -1
  506. package/dist/internal/otel/config.js +17 -20
  507. package/dist/internal/otel/http.d.ts +2 -0
  508. package/dist/internal/otel/http.d.ts.map +1 -1
  509. package/dist/internal/otel/http.js +8 -10
  510. package/dist/internal/otel/mcp.d.ts +16 -0
  511. package/dist/internal/otel/mcp.d.ts.map +1 -0
  512. package/dist/internal/otel/mcp.js +55 -0
  513. package/dist/internal/otel/propagation.d.ts +6 -0
  514. package/dist/internal/otel/propagation.d.ts.map +1 -0
  515. package/dist/internal/otel/propagation.js +14 -0
  516. package/dist/internal/otel/runtime.d.ts +26 -1
  517. package/dist/internal/otel/runtime.d.ts.map +1 -1
  518. package/dist/internal/otel/runtime.js +166 -15
  519. package/dist/internal/package-inline-stdio.d.ts.map +1 -1
  520. package/dist/internal/package-inline-stdio.js +3 -11
  521. package/dist/internal/playground/toolchain.d.ts +1 -1
  522. package/dist/internal/playground/toolchain.d.ts.map +1 -1
  523. package/dist/internal/playground/toolchain.js +1 -1
  524. package/dist/internal/request-error-status.d.ts +12 -0
  525. package/dist/internal/request-error-status.d.ts.map +1 -0
  526. package/dist/internal/request-error-status.js +52 -0
  527. package/dist/internal/resolve-prod-target.d.ts +1 -1
  528. package/dist/internal/resolve-prod-target.d.ts.map +1 -1
  529. package/dist/internal/resolve-prod-target.js +3 -7
  530. package/dist/internal/result-output.d.ts +18 -0
  531. package/dist/internal/result-output.d.ts.map +1 -0
  532. package/dist/internal/result-output.js +33 -0
  533. package/dist/internal/run-client.d.ts +2 -2
  534. package/dist/internal/run-client.js +2 -2
  535. package/dist/internal/runtime-dispatch-runner.d.ts +1 -11
  536. package/dist/internal/runtime-dispatch-runner.d.ts.map +1 -1
  537. package/dist/internal/runtime-dispatch-runner.js +2 -15
  538. package/dist/internal/sdk-runner.d.ts.map +1 -1
  539. package/dist/internal/sdk-runner.js +3 -6
  540. package/dist/internal/server.d.ts.map +1 -1
  541. package/dist/internal/server.js +110 -35
  542. package/dist/internal/session-cost.d.ts +3 -3
  543. package/dist/internal/session-cost.d.ts.map +1 -1
  544. package/dist/internal/session-cost.js +3 -3
  545. package/dist/internal/session-engine.d.ts +31 -11
  546. package/dist/internal/session-engine.d.ts.map +1 -1
  547. package/dist/internal/session-engine.js +208 -102
  548. package/dist/internal/session-run-log.d.ts +2 -1
  549. package/dist/internal/session-run-log.d.ts.map +1 -1
  550. package/dist/internal/session-run-log.js +14 -17
  551. package/dist/internal/skills-sync.d.ts +1 -4
  552. package/dist/internal/skills-sync.d.ts.map +1 -1
  553. package/dist/internal/skills-sync.js +10 -50
  554. package/dist/internal/sleep.d.ts +2 -0
  555. package/dist/internal/sleep.d.ts.map +1 -0
  556. package/dist/internal/sleep.js +3 -0
  557. package/dist/internal/start-log-store.d.ts +1 -1
  558. package/dist/internal/start-log-store.d.ts.map +1 -1
  559. package/dist/internal/start-log-store.js +12 -14
  560. package/dist/internal/storage-coordinator.d.ts +4 -1
  561. package/dist/internal/storage-coordinator.d.ts.map +1 -1
  562. package/dist/internal/storage-coordinator.js +15 -13
  563. package/dist/internal/store-mirror.d.ts +29 -0
  564. package/dist/internal/store-mirror.d.ts.map +1 -0
  565. package/dist/internal/store-mirror.js +70 -0
  566. package/dist/internal/tenant-slack/relay.d.ts +73 -0
  567. package/dist/internal/tenant-slack/relay.d.ts.map +1 -0
  568. package/dist/internal/tenant-slack/relay.js +138 -0
  569. package/dist/internal/testing/scm-continuation-fixtures.d.ts +33 -0
  570. package/dist/internal/testing/scm-continuation-fixtures.d.ts.map +1 -0
  571. package/dist/internal/testing/scm-continuation-fixtures.js +253 -0
  572. package/dist/internal/tool-catalog.d.ts.map +1 -1
  573. package/dist/internal/tool-catalog.js +9 -6
  574. package/dist/internal/turn-cost.d.ts +14 -0
  575. package/dist/internal/turn-cost.d.ts.map +1 -1
  576. package/dist/internal/turn-cost.js +41 -9
  577. package/dist/internal/v2-hosting.d.ts +22 -0
  578. package/dist/internal/v2-hosting.d.ts.map +1 -0
  579. package/dist/internal/v2-hosting.js +23 -0
  580. package/dist/internal/workspace-sync.d.ts +22 -0
  581. package/dist/internal/workspace-sync.d.ts.map +1 -0
  582. package/dist/internal/workspace-sync.js +49 -0
  583. package/dist/internal/workspace.d.ts +7 -0
  584. package/dist/internal/workspace.d.ts.map +1 -1
  585. package/dist/internal/workspace.js +13 -0
  586. package/dist/otel.d.ts +39 -1
  587. package/dist/otel.d.ts.map +1 -1
  588. package/dist/otel.js +118 -1
  589. package/dist/playground/assets/index-59KvgREd.js +67 -0
  590. package/dist/playground/assets/index-MbMxXg-y.css +1 -0
  591. package/dist/playground/index.html +2 -2
  592. package/dist/result.d.ts +24 -0
  593. package/dist/result.d.ts.map +1 -0
  594. package/dist/result.js +27 -0
  595. package/dist/storage-backends/cursor-hosted.d.ts.map +1 -1
  596. package/dist/storage-backends/cursor-hosted.js +7 -4
  597. package/dist/storage-protocol.d.ts +24 -23
  598. package/dist/storage-protocol.d.ts.map +1 -1
  599. package/dist/storage-protocol.js +69 -68
  600. package/dist/storage.d.ts +2 -2
  601. package/dist/storage.d.ts.map +1 -1
  602. package/dist/storage.js +1 -1
  603. package/dist/tools.d.ts +9 -0
  604. package/dist/tools.d.ts.map +1 -1
  605. package/dist/tools.js +9 -0
  606. package/dist/types.d.ts +126 -23
  607. package/dist/types.d.ts.map +1 -1
  608. package/docs/README.md +7 -3
  609. package/docs/concepts.md +5 -7
  610. package/docs/design/runtime-abstraction.md +2 -3
  611. package/docs/evals.md +9 -7
  612. package/docs/guides/cloud-agents.md +96 -0
  613. package/docs/guides/github.md +0 -1
  614. package/docs/guides/opentelemetry.md +41 -17
  615. package/docs/reference/agent-config.md +6 -10
  616. package/docs/reference/channels.md +18 -8
  617. package/docs/reference/cli.md +3 -4
  618. package/docs/reference/extensions.md +269 -0
  619. package/docs/reference/hooks.md +215 -46
  620. package/docs/reference/playground.md +3 -0
  621. package/docs/reference/project-layout.md +4 -0
  622. package/docs/reference/result.md +94 -0
  623. package/docs/reference/sessions.md +3 -1
  624. package/docs/reference/skills.md +2 -0
  625. package/docs/reference/tools.md +3 -2
  626. package/docs/templates/pr-autofixer.md +0 -3
  627. package/package.json +29 -10
  628. package/skills/framework-map/SKILL.md +3 -0
  629. package/skills/otel/SKILL.md +8 -3
  630. package/src/ab.ts +1 -1
  631. package/src/bin/agent-serve.ts +121 -21
  632. package/src/channels/bitbucket/api.ts +623 -0
  633. package/src/channels/bitbucket/binding.ts +414 -0
  634. package/src/channels/bitbucket/bitbucket-channel.ts +182 -0
  635. package/src/channels/bitbucket/bitbucket-webhook.ts +576 -0
  636. package/src/channels/bitbucket/checks.ts +154 -0
  637. package/src/channels/bitbucket/cursor-account.ts +117 -0
  638. package/src/channels/bitbucket/defaults.ts +110 -0
  639. package/src/channels/bitbucket/events.ts +84 -0
  640. package/src/channels/bitbucket/index.ts +49 -0
  641. package/src/channels/bitbucket/replay.ts +439 -0
  642. package/src/channels/bitbucket/state.ts +59 -0
  643. package/src/channels/bitbucket/types.ts +266 -0
  644. package/src/channels/deployments/deployments-channel.ts +25 -43
  645. package/src/channels/deployments/types.ts +12 -6
  646. package/src/channels/github/binding.ts +8 -1
  647. package/src/channels/github/cursor-account.ts +17 -6
  648. package/src/channels/github/events.ts +1 -1
  649. package/src/channels/github/forward.ts +3 -2
  650. package/src/channels/github/github-channel.ts +74 -221
  651. package/src/channels/github/replay.ts +1 -1
  652. package/src/channels/github/state.ts +6 -0
  653. package/src/channels/github/types.ts +2 -5
  654. package/src/channels/gitlab/api.ts +228 -0
  655. package/src/channels/gitlab/binding.ts +233 -0
  656. package/src/channels/gitlab/checks.ts +243 -0
  657. package/src/channels/gitlab/cursor-account.ts +114 -0
  658. package/src/channels/gitlab/defaults.ts +93 -0
  659. package/src/channels/gitlab/events.ts +44 -0
  660. package/src/channels/gitlab/gitlab-channel.ts +176 -0
  661. package/src/channels/gitlab/gitlab-webhook.ts +555 -0
  662. package/src/channels/gitlab/index.ts +43 -0
  663. package/src/channels/gitlab/replay.ts +347 -0
  664. package/src/channels/gitlab/state.ts +55 -0
  665. package/src/channels/gitlab/types.ts +263 -0
  666. package/src/channels/origin/api.ts +4 -2
  667. package/src/channels/origin/origin-channel.ts +19 -94
  668. package/src/channels/origin/types.ts +23 -2
  669. package/src/channels/slack/api.ts +4 -2
  670. package/src/channels/slack/assistant.ts +1 -1
  671. package/src/channels/slack/dispatch.ts +27 -2
  672. package/src/channels/slack/eval-directive.ts +1 -6
  673. package/src/channels/slack/inbound.ts +37 -0
  674. package/src/channels/slack/init.ts +6 -3
  675. package/src/channels/slack/manifest.ts +2 -1
  676. package/src/channels/slack/setup.ts +7 -6
  677. package/src/channels/slack/types.ts +1 -1
  678. package/src/channels.ts +0 -1
  679. package/src/client.ts +1 -1
  680. package/src/connections.ts +1 -1
  681. package/src/evals.ts +1 -1
  682. package/src/extensions/cursor-cloud-agents/extension.ts +9 -7
  683. package/src/extensions/cursor-cloud-agents/lib/backend.ts +395 -0
  684. package/src/extensions/cursor-cloud-agents/lib/inputs.ts +5 -0
  685. package/src/extensions/cursor-cloud-agents/lib/transcript.ts +23 -0
  686. package/src/extensions/cursor-cloud-agents/skills/handoff.md +21 -7
  687. package/src/extensions/cursor-cloud-agents/tools/cancel.ts +19 -0
  688. package/src/extensions/cursor-cloud-agents/tools/dump.ts +51 -0
  689. package/src/extensions/cursor-cloud-agents/tools/get.ts +18 -0
  690. package/src/extensions/cursor-cloud-agents/tools/launch.ts +22 -42
  691. package/src/extensions/cursor-cloud-agents/tools/list.ts +1 -1
  692. package/src/extensions/cursor-cloud-agents/tools/reply.ts +34 -0
  693. package/src/extensions.ts +100 -15
  694. package/src/files-backends/cursor-hosted.ts +1 -17
  695. package/src/files.ts +64 -37
  696. package/src/index.ts +27 -26
  697. package/src/internal/ab-snapshot.ts +0 -3
  698. package/src/internal/advertise-tools.ts +1 -4
  699. package/src/internal/authored-alias-hooks.ts +4 -21
  700. package/src/internal/authored-loaders.ts +6 -23
  701. package/src/internal/channel-dispatch.ts +160 -0
  702. package/src/internal/chat-client.ts +1 -1
  703. package/src/internal/cli-ax.ts +5 -5
  704. package/src/internal/cli-bitbucket.ts +477 -0
  705. package/src/internal/cli-convert-automation.ts +7 -7
  706. package/src/internal/cli-cursor.ts +2 -5
  707. package/src/internal/cli-deploy.ts +2 -8
  708. package/src/internal/cli-github.ts +3 -3
  709. package/src/internal/cli-gitlab.ts +485 -0
  710. package/src/internal/cli-mcp.ts +2 -7
  711. package/src/internal/cli-slack.ts +2 -5
  712. package/src/internal/continuation-channel.ts +82 -1
  713. package/src/internal/continuation-identity.ts +229 -11
  714. package/src/internal/conversation-mirror.ts +27 -21
  715. package/src/internal/convert-automation/types.ts +1 -1
  716. package/src/internal/cursor/account-mcp.ts +1 -4
  717. package/src/internal/cursor/backend-client.ts +41 -20
  718. package/src/internal/cursor/bound-secret-file.ts +108 -0
  719. package/src/internal/cursor/credentials.ts +75 -10
  720. package/src/internal/cursor/hosted-bound-secrets.ts +75 -0
  721. package/src/internal/cursor/hosted-deployment-secrets.ts +42 -11
  722. package/src/internal/cursor/hosted-store-secrets.ts +28 -1
  723. package/src/internal/cursor-account-mcp-auth.ts +2 -5
  724. package/src/internal/cursor-deployment-relay.ts +11 -7
  725. package/src/internal/deploy-manifest.ts +4 -2
  726. package/src/internal/discovery/ab.ts +131 -0
  727. package/src/internal/discovery/agent-config.ts +222 -0
  728. package/src/internal/discovery/agent.ts +319 -0
  729. package/src/internal/discovery/channels.ts +105 -0
  730. package/src/internal/discovery/connections.ts +545 -0
  731. package/src/internal/discovery/context.ts +46 -0
  732. package/src/internal/discovery/cursor-plugin.ts +705 -0
  733. package/src/internal/discovery/extension-overlay.ts +274 -0
  734. package/src/internal/discovery/extensions.ts +573 -0
  735. package/src/internal/discovery/fs.ts +108 -0
  736. package/src/internal/discovery/hooks.ts +63 -0
  737. package/src/internal/discovery/info.ts +186 -0
  738. package/src/internal/discovery/instructions.ts +113 -0
  739. package/src/internal/discovery/modules.ts +113 -0
  740. package/src/internal/discovery/names.ts +45 -0
  741. package/src/internal/discovery/project.ts +341 -0
  742. package/src/internal/discovery/runtime.ts +158 -0
  743. package/src/internal/discovery/schedules.ts +120 -0
  744. package/src/internal/discovery/seed-files.ts +37 -0
  745. package/src/internal/discovery/services.ts +160 -0
  746. package/src/internal/discovery/skills.ts +186 -0
  747. package/src/internal/discovery/subagent.ts +136 -0
  748. package/src/internal/discovery/tools.ts +182 -0
  749. package/src/internal/discovery.ts +18 -3081
  750. package/src/internal/distribution.ts +35 -83
  751. package/src/internal/docs-site.ts +1 -1
  752. package/src/internal/eval-run-store.ts +0 -7
  753. package/src/internal/eval-runner.ts +0 -1
  754. package/src/internal/framework-file-storage.ts +14 -14
  755. package/src/internal/framework-storage-selection.ts +9 -9
  756. package/src/internal/frontmatter.ts +36 -3
  757. package/src/internal/github-fanout.ts +1 -1
  758. package/src/internal/guest-network.ts +383 -0
  759. package/src/internal/host-otel.ts +8 -4
  760. package/src/internal/hosted-admission-adapter.ts +8 -8
  761. package/src/internal/hosted-delivery-protocol.ts +26 -1
  762. package/src/internal/hosted-delivery.ts +376 -192
  763. package/src/internal/http-channel.ts +1 -4
  764. package/src/internal/init-interview.ts +1 -4
  765. package/src/internal/init-project.ts +2 -2
  766. package/src/internal/inline-stdio-define-stub.ts +1 -1
  767. package/src/internal/is-record.ts +3 -0
  768. package/src/internal/json-schema.ts +19 -10
  769. package/src/internal/local-control-plane.ts +5 -24
  770. package/src/internal/mcp-endpoint.ts +1 -4
  771. package/src/internal/mcp-host.ts +84 -31
  772. package/src/internal/otel/collector.ts +200 -165
  773. package/src/internal/otel/config.ts +10 -14
  774. package/src/internal/otel/http.ts +16 -13
  775. package/src/internal/otel/mcp.ts +56 -0
  776. package/src/internal/otel/propagation.ts +17 -0
  777. package/src/internal/otel/runtime.ts +242 -25
  778. package/src/internal/package-inline-stdio.ts +3 -12
  779. package/src/internal/playground/toolchain.ts +1 -1
  780. package/src/internal/request-error-status.ts +72 -0
  781. package/src/internal/resolve-prod-target.ts +3 -8
  782. package/src/internal/result-output.ts +34 -0
  783. package/src/internal/run-client.ts +2 -2
  784. package/src/internal/runtime-dispatch-runner.ts +3 -21
  785. package/src/internal/sdk-runner.ts +3 -7
  786. package/src/internal/server.ts +153 -44
  787. package/src/internal/session-cost.ts +3 -3
  788. package/src/internal/session-engine.ts +274 -81
  789. package/src/internal/session-run-log.ts +18 -20
  790. package/src/internal/skills-sync.ts +13 -63
  791. package/src/internal/sleep.ts +3 -0
  792. package/src/internal/start-log-store.ts +13 -16
  793. package/src/internal/storage-coordinator.ts +19 -16
  794. package/src/internal/store-mirror.ts +86 -0
  795. package/src/internal/tenant-slack/relay.ts +179 -0
  796. package/src/internal/testing/scm-continuation-fixtures.ts +286 -0
  797. package/src/internal/tool-catalog.ts +9 -6
  798. package/src/internal/turn-cost.ts +47 -4
  799. package/src/internal/v2-hosting.ts +38 -0
  800. package/src/internal/workspace-sync.ts +55 -0
  801. package/src/internal/workspace.ts +14 -0
  802. package/src/otel.ts +180 -2
  803. package/src/result.ts +36 -0
  804. package/src/storage-backends/cursor-hosted.ts +7 -4
  805. package/src/storage-protocol.ts +102 -95
  806. package/src/storage.ts +4 -0
  807. package/src/tools.ts +18 -0
  808. package/src/types.ts +146 -34
  809. package/templates/triage/agent/lib/types.ts +0 -2
  810. package/dist/continuation.d.ts +0 -20
  811. package/dist/continuation.d.ts.map +0 -1
  812. package/dist/continuation.js +0 -18
  813. package/dist/docs/assets/chunks/@localSearchIndexroot.DbFXINq2.js +0 -1
  814. package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.js +0 -9
  815. package/dist/docs/assets/guides_cloud-runtime.md.CkYbjnAX.lean.js +0 -1
  816. package/dist/docs/assets/index.md.Bb4k8kUm.js +0 -5
  817. package/dist/docs/assets/reference_hooks.md.a8BJxMR5.js +0 -14
  818. package/dist/docs/assets/skills_framework-map.md.BTi817yv.js +0 -1
  819. package/dist/docs/guides/cloud-runtime.html +0 -35
  820. package/dist/docs/guides/cloud-runtime.md +0 -115
  821. package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts +0 -30
  822. package/dist/extensions/cursor-cloud-agents/lib/cloud.d.ts.map +0 -1
  823. package/dist/extensions/cursor-cloud-agents/lib/cloud.js +0 -45
  824. package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts +0 -4
  825. package/dist/extensions/cursor-cloud-agents/tools/follow_up.d.ts.map +0 -1
  826. package/dist/extensions/cursor-cloud-agents/tools/status.d.ts +0 -4
  827. package/dist/extensions/cursor-cloud-agents/tools/status.d.ts.map +0 -1
  828. package/dist/extensions/cursor-cloud-agents/tools/status.js +0 -41
  829. package/dist/internal/convert-automation/index.d.ts +0 -3
  830. package/dist/internal/convert-automation/index.d.ts.map +0 -1
  831. package/dist/internal/convert-automation/index.js +0 -1
  832. package/dist/internal/grokbot/runner.d.ts +0 -64
  833. package/dist/internal/grokbot/runner.d.ts.map +0 -1
  834. package/dist/internal/grokbot/runner.js +0 -282
  835. package/dist/internal/managed-delivery.d.ts +0 -80
  836. package/dist/internal/managed-delivery.d.ts.map +0 -1
  837. package/dist/internal/managed-delivery.js +0 -86
  838. package/dist/internal/review-comments.d.ts +0 -370
  839. package/dist/internal/review-comments.d.ts.map +0 -1
  840. package/dist/internal/review-comments.js +0 -921
  841. package/dist/internal/shallow-clone.d.ts +0 -176
  842. package/dist/internal/shallow-clone.d.ts.map +0 -1
  843. package/dist/internal/shallow-clone.js +0 -419
  844. package/dist/playground/assets/index-BnNN1-EK.js +0 -69
  845. package/dist/playground/assets/index-DBQCwFp0.css +0 -1
  846. package/docs/guides/cloud-runtime.md +0 -120
  847. package/src/continuation.ts +0 -49
  848. package/src/extensions/cursor-cloud-agents/lib/cloud.ts +0 -79
  849. package/src/extensions/cursor-cloud-agents/tools/follow_up.ts +0 -29
  850. package/src/extensions/cursor-cloud-agents/tools/status.ts +0 -39
  851. package/src/internal/convert-automation/index.ts +0 -10
  852. package/src/internal/grokbot/runner.ts +0 -370
  853. package/src/internal/managed-delivery.ts +0 -125
  854. package/src/internal/review-comments.ts +0 -1363
  855. package/src/internal/shallow-clone.ts +0 -609
  856. /package/dist/docs/assets/{evals.md.CPzDAwoH.lean.js → evals.md.CbMoebP1.lean.js} +0 -0
  857. /package/dist/docs/assets/{guides_github.md.BtPr9GaP.lean.js → guides_github.md.DKYiT9do.lean.js} +0 -0
  858. /package/dist/docs/assets/{reference_agent-config.md.BHeYMgme.lean.js → reference_agent-config.md.CHNpiyp4.lean.js} +0 -0
  859. /package/dist/docs/assets/{reference_cli.md.DfoeyvL0.lean.js → reference_cli.md.CJNc_xYK.lean.js} +0 -0
  860. /package/dist/docs/assets/{reference_playground.md.DnX5nL-B.lean.js → reference_playground.md.4myJPxrf.lean.js} +0 -0
  861. /package/dist/docs/assets/{reference_skills.md.BFW9retM.lean.js → reference_skills.md.l2ezAcaN.lean.js} +0 -0
  862. /package/dist/docs/assets/{reference_tools.md.CvAHsdSp.lean.js → reference_tools.md.aGrn99hP.lean.js} +0 -0
@@ -1,1363 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import type { HostGitHubClient } from "../types.js";
3
- import { parsePrUrl } from "./scm/pr-url.js";
4
-
5
- export type ReviewCommentPublisher = "local_gh" | "host_github" | "host_origin";
6
-
7
- export type ReviewCommentPostResult = {
8
- posted: boolean;
9
- publisher: ReviewCommentPublisher;
10
- mode: "review_with_inline_comments" | "review_body_only" | "skipped";
11
- inlineCommentCount: number;
12
- detail: string;
13
- /**
14
- * Ids of the inline comments this post created, when the publisher could
15
- * read them back. Callers that later re-read a PR's comments use these as
16
- * the provenance allowlist: a comment id we did not create is not ours,
17
- * no matter what its body looks like. Empty when the publisher cannot
18
- * resolve them (it never guesses).
19
- */
20
- postedComments?: PostedReviewComment[];
21
- };
22
-
23
- /** One inline comment this agent created, as the SCM assigned it. */
24
- export type PostedReviewComment = {
25
- id: number;
26
- file: string;
27
- line: number;
28
- };
29
-
30
- export type ReviewInlineComment = {
31
- file: string;
32
- line: number;
33
- start_line?: number;
34
- body: string;
35
- };
36
-
37
- export type ReviewCommentPostArgs = {
38
- prUrl: string;
39
- reviewedHeadSha: string;
40
- message: string;
41
- comments: ReviewInlineComment[];
42
- cleanupPrevious?: boolean;
43
- signal?: AbortSignal;
44
- };
45
-
46
- export type ReviewCommentsRequest = {
47
- provider: "github";
48
- repo: string;
49
- prNumber: number;
50
- headSha: string;
51
- message: string;
52
- comments: ReviewInlineComment[];
53
- cleanupPrevious: boolean;
54
- };
55
-
56
- export type ReviewCommentPublisherImplementation = {
57
- postReview: (args: ReviewCommentPostArgs) => Promise<ReviewCommentPostResult>;
58
- };
59
-
60
- /**
61
- * SCMs this module can address. Same growth seam as `shallow-clone.ts`'s
62
- * {@link import("./shallow-clone.js").ScmProvider}: adding a forge means a
63
- * resolver case plus a publisher (and, when the public API supports it, a
64
- * reader / thread resolver). Callers above this line stay provider-neutral.
65
- */
66
- export type ScmReviewProvider = "github" | "origin";
67
-
68
- /**
69
- * Origin public REST client used to post PR reviews (`ctx.origin` /
70
- * {@link import("../channels/origin/api.js").createOriginClient}). Narrower
71
- * than the full Origin handle so tests and CLI paths can inject `request()`.
72
- */
73
- export type HostOriginReviewClient = {
74
- request(input: {
75
- method: "DELETE" | "GET" | "PATCH" | "POST" | "PUT";
76
- path: string;
77
- body?: unknown;
78
- }): Promise<unknown>;
79
- };
80
-
81
- /** Which SCM's PR to read review comments from. */
82
- export type ScmReviewTarget = {
83
- provider: ScmReviewProvider;
84
- /** `owner/name`. */
85
- repo: string;
86
- prNumber: number;
87
- };
88
-
89
- /** Optional structured logger for the read/resolve seams (`[asr]`-style). */
90
- export type ReviewCommentLog = (message: string) => void;
91
-
92
- /**
93
- * One inline review-thread comment from a PR-wide listing, provider-neutral.
94
- *
95
- * This is the Bugbot listing shape (`minimizePreviousBugBotComments` /
96
- * `getBugBotComments` normalize each provider's `getPRComments` output the
97
- * same way): a re-review lists everything on the PR and filters on its own
98
- * marker, rather than fetching ids it recorded elsewhere.
99
- */
100
- export type ListedReviewComment = {
101
- /**
102
- * Provider-native comment id, stringified for provider neutrality
103
- * (GitHub REST database id in decimal; Origin `cmt_…`).
104
- */
105
- commentId: string;
106
- /** GitHub REST numeric comment id, when the provider exposes one. */
107
- numericCommentId?: number;
108
- /**
109
- * Id of the thread this comment opens, in the form the provider's thread
110
- * resolver accepts (GitHub GraphQL thread node id; Origin `cth_…`).
111
- */
112
- threadId: string;
113
- /** Whether the owning thread is already resolved. */
114
- resolved: boolean;
115
- file: string;
116
- startLine: number;
117
- endLine: number;
118
- body: string;
119
- /**
120
- * Head SHA the comment was filed against (GitHub `originalCommit`; Origin
121
- * the thread version's head SHA), when the provider exposes it. This is
122
- * the commit a follow-up judge diffs forward from.
123
- */
124
- commitSha?: string;
125
- authorLogin?: string;
126
- /**
127
- * Whether the SCM attributes the comment to a machine identity — a
128
- * GitHub App bot (GraphQL author `__typename: "Bot"`) or an Origin
129
- * app/service-account actor. Human accounts are `false`; `undefined`
130
- * when the provider did not return an author (e.g. deleted account).
131
- * Callers deciding whether a comment is their own must require `true`
132
- * AND pin the specific identity (login / app id): body content is
133
- * forgeable by any PR participant, and other bots/apps also comment.
134
- */
135
- authorIsBot?: boolean;
136
- /**
137
- * Origin app actor id (`app_…`) when the comment was authored by an app
138
- * installation. Callers compare it against their own configured app id
139
- * to decide the comment is theirs, not merely some app's.
140
- */
141
- authorAppId?: string;
142
- };
143
-
144
- export type ListReviewCommentsArgs = {
145
- target: ScmReviewTarget;
146
- signal?: AbortSignal;
147
- };
148
-
149
- /**
150
- * Read side of the review-comment seam, mirroring
151
- * {@link ReviewCommentPublisherImplementation}. Bugbot's equivalent is
152
- * `IGitProvider.getPRComments`: list the PR's inline review threads (their
153
- * opening comments) so a re-review can find its own previous comments.
154
- */
155
- export type ReviewCommentListerImplementation = {
156
- listReviewComments: (
157
- args: ListReviewCommentsArgs
158
- ) => Promise<ListedReviewComment[]>;
159
- };
160
-
161
- export type ResolveReviewThreadsArgs = {
162
- target: ScmReviewTarget;
163
- /** Provider-native thread ids (from {@link ListedReviewComment.threadId}). */
164
- threadIds: readonly string[];
165
- signal?: AbortSignal;
166
- };
167
-
168
- /**
169
- * Outcome of resolving a set of review threads. Callers treat this as
170
- * best-effort actuation: a failed resolve must not fail the review that
171
- * already posted.
172
- */
173
- export type ResolveReviewThreadsResult = {
174
- requested: number;
175
- resolved: number;
176
- failed: number;
177
- detail: string;
178
- };
179
-
180
- /**
181
- * Write side of thread resolution, the counterpart of
182
- * {@link ReviewCommentListerImplementation}. Bugbot's equivalent is
183
- * `IGitProvider.resolveReviewThreadForComment` / `resolveThreads`.
184
- *
185
- * GitHub only exposes resolve via GraphQL (`resolveReviewThread`). REST
186
- * has no equivalent. The mutation runs as whatever identity minted the
187
- * bound GitHub client — for `githubChannel({ cursorAccount })` that is
188
- * the Cursor installation, the same identity that posted the comments.
189
- * Origin exposes resolve on the public REST API
190
- * (`PATCH …/pulls/threads/{thread_id}`).
191
- */
192
- export type ReviewThreadResolverImplementation = {
193
- resolveReviewThreads: (
194
- args: ResolveReviewThreadsArgs
195
- ) => Promise<ResolveReviewThreadsResult>;
196
- };
197
-
198
- /** Parse a PR URL into the SCM target to read or post comments on. */
199
- export function resolveScmReviewTarget(
200
- prUrl: string
201
- ): ScmReviewTarget | undefined {
202
- const parsed = parsePrUrl(prUrl);
203
- if (parsed === undefined) {
204
- return undefined;
205
- }
206
- return {
207
- provider: parsed.provider,
208
- repo: `${parsed.owner}/${parsed.repo}`,
209
- prNumber: parsed.number,
210
- };
211
- }
212
-
213
- /**
214
- * Lister for a resolved target, mirroring Bugbot's `createPrGitProvider`
215
- * dispatch. Returns undefined when the host cannot serve that provider (no
216
- * GitHub/Origin client bound), so callers degrade instead of throwing.
217
- */
218
- export function createReviewCommentLister(args: {
219
- target: ScmReviewTarget;
220
- github?: HostGitHubClient;
221
- origin?: HostOriginReviewClient;
222
- log?: ReviewCommentLog;
223
- }): ReviewCommentListerImplementation | undefined {
224
- switch (args.target.provider) {
225
- case "github":
226
- return args.github === undefined
227
- ? undefined
228
- : createHostGithubReviewCommentLister(args.github, args.log);
229
- case "origin":
230
- return args.origin === undefined
231
- ? undefined
232
- : createHostOriginReviewCommentLister(args.origin, args.log);
233
- }
234
- }
235
-
236
- /**
237
- * Resolver for a resolved target. Returns undefined when the host cannot
238
- * serve that provider, so callers degrade instead of throwing.
239
- */
240
- export function createReviewThreadResolver(args: {
241
- target: ScmReviewTarget;
242
- github?: HostGitHubClient;
243
- origin?: HostOriginReviewClient;
244
- log?: ReviewCommentLog;
245
- }): ReviewThreadResolverImplementation | undefined {
246
- switch (args.target.provider) {
247
- case "github":
248
- return args.github === undefined
249
- ? undefined
250
- : createHostGithubReviewThreadResolver(args.github, args.log);
251
- case "origin":
252
- return args.origin === undefined
253
- ? undefined
254
- : createHostOriginReviewThreadResolver(args.origin, args.log);
255
- }
256
- }
257
-
258
- /**
259
- * Resolve `threadIds` on `prUrl`'s PR.
260
- *
261
- * No-ops (never throws) when the PR is on an SCM this host cannot write,
262
- * no client is bound, or `threadIds` is empty. Same degrade-don't-fail
263
- * posture as {@link createReviewCommentLister}.
264
- */
265
- export async function resolveReviewThreads(args: {
266
- prUrl: string;
267
- threadIds: readonly string[];
268
- github?: HostGitHubClient;
269
- origin?: HostOriginReviewClient;
270
- resolver?: ReviewThreadResolverImplementation;
271
- signal?: AbortSignal;
272
- log?: ReviewCommentLog;
273
- }): Promise<ResolveReviewThreadsResult> {
274
- if (args.threadIds.length === 0) {
275
- return skippedResolve("no threads to resolve");
276
- }
277
- const target = resolveScmReviewTarget(args.prUrl);
278
- if (target === undefined) {
279
- return skippedResolve("no SCM resolver for this PR URL");
280
- }
281
- const resolver =
282
- args.resolver ??
283
- createReviewThreadResolver({
284
- target,
285
- github: args.github,
286
- origin: args.origin,
287
- log: args.log,
288
- });
289
- if (resolver === undefined) {
290
- return skippedResolve(
291
- `no ${target.provider} client bound to resolve threads`
292
- );
293
- }
294
- return resolver.resolveReviewThreads({
295
- target,
296
- threadIds: args.threadIds,
297
- signal: args.signal,
298
- });
299
- }
300
-
301
- /** Cap on pages pulled per PR; GitHub serves 100 comments per page. */
302
- const REVIEW_COMMENTS_MAX_PAGES = 5;
303
- const REVIEW_COMMENTS_PAGE_SIZE = 100;
304
- /** Cap on review-thread pages when listing a PR's inline threads. */
305
- const REVIEW_THREADS_MAX_PAGES = 20;
306
- const REVIEW_THREADS_PAGE_SIZE = 100;
307
- /** Cap on Origin comment pages pulled per PR (100 comments per page). */
308
- const ORIGIN_COMMENTS_MAX_PAGES = 20;
309
- const ORIGIN_COMMENTS_PAGE_SIZE = 100;
310
-
311
- type GithubThreadCommentNode = {
312
- databaseId?: number | null;
313
- body?: string | null;
314
- author?: { login?: string | null; __typename?: string | null } | null;
315
- originalCommit?: { oid?: string | null } | null;
316
- };
317
-
318
- type GithubReviewThreadNode = {
319
- id?: string;
320
- isResolved?: boolean;
321
- path?: string | null;
322
- line?: number | null;
323
- originalLine?: number | null;
324
- startLine?: number | null;
325
- originalStartLine?: number | null;
326
- comments?: {
327
- nodes?: Array<GithubThreadCommentNode | null>;
328
- };
329
- };
330
-
331
- type GithubReviewThreadsQuery = {
332
- repository?: {
333
- pullRequest?: {
334
- reviewThreads?: {
335
- nodes?: Array<GithubReviewThreadNode | null>;
336
- pageInfo?: { hasNextPage?: boolean; endCursor?: string | null };
337
- };
338
- } | null;
339
- } | null;
340
- };
341
-
342
- type GithubResolveThreadMutation = {
343
- resolveReviewThread?: {
344
- thread?: { isResolved?: boolean };
345
- };
346
- };
347
-
348
- /**
349
- * Repo-scope header for GraphQL calls through the Cursor github-proxy.
350
- *
351
- * The proxy authorizes each call from `x-cursor-github-repos`, which the
352
- * channel Octokit derives from REST URLs (`/repos/{owner}/{repo}/…`).
353
- * GraphQL posts to `/graphql` — no repo in the URL — so without this
354
- * explicit header every GraphQL call is rejected in proxy mode. Harmless
355
- * against api.github.com, which ignores unknown headers.
356
- */
357
- function githubGraphqlScopeHeaders(repo: string): Record<string, string> {
358
- return { "x-cursor-github-repos": repo.toLowerCase() };
359
- }
360
-
361
- /**
362
- * GitHub review thread → {@link ListedReviewComment} (its opening comment).
363
- *
364
- * Prefers the `original*` line fields — the position as of the review the
365
- * thread belongs to. `line` drifts as the PR gains commits, so a caller
366
- * correlating a comment with the review that produced it needs the original
367
- * position, the same fields Bugbot carries on `PullRequestCommentOutput`.
368
- */
369
- export function listedCommentFromGithubThread(
370
- thread: GithubReviewThreadNode
371
- ): ListedReviewComment | undefined {
372
- const opener = thread.comments?.nodes?.[0];
373
- if (
374
- thread.id === undefined ||
375
- thread.id === "" ||
376
- opener === null ||
377
- opener === undefined ||
378
- opener.databaseId === undefined ||
379
- opener.databaseId === null ||
380
- typeof opener.body !== "string" ||
381
- typeof thread.path !== "string" ||
382
- thread.path === ""
383
- ) {
384
- return undefined;
385
- }
386
- // Take both lines from the same position set. Mixing them (original end
387
- // line with the drifted current start line) would describe a range that
388
- // never existed in either revision.
389
- const original = thread.originalLine ?? undefined;
390
- const endLine = original ?? thread.line ?? undefined;
391
- if (endLine === undefined) {
392
- return undefined;
393
- }
394
- const startLine =
395
- (original === undefined ? thread.startLine : thread.originalStartLine) ??
396
- endLine;
397
- const commitSha = opener.originalCommit?.oid ?? undefined;
398
- const authorLogin = opener.author?.login ?? undefined;
399
- const authorType = opener.author?.__typename ?? undefined;
400
- return {
401
- commentId: String(opener.databaseId),
402
- numericCommentId: opener.databaseId,
403
- threadId: thread.id,
404
- resolved: thread.isResolved === true,
405
- file: thread.path,
406
- startLine,
407
- endLine,
408
- body: opener.body,
409
- ...(commitSha === undefined ? {} : { commitSha }),
410
- ...(authorLogin === undefined ? {} : { authorLogin }),
411
- ...(authorType === undefined ? {} : { authorIsBot: authorType === "Bot" }),
412
- };
413
- }
414
-
415
- /**
416
- * Lists the PR's inline review threads (their opening comments) through the
417
- * host GitHub client (Cursor account lease, App installation token, or
418
- * PAT). One paged GraphQL query yields, per thread: the resolvable thread
419
- * node id, its resolution state, the opener's body/position, and the commit
420
- * it was filed against — everything a Bugbot-style re-review needs.
421
- */
422
- export function createHostGithubReviewCommentLister(
423
- github: HostGitHubClient,
424
- log?: ReviewCommentLog
425
- ): ReviewCommentListerImplementation {
426
- return {
427
- async listReviewComments({ target, signal }) {
428
- const [owner, repo] = target.repo.split("/", 2);
429
- if (owner === undefined || repo === undefined || repo === "") {
430
- log?.(`github list: unparseable owner/repo "${target.repo}"`);
431
- return [];
432
- }
433
- const octokit = await github.getOctokit();
434
- const comments: ListedReviewComment[] = [];
435
- let threadCount = 0;
436
- let cursor: string | null = null;
437
- for (let page = 0; page < REVIEW_THREADS_MAX_PAGES; page++) {
438
- signal?.throwIfAborted();
439
- const response = (await octokit.graphql(
440
- REVIEW_THREAD_COMMENTS_FOR_PR_QUERY,
441
- {
442
- owner,
443
- repo,
444
- number: target.prNumber,
445
- cursor,
446
- headers: githubGraphqlScopeHeaders(target.repo),
447
- }
448
- )) as GithubReviewThreadsQuery;
449
- const reviewThreads = response.repository?.pullRequest?.reviewThreads;
450
- for (const thread of reviewThreads?.nodes ?? []) {
451
- if (thread === null || thread === undefined) {
452
- continue;
453
- }
454
- threadCount += 1;
455
- const listed = listedCommentFromGithubThread(thread);
456
- if (listed !== undefined) {
457
- comments.push(listed);
458
- }
459
- }
460
- const pageInfo = reviewThreads?.pageInfo;
461
- if (pageInfo?.hasNextPage !== true || !pageInfo.endCursor) {
462
- break;
463
- }
464
- cursor = pageInfo.endCursor;
465
- }
466
- log?.(
467
- `github list: ${target.repo}#${target.prNumber} has ${threadCount} review thread(s), ${comments.length} with a normalizable opening comment`
468
- );
469
- return comments;
470
- },
471
- };
472
- }
473
-
474
- /**
475
- * Resolves inline review threads by GraphQL thread node id through the host
476
- * GitHub client (Cursor account lease, App installation token, or PAT) —
477
- * the id the lister already returned, so no comment→thread mapping pass is
478
- * needed. Same mutation as Bugbot's `resolveReviewThreadForComment`.
479
- */
480
- export function createHostGithubReviewThreadResolver(
481
- github: HostGitHubClient,
482
- log?: ReviewCommentLog
483
- ): ReviewThreadResolverImplementation {
484
- return {
485
- async resolveReviewThreads({ target, threadIds, signal }) {
486
- const uniqueIds = [...new Set(threadIds.filter((id) => id !== ""))];
487
- if (uniqueIds.length === 0) {
488
- return skippedResolve("no threads to resolve");
489
- }
490
- let resolved = 0;
491
- let failed = 0;
492
- try {
493
- const octokit = await github.getOctokit();
494
- for (const threadId of uniqueIds) {
495
- signal?.throwIfAborted();
496
- try {
497
- const mutation = (await octokit.graphql(
498
- RESOLVE_REVIEW_THREAD_MUTATION,
499
- {
500
- threadId,
501
- headers: githubGraphqlScopeHeaders(target.repo),
502
- }
503
- )) as GithubResolveThreadMutation;
504
- if (mutation.resolveReviewThread?.thread?.isResolved === true) {
505
- resolved += 1;
506
- log?.(`github resolve: thread ${threadId} resolved`);
507
- } else {
508
- failed += 1;
509
- log?.(
510
- `github resolve: thread ${threadId} mutation did not mark the thread resolved`
511
- );
512
- }
513
- } catch (error) {
514
- if (signal?.aborted) {
515
- throw error;
516
- }
517
- failed += 1;
518
- log?.(
519
- `github resolve: thread ${threadId} failed: ${error instanceof Error ? error.message : String(error)}`
520
- );
521
- }
522
- }
523
- return {
524
- requested: uniqueIds.length,
525
- resolved,
526
- failed,
527
- detail: `resolved ${resolved} of ${uniqueIds.length} thread(s) on ${target.repo}#${target.prNumber} via host GitHub (${failed} failed)`,
528
- };
529
- } catch (error) {
530
- if (signal?.aborted) {
531
- throw error;
532
- }
533
- return {
534
- requested: uniqueIds.length,
535
- resolved,
536
- failed: uniqueIds.length - resolved,
537
- detail: `host GitHub thread resolve failed: ${error instanceof Error ? error.message : String(error)}`,
538
- };
539
- }
540
- },
541
- };
542
- }
543
-
544
- const REVIEW_THREAD_COMMENTS_FOR_PR_QUERY = `
545
- query ReviewThreadCommentsForPr(
546
- $owner: String!
547
- $repo: String!
548
- $number: Int!
549
- $cursor: String
550
- ) {
551
- repository(owner: $owner, name: $repo) {
552
- pullRequest(number: $number) {
553
- reviewThreads(first: ${REVIEW_THREADS_PAGE_SIZE}, after: $cursor) {
554
- nodes {
555
- id
556
- isResolved
557
- path
558
- line
559
- originalLine
560
- startLine
561
- originalStartLine
562
- comments(first: 1) {
563
- nodes {
564
- databaseId
565
- body
566
- author { login __typename }
567
- originalCommit { oid }
568
- }
569
- }
570
- }
571
- pageInfo { hasNextPage endCursor }
572
- }
573
- }
574
- }
575
- }
576
- `;
577
-
578
- const RESOLVE_REVIEW_THREAD_MUTATION = `
579
- mutation ResolveReviewThread($threadId: ID!) {
580
- resolveReviewThread(input: { threadId: $threadId }) {
581
- thread { isResolved }
582
- }
583
- }
584
- `;
585
-
586
- const GITHUB_VIEWER_LOGIN_QUERY = `
587
- query ViewerLogin {
588
- viewer { login }
589
- }
590
- `;
591
-
592
- /**
593
- * The login the bound GitHub client itself acts as — the identity its posts
594
- * appear under. Works for installation tokens too (GraphQL `viewer` returns
595
- * the app's bot, e.g. `cursor[bot]`), so a reader can trust comments whose
596
- * author is provably the same identity it posts with, across every
597
- * environment's app (prod/staging/cloud-dev/custom) without hardcoding.
598
- * `repo` scopes the call through the Cursor github-proxy (the minted token
599
- * — and so the viewer — is per-repo there). Best-effort: `undefined` when
600
- * the lookup fails.
601
- */
602
- export async function fetchGithubSelfLogin(
603
- github: HostGitHubClient,
604
- args: { repo: string; signal?: AbortSignal; log?: ReviewCommentLog }
605
- ): Promise<string | undefined> {
606
- try {
607
- const octokit = await github.getOctokit();
608
- args.signal?.throwIfAborted();
609
- const response = (await octokit.graphql(GITHUB_VIEWER_LOGIN_QUERY, {
610
- headers: githubGraphqlScopeHeaders(args.repo),
611
- })) as {
612
- viewer?: { login?: string | null } | null;
613
- };
614
- const login = response.viewer?.login;
615
- return typeof login === "string" && login !== "" ? login : undefined;
616
- } catch (error) {
617
- if (args.signal?.aborted) {
618
- throw error;
619
- }
620
- args.log?.(
621
- `github viewer lookup failed: ${error instanceof Error ? error.message : String(error)}`
622
- );
623
- return undefined;
624
- }
625
- }
626
-
627
- type OriginThreadJson = {
628
- id?: string;
629
- path?: string;
630
- startLine?: number;
631
- endLine?: number;
632
- resolvedAt?: string;
633
- version?: { headSha?: string };
634
- };
635
-
636
- /**
637
- * Public `OriginActor` proto3 JSON: a `user` / `app` / `serviceAccount`
638
- * oneof (see `origin_actor.proto`).
639
- */
640
- type OriginActorJson = {
641
- user?: { id?: string; email?: string };
642
- // Apps have no slug (they are id + display name); `slug` is being retired
643
- // from the public actor and is never read here.
644
- app?: { id?: string; displayName?: string };
645
- serviceAccount?: { id?: string };
646
- };
647
-
648
- type OriginCommentJson = {
649
- id?: string;
650
- body?: string;
651
- thread?: OriginThreadJson;
652
- author?: OriginActorJson;
653
- };
654
-
655
- type OriginListCommentsJson = {
656
- comments?: Array<OriginCommentJson | null>;
657
- nextPageToken?: string;
658
- };
659
-
660
- /**
661
- * Origin public comment → {@link ListedReviewComment}. Only line-anchored
662
- * threads qualify (general-discussion and file-level threads carry no
663
- * position a review finding can be pinned to).
664
- */
665
- export function listedCommentFromOriginComment(
666
- comment: OriginCommentJson
667
- ): ListedReviewComment | undefined {
668
- const thread = comment.thread;
669
- if (
670
- typeof comment.id !== "string" ||
671
- comment.id === "" ||
672
- typeof comment.body !== "string" ||
673
- thread === undefined ||
674
- typeof thread.id !== "string" ||
675
- thread.id === "" ||
676
- typeof thread.path !== "string" ||
677
- thread.path === "" ||
678
- typeof thread.startLine !== "number" ||
679
- thread.startLine <= 0
680
- ) {
681
- return undefined;
682
- }
683
- const startLine = thread.startLine;
684
- const endLine =
685
- typeof thread.endLine === "number" && thread.endLine >= startLine
686
- ? thread.endLine
687
- : startLine;
688
- const commitSha = thread.version?.headSha;
689
- const author = comment.author;
690
- const authorLogin =
691
- author?.app?.displayName ?? author?.app?.id ?? author?.user?.email;
692
- // App and service-account actors are machine identities; only a `user`
693
- // actor is a human PR participant.
694
- const authorIsBot =
695
- author === undefined
696
- ? undefined
697
- : author.app !== undefined || author.serviceAccount !== undefined;
698
- const authorAppId = author?.app?.id;
699
- return {
700
- commentId: comment.id,
701
- threadId: thread.id,
702
- resolved: typeof thread.resolvedAt === "string" && thread.resolvedAt !== "",
703
- file: thread.path,
704
- startLine,
705
- endLine,
706
- body: comment.body,
707
- ...(typeof commitSha === "string" && commitSha !== "" ? { commitSha } : {}),
708
- ...(typeof authorLogin === "string" && authorLogin !== ""
709
- ? { authorLogin }
710
- : {}),
711
- ...(authorIsBot === undefined ? {} : { authorIsBot }),
712
- ...(typeof authorAppId === "string" && authorAppId !== ""
713
- ? { authorAppId }
714
- : {}),
715
- };
716
- }
717
-
718
- /**
719
- * Lists the PR's inline review threads through the Origin public REST API
720
- * (`GET …/pulls/{n}/comments`, paged). The flattened comment list is
721
- * ordered by creation time, so the first comment seen per thread is the
722
- * thread opener; replies are dropped.
723
- */
724
- export function createHostOriginReviewCommentLister(
725
- origin: HostOriginReviewClient,
726
- log?: ReviewCommentLog
727
- ): ReviewCommentListerImplementation {
728
- return {
729
- async listReviewComments({ target, signal }) {
730
- const [owner, repo] = target.repo.split("/", 2);
731
- if (owner === undefined || repo === undefined || repo === "") {
732
- log?.(`origin list: unparseable owner/repo "${target.repo}"`);
733
- return [];
734
- }
735
- const basePath = `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${target.prNumber}/comments`;
736
- const comments: ListedReviewComment[] = [];
737
- const seenThreads = new Set<string>();
738
- let totalComments = 0;
739
- let pageToken = "";
740
- for (let page = 0; page < ORIGIN_COMMENTS_MAX_PAGES; page++) {
741
- signal?.throwIfAborted();
742
- const query =
743
- pageToken === ""
744
- ? `?pageSize=${ORIGIN_COMMENTS_PAGE_SIZE}`
745
- : `?pageSize=${ORIGIN_COMMENTS_PAGE_SIZE}&pageToken=${encodeURIComponent(pageToken)}`;
746
- const response = (await origin.request({
747
- method: "GET",
748
- path: `${basePath}${query}`,
749
- })) as OriginListCommentsJson | null | undefined;
750
- for (const comment of response?.comments ?? []) {
751
- if (comment === null || comment === undefined) {
752
- continue;
753
- }
754
- totalComments += 1;
755
- const listed = listedCommentFromOriginComment(comment);
756
- if (listed === undefined || seenThreads.has(listed.threadId)) {
757
- // Not line-anchored, or a reply on a thread whose opener was
758
- // already taken (the list is oldest-first).
759
- continue;
760
- }
761
- seenThreads.add(listed.threadId);
762
- comments.push(listed);
763
- }
764
- pageToken = response?.nextPageToken ?? "";
765
- if (pageToken === "") {
766
- break;
767
- }
768
- }
769
- log?.(
770
- `origin list: ${target.repo}#${target.prNumber} has ${totalComments} comment(s), ${comments.length} line-anchored thread opener(s)`
771
- );
772
- return comments;
773
- },
774
- };
775
- }
776
-
777
- /**
778
- * Resolves Origin comment threads through the public REST API
779
- * (`PATCH …/pulls/threads/{thread_id}` with `resolved: true`).
780
- */
781
- export function createHostOriginReviewThreadResolver(
782
- origin: HostOriginReviewClient,
783
- log?: ReviewCommentLog
784
- ): ReviewThreadResolverImplementation {
785
- return {
786
- async resolveReviewThreads({ target, threadIds, signal }) {
787
- const uniqueIds = [...new Set(threadIds.filter((id) => id !== ""))];
788
- if (uniqueIds.length === 0) {
789
- return skippedResolve("no threads to resolve");
790
- }
791
- const [owner, repo] = target.repo.split("/", 2);
792
- if (owner === undefined || repo === undefined || repo === "") {
793
- return skippedResolve("unparseable owner/repo from PR URL");
794
- }
795
- let resolved = 0;
796
- let failed = 0;
797
- for (const threadId of uniqueIds) {
798
- signal?.throwIfAborted();
799
- try {
800
- await origin.request({
801
- method: "PATCH",
802
- path: `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/threads/${encodeURIComponent(threadId)}`,
803
- body: { resolved: true },
804
- });
805
- resolved += 1;
806
- log?.(`origin resolve: thread ${threadId} resolved`);
807
- } catch (error) {
808
- if (signal?.aborted) {
809
- throw error;
810
- }
811
- failed += 1;
812
- log?.(
813
- `origin resolve: thread ${threadId} failed: ${error instanceof Error ? error.message : String(error)}`
814
- );
815
- }
816
- }
817
- return {
818
- requested: uniqueIds.length,
819
- resolved,
820
- failed,
821
- detail: `resolved ${resolved} of ${uniqueIds.length} thread(s) on ${target.repo}#${target.prNumber} via host Origin (${failed} failed)`,
822
- };
823
- },
824
- };
825
- }
826
-
827
- type ParsedGithubPrUrl = {
828
- repo: string;
829
- prNumber: number;
830
- };
831
-
832
- /**
833
- * Prepares the provider-neutral review payload used by local `gh` posting.
834
- */
835
- export function prepareReviewCommentsRequest(
836
- args: ReviewCommentPostArgs
837
- ):
838
- | { kind: "prepared"; request: ReviewCommentsRequest }
839
- | { kind: "skipped"; result: ReviewCommentPostResult } {
840
- const target = parseGithubPrUrl(args.prUrl);
841
- if (target.kind === "invalid") {
842
- return { kind: "skipped", result: skipped(target.detail) };
843
- }
844
-
845
- return {
846
- kind: "prepared",
847
- request: {
848
- provider: "github",
849
- repo: target.value.repo,
850
- prNumber: target.value.prNumber,
851
- headSha: args.reviewedHeadSha,
852
- message: args.message,
853
- comments: args.comments,
854
- cleanupPrevious: args.cleanupPrevious ?? true,
855
- },
856
- };
857
- }
858
-
859
- /**
860
- * Posts a PR review with the local `gh` credentials (`gh auth` / GITHUB_TOKEN /
861
- * GH_TOKEN). Does not use the security-bugbot comments service.
862
- */
863
- export function createLocalGhReviewPublisher(): ReviewCommentPublisherImplementation {
864
- return {
865
- async postReview(args) {
866
- return postReviewViaLocalGh(args);
867
- },
868
- };
869
- }
870
-
871
- /**
872
- * Posts a PR review through the host GitHub client (Cursor account lease,
873
- * App installation token, or PAT). Prefer this on Cursor-deployed agents —
874
- * no separate GitHub write secret is required when `githubChannel({
875
- * cursorAccount })` is bound.
876
- */
877
- export function createHostGithubReviewPublisher(
878
- github: HostGitHubClient
879
- ): ReviewCommentPublisherImplementation {
880
- return {
881
- async postReview(args) {
882
- return postReviewViaHostGithub(github, args);
883
- },
884
- };
885
- }
886
-
887
- /**
888
- * Pick the publisher for `prUrl`'s SCM. GitHub falls back to local `gh`
889
- * when no host client is bound (CLI). Origin has no local CLI publisher —
890
- * returns undefined unless an Origin REST client is provided.
891
- */
892
- export function createReviewCommentPublisher(args: {
893
- prUrl: string;
894
- github?: HostGitHubClient;
895
- origin?: HostOriginReviewClient;
896
- }): ReviewCommentPublisherImplementation | undefined {
897
- const target = resolveScmReviewTarget(args.prUrl);
898
- if (target === undefined) {
899
- return undefined;
900
- }
901
- switch (target.provider) {
902
- case "github":
903
- return args.github !== undefined
904
- ? createHostGithubReviewPublisher(args.github)
905
- : createLocalGhReviewPublisher();
906
- case "origin":
907
- return args.origin === undefined
908
- ? undefined
909
- : createHostOriginReviewPublisher(args.origin);
910
- }
911
- }
912
-
913
- /**
914
- * Posts a COMMENT-verdict Origin review through the public REST API.
915
- *
916
- * Inline comments post as diff-anchored threads via the review's
917
- * `comments` field (`ReviewCommentInput` with an `InlineCommentAnchor`).
918
- * Origin rejects the whole request with INVALID_ARGUMENT when any anchor
919
- * is off the reviewed version's diff — the caller's body-only retry (the
920
- * same fallback GitHub's 422 takes) then folds the findings into the
921
- * review body.
922
- */
923
- export function createHostOriginReviewPublisher(
924
- origin: HostOriginReviewClient
925
- ): ReviewCommentPublisherImplementation {
926
- return {
927
- async postReview(args) {
928
- return postReviewViaHostOrigin(origin, args);
929
- },
930
- };
931
- }
932
-
933
- async function postReviewViaHostGithub(
934
- github: HostGitHubClient,
935
- args: ReviewCommentPostArgs
936
- ): Promise<ReviewCommentPostResult> {
937
- const prepared = prepareReviewCommentsRequest(args);
938
- if (prepared.kind === "skipped") {
939
- return {
940
- ...prepared.result,
941
- publisher: "host_github",
942
- };
943
- }
944
-
945
- const { request } = prepared;
946
- const [owner, repo] = request.repo.split("/", 2);
947
- if (owner === undefined || repo === undefined || repo === "") {
948
- return skippedHost("unparseable owner/repo from PR URL");
949
- }
950
-
951
- try {
952
- args.signal?.throwIfAborted();
953
- const octokit = await github.getOctokit();
954
- args.signal?.throwIfAborted();
955
- const response = await octokit.rest.pulls.createReview({
956
- owner,
957
- repo,
958
- pull_number: request.prNumber,
959
- commit_id: request.headSha,
960
- body: request.message,
961
- event: "COMMENT",
962
- comments: request.comments.map(toGithubPullRequestReviewComment),
963
- });
964
- const htmlUrl =
965
- typeof response.data.html_url === "string"
966
- ? response.data.html_url
967
- : undefined;
968
- const inlineCommentCount = request.comments.length;
969
- return {
970
- posted: true,
971
- publisher: "host_github",
972
- mode:
973
- inlineCommentCount > 0
974
- ? "review_with_inline_comments"
975
- : "review_body_only",
976
- inlineCommentCount,
977
- detail: htmlUrl
978
- ? `posted via host GitHub: ${htmlUrl}`
979
- : `posted via host GitHub with ${inlineCommentCount} inline comment(s)`,
980
- postedComments: await readPostedComments({
981
- octokit,
982
- owner,
983
- repo,
984
- prNumber: request.prNumber,
985
- reviewId: response.data.id,
986
- expected: inlineCommentCount,
987
- signal: args.signal,
988
- }),
989
- };
990
- } catch (error) {
991
- if (args.signal?.aborted) {
992
- throw error;
993
- }
994
- return skippedHost(
995
- `host GitHub review post failed: ${error instanceof Error ? error.message : String(error)}`
996
- );
997
- }
998
- }
999
-
1000
- /**
1001
- * Ids of the inline comments a just-created review owns.
1002
- *
1003
- * `pulls.createReview` returns the review, not its comments.
1004
- * `listCommentsForReview` either omits those rows or returns them with
1005
- * `line` / `original_line` unset, so the line filter drops every id, the
1006
- * store records no findings, and the next run cannot judge or resolve
1007
- * those threads. Read the PR-wide list instead and keep only this
1008
- * review's rows. Newest-first so a busy PR's older comments cannot push
1009
- * ours past the page cap.
1010
- * Best-effort: any failure yields an empty list, which costs the next run
1011
- * its prior findings rather than risking a wrong id. Never throws — the
1012
- * review is already posted by this point.
1013
- */
1014
- async function readPostedComments(args: {
1015
- octokit: Awaited<ReturnType<HostGitHubClient["getOctokit"]>>;
1016
- owner: string;
1017
- repo: string;
1018
- prNumber: number;
1019
- reviewId: number;
1020
- expected: number;
1021
- signal?: AbortSignal;
1022
- }): Promise<PostedReviewComment[]> {
1023
- if (args.expected === 0) {
1024
- return [];
1025
- }
1026
- try {
1027
- const posted: PostedReviewComment[] = [];
1028
- for (let page = 1; page <= REVIEW_COMMENTS_MAX_PAGES; page++) {
1029
- args.signal?.throwIfAborted();
1030
- const response = await args.octokit.rest.pulls.listReviewComments({
1031
- owner: args.owner,
1032
- repo: args.repo,
1033
- pull_number: args.prNumber,
1034
- sort: "created",
1035
- direction: "desc",
1036
- per_page: REVIEW_COMMENTS_PAGE_SIZE,
1037
- page,
1038
- });
1039
- for (const comment of response.data) {
1040
- if (comment.pull_request_review_id !== args.reviewId) {
1041
- continue;
1042
- }
1043
- const line = comment.original_line ?? comment.line;
1044
- if (line === null || line === undefined) {
1045
- continue;
1046
- }
1047
- posted.push({ id: comment.id, file: comment.path, line });
1048
- }
1049
- if (
1050
- posted.length >= args.expected ||
1051
- response.data.length < REVIEW_COMMENTS_PAGE_SIZE
1052
- ) {
1053
- break;
1054
- }
1055
- }
1056
- return posted;
1057
- } catch {
1058
- return [];
1059
- }
1060
- }
1061
-
1062
- async function postReviewViaLocalGh(
1063
- args: ReviewCommentPostArgs
1064
- ): Promise<ReviewCommentPostResult> {
1065
- const prepared = prepareReviewCommentsRequest(args);
1066
- if (prepared.kind === "skipped") {
1067
- return prepared.result;
1068
- }
1069
-
1070
- const { request } = prepared;
1071
- const path = `repos/${request.repo}/pulls/${request.prNumber}/reviews`;
1072
- const payload = {
1073
- commit_id: request.headSha,
1074
- body: request.message,
1075
- event: "COMMENT",
1076
- comments: request.comments.map(toGithubReviewComment),
1077
- };
1078
-
1079
- try {
1080
- args.signal?.throwIfAborted();
1081
- const response = await ghApiPostJson(path, payload, args.signal);
1082
- const htmlUrl =
1083
- typeof response.html_url === "string" ? response.html_url : undefined;
1084
- const inlineCommentCount = request.comments.length;
1085
- return {
1086
- posted: true,
1087
- publisher: "local_gh",
1088
- mode:
1089
- inlineCommentCount > 0
1090
- ? "review_with_inline_comments"
1091
- : "review_body_only",
1092
- inlineCommentCount,
1093
- detail: htmlUrl
1094
- ? `posted via local gh: ${htmlUrl}`
1095
- : `posted via local gh with ${inlineCommentCount} inline comment(s)`,
1096
- };
1097
- } catch (error) {
1098
- if (args.signal?.aborted) {
1099
- throw error;
1100
- }
1101
- return skipped(
1102
- `local gh review post failed: ${error instanceof Error ? error.message : String(error)}`
1103
- );
1104
- }
1105
- }
1106
-
1107
- type GithubPullRequestReviewComment = {
1108
- path: string;
1109
- body: string;
1110
- line: number;
1111
- side: "RIGHT";
1112
- start_line?: number;
1113
- start_side?: "RIGHT";
1114
- };
1115
-
1116
- function toGithubReviewComment(
1117
- comment: ReviewInlineComment
1118
- ): Record<string, string | number> {
1119
- return toGithubPullRequestReviewComment(comment);
1120
- }
1121
-
1122
- function toGithubPullRequestReviewComment(
1123
- comment: ReviewInlineComment
1124
- ): GithubPullRequestReviewComment {
1125
- const body: GithubPullRequestReviewComment = {
1126
- path: comment.file,
1127
- body: comment.body,
1128
- line: comment.line,
1129
- side: "RIGHT",
1130
- };
1131
- if (
1132
- comment.start_line !== undefined &&
1133
- comment.start_line > 0 &&
1134
- comment.start_line !== comment.line
1135
- ) {
1136
- body.start_line = comment.start_line;
1137
- body.start_side = "RIGHT";
1138
- }
1139
- return body;
1140
- }
1141
-
1142
- function skipped(detail: string): ReviewCommentPostResult {
1143
- return {
1144
- posted: false,
1145
- publisher: "local_gh",
1146
- mode: "skipped",
1147
- inlineCommentCount: 0,
1148
- detail,
1149
- };
1150
- }
1151
-
1152
- function skippedHost(detail: string): ReviewCommentPostResult {
1153
- return {
1154
- posted: false,
1155
- publisher: "host_github",
1156
- mode: "skipped",
1157
- inlineCommentCount: 0,
1158
- detail,
1159
- };
1160
- }
1161
-
1162
- function skippedOrigin(detail: string): ReviewCommentPostResult {
1163
- return {
1164
- posted: false,
1165
- publisher: "host_origin",
1166
- mode: "skipped",
1167
- inlineCommentCount: 0,
1168
- detail,
1169
- };
1170
- }
1171
-
1172
- async function postReviewViaHostOrigin(
1173
- origin: HostOriginReviewClient,
1174
- args: ReviewCommentPostArgs
1175
- ): Promise<ReviewCommentPostResult> {
1176
- const target = resolveScmReviewTarget(args.prUrl);
1177
- if (target === undefined || target.provider !== "origin") {
1178
- return skippedOrigin("host Origin publisher only supports Origin PRs");
1179
- }
1180
- const [owner, repo] = target.repo.split("/", 2);
1181
- if (owner === undefined || repo === undefined || repo === "") {
1182
- return skippedOrigin("unparseable owner/repo from PR URL");
1183
- }
1184
-
1185
- try {
1186
- args.signal?.throwIfAborted();
1187
- await origin.request({
1188
- method: "POST",
1189
- path: `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${target.prNumber}/reviews`,
1190
- body: {
1191
- verdict: "comment",
1192
- body: args.message,
1193
- comments: args.comments.map(toOriginReviewCommentInput),
1194
- },
1195
- });
1196
- const inlineCommentCount = args.comments.length;
1197
- return {
1198
- posted: true,
1199
- publisher: "host_origin",
1200
- mode:
1201
- inlineCommentCount > 0
1202
- ? "review_with_inline_comments"
1203
- : "review_body_only",
1204
- inlineCommentCount,
1205
- detail: `posted Origin review on ${target.repo}#${target.prNumber} with ${inlineCommentCount} inline comment(s)`,
1206
- };
1207
- } catch (error) {
1208
- if (args.signal?.aborted) {
1209
- throw error;
1210
- }
1211
- return skippedOrigin(
1212
- `host Origin review post failed: ${error instanceof Error ? error.message : String(error)}`
1213
- );
1214
- }
1215
- }
1216
-
1217
- type OriginReviewCommentInput = {
1218
- body: string;
1219
- inline: {
1220
- path: string;
1221
- side: "right";
1222
- startLine: number;
1223
- endLine?: number;
1224
- };
1225
- };
1226
-
1227
- /** Provider-neutral inline comment → Origin `ReviewCommentInput`. */
1228
- function toOriginReviewCommentInput(
1229
- comment: ReviewInlineComment
1230
- ): OriginReviewCommentInput {
1231
- const startLine =
1232
- comment.start_line !== undefined &&
1233
- comment.start_line > 0 &&
1234
- comment.start_line < comment.line
1235
- ? comment.start_line
1236
- : comment.line;
1237
- return {
1238
- body: comment.body,
1239
- inline: {
1240
- path: comment.file,
1241
- side: "right",
1242
- startLine,
1243
- ...(startLine === comment.line ? {} : { endLine: comment.line }),
1244
- },
1245
- };
1246
- }
1247
-
1248
- function skippedResolve(detail: string): ResolveReviewThreadsResult {
1249
- return {
1250
- requested: 0,
1251
- resolved: 0,
1252
- failed: 0,
1253
- detail,
1254
- };
1255
- }
1256
-
1257
- function parseGithubPrUrl(
1258
- prUrl: string
1259
- ):
1260
- | { kind: "valid"; value: ParsedGithubPrUrl }
1261
- | { kind: "invalid"; detail: string } {
1262
- let url: URL;
1263
- try {
1264
- url = new URL(prUrl);
1265
- } catch (error) {
1266
- return {
1267
- kind: "invalid",
1268
- detail: `unparseable PR URL: ${error instanceof Error ? error.message : String(error)}`,
1269
- };
1270
- }
1271
-
1272
- if (url.hostname !== "github.com") {
1273
- return {
1274
- kind: "invalid",
1275
- detail: "local gh publisher only supports github.com PRs",
1276
- };
1277
- }
1278
-
1279
- const parts = url.pathname.split("/").filter(Boolean);
1280
- if (parts.length !== 4 || parts[2] !== "pull") {
1281
- return {
1282
- kind: "invalid",
1283
- detail:
1284
- "unparseable PR URL: expected https://github.com/{owner}/{repo}/pull/{number}",
1285
- };
1286
- }
1287
-
1288
- const prNumber = Number(parts[3]);
1289
- if (!Number.isInteger(prNumber) || prNumber <= 0) {
1290
- return {
1291
- kind: "invalid",
1292
- detail:
1293
- "unparseable PR URL: pull request number must be a positive integer",
1294
- };
1295
- }
1296
-
1297
- return {
1298
- kind: "valid",
1299
- value: {
1300
- repo: `${parts[0]}/${parts[1]}`,
1301
- prNumber,
1302
- },
1303
- };
1304
- }
1305
-
1306
- async function ghApiPostJson(
1307
- path: string,
1308
- payload: unknown,
1309
- signal?: AbortSignal
1310
- ): Promise<Record<string, unknown>> {
1311
- return new Promise((resolvePromise, rejectPromise) => {
1312
- const child = spawn(
1313
- "gh",
1314
- ["api", path, "--method", "POST", "--input", "-"],
1315
- {
1316
- env: { ...process.env, GH_PROMPT_DISABLED: "1" },
1317
- stdio: ["pipe", "pipe", "pipe"],
1318
- }
1319
- );
1320
- let stdout = "";
1321
- let stderr = "";
1322
- const onAbort = () => {
1323
- child.kill("SIGTERM");
1324
- rejectPromise(signal?.reason ?? new Error("aborted"));
1325
- };
1326
- signal?.addEventListener("abort", onAbort, { once: true });
1327
- child.stdout.on("data", (chunk) => {
1328
- stdout += String(chunk);
1329
- });
1330
- child.stderr.on("data", (chunk) => {
1331
- stderr += String(chunk);
1332
- });
1333
- child.on("error", (error) => {
1334
- signal?.removeEventListener("abort", onAbort);
1335
- rejectPromise(error);
1336
- });
1337
- child.on("close", (code) => {
1338
- signal?.removeEventListener("abort", onAbort);
1339
- if (code !== 0) {
1340
- rejectPromise(
1341
- new Error(
1342
- `gh api ${path} exited with ${code}: ${stderr.trim().slice(0, 2000)}`
1343
- )
1344
- );
1345
- return;
1346
- }
1347
- if (!stdout.trim()) {
1348
- resolvePromise({});
1349
- return;
1350
- }
1351
- try {
1352
- resolvePromise(JSON.parse(stdout) as Record<string, unknown>);
1353
- } catch (error) {
1354
- rejectPromise(
1355
- new Error(
1356
- `gh api ${path} returned invalid JSON: ${error instanceof Error ? error.message : String(error)}`
1357
- )
1358
- );
1359
- }
1360
- });
1361
- child.stdin.end(JSON.stringify(payload));
1362
- });
1363
- }