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