Skip to content

Commit b41df44

Browse files
committed
fix(edit): preserve mismatch hint size bound
1 parent 4fa4226 commit b41df44

2 files changed

Lines changed: 7 additions & 18 deletions

File tree

src/agents/sessions/tools/edit.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe("edit tool", () => {
4646
).rejects.toThrow(/Current file contents:\nactual current content/);
4747
});
4848

49-
it("truncates exact-match mismatch hints without splitting unicode characters", async () => {
49+
it("truncates exact-match mismatch hints without splitting UTF-16 surrogate pairs", async () => {
5050
const boundaryEmoji = "🙂";
5151
const filePath = await createTempFile(`${"a".repeat(799)}${boundaryEmoji}tail`);
5252
const tool = createEditTool(tmpDir);
@@ -60,7 +60,7 @@ describe("edit tool", () => {
6060
},
6161
undefined,
6262
),
63-
).rejects.toThrow(`${"a".repeat(799)}${boundaryEmoji}\n... (truncated)`);
63+
).rejects.toThrow(`${"a".repeat(799)}\n... (truncated)`);
6464
});
6565

6666
it("recovers success after a post-write throw when the edit already applied", async () => {

src/agents/sessions/tools/edit.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
} from "node:fs/promises";
1212
import { Box, Container, Spacer, Text } from "@earendil-works/pi-tui";
1313
import { Type } from "typebox";
14+
import { truncateUtf16Safe } from "../../../shared/utf16-slice.js";
1415
import { renderDiff } from "../../modes/interactive/components/diff.js";
1516
import type { AgentTool } from "../../runtime/index.js";
1617
import { textResult } from "../../tools/common.js";
@@ -173,23 +174,11 @@ function didEditLikelyApply(params: {
173174
);
174175
}
175176

176-
function createMismatchHintSnippet(currentContent: string): string {
177-
let snippet = "";
178-
let length = 0;
179-
180-
for (const char of currentContent) {
181-
if (length === EDIT_MISMATCH_HINT_LIMIT) {
182-
return `${snippet}\n... (truncated)`;
183-
}
184-
snippet += char;
185-
length += 1;
186-
}
187-
188-
return snippet;
189-
}
190-
191177
function appendMismatchHint(error: Error, currentContent: string): Error {
192-
const snippet = createMismatchHintSnippet(currentContent);
178+
const snippet =
179+
currentContent.length <= EDIT_MISMATCH_HINT_LIMIT
180+
? currentContent
181+
: `${truncateUtf16Safe(currentContent, EDIT_MISMATCH_HINT_LIMIT)}\n... (truncated)`;
193182
const enhanced = new Error(`${error.message}\nCurrent file contents:\n${snippet}`, {
194183
cause: error,
195184
});

0 commit comments

Comments
 (0)