diffing 0.17.0 → 0.18.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-qNwkSjxK.mjs → cli-agent-du9TS34N.mjs} +741 -13
- package/dist/{cli-gh-BvoDabKK.mjs → cli-gh-2NEumKQB.mjs} +1 -1
- package/dist/cli.mjs +5 -4
- package/dist/client/assets/{angular-html-ByeJB0rh.js → angular-html-Des_xD-2.js} +1 -1
- package/dist/client/assets/{angular-ts-CiwZGajG.js → angular-ts-FXZjKR0Q.js} +1 -1
- package/dist/client/assets/{apl-C8k5a5fk.js → apl-CU0GH5rh.js} +1 -1
- package/dist/client/assets/{arc-B8VMoqVr.js → arc-DnvfnvVv.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-C-ng2xNL.js → architectureDiagram-3BPJPVTR-Cb41y9QS.js} +1 -1
- package/dist/client/assets/{astro-BE-h-qpp.js → astro-CUWNJBWq.js} +1 -1
- package/dist/client/assets/{blade-D-0BV1wW.js → blade-2PPtLT0e.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-DyAQuONU.js → blockDiagram-GPEHLZMM-BYxsiST2.js} +1 -1
- package/dist/client/assets/{c-Dg_Gx29H.js → c-D3K42QQV.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-k5uKTHvm.js → c4Diagram-AAUBKEIU-BU7I7J1w.js} +1 -1
- package/dist/client/assets/channel-Cx6nXkw1.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-Dod_VwYj.js → chunk-2J33WTMH-DQnKNewn.js} +1 -1
- package/dist/client/assets/{chunk-3OPIFGDE-B8HMjry-.js → chunk-3OPIFGDE-BE6bYzdw.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-TvkJVIZw.js → chunk-4BX2VUAB-CTw-Pjas.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-BsXuKAKc.js → chunk-55IACEB6-BBCsXXSw.js} +1 -1
- package/dist/client/assets/{chunk-5ZQYHXKU-BI1cj2cZ.js → chunk-5ZQYHXKU-BrM_4KH1.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-yWQ27Wk0.js → chunk-727SXJPM-B_Vz3jyP.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-B2BBCtTr.js → chunk-AQP2D5EJ-CHSGbbjn.js} +1 -1
- package/dist/client/assets/{chunk-BSJP7CBP-CXXvPXhK.js → chunk-BSJP7CBP-D6jlDOzg.js} +1 -1
- package/dist/client/assets/{chunk-CSCIHK7Q-jYiloqyi.js → chunk-CSCIHK7Q-D_02XyF0.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-DZzqIT32.js → chunk-FMBD7UC4-DxbqnfDH.js} +1 -1
- package/dist/client/assets/{chunk-KSCS5N6A-krdCf8iG.js → chunk-KSCS5N6A-_Pc1IHYq.js} +1 -1
- package/dist/client/assets/{chunk-L5ZTLDWV-0uuTmeZV.js → chunk-L5ZTLDWV-Dj8OTMjE.js} +1 -1
- package/dist/client/assets/{chunk-LZXEDZCA-BBfUgD06.js → chunk-LZXEDZCA-DQn_LdxZ.js} +2 -2
- package/dist/client/assets/{chunk-ND2GUHAM-jkir4ZKE.js → chunk-ND2GUHAM-BYbHwrXp.js} +1 -1
- package/dist/client/assets/{chunk-NZK2D7GU-DMWZNibJ.js → chunk-NZK2D7GU-Bvgyac_1.js} +1 -1
- package/dist/client/assets/{chunk-O5CBEL6O-B1e1HGaX.js → chunk-O5CBEL6O-DeRRUqxP.js} +1 -1
- package/dist/client/assets/chunk-QZHKN3VN-BkYYlBcO.js +1 -0
- package/dist/client/assets/chunk-WU5MYG2G-DyGKxcFl.js +1 -0
- package/dist/client/assets/{chunk-XPW4576I-AvbCAUav.js → chunk-XPW4576I-BrtDtomN.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DwPqBLeK.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-Mxl80axQ.js +1 -0
- package/dist/client/assets/{cobol-DQnGB_GV.js → cobol-hL9_ibhX.js} +1 -1
- package/dist/client/assets/{coffee-CDV5a89x.js → coffee-DFRt5qt1.js} +1 -1
- package/dist/client/assets/{cose-bilkent-S5V4N54A-t-mDNRF2.js → cose-bilkent-S5V4N54A-DHCJqbho.js} +1 -1
- package/dist/client/assets/{cpp-8G6b-siI.js → cpp-3A0aT-dF.js} +1 -1
- package/dist/client/assets/{crystal-CGYCC6FM.js → crystal-BzBxs8w6.js} +1 -1
- package/dist/client/assets/{css-nez4R8_Z.js → css-C5lLpDbg.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG--azesYIg.js → dagre-BM42HDAG-DOuf0bNE.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-4WJ7nKhA.js → diagram-2AECGRRQ-Bd5Jiq1y.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-C7ZGhLXn.js → diagram-5GNKFQAL-DvYLKuEY.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BobK_rbl.js → diagram-KO2AKTUF-BVvqGAtk.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-BOc-OkIS.js → diagram-LMA3HP47-QqHAHEnc.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BEtLgm86.js → diagram-OG6HWLK6-CkG5SOks.js} +1 -1
- package/dist/client/assets/{dist-DPuBwToc.js → dist-Dh8NC3tY.js} +1 -1
- package/dist/client/assets/{edge-Z5RMbJQv.js → edge-9n_aVc7U.js} +1 -1
- package/dist/client/assets/{edit-CFxbgVPV.js → edit-DlkvWCkd.js} +1 -1
- package/dist/client/assets/{elixir-d3C79FQc.js → elixir-C7ssdzaK.js} +1 -1
- package/dist/client/assets/{elm-CDAf6Uyn.js → elm-CWs6E90H.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-D-pR2GY9.js → erDiagram-TEJ5UH35-CfW0k0ip.js} +1 -1
- package/dist/client/assets/{erb-CTJk9FKH.js → erb-CdXoY37D.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-BwMCy2QV.js → flowDiagram-I6XJVG4X-CBKpQpqx.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-BI1WLJDi.js → ganttDiagram-6RSMTGT7-CS13EpgX.js} +1 -1
- package/dist/client/assets/{git-rebase-Dr0-MVoW.js → git-rebase-BSoXZvcc.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-CUfW0k1f.js → gitGraphDiagram-PVQCEYII-BN0i9pDL.js} +1 -1
- package/dist/client/assets/{glimmer-js-CXhLhyW-.js → glimmer-js-BZMH6HKs.js} +1 -1
- package/dist/client/assets/{glimmer-ts-BFAFT-VD.js → glimmer-ts-DXSo27g6.js} +1 -1
- package/dist/client/assets/{glsl-D7yanhgY.js → glsl-Cl8JUVz8.js} +1 -1
- package/dist/client/assets/{graphql-CpoDxrok.js → graphql-CNR_SNqJ.js} +1 -1
- package/dist/client/assets/{hack-BL5fmC4q.js → hack-iAxNUz76.js} +1 -1
- package/dist/client/assets/{haml-ClAE6RVM.js → haml-D11gKVlW.js} +1 -1
- package/dist/client/assets/{handlebars-nHw91uOv.js → handlebars-BAAs9kjt.js} +1 -1
- package/dist/client/assets/{html-BIiOKqgG.js → html-C-zWst2_.js} +1 -1
- package/dist/client/assets/{html-derivative-D1nPnuOK.js → html-derivative-Bu6k8r8J.js} +1 -1
- package/dist/client/assets/{http-B_QcRZjt.js → http-B_xQ7YQ1.js} +1 -1
- package/dist/client/assets/{hurl-CZE0DsD3.js → hurl-B7IYz3qL.js} +1 -1
- package/dist/client/assets/index-1GDpp-wO.css +1 -0
- package/dist/client/assets/{index-Erqhm7rW.js → index-D_eRtjau.js} +49 -49
- package/dist/client/assets/{infoDiagram-5YYISTIA-w2M_OHua.js → infoDiagram-5YYISTIA-Choq89cB.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-CW_l9PGx.js → ishikawaDiagram-YF4QCWOH-CZY99mk-.js} +1 -1
- package/dist/client/assets/{java-CXTqX09w.js → java-BPJVzio0.js} +1 -1
- package/dist/client/assets/{javascript-9z9ABBep.js → javascript-DiOMtf_A.js} +1 -1
- package/dist/client/assets/{jinja-Cluf_5Bk.js → jinja-l7JM-8PK.js} +1 -1
- package/dist/client/assets/{jison-CqCEUtc4.js → jison-CAc6lM-g.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-D-YwusBa.js → journeyDiagram-JHISSGLW-CDbADAMs.js} +1 -1
- package/dist/client/assets/{json-BMq_bPP8.js → json-DqZO-AEh.js} +1 -1
- package/dist/client/assets/{jsx-Djij59b9.js → jsx-UqnCpKTP.js} +1 -1
- package/dist/client/assets/{julia-DybzCMnh.js → julia-DlbfYJz3.js} +1 -1
- package/dist/client/assets/{just-4ChcAr9-.js → just-9ze8Wi6d.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Brvoukmm.js → kanban-definition-UN3LZRKU-DgrkeisF.js} +1 -1
- package/dist/client/assets/{latex-CS2TtFXG.js → latex-_9Fzq-E3.js} +1 -1
- package/dist/client/assets/{line-CqxM-stA.js → line-b-Rcrqbg.js} +1 -1
- package/dist/client/assets/{linear-C7T82059.js → linear-C_RFbWEw.js} +1 -1
- package/dist/client/assets/{liquid-84AtYenm.js → liquid-CMiBoRv6.js} +1 -1
- package/dist/client/assets/{lua-DJzFx3Cf.js → lua-BzfULkCh.js} +1 -1
- package/dist/client/assets/{marko-BLw9BV9E.js → marko-BfcVqnF5.js} +1 -1
- package/dist/client/assets/{mdc-BjZejN3b.js → mdc-BKqkdcKC.js} +1 -1
- package/dist/client/assets/{mermaid-parser.core-BdiEBAsd.js → mermaid-parser.core-DiJRF2JX.js} +1 -1
- package/dist/client/assets/{mermaid.core-BsnKhnrM.js → mermaid.core-2WkwaCuC.js} +3 -3
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-CBaIFnbc.js → mindmap-definition-RKZ34NQL-BYxdNWsh.js} +1 -1
- package/dist/client/assets/{nginx-DuamCwvX.js → nginx-DiNLSsbI.js} +1 -1
- package/dist/client/assets/{nim-Bt8c9-ge.js → nim-CohF0tPX.js} +1 -1
- package/dist/client/assets/{perl-D52AfmwC.js → perl-Q-a6BHYR.js} +1 -1
- package/dist/client/assets/{php-BBMlJg0_.js → php-DEj4odG7.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-BlmPajcA.js → pieDiagram-4H26LBE5-DIMAUXZJ.js} +1 -1
- package/dist/client/assets/{pug-DFHmDqEE.js → pug-vqq1Jo-6.js} +1 -1
- package/dist/client/assets/{qml-C0333o-g.js → qml-DkOoIH_j.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-Bqlm_zZk.js → quadrantDiagram-W4KKPZXB-DKoe-k2E.js} +1 -1
- package/dist/client/assets/{r-DZFmvIgR.js → r-Cen6c1F0.js} +1 -1
- package/dist/client/assets/{razor-BIGLkWzR.js → razor-SY8AQA9t.js} +1 -1
- package/dist/client/assets/{regexp-BW6jpgf9.js → regexp-CjphwwlN.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-B1PrtUeD.js → requirementDiagram-4Y6WPE33-Du9fS-Dw.js} +1 -1
- package/dist/client/assets/{review-export-BlgD3bdw.js → review-export-FIT7B1uP.js} +1 -1
- package/dist/client/assets/{rst-Cj51ZJaa.js → rst-B79v9bjn.js} +1 -1
- package/dist/client/assets/{ruby-lMhGjwpf.js → ruby-Dia4QaOO.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-D2HtUNVF.js → sankeyDiagram-5OEKKPKP-CsezsM2Z.js} +1 -1
- package/dist/client/assets/{sas-BWSQku7l.js → sas-CYRTwHiQ.js} +1 -1
- package/dist/client/assets/{scss-CdRPuhLN.js → scss-DNWCy5-q.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-D9SQy0XI.js → sequenceDiagram-3UESZ5HK-CNovbaFC.js} +1 -1
- package/dist/client/assets/{shellscript-DOfOBXcj.js → shellscript-BSQLDkAe.js} +1 -1
- package/dist/client/assets/{shellsession-7XAOCVni.js → shellsession-CfvHV3oR.js} +1 -1
- package/dist/client/assets/{soy-DDnzVRIw.js → soy-DLwu5RtN.js} +1 -1
- package/dist/client/assets/{sql-Ba34agKe.js → sql-DlyzTy0P.js} +1 -1
- package/dist/client/assets/{src-BO-qT_v_.js → src-DNJJnOd8.js} +1 -1
- package/dist/client/assets/{stata-BQlYGHQU.js → stata-Djh-WYVT.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-7IEYjFRo.js → stateDiagram-AJRCARHV-cV6R_6CN.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-jmBy204V.js +1 -0
- package/dist/client/assets/{surrealql-BET1l7SW.js → surrealql-Cu-G0NVH.js} +1 -1
- package/dist/client/assets/{svelte-Bd7ZOeQI.js → svelte-CDA2MakI.js} +1 -1
- package/dist/client/assets/{templ-BYvRQdOw.js → templ-H2xc1tDE.js} +1 -1
- package/dist/client/assets/{tex-CT8DpKxX.js → tex-DJ6mQsYC.js} +1 -1
- package/dist/client/assets/{timeline-definition-PNZ67QCA-CurQYWmi.js → timeline-definition-PNZ67QCA-BlCMASdx.js} +1 -1
- package/dist/client/assets/{ts-tags-D4iPPwau.js → ts-tags-bYEWgmJO.js} +1 -1
- package/dist/client/assets/{tsx-Dgk_Aw-B.js → tsx-CtTBiWFd.js} +1 -1
- package/dist/client/assets/{twig-abRNWeh3.js → twig-CgXr9wNF.js} +1 -1
- package/dist/client/assets/{typescript-BgR1JqdC.js → typescript-Na7Lj9Vl.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-DbrRBL5S.js → vennDiagram-CIIHVFJN-CvcrIycD.js} +1 -1
- package/dist/client/assets/{vue-DSkhKq4Q.js → vue-BtOd_AfK.js} +1 -1
- package/dist/client/assets/{vue-html-J0jWoD9X.js → vue-html-CVlcjzDD.js} +1 -1
- package/dist/client/assets/{vue-vine-BgX5MC8-.js → vue-vine-k7M6KtfE.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-DIFXQsoP.js → wardleyDiagram-YWT4CUSO-BUDJvh59.js} +1 -1
- package/dist/client/assets/{xml-Ca53xGLB.js → xml-Brz46P3k.js} +1 -1
- package/dist/client/assets/{xsl-CNnXclYV.js → xsl-Bh5vdfXi.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-CmfInPqa.js → xychartDiagram-2RQKCTM6-T2Bb0lF_.js} +1 -1
- package/dist/client/assets/{yaml-CjjyUhfg.js → yaml-CRsmB7sL.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/{completions-7YSX1neu.mjs → completions-2aHVTmiJ.mjs} +17 -0
- package/dist/completions-CYa5usLb.mjs +2 -0
- package/dist/{mcp-DhynPewa.mjs → mcp-H7ytYScV.mjs} +397 -6
- package/dist/mockup-format-CM3ivHHX.mjs +322 -0
- 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/{review-export-GW4KNsGN.mjs → review-export-DoST2oPt.mjs} +1 -1
- package/dist/{server-CEbp7K-k.mjs → server-CiE24vh-.mjs} +1567 -15
- package/dist/{setup-BnS_rSxK.mjs → setup-BwWZ9Fzq.mjs} +1 -1
- package/extensions/pi/index.ts +452 -5
- package/package.json +1 -1
- package/dist/client/assets/channel-DsuXeLi4.js +0 -1
- package/dist/client/assets/chunk-QZHKN3VN-D5b3mBJ2.js +0 -1
- package/dist/client/assets/chunk-WU5MYG2G-C1Pa4Y04.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-DCnVfYt-.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-BPa1Jkt-.js +0 -1
- package/dist/client/assets/index-BR6EGJ-g.css +0 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-DP6swlL9.js +0 -1
- package/dist/completions-5rtfoxB9.mjs +0 -2
- package/dist/plan-format-BwJh5JSE.mjs +0 -144
- /package/dist/{comment-format-B85NHZnG.mjs → comment-format-D4mCqr7T.mjs} +0 -0
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
const MOCKUP_MAX_SCREEN_BYTES = Math.floor(1.5 * 1024 * 1024);
|
|
2
|
+
const MOCKUP_SCREEN_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/;
|
|
3
|
+
function isMockupViewport(value) {
|
|
4
|
+
return value === "desktop" || value === "tablet" || value === "mobile";
|
|
5
|
+
}
|
|
6
|
+
function normalizeMockupViewport(value) {
|
|
7
|
+
return isMockupViewport(value) ? value : "desktop";
|
|
8
|
+
}
|
|
9
|
+
/** Effective viewport of a comment; legacy comments (no viewport) anchor on desktop. */
|
|
10
|
+
function commentViewport(comment) {
|
|
11
|
+
return comment.viewport ?? "desktop";
|
|
12
|
+
}
|
|
13
|
+
function defaultScreenLabel(id) {
|
|
14
|
+
if (id === "main") return "Main";
|
|
15
|
+
return id.split(/[-_]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
16
|
+
}
|
|
17
|
+
function slugifyScreenId(raw) {
|
|
18
|
+
const slug = raw.trim().toLowerCase().replace(/\.html?$/i, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
19
|
+
if (!MOCKUP_SCREEN_ID_RE.test(slug)) return null;
|
|
20
|
+
return slug;
|
|
21
|
+
}
|
|
22
|
+
function normalizeSubmitScreens(input) {
|
|
23
|
+
const hasHtml = typeof input.html === "string" && input.html.length > 0;
|
|
24
|
+
const hasScreens = Array.isArray(input.screens) && input.screens.length > 0;
|
|
25
|
+
if (hasHtml && hasScreens) return {
|
|
26
|
+
ok: false,
|
|
27
|
+
error: "Provide either html or screens, not both"
|
|
28
|
+
};
|
|
29
|
+
const raw = hasScreens ? input.screens : hasHtml ? [{
|
|
30
|
+
id: "main",
|
|
31
|
+
label: "Main",
|
|
32
|
+
html: input.html
|
|
33
|
+
}] : [];
|
|
34
|
+
if (raw.length === 0) return {
|
|
35
|
+
ok: false,
|
|
36
|
+
error: "A mockup html body or screens[] is required"
|
|
37
|
+
};
|
|
38
|
+
if (raw.length > 12) return {
|
|
39
|
+
ok: false,
|
|
40
|
+
error: `At most 12 screens are allowed`
|
|
41
|
+
};
|
|
42
|
+
const seen = /* @__PURE__ */ new Set();
|
|
43
|
+
const screens = [];
|
|
44
|
+
for (const item of raw) {
|
|
45
|
+
if (typeof item.html !== "string" || !item.html.trim()) return {
|
|
46
|
+
ok: false,
|
|
47
|
+
error: "Each screen needs a non-empty html body"
|
|
48
|
+
};
|
|
49
|
+
if (Buffer.byteLength(item.html, "utf8") > 1572864) return {
|
|
50
|
+
ok: false,
|
|
51
|
+
error: `Each screen must be ≤ ${MOCKUP_MAX_SCREEN_BYTES} bytes`
|
|
52
|
+
};
|
|
53
|
+
const id = item.id ? slugifyScreenId(item.id) : slugifyScreenId("main");
|
|
54
|
+
if (!id) return {
|
|
55
|
+
ok: false,
|
|
56
|
+
error: `Invalid screen id "${item.id ?? ""}"`
|
|
57
|
+
};
|
|
58
|
+
if (seen.has(id)) return {
|
|
59
|
+
ok: false,
|
|
60
|
+
error: `Duplicate screen id "${id}"`
|
|
61
|
+
};
|
|
62
|
+
seen.add(id);
|
|
63
|
+
const label = typeof item.label === "string" && item.label.trim() ? item.label.trim() : defaultScreenLabel(id);
|
|
64
|
+
screens.push({
|
|
65
|
+
id,
|
|
66
|
+
label,
|
|
67
|
+
html: item.html.replace(/\r\n/g, "\n")
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
ok: true,
|
|
72
|
+
screens
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//#endregion
|
|
76
|
+
//#region src/lib/plan-format.ts
|
|
77
|
+
/**
|
|
78
|
+
* Serialize a reviewed plan into the `<plan-review>` XML envelope handed back to
|
|
79
|
+
* a waiting agent. The diff-review counterpart is {@link formatComments}; this
|
|
80
|
+
* keeps the two handoffs structurally consistent so an agent learns one shape.
|
|
81
|
+
*
|
|
82
|
+
* Shared by the server's `/api/plan-review/await` handoff, the `diffing plan`
|
|
83
|
+
* CLI, and the MCP server so every channel emits byte-identical output.
|
|
84
|
+
*/
|
|
85
|
+
function escapeAttr$1(value) {
|
|
86
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
87
|
+
}
|
|
88
|
+
/** Human-readable guidance the agent should act on, derived from the verdict. */
|
|
89
|
+
function decisionSummary(decision) {
|
|
90
|
+
switch (decision) {
|
|
91
|
+
case "approved": return "The reviewer APPROVED this plan. Proceed with implementation exactly as described, taking any inline comments into account.";
|
|
92
|
+
case "rejected": return "The reviewer REJECTED this plan. Do NOT proceed. Reconsider the approach based on the comments; only continue once a new plan is approved.";
|
|
93
|
+
case "changes-requested": return "The reviewer REQUESTED CHANGES. Revise the plan to address every open comment below, then resubmit the updated plan for re-review (do not start implementation yet).";
|
|
94
|
+
case "comment-only": return "The reviewer chose COMMENT-ONLY mode. You MUST NOT edit any files or implement the plan. Only reply to the comments below — answer questions, provide clarification, or discuss. The decision comment (if present) is your prompt for this chat.";
|
|
95
|
+
default: return "This plan has not been decided yet. Wait for the reviewer to approve, reject, or request changes.";
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Resolve the line label for a plan comment: `plan` for whole-plan notes,
|
|
100
|
+
* `12-15` for a multi-line selection, otherwise the single line number.
|
|
101
|
+
*/
|
|
102
|
+
function lineLabel(comment) {
|
|
103
|
+
if (comment.lineNumber === 0) return "plan";
|
|
104
|
+
if (comment.startLineNumber && comment.startLineNumber !== comment.lineNumber) return `${comment.startLineNumber}-${comment.lineNumber}`;
|
|
105
|
+
return `${comment.lineNumber}`;
|
|
106
|
+
}
|
|
107
|
+
function formatPlanReview(plan, options = {}) {
|
|
108
|
+
const { viewingVersion, mode } = options;
|
|
109
|
+
const isHistorical = viewingVersion !== void 0 && viewingVersion !== plan.version;
|
|
110
|
+
const versions = plan.versions ?? [];
|
|
111
|
+
const historical = isHistorical && versions.length > 0 ? versions.find((v) => v.version === viewingVersion) : void 0;
|
|
112
|
+
const bodyToRender = historical ? historical.body : plan.body;
|
|
113
|
+
const titleToRender = historical ? historical.title : plan.title;
|
|
114
|
+
const visibleComments = isHistorical ? (plan.comments ?? []).filter((c) => c.createdAtPlanVersion === viewingVersion) : plan.comments ?? [];
|
|
115
|
+
const modeAttr = mode && mode !== "standard" ? ` mode="${mode}"` : "";
|
|
116
|
+
const lines = [];
|
|
117
|
+
lines.push("<plan-review>");
|
|
118
|
+
lines.push(" <instructions>");
|
|
119
|
+
lines.push(" You are an AI coding assistant receiving a human review of a plan you submitted.");
|
|
120
|
+
if (mode === "comment-only") lines.push(" ⚠️ COMMENT-ONLY MODE: You MUST NOT edit any files or implement the plan. Your only task is to reply to the comments below — answer questions, provide clarification, or discuss. The decision comment (if present) is your prompt for this chat.");
|
|
121
|
+
else {
|
|
122
|
+
lines.push(" - The \"decision\" attribute is the headline verdict: \"approved\", \"rejected\", \"changes-requested\", \"comment-only\", or \"pending\".");
|
|
123
|
+
lines.push(" - <decision-summary> tells you, in plain language, what to do next based on that verdict.");
|
|
124
|
+
lines.push(" - <decision-comment> is the reviewer's overall note (may be absent).");
|
|
125
|
+
lines.push(" - <plan-body> is the exact markdown of the plan being reviewed. Inline comments target lines within it.");
|
|
126
|
+
lines.push(" - Each <comment> targets a line (\"line=42\"), a range (\"line=12-15\"), or the whole plan (\"line=plan\").");
|
|
127
|
+
lines.push(" \"section\" names the nearest markdown heading for context. Only address comments with status=\"open\".");
|
|
128
|
+
lines.push(" - <context> is structured: <quote> is the exact text the human highlighted (when present);");
|
|
129
|
+
lines.push(" <source line=\"N\" end-line=\"M\"> is the full plan source line(s). Prefer <quote> when deciding what they meant.");
|
|
130
|
+
lines.push(" - Optional severity=\"blocking|nit|question|praise\" on <comment>: treat blocking as must-fix,");
|
|
131
|
+
lines.push(" nit as optional polish, question as needing an answer, praise as positive note (no action required).");
|
|
132
|
+
lines.push("");
|
|
133
|
+
lines.push(" HOW TO RESPOND:");
|
|
134
|
+
lines.push(" - If approved: proceed with the work.");
|
|
135
|
+
lines.push(" - If changes-requested: revise the plan and resubmit it for another review round.");
|
|
136
|
+
lines.push(" - If rejected: stop and rethink; do not implement.");
|
|
137
|
+
lines.push(" - If comment-only: do NOT implement; only reply to comments.");
|
|
138
|
+
lines.push(" Prefer the diffing CLI or MCP (port-agnostic, no copy-paste):");
|
|
139
|
+
lines.push(" diffing plan reply <comment-id> --body \"...\" --model \"<your-model-name>\"");
|
|
140
|
+
lines.push(" diffing plan resolve <comment-id>");
|
|
141
|
+
lines.push(" diffing plan submit <revised-plan.md> --id <plan-id> # resubmit a new version for re-review");
|
|
142
|
+
lines.push(" (Or the equivalent MCP tools: reply_to_plan_comment, resolve_plan_comment, submit_plan.)");
|
|
143
|
+
}
|
|
144
|
+
lines.push(" </instructions>");
|
|
145
|
+
const decidedAttr = plan.decidedAt ? ` decided-at="${new Date(plan.decidedAt).toISOString()}"` : "";
|
|
146
|
+
const viewingAttr = isHistorical ? ` viewing-version="${viewingVersion}"` : "";
|
|
147
|
+
lines.push(` <plan id="${escapeAttr$1(plan.id)}" title="${escapeAttr$1(titleToRender)}" version="${plan.version}" decision="${plan.decision}"${decidedAttr}${viewingAttr}${modeAttr}>`);
|
|
148
|
+
lines.push(` <decision-summary><![CDATA[${decisionSummary(plan.decision)}]]></decision-summary>`);
|
|
149
|
+
const trimmedDecisionComment = plan.decisionComment?.trim();
|
|
150
|
+
if (trimmedDecisionComment) lines.push(` <decision-comment><![CDATA[${trimmedDecisionComment}]]></decision-comment>`);
|
|
151
|
+
if (isHistorical) lines.push(` <viewing-version-info><![CDATA[Reviewing historical version ${viewingVersion} of ${plan.version}. Comments are filtered to those anchored to v${viewingVersion}.]]></viewing-version-info>`);
|
|
152
|
+
lines.push(` <plan-body><![CDATA[${bodyToRender}]]></plan-body>`);
|
|
153
|
+
if (visibleComments.length > 0) {
|
|
154
|
+
lines.push(" <comments>");
|
|
155
|
+
for (const comment of visibleComments) {
|
|
156
|
+
const sectionAttr = comment.sectionTitle ? ` section="${escapeAttr$1(comment.sectionTitle)}"` : "";
|
|
157
|
+
const isoDate = new Date(comment.createdAt).toISOString();
|
|
158
|
+
const versionAttr = ` plan-version="${comment.createdAtPlanVersion ?? plan.version}"`;
|
|
159
|
+
const severityAttr = comment.severity && comment.severity !== "none" ? ` severity="${comment.severity}"` : "";
|
|
160
|
+
lines.push(` <comment id="${escapeAttr$1(comment.id)}" line="${lineLabel(comment)}"${sectionAttr} status="${comment.status}"${severityAttr} created-at="${isoDate}"${versionAttr}>`);
|
|
161
|
+
if (comment.lineNumber !== 0 && (comment.lineContent || comment.selectedQuote)) {
|
|
162
|
+
const start = comment.startLineNumber && comment.startLineNumber !== comment.lineNumber ? comment.startLineNumber : comment.lineNumber;
|
|
163
|
+
const end = comment.lineNumber;
|
|
164
|
+
const endAttr = end !== start ? ` end-line="${end}"` : "";
|
|
165
|
+
lines.push(` <context line="${start}"${endAttr}>`);
|
|
166
|
+
if (comment.selectedQuote?.trim()) lines.push(` <quote><![CDATA[${comment.selectedQuote.trim()}]]></quote>`);
|
|
167
|
+
if (comment.lineContent) lines.push(` <source line="${start}"${endAttr}><![CDATA[${comment.lineContent}]]></source>`);
|
|
168
|
+
lines.push(" </context>");
|
|
169
|
+
}
|
|
170
|
+
lines.push(` <body><![CDATA[${comment.body}]]></body>`);
|
|
171
|
+
if (comment.replies && comment.replies.length > 0) {
|
|
172
|
+
lines.push(" <replies>");
|
|
173
|
+
for (const reply of comment.replies) {
|
|
174
|
+
const replyIsoDate = new Date(reply.createdAt).toISOString();
|
|
175
|
+
const roleAttr = reply.role ? ` role="${reply.role}"` : " role=\"agent\"";
|
|
176
|
+
const modelAttr = reply.model ? ` model="${escapeAttr$1(reply.model)}"` : "";
|
|
177
|
+
lines.push(` <reply id="${escapeAttr$1(reply.id)}" created-at="${replyIsoDate}"${roleAttr}${modelAttr}>`);
|
|
178
|
+
lines.push(` <![CDATA[${reply.body}]]>`);
|
|
179
|
+
lines.push(" </reply>");
|
|
180
|
+
}
|
|
181
|
+
lines.push(" </replies>");
|
|
182
|
+
}
|
|
183
|
+
lines.push(" </comment>");
|
|
184
|
+
}
|
|
185
|
+
lines.push(" </comments>");
|
|
186
|
+
}
|
|
187
|
+
lines.push(" </plan>");
|
|
188
|
+
lines.push("</plan-review>");
|
|
189
|
+
return lines.join("\n");
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Find the nearest markdown ATX heading at or above a 1-based line, so a comment
|
|
193
|
+
* can record which section of the plan it belongs to. Returns the heading text
|
|
194
|
+
* without the leading `#`s, or undefined when the line precedes any heading.
|
|
195
|
+
*/
|
|
196
|
+
function sectionTitleForLine(body, lineNumber) {
|
|
197
|
+
if (lineNumber < 1) return void 0;
|
|
198
|
+
const lines = body.split("\n");
|
|
199
|
+
const end = Math.min(lineNumber, lines.length);
|
|
200
|
+
for (let i = end - 1; i >= 0; i--) {
|
|
201
|
+
const match = /^\s{0,3}(#{1,6})\s+(.*?)\s*#*\s*$/.exec(lines[i]);
|
|
202
|
+
if (match) return match[2].trim();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Snapshot the plan text spanned by a 1-based, inclusive [start, end] line
|
|
207
|
+
* range, used as the `lineContent` anchor when a comment is created without one
|
|
208
|
+
* (e.g. posted by an agent over the API).
|
|
209
|
+
*/
|
|
210
|
+
function extractPlanLines(body, startLine, endLine) {
|
|
211
|
+
if (startLine < 1) return "";
|
|
212
|
+
const lines = body.split("\n");
|
|
213
|
+
const from = Math.max(1, startLine);
|
|
214
|
+
const to = Math.min(endLine, lines.length);
|
|
215
|
+
if (to < from) return "";
|
|
216
|
+
return lines.slice(from - 1, to).join("\n");
|
|
217
|
+
}
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/lib/mockup-format.ts
|
|
220
|
+
function escapeAttr(value) {
|
|
221
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
222
|
+
}
|
|
223
|
+
function mockupDecisionSummary(decision) {
|
|
224
|
+
return decisionSummary(decision).replaceAll("plan", "mockup").replaceAll("Plan", "Mockup").replaceAll("PLAN", "MOCKUP");
|
|
225
|
+
}
|
|
226
|
+
function formatMockupReview(mockup, options = {}) {
|
|
227
|
+
const { viewingVersion, mode, focusedScreen, focusedViewport, instructions } = options;
|
|
228
|
+
const isHistorical = viewingVersion !== void 0 && viewingVersion !== mockup.version;
|
|
229
|
+
const versions = mockup.versions ?? [];
|
|
230
|
+
const historical = isHistorical && versions.length > 0 ? versions.find((v) => v.version === viewingVersion) : void 0;
|
|
231
|
+
const titleToRender = historical ? historical.title : mockup.title;
|
|
232
|
+
const screensToRender = historical ? historical.screens : mockup.screens;
|
|
233
|
+
const commentVersion = viewingVersion ?? mockup.version;
|
|
234
|
+
const visibleComments = (mockup.comments ?? []).filter((comment) => comment.status === "open" && comment.createdAtMockupVersion === commentVersion && (!focusedScreen || comment.screenId === focusedScreen) && (!focusedViewport || commentViewport(comment) === focusedViewport));
|
|
235
|
+
const modeAttr = mode && mode !== "standard" ? ` mode="${mode}"` : "";
|
|
236
|
+
const screenAttr = focusedScreen ? ` screen="${escapeAttr(focusedScreen)}"` : "";
|
|
237
|
+
const viewportAttr = focusedViewport ? ` viewport="${focusedViewport}"` : "";
|
|
238
|
+
const lines = [];
|
|
239
|
+
lines.push("<mockup-review>");
|
|
240
|
+
if (instructions || mode === "comment-only") {
|
|
241
|
+
lines.push(" <instructions>");
|
|
242
|
+
if (instructions) {
|
|
243
|
+
lines.push(" You are an AI coding assistant receiving a human review of an HTML mockup you submitted.");
|
|
244
|
+
if (mode === "comment-only") lines.push(" ⚠️ COMMENT-ONLY MODE: You MUST NOT edit any files or implement the mockup. Your only task is to reply to the comments below.");
|
|
245
|
+
else {
|
|
246
|
+
lines.push(" - The \"decision\" attribute is the headline verdict: \"approved\", \"rejected\", \"changes-requested\", \"comment-only\", or \"pending\".");
|
|
247
|
+
lines.push(" - <decision-summary> tells you what to do next.");
|
|
248
|
+
lines.push(" - Each <comment> has kind=\"section|block|point\" and screen=\"<id>\".");
|
|
249
|
+
lines.push(" Locate the spot from <html> (clicked node) and <context-html> (section/parent).");
|
|
250
|
+
lines.push(" selector= is a CSS path to that node. target= is the data-diffing section when present.");
|
|
251
|
+
lines.push(" Do NOT rely on x/y/rect — those change across screens and viewports.");
|
|
252
|
+
lines.push(" - Only address comments with status=\"open\".");
|
|
253
|
+
lines.push(" - Optional severity=\"blocking|nit|question|praise\".");
|
|
254
|
+
lines.push("");
|
|
255
|
+
lines.push(" HOW TO RESPOND:");
|
|
256
|
+
lines.push(" - If approved: implement the mockup.");
|
|
257
|
+
lines.push(" - If changes-requested: revise the mockup and resubmit the same id.");
|
|
258
|
+
lines.push(" - If rejected: stop and rethink; do not implement.");
|
|
259
|
+
lines.push(" - If comment-only: do NOT implement; only reply to comments.");
|
|
260
|
+
lines.push(" Prefer the diffing CLI or MCP:");
|
|
261
|
+
lines.push(" diffing mockup reply <comment-id> --body \"...\" --model \"<your-model-name>\"");
|
|
262
|
+
lines.push(" diffing mockup resolve <comment-id>");
|
|
263
|
+
lines.push(" diffing mockup submit <file-or-dir> --id <mockup-id>");
|
|
264
|
+
}
|
|
265
|
+
} else if (mode === "comment-only") lines.push(" COMMENT-ONLY MODE: reply to the comments below; do NOT edit files or implement the mockup.");
|
|
266
|
+
lines.push(" </instructions>");
|
|
267
|
+
}
|
|
268
|
+
const decidedAttr = mockup.decidedAt ? ` decided-at="${new Date(mockup.decidedAt).toISOString()}"` : "";
|
|
269
|
+
const viewingAttr = isHistorical ? ` viewing-version="${viewingVersion}"` : "";
|
|
270
|
+
const screenIds = (screensToRender ?? []).map((s) => s.id).join(",");
|
|
271
|
+
lines.push(` <mockup id="${escapeAttr(mockup.id)}" title="${escapeAttr(titleToRender)}" version="${mockup.version}" screens="${escapeAttr(screenIds)}" decision="${mockup.decision}"${decidedAttr}${viewingAttr}${modeAttr}${screenAttr}${viewportAttr}>`);
|
|
272
|
+
lines.push(` <decision-summary><![CDATA[${mockupDecisionSummary(mockup.decision)}]]></decision-summary>`);
|
|
273
|
+
const trimmedDecisionComment = mockup.decisionComment?.trim();
|
|
274
|
+
if (trimmedDecisionComment) lines.push(` <decision-comment><![CDATA[${trimmedDecisionComment}]]></decision-comment>`);
|
|
275
|
+
if (visibleComments.length > 0) {
|
|
276
|
+
lines.push(" <comments>");
|
|
277
|
+
for (const comment of visibleComments) lines.push(formatComment(comment, mockup.version, Boolean(instructions)));
|
|
278
|
+
lines.push(" </comments>");
|
|
279
|
+
}
|
|
280
|
+
lines.push(" </mockup>");
|
|
281
|
+
lines.push("</mockup-review>");
|
|
282
|
+
return lines.join("\n");
|
|
283
|
+
}
|
|
284
|
+
function formatComment(comment, fallbackVersion, includeContext) {
|
|
285
|
+
const isoDate = new Date(comment.createdAt).toISOString();
|
|
286
|
+
const versionAttr = ` mockup-version="${comment.createdAtMockupVersion ?? fallbackVersion}"`;
|
|
287
|
+
const viewportAttr = ` viewport="${commentViewport(comment)}"`;
|
|
288
|
+
const severityAttr = comment.severity && comment.severity !== "none" ? ` severity="${comment.severity}"` : "";
|
|
289
|
+
const targetAttr = comment.target ? ` target="${escapeAttr(comment.target)}"` : "";
|
|
290
|
+
const selectorAttr = comment.selector ? ` selector="${escapeAttr(comment.selector)}"` : "";
|
|
291
|
+
const fingerprintAttr = comment.fingerprint ? ` fingerprint="${escapeAttr(comment.fingerprint)}"` : "";
|
|
292
|
+
const xAttr = comment.x !== void 0 ? ` x="${comment.x}%"` : "";
|
|
293
|
+
const yAttr = comment.y !== void 0 ? ` y="${comment.y}%"` : "";
|
|
294
|
+
const sectionXAttr = comment.sectionX !== void 0 ? ` section-x="${comment.sectionX}%"` : "";
|
|
295
|
+
const sectionYAttr = comment.sectionY !== void 0 ? ` section-y="${comment.sectionY}%"` : "";
|
|
296
|
+
const parts = [];
|
|
297
|
+
parts.push(` <comment id="${escapeAttr(comment.id)}" kind="${comment.kind}" screen="${escapeAttr(comment.screenId)}"${targetAttr}${selectorAttr}${fingerprintAttr}${xAttr}${yAttr}${sectionXAttr}${sectionYAttr} status="${comment.status}"${severityAttr} created-at="${isoDate}"${versionAttr}${viewportAttr}>`);
|
|
298
|
+
if (includeContext && (comment.html?.trim() || comment.contextHtml?.trim() || comment.snapshot?.trim())) {
|
|
299
|
+
parts.push(" <location>");
|
|
300
|
+
if (comment.html?.trim()) parts.push(` <html><![CDATA[${comment.html.trim()}]]></html>`);
|
|
301
|
+
if (comment.contextHtml?.trim()) parts.push(` <context-html><![CDATA[${comment.contextHtml.trim()}]]></context-html>`);
|
|
302
|
+
if (comment.snapshot?.trim()) parts.push(` <snapshot><![CDATA[${comment.snapshot.trim()}]]></snapshot>`);
|
|
303
|
+
parts.push(" </location>");
|
|
304
|
+
}
|
|
305
|
+
parts.push(` <body><![CDATA[${comment.body}]]></body>`);
|
|
306
|
+
if (comment.replies && comment.replies.length > 0) {
|
|
307
|
+
parts.push(" <replies>");
|
|
308
|
+
for (const reply of comment.replies) {
|
|
309
|
+
const replyIsoDate = new Date(reply.createdAt).toISOString();
|
|
310
|
+
const roleAttr = reply.role ? ` role="${reply.role}"` : " role=\"agent\"";
|
|
311
|
+
const modelAttr = reply.model ? ` model="${escapeAttr(reply.model)}"` : "";
|
|
312
|
+
parts.push(` <reply id="${escapeAttr(reply.id)}" created-at="${replyIsoDate}"${roleAttr}${modelAttr}>`);
|
|
313
|
+
parts.push(` <![CDATA[${reply.body}]]>`);
|
|
314
|
+
parts.push(" </reply>");
|
|
315
|
+
}
|
|
316
|
+
parts.push(" </replies>");
|
|
317
|
+
}
|
|
318
|
+
parts.push(" </comment>");
|
|
319
|
+
return parts.join("\n");
|
|
320
|
+
}
|
|
321
|
+
//#endregion
|
|
322
|
+
export { MOCKUP_MAX_SCREEN_BYTES as a, defaultScreenLabel as c, normalizeSubmitScreens as d, slugifyScreenId as f, sectionTitleForLine as i, isMockupViewport as l, extractPlanLines as n, MOCKUP_SCREEN_ID_RE as o, formatPlanReview as r, commentViewport as s, formatMockupReview as t, normalizeMockupViewport as u };
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as reviewDecisionSummary } from "./comment-format-
|
|
1
|
+
import { n as reviewDecisionSummary } from "./comment-format-D4mCqr7T.mjs";
|
|
2
2
|
//#region src/lib/review-export.ts
|
|
3
3
|
/**
|
|
4
4
|
* Export a review as human-readable Markdown (clipboard / download / CLI).
|