@heyhuynhgiabuu/pi-diff 0.8.1 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/core/apply-patch.d.ts +18 -3
- package/dist/core/apply-patch.d.ts.map +1 -1
- package/dist/core/apply-patch.js +492 -116
- package/dist/core/apply-patch.js.map +1 -1
- package/dist/core/replace.d.ts +8 -0
- package/dist/core/replace.d.ts.map +1 -1
- package/dist/core/replace.js +38 -19
- package/dist/core/replace.js.map +1 -1
- package/dist/core/text-encoding.d.ts +4 -2
- package/dist/core/text-encoding.d.ts.map +1 -1
- package/dist/core/text-encoding.js +13 -6
- package/dist/core/text-encoding.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +125 -76
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ import { access as accessFile, readFile, writeFile } from "node:fs/promises";
|
|
|
25
25
|
import { extname, relative } from "node:path";
|
|
26
26
|
import { codeToANSI } from "@shikijs/cli";
|
|
27
27
|
import * as Diff from "diff";
|
|
28
|
-
import { executeApplyPatch, formatApplyPatchResult } from "./core/apply-patch.js";
|
|
28
|
+
import { executeApplyPatch, formatApplyPatchResult, parseApplyPatchInput, } from "./core/apply-patch.js";
|
|
29
29
|
import { configIndicatorStyle, loadPiDiffConfig } from "./core/config.js";
|
|
30
30
|
import { computeHunkBlocks, getSepStyle, parseDiff, parsePatchFiles, resolveSepStyle, sepLabelSplit, sepLabelUnified, } from "./core/diff.js";
|
|
31
31
|
import { applyDiffPalette as applySharedDiffPalette, lang as detectDiffLanguage, renderSplit as renderSharedSplit, resolveDiffColors as resolveSharedDiffColors, themeCacheKey as sharedThemeCacheKey, } from "./review/hunk-preview.js";
|
|
@@ -1219,13 +1219,13 @@ export default async function diffRendererExtension(pi) {
|
|
|
1219
1219
|
const TOOL_RESULT_INDENT = " ";
|
|
1220
1220
|
const TOOL_HEADER_LEFT_PAD = 0;
|
|
1221
1221
|
const DIFF_BODY_LEFT_PAD = 0;
|
|
1222
|
-
/**
|
|
1222
|
+
/** Keep `edit` on the default host Box: no extra edge padding, one title/body separator. */
|
|
1223
1223
|
const EDIT_DIFF_RESULT_FRAME = {
|
|
1224
|
-
headerLeftPad:
|
|
1225
|
-
bodyLeftPad:
|
|
1226
|
-
topPad:
|
|
1224
|
+
headerLeftPad: 0,
|
|
1225
|
+
bodyLeftPad: 0,
|
|
1226
|
+
topPad: 0,
|
|
1227
1227
|
bottomPad: 1,
|
|
1228
|
-
previewBottomPad:
|
|
1228
|
+
previewBottomPad: 0,
|
|
1229
1229
|
};
|
|
1230
1230
|
function resolvePreviewDiffColors(theme) {
|
|
1231
1231
|
resolveDiffColors(theme);
|
|
@@ -1266,8 +1266,8 @@ export default async function diffRendererExtension(pi) {
|
|
|
1266
1266
|
}
|
|
1267
1267
|
function formatToolErrorResult(name, message, theme) {
|
|
1268
1268
|
const meta = theme.fg("error", theme.bold(formatToolHeaderName(name)));
|
|
1269
|
-
const header = formatToolFrameHeaderText({ meta, theme,
|
|
1270
|
-
return `${header}\n
|
|
1269
|
+
const header = formatToolFrameHeaderText({ meta, theme, bottomPad: 1 });
|
|
1270
|
+
return `${header}\n${theme.fg("error", message)}`;
|
|
1271
1271
|
}
|
|
1272
1272
|
function summarizeApplyPatchChanges(changes, theme) {
|
|
1273
1273
|
const labels = changes.map((change) => formatToolHeaderPath(theme, sp(change.path)));
|
|
@@ -1279,7 +1279,6 @@ export default async function diffRendererExtension(pi) {
|
|
|
1279
1279
|
const applied = Array.isArray(result?.applied) ? result.applied : [];
|
|
1280
1280
|
if (!applied.length)
|
|
1281
1281
|
return false;
|
|
1282
|
-
const w = termW();
|
|
1283
1282
|
const previewable = applied.filter((change) => {
|
|
1284
1283
|
if (typeof change?.path !== "string")
|
|
1285
1284
|
return false;
|
|
@@ -1289,7 +1288,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1289
1288
|
return typeof change.oldContent === "string";
|
|
1290
1289
|
return false;
|
|
1291
1290
|
});
|
|
1292
|
-
if (previewable.length
|
|
1291
|
+
if (!previewable.length)
|
|
1293
1292
|
return false;
|
|
1294
1293
|
if (previewable.length === 1) {
|
|
1295
1294
|
const change = previewable[0];
|
|
@@ -1297,7 +1296,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1297
1296
|
clearToolHeaderBg(text);
|
|
1298
1297
|
resolvePreviewDiffColors(theme);
|
|
1299
1298
|
const lineCount = change.newContent.split("\n").length;
|
|
1300
|
-
const newHdr =
|
|
1299
|
+
const newHdr = theme.fg("success", `✓ new file (${lineCount} lines)`);
|
|
1301
1300
|
const fp = change.path;
|
|
1302
1301
|
const pk = `ap:nf:${sharedThemeCacheKey(theme)}:${fp}:${lineCount}`;
|
|
1303
1302
|
if (ctx.state._nfk !== pk) {
|
|
@@ -1321,13 +1320,12 @@ export default async function diffRendererExtension(pi) {
|
|
|
1321
1320
|
typeof change.oldContent === "string" &&
|
|
1322
1321
|
typeof change.path === "string") {
|
|
1323
1322
|
const parsed = parseDiff(change.oldContent, change.newContent ?? "");
|
|
1324
|
-
setDiffPreviewTask(text, "ap", (
|
|
1323
|
+
setDiffPreviewTask(text, "ap", () => formatToolFrameHeaderText({
|
|
1325
1324
|
meta: `${theme.fg("toolTitle", theme.bold(formatToolHeaderName("apply_patch")))}${TOOL_RESULT_INDENT}${theme.fg("muted", `(1 change)`)}${TOOL_RESULT_INDENT}${formatToolHeaderPath(theme, sp(change.path))}`,
|
|
1326
1325
|
theme,
|
|
1327
|
-
width,
|
|
1328
1326
|
topPad: 0,
|
|
1329
1327
|
bottomPad: 1,
|
|
1330
|
-
}), parsed, detectDiffLanguage(change.path), MAX_PREVIEW_LINES, theme, ctx, { previewBottomPad:
|
|
1328
|
+
}), parsed, detectDiffLanguage(change.path), MAX_PREVIEW_LINES, theme, ctx, { previewBottomPad: 0, compactGutter: true });
|
|
1331
1329
|
return true;
|
|
1332
1330
|
}
|
|
1333
1331
|
return false;
|
|
@@ -1351,13 +1349,12 @@ export default async function diffRendererExtension(pi) {
|
|
|
1351
1349
|
chars += parsed.chars;
|
|
1352
1350
|
lines.push(...parsed.lines);
|
|
1353
1351
|
}
|
|
1354
|
-
setDiffPreviewTask(text, "ap", (
|
|
1352
|
+
setDiffPreviewTask(text, "ap", () => formatToolFrameHeaderText({
|
|
1355
1353
|
meta: `${theme.fg("toolTitle", theme.bold(formatToolHeaderName("apply_patch")))}${TOOL_RESULT_INDENT}${theme.fg("muted", `(${previewable.length} changes)`)} ${summarizeThemed(added, removed, theme)}${TOOL_RESULT_INDENT}${summarizeApplyPatchChanges(previewable, theme)}`,
|
|
1356
1354
|
theme,
|
|
1357
|
-
width,
|
|
1358
1355
|
topPad: 0,
|
|
1359
1356
|
bottomPad: 1,
|
|
1360
|
-
}), { lines, added, removed, chars }, mixedLanguage ? undefined : language, MAX_PREVIEW_LINES, theme, ctx, { previewBottomPad:
|
|
1357
|
+
}), { lines, added, removed, chars }, mixedLanguage ? undefined : language, MAX_PREVIEW_LINES, theme, ctx, { previewBottomPad: 0, compactGutter: true });
|
|
1361
1358
|
return true;
|
|
1362
1359
|
}
|
|
1363
1360
|
function editEditsCountLabel(edits, diffLines, theme) {
|
|
@@ -1442,7 +1439,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1442
1439
|
return bottom ? `${main}\n${bottom}` : main;
|
|
1443
1440
|
};
|
|
1444
1441
|
text.__piDiffTask = {
|
|
1445
|
-
placeholder: joinHeaderBody(termW(), padDiffBody(theme.fg("muted", "
|
|
1442
|
+
placeholder: joinHeaderBody(termW(), padDiffBody(theme.fg("muted", "rendering diff…"), frame?.bodyLeftPad)),
|
|
1446
1443
|
fallback: header(termW()),
|
|
1447
1444
|
invalidate: ctx.invalidate,
|
|
1448
1445
|
key: (width) => {
|
|
@@ -1499,6 +1496,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1499
1496
|
registerToolIfEnabled("write", {
|
|
1500
1497
|
...origWrite,
|
|
1501
1498
|
name: "write",
|
|
1499
|
+
renderShell: "default",
|
|
1502
1500
|
async execute(tid, params, sig, upd, ctx) {
|
|
1503
1501
|
const fp = params.path ?? params.file_path ?? "";
|
|
1504
1502
|
let old = null;
|
|
@@ -1547,7 +1545,6 @@ export default async function diffRendererExtension(pi) {
|
|
|
1547
1545
|
const label = isNew ? "create" : "write";
|
|
1548
1546
|
const text = ctx.lastComponent ?? new TextComponent("", 0, 0);
|
|
1549
1547
|
resolveDiffColors(theme);
|
|
1550
|
-
const w = termW();
|
|
1551
1548
|
const stats = writeCallStatsSuffix(ctx.toolCallId, theme);
|
|
1552
1549
|
if (args?.content && !ctx.argsComplete) {
|
|
1553
1550
|
const n = String(args.content).split("\n").length;
|
|
@@ -1557,7 +1554,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1557
1554
|
return text;
|
|
1558
1555
|
}
|
|
1559
1556
|
if (args?.content && ctx.argsComplete && isNew) {
|
|
1560
|
-
const title =
|
|
1557
|
+
const title = formatToolFrameHeaderText({ label, filePath: fp, theme, topPad: 0, bottomPad: 1 });
|
|
1561
1558
|
const previewKey = `create:${sharedThemeCacheKey(theme)}:${fp}:${String(args.content).length}`;
|
|
1562
1559
|
if (ctx.state._previewKey !== previewKey) {
|
|
1563
1560
|
ctx.state._previewKey = previewKey;
|
|
@@ -1596,7 +1593,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1596
1593
|
if (d?._type === "diff") {
|
|
1597
1594
|
setDiffPreviewTask(text, "wd", "", d.diff, d.language, MAX_RENDER_LINES, theme, ctx, {
|
|
1598
1595
|
omitHeader: true,
|
|
1599
|
-
previewBottomPad:
|
|
1596
|
+
previewBottomPad: 0,
|
|
1600
1597
|
compactGutter: true,
|
|
1601
1598
|
});
|
|
1602
1599
|
return text;
|
|
@@ -1604,15 +1601,14 @@ export default async function diffRendererExtension(pi) {
|
|
|
1604
1601
|
if (d?._type === "noChange") {
|
|
1605
1602
|
text.__piDiffTask = undefined;
|
|
1606
1603
|
clearToolHeaderBg(text);
|
|
1607
|
-
text.setText(
|
|
1604
|
+
text.setText(theme.fg("muted", "✓ no changes"));
|
|
1608
1605
|
return text;
|
|
1609
1606
|
}
|
|
1610
1607
|
if (d?._type === "new") {
|
|
1611
1608
|
const { lines: lineCount, content: rawContent, filePath: fp } = d;
|
|
1612
1609
|
clearToolHeaderBg(text);
|
|
1613
1610
|
resolvePreviewDiffColors(theme);
|
|
1614
|
-
const
|
|
1615
|
-
const newHdr = bgLine(`${theme.fg("success", `✓ new file (${lineCount} lines)`)}`, w);
|
|
1611
|
+
const newHdr = theme.fg("success", `✓ new file (${lineCount} lines)`);
|
|
1616
1612
|
const pk = `nf:${sharedThemeCacheKey(theme)}:${fp}:${lineCount}`;
|
|
1617
1613
|
if (ctx.state._nfk !== pk) {
|
|
1618
1614
|
ctx.state._nfk = pk;
|
|
@@ -1629,7 +1625,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1629
1625
|
const maxShow = hlLines.length;
|
|
1630
1626
|
const preview = hlLines.slice(0, maxShow).join("\n").replace(/\n+$/, "");
|
|
1631
1627
|
const rem = hlLines.length - maxShow;
|
|
1632
|
-
const moreLine = rem > 0 ? `\n${bgLine(
|
|
1628
|
+
const moreLine = rem > 0 ? `\n${bgLine(theme.fg("muted", `… ${rem} more lines`), width)}` : "";
|
|
1633
1629
|
return `${newHdr}\n${padDiffBody(preview)}${moreLine}`;
|
|
1634
1630
|
},
|
|
1635
1631
|
};
|
|
@@ -1637,7 +1633,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1637
1633
|
return text;
|
|
1638
1634
|
}
|
|
1639
1635
|
clearToolHeaderBg(text);
|
|
1640
|
-
text.setText(
|
|
1636
|
+
text.setText(theme.fg("dim", String(result?.content?.[0]?.text ?? "written").slice(0, 120)));
|
|
1641
1637
|
return text;
|
|
1642
1638
|
},
|
|
1643
1639
|
});
|
|
@@ -1698,6 +1694,7 @@ export default async function diffRendererExtension(pi) {
|
|
|
1698
1694
|
registerToolIfEnabled("edit", {
|
|
1699
1695
|
...origEdit,
|
|
1700
1696
|
name: "edit",
|
|
1697
|
+
renderShell: "default",
|
|
1701
1698
|
parameters: {
|
|
1702
1699
|
...(origEdit.parameters || {}),
|
|
1703
1700
|
properties: {
|
|
@@ -1752,34 +1749,19 @@ export default async function diffRendererExtension(pi) {
|
|
|
1752
1749
|
},
|
|
1753
1750
|
renderCall(args, theme, ctx) {
|
|
1754
1751
|
const fp = args?.path ?? args?.file_path ?? "";
|
|
1755
|
-
const operations = getEditOperations(args);
|
|
1756
1752
|
const text = ctx.lastComponent ?? new TextComponent("", 0, 0);
|
|
1757
1753
|
resolvePreviewDiffColors(theme);
|
|
1758
1754
|
const stats = editCallStatsSuffix(ctx.toolCallId, theme);
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
}));
|
|
1770
|
-
}
|
|
1771
|
-
else {
|
|
1772
|
-
text.setText(formatToolFrameHeader({
|
|
1773
|
-
label: "edit",
|
|
1774
|
-
filePath: fp,
|
|
1775
|
-
theme,
|
|
1776
|
-
width: termW(),
|
|
1777
|
-
suffix: stats,
|
|
1778
|
-
topPad: EDIT_DIFF_RESULT_FRAME.topPad,
|
|
1779
|
-
bottomPad: EDIT_DIFF_RESULT_FRAME.bottomPad,
|
|
1780
|
-
headerLeftPad: EDIT_DIFF_RESULT_FRAME.headerLeftPad,
|
|
1781
|
-
}));
|
|
1782
|
-
}
|
|
1755
|
+
setToolHeaderBg(text);
|
|
1756
|
+
text.setText(formatToolFrameHeaderText({
|
|
1757
|
+
label: "edit",
|
|
1758
|
+
filePath: fp,
|
|
1759
|
+
theme,
|
|
1760
|
+
suffix: stats,
|
|
1761
|
+
topPad: EDIT_DIFF_RESULT_FRAME.topPad,
|
|
1762
|
+
bottomPad: EDIT_DIFF_RESULT_FRAME.bottomPad,
|
|
1763
|
+
headerLeftPad: EDIT_DIFF_RESULT_FRAME.headerLeftPad,
|
|
1764
|
+
}));
|
|
1783
1765
|
return text;
|
|
1784
1766
|
},
|
|
1785
1767
|
renderResult(result, _opt, theme, ctx) {
|
|
@@ -1821,50 +1803,117 @@ export default async function diffRendererExtension(pi) {
|
|
|
1821
1803
|
}
|
|
1822
1804
|
text.__piDiffTask = undefined;
|
|
1823
1805
|
clearToolHeaderBg(text);
|
|
1824
|
-
text.setText(
|
|
1806
|
+
text.setText(theme.fg("dim", String(result?.content?.[0]?.text ?? "edited").slice(0, 120)));
|
|
1825
1807
|
return text;
|
|
1826
1808
|
},
|
|
1827
1809
|
});
|
|
1828
1810
|
registerToolIfEnabled("apply_patch", {
|
|
1829
1811
|
name: "apply_patch",
|
|
1830
1812
|
label: "apply_patch",
|
|
1813
|
+
renderShell: "default",
|
|
1831
1814
|
description: "Multi-file patch engine. One call can add, update, delete, or move multiple files. Uses structured JSON changes array.",
|
|
1832
1815
|
parameters: {
|
|
1833
1816
|
type: "object",
|
|
1817
|
+
additionalProperties: false,
|
|
1834
1818
|
properties: {
|
|
1835
1819
|
changes: {
|
|
1836
1820
|
type: "array",
|
|
1837
|
-
|
|
1821
|
+
minItems: 1,
|
|
1822
|
+
description: "Changes are fully prepared before commit; filesystem rollback after a commit failure is best effort.",
|
|
1838
1823
|
items: {
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1824
|
+
oneOf: [
|
|
1825
|
+
{
|
|
1826
|
+
type: "object",
|
|
1827
|
+
additionalProperties: false,
|
|
1828
|
+
properties: {
|
|
1829
|
+
path: { type: "string", minLength: 1, description: "Path within the current workspace." },
|
|
1830
|
+
action: { type: "string", enum: ["add"] },
|
|
1831
|
+
content: { type: "string", description: "Content for the new file." },
|
|
1832
|
+
},
|
|
1833
|
+
required: ["path", "action", "content"],
|
|
1846
1834
|
},
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1835
|
+
{
|
|
1836
|
+
type: "object",
|
|
1837
|
+
additionalProperties: false,
|
|
1838
|
+
properties: {
|
|
1839
|
+
path: { type: "string", minLength: 1, description: "Path within the current workspace." },
|
|
1840
|
+
action: { type: "string", enum: ["update"] },
|
|
1841
|
+
oldText: { type: "string", minLength: 1, description: "Unique text to find." },
|
|
1842
|
+
newText: { type: "string", description: "Replacement text; omitted means empty text." },
|
|
1843
|
+
},
|
|
1844
|
+
required: ["path", "action", "oldText"],
|
|
1845
|
+
},
|
|
1846
|
+
{
|
|
1847
|
+
type: "object",
|
|
1848
|
+
additionalProperties: false,
|
|
1849
|
+
properties: {
|
|
1850
|
+
path: { type: "string", minLength: 1, description: "Path within the current workspace." },
|
|
1851
|
+
action: { type: "string", enum: ["update"] },
|
|
1852
|
+
edits: {
|
|
1853
|
+
type: "array",
|
|
1854
|
+
minItems: 1,
|
|
1855
|
+
items: {
|
|
1856
|
+
type: "object",
|
|
1857
|
+
additionalProperties: false,
|
|
1858
|
+
properties: {
|
|
1859
|
+
oldText: { type: "string", minLength: 1 },
|
|
1860
|
+
newText: { type: "string" },
|
|
1861
|
+
},
|
|
1862
|
+
required: ["oldText", "newText"],
|
|
1863
|
+
},
|
|
1864
|
+
},
|
|
1865
|
+
},
|
|
1866
|
+
required: ["path", "action", "edits"],
|
|
1867
|
+
},
|
|
1868
|
+
{
|
|
1869
|
+
type: "object",
|
|
1870
|
+
additionalProperties: false,
|
|
1871
|
+
properties: {
|
|
1872
|
+
path: { type: "string", minLength: 1, description: "Path within the current workspace." },
|
|
1873
|
+
action: { type: "string", enum: ["delete"] },
|
|
1874
|
+
},
|
|
1875
|
+
required: ["path", "action"],
|
|
1876
|
+
},
|
|
1877
|
+
{
|
|
1878
|
+
type: "object",
|
|
1879
|
+
additionalProperties: false,
|
|
1880
|
+
properties: {
|
|
1881
|
+
path: { type: "string", minLength: 1, description: "Source path within the current workspace." },
|
|
1882
|
+
action: { type: "string", enum: ["move"] },
|
|
1883
|
+
movePath: {
|
|
1884
|
+
type: "string",
|
|
1885
|
+
minLength: 1,
|
|
1886
|
+
description: "Destination path within the current workspace.",
|
|
1887
|
+
},
|
|
1888
|
+
},
|
|
1889
|
+
required: ["path", "action", "movePath"],
|
|
1890
|
+
},
|
|
1891
|
+
],
|
|
1853
1892
|
},
|
|
1854
1893
|
},
|
|
1855
1894
|
},
|
|
1856
1895
|
required: ["changes"],
|
|
1857
1896
|
},
|
|
1858
|
-
async execute(_tid, params) {
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1897
|
+
async execute(_tid, params, _signal, _onUpdate, ctx) {
|
|
1898
|
+
let result;
|
|
1899
|
+
try {
|
|
1900
|
+
const changes = parseApplyPatchInput(params);
|
|
1901
|
+
const toolCwd = typeof ctx?.cwd === "string" ? ctx.cwd : cwd;
|
|
1902
|
+
result = await executeApplyPatch(changes, { cwd: toolCwd, root: toolCwd });
|
|
1903
|
+
}
|
|
1904
|
+
catch (error) {
|
|
1905
|
+
result = {
|
|
1906
|
+
ok: false,
|
|
1907
|
+
applied: [],
|
|
1908
|
+
errors: [
|
|
1909
|
+
{
|
|
1910
|
+
path: "",
|
|
1911
|
+
action: "input",
|
|
1912
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1913
|
+
},
|
|
1914
|
+
],
|
|
1915
|
+
};
|
|
1916
|
+
}
|
|
1868
1917
|
const output = formatApplyPatchResult(result);
|
|
1869
1918
|
return {
|
|
1870
1919
|
content: [{ type: "text", text: output }],
|