Files
bigwo/dev-assistant-mcp/dist/tools/buildProject.js
2026-03-12 12:47:56 +08:00

115 lines
4.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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