Update code
This commit is contained in:
169
dev-assistant-mcp/dist/tools/gitOps.js
vendored
Normal file
169
dev-assistant-mcp/dist/tools/gitOps.js
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
const execAsync = promisify(exec);
|
||||
export const gitOpsTool = {
|
||||
name: "git_ops",
|
||||
description: "Git 全套操作。支持 status、diff、add、commit、push、pull、log、branch、checkout、stash、reset 等所有常用 Git 命令。自动解析输出为结构化报告。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
action: {
|
||||
type: "string",
|
||||
description: "Git 操作",
|
||||
enum: [
|
||||
"status", "diff", "diff_staged", "add", "add_all", "commit",
|
||||
"push", "pull", "log", "branch", "branch_create", "checkout",
|
||||
"stash", "stash_pop", "reset_soft", "reset_hard", "remote", "init",
|
||||
],
|
||||
},
|
||||
message: {
|
||||
type: "string",
|
||||
description: "commit 消息(commit 时必填)",
|
||||
},
|
||||
target: {
|
||||
type: "string",
|
||||
description: "目标参数(文件路径/分支名/commit hash 等)",
|
||||
},
|
||||
count: {
|
||||
type: "number",
|
||||
description: "log 显示条数(默认 10)",
|
||||
},
|
||||
},
|
||||
required: ["project_path", "action"],
|
||||
},
|
||||
};
|
||||
async function git(args, cwd) {
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(`git ${args}`, {
|
||||
cwd,
|
||||
timeout: 30000,
|
||||
maxBuffer: 1024 * 1024 * 5,
|
||||
});
|
||||
return { stdout, stderr, code: 0 };
|
||||
}
|
||||
catch (error) {
|
||||
return { stdout: error.stdout || "", stderr: error.stderr || "", code: error.code ?? 1 };
|
||||
}
|
||||
}
|
||||
export async function executeGitOps(args) {
|
||||
const { project_path, action, message, target, count = 10 } = args;
|
||||
let result;
|
||||
let title = "";
|
||||
switch (action) {
|
||||
case "status":
|
||||
title = "Git Status";
|
||||
result = await git("status --short --branch", project_path);
|
||||
if (result.code === 0) {
|
||||
const lines = result.stdout.trim().split("\n");
|
||||
const branch = lines[0] || "";
|
||||
const changes = lines.slice(1);
|
||||
const staged = changes.filter((l) => /^[MADRC]/.test(l));
|
||||
const unstaged = changes.filter((l) => /^.[MADRC]/.test(l));
|
||||
const untracked = changes.filter((l) => l.startsWith("??"));
|
||||
return [
|
||||
`# ${title}`, `📂 ${project_path}`, `🌿 ${branch}`, ``,
|
||||
`| 状态 | 数量 |`, `|------|------|`,
|
||||
`| ✅ 已暂存 | ${staged.length} |`,
|
||||
`| 📝 已修改 | ${unstaged.length} |`,
|
||||
`| ❓ 未跟踪 | ${untracked.length} |`, ``,
|
||||
changes.length > 0 ? "```\n" + result.stdout.trim() + "\n```" : "✨ 工作区干净",
|
||||
].join("\n");
|
||||
}
|
||||
break;
|
||||
case "diff":
|
||||
title = "Git Diff (工作区)";
|
||||
result = await git(`diff ${target ? `-- "${target}"` : ""} --stat`, project_path);
|
||||
if (result.stdout.trim()) {
|
||||
const detail = await git(`diff ${target ? `-- "${target}"` : ""} --no-color`, project_path);
|
||||
return `# ${title}\n\n## 摘要\n\`\`\`\n${result.stdout.trim()}\n\`\`\`\n\n## 详细\n\`\`\`diff\n${detail.stdout.slice(0, 8000)}\n\`\`\``;
|
||||
}
|
||||
return `# ${title}\n\n✨ 无差异`;
|
||||
case "diff_staged":
|
||||
title = "Git Diff (暂存区)";
|
||||
result = await git("diff --cached --stat", project_path);
|
||||
if (result.stdout.trim()) {
|
||||
const detail = await git("diff --cached --no-color", project_path);
|
||||
return `# ${title}\n\n## 摘要\n\`\`\`\n${result.stdout.trim()}\n\`\`\`\n\n## 详细\n\`\`\`diff\n${detail.stdout.slice(0, 8000)}\n\`\`\``;
|
||||
}
|
||||
return `# ${title}\n\n✨ 暂存区无内容`;
|
||||
case "add":
|
||||
title = "Git Add";
|
||||
result = await git(`add "${target || "."}"`, project_path);
|
||||
break;
|
||||
case "add_all":
|
||||
title = "Git Add All";
|
||||
result = await git("add -A", project_path);
|
||||
break;
|
||||
case "commit":
|
||||
if (!message)
|
||||
return "❌ commit 需要提供 message 参数";
|
||||
title = "Git Commit";
|
||||
result = await git(`commit -m "${message.replace(/"/g, '\\"')}"`, project_path);
|
||||
break;
|
||||
case "push":
|
||||
title = "Git Push";
|
||||
result = await git(`push ${target || ""}`, project_path);
|
||||
break;
|
||||
case "pull":
|
||||
title = "Git Pull";
|
||||
result = await git(`pull ${target || ""}`, project_path);
|
||||
break;
|
||||
case "log":
|
||||
title = "Git Log";
|
||||
result = await git(`log --oneline --graph --decorate -n ${count}`, project_path);
|
||||
if (result.code === 0) {
|
||||
return `# ${title} (最近 ${count} 条)\n\n\`\`\`\n${result.stdout.trim()}\n\`\`\``;
|
||||
}
|
||||
break;
|
||||
case "branch":
|
||||
title = "Git Branch";
|
||||
result = await git("branch -a -v", project_path);
|
||||
break;
|
||||
case "branch_create":
|
||||
if (!target)
|
||||
return "❌ 创建分支需要提供 target(分支名)";
|
||||
title = `Git Branch Create: ${target}`;
|
||||
result = await git(`checkout -b "${target}"`, project_path);
|
||||
break;
|
||||
case "checkout":
|
||||
if (!target)
|
||||
return "❌ checkout 需要提供 target(分支名或文件)";
|
||||
title = `Git Checkout: ${target}`;
|
||||
result = await git(`checkout "${target}"`, project_path);
|
||||
break;
|
||||
case "stash":
|
||||
title = "Git Stash";
|
||||
result = await git(`stash${message ? ` push -m "${message}"` : ""}`, project_path);
|
||||
break;
|
||||
case "stash_pop":
|
||||
title = "Git Stash Pop";
|
||||
result = await git("stash pop", project_path);
|
||||
break;
|
||||
case "reset_soft":
|
||||
title = "Git Reset (soft)";
|
||||
result = await git(`reset --soft ${target || "HEAD~1"}`, project_path);
|
||||
break;
|
||||
case "reset_hard":
|
||||
title = "Git Reset (hard) ⚠️";
|
||||
result = await git(`reset --hard ${target || "HEAD"}`, project_path);
|
||||
break;
|
||||
case "remote":
|
||||
title = "Git Remote";
|
||||
result = await git("remote -v", project_path);
|
||||
break;
|
||||
case "init":
|
||||
title = "Git Init";
|
||||
result = await git("init", project_path);
|
||||
break;
|
||||
default:
|
||||
return `❌ 未知 Git 操作: ${action}`;
|
||||
}
|
||||
const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
||||
const icon = result.code === 0 ? "✅" : "❌";
|
||||
return `# ${icon} ${title}\n\n📂 ${project_path}\n\n\`\`\`\n${output || "(无输出)"}\n\`\`\``;
|
||||
}
|
||||
//# sourceMappingURL=gitOps.js.map
|
||||
Reference in New Issue
Block a user