# 删除文件确认功能实现文档 ## 1. 功能概述 在 AI 返回删除文件命令时,前端拦截并弹出确认对话框,用户确认后才执行删除操作。 ## 2. 架构设计 ### 2.1 消息流程 ``` AI 后端 → 删除文件工具调用 → 前端拦截 → 用户确认对话框 ↓ 确定/取消 ↓ 执行删除/返回取消结果 ↓ 返回 TOOL_EXECUTION_RESULT ↓ AI 后端 ``` ### 2.2 关键原则 **前端必须返回结果**:无论用户选择什么,前端都必须向后端返回 `TOOL_EXECUTION_RESULT`,否则后端会等待超时。 ## 3. 实现方案 ### 3.1 修改位置 文件:`src/utils/messageHandler.ts` 在处理工具调用的函数中,找到删除文件的工具处理逻辑。 ### 3.2 核心代码实现 ```typescript /** * 处理删除文件工具调用(带用户确认) */ async function handleDeleteFileTool( toolCall: any, panel: vscode.WebviewPanel ): Promise { const filePath = toolCall.arguments.filePath; // 根据实际参数名调整 // 弹出确认对话框 const confirmed = await vscode.window.showWarningMessage( `确定要删除文件吗?\n\n${filePath}`, { modal: true, // 模态对话框,阻止其他操作 detail: '此操作不可撤销' }, '确定删除', '取消' ); // 用户确认删除 if (confirmed === '确定删除') { try { // 执行删除操作 const uri = vscode.Uri.file(filePath); await vscode.workspace.fs.delete(uri, { recursive: false, // 如果是目录需要设置为 true useTrash: true // 移到回收站而非永久删除(推荐) }); // 返回成功结果 return { type: 'TOOL_EXECUTION_RESULT', toolCallId: toolCall.id, result: JSON.stringify({ success: true, message: `文件已删除: ${filePath}` }) }; } catch (error) { // 删除失败 return { type: 'TOOL_EXECUTION_RESULT', toolCallId: toolCall.id, result: JSON.stringify({ success: false, error: `删除失败: ${error.message}` }) }; } } // 用户取消或关闭对话框 return { type: 'TOOL_EXECUTION_RESULT', toolCallId: toolCall.id, result: JSON.stringify({ success: false, message: '用户取消了删除操作' }) }; } ``` ### 3.3 集成到消息处理流程 在 `messageHandler.ts` 的工具调用处理逻辑中: ```typescript // 示例:在处理工具调用的地方 async function handleToolCall(toolCall: any, panel: vscode.WebviewPanel) { switch (toolCall.name) { case 'deleteFile': // 根据实际工具名称调整 return await handleDeleteFileTool(toolCall, panel); case 'deleteDirectory': // 如果有删除目录的工具 return await handleDeleteDirectoryTool(toolCall, panel); // ... 其他工具 } } ``` ## 4. 用户体验优化 ### 4.1 对话框样式 ```typescript const confirmed = await vscode.window.showWarningMessage( `确定要删除文件吗?\n\n📄 ${path.basename(filePath)}\n📁 ${path.dirname(filePath)}`, { modal: true, detail: '⚠️ 文件将被移到回收站,可以恢复' }, '确定删除', '取消' ); ``` ### 4.2 批量删除优化 如果 AI 一次返回多个删除操作: ```typescript // 方案 1:逐个确认 for (const file of filesToDelete) { await handleDeleteFileTool(file, panel); } // 方案 2:批量确认(推荐) const confirmed = await vscode.window.showWarningMessage( `确定要删除以下 ${filesToDelete.length} 个文件吗?\n\n${filesToDelete.join('\n')}`, { modal: true }, '全部删除', '取消' ); ``` ## 5. 安全考虑 ### 5.1 使用回收站 ```typescript await vscode.workspace.fs.delete(uri, { useTrash: true // 移到回收站,可恢复 }); ``` ### 5.2 路径验证 ```typescript // 防止删除工作区外的文件 const workspaceFolders = vscode.workspace.workspaceFolders; if (!workspaceFolders) { return { success: false, error: '未打开工作区' }; } const isInWorkspace = workspaceFolders.some(folder => filePath.startsWith(folder.uri.fsPath) ); if (!isInWorkspace) { return { success: false, error: '只能删除工作区内的文件' }; } ``` ### 5.3 敏感文件保护 ```typescript const protectedFiles = [ 'package.json', 'tsconfig.json', '.git', 'node_modules' ]; const fileName = path.basename(filePath); if (protectedFiles.includes(fileName)) { vscode.window.showErrorMessage(`不允许删除系统文件: ${fileName}`); return { success: false, error: '受保护的文件' }; } ``` ## 6. 错误处理 ### 6.1 常见错误 ```typescript try { await vscode.workspace.fs.delete(uri, { useTrash: true }); } catch (error) { if (error.code === 'FileNotFound') { return { success: false, error: '文件不存在' }; } if (error.code === 'NoPermissions') { return { success: false, error: '没有删除权限' }; } return { success: false, error: error.message }; } ``` ## 7. 测试场景 ### 7.1 基本测试 - [ ] 用户点击"确定删除" → 文件被删除 - [ ] 用户点击"取消" → 文件保留,返回取消消息 - [ ] 用户关闭对话框 → 文件保留,返回取消消息 - [ ] 文件不存在 → 返回错误消息 - [ ] 没有删除权限 → 返回错误消息 ### 7.2 边界测试 - [ ] 删除工作区外的文件 → 拒绝 - [ ] 删除受保护文件 → 拒绝 - [ ] 批量删除 → 正确处理 - [ ] 后端收到取消消息后继续对话 → 流程正常 ## 8. 配置选项(可选) 可以添加用户设置来控制行为: ```json // package.json "configuration": { "properties": { "ic-coder.confirmDelete": { "type": "boolean", "default": true, "description": "删除文件前是否需要确认" }, "ic-coder.useTrash": { "type": "boolean", "default": true, "description": "删除文件时移到回收站而非永久删除" } } } ``` 读取配置: ```typescript const config = vscode.workspace.getConfiguration('ic-coder'); const needConfirm = config.get('confirmDelete', true); const useTrash = config.get('useTrash', true); if (needConfirm) { // 弹出确认对话框 } ``` ## 9. 总结 ### 9.1 后端是否需要修改? **不需要**。后端继续返回删除工具调用,前端负责: 1. 拦截工具调用 2. 弹出确认对话框 3. 执行或取消删除 4. **必须返回结果给后端** ### 9.2 关键要点 - ✅ 前端必须返回 `TOOL_EXECUTION_RESULT` - ✅ 使用 `useTrash: true` 提高安全性 - ✅ 验证文件路径在工作区内 - ✅ 保护敏感文件 - ✅ 提供清晰的错误消息 ### 9.3 下一步 1. 在 `messageHandler.ts` 中找到工具调用处理逻辑 2. 实现 `handleDeleteFileTool` 函数 3. 集成到现有流程 4. 测试各种场景 5. 考虑添加用户配置选项