@cursor/july 0.1.68 → 0.1.74

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 (252) hide show
  1. package/AGENTS.md +17 -13
  2. package/README.md +23 -11
  3. package/dist/bin/agent-serve.js +10 -7
  4. package/dist/channels/github/api.d.ts +2 -0
  5. package/dist/channels/github/api.d.ts.map +1 -1
  6. package/dist/channels/github/api.js +2 -1
  7. package/dist/channels/github/binding.d.ts +7 -0
  8. package/dist/channels/github/binding.d.ts.map +1 -1
  9. package/dist/channels/github/binding.js +4 -0
  10. package/dist/channels/github/checks.d.ts +99 -0
  11. package/dist/channels/github/checks.d.ts.map +1 -0
  12. package/dist/channels/github/checks.js +108 -0
  13. package/dist/channels/github/cursor-account.d.ts +4 -4
  14. package/dist/channels/github/cursor-account.d.ts.map +1 -1
  15. package/dist/channels/github/cursor-account.js +7 -5
  16. package/dist/channels/github/index.d.ts +1 -0
  17. package/dist/channels/github/index.d.ts.map +1 -1
  18. package/dist/channels/github/index.js +1 -0
  19. package/dist/channels/github/types.d.ts +8 -0
  20. package/dist/channels/github/types.d.ts.map +1 -1
  21. package/dist/channels/slack/manifest.d.ts +2 -2
  22. package/dist/channels/slack/manifest.d.ts.map +1 -1
  23. package/dist/channels/slack/manifest.js +13 -11
  24. package/dist/channels/slack/types.d.ts +2 -2
  25. package/dist/channels/slack/types.d.ts.map +1 -1
  26. package/dist/connections.d.ts +17 -5
  27. package/dist/connections.d.ts.map +1 -1
  28. package/dist/connections.js +17 -5
  29. package/dist/docs/404.html +2 -2
  30. package/dist/docs/ab.html +3 -3
  31. package/dist/docs/assets/{app.C5XUTCw9.js → app.BETd-WqU.js} +1 -1
  32. package/dist/docs/assets/chunks/@localSearchIndexroot.DM5INS71.js +1 -0
  33. package/dist/docs/assets/chunks/{VPLocalSearchBox.CGDTAYHY.js → VPLocalSearchBox.wEaGEmV9.js} +1 -1
  34. package/dist/docs/assets/chunks/{theme.lPixh250.js → theme.DNDicFOP.js} +2 -2
  35. package/dist/docs/assets/{concepts.md.CqOsxbMU.js → concepts.md.BXAm6G-C.js} +1 -1
  36. package/dist/docs/assets/{guides_mcp-oauth.md.C7G7IykG.js → guides_mcp-oauth.md.CzEB6RaG.js} +1 -1
  37. package/dist/docs/assets/{reference_agent-config.md.DHkkvcEZ.js → reference_agent-config.md.BZnEKfEc.js} +3 -4
  38. package/dist/docs/assets/{reference_agent-config.md.DHkkvcEZ.lean.js → reference_agent-config.md.BZnEKfEc.lean.js} +1 -1
  39. package/dist/docs/assets/{reference_cli.md.Cl14Jfo3.js → reference_cli.md.TAaYU8br.js} +3 -3
  40. package/dist/docs/assets/{reference_cli.md.Cl14Jfo3.lean.js → reference_cli.md.TAaYU8br.lean.js} +1 -1
  41. package/dist/docs/assets/{reference_connections.md.Bwswbm6H.js → reference_connections.md.Cu3N-S3Q.js} +18 -11
  42. package/dist/docs/assets/{reference_connections.md.Bwswbm6H.lean.js → reference_connections.md.Cu3N-S3Q.lean.js} +1 -1
  43. package/dist/docs/assets/{reference_sessions.md.DBVFi2Sx.js → reference_sessions.md.B0DdlM-K.js} +1 -1
  44. package/dist/docs/assets/{reference_tools.md.Wmvb7Lob.js → reference_tools.md.DTg_kEsx.js} +1 -1
  45. package/dist/docs/assets/scaffolding-agents.md.CiGsJ1aw.js +1 -0
  46. package/dist/docs/assets/{scaffolding-agents.md.CrWSA0Ko.lean.js → scaffolding-agents.md.CiGsJ1aw.lean.js} +1 -1
  47. package/dist/docs/assets/troubleshooting.md.DQ-hYuZT.js +1 -0
  48. package/dist/docs/building-with-agents.html +3 -3
  49. package/dist/docs/concepts.html +5 -5
  50. package/dist/docs/deployment.html +3 -3
  51. package/dist/docs/evals.html +3 -3
  52. package/dist/docs/example-agents/approval-buddy.html +3 -3
  53. package/dist/docs/example-agents/benny.html +3 -3
  54. package/dist/docs/example-agents/bugbot.html +3 -3
  55. package/dist/docs/example-agents/codebase-wiki.html +3 -3
  56. package/dist/docs/example-agents/codeowners-review.html +3 -3
  57. package/dist/docs/example-agents/concierge.html +3 -3
  58. package/dist/docs/example-agents/fsd.html +3 -3
  59. package/dist/docs/example-agents/index.html +3 -3
  60. package/dist/docs/example-agents/knowledge-base.html +3 -3
  61. package/dist/docs/example-agents/oncall.html +3 -3
  62. package/dist/docs/example-agents/security-reviewer.html +3 -3
  63. package/dist/docs/example-agents/slack-agent.html +3 -3
  64. package/dist/docs/example-agents/weather-agent.html +3 -3
  65. package/dist/docs/guides/agent-to-agent.html +3 -3
  66. package/dist/docs/guides/cloud-runtime.html +3 -3
  67. package/dist/docs/guides/convert-automation.html +3 -3
  68. package/dist/docs/guides/github.html +3 -3
  69. package/dist/docs/guides/human-in-the-loop.html +3 -3
  70. package/dist/docs/guides/mcp-oauth.html +5 -5
  71. package/dist/docs/guides/opentelemetry.html +3 -3
  72. package/dist/docs/guides/slack.html +3 -3
  73. package/dist/docs/guides/webhooks.html +3 -3
  74. package/dist/docs/hashmap.json +1 -1
  75. package/dist/docs/hillclimbing.html +3 -3
  76. package/dist/docs/index.html +3 -3
  77. package/dist/docs/quickstart.html +3 -3
  78. package/dist/docs/reference/agent-config.html +5 -6
  79. package/dist/docs/reference/artifacts.html +3 -3
  80. package/dist/docs/reference/channels.html +3 -3
  81. package/dist/docs/reference/cli.html +6 -6
  82. package/dist/docs/reference/connections.html +20 -13
  83. package/dist/docs/reference/hooks.html +3 -3
  84. package/dist/docs/reference/http-api.html +3 -3
  85. package/dist/docs/reference/instructions.html +3 -3
  86. package/dist/docs/reference/playground.html +3 -3
  87. package/dist/docs/reference/project-layout.html +3 -3
  88. package/dist/docs/reference/prompt.html +3 -3
  89. package/dist/docs/reference/schedules.html +3 -3
  90. package/dist/docs/reference/sessions.html +5 -5
  91. package/dist/docs/reference/skills.html +3 -3
  92. package/dist/docs/reference/subagents.html +3 -3
  93. package/dist/docs/reference/tools.html +5 -5
  94. package/dist/docs/scaffolding-agents.html +5 -5
  95. package/dist/docs/storage.html +3 -3
  96. package/dist/docs/templates/agentic-owners.html +3 -3
  97. package/dist/docs/templates/demo.html +3 -3
  98. package/dist/docs/templates/pr-autofixer.html +3 -3
  99. package/dist/docs/templates/security-reviewer.html +3 -3
  100. package/dist/docs/templates/triage.html +3 -3
  101. package/dist/docs/troubleshooting.html +5 -5
  102. package/dist/internal/advertise-tools.d.ts +11 -6
  103. package/dist/internal/advertise-tools.d.ts.map +1 -1
  104. package/dist/internal/advertise-tools.js +63 -30
  105. package/dist/internal/cli-deploy.d.ts.map +1 -1
  106. package/dist/internal/cli-deploy.js +2 -4
  107. package/dist/internal/cli-skills.d.ts +4 -2
  108. package/dist/internal/cli-skills.d.ts.map +1 -1
  109. package/dist/internal/cli-skills.js +8 -3
  110. package/dist/internal/convert-automation/convert-workflow.d.ts.map +1 -1
  111. package/dist/internal/convert-automation/convert-workflow.js +2 -10
  112. package/dist/internal/cursor/account-mcp.d.ts +29 -3
  113. package/dist/internal/cursor/account-mcp.d.ts.map +1 -1
  114. package/dist/internal/cursor/account-mcp.js +147 -67
  115. package/dist/internal/cursor/backend-client.d.ts +11 -6
  116. package/dist/internal/cursor/backend-client.d.ts.map +1 -1
  117. package/dist/internal/cursor/backend-client.js +32 -10
  118. package/dist/internal/cursor-account-mcp-auth.d.ts +11 -0
  119. package/dist/internal/cursor-account-mcp-auth.d.ts.map +1 -1
  120. package/dist/internal/cursor-account-mcp-auth.js +69 -0
  121. package/dist/internal/deploy-client.d.ts +0 -7
  122. package/dist/internal/deploy-client.d.ts.map +1 -1
  123. package/dist/internal/deploy-client.js +2 -4
  124. package/dist/internal/deploy-manifest.d.ts +15 -24
  125. package/dist/internal/deploy-manifest.d.ts.map +1 -1
  126. package/dist/internal/deploy-manifest.js +38 -27
  127. package/dist/internal/deployment-scm-event-stream.d.ts +4 -1
  128. package/dist/internal/deployment-scm-event-stream.d.ts.map +1 -1
  129. package/dist/internal/deployment-scm-event-stream.js +15 -1
  130. package/dist/internal/discovery.d.ts.map +1 -1
  131. package/dist/internal/discovery.js +42 -10
  132. package/dist/internal/init-project.d.ts.map +1 -1
  133. package/dist/internal/init-project.js +7 -106
  134. package/dist/internal/init-scaffold.d.ts +8 -0
  135. package/dist/internal/init-scaffold.d.ts.map +1 -0
  136. package/dist/internal/init-scaffold.js +168 -0
  137. package/dist/internal/inline-stdio-mcp.d.ts +2 -0
  138. package/dist/internal/inline-stdio-mcp.d.ts.map +1 -1
  139. package/dist/internal/inline-stdio-mcp.js +10 -8
  140. package/dist/internal/install-cursor-skills.d.ts +71 -16
  141. package/dist/internal/install-cursor-skills.d.ts.map +1 -1
  142. package/dist/internal/install-cursor-skills.js +160 -48
  143. package/dist/internal/json-schema.d.ts +7 -0
  144. package/dist/internal/json-schema.d.ts.map +1 -1
  145. package/dist/internal/json-schema.js +18 -3
  146. package/dist/internal/mcp-endpoint.js +7 -7
  147. package/dist/internal/mcp-host.js +4 -2
  148. package/dist/internal/mcp-oauth.d.ts +22 -0
  149. package/dist/internal/mcp-oauth.d.ts.map +1 -1
  150. package/dist/internal/mcp-oauth.js +40 -1
  151. package/dist/internal/package-inline-stdio.d.ts.map +1 -1
  152. package/dist/internal/package-inline-stdio.js +5 -5
  153. package/dist/internal/review-comments.d.ts +97 -0
  154. package/dist/internal/review-comments.d.ts.map +1 -1
  155. package/dist/internal/review-comments.js +151 -0
  156. package/dist/internal/sanitize-mcp-tool-name.d.ts +20 -0
  157. package/dist/internal/sanitize-mcp-tool-name.d.ts.map +1 -0
  158. package/dist/internal/sanitize-mcp-tool-name.js +30 -0
  159. package/dist/internal/sdk-runner.d.ts.map +1 -1
  160. package/dist/internal/sdk-runner.js +6 -2
  161. package/dist/internal/session-engine.d.ts.map +1 -1
  162. package/dist/internal/session-engine.js +4 -6
  163. package/dist/internal/shallow-clone.d.ts +94 -39
  164. package/dist/internal/shallow-clone.d.ts.map +1 -1
  165. package/dist/internal/shallow-clone.js +188 -68
  166. package/dist/internal/terminal-style.d.ts +18 -0
  167. package/dist/internal/terminal-style.d.ts.map +1 -1
  168. package/dist/internal/terminal-style.js +46 -1
  169. package/dist/internal/workspace.d.ts +2 -0
  170. package/dist/internal/workspace.d.ts.map +1 -1
  171. package/dist/internal/workspace.js +5 -0
  172. package/dist/playground/assets/index-D_8I9TM0.js +85 -0
  173. package/dist/playground/assets/index-M3nSMc6_.css +1 -0
  174. package/dist/playground/index.html +2 -2
  175. package/dist/tools.d.ts +7 -0
  176. package/dist/tools.d.ts.map +1 -1
  177. package/dist/types.d.ts +28 -3
  178. package/dist/types.d.ts.map +1 -1
  179. package/docs/concepts.md +4 -4
  180. package/docs/guides/mcp-oauth.md +3 -1
  181. package/docs/reference/agent-config.md +11 -12
  182. package/docs/reference/cli.md +16 -8
  183. package/docs/reference/connections.md +44 -26
  184. package/docs/reference/sessions.md +2 -2
  185. package/docs/reference/tools.md +1 -1
  186. package/docs/scaffolding-agents.md +14 -6
  187. package/docs/troubleshooting.md +3 -2
  188. package/package.json +6 -1
  189. package/scripts/install-cursor-skills.mjs +36 -0
  190. package/skills/ab/SKILL.md +1 -1
  191. package/skills/create-agent/SKILL.md +13 -10
  192. package/skills/debug/SKILL.md +3 -2
  193. package/skills/evals/SKILL.md +1 -1
  194. package/skills/framework-map/SKILL.md +7 -7
  195. package/skills/github/SKILL.md +1 -1
  196. package/skills/hillclimb/SKILL.md +1 -1
  197. package/skills/mcp-auth/SKILL.md +9 -7
  198. package/skills/otel/SKILL.md +1 -1
  199. package/skills/setup-slack/SKILL.md +1 -1
  200. package/src/bin/agent-serve.ts +10 -7
  201. package/src/channels/github/api.ts +6 -1
  202. package/src/channels/github/binding.ts +21 -0
  203. package/src/channels/github/checks.ts +179 -0
  204. package/src/channels/github/cursor-account.ts +9 -6
  205. package/src/channels/github/index.ts +1 -0
  206. package/src/channels/github/types.ts +8 -0
  207. package/src/channels/slack/manifest.ts +8 -10
  208. package/src/channels/slack/types.ts +2 -2
  209. package/src/connections.ts +17 -5
  210. package/src/internal/advertise-tools.ts +72 -23
  211. package/src/internal/cli-deploy.ts +4 -15
  212. package/src/internal/cli-skills.ts +10 -2
  213. package/src/internal/convert-automation/convert-workflow.ts +2 -11
  214. package/src/internal/cursor/account-mcp.ts +208 -73
  215. package/src/internal/cursor/backend-client.ts +45 -11
  216. package/src/internal/cursor-account-mcp-auth.ts +83 -0
  217. package/src/internal/deploy-client.ts +0 -10
  218. package/src/internal/deploy-manifest.ts +33 -39
  219. package/src/internal/deployment-scm-event-stream.ts +17 -1
  220. package/src/internal/discovery.ts +47 -3
  221. package/src/internal/init-project.ts +7 -133
  222. package/src/internal/init-scaffold.ts +176 -0
  223. package/src/internal/inline-stdio-mcp.ts +13 -0
  224. package/src/internal/install-cursor-skills.ts +204 -49
  225. package/src/internal/json-schema.ts +24 -3
  226. package/src/internal/mcp-endpoint.ts +6 -0
  227. package/src/internal/mcp-host.ts +4 -0
  228. package/src/internal/mcp-oauth.ts +55 -1
  229. package/src/internal/package-inline-stdio.ts +5 -1
  230. package/src/internal/review-comments.ts +245 -0
  231. package/src/internal/sanitize-mcp-tool-name.ts +33 -0
  232. package/src/internal/sdk-runner.ts +6 -3
  233. package/src/internal/session-engine.ts +7 -0
  234. package/src/internal/shallow-clone.ts +293 -105
  235. package/src/internal/terminal-style.ts +67 -1
  236. package/src/internal/workspace.ts +6 -0
  237. package/src/tools.ts +7 -0
  238. package/src/types.ts +32 -4
  239. package/templates/agentic-owners/agent/agent.ts +3 -0
  240. package/templates/demo/agent/agent.ts +3 -0
  241. package/templates/security-reviewer/agent/agent.ts +3 -0
  242. package/templates/triage/agent/agent.ts +3 -0
  243. package/dist/docs/assets/chunks/@localSearchIndexroot.DvUR3lv9.js +0 -1
  244. package/dist/docs/assets/scaffolding-agents.md.CrWSA0Ko.js +0 -1
  245. package/dist/docs/assets/troubleshooting.md.CuVztCKs.js +0 -1
  246. package/dist/playground/assets/index-CoL7xCJl.css +0 -1
  247. package/dist/playground/assets/index-yxs1heea.js +0 -85
  248. /package/dist/docs/assets/{concepts.md.CqOsxbMU.lean.js → concepts.md.BXAm6G-C.lean.js} +0 -0
  249. /package/dist/docs/assets/{guides_mcp-oauth.md.C7G7IykG.lean.js → guides_mcp-oauth.md.CzEB6RaG.lean.js} +0 -0
  250. /package/dist/docs/assets/{reference_sessions.md.DBVFi2Sx.lean.js → reference_sessions.md.B0DdlM-K.lean.js} +0 -0
  251. /package/dist/docs/assets/{reference_tools.md.Wmvb7Lob.lean.js → reference_tools.md.DTg_kEsx.lean.js} +0 -0
  252. /package/dist/docs/assets/{troubleshooting.md.CuVztCKs.lean.js → troubleshooting.md.DQ-hYuZT.lean.js} +0 -0
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Shallow GitHub PR checkout for SDK agents that review a PR's code.
2
+ * Shallow SCM PR checkout for SDK agents that review a PR's code.
3
3
  *
