@xynogen/pix-edit 0.1.12 → 0.1.14
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/package.json +2 -2
- package/src/edit.test.ts +2 -8
- package/src/edit.ts +27 -43
- package/src/extension.ts +2 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xynogen/pix-edit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.14",
|
|
4
4
|
"description": "Pi tool — precise text replacement edit with diff rendering",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@xynogen/pix-pretty": "^1.7.
|
|
37
|
+
"@xynogen/pix-pretty": "^1.7.20",
|
|
38
38
|
"@xynogen/pix-data": "^0.3.0"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
package/src/edit.test.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import type { CursorStore, FffState } from "@xynogen/pix-pretty/fff";
|
|
3
3
|
import type { PiPrettyApi, TextComponentCtor } from "@xynogen/pix-pretty/types";
|
|
4
|
-
import {
|
|
5
|
-
getEditOperations,
|
|
6
|
-
registerEditTool,
|
|
7
|
-
summarizeEditOperations,
|
|
8
|
-
} from "./edit";
|
|
4
|
+
import { getEditOperations, registerEditTool, summarizeEditOperations } from "./edit";
|
|
9
5
|
|
|
10
6
|
class MockTextComponent {
|
|
11
7
|
private text = "";
|
|
@@ -72,9 +68,7 @@ describe("getEditOperations", () => {
|
|
|
72
68
|
|
|
73
69
|
describe("summarizeEditOperations", () => {
|
|
74
70
|
it("returns a summary string", () => {
|
|
75
|
-
const { summary } = summarizeEditOperations([
|
|
76
|
-
{ oldText: "a\nb", newText: "c\nd\ne" },
|
|
77
|
-
]);
|
|
71
|
+
const { summary } = summarizeEditOperations([{ oldText: "a\nb", newText: "c\nd\ne" }]);
|
|
78
72
|
expect(typeof summary).toBe("string");
|
|
79
73
|
expect(summary.length).toBeGreaterThan(0);
|
|
80
74
|
});
|
package/src/edit.ts
CHANGED
|
@@ -30,7 +30,9 @@ import type {
|
|
|
30
30
|
import {
|
|
31
31
|
fillToolBackground,
|
|
32
32
|
getTextContent,
|
|
33
|
+
hideCollapsedToolCall,
|
|
33
34
|
isTextContent,
|
|
35
|
+
renderCollapsedToolRow,
|
|
34
36
|
renderToolError,
|
|
35
37
|
setResultDetails,
|
|
36
38
|
termW,
|
|
@@ -167,14 +169,16 @@ export function registerEditTool(
|
|
|
167
169
|
return result;
|
|
168
170
|
},
|
|
169
171
|
|
|
170
|
-
renderCall(
|
|
171
|
-
args: EditParams,
|
|
172
|
-
theme: ThemeLike,
|
|
173
|
-
renderCtx: RenderContextLike<EditRenderState>,
|
|
174
|
-
) {
|
|
172
|
+
renderCall(args: EditParams, theme: ThemeLike, renderCtx: RenderContextLike<EditRenderState>) {
|
|
175
173
|
const fp = args?.path ?? args?.file_path ?? "";
|
|
176
174
|
const operations = getEditOperations(args);
|
|
177
175
|
const text = renderCtx.lastComponent ?? new TextComponent("", 0, 0);
|
|
176
|
+
if (
|
|
177
|
+
hideCollapsedToolCall(renderCtx.state as CollapseState, renderCtx.expanded, (value) =>
|
|
178
|
+
text.setText(value),
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
return text;
|
|
178
182
|
const hdr = `${theme.fg("toolTitle", theme.bold("edit"))} ${theme.fg("accent", sp(fp))}`;
|
|
179
183
|
|
|
180
184
|
if (operations.length === 0) {
|
|
@@ -183,10 +187,7 @@ export function registerEditTool(
|
|
|
183
187
|
}
|
|
184
188
|
|
|
185
189
|
const { summary } = summarizeEditOperations(operations);
|
|
186
|
-
const suffix =
|
|
187
|
-
operations.length === 1
|
|
188
|
-
? summary
|
|
189
|
-
: `${operations.length} edits ${summary}`;
|
|
190
|
+
const suffix = operations.length === 1 ? summary : `${operations.length} edits ${summary}`;
|
|
190
191
|
text.setText(fillToolBackground(`${hdr} ${theme.fg("muted", suffix)}`));
|
|
191
192
|
return text;
|
|
192
193
|
},
|
|
@@ -211,23 +212,26 @@ export function registerEditTool(
|
|
|
211
212
|
d?._type === "editInfo"
|
|
212
213
|
? (d.summary as string)
|
|
213
214
|
: d?._type === "multiEditInfo"
|
|
214
|
-
? `${d.editCount} edits ${d.summary}`
|
|
215
|
+
? `${d.editCount} edits · ${d.summary}`
|
|
215
216
|
: "edited";
|
|
216
|
-
|
|
217
|
+
let filePath = "";
|
|
218
|
+
if (d?._type === "editInfo") filePath = String(d.filePath ?? "");
|
|
219
|
+
else if (d?._type === "multiEditInfo") {
|
|
220
|
+
const ops = d.ops as Array<Record<string, unknown>> | undefined;
|
|
221
|
+
filePath = String(ops?.[0]?.filePath ?? "");
|
|
222
|
+
}
|
|
223
|
+
text.setText(renderCollapsedToolRow(theme, "edit", sp(filePath), summary));
|
|
217
224
|
return text;
|
|
218
225
|
}
|
|
219
226
|
|
|
220
227
|
// Single edit — full split diff
|
|
221
228
|
if (d?._type === "editInfo") {
|
|
222
229
|
const key = `ed:${diffThemeCacheKey(theme)}:${termW()}:${d.summary}:${(d.oldContent as string).length}:${(d.newContent as string).length}:${d.language ?? ""}`;
|
|
223
|
-
if (renderCtx.toolCallId)
|
|
224
|
-
trackInvalidator(renderCtx.toolCallId, renderCtx.invalidate);
|
|
230
|
+
if (renderCtx.toolCallId) trackInvalidator(renderCtx.toolCallId, renderCtx.invalidate);
|
|
225
231
|
if (renderCtx.state._edk !== key) {
|
|
226
232
|
renderCtx.state._edk = key;
|
|
227
233
|
const loc =
|
|
228
|
-
(d.editLine as number) > 0
|
|
229
|
-
? ` ${theme.fg("muted", `at line ${d.editLine}`)}`
|
|
230
|
-
: "";
|
|
234
|
+
(d.editLine as number) > 0 ? ` ${theme.fg("muted", `at line ${d.editLine}`)}` : "";
|
|
231
235
|
renderCtx.state._edt = ` ${d.summary}${loc}\n${theme.fg("muted", " rendering diff…")}`;
|
|
232
236
|
const dc = resolveDiffColors(theme);
|
|
233
237
|
const diff = parseDiff(
|
|
@@ -236,18 +240,11 @@ export function registerEditTool(
|
|
|
236
240
|
3,
|
|
237
241
|
d.editLine as number,
|
|
238
242
|
);
|
|
239
|
-
renderSplit(
|
|
240
|
-
diff,
|
|
241
|
-
d.language as string | undefined,
|
|
242
|
-
MAX_RENDER_LINES,
|
|
243
|
-
dc,
|
|
244
|
-
)
|
|
243
|
+
renderSplit(diff, d.language as string | undefined, MAX_RENDER_LINES, dc)
|
|
245
244
|
.then((rendered) => {
|
|
246
245
|
if (renderCtx.state._edk !== key) return;
|
|
247
246
|
const loc2 =
|
|
248
|
-
(d.editLine as number) > 0
|
|
249
|
-
? ` ${theme.fg("muted", `at line ${d.editLine}`)}`
|
|
250
|
-
: "";
|
|
247
|
+
(d.editLine as number) > 0 ? ` ${theme.fg("muted", `at line ${d.editLine}`)}` : "";
|
|
251
248
|
renderCtx.state._edt = ` ${d.summary}${loc2}\n${rendered}`;
|
|
252
249
|
renderCtx.invalidate();
|
|
253
250
|
})
|
|
@@ -264,8 +261,7 @@ export function registerEditTool(
|
|
|
264
261
|
// Multi-edit — stacked diffs
|
|
265
262
|
if (d?._type === "multiEditInfo") {
|
|
266
263
|
const key = `med:${diffThemeCacheKey(theme)}:${termW()}:${d.summary}:${d.editCount}:${d.diffLineCount}`;
|
|
267
|
-
if (renderCtx.toolCallId)
|
|
268
|
-
trackInvalidator(renderCtx.toolCallId, renderCtx.invalidate);
|
|
264
|
+
if (renderCtx.toolCallId) trackInvalidator(renderCtx.toolCallId, renderCtx.invalidate);
|
|
269
265
|
if (renderCtx.state._edk !== key) {
|
|
270
266
|
renderCtx.state._edk = key;
|
|
271
267
|
renderCtx.state._edt = ` ${d.editCount} edits ${d.summary}\n${theme.fg("muted", " rendering diff…")}`;
|
|
@@ -279,12 +275,7 @@ export function registerEditTool(
|
|
|
279
275
|
editLine?: number;
|
|
280
276
|
}>
|
|
281
277
|
).map((op) => {
|
|
282
|
-
const diff = parseDiff(
|
|
283
|
-
op.oldContent,
|
|
284
|
-
op.newContent,
|
|
285
|
-
3,
|
|
286
|
-
op.editLine ?? 0,
|
|
287
|
-
);
|
|
278
|
+
const diff = parseDiff(op.oldContent, op.newContent, 3, op.editLine ?? 0);
|
|
288
279
|
return renderSplit(diff, op.language, MAX_RENDER_LINES, dc);
|
|
289
280
|
}),
|
|
290
281
|
)
|
|
@@ -300,20 +291,13 @@ export function registerEditTool(
|
|
|
300
291
|
renderCtx.invalidate();
|
|
301
292
|
});
|
|
302
293
|
}
|
|
303
|
-
text.setText(
|
|
304
|
-
renderCtx.state._edt ?? ` ${d.editCount} edits ${d.summary}`,
|
|
305
|
-
);
|
|
294
|
+
text.setText(renderCtx.state._edt ?? ` ${d.editCount} edits ${d.summary}`);
|
|
306
295
|
return text;
|
|
307
296
|
}
|
|
308
297
|
|
|
309
298
|
const fallback = result.content?.[0];
|
|
310
|
-
const fallbackText =
|
|
311
|
-
|
|
312
|
-
text.setText(
|
|
313
|
-
fillToolBackground(
|
|
314
|
-
` ${theme.fg("dim", String(fallbackText).slice(0, 120))}`,
|
|
315
|
-
),
|
|
316
|
-
);
|
|
299
|
+
const fallbackText = fallback && isTextContent(fallback) ? fallback.text : "edited";
|
|
300
|
+
text.setText(fillToolBackground(` ${theme.fg("dim", String(fallbackText).slice(0, 120))}`));
|
|
317
301
|
return text;
|
|
318
302
|
},
|
|
319
303
|
});
|
package/src/extension.ts
CHANGED
|
@@ -4,15 +4,8 @@ import {
|
|
|
4
4
|
type EditToolInput,
|
|
5
5
|
} from "@earendil-works/pi-coding-agent";
|
|
6
6
|
import { CursorStore, fffState } from "@xynogen/pix-pretty/fff";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
trackInvalidator,
|
|
10
|
-
} from "@xynogen/pix-pretty/resize";
|
|
11
|
-
import type {
|
|
12
|
-
PiPrettyApi,
|
|
13
|
-
TextComponentCtor,
|
|
14
|
-
ToolFactory,
|
|
15
|
-
} from "@xynogen/pix-pretty/types";
|
|
7
|
+
import { attachResizeListener, trackInvalidator } from "@xynogen/pix-pretty/resize";
|
|
8
|
+
import type { PiPrettyApi, TextComponentCtor, ToolFactory } from "@xynogen/pix-pretty/types";
|
|
16
9
|
import { shortPath } from "@xynogen/pix-pretty/utils";
|
|
17
10
|
import { registerEditTool } from "./edit.js";
|
|
18
11
|
import { once } from "./once.ts";
|