diffing 0.2.1 → 0.3.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 (432) hide show
  1. package/README.md +158 -1
  2. package/dist/{cli-agent-ZAkixf4c.mjs → cli-agent-KxNAFIPf.mjs} +6 -2
  3. package/dist/cli-gh-CDGSpndZ.mjs +147 -0
  4. package/dist/cli.mjs +1064 -44
  5. package/dist/client/assets/{angular-html-DsssUIMZ.js → angular-html-DbbrJavS.js} +1 -1
  6. package/dist/client/assets/{angular-ts-dTg-sJ77.js → angular-ts-tCrxb1ht.js} +1 -1
  7. package/dist/client/assets/{apl-C1yUKbqz.js → apl-DawII0w7.js} +1 -1
  8. package/dist/client/assets/arc-DIRV7ZXr.js +1 -0
  9. package/dist/client/assets/architecture-7EHR7CIX-BM5HxebS.js +1 -0
  10. package/dist/client/assets/architectureDiagram-3BPJPVTR-3IoH78OV.js +36 -0
  11. package/dist/client/assets/array-CkF66D10.js +1 -0
  12. package/dist/client/assets/{astro-BI07ha2y.js → astro-DIyGTFXc.js} +1 -1
  13. package/dist/client/assets/{blade-DkzUGffS.js → blade-CuF4Z1mP.js} +1 -1
  14. package/dist/client/assets/blockDiagram-GPEHLZMM-CFxPndC0.js +132 -0
  15. package/dist/client/assets/{bsl-Dx5tFn3i.js → bsl-BrHd4RA2.js} +1 -1
  16. package/dist/client/assets/{c-KkuqqOvW.js → c-DUrjo9T5.js} +1 -1
  17. package/dist/client/assets/c4Diagram-AAUBKEIU-CGMBnkiv.js +10 -0
  18. package/dist/client/assets/{cairo-wCCQTdA9.js → cairo-BDZ6TRZS.js} +1 -1
  19. package/dist/client/assets/channel-D5AdjEWX.js +1 -0
  20. package/dist/client/assets/chunk-2J33WTMH-CJMBLaXy.js +1 -0
  21. package/dist/client/assets/chunk-3OPIFGDE-C9HQWVLl.js +62 -0
  22. package/dist/client/assets/chunk-4BX2VUAB-Qqg72GQd.js +1 -0
  23. package/dist/client/assets/chunk-4EGX6M5U-C70lfA2p.js +1 -0
  24. package/dist/client/assets/chunk-55IACEB6-DZF8brTR.js +1 -0
  25. package/dist/client/assets/chunk-5DO6E6H7-PprNUwlI.js +1 -0
  26. package/dist/client/assets/chunk-5ZQYHXKU-BflVFV5z.js +2 -0
  27. package/dist/client/assets/chunk-727SXJPM-COn6BRLY.js +206 -0
  28. package/dist/client/assets/chunk-AQP2D5EJ-CNOjODUR.js +231 -0
  29. package/dist/client/assets/chunk-BR22UD5L-D8XCYMy9.js +1 -0
  30. package/dist/client/assets/chunk-BSJP7CBP-PQX4ASCI.js +1 -0
  31. package/dist/client/assets/chunk-CSCIHK7Q-BfmUvL-L.js +124 -0
  32. package/dist/client/assets/chunk-FHYWG6QK-CcHPrHH1.js +1 -0
  33. package/dist/client/assets/chunk-FMBD7UC4-DorfwLnQ.js +15 -0
  34. package/dist/client/assets/chunk-KSCS5N6A-CXY93mId.js +10 -0
  35. package/dist/client/assets/chunk-L5ZTLDWV-BjMrSVmH.js +1 -0
  36. package/dist/client/assets/chunk-LZXEDZCA-q8jj6Nyb.js +2 -0
  37. package/dist/client/assets/chunk-MPE355IW-Bf9yHfDS.js +1 -0
  38. package/dist/client/assets/chunk-MZUSXYTE-CnUIUKI4.js +1 -0
  39. package/dist/client/assets/chunk-N66VUXT2-ahAf9GvV.js +1 -0
  40. package/dist/client/assets/chunk-ND2GUHAM-BRRQbYHl.js +1 -0
  41. package/dist/client/assets/chunk-NNHCCRGN-DHF3V75i.js +159 -0
  42. package/dist/client/assets/chunk-NZK2D7GU-Czt1qHrO.js +1 -0
  43. package/dist/client/assets/chunk-O5CBEL6O-DEopURak.js +70 -0
  44. package/dist/client/assets/chunk-PUPMXCY4-D0KKIhut.js +1 -0
  45. package/dist/client/assets/chunk-QZHKN3VN-BE917fn9.js +1 -0
  46. package/dist/client/assets/chunk-UIBZB4QT-TYsZ_c8u.js +1 -0
  47. package/dist/client/assets/chunk-WCWK7LTN-Dj8SfnMU.js +1 -0
  48. package/dist/client/assets/chunk-WU5MYG2G-DdoWnPla.js +1 -0
  49. package/dist/client/assets/chunk-XPW4576I-DocCoKUT.js +32 -0
  50. package/dist/client/assets/classDiagram-4FO5ZUOK-CxjhKO7s.js +1 -0
  51. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CSScAAQ4.js +1 -0
  52. package/dist/client/assets/{cobol-DRh7-jLi.js → cobol-BylylR2x.js} +1 -1
  53. package/dist/client/assets/{coffee-wR_ZAh9a.js → coffee-DCKfk8xx.js} +1 -1
  54. package/dist/client/assets/cose-bilkent-S5V4N54A-Cm0BD5CS.js +1 -0
  55. package/dist/client/assets/{cpp-OD_qyywn.js → cpp-CfKCIrGK.js} +1 -1
  56. package/dist/client/assets/{crystal-E4ahAddE.js → crystal-v-9RIu3l.js} +1 -1
  57. package/dist/client/assets/{css-2NgE_uxz.js → css-XjlXeGmZ.js} +1 -1
  58. package/dist/client/assets/cytoscape.esm-B7MQoI9k.js +321 -0
  59. package/dist/client/assets/dagre-BM42HDAG-kqgFUaF1.js +4 -0
  60. package/dist/client/assets/dagre-DAhKikc0.js +1 -0
  61. package/dist/client/assets/defaultLocale-B_TxGd0k.js +1 -0
  62. package/dist/client/assets/diagram-2AECGRRQ-B3hBvGUc.js +43 -0
  63. package/dist/client/assets/diagram-5GNKFQAL-r8zU8C-Y.js +10 -0
  64. package/dist/client/assets/diagram-KO2AKTUF-CDWD5zkZ.js +3 -0
  65. package/dist/client/assets/diagram-LMA3HP47-CRRfS6RD.js +24 -0
  66. package/dist/client/assets/diagram-OG6HWLK6-ChBS6E-K.js +24 -0
  67. package/dist/client/assets/dist-DUTeKbN7.js +1 -0
  68. package/dist/client/assets/{edge-8mbscxxD.js → edge-Cwh953i8.js} +1 -1
  69. package/dist/client/assets/{elixir-CJv1b3Q6.js → elixir-C4MgLzTj.js} +1 -1
  70. package/dist/client/assets/{elm-DUPzqZ9H.js → elm-CFBu8r7i.js} +1 -1
  71. package/dist/client/assets/erDiagram-TEJ5UH35-_03Fb9RH.js +85 -0
  72. package/dist/client/assets/{erb-ssvEF26z.js → erb-CrCna7R1.js} +1 -1
  73. package/dist/client/assets/{erlang-CtK0kQ6z.js → erlang-cuhwpmsu.js} +1 -1
  74. package/dist/client/assets/eventmodeling-FCH6USID-hlXE2E34.js +1 -0
  75. package/dist/client/assets/flowDiagram-I6XJVG4X-D9pSaH_8.js +162 -0
  76. package/dist/client/assets/{fortran-fixed-form-DBM4e0_k.js → fortran-fixed-form-DWr0EnJn.js} +1 -1
  77. package/dist/client/assets/{fsharp-CmzzGQLe.js → fsharp-CQ5iYSPA.js} +1 -1
  78. package/dist/client/assets/ganttDiagram-6RSMTGT7-DKBfXY9D.js +292 -0
  79. package/dist/client/assets/{gdresource-B_wbPqHd.js → gdresource-CN-lsNu5.js} +1 -1
  80. package/dist/client/assets/{git-commit-1z4D6NzL.js → git-commit-6e79eN7Q.js} +1 -1
  81. package/dist/client/assets/{git-rebase-DiWIK1Oa.js → git-rebase-CExLk2dD.js} +1 -1
  82. package/dist/client/assets/gitGraph-WXDBUCRP-D_3ZhTam.js +1 -0
  83. package/dist/client/assets/gitGraphDiagram-PVQCEYII-BPQ2kpJA.js +106 -0
  84. package/dist/client/assets/{glimmer-js-DrHg6AuA.js → glimmer-js-wjBSKaMu.js} +1 -1
  85. package/dist/client/assets/{glimmer-ts-wQSGOa8A.js → glimmer-ts-CyjMXDgZ.js} +1 -1
  86. package/dist/client/assets/{glsl-OY27QGY0.js → glsl-CWOoN8or.js} +1 -1
  87. package/dist/client/assets/graphlib-DBdw4opr.js +1 -0
  88. package/dist/client/assets/{graphql-CSWSqe6f.js → graphql-DI5CB58U.js} +1 -1
  89. package/dist/client/assets/{hack-Bi1v624Q.js → hack-Ct_Cm7Pr.js} +1 -1
  90. package/dist/client/assets/{haml-CX94zV9m.js → haml-DzAjli8d.js} +1 -1
  91. package/dist/client/assets/{handlebars-C1j6wnjG.js → handlebars-BfJB0RYx.js} +1 -1
  92. package/dist/client/assets/{html-BcAjMlB7.js → html-CK8auhK8.js} +1 -1
  93. package/dist/client/assets/{html-derivative-DcEpOzdx.js → html-derivative-B7VntYnF.js} +1 -1
  94. package/dist/client/assets/{http-BBxxSc6S.js → http-_Zy71Sv3.js} +1 -1
  95. package/dist/client/assets/{hurl-CpKRNTz4.js → hurl-VbL4I95z.js} +1 -1
  96. package/dist/client/assets/{hxml-DC4KwKt2.js → hxml-nwJci6H5.js} +1 -1
  97. package/dist/client/assets/{index-CoZyJYkw.css → index-C3p7VKOX.css} +1 -1
  98. package/dist/client/assets/index-Dv9jPmOc.js +3921 -0
  99. package/dist/client/assets/info-J43DQDTF-CAllC7mK.js +1 -0
  100. package/dist/client/assets/infoDiagram-5YYISTIA-B5RN-4Ke.js +2 -0
  101. package/dist/client/assets/init-Ce66tIvf.js +1 -0
  102. package/dist/client/assets/ishikawaDiagram-YF4QCWOH-DpbSX3Zy.js +70 -0
  103. package/dist/client/assets/{java-CFUlLvAA.js → java-0CC2DnK9.js} +1 -1
  104. package/dist/client/assets/{javascript-C-HnT3sE.js → javascript-DKSTP7rz.js} +1 -1
  105. package/dist/client/assets/{jinja-CPU8RwNP.js → jinja-DoGBHNJ6.js} +1 -1
  106. package/dist/client/assets/{jison-CW0TBQOs.js → jison-Bnl3lPA2.js} +1 -1
  107. package/dist/client/assets/journeyDiagram-JHISSGLW-B_X4_qPO.js +139 -0
  108. package/dist/client/assets/{json-qUjlNuEJ.js → json-BQ3Ddj6g.js} +1 -1
  109. package/dist/client/assets/{jsx-KWeo60kf.js → jsx-C_aFDuFZ.js} +1 -1
  110. package/dist/client/assets/{julia-CnJB8y2e.js → julia-nIjp5yMR.js} +1 -1
  111. package/dist/client/assets/{just-Do22d9PP.js → just-zc4yJ46n.js} +1 -1
  112. package/dist/client/assets/kanban-definition-UN3LZRKU-BSs4C5DW.js +89 -0
  113. package/dist/client/assets/katex-eRFNlMh0.js +257 -0
  114. package/dist/client/assets/{latex-CCPgzvKn.js → latex-BszBC80j.js} +1 -1
  115. package/dist/client/assets/line-C9HWVwPi.js +1 -0
  116. package/dist/client/assets/linear-DatJfpKY.js +1 -0
  117. package/dist/client/assets/{liquid-B9btdZoI.js → liquid-DglQpTge.js} +1 -1
  118. package/dist/client/assets/{lua-IFRifurW.js → lua-BcbliFeR.js} +1 -1
  119. package/dist/client/assets/{marko-CCaVBFq1.js → marko-BPm4M8j-.js} +1 -1
  120. package/dist/client/assets/{mdc-BtbnOLUc.js → mdc-BNUj07UF.js} +1 -1
  121. package/dist/client/assets/mermaid-parser.core-BVEKlqQr.js +4 -0
  122. package/dist/client/assets/mermaid.core-DVis21V_.js +9 -0
  123. package/dist/client/assets/mindmap-definition-RKZ34NQL-Cuo7KewF.js +96 -0
  124. package/dist/client/assets/{nextflow-CApkvBGW.js → nextflow-DSfydIxt.js} +1 -1
  125. package/dist/client/assets/{nginx-BkbFZHVt.js → nginx-CSSJwkd6.js} +1 -1
  126. package/dist/client/assets/{nim-2uCd5j65.js → nim-nQAskwTR.js} +1 -1
  127. package/dist/client/assets/ordinal-5ziJS8mo.js +1 -0
  128. package/dist/client/assets/packet-YPE3B663-Dy58IAiO.js +1 -0
  129. package/dist/client/assets/path-g3G46IZB.js +1 -0
  130. package/dist/client/assets/{perl-C4ixqSNT.js → perl-CtH8xYH6.js} +1 -1
  131. package/dist/client/assets/{php-DJ8WOtcI.js → php-Dcc3T2PH.js} +1 -1
  132. package/dist/client/assets/pie-LRSECV5Y-FXFFfdz2.js +1 -0
  133. package/dist/client/assets/pieDiagram-4H26LBE5-BfpvCRmo.js +30 -0
  134. package/dist/client/assets/{pug-BOaafhT5.js → pug-BCLaymlV.js} +1 -1
  135. package/dist/client/assets/{qml-CURE-1y4.js → qml-BpKydcOi.js} +1 -1
  136. package/dist/client/assets/quadrantDiagram-W4KKPZXB-CJY6un0-.js +7 -0
  137. package/dist/client/assets/{r-CPWmgzo3.js → r-BzCB9dpd.js} +1 -1
  138. package/dist/client/assets/radar-GUYGQ44K-BKTzSQ68.js +1 -0
  139. package/dist/client/assets/{razor-DH83VP_d.js → razor-BWmujqiQ.js} +1 -1
  140. package/dist/client/assets/{regexp-BXVWi-t_.js → regexp-urCI3YiZ.js} +1 -1
  141. package/dist/client/assets/requirementDiagram-4Y6WPE33-DIHWguS0.js +84 -0
  142. package/dist/client/assets/rough.esm-BBrzuQ0N.js +1 -0
  143. package/dist/client/assets/{rst-Bbxxs6E2.js → rst-YTDC9H6u.js} +1 -1
  144. package/dist/client/assets/{ruby-C-TuWES4.js → ruby-v1IXQAFZ.js} +1 -1
  145. package/dist/client/assets/sankeyDiagram-5OEKKPKP-DJRPEO_F.js +40 -0
  146. package/dist/client/assets/{sas-njzNYNOq.js → sas-KDUG3BSk.js} +1 -1
  147. package/dist/client/assets/{scss-D2i6rHB8.js → scss-pLIGFpjD.js} +1 -1
  148. package/dist/client/assets/sequenceDiagram-3UESZ5HK-DX0jVCOU.js +162 -0
  149. package/dist/client/assets/{shaderlab-DXAhMdPo.js → shaderlab-CbbQwRPF.js} +1 -1
  150. package/dist/client/assets/{shellscript-D6Bxi40C.js → shellscript-B5ZTyEsK.js} +1 -1
  151. package/dist/client/assets/{shellsession-Defxq-I6.js → shellsession-DVK3bw4p.js} +1 -1
  152. package/dist/client/assets/{soy-D0GKXrtT.js → soy-BXgyj2-T.js} +1 -1
  153. package/dist/client/assets/{sparql-BdcL8cbr.js → sparql-DEoxFJ5d.js} +1 -1
  154. package/dist/client/assets/{sql-BRW_ADkU.js → sql-G2vZCmw6.js} +1 -1
  155. package/dist/client/assets/src-D9zkqEEX.js +1 -0
  156. package/dist/client/assets/{stata-w7w59F48.js → stata-C4mEnygx.js} +1 -1
  157. package/dist/client/assets/stateDiagram-AJRCARHV-AMtMxKgQ.js +1 -0
  158. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-C89CM-_4.js +1 -0
  159. package/dist/client/assets/{surrealql-O-lLuqz7.js → surrealql-Bf8gsTcP.js} +1 -1
  160. package/dist/client/assets/{svelte-DN3DR5-t.js → svelte-C1oIyl9t.js} +1 -1
  161. package/dist/client/assets/{templ-CJ2JFoia.js → templ-PJcWUuTF.js} +1 -1
  162. package/dist/client/assets/{tex-CpWrf5g9.js → tex-B7Fnujsi.js} +1 -1
  163. package/dist/client/assets/timeline-definition-PNZ67QCA-BZJSqcAg.js +120 -0
  164. package/dist/client/assets/treeView-BLDUP644-DtjHwb6x.js +1 -0
  165. package/dist/client/assets/treemap-LRROVOQU-GqTXzMFU.js +1 -0
  166. package/dist/client/assets/{ts-tags-CZ6Af6Pe.js → ts-tags-CAAsFnUt.js} +1 -1
  167. package/dist/client/assets/{tsx-gIUSpRih.js → tsx-DAKyTsWW.js} +1 -1
  168. package/dist/client/assets/{twig-DwZINhmw.js → twig-Bd4dieZF.js} +1 -1
  169. package/dist/client/assets/{typescript-Dj2aMECR.js → typescript-8myByDGd.js} +1 -1
  170. package/dist/client/assets/vennDiagram-CIIHVFJN-CMjBZNs2.js +34 -0
  171. package/dist/client/assets/{vue-B5K0aWrP.js → vue-fBA2B-QU.js} +1 -1
  172. package/dist/client/assets/{vue-html-DKGgrypd.js → vue-html-DEZECpsR.js} +1 -1
  173. package/dist/client/assets/{vue-vine-B5iDYTCh.js → vue-vine-B_gG939R.js} +1 -1
  174. package/dist/client/assets/wardley-L42UT6IY-pROVAAhW.js +1 -0
  175. package/dist/client/assets/wardleyDiagram-YWT4CUSO-qeHmPLyL.js +78 -0
  176. package/dist/client/assets/{xml-CbTzxfc-.js → xml-DbXNss3s.js} +1 -1
  177. package/dist/client/assets/{xsl-Dj-Be6nx.js → xsl-B7_dgqqc.js} +1 -1
  178. package/dist/client/assets/xychartDiagram-2RQKCTM6-NN2Et7YL.js +7 -0
  179. package/dist/client/assets/{yaml-rTK8uEjh.js → yaml-DSyIApdJ.js} +1 -1
  180. package/dist/client/index.html +2 -2
  181. package/dist/{mcp-CE77qfjx.mjs → mcp-BWeWR4yd.mjs} +2 -1
  182. package/dist/plan-format-f62JWFI-.mjs +117 -0
  183. package/dist/{server-lock-DpCrvL-Z.mjs → server-lock-Dj9fG9md.mjs} +246 -122
  184. package/package.json +26 -14
  185. package/dist/cli-agent-BLPX3oOP.mjs +0 -443
  186. package/dist/cli-agent-BNwY5lZE.mjs +0 -446
  187. package/dist/cli-agent-CbzXDSSF.mjs +0 -446
  188. package/dist/cli-agent-Cfuy9fLC.mjs +0 -179
  189. package/dist/cli-agent-CtNivjQW.mjs +0 -179
  190. package/dist/cli-agent-DZBvZoXZ.mjs +0 -179
  191. package/dist/cli-agent-DsqbS3n7.mjs +0 -443
  192. package/dist/cli-agent-Vbs-ePHv.mjs +0 -443
  193. package/dist/cli-agent-WzJPMH52.mjs +0 -174
  194. package/dist/cli-agent-uYUoCA4X.mjs +0 -179
  195. package/dist/client/assets/index-Bwv7BWUp.js +0 -3959
  196. package/dist/mcp-BQmH_By-.mjs +0 -119
  197. package/dist/mcp-CFeE13n-.mjs +0 -254
  198. package/dist/mcp-CLgzC8_a.mjs +0 -119
  199. package/dist/mcp-D9E2HQZ9.mjs +0 -119
  200. package/dist/mcp-DKlThflu.mjs +0 -253
  201. package/dist/mcp-LVbLV17O.mjs +0 -119
  202. package/dist/mcp-SGCrfYGo.mjs +0 -254
  203. package/dist/mcp-nMwTAut3.mjs +0 -119
  204. package/dist/server-lock-B4crz9-_.mjs +0 -708
  205. package/dist/server-lock-BbiF7u3F.mjs +0 -493
  206. package/dist/server-lock-Bx9ixiF6.mjs +0 -575
  207. package/dist/server-lock-CAdqFSfl.mjs +0 -691
  208. package/dist/server-lock-DIkImokU.mjs +0 -487
  209. package/dist/server-lock-DbxpfF3j.mjs +0 -575
  210. package/dist/update-check-DJuFE9w6.mjs +0 -128
  211. package/dist/update-check-DSC02MWQ.mjs +0 -129
  212. package/dist/client/assets/{abap-CkQ0tsz-.js → abap-cWYhO34H.js} +0 -0
  213. package/dist/client/assets/{actionscript-3-DHm0ZfF4.js → actionscript-3-B80ndJsD.js} +0 -0
  214. package/dist/client/assets/{ada-DK_ua92Z.js → ada-C0C0SoYB.js} +0 -0
  215. package/dist/client/assets/{andromeeda-D2ccw8v4.js → andromeeda-Ch2kWS7s.js} +0 -0
  216. package/dist/client/assets/{apache-DXtpFu7o.js → apache-DBwBm4bB.js} +0 -0
  217. package/dist/client/assets/{apex-DlnRRWpl.js → apex-FcV7UxQi.js} +0 -0
  218. package/dist/client/assets/{applescript-CShk62ad.js → applescript-hQs8VNpS.js} +0 -0
  219. package/dist/client/assets/{ara-CWN-FDkm.js → ara-BOadBOZg.js} +0 -0
  220. package/dist/client/assets/{asciidoc-Bg-PM9Vn.js → asciidoc-BsfqiBck.js} +0 -0
  221. package/dist/client/assets/{asm-DKOhR24S.js → asm-C2vUqzqz.js} +0 -0
  222. package/dist/client/assets/{aurora-x-DpaEirL8.js → aurora-x-BHLqzt7j.js} +0 -0
  223. package/dist/client/assets/{awk-3ibKHffv.js → awk-D4e-eeZT.js} +0 -0
  224. package/dist/client/assets/{ayu-dark-ursiSH5k.js → ayu-dark-DCotN_ZT.js} +0 -0
  225. package/dist/client/assets/{ayu-light-DMjlrKmx.js → ayu-light-CKB6o_im.js} +0 -0
  226. package/dist/client/assets/{ayu-mirage-DZEMb75h.js → ayu-mirage-B38lW-C5.js} +0 -0
  227. package/dist/client/assets/{ballerina-xx7VNGxs.js → ballerina-BzvFqbha.js} +0 -0
  228. package/dist/client/assets/{bat-DGYsZ5wR.js → bat-CFyw2ERn.js} +0 -0
  229. package/dist/client/assets/{beancount-D_ATR1UV.js → beancount-a6Gsu5WX.js} +0 -0
  230. package/dist/client/assets/{berry-BqYMORfH.js → berry-C2jyz4Ah.js} +0 -0
  231. package/dist/client/assets/{bibtex-CQTBDajW.js → bibtex-Dyet-B83.js} +0 -0
  232. package/dist/client/assets/{bicep-CfNtxPrK.js → bicep-CghvUIvy.js} +0 -0
  233. package/dist/client/assets/{bird2-C0dUPe3I.js → bird2-nHigvs-R.js} +0 -0
  234. package/dist/client/assets/{c3-BUwZ5e3k.js → c3-9ZrcmAmr.js} +0 -0
  235. package/dist/client/assets/{cadence-C3OKDYrr.js → cadence-BPDgYNWy.js} +0 -0
  236. package/dist/client/assets/{catppuccin-frappe-CMnRXVZP.js → catppuccin-frappe-BY_2ofjk.js} +0 -0
  237. package/dist/client/assets/{catppuccin-latte-CqhXSjCC.js → catppuccin-latte-D6GXPBmA.js} +0 -0
  238. package/dist/client/assets/{catppuccin-macchiato-B6kneE0C.js → catppuccin-macchiato-BuW8_cyo.js} +0 -0
  239. package/dist/client/assets/{catppuccin-mocha-CP8YZpvj.js → catppuccin-mocha-znex9DPe.js} +0 -0
  240. package/dist/client/assets/{clarity-Crxe8gSr.js → clarity-Cmao5KSK.js} +0 -0
  241. package/dist/client/assets/{clojure-BuzOUPMr.js → clojure-D2dPuTkk.js} +0 -0
  242. package/dist/client/assets/{cmake-CCpZLdLI.js → cmake-DaqQuj4A.js} +0 -0
  243. package/dist/client/assets/{codeowners-Bo1VYpHz.js → codeowners-B748jmvc.js} +0 -0
  244. package/dist/client/assets/{codeql-Db01hzHE.js → codeql-CXb_8gHR.js} +0 -0
  245. package/dist/client/assets/{common-lisp-CMlJIc6Y.js → common-lisp-UZn9nc_5.js} +0 -0
  246. package/dist/client/assets/{coq-BlzBYp3f.js → coq-DtO6yBIf.js} +0 -0
  247. package/dist/client/assets/{csharp-kfNshAa7.js → csharp-C3YlYcLV.js} +0 -0
  248. package/dist/client/assets/{csv-Dr8ri5Nd.js → csv-BBwiVr0X.js} +0 -0
  249. package/dist/client/assets/{cue-jXfhyOwY.js → cue-ScBFXY5f.js} +0 -0
  250. package/dist/client/assets/{cypher-CayLeiaR.js → cypher-CGStaC1X.js} +0 -0
  251. package/dist/client/assets/{d-BMZQ0mAy.js → d-CuTCIvnX.js} +0 -0
  252. package/dist/client/assets/{dark-plus-B__q47Nr.js → dark-plus-BvePH-r3.js} +0 -0
  253. package/dist/client/assets/{dart-gMOEMyuz.js → dart-CqEodbm2.js} +0 -0
  254. package/dist/client/assets/{dax-C3t5LadU.js → dax-UdE5S0Dh.js} +0 -0
  255. package/dist/client/assets/{desktop-DmhXLwLR.js → desktop-DfmsfHJA.js} +0 -0
  256. package/dist/client/assets/{diff-togOXQX6.js → diff-CW0RWGd9.js} +0 -0
  257. package/dist/client/assets/{docker--6N01olR.js → docker-B1qtW4ha.js} +0 -0
  258. package/dist/client/assets/{dotenv-Bq930Yx8.js → dotenv-BUzOh1k8.js} +0 -0
  259. package/dist/client/assets/{dracula-CBkSghcw.js → dracula-kJQjC_Gy.js} +0 -0
  260. package/dist/client/assets/{dracula-soft-CCSYeoxL.js → dracula-soft-B3XhEjCl.js} +0 -0
  261. package/dist/client/assets/{dream-maker-BiMf3DHl.js → dream-maker-CBvk18nW.js} +0 -0
  262. package/dist/client/assets/{emacs-lisp-Dhht7he2.js → emacs-lisp-DvSgLhDc.js} +0 -0
  263. package/dist/client/assets/{everforest-dark-NqSz4oHS.js → everforest-dark-u0zLn75q.js} +0 -0
  264. package/dist/client/assets/{everforest-light-a3Yzs_lT.js → everforest-light-D3syIoAR.js} +0 -0
  265. package/dist/client/assets/{fennel-BExc9TZf.js → fennel-C-1kWlGf.js} +0 -0
  266. package/dist/client/assets/{fish-C2p-AJmZ.js → fish-CCpdtwqS.js} +0 -0
  267. package/dist/client/assets/{fluent-CeYzs8Qy.js → fluent-BLg032oD.js} +0 -0
  268. package/dist/client/assets/{fortran-free-form-BIQEK2Jw.js → fortran-free-form-Br4jRtSc.js} +0 -0
  269. package/dist/client/assets/{gdscript-B5JQPh_-.js → gdscript-hSAZM1eh.js} +0 -0
  270. package/dist/client/assets/{gdshader-vVjJ_Qr8.js → gdshader-D4XNAEs9.js} +0 -0
  271. package/dist/client/assets/{genie-DGl5rqC8.js → genie-DmN-ICAN.js} +0 -0
  272. package/dist/client/assets/{gherkin-CY_VLUnD.js → gherkin-cuHHmRcX.js} +0 -0
  273. package/dist/client/assets/{github-dark-ClO4AStc.js → github-dark-CEBLh0--.js} +0 -0
  274. package/dist/client/assets/{github-dark-default-CM0dPco8.js → github-dark-default-Dq0Z4Xai.js} +0 -0
  275. package/dist/client/assets/{github-dark-dimmed-Cb6xxpXY.js → github-dark-dimmed-D90YmS4w.js} +0 -0
  276. package/dist/client/assets/{github-dark-high-contrast-BpYtx2-M.js → github-dark-high-contrast-B6BWv1iC.js} +0 -0
  277. package/dist/client/assets/{github-light-default-BmnCWL6x.js → github-light-default-DsPWmj4v.js} +0 -0
  278. package/dist/client/assets/{github-light-high-contrast-rpagNF5O.js → github-light-high-contrast-C7aLb3kp.js} +0 -0
  279. package/dist/client/assets/{github-light-CeOVFgf_.js → github-light-lXSVSq5T.js} +0 -0
  280. package/dist/client/assets/{gleam-BarIG9kQ.js → gleam-D8VhqPDN.js} +0 -0
  281. package/dist/client/assets/{gn-DhYsTPYc.js → gn-BjGRlX27.js} +0 -0
  282. package/dist/client/assets/{gnuplot-CucLlTBc.js → gnuplot-BZCXuE4q.js} +0 -0
  283. package/dist/client/assets/{go-toi-uWvg.js → go-BJpWXZEs.js} +0 -0
  284. package/dist/client/assets/{groovy-Ds4dis_k.js → groovy-D9w3Dn-z.js} +0 -0
  285. package/dist/client/assets/{gruvbox-dark-hard-aPiW8pQh.js → gruvbox-dark-hard-_deksD0U.js} +0 -0
  286. package/dist/client/assets/{gruvbox-dark-medium-2HJCvzsS.js → gruvbox-dark-medium-CT31284j.js} +0 -0
  287. package/dist/client/assets/{gruvbox-dark-soft-Da97ODX9.js → gruvbox-dark-soft-BZuEUCbj.js} +0 -0
  288. package/dist/client/assets/{gruvbox-light-hard-BXlEipFe.js → gruvbox-light-hard-dxv4n_ZS.js} +0 -0
  289. package/dist/client/assets/{gruvbox-light-medium-Cun-GjGk.js → gruvbox-light-medium-BsW_fVfR.js} +0 -0
  290. package/dist/client/assets/{gruvbox-light-soft-Bd3qiiSw.js → gruvbox-light-soft-BiGy99gD.js} +0 -0
  291. package/dist/client/assets/{haskell-B_jvz5Po.js → haskell-DqDdKEgk.js} +0 -0
  292. package/dist/client/assets/{haxe-BRbuo5UO.js → haxe-DMg0jS3a.js} +0 -0
  293. package/dist/client/assets/{hcl-BzNUCtsK.js → hcl-SZIZUK_X.js} +0 -0
  294. package/dist/client/assets/{hjson-BxVo3sS2.js → hjson-DF1VspiE.js} +0 -0
  295. package/dist/client/assets/{hlsl-C8Wes1nf.js → hlsl-DPe9L0Dt.js} +0 -0
  296. package/dist/client/assets/{horizon-D54PjLAY.js → horizon-Ngud75Kn.js} +0 -0
  297. package/dist/client/assets/{horizon-bright-D9RccdIr.js → horizon-bright-Cnljd0XD.js} +0 -0
  298. package/dist/client/assets/{houston-CMu1N_4K.js → houston-BenZxlMr.js} +0 -0
  299. package/dist/client/assets/{hy-dMrJKKU_.js → hy-B0f-B1mH.js} +0 -0
  300. package/dist/client/assets/{imba-DG_oO8tg.js → imba-Bq3j1cW5.js} +0 -0
  301. package/dist/client/assets/{ini-geHw79Aj.js → ini-BayloP2U.js} +0 -0
  302. package/dist/client/assets/{json5-CDUsNqz6.js → json5-CRSfdIrY.js} +0 -0
  303. package/dist/client/assets/{jsonc-D48xcwyD.js → jsonc-y4g9DQPx.js} +0 -0
  304. package/dist/client/assets/{jsonl-cpIYDXEe.js → jsonl-D2paVn9r.js} +0 -0
  305. package/dist/client/assets/{jsonnet-Da1lhszN.js → jsonnet-CLH27mtz.js} +0 -0
  306. package/dist/client/assets/{jssm-B8BLrEGL.js → jssm-CPPYaqX-.js} +0 -0
  307. package/dist/client/assets/{kanagawa-dragon-2Sk8Rx83.js → kanagawa-dragon-Bt5mhLu1.js} +0 -0
  308. package/dist/client/assets/{kanagawa-lotus-CQVSWfJp.js → kanagawa-lotus-FGA3pRJk.js} +0 -0
  309. package/dist/client/assets/{kanagawa-wave-BKWNioLX.js → kanagawa-wave-DnLVZPAD.js} +0 -0
  310. package/dist/client/assets/{kdl-B-2tSRmp.js → kdl-D1BQjjnw.js} +0 -0
  311. package/dist/client/assets/{kotlin-DepsEzh3.js → kotlin-ndCaDnf0.js} +0 -0
  312. package/dist/client/assets/{kusto-BcCtXIb8.js → kusto-D-4nbkD3.js} +0 -0
  313. package/dist/client/assets/{laserwave-BUqkO46F.js → laserwave-D2qAZkaG.js} +0 -0
  314. package/dist/client/assets/{lean-CNO9ffpX.js → lean-YmtAsB0p.js} +0 -0
  315. package/dist/client/assets/{less-Dj0T9pWC.js → less-DyHub3ow.js} +0 -0
  316. package/dist/client/assets/{light-plus-C9Hnuc1T.js → light-plus-CP13QUvm.js} +0 -0
  317. package/dist/client/assets/{llvm-DbV9b66l.js → llvm-DCcqrY0D.js} +0 -0
  318. package/dist/client/assets/{log-BMblmPyH.js → log-DWAAMNbe.js} +0 -0
  319. package/dist/client/assets/{logo-B78qMxws.js → logo-ClQMGkNL.js} +0 -0
  320. package/dist/client/assets/{luau-BUd8xsdE.js → luau-CmcXFvLt.js} +0 -0
  321. package/dist/client/assets/{make-Ev-6cJrd.js → make-DcfJyUzm.js} +0 -0
  322. package/dist/client/assets/{markdown-CS4LI6sN.js → markdown-DXxotAxn.js} +0 -0
  323. package/dist/client/assets/{material-theme-5rA1zn0D.js → material-theme-JFoPTBSr.js} +0 -0
  324. package/dist/client/assets/{material-theme-darker-DGOEiL65.js → material-theme-darker-BHaqZ19v.js} +0 -0
  325. package/dist/client/assets/{material-theme-lighter-CULfFRX0.js → material-theme-lighter-CGnnS2bs.js} +0 -0
  326. package/dist/client/assets/{material-theme-ocean-LQZ9CleP.js → material-theme-ocean-Drhewjqf.js} +0 -0
  327. package/dist/client/assets/{material-theme-palenight-Di_f5oks.js → material-theme-palenight-DbUypmpb.js} +0 -0
  328. package/dist/client/assets/{matlab-C0qEtAx9.js → matlab-BlfbTznR.js} +0 -0
  329. package/dist/client/assets/{mdx-CzvnbLXb.js → mdx-H8fyPQd8.js} +0 -0
  330. package/dist/client/assets/{mermaid-BPquZaKt.js → mermaid-CWAV2dmV.js} +0 -0
  331. package/dist/client/assets/{min-dark-rkuIbtJV.js → min-dark-BEelvXUB.js} +0 -0
  332. package/dist/client/assets/{min-light-Dj_HOGsr.js → min-light-CTPBOACR.js} +0 -0
  333. package/dist/client/assets/{mipsasm-k5DQoS6j.js → mipsasm-BWYFAm2s.js} +0 -0
  334. package/dist/client/assets/{mojo-sTTDuNnR.js → mojo-DZcPJEIN.js} +0 -0
  335. package/dist/client/assets/{monokai-D5p-u2ij.js → monokai-DQlZXbkg.js} +0 -0
  336. package/dist/client/assets/{moonbit-j5ChFtBC.js → moonbit-6eslNlJL.js} +0 -0
  337. package/dist/client/assets/{move-Dj0Gmn6R.js → move-DxFc9-QU.js} +0 -0
  338. package/dist/client/assets/{narrat-DJgMz2oW.js → narrat-gv38dJOT.js} +0 -0
  339. package/dist/client/assets/{nextflow-groovy-eDLuZ_oi.js → nextflow-groovy-DV4H3hok.js} +0 -0
  340. package/dist/client/assets/{night-owl-CEdtPl3A.js → night-owl-BLcrYhaC.js} +0 -0
  341. package/dist/client/assets/{night-owl-light-GdSldewm.js → night-owl-light-BG-tBJOz.js} +0 -0
  342. package/dist/client/assets/{nix-CxIPS3pb.js → nix-NlOz3HGM.js} +0 -0
  343. package/dist/client/assets/{nord-3WFAz5H9.js → nord-Dm2F5_QB.js} +0 -0
  344. package/dist/client/assets/{nushell-GDfBmoBU.js → nushell-D86Z8aFF.js} +0 -0
  345. package/dist/client/assets/{objective-c-MFQ_MGUa.js → objective-c-iuJvUjCv.js} +0 -0
  346. package/dist/client/assets/{objective-cpp-Y83LcBE7.js → objective-cpp-C62JvfMT.js} +0 -0
  347. package/dist/client/assets/{ocaml-FxYfaJxu.js → ocaml-Rbryo9lg.js} +0 -0
  348. package/dist/client/assets/{odin-CprihY3z.js → odin-CfaOVNP_.js} +0 -0
  349. package/dist/client/assets/{one-dark-pro-BB6mpmmA.js → one-dark-pro-DC9SHdX0.js} +0 -0
  350. package/dist/client/assets/{one-light-BYLoxNtg.js → one-light-Doo39p0H.js} +0 -0
  351. package/dist/client/assets/{openscad-Bc1FbpOi.js → openscad-DCRhgheK.js} +0 -0
  352. package/dist/client/assets/{pascal-Bb4d8cUL.js → pascal-CTesTHtV.js} +0 -0
  353. package/dist/client/assets/{pierre-dark-cF19s-RM.js → pierre-dark-Gtc9M_gS.js} +0 -0
  354. package/dist/client/assets/{pierre-light-BdpX8OpD.js → pierre-light-EDxMHmhf.js} +0 -0
  355. package/dist/client/assets/{pkl-tM25Sq0w.js → pkl-BjUMjQkt.js} +0 -0
  356. package/dist/client/assets/{plastic-D3k2Xp_5.js → plastic-B3CcSpon.js} +0 -0
  357. package/dist/client/assets/{plsql-CLEfFhSj.js → plsql-BgKEZSSo.js} +0 -0
  358. package/dist/client/assets/{po-CaAzdrrh.js → po-C5s_CVt8.js} +0 -0
  359. package/dist/client/assets/{poimandres-bPTvT4Da.js → poimandres-BsK70ma5.js} +0 -0
  360. package/dist/client/assets/{polar-TG7aTGdK.js → polar-y4hX8qM0.js} +0 -0
  361. package/dist/client/assets/{postcss-8kqfa9f0.js → postcss-BHCm7Qae.js} +0 -0
  362. package/dist/client/assets/{powerquery-CtSu1Nfd.js → powerquery-C2vMt8aZ.js} +0 -0
  363. package/dist/client/assets/{powershell-87lLBHMy.js → powershell-DEcjmg1c.js} +0 -0
  364. package/dist/client/assets/{prisma-Dnf694DZ.js → prisma-Ba-Tcxy5.js} +0 -0
  365. package/dist/client/assets/{prolog-C0XbHTWa.js → prolog-B4o261Jv.js} +0 -0
  366. package/dist/client/assets/{proto-BZP-HLIb.js → proto-o3IZKiMR.js} +0 -0
  367. package/dist/client/assets/{puppet-CJYWgYC5.js → puppet-BC0dqZ31.js} +0 -0
  368. package/dist/client/assets/{purescript-B95Q6BAd.js → purescript-CLDw1y5G.js} +0 -0
  369. package/dist/client/assets/{python-CqTCsi7P.js → python-D1NFioGW.js} +0 -0
  370. package/dist/client/assets/{qmldir-DlIL4hls.js → qmldir-B7i9e9Vn.js} +0 -0
  371. package/dist/client/assets/{qss-BW72E0q_.js → qss-DIe6oKX8.js} +0 -0
  372. package/dist/client/assets/{racket-CCAimEsC.js → racket-CAOC_yyk.js} +0 -0
  373. package/dist/client/assets/{raku-mSuqElkM.js → raku-Ccua3vW6.js} +0 -0
  374. package/dist/client/assets/{red-C-DA4yBI.js → red-DtDH206x.js} +0 -0
  375. package/dist/client/assets/{reg-CGwMBJ2c.js → reg-CAYZT9kE.js} +0 -0
  376. package/dist/client/assets/{rel-JwrbYgX4.js → rel-cvB6F5nO.js} +0 -0
  377. package/dist/client/assets/{riscv-CoYyE75b.js → riscv-SYGtE4EN.js} +0 -0
  378. package/dist/client/assets/{ron-C5wrhnmJ.js → ron-CRt869SB.js} +0 -0
  379. package/dist/client/assets/{rose-pine-DlrMPYYd.js → rose-pine-CjBfSJ5b.js} +0 -0
  380. package/dist/client/assets/{rose-pine-dawn-DBHFtZD2.js → rose-pine-dawn-C0xwy7iJ.js} +0 -0
  381. package/dist/client/assets/{rose-pine-moon-BBfrpe5q.js → rose-pine-moon-BSNy9Ty0.js} +0 -0
  382. package/dist/client/assets/{rosmsg-DlimTR9t.js → rosmsg-BwrfJ66Z.js} +0 -0
  383. package/dist/client/assets/{rust-Cxnkxx3h.js → rust-DCKTTPxN.js} +0 -0
  384. package/dist/client/assets/{sass-DEyqUIpU.js → sass-CorcwySt.js} +0 -0
  385. package/dist/client/assets/{scala-i3RN3yAN.js → scala-DlI-OmYj.js} +0 -0
  386. package/dist/client/assets/{scheme-BcKdjYkO.js → scheme-CcNEGkZH.js} +0 -0
  387. package/dist/client/assets/{sdbl-Be_XWc3n.js → sdbl-AL_m-RO_.js} +0 -0
  388. package/dist/client/assets/{slack-dark-3PDtm74m.js → slack-dark-rMhrfPm6.js} +0 -0
  389. package/dist/client/assets/{slack-ochin-CwiuFRJD.js → slack-ochin-9w8X74hU.js} +0 -0
  390. package/dist/client/assets/{smalltalk-BdBlL6ks.js → smalltalk-Y2ogrfbk.js} +0 -0
  391. package/dist/client/assets/{snazzy-light-Dyqc8Is2.js → snazzy-light-DHr9ygpP.js} +0 -0
  392. package/dist/client/assets/{solarized-dark-DZiTscIX.js → solarized-dark-UPcKev9Q.js} +0 -0
  393. package/dist/client/assets/{solarized-light-DBcfxrfG.js → solarized-light-DUsjROvl.js} +0 -0
  394. package/dist/client/assets/{solidity-DH-yUSWc.js → solidity-Bfbm9QZQ.js} +0 -0
  395. package/dist/client/assets/{splunk-CIjc4kxs.js → splunk-6DJA2XFa.js} +0 -0
  396. package/dist/client/assets/{ssh-config-BKVd4drG.js → ssh-config-CbQtdF-u.js} +0 -0
  397. package/dist/client/assets/{stylus-tqAsmugv.js → stylus-B_iq45Sj.js} +0 -0
  398. package/dist/client/assets/{swift-CdDBQ3_Z.js → swift-C7KIgN-p.js} +0 -0
  399. package/dist/client/assets/{synthwave-84-CbbRs73K.js → synthwave-84-lf_Wt0K_.js} +0 -0
  400. package/dist/client/assets/{system-verilog-CBqEY-9v.js → system-verilog-C3G9wERd.js} +0 -0
  401. package/dist/client/assets/{systemd-khRP5zwK.js → systemd-CwxGrojj.js} +0 -0
  402. package/dist/client/assets/{talonscript-D_lneH-6.js → talonscript-DqnSo1EO.js} +0 -0
  403. package/dist/client/assets/{tasl-CLymawGe.js → tasl-T8ethp86.js} +0 -0
  404. package/dist/client/assets/{tcl-BRY1S87U.js → tcl-Ccl366o0.js} +0 -0
  405. package/dist/client/assets/{terraform-BqohMo2f.js → terraform-BBf6ZI_0.js} +0 -0
  406. package/dist/client/assets/{tokyo-night-BWUONxad.js → tokyo-night-BF5ata25.js} +0 -0
  407. package/dist/client/assets/{toml-C4c85Lwg.js → toml-C5Z_BR4r.js} +0 -0
  408. package/dist/client/assets/{tsv-DsZq9HBQ.js → tsv-rX8sUJs7.js} +0 -0
  409. package/dist/client/assets/{turtle-Dpr8zLlw.js → turtle-BM-MG8WY.js} +0 -0
  410. package/dist/client/assets/{typespec-DcqgATB-.js → typespec-C5gKydvR.js} +0 -0
  411. package/dist/client/assets/{typst-CeVxmuPg.js → typst--_5VchrY.js} +0 -0
  412. package/dist/client/assets/{v-C2Qsh2-1.js → v-C6PwpmTC.js} +0 -0
  413. package/dist/client/assets/{vala-CvZ3yL7c.js → vala-4pTaceSj.js} +0 -0
  414. package/dist/client/assets/{vb-B_p4qDw4.js → vb-DhoR5A6S.js} +0 -0
  415. package/dist/client/assets/{verilog-D8MGjxD7.js → verilog-B9f_1lPn.js} +0 -0
  416. package/dist/client/assets/{vesper-DossXiE1.js → vesper-CmBi_iCT.js} +0 -0
  417. package/dist/client/assets/{vhdl-MLyYh_Gz.js → vhdl-Cy4RAmOe.js} +0 -0
  418. package/dist/client/assets/{viml-BuYIArcz.js → viml-CFQW-CcD.js} +0 -0
  419. package/dist/client/assets/{vitesse-black-C3kc1227.js → vitesse-black-CE8RoBJP.js} +0 -0
  420. package/dist/client/assets/{vitesse-dark-kWOu5V36.js → vitesse-dark-BpF142p_.js} +0 -0
  421. package/dist/client/assets/{vitesse-light-DMtiL8bK.js → vitesse-light-CMwxPBrg.js} +0 -0
  422. package/dist/client/assets/{vyper-CNqG09-_.js → vyper-BW5zj9bE.js} +0 -0
  423. package/dist/client/assets/{wasm-BsQDV7Y0.js → wasm-BigxSLnm.js} +0 -0
  424. package/dist/client/assets/{wasm-DFVlQlgd.js → wasm-CSccDuAq.js} +0 -0
  425. package/dist/client/assets/{wenyan-BmOQge13.js → wenyan-BZzM1SQT.js} +0 -0
  426. package/dist/client/assets/{wgsl-CgWrmvIg.js → wgsl-xBPHbLlq.js} +0 -0
  427. package/dist/client/assets/{wikitext-DkwckXCk.js → wikitext-BXJWUNJK.js} +0 -0
  428. package/dist/client/assets/{wit-CtyVFGe7.js → wit-2GnUs67P.js} +0 -0
  429. package/dist/client/assets/{wolfram-CXE4FrKz.js → wolfram-DIFDmw-g.js} +0 -0
  430. package/dist/client/assets/{zenscript-DH15wJt0.js → zenscript-DQaUUjbx.js} +0 -0
  431. package/dist/client/assets/{zig-CqXN9brD.js → zig-BDepRvBi.js} +0 -0
  432. package/dist/{update-check-KL-2sGxE.mjs → update-check-DAPFCqpF.mjs} +1 -1
