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.
- package/README.md +76 -41
- package/dist/{cli-agent-BJiATn11.mjs → cli-agent-CWsOHN-j.mjs} +198 -57
- package/dist/{cli-gh-_bkDCxhh.mjs → cli-gh-DI69gJGo.mjs} +27 -17
- package/dist/cli.mjs +189 -229
- package/dist/client/assets/{angular-html-CBcwKYDC.js → angular-html-PLPuQo0k.js} +1 -1
- package/dist/client/assets/{angular-ts-DRBYUaJA.js → angular-ts-CE02Ij4b.js} +1 -1
- package/dist/client/assets/{apl-BM0X8jeL.js → apl-CsuUKZoi.js} +1 -1
- package/dist/client/assets/{arc-DTkmmKl3.js → arc-CgL5kFe-.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-Cw75ay7q.js → architectureDiagram-3BPJPVTR-DxZQWGnx.js} +1 -1
- package/dist/client/assets/{astro-DKTNkoRZ.js → astro-DkFc7sbz.js} +1 -1
- package/dist/client/assets/{blade-DaM7a9Zp.js → blade-BkY07kcC.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DAzINMr_.js → blockDiagram-GPEHLZMM-D5a2KZV2.js} +1 -1
- package/dist/client/assets/{c-B3C0Or4o.js → c-T1BrPfJ6.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-C7SsS28g.js → c4Diagram-AAUBKEIU-mpMH4kFC.js} +1 -1
- package/dist/client/assets/channel-D3niKhl0.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-DHOUGWx8.js → chunk-2J33WTMH-vMtgRLFH.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-D8d2scLX.js → chunk-3OPIFGDE-Dx-FqyO2.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-BSC-E5yg.js → chunk-4BX2VUAB-CUrPd8Kv.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-27pC5pKn.js → chunk-55IACEB6-DHg3Nr8A.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-BM60x82y.js → chunk-5ZQYHXKU-CpDPvbGs.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-CHCF96vE.js → chunk-727SXJPM-3VOGMxwk.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-BoVsvmTa.js → chunk-AQP2D5EJ-4dbfbIS6.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-Iip4uSio.js → chunk-BSJP7CBP-Dfyn0Uwp.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-DuIWPyay.js → chunk-CSCIHK7Q-VTpSKo0F.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Du6rtd2k.js → chunk-FMBD7UC4-kXD1MyOL.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-BBq105vI.js → chunk-KSCS5N6A-BrVoWOAb.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-0DmB5Qp8.js → chunk-L5ZTLDWV-wZEQDPsa.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CoRsjUfr.js → chunk-LZXEDZCA-D3i0B0eg.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-tX8cKEls.js → chunk-ND2GUHAM-hDVHT0bN.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-BoJGgPic.js → chunk-NZK2D7GU-jQUfhp9h.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-mlwCWs97.js → chunk-O5CBEL6O-CX_vPWhk.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-CZLFuGpt.js +1 -0
- package/dist/client/assets/chunk-WU5MYG2G-BhcpjkaB.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-B5efww8M.js → chunk-XPW4576I-Co_-vDB4.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DK5KJNIt.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-y5K9t6Se.js +1 -0
- package/dist/client/assets/{cobol-De9QR_Td.js → cobol-8-qBLs-a.js} +1 -1
- package/dist/client/assets/{coffee-Ct_GvuHP.js → coffee-Bjz5lkyW.js} +1 -1
- package/dist/client/assets/{cose-bilkent-S5V4N54A-ATaJZGF7.js → cose-bilkent-S5V4N54A-BljJ0FSA.js} +1 -1
- package/dist/client/assets/{cpp-Dw52w9cj.js → cpp-5BVQCBXT.js} +1 -1
- package/dist/client/assets/{crystal-Dx8ADdsd.js → crystal-CCkY93GS.js} +1 -1
- package/dist/client/assets/{css-CZ13XvDU.js → css-BTM7Tp2a.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-aDltuYut.js → dagre-BM42HDAG-BSynd_2D.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-DGWnHVMJ.js → diagram-2AECGRRQ-K3E2CVdy.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-Dd7eZBKe.js → diagram-5GNKFQAL-BQHIrfKc.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DWThXREf.js → diagram-KO2AKTUF-Bqs8sNN4.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CXR4Bjtc.js → diagram-LMA3HP47-C9K4bpQe.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-D4Cbf0nW.js → diagram-OG6HWLK6-DK6wIXY2.js} +1 -1
- package/dist/client/assets/{dist-CUDhrHNw.js → dist-1nkZYMRy.js} +1 -1
- package/dist/client/assets/{edge-CQCjdJKj.js → edge-DqN2FJce.js} +1 -1
- package/dist/client/assets/{elixir-bkjwPazA.js → elixir-BiAgRUFF.js} +1 -1
- package/dist/client/assets/{elm-CCweX5Cq.js → elm-N1IbY8sz.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-BmAyt7SU.js → erDiagram-TEJ5UH35-jsHCiP02.js} +1 -1
- package/dist/client/assets/{erb-D-Z-KBLp.js → erb-B-yYlWAZ.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-C6nIFUVc.js → flowDiagram-I6XJVG4X-DOB1dAWG.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DMlxThBf.js → ganttDiagram-6RSMTGT7-BYIewcY5.js} +1 -1
- package/dist/client/assets/{git-rebase-BdoFdenB.js → git-rebase-CVkPxOAF.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-JaIFkAIT.js → gitGraphDiagram-PVQCEYII-VNQzbpv2.js} +1 -1
- package/dist/client/assets/{glimmer-js-CZQrBJKq.js → glimmer-js-BmG1xm72.js} +1 -1
- package/dist/client/assets/{glimmer-ts-CBYW46D4.js → glimmer-ts-CvTgwZsg.js} +1 -1
- package/dist/client/assets/{glsl-wxixKkY_.js → glsl-DwjNNCbW.js} +1 -1
- package/dist/client/assets/{graphql-CqZ0Lo5a.js → graphql-BvgkyF8E.js} +1 -1
- package/dist/client/assets/{hack-rqWymQRV.js → hack-DH3188x2.js} +1 -1
- package/dist/client/assets/{haml-DFw_IoGM.js → haml-B0GTfMhX.js} +1 -1
- package/dist/client/assets/{handlebars-3VmTVMYt.js → handlebars-he7hLDd9.js} +1 -1
- package/dist/client/assets/{html-C0Li76jB.js → html-DIYgdTBq.js} +1 -1
- package/dist/client/assets/{html-derivative-CO-RQW8y.js → html-derivative-2s6MXlci.js} +1 -1
- package/dist/client/assets/{http-sPrZOeBY.js → http-COS23XJP.js} +1 -1
- package/dist/client/assets/{hurl-DUoPe4Lc.js → hurl-BlZPjeJt.js} +1 -1
- package/dist/client/assets/index-BrEVVQOB.js +4021 -0
- package/dist/client/assets/index-BsuX6HVI.css +1 -0
- package/dist/client/assets/{infoDiagram-5YYISTIA-B6AZ5SCV.js → infoDiagram-5YYISTIA-DQRqk24I.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CytMrpo8.js → ishikawaDiagram-YF4QCWOH-DU1rqrLx.js} +1 -1
- package/dist/client/assets/{java-Cj0G6QRg.js → java-BAa5w-Qd.js} +1 -1
- package/dist/client/assets/{javascript-d5SUuyWD.js → javascript-C9e02ssI.js} +1 -1
- package/dist/client/assets/{jinja-BTw9k0vO.js → jinja-Bx37xXwq.js} +1 -1
- package/dist/client/assets/{jison-9xSVvR1q.js → jison-m_DEf8Jo.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-Bd4jZUYI.js → journeyDiagram-JHISSGLW-CoHlfevf.js} +1 -1
- package/dist/client/assets/{json-DjAt53ka.js → json-DtN5AWRW.js} +1 -1
- package/dist/client/assets/{jsx-BX5KmQ7d.js → jsx-BlPpu8bR.js} +1 -1
- package/dist/client/assets/{julia-CLLx1dHC.js → julia-BAOmCbHl.js} +1 -1
- package/dist/client/assets/{just-C0v80bKe.js → just-C_bvVjwE.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Ds4pXHJa.js → kanban-definition-UN3LZRKU-BiqYI7_m.js} +1 -1
- package/dist/client/assets/{latex-DY-oQfwO.js → latex-81pMfNMt.js} +1 -1
- package/dist/client/assets/{line-BbSLfOl6.js → line-DCovs9My.js} +1 -1
- package/dist/client/assets/{linear-BMIZJAAR.js → linear-cJF5XHE7.js} +1 -1
- package/dist/client/assets/{liquid-DDHDgbZx.js → liquid-sKRTk6dT.js} +1 -1
- package/dist/client/assets/{lua-CXymerKS.js → lua-C1uZL4IF.js} +1 -1
- package/dist/client/assets/{marko-DoPFsptl.js → marko-BKEzP1CL.js} +1 -1
- package/dist/client/assets/{mdc-BxSmTphd.js → mdc-CLkfm94H.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-CcYSvN4q.js → mermaid-parser.core-CTsTbvb2.js} +1 -1
- package/dist/client/assets/{mermaid.core-COTNtqgQ.js → mermaid.core-D86HJEwL.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-BTxraRzn.js → mindmap-definition-RKZ34NQL-CL3heUmL.js} +1 -1
- package/dist/client/assets/{nginx-Bma0jNOT.js → nginx-eDGm66pc.js} +1 -1
- package/dist/client/assets/{nim-DMBpjygU.js → nim-CoWZPv8-.js} +1 -1
- package/dist/client/assets/{perl-CrnrV-AJ.js → perl-MoMqtMVr.js} +1 -1
- package/dist/client/assets/{php-CDYxzX6t.js → php-DXXVMAtN.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DglRmzer.js → pieDiagram-4H26LBE5-CWV3TMu4.js} +1 -1
- package/dist/client/assets/{pug-DNewy3GU.js → pug-CPWaB94J.js} +1 -1
- package/dist/client/assets/{qml-COjcnZ-W.js → qml-lhvpx8vk.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BjSmyES7.js → quadrantDiagram-W4KKPZXB-QV25BYos.js} +1 -1
- package/dist/client/assets/{r-CrCaMxLS.js → r-DYbUnmmK.js} +1 -1
- package/dist/client/assets/{razor-jeuOZIar.js → razor-DcyOLv96.js} +1 -1
- package/dist/client/assets/{regexp-DSHVUX08.js → regexp-BdY10jm0.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-B4f430jS.js → requirementDiagram-4Y6WPE33-BPMsmU6J.js} +1 -1
- package/dist/client/assets/{review-export-Cen1WEcX.js → review-export-CMwjJURs.js} +1 -1
- package/dist/client/assets/{rst-CIDgytzc.js → rst-6ShFOzgH.js} +1 -1
- package/dist/client/assets/{ruby-DtuseoNq.js → ruby-B04DeVbi.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-TQPPlxc6.js → sankeyDiagram-5OEKKPKP-DQJeroPp.js} +1 -1
- package/dist/client/assets/{sas-C72Theia.js → sas-Dj26ftNa.js} +1 -1
- package/dist/client/assets/{scss-ClECtwRk.js → scss-BOHpBkgl.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-D1tx07Wg.js → sequenceDiagram-3UESZ5HK-DdV0Y6Sz.js} +1 -1
- package/dist/client/assets/{shellscript-BCwBsi2k.js → shellscript-CpHwjRcU.js} +1 -1
- package/dist/client/assets/{shellsession-BrOddEl5.js → shellsession-BJAvf4GN.js} +1 -1
- package/dist/client/assets/{soy-Dcs0GWFW.js → soy-B67bZJnL.js} +1 -1
- package/dist/client/assets/{sql-BAjA7Gv7.js → sql-8MzOqSsK.js} +1 -1
- package/dist/client/assets/{src-CYYhkqTK.js → src-AaoRSmFl.js} +1 -1
- package/dist/client/assets/{stata-19ngQtzR.js → stata-aCME945h.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-BZRCEzb5.js → stateDiagram-AJRCARHV-CMD_Xj2M.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-vLl7D4ue.js +1 -0
- package/dist/client/assets/{surrealql-Ce2TBRjE.js → surrealql-B_V_HxAi.js} +1 -1
- package/dist/client/assets/{svelte-DQ_1eGZz.js → svelte-BcQvTlqz.js} +1 -1
- package/dist/client/assets/{templ-Cw2DDxWF.js → templ-DZCQ2blz.js} +1 -1
- package/dist/client/assets/{tex-myDSO2eP.js → tex-BfeQ5Wuu.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CP0OZhBT.js → timeline-definition-PNZ67QCA-CyIS7Zoe.js} +1 -1
- package/dist/client/assets/{ts-tags-rh39ZwVs.js → ts-tags-DVWE0E87.js} +1 -1
- package/dist/client/assets/{tsx-B0-26jrU.js → tsx-DdJ7Sfqf.js} +1 -1
- package/dist/client/assets/{twig-CgasHzPb.js → twig-_gVgaha5.js} +1 -1
- package/dist/client/assets/{typescript-Dq3T0c-m.js → typescript-Bj0_LzZV.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DHaKHj0j.js → vennDiagram-CIIHVFJN-C-J2kWyk.js} +1 -1
- package/dist/client/assets/{vue-CzFVh92-.js → vue-Dnt_GBRb.js} +1 -1
- package/dist/client/assets/{vue-html-Bv2uFkTH.js → vue-html-ClVA5__5.js} +1 -1
- package/dist/client/assets/{vue-vine-DzieBk9Y.js → vue-vine-BCcz4SVP.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Dky7jxlZ.js → wardleyDiagram-YWT4CUSO-Dzt4EPh8.js} +1 -1
- package/dist/client/assets/{xml-wcdHRHN8.js → xml-BYeUHEti.js} +1 -1
- package/dist/client/assets/{xsl-CXrwsLG9.js → xsl-Vsx0SZEV.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-BQ2hG60h.js → xychartDiagram-2RQKCTM6-BAWZKvwP.js} +1 -1
- package/dist/client/assets/{yaml-lO6lK6Xe.js → yaml-C6L1khMK.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/{completions-3UF8uzhx.mjs → completions-DvyV49HY.mjs} +22 -1
- package/dist/{doctor-BGYZNIYP.mjs → doctor-Bz9VHuBI.mjs} +7 -6
- package/dist/find-tui-binary-DVQADOSF.mjs +101 -0
- package/dist/{git-Czo96ymM.mjs → git-BGj31GX-.mjs} +71 -7
- package/dist/git-CfDSkUcE.mjs +2 -0
- package/dist/{github-DKT0lJXv.mjs → github-DXiEeHzk.mjs} +1 -1
- package/dist/{github-CEjtGd41.mjs → github-DpzqNrUh.mjs} +3 -3
- package/dist/{github-attachments-Cf17YWp4.mjs → github-attachments-DgOf7BhP.mjs} +2 -2
- package/dist/{mcp-Dq7J5QOP.mjs → mcp-zDVzU1vl.mjs} +42 -33
- package/dist/native/tui-darwin-arm64/diffing-tui +0 -0
- package/dist/native/tui-darwin-x64/diffing-tui +0 -0
- package/dist/native/tui-linux-arm64-gnu/diffing-tui +0 -0
- package/dist/native/tui-linux-arm64-musl/diffing-tui +0 -0
- package/dist/native/tui-linux-x64-gnu/diffing-tui +0 -0
- package/dist/native/tui-linux-x64-musl/diffing-tui +0 -0
- package/dist/native/tui-win32-x64-msvc/diffing-tui.exe +0 -0
- package/dist/{review-export-BBDWvftT.mjs → review-export-B63eRAVa.mjs} +1 -1
- package/dist/{settings-bwe7yQ8U.mjs → search-3R2E5xxr.mjs} +133 -98
- package/dist/search-CQ4nsjBX.mjs +2 -0
- package/dist/{server-C9i4V36o.mjs → server-Dw3lkQ5q.mjs} +296 -110
- package/dist/server-lock-BNI8FKV1.mjs +427 -0
- package/dist/session-conflict-Bqt1M4Mp.mjs +96 -0
- package/dist/session-manager-BKSZQqDJ.mjs +159 -0
- package/dist/session-url-sr7lXXVc.mjs +100 -0
- package/dist/tui-search-bridge-BGgLCwMF.mjs +133 -0
- package/dist/{update-check-DUuHmPeZ.mjs → update-check-BUfh4Y6c.mjs} +16 -15
- package/package.json +9 -4
- package/dist/client/assets/channel-lsVHTuYR.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-AHUiTM0z.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-D41j4yxb.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-D1Eo3kly.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-bAMsbsfB.js +0 -1
- package/dist/client/assets/index-B42c0TyV.css +0 -1
- package/dist/client/assets/index-BN_-di_r.js +0 -3959
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Da-mGMA2.js +0 -1
- package/dist/find-tui-binary-CRpbYXLC.mjs +0 -52
- package/dist/git-DaP_1rVy.mjs +0 -2
- package/dist/server-lock-Dd_ss_Il.mjs +0 -153
- /package/dist/{apply-suggestion-DNNsC5gx.mjs → apply-suggestion-CHYnw68I.mjs} +0 -0
- /package/dist/{comment-format-B5AcGcR-.mjs → comment-format-B85NHZnG.mjs} +0 -0
- /package/dist/{diff-fingerprint-C8YO3TTE.mjs → diff-fingerprint-BgR0tu1o.mjs} +0 -0
- /package/dist/{handoff-DPoIyeWn.mjs → handoff-LAFtmnHf.mjs} +0 -0
- /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
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
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
|
|
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
|
-
|
|
392
|
-
|
|
393
|
-
|
|
397
|
+
onInterrupt();
|
|
398
|
+
} finally {
|
|
399
|
+
process.off("SIGINT", onInterrupt);
|
|
394
400
|
}
|
|
395
401
|
})();
|
|
396
402
|
}
|
|
397
403
|
//#endregion
|
|
398
|
-
//#region src/lib/
|
|
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
|
-
*
|
|
425
|
-
*
|
|
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
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
if (
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
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
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
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
|
-
*
|
|
490
|
-
*
|
|
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
|
|
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
|
-
|
|
507
|
-
} catch {}
|
|
508
|
-
|
|
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
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
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
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
711
|
-
if (
|
|
643
|
+
const activeSession = opts.reuseSession || opts.replaceSession ? resolveActiveServerLock(repoRoot) : null;
|
|
644
|
+
if (activeSession && opts.reuseSession) {
|
|
712
645
|
startupLease.release();
|
|
713
646
|
startupLease = null;
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
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-
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
-
|
|
858
|
-
|
|
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:
|
|
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
|
}
|