@cursor/july 0.1.91 → 0.1.93

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 (351) hide show
  1. package/AGENTS.md +4 -0
  2. package/README.md +117 -162
  3. package/dist/channels/deployments/deployments-channel.d.ts +7 -0
  4. package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
  5. package/dist/channels/deployments/deployments-channel.js +26 -2
  6. package/dist/channels/deployments/types.d.ts +8 -0
  7. package/dist/channels/deployments/types.d.ts.map +1 -1
  8. package/dist/channels/github/github-channel.d.ts +3 -0
  9. package/dist/channels/github/github-channel.d.ts.map +1 -1
  10. package/dist/channels/github/github-channel.js +28 -56
  11. package/dist/continuation.d.ts +1 -1
  12. package/dist/continuation.js +1 -1
  13. package/dist/docs/404.html +4 -2
  14. package/dist/docs/ab.html +10 -8
  15. package/dist/docs/ab.md +332 -0
  16. package/dist/docs/assets/{ab.md.CVzWxLoB.js → ab.md.DJo5r4R-.js} +4 -4
  17. package/dist/docs/assets/{ab.md.CVzWxLoB.lean.js → ab.md.DJo5r4R-.lean.js} +1 -1
  18. package/dist/docs/assets/{app.Bci6CM9E.js → app.CjWU-x0z.js} +1 -1
  19. package/dist/docs/assets/building-with-agents.md.DI4mEzlt.js +13 -0
  20. package/dist/docs/assets/{building-with-agents.md.DH8A_cHA.lean.js → building-with-agents.md.DI4mEzlt.lean.js} +1 -1
  21. package/dist/docs/assets/chunks/@localSearchIndexroot.ChpIC3Zy.js +1 -0
  22. package/dist/docs/assets/chunks/{VPLocalSearchBox.BCPT6xA-.js → VPLocalSearchBox.Cxy8ySFQ.js} +1 -1
  23. package/dist/docs/assets/chunks/{theme.BEA8BF3c.js → theme.Dvq1Bktu.js} +2 -2
  24. package/dist/docs/assets/concepts.md.F6AiPorA.js +1 -0
  25. package/dist/docs/assets/{concepts.md.CRfU3bVg.lean.js → concepts.md.F6AiPorA.lean.js} +1 -1
  26. package/dist/docs/assets/{deployment.md.DX_hc3ze.js → deployment.md.DoLFAzfm.js} +6 -6
  27. package/dist/docs/assets/{evals.md.a0SMN6r9.js → evals.md.lfJoEVc8.js} +6 -6
  28. package/dist/docs/assets/{evals.md.a0SMN6r9.lean.js → evals.md.lfJoEVc8.lean.js} +1 -1
  29. package/dist/docs/assets/{example-agents_approval-buddy.md.DNL83puR.js → example-agents_approval-buddy.md.DmezILPg.js} +1 -1
  30. package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.js → example-agents_benny.md.B0kwY7D_.js} +2 -4
  31. package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.lean.js → example-agents_benny.md.B0kwY7D_.lean.js} +1 -1
  32. package/dist/docs/assets/{example-agents_codebase-wiki.md.Dftj_tPp.js → example-agents_codebase-wiki.md.BBNw9Ekr.js} +3 -3
  33. package/dist/docs/assets/{example-agents_codebase-wiki.md.Dftj_tPp.lean.js → example-agents_codebase-wiki.md.BBNw9Ekr.lean.js} +1 -1
  34. package/dist/docs/assets/{example-agents_concierge.md.MrKpQndp.js → example-agents_concierge.md.BzB2b20R.js} +2 -3
  35. package/dist/docs/assets/example-agents_index.md.ChBp0AX6.js +2 -0
  36. package/dist/docs/assets/example-agents_index.md.ChBp0AX6.lean.js +1 -0
  37. package/dist/docs/assets/{example-agents_knowledge-base.md.DqKqHQ9u.js → example-agents_knowledge-base.md.CrA85ig-.js} +1 -1
  38. package/dist/docs/assets/{example-agents_security-reviewer.md.Bai6D0Ee.js → example-agents_security-reviewer.md.74pPpWYj.js} +1 -1
  39. package/dist/docs/assets/{example-agents_weather-agent.md.lVEAbWFf.js → example-agents_weather-agent.md.CaGpmw3Y.js} +2 -2
  40. package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.js → guides_agent-to-agent.md.B3JIaAqz.js} +1 -1
  41. package/dist/docs/assets/{guides_cloud-runtime.md.BSMLIBHr.js → guides_cloud-runtime.md.BnvjPiia.js} +2 -2
  42. package/dist/docs/assets/{guides_cloud-runtime.md.BSMLIBHr.lean.js → guides_cloud-runtime.md.BnvjPiia.lean.js} +1 -1
  43. package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.js → guides_convert-automation.md.Bboisykk.js} +1 -1
  44. package/dist/docs/assets/{guides_github.md.Cdt1s2QC.js → guides_github.md.DqJhuaN1.js} +5 -5
  45. package/dist/docs/assets/{guides_github.md.Cdt1s2QC.lean.js → guides_github.md.DqJhuaN1.lean.js} +1 -1
  46. package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.js → guides_mcp-oauth.md.CJvrXtkN.js} +2 -2
  47. package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.js → guides_slack.md.mqeNKs84.js} +2 -2
  48. package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.js → guides_webhooks.md.DKdA43Qm.js} +2 -2
  49. package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.js → hillclimbing.md.DhESf3OO.js} +1 -1
  50. package/dist/docs/assets/{index.md.BAaMXLFd.js → index.md.B-lVR4wT.js} +3 -3
  51. package/dist/docs/assets/{index.md.BAaMXLFd.lean.js → index.md.B-lVR4wT.lean.js} +1 -1
  52. package/dist/docs/assets/{quickstart.md.DsrarzEg.js → quickstart.md.BrmfrrIr.js} +1 -1
  53. package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.js → reference_agent-config.md.Cp_x38Nl.js} +3 -3
  54. package/dist/docs/assets/{reference_channels.md.DQZjCnyh.js → reference_channels.md.Cd2f2iyV.js} +2 -2
  55. package/dist/docs/assets/{reference_channels.md.DQZjCnyh.lean.js → reference_channels.md.Cd2f2iyV.lean.js} +1 -1
  56. package/dist/docs/assets/{reference_cli.md.B7GkAJRC.js → reference_cli.md.D9KESDsD.js} +10 -11
  57. package/dist/docs/assets/{reference_cli.md.B7GkAJRC.lean.js → reference_cli.md.D9KESDsD.lean.js} +1 -1
  58. package/dist/docs/assets/{reference_connections.md.DYidrb-j.js → reference_connections.md.DB6SsN6U.js} +3 -3
  59. package/dist/docs/assets/reference_hooks.md.BxN87gCw.js +14 -0
  60. package/dist/docs/assets/{reference_hooks.md.B9FSgdDe.lean.js → reference_hooks.md.BxN87gCw.lean.js} +1 -1
  61. package/dist/docs/assets/reference_http-api.md.C68BERYr.js +11 -0
  62. package/dist/docs/assets/reference_http-api.md.C68BERYr.lean.js +1 -0
  63. package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.js → reference_instructions.md.CR7XSsGk.js} +3 -3
  64. package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.lean.js → reference_instructions.md.CR7XSsGk.lean.js} +1 -1
  65. package/dist/docs/assets/reference_playground.md.DnX5nL-B.js +1 -0
  66. package/dist/docs/assets/reference_playground.md.DnX5nL-B.lean.js +1 -0
  67. package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.js → reference_project-layout.md.WN9nwJht.js} +2 -2
  68. package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.js → reference_prompt.md.DnaD5dNK.js} +1 -1
  69. package/dist/docs/assets/{reference_schedules.md.DNipebiG.js → reference_schedules.md.DI_JrHgq.js} +1 -1
  70. package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +1 -0
  71. package/dist/docs/assets/{reference_sessions.md.tUFzz98S.lean.js → reference_sessions.md.D0mIh4KK.lean.js} +1 -1
  72. package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.js → reference_skills.md.BFW9retM.js} +1 -1
  73. package/dist/docs/assets/{reference_tools.md.wpaJtHn6.js → reference_tools.md.DuKvkYWG.js} +4 -4
  74. package/dist/docs/assets/{reference_tools.md.wpaJtHn6.lean.js → reference_tools.md.DuKvkYWG.lean.js} +1 -1
  75. package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +1 -0
  76. package/dist/docs/assets/{scaffolding-agents.md.CRDDUtYJ.lean.js → scaffolding-agents.md.D7UUkWw0.lean.js} +1 -1
  77. package/dist/docs/assets/{storage.md.JbjlHWZ6.js → storage.md.BOHeqk2M.js} +5 -5
  78. package/dist/docs/assets/{storage.md.JbjlHWZ6.lean.js → storage.md.BOHeqk2M.lean.js} +1 -1
  79. package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.js → templates_agentic-owners.md.DqtPdm6f.js} +2 -2
  80. package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.js → templates_pr-autofixer.md.R4K_qytS.js} +2 -2
  81. package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.lean.js → templates_pr-autofixer.md.R4K_qytS.lean.js} +1 -1
  82. package/dist/docs/assets/troubleshooting.md.vCWwvqcJ.js +1 -0
  83. package/dist/docs/assets/{troubleshooting.md.DYECCZiJ.lean.js → troubleshooting.md.vCWwvqcJ.lean.js} +1 -1
  84. package/dist/docs/building-with-agents.html +9 -7
  85. package/dist/docs/building-with-agents.md +118 -0
  86. package/dist/docs/concepts.html +7 -8
  87. package/dist/docs/concepts.md +169 -0
  88. package/dist/docs/deployment.html +13 -11
  89. package/dist/docs/deployment.md +462 -0
  90. package/dist/docs/evals.html +12 -10
  91. package/dist/docs/evals.md +460 -0
  92. package/dist/docs/example-agents/approval-buddy.html +7 -5
  93. package/dist/docs/example-agents/approval-buddy.md +266 -0
  94. package/dist/docs/example-agents/benny.html +7 -7
  95. package/dist/docs/example-agents/benny.md +173 -0
  96. package/dist/docs/example-agents/bugbot.html +6 -4
  97. package/dist/docs/example-agents/bugbot.md +229 -0
  98. package/dist/docs/example-agents/codebase-wiki.html +8 -6
  99. package/dist/docs/example-agents/codebase-wiki.md +167 -0
  100. package/dist/docs/example-agents/codeowners-review.html +6 -4
  101. package/dist/docs/example-agents/codeowners-review.md +192 -0
  102. package/dist/docs/example-agents/concierge.html +9 -8
  103. package/dist/docs/example-agents/concierge.md +200 -0
  104. package/dist/docs/example-agents/index.html +8 -6
  105. package/dist/docs/example-agents/index.md +99 -0
  106. package/dist/docs/example-agents/knowledge-base.html +8 -6
  107. package/dist/docs/example-agents/knowledge-base.md +168 -0
  108. package/dist/docs/example-agents/oncall.html +6 -4
  109. package/dist/docs/example-agents/oncall.md +212 -0
  110. package/dist/docs/example-agents/security-reviewer.html +9 -7
  111. package/dist/docs/example-agents/security-reviewer.md +265 -0
  112. package/dist/docs/example-agents/slack-agent.html +6 -4
  113. package/dist/docs/example-agents/slack-agent.md +142 -0
  114. package/dist/docs/example-agents/weather-agent.html +9 -7
  115. package/dist/docs/example-agents/weather-agent.md +297 -0
  116. package/dist/docs/guides/agent-to-agent.html +7 -5
  117. package/dist/docs/guides/agent-to-agent.md +113 -0
  118. package/dist/docs/guides/cloud-runtime.html +8 -6
  119. package/dist/docs/guides/cloud-runtime.md +114 -0
  120. package/dist/docs/guides/convert-automation.html +8 -6
  121. package/dist/docs/guides/convert-automation.md +171 -0
  122. package/dist/docs/guides/github.html +11 -9
  123. package/dist/docs/guides/github.md +275 -0
  124. package/dist/docs/guides/human-in-the-loop.html +6 -4
  125. package/dist/docs/guides/human-in-the-loop.md +126 -0
  126. package/dist/docs/guides/mcp-oauth.html +8 -6
  127. package/dist/docs/guides/mcp-oauth.md +159 -0
  128. package/dist/docs/guides/opentelemetry.html +6 -4
  129. package/dist/docs/guides/opentelemetry.md +209 -0
  130. package/dist/docs/guides/slack.html +9 -7
  131. package/dist/docs/guides/slack.md +337 -0
  132. package/dist/docs/guides/webhooks.html +8 -6
  133. package/dist/docs/guides/webhooks.md +463 -0
  134. package/dist/docs/hashmap.json +1 -1
  135. package/dist/docs/hillclimbing.html +8 -6
  136. package/dist/docs/hillclimbing.md +88 -0
  137. package/dist/docs/index.html +8 -6
  138. package/dist/docs/index.md +171 -0
  139. package/dist/docs/llms-full.txt +10968 -0
  140. package/dist/docs/llms.txt +74 -0
  141. package/dist/docs/quickstart.html +7 -5
  142. package/dist/docs/quickstart.md +364 -0
  143. package/dist/docs/reference/agent-config.html +10 -8
  144. package/dist/docs/reference/agent-config.md +251 -0
  145. package/dist/docs/reference/artifacts.html +6 -4
  146. package/dist/docs/reference/artifacts.md +112 -0
  147. package/dist/docs/reference/channels.html +8 -6
  148. package/dist/docs/reference/channels.md +244 -0
  149. package/dist/docs/reference/cli.html +16 -15
  150. package/dist/docs/reference/cli.md +947 -0
  151. package/dist/docs/reference/connections.html +10 -8
  152. package/dist/docs/reference/connections.md +263 -0
  153. package/dist/docs/reference/hooks.html +8 -6
  154. package/dist/docs/reference/hooks.md +98 -0
  155. package/dist/docs/reference/http-api.html +9 -7
  156. package/dist/docs/reference/http-api.md +247 -0
  157. package/dist/docs/reference/instructions.html +8 -6
  158. package/dist/docs/reference/instructions.md +74 -0
  159. package/dist/docs/reference/playground.html +7 -5
  160. package/dist/docs/reference/playground.md +57 -0
  161. package/dist/docs/reference/project-layout.html +9 -7
  162. package/dist/docs/reference/project-layout.md +107 -0
  163. package/dist/docs/reference/prompt.html +8 -6
  164. package/dist/docs/reference/prompt.md +42 -0
  165. package/dist/docs/reference/schedules.html +8 -6
  166. package/dist/docs/reference/schedules.md +214 -0
  167. package/dist/docs/reference/sessions.html +7 -12
  168. package/dist/docs/reference/sessions.md +159 -0
  169. package/dist/docs/reference/skills.html +8 -6
  170. package/dist/docs/reference/skills.md +83 -0
  171. package/dist/docs/reference/subagents.html +6 -4
  172. package/dist/docs/reference/subagents.md +71 -0
  173. package/dist/docs/reference/tools.html +10 -8
  174. package/dist/docs/reference/tools.md +293 -0
  175. package/dist/docs/scaffolding-agents.html +7 -5
  176. package/dist/docs/scaffolding-agents.md +129 -0
  177. package/dist/docs/storage.html +11 -9
  178. package/dist/docs/storage.md +176 -0
  179. package/dist/docs/templates/agentic-owners.html +9 -7
  180. package/dist/docs/templates/agentic-owners.md +92 -0
  181. package/dist/docs/templates/demo.html +6 -4
  182. package/dist/docs/templates/demo.md +79 -0
  183. package/dist/docs/templates/pr-autofixer.html +8 -6
  184. package/dist/docs/templates/pr-autofixer.md +128 -0
  185. package/dist/docs/templates/security-reviewer.html +6 -4
  186. package/dist/docs/templates/security-reviewer.md +84 -0
  187. package/dist/docs/templates/triage.html +6 -4
  188. package/dist/docs/templates/triage.md +98 -0
  189. package/dist/docs/troubleshooting.html +7 -5
  190. package/dist/docs/troubleshooting.md +111 -0
  191. package/dist/internal/authored-alias-hooks.d.ts +14 -11
  192. package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
  193. package/dist/internal/authored-alias-hooks.js +14 -11
  194. package/dist/internal/authored-loaders.d.ts +7 -6
  195. package/dist/internal/authored-loaders.d.ts.map +1 -1
  196. package/dist/internal/authored-loaders.js +14 -10
  197. package/dist/internal/cli-deploy.d.ts +1 -1
  198. package/dist/internal/cli-deploy.js +5 -5
  199. package/dist/internal/continuation-channel.d.ts +6 -3
  200. package/dist/internal/continuation-channel.d.ts.map +1 -1
  201. package/dist/internal/continuation-channel.js +44 -40
  202. package/dist/internal/continuation-identity.d.ts +17 -16
  203. package/dist/internal/continuation-identity.d.ts.map +1 -1
  204. package/dist/internal/continuation-identity.js +109 -36
  205. package/dist/internal/deploy-manifest.d.ts +2 -2
  206. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  207. package/dist/internal/deploy-manifest.js +4 -9
  208. package/dist/internal/discovery.d.ts.map +1 -1
  209. package/dist/internal/discovery.js +3 -0
  210. package/dist/internal/distribution.d.ts +4 -3
  211. package/dist/internal/distribution.d.ts.map +1 -1
  212. package/dist/internal/distribution.js +4 -3
  213. package/dist/internal/hosted-delivery-protocol.d.ts +38 -0
  214. package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -0
  215. package/dist/internal/hosted-delivery-protocol.js +70 -0
  216. package/dist/internal/hosted-delivery.d.ts +35 -0
  217. package/dist/internal/hosted-delivery.d.ts.map +1 -0
  218. package/dist/internal/hosted-delivery.js +226 -0
  219. package/dist/internal/http-channel.d.ts.map +1 -1
  220. package/dist/internal/http-channel.js +1 -1
  221. package/dist/internal/init-scaffold.d.ts.map +1 -1
  222. package/dist/internal/init-scaffold.js +1 -0
  223. package/dist/internal/playground/static.d.ts.map +1 -1
  224. package/dist/internal/playground/static.js +2 -0
  225. package/dist/internal/review-comments.d.ts +186 -63
  226. package/dist/internal/review-comments.d.ts.map +1 -1
  227. package/dist/internal/review-comments.js +350 -168
  228. package/dist/internal/server.d.ts.map +1 -1
  229. package/dist/internal/server.js +21 -3
  230. package/dist/internal/session-engine.d.ts +5 -0
  231. package/dist/internal/session-engine.d.ts.map +1 -1
  232. package/dist/internal/session-engine.js +16 -4
  233. package/dist/internal/shallow-clone.d.ts +8 -2
  234. package/dist/internal/shallow-clone.d.ts.map +1 -1
  235. package/dist/internal/shallow-clone.js +17 -10
  236. package/dist/playground/assets/{index-DDvyC2z6.js → index-D9MFzhNE.js} +1 -1
  237. package/dist/playground/index.html +1 -1
  238. package/dist/types.d.ts +9 -17
  239. package/dist/types.d.ts.map +1 -1
  240. package/docs/README.md +2 -10
  241. package/docs/ab.md +7 -13
  242. package/docs/building-with-agents.md +5 -11
  243. package/docs/concepts.md +12 -17
  244. package/docs/deployment.md +8 -10
  245. package/docs/evals.md +16 -37
  246. package/docs/example-agents/approval-buddy.md +1 -1
  247. package/docs/example-agents/benny.md +4 -13
  248. package/docs/example-agents/codebase-wiki.md +5 -8
  249. package/docs/example-agents/concierge.md +2 -3
  250. package/docs/example-agents/index.md +6 -9
  251. package/docs/example-agents/knowledge-base.md +2 -2
  252. package/docs/example-agents/security-reviewer.md +5 -5
  253. package/docs/example-agents/weather-agent.md +4 -3
  254. package/docs/guides/agent-to-agent.md +1 -1
  255. package/docs/guides/cloud-runtime.md +8 -25
  256. package/docs/guides/convert-automation.md +3 -3
  257. package/docs/guides/github.md +11 -23
  258. package/docs/guides/mcp-oauth.md +4 -4
  259. package/docs/guides/slack.md +4 -4
  260. package/docs/guides/webhooks.md +3 -3
  261. package/docs/hillclimbing.md +1 -1
  262. package/docs/quickstart.md +1 -1
  263. package/docs/reference/agent-config.md +10 -15
  264. package/docs/reference/channels.md +20 -31
  265. package/docs/reference/cli.md +27 -37
  266. package/docs/reference/connections.md +9 -14
  267. package/docs/reference/hooks.md +10 -14
  268. package/docs/reference/http-api.md +18 -38
  269. package/docs/reference/instructions.md +1 -1
  270. package/docs/reference/playground.md +14 -19
  271. package/docs/reference/project-layout.md +2 -2
  272. package/docs/reference/prompt.md +1 -1
  273. package/docs/reference/schedules.md +1 -2
  274. package/docs/reference/sessions.md +8 -19
  275. package/docs/reference/skills.md +3 -3
  276. package/docs/reference/tools.md +12 -17
  277. package/docs/scaffolding-agents.md +4 -5
  278. package/docs/storage.md +37 -80
  279. package/docs/templates/agentic-owners.md +2 -2
  280. package/docs/templates/pr-autofixer.md +3 -6
  281. package/docs/troubleshooting.md +6 -6
  282. package/package.json +9 -2
  283. package/skills/ab/SKILL.md +3 -0
  284. package/skills/create-agent/SKILL.md +3 -0
  285. package/skills/debug/SKILL.md +3 -0
  286. package/skills/evals/SKILL.md +3 -0
  287. package/skills/framework-map/SKILL.md +3 -0
  288. package/skills/github/SKILL.md +3 -0
  289. package/skills/hillclimb/SKILL.md +3 -0
  290. package/skills/mcp-auth/SKILL.md +3 -0
  291. package/skills/otel/SKILL.md +3 -0
  292. package/skills/setup-slack/SKILL.md +3 -0
  293. package/src/channels/deployments/deployments-channel.ts +32 -2
  294. package/src/channels/deployments/types.ts +8 -0
  295. package/src/channels/github/github-channel.ts +71 -21
  296. package/src/continuation.ts +1 -1
  297. package/src/internal/authored-alias-hooks.ts +14 -11
  298. package/src/internal/authored-loaders.ts +14 -10
  299. package/src/internal/cli-deploy.ts +5 -5
  300. package/src/internal/continuation-channel.ts +62 -45
  301. package/src/internal/continuation-identity.ts +123 -38
  302. package/src/internal/deploy-manifest.ts +5 -9
  303. package/src/internal/discovery.ts +3 -0
  304. package/src/internal/distribution.ts +4 -3
  305. package/src/internal/hosted-delivery-protocol.ts +114 -0
  306. package/src/internal/hosted-delivery.ts +327 -0
  307. package/src/internal/http-channel.ts +0 -2
  308. package/src/internal/init-scaffold.ts +1 -0
  309. package/src/internal/playground/static.ts +2 -0
  310. package/src/internal/review-comments.ts +542 -229
  311. package/src/internal/server.ts +29 -2
  312. package/src/internal/session-engine.ts +29 -7
  313. package/src/internal/shallow-clone.ts +30 -16
  314. package/src/types.ts +9 -17
  315. package/dist/docs/assets/building-with-agents.md.DH8A_cHA.js +0 -13
  316. package/dist/docs/assets/chunks/@localSearchIndexroot.Dv-Q0XtU.js +0 -1
  317. package/dist/docs/assets/concepts.md.CRfU3bVg.js +0 -4
  318. package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.js +0 -15
  319. package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.lean.js +0 -1
  320. package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.js +0 -2
  321. package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.lean.js +0 -1
  322. package/dist/docs/assets/reference_hooks.md.B9FSgdDe.js +0 -14
  323. package/dist/docs/assets/reference_http-api.md.CSHVobzG.js +0 -11
  324. package/dist/docs/assets/reference_http-api.md.CSHVobzG.lean.js +0 -1
  325. package/dist/docs/assets/reference_playground.md.Dfb92yQf.js +0 -1
  326. package/dist/docs/assets/reference_playground.md.Dfb92yQf.lean.js +0 -1
  327. package/dist/docs/assets/reference_sessions.md.tUFzz98S.js +0 -8
  328. package/dist/docs/assets/scaffolding-agents.md.CRDDUtYJ.js +0 -1
  329. package/dist/docs/assets/troubleshooting.md.DYECCZiJ.js +0 -1
  330. package/dist/docs/example-agents/fsd.html +0 -39
  331. package/docs/example-agents/fsd.md +0 -334
  332. /package/dist/docs/assets/{deployment.md.DX_hc3ze.lean.js → deployment.md.DoLFAzfm.lean.js} +0 -0
  333. /package/dist/docs/assets/{example-agents_approval-buddy.md.DNL83puR.lean.js → example-agents_approval-buddy.md.DmezILPg.lean.js} +0 -0
  334. /package/dist/docs/assets/{example-agents_concierge.md.MrKpQndp.lean.js → example-agents_concierge.md.BzB2b20R.lean.js} +0 -0
  335. /package/dist/docs/assets/{example-agents_knowledge-base.md.DqKqHQ9u.lean.js → example-agents_knowledge-base.md.CrA85ig-.lean.js} +0 -0
  336. /package/dist/docs/assets/{example-agents_security-reviewer.md.Bai6D0Ee.lean.js → example-agents_security-reviewer.md.74pPpWYj.lean.js} +0 -0
  337. /package/dist/docs/assets/{example-agents_weather-agent.md.lVEAbWFf.lean.js → example-agents_weather-agent.md.CaGpmw3Y.lean.js} +0 -0
  338. /package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.lean.js → guides_agent-to-agent.md.B3JIaAqz.lean.js} +0 -0
  339. /package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.lean.js → guides_convert-automation.md.Bboisykk.lean.js} +0 -0
  340. /package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.lean.js → guides_mcp-oauth.md.CJvrXtkN.lean.js} +0 -0
  341. /package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.lean.js → guides_slack.md.mqeNKs84.lean.js} +0 -0
  342. /package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.lean.js → guides_webhooks.md.DKdA43Qm.lean.js} +0 -0
  343. /package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.lean.js → hillclimbing.md.DhESf3OO.lean.js} +0 -0
  344. /package/dist/docs/assets/{quickstart.md.DsrarzEg.lean.js → quickstart.md.BrmfrrIr.lean.js} +0 -0
  345. /package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.lean.js → reference_agent-config.md.Cp_x38Nl.lean.js} +0 -0
  346. /package/dist/docs/assets/{reference_connections.md.DYidrb-j.lean.js → reference_connections.md.DB6SsN6U.lean.js} +0 -0
  347. /package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.lean.js → reference_project-layout.md.WN9nwJht.lean.js} +0 -0
  348. /package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.lean.js → reference_prompt.md.DnaD5dNK.lean.js} +0 -0
  349. /package/dist/docs/assets/{reference_schedules.md.DNipebiG.lean.js → reference_schedules.md.DI_JrHgq.lean.js} +0 -0
  350. /package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
  351. /package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.lean.js → templates_agentic-owners.md.DqtPdm6f.lean.js} +0 -0
