diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 1781440adb..9451d1385f 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -1168,7 +1168,7 @@ export class Cline { pushToolResult( formatResponse.toolError( `${(error as Error)?.message}\n\n` + - `This is likely because the SEARCH block content doesn't match exactly with what's in the file.\n\n` + + `This is likely because the SEARCH block content doesn't match exactly with what's in the file, or if you used multiple SEARCH/REPLACE blocks they may not have been in the order they appear in the file.\n\n` + `The file was reverted to its original state:\n\n` + `\n${this.diffViewProvider.originalContent}\n\n\n` + `Try again with a more precise SEARCH block.\n(If you keep running into this error, you may use the write_to_file tool as a workaround.)`, @@ -1292,7 +1292,7 @@ export class Cline { } } - const { newProblemsMessage, userEdits, finalContent } = + const { newProblemsMessage, userEdits, autoFormattingEdits, finalContent } = await this.diffViewProvider.saveChanges() this.didEditFile = true // used to determine if we should wait for busy terminal to update before sending api request if (userEdits) { @@ -1306,7 +1306,10 @@ export class Cline { ) pushToolResult( `The user made the following updates to your content:\n\n${userEdits}\n\n` + - `The updated content, which includes both your original modifications and the user's edits, has been successfully saved to ${relPath.toPosix()}. Here is the full, updated content of the file:\n\n` + + (autoFormattingEdits + ? `The user's editor also applied the following auto-formatting to your content:\n\n${autoFormattingEdits}\n\n(Note: Pay close attention to changes such as single quotes being converted to double quotes, semicolons being removed or added, long lines being broken into multiple lines, adjusting indentation style, adding/removing trailing commas, etc. This will help you ensure future SEARCH/REPLACE operations to this file are accurate.)\n\n` + : "") + + `The updated content, which includes both your original modifications and the additional edits, has been successfully saved to ${relPath.toPosix()}. Here is the full, updated content of the file that was saved:\n\n` + `\n${finalContent}\n\n\n` + `Please note:\n` + `1. You do not need to re-write the file with these changes, as they have already been applied.\n` + @@ -1318,7 +1321,10 @@ export class Cline { } else { pushToolResult( `The content was successfully saved to ${relPath.toPosix()}.\n\n` + - `Here is the full, updated content of the file:\n\n` + + (autoFormattingEdits + ? `Along with your edits, the user's editor applied the following auto-formatting to your content:\n\n${autoFormattingEdits}\n\n(Note: Pay close attention to changes such as single quotes being converted to double quotes, semicolons being removed or added, long lines being broken into multiple lines, adjusting indentation style, adding/removing trailing commas, etc. This will help you ensure future SEARCH/REPLACE operations to this file are accurate.)\n\n` + : "") + + `Here is the full, updated content of the file that was saved:\n\n` + `\n${finalContent}\n\n\n` + `IMPORTANT: For any future changes to this file, use the final_file_content shown above as your reference. This content reflects the current state of the file, including any auto-formatting (e.g., if you used single quotes but the formatter converted them to double quotes). Always base your SEARCH/REPLACE operations on this final version to ensure accuracy.\n\n` + `${newProblemsMessage}`, diff --git a/src/core/prompts/system.ts b/src/core/prompts/system.ts index 8f23a50e33..1e39799303 100644 --- a/src/core/prompts/system.ts +++ b/src/core/prompts/system.ts @@ -795,9 +795,8 @@ You have access to two tools for working with files: **write_to_file** and **rep - After using either write_to_file or replace_in_file, the user's editor may automatically format the file - This auto-formatting may modify the file contents, for example: - - Breaking single lines into multiple lines (e.g. long function declarations, object literals, array definitions) + - Breaking single lines into multiple lines - Adjusting indentation to match project style (e.g. 2 spaces vs 4 spaces vs tabs) - - Standardizing spacing and line endings (e.g. removing extra whitespace, ensuring consistent newlines) - Converting single quotes to double quotes (or vice versa based on project preferences) - Organizing imports (e.g. sorting, grouping by type) - Adding/removing trailing commas in objects and arrays diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts index 5eb6a56b8f..4cc9f4b9d0 100644 --- a/src/integrations/editor/DiffViewProvider.ts +++ b/src/integrations/editor/DiffViewProvider.ts @@ -141,10 +141,16 @@ export class DiffViewProvider { async saveChanges(): Promise<{ newProblemsMessage: string | undefined userEdits: string | undefined + autoFormattingEdits: string | undefined finalContent: string | undefined }> { if (!this.relPath || !this.newContent || !this.activeDiffEditor) { - return { newProblemsMessage: undefined, userEdits: undefined, finalContent: undefined } + return { + newProblemsMessage: undefined, + userEdits: undefined, + autoFormattingEdits: undefined, + finalContent: undefined, + } } const absolutePath = path.resolve(this.cwd, this.relPath) const updatedDocument = this.activeDiffEditor.document @@ -197,18 +203,32 @@ export class DiffViewProvider { const normalizedPostSaveContent = postSaveContent.replace(/\r\n|\n/g, newContentEOL).trimEnd() + newContentEOL // this is the final content we return to the model to use as the new baseline for future edits // just in case the new content has a mix of varying EOL characters const normalizedNewContent = this.newContent.replace(/\r\n|\n/g, newContentEOL).trimEnd() + newContentEOL + + let userEdits: string | undefined if (normalizedPreSaveContent !== normalizedNewContent) { // user made changes before approving edit. let the model know about user made changes (not including post-save auto-formatting changes) - const userEdits = formatResponse.createPrettyPatch( + userEdits = formatResponse.createPrettyPatch( this.relPath.toPosix(), normalizedNewContent, normalizedPreSaveContent, ) - return { newProblemsMessage, userEdits, finalContent: normalizedPostSaveContent } + // return { newProblemsMessage, userEdits, finalContent: normalizedPostSaveContent } } else { // no changes to cline's edits - return { newProblemsMessage, userEdits: undefined, finalContent: normalizedPostSaveContent } + // return { newProblemsMessage, userEdits: undefined, finalContent: normalizedPostSaveContent } } + + let autoFormattingEdits: string | undefined + if (normalizedPreSaveContent !== normalizedPostSaveContent) { + // auto-formatting was done by the editor + autoFormattingEdits = formatResponse.createPrettyPatch( + this.relPath.toPosix(), + normalizedPreSaveContent, + normalizedPostSaveContent, + ) + } + + return { newProblemsMessage, userEdits, autoFormattingEdits, finalContent: normalizedPostSaveContent } } async revertChanges(): Promise {