diffing 0.10.5 → 0.12.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 (182) hide show
  1. package/README.md +76 -41
  2. package/dist/{cli-agent-BJiATn11.mjs → cli-agent-CWsOHN-j.mjs} +198 -57
  3. package/dist/{cli-gh-_bkDCxhh.mjs → cli-gh-DI69gJGo.mjs} +27 -17
  4. package/dist/cli.mjs +189 -229
  5. package/dist/client/assets/{angular-html-CBcwKYDC.js → angular-html-PLPuQo0k.js} +1 -1
  6. package/dist/client/assets/{angular-ts-DRBYUaJA.js → angular-ts-CE02Ij4b.js} +1 -1
  7. package/dist/client/assets/{apl-BM0X8jeL.js → apl-CsuUKZoi.js} +1 -1
  8. package/dist/client/assets/{arc-DTkmmKl3.js → arc-CgL5kFe-.js} +1 -1
  9. package/dist/client/assets/{architectureDiagram-3BPJPVTR-Cw75ay7q.js → architectureDiagram-3BPJPVTR-DxZQWGnx.js} +1 -1
  10. package/dist/client/assets/{astro-DKTNkoRZ.js → astro-DkFc7sbz.js} +1 -1
  11. package/dist/client/assets/{blade-DaM7a9Zp.js → blade-BkY07kcC.js} +1 -1
  12. package/dist/client/assets/{blockDiagram-GPEHLZMM-DAzINMr_.js → blockDiagram-GPEHLZMM-D5a2KZV2.js} +1 -1
  13. package/dist/client/assets/{c-B3C0Or4o.js → c-T1BrPfJ6.js} +1 -1
  14. package/dist/client/assets/{c4Diagram-AAUBKEIU-C7SsS28g.js → c4Diagram-AAUBKEIU-mpMH4kFC.js} +1 -1
  15. package/dist/client/assets/channel-D3niKhl0.js +1 -0
  16. package/dist/client/assets/{chunk-2J33WTMH-DHOUGWx8.js → chunk-2J33WTMH-vMtgRLFH.js} +1 -1
  17. package/dist/client/assets/{chunk-3OPIFGDE-D8d2scLX.js → chunk-3OPIFGDE-Dx-FqyO2.js} +1 -1
  18. package/dist/client/assets/{chunk-4BX2VUAB-BSC-E5yg.js → chunk-4BX2VUAB-CUrPd8Kv.js} +1 -1
  19. package/dist/client/assets/{chunk-55IACEB6-27pC5pKn.js → chunk-55IACEB6-DHg3Nr8A.js} +1 -1
  20. package/dist/client/assets/{chunk-5ZQYHXKU-BM60x82y.js → chunk-5ZQYHXKU-CpDPvbGs.js} +1 -1
  21. package/dist/client/assets/{chunk-727SXJPM-CHCF96vE.js → chunk-727SXJPM-3VOGMxwk.js} +1 -1
  22. package/dist/client/assets/{chunk-AQP2D5EJ-BoVsvmTa.js → chunk-AQP2D5EJ-4dbfbIS6.js} +1 -1
  23. package/dist/client/assets/{chunk-BSJP7CBP-Iip4uSio.js → chunk-BSJP7CBP-Dfyn0Uwp.js} +1 -1
  24. package/dist/client/assets/{chunk-CSCIHK7Q-DuIWPyay.js → chunk-CSCIHK7Q-VTpSKo0F.js} +1 -1
  25. package/dist/client/assets/{chunk-FMBD7UC4-Du6rtd2k.js → chunk-FMBD7UC4-kXD1MyOL.js} +1 -1
  26. package/dist/client/assets/{chunk-KSCS5N6A-BBq105vI.js → chunk-KSCS5N6A-BrVoWOAb.js} +1 -1
  27. package/dist/client/assets/{chunk-L5ZTLDWV-0DmB5Qp8.js → chunk-L5ZTLDWV-wZEQDPsa.js} +1 -1
  28. package/dist/client/assets/{chunk-LZXEDZCA-CoRsjUfr.js → chunk-LZXEDZCA-D3i0B0eg.js} +2 -2
  29. package/dist/client/assets/{chunk-ND2GUHAM-tX8cKEls.js → chunk-ND2GUHAM-hDVHT0bN.js} +1 -1
  30. package/dist/client/assets/{chunk-NZK2D7GU-BoJGgPic.js → chunk-NZK2D7GU-jQUfhp9h.js} +1 -1
  31. package/dist/client/assets/{chunk-O5CBEL6O-mlwCWs97.js → chunk-O5CBEL6O-CX_vPWhk.js} +1 -1
  32. package/dist/client/assets/chunk-QZHKN3VN-CZLFuGpt.js +1 -0
  33. package/dist/client/assets/chunk-WU5MYG2G-BhcpjkaB.js +1 -0
  34. package/dist/client/assets/{chunk-XPW4576I-B5efww8M.js → chunk-XPW4576I-Co_-vDB4.js} +1 -1
  35. package/dist/client/assets/classDiagram-4FO5ZUOK-DK5KJNIt.js +1 -0
  36. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-y5K9t6Se.js +1 -0
  37. package/dist/client/assets/{cobol-De9QR_Td.js → cobol-8-qBLs-a.js} +1 -1
  38. package/dist/client/assets/{coffee-Ct_GvuHP.js → coffee-Bjz5lkyW.js} +1 -1
  39. package/dist/client/assets/{cose-bilkent-S5V4N54A-ATaJZGF7.js → cose-bilkent-S5V4N54A-BljJ0FSA.js} +1 -1
  40. package/dist/client/assets/{cpp-Dw52w9cj.js → cpp-5BVQCBXT.js} +1 -1
  41. package/dist/client/assets/{crystal-Dx8ADdsd.js → crystal-CCkY93GS.js} +1 -1
  42. package/dist/client/assets/{css-CZ13XvDU.js → css-BTM7Tp2a.js} +1 -1
  43. package/dist/client/assets/{dagre-BM42HDAG-aDltuYut.js → dagre-BM42HDAG-BSynd_2D.js} +1 -1
  44. package/dist/client/assets/{diagram-2AECGRRQ-DGWnHVMJ.js → diagram-2AECGRRQ-K3E2CVdy.js} +1 -1
  45. package/dist/client/assets/{diagram-5GNKFQAL-Dd7eZBKe.js → diagram-5GNKFQAL-BQHIrfKc.js} +1 -1
  46. package/dist/client/assets/{diagram-KO2AKTUF-DWThXREf.js → diagram-KO2AKTUF-Bqs8sNN4.js} +1 -1
  47. package/dist/client/assets/{diagram-LMA3HP47-CXR4Bjtc.js → diagram-LMA3HP47-C9K4bpQe.js} +1 -1
  48. package/dist/client/assets/{diagram-OG6HWLK6-D4Cbf0nW.js → diagram-OG6HWLK6-DK6wIXY2.js} +1 -1
  49. package/dist/client/assets/{dist-CUDhrHNw.js → dist-1nkZYMRy.js} +1 -1
  50. package/dist/client/assets/{edge-CQCjdJKj.js → edge-DqN2FJce.js} +1 -1
  51. package/dist/client/assets/{elixir-bkjwPazA.js → elixir-BiAgRUFF.js} +1 -1
  52. package/dist/client/assets/{elm-CCweX5Cq.js → elm-N1IbY8sz.js} +1 -1
  53. package/dist/client/assets/{erDiagram-TEJ5UH35-BmAyt7SU.js → erDiagram-TEJ5UH35-jsHCiP02.js} +1 -1
  54. package/dist/client/assets/{erb-D-Z-KBLp.js → erb-B-yYlWAZ.js} +1 -1
  55. package/dist/client/assets/{flowDiagram-I6XJVG4X-C6nIFUVc.js → flowDiagram-I6XJVG4X-DOB1dAWG.js} +1 -1
  56. package/dist/client/assets/{ganttDiagram-6RSMTGT7-DMlxThBf.js → ganttDiagram-6RSMTGT7-BYIewcY5.js} +1 -1
  57. package/dist/client/assets/{git-rebase-BdoFdenB.js → git-rebase-CVkPxOAF.js} +1 -1
  58. package/dist/client/assets/{gitGraphDiagram-PVQCEYII-JaIFkAIT.js → gitGraphDiagram-PVQCEYII-VNQzbpv2.js} +1 -1
  59. package/dist/client/assets/{glimmer-js-CZQrBJKq.js → glimmer-js-BmG1xm72.js} +1 -1
  60. package/dist/client/assets/{glimmer-ts-CBYW46D4.js → glimmer-ts-CvTgwZsg.js} +1 -1
  61. package/dist/client/assets/{glsl-wxixKkY_.js → glsl-DwjNNCbW.js} +1 -1
  62. package/dist/client/assets/{graphql-CqZ0Lo5a.js → graphql-BvgkyF8E.js} +1 -1
  63. package/dist/client/assets/{hack-rqWymQRV.js → hack-DH3188x2.js} +1 -1
  64. package/dist/client/assets/{haml-DFw_IoGM.js → haml-B0GTfMhX.js} +1 -1
  65. package/dist/client/assets/{handlebars-3VmTVMYt.js → handlebars-he7hLDd9.js} +1 -1
  66. package/dist/client/assets/{html-C0Li76jB.js → html-DIYgdTBq.js} +1 -1
  67. package/dist/client/assets/{html-derivative-CO-RQW8y.js → html-derivative-2s6MXlci.js} +1 -1
  68. package/dist/client/assets/{http-sPrZOeBY.js → http-COS23XJP.js} +1 -1
  69. package/dist/client/assets/{hurl-DUoPe4Lc.js → hurl-BlZPjeJt.js} +1 -1
  70. package/dist/client/assets/index-BrEVVQOB.js +4021 -0
  71. package/dist/client/assets/index-BsuX6HVI.css +1 -0
  72. package/dist/client/assets/{infoDiagram-5YYISTIA-B6AZ5SCV.js → infoDiagram-5YYISTIA-DQRqk24I.js} +1 -1
  73. package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CytMrpo8.js → ishikawaDiagram-YF4QCWOH-DU1rqrLx.js} +1 -1
  74. package/dist/client/assets/{java-Cj0G6QRg.js → java-BAa5w-Qd.js} +1 -1
  75. package/dist/client/assets/{javascript-d5SUuyWD.js → javascript-C9e02ssI.js} +1 -1
  76. package/dist/client/assets/{jinja-BTw9k0vO.js → jinja-Bx37xXwq.js} +1 -1
  77. package/dist/client/assets/{jison-9xSVvR1q.js → jison-m_DEf8Jo.js} +1 -1
  78. package/dist/client/assets/{journeyDiagram-JHISSGLW-Bd4jZUYI.js → journeyDiagram-JHISSGLW-CoHlfevf.js} +1 -1
  79. package/dist/client/assets/{json-DjAt53ka.js → json-DtN5AWRW.js} +1 -1
  80. package/dist/client/assets/{jsx-BX5KmQ7d.js → jsx-BlPpu8bR.js} +1 -1
  81. package/dist/client/assets/{julia-CLLx1dHC.js → julia-BAOmCbHl.js} +1 -1
  82. package/dist/client/assets/{just-C0v80bKe.js → just-C_bvVjwE.js} +1 -1
  83. package/dist/client/assets/{kanban-definition-UN3LZRKU-Ds4pXHJa.js → kanban-definition-UN3LZRKU-BiqYI7_m.js} +1 -1
  84. package/dist/client/assets/{latex-DY-oQfwO.js → latex-81pMfNMt.js} +1 -1
  85. package/dist/client/assets/{line-BbSLfOl6.js → line-DCovs9My.js} +1 -1
  86. package/dist/client/assets/{linear-BMIZJAAR.js → linear-cJF5XHE7.js} +1 -1
  87. package/dist/client/assets/{liquid-DDHDgbZx.js → liquid-sKRTk6dT.js} +1 -1
  88. package/dist/client/assets/{lua-CXymerKS.js → lua-C1uZL4IF.js} +1 -1
  89. package/dist/client/assets/{marko-DoPFsptl.js → marko-BKEzP1CL.js} +1 -1
  90. package/dist/client/assets/{mdc-BxSmTphd.js → mdc-CLkfm94H.js} +1 -1
  91. package/dist/client/assets/{mermaid-parser.core-CcYSvN4q.js → mermaid-parser.core-CTsTbvb2.js} +1 -1
  92. package/dist/client/assets/{mermaid.core-COTNtqgQ.js → mermaid.core-D86HJEwL.js} +3 -3
  93. package/dist/client/assets/{mindmap-definition-RKZ34NQL-BTxraRzn.js → mindmap-definition-RKZ34NQL-CL3heUmL.js} +1 -1
  94. package/dist/client/assets/{nginx-Bma0jNOT.js → nginx-eDGm66pc.js} +1 -1
  95. package/dist/client/assets/{nim-DMBpjygU.js → nim-CoWZPv8-.js} +1 -1
  96. package/dist/client/assets/{perl-CrnrV-AJ.js → perl-MoMqtMVr.js} +1 -1
  97. package/dist/client/assets/{php-CDYxzX6t.js → php-DXXVMAtN.js} +1 -1
  98. package/dist/client/assets/{pieDiagram-4H26LBE5-DglRmzer.js → pieDiagram-4H26LBE5-CWV3TMu4.js} +1 -1
  99. package/dist/client/assets/{pug-DNewy3GU.js → pug-CPWaB94J.js} +1 -1
  100. package/dist/client/assets/{qml-COjcnZ-W.js → qml-lhvpx8vk.js} +1 -1
  101. package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BjSmyES7.js → quadrantDiagram-W4KKPZXB-QV25BYos.js} +1 -1
  102. package/dist/client/assets/{r-CrCaMxLS.js → r-DYbUnmmK.js} +1 -1
  103. package/dist/client/assets/{razor-jeuOZIar.js → razor-DcyOLv96.js} +1 -1
  104. package/dist/client/assets/{regexp-DSHVUX08.js → regexp-BdY10jm0.js} +1 -1
  105. package/dist/client/assets/{requirementDiagram-4Y6WPE33-B4f430jS.js → requirementDiagram-4Y6WPE33-BPMsmU6J.js} +1 -1
  106. package/dist/client/assets/{review-export-Cen1WEcX.js → review-export-CMwjJURs.js} +1 -1
  107. package/dist/client/assets/{rst-CIDgytzc.js → rst-6ShFOzgH.js} +1 -1
  108. package/dist/client/assets/{ruby-DtuseoNq.js → ruby-B04DeVbi.js} +1 -1
  109. package/dist/client/assets/{sankeyDiagram-5OEKKPKP-TQPPlxc6.js → sankeyDiagram-5OEKKPKP-DQJeroPp.js} +1 -1
  110. package/dist/client/assets/{sas-C72Theia.js → sas-Dj26ftNa.js} +1 -1
  111. package/dist/client/assets/{scss-ClECtwRk.js → scss-BOHpBkgl.js} +1 -1
  112. package/dist/client/assets/{sequenceDiagram-3UESZ5HK-D1tx07Wg.js → sequenceDiagram-3UESZ5HK-DdV0Y6Sz.js} +1 -1
  113. package/dist/client/assets/{shellscript-BCwBsi2k.js → shellscript-CpHwjRcU.js} +1 -1
  114. package/dist/client/assets/{shellsession-BrOddEl5.js → shellsession-BJAvf4GN.js} +1 -1
  115. package/dist/client/assets/{soy-Dcs0GWFW.js → soy-B67bZJnL.js} +1 -1
  116. package/dist/client/assets/{sql-BAjA7Gv7.js → sql-8MzOqSsK.js} +1 -1
  117. package/dist/client/assets/{src-CYYhkqTK.js → src-AaoRSmFl.js} +1 -1
  118. package/dist/client/assets/{stata-19ngQtzR.js → stata-aCME945h.js} +1 -1
  119. package/dist/client/assets/{stateDiagram-AJRCARHV-BZRCEzb5.js → stateDiagram-AJRCARHV-CMD_Xj2M.js} +1 -1
  120. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-vLl7D4ue.js +1 -0
  121. package/dist/client/assets/{surrealql-Ce2TBRjE.js → surrealql-B_V_HxAi.js} +1 -1
  122. package/dist/client/assets/{svelte-DQ_1eGZz.js → svelte-BcQvTlqz.js} +1 -1
  123. package/dist/client/assets/{templ-Cw2DDxWF.js → templ-DZCQ2blz.js} +1 -1
  124. package/dist/client/assets/{tex-myDSO2eP.js → tex-BfeQ5Wuu.js} +1 -1
  125. package/dist/client/assets/{timeline-definition-PNZ67QCA-CP0OZhBT.js → timeline-definition-PNZ67QCA-CyIS7Zoe.js} +1 -1
  126. package/dist/client/assets/{ts-tags-rh39ZwVs.js → ts-tags-DVWE0E87.js} +1 -1
  127. package/dist/client/assets/{tsx-B0-26jrU.js → tsx-DdJ7Sfqf.js} +1 -1
  128. package/dist/client/assets/{twig-CgasHzPb.js → twig-_gVgaha5.js} +1 -1
  129. package/dist/client/assets/{typescript-Dq3T0c-m.js → typescript-Bj0_LzZV.js} +1 -1
  130. package/dist/client/assets/{vennDiagram-CIIHVFJN-DHaKHj0j.js → vennDiagram-CIIHVFJN-C-J2kWyk.js} +1 -1
  131. package/dist/client/assets/{vue-CzFVh92-.js → vue-Dnt_GBRb.js} +1 -1
  132. package/dist/client/assets/{vue-html-Bv2uFkTH.js → vue-html-ClVA5__5.js} +1 -1
  133. package/dist/client/assets/{vue-vine-DzieBk9Y.js → vue-vine-BCcz4SVP.js} +1 -1
  134. package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Dky7jxlZ.js → wardleyDiagram-YWT4CUSO-Dzt4EPh8.js} +1 -1
  135. package/dist/client/assets/{xml-wcdHRHN8.js → xml-BYeUHEti.js} +1 -1
  136. package/dist/client/assets/{xsl-CXrwsLG9.js → xsl-Vsx0SZEV.js} +1 -1
  137. package/dist/client/assets/{xychartDiagram-2RQKCTM6-BQ2hG60h.js → xychartDiagram-2RQKCTM6-BAWZKvwP.js} +1 -1
  138. package/dist/client/assets/{yaml-lO6lK6Xe.js → yaml-C6L1khMK.js} +1 -1
  139. package/dist/client/index.html +2 -2
  140. package/dist/{completions-3UF8uzhx.mjs → completions-DvyV49HY.mjs} +22 -1
  141. package/dist/{doctor-BGYZNIYP.mjs → doctor-Bz9VHuBI.mjs} +7 -6
  142. package/dist/find-tui-binary-DVQADOSF.mjs +101 -0
  143. package/dist/{git-Czo96ymM.mjs → git-BGj31GX-.mjs} +71 -7
  144. package/dist/git-CfDSkUcE.mjs +2 -0
  145. package/dist/{github-DKT0lJXv.mjs → github-DXiEeHzk.mjs} +1 -1
  146. package/dist/{github-CEjtGd41.mjs → github-DpzqNrUh.mjs} +3 -3
  147. package/dist/{github-attachments-Cf17YWp4.mjs → github-attachments-DgOf7BhP.mjs} +2 -2
  148. package/dist/{mcp-Dq7J5QOP.mjs → mcp-zDVzU1vl.mjs} +42 -33
  149. package/dist/native/tui-darwin-arm64/diffing-tui +0 -0
  150. package/dist/native/tui-darwin-x64/diffing-tui +0 -0
  151. package/dist/native/tui-linux-arm64-gnu/diffing-tui +0 -0
  152. package/dist/native/tui-linux-arm64-musl/diffing-tui +0 -0
  153. package/dist/native/tui-linux-x64-gnu/diffing-tui +0 -0
  154. package/dist/native/tui-linux-x64-musl/diffing-tui +0 -0
  155. package/dist/native/tui-win32-x64-msvc/diffing-tui.exe +0 -0
  156. package/dist/{review-export-BBDWvftT.mjs → review-export-B63eRAVa.mjs} +1 -1
  157. package/dist/{settings-bwe7yQ8U.mjs → search-3R2E5xxr.mjs} +133 -98
  158. package/dist/search-CQ4nsjBX.mjs +2 -0
  159. package/dist/{server-C9i4V36o.mjs → server-Dw3lkQ5q.mjs} +296 -110
  160. package/dist/server-lock-BNI8FKV1.mjs +427 -0
  161. package/dist/session-conflict-Bqt1M4Mp.mjs +96 -0
  162. package/dist/session-manager-BKSZQqDJ.mjs +159 -0
  163. package/dist/session-url-sr7lXXVc.mjs +100 -0
  164. package/dist/tui-search-bridge-BGgLCwMF.mjs +133 -0
  165. package/dist/{update-check-DUuHmPeZ.mjs → update-check-BUfh4Y6c.mjs} +16 -15
  166. package/package.json +9 -4
  167. package/dist/client/assets/channel-lsVHTuYR.js +0 -1
  168. package/dist/client/assets/chunk-QZHKN3VN-AHUiTM0z.js +0 -1
  169. package/dist/client/assets/chunk-WU5MYG2G-D41j4yxb.js +0 -1
  170. package/dist/client/assets/classDiagram-4FO5ZUOK-D1Eo3kly.js +0 -1
  171. package/dist/client/assets/classDiagram-v2-Q7XG4LA2-bAMsbsfB.js +0 -1
  172. package/dist/client/assets/index-B42c0TyV.css +0 -1
  173. package/dist/client/assets/index-BN_-di_r.js +0 -3959
  174. package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Da-mGMA2.js +0 -1
  175. package/dist/find-tui-binary-CRpbYXLC.mjs +0 -52
  176. package/dist/git-DaP_1rVy.mjs +0 -2
  177. package/dist/server-lock-Dd_ss_Il.mjs +0 -153
  178. /package/dist/{apply-suggestion-DNNsC5gx.mjs → apply-suggestion-CHYnw68I.mjs} +0 -0
  179. /package/dist/{comment-format-B5AcGcR-.mjs → comment-format-B85NHZnG.mjs} +0 -0
  180. /package/dist/{diff-fingerprint-C8YO3TTE.mjs → diff-fingerprint-BgR0tu1o.mjs} +0 -0
  181. /package/dist/{handoff-DPoIyeWn.mjs → handoff-LAFtmnHf.mjs} +0 -0
  182. /package/dist/{plan-format-BQyx--mp.mjs → plan-format-BwJh5JSE.mjs} +0 -0
