diffing 0.16.0 → 0.17.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/dist/{cli-agent-Dk0yRtrA.mjs → cli-agent-qNwkSjxK.mjs} +22 -7
- package/dist/cli.mjs +3 -3
- package/dist/client/assets/{angular-html-JZN5kc0L.js → angular-html-ByeJB0rh.js} +1 -1
- package/dist/client/assets/{angular-ts-CJtfwtPm.js → angular-ts-CiwZGajG.js} +1 -1
- package/dist/client/assets/{apl-BW-LdBEV.js → apl-C8k5a5fk.js} +1 -1
- package/dist/client/assets/{arc-CxBp7uj_.js → arc-B8VMoqVr.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-DWRcM6V_.js → architectureDiagram-3BPJPVTR-C-ng2xNL.js} +1 -1
- package/dist/client/assets/{astro-gYWZxO_0.js → astro-BE-h-qpp.js} +1 -1
- package/dist/client/assets/{blade-Dhwn6-nM.js → blade-D-0BV1wW.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-C5RclE5o.js → blockDiagram-GPEHLZMM-DyAQuONU.js} +1 -1
- package/dist/client/assets/{c-DStVJ8gV.js → c-Dg_Gx29H.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BGUA_e0K.js → c4Diagram-AAUBKEIU-k5uKTHvm.js} +1 -1
- package/dist/client/assets/channel-DsuXeLi4.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-B7n4bw-R.js → chunk-2J33WTMH-Dod_VwYj.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-w01g5zoV.js → chunk-3OPIFGDE-B8HMjry-.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-DxqZfswb.js → chunk-4BX2VUAB-TvkJVIZw.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CbDClk6A.js → chunk-55IACEB6-BsXuKAKc.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-CnsO6rSw.js → chunk-5ZQYHXKU-BI1cj2cZ.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-BtcRYmEV.js → chunk-727SXJPM-yWQ27Wk0.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-CGhb3Sth.js → chunk-AQP2D5EJ-B2BBCtTr.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-DeuRDOb1.js → chunk-BSJP7CBP-CXXvPXhK.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-B9E4vQNj.js → chunk-CSCIHK7Q-jYiloqyi.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-Bq9LG2aQ.js → chunk-FMBD7UC4-DZzqIT32.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-BVlK-NC4.js → chunk-KSCS5N6A-krdCf8iG.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-DcdQquQQ.js → chunk-L5ZTLDWV-0uuTmeZV.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-D3hLMWf5.js → chunk-LZXEDZCA-BBfUgD06.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-0nxCj3q_.js → chunk-ND2GUHAM-jkir4ZKE.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-C_Wkgas6.js → chunk-NZK2D7GU-DMWZNibJ.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-BjWUWCBx.js → chunk-O5CBEL6O-B1e1HGaX.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-D5b3mBJ2.js +1 -0
- package/dist/client/assets/chunk-WU5MYG2G-C1Pa4Y04.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-BoIL-UAf.js → chunk-XPW4576I-AvbCAUav.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DCnVfYt-.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BPa1Jkt-.js +1 -0
- package/dist/client/assets/{cobol-BhFBbthm.js → cobol-DQnGB_GV.js} +1 -1
- package/dist/client/assets/{coffee-CIJ9uq8T.js → coffee-CDV5a89x.js} +1 -1
- package/dist/client/assets/{cose-bilkent-S5V4N54A-CbiOjhru.js → cose-bilkent-S5V4N54A-t-mDNRF2.js} +1 -1
- package/dist/client/assets/{cpp-DtSSrq00.js → cpp-8G6b-siI.js} +1 -1
- package/dist/client/assets/{crystal-CukkuPMH.js → crystal-CGYCC6FM.js} +1 -1
- package/dist/client/assets/{css-B1khiVXh.js → css-nez4R8_Z.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-DV-L1RXR.js → dagre-BM42HDAG--azesYIg.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BIS3Tcy4.js → diagram-2AECGRRQ-4WJ7nKhA.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-BT7ScWHB.js → diagram-5GNKFQAL-C7ZGhLXn.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-DhEvzqhQ.js → diagram-KO2AKTUF-BobK_rbl.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DIh9QR2k.js → diagram-LMA3HP47-BOc-OkIS.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-V6xtTYuU.js → diagram-OG6HWLK6-BEtLgm86.js} +1 -1
- package/dist/client/assets/{dist--CAI-jgr.js → dist-DPuBwToc.js} +1 -1
- package/dist/client/assets/{edge-CuCj0fvA.js → edge-Z5RMbJQv.js} +1 -1
- package/dist/client/assets/{edit-BMeAI0Sj.js → edit-CFxbgVPV.js} +1 -1
- package/dist/client/assets/{elixir-CakheKmu.js → elixir-d3C79FQc.js} +1 -1
- package/dist/client/assets/{elm-C1NdUKtL.js → elm-CDAf6Uyn.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-DLJ0CCH3.js → erDiagram-TEJ5UH35-D-pR2GY9.js} +1 -1
- package/dist/client/assets/{erb-CetH6rlA.js → erb-CTJk9FKH.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-aIYTauNq.js → flowDiagram-I6XJVG4X-BwMCy2QV.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-DRQE_4dV.js → ganttDiagram-6RSMTGT7-BI1WLJDi.js} +1 -1
- package/dist/client/assets/{git-rebase-sKnthHnf.js → git-rebase-Dr0-MVoW.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-DbSrYZsG.js → gitGraphDiagram-PVQCEYII-CUfW0k1f.js} +1 -1
- package/dist/client/assets/{glimmer-js-Bt7nvyGa.js → glimmer-js-CXhLhyW-.js} +1 -1
- package/dist/client/assets/{glimmer-ts-YO9zmz82.js → glimmer-ts-BFAFT-VD.js} +1 -1
- package/dist/client/assets/{glsl-DsvRozYb.js → glsl-D7yanhgY.js} +1 -1
- package/dist/client/assets/{graphql-sXzHf_gb.js → graphql-CpoDxrok.js} +1 -1
- package/dist/client/assets/{hack-C3UDBYU5.js → hack-BL5fmC4q.js} +1 -1
- package/dist/client/assets/{haml-Bfx2v9ts.js → haml-ClAE6RVM.js} +1 -1
- package/dist/client/assets/{handlebars-D7y9m08n.js → handlebars-nHw91uOv.js} +1 -1
- package/dist/client/assets/{html-LJt8Nrzd.js → html-BIiOKqgG.js} +1 -1
- package/dist/client/assets/{html-derivative-GRYtRNx6.js → html-derivative-D1nPnuOK.js} +1 -1
- package/dist/client/assets/{http-CFcGSNWA.js → http-B_QcRZjt.js} +1 -1
- package/dist/client/assets/{hurl-EaOExxlv.js → hurl-CZE0DsD3.js} +1 -1
- package/dist/client/assets/{index-DIOUI027.js → index-Erqhm7rW.js} +7 -7
- package/dist/client/assets/{infoDiagram-5YYISTIA-CT2k1ZKR.js → infoDiagram-5YYISTIA-w2M_OHua.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-D9ZWerXw.js → ishikawaDiagram-YF4QCWOH-CW_l9PGx.js} +1 -1
- package/dist/client/assets/{java-QdNEgqNn.js → java-CXTqX09w.js} +1 -1
- package/dist/client/assets/{javascript-C0TUIalv.js → javascript-9z9ABBep.js} +1 -1
- package/dist/client/assets/{jinja-CHXCs943.js → jinja-Cluf_5Bk.js} +1 -1
- package/dist/client/assets/{jison-Cu1JVrPL.js → jison-CqCEUtc4.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-CS0prGm3.js → journeyDiagram-JHISSGLW-D-YwusBa.js} +1 -1
- package/dist/client/assets/{json-DbuC832p.js → json-BMq_bPP8.js} +1 -1
- package/dist/client/assets/{jsx-D2ojEfVP.js → jsx-Djij59b9.js} +1 -1
- package/dist/client/assets/{julia-DBG4gf9M.js → julia-DybzCMnh.js} +1 -1
- package/dist/client/assets/{just-cnG6iJYR.js → just-4ChcAr9-.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-B5_nyCCN.js → kanban-definition-UN3LZRKU-Brvoukmm.js} +1 -1
- package/dist/client/assets/{latex-C-t8YHXx.js → latex-CS2TtFXG.js} +1 -1
- package/dist/client/assets/{line-PhY2p9yO.js → line-CqxM-stA.js} +1 -1
- package/dist/client/assets/{linear-DZfj4bbh.js → linear-C7T82059.js} +1 -1
- package/dist/client/assets/{liquid-BXKFGxIR.js → liquid-84AtYenm.js} +1 -1
- package/dist/client/assets/{lua-BNuqYfRm.js → lua-DJzFx3Cf.js} +1 -1
- package/dist/client/assets/{marko-DSC8kwzM.js → marko-BLw9BV9E.js} +1 -1
- package/dist/client/assets/{mdc-BwB9Dj6D.js → mdc-BjZejN3b.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BrVg46EN.js → mermaid-parser.core-BdiEBAsd.js} +1 -1
- package/dist/client/assets/{mermaid.core-Bnf5T6PT.js → mermaid.core-BsnKhnrM.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CAomoDK8.js → mindmap-definition-RKZ34NQL-CBaIFnbc.js} +1 -1
- package/dist/client/assets/{nginx-BrQvZxpD.js → nginx-DuamCwvX.js} +1 -1
- package/dist/client/assets/{nim-tVYcrqi1.js → nim-Bt8c9-ge.js} +1 -1
- package/dist/client/assets/{perl-B-60oGLc.js → perl-D52AfmwC.js} +1 -1
- package/dist/client/assets/{php-DJJABwVz.js → php-BBMlJg0_.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BOtZhQH4.js → pieDiagram-4H26LBE5-BlmPajcA.js} +1 -1
- package/dist/client/assets/{pug-KJGvmNqp.js → pug-DFHmDqEE.js} +1 -1
- package/dist/client/assets/{qml-6M7QCkVi.js → qml-C0333o-g.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Pcpz6-BU.js → quadrantDiagram-W4KKPZXB-Bqlm_zZk.js} +1 -1
- package/dist/client/assets/{r-CJX_7SfZ.js → r-DZFmvIgR.js} +1 -1
- package/dist/client/assets/{razor-DYZH4-tY.js → razor-BIGLkWzR.js} +1 -1
- package/dist/client/assets/{regexp-DWtQcg88.js → regexp-BW6jpgf9.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-Cruba0r2.js → requirementDiagram-4Y6WPE33-B1PrtUeD.js} +1 -1
- package/dist/client/assets/{review-export-DUMpiyN2.js → review-export-BlgD3bdw.js} +1 -1
- package/dist/client/assets/{rst-idvXY1TW.js → rst-Cj51ZJaa.js} +1 -1
- package/dist/client/assets/{ruby-CBUdU1Jx.js → ruby-lMhGjwpf.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-DpLjNHX_.js → sankeyDiagram-5OEKKPKP-D2HtUNVF.js} +1 -1
- package/dist/client/assets/{sas-CD7-yPwf.js → sas-BWSQku7l.js} +1 -1
- package/dist/client/assets/{scss-CcmN3LNf.js → scss-CdRPuhLN.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-Dxvk3OQI.js → sequenceDiagram-3UESZ5HK-D9SQy0XI.js} +1 -1
- package/dist/client/assets/{shellscript-BxkDFxdN.js → shellscript-DOfOBXcj.js} +1 -1
- package/dist/client/assets/{shellsession-Bz5EKpQO.js → shellsession-7XAOCVni.js} +1 -1
- package/dist/client/assets/{soy-DMVQQ2W2.js → soy-DDnzVRIw.js} +1 -1
- package/dist/client/assets/{sql-B-oK6O9W.js → sql-Ba34agKe.js} +1 -1
- package/dist/client/assets/{src-BNoZKBH3.js → src-BO-qT_v_.js} +1 -1
- package/dist/client/assets/{stata-CUZrRD4_.js → stata-BQlYGHQU.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-DcGkjwzF.js → stateDiagram-AJRCARHV-7IEYjFRo.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DP6swlL9.js +1 -0
- package/dist/client/assets/{surrealql-TyxgDynf.js → surrealql-BET1l7SW.js} +1 -1
- package/dist/client/assets/{svelte-nYNHcaCO.js → svelte-Bd7ZOeQI.js} +1 -1
- package/dist/client/assets/{templ-DfKxw_Rl.js → templ-BYvRQdOw.js} +1 -1
- package/dist/client/assets/{tex-CNwID2CI.js → tex-CT8DpKxX.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CluiloeV.js → timeline-definition-PNZ67QCA-CurQYWmi.js} +1 -1
- package/dist/client/assets/{ts-tags-DgUARkAi.js → ts-tags-D4iPPwau.js} +1 -1
- package/dist/client/assets/{tsx-2yb3iicd.js → tsx-Dgk_Aw-B.js} +1 -1
- package/dist/client/assets/{twig-l1ft8ReI.js → twig-abRNWeh3.js} +1 -1
- package/dist/client/assets/{typescript-BZqXFlL1.js → typescript-BgR1JqdC.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DHRoQg07.js → vennDiagram-CIIHVFJN-DbrRBL5S.js} +1 -1
- package/dist/client/assets/{vue-BgXkMZZj.js → vue-DSkhKq4Q.js} +1 -1
- package/dist/client/assets/{vue-html-Byxl7Gyw.js → vue-html-J0jWoD9X.js} +1 -1
- package/dist/client/assets/{vue-vine-Bzpp44S9.js → vue-vine-BgX5MC8-.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DQ_ujF1q.js → wardleyDiagram-YWT4CUSO-DIFXQsoP.js} +1 -1
- package/dist/client/assets/{xml-CpwLtzxK.js → xml-Ca53xGLB.js} +1 -1
- package/dist/client/assets/{xsl-VlCQyM4_.js → xsl-CNnXclYV.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-DjG2u0Gz.js → xychartDiagram-2RQKCTM6-CmfInPqa.js} +1 -1
- package/dist/client/assets/{yaml-BypQObHK.js → yaml-CjjyUhfg.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/{mcp-C9HpAFs0.mjs → mcp-DhynPewa.mjs} +35 -19
- 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/{server-BmQqrWy4.mjs → server-CEbp7K-k.mjs} +289 -29
- package/extensions/pi/index.ts +283 -86
- package/extensions/pi/pi-modules.d.ts +70 -0
- package/extensions/pi/tsconfig.json +14 -0
- package/package.json +2 -1
- package/dist/client/assets/channel-BqKSU-HY.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-BE1tL2Nx.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-DP73Gify.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK--5lgckcu.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CCQu7EQ7.js +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DVv3yrP9.js +0 -1
package/extensions/pi/index.ts
CHANGED
|
@@ -11,17 +11,28 @@
|
|
|
11
11
|
* `[Skill conflicts]` banner appears when pi runs inside the diffing repo.
|
|
12
12
|
*
|
|
13
13
|
* All tool executions spawn the `diffing` CLI in the consumer repo (ctx.cwd).
|
|
14
|
-
* Install: `pi install
|
|
14
|
+
* Install: `pi install npm:diffing` (published on npm),
|
|
15
|
+
* `pi install git:github.com/ahmedragab20/diffing`, or symlink this
|
|
15
16
|
* directory into `~/.pi/agent/extensions/diffing`.
|
|
16
17
|
*/
|
|
17
18
|
|
|
18
19
|
import { spawn } from "node:child_process";
|
|
19
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
existsSync,
|
|
22
|
+
lstatSync,
|
|
23
|
+
readFileSync,
|
|
24
|
+
realpathSync,
|
|
25
|
+
rmSync,
|
|
26
|
+
symlinkSync,
|
|
27
|
+
} from "node:fs";
|
|
20
28
|
import { homedir } from "node:os";
|
|
21
29
|
import { dirname, join, resolve } from "node:path";
|
|
22
30
|
import { fileURLToPath } from "node:url";
|
|
23
31
|
import { StringEnum } from "@earendil-works/pi-ai";
|
|
24
|
-
import type {
|
|
32
|
+
import type {
|
|
33
|
+
ExtensionAPI,
|
|
34
|
+
ExtensionContext,
|
|
35
|
+
} from "@earendil-works/pi-coding-agent";
|
|
25
36
|
import { Type } from "typebox";
|
|
26
37
|
|
|
27
38
|
// ────────────────────────────────────────────────────────────────────────────
|
|
@@ -34,6 +45,7 @@ const SKILL_NAMES = [
|
|
|
34
45
|
"diffing-plan-review",
|
|
35
46
|
"diffing-pr-address",
|
|
36
47
|
"diffing-pr-read",
|
|
48
|
+
"diffing-release",
|
|
37
49
|
"diffing-review",
|
|
38
50
|
"diffing-start-review",
|
|
39
51
|
] as const;
|
|
@@ -134,12 +146,12 @@ function describe(result: RunResult, command: string): string {
|
|
|
134
146
|
return out || "(no output)";
|
|
135
147
|
}
|
|
136
148
|
const err = result.stderr.trim();
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
149
|
+
let hint = "";
|
|
150
|
+
if (result.exitCode === 127) {
|
|
151
|
+
hint = `\n\n\`diffing\` was not found on PATH (ran: diffing ${command}). Install it with \`npm i -g diffing\` or run \`diffing setup\`.`;
|
|
152
|
+
} else if (result.exitCode === 3) {
|
|
153
|
+
hint = `\n\nNo diffing server is running for this repo (ran: diffing ${command}). Start one with \`diffing\` (or the diffing_start_review tool).`;
|
|
154
|
+
}
|
|
143
155
|
return err ? `${err}${hint}` : `exit code ${result.exitCode}${hint}`;
|
|
144
156
|
}
|
|
145
157
|
|
|
@@ -179,7 +191,10 @@ async function refreshStatus(ctx: ExtensionContext): Promise<void> {
|
|
|
179
191
|
const sessions = await activeSessions(ctx.cwd);
|
|
180
192
|
const active = sessions.find((s) => s.active) ?? sessions[0];
|
|
181
193
|
if (active) {
|
|
182
|
-
ctx.ui.setStatus(
|
|
194
|
+
ctx.ui.setStatus(
|
|
195
|
+
"diffing",
|
|
196
|
+
`diffing: ${active.mode ?? "session"} — ${active.url ?? ""}`,
|
|
197
|
+
);
|
|
183
198
|
} else {
|
|
184
199
|
ctx.ui.setStatus("diffing", "diffing: no server");
|
|
185
200
|
}
|
|
@@ -209,7 +224,9 @@ function findGitRepoRoot(startDir: string): string | null {
|
|
|
209
224
|
|
|
210
225
|
function isDiffingRoot(dir: string): boolean {
|
|
211
226
|
try {
|
|
212
|
-
const pkg = JSON.parse(
|
|
227
|
+
const pkg = JSON.parse(
|
|
228
|
+
readFileSync(join(dir, "package.json"), "utf-8"),
|
|
229
|
+
) as { name?: string };
|
|
213
230
|
if (pkg.name !== "diffing") return false;
|
|
214
231
|
return existsSync(join(dir, SKILLS_REL));
|
|
215
232
|
} catch {
|
|
@@ -262,7 +279,11 @@ function selfHealSkillLinks(canonical: string): void {
|
|
|
262
279
|
|
|
263
280
|
function spawnDetachedReview(cwd: string, args: string[]): void {
|
|
264
281
|
try {
|
|
265
|
-
const child = spawn("diffing", args, {
|
|
282
|
+
const child = spawn("diffing", args, {
|
|
283
|
+
cwd,
|
|
284
|
+
stdio: "ignore",
|
|
285
|
+
detached: true,
|
|
286
|
+
});
|
|
266
287
|
child.unref();
|
|
267
288
|
} catch {
|
|
268
289
|
// surfaced by the URL poll below
|
|
@@ -279,7 +300,12 @@ async function ensureReviewUrl(
|
|
|
279
300
|
const existing = await diffingUrl(cwd);
|
|
280
301
|
if (existing && reuse) return { url: existing, reused: true };
|
|
281
302
|
if (existing && !reuse) return { url: existing, reused: true };
|
|
282
|
-
spawnDetachedReview(cwd, [
|
|
303
|
+
spawnDetachedReview(cwd, [
|
|
304
|
+
"--web",
|
|
305
|
+
"--no-open",
|
|
306
|
+
"--skip-setup",
|
|
307
|
+
...extraArgs,
|
|
308
|
+
]);
|
|
283
309
|
const deadline = Date.now() + REVIEW_START_TIMEOUT_MS;
|
|
284
310
|
for (;;) {
|
|
285
311
|
if (signal?.aborted) break;
|
|
@@ -366,20 +392,33 @@ export default function (pi: ExtensionAPI) {
|
|
|
366
392
|
}),
|
|
367
393
|
),
|
|
368
394
|
reuse: Type.Optional(
|
|
369
|
-
Type.Boolean({
|
|
395
|
+
Type.Boolean({
|
|
396
|
+
description:
|
|
397
|
+
"Reuse the active session if one is running. Default: true.",
|
|
398
|
+
default: true,
|
|
399
|
+
}),
|
|
370
400
|
),
|
|
371
401
|
}),
|
|
372
402
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
373
403
|
try {
|
|
374
404
|
const extra = params.prRef ? ["--gh-pr", params.prRef] : [];
|
|
375
|
-
const { url, reused } = await ensureReviewUrl(
|
|
405
|
+
const { url, reused } = await ensureReviewUrl(
|
|
406
|
+
ctx.cwd,
|
|
407
|
+
extra,
|
|
408
|
+
params.reuse ?? true,
|
|
409
|
+
signal,
|
|
410
|
+
);
|
|
376
411
|
await refreshStatus(ctx);
|
|
412
|
+
return textResult(`Review ${reused ? "reused" : "started"}: ${url}`, {
|
|
413
|
+
url,
|
|
414
|
+
reused,
|
|
415
|
+
mode: params.prRef ? "gh-pr" : "web",
|
|
416
|
+
});
|
|
417
|
+
} catch (error) {
|
|
377
418
|
return textResult(
|
|
378
|
-
|
|
379
|
-
{
|
|
419
|
+
error instanceof Error ? error.message : String(error),
|
|
420
|
+
{ started: false },
|
|
380
421
|
);
|
|
381
|
-
} catch (error) {
|
|
382
|
-
return textResult(error instanceof Error ? error.message : String(error), { started: false });
|
|
383
422
|
}
|
|
384
423
|
},
|
|
385
424
|
});
|
|
@@ -391,9 +430,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
391
430
|
"Snapshot the current review comments as XML (or JSON). Use --open to see only unresolved threads. Parse the returned XML to act on feedback.",
|
|
392
431
|
parameters: Type.Object({
|
|
393
432
|
open: Type.Optional(
|
|
394
|
-
Type.Boolean({
|
|
433
|
+
Type.Boolean({
|
|
434
|
+
description:
|
|
435
|
+
"Only include open (unresolved) comment threads. Default: true.",
|
|
436
|
+
default: true,
|
|
437
|
+
}),
|
|
438
|
+
),
|
|
439
|
+
format: Type.Optional(
|
|
440
|
+
StringEnum(["xml", "json", "md"] as const, {
|
|
441
|
+
description: "Output format. Default: xml.",
|
|
442
|
+
}),
|
|
395
443
|
),
|
|
396
|
-
format: Type.Optional(StringEnum(["xml", "json", "md"] as const, { description: "Output format. Default: xml." })),
|
|
397
444
|
}),
|
|
398
445
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
399
446
|
const args = ["comments"];
|
|
@@ -411,16 +458,33 @@ export default function (pi: ExtensionAPI) {
|
|
|
411
458
|
pi.registerTool({
|
|
412
459
|
name: "diffing_reply",
|
|
413
460
|
label: "Diffing Reply",
|
|
414
|
-
description:
|
|
461
|
+
description:
|
|
462
|
+
"Append a reply to an existing comment thread by id. Answers questions; does not resolve.",
|
|
415
463
|
parameters: Type.Object({
|
|
416
|
-
commentId: Type.String({
|
|
464
|
+
commentId: Type.String({
|
|
465
|
+
description: "UUID of the comment thread to reply to.",
|
|
466
|
+
}),
|
|
417
467
|
body: Type.String({ description: "Markdown reply body." }),
|
|
418
|
-
model: Type.Optional(
|
|
468
|
+
model: Type.Optional(
|
|
469
|
+
Type.String({
|
|
470
|
+
description: "Model name to attribute. Defaults to the active model.",
|
|
471
|
+
}),
|
|
472
|
+
),
|
|
419
473
|
}),
|
|
420
474
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
421
|
-
const result = await runDiffing(
|
|
422
|
-
|
|
423
|
-
|
|
475
|
+
const result = await runDiffing(
|
|
476
|
+
[
|
|
477
|
+
"reply",
|
|
478
|
+
params.commentId,
|
|
479
|
+
"-",
|
|
480
|
+
"--model",
|
|
481
|
+
modelName(ctx, params.model),
|
|
482
|
+
],
|
|
483
|
+
ctx.cwd,
|
|
484
|
+
{
|
|
485
|
+
stdin: params.body,
|
|
486
|
+
},
|
|
487
|
+
);
|
|
424
488
|
return textResult(describe(result, `diffing reply ${params.commentId}`), {
|
|
425
489
|
exitCode: result.exitCode,
|
|
426
490
|
stderr: result.stderr.trim() || undefined,
|
|
@@ -431,14 +495,20 @@ export default function (pi: ExtensionAPI) {
|
|
|
431
495
|
pi.registerTool({
|
|
432
496
|
name: "diffing_resolve",
|
|
433
497
|
label: "Diffing Resolve",
|
|
434
|
-
description:
|
|
435
|
-
|
|
498
|
+
description:
|
|
499
|
+
"Mark a review comment thread resolved. Use after addressing a change request.",
|
|
500
|
+
parameters: Type.Object({
|
|
501
|
+
commentId: Type.String({ description: "UUID of the comment thread." }),
|
|
502
|
+
}),
|
|
436
503
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
437
504
|
const result = await runDiffing(["resolve", params.commentId], ctx.cwd);
|
|
438
|
-
return textResult(
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
505
|
+
return textResult(
|
|
506
|
+
describe(result, `diffing resolve ${params.commentId}`),
|
|
507
|
+
{
|
|
508
|
+
exitCode: result.exitCode,
|
|
509
|
+
stderr: result.stderr.trim() || undefined,
|
|
510
|
+
},
|
|
511
|
+
);
|
|
442
512
|
},
|
|
443
513
|
});
|
|
444
514
|
|
|
@@ -446,13 +516,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
446
516
|
name: "diffing_unresolve",
|
|
447
517
|
label: "Diffing Unresolve",
|
|
448
518
|
description: "Re-open a previously resolved comment thread.",
|
|
449
|
-
parameters: Type.Object({
|
|
519
|
+
parameters: Type.Object({
|
|
520
|
+
commentId: Type.String({ description: "UUID of the comment thread." }),
|
|
521
|
+
}),
|
|
450
522
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
451
523
|
const result = await runDiffing(["unresolve", params.commentId], ctx.cwd);
|
|
452
|
-
return textResult(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
524
|
+
return textResult(
|
|
525
|
+
describe(result, `diffing unresolve ${params.commentId}`),
|
|
526
|
+
{
|
|
527
|
+
exitCode: result.exitCode,
|
|
528
|
+
stderr: result.stderr.trim() || undefined,
|
|
529
|
+
},
|
|
530
|
+
);
|
|
456
531
|
},
|
|
457
532
|
});
|
|
458
533
|
|
|
@@ -462,18 +537,35 @@ export default function (pi: ExtensionAPI) {
|
|
|
462
537
|
description:
|
|
463
538
|
"Post a live progress toast to the review UI so the human sees status while work is underway. Safe to call frequently.",
|
|
464
539
|
parameters: Type.Object({
|
|
465
|
-
message: Type.String({
|
|
466
|
-
|
|
467
|
-
|
|
540
|
+
message: Type.String({
|
|
541
|
+
description: "Progress message, e.g. 'Addressing L42…'.",
|
|
542
|
+
}),
|
|
543
|
+
pct: Type.Optional(
|
|
544
|
+
Type.Number({ description: "Optional 0-100 completion percent." }),
|
|
545
|
+
),
|
|
546
|
+
model: Type.Optional(
|
|
547
|
+
Type.String({
|
|
548
|
+
description: "Model name to attribute. Defaults to the active model.",
|
|
549
|
+
}),
|
|
550
|
+
),
|
|
468
551
|
}),
|
|
469
552
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
470
|
-
const args = [
|
|
553
|
+
const args = [
|
|
554
|
+
"progress",
|
|
555
|
+
"--message",
|
|
556
|
+
params.message,
|
|
557
|
+
"--model",
|
|
558
|
+
modelName(ctx, params.model),
|
|
559
|
+
];
|
|
471
560
|
if (params.pct !== undefined) args.push("--pct", String(params.pct));
|
|
472
561
|
const result = await runDiffing(args, ctx.cwd);
|
|
473
|
-
return textResult(
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
562
|
+
return textResult(
|
|
563
|
+
describe(result, `diffing progress --message "${params.message}"`),
|
|
564
|
+
{
|
|
565
|
+
exitCode: result.exitCode,
|
|
566
|
+
stderr: result.stderr.trim() || undefined,
|
|
567
|
+
},
|
|
568
|
+
);
|
|
477
569
|
},
|
|
478
570
|
});
|
|
479
571
|
|
|
@@ -484,12 +576,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
484
576
|
"Synchronously wait (long-poll) until the human releases the review ('Send to agent'), then return the comments XML. Exit code 2 (or a timeout) is an expected park signal — do not silent-loop; resume once the human says the review is ready.",
|
|
485
577
|
parameters: Type.Object({
|
|
486
578
|
timeout: Type.Optional(
|
|
487
|
-
Type.Number({
|
|
579
|
+
Type.Number({
|
|
580
|
+
description: "Max seconds to block. Default: 60 (park beyond that).",
|
|
581
|
+
default: 60,
|
|
582
|
+
}),
|
|
488
583
|
),
|
|
489
584
|
}),
|
|
490
585
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
491
586
|
const timeout = Math.min(Math.max(params.timeout ?? 60, 1), 600);
|
|
492
|
-
const result = await runDiffing(
|
|
587
|
+
const result = await runDiffing(
|
|
588
|
+
["await-review", "-t", String(timeout)],
|
|
589
|
+
ctx.cwd,
|
|
590
|
+
{ signal },
|
|
591
|
+
);
|
|
493
592
|
const parked = result.exitCode === 2;
|
|
494
593
|
if (parked) {
|
|
495
594
|
return textResult(
|
|
@@ -512,26 +611,52 @@ export default function (pi: ExtensionAPI) {
|
|
|
512
611
|
"Submit (or resubmit) a markdown plan for human review. Pass the plan as file (path) or body (inline text). Returns the plan id and review URL. Default handoff is async: share the URL, end the turn, act on the verdict when the human decides.",
|
|
513
612
|
parameters: Type.Object({
|
|
514
613
|
file: Type.Optional(
|
|
515
|
-
Type.String({
|
|
614
|
+
Type.String({
|
|
615
|
+
description:
|
|
616
|
+
"Path to the plan markdown file. Use the body parameter instead to submit inline text.",
|
|
617
|
+
}),
|
|
618
|
+
),
|
|
619
|
+
body: Type.Optional(
|
|
620
|
+
Type.String({ description: "Inline plan markdown body." }),
|
|
621
|
+
),
|
|
622
|
+
title: Type.Optional(
|
|
623
|
+
Type.String({
|
|
624
|
+
description: "Display title. Defaults to the plan's first heading.",
|
|
625
|
+
}),
|
|
516
626
|
),
|
|
517
|
-
body: Type.Optional(Type.String({ description: "Inline plan markdown body." })),
|
|
518
|
-
title: Type.Optional(Type.String({ description: "Display title. Defaults to the plan's first heading." })),
|
|
519
627
|
planId: Type.Optional(
|
|
520
|
-
Type.String({
|
|
628
|
+
Type.String({
|
|
629
|
+
description:
|
|
630
|
+
"Resubmit a revised body for an existing plan id (bumps version, resets verdict).",
|
|
631
|
+
}),
|
|
632
|
+
),
|
|
633
|
+
model: Type.Optional(
|
|
634
|
+
Type.String({
|
|
635
|
+
description: "Authoring model. Defaults to the active model.",
|
|
636
|
+
}),
|
|
521
637
|
),
|
|
522
|
-
model: Type.Optional(Type.String({ description: "Authoring model. Defaults to the active model." })),
|
|
523
638
|
}),
|
|
524
639
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
525
640
|
let stdin: string | undefined;
|
|
526
641
|
let fileArg = params.file;
|
|
527
642
|
if (!fileArg) {
|
|
528
643
|
if (!params.body) {
|
|
529
|
-
return textResult(
|
|
644
|
+
return textResult(
|
|
645
|
+
"Provide either file (path) or body (inline plan markdown).",
|
|
646
|
+
{ submitted: false },
|
|
647
|
+
);
|
|
530
648
|
}
|
|
531
649
|
fileArg = "-";
|
|
532
650
|
stdin = params.body;
|
|
533
651
|
}
|
|
534
|
-
const args = [
|
|
652
|
+
const args = [
|
|
653
|
+
"plan",
|
|
654
|
+
"submit",
|
|
655
|
+
fileArg,
|
|
656
|
+
"--save-source",
|
|
657
|
+
"--model",
|
|
658
|
+
modelName(ctx, params.model),
|
|
659
|
+
];
|
|
535
660
|
if (params.title) args.push("--title", params.title);
|
|
536
661
|
if (params.planId) args.push("--id", params.planId);
|
|
537
662
|
const result = await runDiffing(args, ctx.cwd, { signal, stdin });
|
|
@@ -559,12 +684,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
559
684
|
"Synchronously wait until the human decides on the submitted plan, then return the <plan-review> XML with the verdict. Exit code 2 is an expected park signal — do not silent-loop.",
|
|
560
685
|
parameters: Type.Object({
|
|
561
686
|
timeout: Type.Optional(
|
|
562
|
-
Type.Number({
|
|
687
|
+
Type.Number({
|
|
688
|
+
description: "Max seconds to block. Default: 60 (park beyond that).",
|
|
689
|
+
default: 60,
|
|
690
|
+
}),
|
|
563
691
|
),
|
|
564
692
|
}),
|
|
565
693
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
566
694
|
const timeout = Math.min(Math.max(params.timeout ?? 60, 1), 600);
|
|
567
|
-
const result = await runDiffing(
|
|
695
|
+
const result = await runDiffing(
|
|
696
|
+
["plan", "await", "-t", String(timeout)],
|
|
697
|
+
ctx.cwd,
|
|
698
|
+
{ signal },
|
|
699
|
+
);
|
|
568
700
|
if (result.exitCode === 2) {
|
|
569
701
|
return textResult(
|
|
570
702
|
`No plan verdict within ${timeout}s (park). Share the plan URL and end your turn; run diffing_plan_await again when the human says the verdict is ready.`,
|
|
@@ -582,9 +714,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
582
714
|
pi.registerTool({
|
|
583
715
|
name: "diffing_plan_list",
|
|
584
716
|
label: "Diffing Plan List",
|
|
585
|
-
description:
|
|
717
|
+
description:
|
|
718
|
+
"List submitted plans for the current repo (id, decision, version, open comments, title).",
|
|
586
719
|
parameters: Type.Object({
|
|
587
|
-
json: Type.Optional(
|
|
720
|
+
json: Type.Optional(
|
|
721
|
+
Type.Boolean({ description: "Emit raw JSON instead of the table." }),
|
|
722
|
+
),
|
|
588
723
|
}),
|
|
589
724
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
590
725
|
const args = ["plan", "list"];
|
|
@@ -600,10 +735,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
600
735
|
pi.registerTool({
|
|
601
736
|
name: "diffing_plan_show",
|
|
602
737
|
label: "Diffing Plan Show",
|
|
603
|
-
description:
|
|
738
|
+
description:
|
|
739
|
+
"Show a single plan as <plan-review> XML (or raw JSON) including the verdict and open comments.",
|
|
604
740
|
parameters: Type.Object({
|
|
605
|
-
planId: Type.Optional(
|
|
606
|
-
|
|
741
|
+
planId: Type.Optional(
|
|
742
|
+
Type.String({ description: "Plan id. Omit for the latest plan." }),
|
|
743
|
+
),
|
|
744
|
+
json: Type.Optional(
|
|
745
|
+
Type.Boolean({ description: "Emit raw JSON instead of XML." }),
|
|
746
|
+
),
|
|
607
747
|
}),
|
|
608
748
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
609
749
|
const args = ["plan", "show"];
|
|
@@ -620,22 +760,37 @@ export default function (pi: ExtensionAPI) {
|
|
|
620
760
|
pi.registerTool({
|
|
621
761
|
name: "diffing_plan_reply",
|
|
622
762
|
label: "Diffing Plan Reply",
|
|
623
|
-
description:
|
|
763
|
+
description:
|
|
764
|
+
"Reply to an inline plan comment (the owning plan is resolved automatically).",
|
|
624
765
|
parameters: Type.Object({
|
|
625
766
|
commentId: Type.String({ description: "UUID of the plan comment." }),
|
|
626
767
|
body: Type.String({ description: "Markdown reply body." }),
|
|
627
|
-
model: Type.Optional(
|
|
768
|
+
model: Type.Optional(
|
|
769
|
+
Type.String({
|
|
770
|
+
description: "Model name to attribute. Defaults to the active model.",
|
|
771
|
+
}),
|
|
772
|
+
),
|
|
628
773
|
}),
|
|
629
774
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
630
775
|
const result = await runDiffing(
|
|
631
|
-
[
|
|
776
|
+
[
|
|
777
|
+
"plan",
|
|
778
|
+
"reply",
|
|
779
|
+
params.commentId,
|
|
780
|
+
"-",
|
|
781
|
+
"--model",
|
|
782
|
+
modelName(ctx, params.model),
|
|
783
|
+
],
|
|
632
784
|
ctx.cwd,
|
|
633
785
|
{ stdin: params.body },
|
|
634
786
|
);
|
|
635
|
-
return textResult(
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
787
|
+
return textResult(
|
|
788
|
+
describe(result, `diffing plan reply ${params.commentId}`),
|
|
789
|
+
{
|
|
790
|
+
exitCode: result.exitCode,
|
|
791
|
+
stderr: result.stderr.trim() || undefined,
|
|
792
|
+
},
|
|
793
|
+
);
|
|
639
794
|
},
|
|
640
795
|
});
|
|
641
796
|
|
|
@@ -643,25 +798,36 @@ export default function (pi: ExtensionAPI) {
|
|
|
643
798
|
name: "diffing_plan_resolve",
|
|
644
799
|
label: "Diffing Plan Resolve",
|
|
645
800
|
description: "Mark a plan comment resolved.",
|
|
646
|
-
parameters: Type.Object({
|
|
801
|
+
parameters: Type.Object({
|
|
802
|
+
commentId: Type.String({ description: "UUID of the plan comment." }),
|
|
803
|
+
}),
|
|
647
804
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
648
|
-
const result = await runDiffing(
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
805
|
+
const result = await runDiffing(
|
|
806
|
+
["plan", "resolve", params.commentId],
|
|
807
|
+
ctx.cwd,
|
|
808
|
+
);
|
|
809
|
+
return textResult(
|
|
810
|
+
describe(result, `diffing plan resolve ${params.commentId}`),
|
|
811
|
+
{
|
|
812
|
+
exitCode: result.exitCode,
|
|
813
|
+
stderr: result.stderr.trim() || undefined,
|
|
814
|
+
},
|
|
815
|
+
);
|
|
653
816
|
},
|
|
654
817
|
});
|
|
655
818
|
|
|
656
819
|
pi.registerTool({
|
|
657
820
|
name: "diffing_url",
|
|
658
821
|
label: "Diffing URL",
|
|
659
|
-
description:
|
|
822
|
+
description:
|
|
823
|
+
"Print the base URL of the active diffing review server for this repo, or report that none is running.",
|
|
660
824
|
parameters: Type.Object({}),
|
|
661
825
|
async execute(_id, _params, _signal, _onUpdate, ctx) {
|
|
662
826
|
const url = await diffingUrl(ctx.cwd);
|
|
663
827
|
return textResult(
|
|
664
|
-
url
|
|
828
|
+
url
|
|
829
|
+
? url
|
|
830
|
+
: "No diffing server running for this repo. Start one with diffing_start_review or `/diffing`.",
|
|
665
831
|
{ url },
|
|
666
832
|
);
|
|
667
833
|
},
|
|
@@ -673,9 +839,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
673
839
|
description:
|
|
674
840
|
"List, select, or stop live diffing review sessions for this repo. use: retarget agent commands to a session id prefix. stop: graceful shutdown of a session.",
|
|
675
841
|
parameters: Type.Object({
|
|
676
|
-
action: Type.Optional(
|
|
677
|
-
|
|
678
|
-
|
|
842
|
+
action: Type.Optional(
|
|
843
|
+
StringEnum(["list", "use", "stop"] as const, {
|
|
844
|
+
description: "Action. Default: list.",
|
|
845
|
+
}),
|
|
846
|
+
),
|
|
847
|
+
value: Type.Optional(
|
|
848
|
+
Type.String({
|
|
849
|
+
description: "Session id prefix (for use/stop), or 'active'/'all'.",
|
|
850
|
+
}),
|
|
851
|
+
),
|
|
852
|
+
json: Type.Optional(
|
|
853
|
+
Type.Boolean({ description: "Emit JSON for list. Default: false." }),
|
|
854
|
+
),
|
|
679
855
|
}),
|
|
680
856
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
681
857
|
const action = params.action ?? "list";
|
|
@@ -700,7 +876,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
700
876
|
description:
|
|
701
877
|
"Probe the active GitHub PR review session: PR identity, head/base SHAs, patch size, and conversation/draft counts. Fails cleanly when no PR session is active.",
|
|
702
878
|
parameters: Type.Object({
|
|
703
|
-
json: Type.Optional(
|
|
879
|
+
json: Type.Optional(
|
|
880
|
+
Type.Boolean({
|
|
881
|
+
description: "Emit raw JSON instead of human-readable output.",
|
|
882
|
+
}),
|
|
883
|
+
),
|
|
704
884
|
}),
|
|
705
885
|
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
706
886
|
const args = ["gh", "overview"];
|
|
@@ -719,15 +899,29 @@ export default function (pi: ExtensionAPI) {
|
|
|
719
899
|
description:
|
|
720
900
|
"Escape hatch: run any documented `diffing` agent subcommand with raw arguments. Examples: ['inspect','summary'], ['comment','edit',id,'--body','...'], ['gh','threads','--unresolved'], ['gh','reviews'], ['plan','versions',id], ['doctor'], ['mode']. Returns stdout + exit code; exit 3 means no server.",
|
|
721
901
|
parameters: Type.Object({
|
|
722
|
-
args: Type.Array(
|
|
723
|
-
|
|
902
|
+
args: Type.Array(
|
|
903
|
+
Type.String({
|
|
904
|
+
description: "Subcommand and arguments, e.g. ['inspect','summary'].",
|
|
905
|
+
}),
|
|
906
|
+
),
|
|
907
|
+
stdin: Type.Optional(
|
|
908
|
+
Type.String({
|
|
909
|
+
description:
|
|
910
|
+
"Optional text to pipe to the command's stdin (e.g. reply bodies).",
|
|
911
|
+
}),
|
|
912
|
+
),
|
|
724
913
|
}),
|
|
725
914
|
async execute(_id, params, signal, _onUpdate, ctx) {
|
|
726
915
|
const args = params.args;
|
|
727
916
|
if (!Array.isArray(args) || args.length === 0) {
|
|
728
|
-
return textResult("Provide at least one subcommand argument.", {
|
|
917
|
+
return textResult("Provide at least one subcommand argument.", {
|
|
918
|
+
ran: false,
|
|
919
|
+
});
|
|
729
920
|
}
|
|
730
|
-
const result = await runDiffing(args, ctx.cwd, {
|
|
921
|
+
const result = await runDiffing(args, ctx.cwd, {
|
|
922
|
+
signal,
|
|
923
|
+
stdin: params.stdin,
|
|
924
|
+
});
|
|
731
925
|
return textResult(describe(result, `diffing ${args.join(" ")}`), {
|
|
732
926
|
exitCode: result.exitCode,
|
|
733
927
|
stderr: result.stderr.trim() || undefined,
|
|
@@ -747,7 +941,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
747
941
|
await refreshStatus(ctx);
|
|
748
942
|
ctx.ui.notify(`diffing review: ${url}`, "info");
|
|
749
943
|
} catch (error) {
|
|
750
|
-
ctx.ui.notify(
|
|
944
|
+
ctx.ui.notify(
|
|
945
|
+
error instanceof Error ? error.message : String(error),
|
|
946
|
+
"error",
|
|
947
|
+
);
|
|
751
948
|
}
|
|
752
949
|
},
|
|
753
950
|
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ambient declarations for pi-bundled modules.
|
|
3
|
+
*
|
|
4
|
+
* The pi harness provides `@earendil-works/pi-ai`, `@earendil-works/pi-coding-agent`
|
|
5
|
+
* and `typebox` at extension load time — they are intentionally NOT installed in
|
|
6
|
+
* this repository (keeps the product lockfile free of the pi runtime tree). These
|
|
7
|
+
* declarations let the extension typecheck standalone for editors/LSP; the
|
|
8
|
+
* authoritative types are the real packages resolved by pi at runtime.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
declare module "@earendil-works/pi-ai" {
|
|
12
|
+
export function StringEnum<T extends readonly string[]>(
|
|
13
|
+
values: T,
|
|
14
|
+
options?: { description?: string; default?: T[number] },
|
|
15
|
+
): { type: "string"; enum: T; description?: string; default?: T[number] };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare module "@earendil-works/pi-coding-agent" {
|
|
19
|
+
export interface ExtensionContext {
|
|
20
|
+
cwd: string;
|
|
21
|
+
hasUI: boolean;
|
|
22
|
+
model?: { id: string; provider?: string };
|
|
23
|
+
ui: {
|
|
24
|
+
setStatus(id: string, text: string): void;
|
|
25
|
+
notify(
|
|
26
|
+
text: string,
|
|
27
|
+
level?: "info" | "error" | "success" | "warning",
|
|
28
|
+
): void;
|
|
29
|
+
setWidget?(id: string, lines: string[]): void;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface ToolResult {
|
|
34
|
+
content: { type: "text"; text: string }[];
|
|
35
|
+
details: Record<string, unknown>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface ToolDefinition {
|
|
39
|
+
name: string;
|
|
40
|
+
label?: string;
|
|
41
|
+
description: string;
|
|
42
|
+
parameters: any;
|
|
43
|
+
execute(
|
|
44
|
+
toolCallId: string,
|
|
45
|
+
params: any,
|
|
46
|
+
signal: AbortSignal | undefined,
|
|
47
|
+
onUpdate: any,
|
|
48
|
+
ctx: ExtensionContext,
|
|
49
|
+
): Promise<ToolResult> | ToolResult;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface ExtensionAPI {
|
|
53
|
+
on(
|
|
54
|
+
event: string,
|
|
55
|
+
handler: (event: any, ctx: ExtensionContext) => any,
|
|
56
|
+
): void;
|
|
57
|
+
registerTool(definition: ToolDefinition): void;
|
|
58
|
+
registerCommand(
|
|
59
|
+
name: string,
|
|
60
|
+
definition: {
|
|
61
|
+
description?: string;
|
|
62
|
+
handler: (args: string | undefined, ctx: ExtensionContext) => any;
|
|
63
|
+
},
|
|
64
|
+
): void;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
declare module "typebox" {
|
|
69
|
+
export const Type: any;
|
|
70
|
+
}
|