feat: pass Edit code diff start line in tool return (#994)
This commit is contained in:
@@ -12,6 +12,7 @@ interface EditArgs {
|
||||
interface EditResult {
|
||||
message: string;
|
||||
replacements: number;
|
||||
startLine?: number;
|
||||
}
|
||||
|
||||
function countOccurrences(content: string, needle: string): number {
|
||||
@@ -184,13 +185,22 @@ export async function edit(args: EditArgs): Promise<EditResult> {
|
||||
(expected_replacements !== undefined && expected_replacements > 1);
|
||||
let newContent: string;
|
||||
let replacements: number;
|
||||
let startLine: number | undefined;
|
||||
|
||||
if (effectiveReplaceAll) {
|
||||
newContent = content.split(finalOldString).join(finalNewString);
|
||||
replacements = occurrences;
|
||||
// For replace_all, calculate line number of first occurrence
|
||||
const firstIndex = content.indexOf(finalOldString);
|
||||
if (firstIndex !== -1) {
|
||||
startLine = content.substring(0, firstIndex).split("\n").length;
|
||||
}
|
||||
} else {
|
||||
const index = content.indexOf(finalOldString);
|
||||
if (index === -1)
|
||||
throw new Error(`String not found in file: ${finalOldString}`);
|
||||
// Calculate the line number where old_string starts (1-indexed)
|
||||
startLine = content.substring(0, index).split("\n").length;
|
||||
newContent =
|
||||
content.substring(0, index) +
|
||||
finalNewString +
|
||||
@@ -198,9 +208,11 @@ export async function edit(args: EditArgs): Promise<EditResult> {
|
||||
replacements = 1;
|
||||
}
|
||||
await fs.writeFile(resolvedPath, newContent, "utf-8");
|
||||
|
||||
return {
|
||||
message: `Successfully replaced ${replacements} occurrence${replacements !== 1 ? "s" : ""} in ${resolvedPath}`,
|
||||
replacements,
|
||||
startLine,
|
||||
};
|
||||
} catch (error) {
|
||||
const err = error as NodeJS.ErrnoException;
|
||||
|
||||
@@ -11,9 +11,15 @@ export interface MultiEditArgs {
|
||||
file_path: string;
|
||||
edits: Edit[];
|
||||
}
|
||||
interface EditWithLine {
|
||||
description: string;
|
||||
startLine: number;
|
||||
}
|
||||
|
||||
interface MultiEditResult {
|
||||
message: string;
|
||||
edits_applied: number;
|
||||
edits: EditWithLine[];
|
||||
}
|
||||
|
||||
export async function multi_edit(
|
||||
@@ -45,7 +51,7 @@ export async function multi_edit(
|
||||
const rawContent = await fs.readFile(resolvedPath, "utf-8");
|
||||
// Normalize line endings to LF for consistent matching (Windows uses CRLF)
|
||||
let content = rawContent.replace(/\r\n/g, "\n");
|
||||
const appliedEdits: string[] = [];
|
||||
const appliedEdits: EditWithLine[] = [];
|
||||
for (let i = 0; i < edits.length; i++) {
|
||||
const edit = edits[i];
|
||||
if (!edit) continue;
|
||||
@@ -61,26 +67,33 @@ export async function multi_edit(
|
||||
`Found ${occurrences} matches of the string to replace, but replace_all is false. To replace all occurrences, set replace_all to true. To replace only one occurrence, please provide more context to uniquely identify the instance.\nString: ${old_string}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Calculate start line before applying the edit
|
||||
const index = content.indexOf(old_string);
|
||||
const startLine = content.substring(0, index).split("\n").length;
|
||||
|
||||
if (replace_all) {
|
||||
content = content.split(old_string).join(new_string);
|
||||
} else {
|
||||
const index = content.indexOf(old_string);
|
||||
content =
|
||||
content.substring(0, index) +
|
||||
new_string +
|
||||
content.substring(index + old_string.length);
|
||||
}
|
||||
appliedEdits.push(
|
||||
`Replaced "${old_string.substring(0, 50)}${old_string.length > 50 ? "..." : ""}" with "${new_string.substring(0, 50)}${new_string.length > 50 ? "..." : ""}"`,
|
||||
);
|
||||
appliedEdits.push({
|
||||
description: `Replaced "${old_string.substring(0, 50)}${old_string.length > 50 ? "..." : ""}" with "${new_string.substring(0, 50)}${new_string.length > 50 ? "..." : ""}"`,
|
||||
startLine,
|
||||
});
|
||||
}
|
||||
await fs.writeFile(resolvedPath, content, "utf-8");
|
||||
const editList = appliedEdits
|
||||
.map((edit, i) => `${i + 1}. ${edit}`)
|
||||
.map((edit, i) => `${i + 1}. ${edit.description}`)
|
||||
.join("\n");
|
||||
|
||||
return {
|
||||
message: `Applied ${edits.length} edit${edits.length !== 1 ? "s" : ""} to ${resolvedPath}:\n${editList}`,
|
||||
edits_applied: edits.length,
|
||||
edits: appliedEdits,
|
||||
};
|
||||
} catch (error) {
|
||||
const err = error as NodeJS.ErrnoException;
|
||||
|
||||
Reference in New Issue
Block a user