@@ -14,20 +14,20 @@ export function resolveScmReviewTarget(prUrl) {
14
14
  return parsed.kind === "valid" ? parsed.value : undefined;
15
15
  }
16
16
  /**
17
- * Reader for a resolved target, mirroring Bugbot's `createPrGitProvider`
17
+ * Lister for a resolved target, mirroring Bugbot's `createPrGitProvider`
18
18
  * dispatch. Returns undefined when the host cannot serve that provider (no
19
- * GitHub client bound), so callers degrade instead of throwing.
19
+ * GitHub/Origin client bound), so callers degrade instead of throwing.
20
20
  */
21
- export function createReviewCommentReader(args) {
21
+ export function createReviewCommentLister(args) {
22
22
  switch (args.target.provider) {
23
23
  case "github":
24
24
  return args.github === undefined
25
25
  ? undefined
26
- : createHostGithubReviewCommentReader(args.github);
26
+ : createHostGithubReviewCommentLister(args.github, args.log);
27
27
  case "origin":
28
- // Public Origin REST lists discussion comments, not diff-anchored
29
- // review threads. Stay undefined until a reader can fetch by id.
30
- return undefined;
28
+ return args.origin === undefined
29
+ ? undefined
30
+ : createHostOriginReviewCommentLister(args.origin, args.log);
31
31
  }
32
32
  }
33
33
  /**
@@ -39,23 +39,25 @@ export function createReviewThreadResolver(args) {
39
39
  case "github":
40
40
  return args.github === undefined
41
41
  ? undefined
42
- : createHostGithubReviewThreadResolver(args.github);
42
+ : createHostGithubReviewThreadResolver(args.github, args.log);
43
43
  case "origin":
44
- return undefined;
44
+ return args.origin === undefined
45
+ ? undefined
46
+ : createHostOriginReviewThreadResolver(args.origin, args.log);
45
47
  }
46
48
  }
47
49
  /**
48
- * Resolve the review threads that own `commentIds` on `prUrl`.
50
+ * Resolve `threadIds` on `prUrl`'s PR.
49
51
  *
50
52
  * No-ops (never throws) when the PR is on an SCM this host cannot write,
51
- * no client is bound, or `commentIds` is empty. Same degrade-don't-fail
52
- * posture as {@link createReviewCommentReader}.
53
+ * no client is bound, or `threadIds` is empty. Same degrade-don't-fail
54
+ * posture as {@link createReviewCommentLister}.
53
55
  */
54
- export function resolveReviewThreadsForComments(args) {
56
+ export function resolveReviewThreads(args) {
55
57
  return __awaiter(this, void 0, void 0, function* () {
56
58
  var _a;
57
- if (args.commentIds.length === 0) {
58
- return skippedResolve("no comments to resolve");
59
+ if (args.threadIds.length === 0) {
60
+ return skippedResolve("no threads to resolve");
59
61
  }
60
62
  const target = resolveScmReviewTarget(args.prUrl);
61
63
  if (target === undefined) {
@@ -64,15 +66,15 @@ export function resolveReviewThreadsForComments(args) {
64
66
  const resolver = (_a = args.resolver) !== null && _a !== void 0 ? _a : createReviewThreadResolver({
65
67
  target,
66
68
  github: args.github,
69
+ origin: args.origin,
70
+ log: args.log,
67
71
  });
68
72
  if (resolver === undefined) {
69
- return skippedResolve(target.provider === "github"
70
- ? "no GitHub client bound to resolve threads"
71
- : `no thread resolver for ${target.provider}`);
73
+ return skippedResolve(`no ${target.provider} client bound to resolve threads`);
72
74
  }
73
- return resolver.resolveReviewThreadsForComments({
75
+ return resolver.resolveReviewThreads({
74
76
  target,
75
- commentIds: args.commentIds,
77
+ threadIds: args.threadIds,
76
78
  signal: args.signal,
77
79
  });
78
80
  });
@@ -80,140 +82,164 @@ export function resolveReviewThreadsForComments(args) {
80
82
  /** Cap on pages pulled per PR; GitHub serves 100 comments per page. */
81
83
  const REVIEW_COMMENTS_MAX_PAGES = 5;
82
84
  const REVIEW_COMMENTS_PAGE_SIZE = 100;
83
- /** Cap on review-thread pages when mapping comment ids to GraphQL thread ids. */
85
+ /** Cap on review-thread pages when listing a PR's inline threads. */
84
86
  const REVIEW_THREADS_MAX_PAGES = 20;
85
87
  const REVIEW_THREADS_PAGE_SIZE = 100;
88
+ /** Cap on Origin comment pages pulled per PR (100 comments per page). */
89
+ const ORIGIN_COMMENTS_MAX_PAGES = 20;
90
+ const ORIGIN_COMMENTS_PAGE_SIZE = 100;
86
91
  /**
87
- * Reads inline review comments through the host GitHub client (Cursor
88
- * account lease, App installation token, or PAT).
92
+ * Repo-scope header for GraphQL calls through the Cursor github-proxy.
93
+ *
94
+ * The proxy authorizes each call from `x-cursor-github-repos`, which the
95
+ * channel Octokit derives from REST URLs (`/repos/{owner}/{repo}/…`).
96
+ * GraphQL posts to `/graphql` — no repo in the URL — so without this
97
+ * explicit header every GraphQL call is rejected in proxy mode. Harmless
98
+ * against api.github.com, which ignores unknown headers.
89
99
  */
90
- export function createHostGithubReviewCommentReader(github) {
100
+ function githubGraphqlScopeHeaders(repo) {
101
+ return { "x-cursor-github-repos": repo.toLowerCase() };
102
+ }
103
+ /**
104
+ * GitHub review thread → {@link ListedReviewComment} (its opening comment).
105
+ *
106
+ * Prefers the `original*` line fields — the position as of the review the
107
+ * thread belongs to. `line` drifts as the PR gains commits, so a caller
108
+ * correlating a comment with the review that produced it needs the original
109
+ * position, the same fields Bugbot carries on `PullRequestCommentOutput`.
110
+ */
111
+ export function listedCommentFromGithubThread(thread) {
112
+ var _a, _b, _c, _d, _e;
113
+ var _f, _g, _h, _j, _k, _l;
114
+ const opener = (_b = (_a = thread.comments) === null || _a === void 0 ? void 0 : _a.nodes) === null || _b === void 0 ? void 0 : _b[0];
115
+ if (thread.id === undefined ||
116
+ thread.id === "" ||
117
+ opener === null ||
118
+ opener === undefined ||
119
+ opener.databaseId === undefined ||
120
+ opener.databaseId === null ||
121
+ typeof opener.body !== "string" ||
122
+ typeof thread.path !== "string" ||
123
+ thread.path === "") {
124
+ return undefined;
125
+ }
126
+ // Take both lines from the same position set. Mixing them (original end
127
+ // line with the drifted current start line) would describe a range that
128
+ // never existed in either revision.
129
+ const original = (_f = thread.originalLine) !== null && _f !== void 0 ? _f : undefined;
130
+ const endLine = (_g = original !== null && original !== void 0 ? original : thread.line) !== null && _g !== void 0 ? _g : undefined;
131
+ if (endLine === undefined) {
132
+ return undefined;
133
+ }
134
+ const startLine = (_h = (original === undefined ? thread.startLine : thread.originalStartLine)) !== null && _h !== void 0 ? _h : endLine;
135
+ const commitSha = (_j = (_c = opener.originalCommit) === null || _c === void 0 ? void 0 : _c.oid) !== null && _j !== void 0 ? _j : undefined;
136
+ const authorLogin = (_k = (_d = opener.author) === null || _d === void 0 ? void 0 : _d.login) !== null && _k !== void 0 ? _k : undefined;
137
+ const authorType = (_l = (_e = opener.author) === null || _e === void 0 ? void 0 : _e.__typename) !== null && _l !== void 0 ? _l : undefined;
138
+ return Object.assign(Object.assign(Object.assign({ commentId: String(opener.databaseId), numericCommentId: opener.databaseId, threadId: thread.id, resolved: thread.isResolved === true, file: thread.path, startLine,
139
+ endLine, body: opener.body }, (commitSha === undefined ? {} : { commitSha })), (authorLogin === undefined ? {} : { authorLogin })), (authorType === undefined ? {} : { authorIsBot: authorType === "Bot" }));
140
+ }
141
+ /**
142
+ * Lists the PR's inline review threads (their opening comments) through the
143
+ * host GitHub client (Cursor account lease, App installation token, or
144
+ * PAT). One paged GraphQL query yields, per thread: the resolvable thread
145
+ * node id, its resolution state, the opener's body/position, and the commit
146
+ * it was filed against — everything a Bugbot-style re-review needs.
147
+ */
148
+ export function createHostGithubReviewCommentLister(github, log) {
91
149
  return {
92
- getReviewComments(_a) {
93
- return __awaiter(this, arguments, void 0, function* ({ target, commentIds, signal }) {
150
+ listReviewComments(_a) {
151
+ return __awaiter(this, arguments, void 0, function* ({ target, signal }) {
152
+ var _b, _c;
153
+ var _d;
94
154
  const [owner, repo] = target.repo.split("/", 2);
95
155
  if (owner === undefined || repo === undefined || repo === "") {
156
+ log === null || log === void 0 ? void 0 : log(`github list: unparseable owner/repo "${target.repo}"`);
96
157
  return [];
97
158
  }
98
159
  const octokit = yield github.getOctokit();
99
160
  const comments = [];
100
- for (const commentId of commentIds) {
161
+ let threadCount = 0;
162
+ let cursor = null;
163
+ for (let page = 0; page < REVIEW_THREADS_MAX_PAGES; page++) {
101
164
  signal === null || signal === void 0 ? void 0 : signal.throwIfAborted();
102
- try {
103
- const response = yield octokit.rest.pulls.getReviewComment({
104
- owner,
105
- repo,
106
- comment_id: commentId,
107
- });
108
- const normalized = normalizeGithubReviewComment(response.data);
109
- if (normalized !== undefined) {
110
- comments.push(normalized);
165
+ const response = (yield octokit.graphql(REVIEW_THREAD_COMMENTS_FOR_PR_QUERY, {
166
+ owner,
167
+ repo,
168
+ number: target.prNumber,
169
+ cursor,
170
+ headers: githubGraphqlScopeHeaders(target.repo),
171
+ }));
172
+ const reviewThreads = (_c = (_b = response.repository) === null || _b === void 0 ? void 0 : _b.pullRequest) === null || _c === void 0 ? void 0 : _c.reviewThreads;
173
+ for (const thread of (_d = reviewThreads === null || reviewThreads === void 0 ? void 0 : reviewThreads.nodes) !== null && _d !== void 0 ? _d : []) {
174
+ if (thread === null || thread === undefined) {
175
+ continue;
176
+ }
177
+ threadCount += 1;
178
+ const listed = listedCommentFromGithubThread(thread);
179
+ if (listed !== undefined) {
180
+ comments.push(listed);
111
181
  }
112
182
  }
113
- catch (_b) {
114
- // Deleted or otherwise unreadable: that finding simply has no
115
- // prior text to judge, which is the same as it not being there.
183
+ const pageInfo = reviewThreads === null || reviewThreads === void 0 ? void 0 : reviewThreads.pageInfo;
184
+ if ((pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.hasNextPage) !== true || !pageInfo.endCursor) {
185
+ break;
116
186
  }
187
+ cursor = pageInfo.endCursor;
117
188
  }
189
+ log === null || log === void 0 ? void 0 : log(`github list: ${target.repo}#${target.prNumber} has ${threadCount} review thread(s), ${comments.length} with a normalizable opening comment`);
118
190
  return comments;
119
191
  });
120
192
  },
121
193
  };
122
194
  }
123
195
  /**
124
- * Resolves inline review threads through the host GitHub client (Cursor
125
- * account lease, App installation token, or PAT). GitHub GraphQL has no
126
- * comment→thread field, so this pages the PR's review threads and matches
127
- * each REST comment id by `databaseId` — the same approach as Bugbot's
128
- * `resolveReviewThreadForComment`.
196
+ * Resolves inline review threads by GraphQL thread node id through the host
197
+ * GitHub client (Cursor account lease, App installation token, or PAT)
198
+ * the id the lister already returned, so no comment→thread mapping pass is
199
+ * needed. Same mutation as Bugbot's `resolveReviewThreadForComment`.
129
200
  */
130
- export function createHostGithubReviewThreadResolver(github) {
201
+ export function createHostGithubReviewThreadResolver(github, log) {
131
202
  return {
132
- resolveReviewThreadsForComments(_a) {
133
- return __awaiter(this, arguments, void 0, function* ({ target, commentIds, signal }) {
134
- var _b, _c, _d, _e, _f;
135
- var _g, _h;
136
- const uniqueIds = [...new Set(commentIds.filter((id) => id > 0))];
203
+ resolveReviewThreads(_a) {
204
+ return __awaiter(this, arguments, void 0, function* ({ target, threadIds, signal }) {
205
+ var _b, _c;
206
+ const uniqueIds = [...new Set(threadIds.filter((id) => id !== ""))];
137
207
  if (uniqueIds.length === 0) {
138
- return skippedResolve("no comments to resolve");
139
- }
140
- const [owner, repo] = target.repo.split("/", 2);
141
- if (owner === undefined || repo === undefined || repo === "") {
142
- return skippedResolve("unparseable owner/repo from PR URL");
208
+ return skippedResolve("no threads to resolve");
143
209
  }
210
+ let resolved = 0;
211
+ let failed = 0;
144
212
  try {
145
213
  const octokit = yield github.getOctokit();
146
- const wanted = new Set(uniqueIds);
147
- const matched = new Map();
148
- let cursor = null;
149
- for (let page = 0; page < REVIEW_THREADS_MAX_PAGES; page++) {
150
- signal === null || signal === void 0 ? void 0 : signal.throwIfAborted();
151
- const response = (yield octokit.graphql(REVIEW_THREADS_FOR_PR_QUERY, {
152
- owner,
153
- repo,
154
- number: target.prNumber,
155
- cursor,
156
- }));
157
- const reviewThreads = (_c = (_b = response.repository) === null || _b === void 0 ? void 0 : _b.pullRequest) === null || _c === void 0 ? void 0 : _c.reviewThreads;
158
- for (const thread of (_g = reviewThreads === null || reviewThreads === void 0 ? void 0 : reviewThreads.nodes) !== null && _g !== void 0 ? _g : []) {
159
- if ((thread === null || thread === void 0 ? void 0 : thread.id) === undefined || thread.id === "") {
160
- continue;
161
- }
162
- for (const comment of (_h = (_d = thread.comments) === null || _d === void 0 ? void 0 : _d.nodes) !== null && _h !== void 0 ? _h : []) {
163
- const databaseId = comment === null || comment === void 0 ? void 0 : comment.databaseId;
164
- if (databaseId !== undefined &&
165
- databaseId !== null &&
166
- wanted.has(databaseId) &&
167
- !matched.has(databaseId)) {
168
- matched.set(databaseId, {
169
- threadId: thread.id,
170
- isResolved: thread.isResolved === true,
171
- });
172
- }
173
- }
174
- }
175
- if (matched.size === wanted.size) {
176
- break;
177
- }
178
- const pageInfo = reviewThreads === null || reviewThreads === void 0 ? void 0 : reviewThreads.pageInfo;
179
- if ((pageInfo === null || pageInfo === void 0 ? void 0 : pageInfo.hasNextPage) !== true || !pageInfo.endCursor) {
180
- break;
181
- }
182
- cursor = pageInfo.endCursor;
183
- }
184
- const toResolve = [
185
- ...new Map([...matched.values()]
186
- .filter((thread) => !thread.isResolved)
187
- .map((thread) => [thread.threadId, thread.threadId])).values(),
188
- ];
189
- let resolved = 0;
190
- let failed = 0;
191
- for (const threadId of toResolve) {
214
+ for (const threadId of uniqueIds) {
192
215
  signal === null || signal === void 0 ? void 0 : signal.throwIfAborted();
193
216
  try {
194
- const mutation = (yield octokit.graphql(RESOLVE_REVIEW_THREAD_MUTATION, { threadId }));
195
- if (((_f = (_e = mutation.resolveReviewThread) === null || _e === void 0 ? void 0 : _e.thread) === null || _f === void 0 ? void 0 : _f.isResolved) === true) {
217
+ const mutation = (yield octokit.graphql(RESOLVE_REVIEW_THREAD_MUTATION, {
218
+ threadId,
219
+ headers: githubGraphqlScopeHeaders(target.repo),
220
+ }));
221
+ if (((_c = (_b = mutation.resolveReviewThread) === null || _b === void 0 ? void 0 : _b.thread) === null || _c === void 0 ? void 0 : _c.isResolved) === true) {
196
222
  resolved += 1;
223
+ log === null || log === void 0 ? void 0 : log(`github resolve: thread ${threadId} resolved`);
197
224
  }
198
225
  else {
199
226
  failed += 1;
227
+ log === null || log === void 0 ? void 0 : log(`github resolve: thread ${threadId} mutation did not mark the thread resolved`);
200
228
  }
201
229
  }
202
- catch (_j) {
230
+ catch (error) {
231
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
232
+ throw error;
233
+ }
203
234
  failed += 1;
235
+ log === null || log === void 0 ? void 0 : log(`github resolve: thread ${threadId} failed: ${error instanceof Error ? error.message : String(error)}`);
204
236
  }
205
237
  }
206
- const alreadyResolved = new Set([...matched.values()]
207
- .filter((thread) => thread.isResolved)
208
- .map((thread) => thread.threadId)).size;
209
- const notFound = wanted.size - matched.size;
210
238
  return {
211
239
  requested: uniqueIds.length,
212
240
  resolved,
213
- alreadyResolved,
214
- notFound,
215
241
  failed,
216
- detail: `resolved ${resolved} of ${toResolve.length} open thread(s) for ${uniqueIds.length} comment(s) via host GitHub (${alreadyResolved} already resolved, ${notFound} not found, ${failed} failed)`,
242
+ detail: `resolved ${resolved} of ${uniqueIds.length} thread(s) on ${target.repo}#${target.prNumber} via host GitHub (${failed} failed)`,
217
243
  };
218
244
  }
219
245
  catch (error) {
@@ -222,10 +248,8 @@ export function createHostGithubReviewThreadResolver(github) {
222
248
  }
223
249
  return {
224
250
  requested: uniqueIds.length,
225
- resolved: 0,
226
- alreadyResolved: 0,
227
- notFound: 0,
228
- failed: uniqueIds.length,
251
+ resolved,
252
+ failed: uniqueIds.length - resolved,
229
253
  detail: `host GitHub thread resolve failed: ${error instanceof Error ? error.message : String(error)}`,
230
254
  };
231
255
  }
@@ -233,8 +257,8 @@ export function createHostGithubReviewThreadResolver(github) {
233
257
  },
234
258
  };
235
259
  }
236
- const REVIEW_THREADS_FOR_PR_QUERY = `
237
- query ReviewThreadsForPr(
260
+ const REVIEW_THREAD_COMMENTS_FOR_PR_QUERY = `
261
+ query ReviewThreadCommentsForPr(
238
262
  $owner: String!
239
263
  $repo: String!
240
264
  $number: Int!
@@ -246,8 +270,18 @@ query ReviewThreadsForPr(
246
270
  nodes {
247
271
  id
248
272
  isResolved
249
- comments(first: ${REVIEW_THREADS_PAGE_SIZE}) {
250
- nodes { databaseId }
273
+ path
274
+ line
275
+ originalLine
276
+ startLine
277
+ originalStartLine
278
+ comments(first: 1) {
279
+ nodes {
280
+ databaseId
281
+ body
282
+ author { login __typename }
283
+ originalCommit { oid }
284
+ }
251
285
  }
252
286
  }
253
287
  pageInfo { hasNextPage endCursor }
@@ -263,34 +297,183 @@ mutation ResolveReviewThread($threadId: ID!) {
263
297
  }
264
298
  }
265
299
  `;
300
+ const GITHUB_VIEWER_LOGIN_QUERY = `
301
+ query ViewerLogin {
302
+ viewer { login }
303
+ }
304
+ `;
266
305
  /**
267
- * GitHub review comment {@link ExistingReviewComment}.
268
- *
269
- * Prefers the `original_*` fields the path/lines/commit as of the review
270
- * the comment belongs to. `line` drifts as the PR gains commits, so a
271
- * caller correlating a comment with the review that produced it needs the
272
- * original position, the same fields Bugbot carries on
273
- * `PullRequestCommentOutput`.
306
+ * The login the bound GitHub client itself acts as — the identity its posts
307
+ * appear under. Works for installation tokens too (GraphQL `viewer` returns
308
+ * the app's bot, e.g. `cursor[bot]`), so a reader can trust comments whose
309
+ * author is provably the same identity it posts with, across every
310
+ * environment's app (prod/staging/cloud-dev/custom) without hardcoding.
311
+ * `repo` scopes the call through the Cursor github-proxy (the minted token
312
+ * — and so the viewer — is per-repo there). Best-effort: `undefined` when
313
+ * the lookup fails.
274
314
  */
275
- export function normalizeGithubReviewComment(comment) {
276
- var _a, _b, _c;
277
- // Take both lines from the same position set. Mixing them (original end
278
- // line with the drifted current start line) would describe a range that
279
- // never existed in either revision.
280
- const original = (_a = comment.original_line) !== null && _a !== void 0 ? _a : undefined;
281
- const endLine = (_b = original !== null && original !== void 0 ? original : comment.line) !== null && _b !== void 0 ? _b : undefined;
282
- if (endLine === undefined || endLine === null) {
315
+ export function fetchGithubSelfLogin(github, args) {
316
+ return __awaiter(this, void 0, void 0, function* () {
317
+ var _a, _b, _c, _d;
318
+ try {
319
+ const octokit = yield github.getOctokit();
320
+ (_a = args.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
321
+ const response = (yield octokit.graphql(GITHUB_VIEWER_LOGIN_QUERY, {
322
+ headers: githubGraphqlScopeHeaders(args.repo),
323
+ }));
324
+ const login = (_b = response.viewer) === null || _b === void 0 ? void 0 : _b.login;
325
+ return typeof login === "string" && login !== "" ? login : undefined;
326
+ }
327
+ catch (error) {
328
+ if ((_c = args.signal) === null || _c === void 0 ? void 0 : _c.aborted) {
329
+ throw error;
330
+ }
331
+ (_d = args.log) === null || _d === void 0 ? void 0 : _d.call(args, `github viewer lookup failed: ${error instanceof Error ? error.message : String(error)}`);
332
+ return undefined;
333
+ }
334
+ });
335
+ }
336
+ /**
337
+ * Origin public comment → {@link ListedReviewComment}. Only line-anchored
338
+ * threads qualify (general-discussion and file-level threads carry no
339
+ * position a review finding can be pinned to).
340
+ */
341
+ export function listedCommentFromOriginComment(comment) {
342
+ var _a, _b, _c, _d;
343
+ var _e;
344
+ const thread = comment.thread;
345
+ if (typeof comment.id !== "string" ||
346
+ comment.id === "" ||
347
+ typeof comment.body !== "string" ||
348
+ thread === undefined ||
349
+ typeof thread.id !== "string" ||
350
+ thread.id === "" ||
351
+ typeof thread.path !== "string" ||
352
+ thread.path === "" ||
353
+ typeof thread.startLine !== "number" ||
354
+ thread.startLine <= 0) {
283
355
  return undefined;
284
356
  }
285
- const startLine = (_c = (original === undefined
286
- ? comment.start_line
287
- : comment.original_start_line)) !== null && _c !== void 0 ? _c : endLine;
357
+ const startLine = thread.startLine;
358
+ const endLine = typeof thread.endLine === "number" && thread.endLine >= startLine
359
+ ? thread.endLine
360
+ : startLine;
361
+ const commitSha = (_a = thread.version) === null || _a === void 0 ? void 0 : _a.headSha;
362
+ const author = comment.author;
363
+ const authorLogin = (_e = (_b = author === null || author === void 0 ? void 0 : author.app) === null || _b === void 0 ? void 0 : _b.slug) !== null && _e !== void 0 ? _e : (_c = author === null || author === void 0 ? void 0 : author.user) === null || _c === void 0 ? void 0 : _c.email;
364
+ // App and service-account actors are machine identities; only a `user`
365
+ // actor is a human PR participant.
366
+ const authorIsBot = author === undefined
367
+ ? undefined
368
+ : author.app !== undefined || author.serviceAccount !== undefined;
369
+ const authorAppId = (_d = author === null || author === void 0 ? void 0 : author.app) === null || _d === void 0 ? void 0 : _d.id;
370
+ return Object.assign(Object.assign(Object.assign(Object.assign({ commentId: comment.id, threadId: thread.id, resolved: typeof thread.resolvedAt === "string" && thread.resolvedAt !== "", file: thread.path, startLine,
371
+ endLine, body: comment.body }, (typeof commitSha === "string" && commitSha !== "" ? { commitSha } : {})), (typeof authorLogin === "string" && authorLogin !== ""
372
+ ? { authorLogin }
373
+ : {})), (authorIsBot === undefined ? {} : { authorIsBot })), (typeof authorAppId === "string" && authorAppId !== ""
374
+ ? { authorAppId }
375
+ : {}));
376
+ }
377
+ /**
378
+ * Lists the PR's inline review threads through the Origin public REST API
379
+ * (`GET …/pulls/{n}/comments`, paged). The flattened comment list is
380
+ * ordered by creation time, so the first comment seen per thread is the
381
+ * thread opener; replies are dropped.
382
+ */
383
+ export function createHostOriginReviewCommentLister(origin, log) {
288
384
  return {
289
- id: comment.id,
290
- file: comment.path,
291
- startLine,
292
- endLine,
293
- body: comment.body,
385
+ listReviewComments(_a) {
386
+ return __awaiter(this, arguments, void 0, function* ({ target, signal }) {
387
+ var _b, _c;
388
+ const [owner, repo] = target.repo.split("/", 2);
389
+ if (owner === undefined || repo === undefined || repo === "") {
390
+ log === null || log === void 0 ? void 0 : log(`origin list: unparseable owner/repo "${target.repo}"`);
391
+ return [];
392
+ }
393
+ const basePath = `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${target.prNumber}/comments`;
394
+ const comments = [];
395
+ const seenThreads = new Set();
396
+ let totalComments = 0;
397
+ let pageToken = "";
398
+ for (let page = 0; page < ORIGIN_COMMENTS_MAX_PAGES; page++) {
399
+ signal === null || signal === void 0 ? void 0 : signal.throwIfAborted();
400
+ const query = pageToken === ""
401
+ ? `?pageSize=${ORIGIN_COMMENTS_PAGE_SIZE}`
402
+ : `?pageSize=${ORIGIN_COMMENTS_PAGE_SIZE}&pageToken=${encodeURIComponent(pageToken)}`;
403
+ const response = (yield origin.request({
404
+ method: "GET",
405
+ path: `${basePath}${query}`,
406
+ }));
407
+ for (const comment of (_b = response === null || response === void 0 ? void 0 : response.comments) !== null && _b !== void 0 ? _b : []) {
408
+ if (comment === null || comment === undefined) {
409
+ continue;
410
+ }
411
+ totalComments += 1;
412
+ const listed = listedCommentFromOriginComment(comment);
413
+ if (listed === undefined || seenThreads.has(listed.threadId)) {
414
+ // Not line-anchored, or a reply on a thread whose opener was
415
+ // already taken (the list is oldest-first).
416
+ continue;
417
+ }
418
+ seenThreads.add(listed.threadId);
419
+ comments.push(listed);
420
+ }
421
+ pageToken = (_c = response === null || response === void 0 ? void 0 : response.nextPageToken) !== null && _c !== void 0 ? _c : "";
422
+ if (pageToken === "") {
423
+ break;
424
+ }
425
+ }
426
+ log === null || log === void 0 ? void 0 : log(`origin list: ${target.repo}#${target.prNumber} has ${totalComments} comment(s), ${comments.length} line-anchored thread opener(s)`);
427
+ return comments;
428
+ });
429
+ },
430
+ };
431
+ }
432
+ /**
433
+ * Resolves Origin comment threads through the public REST API
434
+ * (`PATCH …/pulls/threads/{thread_id}` with `resolved: true`).
435
+ */
436
+ export function createHostOriginReviewThreadResolver(origin, log) {
437
+ return {
438
+ resolveReviewThreads(_a) {
439
+ return __awaiter(this, arguments, void 0, function* ({ target, threadIds, signal }) {
440
+ const uniqueIds = [...new Set(threadIds.filter((id) => id !== ""))];
441
+ if (uniqueIds.length === 0) {
442
+ return skippedResolve("no threads to resolve");
443
+ }
444
+ const [owner, repo] = target.repo.split("/", 2);
445
+ if (owner === undefined || repo === undefined || repo === "") {
446
+ return skippedResolve("unparseable owner/repo from PR URL");
447
+ }
448
+ let resolved = 0;
449
+ let failed = 0;
450
+ for (const threadId of uniqueIds) {
451
+ signal === null || signal === void 0 ? void 0 : signal.throwIfAborted();
452
+ try {
453
+ yield origin.request({
454
+ method: "PATCH",
455
+ path: `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/threads/${encodeURIComponent(threadId)}`,
456
+ body: { resolved: true },
457
+ });
458
+ resolved += 1;
459
+ log === null || log === void 0 ? void 0 : log(`origin resolve: thread ${threadId} resolved`);
460
+ }
461
+ catch (error) {
462
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
463
+ throw error;
464
+ }
465
+ failed += 1;
466
+ log === null || log === void 0 ? void 0 : log(`origin resolve: thread ${threadId} failed: ${error instanceof Error ? error.message : String(error)}`);
467
+ }
468
+ }
469
+ return {
470
+ requested: uniqueIds.length,
471
+ resolved,
472
+ failed,
473
+ detail: `resolved ${resolved} of ${uniqueIds.length} thread(s) on ${target.repo}#${target.prNumber} via host Origin (${failed} failed)`,
474
+ };
475
+ });
476
+ },
294
477
  };
295
478
  }
296
479
  /**
@@ -367,9 +550,12 @@ export function createReviewCommentPublisher(args) {
367
550
  /**
368
551
  * Posts a COMMENT-verdict Origin review through the public REST API.
369
552
  *
370
- * Public Origin REST has no diff-anchored review comments (those are an
371
- * internal CreateCommentThread RPC). Inline comments in the request are
372
- * folded into the review body so findings still land on the PR.
553
+ * Inline comments post as diff-anchored threads via the review's
554
+ * `comments` field (`ReviewCommentInput` with an `InlineCommentAnchor`).
555
+ * Origin rejects the whole request with INVALID_ARGUMENT when any anchor
556
+ * is off the reviewed version's diff — the caller's body-only retry (the
557
+ * same fallback GitHub's 422 takes) then folds the findings into the
558
+ * review body.
373
559
  */
374
560
  export function createHostOriginReviewPublisher(origin) {
375
561
  return {
@@ -597,15 +783,19 @@ function postReviewViaHostOrigin(origin, args) {
597
783
  path: `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${target.prNumber}/reviews`,
598
784
  body: {
599
785
  verdict: "comment",
600
- body: originReviewBody(args),
786
+ body: args.message,
787
+ comments: args.comments.map(toOriginReviewCommentInput),
601
788
  },
602
789
  });
790
+ const inlineCommentCount = args.comments.length;
603
791
  return {
604
792
  posted: true,
605
793
  publisher: "host_origin",
606
- mode: "review_body_only",
607
- inlineCommentCount: 0,
608
- detail: `posted Origin review on ${target.repo}#${target.prNumber}`,
794
+ mode: inlineCommentCount > 0
795
+ ? "review_with_inline_comments"
796
+ : "review_body_only",
797
+ inlineCommentCount,
798
+ detail: `posted Origin review on ${target.repo}#${target.prNumber} with ${inlineCommentCount} inline comment(s)`,
609
799
  };
610
800
  }
611
801
  catch (error) {
@@ -616,30 +806,22 @@ function postReviewViaHostOrigin(origin, args) {
616
806
  }
617
807
  });
618
808
  }
619
- /**
620
- * Origin's public CreatePullRequestReview has a body, not inline comments.
621
- * Fold attempted anchors into the summary so findings are not dropped.
622
- */
623
- function originReviewBody(args) {
624
- if (args.comments.length === 0) {
625
- return args.message;
626
- }
627
- const sections = args.comments.map((comment) => {
628
- const location = comment.start_line !== undefined &&
629
- comment.start_line > 0 &&
630
- comment.start_line !== comment.line
631
- ? `${comment.file}:${comment.start_line}-${comment.line}`
632
- : `${comment.file}:${comment.line}`;
633
- return `### \`${location}\`\n\n${comment.body}`;
634
- });
635
- return [args.message, ...sections].join("\n\n");
809
+ /** Provider-neutral inline comment → Origin `ReviewCommentInput`. */
810
+ function toOriginReviewCommentInput(comment) {
811
+ const startLine = comment.start_line !== undefined &&
812
+ comment.start_line > 0 &&
813
+ comment.start_line < comment.line
814
+ ? comment.start_line
815
+ : comment.line;
816
+ return {
817
+ body: comment.body,
818
+ inline: Object.assign({ path: comment.file, side: "right", startLine }, (startLine === comment.line ? {} : { endLine: comment.line })),
819
+ };
636
820
  }
637
821
  function skippedResolve(detail) {
638
822
  return {
639
823
  requested: 0,
640
824
  resolved: 0,
641
- alreadyResolved: 0,
642
- notFound: 0,
643
825
  failed: 0,
644
826
  detail,
645
827
  };