diffing 0.11.0 → 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 +2 -12
- package/dist/{cli-agent-DkwGxuy2.mjs → cli-agent-CWsOHN-j.mjs} +165 -53
- package/dist/{cli-gh-D0NfKpOp.mjs → cli-gh-DI69gJGo.mjs} +24 -14
- package/dist/cli.mjs +53 -22
- package/dist/client/assets/{angular-html-Dl53kkiy.js → angular-html-PLPuQo0k.js} +1 -1
- package/dist/client/assets/{angular-ts-wNJFFkey.js → angular-ts-CE02Ij4b.js} +1 -1
- package/dist/client/assets/{apl-BxtQST-h.js → apl-CsuUKZoi.js} +1 -1
- package/dist/client/assets/{arc-CBmZuzPB.js → arc-CgL5kFe-.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-CEci_K9f.js → architectureDiagram-3BPJPVTR-DxZQWGnx.js} +1 -1
- package/dist/client/assets/{astro-BpADD5rh.js → astro-DkFc7sbz.js} +1 -1
- package/dist/client/assets/{blade-B4I5SQmP.js → blade-BkY07kcC.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DcKhDtnE.js → blockDiagram-GPEHLZMM-D5a2KZV2.js} +1 -1
- package/dist/client/assets/{c-C3VtOgg8.js → c-T1BrPfJ6.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CaHozoxF.js → c4Diagram-AAUBKEIU-mpMH4kFC.js} +1 -1
- package/dist/client/assets/channel-D3niKhl0.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-tvuzKhdK.js → chunk-2J33WTMH-vMtgRLFH.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-D_nBoD9w.js → chunk-3OPIFGDE-Dx-FqyO2.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-yHPdy1G8.js → chunk-4BX2VUAB-CUrPd8Kv.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-yXpL8wjV.js → chunk-55IACEB6-DHg3Nr8A.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-DZ5cvCDV.js → chunk-5ZQYHXKU-CpDPvbGs.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-CJjgOWmY.js → chunk-727SXJPM-3VOGMxwk.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CQYQKXSE.js → chunk-AQP2D5EJ-4dbfbIS6.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-CP_f908b.js → chunk-BSJP7CBP-Dfyn0Uwp.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-tcgA8jR0.js → chunk-CSCIHK7Q-VTpSKo0F.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DlpmhBYg.js → chunk-FMBD7UC4-kXD1MyOL.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-BkfieXpV.js → chunk-KSCS5N6A-BrVoWOAb.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-BjVXSZnt.js → chunk-L5ZTLDWV-wZEQDPsa.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-CaAWmy4Q.js → chunk-LZXEDZCA-D3i0B0eg.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-kWh41zUn.js → chunk-ND2GUHAM-hDVHT0bN.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-CDrIi44_.js → chunk-NZK2D7GU-jQUfhp9h.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-CbNGK3Te.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-Cca0fTtG.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-j-6eG2UQ.js → cobol-8-qBLs-a.js} +1 -1
- package/dist/client/assets/{coffee-CZLH0dtt.js → coffee-Bjz5lkyW.js} +1 -1
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DlxESVex.js → cose-bilkent-S5V4N54A-BljJ0FSA.js} +1 -1
- package/dist/client/assets/{cpp-j6Bp24RI.js → cpp-5BVQCBXT.js} +1 -1
- package/dist/client/assets/{crystal-DW7wcFUs.js → crystal-CCkY93GS.js} +1 -1
- package/dist/client/assets/{css-C43BDU2i.js → css-BTM7Tp2a.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BaemEJFh.js → dagre-BM42HDAG-BSynd_2D.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BaM-bkJ3.js → diagram-2AECGRRQ-K3E2CVdy.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-BOH04DJO.js → diagram-5GNKFQAL-BQHIrfKc.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BP5MyqDZ.js → diagram-KO2AKTUF-Bqs8sNN4.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-Dt4gKMYF.js → diagram-LMA3HP47-C9K4bpQe.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-DoT1VshN.js → diagram-OG6HWLK6-DK6wIXY2.js} +1 -1
- package/dist/client/assets/{dist-DEAxvC4F.js → dist-1nkZYMRy.js} +1 -1
- package/dist/client/assets/{edge-D9ySFlnD.js → edge-DqN2FJce.js} +1 -1
- package/dist/client/assets/{elixir-CoJz_LQ5.js → elixir-BiAgRUFF.js} +1 -1
- package/dist/client/assets/{elm-CvedWh_e.js → elm-N1IbY8sz.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-CMP78FsQ.js → erDiagram-TEJ5UH35-jsHCiP02.js} +1 -1
- package/dist/client/assets/{erb-lD_yYZsm.js → erb-B-yYlWAZ.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Dp0s5BFj.js → flowDiagram-I6XJVG4X-DOB1dAWG.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-GmSG31U-.js → ganttDiagram-6RSMTGT7-BYIewcY5.js} +1 -1
- package/dist/client/assets/{git-rebase-DwZABzof.js → git-rebase-CVkPxOAF.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-C1SXShag.js → gitGraphDiagram-PVQCEYII-VNQzbpv2.js} +1 -1
- package/dist/client/assets/{glimmer-js-CWcs3w1Z.js → glimmer-js-BmG1xm72.js} +1 -1
- package/dist/client/assets/{glimmer-ts-CrzGN4lJ.js → glimmer-ts-CvTgwZsg.js} +1 -1
- package/dist/client/assets/{glsl-DRCtwX7h.js → glsl-DwjNNCbW.js} +1 -1
- package/dist/client/assets/{graphql-rpmrismS.js → graphql-BvgkyF8E.js} +1 -1
- package/dist/client/assets/{hack-Ba02RnuQ.js → hack-DH3188x2.js} +1 -1
- package/dist/client/assets/{haml-BHBACStm.js → haml-B0GTfMhX.js} +1 -1
- package/dist/client/assets/{handlebars-BtlQ1SCa.js → handlebars-he7hLDd9.js} +1 -1
- package/dist/client/assets/{html-BkVU3Dge.js → html-DIYgdTBq.js} +1 -1
- package/dist/client/assets/{html-derivative-DoK92vwi.js → html-derivative-2s6MXlci.js} +1 -1
- package/dist/client/assets/{http-CJAwKSPH.js → http-COS23XJP.js} +1 -1
- package/dist/client/assets/{hurl-kaX5jwuN.js → hurl-BlZPjeJt.js} +1 -1
- package/dist/client/assets/{index-BHeNiC07.js → index-BrEVVQOB.js} +154 -154
- package/dist/client/assets/{index-D8hOoJCg.css → index-BsuX6HVI.css} +1 -1
- package/dist/client/assets/{infoDiagram-5YYISTIA-B0i3BlNR.js → infoDiagram-5YYISTIA-DQRqk24I.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-BN8sEei4.js → ishikawaDiagram-YF4QCWOH-DU1rqrLx.js} +1 -1
- package/dist/client/assets/{java-BvrigIoq.js → java-BAa5w-Qd.js} +1 -1
- package/dist/client/assets/{javascript-DZkPTYAi.js → javascript-C9e02ssI.js} +1 -1
- package/dist/client/assets/{jinja-Ceg7ui1S.js → jinja-Bx37xXwq.js} +1 -1
- package/dist/client/assets/{jison-iE1GaOyN.js → jison-m_DEf8Jo.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CE6O3NhU.js → journeyDiagram-JHISSGLW-CoHlfevf.js} +1 -1
- package/dist/client/assets/{json-C0j8rEcg.js → json-DtN5AWRW.js} +1 -1
- package/dist/client/assets/{jsx-B7eXljgz.js → jsx-BlPpu8bR.js} +1 -1
- package/dist/client/assets/{julia-DMDw0aMP.js → julia-BAOmCbHl.js} +1 -1
- package/dist/client/assets/{just-BryMKRJ_.js → just-C_bvVjwE.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-j-aU6Yzp.js → kanban-definition-UN3LZRKU-BiqYI7_m.js} +1 -1
- package/dist/client/assets/{latex-BNC9-sjr.js → latex-81pMfNMt.js} +1 -1
- package/dist/client/assets/{line-CyEqpEDp.js → line-DCovs9My.js} +1 -1
- package/dist/client/assets/{linear-CXeaA9km.js → linear-cJF5XHE7.js} +1 -1
- package/dist/client/assets/{liquid-D-fQw-oJ.js → liquid-sKRTk6dT.js} +1 -1
- package/dist/client/assets/{lua-CD2aJ_rS.js → lua-C1uZL4IF.js} +1 -1
- package/dist/client/assets/{marko-BQ37hu6z.js → marko-BKEzP1CL.js} +1 -1
- package/dist/client/assets/{mdc-B5NUi3zZ.js → mdc-CLkfm94H.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BxHF_XbX.js → mermaid-parser.core-CTsTbvb2.js} +1 -1
- package/dist/client/assets/{mermaid.core-BUtaf4P1.js → mermaid.core-D86HJEwL.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-D13tPu2o.js → mindmap-definition-RKZ34NQL-CL3heUmL.js} +1 -1
- package/dist/client/assets/{nginx-1W1E03Rg.js → nginx-eDGm66pc.js} +1 -1
- package/dist/client/assets/{nim-C5A88bFP.js → nim-CoWZPv8-.js} +1 -1
- package/dist/client/assets/{perl-BYoP0wNt.js → perl-MoMqtMVr.js} +1 -1
- package/dist/client/assets/{php-CFxna09e.js → php-DXXVMAtN.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-CHL7Ml5w.js → pieDiagram-4H26LBE5-CWV3TMu4.js} +1 -1
- package/dist/client/assets/{pug-BR4JgWAk.js → pug-CPWaB94J.js} +1 -1
- package/dist/client/assets/{qml-D1U1EFEe.js → qml-lhvpx8vk.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-BnYtv-HY.js → quadrantDiagram-W4KKPZXB-QV25BYos.js} +1 -1
- package/dist/client/assets/{r-ChE6X060.js → r-DYbUnmmK.js} +1 -1
- package/dist/client/assets/{razor-B5iVfQMe.js → razor-DcyOLv96.js} +1 -1
- package/dist/client/assets/{regexp-Dz2drUIf.js → regexp-BdY10jm0.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-D8QEGLKB.js → requirementDiagram-4Y6WPE33-BPMsmU6J.js} +1 -1
- package/dist/client/assets/{review-export-CvFFbCAB.js → review-export-CMwjJURs.js} +1 -1
- package/dist/client/assets/{rst-DZM3RGRs.js → rst-6ShFOzgH.js} +1 -1
- package/dist/client/assets/{ruby-DkXnm-J8.js → ruby-B04DeVbi.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-wVaks6lB.js → sankeyDiagram-5OEKKPKP-DQJeroPp.js} +1 -1
- package/dist/client/assets/{sas-DMbpc71c.js → sas-Dj26ftNa.js} +1 -1
- package/dist/client/assets/{scss-IwVMMp22.js → scss-BOHpBkgl.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Cg31TB-R.js → sequenceDiagram-3UESZ5HK-DdV0Y6Sz.js} +1 -1
- package/dist/client/assets/{shellscript-CIStAKx3.js → shellscript-CpHwjRcU.js} +1 -1
- package/dist/client/assets/{shellsession-uLtzHhlo.js → shellsession-BJAvf4GN.js} +1 -1
- package/dist/client/assets/{soy-BkxBYigm.js → soy-B67bZJnL.js} +1 -1
- package/dist/client/assets/{sql-Ba9y9EvJ.js → sql-8MzOqSsK.js} +1 -1
- package/dist/client/assets/{src-9MKexpFu.js → src-AaoRSmFl.js} +1 -1
- package/dist/client/assets/{stata-CrPCbiIZ.js → stata-aCME945h.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-BbvNjVF6.js → stateDiagram-AJRCARHV-CMD_Xj2M.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-vLl7D4ue.js +1 -0
- package/dist/client/assets/{surrealql-Dvip5u_o.js → surrealql-B_V_HxAi.js} +1 -1
- package/dist/client/assets/{svelte-xBLD60Zd.js → svelte-BcQvTlqz.js} +1 -1
- package/dist/client/assets/{templ-CWv68xbP.js → templ-DZCQ2blz.js} +1 -1
- package/dist/client/assets/{tex-CHqz-fYs.js → tex-BfeQ5Wuu.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CWKkJ3QZ.js → timeline-definition-PNZ67QCA-CyIS7Zoe.js} +1 -1
- package/dist/client/assets/{ts-tags-DS82EDuE.js → ts-tags-DVWE0E87.js} +1 -1
- package/dist/client/assets/{tsx-B2GBjp2F.js → tsx-DdJ7Sfqf.js} +1 -1
- package/dist/client/assets/{twig-CC8x9pG0.js → twig-_gVgaha5.js} +1 -1
- package/dist/client/assets/{typescript-g7i13lnC.js → typescript-Bj0_LzZV.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-OLItKWeg.js → vennDiagram-CIIHVFJN-C-J2kWyk.js} +1 -1
- package/dist/client/assets/{vue-rFbe7luB.js → vue-Dnt_GBRb.js} +1 -1
- package/dist/client/assets/{vue-html-D9GQtYub.js → vue-html-ClVA5__5.js} +1 -1
- package/dist/client/assets/{vue-vine-mrNtQtY5.js → vue-vine-BCcz4SVP.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Dy1yfeb4.js → wardleyDiagram-YWT4CUSO-Dzt4EPh8.js} +1 -1
- package/dist/client/assets/{xml-CHfMjyAM.js → xml-BYeUHEti.js} +1 -1
- package/dist/client/assets/{xsl-BFkNSogJ.js → xsl-Vsx0SZEV.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DfSnfjVL.js → xychartDiagram-2RQKCTM6-BAWZKvwP.js} +1 -1
- package/dist/client/assets/{yaml-BfSgHc04.js → yaml-C6L1khMK.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/{completions-BO2DUM-8.mjs → completions-DvyV49HY.mjs} +1 -0
- package/dist/{doctor-D0Y3kOY7.mjs → doctor-Bz9VHuBI.mjs} +7 -7
- package/dist/{find-tui-binary-B71xiwWu.mjs → find-tui-binary-DVQADOSF.mjs} +56 -25
- package/dist/{git-Czo96ymM.mjs → git-BGj31GX-.mjs} +71 -7
- package/dist/git-CfDSkUcE.mjs +2 -0
- package/dist/{github-CErBub2y.mjs → github-DXiEeHzk.mjs} +1 -1
- package/dist/{github-DBsZ0h_l.mjs → github-DpzqNrUh.mjs} +3 -3
- package/dist/{github-attachments-plDeB0iE.mjs → github-attachments-DgOf7BhP.mjs} +2 -2
- package/dist/{mcp-DtVrMR2S.mjs → mcp-zDVzU1vl.mjs} +32 -29
- 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/{search-BMPY_ZW8.mjs → search-3R2E5xxr.mjs} +16 -1
- package/dist/{search-BO9Im7eu.mjs → search-CQ4nsjBX.mjs} +1 -1
- package/dist/{server-j0PnTVX1.mjs → server-Dw3lkQ5q.mjs} +157 -42
- package/dist/{server-lock-CY0_1mcS.mjs → server-lock-BNI8FKV1.mjs} +175 -23
- package/dist/{session-conflict-C6V9ZKo7.mjs → session-conflict-Bqt1M4Mp.mjs} +7 -7
- package/dist/{session-manager-CYNchhVA.mjs → session-manager-BKSZQqDJ.mjs} +2 -2
- package/dist/session-url-sr7lXXVc.mjs +100 -0
- package/dist/{tui-search-bridge-Bfb2ktdA.mjs → tui-search-bridge-BGgLCwMF.mjs} +3 -3
- package/dist/{update-check-Copcz9eb.mjs → update-check-BUfh4Y6c.mjs} +16 -15
- package/package.json +4 -1
- package/dist/client/assets/channel-Ct4-oSQN.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-BXhKFVX7.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-_EwuC51_.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C8bdx9R4.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-B26wrQuH.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-B5BbZkU5.js +0 -1
- package/dist/git-DaP_1rVy.mjs +0 -2
- package/dist/settings-yK0GYpbn.mjs +0 -60
package/README.md
CHANGED
|
@@ -110,7 +110,7 @@ Blazing-fast, native fuzzy code search integrated directly into the sidebar sear
|
|
|
110
110
|
|
|
111
111
|
- **Fuzzy File Search** (`Files` scope) — Error-tolerant fuzzy matching on workspace paths using a native Rust engine.
|
|
112
112
|
- **Codebase Grep** (`Text` scope) — Instant case-insensitive text search with full **Regular Expression** support.
|
|
113
|
-
- **Syntactic Symbol Search** (`Symbols` scope) — Finds function declarations, class headers, type definitions, and variable assignments across JavaScript, TypeScript, Go, Rust, and
|
|
113
|
+
- **Syntactic Symbol Search** (`Symbols` scope) — Finds function declarations, class headers, type definitions, and variable assignments across JavaScript, TypeScript, Go, Rust, Python, and PHP (27 language patterns).
|
|
114
114
|
- **Unified "All" Search** — Concurrent search across files, text, and symbols with automatic deduplication.
|
|
115
115
|
- **Frecency Ranking** — SQLite-backed history database remembers which files you open for specific queries, floating high-value results to the top.
|
|
116
116
|
- **"Changed Only" Filter** — Restricts search scope exclusively to files changed in the active git diff.
|
|
@@ -176,18 +176,8 @@ A vim-style status bar at the bottom displays the current mode (NORMAL/INSERT),
|
|
|
176
176
|
|
|
177
177
|
## Native Terminal UI (TUI) — *Experimental*
|
|
178
178
|
|
|
179
|
-
|
|
180
|
-
> The TUI is **experimental**. The interface, keymap, and on-disk format of
|
|
181
|
-
> `server.json` (`mode: "tui"`) may change in a minor release before
|
|
182
|
-
> stabilisation. The web UI is the supported path for production workflows;
|
|
183
|
-
> please open an issue before depending on the TUI for CI / agent automation.
|
|
184
|
-
> The web review flow, plan review, and PR review are unaffected.
|
|
179
|
+
<img width="1624" height="1061" alt="image" src="https://github.com/user-attachments/assets/2756dbe5-6329-4d70-a8c0-ca61600c2154" />
|
|
185
180
|
|
|
186
|
-
> [!IMPORTANT]
|
|
187
|
-
> Native binaries are published as optional, platform-specific npm packages
|
|
188
|
-
> for macOS, Windows, and glibc/musl Linux. The main package never compiles Rust
|
|
189
|
-
> during installation and never installs a binary for the wrong platform. A
|
|
190
|
-
> source build and `$PATH` remain supported fallbacks.
|
|
191
181
|
|
|
192
182
|
`diffing --tui` opens an **opt-in native-Rust terminal interface** that mirrors the local code-review workflow — no browser or Electron. The renderer and headless tools share one sparse diff index. Review sessions publish a capability-scoped loopback API through the per-repository session registry; web and TUI reviews can run concurrently, while `server.json` points agent commands at the selected active session. Read-only viewers do not register a review session.
|
|
193
183
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { f as getProjectStorageDir } from "./git-BGj31GX-.mjs";
|
|
2
|
+
import { a as loadSettings, i as reviewSessionUrl, o as saveSettings, t as appendSessionToken } from "./session-url-sr7lXXVc.mjs";
|
|
3
3
|
import { t as formatComments } from "./comment-format-B85NHZnG.mjs";
|
|
4
4
|
import { n as formatPlanReview } from "./plan-format-BwJh5JSE.mjs";
|
|
5
|
-
import { u as resolveActiveServerLock } from "./server-lock-
|
|
5
|
+
import { h as SESSION_TOKEN_HEADER, u as resolveActiveServerLock } from "./server-lock-BNI8FKV1.mjs";
|
|
6
6
|
import { a as CLI_AWAIT_REVIEW_TIMEOUT_HINT, i as CLI_AWAIT_PLAN_TIMEOUT_HINT, o as CLI_PLAN_SUBMIT_PARK_HINT } from "./handoff-LAFtmnHf.mjs";
|
|
7
7
|
import { join } from "node:path";
|
|
8
8
|
import { parseArgs } from "node:util";
|
|
@@ -25,6 +25,7 @@ const EXIT_NO_SERVER = 3;
|
|
|
25
25
|
const EXIT_NOT_FOUND = 4;
|
|
26
26
|
const EXIT_USAGE = 5;
|
|
27
27
|
let activeCapability;
|
|
28
|
+
let activeAuthToken;
|
|
28
29
|
/** Resolve the running server's base URL from the lockfile, or exit cleanly. */
|
|
29
30
|
function baseUrl() {
|
|
30
31
|
const lock = resolveActiveServerLock();
|
|
@@ -34,17 +35,41 @@ function baseUrl() {
|
|
|
34
35
|
}
|
|
35
36
|
const host = lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host;
|
|
36
37
|
activeCapability = lock.mode === "tui" ? lock.capability : void 0;
|
|
38
|
+
activeAuthToken = lock.authToken;
|
|
37
39
|
return `http://${host}:${lock.port}`;
|
|
38
40
|
}
|
|
39
|
-
/** Attach
|
|
41
|
+
/** Attach session credentials while preserving ordinary web calls. */
|
|
40
42
|
function apiFetch(input, init = {}) {
|
|
41
43
|
const headers = new Headers(init.headers);
|
|
42
44
|
if (activeCapability) headers.set("X-Diffing-Capability", activeCapability);
|
|
45
|
+
if (activeAuthToken) headers.set(SESSION_TOKEN_HEADER, activeAuthToken);
|
|
43
46
|
return fetch(input, {
|
|
44
47
|
...init,
|
|
45
48
|
headers
|
|
46
49
|
});
|
|
47
50
|
}
|
|
51
|
+
function connectionErrorMessage(err) {
|
|
52
|
+
if (err instanceof Error) return err.message;
|
|
53
|
+
return String(err);
|
|
54
|
+
}
|
|
55
|
+
/** apiFetch wrapper that logs connection failures and returns null instead of throwing. */
|
|
56
|
+
async function tryApiFetch(input, init) {
|
|
57
|
+
try {
|
|
58
|
+
return await apiFetch(input, init);
|
|
59
|
+
} catch (err) {
|
|
60
|
+
console.error(`Failed to reach diffing server: ${connectionErrorMessage(err)}`);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function parseTimeoutSeconds(raw, flag = "--timeout") {
|
|
65
|
+
if (raw === void 0) return 570;
|
|
66
|
+
const t = Number(raw);
|
|
67
|
+
if (!Number.isFinite(t) || t <= 0) {
|
|
68
|
+
console.error(`${flag} must be a positive number of seconds.`);
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
return t;
|
|
72
|
+
}
|
|
48
73
|
async function readStdin() {
|
|
49
74
|
const chunks = [];
|
|
50
75
|
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
@@ -68,7 +93,9 @@ async function awaitReview(args) {
|
|
|
68
93
|
},
|
|
69
94
|
allowPositionals: false
|
|
70
95
|
});
|
|
71
|
-
const
|
|
96
|
+
const timeoutSeconds = parseTimeoutSeconds(values.timeout);
|
|
97
|
+
if (timeoutSeconds === null) return EXIT_USAGE;
|
|
98
|
+
const totalBudgetMs = timeoutSeconds * 1e3;
|
|
72
99
|
const base = baseUrl();
|
|
73
100
|
let agentId = typeof values["agent-id"] === "string" ? values["agent-id"] : void 0;
|
|
74
101
|
try {
|
|
@@ -84,9 +111,8 @@ async function awaitReview(args) {
|
|
|
84
111
|
if (reg.ok) agentId = (await reg.json()).agentId ?? agentId;
|
|
85
112
|
} catch {}
|
|
86
113
|
let sinceRound = 0;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} catch {}
|
|
114
|
+
const statusRes = await tryApiFetch(`${base}/api/review/status`);
|
|
115
|
+
if (statusRes?.ok) sinceRound = (await statusRes.json()).round ?? 0;
|
|
90
116
|
const unregister = async () => {
|
|
91
117
|
if (!agentId) return;
|
|
92
118
|
try {
|
|
@@ -100,10 +126,15 @@ async function awaitReview(args) {
|
|
|
100
126
|
res = await apiFetch(`${base}/api/review/await?timeoutMs=25000&sinceRound=${sinceRound}`, { signal: AbortSignal.timeout(3e4) });
|
|
101
127
|
} catch (err) {
|
|
102
128
|
if (err?.name === "TimeoutError") continue;
|
|
103
|
-
console.error(`Failed to reach diffing server: ${err
|
|
129
|
+
console.error(`Failed to reach diffing server: ${connectionErrorMessage(err)}`);
|
|
104
130
|
await unregister();
|
|
105
131
|
return EXIT_NO_SERVER;
|
|
106
132
|
}
|
|
133
|
+
if (!res.ok) {
|
|
134
|
+
console.error(`Failed to await review: HTTP ${res.status}`);
|
|
135
|
+
await unregister();
|
|
136
|
+
return 1;
|
|
137
|
+
}
|
|
107
138
|
const result = await res.json();
|
|
108
139
|
if (result.status === "released") {
|
|
109
140
|
process.stdout.write(result.payload.commentXml + "\n");
|
|
@@ -139,12 +170,18 @@ async function reply(args) {
|
|
|
139
170
|
return EXIT_USAGE;
|
|
140
171
|
}
|
|
141
172
|
let body = values.body;
|
|
142
|
-
if (body ===
|
|
173
|
+
if (body === void 0) {
|
|
174
|
+
if (process.stdin.isTTY) {
|
|
175
|
+
console.error("Usage: diffing reply <commentId> --body <text> [--model <name>]");
|
|
176
|
+
return EXIT_USAGE;
|
|
177
|
+
}
|
|
178
|
+
body = (await readStdin()).trim();
|
|
179
|
+
} else if (body === "-") body = (await readStdin()).trim();
|
|
143
180
|
if (!body) {
|
|
144
181
|
console.error("A reply body is required (--body <text> or pipe via stdin).");
|
|
145
182
|
return EXIT_USAGE;
|
|
146
183
|
}
|
|
147
|
-
const res = await
|
|
184
|
+
const res = await tryApiFetch(`${baseUrl()}/api/comments/${commentId}/replies`, {
|
|
148
185
|
method: "POST",
|
|
149
186
|
headers: { "Content-Type": "application/json" },
|
|
150
187
|
body: JSON.stringify({
|
|
@@ -153,6 +190,7 @@ async function reply(args) {
|
|
|
153
190
|
model: values.model
|
|
154
191
|
})
|
|
155
192
|
});
|
|
193
|
+
if (!res) return EXIT_NO_SERVER;
|
|
156
194
|
if (res.status === 404) {
|
|
157
195
|
console.error(`Comment ${commentId} not found.`);
|
|
158
196
|
return EXIT_NOT_FOUND;
|
|
@@ -175,11 +213,12 @@ async function resolve$1(args) {
|
|
|
175
213
|
console.error("Usage: diffing resolve <commentId>");
|
|
176
214
|
return EXIT_USAGE;
|
|
177
215
|
}
|
|
178
|
-
const res = await
|
|
216
|
+
const res = await tryApiFetch(`${baseUrl()}/api/comments/${commentId}`, {
|
|
179
217
|
method: "PUT",
|
|
180
218
|
headers: { "Content-Type": "application/json" },
|
|
181
219
|
body: JSON.stringify({ status: "resolved" })
|
|
182
220
|
});
|
|
221
|
+
if (!res) return EXIT_NO_SERVER;
|
|
183
222
|
if (res.status === 404) {
|
|
184
223
|
console.error(`Comment ${commentId} not found.`);
|
|
185
224
|
return EXIT_NOT_FOUND;
|
|
@@ -202,11 +241,12 @@ async function unresolve(args) {
|
|
|
202
241
|
console.error("Usage: diffing unresolve <commentId>");
|
|
203
242
|
return EXIT_USAGE;
|
|
204
243
|
}
|
|
205
|
-
const res = await
|
|
244
|
+
const res = await tryApiFetch(`${baseUrl()}/api/comments/${commentId}`, {
|
|
206
245
|
method: "PUT",
|
|
207
246
|
headers: { "Content-Type": "application/json" },
|
|
208
247
|
body: JSON.stringify({ status: "open" })
|
|
209
248
|
});
|
|
249
|
+
if (!res) return EXIT_NO_SERVER;
|
|
210
250
|
if (res.status === 404) {
|
|
211
251
|
console.error(`Comment ${commentId} not found.`);
|
|
212
252
|
return EXIT_NOT_FOUND;
|
|
@@ -233,16 +273,23 @@ async function commentEdit(args) {
|
|
|
233
273
|
return EXIT_USAGE;
|
|
234
274
|
}
|
|
235
275
|
let body = values.body;
|
|
236
|
-
if (body ===
|
|
276
|
+
if (body === void 0) {
|
|
277
|
+
if (process.stdin.isTTY) {
|
|
278
|
+
console.error("Usage: diffing comment edit <commentId> --body <text>");
|
|
279
|
+
return EXIT_USAGE;
|
|
280
|
+
}
|
|
281
|
+
body = (await readStdin()).trim();
|
|
282
|
+
} else if (body === "-") body = (await readStdin()).trim();
|
|
237
283
|
if (!body) {
|
|
238
284
|
console.error("A body is required (--body <text> or stdin).");
|
|
239
285
|
return EXIT_USAGE;
|
|
240
286
|
}
|
|
241
|
-
const res = await
|
|
287
|
+
const res = await tryApiFetch(`${baseUrl()}/api/comments/${commentId}`, {
|
|
242
288
|
method: "PUT",
|
|
243
289
|
headers: { "Content-Type": "application/json" },
|
|
244
290
|
body: JSON.stringify({ body })
|
|
245
291
|
});
|
|
292
|
+
if (!res) return EXIT_NO_SERVER;
|
|
246
293
|
if (res.status === 404) {
|
|
247
294
|
console.error(`Comment ${commentId} not found.`);
|
|
248
295
|
return EXIT_NOT_FOUND;
|
|
@@ -265,7 +312,8 @@ async function commentDelete(args) {
|
|
|
265
312
|
console.error("Usage: diffing comment delete <commentId>");
|
|
266
313
|
return EXIT_USAGE;
|
|
267
314
|
}
|
|
268
|
-
const res = await
|
|
315
|
+
const res = await tryApiFetch(`${baseUrl()}/api/comments/${commentId}`, { method: "DELETE" });
|
|
316
|
+
if (!res) return EXIT_NO_SERVER;
|
|
269
317
|
if (res.status === 404) {
|
|
270
318
|
console.error(`Comment ${commentId} not found.`);
|
|
271
319
|
return EXIT_NOT_FOUND;
|
|
@@ -289,7 +337,13 @@ async function commentCmd(args) {
|
|
|
289
337
|
}
|
|
290
338
|
}
|
|
291
339
|
async function url() {
|
|
292
|
-
|
|
340
|
+
const lock = resolveActiveServerLock();
|
|
341
|
+
if (!lock) {
|
|
342
|
+
console.error("No diffing server running for this repo. Start one with `diffing`.");
|
|
343
|
+
process.exit(EXIT_NO_SERVER);
|
|
344
|
+
}
|
|
345
|
+
const printed = reviewSessionUrl(lock) ?? baseUrl();
|
|
346
|
+
process.stdout.write(`${printed}\n`);
|
|
293
347
|
return EXIT_OK;
|
|
294
348
|
}
|
|
295
349
|
async function comments(args) {
|
|
@@ -302,9 +356,19 @@ async function comments(args) {
|
|
|
302
356
|
},
|
|
303
357
|
allowPositionals: false
|
|
304
358
|
});
|
|
305
|
-
const
|
|
359
|
+
const res = await tryApiFetch(`${baseUrl()}/api/comments`);
|
|
360
|
+
if (!res) return EXIT_NO_SERVER;
|
|
361
|
+
if (!res.ok) {
|
|
362
|
+
console.error(`Failed to fetch comments: HTTP ${res.status}`);
|
|
363
|
+
return 1;
|
|
364
|
+
}
|
|
365
|
+
const all = await res.json();
|
|
306
366
|
const selected = values.open ? all.filter((c) => c.status === "open") : all;
|
|
307
367
|
const format = values.format?.toLowerCase();
|
|
368
|
+
if (format && format !== "xml" && format !== "json" && format !== "md" && format !== "markdown") {
|
|
369
|
+
console.error("Unknown --format. Use xml, json, md, or markdown.");
|
|
370
|
+
return EXIT_USAGE;
|
|
371
|
+
}
|
|
308
372
|
if (values.json || format === "json") process.stdout.write(JSON.stringify(selected, null, 2) + "\n");
|
|
309
373
|
else if (format === "markdown" || format === "md") {
|
|
310
374
|
const { formatCommentsMarkdown } = await import("./review-export-B63eRAVa.mjs");
|
|
@@ -349,9 +413,10 @@ function deriveTitle(body) {
|
|
|
349
413
|
/** Long-poll the plan-review handoff until a decision arrives or time runs out. */
|
|
350
414
|
async function pollPlanDecision(base, totalBudgetMs, seedSince) {
|
|
351
415
|
let sinceRound = seedSince ?? 0;
|
|
352
|
-
if (seedSince === void 0)
|
|
353
|
-
|
|
354
|
-
|
|
416
|
+
if (seedSince === void 0) {
|
|
417
|
+
const statusRes = await tryApiFetch(`${base}/api/plan-review/status`);
|
|
418
|
+
if (statusRes?.ok) sinceRound = (await statusRes.json()).round ?? 0;
|
|
419
|
+
}
|
|
355
420
|
const deadline = Date.now() + totalBudgetMs;
|
|
356
421
|
while (Date.now() < deadline) {
|
|
357
422
|
let res;
|
|
@@ -359,9 +424,13 @@ async function pollPlanDecision(base, totalBudgetMs, seedSince) {
|
|
|
359
424
|
res = await apiFetch(`${base}/api/plan-review/await?timeoutMs=25000&sinceRound=${sinceRound}`, { signal: AbortSignal.timeout(3e4) });
|
|
360
425
|
} catch (err) {
|
|
361
426
|
if (err?.name === "TimeoutError") continue;
|
|
362
|
-
console.error(`Failed to reach diffing server: ${err
|
|
427
|
+
console.error(`Failed to reach diffing server: ${connectionErrorMessage(err)}`);
|
|
363
428
|
return EXIT_NO_SERVER;
|
|
364
429
|
}
|
|
430
|
+
if (!res.ok) {
|
|
431
|
+
console.error(`Failed to await plan review: HTTP ${res.status}`);
|
|
432
|
+
return 1;
|
|
433
|
+
}
|
|
365
434
|
const result = await res.json();
|
|
366
435
|
if (result.status === "released") {
|
|
367
436
|
process.stdout.write(result.payload.reviewXml + "\n");
|
|
@@ -428,10 +497,11 @@ async function planSubmit(args) {
|
|
|
428
497
|
source = file;
|
|
429
498
|
}
|
|
430
499
|
let sinceRound = 0;
|
|
431
|
-
if (values.wait)
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
500
|
+
if (values.wait) {
|
|
501
|
+
const statusRes = await tryApiFetch(`${base}/api/plan-review/status`);
|
|
502
|
+
if (statusRes?.ok) sinceRound = (await statusRes.json()).round ?? 0;
|
|
503
|
+
}
|
|
504
|
+
const submitRes = await tryApiFetch(`${base}/api/plans`, {
|
|
435
505
|
method: "POST",
|
|
436
506
|
headers: { "Content-Type": "application/json" },
|
|
437
507
|
body: JSON.stringify({
|
|
@@ -442,12 +512,13 @@ async function planSubmit(args) {
|
|
|
442
512
|
model: values.model
|
|
443
513
|
})
|
|
444
514
|
});
|
|
445
|
-
if (!
|
|
446
|
-
|
|
515
|
+
if (!submitRes) return EXIT_NO_SERVER;
|
|
516
|
+
if (!submitRes.ok) {
|
|
517
|
+
console.error(`Failed to submit plan: HTTP ${submitRes.status}`);
|
|
447
518
|
return 1;
|
|
448
519
|
}
|
|
449
|
-
const plan = await
|
|
450
|
-
console.error(`Submitted plan ${plan.id} (v${plan.version}) — review at ${base}/plan/${plan.id}`);
|
|
520
|
+
const plan = await submitRes.json();
|
|
521
|
+
console.error(`Submitted plan ${plan.id} (v${plan.version}) — review at ${appendSessionToken(`${base}/plan/${plan.id}`, activeAuthToken)}`);
|
|
451
522
|
if (plan.sourcePath) console.error(`Source path: ${plan.sourcePath}`);
|
|
452
523
|
if (!values.wait) console.error(CLI_PLAN_SUBMIT_PARK_HINT);
|
|
453
524
|
if (values.saveSource) try {
|
|
@@ -463,7 +534,9 @@ async function planSubmit(args) {
|
|
|
463
534
|
process.stdout.write(plan.id + "\n");
|
|
464
535
|
return EXIT_OK;
|
|
465
536
|
}
|
|
466
|
-
|
|
537
|
+
const timeoutSeconds = parseTimeoutSeconds(values.timeout);
|
|
538
|
+
if (timeoutSeconds === null) return EXIT_USAGE;
|
|
539
|
+
return pollPlanDecision(base, timeoutSeconds * 1e3, sinceRound);
|
|
467
540
|
}
|
|
468
541
|
async function planAwait(args) {
|
|
469
542
|
const { values } = parseArgs({
|
|
@@ -474,8 +547,9 @@ async function planAwait(args) {
|
|
|
474
547
|
} },
|
|
475
548
|
allowPositionals: false
|
|
476
549
|
});
|
|
477
|
-
const
|
|
478
|
-
|
|
550
|
+
const timeoutSeconds = parseTimeoutSeconds(values.timeout);
|
|
551
|
+
if (timeoutSeconds === null) return EXIT_USAGE;
|
|
552
|
+
return pollPlanDecision(baseUrl(), timeoutSeconds * 1e3);
|
|
479
553
|
}
|
|
480
554
|
async function planList(args) {
|
|
481
555
|
const { values } = parseArgs({
|
|
@@ -483,7 +557,13 @@ async function planList(args) {
|
|
|
483
557
|
options: { json: { type: "boolean" } },
|
|
484
558
|
allowPositionals: false
|
|
485
559
|
});
|
|
486
|
-
const
|
|
560
|
+
const res = await tryApiFetch(`${baseUrl()}/api/plans`);
|
|
561
|
+
if (!res) return EXIT_NO_SERVER;
|
|
562
|
+
if (!res.ok) {
|
|
563
|
+
console.error(`Failed to list plans: HTTP ${res.status}`);
|
|
564
|
+
return 1;
|
|
565
|
+
}
|
|
566
|
+
const all = await res.json();
|
|
487
567
|
if (values.json) {
|
|
488
568
|
process.stdout.write(JSON.stringify(all, null, 2) + "\n");
|
|
489
569
|
return EXIT_OK;
|
|
@@ -510,18 +590,29 @@ async function planShow(args) {
|
|
|
510
590
|
const base = baseUrl();
|
|
511
591
|
let planId = positionals[0];
|
|
512
592
|
if (!planId) {
|
|
513
|
-
const
|
|
593
|
+
const listRes = await tryApiFetch(`${base}/api/plans`);
|
|
594
|
+
if (!listRes) return EXIT_NO_SERVER;
|
|
595
|
+
if (!listRes.ok) {
|
|
596
|
+
console.error(`Failed to list plans: HTTP ${listRes.status}`);
|
|
597
|
+
return 1;
|
|
598
|
+
}
|
|
599
|
+
const all = await listRes.json();
|
|
514
600
|
if (all.length === 0) {
|
|
515
601
|
console.error("No plans submitted yet.");
|
|
516
602
|
return EXIT_NOT_FOUND;
|
|
517
603
|
}
|
|
518
604
|
planId = all[all.length - 1].id;
|
|
519
605
|
}
|
|
520
|
-
const res = await
|
|
606
|
+
const res = await tryApiFetch(`${base}/api/plans/${planId}`);
|
|
607
|
+
if (!res) return EXIT_NO_SERVER;
|
|
521
608
|
if (res.status === 404) {
|
|
522
609
|
console.error(`Plan ${planId} not found.`);
|
|
523
610
|
return EXIT_NOT_FOUND;
|
|
524
611
|
}
|
|
612
|
+
if (!res.ok) {
|
|
613
|
+
console.error(`Failed to load plan: HTTP ${res.status}`);
|
|
614
|
+
return 1;
|
|
615
|
+
}
|
|
525
616
|
const plan = await res.json();
|
|
526
617
|
const requestedVersion = values.version !== void 0 ? Number(values.version) : void 0;
|
|
527
618
|
if (requestedVersion !== void 0 && (!Number.isFinite(requestedVersion) || requestedVersion < 1)) {
|
|
@@ -550,11 +641,16 @@ async function planVersions(args) {
|
|
|
550
641
|
console.error("Usage: diffing plan versions <id> [--json]");
|
|
551
642
|
return EXIT_USAGE;
|
|
552
643
|
}
|
|
553
|
-
const planRes = await
|
|
644
|
+
const planRes = await tryApiFetch(`${base}/api/plans/${planId}`);
|
|
645
|
+
if (!planRes) return EXIT_NO_SERVER;
|
|
554
646
|
if (planRes.status === 404) {
|
|
555
647
|
console.error(`Plan ${planId} not found.`);
|
|
556
648
|
return EXIT_NOT_FOUND;
|
|
557
649
|
}
|
|
650
|
+
if (!planRes.ok) {
|
|
651
|
+
console.error(`Failed to load plan: HTTP ${planRes.status}`);
|
|
652
|
+
return 1;
|
|
653
|
+
}
|
|
558
654
|
const plan = await planRes.json();
|
|
559
655
|
const versions = plan.versions ?? [];
|
|
560
656
|
if (values.json) {
|
|
@@ -574,7 +670,9 @@ async function planVersions(args) {
|
|
|
574
670
|
}
|
|
575
671
|
/** Locate which plan owns a given comment id (comment ids are globally unique). */
|
|
576
672
|
async function findCommentPlan(base, commentId) {
|
|
577
|
-
|
|
673
|
+
const res = await tryApiFetch(`${base}/api/plans`);
|
|
674
|
+
if (!res?.ok) return null;
|
|
675
|
+
return (await res.json()).find((p) => (p.comments ?? []).some((c) => c.id === commentId)) ?? null;
|
|
578
676
|
}
|
|
579
677
|
async function planReply(args) {
|
|
580
678
|
const { values, positionals } = parseArgs({
|
|
@@ -597,7 +695,13 @@ async function planReply(args) {
|
|
|
597
695
|
return EXIT_USAGE;
|
|
598
696
|
}
|
|
599
697
|
let body = values.body;
|
|
600
|
-
if (body ===
|
|
698
|
+
if (body === void 0) {
|
|
699
|
+
if (process.stdin.isTTY) {
|
|
700
|
+
console.error("Usage: diffing plan reply <commentId> --body <text> [--model <name>]");
|
|
701
|
+
return EXIT_USAGE;
|
|
702
|
+
}
|
|
703
|
+
body = (await readStdin()).trim();
|
|
704
|
+
} else if (body === "-") body = (await readStdin()).trim();
|
|
601
705
|
if (!body) {
|
|
602
706
|
console.error("A reply body is required (--body <text> or pipe via stdin).");
|
|
603
707
|
return EXIT_USAGE;
|
|
@@ -608,7 +712,7 @@ async function planReply(args) {
|
|
|
608
712
|
console.error(`Plan comment ${commentId} not found.`);
|
|
609
713
|
return EXIT_NOT_FOUND;
|
|
610
714
|
}
|
|
611
|
-
const res = await
|
|
715
|
+
const res = await tryApiFetch(`${base}/api/plans/${plan.id}/comments/${commentId}/replies`, {
|
|
612
716
|
method: "POST",
|
|
613
717
|
headers: { "Content-Type": "application/json" },
|
|
614
718
|
body: JSON.stringify({
|
|
@@ -617,6 +721,7 @@ async function planReply(args) {
|
|
|
617
721
|
model: values.model
|
|
618
722
|
})
|
|
619
723
|
});
|
|
724
|
+
if (!res) return EXIT_NO_SERVER;
|
|
620
725
|
if (!res.ok) {
|
|
621
726
|
console.error(`Failed to reply: HTTP ${res.status}`);
|
|
622
727
|
return 1;
|
|
@@ -641,11 +746,12 @@ async function planResolve(args) {
|
|
|
641
746
|
console.error(`Plan comment ${commentId} not found.`);
|
|
642
747
|
return EXIT_NOT_FOUND;
|
|
643
748
|
}
|
|
644
|
-
const res = await
|
|
749
|
+
const res = await tryApiFetch(`${base}/api/plans/${plan.id}/comments/${commentId}`, {
|
|
645
750
|
method: "PUT",
|
|
646
751
|
headers: { "Content-Type": "application/json" },
|
|
647
752
|
body: JSON.stringify({ status: "resolved" })
|
|
648
753
|
});
|
|
754
|
+
if (!res) return EXIT_NO_SERVER;
|
|
649
755
|
if (!res.ok) {
|
|
650
756
|
console.error(`Failed to resolve: HTTP ${res.status}`);
|
|
651
757
|
return 1;
|
|
@@ -670,7 +776,7 @@ async function plan(args) {
|
|
|
670
776
|
}
|
|
671
777
|
}
|
|
672
778
|
async function doctor() {
|
|
673
|
-
const { runDoctor, formatDoctorReport } = await import("./doctor-
|
|
779
|
+
const { runDoctor, formatDoctorReport } = await import("./doctor-Bz9VHuBI.mjs");
|
|
674
780
|
const report = await runDoctor({
|
|
675
781
|
cwd: process.cwd(),
|
|
676
782
|
cliImportMetaUrl: import.meta.url
|
|
@@ -679,16 +785,20 @@ async function doctor() {
|
|
|
679
785
|
return report.ok ? EXIT_OK : 1;
|
|
680
786
|
}
|
|
681
787
|
async function completion(args) {
|
|
682
|
-
|
|
683
|
-
if (!shell || args.includes("--help") || args.includes("-h")) {
|
|
788
|
+
if (args.includes("--help") || args.includes("-h")) {
|
|
684
789
|
console.error("Usage: diffing completion <bash|zsh|fish>");
|
|
685
790
|
console.error(" # Install examples:");
|
|
686
791
|
console.error(" # diffing completion bash >> ~/.bashrc");
|
|
687
792
|
console.error(" # diffing completion zsh > ~/.zfunc/_diffing");
|
|
688
793
|
console.error(" # diffing completion fish > ~/.config/fish/completions/diffing.fish");
|
|
794
|
+
return EXIT_OK;
|
|
795
|
+
}
|
|
796
|
+
const shell = args[0];
|
|
797
|
+
if (!shell) {
|
|
798
|
+
console.error("Usage: diffing completion <bash|zsh|fish>");
|
|
689
799
|
return EXIT_USAGE;
|
|
690
800
|
}
|
|
691
|
-
const { completionFor } = await import("./completions-
|
|
801
|
+
const { completionFor } = await import("./completions-DvyV49HY.mjs");
|
|
692
802
|
const script = completionFor(shell);
|
|
693
803
|
if (!script) {
|
|
694
804
|
console.error(`Unknown shell: ${shell}. Use bash, zsh, or fish.`);
|
|
@@ -788,11 +898,12 @@ Add --pretty for indented JSON. Compact JSON is the token-efficient default.`);
|
|
|
788
898
|
return EXIT_USAGE;
|
|
789
899
|
}
|
|
790
900
|
const base = baseUrl();
|
|
901
|
+
const queryString = params.toString();
|
|
791
902
|
let response;
|
|
792
903
|
try {
|
|
793
|
-
response = await apiFetch(`${base}${endpoint}${
|
|
904
|
+
response = await apiFetch(`${base}${endpoint}${queryString ? `?${queryString}` : ""}`);
|
|
794
905
|
} catch (error) {
|
|
795
|
-
console.error(`Failed to reach diffing server: ${error
|
|
906
|
+
console.error(`Failed to reach diffing server: ${connectionErrorMessage(error)}`);
|
|
796
907
|
return EXIT_NO_SERVER;
|
|
797
908
|
}
|
|
798
909
|
const body = await response.json().catch(() => ({ error: response.statusText }));
|
|
@@ -804,7 +915,7 @@ Add --pretty for indented JSON. Compact JSON is the token-efficient default.`);
|
|
|
804
915
|
return EXIT_OK;
|
|
805
916
|
}
|
|
806
917
|
async function progress(args) {
|
|
807
|
-
const { values } = parseArgs({
|
|
918
|
+
const { values, positionals } = parseArgs({
|
|
808
919
|
args,
|
|
809
920
|
options: {
|
|
810
921
|
message: {
|
|
@@ -818,12 +929,12 @@ async function progress(args) {
|
|
|
818
929
|
},
|
|
819
930
|
allowPositionals: true
|
|
820
931
|
});
|
|
821
|
-
const message = values.message ||
|
|
932
|
+
const message = values.message || positionals[0] || "";
|
|
822
933
|
if (!message) {
|
|
823
934
|
console.error("Usage: diffing progress --message \"Working on comment…\" [--model M] [--pct N]");
|
|
824
935
|
return EXIT_USAGE;
|
|
825
936
|
}
|
|
826
|
-
const res = await
|
|
937
|
+
const res = await tryApiFetch(`${baseUrl()}/api/agent/progress`, {
|
|
827
938
|
method: "POST",
|
|
828
939
|
headers: { "Content-Type": "application/json" },
|
|
829
940
|
body: JSON.stringify({
|
|
@@ -834,6 +945,7 @@ async function progress(args) {
|
|
|
834
945
|
pct: values.pct != null ? Number(values.pct) : void 0
|
|
835
946
|
})
|
|
836
947
|
});
|
|
948
|
+
if (!res) return EXIT_NO_SERVER;
|
|
837
949
|
if (!res.ok) {
|
|
838
950
|
const err = await res.json().catch(() => ({}));
|
|
839
951
|
console.error(err.error ?? res.statusText);
|
|
@@ -852,10 +964,10 @@ async function runSubcommand(name, args) {
|
|
|
852
964
|
case "url": return url();
|
|
853
965
|
case "plan": return plan(args);
|
|
854
966
|
case "update":
|
|
855
|
-
const { runUpdateCommand } = await import("./update-check-
|
|
967
|
+
const { runUpdateCommand } = await import("./update-check-BUfh4Y6c.mjs");
|
|
856
968
|
return runUpdateCommand();
|
|
857
969
|
case "gh":
|
|
858
|
-
const { runGhSubcommand } = await import("./cli-gh-
|
|
970
|
+
const { runGhSubcommand } = await import("./cli-gh-DI69gJGo.mjs");
|
|
859
971
|
return runGhSubcommand(args);
|
|
860
972
|
case "doctor": return doctor();
|
|
861
973
|
case "completion": return completion(args);
|
|
@@ -863,7 +975,7 @@ async function runSubcommand(name, args) {
|
|
|
863
975
|
case "inspect": return inspect(args);
|
|
864
976
|
case "mode": return mode(args);
|
|
865
977
|
case "sessions":
|
|
866
|
-
const { runSessionsCommand } = await import("./session-manager-
|
|
978
|
+
const { runSessionsCommand } = await import("./session-manager-BKSZQqDJ.mjs");
|
|
867
979
|
return runSessionsCommand(args);
|
|
868
980
|
default:
|
|
869
981
|
console.error(`Unknown subcommand: ${name}`);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as formatComments } from "./comment-format-B85NHZnG.mjs";
|
|
2
|
-
import { u as resolveActiveServerLock } from "./server-lock-
|
|
2
|
+
import { h as SESSION_TOKEN_HEADER, u as resolveActiveServerLock } from "./server-lock-BNI8FKV1.mjs";
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
//#region src/cli-gh.ts
|
|
5
5
|
/**
|
|
@@ -20,16 +20,27 @@ const EXIT_OK = 0;
|
|
|
20
20
|
const EXIT_NO_SERVER = 3;
|
|
21
21
|
const EXIT_NOT_FOUND = 4;
|
|
22
22
|
const EXIT_USAGE = 5;
|
|
23
|
+
let activeAuthToken;
|
|
23
24
|
function baseUrl() {
|
|
24
25
|
const lock = resolveActiveServerLock();
|
|
25
26
|
if (!lock) {
|
|
26
27
|
console.error("No diffing server running for this repo. Start one with `diffing \"gh pr <ref>\"`.");
|
|
27
28
|
process.exit(EXIT_NO_SERVER);
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
+
const host = lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host;
|
|
31
|
+
activeAuthToken = lock.authToken;
|
|
32
|
+
return `http://${host}:${lock.port}`;
|
|
33
|
+
}
|
|
34
|
+
function apiFetch(input, init = {}) {
|
|
35
|
+
const headers = new Headers(init.headers);
|
|
36
|
+
if (activeAuthToken) headers.set(SESSION_TOKEN_HEADER, activeAuthToken);
|
|
37
|
+
return fetch(input, {
|
|
38
|
+
...init,
|
|
39
|
+
headers
|
|
40
|
+
});
|
|
30
41
|
}
|
|
31
42
|
async function fetchJson(path) {
|
|
32
|
-
const res = await
|
|
43
|
+
const res = await apiFetch(`${baseUrl()}${path}`);
|
|
33
44
|
if (res.status === 404) return {
|
|
34
45
|
ok: false,
|
|
35
46
|
status: 404,
|
|
@@ -78,14 +89,14 @@ async function ghOverview(args) {
|
|
|
78
89
|
return EXIT_OK;
|
|
79
90
|
}
|
|
80
91
|
async function ghStatus() {
|
|
81
|
-
const overview = await
|
|
92
|
+
const overview = await apiFetch(`${baseUrl()}/api/gh/overview`);
|
|
82
93
|
if (overview.ok) {
|
|
83
94
|
const session = await overview.json();
|
|
84
95
|
const submitted = session.submittedAt ? `submitted ${new Date(session.submittedAt).toISOString()}` : "not submitted";
|
|
85
96
|
console.log(`PR #${session.pullNumber} ${session.owner}/${session.repo} [${session.headSha.slice(0, 7)}] — ${session.counts.localDrafts} local draft(s), ${session.counts.unresolvedThreads} unresolved thread(s) — ${submitted}`);
|
|
86
97
|
return EXIT_OK;
|
|
87
98
|
}
|
|
88
|
-
const res = await
|
|
99
|
+
const res = await apiFetch(`${baseUrl()}/api/gh/session`);
|
|
89
100
|
if (res.status === 404) {
|
|
90
101
|
console.error("No active PR session. Start one with `diffing \"gh pr <ref>\"`.");
|
|
91
102
|
return EXIT_NOT_FOUND;
|
|
@@ -138,7 +149,7 @@ async function ghThreads(args) {
|
|
|
138
149
|
return EXIT_USAGE;
|
|
139
150
|
}
|
|
140
151
|
params.set("format", format);
|
|
141
|
-
const res = await
|
|
152
|
+
const res = await apiFetch(`${baseUrl()}/api/gh/threads?${params}`);
|
|
142
153
|
if (res.status === 404) {
|
|
143
154
|
console.error("No active PR session.");
|
|
144
155
|
return EXIT_NOT_FOUND;
|
|
@@ -181,7 +192,7 @@ async function ghReviews(args) {
|
|
|
181
192
|
return EXIT_USAGE;
|
|
182
193
|
}
|
|
183
194
|
params.set("format", format);
|
|
184
|
-
const res = await
|
|
195
|
+
const res = await apiFetch(`${baseUrl()}/api/gh/reviews?${params}`);
|
|
185
196
|
if (res.status === 404) {
|
|
186
197
|
console.error("No active PR session.");
|
|
187
198
|
return EXIT_NOT_FOUND;
|
|
@@ -210,8 +221,8 @@ async function ghPrFetch(args) {
|
|
|
210
221
|
return EXIT_USAGE;
|
|
211
222
|
}
|
|
212
223
|
const base = baseUrl();
|
|
213
|
-
let res = await
|
|
214
|
-
if (res.status === 404) res = await
|
|
224
|
+
let res = await apiFetch(`${base}/api/gh/pr/refresh`, { method: "POST" });
|
|
225
|
+
if (res.status === 404) res = await apiFetch(`${base}/api/gh/pr/init`, {
|
|
215
226
|
method: "POST",
|
|
216
227
|
headers: { "Content-Type": "application/json" },
|
|
217
228
|
body: JSON.stringify({ ref })
|
|
@@ -221,22 +232,21 @@ async function ghPrFetch(args) {
|
|
|
221
232
|
console.error(`Failed to fetch PR: ${err.error ?? res.statusText}`);
|
|
222
233
|
return 1;
|
|
223
234
|
}
|
|
224
|
-
const overviewRes = await
|
|
235
|
+
const overviewRes = await apiFetch(`${base}/api/gh/overview`);
|
|
225
236
|
if (overviewRes.ok) {
|
|
226
237
|
const result = await overviewRes.json();
|
|
227
238
|
if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
228
239
|
else console.log(`${result.owner}/${result.repo}#${result.pullNumber} ${result.url}`);
|
|
229
240
|
return EXIT_OK;
|
|
230
241
|
}
|
|
231
|
-
const sessionRes = await
|
|
242
|
+
const sessionRes = await apiFetch(`${base}/api/gh/session`);
|
|
232
243
|
const result = sessionRes.ok ? await sessionRes.json() : await res.json();
|
|
233
244
|
if (values.json) process.stdout.write(JSON.stringify(result, null, 2) + "\n");
|
|
234
245
|
else console.log(`${result.owner}/${result.repo}#${result.pullNumber} ${result.url}`);
|
|
235
246
|
return EXIT_OK;
|
|
236
247
|
}
|
|
237
248
|
async function ghPrListComments() {
|
|
238
|
-
const
|
|
239
|
-
const res = await fetch(`${base}/api/gh/pr-session/comments`);
|
|
249
|
+
const res = await apiFetch(`${baseUrl()}/api/gh/pr-session/comments`);
|
|
240
250
|
if (res.status === 404) {
|
|
241
251
|
console.error("No active PR session.");
|
|
242
252
|
return EXIT_NOT_FOUND;
|
|
@@ -273,7 +283,7 @@ async function ghPrReview(args) {
|
|
|
273
283
|
body: values.body ?? "",
|
|
274
284
|
dryRun: values["dry-run"] === true
|
|
275
285
|
};
|
|
276
|
-
const res = await
|
|
286
|
+
const res = await apiFetch(`${base}/api/gh/submit`, {
|
|
277
287
|
method: "POST",
|
|
278
288
|
headers: { "Content-Type": "application/json" },
|
|
279
289
|
body: JSON.stringify(payload)
|