@cursor/july 0.1.92 → 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.
- package/README.md +117 -162
- package/dist/channels/deployments/deployments-channel.d.ts +7 -0
- package/dist/channels/deployments/deployments-channel.d.ts.map +1 -1
- package/dist/channels/deployments/deployments-channel.js +26 -2
- package/dist/channels/deployments/types.d.ts +8 -0
- package/dist/channels/deployments/types.d.ts.map +1 -1
- package/dist/channels/github/github-channel.d.ts +3 -0
- package/dist/channels/github/github-channel.d.ts.map +1 -1
- package/dist/channels/github/github-channel.js +28 -56
- package/dist/continuation.d.ts +1 -1
- package/dist/continuation.js +1 -1
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +8 -8
- package/dist/docs/ab.md +7 -13
- package/dist/docs/assets/{ab.md.CVzWxLoB.js → ab.md.DJo5r4R-.js} +4 -4
- package/dist/docs/assets/{ab.md.CVzWxLoB.lean.js → ab.md.DJo5r4R-.lean.js} +1 -1
- package/dist/docs/assets/{app.Bci6CM9E.js → app.CjWU-x0z.js} +1 -1
- package/dist/docs/assets/building-with-agents.md.DI4mEzlt.js +13 -0
- package/dist/docs/assets/{building-with-agents.md.DH8A_cHA.lean.js → building-with-agents.md.DI4mEzlt.lean.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.ChpIC3Zy.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.BCPT6xA-.js → VPLocalSearchBox.Cxy8ySFQ.js} +1 -1
- package/dist/docs/assets/chunks/{theme.BEA8BF3c.js → theme.Dvq1Bktu.js} +2 -2
- package/dist/docs/assets/concepts.md.F6AiPorA.js +1 -0
- package/dist/docs/assets/{concepts.md.CRfU3bVg.lean.js → concepts.md.F6AiPorA.lean.js} +1 -1
- package/dist/docs/assets/{deployment.md.DX_hc3ze.js → deployment.md.DoLFAzfm.js} +6 -6
- package/dist/docs/assets/{evals.md.a0SMN6r9.js → evals.md.lfJoEVc8.js} +6 -6
- package/dist/docs/assets/{evals.md.a0SMN6r9.lean.js → evals.md.lfJoEVc8.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_approval-buddy.md.DNL83puR.js → example-agents_approval-buddy.md.DmezILPg.js} +1 -1
- package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.js → example-agents_benny.md.B0kwY7D_.js} +2 -4
- package/dist/docs/assets/{example-agents_benny.md.C40vHRLc.lean.js → example-agents_benny.md.B0kwY7D_.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_codebase-wiki.md.Dftj_tPp.js → example-agents_codebase-wiki.md.BBNw9Ekr.js} +3 -3
- package/dist/docs/assets/{example-agents_codebase-wiki.md.Dftj_tPp.lean.js → example-agents_codebase-wiki.md.BBNw9Ekr.lean.js} +1 -1
- package/dist/docs/assets/{example-agents_concierge.md.MrKpQndp.js → example-agents_concierge.md.BzB2b20R.js} +2 -3
- package/dist/docs/assets/example-agents_index.md.ChBp0AX6.js +2 -0
- package/dist/docs/assets/example-agents_index.md.ChBp0AX6.lean.js +1 -0
- package/dist/docs/assets/{example-agents_knowledge-base.md.DqKqHQ9u.js → example-agents_knowledge-base.md.CrA85ig-.js} +1 -1
- package/dist/docs/assets/{example-agents_security-reviewer.md.Bai6D0Ee.js → example-agents_security-reviewer.md.74pPpWYj.js} +1 -1
- package/dist/docs/assets/{example-agents_weather-agent.md.lVEAbWFf.js → example-agents_weather-agent.md.CaGpmw3Y.js} +2 -2
- package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.js → guides_agent-to-agent.md.B3JIaAqz.js} +1 -1
- package/dist/docs/assets/{guides_cloud-runtime.md.BSMLIBHr.js → guides_cloud-runtime.md.BnvjPiia.js} +2 -2
- package/dist/docs/assets/{guides_cloud-runtime.md.BSMLIBHr.lean.js → guides_cloud-runtime.md.BnvjPiia.lean.js} +1 -1
- package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.js → guides_convert-automation.md.Bboisykk.js} +1 -1
- package/dist/docs/assets/{guides_github.md.Cdt1s2QC.js → guides_github.md.DqJhuaN1.js} +5 -5
- package/dist/docs/assets/{guides_github.md.Cdt1s2QC.lean.js → guides_github.md.DqJhuaN1.lean.js} +1 -1
- package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.js → guides_mcp-oauth.md.CJvrXtkN.js} +2 -2
- package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.js → guides_slack.md.mqeNKs84.js} +2 -2
- package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.js → guides_webhooks.md.DKdA43Qm.js} +2 -2
- package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.js → hillclimbing.md.DhESf3OO.js} +1 -1
- package/dist/docs/assets/{index.md.BAaMXLFd.js → index.md.B-lVR4wT.js} +3 -3
- package/dist/docs/assets/{index.md.BAaMXLFd.lean.js → index.md.B-lVR4wT.lean.js} +1 -1
- package/dist/docs/assets/{quickstart.md.DsrarzEg.js → quickstart.md.BrmfrrIr.js} +1 -1
- package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.js → reference_agent-config.md.Cp_x38Nl.js} +3 -3
- package/dist/docs/assets/{reference_channels.md.DQZjCnyh.js → reference_channels.md.Cd2f2iyV.js} +2 -2
- package/dist/docs/assets/{reference_channels.md.DQZjCnyh.lean.js → reference_channels.md.Cd2f2iyV.lean.js} +1 -1
- package/dist/docs/assets/{reference_cli.md.B7GkAJRC.js → reference_cli.md.D9KESDsD.js} +10 -11
- package/dist/docs/assets/{reference_cli.md.B7GkAJRC.lean.js → reference_cli.md.D9KESDsD.lean.js} +1 -1
- package/dist/docs/assets/{reference_connections.md.DYidrb-j.js → reference_connections.md.DB6SsN6U.js} +3 -3
- package/dist/docs/assets/reference_hooks.md.BxN87gCw.js +14 -0
- package/dist/docs/assets/{reference_hooks.md.B9FSgdDe.lean.js → reference_hooks.md.BxN87gCw.lean.js} +1 -1
- package/dist/docs/assets/reference_http-api.md.C68BERYr.js +11 -0
- package/dist/docs/assets/reference_http-api.md.C68BERYr.lean.js +1 -0
- package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.js → reference_instructions.md.CR7XSsGk.js} +3 -3
- package/dist/docs/assets/{reference_instructions.md.DhNCOl7r.lean.js → reference_instructions.md.CR7XSsGk.lean.js} +1 -1
- package/dist/docs/assets/reference_playground.md.DnX5nL-B.js +1 -0
- package/dist/docs/assets/reference_playground.md.DnX5nL-B.lean.js +1 -0
- package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.js → reference_project-layout.md.WN9nwJht.js} +2 -2
- package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.js → reference_prompt.md.DnaD5dNK.js} +1 -1
- package/dist/docs/assets/{reference_schedules.md.DNipebiG.js → reference_schedules.md.DI_JrHgq.js} +1 -1
- package/dist/docs/assets/reference_sessions.md.D0mIh4KK.js +1 -0
- package/dist/docs/assets/{reference_sessions.md.tUFzz98S.lean.js → reference_sessions.md.D0mIh4KK.lean.js} +1 -1
- package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.js → reference_skills.md.BFW9retM.js} +1 -1
- package/dist/docs/assets/{reference_tools.md.wpaJtHn6.js → reference_tools.md.DuKvkYWG.js} +4 -4
- package/dist/docs/assets/{reference_tools.md.wpaJtHn6.lean.js → reference_tools.md.DuKvkYWG.lean.js} +1 -1
- package/dist/docs/assets/scaffolding-agents.md.D7UUkWw0.js +1 -0
- package/dist/docs/assets/{scaffolding-agents.md.CRDDUtYJ.lean.js → scaffolding-agents.md.D7UUkWw0.lean.js} +1 -1
- package/dist/docs/assets/{storage.md.JbjlHWZ6.js → storage.md.BOHeqk2M.js} +5 -5
- package/dist/docs/assets/{storage.md.JbjlHWZ6.lean.js → storage.md.BOHeqk2M.lean.js} +1 -1
- package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.js → templates_agentic-owners.md.DqtPdm6f.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.js → templates_pr-autofixer.md.R4K_qytS.js} +2 -2
- package/dist/docs/assets/{templates_pr-autofixer.md.1HAR3RXE.lean.js → templates_pr-autofixer.md.R4K_qytS.lean.js} +1 -1
- package/dist/docs/assets/troubleshooting.md.vCWwvqcJ.js +1 -0
- package/dist/docs/assets/{troubleshooting.md.DYECCZiJ.lean.js → troubleshooting.md.vCWwvqcJ.lean.js} +1 -1
- package/dist/docs/building-with-agents.html +7 -7
- package/dist/docs/building-with-agents.md +5 -11
- package/dist/docs/concepts.html +5 -8
- package/dist/docs/concepts.md +12 -17
- package/dist/docs/deployment.html +11 -11
- package/dist/docs/deployment.md +8 -10
- package/dist/docs/evals.html +10 -10
- package/dist/docs/evals.md +16 -37
- package/dist/docs/example-agents/approval-buddy.html +5 -5
- package/dist/docs/example-agents/approval-buddy.md +1 -1
- package/dist/docs/example-agents/benny.html +5 -7
- package/dist/docs/example-agents/benny.md +4 -13
- package/dist/docs/example-agents/bugbot.html +4 -4
- package/dist/docs/example-agents/codebase-wiki.html +6 -6
- package/dist/docs/example-agents/codebase-wiki.md +5 -8
- package/dist/docs/example-agents/codeowners-review.html +4 -4
- package/dist/docs/example-agents/concierge.html +7 -8
- package/dist/docs/example-agents/concierge.md +2 -3
- package/dist/docs/example-agents/index.html +6 -6
- package/dist/docs/example-agents/index.md +5 -8
- package/dist/docs/example-agents/knowledge-base.html +6 -6
- package/dist/docs/example-agents/knowledge-base.md +2 -2
- package/dist/docs/example-agents/oncall.html +4 -4
- package/dist/docs/example-agents/security-reviewer.html +7 -7
- package/dist/docs/example-agents/security-reviewer.md +5 -5
- package/dist/docs/example-agents/slack-agent.html +4 -4
- package/dist/docs/example-agents/weather-agent.html +7 -7
- package/dist/docs/example-agents/weather-agent.md +4 -3
- package/dist/docs/guides/agent-to-agent.html +5 -5
- package/dist/docs/guides/agent-to-agent.md +1 -1
- package/dist/docs/guides/cloud-runtime.html +6 -6
- package/dist/docs/guides/cloud-runtime.md +8 -25
- package/dist/docs/guides/convert-automation.html +6 -6
- package/dist/docs/guides/convert-automation.md +3 -3
- package/dist/docs/guides/github.html +9 -9
- package/dist/docs/guides/github.md +11 -23
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/mcp-oauth.html +6 -6
- package/dist/docs/guides/mcp-oauth.md +4 -4
- package/dist/docs/guides/opentelemetry.html +4 -4
- package/dist/docs/guides/slack.html +7 -7
- package/dist/docs/guides/slack.md +4 -4
- package/dist/docs/guides/webhooks.html +6 -6
- package/dist/docs/guides/webhooks.md +3 -3
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +6 -6
- package/dist/docs/hillclimbing.md +1 -1
- package/dist/docs/index.html +6 -6
- package/dist/docs/index.md +2 -10
- package/dist/docs/llms-full.txt +300 -850
- package/dist/docs/llms.txt +2 -3
- package/dist/docs/quickstart.html +5 -5
- package/dist/docs/quickstart.md +1 -1
- package/dist/docs/reference/agent-config.html +8 -8
- package/dist/docs/reference/agent-config.md +10 -15
- package/dist/docs/reference/artifacts.html +4 -4
- package/dist/docs/reference/channels.html +6 -6
- package/dist/docs/reference/channels.md +20 -31
- package/dist/docs/reference/cli.html +14 -15
- package/dist/docs/reference/cli.md +27 -37
- package/dist/docs/reference/connections.html +8 -8
- package/dist/docs/reference/connections.md +9 -14
- package/dist/docs/reference/hooks.html +6 -6
- package/dist/docs/reference/hooks.md +10 -14
- package/dist/docs/reference/http-api.html +7 -7
- package/dist/docs/reference/http-api.md +17 -37
- package/dist/docs/reference/instructions.html +6 -6
- package/dist/docs/reference/instructions.md +1 -1
- package/dist/docs/reference/playground.html +5 -5
- package/dist/docs/reference/playground.md +14 -19
- package/dist/docs/reference/project-layout.html +7 -7
- package/dist/docs/reference/project-layout.md +2 -2
- package/dist/docs/reference/prompt.html +6 -6
- package/dist/docs/reference/prompt.md +1 -1
- package/dist/docs/reference/schedules.html +6 -6
- package/dist/docs/reference/schedules.md +1 -2
- package/dist/docs/reference/sessions.html +5 -12
- package/dist/docs/reference/sessions.md +8 -19
- package/dist/docs/reference/skills.html +6 -6
- package/dist/docs/reference/skills.md +3 -3
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +8 -8
- package/dist/docs/reference/tools.md +12 -17
- package/dist/docs/scaffolding-agents.html +5 -5
- package/dist/docs/scaffolding-agents.md +4 -5
- package/dist/docs/storage.html +9 -9
- package/dist/docs/storage.md +37 -80
- package/dist/docs/templates/agentic-owners.html +7 -7
- package/dist/docs/templates/agentic-owners.md +2 -2
- package/dist/docs/templates/demo.html +4 -4
- package/dist/docs/templates/pr-autofixer.html +6 -6
- package/dist/docs/templates/pr-autofixer.md +3 -6
- package/dist/docs/templates/security-reviewer.html +4 -4
- package/dist/docs/templates/triage.html +4 -4
- package/dist/docs/troubleshooting.html +5 -5
- package/dist/docs/troubleshooting.md +6 -6
- package/dist/internal/authored-alias-hooks.d.ts +14 -11
- package/dist/internal/authored-alias-hooks.d.ts.map +1 -1
- package/dist/internal/authored-alias-hooks.js +14 -11
- package/dist/internal/authored-loaders.d.ts +7 -6
- package/dist/internal/authored-loaders.d.ts.map +1 -1
- package/dist/internal/authored-loaders.js +14 -10
- package/dist/internal/cli-deploy.d.ts +1 -1
- package/dist/internal/cli-deploy.js +5 -5
- package/dist/internal/continuation-channel.d.ts +6 -3
- package/dist/internal/continuation-channel.d.ts.map +1 -1
- package/dist/internal/continuation-channel.js +44 -40
- package/dist/internal/continuation-identity.d.ts +17 -16
- package/dist/internal/continuation-identity.d.ts.map +1 -1
- package/dist/internal/continuation-identity.js +109 -36
- package/dist/internal/deploy-manifest.d.ts +2 -2
- package/dist/internal/deploy-manifest.d.ts.map +1 -1
- package/dist/internal/deploy-manifest.js +4 -9
- package/dist/internal/discovery.d.ts.map +1 -1
- package/dist/internal/discovery.js +3 -0
- package/dist/internal/distribution.d.ts +4 -3
- package/dist/internal/distribution.d.ts.map +1 -1
- package/dist/internal/distribution.js +4 -3
- package/dist/internal/hosted-delivery-protocol.d.ts +38 -0
- package/dist/internal/hosted-delivery-protocol.d.ts.map +1 -0
- package/dist/internal/hosted-delivery-protocol.js +70 -0
- package/dist/internal/hosted-delivery.d.ts +35 -0
- package/dist/internal/hosted-delivery.d.ts.map +1 -0
- package/dist/internal/hosted-delivery.js +226 -0
- package/dist/internal/http-channel.d.ts.map +1 -1
- package/dist/internal/http-channel.js +1 -1
- package/dist/internal/review-comments.d.ts +186 -63
- package/dist/internal/review-comments.d.ts.map +1 -1
- package/dist/internal/review-comments.js +350 -168
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +21 -3
- package/dist/internal/session-engine.d.ts +5 -0
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +13 -3
- package/dist/internal/shallow-clone.d.ts +8 -2
- package/dist/internal/shallow-clone.d.ts.map +1 -1
- package/dist/internal/shallow-clone.js +17 -10
- package/dist/playground/assets/{index-DDvyC2z6.js → index-D9MFzhNE.js} +1 -1
- package/dist/playground/index.html +1 -1
- package/dist/types.d.ts +9 -17
- package/dist/types.d.ts.map +1 -1
- package/docs/README.md +2 -10
- package/docs/ab.md +7 -13
- package/docs/building-with-agents.md +5 -11
- package/docs/concepts.md +12 -17
- package/docs/deployment.md +8 -10
- package/docs/evals.md +16 -37
- package/docs/example-agents/approval-buddy.md +1 -1
- package/docs/example-agents/benny.md +4 -13
- package/docs/example-agents/codebase-wiki.md +5 -8
- package/docs/example-agents/concierge.md +2 -3
- package/docs/example-agents/index.md +6 -9
- package/docs/example-agents/knowledge-base.md +2 -2
- package/docs/example-agents/security-reviewer.md +5 -5
- package/docs/example-agents/weather-agent.md +4 -3
- package/docs/guides/agent-to-agent.md +1 -1
- package/docs/guides/cloud-runtime.md +8 -25
- package/docs/guides/convert-automation.md +3 -3
- package/docs/guides/github.md +11 -23
- package/docs/guides/mcp-oauth.md +4 -4
- package/docs/guides/slack.md +4 -4
- package/docs/guides/webhooks.md +3 -3
- package/docs/hillclimbing.md +1 -1
- package/docs/quickstart.md +1 -1
- package/docs/reference/agent-config.md +10 -15
- package/docs/reference/channels.md +20 -31
- package/docs/reference/cli.md +27 -37
- package/docs/reference/connections.md +9 -14
- package/docs/reference/hooks.md +10 -14
- package/docs/reference/http-api.md +18 -38
- package/docs/reference/instructions.md +1 -1
- package/docs/reference/playground.md +14 -19
- package/docs/reference/project-layout.md +2 -2
- package/docs/reference/prompt.md +1 -1
- package/docs/reference/schedules.md +1 -2
- package/docs/reference/sessions.md +8 -19
- package/docs/reference/skills.md +3 -3
- package/docs/reference/tools.md +12 -17
- package/docs/scaffolding-agents.md +4 -5
- package/docs/storage.md +37 -80
- package/docs/templates/agentic-owners.md +2 -2
- package/docs/templates/pr-autofixer.md +3 -6
- package/docs/troubleshooting.md +6 -6
- package/package.json +8 -1
- package/src/channels/deployments/deployments-channel.ts +32 -2
- package/src/channels/deployments/types.ts +8 -0
- package/src/channels/github/github-channel.ts +71 -21
- package/src/continuation.ts +1 -1
- package/src/internal/authored-alias-hooks.ts +14 -11
- package/src/internal/authored-loaders.ts +14 -10
- package/src/internal/cli-deploy.ts +5 -5
- package/src/internal/continuation-channel.ts +62 -45
- package/src/internal/continuation-identity.ts +123 -38
- package/src/internal/deploy-manifest.ts +5 -9
- package/src/internal/discovery.ts +3 -0
- package/src/internal/distribution.ts +4 -3
- package/src/internal/hosted-delivery-protocol.ts +114 -0
- package/src/internal/hosted-delivery.ts +327 -0
- package/src/internal/http-channel.ts +0 -2
- package/src/internal/review-comments.ts +542 -229
- package/src/internal/server.ts +29 -2
- package/src/internal/session-engine.ts +25 -1
- package/src/internal/shallow-clone.ts +30 -16
- package/src/types.ts +9 -17
- package/dist/docs/assets/building-with-agents.md.DH8A_cHA.js +0 -13
- package/dist/docs/assets/chunks/@localSearchIndexroot.Dv-Q0XtU.js +0 -1
- package/dist/docs/assets/concepts.md.CRfU3bVg.js +0 -4
- package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.js +0 -15
- package/dist/docs/assets/example-agents_fsd.md.ZWHWWZPE.lean.js +0 -1
- package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.js +0 -2
- package/dist/docs/assets/example-agents_index.md.QZ8mhr6n.lean.js +0 -1
- package/dist/docs/assets/reference_hooks.md.B9FSgdDe.js +0 -14
- package/dist/docs/assets/reference_http-api.md.CSHVobzG.js +0 -11
- package/dist/docs/assets/reference_http-api.md.CSHVobzG.lean.js +0 -1
- package/dist/docs/assets/reference_playground.md.Dfb92yQf.js +0 -1
- package/dist/docs/assets/reference_playground.md.Dfb92yQf.lean.js +0 -1
- package/dist/docs/assets/reference_sessions.md.tUFzz98S.js +0 -8
- package/dist/docs/assets/scaffolding-agents.md.CRDDUtYJ.js +0 -1
- package/dist/docs/assets/troubleshooting.md.DYECCZiJ.js +0 -1
- package/dist/docs/example-agents/fsd.html +0 -41
- package/dist/docs/example-agents/fsd.md +0 -329
- package/docs/example-agents/fsd.md +0 -334
- /package/dist/docs/assets/{deployment.md.DX_hc3ze.lean.js → deployment.md.DoLFAzfm.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_approval-buddy.md.DNL83puR.lean.js → example-agents_approval-buddy.md.DmezILPg.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_concierge.md.MrKpQndp.lean.js → example-agents_concierge.md.BzB2b20R.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_knowledge-base.md.DqKqHQ9u.lean.js → example-agents_knowledge-base.md.CrA85ig-.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_security-reviewer.md.Bai6D0Ee.lean.js → example-agents_security-reviewer.md.74pPpWYj.lean.js} +0 -0
- /package/dist/docs/assets/{example-agents_weather-agent.md.lVEAbWFf.lean.js → example-agents_weather-agent.md.CaGpmw3Y.lean.js} +0 -0
- /package/dist/docs/assets/{guides_agent-to-agent.md.BCeVdJRJ.lean.js → guides_agent-to-agent.md.B3JIaAqz.lean.js} +0 -0
- /package/dist/docs/assets/{guides_convert-automation.md.D06eIzea.lean.js → guides_convert-automation.md.Bboisykk.lean.js} +0 -0
- /package/dist/docs/assets/{guides_mcp-oauth.md.Du0f7pGU.lean.js → guides_mcp-oauth.md.CJvrXtkN.lean.js} +0 -0
- /package/dist/docs/assets/{guides_slack.md.DiUmk_Oi.lean.js → guides_slack.md.mqeNKs84.lean.js} +0 -0
- /package/dist/docs/assets/{guides_webhooks.md.BpnIdO0i.lean.js → guides_webhooks.md.DKdA43Qm.lean.js} +0 -0
- /package/dist/docs/assets/{hillclimbing.md.ywF3yDAd.lean.js → hillclimbing.md.DhESf3OO.lean.js} +0 -0
- /package/dist/docs/assets/{quickstart.md.DsrarzEg.lean.js → quickstart.md.BrmfrrIr.lean.js} +0 -0
- /package/dist/docs/assets/{reference_agent-config.md.Bqylgw50.lean.js → reference_agent-config.md.Cp_x38Nl.lean.js} +0 -0
- /package/dist/docs/assets/{reference_connections.md.DYidrb-j.lean.js → reference_connections.md.DB6SsN6U.lean.js} +0 -0
- /package/dist/docs/assets/{reference_project-layout.md.CwkSbEWT.lean.js → reference_project-layout.md.WN9nwJht.lean.js} +0 -0
- /package/dist/docs/assets/{reference_prompt.md.DZUMtLPD.lean.js → reference_prompt.md.DnaD5dNK.lean.js} +0 -0
- /package/dist/docs/assets/{reference_schedules.md.DNipebiG.lean.js → reference_schedules.md.DI_JrHgq.lean.js} +0 -0
- /package/dist/docs/assets/{reference_skills.md.B5ZEuHfG.lean.js → reference_skills.md.BFW9retM.lean.js} +0 -0
- /package/dist/docs/assets/{templates_agentic-owners.md.DSJSIpWU.lean.js → templates_agentic-owners.md.DqtPdm6f.lean.js} +0 -0
|
@@ -85,77 +85,111 @@ export type ScmReviewTarget = {
|
|
|
85
85
|
prNumber: number;
|
|
86
86
|
};
|
|
87
87
|
|
|
88
|
+
/** Optional structured logger for the read/resolve seams (`[asr]`-style). */
|
|
89
|
+
export type ReviewCommentLog = (message: string) => void;
|
|
90
|
+
|
|
88
91
|
/**
|
|
89
|
-
* One
|
|
92
|
+
* One inline review-thread comment from a PR-wide listing, provider-neutral.
|
|
90
93
|
*
|
|
91
|
-
*
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
94
|
+
* This is the Bugbot listing shape (`minimizePreviousBugBotComments` /
|
|
95
|
+
* `getBugBotComments` normalize each provider's `getPRComments` output the
|
|
96
|
+
* same way): a re-review lists everything on the PR and filters on its own
|
|
97
|
+
* marker, rather than fetching ids it recorded elsewhere.
|
|
95
98
|
*/
|
|
96
|
-
export type
|
|
97
|
-
|
|
99
|
+
export type ListedReviewComment = {
|
|
100
|
+
/**
|
|
101
|
+
* Provider-native comment id, stringified for provider neutrality
|
|
102
|
+
* (GitHub REST database id in decimal; Origin `cmt_…`).
|
|
103
|
+
*/
|
|
104
|
+
commentId: string;
|
|
105
|
+
/** GitHub REST numeric comment id, when the provider exposes one. */
|
|
106
|
+
numericCommentId?: number;
|
|
107
|
+
/**
|
|
108
|
+
* Id of the thread this comment opens, in the form the provider's thread
|
|
109
|
+
* resolver accepts (GitHub GraphQL thread node id; Origin `cth_…`).
|
|
110
|
+
*/
|
|
111
|
+
threadId: string;
|
|
112
|
+
/** Whether the owning thread is already resolved. */
|
|
113
|
+
resolved: boolean;
|
|
98
114
|
file: string;
|
|
99
115
|
startLine: number;
|
|
100
116
|
endLine: number;
|
|
101
117
|
body: string;
|
|
118
|
+
/**
|
|
119
|
+
* Head SHA the comment was filed against (GitHub `originalCommit`; Origin
|
|
120
|
+
* the thread version's head SHA), when the provider exposes it. This is
|
|
121
|
+
* the commit a follow-up judge diffs forward from.
|
|
122
|
+
*/
|
|
123
|
+
commitSha?: string;
|
|
124
|
+
authorLogin?: string;
|
|
125
|
+
/**
|
|
126
|
+
* Whether the SCM attributes the comment to a machine identity — a
|
|
127
|
+
* GitHub App bot (GraphQL author `__typename: "Bot"`) or an Origin
|
|
128
|
+
* app/service-account actor. Human accounts are `false`; `undefined`
|
|
129
|
+
* when the provider did not return an author (e.g. deleted account).
|
|
130
|
+
* Callers deciding whether a comment is their own must require `true`
|
|
131
|
+
* AND pin the specific identity (login / app id): body content is
|
|
132
|
+
* forgeable by any PR participant, and other bots/apps also comment.
|
|
133
|
+
*/
|
|
134
|
+
authorIsBot?: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* Origin app actor id (`app_…`) when the comment was authored by an app
|
|
137
|
+
* installation. Callers compare it against their own configured app id
|
|
138
|
+
* to decide the comment is theirs, not merely some app's.
|
|
139
|
+
*/
|
|
140
|
+
authorAppId?: string;
|
|
102
141
|
};
|
|
103
142
|
|
|
104
|
-
export type
|
|
143
|
+
export type ListReviewCommentsArgs = {
|
|
105
144
|
target: ScmReviewTarget;
|
|
106
|
-
/** Comment ids to fetch; ids the SCM no longer has are omitted. */
|
|
107
|
-
commentIds: readonly number[];
|
|
108
145
|
signal?: AbortSignal;
|
|
109
146
|
};
|
|
110
147
|
|
|
111
148
|
/**
|
|
112
149
|
* Read side of the review-comment seam, mirroring
|
|
113
150
|
* {@link ReviewCommentPublisherImplementation}. Bugbot's equivalent is
|
|
114
|
-
* `IGitProvider.getPRComments
|
|
115
|
-
*
|
|
116
|
-
* By id rather than by listing: callers only ever want comments they
|
|
117
|
-
* recorded creating, and a busy PR's comment list runs to thousands, where
|
|
118
|
-
* any page cap silently drops exactly the older comments a re-review needs.
|
|
151
|
+
* `IGitProvider.getPRComments`: list the PR's inline review threads (their
|
|
152
|
+
* opening comments) so a re-review can find its own previous comments.
|
|
119
153
|
*/
|
|
120
|
-
export type
|
|
121
|
-
|
|
122
|
-
args:
|
|
123
|
-
) => Promise<
|
|
154
|
+
export type ReviewCommentListerImplementation = {
|
|
155
|
+
listReviewComments: (
|
|
156
|
+
args: ListReviewCommentsArgs
|
|
157
|
+
) => Promise<ListedReviewComment[]>;
|
|
124
158
|
};
|
|
125
159
|
|
|
126
160
|
export type ResolveReviewThreadsArgs = {
|
|
127
161
|
target: ScmReviewTarget;
|
|
128
|
-
/**
|
|
129
|
-
|
|
162
|
+
/** Provider-native thread ids (from {@link ListedReviewComment.threadId}). */
|
|
163
|
+
threadIds: readonly string[];
|
|
130
164
|
signal?: AbortSignal;
|
|
131
165
|
};
|
|
132
166
|
|
|
133
167
|
/**
|
|
134
|
-
* Outcome of resolving
|
|
135
|
-
*
|
|
136
|
-
*
|
|
168
|
+
* Outcome of resolving a set of review threads. Callers treat this as
|
|
169
|
+
* best-effort actuation: a failed resolve must not fail the review that
|
|
170
|
+
* already posted.
|
|
137
171
|
*/
|
|
138
172
|
export type ResolveReviewThreadsResult = {
|
|
139
173
|
requested: number;
|
|
140
174
|
resolved: number;
|
|
141
|
-
alreadyResolved: number;
|
|
142
|
-
notFound: number;
|
|
143
175
|
failed: number;
|
|
144
176
|
detail: string;
|
|
145
177
|
};
|
|
146
178
|
|
|
147
179
|
/**
|
|
148
180
|
* Write side of thread resolution, the counterpart of
|
|
149
|
-
* {@link
|
|
181
|
+
* {@link ReviewCommentListerImplementation}. Bugbot's equivalent is
|
|
150
182
|
* `IGitProvider.resolveReviewThreadForComment` / `resolveThreads`.
|
|
151
183
|
*
|
|
152
184
|
* GitHub only exposes resolve via GraphQL (`resolveReviewThread`). REST
|
|
153
185
|
* has no equivalent. The mutation runs as whatever identity minted the
|
|
154
186
|
* bound GitHub client — for `githubChannel({ cursorAccount })` that is
|
|
155
187
|
* the Cursor installation, the same identity that posted the comments.
|
|
188
|
+
* Origin exposes resolve on the public REST API
|
|
189
|
+
* (`PATCH …/pulls/threads/{thread_id}`).
|
|
156
190
|
*/
|
|
157
191
|
export type ReviewThreadResolverImplementation = {
|
|
158
|
-
|
|
192
|
+
resolveReviewThreads: (
|
|
159
193
|
args: ResolveReviewThreadsArgs
|
|
160
194
|
) => Promise<ResolveReviewThreadsResult>;
|
|
161
195
|
};
|
|
@@ -169,23 +203,25 @@ export function resolveScmReviewTarget(
|
|
|
169
203
|
}
|
|
170
204
|
|
|
171
205
|
/**
|
|
172
|
-
*
|
|
206
|
+
* Lister for a resolved target, mirroring Bugbot's `createPrGitProvider`
|
|
173
207
|
* dispatch. Returns undefined when the host cannot serve that provider (no
|
|
174
|
-
* GitHub client bound), so callers degrade instead of throwing.
|
|
208
|
+
* GitHub/Origin client bound), so callers degrade instead of throwing.
|
|
175
209
|
*/
|
|
176
|
-
export function
|
|
210
|
+
export function createReviewCommentLister(args: {
|
|
177
211
|
target: ScmReviewTarget;
|
|
178
212
|
github?: HostGitHubClient;
|
|
179
|
-
|
|
213
|
+
origin?: HostOriginReviewClient;
|
|
214
|
+
log?: ReviewCommentLog;
|
|
215
|
+
}): ReviewCommentListerImplementation | undefined {
|
|
180
216
|
switch (args.target.provider) {
|
|
181
217
|
case "github":
|
|
182
218
|
return args.github === undefined
|
|
183
219
|
? undefined
|
|
184
|
-
:
|
|
220
|
+
: createHostGithubReviewCommentLister(args.github, args.log);
|
|
185
221
|
case "origin":
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
222
|
+
return args.origin === undefined
|
|
223
|
+
? undefined
|
|
224
|
+
: createHostOriginReviewCommentLister(args.origin, args.log);
|
|
189
225
|
}
|
|
190
226
|
}
|
|
191
227
|
|
|
@@ -196,33 +232,39 @@ export function createReviewCommentReader(args: {
|
|
|
196
232
|
export function createReviewThreadResolver(args: {
|
|
197
233
|
target: ScmReviewTarget;
|
|
198
234
|
github?: HostGitHubClient;
|
|
235
|
+
origin?: HostOriginReviewClient;
|
|
236
|
+
log?: ReviewCommentLog;
|
|
199
237
|
}): ReviewThreadResolverImplementation | undefined {
|
|
200
238
|
switch (args.target.provider) {
|
|
201
239
|
case "github":
|
|
202
240
|
return args.github === undefined
|
|
203
241
|
? undefined
|
|
204
|
-
: createHostGithubReviewThreadResolver(args.github);
|
|
242
|
+
: createHostGithubReviewThreadResolver(args.github, args.log);
|
|
205
243
|
case "origin":
|
|
206
|
-
return undefined
|
|
244
|
+
return args.origin === undefined
|
|
245
|
+
? undefined
|
|
246
|
+
: createHostOriginReviewThreadResolver(args.origin, args.log);
|
|
207
247
|
}
|
|
208
248
|
}
|
|
209
249
|
|
|
210
250
|
/**
|
|
211
|
-
* Resolve
|
|
251
|
+
* Resolve `threadIds` on `prUrl`'s PR.
|
|
212
252
|
*
|
|
213
253
|
* No-ops (never throws) when the PR is on an SCM this host cannot write,
|
|
214
|
-
* no client is bound, or `
|
|
215
|
-
* posture as {@link
|
|
254
|
+
* no client is bound, or `threadIds` is empty. Same degrade-don't-fail
|
|
255
|
+
* posture as {@link createReviewCommentLister}.
|
|
216
256
|
*/
|
|
217
|
-
export async function
|
|
257
|
+
export async function resolveReviewThreads(args: {
|
|
218
258
|
prUrl: string;
|
|
219
|
-
|
|
259
|
+
threadIds: readonly string[];
|
|
220
260
|
github?: HostGitHubClient;
|
|
261
|
+
origin?: HostOriginReviewClient;
|
|
221
262
|
resolver?: ReviewThreadResolverImplementation;
|
|
222
263
|
signal?: AbortSignal;
|
|
264
|
+
log?: ReviewCommentLog;
|
|
223
265
|
}): Promise<ResolveReviewThreadsResult> {
|
|
224
|
-
if (args.
|
|
225
|
-
return skippedResolve("no
|
|
266
|
+
if (args.threadIds.length === 0) {
|
|
267
|
+
return skippedResolve("no threads to resolve");
|
|
226
268
|
}
|
|
227
269
|
const target = resolveScmReviewTarget(args.prUrl);
|
|
228
270
|
if (target === undefined) {
|
|
@@ -233,17 +275,17 @@ export async function resolveReviewThreadsForComments(args: {
|
|
|
233
275
|
createReviewThreadResolver({
|
|
234
276
|
target,
|
|
235
277
|
github: args.github,
|
|
278
|
+
origin: args.origin,
|
|
279
|
+
log: args.log,
|
|
236
280
|
});
|
|
237
281
|
if (resolver === undefined) {
|
|
238
282
|
return skippedResolve(
|
|
239
|
-
target.provider
|
|
240
|
-
? "no GitHub client bound to resolve threads"
|
|
241
|
-
: `no thread resolver for ${target.provider}`
|
|
283
|
+
`no ${target.provider} client bound to resolve threads`
|
|
242
284
|
);
|
|
243
285
|
}
|
|
244
|
-
return resolver.
|
|
286
|
+
return resolver.resolveReviewThreads({
|
|
245
287
|
target,
|
|
246
|
-
|
|
288
|
+
threadIds: args.threadIds,
|
|
247
289
|
signal: args.signal,
|
|
248
290
|
});
|
|
249
291
|
}
|
|
@@ -251,52 +293,30 @@ export async function resolveReviewThreadsForComments(args: {
|
|
|
251
293
|
/** Cap on pages pulled per PR; GitHub serves 100 comments per page. */
|
|
252
294
|
const REVIEW_COMMENTS_MAX_PAGES = 5;
|
|
253
295
|
const REVIEW_COMMENTS_PAGE_SIZE = 100;
|
|
254
|
-
/** Cap on review-thread pages when
|
|
296
|
+
/** Cap on review-thread pages when listing a PR's inline threads. */
|
|
255
297
|
const REVIEW_THREADS_MAX_PAGES = 20;
|
|
256
298
|
const REVIEW_THREADS_PAGE_SIZE = 100;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
const [owner, repo] = target.repo.split("/", 2);
|
|
268
|
-
if (owner === undefined || repo === undefined || repo === "") {
|
|
269
|
-
return [];
|
|
270
|
-
}
|
|
271
|
-
const octokit = await github.getOctokit();
|
|
272
|
-
const comments: ExistingReviewComment[] = [];
|
|
273
|
-
for (const commentId of commentIds) {
|
|
274
|
-
signal?.throwIfAborted();
|
|
275
|
-
try {
|
|
276
|
-
const response = await octokit.rest.pulls.getReviewComment({
|
|
277
|
-
owner,
|
|
278
|
-
repo,
|
|
279
|
-
comment_id: commentId,
|
|
280
|
-
});
|
|
281
|
-
const normalized = normalizeGithubReviewComment(response.data);
|
|
282
|
-
if (normalized !== undefined) {
|
|
283
|
-
comments.push(normalized);
|
|
284
|
-
}
|
|
285
|
-
} catch {
|
|
286
|
-
// Deleted or otherwise unreadable: that finding simply has no
|
|
287
|
-
// prior text to judge, which is the same as it not being there.
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
return comments;
|
|
291
|
-
},
|
|
292
|
-
};
|
|
293
|
-
}
|
|
299
|
+
/** Cap on Origin comment pages pulled per PR (100 comments per page). */
|
|
300
|
+
const ORIGIN_COMMENTS_MAX_PAGES = 20;
|
|
301
|
+
const ORIGIN_COMMENTS_PAGE_SIZE = 100;
|
|
302
|
+
|
|
303
|
+
type GithubThreadCommentNode = {
|
|
304
|
+
databaseId?: number | null;
|
|
305
|
+
body?: string | null;
|
|
306
|
+
author?: { login?: string | null; __typename?: string | null } | null;
|
|
307
|
+
originalCommit?: { oid?: string | null } | null;
|
|
308
|
+
};
|
|
294
309
|
|
|
295
310
|
type GithubReviewThreadNode = {
|
|
296
311
|
id?: string;
|
|
297
312
|
isResolved?: boolean;
|
|
313
|
+
path?: string | null;
|
|
314
|
+
line?: number | null;
|
|
315
|
+
originalLine?: number | null;
|
|
316
|
+
startLine?: number | null;
|
|
317
|
+
originalStartLine?: number | null;
|
|
298
318
|
comments?: {
|
|
299
|
-
nodes?: Array<
|
|
319
|
+
nodes?: Array<GithubThreadCommentNode | null>;
|
|
300
320
|
};
|
|
301
321
|
};
|
|
302
322
|
|
|
@@ -318,112 +338,185 @@ type GithubResolveThreadMutation = {
|
|
|
318
338
|
};
|
|
319
339
|
|
|
320
340
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
* `
|
|
341
|
+
* Repo-scope header for GraphQL calls through the Cursor github-proxy.
|
|
342
|
+
*
|
|
343
|
+
* The proxy authorizes each call from `x-cursor-github-repos`, which the
|
|
344
|
+
* channel Octokit derives from REST URLs (`/repos/{owner}/{repo}/…`).
|
|
345
|
+
* GraphQL posts to `/graphql` — no repo in the URL — so without this
|
|
346
|
+
* explicit header every GraphQL call is rejected in proxy mode. Harmless
|
|
347
|
+
* against api.github.com, which ignores unknown headers.
|
|
326
348
|
*/
|
|
327
|
-
|
|
328
|
-
github:
|
|
329
|
-
|
|
349
|
+
function githubGraphqlScopeHeaders(repo: string): Record<string, string> {
|
|
350
|
+
return { "x-cursor-github-repos": repo.toLowerCase() };
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* GitHub review thread → {@link ListedReviewComment} (its opening comment).
|
|
355
|
+
*
|
|
356
|
+
* Prefers the `original*` line fields — the position as of the review the
|
|
357
|
+
* thread belongs to. `line` drifts as the PR gains commits, so a caller
|
|
358
|
+
* correlating a comment with the review that produced it needs the original
|
|
359
|
+
* position, the same fields Bugbot carries on `PullRequestCommentOutput`.
|
|
360
|
+
*/
|
|
361
|
+
export function listedCommentFromGithubThread(
|
|
362
|
+
thread: GithubReviewThreadNode
|
|
363
|
+
): ListedReviewComment | undefined {
|
|
364
|
+
const opener = thread.comments?.nodes?.[0];
|
|
365
|
+
if (
|
|
366
|
+
thread.id === undefined ||
|
|
367
|
+
thread.id === "" ||
|
|
368
|
+
opener === null ||
|
|
369
|
+
opener === undefined ||
|
|
370
|
+
opener.databaseId === undefined ||
|
|
371
|
+
opener.databaseId === null ||
|
|
372
|
+
typeof opener.body !== "string" ||
|
|
373
|
+
typeof thread.path !== "string" ||
|
|
374
|
+
thread.path === ""
|
|
375
|
+
) {
|
|
376
|
+
return undefined;
|
|
377
|
+
}
|
|
378
|
+
// Take both lines from the same position set. Mixing them (original end
|
|
379
|
+
// line with the drifted current start line) would describe a range that
|
|
380
|
+
// never existed in either revision.
|
|
381
|
+
const original = thread.originalLine ?? undefined;
|
|
382
|
+
const endLine = original ?? thread.line ?? undefined;
|
|
383
|
+
if (endLine === undefined) {
|
|
384
|
+
return undefined;
|
|
385
|
+
}
|
|
386
|
+
const startLine =
|
|
387
|
+
(original === undefined ? thread.startLine : thread.originalStartLine) ??
|
|
388
|
+
endLine;
|
|
389
|
+
const commitSha = opener.originalCommit?.oid ?? undefined;
|
|
390
|
+
const authorLogin = opener.author?.login ?? undefined;
|
|
391
|
+
const authorType = opener.author?.__typename ?? undefined;
|
|
330
392
|
return {
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
393
|
+
commentId: String(opener.databaseId),
|
|
394
|
+
numericCommentId: opener.databaseId,
|
|
395
|
+
threadId: thread.id,
|
|
396
|
+
resolved: thread.isResolved === true,
|
|
397
|
+
file: thread.path,
|
|
398
|
+
startLine,
|
|
399
|
+
endLine,
|
|
400
|
+
body: opener.body,
|
|
401
|
+
...(commitSha === undefined ? {} : { commitSha }),
|
|
402
|
+
...(authorLogin === undefined ? {} : { authorLogin }),
|
|
403
|
+
...(authorType === undefined ? {} : { authorIsBot: authorType === "Bot" }),
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Lists the PR's inline review threads (their opening comments) through the
|
|
409
|
+
* host GitHub client (Cursor account lease, App installation token, or
|
|
410
|
+
* PAT). One paged GraphQL query yields, per thread: the resolvable thread
|
|
411
|
+
* node id, its resolution state, the opener's body/position, and the commit
|
|
412
|
+
* it was filed against — everything a Bugbot-style re-review needs.
|
|
413
|
+
*/
|
|
414
|
+
export function createHostGithubReviewCommentLister(
|
|
415
|
+
github: HostGitHubClient,
|
|
416
|
+
log?: ReviewCommentLog
|
|
417
|
+
): ReviewCommentListerImplementation {
|
|
418
|
+
return {
|
|
419
|
+
async listReviewComments({ target, signal }) {
|
|
336
420
|
const [owner, repo] = target.repo.split("/", 2);
|
|
337
421
|
if (owner === undefined || repo === undefined || repo === "") {
|
|
338
|
-
|
|
422
|
+
log?.(`github list: unparseable owner/repo "${target.repo}"`);
|
|
423
|
+
return [];
|
|
339
424
|
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
let cursor: string | null = null;
|
|
350
|
-
for (let page = 0; page < REVIEW_THREADS_MAX_PAGES; page++) {
|
|
351
|
-
signal?.throwIfAborted();
|
|
352
|
-
const response = (await octokit.graphql(REVIEW_THREADS_FOR_PR_QUERY, {
|
|
425
|
+
const octokit = await github.getOctokit();
|
|
426
|
+
const comments: ListedReviewComment[] = [];
|
|
427
|
+
let threadCount = 0;
|
|
428
|
+
let cursor: string | null = null;
|
|
429
|
+
for (let page = 0; page < REVIEW_THREADS_MAX_PAGES; page++) {
|
|
430
|
+
signal?.throwIfAborted();
|
|
431
|
+
const response = (await octokit.graphql(
|
|
432
|
+
REVIEW_THREAD_COMMENTS_FOR_PR_QUERY,
|
|
433
|
+
{
|
|
353
434
|
owner,
|
|
354
435
|
repo,
|
|
355
436
|
number: target.prNumber,
|
|
356
437
|
cursor,
|
|
357
|
-
|
|
358
|
-
const reviewThreads = response.repository?.pullRequest?.reviewThreads;
|
|
359
|
-
for (const thread of reviewThreads?.nodes ?? []) {
|
|
360
|
-
if (thread?.id === undefined || thread.id === "") {
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
for (const comment of thread.comments?.nodes ?? []) {
|
|
364
|
-
const databaseId = comment?.databaseId;
|
|
365
|
-
if (
|
|
366
|
-
databaseId !== undefined &&
|
|
367
|
-
databaseId !== null &&
|
|
368
|
-
wanted.has(databaseId) &&
|
|
369
|
-
!matched.has(databaseId)
|
|
370
|
-
) {
|
|
371
|
-
matched.set(databaseId, {
|
|
372
|
-
threadId: thread.id,
|
|
373
|
-
isResolved: thread.isResolved === true,
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
}
|
|
438
|
+
headers: githubGraphqlScopeHeaders(target.repo),
|
|
377
439
|
}
|
|
378
|
-
|
|
379
|
-
|
|
440
|
+
)) as GithubReviewThreadsQuery;
|
|
441
|
+
const reviewThreads = response.repository?.pullRequest?.reviewThreads;
|
|
442
|
+
for (const thread of reviewThreads?.nodes ?? []) {
|
|
443
|
+
if (thread === null || thread === undefined) {
|
|
444
|
+
continue;
|
|
380
445
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
446
|
+
threadCount += 1;
|
|
447
|
+
const listed = listedCommentFromGithubThread(thread);
|
|
448
|
+
if (listed !== undefined) {
|
|
449
|
+
comments.push(listed);
|
|
384
450
|
}
|
|
385
|
-
cursor = pageInfo.endCursor;
|
|
386
451
|
}
|
|
452
|
+
const pageInfo = reviewThreads?.pageInfo;
|
|
453
|
+
if (pageInfo?.hasNextPage !== true || !pageInfo.endCursor) {
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
cursor = pageInfo.endCursor;
|
|
457
|
+
}
|
|
458
|
+
log?.(
|
|
459
|
+
`github list: ${target.repo}#${target.prNumber} has ${threadCount} review thread(s), ${comments.length} with a normalizable opening comment`
|
|
460
|
+
);
|
|
461
|
+
return comments;
|
|
462
|
+
},
|
|
463
|
+
};
|
|
464
|
+
}
|
|
387
465
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
466
|
+
/**
|
|
467
|
+
* Resolves inline review threads by GraphQL thread node id through the host
|
|
468
|
+
* GitHub client (Cursor account lease, App installation token, or PAT) —
|
|
469
|
+
* the id the lister already returned, so no comment→thread mapping pass is
|
|
470
|
+
* needed. Same mutation as Bugbot's `resolveReviewThreadForComment`.
|
|
471
|
+
*/
|
|
472
|
+
export function createHostGithubReviewThreadResolver(
|
|
473
|
+
github: HostGitHubClient,
|
|
474
|
+
log?: ReviewCommentLog
|
|
475
|
+
): ReviewThreadResolverImplementation {
|
|
476
|
+
return {
|
|
477
|
+
async resolveReviewThreads({ target, threadIds, signal }) {
|
|
478
|
+
const uniqueIds = [...new Set(threadIds.filter((id) => id !== ""))];
|
|
479
|
+
if (uniqueIds.length === 0) {
|
|
480
|
+
return skippedResolve("no threads to resolve");
|
|
481
|
+
}
|
|
482
|
+
let resolved = 0;
|
|
483
|
+
let failed = 0;
|
|
484
|
+
try {
|
|
485
|
+
const octokit = await github.getOctokit();
|
|
486
|
+
for (const threadId of uniqueIds) {
|
|
398
487
|
signal?.throwIfAborted();
|
|
399
488
|
try {
|
|
400
489
|
const mutation = (await octokit.graphql(
|
|
401
490
|
RESOLVE_REVIEW_THREAD_MUTATION,
|
|
402
|
-
{
|
|
491
|
+
{
|
|
492
|
+
threadId,
|
|
493
|
+
headers: githubGraphqlScopeHeaders(target.repo),
|
|
494
|
+
}
|
|
403
495
|
)) as GithubResolveThreadMutation;
|
|
404
496
|
if (mutation.resolveReviewThread?.thread?.isResolved === true) {
|
|
405
497
|
resolved += 1;
|
|
498
|
+
log?.(`github resolve: thread ${threadId} resolved`);
|
|
406
499
|
} else {
|
|
407
500
|
failed += 1;
|
|
501
|
+
log?.(
|
|
502
|
+
`github resolve: thread ${threadId} mutation did not mark the thread resolved`
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
} catch (error) {
|
|
506
|
+
if (signal?.aborted) {
|
|
507
|
+
throw error;
|
|
408
508
|
}
|
|
409
|
-
} catch {
|
|
410
509
|
failed += 1;
|
|
510
|
+
log?.(
|
|
511
|
+
`github resolve: thread ${threadId} failed: ${error instanceof Error ? error.message : String(error)}`
|
|
512
|
+
);
|
|
411
513
|
}
|
|
412
514
|
}
|
|
413
|
-
|
|
414
|
-
const alreadyResolved = new Set(
|
|
415
|
-
[...matched.values()]
|
|
416
|
-
.filter((thread) => thread.isResolved)
|
|
417
|
-
.map((thread) => thread.threadId)
|
|
418
|
-
).size;
|
|
419
|
-
const notFound = wanted.size - matched.size;
|
|
420
515
|
return {
|
|
421
516
|
requested: uniqueIds.length,
|
|
422
517
|
resolved,
|
|
423
|
-
alreadyResolved,
|
|
424
|
-
notFound,
|
|
425
518
|
failed,
|
|
426
|
-
detail: `resolved ${resolved} of ${
|
|
519
|
+
detail: `resolved ${resolved} of ${uniqueIds.length} thread(s) on ${target.repo}#${target.prNumber} via host GitHub (${failed} failed)`,
|
|
427
520
|
};
|
|
428
521
|
} catch (error) {
|
|
429
522
|
if (signal?.aborted) {
|
|
@@ -431,10 +524,8 @@ export function createHostGithubReviewThreadResolver(
|
|
|
431
524
|
}
|
|
432
525
|
return {
|
|
433
526
|
requested: uniqueIds.length,
|
|
434
|
-
resolved
|
|
435
|
-
|
|
436
|
-
notFound: 0,
|
|
437
|
-
failed: uniqueIds.length,
|
|
527
|
+
resolved,
|
|
528
|
+
failed: uniqueIds.length - resolved,
|
|
438
529
|
detail: `host GitHub thread resolve failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
439
530
|
};
|
|
440
531
|
}
|
|
@@ -442,8 +533,8 @@ export function createHostGithubReviewThreadResolver(
|
|
|
442
533
|
};
|
|
443
534
|
}
|
|
444
535
|
|
|
445
|
-
const
|
|
446
|
-
query
|
|
536
|
+
const REVIEW_THREAD_COMMENTS_FOR_PR_QUERY = `
|
|
537
|
+
query ReviewThreadCommentsForPr(
|
|
447
538
|
$owner: String!
|
|
448
539
|
$repo: String!
|
|
449
540
|
$number: Int!
|
|
@@ -455,8 +546,18 @@ query ReviewThreadsForPr(
|
|
|
455
546
|
nodes {
|
|
456
547
|
id
|
|
457
548
|
isResolved
|
|
458
|
-
|
|
459
|
-
|
|
549
|
+
path
|
|
550
|
+
line
|
|
551
|
+
originalLine
|
|
552
|
+
startLine
|
|
553
|
+
originalStartLine
|
|
554
|
+
comments(first: 1) {
|
|
555
|
+
nodes {
|
|
556
|
+
databaseId
|
|
557
|
+
body
|
|
558
|
+
author { login __typename }
|
|
559
|
+
originalCommit { oid }
|
|
560
|
+
}
|
|
460
561
|
}
|
|
461
562
|
}
|
|
462
563
|
pageInfo { hasNextPage endCursor }
|
|
@@ -474,46 +575,241 @@ mutation ResolveReviewThread($threadId: ID!) {
|
|
|
474
575
|
}
|
|
475
576
|
`;
|
|
476
577
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
578
|
+
const GITHUB_VIEWER_LOGIN_QUERY = `
|
|
579
|
+
query ViewerLogin {
|
|
580
|
+
viewer { login }
|
|
581
|
+
}
|
|
582
|
+
`;
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* The login the bound GitHub client itself acts as — the identity its posts
|
|
586
|
+
* appear under. Works for installation tokens too (GraphQL `viewer` returns
|
|
587
|
+
* the app's bot, e.g. `cursor[bot]`), so a reader can trust comments whose
|
|
588
|
+
* author is provably the same identity it posts with, across every
|
|
589
|
+
* environment's app (prod/staging/cloud-dev/custom) without hardcoding.
|
|
590
|
+
* `repo` scopes the call through the Cursor github-proxy (the minted token
|
|
591
|
+
* — and so the viewer — is per-repo there). Best-effort: `undefined` when
|
|
592
|
+
* the lookup fails.
|
|
593
|
+
*/
|
|
594
|
+
export async function fetchGithubSelfLogin(
|
|
595
|
+
github: HostGitHubClient,
|
|
596
|
+
args: { repo: string; signal?: AbortSignal; log?: ReviewCommentLog }
|
|
597
|
+
): Promise<string | undefined> {
|
|
598
|
+
try {
|
|
599
|
+
const octokit = await github.getOctokit();
|
|
600
|
+
args.signal?.throwIfAborted();
|
|
601
|
+
const response = (await octokit.graphql(GITHUB_VIEWER_LOGIN_QUERY, {
|
|
602
|
+
headers: githubGraphqlScopeHeaders(args.repo),
|
|
603
|
+
})) as {
|
|
604
|
+
viewer?: { login?: string | null } | null;
|
|
605
|
+
};
|
|
606
|
+
const login = response.viewer?.login;
|
|
607
|
+
return typeof login === "string" && login !== "" ? login : undefined;
|
|
608
|
+
} catch (error) {
|
|
609
|
+
if (args.signal?.aborted) {
|
|
610
|
+
throw error;
|
|
611
|
+
}
|
|
612
|
+
args.log?.(
|
|
613
|
+
`github viewer lookup failed: ${error instanceof Error ? error.message : String(error)}`
|
|
614
|
+
);
|
|
615
|
+
return undefined;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
type OriginThreadJson = {
|
|
620
|
+
id?: string;
|
|
621
|
+
path?: string;
|
|
622
|
+
startLine?: number;
|
|
623
|
+
endLine?: number;
|
|
624
|
+
resolvedAt?: string;
|
|
625
|
+
version?: { headSha?: string };
|
|
485
626
|
};
|
|
486
627
|
|
|
487
628
|
/**
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
* Prefers the `original_*` fields — the path/lines/commit as of the review
|
|
491
|
-
* the comment belongs to. `line` drifts as the PR gains commits, so a
|
|
492
|
-
* caller correlating a comment with the review that produced it needs the
|
|
493
|
-
* original position, the same fields Bugbot carries on
|
|
494
|
-
* `PullRequestCommentOutput`.
|
|
629
|
+
* Public `OriginActor` proto3 JSON: a `user` / `app` / `serviceAccount`
|
|
630
|
+
* oneof (see `origin_actor.proto`).
|
|
495
631
|
*/
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
632
|
+
type OriginActorJson = {
|
|
633
|
+
user?: { id?: string; email?: string };
|
|
634
|
+
app?: { id?: string; slug?: string };
|
|
635
|
+
serviceAccount?: { id?: string };
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
type OriginCommentJson = {
|
|
639
|
+
id?: string;
|
|
640
|
+
body?: string;
|
|
641
|
+
thread?: OriginThreadJson;
|
|
642
|
+
author?: OriginActorJson;
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
type OriginListCommentsJson = {
|
|
646
|
+
comments?: Array<OriginCommentJson | null>;
|
|
647
|
+
nextPageToken?: string;
|
|
648
|
+
};
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Origin public comment → {@link ListedReviewComment}. Only line-anchored
|
|
652
|
+
* threads qualify (general-discussion and file-level threads carry no
|
|
653
|
+
* position a review finding can be pinned to).
|
|
654
|
+
*/
|
|
655
|
+
export function listedCommentFromOriginComment(
|
|
656
|
+
comment: OriginCommentJson
|
|
657
|
+
): ListedReviewComment | undefined {
|
|
658
|
+
const thread = comment.thread;
|
|
659
|
+
if (
|
|
660
|
+
typeof comment.id !== "string" ||
|
|
661
|
+
comment.id === "" ||
|
|
662
|
+
typeof comment.body !== "string" ||
|
|
663
|
+
thread === undefined ||
|
|
664
|
+
typeof thread.id !== "string" ||
|
|
665
|
+
thread.id === "" ||
|
|
666
|
+
typeof thread.path !== "string" ||
|
|
667
|
+
thread.path === "" ||
|
|
668
|
+
typeof thread.startLine !== "number" ||
|
|
669
|
+
thread.startLine <= 0
|
|
670
|
+
) {
|
|
505
671
|
return undefined;
|
|
506
672
|
}
|
|
507
|
-
const startLine =
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
673
|
+
const startLine = thread.startLine;
|
|
674
|
+
const endLine =
|
|
675
|
+
typeof thread.endLine === "number" && thread.endLine >= startLine
|
|
676
|
+
? thread.endLine
|
|
677
|
+
: startLine;
|
|
678
|
+
const commitSha = thread.version?.headSha;
|
|
679
|
+
const author = comment.author;
|
|
680
|
+
const authorLogin = author?.app?.slug ?? author?.user?.email;
|
|
681
|
+
// App and service-account actors are machine identities; only a `user`
|
|
682
|
+
// actor is a human PR participant.
|
|
683
|
+
const authorIsBot =
|
|
684
|
+
author === undefined
|
|
685
|
+
? undefined
|
|
686
|
+
: author.app !== undefined || author.serviceAccount !== undefined;
|
|
687
|
+
const authorAppId = author?.app?.id;
|
|
511
688
|
return {
|
|
512
|
-
|
|
513
|
-
|
|
689
|
+
commentId: comment.id,
|
|
690
|
+
threadId: thread.id,
|
|
691
|
+
resolved: typeof thread.resolvedAt === "string" && thread.resolvedAt !== "",
|
|
692
|
+
file: thread.path,
|
|
514
693
|
startLine,
|
|
515
694
|
endLine,
|
|
516
695
|
body: comment.body,
|
|
696
|
+
...(typeof commitSha === "string" && commitSha !== "" ? { commitSha } : {}),
|
|
697
|
+
...(typeof authorLogin === "string" && authorLogin !== ""
|
|
698
|
+
? { authorLogin }
|
|
699
|
+
: {}),
|
|
700
|
+
...(authorIsBot === undefined ? {} : { authorIsBot }),
|
|
701
|
+
...(typeof authorAppId === "string" && authorAppId !== ""
|
|
702
|
+
? { authorAppId }
|
|
703
|
+
: {}),
|
|
704
|
+
};
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* Lists the PR's inline review threads through the Origin public REST API
|
|
709
|
+
* (`GET …/pulls/{n}/comments`, paged). The flattened comment list is
|
|
710
|
+
* ordered by creation time, so the first comment seen per thread is the
|
|
711
|
+
* thread opener; replies are dropped.
|
|
712
|
+
*/
|
|
713
|
+
export function createHostOriginReviewCommentLister(
|
|
714
|
+
origin: HostOriginReviewClient,
|
|
715
|
+
log?: ReviewCommentLog
|
|
716
|
+
): ReviewCommentListerImplementation {
|
|
717
|
+
return {
|
|
718
|
+
async listReviewComments({ target, signal }) {
|
|
719
|
+
const [owner, repo] = target.repo.split("/", 2);
|
|
720
|
+
if (owner === undefined || repo === undefined || repo === "") {
|
|
721
|
+
log?.(`origin list: unparseable owner/repo "${target.repo}"`);
|
|
722
|
+
return [];
|
|
723
|
+
}
|
|
724
|
+
const basePath = `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${target.prNumber}/comments`;
|
|
725
|
+
const comments: ListedReviewComment[] = [];
|
|
726
|
+
const seenThreads = new Set<string>();
|
|
727
|
+
let totalComments = 0;
|
|
728
|
+
let pageToken = "";
|
|
729
|
+
for (let page = 0; page < ORIGIN_COMMENTS_MAX_PAGES; page++) {
|
|
730
|
+
signal?.throwIfAborted();
|
|
731
|
+
const query =
|
|
732
|
+
pageToken === ""
|
|
733
|
+
? `?pageSize=${ORIGIN_COMMENTS_PAGE_SIZE}`
|
|
734
|
+
: `?pageSize=${ORIGIN_COMMENTS_PAGE_SIZE}&pageToken=${encodeURIComponent(pageToken)}`;
|
|
735
|
+
const response = (await origin.request({
|
|
736
|
+
method: "GET",
|
|
737
|
+
path: `${basePath}${query}`,
|
|
738
|
+
})) as OriginListCommentsJson | null | undefined;
|
|
739
|
+
for (const comment of response?.comments ?? []) {
|
|
740
|
+
if (comment === null || comment === undefined) {
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
totalComments += 1;
|
|
744
|
+
const listed = listedCommentFromOriginComment(comment);
|
|
745
|
+
if (listed === undefined || seenThreads.has(listed.threadId)) {
|
|
746
|
+
// Not line-anchored, or a reply on a thread whose opener was
|
|
747
|
+
// already taken (the list is oldest-first).
|
|
748
|
+
continue;
|
|
749
|
+
}
|
|
750
|
+
seenThreads.add(listed.threadId);
|
|
751
|
+
comments.push(listed);
|
|
752
|
+
}
|
|
753
|
+
pageToken = response?.nextPageToken ?? "";
|
|
754
|
+
if (pageToken === "") {
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
log?.(
|
|
759
|
+
`origin list: ${target.repo}#${target.prNumber} has ${totalComments} comment(s), ${comments.length} line-anchored thread opener(s)`
|
|
760
|
+
);
|
|
761
|
+
return comments;
|
|
762
|
+
},
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Resolves Origin comment threads through the public REST API
|
|
768
|
+
* (`PATCH …/pulls/threads/{thread_id}` with `resolved: true`).
|
|
769
|
+
*/
|
|
770
|
+
export function createHostOriginReviewThreadResolver(
|
|
771
|
+
origin: HostOriginReviewClient,
|
|
772
|
+
log?: ReviewCommentLog
|
|
773
|
+
): ReviewThreadResolverImplementation {
|
|
774
|
+
return {
|
|
775
|
+
async resolveReviewThreads({ target, threadIds, signal }) {
|
|
776
|
+
const uniqueIds = [...new Set(threadIds.filter((id) => id !== ""))];
|
|
777
|
+
if (uniqueIds.length === 0) {
|
|
778
|
+
return skippedResolve("no threads to resolve");
|
|
779
|
+
}
|
|
780
|
+
const [owner, repo] = target.repo.split("/", 2);
|
|
781
|
+
if (owner === undefined || repo === undefined || repo === "") {
|
|
782
|
+
return skippedResolve("unparseable owner/repo from PR URL");
|
|
783
|
+
}
|
|
784
|
+
let resolved = 0;
|
|
785
|
+
let failed = 0;
|
|
786
|
+
for (const threadId of uniqueIds) {
|
|
787
|
+
signal?.throwIfAborted();
|
|
788
|
+
try {
|
|
789
|
+
await origin.request({
|
|
790
|
+
method: "PATCH",
|
|
791
|
+
path: `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/threads/${encodeURIComponent(threadId)}`,
|
|
792
|
+
body: { resolved: true },
|
|
793
|
+
});
|
|
794
|
+
resolved += 1;
|
|
795
|
+
log?.(`origin resolve: thread ${threadId} resolved`);
|
|
796
|
+
} catch (error) {
|
|
797
|
+
if (signal?.aborted) {
|
|
798
|
+
throw error;
|
|
799
|
+
}
|
|
800
|
+
failed += 1;
|
|
801
|
+
log?.(
|
|
802
|
+
`origin resolve: thread ${threadId} failed: ${error instanceof Error ? error.message : String(error)}`
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
return {
|
|
807
|
+
requested: uniqueIds.length,
|
|
808
|
+
resolved,
|
|
809
|
+
failed,
|
|
810
|
+
detail: `resolved ${resolved} of ${uniqueIds.length} thread(s) on ${target.repo}#${target.prNumber} via host Origin (${failed} failed)`,
|
|
811
|
+
};
|
|
812
|
+
},
|
|
517
813
|
};
|
|
518
814
|
}
|
|
519
815
|
|
|
@@ -606,9 +902,12 @@ export function createReviewCommentPublisher(args: {
|
|
|
606
902
|
/**
|
|
607
903
|
* Posts a COMMENT-verdict Origin review through the public REST API.
|
|
608
904
|
*
|
|
609
|
-
*
|
|
610
|
-
*
|
|
611
|
-
*
|
|
905
|
+
* Inline comments post as diff-anchored threads via the review's
|
|
906
|
+
* `comments` field (`ReviewCommentInput` with an `InlineCommentAnchor`).
|
|
907
|
+
* Origin rejects the whole request with INVALID_ARGUMENT when any anchor
|
|
908
|
+
* is off the reviewed version's diff — the caller's body-only retry (the
|
|
909
|
+
* same fallback GitHub's 422 takes) then folds the findings into the
|
|
910
|
+
* review body.
|
|
612
911
|
*/
|
|
613
912
|
export function createHostOriginReviewPublisher(
|
|
614
913
|
origin: HostOriginReviewClient
|
|
@@ -879,15 +1178,20 @@ async function postReviewViaHostOrigin(
|
|
|
879
1178
|
path: `/v1/origin/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/pulls/${target.prNumber}/reviews`,
|
|
880
1179
|
body: {
|
|
881
1180
|
verdict: "comment",
|
|
882
|
-
body:
|
|
1181
|
+
body: args.message,
|
|
1182
|
+
comments: args.comments.map(toOriginReviewCommentInput),
|
|
883
1183
|
},
|
|
884
1184
|
});
|
|
1185
|
+
const inlineCommentCount = args.comments.length;
|
|
885
1186
|
return {
|
|
886
1187
|
posted: true,
|
|
887
1188
|
publisher: "host_origin",
|
|
888
|
-
mode:
|
|
889
|
-
|
|
890
|
-
|
|
1189
|
+
mode:
|
|
1190
|
+
inlineCommentCount > 0
|
|
1191
|
+
? "review_with_inline_comments"
|
|
1192
|
+
: "review_body_only",
|
|
1193
|
+
inlineCommentCount,
|
|
1194
|
+
detail: `posted Origin review on ${target.repo}#${target.prNumber} with ${inlineCommentCount} inline comment(s)`,
|
|
891
1195
|
};
|
|
892
1196
|
} catch (error) {
|
|
893
1197
|
if (args.signal?.aborted) {
|
|
@@ -899,32 +1203,41 @@ async function postReviewViaHostOrigin(
|
|
|
899
1203
|
}
|
|
900
1204
|
}
|
|
901
1205
|
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
1206
|
+
type OriginReviewCommentInput = {
|
|
1207
|
+
body: string;
|
|
1208
|
+
inline: {
|
|
1209
|
+
path: string;
|
|
1210
|
+
side: "right";
|
|
1211
|
+
startLine: number;
|
|
1212
|
+
endLine?: number;
|
|
1213
|
+
};
|
|
1214
|
+
};
|
|
1215
|
+
|
|
1216
|
+
/** Provider-neutral inline comment → Origin `ReviewCommentInput`. */
|
|
1217
|
+
function toOriginReviewCommentInput(
|
|
1218
|
+
comment: ReviewInlineComment
|
|
1219
|
+
): OriginReviewCommentInput {
|
|
1220
|
+
const startLine =
|
|
1221
|
+
comment.start_line !== undefined &&
|
|
1222
|
+
comment.start_line > 0 &&
|
|
1223
|
+
comment.start_line < comment.line
|
|
1224
|
+
? comment.start_line
|
|
1225
|
+
: comment.line;
|
|
1226
|
+
return {
|
|
1227
|
+
body: comment.body,
|
|
1228
|
+
inline: {
|
|
1229
|
+
path: comment.file,
|
|
1230
|
+
side: "right",
|
|
1231
|
+
startLine,
|
|
1232
|
+
...(startLine === comment.line ? {} : { endLine: comment.line }),
|
|
1233
|
+
},
|
|
1234
|
+
};
|
|
920
1235
|
}
|
|
921
1236
|
|
|
922
1237
|
function skippedResolve(detail: string): ResolveReviewThreadsResult {
|
|
923
1238
|
return {
|
|
924
1239
|
requested: 0,
|
|
925
1240
|
resolved: 0,
|
|
926
|
-
alreadyResolved: 0,
|
|
927
|
-
notFound: 0,
|
|
928
1241
|
failed: 0,
|
|
929
1242
|
detail,
|
|
930
1243
|
};
|