4
4
  * Mirrors Bugbot's `shallow_fetch` prefetch strategy
5
5
  * (`backend/crates/napi_bugbot/src/temp_clone.rs`): instead of cloning the
@@ -10,11 +10,19 @@
10
10
  * clone because its tools stream objects on demand; SDK agents read a real
11
11
  * working tree, so we materialize the head checkout instead.
12
12
  *
13
- * Auth also mirrors Bugbot's provider model (`IGitProvider.getAccessToken`
14
- * token handed straight to git): the clone takes one explicit repo-scoped
15
- * bearer token. The default source is the serve host's Cursor-account
16
- * GitHub lease the same backend `GithubAccessService` mint Bugbot uses —
17
- * which `CursorGithubCredentialProvider` installs as `GH_TOKEN` for child
13
+ * SCM support follows Bugbot's provider seam (`IGitProvider.getCloneTarget`
14
+ * / the Rust `clone_url` dispatch): everything provider-specific remote
15
+ * URL shape, git credential username convention, PR head ref layout — lives
16
+ * in one {@link ScmCloneTarget} produced by {@link resolveScmCloneTarget}.
17
+ * Supporting another SCM (GitLab, Bitbucket, …) means adding a resolver
18
+ * case and a default credential source; the fetch/verify/checkout machinery
19
+ * is provider-agnostic.
20
+ *
21
+ * Auth also mirrors Bugbot (`IGitProvider.getAccessToken` → token handed
22
+ * straight to git): the clone takes one explicit repo-scoped bearer token.
23
+ * For GitHub the default source is the serve host's Cursor-account lease —
24
+ * the same backend `GithubAccessService` mint Bugbot uses — which
25
+ * `CursorGithubCredentialProvider` installs as `GH_TOKEN` for child
18
26
  * processes. Where Bugbot embeds the token in the clone URL, this module
