(params: EditParams, task: Task, callbacks: ToolCallbacks)
| 26 | readonly name = "edit" as const |
| 27 | |
| 28 | async execute(params: EditParams, task: Task, callbacks: ToolCallbacks): Promise<void> { |
| 29 | const { file_path: relPath, old_string: oldString, new_string: newString, replace_all: replaceAll } = params |
| 30 | const { askApproval, handleError, pushToolResult } = callbacks |
| 31 | |
| 32 | try { |
| 33 | // Validate required parameters |
| 34 | if (!relPath) { |
| 35 | task.consecutiveMistakeCount++ |
| 36 | task.recordToolError("edit") |
| 37 | pushToolResult(await task.sayAndCreateMissingParamError("edit", "file_path")) |
| 38 | return |
| 39 | } |
| 40 | |
| 41 | if (!oldString) { |
| 42 | task.consecutiveMistakeCount++ |
| 43 | task.recordToolError("edit") |
| 44 | pushToolResult(await task.sayAndCreateMissingParamError("edit", "old_string")) |
| 45 | return |
| 46 | } |
| 47 | |
| 48 | if (newString === undefined) { |
| 49 | task.consecutiveMistakeCount++ |
| 50 | task.recordToolError("edit") |
| 51 | pushToolResult(await task.sayAndCreateMissingParamError("edit", "new_string")) |
| 52 | return |
| 53 | } |
| 54 | |
| 55 | // Check old_string !== new_string |
| 56 | if (oldString === newString) { |
| 57 | task.consecutiveMistakeCount++ |
| 58 | task.recordToolError("edit") |
| 59 | pushToolResult( |
| 60 | formatResponse.toolError( |
| 61 | "'old_string' and 'new_string' are identical. No changes needed. If you want to make a change, ensure 'old_string' and 'new_string' are different.", |
| 62 | ), |
| 63 | ) |
| 64 | return |
| 65 | } |
| 66 | |
| 67 | const accessAllowed = task.rooIgnoreController?.validateAccess(relPath) |
| 68 | |
| 69 | if (!accessAllowed) { |
| 70 | await task.say("rooignore_error", relPath) |
| 71 | pushToolResult(formatResponse.rooIgnoreError(relPath)) |
| 72 | return |
| 73 | } |
| 74 | |
| 75 | // Check if file is write-protected |
| 76 | const isWriteProtected = task.rooProtectedController?.isWriteProtected(relPath) || false |
| 77 | |
| 78 | const absolutePath = path.resolve(task.cwd, relPath) |
| 79 | |
| 80 | const fileExists = await fileExistsAtPath(absolutePath) |
| 81 | if (!fileExists) { |
| 82 | task.consecutiveMistakeCount++ |
| 83 | task.recordToolError("edit") |
| 84 | const errorMessage = `File not found: ${relPath}. Cannot perform edit on a non-existent file.` |
| 85 | await task.say("error", errorMessage) |
no test coverage detected