diffing 0.3.0 → 0.4.1
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 +11 -2
- package/dist/cli-agent-B4hU6Xay.mjs +499 -0
- package/dist/cli-agent-B_PHd635.mjs +499 -0
- package/dist/cli-gh-abs-IJrz.mjs +147 -0
- package/dist/cli.mjs +204 -58
- package/dist/client/assets/{angular-html-DbbrJavS.js → angular-html-DIKVmS-w.js} +1 -1
- package/dist/client/assets/{angular-ts-tCrxb1ht.js → angular-ts-DK13mfBQ.js} +1 -1
- package/dist/client/assets/{apl-DawII0w7.js → apl-NVZUxqwo.js} +1 -1
- package/dist/client/assets/{arc-DIRV7ZXr.js → arc-kijUuucY.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-3IoH78OV.js → architectureDiagram-3BPJPVTR-Dup-CzBS.js} +1 -1
- package/dist/client/assets/{astro-DIyGTFXc.js → astro-RPdCumat.js} +1 -1
- package/dist/client/assets/{blade-CuF4Z1mP.js → blade-_ubz_KMD.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-CFxPndC0.js → blockDiagram-GPEHLZMM-Cl0-G1MY.js} +1 -1
- package/dist/client/assets/{c-DUrjo9T5.js → c-IEKcSTtW.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-CGMBnkiv.js → c4Diagram-AAUBKEIU-C3T6FV-K.js} +1 -1
- package/dist/client/assets/channel-CpWSvbvQ.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-CJMBLaXy.js → chunk-2J33WTMH-B5MFxFjX.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-C9HQWVLl.js → chunk-3OPIFGDE-DWxCOZgI.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-Qqg72GQd.js → chunk-4BX2VUAB-DWdovlBC.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-DZF8brTR.js → chunk-55IACEB6-CFSaZijP.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-BflVFV5z.js → chunk-5ZQYHXKU-BH_cLkIj.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-COn6BRLY.js → chunk-727SXJPM-BbsJC2PT.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CNOjODUR.js → chunk-AQP2D5EJ-tFAP6fC1.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-PQX4ASCI.js → chunk-BSJP7CBP-BGuhsdwy.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-BfmUvL-L.js → chunk-CSCIHK7Q-DXSJWhsY.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DorfwLnQ.js → chunk-FMBD7UC4-6vBylg_I.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-CXY93mId.js → chunk-KSCS5N6A-C7iBFsUg.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-BjMrSVmH.js → chunk-L5ZTLDWV-CRU3nvaK.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-q8jj6Nyb.js → chunk-LZXEDZCA-6ppA-_4h.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-BRRQbYHl.js → chunk-ND2GUHAM-D1cTmgHe.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-Czt1qHrO.js → chunk-NZK2D7GU-CpUab6v7.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-DEopURak.js → chunk-O5CBEL6O-cDxBycWe.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-HhMIifwl.js +1 -0
- package/dist/client/assets/chunk-WU5MYG2G-CvIzXEms.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-DocCoKUT.js → chunk-XPW4576I-CI9GEEdy.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DFu-dNVy.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-D7Xcgo6q.js +1 -0
- package/dist/client/assets/{cobol-BylylR2x.js → cobol-BVhbHJgp.js} +1 -1
- package/dist/client/assets/{coffee-DCKfk8xx.js → coffee-gY6asS_B.js} +1 -1
- package/dist/client/assets/{cose-bilkent-S5V4N54A-Cm0BD5CS.js → cose-bilkent-S5V4N54A-BOs7zxZa.js} +1 -1
- package/dist/client/assets/{cpp-CfKCIrGK.js → cpp-el3R6exS.js} +1 -1
- package/dist/client/assets/{crystal-v-9RIu3l.js → crystal-D2_0btIo.js} +1 -1
- package/dist/client/assets/{css-XjlXeGmZ.js → css-DtPe7dg4.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-kqgFUaF1.js → dagre-BM42HDAG-CR_0cBOz.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-B3hBvGUc.js → diagram-2AECGRRQ-D9um0wp2.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-r8zU8C-Y.js → diagram-5GNKFQAL-Dx0TEfBJ.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-CDWD5zkZ.js → diagram-KO2AKTUF-DjBHOuUD.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-CRRfS6RD.js → diagram-LMA3HP47-CK2MO5Gx.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-ChBS6E-K.js → diagram-OG6HWLK6-CANQancN.js} +1 -1
- package/dist/client/assets/{dist-DUTeKbN7.js → dist-DGlwcsQQ.js} +1 -1
- package/dist/client/assets/{edge-Cwh953i8.js → edge-Ch_PYBsB.js} +1 -1
- package/dist/client/assets/{elixir-C4MgLzTj.js → elixir-DEJrJATq.js} +1 -1
- package/dist/client/assets/{elm-CFBu8r7i.js → elm-Brlko4-d.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-_03Fb9RH.js → erDiagram-TEJ5UH35-Dnfrs6yk.js} +1 -1
- package/dist/client/assets/{erb-CrCna7R1.js → erb-DQPphNua.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-D9pSaH_8.js → flowDiagram-I6XJVG4X-BNMdFtjG.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DKBfXY9D.js → ganttDiagram-6RSMTGT7-X-fPXz_A.js} +1 -1
- package/dist/client/assets/{git-rebase-CExLk2dD.js → git-rebase-BpS915SI.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-BPQ2kpJA.js → gitGraphDiagram-PVQCEYII-CRN_dRXM.js} +1 -1
- package/dist/client/assets/{glimmer-js-wjBSKaMu.js → glimmer-js-DZDngVuD.js} +1 -1
- package/dist/client/assets/{glimmer-ts-CyjMXDgZ.js → glimmer-ts-DKNjJvyp.js} +1 -1
- package/dist/client/assets/{glsl-CWOoN8or.js → glsl-C-Y1tHoU.js} +1 -1
- package/dist/client/assets/{graphql-DI5CB58U.js → graphql-DYVBNazO.js} +1 -1
- package/dist/client/assets/{hack-Ct_Cm7Pr.js → hack-DewKAtLe.js} +1 -1
- package/dist/client/assets/{haml-DzAjli8d.js → haml-CIA_AeXu.js} +1 -1
- package/dist/client/assets/{handlebars-BfJB0RYx.js → handlebars-Bade6JXX.js} +1 -1
- package/dist/client/assets/{html-CK8auhK8.js → html-C4hhbuGp.js} +1 -1
- package/dist/client/assets/{html-derivative-B7VntYnF.js → html-derivative-BXfztBtv.js} +1 -1
- package/dist/client/assets/{http-_Zy71Sv3.js → http-Cq90-CTl.js} +1 -1
- package/dist/client/assets/{hurl-VbL4I95z.js → hurl-DklQHYoa.js} +1 -1
- package/dist/client/assets/index-CMyunQt6.css +1 -0
- package/dist/client/assets/{index-Dv9jPmOc.js → index-j9gqGQit.js} +97 -96
- package/dist/client/assets/{infoDiagram-5YYISTIA-B5RN-4Ke.js → infoDiagram-5YYISTIA-Ht-AcvP4.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-DpbSX3Zy.js → ishikawaDiagram-YF4QCWOH-k_l70iFb.js} +1 -1
- package/dist/client/assets/{java-0CC2DnK9.js → java-BMUwLm1h.js} +1 -1
- package/dist/client/assets/{javascript-DKSTP7rz.js → javascript-B8nPCUVp.js} +1 -1
- package/dist/client/assets/{jinja-DoGBHNJ6.js → jinja-CkxiRcB3.js} +1 -1
- package/dist/client/assets/{jison-Bnl3lPA2.js → jison-CFnN5uQs.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-B_X4_qPO.js → journeyDiagram-JHISSGLW-C98PUC9Y.js} +1 -1
- package/dist/client/assets/{json-BQ3Ddj6g.js → json-B7HNnjIx.js} +1 -1
- package/dist/client/assets/{jsx-C_aFDuFZ.js → jsx-BfVPuW3i.js} +1 -1
- package/dist/client/assets/{julia-nIjp5yMR.js → julia-Bj0ETGjT.js} +1 -1
- package/dist/client/assets/{just-zc4yJ46n.js → just-CqIe_c9k.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-BSs4C5DW.js → kanban-definition-UN3LZRKU-BE-uvH7w.js} +1 -1
- package/dist/client/assets/{latex-BszBC80j.js → latex-Cvy8E64e.js} +1 -1
- package/dist/client/assets/{line-C9HWVwPi.js → line-BpooNUgm.js} +1 -1
- package/dist/client/assets/{linear-DatJfpKY.js → linear-CM6ZoyCp.js} +1 -1
- package/dist/client/assets/{liquid-DglQpTge.js → liquid-x09l8QqE.js} +1 -1
- package/dist/client/assets/{lua-BcbliFeR.js → lua-BSlDLjt5.js} +1 -1
- package/dist/client/assets/{marko-BPm4M8j-.js → marko-CoNMQlTn.js} +1 -1
- package/dist/client/assets/{mdc-BNUj07UF.js → mdc-BSzVESPu.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BVEKlqQr.js → mermaid-parser.core-BDXJMxHu.js} +1 -1
- package/dist/client/assets/{mermaid.core-DVis21V_.js → mermaid.core-Dw-_vXTc.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-Cuo7KewF.js → mindmap-definition-RKZ34NQL-BTxGT8rM.js} +1 -1
- package/dist/client/assets/{nginx-CSSJwkd6.js → nginx-CBhJTj0i.js} +1 -1
- package/dist/client/assets/{nim-nQAskwTR.js → nim-CtHbOBlO.js} +1 -1
- package/dist/client/assets/{perl-CtH8xYH6.js → perl-DLMzG3tu.js} +1 -1
- package/dist/client/assets/{php-Dcc3T2PH.js → php-KomVR3Hz.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BfpvCRmo.js → pieDiagram-4H26LBE5-BBUObAJW.js} +1 -1
- package/dist/client/assets/{pug-BCLaymlV.js → pug-T4SRLx8P.js} +1 -1
- package/dist/client/assets/{qml-BpKydcOi.js → qml-DJdSRUmU.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-CJY6un0-.js → quadrantDiagram-W4KKPZXB-B7vvauZv.js} +1 -1
- package/dist/client/assets/{r-BzCB9dpd.js → r-CwuTg9lK.js} +1 -1
- package/dist/client/assets/{razor-BWmujqiQ.js → razor-Ch4dgsGY.js} +1 -1
- package/dist/client/assets/{regexp-urCI3YiZ.js → regexp-D2GTwJE0.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-DIHWguS0.js → requirementDiagram-4Y6WPE33-DpcNiR3Y.js} +1 -1
- package/dist/client/assets/{rst-YTDC9H6u.js → rst-D78f0DyR.js} +1 -1
- package/dist/client/assets/{ruby-v1IXQAFZ.js → ruby-BUcw6ITs.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DJRPEO_F.js → sankeyDiagram-5OEKKPKP-ChzSQD2O.js} +1 -1
- package/dist/client/assets/{sas-KDUG3BSk.js → sas-DoT2JDsj.js} +1 -1
- package/dist/client/assets/{scss-pLIGFpjD.js → scss-B6G_d-6b.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-DX0jVCOU.js → sequenceDiagram-3UESZ5HK-CzkdL8s7.js} +1 -1
- package/dist/client/assets/{shellscript-B5ZTyEsK.js → shellscript-DI252Bga.js} +1 -1
- package/dist/client/assets/{shellsession-DVK3bw4p.js → shellsession-BuO_s8FQ.js} +1 -1
- package/dist/client/assets/{soy-BXgyj2-T.js → soy-DZTZJTEE.js} +1 -1
- package/dist/client/assets/{sql-G2vZCmw6.js → sql-C4isoJr_.js} +1 -1
- package/dist/client/assets/{src-D9zkqEEX.js → src-BMvz5HE8.js} +1 -1
- package/dist/client/assets/{stata-C4mEnygx.js → stata-Dhu6qITh.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-AMtMxKgQ.js → stateDiagram-AJRCARHV-DvYcrdap.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-D5igY81I.js +1 -0
- package/dist/client/assets/{surrealql-Bf8gsTcP.js → surrealql-CSDpq5j3.js} +1 -1
- package/dist/client/assets/{svelte-C1oIyl9t.js → svelte-C4ITAvxr.js} +1 -1
- package/dist/client/assets/{templ-PJcWUuTF.js → templ-BTgKA9-7.js} +1 -1
- package/dist/client/assets/{tex-B7Fnujsi.js → tex-Dg4N9ndP.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-BZJSqcAg.js → timeline-definition-PNZ67QCA-Djt5Lwk2.js} +1 -1
- package/dist/client/assets/{ts-tags-CAAsFnUt.js → ts-tags-BufYnYos.js} +1 -1
- package/dist/client/assets/{tsx-DAKyTsWW.js → tsx-DmkFP0sw.js} +1 -1
- package/dist/client/assets/{twig-Bd4dieZF.js → twig-BJv_IWYK.js} +1 -1
- package/dist/client/assets/{typescript-8myByDGd.js → typescript-BKp05Qme.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-CMjBZNs2.js → vennDiagram-CIIHVFJN-DDVADTIa.js} +1 -1
- package/dist/client/assets/{vue-fBA2B-QU.js → vue-BsHXCXzh.js} +1 -1
- package/dist/client/assets/{vue-html-DEZECpsR.js → vue-html-CCsH-lmo.js} +1 -1
- package/dist/client/assets/{vue-vine-B_gG939R.js → vue-vine-B5P1JXxo.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-qeHmPLyL.js → wardleyDiagram-YWT4CUSO-yeVKWvtX.js} +1 -1
- package/dist/client/assets/{xml-DbXNss3s.js → xml-CFkhYff0.js} +1 -1
- package/dist/client/assets/{xsl-B7_dgqqc.js → xsl-Dc5XRzm6.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-NN2Et7YL.js → xychartDiagram-2RQKCTM6--8Ik-9v0.js} +1 -1
- package/dist/client/assets/{yaml-DSyIApdJ.js → yaml-BTCCxCxi.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/mcp-DNZQvKKF.mjs +298 -0
- package/dist/mcp-DO4zfNZX.mjs +298 -0
- package/dist/plan-format-DVnF8xrq.mjs +126 -0
- package/dist/plan-format-mSDtsPcC.mjs +132 -0
- package/dist/server-lock-D73NKKbn.mjs +842 -0
- package/package.json +1 -1
- package/dist/client/assets/channel-D5AdjEWX.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-BE917fn9.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-DdoWnPla.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CxjhKO7s.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CSScAAQ4.js +0 -1
- package/dist/client/assets/index-C3p7VKOX.css +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-C89CM-_4.js +0 -1
package/README.md
CHANGED
|
@@ -121,6 +121,7 @@ Full keyboard-driven navigation with vim-like motions and a modal status bar:
|
|
|
121
121
|
| `n` | Toggle line numbers |
|
|
122
122
|
| `i` | Cycle diff indicators |
|
|
123
123
|
| `I` | Cycle inline diff type |
|
|
124
|
+
| `Cmd+Shift+P` | Toggle preview mode in comments |
|
|
124
125
|
|
|
125
126
|
### File Navigation & UI
|
|
126
127
|
| Key | Action |
|
|
@@ -268,7 +269,8 @@ diffing url # Retrieve the active server base URL
|
|
|
268
269
|
diffing plan submit <file> [--title T] [--model M] [--id <id>] [--wait] # Submit/resubmit a plan; prints its id
|
|
269
270
|
diffing plan await [--timeout N] # Block until the human approves/rejects/requests-changes; outputs the verdict XML
|
|
270
271
|
diffing plan list [--json] # List submitted plans with their verdicts
|
|
271
|
-
diffing plan show [<id>] [--json]
|
|
272
|
+
diffing plan show [<id>] [--json] [--version N] # Show one plan as <plan-review> XML (latest if omitted; use --version to read a historical body)
|
|
273
|
+
diffing plan versions <id> [--json] # List every submitted version of a plan, oldest-first (current marked with `*`)
|
|
272
274
|
diffing plan reply <commentId> --body "..." # Reply to an inline plan comment
|
|
273
275
|
diffing plan resolve <commentId> # Mark a plan comment resolved
|
|
274
276
|
```
|
|
@@ -286,7 +288,7 @@ If your agent supports MCP (such as Cursor, Claude Desktop, or Gemini), configur
|
|
|
286
288
|
}
|
|
287
289
|
}
|
|
288
290
|
```
|
|
289
|
-
Exposes tools directly to your agent for both review flows — diff review: `await_review`, `list_comments`, `reply_to_comment`, `resolve_comment`; and plan review: `submit_plan`, `await_plan_review`, `list_plans`, `get_plan`, `reply_to_plan_comment`, `resolve_plan_comment`.
|
|
291
|
+
Exposes tools directly to your agent for both review flows — diff review: `await_review`, `list_comments`, `reply_to_comment`, `resolve_comment`; and plan review: `submit_plan`, `await_plan_review`, `list_plans`, `get_plan`, `get_plan_versions`, `get_plan_version`, `reply_to_plan_comment`, `resolve_plan_comment`.
|
|
290
292
|
|
|
291
293
|
### C. Agent Skills
|
|
292
294
|
You can install diffing skills directly into your AI coding assistant:
|
|
@@ -336,6 +338,13 @@ releases" handoff, applied *before* any code is written.
|
|
|
336
338
|
- **Three-way verdict** — Approve / Request changes / Reject, GitHub-style, with
|
|
337
339
|
an optional overall comment. Resubmitting a revised plan (same id) bumps the
|
|
338
340
|
version and re-opens it for review.
|
|
341
|
+
- **Browse plan versions** — every submitted body is kept on disk, oldest-first.
|
|
342
|
+
A version dropdown next to the `v{n}` chip switches the viewer to any past
|
|
343
|
+
version; comments are filtered to those anchored to the version you're
|
|
344
|
+
reading; a "viewing v{N} of v{M}" banner makes the historical context obvious.
|
|
345
|
+
Available from the CLI (`diffing plan versions <id>`, `diffing plan show <id> --version N`),
|
|
346
|
+
MCP (`get_plan_versions`, `get_plan_version`), and the HTTP API
|
|
347
|
+
(`GET /api/plans/:id/versions`, `GET /api/plans/:id/versions/:n`).
|
|
339
348
|
- **Live "Plans" badge** — the diff toolbar shows a badge counting plans awaiting
|
|
340
349
|
your review, with a green dot when an agent is connected and waiting.
|
|
341
350
|
- **Same channels everywhere** — drive it from the CLI (`diffing plan …`), the
|
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { a as formatComments, n as readServerLock, t as isLockAlive } from "./server-lock-D73NKKbn.mjs";
|
|
2
|
+
import { n as formatPlanReview } from "./plan-format-mSDtsPcC.mjs";
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
//#region src/cli-agent.ts
|
|
6
|
+
/**
|
|
7
|
+
* Agent-facing `diffing` subcommands. These make the user→agent handoff
|
|
8
|
+
* port-agnostic: each resolves the running server via the per-repo lockfile
|
|
9
|
+
* (`server.json`) so any agent with a shell — or a human — can drive the loop
|
|
10
|
+
* without being told a port.
|
|
11
|
+
*
|
|
12
|
+
* diffing await-review block until the human clicks "Send to agent"
|
|
13
|
+
* diffing reply <id> post an agent reply to a comment
|
|
14
|
+
* diffing resolve <id> mark a comment resolved
|
|
15
|
+
* diffing comments dump the current comments (XML or JSON)
|
|
16
|
+
*/
|
|
17
|
+
const EXIT_OK = 0;
|
|
18
|
+
const EXIT_AWAIT_TIMEOUT = 2;
|
|
19
|
+
const EXIT_NO_SERVER = 3;
|
|
20
|
+
const EXIT_NOT_FOUND = 4;
|
|
21
|
+
const EXIT_USAGE = 5;
|
|
22
|
+
/** Resolve the running server's base URL from the lockfile, or exit cleanly. */
|
|
23
|
+
function baseUrl() {
|
|
24
|
+
const lock = readServerLock();
|
|
25
|
+
if (!lock || !isLockAlive(lock)) {
|
|
26
|
+
console.error("No diffing server running for this repo. Start one with `diffing`.");
|
|
27
|
+
process.exit(EXIT_NO_SERVER);
|
|
28
|
+
}
|
|
29
|
+
return `http://${lock.host === "0.0.0.0" || lock.host === "::" ? "127.0.0.1" : lock.host}:${lock.port}`;
|
|
30
|
+
}
|
|
31
|
+
async function readStdin() {
|
|
32
|
+
const chunks = [];
|
|
33
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
34
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
35
|
+
}
|
|
36
|
+
async function awaitReview(args) {
|
|
37
|
+
const { values } = parseArgs({
|
|
38
|
+
args,
|
|
39
|
+
options: {
|
|
40
|
+
timeout: {
|
|
41
|
+
type: "string",
|
|
42
|
+
short: "t"
|
|
43
|
+
},
|
|
44
|
+
since: { type: "string" }
|
|
45
|
+
},
|
|
46
|
+
allowPositionals: false
|
|
47
|
+
});
|
|
48
|
+
const totalBudgetMs = (values.timeout ? Number(values.timeout) : 570) * 1e3;
|
|
49
|
+
const base = baseUrl();
|
|
50
|
+
let sinceRound = 0;
|
|
51
|
+
try {
|
|
52
|
+
sinceRound = (await fetch(`${base}/api/review/status`).then((r) => r.json())).round ?? 0;
|
|
53
|
+
} catch {}
|
|
54
|
+
const deadline = Date.now() + totalBudgetMs;
|
|
55
|
+
while (Date.now() < deadline) {
|
|
56
|
+
let res;
|
|
57
|
+
try {
|
|
58
|
+
res = await fetch(`${base}/api/review/await?timeoutMs=25000&sinceRound=${sinceRound}`, { signal: AbortSignal.timeout(3e4) });
|
|
59
|
+
} catch (err) {
|
|
60
|
+
if (err?.name === "TimeoutError") continue;
|
|
61
|
+
console.error(`Failed to reach diffing server: ${err?.message ?? err}`);
|
|
62
|
+
return EXIT_NO_SERVER;
|
|
63
|
+
}
|
|
64
|
+
const result = await res.json();
|
|
65
|
+
if (result.status === "released") {
|
|
66
|
+
process.stdout.write(result.payload.commentXml + "\n");
|
|
67
|
+
console.error(`DIFFING_REVIEW_ROUND=${result.payload.round}`);
|
|
68
|
+
return EXIT_OK;
|
|
69
|
+
}
|
|
70
|
+
sinceRound = result.round ?? sinceRound;
|
|
71
|
+
}
|
|
72
|
+
console.error("DIFFING_AWAIT_TIMEOUT");
|
|
73
|
+
console.error("No review sent within the timeout. Run `diffing await-review` again to keep waiting.");
|
|
74
|
+
return EXIT_AWAIT_TIMEOUT;
|
|
75
|
+
}
|
|
76
|
+
async function reply(args) {
|
|
77
|
+
const { values, positionals } = parseArgs({
|
|
78
|
+
args,
|
|
79
|
+
options: {
|
|
80
|
+
body: {
|
|
81
|
+
type: "string",
|
|
82
|
+
short: "b"
|
|
83
|
+
},
|
|
84
|
+
model: {
|
|
85
|
+
type: "string",
|
|
86
|
+
short: "m"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
allowPositionals: true
|
|
90
|
+
});
|
|
91
|
+
const commentId = positionals[0];
|
|
92
|
+
if (!commentId) {
|
|
93
|
+
console.error("Usage: diffing reply <commentId> --body <text> [--model <name>]");
|
|
94
|
+
return EXIT_USAGE;
|
|
95
|
+
}
|
|
96
|
+
let body = values.body;
|
|
97
|
+
if (body === "-" || body === void 0) body = (await readStdin()).trim();
|
|
98
|
+
if (!body) {
|
|
99
|
+
console.error("A reply body is required (--body <text> or pipe via stdin).");
|
|
100
|
+
return EXIT_USAGE;
|
|
101
|
+
}
|
|
102
|
+
const res = await fetch(`${baseUrl()}/api/comments/${commentId}/replies`, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: { "Content-Type": "application/json" },
|
|
105
|
+
body: JSON.stringify({
|
|
106
|
+
body,
|
|
107
|
+
role: "agent",
|
|
108
|
+
model: values.model
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
if (res.status === 404) {
|
|
112
|
+
console.error(`Comment ${commentId} not found.`);
|
|
113
|
+
return EXIT_NOT_FOUND;
|
|
114
|
+
}
|
|
115
|
+
if (!res.ok) {
|
|
116
|
+
console.error(`Failed to reply: HTTP ${res.status}`);
|
|
117
|
+
return 1;
|
|
118
|
+
}
|
|
119
|
+
console.error(`Replied to ${commentId}.`);
|
|
120
|
+
return EXIT_OK;
|
|
121
|
+
}
|
|
122
|
+
async function resolve(args) {
|
|
123
|
+
const { positionals } = parseArgs({
|
|
124
|
+
args,
|
|
125
|
+
allowPositionals: true,
|
|
126
|
+
options: {}
|
|
127
|
+
});
|
|
128
|
+
const commentId = positionals[0];
|
|
129
|
+
if (!commentId) {
|
|
130
|
+
console.error("Usage: diffing resolve <commentId>");
|
|
131
|
+
return EXIT_USAGE;
|
|
132
|
+
}
|
|
133
|
+
const res = await fetch(`${baseUrl()}/api/comments/${commentId}`, {
|
|
134
|
+
method: "PUT",
|
|
135
|
+
headers: { "Content-Type": "application/json" },
|
|
136
|
+
body: JSON.stringify({ status: "resolved" })
|
|
137
|
+
});
|
|
138
|
+
if (res.status === 404) {
|
|
139
|
+
console.error(`Comment ${commentId} not found.`);
|
|
140
|
+
return EXIT_NOT_FOUND;
|
|
141
|
+
}
|
|
142
|
+
if (!res.ok) {
|
|
143
|
+
console.error(`Failed to resolve: HTTP ${res.status}`);
|
|
144
|
+
return 1;
|
|
145
|
+
}
|
|
146
|
+
console.error(`Resolved ${commentId}.`);
|
|
147
|
+
return EXIT_OK;
|
|
148
|
+
}
|
|
149
|
+
async function url() {
|
|
150
|
+
process.stdout.write(baseUrl() + "\n");
|
|
151
|
+
return EXIT_OK;
|
|
152
|
+
}
|
|
153
|
+
async function comments(args) {
|
|
154
|
+
const { values } = parseArgs({
|
|
155
|
+
args,
|
|
156
|
+
options: {
|
|
157
|
+
open: { type: "boolean" },
|
|
158
|
+
json: { type: "boolean" }
|
|
159
|
+
},
|
|
160
|
+
allowPositionals: false
|
|
161
|
+
});
|
|
162
|
+
const all = await fetch(`${baseUrl()}/api/comments`).then((r) => r.json());
|
|
163
|
+
const selected = values.open ? all.filter((c) => c.status === "open") : all;
|
|
164
|
+
if (values.json) process.stdout.write(JSON.stringify(selected, null, 2) + "\n");
|
|
165
|
+
else process.stdout.write(formatComments(selected) + "\n");
|
|
166
|
+
return EXIT_OK;
|
|
167
|
+
}
|
|
168
|
+
/** Derive a human title from a plan's first heading or non-empty line. */
|
|
169
|
+
function deriveTitle(body) {
|
|
170
|
+
for (const raw of body.split("\n")) {
|
|
171
|
+
const line = raw.trim();
|
|
172
|
+
if (!line) continue;
|
|
173
|
+
const heading = /^#{1,6}\s+(.*)$/.exec(line);
|
|
174
|
+
return (heading ? heading[1] : line).slice(0, 120);
|
|
175
|
+
}
|
|
176
|
+
return "Untitled plan";
|
|
177
|
+
}
|
|
178
|
+
/** Long-poll the plan-review handoff until a decision arrives or time runs out. */
|
|
179
|
+
async function pollPlanDecision(base, totalBudgetMs, seedSince) {
|
|
180
|
+
let sinceRound = seedSince ?? 0;
|
|
181
|
+
if (seedSince === void 0) try {
|
|
182
|
+
sinceRound = (await fetch(`${base}/api/plan-review/status`).then((r) => r.json())).round ?? 0;
|
|
183
|
+
} catch {}
|
|
184
|
+
const deadline = Date.now() + totalBudgetMs;
|
|
185
|
+
while (Date.now() < deadline) {
|
|
186
|
+
let res;
|
|
187
|
+
try {
|
|
188
|
+
res = await fetch(`${base}/api/plan-review/await?timeoutMs=25000&sinceRound=${sinceRound}`, { signal: AbortSignal.timeout(3e4) });
|
|
189
|
+
} catch (err) {
|
|
190
|
+
if (err?.name === "TimeoutError") continue;
|
|
191
|
+
console.error(`Failed to reach diffing server: ${err?.message ?? err}`);
|
|
192
|
+
return EXIT_NO_SERVER;
|
|
193
|
+
}
|
|
194
|
+
const result = await res.json();
|
|
195
|
+
if (result.status === "released") {
|
|
196
|
+
process.stdout.write(result.payload.reviewXml + "\n");
|
|
197
|
+
console.error(`DIFFING_PLAN_DECISION=${result.payload.decision}`);
|
|
198
|
+
console.error(`DIFFING_PLAN_ROUND=${result.payload.round}`);
|
|
199
|
+
return EXIT_OK;
|
|
200
|
+
}
|
|
201
|
+
sinceRound = result.round ?? sinceRound;
|
|
202
|
+
}
|
|
203
|
+
console.error("DIFFING_PLAN_AWAIT_TIMEOUT");
|
|
204
|
+
console.error("No plan decision within the timeout. Run `diffing plan await` again to keep waiting.");
|
|
205
|
+
return EXIT_AWAIT_TIMEOUT;
|
|
206
|
+
}
|
|
207
|
+
async function planSubmit(args) {
|
|
208
|
+
const { values, positionals } = parseArgs({
|
|
209
|
+
args,
|
|
210
|
+
options: {
|
|
211
|
+
title: { type: "string" },
|
|
212
|
+
source: {
|
|
213
|
+
type: "string",
|
|
214
|
+
short: "s"
|
|
215
|
+
},
|
|
216
|
+
model: {
|
|
217
|
+
type: "string",
|
|
218
|
+
short: "m"
|
|
219
|
+
},
|
|
220
|
+
id: { type: "string" },
|
|
221
|
+
wait: {
|
|
222
|
+
type: "boolean",
|
|
223
|
+
short: "w"
|
|
224
|
+
},
|
|
225
|
+
timeout: {
|
|
226
|
+
type: "string",
|
|
227
|
+
short: "t"
|
|
228
|
+
}
|
|
229
|
+
},
|
|
230
|
+
allowPositionals: true
|
|
231
|
+
});
|
|
232
|
+
const file = positionals[0];
|
|
233
|
+
let body;
|
|
234
|
+
if (!file || file === "-") body = await readStdin();
|
|
235
|
+
else try {
|
|
236
|
+
body = await readFile(file, "utf-8");
|
|
237
|
+
} catch (err) {
|
|
238
|
+
console.error(`Failed to read plan file ${file}: ${err?.message ?? err}`);
|
|
239
|
+
return EXIT_USAGE;
|
|
240
|
+
}
|
|
241
|
+
body = body.replace(/\r\n/g, "\n");
|
|
242
|
+
if (!body.trim()) {
|
|
243
|
+
console.error("A plan body is required (pass a markdown file path or pipe via stdin).");
|
|
244
|
+
return EXIT_USAGE;
|
|
245
|
+
}
|
|
246
|
+
const title = values.title || deriveTitle(body);
|
|
247
|
+
const base = baseUrl();
|
|
248
|
+
let sinceRound = 0;
|
|
249
|
+
if (values.wait) try {
|
|
250
|
+
sinceRound = (await fetch(`${base}/api/plan-review/status`).then((r) => r.json())).round ?? 0;
|
|
251
|
+
} catch {}
|
|
252
|
+
const res = await fetch(`${base}/api/plans`, {
|
|
253
|
+
method: "POST",
|
|
254
|
+
headers: { "Content-Type": "application/json" },
|
|
255
|
+
body: JSON.stringify({
|
|
256
|
+
id: values.id,
|
|
257
|
+
title,
|
|
258
|
+
body,
|
|
259
|
+
source: values.source,
|
|
260
|
+
model: values.model
|
|
261
|
+
})
|
|
262
|
+
});
|
|
263
|
+
if (!res.ok) {
|
|
264
|
+
console.error(`Failed to submit plan: HTTP ${res.status}`);
|
|
265
|
+
return 1;
|
|
266
|
+
}
|
|
267
|
+
const plan = await res.json();
|
|
268
|
+
console.error(`Submitted plan ${plan.id} (v${plan.version}) — review at ${base}/plan/${plan.id}`);
|
|
269
|
+
if (!values.wait) {
|
|
270
|
+
process.stdout.write(plan.id + "\n");
|
|
271
|
+
return EXIT_OK;
|
|
272
|
+
}
|
|
273
|
+
return pollPlanDecision(base, (values.timeout ? Number(values.timeout) : 570) * 1e3, sinceRound);
|
|
274
|
+
}
|
|
275
|
+
async function planAwait(args) {
|
|
276
|
+
const { values } = parseArgs({
|
|
277
|
+
args,
|
|
278
|
+
options: { timeout: {
|
|
279
|
+
type: "string",
|
|
280
|
+
short: "t"
|
|
281
|
+
} },
|
|
282
|
+
allowPositionals: false
|
|
283
|
+
});
|
|
284
|
+
const totalBudgetMs = (values.timeout ? Number(values.timeout) : 570) * 1e3;
|
|
285
|
+
return pollPlanDecision(baseUrl(), totalBudgetMs);
|
|
286
|
+
}
|
|
287
|
+
async function planList(args) {
|
|
288
|
+
const { values } = parseArgs({
|
|
289
|
+
args,
|
|
290
|
+
options: { json: { type: "boolean" } },
|
|
291
|
+
allowPositionals: false
|
|
292
|
+
});
|
|
293
|
+
const all = await fetch(`${baseUrl()}/api/plans`).then((r) => r.json());
|
|
294
|
+
if (values.json) {
|
|
295
|
+
process.stdout.write(JSON.stringify(all, null, 2) + "\n");
|
|
296
|
+
return EXIT_OK;
|
|
297
|
+
}
|
|
298
|
+
if (all.length === 0) {
|
|
299
|
+
console.error("No plans submitted yet.");
|
|
300
|
+
return EXIT_OK;
|
|
301
|
+
}
|
|
302
|
+
for (const p of all) {
|
|
303
|
+
const open = (p.comments ?? []).filter((c) => c.status === "open").length;
|
|
304
|
+
process.stdout.write(`${p.id}\t[${p.decision}]\tv${p.version}\t${open} open comment(s)\t${p.title}\n`);
|
|
305
|
+
}
|
|
306
|
+
return EXIT_OK;
|
|
307
|
+
}
|
|
308
|
+
async function planShow(args) {
|
|
309
|
+
const { values, positionals } = parseArgs({
|
|
310
|
+
args,
|
|
311
|
+
options: {
|
|
312
|
+
json: { type: "boolean" },
|
|
313
|
+
version: { type: "string" }
|
|
314
|
+
},
|
|
315
|
+
allowPositionals: true
|
|
316
|
+
});
|
|
317
|
+
const base = baseUrl();
|
|
318
|
+
let planId = positionals[0];
|
|
319
|
+
if (!planId) {
|
|
320
|
+
const all = await fetch(`${base}/api/plans`).then((r) => r.json());
|
|
321
|
+
if (all.length === 0) {
|
|
322
|
+
console.error("No plans submitted yet.");
|
|
323
|
+
return EXIT_NOT_FOUND;
|
|
324
|
+
}
|
|
325
|
+
planId = all[all.length - 1].id;
|
|
326
|
+
}
|
|
327
|
+
const res = await fetch(`${base}/api/plans/${planId}`);
|
|
328
|
+
if (res.status === 404) {
|
|
329
|
+
console.error(`Plan ${planId} not found.`);
|
|
330
|
+
return EXIT_NOT_FOUND;
|
|
331
|
+
}
|
|
332
|
+
const plan = await res.json();
|
|
333
|
+
const requestedVersion = values.version !== void 0 ? Number(values.version) : void 0;
|
|
334
|
+
if (requestedVersion !== void 0 && (!Number.isFinite(requestedVersion) || requestedVersion < 1)) {
|
|
335
|
+
console.error(`--version must be a positive integer.`);
|
|
336
|
+
return EXIT_USAGE;
|
|
337
|
+
}
|
|
338
|
+
if (requestedVersion !== void 0 && requestedVersion !== plan.version) {
|
|
339
|
+
if (!(plan.versions ?? []).find((v) => v.version === requestedVersion)) {
|
|
340
|
+
console.error(`Version ${requestedVersion} not found for plan ${planId} (current: v${plan.version}).`);
|
|
341
|
+
return EXIT_NOT_FOUND;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (values.json) process.stdout.write(JSON.stringify(plan, null, 2) + "\n");
|
|
345
|
+
else process.stdout.write(formatPlanReview(plan, { viewingVersion: requestedVersion }) + "\n");
|
|
346
|
+
return EXIT_OK;
|
|
347
|
+
}
|
|
348
|
+
async function planVersions(args) {
|
|
349
|
+
const { values, positionals } = parseArgs({
|
|
350
|
+
args,
|
|
351
|
+
options: { json: { type: "boolean" } },
|
|
352
|
+
allowPositionals: true
|
|
353
|
+
});
|
|
354
|
+
const base = baseUrl();
|
|
355
|
+
let planId = positionals[0];
|
|
356
|
+
if (!planId) {
|
|
357
|
+
console.error("Usage: diffing plan versions <id> [--json]");
|
|
358
|
+
return EXIT_USAGE;
|
|
359
|
+
}
|
|
360
|
+
const planRes = await fetch(`${base}/api/plans/${planId}`);
|
|
361
|
+
if (planRes.status === 404) {
|
|
362
|
+
console.error(`Plan ${planId} not found.`);
|
|
363
|
+
return EXIT_NOT_FOUND;
|
|
364
|
+
}
|
|
365
|
+
const plan = await planRes.json();
|
|
366
|
+
const versions = plan.versions ?? [];
|
|
367
|
+
if (values.json) {
|
|
368
|
+
process.stdout.write(JSON.stringify(versions, null, 2) + "\n");
|
|
369
|
+
return EXIT_OK;
|
|
370
|
+
}
|
|
371
|
+
if (versions.length === 0) {
|
|
372
|
+
console.error("This plan has no recorded versions.");
|
|
373
|
+
return EXIT_OK;
|
|
374
|
+
}
|
|
375
|
+
for (const v of versions) {
|
|
376
|
+
const marker = v.version === plan.version ? "*" : " ";
|
|
377
|
+
const date = new Date(v.createdAt).toISOString().slice(0, 16).replace("T", " ");
|
|
378
|
+
process.stdout.write(`${marker} v${v.version}\t${date}\t${v.title}\n`);
|
|
379
|
+
}
|
|
380
|
+
return EXIT_OK;
|
|
381
|
+
}
|
|
382
|
+
/** Locate which plan owns a given comment id (comment ids are globally unique). */
|
|
383
|
+
async function findCommentPlan(base, commentId) {
|
|
384
|
+
return (await fetch(`${base}/api/plans`).then((r) => r.json())).find((p) => (p.comments ?? []).some((c) => c.id === commentId)) ?? null;
|
|
385
|
+
}
|
|
386
|
+
async function planReply(args) {
|
|
387
|
+
const { values, positionals } = parseArgs({
|
|
388
|
+
args,
|
|
389
|
+
options: {
|
|
390
|
+
body: {
|
|
391
|
+
type: "string",
|
|
392
|
+
short: "b"
|
|
393
|
+
},
|
|
394
|
+
model: {
|
|
395
|
+
type: "string",
|
|
396
|
+
short: "m"
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
allowPositionals: true
|
|
400
|
+
});
|
|
401
|
+
const commentId = positionals[0];
|
|
402
|
+
if (!commentId) {
|
|
403
|
+
console.error("Usage: diffing plan reply <commentId> --body <text> [--model <name>]");
|
|
404
|
+
return EXIT_USAGE;
|
|
405
|
+
}
|
|
406
|
+
let body = values.body;
|
|
407
|
+
if (body === "-" || body === void 0) body = (await readStdin()).trim();
|
|
408
|
+
if (!body) {
|
|
409
|
+
console.error("A reply body is required (--body <text> or pipe via stdin).");
|
|
410
|
+
return EXIT_USAGE;
|
|
411
|
+
}
|
|
412
|
+
const base = baseUrl();
|
|
413
|
+
const plan = await findCommentPlan(base, commentId);
|
|
414
|
+
if (!plan) {
|
|
415
|
+
console.error(`Plan comment ${commentId} not found.`);
|
|
416
|
+
return EXIT_NOT_FOUND;
|
|
417
|
+
}
|
|
418
|
+
const res = await fetch(`${base}/api/plans/${plan.id}/comments/${commentId}/replies`, {
|
|
419
|
+
method: "POST",
|
|
420
|
+
headers: { "Content-Type": "application/json" },
|
|
421
|
+
body: JSON.stringify({
|
|
422
|
+
body,
|
|
423
|
+
role: "agent",
|
|
424
|
+
model: values.model
|
|
425
|
+
})
|
|
426
|
+
});
|
|
427
|
+
if (!res.ok) {
|
|
428
|
+
console.error(`Failed to reply: HTTP ${res.status}`);
|
|
429
|
+
return 1;
|
|
430
|
+
}
|
|
431
|
+
console.error(`Replied to plan comment ${commentId}.`);
|
|
432
|
+
return EXIT_OK;
|
|
433
|
+
}
|
|
434
|
+
async function planResolve(args) {
|
|
435
|
+
const { positionals } = parseArgs({
|
|
436
|
+
args,
|
|
437
|
+
allowPositionals: true,
|
|
438
|
+
options: {}
|
|
439
|
+
});
|
|
440
|
+
const commentId = positionals[0];
|
|
441
|
+
if (!commentId) {
|
|
442
|
+
console.error("Usage: diffing plan resolve <commentId>");
|
|
443
|
+
return EXIT_USAGE;
|
|
444
|
+
}
|
|
445
|
+
const base = baseUrl();
|
|
446
|
+
const plan = await findCommentPlan(base, commentId);
|
|
447
|
+
if (!plan) {
|
|
448
|
+
console.error(`Plan comment ${commentId} not found.`);
|
|
449
|
+
return EXIT_NOT_FOUND;
|
|
450
|
+
}
|
|
451
|
+
const res = await fetch(`${base}/api/plans/${plan.id}/comments/${commentId}`, {
|
|
452
|
+
method: "PUT",
|
|
453
|
+
headers: { "Content-Type": "application/json" },
|
|
454
|
+
body: JSON.stringify({ status: "resolved" })
|
|
455
|
+
});
|
|
456
|
+
if (!res.ok) {
|
|
457
|
+
console.error(`Failed to resolve: HTTP ${res.status}`);
|
|
458
|
+
return 1;
|
|
459
|
+
}
|
|
460
|
+
console.error(`Resolved plan comment ${commentId}.`);
|
|
461
|
+
return EXIT_OK;
|
|
462
|
+
}
|
|
463
|
+
async function plan(args) {
|
|
464
|
+
const action = args[0];
|
|
465
|
+
const rest = args.slice(1);
|
|
466
|
+
switch (action) {
|
|
467
|
+
case "submit": return planSubmit(rest);
|
|
468
|
+
case "await": return planAwait(rest);
|
|
469
|
+
case "list": return planList(rest);
|
|
470
|
+
case "show": return planShow(rest);
|
|
471
|
+
case "versions": return planVersions(rest);
|
|
472
|
+
case "reply": return planReply(rest);
|
|
473
|
+
case "resolve": return planResolve(rest);
|
|
474
|
+
default:
|
|
475
|
+
console.error("Usage: diffing plan <submit|await|list|show|versions|reply|resolve> [...]");
|
|
476
|
+
return EXIT_USAGE;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
async function runSubcommand(name, args) {
|
|
480
|
+
switch (name) {
|
|
481
|
+
case "await-review": return awaitReview(args);
|
|
482
|
+
case "reply": return reply(args);
|
|
483
|
+
case "resolve": return resolve(args);
|
|
484
|
+
case "comments": return comments(args);
|
|
485
|
+
case "url": return url();
|
|
486
|
+
case "plan": return plan(args);
|
|
487
|
+
case "update":
|
|
488
|
+
const { runUpdateCommand } = await import("./update-check-DAPFCqpF.mjs");
|
|
489
|
+
return runUpdateCommand();
|
|
490
|
+
case "gh":
|
|
491
|
+
const { runGhSubcommand } = await import("./cli-gh-abs-IJrz.mjs");
|
|
492
|
+
return runGhSubcommand(args);
|
|
493
|
+
default:
|
|
494
|
+
console.error(`Unknown subcommand: ${name}`);
|
|
495
|
+
return EXIT_USAGE;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
//#endregion
|
|
499
|
+
export { runSubcommand };
|