Update code
This commit is contained in:
140
dev-assistant-mcp/src/tools/autoFix.ts
Normal file
140
dev-assistant-mcp/src/tools/autoFix.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { existsSync } from "fs";
|
||||
import { join } from "path";
|
||||
|
||||
const execAsync = promisify(exec);
|
||||
|
||||
export const autoFixTool = {
|
||||
name: "auto_fix",
|
||||
description:
|
||||
"自动修复代码问题。运行 Prettier 格式化、ESLint --fix 自动修复、以及其他自动修复工具。返回修复前后的变更摘要。",
|
||||
inputSchema: {
|
||||
type: "object" as const,
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
files: {
|
||||
type: "string",
|
||||
description: "指定修复的文件或 glob(可选,默认修复整个项目)",
|
||||
},
|
||||
tools: {
|
||||
type: "string",
|
||||
description: "指定修复工具,逗号分隔(可选):prettier, eslint, autopep8。默认自动检测。",
|
||||
},
|
||||
},
|
||||
required: ["project_path"],
|
||||
},
|
||||
};
|
||||
|
||||
async function runFix(cmd: string, cwd: string): Promise<{ success: boolean; output: string }> {
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(cmd, {
|
||||
cwd,
|
||||
timeout: 30000,
|
||||
maxBuffer: 1024 * 1024 * 5,
|
||||
shell: process.platform === "win32" ? "powershell.exe" : "/bin/bash",
|
||||
});
|
||||
return { success: true, output: stdout || stderr || "✅ 修复完成" };
|
||||
} catch (error: any) {
|
||||
return { success: false, output: error.stdout || error.stderr || error.message };
|
||||
}
|
||||
}
|
||||
|
||||
export async function executeAutoFix(args: {
|
||||
project_path: string;
|
||||
files?: string;
|
||||
tools?: string;
|
||||
}): Promise<string> {
|
||||
const { project_path, files, tools } = args;
|
||||
const hasFile = (name: string) => existsSync(join(project_path, name));
|
||||
|
||||
const fixResults: { tool: string; success: boolean; output: string }[] = [];
|
||||
|
||||
// 先获取 git diff 作为修复前基线
|
||||
let diffBefore = "";
|
||||
try {
|
||||
const { stdout } = await execAsync("git diff --stat", { cwd: project_path, timeout: 5000 });
|
||||
diffBefore = stdout;
|
||||
} catch {}
|
||||
|
||||
const requestedTools = tools ? tools.split(",").map((t) => t.trim().toLowerCase()) : [];
|
||||
const autoDetect = requestedTools.length === 0;
|
||||
|
||||
// Prettier
|
||||
if (autoDetect ? (hasFile(".prettierrc") || hasFile(".prettierrc.json") || hasFile("prettier.config.js")) : requestedTools.includes("prettier")) {
|
||||
const target = files || ".";
|
||||
const result = await runFix(`npx prettier --write "${target}"`, project_path);
|
||||
fixResults.push({ tool: "Prettier", ...result });
|
||||
}
|
||||
|
||||
// ESLint --fix
|
||||
if (autoDetect ? (hasFile(".eslintrc.js") || hasFile(".eslintrc.json") || hasFile("eslint.config.js") || hasFile("eslint.config.mjs")) : requestedTools.includes("eslint")) {
|
||||
const target = files || "src/";
|
||||
const result = await runFix(`npx eslint "${target}" --fix`, project_path);
|
||||
fixResults.push({ tool: "ESLint --fix", ...result });
|
||||
}
|
||||
|
||||
// Python autopep8
|
||||
if (autoDetect ? (hasFile("requirements.txt") || hasFile("pyproject.toml")) : requestedTools.includes("autopep8")) {
|
||||
const target = files || ".";
|
||||
const result = await runFix(`python -m autopep8 --in-place --recursive "${target}"`, project_path);
|
||||
if (!result.output.includes("No module named")) {
|
||||
fixResults.push({ tool: "autopep8", ...result });
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有检测到工具配置,尝试 package.json 中的 format 脚本
|
||||
if (fixResults.length === 0 && hasFile("package.json")) {
|
||||
const result = await runFix("npm run format 2>&1 || npm run lint:fix 2>&1 || echo NO_FIX_SCRIPT", project_path);
|
||||
if (!result.output.includes("NO_FIX_SCRIPT") && !result.output.includes("Missing script")) {
|
||||
fixResults.push({ tool: "npm script (format/lint:fix)", ...result });
|
||||
}
|
||||
}
|
||||
|
||||
// 获取修复后的 diff
|
||||
let diffAfter = "";
|
||||
try {
|
||||
const { stdout } = await execAsync("git diff --stat", { cwd: project_path, timeout: 5000 });
|
||||
diffAfter = stdout;
|
||||
} catch {}
|
||||
|
||||
// 组装报告
|
||||
const output: string[] = [
|
||||
`# 自动修复报告`,
|
||||
``,
|
||||
`📂 项目: ${project_path}`,
|
||||
``,
|
||||
];
|
||||
|
||||
if (fixResults.length === 0) {
|
||||
output.push(
|
||||
"⚠️ 未检测到格式化/修复工具",
|
||||
"",
|
||||
"建议安装:",
|
||||
"- `npm install -D prettier` — 代码格式化",
|
||||
"- `npm install -D eslint` — 代码质量检查和自动修复",
|
||||
"- `pip install autopep8` — Python 代码格式化",
|
||||
);
|
||||
} else {
|
||||
for (const r of fixResults) {
|
||||
output.push(
|
||||
`## ${r.success ? "✅" : "⚠️"} ${r.tool}`,
|
||||
"```",
|
||||
r.output.slice(0, 2000),
|
||||
"```",
|
||||
``
|
||||
);
|
||||
}
|
||||
|
||||
if (diffAfter && diffAfter !== diffBefore) {
|
||||
output.push("## 变更摘要 (git diff --stat)", "```", diffAfter, "```");
|
||||
} else if (fixResults.some((r) => r.success)) {
|
||||
output.push("📝 修复完成,代码已更新");
|
||||
}
|
||||
}
|
||||
|
||||
return output.join("\n");
|
||||
}
|
||||
Reference in New Issue
Block a user