import * as fs from 'fs/promises'; import * as path from 'path'; import type { ToolResult } from '../../types/index.js'; import type { ToolWithMetadata } from '../types.js'; import { loadDescription } from '../load_description.js'; import { getPermissionManager } from '../../permission/index.js'; async function copyRecursive(source: string, dest: string): Promise { const stats = await fs.stat(source); if (stats.isDirectory()) { await fs.mkdir(dest, { recursive: true }); const entries = await fs.readdir(source); for (const entry of entries) { await copyRecursive(path.join(source, entry), path.join(dest, entry)); } } else { await fs.copyFile(source, dest); } } export const copyFileTool: ToolWithMetadata = { name: 'copy_file', description: loadDescription('copy_file'), metadata: { name: 'copy_file', category: 'filesystem', description: '复制文件或目录', keywords: ['copy', 'file', 'cp', 'duplicate', '复制', '文件', '拷贝'], deferLoading: true, }, parameters: { source: { type: 'string', description: '源文件或目录的路径', required: true, }, destination: { type: 'string', description: '目标路径', required: true, }, }, execute: async (params: Record): Promise => { const source = params.source as string; const destination = params.destination as string; const cwd = process.cwd(); const absoluteSource = path.isAbsolute(source) ? source : path.join(cwd, source); const absoluteDest = path.isAbsolute(destination) ? destination : path.join(cwd, destination); // 权限检查 - 源文件需要 read 权限 const permissionManager = getPermissionManager(); const sourcePermResult = await permissionManager.checkFilePermission({ operation: 'read', path: absoluteSource, workdir: cwd, }); if (!sourcePermResult.allowed) { if (sourcePermResult.needsConfirmation) { return { success: false, output: '', error: `需要用户确认: 读取 ${absoluteSource}\n原因: ${sourcePermResult.reason || '需要权限确认'}`, }; } return { success: false, output: '', error: `权限被拒绝: ${sourcePermResult.reason || '不允许读取此文件'}`, }; } // 权限检查 - 目标位置需要 copy 权限 const destPermResult = await permissionManager.checkFilePermission({ operation: 'copy', path: absoluteDest, workdir: cwd, }); if (!destPermResult.allowed) { if (destPermResult.needsConfirmation) { return { success: false, output: '', error: `需要用户确认: 复制到 ${absoluteDest}\n原因: ${destPermResult.reason || '需要权限确认'}`, }; } return { success: false, output: '', error: `权限被拒绝: ${destPermResult.reason || '不允许复制到此位置'}`, }; } try { // 检查源文件是否存在 const sourceStats = await fs.stat(absoluteSource); // 检查目标是否是目录 let finalDest = absoluteDest; try { const destStats = await fs.stat(absoluteDest); if (destStats.isDirectory()) { // 如果目标是目录,将源文件复制到该目录下 finalDest = path.join(absoluteDest, path.basename(absoluteSource)); } } catch { // 目标不存在,直接使用目标路径 } // 确保目标目录存在 await fs.mkdir(path.dirname(finalDest), { recursive: true }); // 执行复制 if (sourceStats.isDirectory()) { await copyRecursive(absoluteSource, finalDest); } else { await fs.copyFile(absoluteSource, finalDest); } return { success: true, output: `已复制: ${absoluteSource} -> ${finalDest}`, }; } catch (error) { return { success: false, output: '', error: error instanceof Error ? error.message : String(error), }; } }, };