refactor(agents): use diff native APIs

This commit is contained in:
Peter Steinberger
2026-07-14 12:29:35 +01:00
parent 9c03b2310e
commit e5e8d8717e
3 changed files with 23 additions and 53 deletions
+17 -39
View File
@@ -3,7 +3,7 @@
*
* Produces colored line and intra-line highlights for the Pi TUI review surfaces.
*/
import * as Diff from "diff";
import { diffWords } from "diff";
import { theme } from "../theme/theme.js";
/**
@@ -37,59 +37,37 @@ function renderIntraLineDiff(
oldContent: string,
newContent: string,
): { removedLine: string; addedLine: string } {
const wordDiff = Diff.diffWords(oldContent, newContent);
let removedLine = "";
let addedLine = "";
let isFirstRemoved = true;
let isFirstAdded = true;
const seen = { added: false, removed: false };
for (const part of wordDiff) {
if (part.removed) {
let value = part.value;
// Strip leading whitespace from the first removed part
if (isFirstRemoved) {
const leadingWs = value.match(/^(\s*)/)?.[1] || "";
value = value.slice(leadingWs.length);
removedLine += leadingWs;
isFirstRemoved = false;
}
if (value) {
removedLine += theme.inverse(value);
}
} else if (part.added) {
let value = part.value;
// Strip leading whitespace from the first added part
if (isFirstAdded) {
const leadingWs = value.match(/^(\s*)/)?.[1] || "";
value = value.slice(leadingWs.length);
addedLine += leadingWs;
isFirstAdded = false;
}
if (value) {
addedLine += theme.inverse(value);
}
} else {
removedLine += part.value;
addedLine += part.value;
for (const part of diffWords(oldContent, newContent)) {
const kind = part.added ? "added" : part.removed ? "removed" : undefined;
let value = part.value;
if (kind) {
const changed = seen[kind] ? value : value.trimStart();
const leadingWhitespace = value.slice(0, value.length - changed.length);
value = leadingWhitespace + (changed ? theme.inverse(changed) : "");
seen[kind] = true;
}
if (!part.added) {
removedLine += value;
}
if (!part.removed) {
addedLine += value;
}
}
return { removedLine, addedLine };
}
interface RenderDiffOptions {
/** File path (unused, kept for API compatibility) */
filePath?: string;
}
/**
* Render a diff string with colored lines and intra-line change highlighting.
* - Context lines: dim/gray
* - Removed lines: red, with inverse on changed tokens
* - Added lines: green, with inverse on changed tokens
*/
export function renderDiff(diffText: string, _options: RenderDiffOptions = {}): string {
export function renderDiff(diffText: string): string {
const lines = diffText.split("\n");
const result: string[] = [];
+4 -4
View File
@@ -5,7 +5,7 @@
import { constants } from "node:fs";
import { access, readFile } from "node:fs/promises";
import * as Diff from "diff";
import { createPatch, FILE_HEADERS_ONLY, structuredPatch } from "diff";
import { levenshteinDistance } from "../../../shared/levenshtein-distance.js";
import { resolveToCwd } from "./path-utils.js";
@@ -540,9 +540,9 @@ export function generateUnifiedPatch(
newContent: string,
contextLines = 4,
): string {
return Diff.createTwoFilesPatch(path, path, oldContent, newContent, undefined, undefined, {
return createPatch(path, oldContent, newContent, undefined, undefined, {
context: contextLines,
headerOptions: Diff.FILE_HEADERS_ONLY,
headerOptions: FILE_HEADERS_ONLY,
});
}
@@ -555,7 +555,7 @@ export function generateDiffString(
newContent: string,
contextLines = 4,
): { diff: string; firstChangedLine: number | undefined } {
const hunks = Diff.structuredPatch("", "", oldContent, newContent, undefined, undefined, {
const hunks = structuredPatch("", "", oldContent, newContent, undefined, undefined, {
context: contextLines,
}).hunks;
const oldLineCount = oldContent.split("\n").length;
+2 -10
View File
@@ -291,13 +291,11 @@ function formatEditCall(
}
function formatEditResult(
args: RenderableEditArgs | undefined,
preview: EditPreview | undefined,
result: EditToolResultLike,
theme: typeof import("../../modes/interactive/theme/theme.js").theme,
isError: boolean,
): string | undefined {
const rawPath = str(args?.file_path ?? args?.path);
const previewDiff = preview && !("error" in preview) ? preview.diff : undefined;
const previewError = preview && "error" in preview ? preview.error : undefined;
if (isError) {
@@ -313,7 +311,7 @@ function formatEditResult(
const resultDiff = result.details?.diff;
if (resultDiff && resultDiff !== previewDiff) {
return renderDiff(resultDiff, { filePath: rawPath ?? undefined });
return renderDiff(resultDiff);
}
return undefined;
@@ -579,13 +577,7 @@ export function createEditToolDefinition(
}
}
const output = formatEditResult(
context.args,
callComponent?.preview,
typedResult,
theme,
context.isError,
);
const output = formatEditResult(callComponent?.preview, typedResult, theme, context.isError);
const component = (context.lastComponent as Container | undefined) ?? new Container();
component.clear();
if (!output) {