diffing 0.6.2 → 0.7.0

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 (186) hide show
  1. package/README.md +134 -100
  2. package/dist/apply-suggestion-BAuyCYk6.mjs +54 -0
  3. package/dist/cli-agent-BlMtx1Tx.mjs +736 -0
  4. package/dist/cli-agent-C4Fb90GL.mjs +728 -0
  5. package/dist/cli-agent-ChALuNbw.mjs +841 -0
  6. package/dist/cli-agent-D71pq2ep.mjs +841 -0
  7. package/dist/cli-agent-qBT8clNM.mjs +841 -0
  8. package/dist/cli-gh-6qiblgj7.mjs +150 -0
  9. package/dist/cli-gh-D5OCnjNe.mjs +150 -0
  10. package/dist/cli-gh-KjPnyST6.mjs +150 -0
  11. package/dist/cli.mjs +38 -66
  12. package/dist/client/assets/{angular-html-Dg8frIKA.js → angular-html-Dh86jUvr.js} +1 -1
  13. package/dist/client/assets/{angular-ts-BgXWv16g.js → angular-ts-Bh4wRJtT.js} +1 -1
  14. package/dist/client/assets/{apl-uFl-_xI6.js → apl-BSXBHduT.js} +1 -1
  15. package/dist/client/assets/{arc-2DyFlUoQ.js → arc-CRQlhBrV.js} +1 -1
  16. package/dist/client/assets/{architectureDiagram-3BPJPVTR-Cpo5XnQh.js → architectureDiagram-3BPJPVTR-BXq3UvEv.js} +1 -1
  17. package/dist/client/assets/{astro-CsSgohj_.js → astro-Bh00klUw.js} +1 -1
  18. package/dist/client/assets/{blade-tmMbmea0.js → blade-CisA3zhm.js} +1 -1
  19. package/dist/client/assets/{blockDiagram-GPEHLZMM-C2j4VeON.js → blockDiagram-GPEHLZMM-Bw-PTAJr.js} +1 -1
  20. package/dist/client/assets/{c-CYFchk-Y.js → c-D-pHVWrf.js} +1 -1
  21. package/dist/client/assets/{c4Diagram-AAUBKEIU-B9Iu60rg.js → c4Diagram-AAUBKEIU-C0XyiqC_.js} +1 -1
  22. package/dist/client/assets/channel-CDxgOu-3.js +1 -0
  23. package/dist/client/assets/{chunk-2J33WTMH-CYF5wgmI.js → chunk-2J33WTMH-DekjZXNj.js} +1 -1
  24. package/dist/client/assets/{chunk-3OPIFGDE-BsCKEfSk.js → chunk-3OPIFGDE-BtROpcL8.js} +1 -1
  25. package/dist/client/assets/{chunk-4BX2VUAB-CKaohpWW.js → chunk-4BX2VUAB-C92XLTlx.js} +1 -1
  26. package/dist/client/assets/{chunk-55IACEB6-CPg0c8fY.js → chunk-55IACEB6-CceUgh8N.js} +1 -1
  27. package/dist/client/assets/{chunk-5ZQYHXKU-qstslfP1.js → chunk-5ZQYHXKU-DSbYPAe7.js} +1 -1
  28. package/dist/client/assets/{chunk-727SXJPM-C1WRwOi2.js → chunk-727SXJPM-DVzUJa-9.js} +1 -1
  29. package/dist/client/assets/{chunk-AQP2D5EJ-_jbfFh_H.js → chunk-AQP2D5EJ-6n3Z_IFa.js} +1 -1
  30. package/dist/client/assets/{chunk-BSJP7CBP-CjQkUxwj.js → chunk-BSJP7CBP-BgVLnkxr.js} +1 -1
  31. package/dist/client/assets/{chunk-CSCIHK7Q-D4khYgW5.js → chunk-CSCIHK7Q-CkGMXntp.js} +1 -1
  32. package/dist/client/assets/{chunk-FMBD7UC4-B1r9As4X.js → chunk-FMBD7UC4-BM8lrLBo.js} +1 -1
  33. package/dist/client/assets/{chunk-KSCS5N6A-XehlazPT.js → chunk-KSCS5N6A-Bm2pjMQg.js} +1 -1
  34. package/dist/client/assets/{chunk-L5ZTLDWV-5KMCRmgT.js → chunk-L5ZTLDWV-VL17ikXM.js} +1 -1
  35. package/dist/client/assets/{chunk-LZXEDZCA--x7aE-36.js → chunk-LZXEDZCA-B629g67M.js} +2 -2
  36. package/dist/client/assets/{chunk-ND2GUHAM-BcUeNQF6.js → chunk-ND2GUHAM-CjZGwhKA.js} +1 -1
  37. package/dist/client/assets/{chunk-NZK2D7GU-HdA4zA81.js → chunk-NZK2D7GU-DGsLjESY.js} +1 -1
  38. package/dist/client/assets/{chunk-O5CBEL6O-BbkpkgBW.js → chunk-O5CBEL6O-EyUrGY3l.js} +1 -1
  39. package/dist/client/assets/chunk-QZHKN3VN-DJCeMpP8.js +1 -0
  40. package/dist/client/assets/chunk-WU5MYG2G-BbuOkMaH.js +1 -0
  41. package/dist/client/assets/{chunk-XPW4576I-BrjJtb92.js → chunk-XPW4576I-C2TeAQmQ.js} +1 -1
  42. package/dist/client/assets/classDiagram-4FO5ZUOK-D5oJbiED.js +1 -0
  43. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-5MJt5ZxQ.js +1 -0
  44. package/dist/client/assets/{cobol-CbEdzJpe.js → cobol-DsRZMP16.js} +1 -1
  45. package/dist/client/assets/{coffee-BYBPPvKf.js → coffee-DP0-MMsE.js} +1 -1
  46. package/dist/client/assets/{cose-bilkent-S5V4N54A-C2UlmvWG.js → cose-bilkent-S5V4N54A-DMmK0b0W.js} +1 -1
  47. package/dist/client/assets/{cpp-Cy1Wnp8d.js → cpp-B6XYbbze.js} +1 -1
  48. package/dist/client/assets/{crystal-Bg1sUJya.js → crystal-dBLPFLMp.js} +1 -1
  49. package/dist/client/assets/{css-C6iyzRBi.js → css-tgwuSZL0.js} +1 -1
  50. package/dist/client/assets/{dagre-BM42HDAG-CLP5IYO3.js → dagre-BM42HDAG-CgNkf0TR.js} +1 -1
  51. package/dist/client/assets/{diagram-2AECGRRQ-Dg8GXMUD.js → diagram-2AECGRRQ-ocAqn0LV.js} +1 -1
  52. package/dist/client/assets/{diagram-5GNKFQAL-D5eskvC7.js → diagram-5GNKFQAL-CB1Yo4Gc.js} +1 -1
  53. package/dist/client/assets/{diagram-KO2AKTUF-SO-9Apcj.js → diagram-KO2AKTUF-B2vpMBRT.js} +1 -1
  54. package/dist/client/assets/{diagram-LMA3HP47-Dz15-yRy.js → diagram-LMA3HP47-DuxZOaQS.js} +1 -1
  55. package/dist/client/assets/{diagram-OG6HWLK6-BuQK0W1m.js → diagram-OG6HWLK6-CkShDmcv.js} +1 -1
  56. package/dist/client/assets/{dist-CZ555WMx.js → dist-BgZIvk5w.js} +1 -1
  57. package/dist/client/assets/{edge-CmOR4HCT.js → edge-Bokubn8E.js} +1 -1
  58. package/dist/client/assets/{elixir-CK9qhOZG.js → elixir-BEzcf3Xg.js} +1 -1
  59. package/dist/client/assets/{elm-DZWlTp8-.js → elm-vJyLTAER.js} +1 -1
  60. package/dist/client/assets/{erDiagram-TEJ5UH35-D7vADGZy.js → erDiagram-TEJ5UH35-BFV1NQAH.js} +1 -1
  61. package/dist/client/assets/{erb-CTTGdXJ0.js → erb-DDkAmjBS.js} +1 -1
  62. package/dist/client/assets/{flowDiagram-I6XJVG4X-BwcgAtP3.js → flowDiagram-I6XJVG4X-DU8xbFdO.js} +1 -1
  63. package/dist/client/assets/{ganttDiagram-6RSMTGT7-kInginE9.js → ganttDiagram-6RSMTGT7-DCb7Qh0c.js} +1 -1
  64. package/dist/client/assets/{git-rebase-B_sSbVaY.js → git-rebase-DWcifAdK.js} +1 -1
  65. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-C4pDDMLO.js → gitGraphDiagram-PVQCEYII-C_Tw-piE.js} +1 -1
  66. package/dist/client/assets/{glimmer-js-BaLXlo90.js → glimmer-js--HDru5ys.js} +1 -1
  67. package/dist/client/assets/{glimmer-ts-ugNWY62Y.js → glimmer-ts-DAdXisHh.js} +1 -1
  68. package/dist/client/assets/{glsl-CDofiyvf.js → glsl-CmIRlJht.js} +1 -1
  69. package/dist/client/assets/{graphql-lRTsx6gb.js → graphql-tx4-7I3U.js} +1 -1
  70. package/dist/client/assets/{hack-DG646xxf.js → hack-yA0XjhF7.js} +1 -1
  71. package/dist/client/assets/{haml-CjNyEqTY.js → haml-BR5MUE1b.js} +1 -1
  72. package/dist/client/assets/{handlebars-DmTlsycc.js → handlebars-BPOF7iOf.js} +1 -1
  73. package/dist/client/assets/{html-CYKa0iGt.js → html-BbteRk96.js} +1 -1
  74. package/dist/client/assets/{html-derivative-CJrmldEy.js → html-derivative-59NNrcMm.js} +1 -1
  75. package/dist/client/assets/{http-Dv_sB6KO.js → http-D3odGQI4.js} +1 -1
  76. package/dist/client/assets/{hurl-aIa6gC3s.js → hurl-BLTj8fPj.js} +1 -1
  77. package/dist/client/assets/index-BZcKS8Sb.css +1 -0
  78. package/dist/client/assets/{index-DLwFuHoH.js → index-DHXpO7eS.js} +136 -98
  79. package/dist/client/assets/{infoDiagram-5YYISTIA-DE1yaqeG.js → infoDiagram-5YYISTIA-CI6hJyRl.js} +1 -1
  80. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-D61KC690.js → ishikawaDiagram-YF4QCWOH-gMS1P1LQ.js} +1 -1
  81. package/dist/client/assets/{java--GCJC5Ht.js → java-CsViuzs_.js} +1 -1
  82. package/dist/client/assets/{javascript-CLU-vrsL.js → javascript-DQgsl2Dh.js} +1 -1
  83. package/dist/client/assets/{jinja-DpKxO4hN.js → jinja-DQNp2NUA.js} +1 -1
  84. package/dist/client/assets/{jison-DAzEKgwk.js → jison-CDDOZQdc.js} +1 -1
  85. package/dist/client/assets/{journeyDiagram-JHISSGLW-Bt37oidm.js → journeyDiagram-JHISSGLW-BTQ_Ws_h.js} +1 -1
  86. package/dist/client/assets/{json-CoxC1kMn.js → json-DP4TqCuE.js} +1 -1
  87. package/dist/client/assets/{jsx-Bjv8cqXv.js → jsx-Df5hn0Tf.js} +1 -1
  88. package/dist/client/assets/{julia-2HI5Piu6.js → julia--u33yGLi.js} +1 -1
  89. package/dist/client/assets/{just-AUrPjdB4.js → just-BCpMmSOD.js} +1 -1
  90. package/dist/client/assets/{kanban-definition-UN3LZRKU-D46QdRYJ.js → kanban-definition-UN3LZRKU-CvqGbLR_.js} +1 -1
  91. package/dist/client/assets/{latex-DjzDlfkY.js → latex-D8D4jZGw.js} +1 -1
  92. package/dist/client/assets/{line-D_rKDTVX.js → line-DBgaS_RW.js} +1 -1
  93. package/dist/client/assets/{linear-DCm3ZWOL.js → linear-RQVzKNVU.js} +1 -1
  94. package/dist/client/assets/{liquid-DZ8JEV93.js → liquid-CkH85f12.js} +1 -1
  95. package/dist/client/assets/{lua-iKYCK6sd.js → lua-iKoV7WE3.js} +1 -1
  96. package/dist/client/assets/{marko-CrhrBZpj.js → marko-N8ScQSqT.js} +1 -1
  97. package/dist/client/assets/{mdc-M6YkRqT_.js → mdc-BvHTOxsp.js} +1 -1
  98. package/dist/client/assets/{mermaid-parser.core-DOlZkAUl.js → mermaid-parser.core-CwDRwMR7.js} +1 -1
  99. package/dist/client/assets/{mermaid.core-B5kraaYr.js → mermaid.core-D2LDJgXO.js} +3 -3
  100. package/dist/client/assets/{mindmap-definition-RKZ34NQL-CG-S_0Tm.js → mindmap-definition-RKZ34NQL-FRnPh642.js} +1 -1
  101. package/dist/client/assets/{nginx-DGSv66H3.js → nginx-DGgvASuI.js} +1 -1
  102. package/dist/client/assets/{nim-wTb9iFPK.js → nim-D-v9hzvR.js} +1 -1
  103. package/dist/client/assets/{perl-BrLOtih-.js → perl-CG8leJ8K.js} +1 -1
  104. package/dist/client/assets/{php-BpG59zED.js → php-DvkeSP10.js} +1 -1
  105. package/dist/client/assets/{pieDiagram-4H26LBE5-BSsvT950.js → pieDiagram-4H26LBE5-CepOg38Y.js} +1 -1
  106. package/dist/client/assets/{pug-L7QegceF.js → pug-B4T7-xaL.js} +1 -1
  107. package/dist/client/assets/{qml-Bhe1hZ7B.js → qml-BE6D5Bxn.js} +1 -1
  108. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Bxs1ZIId.js → quadrantDiagram-W4KKPZXB-DOFAsP60.js} +1 -1
  109. package/dist/client/assets/{r-D1TBw_pw.js → r-BKZg9Mcq.js} +1 -1
  110. package/dist/client/assets/{razor-CQm1uFKr.js → razor-D-02oaxL.js} +1 -1
  111. package/dist/client/assets/{regexp--jRne08M.js → regexp-BDFvAR1k.js} +1 -1
  112. package/dist/client/assets/{requirementDiagram-4Y6WPE33-BvrwIHRn.js → requirementDiagram-4Y6WPE33-BBVNH-2W.js} +1 -1
  113. package/dist/client/assets/review-export-D5iIl46_.js +7 -0
  114. package/dist/client/assets/{rst-DojkdR69.js → rst-BcT26OSj.js} +1 -1
  115. package/dist/client/assets/{ruby-CihGsdWE.js → ruby-Cq_YQvFT.js} +1 -1
  116. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-ChVx7-uL.js → sankeyDiagram-5OEKKPKP-BQfCTbBX.js} +1 -1
  117. package/dist/client/assets/{sas-De9KOrSF.js → sas-DN9oTxKY.js} +1 -1
  118. package/dist/client/assets/{scss-s1VsrZAM.js → scss-BK_sp3z2.js} +1 -1
  119. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DfGXu7Db.js → sequenceDiagram-3UESZ5HK-CKAW2eyx.js} +1 -1
  120. package/dist/client/assets/{shellscript-BQarhH5B.js → shellscript-CvNpOu0J.js} +1 -1
  121. package/dist/client/assets/{shellsession-DudKTKQ_.js → shellsession-8-yj2cJj.js} +1 -1
  122. package/dist/client/assets/{soy-CQggW1_P.js → soy-C6Q9atPF.js} +1 -1
  123. package/dist/client/assets/{sql-CyxjmxEX.js → sql-CBL3BuHb.js} +1 -1
  124. package/dist/client/assets/{src-Be3tFbq6.js → src-D-VUWIK5.js} +1 -1
  125. package/dist/client/assets/{stata-Baq2oukf.js → stata-B2Q7Vqzu.js} +1 -1
  126. package/dist/client/assets/{stateDiagram-AJRCARHV-DUsSkWi-.js → stateDiagram-AJRCARHV-BGJiv0qO.js} +1 -1
  127. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CdUgMghp.js +1 -0
  128. package/dist/client/assets/{surrealql-DY_lPQU6.js → surrealql-C-A2N8vk.js} +1 -1
  129. package/dist/client/assets/{svelte-oBaORrzD.js → svelte-VAut_-uy.js} +1 -1
  130. package/dist/client/assets/{templ-WpkyVGPg.js → templ-mUetM--K.js} +1 -1
  131. package/dist/client/assets/{tex-t_gMyObp.js → tex-BT53mWGp.js} +1 -1
  132. package/dist/client/assets/{timeline-definition-PNZ67QCA-DO30eyIk.js → timeline-definition-PNZ67QCA-lVwMt1rk.js} +1 -1
  133. package/dist/client/assets/{ts-tags-Dn6NjJLA.js → ts-tags-VkIOkgLN.js} +1 -1
  134. package/dist/client/assets/{tsx-DDWp_p5y.js → tsx-D_aaGHTf.js} +1 -1
  135. package/dist/client/assets/{twig-FBY22xUa.js → twig-CufwqKkk.js} +1 -1
  136. package/dist/client/assets/{typescript-BHZBosYe.js → typescript-osFD2CEV.js} +1 -1
  137. package/dist/client/assets/{vennDiagram-CIIHVFJN-DbE8UKE1.js → vennDiagram-CIIHVFJN-_K9NtpA5.js} +1 -1
  138. package/dist/client/assets/{vue-CrOmWBlh.js → vue-Bub1rXmL.js} +1 -1
  139. package/dist/client/assets/{vue-html-jBuGpXgg.js → vue-html-CN3x2pYg.js} +1 -1
  140. package/dist/client/assets/{vue-vine-DEzqOkvG.js → vue-vine-C0csYkGm.js} +1 -1
  141. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-BqhSY5Qs.js → wardleyDiagram-YWT4CUSO-B2jTMfra.js} +1 -1
  142. package/dist/client/assets/{xml-DkWImCZV.js → xml-my6OjeGb.js} +1 -1
  143. package/dist/client/assets/{xsl-BotuNSYU.js → xsl-Bx0YVn26.js} +1 -1
  144. package/dist/client/assets/{xychartDiagram-2RQKCTM6-DA2pXGD9.js → xychartDiagram-2RQKCTM6-DfZ4YYXU.js} +1 -1
  145. package/dist/client/assets/{yaml-8lMTQUH5.js → yaml-DanwOypk.js} +1 -1
  146. package/dist/client/index.html +2 -2
  147. package/dist/comment-format-B5AcGcR-.mjs +118 -0
  148. package/dist/comment-format-CKTt0fzi.mjs +113 -0
  149. package/dist/comment-format-DG_PAehC.mjs +117 -0
  150. package/dist/completions-ZSKYvW06.mjs +126 -0
  151. package/dist/diff-fingerprint-CWa-soYD.mjs +78 -0
  152. package/dist/doctor-q6oA64hm.mjs +195 -0
  153. package/dist/find-tui-binary-CRpbYXLC.mjs +52 -0
  154. package/dist/git-Czo96ymM.mjs +789 -0
  155. package/dist/git-DaP_1rVy.mjs +2 -0
  156. package/dist/github-C9GLNak7.mjs +2 -0
  157. package/dist/github-HfIlIS-J.mjs +525 -0
  158. package/dist/mcp-7eXATtez.mjs +1334 -0
  159. package/dist/mcp-BBk8AIO4.mjs +1334 -0
  160. package/dist/mcp-BJxrW9dS.mjs +1334 -0
  161. package/dist/mcp-BhT5GgYF.mjs +1334 -0
  162. package/dist/mcp-BsGdNA88.mjs +1334 -0
  163. package/dist/mcp-Ca9QAlJ0.mjs +1334 -0
  164. package/dist/mcp-eor39qmD.mjs +1352 -0
  165. package/dist/plan-format-BQyx--mp.mjs +144 -0
  166. package/dist/plan-format-Bi46QS0m.mjs +132 -0
  167. package/dist/review-export-BoV0884M.mjs +66 -0
  168. package/dist/review-export-CKTI5Od_.mjs +66 -0
  169. package/dist/review-export-DjxKBeIZ.mjs +66 -0
  170. package/dist/server-AisDKkpW.mjs +3227 -0
  171. package/dist/server-BUsRhL1B.mjs +3283 -0
  172. package/dist/server-Bc2m9R5-.mjs +3263 -0
  173. package/dist/server-C105rwQw.mjs +3283 -0
  174. package/dist/server-D0Ni8PKP.mjs +3252 -0
  175. package/dist/server-TOElOuNP.mjs +3258 -0
  176. package/dist/server-lock-uqSdDYeR.mjs +153 -0
  177. package/dist/settings-BVnzGFL7.mjs +478 -0
  178. package/dist/update-check-fe0tR8tx.mjs +129 -0
  179. package/package.json +1 -1
  180. package/dist/client/assets/channel-Br3gV-0C.js +0 -1
  181. package/dist/client/assets/chunk-QZHKN3VN-yNyHmFLj.js +0 -1
  182. package/dist/client/assets/chunk-WU5MYG2G-DOSgjhZV.js +0 -1
  183. package/dist/client/assets/classDiagram-4FO5ZUOK-BV8x1oiD.js +0 -1
  184. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-AibFxRy2.js +0 -1
  185. package/dist/client/assets/index-CkjX2qPW.css +0 -1
  186. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DczGQieS.js +0 -1
