Update code
This commit is contained in:
2
dev-assistant-mcp/dist/index.d.ts
vendored
Normal file
2
dev-assistant-mcp/dist/index.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
export {};
|
||||
//# sourceMappingURL=index.d.ts.map
|
||||
1
dev-assistant-mcp/dist/index.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/index.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
||||
183
dev-assistant-mcp/dist/index.js
vendored
Normal file
183
dev-assistant-mcp/dist/index.js
vendored
Normal file
@@ -0,0 +1,183 @@
|
||||
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
||||
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
||||
import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
||||
// ===== 分析工具 =====
|
||||
import { codeReviewTool, executeCodeReview } from "./tools/codeReview.js";
|
||||
import { codeWriteTool, executeCodeWrite } from "./tools/codeWrite.js";
|
||||
import { codeDebugTool, executeCodeDebug } from "./tools/codeDebug.js";
|
||||
import { docWriteTool, executeDocWrite } from "./tools/docWrite.js";
|
||||
// ===== 本地执行工具(自动化闭环核心) =====
|
||||
import { execCommandTool, executeExecCommand } from "./tools/execCommand.js";
|
||||
import { lintCheckTool, executeLintCheck } from "./tools/lintCheck.js";
|
||||
import { autoFixTool, executeAutoFix } from "./tools/autoFix.js";
|
||||
import { runTestsTool, executeRunTests } from "./tools/runTests.js";
|
||||
import { buildProjectTool, executeBuildProject } from "./tools/buildProject.js";
|
||||
import { projectScanTool, executeProjectScan } from "./tools/projectScan.js";
|
||||
import { readFileTool, executeReadFile, writeFileTool, executeWriteFile, patchFileTool, executePatchFile, } from "./tools/fileOps.js";
|
||||
// ===== 高级工具(极致版) =====
|
||||
import { gitOpsTool, executeGitOps } from "./tools/gitOps.js";
|
||||
import { depManageTool, executeDepManage } from "./tools/depManage.js";
|
||||
import { searchCodeTool, executeSearchCode } from "./tools/searchCode.js";
|
||||
import { devServerTool, executeDevServer } from "./tools/devServer.js";
|
||||
import { envCheckTool, executeEnvCheck } from "./tools/envCheck.js";
|
||||
import { workflowTool, executeWorkflow } from "./tools/workflow.js";
|
||||
// ===== 资源 =====
|
||||
import { codingStandardsResource, getCodingStandards, } from "./resources/codingStandards.js";
|
||||
import { debugGuideResource, getDebugGuide } from "./resources/debugGuide.js";
|
||||
import { docTemplatesResource, getDocTemplates, } from "./resources/docTemplates.js";
|
||||
// ========== MCP Server ==========
|
||||
const server = new Server({ name: "dev-assistant", version: "2.0.0" }, { capabilities: { tools: {}, resources: {} } });
|
||||
// ========== 注册工具列表 ==========
|
||||
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
||||
tools: [
|
||||
// 分析工具
|
||||
codeReviewTool, codeWriteTool, codeDebugTool, docWriteTool,
|
||||
// 本地执行工具(自动化闭环核心)
|
||||
execCommandTool, lintCheckTool, autoFixTool, runTestsTool,
|
||||
buildProjectTool, projectScanTool,
|
||||
readFileTool, writeFileTool, patchFileTool,
|
||||
// 高级工具(极致版)
|
||||
gitOpsTool, depManageTool, searchCodeTool,
|
||||
devServerTool, envCheckTool, workflowTool,
|
||||
],
|
||||
}));
|
||||
// ========== 工具执行 ==========
|
||||
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
||||
const { name, arguments: args } = request.params;
|
||||
try {
|
||||
let result;
|
||||
switch (name) {
|
||||
// 分析工具
|
||||
case "code_review":
|
||||
result = await executeCodeReview(args);
|
||||
break;
|
||||
case "code_write":
|
||||
result = await executeCodeWrite(args);
|
||||
break;
|
||||
case "code_debug":
|
||||
result = await executeCodeDebug(args);
|
||||
break;
|
||||
case "doc_write":
|
||||
result = await executeDocWrite(args);
|
||||
break;
|
||||
// 本地执行工具
|
||||
case "exec_command":
|
||||
result = await executeExecCommand(args);
|
||||
break;
|
||||
case "lint_check":
|
||||
result = await executeLintCheck(args);
|
||||
break;
|
||||
case "auto_fix":
|
||||
result = await executeAutoFix(args);
|
||||
break;
|
||||
case "run_tests":
|
||||
result = await executeRunTests(args);
|
||||
break;
|
||||
case "build_project":
|
||||
result = await executeBuildProject(args);
|
||||
break;
|
||||
case "project_scan":
|
||||
result = await executeProjectScan(args);
|
||||
break;
|
||||
// 文件操作
|
||||
case "read_local_file":
|
||||
result = await executeReadFile(args);
|
||||
break;
|
||||
case "write_local_file":
|
||||
result = await executeWriteFile(args);
|
||||
break;
|
||||
case "patch_file":
|
||||
result = await executePatchFile(args);
|
||||
break;
|
||||
// 高级工具
|
||||
case "git_ops":
|
||||
result = await executeGitOps(args);
|
||||
break;
|
||||
case "dep_manage":
|
||||
result = await executeDepManage(args);
|
||||
break;
|
||||
case "search_code":
|
||||
result = await executeSearchCode(args);
|
||||
break;
|
||||
case "dev_server":
|
||||
result = await executeDevServer(args);
|
||||
break;
|
||||
case "env_check":
|
||||
result = await executeEnvCheck(args);
|
||||
break;
|
||||
case "workflow":
|
||||
result = await executeWorkflow(args);
|
||||
break;
|
||||
default:
|
||||
return {
|
||||
content: [{ type: "text", text: `未知工具: ${name}` }],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
return { content: [{ type: "text", text: result }] };
|
||||
}
|
||||
catch (error) {
|
||||
return {
|
||||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: `执行出错: ${error.message}`,
|
||||
},
|
||||
],
|
||||
isError: true,
|
||||
};
|
||||
}
|
||||
});
|
||||
// ========== 注册资源列表 ==========
|
||||
server.setRequestHandler(ListResourcesRequestSchema, async () => ({
|
||||
resources: [codingStandardsResource, debugGuideResource, docTemplatesResource],
|
||||
}));
|
||||
// ========== 资源读取 ==========
|
||||
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
||||
const { uri } = request.params;
|
||||
switch (uri) {
|
||||
case codingStandardsResource.uri:
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri,
|
||||
mimeType: "text/markdown",
|
||||
text: getCodingStandards(),
|
||||
},
|
||||
],
|
||||
};
|
||||
case debugGuideResource.uri:
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri,
|
||||
mimeType: "text/markdown",
|
||||
text: getDebugGuide(),
|
||||
},
|
||||
],
|
||||
};
|
||||
case docTemplatesResource.uri:
|
||||
return {
|
||||
contents: [
|
||||
{
|
||||
uri,
|
||||
mimeType: "text/markdown",
|
||||
text: getDocTemplates(),
|
||||
},
|
||||
],
|
||||
};
|
||||
default:
|
||||
throw new Error(`未知资源: ${uri}`);
|
||||
}
|
||||
});
|
||||
// ========== 启动 ==========
|
||||
async function main() {
|
||||
const transport = new StdioServerTransport();
|
||||
await server.connect(transport);
|
||||
console.error("Dev Assistant MCP Server v2.0.0 (19 tools) running on stdio");
|
||||
}
|
||||
main().catch((err) => {
|
||||
console.error("Fatal:", err);
|
||||
process.exit(1);
|
||||
});
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dev-assistant-mcp/dist/index.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/index.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
8
dev-assistant-mcp/dist/resources/codingStandards.d.ts
vendored
Normal file
8
dev-assistant-mcp/dist/resources/codingStandards.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export declare const codingStandardsResource: {
|
||||
uri: string;
|
||||
name: string;
|
||||
description: string;
|
||||
mimeType: string;
|
||||
};
|
||||
export declare function getCodingStandards(): string;
|
||||
//# sourceMappingURL=codingStandards.d.ts.map
|
||||
1
dev-assistant-mcp/dist/resources/codingStandards.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/resources/codingStandards.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codingStandards.d.ts","sourceRoot":"","sources":["../../src/resources/codingStandards.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB;;;;;CAKnC,CAAC;AAEF,wBAAgB,kBAAkB,IAAI,MAAM,CA2B3C"}
|
||||
35
dev-assistant-mcp/dist/resources/codingStandards.js
vendored
Normal file
35
dev-assistant-mcp/dist/resources/codingStandards.js
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
export const codingStandardsResource = {
|
||||
uri: "devassistant://resources/coding-standards",
|
||||
name: "编码规范",
|
||||
description: "各主流语言的编码最佳实践和规范",
|
||||
mimeType: "text/markdown",
|
||||
};
|
||||
export function getCodingStandards() {
|
||||
return `# 编码规范速查
|
||||
|
||||
## TypeScript / JavaScript
|
||||
- 使用 \`const\` 优先,\`let\` 次之,禁用 \`var\`
|
||||
- 函数和变量使用 camelCase,类和接口使用 PascalCase
|
||||
- 优先使用 \`async/await\` 而非回调和 \`.then()\` 链
|
||||
- 使用严格类型,避免 \`any\`
|
||||
- 错误处理:始终 catch 异步操作的异常
|
||||
- 单个函数不超过 50 行,单个文件不超过 300 行
|
||||
|
||||
## Python
|
||||
- 遵循 PEP 8 规范
|
||||
- 函数和变量使用 snake_case,类使用 PascalCase
|
||||
- 使用 type hints 标注参数和返回值
|
||||
- 使用 f-string 格式化字符串
|
||||
- 使用 \`with\` 语句管理资源
|
||||
- 使用 \`pathlib\` 替代 \`os.path\`
|
||||
|
||||
## 通用原则
|
||||
- **DRY** — Don't Repeat Yourself,消除重复代码
|
||||
- **KISS** — Keep It Simple, Stupid,保持简单
|
||||
- **单一职责** — 每个函数/类只做一件事
|
||||
- **提前返回** — 用 guard clause 减少嵌套
|
||||
- **有意义的命名** — 变量名应表达意图,不用缩写
|
||||
- **最小暴露** — 只暴露必要的公开接口
|
||||
`;
|
||||
}
|
||||
//# sourceMappingURL=codingStandards.js.map
|
||||
1
dev-assistant-mcp/dist/resources/codingStandards.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/resources/codingStandards.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codingStandards.js","sourceRoot":"","sources":["../../src/resources/codingStandards.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,GAAG,EAAE,2CAA2C;IAChD,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,iBAAiB;IAC9B,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,UAAU,kBAAkB;IAChC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;CAyBR,CAAC;AACF,CAAC"}
|
||||
8
dev-assistant-mcp/dist/resources/debugGuide.d.ts
vendored
Normal file
8
dev-assistant-mcp/dist/resources/debugGuide.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export declare const debugGuideResource: {
|
||||
uri: string;
|
||||
name: string;
|
||||
description: string;
|
||||
mimeType: string;
|
||||
};
|
||||
export declare function getDebugGuide(): string;
|
||||
//# sourceMappingURL=debugGuide.d.ts.map
|
||||
1
dev-assistant-mcp/dist/resources/debugGuide.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/resources/debugGuide.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"debugGuide.d.ts","sourceRoot":"","sources":["../../src/resources/debugGuide.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;;;;;CAK9B,CAAC;AAEF,wBAAgB,aAAa,IAAI,MAAM,CA4CtC"}
|
||||
52
dev-assistant-mcp/dist/resources/debugGuide.js
vendored
Normal file
52
dev-assistant-mcp/dist/resources/debugGuide.js
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
export const debugGuideResource = {
|
||||
uri: "devassistant://resources/debug-guide",
|
||||
name: "调试指南",
|
||||
description: "常见错误模式和排查方法",
|
||||
mimeType: "text/markdown",
|
||||
};
|
||||
export function getDebugGuide() {
|
||||
return `# 调试指南
|
||||
|
||||
## 调试步骤
|
||||
1. **复现问题** — 找到稳定的复现路径
|
||||
2. **阅读错误信息** — 仔细看完整报错和堆栈
|
||||
3. **缩小范围** — 二分法定位问题代码
|
||||
4. **检查假设** — 用 console.log / print 验证变量值
|
||||
5. **查看变更** — git diff 看最近改了什么
|
||||
6. **搜索已知问题** — Google / StackOverflow / GitHub Issues
|
||||
|
||||
## 常见错误模式
|
||||
|
||||
### TypeError: Cannot read properties of undefined
|
||||
- **原因**:访问了 null/undefined 的属性
|
||||
- **排查**:检查调用链上哪个变量可能为空
|
||||
- **修复**:使用可选链 \`?.\` 或提前判空
|
||||
|
||||
### ECONNREFUSED / ETIMEDOUT
|
||||
- **原因**:网络连接被拒绝或超时
|
||||
- **排查**:检查目标服务是否启动、端口是否正确、防火墙规则
|
||||
- **修复**:确认服务地址和端口,添加重试机制
|
||||
|
||||
### Memory Leak
|
||||
- **表现**:内存持续增长不释放
|
||||
- **排查**:检查未清理的定时器、事件监听器、闭包引用
|
||||
- **修复**:在组件销毁/函数退出时清理资源
|
||||
|
||||
### Race Condition
|
||||
- **表现**:偶发的数据不一致
|
||||
- **排查**:检查并发操作共享状态
|
||||
- **修复**:加锁、使用原子操作、或重新设计数据流
|
||||
|
||||
### Import/Module Error
|
||||
- **原因**:路径错误、循环依赖、导出方式不匹配
|
||||
- **排查**:检查文件路径、ESM vs CJS、default vs named export
|
||||
- **修复**:修正导入路径和方式
|
||||
|
||||
## 调试工具
|
||||
- **Node.js**: \`node --inspect\`, Chrome DevTools
|
||||
- **Python**: \`pdb\`, \`ipdb\`, VS Code debugger
|
||||
- **浏览器**: Chrome DevTools (Sources, Network, Console)
|
||||
- **通用**: \`git bisect\` 定位引入 bug 的提交
|
||||
`;
|
||||
}
|
||||
//# sourceMappingURL=debugGuide.js.map
|
||||
1
dev-assistant-mcp/dist/resources/debugGuide.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/resources/debugGuide.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"debugGuide.js","sourceRoot":"","sources":["../../src/resources/debugGuide.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,GAAG,EAAE,sCAAsC;IAC3C,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,UAAU,aAAa;IAC3B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0CR,CAAC;AACF,CAAC"}
|
||||
8
dev-assistant-mcp/dist/resources/docTemplates.d.ts
vendored
Normal file
8
dev-assistant-mcp/dist/resources/docTemplates.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
export declare const docTemplatesResource: {
|
||||
uri: string;
|
||||
name: string;
|
||||
description: string;
|
||||
mimeType: string;
|
||||
};
|
||||
export declare function getDocTemplates(): string;
|
||||
//# sourceMappingURL=docTemplates.d.ts.map
|
||||
1
dev-assistant-mcp/dist/resources/docTemplates.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/resources/docTemplates.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"docTemplates.d.ts","sourceRoot":"","sources":["../../src/resources/docTemplates.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB;;;;;CAKhC,CAAC;AAEF,wBAAgB,eAAe,IAAI,MAAM,CAiGxC"}
|
||||
105
dev-assistant-mcp/dist/resources/docTemplates.js
vendored
Normal file
105
dev-assistant-mcp/dist/resources/docTemplates.js
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
export const docTemplatesResource = {
|
||||
uri: "devassistant://resources/doc-templates",
|
||||
name: "文档模板",
|
||||
description: "README、API 文档、CHANGELOG 等标准模板",
|
||||
mimeType: "text/markdown",
|
||||
};
|
||||
export function getDocTemplates() {
|
||||
return `# 文档模板集合
|
||||
|
||||
---
|
||||
|
||||
## README.md 模板
|
||||
|
||||
\`\`\`markdown
|
||||
# 项目名称
|
||||
|
||||
简短的项目描述(一句话)。
|
||||
|
||||
## 功能特性
|
||||
|
||||
- 特性 1
|
||||
- 特性 2
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 环境要求
|
||||
- Node.js >= 18
|
||||
|
||||
### 安装
|
||||
\\\`\\\`\\\`bash
|
||||
npm install
|
||||
\\\`\\\`\\\`
|
||||
|
||||
### 配置
|
||||
复制 \`.env.example\` 为 \`.env\`,填写配置。
|
||||
|
||||
### 运行
|
||||
\\\`\\\`\\\`bash
|
||||
npm start
|
||||
\\\`\\\`\\\`
|
||||
|
||||
## 项目结构
|
||||
\\\`\\\`\\\`
|
||||
src/
|
||||
├── index.ts # 入口
|
||||
├── routes/ # 路由
|
||||
├── services/ # 业务逻辑
|
||||
└── utils/ # 工具函数
|
||||
\\\`\\\`\\\`
|
||||
|
||||
## API 文档
|
||||
见 [API.md](./API.md)
|
||||
|
||||
## License
|
||||
MIT
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## API 文档模板
|
||||
|
||||
\`\`\`markdown
|
||||
# API 文档
|
||||
|
||||
## Base URL
|
||||
\\\`https://api.example.com/v1\\\`
|
||||
|
||||
## 认证
|
||||
Header: \\\`Authorization: Bearer <token>\\\`
|
||||
|
||||
## 端点
|
||||
|
||||
### POST /endpoint
|
||||
描述
|
||||
|
||||
**请求参数**
|
||||
| 字段 | 类型 | 必填 | 描述 |
|
||||
|------|------|------|------|
|
||||
| name | string | 是 | 名称 |
|
||||
|
||||
**响应**
|
||||
\\\`\\\`\\\`json
|
||||
{ "code": 0, "data": {} }
|
||||
\\\`\\\`\\\`
|
||||
\`\`\`
|
||||
|
||||
---
|
||||
|
||||
## CHANGELOG 模板
|
||||
|
||||
\`\`\`markdown
|
||||
# Changelog
|
||||
|
||||
## [1.0.0] - 2025-01-01
|
||||
### Added
|
||||
- 初始版本发布
|
||||
- 功能 A
|
||||
- 功能 B
|
||||
|
||||
### Fixed
|
||||
- 修复问题 X
|
||||
\`\`\`
|
||||
`;
|
||||
}
|
||||
//# sourceMappingURL=docTemplates.js.map
|
||||
1
dev-assistant-mcp/dist/resources/docTemplates.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/resources/docTemplates.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"docTemplates.js","sourceRoot":"","sources":["../../src/resources/docTemplates.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,GAAG,EAAE,wCAAwC;IAC7C,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,+BAA+B;IAC5C,QAAQ,EAAE,eAAe;CAC1B,CAAC;AAEF,MAAM,UAAU,eAAe;IAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+FR,CAAC;AACF,CAAC"}
|
||||
28
dev-assistant-mcp/dist/tools/autoFix.d.ts
vendored
Normal file
28
dev-assistant-mcp/dist/tools/autoFix.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
export declare const autoFixTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
files: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
tools: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeAutoFix(args: {
|
||||
project_path: string;
|
||||
files?: string;
|
||||
tools?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=autoFix.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/autoFix.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/autoFix.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"autoFix.d.ts","sourceRoot":"","sources":["../../src/tools/autoFix.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;CAsBvB,CAAC;AAgBF,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0FlB"}
|
||||
112
dev-assistant-mcp/dist/tools/autoFix.js
vendored
Normal file
112
dev-assistant-mcp/dist/tools/autoFix.js
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
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",
|
||||
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, cwd) {
|
||||
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) {
|
||||
return { success: false, output: error.stdout || error.stderr || error.message };
|
||||
}
|
||||
}
|
||||
export async function executeAutoFix(args) {
|
||||
const { project_path, files, tools } = args;
|
||||
const hasFile = (name) => existsSync(join(project_path, name));
|
||||
const fixResults = [];
|
||||
// 先获取 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 = [
|
||||
`# 自动修复报告`,
|
||||
``,
|
||||
`📂 项目: ${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");
|
||||
}
|
||||
//# sourceMappingURL=autoFix.js.map
|
||||
1
dev-assistant-mcp/dist/tools/autoFix.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/autoFix.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"autoFix.js","sourceRoot":"","sources":["../../src/tools/autoFix.ts"],"names":[],"mappings":"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"}
|
||||
23
dev-assistant-mcp/dist/tools/buildProject.d.ts
vendored
Normal file
23
dev-assistant-mcp/dist/tools/buildProject.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export declare const buildProjectTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
command: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeBuildProject(args: {
|
||||
project_path: string;
|
||||
command?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=buildProject.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/buildProject.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/buildProject.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"buildProject.d.ts","sourceRoot":"","sources":["../../src/tools/buildProject.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;CAkB5B,CAAC;AAsBF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE;IAC9C,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6FlB"}
|
||||
115
dev-assistant-mcp/dist/tools/buildProject.js
vendored
Normal file
115
dev-assistant-mcp/dist/tools/buildProject.js
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
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
|
||||
1
dev-assistant-mcp/dist/tools/buildProject.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/buildProject.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"buildProject.js","sourceRoot":"","sources":["../../src/tools/buildProject.ts"],"names":[],"mappings":"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"}
|
||||
33
dev-assistant-mcp/dist/tools/codeDebug.d.ts
vendored
Normal file
33
dev-assistant-mcp/dist/tools/codeDebug.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
export declare const codeDebugTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
code: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
error_message: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
language: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
expected_behavior: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeCodeDebug(args: {
|
||||
code: string;
|
||||
error_message: string;
|
||||
language: string;
|
||||
expected_behavior?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=codeDebug.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/codeDebug.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/codeDebug.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codeDebug.d.ts","sourceRoot":"","sources":["../../src/tools/codeDebug.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;CA0BzB,CAAC;AAwHF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,GAAG,OAAO,CAAC,MAAM,CAAC,CAkElB"}
|
||||
176
dev-assistant-mcp/dist/tools/codeDebug.js
vendored
Normal file
176
dev-assistant-mcp/dist/tools/codeDebug.js
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
export const codeDebugTool = {
|
||||
name: "code_debug",
|
||||
description: "分析代码错误,返回结构化的调试信息:错误分类、常见原因、排查步骤和修复模式。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
code: {
|
||||
type: "string",
|
||||
description: "有问题的代码",
|
||||
},
|
||||
error_message: {
|
||||
type: "string",
|
||||
description: "错误信息或堆栈跟踪",
|
||||
},
|
||||
language: {
|
||||
type: "string",
|
||||
description: "编程语言",
|
||||
},
|
||||
expected_behavior: {
|
||||
type: "string",
|
||||
description: "期望的正确行为(可选)",
|
||||
},
|
||||
},
|
||||
required: ["code", "error_message", "language"],
|
||||
},
|
||||
};
|
||||
const errorPatterns = [
|
||||
{
|
||||
pattern: /TypeError.*(?:undefined|null|is not a function|Cannot read prop)/i,
|
||||
category: "类型错误 (TypeError)",
|
||||
commonCauses: [
|
||||
"访问了 undefined/null 的属性",
|
||||
"函数调用目标不是函数",
|
||||
"异步操作返回值未正确 await",
|
||||
"解构赋值时对象为空",
|
||||
],
|
||||
fixStrategies: [
|
||||
"使用可选链 ?. 和空值合并 ??",
|
||||
"添加前置空值检查",
|
||||
"确认异步操作是否正确 await",
|
||||
"检查 import 路径和导出方式是否匹配",
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /ReferenceError.*is not defined/i,
|
||||
category: "引用错误 (ReferenceError)",
|
||||
commonCauses: [
|
||||
"变量/函数未声明就使用",
|
||||
"拼写错误",
|
||||
"作用域问题(块级作用域、闭包)",
|
||||
"缺少 import 语句",
|
||||
],
|
||||
fixStrategies: [
|
||||
"检查变量名拼写",
|
||||
"确认 import/require 语句",
|
||||
"检查变量声明的作用域",
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /SyntaxError/i,
|
||||
category: "语法错误 (SyntaxError)",
|
||||
commonCauses: [
|
||||
"括号/引号不匹配",
|
||||
"缺少分号或逗号",
|
||||
"关键字拼写错误",
|
||||
"ESM/CJS 混用",
|
||||
],
|
||||
fixStrategies: [
|
||||
"检查报错行及前几行的括号/引号匹配",
|
||||
"确认模块系统一致性(import vs require)",
|
||||
"使用格式化工具自动修复",
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /ECONNREFUSED|ETIMEDOUT|ENOTFOUND|fetch failed|network/i,
|
||||
category: "网络错误",
|
||||
commonCauses: [
|
||||
"目标服务未启动",
|
||||
"URL/端口配置错误",
|
||||
"DNS 解析失败",
|
||||
"防火墙/代理阻断",
|
||||
"SSL 证书问题",
|
||||
],
|
||||
fixStrategies: [
|
||||
"确认目标服务运行状态和端口",
|
||||
"检查 URL 配置(协议、域名、端口)",
|
||||
"添加重试机制和超时控制",
|
||||
"检查网络连通性",
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /ENOENT|no such file|Module not found|Cannot find module/i,
|
||||
category: "文件/模块未找到",
|
||||
commonCauses: [
|
||||
"文件路径错误",
|
||||
"依赖未安装(缺少 npm install)",
|
||||
"相对路径 vs 绝对路径搞混",
|
||||
"文件扩展名不匹配",
|
||||
],
|
||||
fixStrategies: [
|
||||
"检查文件路径和大小写",
|
||||
"运行 npm install 安装依赖",
|
||||
"检查 tsconfig/webpack 的路径别名配置",
|
||||
"确认文件扩展名(.js/.ts/.mjs)",
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /Permission denied|EACCES|403|401|Unauthorized/i,
|
||||
category: "权限错误",
|
||||
commonCauses: [
|
||||
"文件权限不足",
|
||||
"API 认证失败(Token 过期/错误)",
|
||||
"CORS 跨域限制",
|
||||
],
|
||||
fixStrategies: [
|
||||
"检查文件/目录权限(chmod)",
|
||||
"检查 API Key / Token 是否有效",
|
||||
"配置正确的 CORS 头",
|
||||
],
|
||||
},
|
||||
{
|
||||
pattern: /out of memory|heap|stack overflow|Maximum call stack/i,
|
||||
category: "内存/栈溢出",
|
||||
commonCauses: [
|
||||
"无限递归",
|
||||
"处理超大数据集未分页",
|
||||
"内存泄漏(未清理的引用)",
|
||||
],
|
||||
fixStrategies: [
|
||||
"检查递归终止条件",
|
||||
"对大数据使用流式处理或分页",
|
||||
"使用 --max-old-space-size 调整堆内存",
|
||||
"排查事件监听器和定时器泄漏",
|
||||
],
|
||||
},
|
||||
];
|
||||
export async function executeCodeDebug(args) {
|
||||
const { code, error_message, language, expected_behavior } = args;
|
||||
// 匹配错误模式
|
||||
const matched = errorPatterns.filter((ep) => ep.pattern.test(error_message));
|
||||
const categories = matched.length > 0 ? matched : [{
|
||||
category: "未分类错误",
|
||||
commonCauses: ["请仔细阅读完整错误信息和堆栈"],
|
||||
fixStrategies: ["根据错误信息定位问题代码行", "添加日志逐步排查"],
|
||||
}];
|
||||
// 从堆栈中提取行号
|
||||
const lineRefs = [];
|
||||
const lineRegex = /(?:at\s+.+?|File\s+.+?):(\d+)(?::(\d+))?/g;
|
||||
let match;
|
||||
while ((match = lineRegex.exec(error_message)) !== null) {
|
||||
lineRefs.push(`行 ${match[1]}${match[2] ? `:${match[2]}` : ""}`);
|
||||
}
|
||||
const output = [
|
||||
`# 调试分析报告`,
|
||||
``,
|
||||
`**语言**: ${language}`,
|
||||
``,
|
||||
`## 错误信息`,
|
||||
"```",
|
||||
error_message,
|
||||
"```",
|
||||
``,
|
||||
];
|
||||
if (lineRefs.length > 0) {
|
||||
output.push(`## 堆栈中的关键位置`, ...lineRefs.map((l) => `- ${l}`), ``);
|
||||
}
|
||||
for (const cat of categories) {
|
||||
output.push(`## 错误类型: ${cat.category}`, ``, `### 常见原因`, ...cat.commonCauses.map((c) => `- ${c}`), ``, `### 修复策略`, ...cat.fixStrategies.map((s) => `- ${s}`), ``);
|
||||
}
|
||||
if (expected_behavior) {
|
||||
output.push(`## 期望行为`, expected_behavior, ``);
|
||||
}
|
||||
output.push(`## 问题代码`, "```" + language, code, "```", ``, `## 排查步骤`, `1. 根据以上错误分类和常见原因,定位问题代码行`, `2. 在可疑位置添加日志输出,验证变量值`, `3. 根据修复策略实施修改`, `4. 编写测试用例确认修复有效`);
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=codeDebug.js.map
|
||||
1
dev-assistant-mcp/dist/tools/codeDebug.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/codeDebug.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codeDebug.js","sourceRoot":"","sources":["../../src/tools/codeDebug.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,IAAI,EAAE,YAAY;IAClB,WAAW,EACT,wCAAwC;IAC1C,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,QAAQ;aACtB;YACD,aAAa,EAAE;gBACb,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,WAAW;aACzB;YACD,QAAQ,EAAE;gBACR,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,MAAM;aACpB;YACD,iBAAiB,EAAE;gBACjB,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,aAAa;aAC3B;SACF;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,eAAe,EAAE,UAAU,CAAC;KAChD;CACF,CAAC;AASF,MAAM,aAAa,GAAmB;IACpC;QACE,OAAO,EAAE,mEAAmE;QAC5E,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE;YACZ,wBAAwB;YACxB,YAAY;YACZ,kBAAkB;YAClB,WAAW;SACZ;QACD,aAAa,EAAE;YACb,mBAAmB;YACnB,UAAU;YACV,kBAAkB;YAClB,uBAAuB;SACxB;KACF;IACD;QACE,OAAO,EAAE,iCAAiC;QAC1C,QAAQ,EAAE,uBAAuB;QACjC,YAAY,EAAE;YACZ,aAAa;YACb,MAAM;YACN,iBAAiB;YACjB,cAAc;SACf;QACD,aAAa,EAAE;YACb,SAAS;YACT,sBAAsB;YACtB,YAAY;SACb;KACF;IACD;QACE,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,oBAAoB;QAC9B,YAAY,EAAE;YACZ,UAAU;YACV,SAAS;YACT,SAAS;YACT,YAAY;SACb;QACD,aAAa,EAAE;YACb,mBAAmB;YACnB,8BAA8B;YAC9B,aAAa;SACd;KACF;IACD;QACE,OAAO,EAAE,wDAAwD;QACjE,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE;YACZ,SAAS;YACT,YAAY;YACZ,UAAU;YACV,UAAU;YACV,UAAU;SACX;QACD,aAAa,EAAE;YACb,eAAe;YACf,qBAAqB;YACrB,aAAa;YACb,SAAS;SACV;KACF;IACD;QACE,OAAO,EAAE,0DAA0D;QACnE,QAAQ,EAAE,UAAU;QACpB,YAAY,EAAE;YACZ,QAAQ;YACR,uBAAuB;YACvB,gBAAgB;YAChB,UAAU;SACX;QACD,aAAa,EAAE;YACb,YAAY;YACZ,qBAAqB;YACrB,6BAA6B;YAC7B,uBAAuB;SACxB;KACF;IACD;QACE,OAAO,EAAE,gDAAgD;QACzD,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE;YACZ,QAAQ;YACR,uBAAuB;YACvB,WAAW;SACZ;QACD,aAAa,EAAE;YACb,kBAAkB;YAClB,yBAAyB;YACzB,cAAc;SACf;KACF;IACD;QACE,OAAO,EAAE,uDAAuD;QAChE,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE;YACZ,MAAM;YACN,YAAY;YACZ,cAAc;SACf;QACD,aAAa,EAAE;YACb,UAAU;YACV,eAAe;YACf,+BAA+B;YAC/B,eAAe;SAChB;KACF;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAKtC;IACC,MAAM,EAAE,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC;IAElE,SAAS;IACT,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC;IAC7E,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACjD,QAAQ,EAAE,OAAO;YACjB,YAAY,EAAE,CAAC,gBAAgB,CAAC;YAChC,aAAa,EAAE,CAAC,eAAe,EAAE,UAAU,CAAC;SAC7C,CAAC,CAAC;IAEH,WAAW;IACX,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,2CAA2C,CAAC;IAC9D,IAAI,KAAK,CAAC;IACV,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACxD,QAAQ,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IAED,MAAM,MAAM,GAAa;QACvB,UAAU;QACV,EAAE;QACF,WAAW,QAAQ,EAAE;QACrB,EAAE;QACF,SAAS;QACT,KAAK;QACL,aAAa;QACb,KAAK;QACL,EAAE;KACH,CAAC;IAEF,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CACT,YAAY,GAAG,CAAC,QAAQ,EAAE,EAC1B,EAAE,EACF,UAAU,EACV,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EACxC,EAAE,EACF,UAAU,EACV,GAAG,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EACzC,EAAE,CACH,CAAC;IACJ,CAAC;IAED,IAAI,iBAAiB,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,CAAC,IAAI,CACT,SAAS,EACT,KAAK,GAAG,QAAQ,EAChB,IAAI,EACJ,KAAK,EACL,EAAE,EACF,SAAS,EACT,0BAA0B,EAC1B,sBAAsB,EACtB,eAAe,EACf,iBAAiB,CAClB,CAAC;IAEF,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC"}
|
||||
29
dev-assistant-mcp/dist/tools/codeReview.d.ts
vendored
Normal file
29
dev-assistant-mcp/dist/tools/codeReview.d.ts
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
export declare const codeReviewTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
code: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
language: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
focus: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeCodeReview(args: {
|
||||
code: string;
|
||||
language: string;
|
||||
focus?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=codeReview.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/codeReview.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/codeReview.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codeReview.d.ts","sourceRoot":"","sources":["../../src/tools/codeReview.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;CAwB1B,CAAC;AA6BF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAyGlB"}
|
||||
159
dev-assistant-mcp/dist/tools/codeReview.js
vendored
Normal file
159
dev-assistant-mcp/dist/tools/codeReview.js
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
export const codeReviewTool = {
|
||||
name: "code_review",
|
||||
description: "审查代码质量。根据审查重点返回结构化的检查清单和分析结果,涵盖 bug、安全、性能、风格等维度。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
code: {
|
||||
type: "string",
|
||||
description: "要审查的代码",
|
||||
},
|
||||
language: {
|
||||
type: "string",
|
||||
description: "编程语言(如 typescript, python, java 等)",
|
||||
},
|
||||
focus: {
|
||||
type: "string",
|
||||
description: "审查重点(可选):security=安全性, performance=性能, style=代码风格, all=全面审查",
|
||||
enum: ["security", "performance", "style", "all"],
|
||||
},
|
||||
},
|
||||
required: ["code", "language"],
|
||||
},
|
||||
};
|
||||
const reviewChecklists = {
|
||||
security: [
|
||||
"检查是否存在 SQL 注入、XSS、CSRF 等注入攻击风险",
|
||||
"检查是否硬编码了密钥、密码、Token 等敏感信息",
|
||||
"检查用户输入是否经过验证和清洗",
|
||||
"检查权限控制是否完善,是否有越权风险",
|
||||
"检查是否使用了不安全的加密算法或随机数生成",
|
||||
"检查第三方依赖是否有已知安全漏洞",
|
||||
],
|
||||
performance: [
|
||||
"检查是否存在不必要的循环嵌套或 O(n²) 以上复杂度",
|
||||
"检查是否有内存泄漏(未清理的定时器、事件监听、闭包)",
|
||||
"检查是否有不必要的重复计算,是否需要缓存/记忆化",
|
||||
"检查异步操作是否可以并行化(Promise.all)",
|
||||
"检查是否有阻塞主线程的同步操作",
|
||||
"检查数据库查询是否有 N+1 问题",
|
||||
],
|
||||
style: [
|
||||
"检查命名是否清晰表达意图(变量、函数、类)",
|
||||
"检查函数长度是否超过 50 行,是否需要拆分",
|
||||
"检查嵌套层级是否过深(>3 层),是否可用 guard clause",
|
||||
"检查是否有重复代码(DRY 原则)",
|
||||
"检查注释是否准确且必要,而非冗余",
|
||||
"检查是否遵循语言社区的标准代码风格",
|
||||
],
|
||||
};
|
||||
export async function executeCodeReview(args) {
|
||||
const { code, language, focus = "all" } = args;
|
||||
const lines = code.split("\n");
|
||||
const lineCount = lines.length;
|
||||
// 基础代码统计
|
||||
const stats = {
|
||||
totalLines: lineCount,
|
||||
blankLines: lines.filter((l) => l.trim() === "").length,
|
||||
commentLines: lines.filter((l) => {
|
||||
const t = l.trim();
|
||||
return t.startsWith("//") || t.startsWith("#") || t.startsWith("/*") || t.startsWith("*");
|
||||
}).length,
|
||||
codeLines: 0,
|
||||
maxLineLength: Math.max(...lines.map((l) => l.length)),
|
||||
maxNestingDepth: 0,
|
||||
};
|
||||
stats.codeLines = stats.totalLines - stats.blankLines - stats.commentLines;
|
||||
// 计算最大嵌套深度
|
||||
let depth = 0;
|
||||
for (const line of lines) {
|
||||
const opens = (line.match(/{/g) || []).length;
|
||||
const closes = (line.match(/}/g) || []).length;
|
||||
depth += opens - closes;
|
||||
if (depth > stats.maxNestingDepth)
|
||||
stats.maxNestingDepth = depth;
|
||||
}
|
||||
// 检测潜在问题
|
||||
const issues = [];
|
||||
// 通用检查
|
||||
if (stats.maxLineLength > 120)
|
||||
issues.push(`⚠️ 存在超长行(最长 ${stats.maxLineLength} 字符),建议不超过 120`);
|
||||
if (stats.maxNestingDepth > 4)
|
||||
issues.push(`⚠️ 嵌套层级过深(${stats.maxNestingDepth} 层),建议重构`);
|
||||
if (stats.codeLines > 300)
|
||||
issues.push(`⚠️ 文件过长(${stats.codeLines} 行代码),建议拆分`);
|
||||
if (stats.commentLines === 0 && stats.codeLines > 30)
|
||||
issues.push("🔵 缺少注释,建议为关键逻辑添加说明");
|
||||
// 安全检查
|
||||
if (focus === "security" || focus === "all") {
|
||||
if (/eval\s*\(/.test(code))
|
||||
issues.push("🔴 使用了 eval(),存在代码注入风险");
|
||||
if (/innerHTML\s*=/.test(code))
|
||||
issues.push("🔴 使用了 innerHTML,存在 XSS 风险");
|
||||
if (/(password|secret|api_?key|token)\s*=\s*["'][^"']+["']/i.test(code))
|
||||
issues.push("🔴 可能硬编码了敏感信息");
|
||||
if (/\bhttp:\/\//.test(code))
|
||||
issues.push("🟡 使用了 HTTP 而非 HTTPS");
|
||||
if (/exec\s*\(|spawn\s*\(/.test(code) && !/sanitize|escape|validate/.test(code))
|
||||
issues.push("🟡 执行了外部命令,确认输入已清洗");
|
||||
}
|
||||
// 性能检查
|
||||
if (focus === "performance" || focus === "all") {
|
||||
if (/for\s*\(.*for\s*\(/s.test(code))
|
||||
issues.push("🟡 存在嵌套循环,注意时间复杂度");
|
||||
if (/setTimeout|setInterval/.test(code) && !/clearTimeout|clearInterval/.test(code))
|
||||
issues.push("<22> 设置了定时器但未见清理,可能内存泄漏");
|
||||
if (/\.forEach\(.*await/.test(code))
|
||||
issues.push("🟡 在 forEach 中使用 await,不会等待完成,建议用 for...of");
|
||||
if (/new RegExp\(/.test(code) && /for|while|map|forEach/.test(code))
|
||||
issues.push("🔵 循环中创建正则表达式,建议提取到循环外");
|
||||
}
|
||||
// 风格检查
|
||||
if (focus === "style" || focus === "all") {
|
||||
if (/var\s+/.test(code) && (language === "typescript" || language === "javascript"))
|
||||
issues.push("🔵 使用了 var,建议改用 const/let");
|
||||
if (/console\.log/.test(code))
|
||||
issues.push("🔵 包含 console.log,确认是否需要在生产环境移除");
|
||||
if (/any/.test(code) && language === "typescript")
|
||||
issues.push("🔵 使用了 any 类型,建议使用具体类型");
|
||||
if (/TODO|FIXME|HACK|XXX/.test(code))
|
||||
issues.push("🔵 存在 TODO/FIXME 标记,建议处理");
|
||||
}
|
||||
// 获取对应的检查清单
|
||||
let checklist;
|
||||
if (focus === "all") {
|
||||
checklist = [
|
||||
...reviewChecklists.security,
|
||||
...reviewChecklists.performance,
|
||||
...reviewChecklists.style,
|
||||
];
|
||||
}
|
||||
else {
|
||||
checklist = reviewChecklists[focus] || reviewChecklists.style;
|
||||
}
|
||||
// 组装结果
|
||||
const output = [
|
||||
`# 代码审查报告`,
|
||||
``,
|
||||
`**语言**: ${language} | **审查重点**: ${focus}`,
|
||||
``,
|
||||
`## 代码统计`,
|
||||
`- 总行数: ${stats.totalLines}(代码 ${stats.codeLines} / 注释 ${stats.commentLines} / 空行 ${stats.blankLines})`,
|
||||
`- 最长行: ${stats.maxLineLength} 字符`,
|
||||
`- 最大嵌套深度: ${stats.maxNestingDepth} 层`,
|
||||
``,
|
||||
`## 自动检测到的问题(${issues.length} 项)`,
|
||||
issues.length > 0 ? issues.map((i) => `- ${i}`).join("\n") : "- ✅ 未检测到明显问题",
|
||||
``,
|
||||
`## 人工审查清单`,
|
||||
`请逐项检查以下内容:`,
|
||||
...checklist.map((item, idx) => `${idx + 1}. ${item}`),
|
||||
``,
|
||||
`## 待审查代码`,
|
||||
"```" + language,
|
||||
code,
|
||||
"```",
|
||||
];
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=codeReview.js.map
|
||||
1
dev-assistant-mcp/dist/tools/codeReview.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/codeReview.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
33
dev-assistant-mcp/dist/tools/codeWrite.d.ts
vendored
Normal file
33
dev-assistant-mcp/dist/tools/codeWrite.d.ts
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
export declare const codeWriteTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
requirement: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
language: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
framework: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
context: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeCodeWrite(args: {
|
||||
requirement: string;
|
||||
language: string;
|
||||
framework?: string;
|
||||
context?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=codeWrite.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/codeWrite.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/codeWrite.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codeWrite.d.ts","sourceRoot":"","sources":["../../src/tools/codeWrite.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;CA0BzB,CAAC;AA4GF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4DlB"}
|
||||
162
dev-assistant-mcp/dist/tools/codeWrite.js
vendored
Normal file
162
dev-assistant-mcp/dist/tools/codeWrite.js
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
export const codeWriteTool = {
|
||||
name: "code_write",
|
||||
description: "根据需求描述生成代码编写指引。返回结构化的需求分析、技术方案、代码骨架和最佳实践建议。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
requirement: {
|
||||
type: "string",
|
||||
description: "功能需求描述",
|
||||
},
|
||||
language: {
|
||||
type: "string",
|
||||
description: "编程语言(如 typescript, python, java 等)",
|
||||
},
|
||||
framework: {
|
||||
type: "string",
|
||||
description: "框架(可选,如 react, express, fastapi 等)",
|
||||
},
|
||||
context: {
|
||||
type: "string",
|
||||
description: "额外上下文(可选,如现有代码片段、接口定义等)",
|
||||
},
|
||||
},
|
||||
required: ["requirement", "language"],
|
||||
},
|
||||
};
|
||||
const languageBestPractices = {
|
||||
typescript: [
|
||||
"使用严格类型,避免 any",
|
||||
"用 interface/type 定义数据结构",
|
||||
"async/await 处理异步",
|
||||
"使用 const 优先,必要时 let",
|
||||
"错误处理使用 try-catch + 自定义 Error 类",
|
||||
],
|
||||
javascript: [
|
||||
"使用 const/let,禁用 var",
|
||||
"使用 JSDoc 注释函数签名",
|
||||
"async/await 处理异步",
|
||||
"使用解构赋值简化代码",
|
||||
"模块化:每个文件单一职责",
|
||||
],
|
||||
python: [
|
||||
"遵循 PEP 8 风格规范",
|
||||
"使用 type hints 标注类型",
|
||||
"使用 dataclass/Pydantic 定义数据模型",
|
||||
"用 with 语句管理资源",
|
||||
"异常处理:捕获具体异常而非 Exception",
|
||||
],
|
||||
java: [
|
||||
"遵循 Java 命名约定",
|
||||
"使用 Optional 避免 NullPointerException",
|
||||
"用 Stream API 处理集合",
|
||||
"接口优先于实现",
|
||||
"使用 Lombok 减少样板代码",
|
||||
],
|
||||
};
|
||||
const frameworkTemplates = {
|
||||
react: `// React 组件骨架
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
interface Props {
|
||||
// TODO: 定义 props
|
||||
}
|
||||
|
||||
export function ComponentName({ }: Props) {
|
||||
const [state, setState] = useState();
|
||||
|
||||
useEffect(() => {
|
||||
// TODO: 副作用逻辑
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
{/* TODO: JSX 结构 */}
|
||||
</div>
|
||||
);
|
||||
}`,
|
||||
express: `// Express 路由骨架
|
||||
import express from 'express';
|
||||
const router = express.Router();
|
||||
|
||||
router.get('/', async (req, res) => {
|
||||
try {
|
||||
// TODO: 业务逻辑
|
||||
res.json({ success: true, data: {} });
|
||||
} catch (error) {
|
||||
res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
});
|
||||
|
||||
export default router;`,
|
||||
fastapi: `# FastAPI 路由骨架
|
||||
from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class RequestModel(BaseModel):
|
||||
# TODO: 定义请求模型
|
||||
pass
|
||||
|
||||
class ResponseModel(BaseModel):
|
||||
success: bool
|
||||
data: dict = {}
|
||||
|
||||
@router.get("/", response_model=ResponseModel)
|
||||
async def handler():
|
||||
try:
|
||||
# TODO: 业务逻辑
|
||||
return ResponseModel(success=True, data={})
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))`,
|
||||
vue: `<!-- Vue 组件骨架 -->
|
||||
<template>
|
||||
<div>
|
||||
<!-- TODO: 模板结构 -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
|
||||
// TODO: 定义响应式状态
|
||||
const state = ref();
|
||||
|
||||
onMounted(() => {
|
||||
// TODO: 初始化逻辑
|
||||
});
|
||||
</script>`,
|
||||
};
|
||||
export async function executeCodeWrite(args) {
|
||||
const { requirement, language, framework, context } = args;
|
||||
const practices = languageBestPractices[language.toLowerCase()] || [
|
||||
"遵循语言社区标准",
|
||||
"添加类型标注",
|
||||
"做好错误处理",
|
||||
"保持函数单一职责",
|
||||
];
|
||||
const output = [
|
||||
`# 代码编写指引`,
|
||||
``,
|
||||
`## 需求`,
|
||||
requirement,
|
||||
``,
|
||||
`## 技术规格`,
|
||||
`- **语言**: ${language}`,
|
||||
];
|
||||
if (framework) {
|
||||
output.push(`- **框架**: ${framework}`);
|
||||
}
|
||||
output.push(``, `## ${language} 最佳实践`, ...practices.map((p) => `- ${p}`), ``);
|
||||
if (framework && frameworkTemplates[framework.toLowerCase()]) {
|
||||
output.push(`## 代码骨架模板`, "```" + language, frameworkTemplates[framework.toLowerCase()], "```", ``);
|
||||
}
|
||||
output.push(`## 编写要求`, `1. 代码必须完整可运行,包含所有必要的 import`, `2. 遵循 ${language} 最佳实践和命名规范`, `3. 关键逻辑添加简洁注释`, `4. 包含必要的错误处理和边界检查`, `5. 函数保持单一职责,不超过 50 行`, ``);
|
||||
if (context) {
|
||||
output.push(`## 参考上下文`, "```", context, "```", ``);
|
||||
}
|
||||
output.push(`## 请根据以上指引生成完整代码`);
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=codeWrite.js.map
|
||||
1
dev-assistant-mcp/dist/tools/codeWrite.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/codeWrite.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"codeWrite.js","sourceRoot":"","sources":["../../src/tools/codeWrite.ts"],"names":[],"mappings":"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"}
|
||||
34
dev-assistant-mcp/dist/tools/depManage.d.ts
vendored
Normal file
34
dev-assistant-mcp/dist/tools/depManage.d.ts
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
export declare const depManageTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
action: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
packages: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
dev: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeDepManage(args: {
|
||||
project_path: string;
|
||||
action: string;
|
||||
packages?: string;
|
||||
dev?: boolean;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=depManage.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/depManage.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/depManage.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"depManage.d.ts","sourceRoot":"","sources":["../../src/tools/depManage.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BzB,CAAC;AAeF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAgIlB"}
|
||||
175
dev-assistant-mcp/dist/tools/depManage.js
vendored
Normal file
175
dev-assistant-mcp/dist/tools/depManage.js
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { existsSync } from "fs";
|
||||
import { join } from "path";
|
||||
const execAsync = promisify(exec);
|
||||
export const depManageTool = {
|
||||
name: "dep_manage",
|
||||
description: "依赖管理。安装/更新/删除依赖、检查过时包、安全漏洞审计、分析 bundle 大小。支持 npm 和 pip。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
action: {
|
||||
type: "string",
|
||||
description: "操作类型",
|
||||
enum: ["install", "add", "remove", "update", "outdated", "audit", "list", "why"],
|
||||
},
|
||||
packages: {
|
||||
type: "string",
|
||||
description: "包名(多个用空格分隔),add/remove/why 时必填",
|
||||
},
|
||||
dev: {
|
||||
type: "boolean",
|
||||
description: "是否为开发依赖(默认 false)",
|
||||
},
|
||||
},
|
||||
required: ["project_path", "action"],
|
||||
},
|
||||
};
|
||||
async function run(cmd, cwd, timeout = 120000) {
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(cmd, {
|
||||
cwd, timeout,
|
||||
maxBuffer: 1024 * 1024 * 10,
|
||||
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 executeDepManage(args) {
|
||||
const { project_path, action, packages, dev = false } = args;
|
||||
const hasFile = (name) => existsSync(join(project_path, name));
|
||||
const isNode = hasFile("package.json");
|
||||
const isPython = hasFile("requirements.txt") || hasFile("pyproject.toml");
|
||||
if (!isNode && !isPython) {
|
||||
return "❌ 未检测到 package.json 或 requirements.txt";
|
||||
}
|
||||
let cmd = "";
|
||||
let title = "";
|
||||
if (isNode) {
|
||||
switch (action) {
|
||||
case "install":
|
||||
cmd = "npm install";
|
||||
title = "npm install";
|
||||
break;
|
||||
case "add":
|
||||
if (!packages)
|
||||
return "❌ add 需要 packages 参数";
|
||||
cmd = `npm install ${packages}${dev ? " --save-dev" : ""}`;
|
||||
title = `npm install ${packages}${dev ? " (dev)" : ""}`;
|
||||
break;
|
||||
case "remove":
|
||||
if (!packages)
|
||||
return "❌ remove 需要 packages 参数";
|
||||
cmd = `npm uninstall ${packages}`;
|
||||
title = `npm uninstall ${packages}`;
|
||||
break;
|
||||
case "update":
|
||||
cmd = packages ? `npm update ${packages}` : "npm update";
|
||||
title = `npm update${packages ? ` ${packages}` : ""}`;
|
||||
break;
|
||||
case "outdated":
|
||||
cmd = "npm outdated --long 2>&1 || true";
|
||||
title = "npm outdated(过时依赖检查)";
|
||||
break;
|
||||
case "audit":
|
||||
cmd = "npm audit 2>&1 || true";
|
||||
title = "npm audit(安全漏洞审计)";
|
||||
break;
|
||||
case "list":
|
||||
cmd = "npm list --depth=0 2>&1";
|
||||
title = "npm list(已安装依赖)";
|
||||
break;
|
||||
case "why":
|
||||
if (!packages)
|
||||
return "❌ why 需要 packages 参数";
|
||||
cmd = `npm why ${packages} 2>&1`;
|
||||
title = `npm why ${packages}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (isPython) {
|
||||
switch (action) {
|
||||
case "install":
|
||||
cmd = hasFile("requirements.txt") ? "pip install -r requirements.txt" : "pip install -e .";
|
||||
title = "pip install";
|
||||
break;
|
||||
case "add":
|
||||
if (!packages)
|
||||
return "❌ add 需要 packages 参数";
|
||||
cmd = `pip install ${packages}`;
|
||||
title = `pip install ${packages}`;
|
||||
break;
|
||||
case "remove":
|
||||
if (!packages)
|
||||
return "❌ remove 需要 packages 参数";
|
||||
cmd = `pip uninstall -y ${packages}`;
|
||||
title = `pip uninstall ${packages}`;
|
||||
break;
|
||||
case "update":
|
||||
cmd = packages ? `pip install --upgrade ${packages}` : "pip install --upgrade -r requirements.txt";
|
||||
title = `pip upgrade${packages ? ` ${packages}` : ""}`;
|
||||
break;
|
||||
case "outdated":
|
||||
cmd = "pip list --outdated 2>&1";
|
||||
title = "pip outdated";
|
||||
break;
|
||||
case "audit":
|
||||
cmd = "pip-audit 2>&1 || pip check 2>&1";
|
||||
title = "pip audit / check";
|
||||
break;
|
||||
case "list":
|
||||
cmd = "pip list 2>&1";
|
||||
title = "pip list";
|
||||
break;
|
||||
case "why":
|
||||
if (!packages)
|
||||
return "❌ why 需要 packages 参数";
|
||||
cmd = `pip show ${packages} 2>&1`;
|
||||
title = `pip show ${packages}`;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cmd)
|
||||
return `❌ 未知操作: ${action}`;
|
||||
const result = await run(cmd, project_path);
|
||||
const fullOutput = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
||||
const icon = result.code === 0 ? "✅" : "⚠️";
|
||||
const output = [
|
||||
`# ${icon} ${title}`,
|
||||
``,
|
||||
`📂 ${project_path}`,
|
||||
`📦 ${isNode ? "npm" : "pip"}`,
|
||||
``,
|
||||
"```",
|
||||
fullOutput.slice(0, 6000) || "(无输出)",
|
||||
"```",
|
||||
];
|
||||
// audit 额外解析
|
||||
if (action === "audit" && isNode) {
|
||||
const criticalMatch = fullOutput.match(/(\d+)\s+(critical|high)/gi);
|
||||
if (criticalMatch && criticalMatch.length > 0) {
|
||||
output.push(``, `⚠️ **发现高危漏洞!** 建议运行 \`npm audit fix\` 或 \`npm audit fix --force\``);
|
||||
}
|
||||
else if (result.code === 0) {
|
||||
output.push(``, `✅ 未发现已知安全漏洞`);
|
||||
}
|
||||
}
|
||||
// outdated 额外解析
|
||||
if (action === "outdated" && fullOutput.trim()) {
|
||||
const lines = fullOutput.trim().split("\n").filter((l) => l.trim());
|
||||
if (lines.length > 1) {
|
||||
output.push(``, `📊 发现 ${lines.length - 1} 个可更新的包`);
|
||||
output.push(`💡 运行 \`dep_manage action=update\` 更新所有包`);
|
||||
}
|
||||
}
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=depManage.js.map
|
||||
1
dev-assistant-mcp/dist/tools/depManage.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/depManage.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
39
dev-assistant-mcp/dist/tools/devServer.d.ts
vendored
Normal file
39
dev-assistant-mcp/dist/tools/devServer.d.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
export declare const devServerTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
action: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
command: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
name: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
tail: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeDevServer(args: {
|
||||
project_path?: string;
|
||||
action: string;
|
||||
command?: string;
|
||||
name?: string;
|
||||
tail?: number;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=devServer.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/devServer.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/devServer.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"devServer.d.ts","sourceRoot":"","sources":["../../src/tools/devServer.ts"],"names":[],"mappings":"AAgBA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BzB,CAAC;AAkCF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAuLlB"}
|
||||
229
dev-assistant-mcp/dist/tools/devServer.js
vendored
Normal file
229
dev-assistant-mcp/dist/tools/devServer.js
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
import { exec, spawn } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { existsSync, readFileSync } from "fs";
|
||||
import { join } from "path";
|
||||
const execAsync = promisify(exec);
|
||||
// 进程管理器 - 跟踪所有启动的开发服务器
|
||||
const managedProcesses = new Map();
|
||||
export const devServerTool = {
|
||||
name: "dev_server",
|
||||
description: "开发服务器管理。启动/停止/重启开发服务器,查看运行状态和实时日志。支持自动检测项目的 dev 命令。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
action: {
|
||||
type: "string",
|
||||
description: "操作类型",
|
||||
enum: ["start", "stop", "restart", "status", "logs", "list"],
|
||||
},
|
||||
command: {
|
||||
type: "string",
|
||||
description: "自定义启动命令(可选,默认自动检测 npm run dev 等)",
|
||||
},
|
||||
name: {
|
||||
type: "string",
|
||||
description: "服务器名称/标识(可选,默认使用目录名)",
|
||||
},
|
||||
tail: {
|
||||
type: "number",
|
||||
description: "显示最近几行日志(默认 30)",
|
||||
},
|
||||
},
|
||||
required: ["action"],
|
||||
},
|
||||
};
|
||||
function getServerName(projectPath, name) {
|
||||
if (name)
|
||||
return name;
|
||||
if (projectPath)
|
||||
return projectPath.split(/[/\\]/).pop() || "server";
|
||||
return "default";
|
||||
}
|
||||
function detectDevCommand(projectPath) {
|
||||
const pkgPath = join(projectPath, "package.json");
|
||||
if (existsSync(pkgPath)) {
|
||||
try {
|
||||
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
||||
const scripts = pkg.scripts || {};
|
||||
// 按优先级检测
|
||||
for (const name of ["dev", "start:dev", "serve", "start"]) {
|
||||
if (scripts[name])
|
||||
return `npm run ${name}`;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (existsSync(join(projectPath, "manage.py"))) {
|
||||
return "python manage.py runserver";
|
||||
}
|
||||
if (existsSync(join(projectPath, "main.py"))) {
|
||||
return "python main.py";
|
||||
}
|
||||
if (existsSync(join(projectPath, "app.py"))) {
|
||||
return "python app.py";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
export async function executeDevServer(args) {
|
||||
const { project_path, action, command, name, tail = 30 } = args;
|
||||
switch (action) {
|
||||
case "list": {
|
||||
if (managedProcesses.size === 0) {
|
||||
return "# 开发服务器\n\n_没有正在运行的服务器_";
|
||||
}
|
||||
const output = ["# 运行中的开发服务器", ""];
|
||||
for (const [key, info] of managedProcesses) {
|
||||
const running = !info.process.killed && info.process.exitCode === null;
|
||||
const uptime = Math.round((Date.now() - info.startTime) / 1000);
|
||||
output.push(`## ${running ? "🟢" : "🔴"} ${key}`, `- 命令: \`${info.command}\``, `- 目录: ${info.cwd}`, `- PID: ${info.process.pid}`, `- 运行时间: ${uptime}s`, `- 状态: ${running ? "运行中" : "已停止"}`, ``);
|
||||
}
|
||||
return output.join("\n");
|
||||
}
|
||||
case "start": {
|
||||
if (!project_path)
|
||||
return "❌ start 需要 project_path 参数";
|
||||
const serverName = getServerName(project_path, name);
|
||||
const existing = managedProcesses.get(serverName);
|
||||
if (existing && !existing.process.killed && existing.process.exitCode === null) {
|
||||
return `⚠️ 服务器 "${serverName}" 已在运行中 (PID: ${existing.process.pid})\n\n使用 action=restart 重启,或 action=stop 先停止`;
|
||||
}
|
||||
const startCmd = command || detectDevCommand(project_path);
|
||||
if (!startCmd) {
|
||||
return `❌ 未检测到启动命令,请手动指定 command 参数\n\n常见命令:\n- npm run dev\n- npm start\n- python app.py`;
|
||||
}
|
||||
// 解析命令
|
||||
const isWin = process.platform === "win32";
|
||||
const child = spawn(isWin ? "cmd" : "sh", [isWin ? "/c" : "-c", startCmd], {
|
||||
cwd: project_path,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
detached: false,
|
||||
});
|
||||
const logs = [];
|
||||
const maxLogs = 200;
|
||||
const addLog = (data, stream) => {
|
||||
const lines = data.toString().split("\n").filter(Boolean);
|
||||
for (const line of lines) {
|
||||
logs.push(`[${stream}] ${line}`);
|
||||
if (logs.length > maxLogs)
|
||||
logs.shift();
|
||||
}
|
||||
};
|
||||
child.stdout?.on("data", (data) => addLog(data, "out"));
|
||||
child.stderr?.on("data", (data) => addLog(data, "err"));
|
||||
managedProcesses.set(serverName, {
|
||||
process: child,
|
||||
command: startCmd,
|
||||
cwd: project_path,
|
||||
startTime: Date.now(),
|
||||
logs,
|
||||
});
|
||||
// 等待一会检查是否立即崩溃
|
||||
await new Promise((r) => setTimeout(r, 2000));
|
||||
const crashed = child.exitCode !== null;
|
||||
if (crashed) {
|
||||
const output = logs.join("\n");
|
||||
managedProcesses.delete(serverName);
|
||||
return `# ❌ 服务器启动失败\n\n命令: \`${startCmd}\`\n退出码: ${child.exitCode}\n\n\`\`\`\n${output.slice(0, 3000)}\n\`\`\``;
|
||||
}
|
||||
return [
|
||||
`# ✅ 服务器已启动`,
|
||||
``,
|
||||
`- 名称: ${serverName}`,
|
||||
`- 命令: \`${startCmd}\``,
|
||||
`- PID: ${child.pid}`,
|
||||
`- 目录: ${project_path}`,
|
||||
``,
|
||||
`最近日志:`,
|
||||
"```",
|
||||
logs.slice(-10).join("\n") || "(等待输出...)",
|
||||
"```",
|
||||
``,
|
||||
`💡 使用 \`dev_server action=logs\` 查看实时日志`,
|
||||
].join("\n");
|
||||
}
|
||||
case "stop": {
|
||||
const serverName = getServerName(project_path, name);
|
||||
const info = managedProcesses.get(serverName);
|
||||
if (!info) {
|
||||
return `❌ 未找到服务器 "${serverName}"\n\n使用 action=list 查看所有运行中的服务器`;
|
||||
}
|
||||
const pid = info.process.pid;
|
||||
try {
|
||||
// Windows 需要 taskkill 杀进程树
|
||||
if (process.platform === "win32" && pid) {
|
||||
await execAsync(`taskkill /PID ${pid} /T /F`).catch(() => { });
|
||||
}
|
||||
else {
|
||||
info.process.kill("SIGTERM");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
managedProcesses.delete(serverName);
|
||||
return `# ✅ 服务器已停止\n\n- 名称: ${serverName}\n- PID: ${pid}`;
|
||||
}
|
||||
case "restart": {
|
||||
const serverName = getServerName(project_path, name);
|
||||
const info = managedProcesses.get(serverName);
|
||||
if (info) {
|
||||
try {
|
||||
if (process.platform === "win32" && info.process.pid) {
|
||||
await execAsync(`taskkill /PID ${info.process.pid} /T /F`).catch(() => { });
|
||||
}
|
||||
else {
|
||||
info.process.kill("SIGTERM");
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
managedProcesses.delete(serverName);
|
||||
await new Promise((r) => setTimeout(r, 1000));
|
||||
}
|
||||
// 重新启动
|
||||
return executeDevServer({
|
||||
project_path: info?.cwd || project_path,
|
||||
action: "start",
|
||||
command: command || info?.command,
|
||||
name: serverName,
|
||||
});
|
||||
}
|
||||
case "status": {
|
||||
const serverName = getServerName(project_path, name);
|
||||
const info = managedProcesses.get(serverName);
|
||||
if (!info) {
|
||||
return `❌ 未找到服务器 "${serverName}"`;
|
||||
}
|
||||
const running = !info.process.killed && info.process.exitCode === null;
|
||||
const uptime = Math.round((Date.now() - info.startTime) / 1000);
|
||||
return [
|
||||
`# ${running ? "🟢" : "🔴"} ${serverName}`,
|
||||
``,
|
||||
`- 状态: ${running ? "运行中" : `已停止 (退出码: ${info.process.exitCode})`}`,
|
||||
`- 命令: \`${info.command}\``,
|
||||
`- PID: ${info.process.pid}`,
|
||||
`- 运行时间: ${uptime}s`,
|
||||
`- 目录: ${info.cwd}`,
|
||||
].join("\n");
|
||||
}
|
||||
case "logs": {
|
||||
const serverName = getServerName(project_path, name);
|
||||
const info = managedProcesses.get(serverName);
|
||||
if (!info) {
|
||||
return `❌ 未找到服务器 "${serverName}"`;
|
||||
}
|
||||
const recentLogs = info.logs.slice(-tail);
|
||||
return [
|
||||
`# 📋 ${serverName} 日志(最近 ${tail} 行)`,
|
||||
``,
|
||||
"```",
|
||||
recentLogs.join("\n") || "(无日志)",
|
||||
"```",
|
||||
].join("\n");
|
||||
}
|
||||
default:
|
||||
return `❌ 未知操作: ${action}`;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=devServer.js.map
|
||||
1
dev-assistant-mcp/dist/tools/devServer.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/devServer.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
39
dev-assistant-mcp/dist/tools/docWrite.d.ts
vendored
Normal file
39
dev-assistant-mcp/dist/tools/docWrite.d.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
export declare const docWriteTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
code: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
doc_type: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
language: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
project_name: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
extra_info: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeDocWrite(args: {
|
||||
code: string;
|
||||
doc_type: string;
|
||||
language: string;
|
||||
project_name?: string;
|
||||
extra_info?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=docWrite.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/docWrite.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/docWrite.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"docWrite.d.ts","sourceRoot":"","sources":["../../src/tools/docWrite.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+BxB,CAAC;AA8FF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GAAG,OAAO,CAAC,MAAM,CAAC,CA6ElB"}
|
||||
167
dev-assistant-mcp/dist/tools/docWrite.js
vendored
Normal file
167
dev-assistant-mcp/dist/tools/docWrite.js
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
export const docWriteTool = {
|
||||
name: "doc_write",
|
||||
description: "为代码生成文档指引。分析代码结构,提取函数/类/接口信息,返回结构化的文档框架和编写指引。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
code: {
|
||||
type: "string",
|
||||
description: "需要生成文档的代码",
|
||||
},
|
||||
doc_type: {
|
||||
type: "string",
|
||||
description: "文档类型",
|
||||
enum: ["readme", "api", "inline", "changelog", "jsdoc"],
|
||||
},
|
||||
language: {
|
||||
type: "string",
|
||||
description: "编程语言",
|
||||
},
|
||||
project_name: {
|
||||
type: "string",
|
||||
description: "项目名称(可选,用于 README)",
|
||||
},
|
||||
extra_info: {
|
||||
type: "string",
|
||||
description: "额外信息(可选,如版本号、变更内容等)",
|
||||
},
|
||||
},
|
||||
required: ["code", "doc_type", "language"],
|
||||
},
|
||||
};
|
||||
function extractSymbols(code, language) {
|
||||
const symbols = [];
|
||||
const lines = code.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i].trim();
|
||||
const lineNum = i + 1;
|
||||
// 函数
|
||||
let m;
|
||||
if ((m = line.match(/(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(([^)]*)\)/))) {
|
||||
symbols.push({ type: "function", name: m[1], line: lineNum, signature: m[0] });
|
||||
}
|
||||
// 箭头函数 / const 赋值
|
||||
else if ((m = line.match(/(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(?([^)]*)\)?\s*=>/))) {
|
||||
symbols.push({ type: "function", name: m[1], line: lineNum, signature: m[0] });
|
||||
}
|
||||
// 类
|
||||
else if ((m = line.match(/(?:export\s+)?class\s+(\w+)/))) {
|
||||
symbols.push({ type: "class", name: m[1], line: lineNum });
|
||||
}
|
||||
// 接口 (TS)
|
||||
else if ((m = line.match(/(?:export\s+)?interface\s+(\w+)/))) {
|
||||
symbols.push({ type: "interface", name: m[1], line: lineNum });
|
||||
}
|
||||
// 路由 (Express/FastAPI)
|
||||
else if ((m = line.match(/(?:router|app)\.(get|post|put|delete|patch)\s*\(\s*['"]([^'"]+)['"]/))) {
|
||||
symbols.push({ type: "route", name: `${m[1].toUpperCase()} ${m[2]}`, line: lineNum });
|
||||
}
|
||||
// Python 函数
|
||||
else if ((m = line.match(/(?:async\s+)?def\s+(\w+)\s*\(([^)]*)\)/))) {
|
||||
symbols.push({ type: "function", name: m[1], line: lineNum, signature: m[0] });
|
||||
}
|
||||
// Python 类
|
||||
else if ((m = line.match(/class\s+(\w+)(?:\(([^)]*)\))?:/))) {
|
||||
symbols.push({ type: "class", name: m[1], line: lineNum });
|
||||
}
|
||||
// export default
|
||||
else if ((m = line.match(/export\s+default\s+(\w+)/))) {
|
||||
symbols.push({ type: "export", name: m[1], line: lineNum });
|
||||
}
|
||||
}
|
||||
return symbols;
|
||||
}
|
||||
const docTypeInstructions = {
|
||||
readme: `请生成 README.md,包含以下章节:
|
||||
# 项目名称
|
||||
## 简介(一句话描述)
|
||||
## 功能特性
|
||||
## 快速开始(安装、配置、运行)
|
||||
## API / 使用说明
|
||||
## 项目结构
|
||||
## License`,
|
||||
api: `请生成 API 文档,每个端点/函数包含:
|
||||
- 描述
|
||||
- 请求方法和路径(如适用)
|
||||
- 参数(名称、类型、是否必填、描述)
|
||||
- 返回值(类型、描述)
|
||||
- 示例代码
|
||||
- 错误码(如适用)`,
|
||||
inline: `请为代码添加内联注释:
|
||||
- 每个函数/方法添加文档注释(JSDoc / docstring)
|
||||
- 关键逻辑添加简洁的解释性注释
|
||||
- 不要过度注释显而易见的代码
|
||||
- 返回带注释的完整代码`,
|
||||
changelog: `请生成 CHANGELOG.md,遵循 Keep a Changelog 格式:
|
||||
## [版本号] - 日期
|
||||
### Added(新增)
|
||||
### Changed(变更)
|
||||
### Fixed(修复)
|
||||
### Removed(移除)`,
|
||||
jsdoc: `请为所有函数/类/接口生成文档注释:
|
||||
- @param 参数(类型、描述)
|
||||
- @returns 返回值(类型、描述)
|
||||
- @throws 可能的异常
|
||||
- @example 使用示例
|
||||
- 返回带完整文档注释的代码`,
|
||||
};
|
||||
export async function executeDocWrite(args) {
|
||||
const { code, doc_type, language, project_name, extra_info } = args;
|
||||
const symbols = extractSymbols(code, language);
|
||||
const lines = code.split("\n");
|
||||
const output = [
|
||||
`# 文档生成指引`,
|
||||
``,
|
||||
`**文档类型**: ${doc_type} | **语言**: ${language}${project_name ? ` | **项目**: ${project_name}` : ""}`,
|
||||
``,
|
||||
];
|
||||
// 代码结构分析
|
||||
output.push(`## 代码结构分析`, ``);
|
||||
const functions = symbols.filter((s) => s.type === "function");
|
||||
const classes = symbols.filter((s) => s.type === "class");
|
||||
const interfaces = symbols.filter((s) => s.type === "interface");
|
||||
const routes = symbols.filter((s) => s.type === "route");
|
||||
if (functions.length > 0) {
|
||||
output.push(`### 函数 (${functions.length})`);
|
||||
for (const f of functions) {
|
||||
output.push(`- **${f.name}** (行 ${f.line})${f.signature ? `: \`${f.signature}\`` : ""}`);
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
if (classes.length > 0) {
|
||||
output.push(`### 类 (${classes.length})`);
|
||||
for (const c of classes) {
|
||||
output.push(`- **${c.name}** (行 ${c.line})`);
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
if (interfaces.length > 0) {
|
||||
output.push(`### 接口 (${interfaces.length})`);
|
||||
for (const i of interfaces) {
|
||||
output.push(`- **${i.name}** (行 ${i.line})`);
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
if (routes.length > 0) {
|
||||
output.push(`### API 路由 (${routes.length})`);
|
||||
for (const r of routes) {
|
||||
output.push(`- **${r.name}** (行 ${r.line})`);
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
if (symbols.length === 0) {
|
||||
output.push(`_未检测到标准的函数/类/接口/路由定义_`, ``);
|
||||
}
|
||||
// 统计
|
||||
output.push(`### 文件统计`, `- 总行数: ${lines.length}`, `- 代码符号: ${symbols.length} 个`, ``);
|
||||
// 文档编写指引
|
||||
const instruction = docTypeInstructions[doc_type] || docTypeInstructions.readme;
|
||||
output.push(`## 文档编写指引`, ``, instruction, ``);
|
||||
if (extra_info) {
|
||||
output.push(`## 补充信息`, extra_info, ``);
|
||||
}
|
||||
// 附上源代码
|
||||
output.push(`## 源代码`, "```" + language, code, "```");
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=docWrite.js.map
|
||||
1
dev-assistant-mcp/dist/tools/docWrite.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/docWrite.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
23
dev-assistant-mcp/dist/tools/envCheck.d.ts
vendored
Normal file
23
dev-assistant-mcp/dist/tools/envCheck.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export declare const envCheckTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
checks: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
ports: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: never[];
|
||||
};
|
||||
};
|
||||
export declare function executeEnvCheck(args: {
|
||||
checks?: string;
|
||||
ports?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=envCheck.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/envCheck.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/envCheck.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"envCheck.d.ts","sourceRoot":"","sources":["../../src/tools/envCheck.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;CAkBxB,CAAC;AAmCF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmJlB"}
|
||||
131
dev-assistant-mcp/dist/tools/envCheck.js
vendored
Normal file
131
dev-assistant-mcp/dist/tools/envCheck.js
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { platform, totalmem, freemem, cpus, hostname, userInfo } from "os";
|
||||
const execAsync = promisify(exec);
|
||||
export const envCheckTool = {
|
||||
name: "env_check",
|
||||
description: "环境检测。检查 Node.js、Python、Git 等工具版本,检测端口占用,查看系统资源(CPU/内存/磁盘),验证开发环境是否就绪。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
checks: {
|
||||
type: "string",
|
||||
description: "要检查的项目,逗号分隔(可选):all, node, python, git, ports, system, docker。默认 all。",
|
||||
},
|
||||
ports: {
|
||||
type: "string",
|
||||
description: "要检测的端口号,逗号分隔(如 3000,8080,5173)",
|
||||
},
|
||||
},
|
||||
required: [],
|
||||
},
|
||||
};
|
||||
async function getVersion(cmd) {
|
||||
try {
|
||||
const { stdout } = await execAsync(cmd, { timeout: 5000 });
|
||||
return stdout.trim().split("\n")[0];
|
||||
}
|
||||
catch {
|
||||
return "❌ 未安装";
|
||||
}
|
||||
}
|
||||
async function checkPort(port) {
|
||||
try {
|
||||
const cmd = process.platform === "win32"
|
||||
? `netstat -ano | findstr :${port}`
|
||||
: `lsof -i :${port} 2>/dev/null || ss -tlnp | grep :${port}`;
|
||||
const { stdout } = await execAsync(cmd, { timeout: 5000 });
|
||||
return stdout.trim().length > 0;
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async function getDiskSpace() {
|
||||
try {
|
||||
const cmd = process.platform === "win32"
|
||||
? 'powershell -command "Get-PSDrive -PSProvider FileSystem | Select-Object Name, @{N=\'Used(GB)\';E={[math]::Round($_.Used/1GB,1)}}, @{N=\'Free(GB)\';E={[math]::Round($_.Free/1GB,1)}} | Format-Table -AutoSize"'
|
||||
: "df -h / /home 2>/dev/null";
|
||||
const { stdout } = await execAsync(cmd, { timeout: 10000 });
|
||||
return stdout.trim();
|
||||
}
|
||||
catch {
|
||||
return "无法获取";
|
||||
}
|
||||
}
|
||||
export async function executeEnvCheck(args) {
|
||||
const { checks = "all", ports } = args;
|
||||
const checkList = checks.split(",").map((c) => c.trim().toLowerCase());
|
||||
const doAll = checkList.includes("all");
|
||||
const output = [
|
||||
`# 环境检测报告`,
|
||||
``,
|
||||
`🖥️ ${hostname()} | ${platform()} | ${userInfo().username}`,
|
||||
`📅 ${new Date().toLocaleString("zh-CN")}`,
|
||||
``,
|
||||
];
|
||||
// 系统资源
|
||||
if (doAll || checkList.includes("system")) {
|
||||
const totalMem = (totalmem() / 1024 / 1024 / 1024).toFixed(1);
|
||||
const freeMem = (freemem() / 1024 / 1024 / 1024).toFixed(1);
|
||||
const usedMem = ((totalmem() - freemem()) / 1024 / 1024 / 1024).toFixed(1);
|
||||
const memPercent = ((1 - freemem() / totalmem()) * 100).toFixed(0);
|
||||
const cpuInfo = cpus();
|
||||
const cpuModel = cpuInfo[0]?.model || "未知";
|
||||
output.push(`## 💻 系统资源`, ``, `| 项目 | 值 |`, `|------|------|`, `| CPU | ${cpuModel} |`, `| 核心数 | ${cpuInfo.length} |`, `| 内存 | ${usedMem} / ${totalMem} GB (${memPercent}%) |`, `| 空闲内存 | ${freeMem} GB |`, ``);
|
||||
const disk = await getDiskSpace();
|
||||
if (disk !== "无法获取") {
|
||||
output.push(`### 磁盘空间`, "```", disk, "```", ``);
|
||||
}
|
||||
}
|
||||
// Node.js
|
||||
if (doAll || checkList.includes("node")) {
|
||||
const [nodeVer, npmVer, npxVer, yarnVer, pnpmVer] = await Promise.all([
|
||||
getVersion("node --version"),
|
||||
getVersion("npm --version"),
|
||||
getVersion("npx --version"),
|
||||
getVersion("yarn --version"),
|
||||
getVersion("pnpm --version"),
|
||||
]);
|
||||
output.push(`## 📦 Node.js 生态`, ``, `| 工具 | 版本 |`, `|------|------|`, `| Node.js | ${nodeVer} |`, `| npm | ${npmVer} |`, `| npx | ${npxVer} |`, `| yarn | ${yarnVer} |`, `| pnpm | ${pnpmVer} |`, ``);
|
||||
}
|
||||
// Python
|
||||
if (doAll || checkList.includes("python")) {
|
||||
const [pyVer, py3Ver, pipVer] = await Promise.all([
|
||||
getVersion("python --version"),
|
||||
getVersion("python3 --version"),
|
||||
getVersion("pip --version"),
|
||||
]);
|
||||
output.push(`## 🐍 Python 生态`, ``, `| 工具 | 版本 |`, `|------|------|`, `| Python | ${pyVer} |`, `| Python3 | ${py3Ver} |`, `| pip | ${pipVer} |`, ``);
|
||||
}
|
||||
// Git
|
||||
if (doAll || checkList.includes("git")) {
|
||||
const gitVer = await getVersion("git --version");
|
||||
const gitUser = await getVersion("git config --global user.name");
|
||||
const gitEmail = await getVersion("git config --global user.email");
|
||||
output.push(`## 🔧 Git`, ``, `| 项目 | 值 |`, `|------|------|`, `| 版本 | ${gitVer} |`, `| 用户名 | ${gitUser} |`, `| 邮箱 | ${gitEmail} |`, ``);
|
||||
}
|
||||
// Docker
|
||||
if (doAll || checkList.includes("docker")) {
|
||||
const [dockerVer, composeVer] = await Promise.all([
|
||||
getVersion("docker --version"),
|
||||
getVersion("docker compose version 2>&1 || docker-compose --version 2>&1"),
|
||||
]);
|
||||
output.push(`## 🐳 Docker`, ``, `| 工具 | 版本 |`, `|------|------|`, `| Docker | ${dockerVer} |`, `| Compose | ${composeVer} |`, ``);
|
||||
}
|
||||
// 端口检测
|
||||
if (doAll || checkList.includes("ports") || ports) {
|
||||
const portsToCheck = ports
|
||||
? ports.split(",").map((p) => parseInt(p.trim())).filter(Boolean)
|
||||
: [3000, 3001, 5173, 5174, 8080, 8081, 4000, 4173, 5000, 5500];
|
||||
const portResults = await Promise.all(portsToCheck.map(async (port) => ({
|
||||
port,
|
||||
occupied: await checkPort(port),
|
||||
})));
|
||||
output.push(`## 🔌 端口状态`, ``, `| 端口 | 状态 |`, `|------|------|`, ...portResults.map((r) => `| ${r.port} | ${r.occupied ? "🔴 已占用" : "🟢 空闲"} |`), ``);
|
||||
}
|
||||
// 总结
|
||||
output.push(`---`, `_检测完成_`);
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=envCheck.js.map
|
||||
1
dev-assistant-mcp/dist/tools/envCheck.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/envCheck.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
28
dev-assistant-mcp/dist/tools/execCommand.d.ts
vendored
Normal file
28
dev-assistant-mcp/dist/tools/execCommand.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
export declare const execCommandTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
command: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
cwd: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
timeout: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeExecCommand(args: {
|
||||
command: string;
|
||||
cwd?: string;
|
||||
timeout?: number;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=execCommand.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/execCommand.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/execCommand.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"execCommand.d.ts","sourceRoot":"","sources":["../../src/tools/execCommand.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;CAsB3B,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiClB"}
|
||||
62
dev-assistant-mcp/dist/tools/execCommand.js
vendored
Normal file
62
dev-assistant-mcp/dist/tools/execCommand.js
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
const execAsync = promisify(exec);
|
||||
export const execCommandTool = {
|
||||
name: "exec_command",
|
||||
description: "在本地电脑上执行 Shell 命令。用于运行编译、测试、构建、安装依赖等任何命令。返回 stdout、stderr 和退出码。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
command: {
|
||||
type: "string",
|
||||
description: "要执行的命令(如 npm install, tsc --noEmit, python script.py)",
|
||||
},
|
||||
cwd: {
|
||||
type: "string",
|
||||
description: "工作目录(绝对路径)",
|
||||
},
|
||||
timeout: {
|
||||
type: "number",
|
||||
description: "超时时间(毫秒),默认 60000",
|
||||
},
|
||||
},
|
||||
required: ["command"],
|
||||
},
|
||||
};
|
||||
export async function executeExecCommand(args) {
|
||||
const { command, cwd, timeout = 60000 } = args;
|
||||
const workDir = cwd || process.cwd();
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(command, {
|
||||
cwd: workDir,
|
||||
timeout,
|
||||
maxBuffer: 1024 * 1024 * 10, // 10MB
|
||||
shell: process.platform === "win32" ? "powershell.exe" : "/bin/bash",
|
||||
});
|
||||
const output = [
|
||||
`$ ${command}`,
|
||||
`📂 ${workDir}`,
|
||||
`✅ 退出码: 0`,
|
||||
];
|
||||
if (stdout.trim())
|
||||
output.push(`\n--- stdout ---\n${stdout.trim()}`);
|
||||
if (stderr.trim())
|
||||
output.push(`\n--- stderr ---\n${stderr.trim()}`);
|
||||
return output.join("\n");
|
||||
}
|
||||
catch (error) {
|
||||
const output = [
|
||||
`$ ${command}`,
|
||||
`📂 ${workDir}`,
|
||||
`❌ 退出码: ${error.code ?? "unknown"}`,
|
||||
];
|
||||
if (error.stdout?.trim())
|
||||
output.push(`\n--- stdout ---\n${error.stdout.trim()}`);
|
||||
if (error.stderr?.trim())
|
||||
output.push(`\n--- stderr ---\n${error.stderr.trim()}`);
|
||||
if (error.killed)
|
||||
output.push(`\n⏰ 命令超时(${timeout}ms)被终止`);
|
||||
return output.join("\n");
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=execCommand.js.map
|
||||
1
dev-assistant-mcp/dist/tools/execCommand.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/execCommand.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"execCommand.js","sourceRoot":"","sources":["../../src/tools/execCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAS,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,cAAc;IACpB,WAAW,EACT,iEAAiE;IACnE,WAAW,EAAE;QACX,IAAI,EAAE,QAAiB;QACvB,UAAU,EAAE;YACV,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,uDAAuD;aACrE;YACD,GAAG,EAAE;gBACH,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,YAAY;aAC1B;YACD,OAAO,EAAE;gBACP,IAAI,EAAE,QAAQ;gBACd,WAAW,EAAE,mBAAmB;aACjC;SACF;QACD,QAAQ,EAAE,CAAC,SAAS,CAAC;KACtB;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,IAIxC;IACC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;IAC/C,MAAM,OAAO,GAAG,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAErC,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,OAAO,EAAE;YAClD,GAAG,EAAE,OAAO;YACZ,OAAO;YACP,SAAS,EAAE,IAAI,GAAG,IAAI,GAAG,EAAE,EAAE,OAAO;YACpC,KAAK,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW;SACrE,CAAC,CAAC;QAEH,MAAM,MAAM,GAAa;YACvB,KAAK,OAAO,EAAE;YACd,MAAM,OAAO,EAAE;YACf,UAAU;SACX,CAAC;QACF,IAAI,MAAM,CAAC,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACrE,IAAI,MAAM,CAAC,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAErE,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,MAAM,MAAM,GAAa;YACvB,KAAK,OAAO,EAAE;YACd,MAAM,OAAO,EAAE;YACf,UAAU,KAAK,CAAC,IAAI,IAAI,SAAS,EAAE;SACpC,CAAC;QACF,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClF,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,EAAE;YAAE,MAAM,CAAC,IAAI,CAAC,qBAAqB,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAClF,IAAI,KAAK,CAAC,MAAM;YAAE,MAAM,CAAC,IAAI,CAAC,YAAY,OAAO,QAAQ,CAAC,CAAC;QAE3D,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;AACH,CAAC"}
|
||||
87
dev-assistant-mcp/dist/tools/fileOps.d.ts
vendored
Normal file
87
dev-assistant-mcp/dist/tools/fileOps.d.ts
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
export declare const readFileTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
start_line: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
end_line: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare const writeFileTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
content: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
create_dirs: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare const patchFileTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
old_text: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
new_text: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
replace_all: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeReadFile(args: {
|
||||
path: string;
|
||||
start_line?: number;
|
||||
end_line?: number;
|
||||
}): Promise<string>;
|
||||
export declare function executeWriteFile(args: {
|
||||
path: string;
|
||||
content: string;
|
||||
create_dirs?: boolean;
|
||||
}): Promise<string>;
|
||||
export declare function executePatchFile(args: {
|
||||
path: string;
|
||||
old_text: string;
|
||||
new_text: string;
|
||||
replace_all?: boolean;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=fileOps.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/fileOps.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/fileOps.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fileOps.d.ts","sourceRoot":"","sources":["../../src/tools/fileOps.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;CAsBxB,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;CAsBzB,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;CA0BzB,CAAC;AAEF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CA0BlB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwBlB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4ClB"}
|
||||
159
dev-assistant-mcp/dist/tools/fileOps.js
vendored
Normal file
159
dev-assistant-mcp/dist/tools/fileOps.js
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
|
||||
import { dirname, extname } from "path";
|
||||
export const readFileTool = {
|
||||
name: "read_local_file",
|
||||
description: "读取本地文件内容。支持任意文本文件,返回带行号的内容。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "文件绝对路径",
|
||||
},
|
||||
start_line: {
|
||||
type: "number",
|
||||
description: "起始行号(可选,从 1 开始)",
|
||||
},
|
||||
end_line: {
|
||||
type: "number",
|
||||
description: "结束行号(可选)",
|
||||
},
|
||||
},
|
||||
required: ["path"],
|
||||
},
|
||||
};
|
||||
export const writeFileTool = {
|
||||
name: "write_local_file",
|
||||
description: "写入内容到本地文件。如果文件不存在会自动创建(含父目录)。支持完整写入或按行替换。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "文件绝对路径",
|
||||
},
|
||||
content: {
|
||||
type: "string",
|
||||
description: "要写入的完整文件内容",
|
||||
},
|
||||
create_dirs: {
|
||||
type: "boolean",
|
||||
description: "是否自动创建父目录(默认 true)",
|
||||
},
|
||||
},
|
||||
required: ["path", "content"],
|
||||
},
|
||||
};
|
||||
export const patchFileTool = {
|
||||
name: "patch_file",
|
||||
description: "精确修改本地文件。查找指定文本并替换为新文本,支持多次替换。适合自动纠错和代码修改。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
path: {
|
||||
type: "string",
|
||||
description: "文件绝对路径",
|
||||
},
|
||||
old_text: {
|
||||
type: "string",
|
||||
description: "要查找并替换的原文本(必须精确匹配)",
|
||||
},
|
||||
new_text: {
|
||||
type: "string",
|
||||
description: "替换后的新文本",
|
||||
},
|
||||
replace_all: {
|
||||
type: "boolean",
|
||||
description: "是否替换所有匹配项(默认 false,只替换第一个)",
|
||||
},
|
||||
},
|
||||
required: ["path", "old_text", "new_text"],
|
||||
},
|
||||
};
|
||||
export async function executeReadFile(args) {
|
||||
const { path: filePath, start_line, end_line } = args;
|
||||
if (!existsSync(filePath)) {
|
||||
return `❌ 文件不存在: ${filePath}`;
|
||||
}
|
||||
try {
|
||||
const content = readFileSync(filePath, "utf-8");
|
||||
const lines = content.split("\n");
|
||||
const start = (start_line || 1) - 1;
|
||||
const end = end_line || lines.length;
|
||||
const selected = lines.slice(start, end);
|
||||
const numbered = selected.map((line, i) => `${String(start + i + 1).padStart(4)} | ${line}`).join("\n");
|
||||
return [
|
||||
`📄 ${filePath}`,
|
||||
`行数: ${lines.length} | 显示: ${start + 1}-${Math.min(end, lines.length)}`,
|
||||
`类型: ${extname(filePath) || "unknown"}`,
|
||||
``,
|
||||
numbered,
|
||||
].join("\n");
|
||||
}
|
||||
catch (error) {
|
||||
return `❌ 读取失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
export async function executeWriteFile(args) {
|
||||
const { path: filePath, content, create_dirs = true } = args;
|
||||
try {
|
||||
if (create_dirs) {
|
||||
const dir = dirname(filePath);
|
||||
if (!existsSync(dir)) {
|
||||
mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
}
|
||||
const existed = existsSync(filePath);
|
||||
const oldLines = existed ? readFileSync(filePath, "utf-8").split("\n").length : 0;
|
||||
writeFileSync(filePath, content, "utf-8");
|
||||
const newLines = content.split("\n").length;
|
||||
return [
|
||||
`✅ 文件已${existed ? "更新" : "创建"}: ${filePath}`,
|
||||
existed ? `行数变化: ${oldLines} → ${newLines}` : `行数: ${newLines}`,
|
||||
].join("\n");
|
||||
}
|
||||
catch (error) {
|
||||
return `❌ 写入失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
export async function executePatchFile(args) {
|
||||
const { path: filePath, old_text, new_text, replace_all = false } = args;
|
||||
if (!existsSync(filePath)) {
|
||||
return `❌ 文件不存在: ${filePath}`;
|
||||
}
|
||||
try {
|
||||
const content = readFileSync(filePath, "utf-8");
|
||||
if (!content.includes(old_text)) {
|
||||
return `❌ 未找到匹配文本。\n\n搜索内容:\n\`\`\`\n${old_text.slice(0, 200)}\n\`\`\`\n\n提示: old_text 必须精确匹配文件中的内容(包括空格和换行)`;
|
||||
}
|
||||
const occurrences = content.split(old_text).length - 1;
|
||||
let newContent;
|
||||
if (replace_all) {
|
||||
newContent = content.split(old_text).join(new_text);
|
||||
}
|
||||
else {
|
||||
const idx = content.indexOf(old_text);
|
||||
newContent = content.substring(0, idx) + new_text + content.substring(idx + old_text.length);
|
||||
}
|
||||
writeFileSync(filePath, newContent, "utf-8");
|
||||
const replacedCount = replace_all ? occurrences : 1;
|
||||
return [
|
||||
`✅ 文件已修改: ${filePath}`,
|
||||
`替换: ${replacedCount} 处${occurrences > 1 && !replace_all ? `(共找到 ${occurrences} 处匹配,仅替换第 1 处)` : ""}`,
|
||||
``,
|
||||
`--- 旧代码 ---`,
|
||||
"```",
|
||||
old_text.slice(0, 500),
|
||||
"```",
|
||||
``,
|
||||
`+++ 新代码 +++`,
|
||||
"```",
|
||||
new_text.slice(0, 500),
|
||||
"```",
|
||||
].join("\n");
|
||||
}
|
||||
catch (error) {
|
||||
return `❌ 修改失败: ${error.message}`;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=fileOps.js.map
|
||||
1
dev-assistant-mcp/dist/tools/fileOps.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/fileOps.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fileOps.js","sourceRoot":"","sources":["../../src/tools/fileOps.ts"],"names":[],"mappings":"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"}
|
||||
39
dev-assistant-mcp/dist/tools/gitOps.d.ts
vendored
Normal file
39
dev-assistant-mcp/dist/tools/gitOps.d.ts
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
export declare const gitOpsTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
action: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
message: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
target: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
count: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeGitOps(args: {
|
||||
project_path: string;
|
||||
action: string;
|
||||
message?: string;
|
||||
target?: string;
|
||||
count?: number;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=gitOps.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/gitOps.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/gitOps.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"gitOps.d.ts","sourceRoot":"","sources":["../../src/tools/gitOps.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCtB,CAAC;AAeF,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAwIlB"}
|
||||
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
|
||||
1
dev-assistant-mcp/dist/tools/gitOps.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/gitOps.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
28
dev-assistant-mcp/dist/tools/lintCheck.d.ts
vendored
Normal file
28
dev-assistant-mcp/dist/tools/lintCheck.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
export declare const lintCheckTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
fix: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
files: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeLintCheck(args: {
|
||||
project_path: string;
|
||||
fix?: boolean;
|
||||
files?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=lintCheck.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/lintCheck.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/lintCheck.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"lintCheck.d.ts","sourceRoot":"","sources":["../../src/tools/lintCheck.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;CAsBzB,CAAC;AA4BF,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,YAAY,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAuGlB"}
|
||||
133
dev-assistant-mcp/dist/tools/lintCheck.js
vendored
Normal file
133
dev-assistant-mcp/dist/tools/lintCheck.js
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
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
|
||||
1
dev-assistant-mcp/dist/tools/lintCheck.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/lintCheck.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
23
dev-assistant-mcp/dist/tools/projectScan.d.ts
vendored
Normal file
23
dev-assistant-mcp/dist/tools/projectScan.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
export declare const projectScanTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
max_depth: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeProjectScan(args: {
|
||||
project_path: string;
|
||||
max_depth?: number;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=projectScan.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/projectScan.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/projectScan.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"projectScan.d.ts","sourceRoot":"","sources":["../../src/tools/projectScan.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;CAkB3B,CAAC;AAmDF,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CA4GlB"}
|
||||
196
dev-assistant-mcp/dist/tools/projectScan.js
vendored
Normal file
196
dev-assistant-mcp/dist/tools/projectScan.js
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
||||
import { join, extname } from "path";
|
||||
export const projectScanTool = {
|
||||
name: "project_scan",
|
||||
description: "扫描分析项目结构。返回项目类型、技术栈、文件结构、依赖列表、可用脚本、配置文件等全局信息,帮助快速理解项目。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
max_depth: {
|
||||
type: "number",
|
||||
description: "目录扫描最大深度(默认 3)",
|
||||
},
|
||||
},
|
||||
required: ["project_path"],
|
||||
},
|
||||
};
|
||||
function scanDir(dir, depth, maxDepth, prefix = "") {
|
||||
if (depth > maxDepth)
|
||||
return [];
|
||||
const lines = [];
|
||||
try {
|
||||
const entries = readdirSync(dir).filter((e) => !e.startsWith(".") && e !== "node_modules" && e !== "__pycache__" && e !== "dist" && e !== "build" && e !== ".git");
|
||||
for (const entry of entries.slice(0, 30)) { // 限制每层最多30项
|
||||
const fullPath = join(dir, entry);
|
||||
try {
|
||||
const stat = statSync(fullPath);
|
||||
if (stat.isDirectory()) {
|
||||
lines.push(`${prefix}📂 ${entry}/`);
|
||||
lines.push(...scanDir(fullPath, depth + 1, maxDepth, prefix + " "));
|
||||
}
|
||||
else {
|
||||
const size = stat.size;
|
||||
const sizeStr = size < 1024 ? `${size}B` : size < 1024 * 1024 ? `${(size / 1024).toFixed(0)}KB` : `${(size / 1024 / 1024).toFixed(1)}MB`;
|
||||
lines.push(`${prefix}📄 ${entry} (${sizeStr})`);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
if (entries.length > 30) {
|
||||
lines.push(`${prefix}... 还有 ${entries.length - 30} 个条目`);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return lines;
|
||||
}
|
||||
function countFiles(dir, ext, depth = 0) {
|
||||
if (depth > 5)
|
||||
return 0;
|
||||
let count = 0;
|
||||
try {
|
||||
for (const entry of readdirSync(dir)) {
|
||||
if (entry.startsWith(".") || entry === "node_modules" || entry === "__pycache__" || entry === "dist")
|
||||
continue;
|
||||
const fullPath = join(dir, entry);
|
||||
try {
|
||||
const stat = statSync(fullPath);
|
||||
if (stat.isDirectory())
|
||||
count += countFiles(fullPath, ext, depth + 1);
|
||||
else if (extname(entry) === ext)
|
||||
count++;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return count;
|
||||
}
|
||||
export async function executeProjectScan(args) {
|
||||
const { project_path, max_depth = 3 } = args;
|
||||
const hasFile = (name) => existsSync(join(project_path, name));
|
||||
const readJson = (name) => {
|
||||
try {
|
||||
return JSON.parse(readFileSync(join(project_path, name), "utf-8"));
|
||||
}
|
||||
catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
const output = [
|
||||
`# 项目分析报告`,
|
||||
``,
|
||||
`📂 路径: ${project_path}`,
|
||||
``,
|
||||
];
|
||||
// 项目类型和技术栈检测
|
||||
const techStack = [];
|
||||
const configs = [];
|
||||
if (hasFile("package.json"))
|
||||
techStack.push("Node.js");
|
||||
if (hasFile("tsconfig.json"))
|
||||
techStack.push("TypeScript");
|
||||
if (hasFile("next.config.js") || hasFile("next.config.mjs") || hasFile("next.config.ts"))
|
||||
techStack.push("Next.js");
|
||||
if (hasFile("vite.config.ts") || hasFile("vite.config.js"))
|
||||
techStack.push("Vite");
|
||||
if (hasFile("webpack.config.js"))
|
||||
techStack.push("Webpack");
|
||||
if (hasFile("requirements.txt") || hasFile("pyproject.toml"))
|
||||
techStack.push("Python");
|
||||
if (hasFile("Cargo.toml"))
|
||||
techStack.push("Rust");
|
||||
if (hasFile("go.mod"))
|
||||
techStack.push("Go");
|
||||
if (hasFile("pom.xml") || hasFile("build.gradle"))
|
||||
techStack.push("Java");
|
||||
if (hasFile("docker-compose.yml") || hasFile("Dockerfile"))
|
||||
techStack.push("Docker");
|
||||
if (hasFile(".eslintrc.js") || hasFile("eslint.config.js"))
|
||||
configs.push("ESLint");
|
||||
if (hasFile(".prettierrc") || hasFile(".prettierrc.json"))
|
||||
configs.push("Prettier");
|
||||
if (hasFile("jest.config.js") || hasFile("jest.config.ts"))
|
||||
configs.push("Jest");
|
||||
if (hasFile("vitest.config.ts"))
|
||||
configs.push("Vitest");
|
||||
if (hasFile(".env") || hasFile(".env.example"))
|
||||
configs.push(".env");
|
||||
output.push(`## 技术栈`, techStack.length > 0 ? techStack.join(" + ") : "未检测到", ``);
|
||||
if (configs.length > 0) {
|
||||
output.push(`## 工具配置`, configs.join(", "), ``);
|
||||
}
|
||||
// package.json 分析
|
||||
const pkg = readJson("package.json");
|
||||
if (pkg) {
|
||||
output.push(`## package.json`);
|
||||
if (pkg.name)
|
||||
output.push(`- **名称**: ${pkg.name}`);
|
||||
if (pkg.version)
|
||||
output.push(`- **版本**: ${pkg.version}`);
|
||||
if (pkg.description)
|
||||
output.push(`- **描述**: ${pkg.description}`);
|
||||
if (pkg.scripts && Object.keys(pkg.scripts).length > 0) {
|
||||
output.push(``, `### 可用脚本`);
|
||||
for (const [name, cmd] of Object.entries(pkg.scripts)) {
|
||||
output.push(`- \`npm run ${name}\` → ${cmd}`);
|
||||
}
|
||||
}
|
||||
if (pkg.dependencies) {
|
||||
const deps = Object.entries(pkg.dependencies);
|
||||
output.push(``, `### 依赖 (${deps.length})`);
|
||||
for (const [name, ver] of deps.slice(0, 20)) {
|
||||
output.push(`- ${name}: ${ver}`);
|
||||
}
|
||||
if (deps.length > 20)
|
||||
output.push(`... 还有 ${deps.length - 20} 个`);
|
||||
}
|
||||
if (pkg.devDependencies) {
|
||||
const devDeps = Object.entries(pkg.devDependencies);
|
||||
output.push(``, `### 开发依赖 (${devDeps.length})`);
|
||||
for (const [name, ver] of devDeps.slice(0, 15)) {
|
||||
output.push(`- ${name}: ${ver}`);
|
||||
}
|
||||
if (devDeps.length > 15)
|
||||
output.push(`... 还有 ${devDeps.length - 15} 个`);
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
// Python 依赖
|
||||
if (hasFile("requirements.txt")) {
|
||||
try {
|
||||
const reqs = readFileSync(join(project_path, "requirements.txt"), "utf-8")
|
||||
.split("\n").filter((l) => l.trim() && !l.startsWith("#"));
|
||||
output.push(`## Python 依赖 (${reqs.length})`);
|
||||
for (const r of reqs.slice(0, 20))
|
||||
output.push(`- ${r.trim()}`);
|
||||
if (reqs.length > 20)
|
||||
output.push(`... 还有 ${reqs.length - 20} 个`);
|
||||
output.push(``);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
// 文件统计
|
||||
const fileCounts = {};
|
||||
for (const ext of [".ts", ".tsx", ".js", ".jsx", ".py", ".css", ".html", ".json", ".md"]) {
|
||||
const count = countFiles(project_path, ext);
|
||||
if (count > 0)
|
||||
fileCounts[ext] = count;
|
||||
}
|
||||
if (Object.keys(fileCounts).length > 0) {
|
||||
output.push(`## 文件统计`);
|
||||
for (const [ext, count] of Object.entries(fileCounts).sort((a, b) => b[1] - a[1])) {
|
||||
output.push(`- ${ext}: ${count} 个文件`);
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
// 目录树
|
||||
output.push(`## 目录结构`);
|
||||
const tree = scanDir(project_path, 0, max_depth);
|
||||
output.push(...tree);
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=projectScan.js.map
|
||||
1
dev-assistant-mcp/dist/tools/projectScan.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/projectScan.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
28
dev-assistant-mcp/dist/tools/runTests.d.ts
vendored
Normal file
28
dev-assistant-mcp/dist/tools/runTests.d.ts
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
export declare const runTestsTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
test_file: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
test_name: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeRunTests(args: {
|
||||
project_path: string;
|
||||
test_file?: string;
|
||||
test_name?: string;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=runTests.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/runTests.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/runTests.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"runTests.d.ts","sourceRoot":"","sources":["../../src/tools/runTests.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;CAsBxB,CAAC;AAoBF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiGlB"}
|
||||
137
dev-assistant-mcp/dist/tools/runTests.js
vendored
Normal file
137
dev-assistant-mcp/dist/tools/runTests.js
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { existsSync } from "fs";
|
||||
import { join } from "path";
|
||||
const execAsync = promisify(exec);
|
||||
export const runTestsTool = {
|
||||
name: "run_tests",
|
||||
description: "运行项目测试。自动检测测试框架(Jest、Mocha、Pytest 等),执行测试并返回结构化的结果(通过/失败/跳过数量及失败详情)。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
test_file: {
|
||||
type: "string",
|
||||
description: "指定测试文件(可选,默认运行全部测试)",
|
||||
},
|
||||
test_name: {
|
||||
type: "string",
|
||||
description: "指定测试名称或模式(可选)",
|
||||
},
|
||||
},
|
||||
required: ["project_path"],
|
||||
},
|
||||
};
|
||||
async function runCommand(cmd, cwd) {
|
||||
try {
|
||||
const { stdout, stderr } = await execAsync(cmd, {
|
||||
cwd,
|
||||
timeout: 120000,
|
||||
maxBuffer: 1024 * 1024 * 10,
|
||||
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 executeRunTests(args) {
|
||||
const { project_path, test_file, test_name } = args;
|
||||
const hasFile = (name) => existsSync(join(project_path, name));
|
||||
let testCmd = "";
|
||||
let framework = "";
|
||||
// 检测测试框架
|
||||
if (hasFile("jest.config.js") || hasFile("jest.config.ts") || hasFile("jest.config.mjs")) {
|
||||
framework = "Jest";
|
||||
testCmd = "npx jest --verbose --no-coverage";
|
||||
if (test_file)
|
||||
testCmd += ` "${test_file}"`;
|
||||
if (test_name)
|
||||
testCmd += ` -t "${test_name}"`;
|
||||
}
|
||||
else if (hasFile("vitest.config.ts") || hasFile("vitest.config.js")) {
|
||||
framework = "Vitest";
|
||||
testCmd = "npx vitest run --reporter verbose";
|
||||
if (test_file)
|
||||
testCmd += ` "${test_file}"`;
|
||||
}
|
||||
else if (hasFile("pytest.ini") || hasFile("pyproject.toml") || hasFile("setup.cfg")) {
|
||||
framework = "Pytest";
|
||||
testCmd = "python -m pytest -v";
|
||||
if (test_file)
|
||||
testCmd += ` "${test_file}"`;
|
||||
if (test_name)
|
||||
testCmd += ` -k "${test_name}"`;
|
||||
}
|
||||
else if (hasFile("package.json")) {
|
||||
// 尝试 package.json 中的 test 脚本
|
||||
framework = "npm test";
|
||||
testCmd = "npm test 2>&1";
|
||||
}
|
||||
else if (hasFile("requirements.txt")) {
|
||||
framework = "Pytest (default)";
|
||||
testCmd = "python -m pytest -v";
|
||||
if (test_file)
|
||||
testCmd += ` "${test_file}"`;
|
||||
}
|
||||
if (!testCmd) {
|
||||
return `# 测试结果\n\n⚠️ 未检测到测试框架\n项目路径: ${project_path}\n\n建议:\n- JS/TS: npm install -D jest 或 vitest\n- Python: pip install pytest`;
|
||||
}
|
||||
const result = await runCommand(testCmd, project_path);
|
||||
const fullOutput = (result.stdout + "\n" + result.stderr).trim();
|
||||
// 解析测试结果
|
||||
let passed = 0, failed = 0, skipped = 0;
|
||||
// Jest / Vitest 格式
|
||||
const jestMatch = fullOutput.match(/Tests:\s+(?:(\d+) failed,?\s*)?(?:(\d+) skipped,?\s*)?(?:(\d+) passed)?/);
|
||||
if (jestMatch) {
|
||||
failed = parseInt(jestMatch[1] || "0");
|
||||
skipped = parseInt(jestMatch[2] || "0");
|
||||
passed = parseInt(jestMatch[3] || "0");
|
||||
}
|
||||
// Pytest 格式
|
||||
const pytestMatch = fullOutput.match(/(\d+) passed(?:.*?(\d+) failed)?(?:.*?(\d+) skipped)?/);
|
||||
if (pytestMatch) {
|
||||
passed = parseInt(pytestMatch[1] || "0");
|
||||
failed = parseInt(pytestMatch[2] || "0");
|
||||
skipped = parseInt(pytestMatch[3] || "0");
|
||||
}
|
||||
const total = passed + failed + skipped;
|
||||
const allPassed = failed === 0 && result.code === 0;
|
||||
const output = [
|
||||
`# 测试报告`,
|
||||
``,
|
||||
`📂 项目: ${project_path}`,
|
||||
`🔧 框架: ${framework}`,
|
||||
``,
|
||||
`## 结果`,
|
||||
allPassed ? "✅ **全部通过**" : "❌ **存在失败**",
|
||||
``,
|
||||
`| 状态 | 数量 |`,
|
||||
`|------|------|`,
|
||||
`| ✅ 通过 | ${passed} |`,
|
||||
`| ❌ 失败 | ${failed} |`,
|
||||
`| ⏭️ 跳过 | ${skipped} |`,
|
||||
`| 📊 总计 | ${total} |`,
|
||||
``,
|
||||
`## 命令`,
|
||||
`\`${testCmd}\``,
|
||||
``,
|
||||
`## 完整输出`,
|
||||
"```",
|
||||
fullOutput.slice(0, 5000),
|
||||
"```",
|
||||
];
|
||||
if (failed > 0) {
|
||||
output.push(``, `## 建议`, `1. 查看上方失败的测试用例详情`, `2. 使用 code_debug 工具分析失败原因`, `3. 修复后重新运行 run_tests 验证`);
|
||||
}
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=runTests.js.map
|
||||
1
dev-assistant-mcp/dist/tools/runTests.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/runTests.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"runTests.js","sourceRoot":"","sources":["../../src/tools/runTests.ts"],"names":[],"mappings":"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"}
|
||||
44
dev-assistant-mcp/dist/tools/searchCode.d.ts
vendored
Normal file
44
dev-assistant-mcp/dist/tools/searchCode.d.ts
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
export declare const searchCodeTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
query: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
mode: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
includes: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
case_sensitive: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
max_results: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeSearchCode(args: {
|
||||
project_path: string;
|
||||
query: string;
|
||||
mode?: string;
|
||||
includes?: string;
|
||||
case_sensitive?: boolean;
|
||||
max_results?: number;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=searchCode.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/searchCode.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/searchCode.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"searchCode.d.ts","sourceRoot":"","sources":["../../src/tools/searchCode.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmC1B,CAAC;AAiGF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2DlB"}
|
||||
176
dev-assistant-mcp/dist/tools/searchCode.js
vendored
Normal file
176
dev-assistant-mcp/dist/tools/searchCode.js
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
import { exec } from "child_process";
|
||||
import { promisify } from "util";
|
||||
import { readdirSync, readFileSync, statSync } from "fs";
|
||||
import { join, extname, relative } from "path";
|
||||
const execAsync = promisify(exec);
|
||||
export const searchCodeTool = {
|
||||
name: "search_code",
|
||||
description: "在项目中搜索代码。支持正则表达式、文本搜索、文件名搜索。返回匹配的文件、行号和上下文。类似 grep/ripgrep。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
query: {
|
||||
type: "string",
|
||||
description: "搜索内容(支持正则表达式)",
|
||||
},
|
||||
mode: {
|
||||
type: "string",
|
||||
description: "搜索模式:content=代码内容(默认)、filename=文件名、symbol=函数/类名",
|
||||
enum: ["content", "filename", "symbol"],
|
||||
},
|
||||
includes: {
|
||||
type: "string",
|
||||
description: "文件过滤 glob(如 *.ts, *.py)",
|
||||
},
|
||||
case_sensitive: {
|
||||
type: "boolean",
|
||||
description: "是否区分大小写(默认 false)",
|
||||
},
|
||||
max_results: {
|
||||
type: "number",
|
||||
description: "最大结果数(默认 50)",
|
||||
},
|
||||
},
|
||||
required: ["project_path", "query"],
|
||||
},
|
||||
};
|
||||
const SKIP_DIRS = new Set([
|
||||
"node_modules", ".git", "__pycache__", "dist", "build", ".next",
|
||||
".nuxt", "coverage", ".cache", ".tsbuildinfo", "vendor",
|
||||
]);
|
||||
const TEXT_EXTS = new Set([
|
||||
".ts", ".tsx", ".js", ".jsx", ".py", ".java", ".go", ".rs", ".c", ".cpp", ".h",
|
||||
".css", ".scss", ".less", ".html", ".vue", ".svelte", ".json", ".yaml", ".yml",
|
||||
".toml", ".md", ".txt", ".sh", ".bat", ".ps1", ".sql", ".graphql", ".prisma",
|
||||
".env", ".gitignore", ".eslintrc", ".prettierrc",
|
||||
]);
|
||||
function searchInDir(dir, rootDir, regex, mode, includeExt, results, maxResults, depth = 0) {
|
||||
if (depth > 10 || results.length >= maxResults)
|
||||
return;
|
||||
try {
|
||||
const entries = readdirSync(dir);
|
||||
for (const entry of entries) {
|
||||
if (results.length >= maxResults)
|
||||
break;
|
||||
if (SKIP_DIRS.has(entry) || entry.startsWith("."))
|
||||
continue;
|
||||
const fullPath = join(dir, entry);
|
||||
try {
|
||||
const stat = statSync(fullPath);
|
||||
if (stat.isDirectory()) {
|
||||
searchInDir(fullPath, rootDir, regex, mode, includeExt, results, maxResults, depth + 1);
|
||||
}
|
||||
else if (stat.isFile()) {
|
||||
const ext = extname(entry).toLowerCase();
|
||||
// 文件名搜索
|
||||
if (mode === "filename") {
|
||||
if (regex.test(entry)) {
|
||||
results.push({ file: relative(rootDir, fullPath), line: 0, content: entry });
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// 内容搜索 - 只搜索文本文件
|
||||
if (!TEXT_EXTS.has(ext) && ext !== "")
|
||||
continue;
|
||||
if (includeExt && !entry.endsWith(includeExt.replace("*", "")))
|
||||
continue;
|
||||
if (stat.size > 1024 * 512)
|
||||
continue; // 跳过 >512KB 的文件
|
||||
const content = readFileSync(fullPath, "utf-8");
|
||||
const lines = content.split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (results.length >= maxResults)
|
||||
break;
|
||||
if (mode === "symbol") {
|
||||
// 只匹配函数/类/接口定义
|
||||
const line = lines[i];
|
||||
if (/(?:function|class|interface|def|const|let|var|export)\s/.test(line) && regex.test(line)) {
|
||||
results.push({
|
||||
file: relative(rootDir, fullPath),
|
||||
line: i + 1,
|
||||
content: line.trim(),
|
||||
context_before: i > 0 ? lines[i - 1].trim() : undefined,
|
||||
context_after: i < lines.length - 1 ? lines[i + 1].trim() : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (regex.test(lines[i])) {
|
||||
results.push({
|
||||
file: relative(rootDir, fullPath),
|
||||
line: i + 1,
|
||||
content: lines[i].trim(),
|
||||
context_before: i > 0 ? lines[i - 1].trim() : undefined,
|
||||
context_after: i < lines.length - 1 ? lines[i + 1].trim() : undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
export async function executeSearchCode(args) {
|
||||
const { project_path, query, mode = "content", includes, case_sensitive = false, max_results = 50 } = args;
|
||||
const flags = case_sensitive ? "" : "i";
|
||||
let regex;
|
||||
try {
|
||||
regex = new RegExp(query, flags);
|
||||
}
|
||||
catch {
|
||||
regex = new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), flags);
|
||||
}
|
||||
const results = [];
|
||||
const includeExt = includes ? includes.replace("*", "") : null;
|
||||
searchInDir(project_path, project_path, regex, mode, includeExt, results, max_results);
|
||||
if (results.length === 0) {
|
||||
return `# 搜索结果\n\n🔍 "${query}" (${mode})\n📂 ${project_path}\n\n_未找到匹配结果_`;
|
||||
}
|
||||
// 按文件分组
|
||||
const grouped = {};
|
||||
for (const r of results) {
|
||||
(grouped[r.file] || (grouped[r.file] = [])).push(r);
|
||||
}
|
||||
const fileCount = Object.keys(grouped).length;
|
||||
const output = [
|
||||
`# 搜索结果`,
|
||||
``,
|
||||
`🔍 "${query}" | 模式: ${mode}${includes ? ` | 过滤: ${includes}` : ""}`,
|
||||
`📂 ${project_path}`,
|
||||
`📊 ${results.length} 个匹配,${fileCount} 个文件`,
|
||||
``,
|
||||
];
|
||||
for (const [file, matches] of Object.entries(grouped)) {
|
||||
output.push(`## 📄 ${file} (${matches.length} 处)`);
|
||||
for (const m of matches) {
|
||||
if (mode === "filename") {
|
||||
output.push(`- ${m.content}`);
|
||||
}
|
||||
else {
|
||||
output.push(`**行 ${m.line}:**`);
|
||||
if (m.context_before)
|
||||
output.push(`\`\`\`\n ${m.context_before}`);
|
||||
else
|
||||
output.push("```");
|
||||
output.push(`→ ${m.content}`);
|
||||
if (m.context_after)
|
||||
output.push(` ${m.context_after}\n\`\`\``);
|
||||
else
|
||||
output.push("```");
|
||||
}
|
||||
}
|
||||
output.push(``);
|
||||
}
|
||||
if (results.length >= max_results) {
|
||||
output.push(`\n⚠️ 结果已截断(最大 ${max_results} 条),可增大 max_results 或缩小搜索范围`);
|
||||
}
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=searchCode.js.map
|
||||
1
dev-assistant-mcp/dist/tools/searchCode.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/searchCode.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
34
dev-assistant-mcp/dist/tools/workflow.d.ts
vendored
Normal file
34
dev-assistant-mcp/dist/tools/workflow.d.ts
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
export declare const workflowTool: {
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: {
|
||||
type: "object";
|
||||
properties: {
|
||||
project_path: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
preset: {
|
||||
type: string;
|
||||
description: string;
|
||||
enum: string[];
|
||||
};
|
||||
steps: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
stop_on_error: {
|
||||
type: string;
|
||||
description: string;
|
||||
};
|
||||
};
|
||||
required: string[];
|
||||
};
|
||||
};
|
||||
export declare function executeWorkflow(args: {
|
||||
project_path: string;
|
||||
preset?: string;
|
||||
steps?: string;
|
||||
stop_on_error?: boolean;
|
||||
}): Promise<string>;
|
||||
//# sourceMappingURL=workflow.d.ts.map
|
||||
1
dev-assistant-mcp/dist/tools/workflow.d.ts.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/workflow.d.ts.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../../src/tools/workflow.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCxB,CAAC;AA+DF,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkIlB"}
|
||||
180
dev-assistant-mcp/dist/tools/workflow.js
vendored
Normal file
180
dev-assistant-mcp/dist/tools/workflow.js
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
import { executeProjectScan } from "./projectScan.js";
|
||||
import { executeLintCheck } from "./lintCheck.js";
|
||||
import { executeAutoFix } from "./autoFix.js";
|
||||
import { executeBuildProject } from "./buildProject.js";
|
||||
import { executeRunTests } from "./runTests.js";
|
||||
import { executeGitOps } from "./gitOps.js";
|
||||
import { executeDepManage } from "./depManage.js";
|
||||
export const workflowTool = {
|
||||
name: "workflow",
|
||||
description: "自动化工作流编排。串联多个工具形成流水线,一键执行完整开发流程。内置多种预设流程(全量检查、CI 模拟、项目初始化等),也支持自定义步骤。",
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {
|
||||
project_path: {
|
||||
type: "string",
|
||||
description: "项目根目录(绝对路径)",
|
||||
},
|
||||
preset: {
|
||||
type: "string",
|
||||
description: "预设工作流",
|
||||
enum: [
|
||||
"full_check", // 全量检查:scan → lint → build → test
|
||||
"fix_and_verify", // 修复验证:auto_fix → lint → build → test
|
||||
"pre_commit", // 提交前检查:lint → build → test → git status
|
||||
"ci_simulate", // CI 模拟:install → lint → build → test → audit
|
||||
"quick_scan", // 快速扫描:scan → lint
|
||||
"deploy_prep", // 部署准备:lint → build → test → git status
|
||||
],
|
||||
},
|
||||
steps: {
|
||||
type: "string",
|
||||
description: "自定义步骤,逗号分隔(如 scan,lint,fix,build,test,git_status,audit)。与 preset 二选一。",
|
||||
},
|
||||
stop_on_error: {
|
||||
type: "boolean",
|
||||
description: "遇到错误是否停止(默认 true)",
|
||||
},
|
||||
},
|
||||
required: ["project_path"],
|
||||
},
|
||||
};
|
||||
const STEP_MAP = {
|
||||
scan: {
|
||||
name: "📋 项目扫描",
|
||||
fn: (p) => executeProjectScan({ project_path: p }),
|
||||
},
|
||||
lint: {
|
||||
name: "🔍 代码检查",
|
||||
fn: (p) => executeLintCheck({ project_path: p }),
|
||||
},
|
||||
fix: {
|
||||
name: "🔧 自动修复",
|
||||
fn: (p) => executeAutoFix({ project_path: p }),
|
||||
},
|
||||
build: {
|
||||
name: "🏗️ 构建项目",
|
||||
fn: (p) => executeBuildProject({ project_path: p }),
|
||||
},
|
||||
test: {
|
||||
name: "🧪 运行测试",
|
||||
fn: (p) => executeRunTests({ project_path: p }),
|
||||
},
|
||||
git_status: {
|
||||
name: "📊 Git 状态",
|
||||
fn: (p) => executeGitOps({ project_path: p, action: "status" }),
|
||||
},
|
||||
git_diff: {
|
||||
name: "📝 Git Diff",
|
||||
fn: (p) => executeGitOps({ project_path: p, action: "diff" }),
|
||||
},
|
||||
audit: {
|
||||
name: "🛡️ 安全审计",
|
||||
fn: (p) => executeDepManage({ project_path: p, action: "audit" }),
|
||||
},
|
||||
outdated: {
|
||||
name: "📦 过时依赖检查",
|
||||
fn: (p) => executeDepManage({ project_path: p, action: "outdated" }),
|
||||
},
|
||||
install: {
|
||||
name: "📥 安装依赖",
|
||||
fn: (p) => executeDepManage({ project_path: p, action: "install" }),
|
||||
},
|
||||
};
|
||||
const PRESETS = {
|
||||
full_check: ["scan", "lint", "build", "test"],
|
||||
fix_and_verify: ["fix", "lint", "build", "test"],
|
||||
pre_commit: ["lint", "build", "test", "git_status"],
|
||||
ci_simulate: ["install", "lint", "build", "test", "audit"],
|
||||
quick_scan: ["scan", "lint"],
|
||||
deploy_prep: ["lint", "build", "test", "git_status"],
|
||||
};
|
||||
export async function executeWorkflow(args) {
|
||||
const { project_path, preset, steps, stop_on_error = true } = args;
|
||||
// 确定步骤列表
|
||||
let stepKeys;
|
||||
let workflowName;
|
||||
if (steps) {
|
||||
stepKeys = steps.split(",").map((s) => s.trim());
|
||||
workflowName = "自定义工作流";
|
||||
}
|
||||
else if (preset && PRESETS[preset]) {
|
||||
stepKeys = PRESETS[preset];
|
||||
workflowName = `预设: ${preset}`;
|
||||
}
|
||||
else {
|
||||
// 默认全量检查
|
||||
stepKeys = PRESETS.full_check;
|
||||
workflowName = "预设: full_check(全量检查)";
|
||||
}
|
||||
// 验证步骤
|
||||
const invalidSteps = stepKeys.filter((k) => !STEP_MAP[k]);
|
||||
if (invalidSteps.length > 0) {
|
||||
return `❌ 未知步骤: ${invalidSteps.join(", ")}\n\n可用步骤: ${Object.keys(STEP_MAP).join(", ")}`;
|
||||
}
|
||||
const totalSteps = stepKeys.length;
|
||||
const startTime = Date.now();
|
||||
const results = [];
|
||||
const output = [
|
||||
`# 🚀 工作流执行`,
|
||||
``,
|
||||
`📂 ${project_path}`,
|
||||
`📋 ${workflowName}`,
|
||||
`📊 共 ${totalSteps} 个步骤`,
|
||||
`${stop_on_error ? "⛔ 遇错停止" : "⏭️ 遇错继续"}`,
|
||||
``,
|
||||
`---`,
|
||||
``,
|
||||
];
|
||||
let hasError = false;
|
||||
for (let i = 0; i < stepKeys.length; i++) {
|
||||
const key = stepKeys[i];
|
||||
const step = STEP_MAP[key];
|
||||
output.push(`## [${i + 1}/${totalSteps}] ${step.name}`);
|
||||
const stepStart = Date.now();
|
||||
try {
|
||||
const result = await step.fn(project_path);
|
||||
const duration = Date.now() - stepStart;
|
||||
// 判断步骤是否成功(检查输出中的错误标志)
|
||||
const isError = result.includes("❌") && !result.includes("✅");
|
||||
const stepSuccess = !isError;
|
||||
results.push({
|
||||
name: step.name,
|
||||
success: stepSuccess,
|
||||
duration,
|
||||
output: result,
|
||||
});
|
||||
output.push(`${stepSuccess ? "✅ 通过" : "❌ 失败"} (${(duration / 1000).toFixed(1)}s)`, ``, `<details>`, `<summary>查看详情</summary>`, ``, result.slice(0, 3000), ``, `</details>`, ``);
|
||||
if (!stepSuccess) {
|
||||
hasError = true;
|
||||
if (stop_on_error) {
|
||||
output.push(`\n⛔ **遇到错误,工作流停止。** 后续步骤: ${stepKeys.slice(i + 1).join(" → ")}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
const duration = Date.now() - stepStart;
|
||||
results.push({ name: step.name, success: false, duration, output: error.message });
|
||||
output.push(`❌ 异常 (${(duration / 1000).toFixed(1)}s): ${error.message}`, ``);
|
||||
hasError = true;
|
||||
if (stop_on_error) {
|
||||
output.push(`\n⛔ **工作流中断**`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 总结报告
|
||||
const totalDuration = Date.now() - startTime;
|
||||
const passed = results.filter((r) => r.success).length;
|
||||
const failed = results.filter((r) => !r.success).length;
|
||||
output.push(``, `---`, ``, `# 📊 工作流总结`, ``, `| 项目 | 值 |`, `|------|------|`, `| 总耗时 | ${(totalDuration / 1000).toFixed(1)}s |`, `| 已执行 | ${results.length}/${totalSteps} |`, `| ✅ 通过 | ${passed} |`, `| ❌ 失败 | ${failed} |`, `| 最终结果 | ${hasError ? "❌ 有问题需要处理" : "✅ 全部通过"} |`, ``);
|
||||
if (hasError) {
|
||||
output.push(`## 💡 建议`, `1. 查看失败步骤的详情`, `2. 使用 \`auto_fix\` 自动修复格式问题`, `3. 使用 \`code_debug\` 分析编译错误`, `4. 修复后运行 \`workflow preset=fix_and_verify\` 验证`);
|
||||
}
|
||||
else {
|
||||
output.push(`✨ **所有检查通过,代码质量良好!**`);
|
||||
}
|
||||
return output.join("\n");
|
||||
}
|
||||
//# sourceMappingURL=workflow.js.map
|
||||
1
dev-assistant-mcp/dist/tools/workflow.js.map
vendored
Normal file
1
dev-assistant-mcp/dist/tools/workflow.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user