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,525 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
//#region src/lib/github.ts
|
|
4
|
+
const execFileAsync = promisify(execFile);
|
|
5
|
+
/**
|
|
6
|
+
* Probe the `gh` CLI: is it on `$PATH`, and is the user authenticated?
|
|
7
|
+
* Never throws — returns a permissive `available: false` on any failure.
|
|
8
|
+
*/
|
|
9
|
+
async function detectGhCli() {
|
|
10
|
+
try {
|
|
11
|
+
const { stdout } = await execFileAsync("gh", ["--version"], { encoding: "utf-8" });
|
|
12
|
+
const version = stdout.split("\n")[0]?.trim() || void 0;
|
|
13
|
+
try {
|
|
14
|
+
const result = await execFileAsync("gh", ["auth", "status"], { encoding: "utf-8" });
|
|
15
|
+
return {
|
|
16
|
+
available: true,
|
|
17
|
+
authenticated: true,
|
|
18
|
+
version,
|
|
19
|
+
user: parseGhAuthStatusUser(`${result.stdout ?? ""}\n${result.stderr ?? ""}`)
|
|
20
|
+
};
|
|
21
|
+
} catch {
|
|
22
|
+
return {
|
|
23
|
+
available: true,
|
|
24
|
+
authenticated: false,
|
|
25
|
+
version
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
return {
|
|
30
|
+
available: false,
|
|
31
|
+
authenticated: false
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Extract the GitHub username from `gh auth status` output. Exported for
|
|
37
|
+
* unit tests — see `__tests__/github-auth.test.ts`.
|
|
38
|
+
*
|
|
39
|
+
* Real-world samples:
|
|
40
|
+
* `✓ Logged in to github.com account octocat (keyring)` (gh 2.40+)
|
|
41
|
+
* `Logged in to github.com as octocat (oauth_token)` (older gh)
|
|
42
|
+
* ` ✓ Logged in to github.com as octocat (~/.config/gh/hosts.yml)`
|
|
43
|
+
*/
|
|
44
|
+
function parseGhAuthStatusUser(output) {
|
|
45
|
+
const account = /Logged in to [^\s]+ account\s+([^\s(]+)/.exec(output);
|
|
46
|
+
if (account) return account[1];
|
|
47
|
+
return /Logged in to [^\s]+ as\s+([^\s(]+)/.exec(output)?.[1];
|
|
48
|
+
}
|
|
49
|
+
/** Read the most-preferred GitHub token from the env. */
|
|
50
|
+
function readGithubToken() {
|
|
51
|
+
const env = process.env;
|
|
52
|
+
return env.GH_TOKEN || env.GITHUB_TOKEN || env.GITHUB_API_TOKEN || null;
|
|
53
|
+
}
|
|
54
|
+
function parsePrRef(input, cwdRepo) {
|
|
55
|
+
const trimmed = input.trim();
|
|
56
|
+
const urlMatch = /^https?:\/\/github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/i.exec(trimmed);
|
|
57
|
+
if (urlMatch) return {
|
|
58
|
+
owner: urlMatch[1],
|
|
59
|
+
repo: urlMatch[2],
|
|
60
|
+
pullNumber: Number(urlMatch[3]),
|
|
61
|
+
ref: trimmed
|
|
62
|
+
};
|
|
63
|
+
const shorthand = /^([^/\s]+)\/([^#\s]+)#(\d+)$/.exec(trimmed);
|
|
64
|
+
if (shorthand) return {
|
|
65
|
+
owner: shorthand[1],
|
|
66
|
+
repo: shorthand[2],
|
|
67
|
+
pullNumber: Number(shorthand[3]),
|
|
68
|
+
ref: trimmed
|
|
69
|
+
};
|
|
70
|
+
const bare = /^#?(\d+)$/.exec(trimmed);
|
|
71
|
+
if (bare && cwdRepo) return {
|
|
72
|
+
owner: cwdRepo.owner,
|
|
73
|
+
repo: cwdRepo.repo,
|
|
74
|
+
pullNumber: Number(bare[1]),
|
|
75
|
+
ref: trimmed
|
|
76
|
+
};
|
|
77
|
+
if (bare) throw new Error(`Cannot resolve bare PR number "${trimmed}" — run from inside the target repo, or pass a full URL or \`owner/repo#1234\`.`);
|
|
78
|
+
throw new Error(`Unrecognised PR ref: ${trimmed}`);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Best-effort: derive `{ owner, repo }` for the current working directory
|
|
82
|
+
* from `git remote get-url origin`. Falls back to throwing.
|
|
83
|
+
*/
|
|
84
|
+
async function detectCwdRepo() {
|
|
85
|
+
try {
|
|
86
|
+
const { stdout } = await execFileAsync("git", [
|
|
87
|
+
"remote",
|
|
88
|
+
"get-url",
|
|
89
|
+
"origin"
|
|
90
|
+
], { encoding: "utf-8" });
|
|
91
|
+
const url = stdout.trim();
|
|
92
|
+
const m = /github\.com[:/]([^/\s]+)\/([^/\s]+?)(?:\.git)?\s*$/.exec(url);
|
|
93
|
+
if (m) return {
|
|
94
|
+
owner: m[1],
|
|
95
|
+
repo: m[2]
|
|
96
|
+
};
|
|
97
|
+
} catch {}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Fetch PR metadata + diff + existing review comments using `gh`.
|
|
102
|
+
* Throws with a user-readable message on failure.
|
|
103
|
+
*/
|
|
104
|
+
async function fetchPrMetadataViaGh(resolved) {
|
|
105
|
+
const args = ["-R", `${resolved.owner}/${resolved.repo}`];
|
|
106
|
+
let metaJson;
|
|
107
|
+
try {
|
|
108
|
+
const { stdout } = await execFileAsync("gh", [
|
|
109
|
+
"pr",
|
|
110
|
+
"view",
|
|
111
|
+
String(resolved.pullNumber),
|
|
112
|
+
...args,
|
|
113
|
+
"--json",
|
|
114
|
+
"number,title,url,author,baseRefOid,headRefOid,additions,deletions,changedFiles,headRepositoryOwner,headRepository"
|
|
115
|
+
], {
|
|
116
|
+
encoding: "utf-8",
|
|
117
|
+
maxBuffer: 20 * 1024 * 1024
|
|
118
|
+
});
|
|
119
|
+
metaJson = JSON.parse(stdout);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
const stderr = err?.stderr || err?.message || "unknown error";
|
|
122
|
+
throw new Error(`gh pr view failed: ${stderr.trim()}`);
|
|
123
|
+
}
|
|
124
|
+
let diff = "";
|
|
125
|
+
try {
|
|
126
|
+
const { stdout } = await execFileAsync("gh", [
|
|
127
|
+
"pr",
|
|
128
|
+
"diff",
|
|
129
|
+
String(resolved.pullNumber),
|
|
130
|
+
...args
|
|
131
|
+
], {
|
|
132
|
+
encoding: "utf-8",
|
|
133
|
+
maxBuffer: 50 * 1024 * 1024
|
|
134
|
+
});
|
|
135
|
+
diff = stdout;
|
|
136
|
+
} catch (err) {
|
|
137
|
+
const stderr = err?.stderr || err?.message || "unknown error";
|
|
138
|
+
throw new Error(`gh pr diff failed: ${stderr.trim()}`);
|
|
139
|
+
}
|
|
140
|
+
const author = metaJson.author ? {
|
|
141
|
+
login: metaJson.author.login,
|
|
142
|
+
avatarUrl: metaJson.author.avatarUrl
|
|
143
|
+
} : null;
|
|
144
|
+
const existingComments = await fetchExistingCommentsViaGh(resolved);
|
|
145
|
+
return {
|
|
146
|
+
number: metaJson.number,
|
|
147
|
+
title: metaJson.title,
|
|
148
|
+
url: metaJson.url,
|
|
149
|
+
author,
|
|
150
|
+
baseSha: metaJson.baseRefOid,
|
|
151
|
+
headSha: metaJson.headRefOid,
|
|
152
|
+
additions: metaJson.additions,
|
|
153
|
+
deletions: metaJson.deletions,
|
|
154
|
+
changedFiles: metaJson.changedFiles,
|
|
155
|
+
owner: resolved.owner,
|
|
156
|
+
repo: resolved.repo,
|
|
157
|
+
diff,
|
|
158
|
+
existingComments
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
async function fetchExistingCommentsViaGh(resolved) {
|
|
162
|
+
`${resolved.owner}${resolved.repo}`;
|
|
163
|
+
const endpoint = `repos/${resolved.owner}/${resolved.repo}/pulls/${resolved.pullNumber}/comments`;
|
|
164
|
+
const reviewsEndpoint = `repos/${resolved.owner}/${resolved.repo}/pulls/${resolved.pullNumber}/reviews`;
|
|
165
|
+
let reviews = [];
|
|
166
|
+
try {
|
|
167
|
+
const { stdout } = await execFileAsync("gh", [
|
|
168
|
+
"api",
|
|
169
|
+
reviewsEndpoint,
|
|
170
|
+
"--paginate"
|
|
171
|
+
], {
|
|
172
|
+
encoding: "utf-8",
|
|
173
|
+
maxBuffer: 20 * 1024 * 1024
|
|
174
|
+
});
|
|
175
|
+
const all = JSON.parse(stdout);
|
|
176
|
+
if (Array.isArray(all)) reviews = all;
|
|
177
|
+
} catch {}
|
|
178
|
+
reviews.sort((a, b) => a.submitted_at < b.submitted_at ? 1 : -1);
|
|
179
|
+
const recentReviews = reviews.slice(0, 50);
|
|
180
|
+
const reviewStateById = /* @__PURE__ */ new Map();
|
|
181
|
+
for (const r of recentReviews) reviewStateById.set(r.id, r.state);
|
|
182
|
+
let commentsRaw = [];
|
|
183
|
+
try {
|
|
184
|
+
const { stdout } = await execFileAsync("gh", [
|
|
185
|
+
"api",
|
|
186
|
+
`${endpoint}?per_page=100`,
|
|
187
|
+
"--paginate"
|
|
188
|
+
], {
|
|
189
|
+
encoding: "utf-8",
|
|
190
|
+
maxBuffer: 20 * 1024 * 1024
|
|
191
|
+
});
|
|
192
|
+
const parsed = JSON.parse(stdout);
|
|
193
|
+
if (Array.isArray(parsed)) commentsRaw = parsed;
|
|
194
|
+
} catch {
|
|
195
|
+
return [];
|
|
196
|
+
}
|
|
197
|
+
const byId = /* @__PURE__ */ new Map();
|
|
198
|
+
for (const c of commentsRaw) byId.set(c.id, c);
|
|
199
|
+
const replyByParent = /* @__PURE__ */ new Map();
|
|
200
|
+
for (const c of commentsRaw) if (c.in_reply_to_id && byId.has(c.in_reply_to_id)) {
|
|
201
|
+
const list = replyByParent.get(c.in_reply_to_id) ?? [];
|
|
202
|
+
list.push(c);
|
|
203
|
+
replyByParent.set(c.in_reply_to_id, list);
|
|
204
|
+
}
|
|
205
|
+
const tops = [];
|
|
206
|
+
for (const c of commentsRaw) {
|
|
207
|
+
if (c.in_reply_to_id) continue;
|
|
208
|
+
const state = c.pull_request_review_id ? reviewStateById.get(c.pull_request_review_id) ?? null : null;
|
|
209
|
+
tops.push({
|
|
210
|
+
id: c.id,
|
|
211
|
+
author: c.user ? {
|
|
212
|
+
login: c.user.login,
|
|
213
|
+
avatarUrl: c.user.avatar_url
|
|
214
|
+
} : null,
|
|
215
|
+
body: c.body ?? "",
|
|
216
|
+
path: c.path,
|
|
217
|
+
line: typeof c.line === "number" ? c.line : null,
|
|
218
|
+
side: c.side === "LEFT" || c.side === "RIGHT" ? c.side : null,
|
|
219
|
+
createdAt: c.created_at,
|
|
220
|
+
updatedAt: c.updated_at,
|
|
221
|
+
state,
|
|
222
|
+
replies: (replyByParent.get(c.id) ?? []).map((r) => ({
|
|
223
|
+
id: r.id,
|
|
224
|
+
author: r.user ? {
|
|
225
|
+
login: r.user.login,
|
|
226
|
+
avatarUrl: r.user.avatar_url
|
|
227
|
+
} : null,
|
|
228
|
+
body: r.body ?? "",
|
|
229
|
+
createdAt: r.created_at,
|
|
230
|
+
updatedAt: r.updated_at
|
|
231
|
+
})),
|
|
232
|
+
isOutdated: Boolean(c.line == null && c.original_line != null || c.position === null && c.original_position != null)
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
tops.sort((a, b) => {
|
|
236
|
+
if (a.path !== b.path) return a.path.localeCompare(b.path);
|
|
237
|
+
return (a.line ?? 0) - (b.line ?? 0);
|
|
238
|
+
});
|
|
239
|
+
return tops;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* POST the review to GitHub. Prefers `gh api` (uses the user's existing
|
|
243
|
+
* `gh auth`); falls back to a direct HTTP call with `$GITHUB_TOKEN` when
|
|
244
|
+
* `gh` is unavailable.
|
|
245
|
+
*/
|
|
246
|
+
async function submitReview(input) {
|
|
247
|
+
const gh = await detectGhCli();
|
|
248
|
+
if (gh.available && gh.authenticated) return submitViaGh(input);
|
|
249
|
+
const token = readGithubToken();
|
|
250
|
+
if (token) return submitViaToken(input, token);
|
|
251
|
+
return {
|
|
252
|
+
ok: false,
|
|
253
|
+
authSource: "none",
|
|
254
|
+
error: "Cannot submit: no `gh` CLI on $PATH (or not authenticated) and no $GITHUB_TOKEN env var. Run `gh auth login` or set $GITHUB_TOKEN."
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Map our `PrDecision` to the GitHub REST event string. Exported so the
|
|
259
|
+
* test suite can pin the mapping (including the `rejected → REQUEST_CHANGES`
|
|
260
|
+
* quirk, which exists because GitHub has no REJECT event).
|
|
261
|
+
*
|
|
262
|
+
* Returns `null` for `draft` — GitHub creates a PENDING review when `event`
|
|
263
|
+
* is omitted from the payload.
|
|
264
|
+
*/
|
|
265
|
+
function decisionToEvent(decision) {
|
|
266
|
+
if (decision === "draft") return null;
|
|
267
|
+
if (decision === "approve") return "APPROVE";
|
|
268
|
+
if (decision === "request-changes") return "REQUEST_CHANGES";
|
|
269
|
+
return "COMMENT";
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Map open line-anchored `ReviewComment`s to GitHub multi-line review comments.
|
|
273
|
+
* - `deletions` → LEFT, `additions` → RIGHT
|
|
274
|
+
* - Ranges use `start_line`/`line` (no N-part explosion)
|
|
275
|
+
* - File-level comments (`lineNumber === 0`) are excluded; callers fold them
|
|
276
|
+
* into the review body via {@link buildReviewPayload}.
|
|
277
|
+
*/
|
|
278
|
+
function expandMultiLineComments(comments) {
|
|
279
|
+
const flat = [];
|
|
280
|
+
for (const c of comments) {
|
|
281
|
+
if (c.status !== "open") continue;
|
|
282
|
+
if (c.lineNumber === 0) continue;
|
|
283
|
+
const path = stripBPrefix(c.filePath);
|
|
284
|
+
const side = c.side === "deletions" ? "LEFT" : "RIGHT";
|
|
285
|
+
const start = c.startLineNumber && c.startLineNumber < c.lineNumber ? c.startLineNumber : void 0;
|
|
286
|
+
const entry = {
|
|
287
|
+
path,
|
|
288
|
+
line: c.lineNumber,
|
|
289
|
+
side,
|
|
290
|
+
body: c.body
|
|
291
|
+
};
|
|
292
|
+
if (start !== void 0) {
|
|
293
|
+
entry.start_line = start;
|
|
294
|
+
entry.start_side = side;
|
|
295
|
+
}
|
|
296
|
+
flat.push(entry);
|
|
297
|
+
}
|
|
298
|
+
return flat;
|
|
299
|
+
}
|
|
300
|
+
function buildReviewPayload(input) {
|
|
301
|
+
const comments = input.comments ?? [];
|
|
302
|
+
const inline = expandMultiLineComments(comments);
|
|
303
|
+
const fileLevel = comments.filter((c) => c.status === "open" && c.lineNumber === 0);
|
|
304
|
+
let body = typeof input.body === "string" ? input.body.trim() : "";
|
|
305
|
+
if (fileLevel.length > 0) {
|
|
306
|
+
const block = ["### File comments", ...fileLevel.map((c) => {
|
|
307
|
+
return `**\`${stripBPrefix(c.filePath)}\`:** ${c.body}`;
|
|
308
|
+
})].join("\n\n");
|
|
309
|
+
body = body ? `${body}\n\n${block}` : block;
|
|
310
|
+
}
|
|
311
|
+
const event = decisionToEvent(input.decision ?? "comment");
|
|
312
|
+
if (event === null) return {
|
|
313
|
+
body: body || void 0,
|
|
314
|
+
comments: inline
|
|
315
|
+
};
|
|
316
|
+
return {
|
|
317
|
+
body: body || void 0,
|
|
318
|
+
event,
|
|
319
|
+
comments: inline
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function stripBPrefix(path) {
|
|
323
|
+
if (path.startsWith("b/")) return path.slice(2);
|
|
324
|
+
if (path.startsWith("a/")) return path.slice(2);
|
|
325
|
+
return path;
|
|
326
|
+
}
|
|
327
|
+
async function submitViaGh(input) {
|
|
328
|
+
const payload = buildReviewPayload(input);
|
|
329
|
+
`${input.resolved.owner}${input.resolved.repo}`;
|
|
330
|
+
const args = [
|
|
331
|
+
"api",
|
|
332
|
+
"--method",
|
|
333
|
+
"POST",
|
|
334
|
+
`repos/${input.resolved.owner}/${input.resolved.repo}/pulls/${input.resolved.pullNumber}/reviews`,
|
|
335
|
+
"-H",
|
|
336
|
+
"Accept: application/vnd.github+json",
|
|
337
|
+
"--input",
|
|
338
|
+
"-"
|
|
339
|
+
];
|
|
340
|
+
try {
|
|
341
|
+
const { stdout } = await execFileAsync("gh", args, {
|
|
342
|
+
encoding: "utf-8",
|
|
343
|
+
maxBuffer: 20 * 1024 * 1024,
|
|
344
|
+
input: JSON.stringify(payload)
|
|
345
|
+
});
|
|
346
|
+
const result = JSON.parse(stdout);
|
|
347
|
+
return {
|
|
348
|
+
ok: true,
|
|
349
|
+
authSource: "gh",
|
|
350
|
+
reviewId: result.id,
|
|
351
|
+
reviewUrl: result.html_url
|
|
352
|
+
};
|
|
353
|
+
} catch (err) {
|
|
354
|
+
const stdout = err?.stdout || "";
|
|
355
|
+
const stderr = err?.stderr || err?.message || "unknown error";
|
|
356
|
+
let parsed = null;
|
|
357
|
+
try {
|
|
358
|
+
parsed = JSON.parse(stdout);
|
|
359
|
+
} catch {}
|
|
360
|
+
return {
|
|
361
|
+
ok: false,
|
|
362
|
+
authSource: "gh",
|
|
363
|
+
error: parsed?.message || stderr.trim()
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
async function submitViaToken(input, token) {
|
|
368
|
+
const payload = buildReviewPayload(input);
|
|
369
|
+
const url = `https://api.github.com/repos/${input.resolved.owner}/${input.resolved.repo}/pulls/${input.resolved.pullNumber}/reviews`;
|
|
370
|
+
try {
|
|
371
|
+
const res = await fetch(url, {
|
|
372
|
+
method: "POST",
|
|
373
|
+
headers: {
|
|
374
|
+
Authorization: `Bearer ${token}`,
|
|
375
|
+
Accept: "application/vnd.github+json",
|
|
376
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
377
|
+
"Content-Type": "application/json",
|
|
378
|
+
"User-Agent": "diffing-cli"
|
|
379
|
+
},
|
|
380
|
+
body: JSON.stringify(payload)
|
|
381
|
+
});
|
|
382
|
+
if (!res.ok) {
|
|
383
|
+
const errBody = await res.text().catch(() => "");
|
|
384
|
+
return {
|
|
385
|
+
ok: false,
|
|
386
|
+
authSource: "token",
|
|
387
|
+
error: `HTTP ${res.status}: ${errBody.slice(0, 500)}`
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
const result = await res.json();
|
|
391
|
+
return {
|
|
392
|
+
ok: true,
|
|
393
|
+
authSource: "token",
|
|
394
|
+
reviewId: result.id,
|
|
395
|
+
reviewUrl: result.html_url
|
|
396
|
+
};
|
|
397
|
+
} catch (err) {
|
|
398
|
+
return {
|
|
399
|
+
ok: false,
|
|
400
|
+
authSource: "token",
|
|
401
|
+
error: err?.message || "Network error"
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Fetch check runs + combined status for a PR head via `gh api`.
|
|
407
|
+
* Best-effort: returns [] on any failure so the UI can degrade gracefully.
|
|
408
|
+
*/
|
|
409
|
+
async function fetchPrChecks(resolved, headSha) {
|
|
410
|
+
const checks = [];
|
|
411
|
+
try {
|
|
412
|
+
const { stdout } = await execFileAsync("gh", [
|
|
413
|
+
"api",
|
|
414
|
+
`repos/${resolved.owner}/${resolved.repo}/commits/${headSha}/check-runs?per_page=50`,
|
|
415
|
+
"-H",
|
|
416
|
+
"Accept: application/vnd.github+json"
|
|
417
|
+
], {
|
|
418
|
+
encoding: "utf-8",
|
|
419
|
+
maxBuffer: 10 * 1024 * 1024
|
|
420
|
+
});
|
|
421
|
+
const parsed = JSON.parse(stdout);
|
|
422
|
+
for (const run of parsed.check_runs ?? []) {
|
|
423
|
+
let state = "unknown";
|
|
424
|
+
if (run.status === "completed") {
|
|
425
|
+
const c = (run.conclusion ?? "").toLowerCase();
|
|
426
|
+
if (c === "success") state = "success";
|
|
427
|
+
else if (c === "failure" || c === "startup_failure") state = "failure";
|
|
428
|
+
else if (c === "neutral") state = "neutral";
|
|
429
|
+
else if (c === "cancelled") state = "cancelled";
|
|
430
|
+
else if (c === "timed_out") state = "timed_out";
|
|
431
|
+
else if (c === "skipped") state = "skipped";
|
|
432
|
+
else if (c === "action_required") state = "action_required";
|
|
433
|
+
else state = "error";
|
|
434
|
+
} else state = "pending";
|
|
435
|
+
checks.push({
|
|
436
|
+
name: run.name,
|
|
437
|
+
state,
|
|
438
|
+
conclusion: run.conclusion,
|
|
439
|
+
detailsUrl: run.html_url ?? null
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
} catch {}
|
|
443
|
+
return checks;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Reply to an existing GitHub review comment (thread).
|
|
447
|
+
* POST /repos/{owner}/{repo}/pulls/{pull_number}/comments with in_reply_to.
|
|
448
|
+
*/
|
|
449
|
+
async function replyToPrComment(input) {
|
|
450
|
+
const endpoint = `repos/${input.resolved.owner}/${input.resolved.repo}/pulls/${input.resolved.pullNumber}/comments`;
|
|
451
|
+
const payload = JSON.stringify({
|
|
452
|
+
body: input.body,
|
|
453
|
+
in_reply_to: input.inReplyTo
|
|
454
|
+
});
|
|
455
|
+
try {
|
|
456
|
+
const { stdout } = await execFileAsync("gh", [
|
|
457
|
+
"api",
|
|
458
|
+
"--method",
|
|
459
|
+
"POST",
|
|
460
|
+
endpoint,
|
|
461
|
+
"-H",
|
|
462
|
+
"Accept: application/vnd.github+json",
|
|
463
|
+
"--input",
|
|
464
|
+
"-"
|
|
465
|
+
], {
|
|
466
|
+
encoding: "utf-8",
|
|
467
|
+
input: payload,
|
|
468
|
+
maxBuffer: 5 * 1024 * 1024
|
|
469
|
+
});
|
|
470
|
+
return {
|
|
471
|
+
ok: true,
|
|
472
|
+
id: JSON.parse(stdout).id
|
|
473
|
+
};
|
|
474
|
+
} catch (err) {
|
|
475
|
+
const msg = err?.stderr || err?.stdout || err?.message || "reply failed";
|
|
476
|
+
return {
|
|
477
|
+
ok: false,
|
|
478
|
+
error: String(msg).slice(0, 500)
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
async function buildPrSession(ref) {
|
|
483
|
+
const meta = await fetchPrMetadataViaGh(parsePrRef(ref, await detectCwdRepo() ?? void 0));
|
|
484
|
+
return {
|
|
485
|
+
ref,
|
|
486
|
+
owner: meta.owner,
|
|
487
|
+
repo: meta.repo,
|
|
488
|
+
pullNumber: meta.number,
|
|
489
|
+
baseSha: meta.baseSha,
|
|
490
|
+
headSha: meta.headSha,
|
|
491
|
+
title: meta.title,
|
|
492
|
+
url: meta.url,
|
|
493
|
+
author: meta.author,
|
|
494
|
+
additions: meta.additions,
|
|
495
|
+
deletions: meta.deletions,
|
|
496
|
+
changedFiles: meta.changedFiles,
|
|
497
|
+
diff: meta.diff,
|
|
498
|
+
comments: [],
|
|
499
|
+
existingComments: meta.existingComments
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
/** Refresh `diff` + `existingComments` + head SHA in an existing session. */
|
|
503
|
+
async function refreshPrSession(session) {
|
|
504
|
+
const meta = await fetchPrMetadataViaGh({
|
|
505
|
+
owner: session.owner,
|
|
506
|
+
repo: session.repo,
|
|
507
|
+
pullNumber: session.pullNumber,
|
|
508
|
+
ref: session.ref
|
|
509
|
+
});
|
|
510
|
+
return {
|
|
511
|
+
...session,
|
|
512
|
+
baseSha: meta.baseSha,
|
|
513
|
+
headSha: meta.headSha,
|
|
514
|
+
title: meta.title,
|
|
515
|
+
url: meta.url,
|
|
516
|
+
author: meta.author,
|
|
517
|
+
additions: meta.additions,
|
|
518
|
+
deletions: meta.deletions,
|
|
519
|
+
changedFiles: meta.changedFiles,
|
|
520
|
+
diff: meta.diff,
|
|
521
|
+
existingComments: meta.existingComments
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
//#endregion
|
|
525
|
+
export { detectGhCli as a, fetchPrMetadataViaGh as c, readGithubToken as d, refreshPrSession as f, detectCwdRepo as i, parseGhAuthStatusUser as l, submitReview as m, buildReviewPayload as n, expandMultiLineComments as o, replyToPrComment as p, decisionToEvent as r, fetchPrChecks as s, buildPrSession as t, parsePrRef as u };
|