@@ -0,0 +1,150 @@
1
+ import { t as formatComments } from "./comment-format-CKTt0fzi.mjs";
2
+ import { i as readServerLock, r as isLockAlive } from "./server-lock-uqSdDYeR.mjs";
3
+ import { parseArgs } from "node:util";
4
+ //#region src/cli-gh.ts
5
+ /**
6
+ * `diffing gh …` — the headless / port-agnostic surface for the PR review
7
+ * mode. Mirrors the shape of the local review CLI: each subcommand resolves
8
+ * the running server from the per-repo lockfile and talks to it via
9
+ * localhost HTTP. No port ever leaves the lockfile.
10
+ *
11
+ * diffing gh pr-fetch <ref> → GET /api/gh/pr/init then dump
12
+ * diffing gh pr-review → POST /api/gh/submit (current session)
13
+ * diffing gh pr-list-comments → GET /api/gh/pr-session/comments (XML)
14
+ * diffing gh status → GET /api/gh/session (one-line summary)
15
+ */
16
+ const EXIT_OK = 0;
17
+ const EXIT_NO_SERVER = 3;
18
+ const EXIT_NOT_FOUND = 4;
19
+ const EXIT_USAGE = 5;
20
+ function baseUrl() {
21
+ const lock = readServerLock();
22
+ if (!lock || !isLockAlive(lock)) {
23
+ console.error("No diffing server running for this repo. Start one with `diffing \"gh pr <ref>\"`.");
24
+ process.exit(EXIT_NO_SERVER);
25
+ }
26
+ return `http://${lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host}:${lock.port}`;
27
+ }
28
+ async function ghStatus() {
29
+ const base = baseUrl();
30
+ const res = await fetch(`${base}/api/gh/session`);
31
+ if (res.status === 404) {
32
+ console.error("No active PR session. Start one with `diffing \"gh pr <ref>\"`.");
33
+ return EXIT_NOT_FOUND;
34
+ }
35
+ const s = await res.json();
36
+ const submittedLine = s.submittedAt ? `submitted at ${new Date(s.submittedAt).toISOString()} → ${s.submittedReviewUrl ?? "(no url)"}` : "not submitted yet";
37
+ console.log(`${s.owner}/${s.repo}#${s.pullNumber} ${s.title}`);
38
+ console.log(` url: ${s.url}`);
39
+ console.log(` author: ${s.author?.login ?? "(unknown)"}`);
40
+ console.log(` +${s.additions} -${s.deletions} (${s.changedFiles} files)`);
41
+ console.log(` head: ${s.headSha.slice(0, 7)}`);
42
+ console.log(` base: ${s.baseSha.slice(0, 7)}`);
43
+ console.log(` existing: ${s.existingComments?.length ?? 0} review comments (read-only context)`);
44
+ console.log(` new: ${s.comments?.length ?? 0} comments in this session`);
45
+ console.log(` status: ${submittedLine}`);
46
+ return EXIT_OK;
47
+ }
48
+ async function ghPrFetch(args) {
49
+ const { values, positionals } = parseArgs({
50
+ args,
51
+ options: { json: { type: "boolean" } },
52
+ allowPositionals: true
53
+ });
54
+ const ref = positionals[0];
55
+ if (!ref) {
56
+ console.error("Usage: diffing gh pr-fetch <ref> [--json]");
57
+ return EXIT_USAGE;
58
+ }
59
+ const base = baseUrl();
60
+ let res = await fetch(`${base}/api/gh/pr/refresh`, { method: "POST" });
61
+ if (res.status === 404) res = await fetch(`${base}/api/gh/pr/init`, {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({ ref })
65
+ });
66
+ if (!res.ok) {
67
+ const err = await res.json().catch(() => ({}));
68
+ console.error(`Failed to fetch PR: ${err.error ?? res.statusText}`);
69
+ return 1;
70
+ }
71
+ const sessionRes = await fetch(`${base}/api/gh/session`);
72
+ const result = sessionRes.ok ? await sessionRes.json() : await res.json();
73
+ if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
74
+ else console.log(`${result.owner}/${result.repo}#${result.pullNumber} ${result.url}`);
75
+ return EXIT_OK;
76
+ }
77
+ async function ghPrListComments() {
78
+ const base = baseUrl();
79
+ const res = await fetch(`${base}/api/gh/pr-session/comments`);
80
+ if (res.status === 404) {
81
+ console.error("No active PR session.");
82
+ return EXIT_NOT_FOUND;
83
+ }
84
+ const comments = await res.json();
85
+ process.stdout.write(formatComments(comments) + "\n");
86
+ return EXIT_OK;
87
+ }
88
+ async function ghPrReview(args) {
89
+ const { values } = parseArgs({
90
+ args,
91
+ options: {
92
+ decision: {
93
+ type: "string",
94
+ short: "d"
95
+ },
96
+ body: {
97
+ type: "string",
98
+ short: "b"
99
+ },
100
+ "dry-run": { type: "boolean" },
101
+ json: { type: "boolean" }
102
+ },
103
+ allowPositionals: false
104
+ });
105
+ const decision = values.decision;
106
+ if (decision !== "approve" && decision !== "comment" && decision !== "request-changes" && decision !== "draft") {
107
+ console.error("Usage: diffing gh pr-review --decision <approve|comment|request-changes|draft> [--body <text>] [--dry-run]");
108
+ return EXIT_USAGE;
109
+ }
110
+ const base = baseUrl();
111
+ const payload = {
112
+ decision,
113
+ body: values.body ?? "",
114
+ dryRun: values["dry-run"] === true
115
+ };
116
+ const res = await fetch(`${base}/api/gh/submit`, {
117
+ method: "POST",
118
+ headers: { "Content-Type": "application/json" },
119
+ body: JSON.stringify(payload)
120
+ });
121
+ if (!res.ok) {
122
+ const err = await res.json().catch(() => ({}));
123
+ console.error(`Failed to submit review: ${err.error ?? res.statusText}`);
124
+ return 1;
125
+ }
126
+ const result = await res.json();
127
+ if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
128
+ else if (result.ok) if (result.dryRun) console.log("Dry run OK — payload would have been accepted by GitHub.");
129
+ else console.log(`Review submitted via ${result.authSource}: ${result.reviewUrl ?? `#${result.reviewId}`}`);
130
+ else {
131
+ console.error(`Submit failed (auth=${result.authSource}): ${result.error ?? "unknown error"}`);
132
+ return 1;
133
+ }
134
+ return EXIT_OK;
135
+ }
136
+ async function runGhSubcommand(args) {
137
+ const action = args[0];
138
+ const rest = args.slice(1);
139
+ switch (action) {
140
+ case "status": return ghStatus();
141
+ case "pr-fetch": return ghPrFetch(rest);
142
+ case "pr-review": return ghPrReview(rest);
143
+ case "pr-list-comments": return ghPrListComments();
144
+ default:
145
+ console.error("Usage: diffing gh <status|pr-fetch|pr-review|pr-list-comments> [...]");
146
+ return EXIT_USAGE;
147
+ }
148
+ }
149
+ //#endregion
150
+ export { runGhSubcommand };
@@ -0,0 +1,150 @@
1
+ import { t as formatComments } from "./comment-format-B5AcGcR-.mjs";
2
+ import { i as readServerLock, r as isLockAlive } from "./server-lock-uqSdDYeR.mjs";
3
+ import { parseArgs } from "node:util";
4
+ //#region src/cli-gh.ts
5
+ /**
6
+ * `diffing gh …` — the headless / port-agnostic surface for the PR review
7
+ * mode. Mirrors the shape of the local review CLI: each subcommand resolves
8
+ * the running server from the per-repo lockfile and talks to it via
9
+ * localhost HTTP. No port ever leaves the lockfile.
10
+ *
11
+ * diffing gh pr-fetch <ref> → GET /api/gh/pr/init then dump
12
+ * diffing gh pr-review → POST /api/gh/submit (current session)
13
+ * diffing gh pr-list-comments → GET /api/gh/pr-session/comments (XML)
14
+ * diffing gh status → GET /api/gh/session (one-line summary)
15
+ */
16
+ const EXIT_OK = 0;
17
+ const EXIT_NO_SERVER = 3;
18
+ const EXIT_NOT_FOUND = 4;
19
+ const EXIT_USAGE = 5;
20
+ function baseUrl() {
21
+ const lock = readServerLock();
22
+ if (!lock || !isLockAlive(lock)) {
23
+ console.error("No diffing server running for this repo. Start one with `diffing \"gh pr <ref>\"`.");
24
+ process.exit(EXIT_NO_SERVER);
25
+ }
26
+ return `http://${lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host}:${lock.port}`;
27
+ }
28
+ async function ghStatus() {
29
+ const base = baseUrl();
30
+ const res = await fetch(`${base}/api/gh/session`);
31
+ if (res.status === 404) {
32
+ console.error("No active PR session. Start one with `diffing \"gh pr <ref>\"`.");
33
+ return EXIT_NOT_FOUND;
34
+ }
35
+ const s = await res.json();
36
+ const submittedLine = s.submittedAt ? `submitted at ${new Date(s.submittedAt).toISOString()} → ${s.submittedReviewUrl ?? "(no url)"}` : "not submitted yet";
37
+ console.log(`${s.owner}/${s.repo}#${s.pullNumber} ${s.title}`);
38
+ console.log(` url: ${s.url}`);
39
+ console.log(` author: ${s.author?.login ?? "(unknown)"}`);
40
+ console.log(` +${s.additions} -${s.deletions} (${s.changedFiles} files)`);
41
+ console.log(` head: ${s.headSha.slice(0, 7)}`);
42
+ console.log(` base: ${s.baseSha.slice(0, 7)}`);
43
+ console.log(` existing: ${s.existingComments?.length ?? 0} review comments (read-only context)`);
44
+ console.log(` new: ${s.comments?.length ?? 0} comments in this session`);
45
+ console.log(` status: ${submittedLine}`);
46
+ return EXIT_OK;
47
+ }
48
+ async function ghPrFetch(args) {
49
+ const { values, positionals } = parseArgs({
50
+ args,
51
+ options: { json: { type: "boolean" } },
52
+ allowPositionals: true
53
+ });
54
+ const ref = positionals[0];
55
+ if (!ref) {
56
+ console.error("Usage: diffing gh pr-fetch <ref> [--json]");
57
+ return EXIT_USAGE;
58
+ }
59
+ const base = baseUrl();
60
+ let res = await fetch(`${base}/api/gh/pr/refresh`, { method: "POST" });
61
+ if (res.status === 404) res = await fetch(`${base}/api/gh/pr/init`, {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({ ref })
65
+ });
66
+ if (!res.ok) {
67
+ const err = await res.json().catch(() => ({}));
68
+ console.error(`Failed to fetch PR: ${err.error ?? res.statusText}`);
69
+ return 1;
70
+ }
71
+ const sessionRes = await fetch(`${base}/api/gh/session`);
72
+ const result = sessionRes.ok ? await sessionRes.json() : await res.json();
73
+ if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
74
+ else console.log(`${result.owner}/${result.repo}#${result.pullNumber} ${result.url}`);
75
+ return EXIT_OK;
76
+ }
77
+ async function ghPrListComments() {
78
+ const base = baseUrl();
79
+ const res = await fetch(`${base}/api/gh/pr-session/comments`);
80
+ if (res.status === 404) {
81
+ console.error("No active PR session.");
82
+ return EXIT_NOT_FOUND;
83
+ }
84
+ const comments = await res.json();
85
+ process.stdout.write(formatComments(comments) + "\n");
86
+ return EXIT_OK;
87
+ }
88
+ async function ghPrReview(args) {
89
+ const { values } = parseArgs({
90
+ args,
91
+ options: {
92
+ decision: {
93
+ type: "string",
94
+ short: "d"
95
+ },
96
+ body: {
97
+ type: "string",
98
+ short: "b"
99
+ },
100
+ "dry-run": { type: "boolean" },
101
+ json: { type: "boolean" }
102
+ },
103
+ allowPositionals: false
104
+ });
105
+ const decision = values.decision;
106
+ if (decision !== "approve" && decision !== "comment" && decision !== "request-changes" && decision !== "draft") {
107
+ console.error("Usage: diffing gh pr-review --decision <approve|comment|request-changes|draft> [--body <text>] [--dry-run]");
108
+ return EXIT_USAGE;
109
+ }
110
+ const base = baseUrl();
111
+ const payload = {
112
+ decision,
113
+ body: values.body ?? "",
114
+ dryRun: values["dry-run"] === true
115
+ };
116
+ const res = await fetch(`${base}/api/gh/submit`, {
117
+ method: "POST",
118
+ headers: { "Content-Type": "application/json" },
119
+ body: JSON.stringify(payload)
120
+ });
121
+ if (!res.ok) {
122
+ const err = await res.json().catch(() => ({}));
123
+ console.error(`Failed to submit review: ${err.error ?? res.statusText}`);
124
+ return 1;
125
+ }
126
+ const result = await res.json();
127
+ if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
128
+ else if (result.ok) if (result.dryRun) console.log("Dry run OK — payload would have been accepted by GitHub.");
129
+ else console.log(`Review submitted via ${result.authSource}: ${result.reviewUrl ?? `#${result.reviewId}`}`);
130
+ else {
131
+ console.error(`Submit failed (auth=${result.authSource}): ${result.error ?? "unknown error"}`);
132
+ return 1;
133
+ }
134
+ return EXIT_OK;
135
+ }
136
+ async function runGhSubcommand(args) {
137
+ const action = args[0];
138
+ const rest = args.slice(1);
139
+ switch (action) {
140
+ case "status": return ghStatus();
141
+ case "pr-fetch": return ghPrFetch(rest);
142
+ case "pr-review": return ghPrReview(rest);
143
+ case "pr-list-comments": return ghPrListComments();
144
+ default:
145
+ console.error("Usage: diffing gh <status|pr-fetch|pr-review|pr-list-comments> [...]");
146
+ return EXIT_USAGE;
147
+ }
148
+ }
149
+ //#endregion
150
+ export { runGhSubcommand };
@@ -0,0 +1,150 @@
1
+ import { t as formatComments } from "./comment-format-DG_PAehC.mjs";
2
+ import { i as readServerLock, r as isLockAlive } from "./server-lock-uqSdDYeR.mjs";
3
+ import { parseArgs } from "node:util";
4
+ //#region src/cli-gh.ts
5
+ /**
6
+ * `diffing gh …` — the headless / port-agnostic surface for the PR review
7
+ * mode. Mirrors the shape of the local review CLI: each subcommand resolves
8
+ * the running server from the per-repo lockfile and talks to it via
9
+ * localhost HTTP. No port ever leaves the lockfile.
10
+ *
11
+ * diffing gh pr-fetch <ref> → GET /api/gh/pr/init then dump
12
+ * diffing gh pr-review → POST /api/gh/submit (current session)
13
+ * diffing gh pr-list-comments → GET /api/gh/pr-session/comments (XML)
14
+ * diffing gh status → GET /api/gh/session (one-line summary)
15
+ */
16
+ const EXIT_OK = 0;
17
+ const EXIT_NO_SERVER = 3;
18
+ const EXIT_NOT_FOUND = 4;
19
+ const EXIT_USAGE = 5;
20
+ function baseUrl() {
21
+ const lock = readServerLock();
22
+ if (!lock || !isLockAlive(lock)) {
23
+ console.error("No diffing server running for this repo. Start one with `diffing \"gh pr <ref>\"`.");
24
+ process.exit(EXIT_NO_SERVER);
25
+ }
26
+ return `http://${lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host}:${lock.port}`;
27
+ }
28
+ async function ghStatus() {
29
+ const base = baseUrl();
30
+ const res = await fetch(`${base}/api/gh/session`);
31
+ if (res.status === 404) {
32
+ console.error("No active PR session. Start one with `diffing \"gh pr <ref>\"`.");
33
+ return EXIT_NOT_FOUND;
34
+ }
35
+ const s = await res.json();
36
+ const submittedLine = s.submittedAt ? `submitted at ${new Date(s.submittedAt).toISOString()} → ${s.submittedReviewUrl ?? "(no url)"}` : "not submitted yet";
37
+ console.log(`${s.owner}/${s.repo}#${s.pullNumber} ${s.title}`);
38
+ console.log(` url: ${s.url}`);
39
+ console.log(` author: ${s.author?.login ?? "(unknown)"}`);
40
+ console.log(` +${s.additions} -${s.deletions} (${s.changedFiles} files)`);
41
+ console.log(` head: ${s.headSha.slice(0, 7)}`);
42
+ console.log(` base: ${s.baseSha.slice(0, 7)}`);
43
+ console.log(` existing: ${s.existingComments?.length ?? 0} review comments (read-only context)`);
44
+ console.log(` new: ${s.comments?.length ?? 0} comments in this session`);
45
+ console.log(` status: ${submittedLine}`);
46
+ return EXIT_OK;
47
+ }
48
+ async function ghPrFetch(args) {
49
+ const { values, positionals } = parseArgs({
50
+ args,
51
+ options: { json: { type: "boolean" } },
52
+ allowPositionals: true
53
+ });
54
+ const ref = positionals[0];
55
+ if (!ref) {
56
+ console.error("Usage: diffing gh pr-fetch <ref> [--json]");
57
+ return EXIT_USAGE;
58
+ }
59
+ const base = baseUrl();
60
+ let res = await fetch(`${base}/api/gh/pr/refresh`, { method: "POST" });
61
+ if (res.status === 404) res = await fetch(`${base}/api/gh/pr/init`, {
62
+ method: "POST",
63
+ headers: { "Content-Type": "application/json" },
64
+ body: JSON.stringify({ ref })
65
+ });
66
+ if (!res.ok) {
67
+ const err = await res.json().catch(() => ({}));
68
+ console.error(`Failed to fetch PR: ${err.error ?? res.statusText}`);
69
+ return 1;
70
+ }
71
+ const sessionRes = await fetch(`${base}/api/gh/session`);
72
+ const result = sessionRes.ok ? await sessionRes.json() : await res.json();
73
+ if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
74
+ else console.log(`${result.owner}/${result.repo}#${result.pullNumber} ${result.url}`);
75
+ return EXIT_OK;
76
+ }
77
+ async function ghPrListComments() {
78
+ const base = baseUrl();
79
+ const res = await fetch(`${base}/api/gh/pr-session/comments`);
80
+ if (res.status === 404) {
81
+ console.error("No active PR session.");
82
+ return EXIT_NOT_FOUND;
83
+ }
84
+ const comments = await res.json();
85
+ process.stdout.write(formatComments(comments) + "\n");
86
+ return EXIT_OK;
87
+ }
88
+ async function ghPrReview(args) {
89
+ const { values } = parseArgs({
90
+ args,
91
+ options: {
92
+ decision: {
93
+ type: "string",
94
+ short: "d"
95
+ },
96
+ body: {
97
+ type: "string",
98
+ short: "b"
99
+ },
100
+ "dry-run": { type: "boolean" },
101
+ json: { type: "boolean" }
102
+ },
103
+ allowPositionals: false
104
+ });
105
+ const decision = values.decision;
106
+ if (decision !== "approve" && decision !== "comment" && decision !== "request-changes" && decision !== "draft") {
107
+ console.error("Usage: diffing gh pr-review --decision <approve|comment|request-changes|draft> [--body <text>] [--dry-run]");
108
+ return EXIT_USAGE;
109
+ }
110
+ const base = baseUrl();
111
+ const payload = {
112
+ decision,
113
+ body: values.body ?? "",
114
+ dryRun: values["dry-run"] === true
115
+ };
116
+ const res = await fetch(`${base}/api/gh/submit`, {
117
+ method: "POST",
118
+ headers: { "Content-Type": "application/json" },
119
+ body: JSON.stringify(payload)
120
+ });
121
+ if (!res.ok) {
122
+ const err = await res.json().catch(() => ({}));
123
+ console.error(`Failed to submit review: ${err.error ?? res.statusText}`);
124
+ return 1;
125
+ }
126
+ const result = await res.json();
127
+ if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
128
+ else if (result.ok) if (result.dryRun) console.log("Dry run OK — payload would have been accepted by GitHub.");
129
+ else console.log(`Review submitted via ${result.authSource}: ${result.reviewUrl ?? `#${result.reviewId}`}`);
130
+ else {
131
+ console.error(`Submit failed (auth=${result.authSource}): ${result.error ?? "unknown error"}`);
132
+ return 1;
133
+ }
134
+ return EXIT_OK;
135
+ }
136
+ async function runGhSubcommand(args) {
137
+ const action = args[0];
138
+ const rest = args.slice(1);
139
+ switch (action) {
140
+ case "status": return ghStatus();
141
+ case "pr-fetch": return ghPrFetch(rest);
142
+ case "pr-review": return ghPrReview(rest);
143
+ case "pr-list-comments": return ghPrListComments();
144
+ default:
145
+ console.error("Usage: diffing gh <status|pr-fetch|pr-review|pr-list-comments> [...]");
146
+ return EXIT_USAGE;
147
+ }
148
+ }
149
+ //#endregion
150
+ export { runGhSubcommand };
package/dist/cli.mjs CHANGED
@@ -1,7 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { c as printHelp, i as validateEnvironment, n as loadSettings, o as intoShowMode, r as runTerminalDiff, s as parseDiffOptions, t as startServer } from "./server-BZBFquG8.mjs";
3
- import { i as readServerLock, n as diffScopeKey, o as removeServerLockIfOwned, r as isLockAlive, s as writeServerLock, t as acquireServerStartupLease, v as getRepoRoot } from "./server-lock-DaSx7DjW.mjs";
4
- import { execFileSync, spawn } from "node:child_process";
2
+ import { a as intoShowMode, n as runTerminalDiff, o as parseDiffOptions, r as validateEnvironment, s as printHelp, t as startServer } from "./server-C105rwQw.mjs";
3
+ import { p as getRepoRoot } from "./git-Czo96ymM.mjs";
4
+ import { t as loadSettings } from "./settings-BVnzGFL7.mjs";
5
+ import { i as readServerLock, n as diffScopeKey, o as removeServerLockIfOwned, r as isLockAlive, s as writeServerLock, t as acquireServerStartupLease } from "./server-lock-uqSdDYeR.mjs";
6
+ import { t as findTuiBinary$1 } from "./find-tui-binary-CRpbYXLC.mjs";
7
+ import { spawn } from "node:child_process";
5
8
  import { randomUUID } from "node:crypto";
6
9
  import { fileURLToPath } from "node:url";
7
10
  import { dirname, isAbsolute, resolve } from "node:path";
@@ -391,53 +394,6 @@ function playStartupDisplay() {
391
394
  })();
392
395
  }
393
396
  //#endregion
394
- //#region src/lib/find-tui-binary.ts
395
- /**
396
- * Locate the `diffing-tui` native binary. Looks, in order:
397
- * 1. Sibling of the calling module (`dist/diffing-tui[.exe]` after build).
398
- * 2. `bin/diffing-tui[.exe]` next to the package root.
399
- * 3. `target/release/diffing-tui[.exe]` next to the package root
400
- * (cargo release build).
401
- * 4. `target/debug/diffing-tui[.exe]` next to the package root
402
- * (cargo debug build — the common case during development, especially
403
- * on Windows where release builds are slow).
404
- * 5. `$PATH` lookup via `which` / `where`.
405
- *
406
- * Returns the absolute path of the first match, or `null` if none are found.
407
- *
408
- * `callerUrl` is the `import.meta.url` of the caller — pass `import.meta.url`
409
- * from `cli.ts`. Exposed as a parameter so unit tests can pin the search
410
- * root to a known location instead of depending on the test runner's CWD.
411
- */
412
- function findTuiBinary$1(callerUrl) {
413
- const ext = process.platform === "win32" ? ".exe" : "";
414
- const here = dirname(fileURLToPath(callerUrl));
415
- const candidates = [
416
- resolve(here, `diffing-tui${ext}`),
417
- resolve(here, "..", "bin", `diffing-tui${ext}`),
418
- resolve(here, "..", "target", "release", `diffing-tui${ext}`),
419
- resolve(here, "..", "..", "target", "release", `diffing-tui${ext}`),
420
- resolve(here, "..", "target", "debug", `diffing-tui${ext}`),
421
- resolve(here, "..", "..", "target", "debug", `diffing-tui${ext}`)
422
- ];
423
- for (const c of candidates) if (existsSync(c)) return c;
424
- try {
425
- const out = execFileSync(process.platform === "win32" ? "where" : "which", ["diffing-tui"], {
426
- encoding: "utf-8",
427
- stdio: [
428
- "ignore",
429
- "pipe",
430
- "ignore"
431
- ]
432
- }).trim();
433
- if (out) {
434
- const first = out.split(/\r?\n/)[0]?.trim();
435
- if (first && isAbsolute(first)) return first;
436
- }
437
- } catch {}
438
- return null;
439
- }
440
- //#endregion
441
397
  //#region src/cli.ts
442
398
  const args = process.argv.slice(2);
443
399
  let prRef = null;
@@ -457,12 +413,18 @@ if (new Set([
457
413
  "await-review",
458
414
  "reply",
459
415
  "resolve",
416
+ "unresolve",
417
+ "comment",
460
418
  "comments",
461
419
  "url",
462
420
  "mcp",
463
421
  "plan",
464
422
  "update",
465
- "gh"
423
+ "gh",
424
+ "doctor",
425
+ "completion",
426
+ "progress",
427
+ "inspect"
466
428
  ]).has(args[0])) {
467
429
  if (args[0] === "mcp") {
468
430
  const mcpArgs = args.slice(1);
@@ -471,10 +433,16 @@ if (new Set([
471
433
 
472
434
  Run diffing as a local stdio MCP server bound to one Git repository.
473
435
 
436
+ The server advertises session, diff inspection, comment lifecycle, plan
437
+ review, progress, and history tools. Prefer MCP when the harness exposes
438
+ it; otherwise use the CLI mirrors (await-review, comments, plan, …).
439
+
474
440
  Options:
475
441
  --repo <path> Bind to this absolute Git repository path.
476
442
  If omitted, the Git repository containing the current directory is used.
477
- -h, --help Show this help.`);
443
+ -h, --help Show this help.
444
+
445
+ See docs/cli.md §5 (MCP) for the full tool table.`);
478
446
  process.exit(0);
479
447
  }
480
448
  let repoPath;
@@ -507,11 +475,11 @@ Options:
507
475
  console.error("diffing mcp: --repo must be an absolute path");
508
476
  process.exit(5);
509
477
  }
510
- const { startMcpServer } = await import("./mcp-BgZO-iXI.mjs");
478
+ const { startMcpServer } = await import("./mcp-eor39qmD.mjs");
511
479
  await startMcpServer({ repoPath });
512
480
  await new Promise(() => {});
513
481
  }
514
- const { runSubcommand } = await import("./cli-agent-BkkRbKqq.mjs");
482
+ const { runSubcommand } = await import("./cli-agent-D71pq2ep.mjs");
515
483
  process.exit(await runSubcommand(args[0], args.slice(1)));
516
484
  }
517
485
  let showSubcommand = false;
@@ -520,6 +488,7 @@ if (args[0] === "show") {
520
488
  args.shift();
521
489
  }
522
490
  const opts = parseDiffOptions(args);
491
+ if (!prRef && opts.ghPr) prRef = opts.ghPr;
523
492
  if (showSubcommand) {
524
493
  if (opts.revisions.length === 0 && !opts.help && !opts.version) {
525
494
  console.error("Usage: diffing show <revspec>... [-- <pathspec>...]");
@@ -554,7 +523,7 @@ const __pkgDir = dirname(fileURLToPath(import.meta.url));
554
523
  const currentVersion = JSON.parse(readFileSync(resolve(__pkgDir, "..", "package.json"), "utf-8")).version;
555
524
  const updateCheckPromise = (async () => {
556
525
  try {
557
- const { checkForUpdates } = await import("./update-check-CXeSZANo.mjs");
526
+ const { checkForUpdates } = await import("./update-check-fe0tR8tx.mjs");
558
527
  return await checkForUpdates(currentVersion);
559
528
  } catch {
560
529
  return null;
@@ -564,6 +533,7 @@ const port = await getPort(opts.port ? { port: opts.port } : void 0);
564
533
  const host = opts.host;
565
534
  const clientDir = resolve(__pkgDir, "client");
566
535
  const resolvedClientDir = existsSync(clientDir) ? clientDir : resolve(process.cwd(), "dist/client");
536
+ const openModulePromise = opts.noOpen ? null : import("open");
567
537
  let repoRoot;
568
538
  try {
569
539
  repoRoot = getRepoRoot();
@@ -616,23 +586,25 @@ try {
616
586
  startupLease.release();
617
587
  const localUrl = `http://${host}:${actualPort}`;
618
588
  console.log(`diffing server running at ${localUrl}`);
619
- await playStartupDisplay();
620
- try {
621
- const updateInfo = await updateCheckPromise;
622
- if (updateInfo?.hasUpdate) {
623
- const { printUpdateDisclaimer } = await import("./update-check-CXeSZANo.mjs");
624
- printUpdateDisclaimer(currentVersion, updateInfo.latestVersion);
625
- }
626
- } catch {}
627
- if (!opts.noOpen) {
589
+ if (openModulePromise) try {
628
590
  const settings = loadSettings();
629
- const openUrl = `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${actualPort}`;
630
- const openModule = await import("open");
591
+ const openUrl = `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${actualPort}${prMode ? "/gh/pr" : ""}`;
592
+ const openModule = await openModulePromise;
631
593
  let appName;
632
594
  if (settings.browser) appName = openModule.apps[settings.browser] || settings.browser;
633
595
  const options = appName ? { app: { name: appName } } : {};
634
596
  openModule.default(openUrl, options);
597
+ } catch (err) {
598
+ console.error("Failed to open browser:", err instanceof Error ? err.message : err);
635
599
  }
600
+ playStartupDisplay();
601
+ try {
602
+ const updateInfo = await updateCheckPromise;
603
+ if (updateInfo?.hasUpdate) {
604
+ const { printUpdateDisclaimer } = await import("./update-check-fe0tR8tx.mjs");
605
+ printUpdateDisclaimer(currentVersion, updateInfo.latestVersion);
606
+ }
607
+ } catch {}
636
608
  const shutdown = () => {
637
609
  console.log("\nShutting down...");
638
610
  removeServerLockIfOwned(repoRoot, process.pid, sessionOwnerId);