Files
bigwo/dev-assistant-mcp/dist/tools/buildProject.js

115 lines
4.4 KiB
JavaScript
Raw Normal View History

2026-03-12 12:47:56 +08:00
import { exec } from "child_process";
import { promisify } from "util";
import { existsSync, readFileSync } from "fs";
import { join } from "path";
const execAsync = promisify(exec);
export const buildProjectTool = {
name: "build_project",
description: "构建项目。自动检测构建方式npm run build、tsc、vite build、webpack 等),执行构建并返回结果。如果构建失败,返回错误详情供自动修复。",
inputSchema: {
type: "object",
properties: {
project_path: {
type: "string",
description: "项目根目录(绝对路径)",
},
command: {
type: "string",
description: "自定义构建命令(可选,默认自动检测)",
},
},
required: ["project_path"],
},
};
async function runBuild(cmd, cwd) {
const start = Date.now();
try {
const { stdout, stderr } = await execAsync(cmd, {
cwd,
timeout: 300000, // 5分钟
maxBuffer: 1024 * 1024 * 10,
shell: process.platform === "win32" ? "powershell.exe" : "/bin/bash",
});
return { stdout, stderr, code: 0, duration: Date.now() - start };
}
catch (error) {
return {
stdout: error.stdout || "",
stderr: error.stderr || "",
code: error.code ?? 1,
duration: Date.now() - start,
};
}
}
export async function executeBuildProject(args) {
const { project_path, command } = args;
const hasFile = (name) => existsSync(join(project_path, name));
let buildCmd = command || "";
let buildTool = "自定义";
if (!buildCmd) {
// 自动检测构建方式
if (hasFile("package.json")) {
try {
const pkg = JSON.parse(readFileSync(join(project_path, "package.json"), "utf-8"));
if (pkg.scripts?.build) {
buildCmd = "npm run build";
buildTool = `npm (${pkg.scripts.build})`;
}
else if (hasFile("tsconfig.json")) {
buildCmd = "npx tsc";
buildTool = "TypeScript (tsc)";
}
}
catch { }
}
else if (hasFile("Makefile")) {
buildCmd = "make";
buildTool = "Make";
}
else if (hasFile("setup.py") || hasFile("pyproject.toml")) {
buildCmd = "python -m build 2>&1 || python setup.py build 2>&1";
buildTool = "Python";
}
}
if (!buildCmd) {
return `# 构建结果\n\n⚠️ 未检测到构建配置\n项目路径: ${project_path}\n\n建议手动指定 command 参数`;
}
// 检查依赖是否安装
if (hasFile("package.json") && !hasFile("node_modules")) {
const installResult = await runBuild("npm install", project_path);
if (installResult.code !== 0) {
return `# 构建失败\n\n❌ 依赖安装失败 (npm install)\n\n\`\`\`\n${installResult.stderr || installResult.stdout}\n\`\`\``;
}
}
const result = await runBuild(buildCmd, project_path);
const fullOutput = (result.stdout + "\n" + result.stderr).trim();
// 提取错误信息
const errors = [];
const lines = fullOutput.split("\n");
for (const line of lines) {
if (/error\s+TS\d+/i.test(line) || /Error:/i.test(line) || /ERROR/i.test(line) || /Failed/i.test(line)) {
errors.push(line.trim());
}
}
const output = [
`# 构建报告`,
``,
`📂 项目: ${project_path}`,
`🔧 工具: ${buildTool}`,
`⏱️ 耗时: ${(result.duration / 1000).toFixed(1)}s`,
`${result.code === 0 ? "✅ **构建成功**" : "❌ **构建失败**"}`,
``,
`## 命令`,
`\`${buildCmd}\``,
``,
];
if (errors.length > 0 && result.code !== 0) {
output.push(`## 错误摘要(${errors.length} 项)`, ...errors.slice(0, 20).map((e) => `- ${e}`), errors.length > 20 ? `\n... 还有 ${errors.length - 20} 项错误` : "", ``);
}
output.push(`## 完整输出`, "```", fullOutput.slice(0, 5000), "```");
if (result.code !== 0) {
output.push(``, `## 自动修复建议`, `1. 使用 code_debug 分析上方错误`, `2. 修复代码后重新运行 build_project`, `3. 或使用 lint_check 先检查代码质量`);
}
return output.join("\n");
}
//# sourceMappingURL=buildProject.js.map