Skip to content

Commit 563370e

Browse files
committed
create programmatic confirmation on delete_file and delete_directory
1 parent 37ca805 commit 563370e

5 files changed

Lines changed: 65 additions & 11 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ Claude can automatically use these tools:
9090
- `morph_edit_file` - Ultra-fast code editing (requires MORPH_API_KEY)
9191
- `list_directory` - List directory contents
9292
- `create_directory` - Create directories
93-
- `delete_file` - Delete files (asks for confirmation)
94-
- `delete_directory` - Delete directories recursively (asks for confirmation)
93+
- `delete_file` - Delete files (automatic confirmation prompt)
94+
- `delete_directory` - Delete directories recursively (automatic confirmation prompt)
9595
- `move_file` - Move or rename files/directories
9696
- `copy_file` - Copy files
9797

src/conversation.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,13 @@ IMPORTANT: All file operations are restricted to the current working directory f
3939
4040
When helping users:
4141
- Be concise and practical
42+
- ALWAYS explore first: Use list_directory to find files before trying to read them if you're unsure of their location
4243
- Use your tools to read files before suggesting changes
4344
{}
4445
- Search the web when you need current information or documentation
4546
- Execute bash commands to test code and verify functionality (read-only, no sudo or file modifications)
4647
- Explain your reasoning when using tools
4748
48-
File deletion safety:
49-
- ALWAYS ask the user for explicit confirmation before using delete_file or delete_directory
50-
- List the files/directories that will be deleted and wait for user approval
51-
- Never delete files without prior user confirmation
52-
5349
Testing after code changes:
5450
- After editing code files (not comments, README, or documentation), ALWAYS test the changes using execute_bash
5551
- Run appropriate build/test commands based on the project type:

src/repl.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ impl Repl {
179179
self.conversation.add_assistant_content(&content_blocks);
180180

181181
if !tool_uses.is_empty() {
182+
let mut user_cancelled = false;
183+
182184
for (_tool_id, tool_name, tool_input) in &tool_uses {
183185
if tool_name == "execute_bash" {
184186
if let Some(command) = tool_input.get("command").and_then(|v| v.as_str()) {
@@ -203,6 +205,12 @@ impl Repl {
203205
println!("{}", output.dimmed());
204206
println!();
205207
self.conversation.add_tool_result(tool_name, &output);
208+
209+
// If deletion was cancelled, stop executing remaining tools
210+
if output.contains("cancelled by user") {
211+
user_cancelled = true;
212+
break;
213+
}
206214
}
207215
Err(e) => {
208216
let error_msg = format!("Tool execution failed: {}", e);
@@ -213,6 +221,11 @@ impl Repl {
213221
}
214222
}
215223

224+
// If user cancelled deletion, don't make another API request - let them respond
225+
if user_cancelled {
226+
return Ok(());
227+
}
228+
216229
// After executing tools, get another response from Claude
217230
let request = CreateMessageRequest {
218231
model: self.model.clone(),

src/tools/mod.rs

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,21 @@ use codesearch::CodeSearchTool;
1111
use filesystem::FileSystemTool;
1212
use search::WebSearchTool;
1313
use serde_json::Value;
14+
use std::io::{self, Write};
1415

1516
pub use types::{add_code_search_tool, get_tools, get_tools_with_morph};
1617

18+
fn confirm_action(prompt: &str) -> Result<bool> {
19+
print!("{} (y/n): ", prompt);
20+
io::stdout().flush()?;
21+
22+
let mut input = String::new();
23+
io::stdin().read_line(&mut input)?;
24+
25+
let answer = input.trim().to_lowercase();
26+
Ok(answer == "y" || answer == "yes")
27+
}
28+
1729
/// ToolExecutor handles execution of tool calls from Claude
1830
pub struct ToolExecutor {
1931
fs_tool: FileSystemTool,
@@ -57,8 +69,23 @@ impl ToolExecutor {
5769
.as_str()
5870
.ok_or_else(|| SofosError::ToolExecution("Missing 'path' parameter".to_string()))?;
5971

60-
let content = self.fs_tool.read_file(path)?;
61-
Ok(format!("File content of '{}':\n\n{}", path, content))
72+
match self.fs_tool.read_file(path) {
73+
Ok(content) => Ok(format!("File content of '{}':\n\n{}", path, content)),
74+
Err(e) => {
75+
if matches!(e, SofosError::FileNotFound(_)) {
76+
let parent_dir = std::path::Path::new(path)
77+
.parent()
78+
.and_then(|p| p.to_str())
79+
.unwrap_or(".");
80+
Err(SofosError::ToolExecution(format!(
81+
"File not found: '{}'. Suggestion: Use list_directory with path '{}' to see available files.",
82+
path, parent_dir
83+
)))
84+
} else {
85+
Err(e)
86+
}
87+
}
88+
}
6289
}
6390
"write_file" => {
6491
let path = input["path"]
@@ -155,6 +182,15 @@ impl ToolExecutor {
155182
.as_str()
156183
.ok_or_else(|| SofosError::ToolExecution("Missing 'path' parameter".to_string()))?;
157184

185+
let confirmed = confirm_action(&format!("Delete file '{}'?", path))?;
186+
187+
if !confirmed {
188+
return Ok(format!(
189+
"File deletion cancelled by user. The file '{}' was not deleted.",
190+
path
191+
));
192+
}
193+
158194
self.fs_tool.delete_file(path)?;
159195
Ok(format!("Successfully deleted file '{}'", path))
160196
}
@@ -163,6 +199,15 @@ impl ToolExecutor {
163199
.as_str()
164200
.ok_or_else(|| SofosError::ToolExecution("Missing 'path' parameter".to_string()))?;
165201

202+
let confirmed = confirm_action(&format!("Delete directory '{}' and all its contents?", path))?;
203+
204+
if !confirmed {
205+
return Ok(format!(
206+
"Directory deletion cancelled by user. The directory '{}' and its contents were not deleted. What would you like to do instead?",
207+
path
208+
));
209+
}
210+
166211
self.fs_tool.delete_directory(path)?;
167212
Ok(format!("Successfully deleted directory '{}'", path))
168213
}

src/tools/types.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ fn execute_bash_tool() -> Tool {
121121
fn delete_file_tool() -> Tool {
122122
Tool {
123123
name: "delete_file".to_string(),
124-
description: "Delete a file in the current workspace. IMPORTANT: Always ask the user for confirmation before deleting files. Use this only after explicit user approval.".to_string(),
124+
description: "Delete a file in the current workspace. A confirmation prompt will be shown to the user before deletion.".to_string(),
125125
input_schema: json!({
126126
"type": "object",
127127
"properties": {
@@ -138,7 +138,7 @@ fn delete_file_tool() -> Tool {
138138
fn delete_directory_tool() -> Tool {
139139
Tool {
140140
name: "delete_directory".to_string(),
141-
description: "Delete a directory and all its contents in the current workspace. IMPORTANT: Always ask the user for confirmation before deleting directories. Use this only after explicit user approval.".to_string(),
141+
description: "Delete a directory and all its contents in the current workspace. A confirmation prompt will be shown to the user before deletion.".to_string(),
142142
input_schema: json!({
143143
"type": "object",
144144
"properties": {

0 commit comments

Comments
 (0)