package/dist/cli.mjs CHANGED
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
- import { a as intoShowMode, n as runTerminalDiff, o as parseDiffOptions, r as validateEnvironment, s as printHelp, t as startServer } from "./server-C9i4V36o.mjs";
3
- import { p as getRepoRoot } from "./git-Czo96ymM.mjs";
4
- import { t as loadSettings } from "./settings-bwe7yQ8U.mjs";
5
- import { a as removeServerLock, i as readServerLock, n as diffScopeKey, o as removeServerLockIfOwned, r as isLockAlive, s as writeServerLock, t as acquireServerStartupLease } from "./server-lock-Dd_ss_Il.mjs";
6
- import { t as findTuiBinary$1 } from "./find-tui-binary-CRpbYXLC.mjs";
7
- import { spawn } from "node:child_process";
2
+ import { a as buildTuiGitDiffArgs, c as printHelp, n as runTerminalDiff, o as intoShowMode, r as validateEnvironment, s as parseDiffOptions, t as startServer } from "./server-Dw3lkQ5q.mjs";
3
+ import { h as getRepoRoot, r as getBranchName } from "./git-BGj31GX-.mjs";
4
+ import { a as loadSettings, t as appendSessionToken } from "./session-url-sr7lXXVc.mjs";
5
+ import { S as isWildcardBindHost, c as removeServerLockIfOwned, p as writeServerLock, r as diffScopeKey, t as acquireServerStartupLease, u as resolveActiveServerLock, y as generateSessionToken } from "./server-lock-BNI8FKV1.mjs";
6
+ import { n as openExistingSession, r as stopLockOwner } from "./session-conflict-Bqt1M4Mp.mjs";
7
+ import { n as findTuiBinary$1, r as findViewerTuiBinary, t as findTuiBinaries } from "./find-tui-binary-DVQADOSF.mjs";
8
+ import { execFileSync, spawn } from "node:child_process";
8
9
  import { randomUUID } from "node:crypto";
