import { exec } from "child_process"; import { promisify } from "util"; import { existsSync } from "fs"; import { join } from "path"; const execAsync = promisify(exec); export const lintCheckTool = { name: "lint_check", description: "对项目执行代码检查。自动检测项目类型并运行对应的 lint 工具(ESLint、TypeScript 编译检查、Pylint 等),返回结构化的错误列表。", inputSchema: { type: "object", properties: { project_path: { type: "string", description: "项目根目录(绝对路径)", }, fix: { type: "boolean", description: "是否自动修复可修复的问题(默认 false)", }, files: { type: "string", description: "指定检查的文件或 glob(可选,默认检查整个项目)", }, }, required: ["project_path"], }, }; async function runCommand(cmd, cwd, timeout = 30000) { try { const { stdout, stderr } = await execAsync(cmd, { cwd, timeout, maxBuffer: 1024 * 1024 * 5, shell: process.platform === "win32" ? "powershell.exe" : "/bin/bash", }); return { stdout, stderr, code: 0 }; } catch (error) { return { stdout: error.stdout || "", stderr: error.stderr || "", code: error.code ?? 1, }; } } export async function executeLintCheck(args) { const { project_path, fix = false, files } = args; const results = []; const hasFile = (name) => existsSync(join(project_path, name)); const hasNodeModules = hasFile("node_modules"); // TypeScript 编译检查 if (hasFile("tsconfig.json")) { const result = await runCommand("npx tsc --noEmit --pretty", project_path); const errorCount = (result.stdout.match(/error TS/g) || []).length; results.push({ tool: "TypeScript (tsc --noEmit)", success: result.code === 0, errorCount, warningCount: 0, output: result.stdout || result.stderr || "(无输出)", }); } // ESLint if (hasFile(".eslintrc.js") || hasFile(".eslintrc.json") || hasFile(".eslintrc.yml") || hasFile("eslint.config.js") || hasFile("eslint.config.mjs")) { const target = files || "src/"; const fixFlag = fix ? " --fix" : ""; const result = await runCommand(`npx eslint ${target}${fixFlag} --format stylish`, project_path); const errorMatch = result.stdout.match(/(\d+) errors?/); const warnMatch = result.stdout.match(/(\d+) warnings?/); results.push({ tool: `ESLint${fix ? " (--fix)" : ""}`, success: result.code === 0, errorCount: errorMatch ? parseInt(errorMatch[1]) : 0, warningCount: warnMatch ? parseInt(warnMatch[1]) : 0, output: result.stdout || result.stderr || "✅ 无问题", }); } // Python: pylint / flake8 if (hasFile("requirements.txt") || hasFile("setup.py") || hasFile("pyproject.toml")) { const target = files || "."; // 优先 flake8 const result = await runCommand(`python -m flake8 ${target} --max-line-length=120 --count`, project_path); if (result.code !== 127) { // 127 = command not found const lines = result.stdout.trim().split("\n").filter(Boolean); results.push({ tool: "Flake8", success: result.code === 0, errorCount: lines.length, warningCount: 0, output: result.stdout || result.stderr || "✅ 无问题", }); } } // 如果什么检查工具都没找到 if (results.length === 0) { // 尝试通用的 package.json lint 脚本 if (hasFile("package.json")) { const result = await runCommand("npm run lint 2>&1 || echo LINT_SCRIPT_NOT_FOUND", project_path); if (!result.stdout.includes("LINT_SCRIPT_NOT_FOUND") && !result.stdout.includes("Missing script")) { results.push({ tool: "npm run lint", success: result.code === 0, errorCount: result.code === 0 ? 0 : 1, warningCount: 0, output: result.stdout || result.stderr, }); } } } if (results.length === 0) { return `# Lint 检查结果\n\n⚠️ 未检测到 lint 工具配置(ESLint、tsconfig、pylint 等)\n项目路径: ${project_path}\n\n建议:\n- TypeScript 项目:添加 tsconfig.json\n- JS 项目:npm init @eslint/config\n- Python 项目:pip install flake8`; } // 组装报告 const totalErrors = results.reduce((sum, r) => sum + r.errorCount, 0); const totalWarnings = results.reduce((sum, r) => sum + r.warningCount, 0); const allPassed = results.every((r) => r.success); const output = [ `# Lint 检查报告`, ``, `📂 项目: ${project_path}`, `${allPassed ? "✅ 全部通过" : "❌ 发现问题"} | 错误: ${totalErrors} | 警告: ${totalWarnings}`, ``, ]; for (const r of results) { output.push(`## ${r.success ? "✅" : "❌"} ${r.tool}`, `错误: ${r.errorCount} | 警告: ${r.warningCount}`, "```", r.output.slice(0, 3000), // 限制输出长度 "```", ``); } if (!allPassed && !fix) { output.push(`💡 提示: 可以设置 fix=true 自动修复可修复的问题`); } return output.join("\n"); } //# sourceMappingURL=lintCheck.js.map