package/dist/cli.mjs CHANGED
@@ -1,11 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { C as revertHunk, S as listRepoFiles, T as toSafeRelativePath, _ as getRepoRoot, a as extractPlanLines, b as gitAddFile, c as formatComments, d as getFileContent, f as getGitDiffAsync, g as getRepoName, h as getProjectStorageDir, i as writeServerLock, l as getBranchName, m as getMergeStatus, o as formatPlanReview, p as getHunkHistory, r as removeServerLock, s as sectionTitleForLine, u as getCustomGitDiffAsync, v as getTabSizeForFiles, w as isSafePath, x as isGitRepo, y as getUntrackedFilePathsAsync } from "./server-lock-DpCrvL-Z.mjs";
2
+ import { C as toSafeRelativePath, S as isSafePath, _ as getUntrackedFilePathsAsync, a as formatComments, b as listRepoFiles, c as getFileContent, d as getMergeStatus, f as getProjectStorageDir, g as getTabSizeForFiles, h as getShowDiff, i as writeServerLock, l as getGitDiffAsync, m as getRepoRoot, o as getBranchName, p as getRepoName, r as removeServerLock, s as getCustomGitDiffAsync, u as getHunkHistory, v as gitAddFile, x as revertHunk, y as isGitRepo } from "./server-lock-Dj9fG9md.mjs";
3
+ import { n as formatPlanReview, r as sectionTitleForLine, t as extractPlanLines } from "./plan-format-f62JWFI-.mjs";
4
+ import { execFile, execFileSync, spawn } from "node:child_process";
3
5
  import { fileURLToPath } from "node:url";
