From a8914e7305488041301f8c53293a8e12b92912ea Mon Sep 17 00:00:00 2001 From: Roo Code Date: Thu, 24 Jul 2025 19:42:07 +0000 Subject: [PATCH] fix: clarify apply_diff is for surgical edits only, not full file rewrites - Updated apply_diff tool description to emphasize it is for SURGICAL EDITS ONLY - Added CRITICAL warning that apply_diff is NOT for rewriting entire files - Added clear examples of GOOD use (single line change) vs BAD use (entire file rewrite) - Updated rules section to emphasize using apply_diff for small, targeted changes - Applied same improvements to both single-file and multi-file diff strategies - Fixed ESLint warning by removing unused directive This should help prevent models from misusing apply_diff to rewrite entire files when they should be using write_to_file instead. --- .../strategies/multi-file-search-replace.ts | 10 ++- .../diff/strategies/multi-search-replace.ts | 71 ++++++++++++------- src/core/prompts/sections/rules.ts | 5 +- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/src/core/diff/strategies/multi-file-search-replace.ts b/src/core/diff/strategies/multi-file-search-replace.ts index d875d723a1..d0391695fb 100644 --- a/src/core/diff/strategies/multi-file-search-replace.ts +++ b/src/core/diff/strategies/multi-file-search-replace.ts @@ -93,10 +93,18 @@ export class MultiFileSearchReplaceDiffStrategy implements DiffStrategy { getToolDescription(args: { cwd: string; toolOptions?: { [key: string]: string } }): string { return `## apply_diff -Description: Request to apply targeted modifications to one or more files by searching for specific sections of content and replacing them. This tool supports both single-file and multi-file operations, allowing you to make changes across multiple files in a single request. +Description: Request to apply PRECISE, TARGETED modifications to one or more files by searching for specific sections of content and replacing them. This tool is for SURGICAL EDITS ONLY - small, specific changes to existing code. This tool supports both single-file and multi-file operations, allowing you to make changes across multiple files in a single request. + +**CRITICAL: This tool is NOT for rewriting entire files or making large-scale changes. Use write_to_file for that purpose.** **IMPORTANT: You MUST use multiple files in a single operation whenever possible to maximize efficiency and minimize back-and-forth.** +Key characteristics: +- Ideal for changing specific lines, functions, or small code blocks +- Preserves the rest of the file unchanged +- Requires exact matching of existing content (including whitespace) +- Can perform multiple small edits in one operation across multiple files + You can perform multiple distinct search and replace operations within a single \`apply_diff\` call by providing multiple SEARCH/REPLACE blocks in the \`diff\` parameter. This is the preferred way to make several targeted changes efficiently. The SEARCH section must exactly match existing content including whitespace and indentation. diff --git a/src/core/diff/strategies/multi-search-replace.ts b/src/core/diff/strategies/multi-search-replace.ts index b90ef4072d..e6f7711083 100644 --- a/src/core/diff/strategies/multi-search-replace.ts +++ b/src/core/diff/strategies/multi-search-replace.ts @@ -1,5 +1,3 @@ -/* eslint-disable no-irregular-whitespace */ - import { distance } from "fastest-levenshtein" import { ToolProgressStatus } from "@roo-code/types" @@ -92,11 +90,22 @@ export class MultiSearchReplaceDiffStrategy implements DiffStrategy { getToolDescription(args: { cwd: string; toolOptions?: { [key: string]: string } }): string { return `## apply_diff -Description: Request to apply targeted modifications to an existing file by searching for specific sections of content and replacing them. This tool is ideal for precise, surgical edits when you know the exact content to change. It helps maintain proper indentation and formatting. +Description: Request to apply PRECISE, TARGETED modifications to an existing file by searching for specific sections of content and replacing them. This tool is for SURGICAL EDITS ONLY - small, specific changes to existing code. + +**CRITICAL: This tool is NOT for rewriting entire files or making large-scale changes. Use write_to_file for that purpose.** + +Key characteristics: +- Ideal for changing specific lines, functions, or small code blocks +- Preserves the rest of the file unchanged +- Requires exact matching of existing content (including whitespace) +- Can perform multiple small edits in one operation + You can perform multiple distinct search and replace operations within a single \`apply_diff\` call by providing multiple SEARCH/REPLACE blocks in the \`diff\` parameter. This is the preferred way to make several targeted changes efficiently. -The SEARCH section must exactly match existing content including whitespace and indentation. -If you're not confident in the exact content to search for, use the read_file tool first to get the exact content. + +IMPORTANT: The SEARCH section must exactly match existing content including whitespace and indentation. If you're not confident in the exact content to search for, use the read_file tool first to get the exact content. + When applying the diffs, be extra careful to remember to change any closing brackets or other syntax that may be affected by the diff farther down in the file. + ALWAYS make as many changes in a single 'apply_diff' request as possible using multiple SEARCH/REPLACE blocks Parameters: @@ -116,7 +125,7 @@ Diff format: \`\`\` -Example: +Example of GOOD use (surgical edit - changing a single line): Original file: \`\`\` @@ -129,7 +138,18 @@ Original file: Search/Replace content: \`\`\` -<<<<<<< SEARCH +\\<<<<<<< SEARCH +:start_line:2 +------- + total = 0 +\\======= + total = 0 # Initialize sum +\\>>>>>>> REPLACE +\`\`\` + +Example of BAD use (trying to rewrite entire file - use write_to_file instead): +\`\`\` +\\<<<<<<< SEARCH :start_line:1 ------- def calculate_total(items): @@ -137,35 +157,34 @@ def calculate_total(items): for item in items: total += item return total -======= +\\======= def calculate_total(items): """Calculate total with 10% markup""" return sum(item * 1.1 for item in items) ->>>>>>> REPLACE - +\\>>>>>>> REPLACE \`\`\` -Search/Replace content with multiple edits: +Example with multiple surgical edits: \`\`\` -<<<<<<< SEARCH +\\<<<<<<< SEARCH :start_line:1 ------- def calculate_total(items): sum = 0 -======= +\\======= def calculate_sum(items): sum = 0 ->>>>>>> REPLACE +\\>>>>>>> REPLACE -<<<<<<< SEARCH +\\<<<<<<< SEARCH :start_line:4 ------- total += item return total -======= +\\======= sum += item return sum ->>>>>>> REPLACE +\\>>>>>>> REPLACE \`\`\` @@ -349,31 +368,31 @@ Only use a single line of '=======' between search and replacement content, beca Regex parts: 1. (?:^|\n) -   Ensures the first marker starts at the beginning of the file or right after a newline. + Ensures the first marker starts at the beginning of the file or right after a newline. 2. (?>>>>>> REPLACE)(?=\n|$) -   Matches the final “>>>>>>> REPLACE” marker on its own line (and requires a following newline or the end of file). + Matches the final ">>>>>>> REPLACE" marker on its own line (and requires a following newline or the end of file). */ let matches = [ diff --git a/src/core/prompts/sections/rules.ts b/src/core/prompts/sections/rules.ts index 5828568ac4..d1b95cb7ae 100644 --- a/src/core/prompts/sections/rules.ts +++ b/src/core/prompts/sections/rules.ts @@ -8,7 +8,7 @@ function getEditingInstructions(diffStrategy?: DiffStrategy): string { // Collect available editing tools if (diffStrategy) { availableTools.push( - "apply_diff (for replacing lines in existing files)", + "apply_diff (for surgical edits - small, targeted changes to specific lines or functions)", "write_to_file (for creating new files or complete file rewrites)", ) } else { @@ -34,7 +34,8 @@ function getEditingInstructions(diffStrategy?: DiffStrategy): string { if (availableTools.length > 1) { instructions.push( - "- You should always prefer using other editing tools over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files.", + "- CRITICAL: Use apply_diff for small, surgical edits to existing files. Do NOT use apply_diff to rewrite entire files - use write_to_file for that purpose.", + "- You should always prefer using apply_diff, insert_content, or search_and_replace over write_to_file when making changes to existing files since write_to_file is much slower and cannot handle large files.", ) }