9
10
  import { fileURLToPath } from "node:url";
10
11
  import { dirname, isAbsolute, resolve } from "node:path";
11
12
  import { existsSync, readFileSync } from "node:fs";
12
13
  import getPort from "get-port";
13
14
  import { stdout } from "node:process";
14
- import { createInterface } from "node:readline";
15
15
  //#region src/lib/startup-display.ts
16
16
  const R = "\x1B[0m";
17
17
  const B = "\x1B[1m";
@@ -144,7 +144,7 @@ const QUOTES = [
144
144
  author: "Unknown"
145
145
  },
146
146
  {
147
- text: "A QA engineer walks into a coffie shop. Orders 0 cups. Orders 999999 cups. Orders NULL cups. Walks in through the window.",
147
+ text: "A QA engineer walks into a coffee shop. Orders 0 cups. Orders 999999 cups. Orders NULL cups. Walks in through the window.",
148
148
  author: "Unknown"
149
149
  },
150
150
  {
@@ -379,6 +379,12 @@ const ANIMS = [
379
379
  function playStartupDisplay() {
380
380
  if (!stdout.isTTY) return Promise.resolve();
381
381
  return (async () => {
382
+ const onInterrupt = () => {
383
+ try {
384
+ stdout.write(SHOW);
385
+ } catch {}
386
+ };
387
+ process.once("SIGINT", onInterrupt);
382
388
  try {
383
389
  const quote = QUOTES[Math.floor(Math.random() * QUOTES.length)];
384
390
  const pal = PALETTES[Math.floor(Math.random() * PALETTES.length)];
@@ -388,174 +394,85 @@ function playStartupDisplay() {
388
394
  await anim(b);
389
395
  stdout.write(SHOW);
390
396
  } catch {
391
- try {
392
- stdout.write(SHOW);
393
- } catch {}
397
+ onInterrupt();
398
+ } finally {
399
+ process.off("SIGINT", onInterrupt);
394
400
  }
395
401
  })();
396
402
  }
397
403
  //#endregion
398
- //#region src/lib/session-conflict.ts
399
- function sleepMs(ms) {
400
- return new Promise((resolve) => setTimeout(resolve, ms));
401
- }
402
- /** Loopback-safe review URL for web / gh-pr locks; null for TUI or invalid ports. */
403
- function existingSessionUrl(lock) {
404
- const mode = lock.mode ?? "web";
405
- if (mode === "tui" || !(lock.port > 0)) return null;
406
- const host = lock.host === "0.0.0.0" ? "127.0.0.1" : lock.host;
407
- const path = mode === "gh-pr" ? "/gh/pr" : "";
408
- return `http://${host}:${lock.port}${path}`;
409
- }
410
- function formatExistingSession(lock) {
411
- const mode = lock.mode ?? "web";
412
- const url = existingSessionUrl(lock);
413
- return [
414
- "A diffing review is already running for this repository",
415
- url ? ` url: ${url}` : " url: (TUI session — no browser URL)",
416
- ` mode: ${mode}`,
417
- ` pid: ${lock.pid}`
418
- ].join("\n");
419
- }
420
- function conflictFailMessage(lock) {
421
- return `A diffing review is already running for this repository at ${existingSessionUrl(lock) ?? (lock.mode === "tui" || lock.port <= 0 ? "a TUI session" : `http://${lock.host}:${lock.port}`)}. End it before starting another scope.`;
422
- }
404
+ //#region src/lib/tui-diff-context.ts
423
405
  /**
424
- * Resolve how to handle a live session conflict.
425
- * Flags win over the prompt; non-interactive callers get `cancel`.
406
+ * Build the compact "what is this diff?" label consumed by the native TUI.
407
+ *
408
+ * This deliberately uses the options the CLI already parsed instead of
409
+ * executing the diff a second time just to reproduce the web overview.
410
+ * File and line counts are added by the TUI from its live sparse index.
426
411
  */
427
- async function resolveSessionConflictAction(options) {
428
- if (options.reuseSession && options.replaceSession) throw new Error("Cannot combine --reuse-session and --replace-session.");
429
- if (options.reuseSession) return "open";
430
- if (options.replaceSession) return "replace";
431
- if (!options.canPrompt) return "cancel";
432
- return (options.prompt ?? promptSessionConflict)(options.lock);
433
- }
434
- /**
435
- * Interactive o/r/c prompt. Empty input defaults to open. Ctrl+C → cancel.
436
- */
437
- async function promptSessionConflict(lock) {
438
- const rl = createInterface({
439
- input: process.stdin,
440
- output: process.stderr
441
- });
442
- try {
443
- console.error(formatExistingSession(lock));
444
- console.error("");
445
- console.error("What do you want to do?");
446
- console.error(" [o] Open the existing session (default)");
447
- console.error(` [r] Replace it (stop pid ${lock.pid}, start a new review)`);
448
- console.error(" [c] Cancel");
449
- console.error("");
450
- while (true) {
451
- const choice = (await new Promise((resolve, reject) => {
452
- const onSigInt = () => {
453
- cleanup();
454
- reject(/* @__PURE__ */ new Error("cancelled"));
455
- };
456
- const cleanup = () => {
457
- process.off("SIGINT", onSigInt);
458
- };
459
- process.on("SIGINT", onSigInt);
460
- rl.question("Choice [o/r/c]: ", (raw) => {
461
- cleanup();
462
- resolve(raw);
463
- });
464
- })).trim().toLowerCase();
465
- if (choice === "" || choice === "o" || choice === "open") return "open";
466
- if (choice === "r" || choice === "replace") return "replace";
467
- if (choice === "c" || choice === "cancel" || choice === "q" || choice === "quit") return "cancel";
468
- console.error("Please enter o, r, or c.");
469
- }
470
- } catch {
471
- return "cancel";
472
- } finally {
473
- rl.close();
474
- }
475
- }
476
- function defaultClearLock(lock) {
477
- const current = readServerLock(lock.repoRoot);
478
- if (current && current.pid === lock.pid) removeServerLock(lock.repoRoot);
412
+ function buildTuiDiffContext(opts, branch) {
413
+ const onBranch = branch ? ` on ${branch}` : "";
414
+ const detail = pathspecDetail(opts.pathspecs);
415
+ if (opts.showMode) {
416
+ const label = opts.showRevspecs.join(" ");
417
+ return {
418
+ kind: "commit",
419
+ headline: label ? `Showing ${label}` : "Commit changes",
420
+ ...detail ? { detail } : {}
421
+ };
422
+ }
423
+ if (opts.revisions.length > 0) {
424
+ const current = branch ? ` (current: ${branch})` : "";
425
+ return {
426
+ kind: "range",
427
+ headline: `Comparing ${opts.revisions.join(" ")}${current}`,
428
+ ...detail ? { detail } : {}
429
+ };
430
+ }
431
+ if (opts.staged) return {
432
+ kind: "staged-only",
433
+ headline: `Staged changes${onBranch}`,
434
+ ...detail ? { detail } : {}
435
+ };
436
+ return {
437
+ kind: "working-tree",
438
+ headline: `Working-tree changes${onBranch}`,
439
+ ...detail ? { detail } : {}
440
+ };
479
441
  }
480
- function pidAlive(pid, kill) {
481
- try {
482
- kill(pid, 0);
483
- return true;
484
- } catch {
485
- return false;
486
- }
442
+ function pathspecDetail(pathspecs) {
443
+ if (pathspecs.length === 0) return void 0;
444
+ if (pathspecs.length === 1) return `Path: ${pathspecs[0]}`;
445
+ return `${pathspecs.length} path filters`;
487
446
  }
447
+ //#endregion
448
+ //#region src/lib/tui-child-lifecycle.ts
488
449
  /**
489
- * Gracefully stop the process that owns `lock`, then clear a matching lockfile.
490
- * SIGTERM wait SIGKILL wait throw.
450
+ * Release optional TUI-side resources without leaving the CLI's launch
451
+ * promise pending. Cleanup failures must not replace the native process's
452
+ * exit code.
491
453
  */
492
- async function stopLockOwner(lock, options = {}) {
493
- const timeoutMs = options.timeoutMs ?? 5e3;
494
- const killDeadlineMs = options.killDeadlineMs ?? 2e3;
495
- const pollMs = options.pollMs ?? 100;
496
- const kill = options.kill ?? ((pid, signal) => process.kill(pid, signal));
497
- const sleep = options.sleep ?? sleepMs;
498
- const now = options.now ?? Date.now;
499
- const isAlive = options.isAlive ?? ((candidate) => pidAlive(candidate.pid, kill));
500
- const clearLock = options.clearLock ?? defaultClearLock;
501
- if (!isAlive(lock)) {
502
- clearLock(lock);
503
- return;
504
- }
454
+ async function finishTuiChild(resource, settle) {
505
455
  try {
506
- kill(lock.pid, "SIGTERM");
507
- } catch {}
508
- const termDeadline = now() + timeoutMs;
509
- while (now() < termDeadline) {
510
- if (!isAlive(lock)) {
511
- clearLock(lock);
512
- return;
513
- }
514
- await sleep(pollMs);
456
+ await resource?.close();
457
+ } catch {} finally {
458
+ settle();
515
459
  }
516
- try {
517
- kill(lock.pid, "SIGKILL");
518
- } catch {}
519
- const killDeadline = now() + killDeadlineMs;
520
- while (now() < killDeadline) {
521
- if (!isAlive(lock)) {
522
- clearLock(lock);
523
- return;
524
- }
525
- await sleep(pollMs);
526
- }
527
- throw new Error(`Timed out waiting for diffing pid ${lock.pid} to exit after SIGTERM/SIGKILL. End that process manually and try again.`);
528
460
  }
529
- /** Print and optionally open the existing web/gh-pr session; message-only for TUI. */
530
- async function openExistingSession(lock, options) {
531
- if ((lock.mode ?? "web") === "tui") {
532
- console.log(`A diffing TUI session is already open for this repository (pid ${lock.pid}). Use that terminal, or replace it with --replace-session.`);
533
- return;
534
- }
535
- const url = existingSessionUrl(lock);
536
- if (!url) {
537
- console.log(`A diffing review is already running for this repository (pid ${lock.pid}).`);
538
- return;
539
- }
540
- console.log(`Opening existing diffing session at ${url}`);
541
- if (options.noOpen) return;
542
- if (options.openUrl) {
543
- await options.openUrl(url);
544
- return;
461
+ //#endregion
462
+ //#region src/cli.ts
463
+ async function resolveServerPort(requested) {
464
+ if (requested === void 0) return getPort();
465
+ if (!Number.isInteger(requested) || requested < 1 || requested > 65535) {
466
+ console.error(`--port must be an integer between 1 and 65535 (got ${String(requested)}).`);
467
+ process.exit(5);
545
468
  }
546
- try {
547
- const settings = loadSettings();
548
- const openModule = await import("open");
549
- let appName;
550
- if (settings.browser) appName = openModule.apps[settings.browser] || settings.browser;
551
- const openOptions = appName ? { app: { name: appName } } : {};
552
- await openModule.default(url, openOptions);
553
- } catch (err) {
554
- console.error("Failed to open browser:", err instanceof Error ? err.message : err);
469
+ const port = await getPort({ port: requested });
470
+ if (port !== requested) {
471
+ console.error(`Port ${requested} is not available.`);
472
+ process.exit(1);
555
473
  }
474
+ return port;
556
475
  }
557
- //#endregion
558
- //#region src/cli.ts
559
476
  const args = process.argv.slice(2);
560
477
  let prRef = null;
561
478
  let ghPrConsumed = 0;
@@ -585,7 +502,9 @@ if (new Set([
585
502
  "doctor",
586
503
  "completion",
587
504
  "progress",
588
- "inspect"
505
+ "inspect",
506
+ "mode",
507
+ "sessions"
589
508
  ]).has(args[0])) {
590
509
  if (args[0] === "mcp") {
591
510
  const mcpArgs = args.slice(1);
@@ -636,19 +555,27 @@ See docs/cli.md §5 (MCP) for the full tool table.`);
636
555
  console.error("diffing mcp: --repo must be an absolute path");
637
556
  process.exit(5);
638
557
  }
639
- const { startMcpServer } = await import("./mcp-Dq7J5QOP.mjs");
558
+ const { startMcpServer } = await import("./mcp-zDVzU1vl.mjs");
640
559
  await startMcpServer({ repoPath });
641
560
  await new Promise(() => {});
642
561
  }
643
- const { runSubcommand } = await import("./cli-agent-BJiATn11.mjs");
562
+ const { runSubcommand } = await import("./cli-agent-CWsOHN-j.mjs");
644
563
  process.exit(await runSubcommand(args[0], args.slice(1)));
645
564
  }
565
+ if (args[0] === "view") {
566
+ args.shift();
567
+ args.unshift("--view");
568
+ }
646
569
  let showSubcommand = false;
647
570
  if (args[0] === "show") {
648
571
  showSubcommand = true;
649
572
  args.shift();
650
573
  }
651
- const opts = parseDiffOptions(args);
574
+ const opts = parseDiffOptions(args, prRef ? "web" : loadSettings().defaultMode);
575
+ if (opts.reuseSession && opts.replaceSession) {
576
+ console.error("Cannot combine --reuse-session and --replace-session.");
577
+ process.exit(5);
578
+ }
652
579
  if (!prRef && opts.ghPr) prRef = opts.ghPr;
653
580
  if (showSubcommand) {
654
581
  if (opts.revisions.length === 0 && !opts.help && !opts.version) {
@@ -673,7 +600,7 @@ if (envErr) {
673
600
  process.exit(1);
674
601
  }
675
602
  if (opts.outputMode === "tui") {
676
- const tuiResult = await launchTui(args);
603
+ const tuiResult = await launchTui(args, opts);
677
604
  process.exit(tuiResult);
678
605
  }
679
606
  if (opts.outputMode === "terminal") {
@@ -684,14 +611,20 @@ const __pkgDir = dirname(fileURLToPath(import.meta.url));
684
611
  const currentVersion = JSON.parse(readFileSync(resolve(__pkgDir, "..", "package.json"), "utf-8")).version;
685
612
  const updateCheckPromise = (async () => {
686
613
  try {
687
- const { checkForUpdates } = await import("./update-check-DUuHmPeZ.mjs");
614
+ const { checkForUpdates } = await import("./update-check-BUfh4Y6c.mjs");
688
615
  return await checkForUpdates(currentVersion);
689
616
  } catch {
690
617
  return null;
691
618
  }
692
619
  })();
693
- const port = await getPort(opts.port ? { port: opts.port } : void 0);
620
+ const port = await resolveServerPort(opts.port);
694
621
  const host = opts.host;
622
+ if (isWildcardBindHost(host) && !opts.insecureNoAuth) {
623
+ console.error("Binding to all interfaces requires --insecure-no-auth. Loopback review (default --host 127.0.0.1) uses a per-session API token instead.");
624
+ process.exit(1);
625
+ }
626
+ const authToken = opts.insecureNoAuth ? null : generateSessionToken();
627
+ if (isWildcardBindHost(host) && opts.insecureNoAuth) console.error("WARNING: diffing is exposed on the LAN without API authentication. Anyone on your network can read and modify review data.");
695
628
  const clientDir = resolve(__pkgDir, "client");
696
629
  const resolvedClientDir = existsSync(clientDir) ? clientDir : resolve(process.cwd(), "dist/client");
697
630
  const openModulePromise = opts.noOpen ? null : import("open");
@@ -707,51 +640,21 @@ if (!startupLease) {
707
640
  console.error("Another diffing process is starting a review for this repository. Retry in a moment.");
708
641
  process.exit(3);
709
642
  }
710
- const existingLock = readServerLock(repoRoot);
711
- if (existingLock && isLockAlive(existingLock, repoRoot)) {
643
+ const activeSession = opts.reuseSession || opts.replaceSession ? resolveActiveServerLock(repoRoot) : null;
644
+ if (activeSession && opts.reuseSession) {
712
645
  startupLease.release();
713
646
  startupLease = null;
714
- if (opts.reuseSession && opts.replaceSession) {
715
- console.error("Cannot combine --reuse-session and --replace-session.");
716
- process.exit(5);
717
- }
718
- let action;
719
- try {
720
- action = await resolveSessionConflictAction({
721
- lock: existingLock,
722
- reuseSession: opts.reuseSession,
723
- replaceSession: opts.replaceSession,
724
- canPrompt: Boolean(process.stdin.isTTY && process.stdout.isTTY)
725
- });
726
- } catch (error) {
727
- const detail = error instanceof Error ? error.message : String(error);
728
- console.error(detail);
729
- process.exit(5);
730
- }
731
- if (action === "cancel") {
732
- console.error(conflictFailMessage(existingLock));
733
- process.exit(3);
734
- }
735
- if (action === "open") {
736
- const live = readServerLock(repoRoot);
737
- await openExistingSession(live && isLockAlive(live, repoRoot) ? live : existingLock, { noOpen: opts.noOpen });
738
- process.exit(0);
739
- }
740
- startupLease = acquireServerStartupLease(repoRoot, sessionOwnerId);
741
- if (!startupLease) {
742
- console.error("Another diffing process is starting a review for this repository. Retry in a moment.");
743
- process.exit(3);
744
- }
745
- const afterLease = readServerLock(repoRoot);
746
- if (afterLease && isLockAlive(afterLease, repoRoot)) try {
747
- console.error(`Stopping existing diffing session (pid ${afterLease.pid})…`);
748
- await stopLockOwner(afterLease);
749
- } catch (error) {
750
- startupLease.release();
751
- const detail = error instanceof Error ? error.message : String(error);
752
- console.error(detail);
753
- process.exit(1);
754
- }
647
+ await openExistingSession(activeSession, { noOpen: opts.noOpen });
648
+ process.exit(0);
649
+ }
650
+ if (activeSession && opts.replaceSession) try {
651
+ console.error(`Stopping active diffing session (pid ${activeSession.pid})…`);
652
+ await stopLockOwner(activeSession);
653
+ } catch (error) {
654
+ startupLease.release();
655
+ const detail = error instanceof Error ? error.message : String(error);
656
+ console.error(detail);
657
+ process.exit(1);
755
658
  }
756
659
  let actualPort;
757
660
  let prMode;
@@ -761,7 +664,12 @@ try {
761
664
  host,
762
665
  clientDir: resolvedClientDir,
763
666
  diffOpts: opts,
764
- prRef: prRef ?? void 0
667
+ prRef: prRef ?? void 0,
668
+ security: {
669
+ bindHost: host,
670
+ authToken,
671
+ insecureNoAuth: opts.insecureNoAuth
672
+ }
765
673
  });
766
674
  actualPort = started.port;
767
675
  prMode = started.prMode;
@@ -775,7 +683,9 @@ try {
775
683
  mode: prMode ? "gh-pr" : "web",
776
684
  prRef: prMode ? prRef ?? void 0 : void 0,
777
685
  scope: diffScopeKey(opts),
778
- ownerId: sessionOwnerId
686
+ ownerId: sessionOwnerId,
687
+ sessionId: sessionOwnerId,
688
+ authToken: authToken ?? void 0
779
689
  });
780
690
  } catch (error) {
781
691
  startupLease?.release();
@@ -785,11 +695,11 @@ try {
785
695
  }
786
696
  startupLease?.release();
787
697
  startupLease = null;
788
- const localUrl = `http://${host}:${actualPort}`;
698
+ const localUrl = appendSessionToken(`http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${actualPort}${prMode ? "/gh/pr" : ""}`, authToken ?? void 0);
789
699
  console.log(`diffing server running at ${localUrl}`);
790
700
  if (openModulePromise) try {
791
701
  const settings = loadSettings();
792
- const openUrl = `http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${actualPort}${prMode ? "/gh/pr" : ""}`;
702
+ const openUrl = appendSessionToken(`http://${host === "0.0.0.0" ? "127.0.0.1" : host}:${actualPort}${prMode ? "/gh/pr" : ""}`, authToken ?? void 0);
793
703
  const openModule = await openModulePromise;
794
704
  let appName;
795
705
  if (settings.browser) appName = openModule.apps[settings.browser] || settings.browser;
@@ -798,11 +708,11 @@ if (openModulePromise) try {
798
708
  } catch (err) {
799
709
  console.error("Failed to open browser:", err instanceof Error ? err.message : err);
800
710
  }
801
- playStartupDisplay();
711
+ await playStartupDisplay();
802
712
  try {
803
713
  const updateInfo = await updateCheckPromise;
804
714
  if (updateInfo?.hasUpdate) {
805
- const { printUpdateDisclaimer } = await import("./update-check-DUuHmPeZ.mjs");
715
+ const { printUpdateDisclaimer } = await import("./update-check-BUfh4Y6c.mjs");
806
716
  printUpdateDisclaimer(currentVersion, updateInfo.latestVersion);
807
717
  }
808
718
  } catch {}
@@ -818,8 +728,23 @@ process.on("SIGTERM", shutdown);
818
728
  * so the search paths anchor to the bundled CLI's directory. The real
819
729
  * implementation lives in `lib/find-tui-binary.ts` and is unit-tested there.
820
730
  */
821
- function findTuiBinary() {
822
- return findTuiBinary$1(import.meta.url);
731
+ function findTuiBinary(requireViewer = false) {
732
+ if (!requireViewer) return findTuiBinary$1(import.meta.url);
733
+ return findTuiBinaries(import.meta.url).find((candidate) => {
734
+ try {
735
+ return execFileSync(candidate, ["--help"], {
736
+ encoding: "utf-8",
737
+ stdio: [
738
+ "ignore",
739
+ "pipe",
740
+ "ignore"
741
+ ],
742
+ timeout: 5e3
743
+ }).includes("--view-only");
744
+ } catch {
745
+ return false;
746
+ }
747
+ }) ?? null;
823
748
  }
824
749
  /**
825
750
  * Fall back to default `git diff` output when the TUI cannot run.
@@ -827,9 +752,10 @@ function findTuiBinary() {
827
752
  * in a non-TTY context.
828
753
  */
829
754
  function runTerminalFallback(args) {
830
- const terminalOpts = parseDiffOptions(args.filter((a) => a !== "--tui"));
755
+ const terminalOpts = parseDiffOptions(args.filter((a) => a !== "--tui" && a !== "--view"));
831
756
  terminalOpts.outputMode = "terminal";
832
757
  terminalOpts.tui = false;
758
+ terminalOpts.viewOnly = false;
833
759
  return runTerminalDiff(terminalOpts);
834
760
  }
835
761
  /**
@@ -837,38 +763,72 @@ function runTerminalFallback(args) {
837
763
  * exit code. If the TUI cannot start (no TTY, missing binary), prints a
838
764
  * single stderr line and falls back to the default `git diff` output.
839
765
  */
840
- async function launchTui(args) {
766
+ async function launchTui(args, opts) {
767
+ const viewOnly = args.includes("--view");
768
+ const requestedMode = viewOnly ? "diffing view" : "diffing --tui";
841
769
  if (!process.stdout.isTTY || !process.stdin.isTTY) {
842
- console.error("diffing --tui requires a TTY; falling back to git diff");
770
+ console.error(`${requestedMode} requires a TTY; falling back to git diff`);
843
771
  return runTerminalFallback(args);
844
772
  }
845
- const bin = findTuiBinary();
773
+ const bin = viewOnly ? await findViewerTuiBinary(import.meta.url) : findTuiBinary$1(import.meta.url);
846
774
  if (!bin) {
847
- console.error("diffing-tui binary not found; build it with `pnpm build:tui`; falling back to git diff");
775
+ console.error(`${viewOnly ? "compatible " : ""}diffing-tui binary not found; reinstall with \`npm i -g diffing@latest\` or build it with \`pnpm build:tui\`; falling back to git diff`);
848
776
  return runTerminalFallback(args);
849
777
  }
850
- const forwarded = args.filter((a) => a !== "--tui");
778
+ const forwarded = buildTuiGitDiffArgs(opts);
851
779
  let repoRoot;
852
780
  try {
853
781
  repoRoot = getRepoRoot();
854
782
  } catch {
855
783
  repoRoot = process.cwd();
856
784
  }
857
- console.log(`diffing TUI starting (binary: ${bin})`);
858
- await playStartupDisplay();
785
+ const activeSession = opts.reuseSession || opts.replaceSession ? resolveActiveServerLock(repoRoot) : null;
786
+ if (activeSession && opts.reuseSession) {
787
+ await openExistingSession(activeSession, { noOpen: opts.noOpen });
788
+ return 0;
789
+ }
790
+ if (activeSession && opts.replaceSession) try {
791
+ console.error(`Stopping active diffing session (pid ${activeSession.pid})…`);
792
+ await stopLockOwner(activeSession);
793
+ } catch (error) {
794
+ console.error(error instanceof Error ? error.message : String(error));
795
+ return 1;
796
+ }
797
+ let searchBridge = null;
798
+ try {
799
+ const { startTuiSearchBridge } = await import("./tui-search-bridge-BGgLCwMF.mjs");
800
+ searchBridge = await startTuiSearchBridge();
801
+ } catch (error) {
802
+ console.error(`diffing: fff search unavailable in TUI: ${error?.message ?? error}`);
803
+ }
804
+ const diffContext = buildTuiDiffContext(opts, getBranchName());
805
+ const sessionId = randomUUID();
859
806
  return new Promise((resolveP) => {
860
807
  const child = spawn(bin, [
861
808
  "--repo",
862
809
  repoRoot,
810
+ ...viewOnly ? ["--view-only"] : [],
863
811
  ...forwarded
864
812
  ], {
865
813
  stdio: "inherit",
866
- env: process.env
814
+ env: {
815
+ ...process.env,
816
+ DIFFING_TUI_DIFF_CONTEXT: JSON.stringify(diffContext),
817
+ DIFFING_TUI_SESSION_ID: sessionId,
818
+ DIFFING_TUI_SESSION_SCOPE: diffScopeKey(opts),
819
+ DIFFING_TUI_SESSION_ARGS: JSON.stringify(forwarded),
820
+ ...searchBridge ? {
821
+ DIFFING_TUI_SEARCH_ENDPOINT: searchBridge.endpoint,
822
+ DIFFING_TUI_SEARCH_CAPABILITY: searchBridge.capability
823
+ } : {}
824
+ }
825
+ });
826
+ child.on("exit", (code) => {
827
+ finishTuiChild(searchBridge, () => resolveP(code ?? 0));
867
828
  });
868
- child.on("exit", (code) => resolveP(code ?? 0));
869
829
  child.on("error", (err) => {
870
830
  console.error(`diffing-tui failed to start: ${err.message}; falling back to git diff`);
871
- resolveP(runTerminalFallback(args));
831
+ finishTuiChild(searchBridge, () => resolveP(runTerminalFallback(args)));
872
832
  });
873
833
  });
874
834
  }