4
- import { dirname, extname, join, resolve } from "node:path";
6
+ import { dirname, extname, isAbsolute, join, resolve } from "node:path";
5
7
  import { existsSync, mkdirSync, readFileSync, watch, writeFileSync } from "node:fs";
6
8
  import getPort from "get-port";
7
- import { parseArgs } from "node:util";
8
- import { execFileSync } from "node:child_process";
9
+ import { parseArgs, promisify } from "node:util";
9
10
  import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
10
11
  import { homedir } from "node:os";
11
12
  import { Hono } from "hono";
@@ -48,7 +49,11 @@ const DEFAULTS$1 = {
48
49
  help: false,
49
50
  version: false,
50
51
  includeUnstaged: true,
51
- includeUntracked: true
52
+ includeUntracked: true,
53
+ tui: false,
54
+ gpu: false,
55
+ showMode: false,
56
+ showRevspecs: []
52
57
  };
53
58
  /**
54
59
  * All git-diff option definitions for `node:util.parseArgs`.
@@ -173,6 +178,15 @@ const DIFFING_OPTIONS = {
173
178
  type: "boolean",
174
179
  default: false
175
180
  },
181
+ tui: {
182
+ type: "boolean",
183
+ default: false
184
+ },
185
+ gpu: {
186
+ type: "boolean",
187
+ default: false
188
+ },
189
+ "gh-pr": { type: "string" },
176
190
  help: {
177
191
  type: "boolean",
178
192
  short: "h"
@@ -209,18 +223,37 @@ Output Modes:
209
223
  - Terminal mode: when output is a pipe, redirect, or non-TTY
210
224
  - Web mode: when output is a TTY (interactive terminal)
211
225
 
212
- Force a mode with --web or --terminal flags.
226
+ Force a mode with --web, --terminal, or --tui flags.
227
+ --tui is experimental and opt-in. It opens a native-Rust terminal
228
+ interface that mirrors the web dashboard. Falls back to git diff
229
+ output if the environment cannot support a TUI (piped stdin, CI,
230
+ missing binary).
231
+
232
+ Subcommands:
233
+ show <revspec>... Drop-in for 'git show'. Renders commit metadata
234
+ (subject, author, date, message body) above the
235
+ diff in the web UI. Accepts single commits,
236
+ ranges (a..b, a...b), tags, and multiple SHAs.
237
+ Use '--' to separate revspecs from pathspecs.
213
238
 
214
239
  Examples:
215
240
  diffing Review uncommitted changes (web UI)
216
241
  diffing --staged Review staged changes
217
242
  diffing HEAD~3 Review last 3 commits
218
243
  diffing main..feature Compare branches
244
+ diffing show HEAD Review a single commit's metadata + diff
245
+ diffing show HEAD~3..HEAD Review the last 3 commits as a series
246
+ diffing show HEAD -- src/ Limit a commit review to a directory
219
247
  diffing --diff-algorithm=patience src/ Diff with patience algorithm
220
248
  diffing -U10 Diff with 10 context lines
221
249
  diffing --word-diff=color Word-level diff in color
222
250
  diffing -b -w Ignore whitespace changes
223
- diffing --host 0.0.0.0 Allow other machines on the LAN to review`);
251
+ diffing --host 0.0.0.0 Allow other machines on the LAN to review
252
+ diffing --tui Open the experimental TUI (native Rust)
253
+
254
+ Note: 'diffing <sha>' runs 'git diff <sha>' (working tree vs <sha>); it
255
+ is not the same as 'diffing show <sha>'. Use 'show' when you want to
256
+ review a commit's changes.`);
224
257
  }
225
258
  function printGitDiffHelp() {
226
259
  console.log(`
@@ -464,7 +497,8 @@ function parseDiffOptions(rawArgs) {
464
497
  }
465
498
  for (let i = dashDashIdx + 1; i < rawArgs.length; i++) opts.pathspecs.push(rawArgs[i]);
466
499
  } else for (const p of positionals) opts.revisions.push(p);
467
- if (values.web) opts.outputMode = "web";
500
+ if (values.tui) opts.outputMode = "tui";
501
+ else if (values.web) opts.outputMode = "web";
468
502
  else if (values.terminal) opts.outputMode = "terminal";
469
503
  if (process.stdout.isTTY && opts.outputMode === "auto") opts.outputMode = "web";
470
504
  else if (!process.stdout.isTTY && opts.outputMode === "auto") opts.outputMode = "terminal";
@@ -545,6 +579,21 @@ function buildGitDiffArgs(opts) {
545
579
  }
546
580
  return args;
547
581
  }
582
+ /**
583
+ * Transform a `parseDiffOptions(...)` result into a "show mode" variant:
584
+ * moves any parsed revisions into `showRevspecs`, clears `revisions` (so the
585
+ * existing diff-engine path does not try to `git diff` them), and sets the
586
+ * `showMode` flag. Pathspecs and every other flag survive unchanged.
587
+ *
588
+ * Returns the same object for callsite ergonomics — the mutation is in-place
589
+ * because `parseDiffOptions` always returns a fresh object.
590
+ */
591
+ function intoShowMode(opts) {
592
+ opts.showRevspecs = opts.revisions;
593
+ opts.revisions = [];
594
+ opts.showMode = true;
595
+ return opts;
596
+ }
548
597
  //#endregion