19
27
  * serves it through an inline credential helper that reads a child-process
20
28
  * env var, so the token never lands in argv or in `.git/config` inside a
@@ -24,34 +32,90 @@
24
32
  * the security reviewer's `prepare_review` stage). Consumed via relative
25
33
  * source imports, following `tenant-mcp/run-mcp-registry.ts`.
26
34
  */
27
- export type ShallowPrCheckout = {
28
- /** Directory containing the PR head working tree (detached at headSha). */
29
- checkoutDir: string;
30
- headSha: string;
31
- /** True when the merge-base commit was also fetched (enables local diffs). */
32
- baseFetched: boolean;
33
- /** How the head commit was obtained. */
34
- headSource: "sha_fetch" | "pr_ref_fetch";
35
+ /** SCMs with shallow-clone support. */
36
+ export type ScmProvider = "github";
37
+ /**
38
+ * Everything git needs to clone one SCM's PR head. Provider-specific
39
+ * conventions live here and nowhere else.
40
+ */
41
+ export type ScmCloneTarget = {
42
+ provider: ScmProvider;
43
+ /** `owner/name` — used for logs and error messages. */
44
+ repo: string;
45
+ prNumber: number;
46
+ /** HTTPS remote to fetch from. */
47
+ remoteUrl: string;
48
+ /** Username paired with the bearer token for git-over-HTTPS basic auth. */
49
+ credentialUsername: string;
50
+ /**
51
+ * Server-advertised PR head ref (e.g. GitHub `refs/pull/<n>/head`,
52
+ * GitLab `refs/merge-requests/<n>/head`) — the fallback when the pinned
53
+ * SHA cannot be fetched directly.
54
+ */
55
+ prHeadRef: string;
35
56
  };
36
- /** Repo-scoped bearer for git-over-HTTPS (installation token or PAT). */
57
+ /**
58
+ * Resolve a PR URL to its clone target, or `undefined` when the SCM has no
59
+ * shallow-clone support (callers then review on their fallback checkout —
60
+ * e.g. Origin PRs, where the host checkout already is the reviewed repo).
61
+ */
62
+ export declare function resolveScmCloneTarget(prUrl: string): ScmCloneTarget | undefined;
63
+ /** Repo-scoped bearer for git-over-HTTPS. */
37
64
  export type ShallowCloneAuth = {
38
65
  token: string;
39
66
  };
40
67
  /**
41
- * Default clone credential: the serve host's Cursor-account GitHub lease.
68
+ * Default GitHub clone credential: the serve host's Cursor-account lease.
42
69
  * `CursorGithubCredentialProvider` mints it repo-scoped from the backend and
43
70
  * keeps `GH_TOKEN` refreshed for child processes; `GITHUB_TOKEN` covers
44
71
  * local/CI runs that export the conventional variable instead.
45
72
  */
46
73
  export declare function serveHostGithubAuth(env?: NodeJS.ProcessEnv): ShallowCloneAuth | undefined;
74
+ export type CommitRangeDiff = {
75
+ status: "ok";
76
+ diff: string;
77
+ } | {
78
+ status: "unavailable";
79
+ reason: string;
80
+ };
47
81
  /**
48
- * Create a fresh shallow checkout of a GitHub PR head at `checkoutDir`.
82
+ * Diff two commits inside an existing shallow PR checkout, fetching either
83
+ * end on demand when the shallow history does not already contain it.
84
+ *
85
+ * Lives here because it needs the same authenticated git the clone uses —
86
+ * a `--depth=1` checkout usually lacks the older commit, so reading a range
87
+ * means another credentialed fetch. Never throws: every failure becomes an
88
+ * `unavailable` reason the caller can act on or surface.
89
+ */
90
+ export declare function tryDiffCommitRange(args: {
91
+ /** Existing checkout to run git in (see {@link createShallowPrCheckout}). */
92
+ checkoutDir: string;
93
+ /** The checkout's clone target; supplies the remote's ref + auth conventions. */
94
+ target: ScmCloneTarget;
95
+ from: string;
96
+ to: string;
97
+ /** Restrict the diff to one path when set. */
98
+ file?: string | undefined;
99
+ /** Fetch credential; defaults to the target provider's credential source. */
100
+ auth?: ShallowCloneAuth | undefined;
101
+ }): Promise<CommitRangeDiff>;
102
+ export type ShallowPrCheckout = {
103
+ /** Directory containing the PR head working tree (detached at headSha). */
104
+ checkoutDir: string;
105
+ headSha: string;
106
+ /** True when the merge-base commit was also fetched (enables local diffs). */
107
+ baseFetched: boolean;
108
+ /** How the head commit was obtained. */
109
+ headSource: "sha_fetch" | "pr_ref_fetch";
110
+ };
111
+ /**
112
+ * Create a fresh shallow checkout of a PR head at `checkoutDir`.
49
113
  *
50
114
  * Fetch order (both single depth-1 round-trips):
51
115
  * 1. Fetch `headSha` (and `baseSha` when known) directly — GitHub advertises
52
116
  * `allow-reachable-sha1-in-want`, and this pins the exact reviewed commit
53
117
  * the way Bugbot's `shallow_fetch` does.
54
- * 2. Fall back to `refs/pull/<n>/head`, verifying it still resolves to
118
+ * 2. Fall back to the target's PR head ref, verifying it still resolves to
55
119
  * `headSha` so the working tree cannot silently drift from the pinned
56
120
  * patch in the review bundle.
57
121
  *
@@ -59,35 +123,26 @@ export declare function serveHostGithubAuth(env?: NodeJS.ProcessEnv): ShallowClo
59
123
  * patch text in their prompt); a missing head checkout throws.
60
124
  */
61
125
  export declare function createShallowPrCheckout(args: {
62
- /** `owner/name`. */
63
- repo: string;
64
- prNumber?: number | undefined;
126
+ target: ScmCloneTarget;
65
127
  headSha: string;
66
128
  /** Merge-base SHA; fetched too so `git diff baseSha headSha` works locally. */
67
129
  baseSha?: string | undefined;
68
130
  checkoutDir: string;
69
- /** Clone credential; required for GitHub remotes, unused for file fixtures. */
131
+ /** Clone credential; required for HTTPS remotes, unused for file fixtures. */
70
132
  auth?: ShallowCloneAuth | undefined;
71
- /** Test seam: clone from this URL instead of `https://github.com/<repo>.git`. */
72
- remoteUrl?: string | undefined;
73
133
  }): Promise<ShallowPrCheckout>;
74
- /** True for `https://github.com/<owner>/<repo>/pull/<n>` URLs. */
75
- export declare function isGithubPrUrl(prUrl: string): boolean;
76
134
  export type TryShallowPrCheckoutOptions = {
77
- /** PR URL; only GitHub PR URLs are cloned (others skip). */
135
+ /** PR URL; resolved to a clone target (unsupported SCMs skip). */
78
136
  prUrl: string;
79
- /** `owner/name`. */
80
- repo: string;
81
- prNumber?: number | undefined;
82
137
  /** Pinned head SHA; skipped (undefined result) when unknown. */
83
138
  headSha?: string | undefined;
84
139
  /** Merge-base SHA; fetched too so `git diff baseSha headSha` works locally. */
85
140
  baseSha?: string | undefined;
86
141
  checkoutDir: string;
87
- /** Clone credential; defaults to {@link serveHostGithubAuth}. */
142
+ /** Clone credential; defaults to the target provider's credential source. */
88
143
  auth?: ShallowCloneAuth | undefined;
89
- /** Test seam: clone from this URL instead of `https://github.com/<repo>.git`. */
90
- remoteUrl?: string | undefined;
144
+ /** Test seam: clone this target instead of resolving `prUrl`. */
145
+ target?: ScmCloneTarget | undefined;
91
146
  };
92
147
  export type TryShallowPrCheckoutResult = {
93
148
  /** Set when the shallow checkout succeeded. */
@@ -104,12 +159,12 @@ export type TryShallowPrCheckoutResult = {
104
159
  * reviewed repo instead of the host's own checkout.
105
160
  *
106
161
  * Returns no checkout — leaving the caller on its fallback working
107
- * directory — when the PR is not on GitHub (e.g. Origin PRs, where the host
108
- * checkout is the reviewed repo), when no head SHA is pinned, when no clone
109
- * credential is available, or when the clone fails; `fallbackReason` says
110
- * which. Failures are logged, never thrown: agents still have the pinned
111
- * patch in their prompts, so a missing checkout degrades quality rather
112
- * than the run.
162
+ * directory — when the PR's SCM has no clone support (e.g. Origin PRs,
163
+ * where the host checkout is the reviewed repo), when no head SHA is
164
+ * pinned, when no clone credential is available, or when the clone fails;
165
+ * `fallbackReason` says which. Failures are logged, never thrown: agents
166
+ * still have the pinned patch in their prompts, so a missing checkout
167
+ * degrades quality rather than the run.
113
168
  */
114
169
  export declare function tryCreateShallowPrCheckout(options: TryShallowPrCheckoutOptions): Promise<TryShallowPrCheckoutResult>;
115
170
  //# sourceMappingURL=shallow-clone.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"shallow-clone.d.ts","sourceRoot":"","sources":["../../src/internal/shallow-clone.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,2EAA2E;IAC3E,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,WAAW,EAAE,OAAO,CAAC;IACrB,wCAAwC;IACxC,UAAU,EAAE,WAAW,GAAG,cAAc,CAAC;CAC1C,CAAC;AAEF,yEAAyE;AACzE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,gBAAgB,GAAG,SAAS,CAG9B;AA0GD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IAClD,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgH7B;AAED,kEAAkE;AAClE,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAapD;AAED,MAAM,MAAM,2BAA2B,GAAG;IACxC,4DAA4D;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,iEAAiE;IACjE,IAAI,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACpC,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,+CAA+C;IAC/C,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,wBAAsB,0BAA0B,CAC9C,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,0BAA0B,CAAC,CA2CrC"}
1
+ {"version":3,"file":"shallow-clone.d.ts","sourceRoot":"","sources":["../../src/internal/shallow-clone.ts"],"names":[],"mappings":"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"}
@@ -12,7 +12,38 @@ import { mkdirSync, rmSync } from "node:fs";
12
12
  import { promisify } from "node:util";
13
13
  const execFileAsync = promisify(execFile);
14
14
  /**
15
- * Default clone credential: the serve host's Cursor-account GitHub lease.
15
+ * Resolve a PR URL to its clone target, or `undefined` when the SCM has no
16
+ * shallow-clone support (callers then review on their fallback checkout —
17
+ * e.g. Origin PRs, where the host checkout already is the reviewed repo).
18
+ */
19
+ export function resolveScmCloneTarget(prUrl) {
20
+ let url;
21
+ try {
22
+ url = new URL(prUrl);
23
+ }
24
+ catch (_a) {
25
+ return undefined;
26
+ }
27
+ const parts = url.pathname.split("/").filter(Boolean);
28
+ if (url.hostname === "github.com" &&
29
+ parts.length >= 4 &&
30
+ parts[2] === "pull" &&
31
+ Number.isInteger(Number(parts[3]))) {
32
+ const repo = `${parts[0]}/${parts[1]}`;
33
+ const prNumber = Number(parts[3]);
34
+ return {
35
+ provider: "github",
36
+ repo,
37
+ prNumber,
38
+ remoteUrl: `https://github.com/${repo}.git`,
39
+ credentialUsername: "x-access-token",
40
+ prHeadRef: `refs/pull/${prNumber}/head`,
41
+ };
42
+ }
43
+ return undefined;
44
+ }
45
+ /**
46
+ * Default GitHub clone credential: the serve host's Cursor-account lease.
16
47
  * `CursorGithubCredentialProvider` mints it repo-scoped from the backend and
17
48
  * keeps `GH_TOKEN` refreshed for child processes; `GITHUB_TOKEN` covers
18
49
  * local/CI runs that export the conventional variable instead.
@@ -22,6 +53,107 @@ export function serveHostGithubAuth(env = process.env) {
22
53
  const token = ((_b = (_a = env.GH_TOKEN) !== null && _a !== void 0 ? _a : env.GITHUB_TOKEN) !== null && _b !== void 0 ? _b : "").trim();
23
54
  return token === "" ? undefined : { token };
24
55
  }
56
+ /** Pair the provider's git-over-HTTPS username with the bearer token. */
57
+ function cloneCredential(target, auth) {
58
+ return auth === undefined
59
+ ? undefined
60
+ : { username: target.credentialUsername, token: auth.token };
61
+ }
62
+ /** Default clone credential source per provider. */
63
+ function defaultCloneAuth(target) {
64
+ switch (target.provider) {
65
+ case "github":
66
+ return serveHostGithubAuth();
67
+ }
68
+ }
69
+ /** Cap on diff text handed to a model; beyond this it is truncated. */
70
+ const DIFF_MAX_CHARS = 80000;
71
+ /**
72
+ * Diff two commits inside an existing shallow PR checkout, fetching either
73
+ * end on demand when the shallow history does not already contain it.
74
+ *
75
+ * Lives here because it needs the same authenticated git the clone uses —
76
+ * a `--depth=1` checkout usually lacks the older commit, so reading a range
77
+ * means another credentialed fetch. Never throws: every failure becomes an
78
+ * `unavailable` reason the caller can act on or surface.
79
+ */
80
+ export function tryDiffCommitRange(args) {
81
+ return __awaiter(this, void 0, void 0, function* () {
82
+ var _a;
83
+ if (!isFullCommitSha(args.from) || !isFullCommitSha(args.to)) {
84
+ return {
85
+ status: "unavailable",
86
+ reason: "Could not compute a reliable diff because a commit SHA was not a full 40-character SHA.",
87
+ };
88
+ }
89
+ const credential = cloneCredential(args.target, (_a = args.auth) !== null && _a !== void 0 ? _a : defaultCloneAuth(args.target));
90
+ for (const sha of [args.from, args.to]) {
91
+ if (!(yield ensureCommitFetched(args.checkoutDir, sha, args.target, credential))) {
92
+ return {
93
+ status: "unavailable",
94
+ reason: "Could not compute a reliable diff because a commit was unavailable in the checkout.",
95
+ };
96
+ }
97
+ }
98
+ try {
99
+ const diff = yield git(args.checkoutDir, [
100
+ "diff",
101
+ "--no-ext-diff",
102
+ "--unified=80",
103
+ `${args.from}..${args.to}`,
104
+ ...(args.file === undefined ? [] : ["--", args.file]),
105
+ ]);
106
+ return {
107
+ status: "ok",
108
+ diff: diff.length <= DIFF_MAX_CHARS
109
+ ? diff
110
+ : `${diff.slice(0, DIFF_MAX_CHARS)}\n\n[diff truncated at ${DIFF_MAX_CHARS} characters]`,
111
+ };
112
+ }
113
+ catch (_b) {
114
+ return {
115
+ status: "unavailable",
116
+ reason: "Could not compute a reliable diff because git diff failed.",
117
+ };
118
+ }
119
+ });
120
+ }
121
+ function isFullCommitSha(value) {
122
+ return /^[0-9a-f]{40}$/i.test(value);
123
+ }
124
+ /** Present already, or fetchable by SHA, or reachable from the PR head ref. */
125
+ function ensureCommitFetched(checkoutDir, sha, target, credential) {
126
+ return __awaiter(this, void 0, void 0, function* () {
127
+ if ((yield revParse(checkoutDir, sha)) !== undefined) {
128
+ return true;
129
+ }
130
+ const attempts = [
131
+ [...FETCH_ARGS, sha],
132
+ // Deeper history on the PR head ref: the older end of an inter-run range
133
+ // is usually an ancestor of the tip rather than the tip itself.
134
+ [
135
+ "fetch",
136
+ "--depth=200",
137
+ "--no-tags",
138
+ "--quiet",
139
+ "origin",
140
+ target.prHeadRef,
141
+ ],
142
+ ];
143
+ for (const attempt of attempts) {
144
+ try {
145
+ yield git(checkoutDir, attempt, credential);
146
+ if ((yield revParse(checkoutDir, sha)) !== undefined) {
147
+ return true;
148
+ }
149
+ }
150
+ catch (_a) {
151
+ // Try the next strategy; the caller fails closed if none work.
152
+ }
153
+ }
154
+ return false;
155
+ });
156
+ }
25
157
  function logShallowClone(message, fields = {}) {
26
158
  const suffix = Object.entries(fields)
27
159
  .filter(([, value]) => value !== undefined)
@@ -55,12 +187,12 @@ function gitError(args, error) {
55
187
  return new Error(`git ${args.join(" ")} failed — ${detail}`);
56
188
  }
57
189
  /**
58
- * The one credential helper git may use: serve the caller-provided token
59
- * from the child process env at request time. The shell reads
60
- * `$SHALLOW_CLONE_GIT_TOKEN` when git asks, keeping the token out of argv.
190
+ * The one credential helper git may use: serve the caller-provided
191
+ * credential from the child process env at request time. The shell reads
192
+ * the values when git asks, keeping the token out of argv.
61
193
  */
62
- const TOKEN_CREDENTIAL_HELPER = '!f() { test "$1" = get && printf "username=x-access-token\\npassword=$SHALLOW_CLONE_GIT_TOKEN\\n"; }; f';
63
- function git(cwd, args, auth) {
194
+ const CREDENTIAL_HELPER = '!f() { test "$1" = get && printf "username=$SHALLOW_CLONE_GIT_USERNAME\\npassword=$SHALLOW_CLONE_GIT_TOKEN\\n"; }; f';
195
+ function git(cwd, args, credential) {
64
196
  return __awaiter(this, void 0, void 0, function* () {
65
197
  // Async on purpose: fetches/checkouts of large repos take minutes, and the
66
198
  // serve host runs the clone in-process. A synchronous git call blocks the
@@ -68,9 +200,9 @@ function git(cwd, args, auth) {
68
200
  // long enough for the platform's probe budget to replace the engine.
69
201
  try {
70
202
  const { stdout } = yield execFileAsync("git", [
71
- ...(auth === undefined
203
+ ...(credential === undefined
72
204
  ? []
73
- : ["-c", `credential.helper=${TOKEN_CREDENTIAL_HELPER}`]),
205
+ : ["-c", `credential.helper=${CREDENTIAL_HELPER}`]),
74
206
  ...args,
75
207
  ], {
76
208
  cwd,
@@ -82,9 +214,12 @@ function git(cwd, args, auth) {
82
214
  // .com/.insteadOf` entries scoped to a *different* repo, as cloud
83
215
  // VMs bake in) cannot hijack auth away from the explicit token,
84
216
  // and no ambient credential helpers run against PR-author input.
85
- GIT_CONFIG_GLOBAL: "/dev/null", GIT_CONFIG_SYSTEM: "/dev/null", GIT_TERMINAL_PROMPT: "0" }), (auth === undefined
217
+ GIT_CONFIG_GLOBAL: "/dev/null", GIT_CONFIG_SYSTEM: "/dev/null", GIT_TERMINAL_PROMPT: "0" }), (credential === undefined
86
218
  ? {}
87
- : { SHALLOW_CLONE_GIT_TOKEN: auth.token })),
219
+ : {
220
+ SHALLOW_CLONE_GIT_USERNAME: credential.username,
221
+ SHALLOW_CLONE_GIT_TOKEN: credential.token,
222
+ })),
88
223
  });
89
224
  return stdout;
90
225
  }
@@ -105,14 +240,16 @@ function revParse(cwd, rev) {
105
240
  });
106
241
  }
107
242
  const FETCH_ARGS = ["fetch", "--depth=1", "--no-tags", "--quiet", "origin"];
243
+ /** Local tracking ref the PR head ref is fetched into. */
244
+ const LOCAL_PR_HEAD_REF = "refs/remotes/origin/shallow-clone-pr-head";
108
245
  /**
109
- * Create a fresh shallow checkout of a GitHub PR head at `checkoutDir`.
246
+ * Create a fresh shallow checkout of a PR head at `checkoutDir`.
110
247
  *
111
248
  * Fetch order (both single depth-1 round-trips):
112
249
  * 1. Fetch `headSha` (and `baseSha` when known) directly — GitHub advertises
113
250
  * `allow-reachable-sha1-in-want`, and this pins the exact reviewed commit
114
251
  * the way Bugbot's `shallow_fetch` does.
115
- * 2. Fall back to `refs/pull/<n>/head`, verifying it still resolves to
252
+ * 2. Fall back to the target's PR head ref, verifying it still resolves to
116
253
  * `headSha` so the working tree cannot silently drift from the pinned
117
254
  * patch in the review bundle.
118
255
  *
@@ -121,23 +258,19 @@ const FETCH_ARGS = ["fetch", "--depth=1", "--no-tags", "--quiet", "origin"];
121
258
  */
122
259
  export function createShallowPrCheckout(args) {
123
260
  return __awaiter(this, void 0, void 0, function* () {
124
- var _a;
125
- const { repo, prNumber, headSha, baseSha, checkoutDir, auth } = args;
261
+ const { target, headSha, baseSha, checkoutDir, auth } = args;
262
+ const { repo, prNumber } = target;
263
+ const credential = cloneCredential(target, auth);
126
264
  const startedAt = Date.now();
127
265
  logShallowClone("cloning PR head", { repo, prNumber, headSha, baseSha });
128
266
  rmSync(checkoutDir, { recursive: true, force: true });
129
267
  mkdirSync(checkoutDir, { recursive: true });
130
268
  yield git(checkoutDir, ["init", "--quiet"]);
131
- yield git(checkoutDir, [
132
- "remote",
133
- "add",
134
- "origin",
135
- (_a = args.remoteUrl) !== null && _a !== void 0 ? _a : `https://github.com/${repo}.git`,
136
- ]);
269
+ yield git(checkoutDir, ["remote", "add", "origin", target.remoteUrl]);
137
270
  const shaFetch = () => __awaiter(this, void 0, void 0, function* () {
138
271
  const extraBase = baseSha === undefined || baseSha === headSha ? [] : [baseSha];
139
272
  try {
140
- yield git(checkoutDir, [...FETCH_ARGS, headSha, ...extraBase], auth);
273
+ yield git(checkoutDir, [...FETCH_ARGS, headSha, ...extraBase], credential);
141
274
  }
142
275
  catch (error) {
143
276
  if (extraBase.length === 0) {
@@ -151,29 +284,24 @@ export function createShallowPrCheckout(args) {
151
284
  baseSha,
152
285
  error: errorSummary(error),
153
286
  });
154
- yield git(checkoutDir, [...FETCH_ARGS, headSha], auth);
287
+ yield git(checkoutDir, [...FETCH_ARGS, headSha], credential);
155
288
  }
156
289
  });
157
290
  let headSource;
158
- let shaFetchError;
159
291
  try {
160
292
  yield shaFetch();
161
293
  headSource = "sha_fetch";
162
294
  }
163
295
  catch (error) {
164
- shaFetchError = errorSummary(error);
165
- if (prNumber === undefined) {
166
- throw new Error(`Shallow SHA fetch failed for ${repo}@${headSha} and no PR number is available for a ref fallback: ${shaFetchError}`);
167
- }
296
+ const shaFetchError = errorSummary(error);
168
297
  logShallowClone("sha fetch failed; falling back to PR head ref", {
169
298
  repo,
170
299
  prNumber,
171
300
  headSha,
172
301
  error: shaFetchError,
173
302
  });
174
- const prRef = `refs/pull/${prNumber}/head`;
175
- yield git(checkoutDir, [...FETCH_ARGS, `+${prRef}:refs/remotes/origin/pr/${prNumber}/head`], auth);
176
- const fetchedSha = yield revParse(checkoutDir, `refs/remotes/origin/pr/${prNumber}/head`);
303
+ yield git(checkoutDir, [...FETCH_ARGS, `+${target.prHeadRef}:${LOCAL_PR_HEAD_REF}`], credential);
304
+ const fetchedSha = yield revParse(checkoutDir, LOCAL_PR_HEAD_REF);
177
305
  if (fetchedSha !== headSha) {
178
306
  throw new Error(`Shallow PR ref fetch for ${repo}#${prNumber} resolved to ${fetchedSha !== null && fetchedSha !== void 0 ? fetchedSha : "nothing"}, expected pinned head ${headSha} (sha fetch error: ${shaFetchError})`);
179
307
  }
@@ -194,7 +322,7 @@ export function createShallowPrCheckout(args) {
194
322
  // Best-effort: local diffs are nice-to-have, the pinned patch in the
195
323
  // prompt is the authoritative delta either way.
196
324
  try {
197
- yield git(checkoutDir, [...FETCH_ARGS, baseSha], auth);
325
+ yield git(checkoutDir, [...FETCH_ARGS, baseSha], credential);
198
326
  baseFetched = (yield revParse(checkoutDir, baseSha)) !== undefined;
199
327
  }
200
328
  catch (error) {
@@ -218,71 +346,63 @@ export function createShallowPrCheckout(args) {
218
346
  return { checkoutDir, headSha, baseFetched, headSource };
219
347
  });
220
348
  }
221
- /** True for `https://github.com/<owner>/<repo>/pull/<n>` URLs. */
222
- export function isGithubPrUrl(prUrl) {
223
- try {
224
- const url = new URL(prUrl);
225
- const parts = url.pathname.split("/").filter(Boolean);
226
- return (url.hostname === "github.com" &&
227
- parts.length >= 4 &&
228
- parts[2] === "pull" &&
229
- Number.isInteger(Number(parts[3])));
230
- }
231
- catch (_a) {
232
- return false;
233
- }
234
- }
235
349
  /**
236
350
  * Best-effort shallow PR checkout for hosts whose SDK agents should read the
237
351
  * reviewed repo instead of the host's own checkout.
238
352
  *
239
353
  * Returns no checkout — leaving the caller on its fallback working
240
- * directory — when the PR is not on GitHub (e.g. Origin PRs, where the host
241
- * checkout is the reviewed repo), when no head SHA is pinned, when no clone
242
- * credential is available, or when the clone fails; `fallbackReason` says
243
- * which. Failures are logged, never thrown: agents still have the pinned
244
- * patch in their prompts, so a missing checkout degrades quality rather
245
- * than the run.
354
+ * directory — when the PR's SCM has no clone support (e.g. Origin PRs,
355
+ * where the host checkout is the reviewed repo), when no head SHA is
356
+ * pinned, when no clone credential is available, or when the clone fails;
357
+ * `fallbackReason` says which. Failures are logged, never thrown: agents
358
+ * still have the pinned patch in their prompts, so a missing checkout
359
+ * degrades quality rather than the run.
246
360
  */
247
361
  export function tryCreateShallowPrCheckout(options) {
248
362
  return __awaiter(this, void 0, void 0, function* () {
249
- var _a;
250
- const { prUrl, repo, prNumber, headSha, baseSha, checkoutDir, remoteUrl } = options;
251
- if (remoteUrl === undefined && !isGithubPrUrl(prUrl)) {
252
- logShallowClone("skipped: not a GitHub PR URL", { prUrl });
253
- return { fallbackReason: "skipped: not a GitHub PR URL" };
363
+ var _a, _b;
364
+ const { prUrl, headSha, baseSha, checkoutDir } = options;
365
+ const target = (_a = options.target) !== null && _a !== void 0 ? _a : resolveScmCloneTarget(prUrl);
366
+ if (target === undefined) {
367
+ logShallowClone("skipped: unsupported SCM for shallow clone", { prUrl });
368
+ return { fallbackReason: "skipped: unsupported SCM for shallow clone" };
254
369
  }
255
370
  if (headSha === undefined) {
256
- logShallowClone("skipped: no pinned head SHA", { repo, prUrl });
371
+ logShallowClone("skipped: no pinned head SHA", {
372
+ repo: target.repo,
373
+ prUrl,
374
+ });
257
375
  return { fallbackReason: "skipped: no pinned head SHA" };
258
376
  }
259
- const auth = (_a = options.auth) !== null && _a !== void 0 ? _a : serveHostGithubAuth();
260
- if (remoteUrl === undefined && auth === undefined) {
261
- // Fail fast instead of letting an unauthenticated fetch 404/hang: real
262
- // GitHub clones need the serve host's lease (or an explicit token).
263
- logShallowClone("skipped: no GitHub clone credential", { repo, prUrl });
377
+ const auth = (_b = options.auth) !== null && _b !== void 0 ? _b : defaultCloneAuth(target);
378
+ if (auth === undefined && target.remoteUrl.startsWith("https://")) {
379
+ // Fail fast instead of letting an unauthenticated fetch 404/hang: HTTPS
380
+ // clones need the provider's credential (or an explicit token).
381
+ logShallowClone("skipped: no clone credential", {
382
+ repo: target.repo,
383
+ provider: target.provider,
384
+ prUrl,
385
+ });
264
386
  return {
265
- fallbackReason: "skipped: no GitHub clone credential (serve host GH_TOKEN lease not installed)",
387
+ fallbackReason: `skipped: no ${target.provider} clone credential (serve host token lease not installed)`,
266
388
  };
267
389
  }
268
390
  try {
269
391
  return {
270
392
  checkout: yield createShallowPrCheckout({
271
- repo,
272
- prNumber,
393
+ target,
273
394
  headSha,
274
395
  baseSha,
275
396
  checkoutDir,
276
397
  auth,
277
- remoteUrl,
278
398
  }),
279
399
  };
280
400
  }
281
401
  catch (error) {
282
402
  const reason = errorSummary(error);
283
403
  logShallowClone("failed; caller falls back to host checkout", {
284
- repo,
285
- prNumber,
404
+ repo: target.repo,
405
+ prNumber: target.prNumber,
286
406
  headSha,
287
407
  error: reason,
288
408
  });
@@ -17,6 +17,24 @@ export declare function makePalette(enabled: boolean): TerminalPalette;
17
17
  export declare function stdoutPalette(): TerminalPalette;
18
18
  /** Palette for human-facing stderr (login progress, warnings). */
19
19
  export declare function stderrPalette(): TerminalPalette;
20
+ /** Visible column count, ignoring CSI color/style and OSC 8 hyperlinks. */
21
+ export declare function visibleWidth(text: string): number;
22
+ /** True when `text` already carries CSI styling or OSC 8 (do not wrap again). */
23
+ export declare function hasAnsiStyling(text: string): boolean;
24
+ /**
25
+ * Clickable terminal hyperlink (OSC 8). The URI is the click target; `label`
26
+ * is what the user sees. `visibleWidth` ignores the OSC wrapper.
27
+ */
28
+ export declare function terminalHyperlink(url: string, label: string, enabled?: boolean): string;
29
+ /**
30
+ * Unicode box around `lines`. `color` wraps the whole box (borders + body)
31
+ * so a warning panel can be yellow without per-line prefixes.
32
+ */
33
+ export declare function formatTerminalBox(lines: readonly string[], options?: {
34
+ color?: (s: string) => string;
35
+ minWidth?: number;
36
+ padding?: number;
37
+ }): string;
20
38
  /** Wipe the terminal before a `dev` Enter-to-restart cycle. */
21
39
  export declare function clearTerminal(stream?: NodeJS.WriteStream): void;
22
40
  //# sourceMappingURL=terminal-style.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"terminal-style.d.ts","sourceRoot":"","sources":["../../src/internal/terminal-style.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAcD,wBAAgB,eAAe,CAC7B,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,OAAO,CAET;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAiB7D;AAED,oEAAoE;AACpE,wBAAgB,aAAa,IAAI,eAAe,CAE/C;AAED,kEAAkE;AAClE,wBAAgB,aAAa,IAAI,eAAe,CAE/C;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAC3B,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,IAAI,CAMN"}
1
+ {"version":3,"file":"terminal-style.d.ts","sourceRoot":"","sources":["../../src/internal/terminal-style.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5B,KAAK,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7B,GAAG,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC3B,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC/B,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAC/B;AAsBD,wBAAgB,eAAe,CAC7B,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,OAAO,CAET;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,CAiB7D;AAED,oEAAoE;AACpE,wBAAgB,aAAa,IAAI,eAAe,CAE/C;AAED,kEAAkE;AAClE,wBAAgB,aAAa,IAAI,eAAe,CAE/C;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAA2B,GACnC,MAAM,CAKR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,OAAO,CAAC,EAAE;IACR,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GACA,MAAM,CAoBR;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAC3B,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,IAAI,CAMN"}