549
598
  //#region src/lib/diff-engine.ts
550
599
  const MAX_BUFFER = 50 * 1024 * 1024;
@@ -553,10 +602,11 @@ const MAX_BUFFER = 50 * 1024 * 1024;
553
602
  * or a "custom" mode (specific revisions / pathspecs).
554
603
  *
555
604
  * Custom mode is used when the user provides explicit revisions or pathspecs
556
- * beyond just toggling staged/untracked.
605
+ * beyond just toggling staged/untracked. `showMode` is *also* a custom mode
606
+ * — the "Show staged / Show untracked" toggles don't apply to a commit view.
557
607
  */
558
608
  function isCustomMode$1(opts) {
559
- return opts.revisions.length > 0 || opts.pathspecs.length > 0;
609
+ return opts.revisions.length > 0 || opts.pathspecs.length > 0 || opts.showMode;
560
610
  }
561
611
  function parseFilePaths(patch) {
562
612
  const paths = /* @__PURE__ */ new Set();
@@ -603,8 +653,24 @@ function parseBinaryFiles(patch, untrackedFiles) {
603
653
  }
604
654
  /**
605
655
  * Execute a diff asynchronously — used by the server.
656
+ *
657
+ * Show mode bypasses the normal `git diff` path entirely: it resolves
658
+ * revspecs to a commit list and fetches per-commit metadata + patches in
659
+ * one `git log` call. The concatenated patch is returned in the same shape
660
+ * the existing UI pipeline expects (so file tree, binary detection, and
661
+ * tab-size detection all keep working unchanged); the per-commit data
662
+ * rides along on `commits` for the metadata banners.
606
663
  */
607
664
  async function executeDiffAsync(opts) {
665
+ if (opts.showMode) {
666
+ const { commits, patch, truncated } = await getShowDiff(opts.showRevspecs, opts.pathspecs);
667
+ return {
668
+ patch,
669
+ args: [],
670
+ commits,
671
+ truncated
672
+ };
673
+ }
608
674
  if (isCustomMode$1(opts)) {
609
675
  const args = buildGitDiffArgs(opts);
610
676
  return {
@@ -624,10 +690,10 @@ async function executeDiffAsync(opts) {
624
690
  * Execute a diff and produce the full enriched result used by the web API.
625
691
  */
626
692
  async function executeDiffWithMeta(opts) {
627
- const { patch } = await executeDiffAsync(opts);
693
+ const { patch, commits, truncated } = await executeDiffAsync(opts);
628
694
  const repoName = getRepoName();
629
695
  const branch = getBranchName();
630
- const untrackedFiles = opts.includeUntracked ? await getUntrackedFilePathsAsync() : [];
696
+ const untrackedFiles = opts.includeUntracked && !opts.showMode ? await getUntrackedFilePathsAsync() : [];
631
697
  const binaryFiles = parseBinaryFiles(patch, new Set(untrackedFiles));
632
698
  const filePaths = parseFilePaths(patch);
633
699
  return {
@@ -637,14 +703,19 @@ async function executeDiffWithMeta(opts) {
637
703
  tabSizeMap: getTabSizeForFiles(filePaths),
638
704
  untrackedFiles,
639
705
  repoName,
640
- branch
706
+ branch,
707
+ ...commits ? { commits } : {},
708
+ ...truncated ? { truncated } : {}
641
709
  };
642
710
  }
643
711
  /**
644
712
  * Run the diff in terminal mode: forward to git diff with full flags,
645
- * output to stdout. Behaves identically to `git diff`.
713
+ * output to stdout. Behaves identically to `git diff`. In show mode this
714
+ * delegates to `git show` instead so `diffing show <rev>... --terminal`
715
+ * is a drop-in for `git show <rev>...`.
646
716
  */
647
717
  function runTerminalDiff(opts) {
718
+ if (opts.showMode) return runTerminalShow(opts);
648
719
  const args = buildGitDiffArgs(opts);
649
720
  const enforceDefaults = !opts.outputFormat && !opts.quiet;
650
721
  const finalArgs = [];
@@ -665,6 +736,30 @@ function runTerminalDiff(opts) {
665
736
  }
666
737
  }
667
738
  /**
739
+ * Terminal mode for `diffing show`: spawn `git show` with the user's revspecs
740
+ * and pathspecs, inherit stdio, propagate exit code. We pass `--no-ext-diff`
741
+ * so the output is a clean unified diff regardless of the user's git config
742
+ * (matches the web-mode pipeline), but otherwise hand everything to git.
743
+ */
744
+ function runTerminalShow(opts) {
745
+ const args = [
746
+ "show",
747
+ "--no-ext-diff",
748
+ ...opts.showRevspecs
749
+ ];
750
+ if (opts.pathspecs.length > 0) args.push("--", ...opts.pathspecs);
751
+ try {
752
+ execFileSync("git", args, {
753
+ encoding: "utf-8",
754
+ maxBuffer: MAX_BUFFER,
755
+ stdio: "inherit"
756
+ });
757
+ return 0;
758
+ } catch (err) {
759
+ return err.status ?? 1;
760
+ }
761
+ }
762
+ /**
668
763
  * Validate the environment: check that we're in a git repo.
669
764
  * Returns an error message or null.
670
765
  */
@@ -1438,6 +1533,62 @@ var FileUiStateStore = class {
1438
1533
  }
1439
1534
  };
1440
1535
  //#endregion
1536
+ //#region src/lib/editor-launcher.ts
1537
+ function resolveEditorCommand(editor, absolutePath, platform = process.platform, env = process.env) {
1538
+ switch (editor) {
1539
+ case "vscode": return guiEditorCommand("code", absolutePath, platform);
1540
+ case "zed": return guiEditorCommand("zed", absolutePath, platform);
1541
+ case "vim": return terminalEditorCommand("vim", absolutePath, platform, env);
1542
+ case "neovim": return terminalEditorCommand("nvim", absolutePath, platform, env);
1543
+ default: return null;
1544
+ }
1545
+ }
1546
+ function guiEditorCommand(bin, absolutePath, platform) {
1547
+ if (platform === "win32") return {
1548
+ cmd: `${bin}.cmd`,
1549
+ args: [absolutePath]
1550
+ };
1551
+ return {
1552
+ cmd: bin,
1553
+ args: [absolutePath]
1554
+ };
1555
+ }
1556
+ function terminalEditorCommand(bin, absolutePath, platform, env) {
1557
+ if (platform === "darwin") return {
1558
+ cmd: "osascript",
1559
+ args: ["-e", `tell application "Terminal" to do script "${bin} \\"${absolutePath.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}\\""`]
1560
+ };
1561
+ if (platform === "win32") return {
1562
+ cmd: "cmd.exe",
1563
+ args: [
1564
+ "/c",
1565
+ "start",
1566
+ "\"\"",
1567
+ "cmd.exe",
1568
+ "/k",
1569
+ bin,
1570
+ absolutePath
1571
+ ]
1572
+ };
1573
+ const term = env.TERMINAL?.trim();
1574
+ if (term) return {
1575
+ cmd: term,
1576
+ args: [
1577
+ "-e",
1578
+ bin,
1579
+ absolutePath
1580
+ ]
1581
+ };
1582
+ return {
1583
+ cmd: "x-terminal-emulator",
1584
+ args: [
1585
+ "-e",
1586
+ bin,
1587
+ absolutePath
1588
+ ]
1589
+ };
1590
+ }
1591
+ //#endregion
1441
1592
  //#region src/lib/review-session.ts
1442
1593
  var ReviewSession = class {
1443
1594
  round = 0;
@@ -1630,6 +1781,483 @@ var PlanReviewSession = class {
1630
1781
  }
1631
1782
  };
1632
1783
  //#endregion
1784
+ //#region src/lib/pr-session.ts
1785
+ var FilePrSessionStore = class {
1786
+ dirPath;
1787
+ filePath;
1788
+ constructor(storageDir) {
1789
+ this.dirPath = storageDir ?? getProjectStorageDir();
1790
+ this.filePath = join(this.dirPath, "pr-session.json");
1791
+ }
1792
+ async get() {
1793
+ try {
1794
+ const data = await readFile(this.filePath, "utf-8");
1795
+ return JSON.parse(data);
1796
+ } catch {
1797
+ return null;
1798
+ }
1799
+ }
1800
+ async save(session) {
1801
+ try {
1802
+ await mkdir(this.dirPath, { recursive: true });
1803
+ await writeFile(this.filePath, JSON.stringify(session, null, 2), "utf-8");
1804
+ } catch (err) {
1805
+ console.error("Failed to save pr-session to file:", err);
1806
+ }
1807
+ }
1808
+ async set(session) {
1809
+ await this.save(session);
1810
+ }
1811
+ async update(fields) {
1812
+ const current = await this.get();
1813
+ if (!current) return null;
1814
+ const next = {
1815
+ ...current,
1816
+ ...fields
1817
+ };
1818
+ await this.save(next);
1819
+ return next;
1820
+ }
1821
+ async clear() {
1822
+ try {
1823
+ const { unlink } = await import("node:fs/promises");
1824
+ await unlink(this.filePath);
1825
+ } catch {}
1826
+ }
1827
+ };
1828
+ //#endregion
1829
+ //#region src/lib/github.ts
1830
+ const execFileAsync = promisify(execFile);
1831
+ /**
1832
+ * Probe the `gh` CLI: is it on `$PATH`, and is the user authenticated?
1833
+ * Never throws — returns a permissive `available: false` on any failure.
1834
+ */
1835
+ async function detectGhCli() {
1836
+ try {
1837
+ const { stdout } = await execFileAsync("gh", ["--version"], { encoding: "utf-8" });
1838
+ const version = stdout.split("\n")[0]?.trim() || void 0;
1839
+ try {
1840
+ const result = await execFileAsync("gh", ["auth", "status"], { encoding: "utf-8" });
1841
+ return {
1842
+ available: true,
1843
+ authenticated: true,
1844
+ version,
1845
+ user: parseGhAuthStatusUser(`${result.stdout ?? ""}\n${result.stderr ?? ""}`)
1846
+ };
1847
+ } catch {
1848
+ return {
1849
+ available: true,
1850
+ authenticated: false,
1851
+ version
1852
+ };
1853
+ }
1854
+ } catch {
1855
+ return {
1856
+ available: false,
1857
+ authenticated: false
1858
+ };
1859
+ }
1860
+ }
1861
+ /**
1862
+ * Extract the GitHub username from `gh auth status` output. Exported for
1863
+ * unit tests — see `__tests__/github-auth.test.ts`.
1864
+ *
1865
+ * Real-world samples:
1866
+ * `✓ Logged in to github.com account octocat (keyring)` (gh 2.40+)
1867
+ * `Logged in to github.com as octocat (oauth_token)` (older gh)
1868
+ * ` ✓ Logged in to github.com as octocat (~/.config/gh/hosts.yml)`
1869
+ */
1870
+ function parseGhAuthStatusUser(output) {
1871
+ const account = /Logged in to [^\s]+ account\s+([^\s(]+)/.exec(output);
1872
+ if (account) return account[1];
1873
+ return /Logged in to [^\s]+ as\s+([^\s(]+)/.exec(output)?.[1];
1874
+ }
1875
+ /** Read the most-preferred GitHub token from the env. */
1876
+ function readGithubToken() {
1877
+ const env = process.env;
1878
+ return env.GH_TOKEN || env.GITHUB_TOKEN || env.GITHUB_API_TOKEN || null;
1879
+ }
1880
+ function parsePrRef(input, cwdRepo) {
1881
+ const trimmed = input.trim();
1882
+ const urlMatch = /^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/i.exec(trimmed);
1883
+ if (urlMatch) return {
1884
+ owner: urlMatch[1],
1885
+ repo: urlMatch[2],
1886
+ pullNumber: Number(urlMatch[3]),
1887
+ ref: trimmed
1888
+ };
1889
+ const shorthand = /^([^/\s]+)\/([^#\s]+)#(\d+)$/.exec(trimmed);
1890
+ if (shorthand) return {
1891
+ owner: shorthand[1],
1892
+ repo: shorthand[2],
1893
+ pullNumber: Number(shorthand[3]),
1894
+ ref: trimmed
1895
+ };
1896
+ const bare = /^#?(\d+)$/.exec(trimmed);
1897
+ if (bare && cwdRepo) return {
1898
+ owner: cwdRepo.owner,
1899
+ repo: cwdRepo.repo,
1900
+ pullNumber: Number(bare[1]),
1901
+ ref: trimmed
1902
+ };
1903
+ if (bare) throw new Error(`Cannot resolve bare PR number "${trimmed}" — run from inside the target repo, or pass a full URL or \`owner/repo#1234\`.`);
1904
+ throw new Error(`Unrecognised PR ref: ${trimmed}`);
1905
+ }
1906
+ /**
1907
+ * Best-effort: derive `{ owner, repo }` for the current working directory
1908
+ * from `git remote get-url origin`. Falls back to throwing.
1909
+ */
1910
+ async function detectCwdRepo() {
1911
+ try {
1912
+ const { stdout } = await execFileAsync("git", [
1913
+ "remote",
1914
+ "get-url",
1915
+ "origin"
1916
+ ], { encoding: "utf-8" });
1917
+ const url = stdout.trim();
1918
+ const m = /github\.com[:/]([^/\s]+)\/([^/\s]+?)(?:\.git)?\s*$/.exec(url);
1919
+ if (m) return {
1920
+ owner: m[1],
1921
+ repo: m[2]
1922
+ };
1923
+ } catch {}
1924
+ return null;
1925
+ }
1926
+ /**
1927
+ * Fetch PR metadata + diff + existing review comments using `gh`.
1928
+ * Throws with a user-readable message on failure.
1929
+ */
1930
+ async function fetchPrMetadataViaGh(resolved) {
1931
+ const args = ["-R", `${resolved.owner}/${resolved.repo}`];
1932
+ let metaJson;
1933
+ try {
1934
+ const { stdout } = await execFileAsync("gh", [
1935
+ "pr",
1936
+ "view",
1937
+ String(resolved.pullNumber),
1938
+ ...args,
1939
+ "--json",
1940
+ "number,title,url,author,baseRefOid,headRefOid,additions,deletions,changedFiles,headRepositoryOwner,headRepository"
1941
+ ], {
1942
+ encoding: "utf-8",
1943
+ maxBuffer: 20 * 1024 * 1024
1944
+ });
1945
+ metaJson = JSON.parse(stdout);
1946
+ } catch (err) {
1947
+ const stderr = err?.stderr || err?.message || "unknown error";
1948
+ throw new Error(`gh pr view failed: ${stderr.trim()}`);
1949
+ }
1950
+ let diff = "";
1951
+ try {
1952
+ const { stdout } = await execFileAsync("gh", [
1953
+ "pr",
1954
+ "diff",
1955
+ String(resolved.pullNumber),
1956
+ ...args
1957
+ ], {
1958
+ encoding: "utf-8",
1959
+ maxBuffer: 50 * 1024 * 1024
1960
+ });
1961
+ diff = stdout;
1962
+ } catch (err) {
1963
+ const stderr = err?.stderr || err?.message || "unknown error";
1964
+ throw new Error(`gh pr diff failed: ${stderr.trim()}`);
1965
+ }
1966
+ const headOwner = metaJson.headRepositoryOwner?.login || metaJson.headRepository?.owner?.login || resolved.owner;
1967
+ const repoName = metaJson.headRepository?.name || resolved.repo;
1968
+ const author = metaJson.author ? {
1969
+ login: metaJson.author.login,
1970
+ avatarUrl: metaJson.author.avatarUrl
1971
+ } : null;
1972
+ const existingComments = await fetchExistingCommentsViaGh(resolved);
1973
+ return {
1974
+ number: metaJson.number,
1975
+ title: metaJson.title,
1976
+ url: metaJson.url,
1977
+ author,
1978
+ baseSha: metaJson.baseRefOid,
1979
+ headSha: metaJson.headRefOid,
1980
+ additions: metaJson.additions,
1981
+ deletions: metaJson.deletions,
1982
+ changedFiles: metaJson.changedFiles,
1983
+ owner: headOwner,
1984
+ repo: repoName,
1985
+ diff,
1986
+ existingComments
1987
+ };
1988
+ }
1989
+ async function fetchExistingCommentsViaGh(resolved) {
1990
+ `${resolved.owner}${resolved.repo}`;
1991
+ const endpoint = `repos/${resolved.owner}/${resolved.repo}/pulls/${resolved.pullNumber}/comments`;
1992
+ const reviewsEndpoint = `repos/${resolved.owner}/${resolved.repo}/pulls/${resolved.pullNumber}/reviews`;
1993
+ let reviews = [];
1994
+ try {
1995
+ const { stdout } = await execFileAsync("gh", [
1996
+ "api",
1997
+ reviewsEndpoint,
1998
+ "--paginate"
1999
+ ], {
2000
+ encoding: "utf-8",
2001
+ maxBuffer: 20 * 1024 * 1024
2002
+ });
2003
+ const all = JSON.parse(stdout);
2004
+ if (Array.isArray(all)) reviews = all;
2005
+ } catch {}
2006
+ reviews.sort((a, b) => a.submitted_at < b.submitted_at ? 1 : -1);
2007
+ const recentReviews = reviews.slice(0, 50);
2008
+ const reviewStateById = /* @__PURE__ */ new Map();
2009
+ for (const r of recentReviews) reviewStateById.set(r.id, r.state);
2010
+ let commentsRaw = [];
2011
+ try {
2012
+ const { stdout } = await execFileAsync("gh", [
2013
+ "api",
2014
+ `${endpoint}?per_page=100`,
2015
+ "--paginate"
2016
+ ], {
2017
+ encoding: "utf-8",
2018
+ maxBuffer: 20 * 1024 * 1024
2019
+ });
2020
+ const parsed = JSON.parse(stdout);
2021
+ if (Array.isArray(parsed)) commentsRaw = parsed;
2022
+ } catch {
2023
+ return [];
2024
+ }
2025
+ const byId = /* @__PURE__ */ new Map();
2026
+ for (const c of commentsRaw) byId.set(c.id, c);
2027
+ const replyByParent = /* @__PURE__ */ new Map();
2028
+ for (const c of commentsRaw) if (c.in_reply_to_id && byId.has(c.in_reply_to_id)) {
2029
+ const list = replyByParent.get(c.in_reply_to_id) ?? [];
2030
+ list.push(c);
2031
+ replyByParent.set(c.in_reply_to_id, list);
2032
+ }
2033
+ const tops = [];
2034
+ for (const c of commentsRaw) {
2035
+ if (c.in_reply_to_id) continue;
2036
+ const state = c.pull_request_review_id ? reviewStateById.get(c.pull_request_review_id) ?? null : null;
2037
+ tops.push({
2038
+ id: c.id,
2039
+ author: c.user ? {
2040
+ login: c.user.login,
2041
+ avatarUrl: c.user.avatar_url
2042
+ } : null,
2043
+ body: c.body ?? "",
2044
+ path: c.path,
2045
+ line: typeof c.line === "number" ? c.line : null,
2046
+ side: c.side === "LEFT" || c.side === "RIGHT" ? c.side : null,
2047
+ createdAt: c.created_at,
2048
+ updatedAt: c.updated_at,
2049
+ state,
2050
+ replies: (replyByParent.get(c.id) ?? []).map((r) => ({
2051
+ id: r.id,
2052
+ author: r.user ? {
2053
+ login: r.user.login,
2054
+ avatarUrl: r.user.avatar_url
2055
+ } : null,
2056
+ body: r.body ?? "",
2057
+ createdAt: r.created_at,
2058
+ updatedAt: r.updated_at
2059
+ })),
2060
+ isOutdated: typeof c.position === "number" && c.position === null ? false : false
2061
+ });
2062
+ }
2063
+ tops.sort((a, b) => {
2064
+ if (a.path !== b.path) return a.path.localeCompare(b.path);
2065
+ return (a.line ?? 0) - (b.line ?? 0);
2066
+ });
2067
+ return tops;
2068
+ }
2069
+ /**
2070
+ * POST the review to GitHub. Prefers `gh api` (uses the user's existing
2071
+ * `gh auth`); falls back to a direct HTTP call with `$GITHUB_TOKEN` when
2072
+ * `gh` is unavailable.
2073
+ */
2074
+ async function submitReview(input) {
2075
+ const gh = await detectGhCli();
2076
+ if (gh.available && gh.authenticated) return submitViaGh(input);
2077
+ const token = readGithubToken();
2078
+ if (token) return submitViaToken(input, token);
2079
+ return {
2080
+ ok: false,
2081
+ authSource: "none",
2082
+ error: "Cannot submit: no `gh` CLI on $PATH (or not authenticated) and no $GITHUB_TOKEN env var. Run `gh auth login` or set $GITHUB_TOKEN."
2083
+ };
2084
+ }
2085
+ /**
2086
+ * Map our `PrDecision` to the GitHub REST event string. Exported so the
2087
+ * test suite can pin the mapping (including the `rejected → REQUEST_CHANGES`
2088
+ * quirk, which exists because GitHub has no REJECT event).
2089
+ */
2090
+ function decisionToEvent(decision) {
2091
+ if (decision === "approve") return "APPROVE";
2092
+ if (decision === "request-changes") return "REQUEST_CHANGES";
2093
+ return "COMMENT";
2094
+ }
2095
+ /**
2096
+ * Expand multi-line `ReviewComment`s into N single-line `gh`-shaped entries
2097
+ * with `[part N/M]` prefixes. Exported for the test suite — the body of the
2098
+ * caller (`buildReviewPayload`) is otherwise private.
2099
+ *
2100
+ * Skips: non-`open` comments, file-level comments (`lineNumber === 0`).
2101
+ * Strips the `a/` / `b/` prefix from the file path (GitHub expects PR-relative
2102
+ * paths in the `path` field).
2103
+ */
2104
+ function expandMultiLineComments(comments) {
2105
+ const flat = [];
2106
+ for (const c of comments) {
2107
+ if (c.status !== "open") continue;
2108
+ if (c.lineNumber === 0) continue;
2109
+ const path = stripBPrefix(c.filePath);
2110
+ const start = c.startLineNumber && c.startLineNumber < c.lineNumber ? c.startLineNumber : c.lineNumber;
2111
+ const end = c.lineNumber;
2112
+ const span = end - start + 1;
2113
+ if (span > 1) for (let i = 0; i < span; i++) flat.push({
2114
+ path,
2115
+ line: start + i,
2116
+ side: "RIGHT",
2117
+ body: `[part ${i + 1}/${span}]\n${c.body}`
2118
+ });
2119
+ else flat.push({
2120
+ path,
2121
+ line: end,
2122
+ side: "RIGHT",
2123
+ body: c.body
2124
+ });
2125
+ }
2126
+ return flat;
2127
+ }
2128
+ function buildReviewPayload(input) {
2129
+ return {
2130
+ body: input.body,
2131
+ event: decisionToEvent(input.decision ?? "comment"),
2132
+ comments: expandMultiLineComments(input.comments ?? [])
2133
+ };
2134
+ }
2135
+ function stripBPrefix(path) {
2136
+ if (path.startsWith("b/")) return path.slice(2);
2137
+ if (path.startsWith("a/")) return path.slice(2);
2138
+ return path;
2139
+ }
2140
+ async function submitViaGh(input) {
2141
+ const payload = buildReviewPayload(input);
2142
+ `${input.resolved.owner}${input.resolved.repo}`;
2143
+ const args = [
2144
+ "api",
2145
+ "--method",
2146
+ "POST",
2147
+ `repos/${input.resolved.owner}/${input.resolved.repo}/pulls/${input.resolved.pullNumber}/reviews`,
2148
+ "-H",
2149
+ "Accept: application/vnd.github+json",
2150
+ "--input",
2151
+ "-"
2152
+ ];
2153
+ try {
2154
+ const { stdout } = await execFileAsync("gh", args, {
2155
+ encoding: "utf-8",
2156
+ maxBuffer: 20 * 1024 * 1024,
2157
+ input: JSON.stringify(payload)
2158
+ });
2159
+ const result = JSON.parse(stdout);
2160
+ return {
2161
+ ok: true,
2162
+ authSource: "gh",
2163
+ reviewId: result.id,
2164
+ reviewUrl: result.html_url
2165
+ };
2166
+ } catch (err) {
2167
+ const stdout = err?.stdout || "";
2168
+ const stderr = err?.stderr || err?.message || "unknown error";
2169
+ let parsed = null;
2170
+ try {
2171
+ parsed = JSON.parse(stdout);
2172
+ } catch {}
2173
+ return {
2174
+ ok: false,
2175
+ authSource: "gh",
2176
+ error: parsed?.message || stderr.trim()
2177
+ };
2178
+ }
2179
+ }
2180
+ async function submitViaToken(input, token) {
2181
+ const payload = buildReviewPayload(input);
2182
+ const url = `https://api.github.com/repos/${input.resolved.owner}/${input.resolved.repo}/pulls/${input.resolved.pullNumber}/reviews`;
2183
+ try {
2184
+ const res = await fetch(url, {
2185
+ method: "POST",
2186
+ headers: {
2187
+ Authorization: `Bearer ${token}`,
2188
+ Accept: "application/vnd.github+json",
2189
+ "X-GitHub-Api-Version": "2022-11-28",
2190
+ "Content-Type": "application/json",
2191
+ "User-Agent": "diffing-cli"
2192
+ },
2193
+ body: JSON.stringify(payload)
2194
+ });
2195
+ if (!res.ok) {
2196
+ const errBody = await res.text().catch(() => "");
2197
+ return {
2198
+ ok: false,
2199
+ authSource: "token",
2200
+ error: `HTTP ${res.status}: ${errBody.slice(0, 500)}`
2201
+ };
2202
+ }
2203
+ const result = await res.json();
2204
+ return {
2205
+ ok: true,
2206
+ authSource: "token",
2207
+ reviewId: result.id,
2208
+ reviewUrl: result.html_url
2209
+ };
2210
+ } catch (err) {
2211
+ return {
2212
+ ok: false,
2213
+ authSource: "token",
2214
+ error: err?.message || "Network error"
2215
+ };
2216
+ }
2217
+ }
2218
+ async function buildPrSession(ref) {
2219
+ const meta = await fetchPrMetadataViaGh(parsePrRef(ref, await detectCwdRepo() ?? void 0));
2220
+ return {
2221
+ ref,
2222
+ owner: meta.owner,
2223
+ repo: meta.repo,
2224
+ pullNumber: meta.number,
2225
+ baseSha: meta.baseSha,
2226
+ headSha: meta.headSha,
2227
+ title: meta.title,
2228
+ url: meta.url,
2229
+ author: meta.author,
2230
+ additions: meta.additions,
2231
+ deletions: meta.deletions,
2232
+ changedFiles: meta.changedFiles,
2233
+ diff: meta.diff,
2234
+ comments: [],
2235
+ existingComments: meta.existingComments
2236
+ };
2237
+ }
2238
+ /** Refresh `diff` + `existingComments` + head SHA in an existing session. */
2239
+ async function refreshPrSession(session) {
2240
+ const meta = await fetchPrMetadataViaGh({
2241
+ owner: session.owner,
2242
+ repo: session.repo,
2243
+ pullNumber: session.pullNumber,
2244
+ ref: session.ref
2245
+ });
2246
+ return {
2247
+ ...session,
2248
+ baseSha: meta.baseSha,
2249
+ headSha: meta.headSha,
2250
+ title: meta.title,
2251
+ url: meta.url,
2252
+ author: meta.author,
2253
+ additions: meta.additions,
2254
+ deletions: meta.deletions,
2255
+ changedFiles: meta.changedFiles,
2256
+ diff: meta.diff,
2257
+ existingComments: meta.existingComments
2258
+ };
2259
+ }
2260
+ //#endregion
1633
2261
  //#region src/server.ts
1634
2262
  const MIME_TYPES = {
1635
2263
  ".html": "text/html",
@@ -1647,13 +2275,14 @@ const MIME_TYPES = {
1647
2275
  ".avif": "image/avif"
1648
2276
  };
1649
2277
  function isCustomMode(opts) {
1650
- return opts.revisions.length > 0 || opts.pathspecs.length > 0;
2278
+ return opts.revisions.length > 0 || opts.pathspecs.length > 0 || opts.showMode;
1651
2279
  }
1652
- function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
2280
+ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore, prSessionStore) {
1653
2281
  const app = new Hono();
1654
2282
  const customMode = isCustomMode(diffOpts);
1655
2283
  const store = commentStore ?? new FileCommentStore();
1656
2284
  const plans = planStore ?? new FilePlanStore();
2285
+ const prStore = prSessionStore ?? new FilePrSessionStore();
1657
2286
  const uiStateStore = new FileUiStateStore();
1658
2287
  const viewedFiles = /* @__PURE__ */ new Set();
1659
2288
  const activeClients = /* @__PURE__ */ new Set();
@@ -1675,6 +2304,7 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
1675
2304
  mkdirSync(storageDir, { recursive: true });
1676
2305
  let commentsDebounce = null;
1677
2306
  let plansDebounce = null;
2307
+ let prSessionDebounce = null;
1678
2308
  watch(storageDir, (_eventType, filename) => {
1679
2309
  if (!filename) return;
1680
2310
  if (filename.startsWith("comments.json")) {
@@ -1683,6 +2313,9 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
1683
2313
  } else if (filename.startsWith("plans.json")) {
1684
2314
  if (plansDebounce) clearTimeout(plansDebounce);
1685
2315
  plansDebounce = setTimeout(() => broadcast("plans", Date.now().toString()), 120);
2316
+ } else if (filename.startsWith("pr-session.json")) {
2317
+ if (prSessionDebounce) clearTimeout(prSessionDebounce);
2318
+ prSessionDebounce = setTimeout(() => broadcast("pr-session", Date.now().toString()), 120);
1686
2319
  }
1687
2320
  }).unref();
1688
2321
  } catch (err) {
@@ -1743,11 +2376,40 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
1743
2376
  app.get("/api/diff", async (c) => {
1744
2377
  const staged = c.req.query("staged") === "true";
1745
2378
  const untracked = c.req.query("untracked") === "true";
1746
- const result = await executeDiffWithMeta(customMode ? diffOpts : {
2379
+ const prSession = await prStore.get();
2380
+ if (prSession) {
2381
+ const binaryFiles = [];
2382
+ const filePaths = [];
2383
+ for (const line of prSession.diff.split("\n")) {
2384
+ const m = /^diff --git a\/.+ b\/(.+)$/.exec(line);
2385
+ if (m) filePaths.push(m[1]);
2386
+ }
2387
+ return c.json({
2388
+ patch: prSession.diff,
2389
+ repoName: prSession.repo,
2390
+ branch: `#${prSession.pullNumber}`,
2391
+ customMode: true,
2392
+ binaryFiles,
2393
+ tabSizeMap: {},
2394
+ untrackedFiles: [],
2395
+ prMode: true,
2396
+ prRef: prSession.ref,
2397
+ prOwner: prSession.owner,
2398
+ prRepo: prSession.repo,
2399
+ prPullNumber: prSession.pullNumber,
2400
+ prUrl: prSession.url,
2401
+ prTitle: prSession.title,
2402
+ prAuthor: prSession.author,
2403
+ prHeadSha: prSession.headSha,
2404
+ prBaseSha: prSession.baseSha
2405
+ });
2406
+ }
2407
+ const optsForDiff = customMode ? diffOpts : {
1747
2408
  ...diffOpts,
1748
2409
  staged,
1749
2410
  includeUntracked: untracked
1750
- });
2411
+ };
2412
+ const result = await executeDiffWithMeta(optsForDiff);
1751
2413
  return c.json({
1752
2414
  patch: result.patch,
1753
2415
  repoName: result.repoName,
@@ -1755,7 +2417,10 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
1755
2417
  customMode,
1756
2418
  binaryFiles: result.binaryFiles,
1757
2419
  tabSizeMap: result.tabSizeMap,
1758
- untrackedFiles: result.untrackedFiles
2420
+ untrackedFiles: result.untrackedFiles,
2421
+ showMode: optsForDiff.showMode || void 0,
2422
+ commits: result.commits,
2423
+ truncated: result.truncated
1759
2424
  });
1760
2425
  });
1761
2426
  app.get("/api/file-content", (c) => {
@@ -1791,12 +2456,17 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
1791
2456
  const relPath = toSafeRelativePath(filePath, root);
1792
2457
  if (!relPath) return c.json({ error: "Forbidden file path" }, 403);
1793
2458
  const absolutePath = resolve(root, relPath);
1794
- const { exec } = await import("node:child_process");
1795
- if (editor === "vscode") exec(`code "${absolutePath}"`);
1796
- else if (editor === "zed") exec(`zed "${absolutePath}"`);
1797
- else if (editor === "vim") exec(`osascript -e 'tell application "Terminal" to do script "vim \\"${absolutePath}\\""'`);
1798
- else if (editor === "neovim") exec(`osascript -e 'tell application "Terminal" to do script "nvim \\"${absolutePath}\\""'`);
1799
- else await (await import("open")).default(absolutePath);
2459
+ if (editor && editor !== "default") {
2460
+ const command = resolveEditorCommand(editor, absolutePath);
2461
+ if (command) {
2462
+ const { execFile } = await import("node:child_process");
2463
+ execFile(command.cmd, command.args, (err) => {
2464
+ if (err) console.error(`Failed to launch ${editor} for ${absolutePath}: ${err.message}`);
2465
+ });
2466
+ return c.json({ ok: true });
2467
+ }
2468
+ }
2469
+ await (await import("open")).default(absolutePath);
1800
2470
  return c.json({ ok: true });
1801
2471
  } catch (err) {
1802
2472
  return c.json({ error: `Failed to open file: ${err.message}` }, 500);
@@ -1881,7 +2551,7 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
1881
2551
  try {
1882
2552
  const relPath = toSafeRelativePath(filePath, getRepoRoot());
1883
2553
  if (!relPath) return c.json({ error: "Forbidden file path" }, 403);
1884
- const history = getHunkHistory(relPath, deletionStart, deletionCount, diffOpts.revisions[0] || "HEAD");
2554
+ const history = getHunkHistory(relPath, deletionStart, deletionCount, diffOpts.showMode ? diffOpts.showRevspecs[diffOpts.showRevspecs.length - 1] || "HEAD" : diffOpts.revisions[0] || "HEAD");
1885
2555
  return c.json(history);
1886
2556
  } catch (err) {
1887
2557
  return c.json({ error: err.message || "Failed to fetch hunk history" }, 500);
@@ -2027,6 +2697,193 @@ function createApp(clientDir, diffOpts = DEFAULTS$1, commentStore, planStore) {
2027
2697
  if (!await store.remove(id)) return c.json({ error: "Comment not found" }, 404);
2028
2698
  return c.json({ ok: true });
2029
2699
  });
2700
+ /** Shared helper: 404 with a stable shape so the client knows "not in PR mode". */
2701
+ const notInPrMode = (c) => c.json({
2702
+ error: "Not in PR review mode",
2703
+ prMode: false
2704
+ }, 404);
2705
+ app.get("/api/gh/session", async (c) => {
2706
+ const session = await prStore.get();
2707
+ if (!session) return notInPrMode(c);
2708
+ return c.json({
2709
+ prMode: true,
2710
+ ref: session.ref,
2711
+ owner: session.owner,
2712
+ repo: session.repo,
2713
+ pullNumber: session.pullNumber,
2714
+ baseSha: session.baseSha,
2715
+ headSha: session.headSha,
2716
+ title: session.title,
2717
+ url: session.url,
2718
+ author: session.author,
2719
+ additions: session.additions,
2720
+ deletions: session.deletions,
2721
+ changedFiles: session.changedFiles,
2722
+ existingComments: session.existingComments,
2723
+ submittedAt: session.submittedAt,
2724
+ submittedReviewId: session.submittedReviewId,
2725
+ submittedReviewUrl: session.submittedReviewUrl,
2726
+ authSource: session.authSource
2727
+ });
2728
+ });
2729
+ /** Re-fetch PR metadata (head SHA, diff, existing comments) and persist. */
2730
+ app.post("/api/gh/pr/refresh", async (c) => {
2731
+ const session = await prStore.get();
2732
+ if (!session) return notInPrMode(c);
2733
+ try {
2734
+ const refreshed = await refreshPrSession(session);
2735
+ await prStore.set(refreshed);
2736
+ return c.json({
2737
+ ok: true,
2738
+ headSha: refreshed.headSha
2739
+ });
2740
+ } catch (err) {
2741
+ return c.json({ error: err?.message ?? "Refresh failed" }, 500);
2742
+ }
2743
+ });
2744
+ /** Initialize a PR session from a ref like `1234`, `o/r#42`, or a GitHub URL. */
2745
+ app.post("/api/gh/pr/init", async (c) => {
2746
+ const body = await c.req.json().catch(() => ({}));
2747
+ const ref = typeof body?.ref === "string" ? body.ref : "";
2748
+ if (!ref.trim()) return c.json({ error: "ref is required" }, 400);
2749
+ try {
2750
+ parsePrRef(ref, await detectCwdRepo() ?? void 0);
2751
+ const session = await buildPrSession(ref);
2752
+ await prStore.set(session);
2753
+ return c.json({
2754
+ ok: true,
2755
+ ref: session.ref,
2756
+ owner: session.owner,
2757
+ repo: session.repo,
2758
+ pullNumber: session.pullNumber,
2759
+ url: session.url
2760
+ });
2761
+ } catch (err) {
2762
+ return c.json({ error: err?.message ?? "Failed to initialise PR session" }, 500);
2763
+ }
2764
+ });
2765
+ app.get("/api/gh/pr-session/comments", async (c) => {
2766
+ const session = await prStore.get();
2767
+ if (!session) return notInPrMode(c);
2768
+ return c.json(session.comments ?? []);
2769
+ });
2770
+ app.post("/api/gh/pr-session/comments", async (c) => {
2771
+ const body = await c.req.json();
2772
+ const session = await prStore.get();
2773
+ if (!session) return notInPrMode(c);
2774
+ const comment = {
2775
+ id: crypto.randomUUID(),
2776
+ filePath: body.filePath,
2777
+ side: body.side,
2778
+ lineNumber: body.lineNumber,
2779
+ startLineNumber: body.startLineNumber,
2780
+ lineContent: body.lineContent,
2781
+ body: body.body,
2782
+ status: "open",
2783
+ createdAt: Date.now(),
2784
+ replies: []
2785
+ };
2786
+ const next = {
2787
+ ...session,
2788
+ comments: [...session.comments ?? [], comment]
2789
+ };
2790
+ await prStore.set(next);
2791
+ return c.json(comment, 201);
2792
+ });
2793
+ app.put("/api/gh/pr-session/comments/:id", async (c) => {
2794
+ const id = c.req.param("id");
2795
+ const { body, status } = await c.req.json();
2796
+ const session = await prStore.get();
2797
+ if (!session) return notInPrMode(c);
2798
+ const comments = (session.comments ?? []).map((cm) => cm.id === id ? {
2799
+ ...cm,
2800
+ body: body ?? cm.body,
2801
+ status: status ?? cm.status
2802
+ } : cm);
2803
+ await prStore.set({
2804
+ ...session,
2805
+ comments
2806
+ });
2807
+ const updated = comments.find((cm) => cm.id === id) ?? null;
2808
+ if (!updated) return c.json({ error: "Comment not found" }, 404);
2809
+ return c.json(updated);
2810
+ });
2811
+ app.delete("/api/gh/pr-session/comments/:id", async (c) => {
2812
+ const id = c.req.param("id");
2813
+ const session = await prStore.get();
2814
+ if (!session) return notInPrMode(c);
2815
+ const comments = (session.comments ?? []).filter((cm) => cm.id !== id);
2816
+ await prStore.set({
2817
+ ...session,
2818
+ comments
2819
+ });
2820
+ return c.json({ ok: true });
2821
+ });
2822
+ app.post("/api/gh/pr-session/comments/:id/replies", async (c) => {
2823
+ const id = c.req.param("id");
2824
+ const { body, role, model } = await c.req.json();
2825
+ const session = await prStore.get();
2826
+ if (!session) return notInPrMode(c);
2827
+ const comments = (session.comments ?? []).map((cm) => {
2828
+ if (cm.id !== id) return cm;
2829
+ const reply = {
2830
+ id: crypto.randomUUID(),
2831
+ body,
2832
+ createdAt: Date.now(),
2833
+ role: role || (model ? "agent" : "user"),
2834
+ model: model || void 0
2835
+ };
2836
+ return {
2837
+ ...cm,
2838
+ replies: [...cm.replies ?? [], reply]
2839
+ };
2840
+ });
2841
+ await prStore.set({
2842
+ ...session,
2843
+ comments
2844
+ });
2845
+ return c.json(comments.find((cm) => cm.id === id));
2846
+ });
2847
+ /** Submit the current PR session's review (new comments + verdict + body) to GitHub. */
2848
+ app.post("/api/gh/submit", async (c) => {
2849
+ const session = await prStore.get();
2850
+ if (!session) return notInPrMode(c);
2851
+ const body = await c.req.json().catch(() => ({}));
2852
+ const decision = body.decision;
2853
+ if (decision !== "approve" && decision !== "comment" && decision !== "request-changes") return c.json({ error: "decision must be one of: approve, comment, request-changes" }, 400);
2854
+ const generalBody = typeof body.body === "string" ? body.body : "";
2855
+ const dryRun = body.dryRun === true;
2856
+ const result = await submitReview({
2857
+ resolved: {
2858
+ owner: session.owner,
2859
+ repo: session.repo,
2860
+ pullNumber: session.pullNumber,
2861
+ ref: session.ref
2862
+ },
2863
+ decision,
2864
+ body: generalBody,
2865
+ comments: session.comments ?? []
2866
+ });
2867
+ if (result.ok && !dryRun) {
2868
+ const next = {
2869
+ ...session,
2870
+ submittedAt: Date.now(),
2871
+ submittedReviewId: result.reviewId,
2872
+ submittedReviewUrl: result.reviewUrl,
2873
+ authSource: result.authSource
2874
+ };
2875
+ await prStore.set(next);
2876
+ }
2877
+ return c.json({
2878
+ ok: result.ok,
2879
+ reviewId: result.reviewId,
2880
+ reviewUrl: result.reviewUrl,
2881
+ failedComments: result.failedComments ?? 0,
2882
+ authSource: result.authSource,
2883
+ error: result.error,
2884
+ dryRun
2885
+ });
2886
+ });
2030
2887
  app.post("/api/review/send", async (c) => {
2031
2888
  const body = await c.req.json().catch(() => ({}));
2032
2889
  const generalComment = typeof body?.generalComment === "string" ? body.generalComment : void 0;
@@ -2269,7 +3126,11 @@ async function newestActivityMs(projectDir) {
2269
3126
  return null;
2270
3127
  }
2271
3128
  };
2272
- for (const name of ["comments.json", "plans.json"]) {
3129
+ for (const name of [
3130
+ "comments.json",
3131
+ "plans.json",
3132
+ "pr-session.json"
3133
+ ]) {
2273
3134
  const file = join(projectDir, name);
2274
3135
  if (!existsSync(file)) continue;
2275
3136
  const m = await safeStat(file);
@@ -2320,14 +3181,35 @@ function startServer(options) {
2320
3181
  cleanupStaleProjects().catch((err) => {
2321
3182
  console.error("Failed to clean up stale projects:", err);
2322
3183
  });
3184
+ let prMode = false;
3185
+ const prReady = (async () => {
3186
+ if (!options.prRef) return;
3187
+ console.error(`Building PR session for ${options.prRef}...`);
3188
+ try {
3189
+ const store = new FilePrSessionStore();
3190
+ const existing = await store.get();
3191
+ if (!existing || existing.ref !== options.prRef) {
3192
+ const session = await buildPrSession(options.prRef);
3193
+ await store.set(session);
3194
+ }
3195
+ prMode = true;
3196
+ } catch (err) {
3197
+ console.error(`[pr-session] failed to build session for ${options.prRef}: ${err?.message ?? err}`);
3198
+ }
3199
+ })();
2323
3200
  const app = createApp(options.clientDir, options.diffOpts);
2324
3201
  return new Promise((resolve) => {
2325
- serve({
2326
- fetch: app.fetch,
2327
- port: options.port,
2328
- hostname: options.host
2329
- }, (info) => {
2330
- resolve({ port: info.port });
3202
+ prReady.then(() => {
3203
+ serve({
3204
+ fetch: app.fetch,
3205
+ port: options.port,
3206
+ hostname: options.host
3207
+ }, (info) => {
3208
+ resolve({
3209
+ port: info.port,
3210
+ prMode
3211
+ });
3212
+ });
2331
3213
  });
2332
3214
  });
2333
3215
  }
@@ -2715,8 +3597,68 @@ function playStartupDisplay() {
2715
3597
  })();
2716
3598
  }
2717
3599
  //#endregion
3600
+ //#region src/lib/find-tui-binary.ts
3601
+ /**
3602
+ * Locate the `diffing-tui` native binary. Looks, in order:
3603
+ * 1. Sibling of the calling module (`dist/diffing-tui[.exe]` after build).
3604
+ * 2. `bin/diffing-tui[.exe]` next to the package root.
3605
+ * 3. `target/release/diffing-tui[.exe]` next to the package root
3606
+ * (cargo release build).
3607
+ * 4. `target/debug/diffing-tui[.exe]` next to the package root
3608
+ * (cargo debug build — the common case during development, especially
3609
+ * on Windows where release builds are slow).
3610
+ * 5. `$PATH` lookup via `which` / `where`.
3611
+ *
3612
+ * Returns the absolute path of the first match, or `null` if none are found.
3613
+ *
3614
+ * `callerUrl` is the `import.meta.url` of the caller — pass `import.meta.url`
3615
+ * from `cli.ts`. Exposed as a parameter so unit tests can pin the search
3616
+ * root to a known location instead of depending on the test runner's CWD.
3617
+ */
3618
+ function findTuiBinary$1(callerUrl) {
3619
+ const ext = process.platform === "win32" ? ".exe" : "";
3620
+ const here = dirname(fileURLToPath(callerUrl));
3621
+ const candidates = [
3622
+ resolve(here, `diffing-tui${ext}`),
3623
+ resolve(here, "..", "bin", `diffing-tui${ext}`),
3624
+ resolve(here, "..", "target", "release", `diffing-tui${ext}`),
3625
+ resolve(here, "..", "..", "target", "release", `diffing-tui${ext}`),
3626
+ resolve(here, "..", "target", "debug", `diffing-tui${ext}`),
3627
+ resolve(here, "..", "..", "target", "debug", `diffing-tui${ext}`)
3628
+ ];
3629
+ for (const c of candidates) if (existsSync(c)) return c;
3630
+ try {
3631
+ const out = execFileSync(process.platform === "win32" ? "where" : "which", ["diffing-tui"], {
3632
+ encoding: "utf-8",
3633
+ stdio: [
3634
+ "ignore",
3635
+ "pipe",
3636
+ "ignore"
3637
+ ]
3638
+ }).trim();
3639
+ if (out) {
3640
+ const first = out.split(/\r?\n/)[0]?.trim();
3641
+ if (first && isAbsolute(first)) return first;
3642
+ }
3643
+ } catch {}
3644
+ return null;
3645
+ }
3646
+ //#endregion
2718
3647
  //#region src/cli.ts
2719
3648
  const args = process.argv.slice(2);
3649
+ let prRef = null;
3650
+ let ghPrConsumed = 0;
3651
+ if (args[0]?.startsWith("gh pr ") === true) {
3652
+ const rest = args[0].slice(6).trim();
3653
+ if (rest) {
3654
+ prRef = rest;
3655
+ ghPrConsumed = 1;
3656
+ }
3657
+ } else if (args[0] === "gh" && args[1] === "pr" && args[2] !== void 0) {
3658
+ prRef = args[2];
3659
+ ghPrConsumed = 3;
3660
+ }
3661
+ if (ghPrConsumed > 0) args.splice(0, ghPrConsumed);
2720
3662
  if (new Set([
2721
3663
  "await-review",
2722
3664
  "reply",
@@ -2725,17 +3667,30 @@ if (new Set([
2725
3667
  "url",
2726
3668
  "mcp",
2727
3669
  "plan",
2728
- "update"
3670
+ "update",
3671
+ "gh"
2729
3672
  ]).has(args[0])) {
2730
3673
  if (args[0] === "mcp") {
2731
- const { startMcpServer } = await import("./mcp-CFeE13n-.mjs");
3674
+ const { startMcpServer } = await import("./mcp-BWeWR4yd.mjs");
2732
3675
  await startMcpServer();
2733
3676
  await new Promise(() => {});
2734
3677
  }
2735
- const { runSubcommand } = await import("./cli-agent-BNwY5lZE.mjs");
3678
+ const { runSubcommand } = await import("./cli-agent-KxNAFIPf.mjs");
2736
3679
  process.exit(await runSubcommand(args[0], args.slice(1)));
2737
3680
  }
3681
+ let showSubcommand = false;
3682
+ if (args[0] === "show") {
3683
+ showSubcommand = true;
3684
+ args.shift();
3685
+ }
2738
3686
  const opts = parseDiffOptions(args);
3687
+ if (showSubcommand) {
3688
+ if (opts.revisions.length === 0 && !opts.help && !opts.version) {
3689
+ console.error("Usage: diffing show <revspec>... [-- <pathspec>...]");
3690
+ process.exit(5);
3691
+ }
3692
+ intoShowMode(opts);
3693
+ }
2739
3694
  if (opts.help) {
2740
3695
  printHelp();
2741
3696
  process.exit(0);
@@ -2751,6 +3706,10 @@ if (envErr) {
2751
3706
  console.error(envErr);
2752
3707
  process.exit(1);
2753
3708
  }
3709
+ if (opts.outputMode === "tui") {
3710
+ const tuiResult = await launchTui(args);
3711
+ process.exit(tuiResult);
3712
+ }
2754
3713
  if (opts.outputMode === "terminal") {
2755
3714
  const exitCode = runTerminalDiff(opts);
2756
3715
  process.exit(exitCode);
@@ -2759,7 +3718,7 @@ const __pkgDir = dirname(fileURLToPath(import.meta.url));
2759
3718
  const currentVersion = JSON.parse(readFileSync(resolve(__pkgDir, "..", "package.json"), "utf-8")).version;
2760
3719
  const updateCheckPromise = (async () => {
2761
3720
  try {
2762
- const { checkForUpdates } = await import("./update-check-KL-2sGxE.mjs");
3721
+ const { checkForUpdates } = await import("./update-check-DAPFCqpF.mjs");
2763
3722
  return await checkForUpdates(currentVersion);
2764
3723
  } catch {
2765
3724
  return null;
@@ -2768,12 +3727,12 @@ const updateCheckPromise = (async () => {
2768
3727
  const port = await getPort(opts.port ? { port: opts.port } : void 0);
2769
3728
  const host = opts.host;
2770
3729
  const clientDir = resolve(__pkgDir, "client");
2771
- const { existsSync: existsSync$1 } = await import("node:fs");
2772
- const { port: actualPort } = await startServer({
3730
+ const { port: actualPort, prMode } = await startServer({
2773
3731
  port,
2774
3732
  host,
2775
- clientDir: existsSync$1(clientDir) ? clientDir : resolve(process.cwd(), "dist/client"),
2776
- diffOpts: opts
3733
+ clientDir: existsSync(clientDir) ? clientDir : resolve(process.cwd(), "dist/client"),
3734
+ diffOpts: opts,
3735
+ prRef: prRef ?? void 0
2777
3736
  });
2778
3737
  const localUrl = `http://${host}:${actualPort}`;
2779
3738
  try {
@@ -2789,7 +3748,9 @@ try {
2789
3748
  pid: process.pid,
2790
3749
  repoRoot,
2791
3750
  startedAt: Date.now(),
2792
- version: currentVersion
3751
+ version: currentVersion,
3752
+ mode: prMode ? "gh-pr" : "web",
3753
+ prRef: prMode ? prRef ?? void 0 : void 0
2793
3754
  });
2794
3755
  } catch {}
2795
3756
  console.log(`diffing server running at ${localUrl}`);
@@ -2797,7 +3758,7 @@ await playStartupDisplay();
2797
3758
  try {
2798
3759
  const updateInfo = await updateCheckPromise;
2799
3760
  if (updateInfo?.hasUpdate) {
2800
- const { printUpdateDisclaimer } = await import("./update-check-KL-2sGxE.mjs");
3761
+ const { printUpdateDisclaimer } = await import("./update-check-DAPFCqpF.mjs");
2801
3762
  printUpdateDisclaimer(currentVersion, updateInfo.latestVersion);
2802
3763
  }
2803
3764
  } catch {}
@@ -2817,5 +3778,64 @@ const shutdown = () => {
2817
3778
  };
2818
3779
  process.on("SIGINT", shutdown);
2819
3780
  process.on("SIGTERM", shutdown);
3781
+ /**
3782
+ * Wrapper around `findTuiBinary` that passes this script's `import.meta.url`
3783
+ * so the search paths anchor to the bundled CLI's directory. The real
3784
+ * implementation lives in `lib/find-tui-binary.ts` and is unit-tested there.
3785
+ */
3786
+ function findTuiBinary() {
3787
+ return findTuiBinary$1(import.meta.url);
3788
+ }
3789
+ /**
3790
+ * Fall back to default `git diff` output when the TUI cannot run.
3791
+ * Re-parses `args` so the terminal output exactly matches `diffing` (no flag)
3792
+ * in a non-TTY context.
3793
+ */
3794
+ function runTerminalFallback(args) {
3795
+ const terminalOpts = parseDiffOptions(args.filter((a) => a !== "--tui"));
3796
+ terminalOpts.outputMode = "terminal";
3797
+ terminalOpts.tui = false;
3798
+ return runTerminalDiff(terminalOpts);
3799
+ }
3800
+ /**
3801
+ * Launch the native-Rust TUI binary as a child process. Returns the process
3802
+ * exit code. If the TUI cannot start (no TTY, missing binary), prints a
3803
+ * single stderr line and falls back to the default `git diff` output.
3804
+ */
3805
+ async function launchTui(args) {
3806
+ if (!process.stdout.isTTY || !process.stdin.isTTY) {
3807
+ console.error("diffing --tui requires a TTY; falling back to git diff");
3808
+ return runTerminalFallback(args);
3809
+ }
3810
+ const bin = findTuiBinary();
3811
+ if (!bin) {
3812
+ console.error("diffing-tui binary not found; build it with `pnpm build:tui`; falling back to git diff");
3813
+ return runTerminalFallback(args);
3814
+ }
3815
+ const forwarded = args.filter((a) => a !== "--tui");
3816
+ let repoRoot;
3817
+ try {
3818
+ repoRoot = getRepoRoot();
3819
+ } catch {
3820
+ repoRoot = process.cwd();
3821
+ }
3822
+ console.log(`diffing TUI starting (binary: ${bin})`);
3823
+ await playStartupDisplay();
3824
+ return new Promise((resolveP) => {
3825
+ const child = spawn(bin, [
3826
+ "--repo",
3827
+ repoRoot,
3828
+ ...forwarded
3829
+ ], {
3830
+ stdio: "inherit",
3831
+ env: process.env
3832
+ });
3833
+ child.on("exit", (code) => resolveP(code ?? 0));
3834
+ child.on("error", (err) => {
3835
+ console.error(`diffing-tui failed to start: ${err.message}; falling back to git diff`);
3836
+ resolveP(runTerminalFallback(args));
3837
+ });
3838
+ });
3839
+ }
2820
3840
  //#endregion
2821
- export {};
3841
+ export { findTuiBinary };