mta-mcp 1.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/CHANGELOG.md +457 -0
  2. package/README.md +680 -0
  3. package/archive/docs/CLAUDE_SETUP.md +103 -0
  4. package/archive/docs/DEVELOPMENT_ROADMAP.md +186 -0
  5. package/archive/docs/GETTING_STARTED.md +337 -0
  6. package/archive/docs/MIGRATION_GUIDE.md +189 -0
  7. package/archive/docs/TROUBLESHOOTING.md +386 -0
  8. package/archive/docs/USAGE_GUIDE.md +739 -0
  9. package/archive/tests/test-cloud-dev.cjs +158 -0
  10. package/archive/tests/test-mcp.sh +46 -0
  11. package/archive/tests/test-miniprogram.cjs +94 -0
  12. package/archive/tests/test-phase2.cjs +144 -0
  13. package/archive/tests/test-phase3.cjs +121 -0
  14. package/archive/tests/test-phase4.cjs +249 -0
  15. package/archive/tests/test-standards.cjs +111 -0
  16. package/archive/tests/test-vitasage-config.cjs +25 -0
  17. package/build/core/agentTemplate.d.ts +33 -0
  18. package/build/core/agentTemplate.d.ts.map +1 -0
  19. package/build/core/agentTemplate.js +158 -0
  20. package/build/core/agentTemplate.js.map +1 -0
  21. package/build/core/codeValidator.d.ts +82 -0
  22. package/build/core/codeValidator.d.ts.map +1 -0
  23. package/build/core/codeValidator.js +287 -0
  24. package/build/core/codeValidator.js.map +1 -0
  25. package/build/core/githubClient.d.ts +26 -0
  26. package/build/core/githubClient.d.ts.map +1 -0
  27. package/build/core/githubClient.js +60 -0
  28. package/build/core/githubClient.js.map +1 -0
  29. package/build/core/i18nDetector.d.ts +47 -0
  30. package/build/core/i18nDetector.d.ts.map +1 -0
  31. package/build/core/i18nDetector.js +314 -0
  32. package/build/core/i18nDetector.js.map +1 -0
  33. package/build/core/projectContextManager.d.ts +39 -0
  34. package/build/core/projectContextManager.d.ts.map +1 -0
  35. package/build/core/projectContextManager.js +147 -0
  36. package/build/core/projectContextManager.js.map +1 -0
  37. package/build/core/smartAgentMatcher.d.ts +51 -0
  38. package/build/core/smartAgentMatcher.d.ts.map +1 -0
  39. package/build/core/smartAgentMatcher.js +493 -0
  40. package/build/core/smartAgentMatcher.js.map +1 -0
  41. package/build/core/standardsManager.d.ts +130 -0
  42. package/build/core/standardsManager.d.ts.map +1 -0
  43. package/build/core/standardsManager.js +595 -0
  44. package/build/core/standardsManager.js.map +1 -0
  45. package/build/core/types.d.ts +55 -0
  46. package/build/core/types.d.ts.map +1 -0
  47. package/build/core/types.js +21 -0
  48. package/build/core/types.js.map +1 -0
  49. package/build/index.d.ts +3 -0
  50. package/build/index.d.ts.map +1 -0
  51. package/build/index.js +463 -0
  52. package/build/index.js.map +1 -0
  53. package/build/tools/analyzeProject.d.ts +12 -0
  54. package/build/tools/analyzeProject.d.ts.map +1 -0
  55. package/build/tools/analyzeProject.js +85 -0
  56. package/build/tools/analyzeProject.js.map +1 -0
  57. package/build/tools/autoSetup.d.ts +15 -0
  58. package/build/tools/autoSetup.d.ts.map +1 -0
  59. package/build/tools/autoSetup.js +291 -0
  60. package/build/tools/autoSetup.js.map +1 -0
  61. package/build/tools/generateConfig.d.ts +16 -0
  62. package/build/tools/generateConfig.d.ts.map +1 -0
  63. package/build/tools/generateConfig.js +379 -0
  64. package/build/tools/generateConfig.js.map +1 -0
  65. package/build/tools/generateProjectAgent.d.ts +15 -0
  66. package/build/tools/generateProjectAgent.d.ts.map +1 -0
  67. package/build/tools/generateProjectAgent.js +348 -0
  68. package/build/tools/generateProjectAgent.js.map +1 -0
  69. package/build/tools/getCompactStandards.d.ts +20 -0
  70. package/build/tools/getCompactStandards.d.ts.map +1 -0
  71. package/build/tools/getCompactStandards.js +367 -0
  72. package/build/tools/getCompactStandards.js.map +1 -0
  73. package/build/tools/getSmartStandards.d.ts +14 -0
  74. package/build/tools/getSmartStandards.d.ts.map +1 -0
  75. package/build/tools/getSmartStandards.js +184 -0
  76. package/build/tools/getSmartStandards.js.map +1 -0
  77. package/build/tools/healthCheck.d.ts +14 -0
  78. package/build/tools/healthCheck.d.ts.map +1 -0
  79. package/build/tools/healthCheck.js +237 -0
  80. package/build/tools/healthCheck.js.map +1 -0
  81. package/build/tools/listAgents.d.ts +10 -0
  82. package/build/tools/listAgents.d.ts.map +1 -0
  83. package/build/tools/listAgents.js +79 -0
  84. package/build/tools/listAgents.js.map +1 -0
  85. package/build/tools/matchAgents.d.ts +14 -0
  86. package/build/tools/matchAgents.d.ts.map +1 -0
  87. package/build/tools/matchAgents.js +70 -0
  88. package/build/tools/matchAgents.js.map +1 -0
  89. package/build/tools/usePreset.d.ts +23 -0
  90. package/build/tools/usePreset.d.ts.map +1 -0
  91. package/build/tools/usePreset.js +163 -0
  92. package/build/tools/usePreset.js.map +1 -0
  93. package/generate-project-config.cjs +97 -0
  94. package/package.json +45 -0
  95. package/regenerate-vitasage.sh +30 -0
  96. package/src/core/codeValidator.ts +357 -0
  97. package/src/core/githubClient.ts +64 -0
  98. package/src/core/i18nDetector.ts +357 -0
  99. package/src/core/smartAgentMatcher.ts +490 -0
  100. package/src/core/standardsManager.ts +763 -0
  101. package/src/core/types.ts +72 -0
  102. package/src/index.ts +519 -0
  103. package/src/tools/analyzeProject.ts +94 -0
  104. package/src/tools/autoSetup.ts +312 -0
  105. package/src/tools/generateConfig.ts +429 -0
  106. package/src/tools/getCompactStandards.ts +413 -0
  107. package/src/tools/getSmartStandards.ts +205 -0
  108. package/src/tools/healthCheck.ts +261 -0
  109. package/src/tools/listAgents.ts +91 -0
  110. package/src/tools/matchAgents.ts +80 -0
  111. package/src/tools/usePreset.ts +180 -0
  112. package/tsconfig.json +20 -0
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * 通用配置生成工具
5
+ * 可为任何项目生成 Copilot 配置
6
+ *
7
+ * 使用方法:
8
+ * node generate-project-config.cjs <项目路径> [配置ID] [agents...]
9
+ *
10
+ * 示例:
11
+ * # VitaSage 项目
12
+ * node generate-project-config.cjs /Users/pailasi/Work/VitaSage vitasage vitasage,vue3,logicflow
13
+ *
14
+ * # Flutter 项目
15
+ * node generate-project-config.cjs /Users/pailasi/Work/my_flutter flutter-recipe flutter
16
+ *
17
+ * # 微信小程序
18
+ * node generate-project-config.cjs /Users/pailasi/Work/MTA-Market wechat wechat-miniprogram
19
+ *
20
+ * # 自动匹配
21
+ * node generate-project-config.cjs /Users/pailasi/Work/weipin
22
+ */
23
+
24
+ const { generateConfig } = require('./build/tools/generateConfig.js');
25
+
26
+ async function main() {
27
+ const args = process.argv.slice(2);
28
+
29
+ if (args.length === 0) {
30
+ console.log(`
31
+ 📋 通用配置生成工具
32
+
33
+ 使用方法:
34
+ node generate-project-config.cjs <项目路径> [配置ID] [agents]
35
+
36
+ 参数说明:
37
+ 项目路径 必填,项目的绝对路径
38
+ 配置ID 可选,配置方案ID(如 vitasage, flutter-recipe)
39
+ agents 可选,手动指定agents,用逗号分隔(如 vue3,pinia)
40
+
41
+ 示例:
42
+
43
+ # VitaSage 项目(使用 vitasage 配置方案)
44
+ node generate-project-config.cjs /Users/pailasi/Work/VitaSage vitasage vitasage,vue3,logicflow
45
+
46
+ # Flutter 项目(使用 flutter-recipe 配置方案)
47
+ node generate-project-config.cjs /Users/pailasi/Work/my_flutter flutter-recipe flutter
48
+
49
+ # 微信小程序(自动匹配 agents)
50
+ node generate-project-config.cjs /Users/pailasi/Work/MTA-Market wechat
51
+
52
+ # 标准 Vue 项目(自动匹配)
53
+ node generate-project-config.cjs /Users/pailasi/Work/weipin
54
+
55
+ 配置方案列表:
56
+ - vitasage VitaSage 工业配方系统(Element Plus)
57
+ - flutter-recipe Flutter 配方管理项目
58
+ - wechat 微信小程序标准配置
59
+ - standard 标准 Web 项目配置
60
+ `);
61
+ process.exit(0);
62
+ }
63
+
64
+ const projectPath = args[0];
65
+ const configId = args[1] || undefined;
66
+ const agentIds = args[2] ? args[2].split(',').map(a => a.trim()) : undefined;
67
+
68
+ console.log(`🚀 生成配置`);
69
+ console.log(` 项目: ${projectPath}`);
70
+ if (configId) console.log(` 配置方案: ${configId}`);
71
+ if (agentIds) console.log(` Agents: ${agentIds.join(', ')}`);
72
+ console.log('');
73
+
74
+ const result = await generateConfig({
75
+ projectPath,
76
+ agentIds,
77
+ autoMatch: !agentIds, // 如果没有指定agents,则自动匹配
78
+ updateMode: 'merge', // 默认保护模式
79
+ configId,
80
+ });
81
+
82
+ const data = JSON.parse(result.content[0].text);
83
+
84
+ if (data.success) {
85
+ console.log('\n✅ 成功!');
86
+ console.log(`\n配置文件: ${data.configPath}`);
87
+ console.log(`应用的 Agents: ${data.agents.map(a => a.id).join(', ')}`);
88
+ } else {
89
+ console.error('\n❌ 失败:', data.error);
90
+ process.exit(1);
91
+ }
92
+ }
93
+
94
+ main().catch(err => {
95
+ console.error('❌ 错误:', err.message);
96
+ process.exit(1);
97
+ });
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "mta-mcp",
3
+ "version": "1.8.1",
4
+ "description": "MTA - 智能项目分析与编码规范管理 MCP 服务器",
5
+ "type": "module",
6
+ "main": "build/index.js",
7
+ "bin": {
8
+ "mta": "build/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "watch": "tsc --watch",
13
+ "start": "node build/index.js",
14
+ "dev": "tsc --watch",
15
+ "prepare": "npm run build",
16
+ "clean": "rm -rf build"
17
+ },
18
+ "keywords": [
19
+ "mcp",
20
+ "copilot",
21
+ "ai",
22
+ "agents",
23
+ "github",
24
+ "claude"
25
+ ],
26
+ "author": "ForLear",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.24.3",
30
+ "axios": "^1.6.5",
31
+ "fast-glob": "^3.3.2"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^20.11.0",
35
+ "typescript": "^5.3.3"
36
+ },
37
+ "engines": {
38
+ "node": ">=18.0.0"
39
+ },
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "https://github.com/ForLear/copilot-prompts.git",
43
+ "directory": "mcp-server"
44
+ }
45
+ }
@@ -0,0 +1,30 @@
1
+ #!/bin/bash
2
+
3
+ # VitaSage 配置重新生成脚本
4
+ # 使用 merge 模式,保护自定义内容
5
+
6
+ set -e
7
+
8
+ echo "🔄 重新生成 VitaSage 项目配置..."
9
+ echo ""
10
+
11
+ cd "$(dirname "$0")"
12
+
13
+ # 编译最新代码
14
+ echo "📦 编译 MCP 服务器..."
15
+ npm run build
16
+
17
+ echo ""
18
+ echo "✨ 生成配置文件..."
19
+ node test-vitasage-config.cjs
20
+
21
+ echo ""
22
+ echo "✅ 配置已更新!"
23
+ echo ""
24
+ echo "📋 配置文件位置: /Users/pailasi/Work/VitaSage/.github/copilot-instructions.md"
25
+ echo ""
26
+ echo "💡 提示:"
27
+ echo " - 使用 CUSTOM_START/CUSTOM_END 标记可保护自定义内容"
28
+ echo " - 配置会自动应用 vitasage 配置方案"
29
+ echo " - 包含 3 个 Agents: vitasage, vue3, logicflow"
30
+ echo ""
@@ -0,0 +1,357 @@
1
+ /**
2
+ * 代码验证器 (v1.1.0)
3
+ * 用于检测和防止常见的代码生成错误
4
+ */
5
+
6
+ import { ConsoleLogger } from './types.js';
7
+
8
+ /**
9
+ * 验证结果接口
10
+ */
11
+ export interface ValidationResult {
12
+ isValid: boolean;
13
+ errors: ValidationError[];
14
+ warnings: ValidationWarning[];
15
+ }
16
+
17
+ /**
18
+ * 验证错误
19
+ */
20
+ export interface ValidationError {
21
+ type: 'syntax' | 'completeness' | 'compatibility';
22
+ message: string;
23
+ line?: number;
24
+ suggestion?: string;
25
+ }
26
+
27
+ /**
28
+ * 验证警告
29
+ */
30
+ export interface ValidationWarning {
31
+ type: 'best-practice' | 'performance' | 'compatibility' | 'completeness';
32
+ message: string;
33
+ suggestion?: string;
34
+ }
35
+
36
+ /**
37
+ * 代码验证器类
38
+ */
39
+ export class CodeValidator {
40
+ private logger: ConsoleLogger;
41
+
42
+ constructor(logger?: ConsoleLogger) {
43
+ this.logger = logger || new ConsoleLogger();
44
+ }
45
+
46
+ /**
47
+ * 验证生成的配置文件内容
48
+ */
49
+ validateConfigContent(content: string): ValidationResult {
50
+ const errors: ValidationError[] = [];
51
+ const warnings: ValidationWarning[] = [];
52
+
53
+ // 1. 检查重复标签闭合 (如 </style></style>)
54
+ this.checkDuplicateTags(content, errors);
55
+
56
+ // 2. 检查括号匹配
57
+ this.checkBracketMatching(content, errors);
58
+
59
+ // 3. 检查 Markdown 语法
60
+ this.checkMarkdownSyntax(content, errors);
61
+
62
+ // 4. 检查必要章节完整性
63
+ this.checkRequiredSections(content, warnings);
64
+
65
+ // 5. 检查自定义内容标记
66
+ this.checkCustomContentMarkers(content, warnings);
67
+
68
+ return {
69
+ isValid: errors.length === 0,
70
+ errors,
71
+ warnings
72
+ };
73
+ }
74
+
75
+ /**
76
+ * 检查重复的HTML标签
77
+ */
78
+ private checkDuplicateTags(content: string, errors: ValidationError[]): void {
79
+ const lines = content.split('\n');
80
+ const tagPattern = /<\/([\w-]+)>/g;
81
+
82
+ for (let i = 0; i < lines.length; i++) {
83
+ const line = lines[i];
84
+ const matches = Array.from(line.matchAll(tagPattern));
85
+
86
+ if (matches.length > 0) {
87
+ const tags = matches.map(m => m[1]);
88
+ const tagCounts = new Map<string, number>();
89
+
90
+ tags.forEach(tag => {
91
+ tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1);
92
+ });
93
+
94
+ tagCounts.forEach((count, tag) => {
95
+ if (count > 1) {
96
+ errors.push({
97
+ type: 'syntax',
98
+ message: `重复的闭合标签 </${tag}> 在同一行出现 ${count} 次`,
99
+ line: i + 1,
100
+ suggestion: `检查是否有多余的闭合标签,应该只保留一个 </${tag}>`
101
+ });
102
+ }
103
+ });
104
+ }
105
+ }
106
+ }
107
+
108
+ /**
109
+ * 检查括号匹配
110
+ */
111
+ private checkBracketMatching(content: string, errors: ValidationError[]): void {
112
+ const brackets = {
113
+ '(': ')',
114
+ '[': ']',
115
+ '{': '}',
116
+ '<': '>'
117
+ };
118
+
119
+ const stack: Array<{ char: string; line: number; col: number }> = [];
120
+ const lines = content.split('\n');
121
+
122
+ for (let lineNum = 0; lineNum < lines.length; lineNum++) {
123
+ const line = lines[lineNum];
124
+
125
+ // 跳过代码块内容
126
+ if (line.trim().startsWith('```')) {
127
+ continue;
128
+ }
129
+
130
+ // 跳过 Markdown blockquote 行(以 > 开头)
131
+ if (line.trim().startsWith('>')) {
132
+ continue;
133
+ }
134
+
135
+ for (let col = 0; col < line.length; col++) {
136
+ const char = line[col];
137
+
138
+ // 跳过 Markdown blockquote 的 > 符号
139
+ if (char === '>' && (col === 0 || line[col - 1] === ' ') &&
140
+ (col === line.length - 1 || line[col + 1] === ' ')) {
141
+ continue;
142
+ }
143
+
144
+ if (char in brackets) {
145
+ stack.push({ char, line: lineNum + 1, col: col + 1 });
146
+ } else if (Object.values(brackets).includes(char)) {
147
+ if (stack.length === 0) {
148
+ errors.push({
149
+ type: 'syntax',
150
+ message: `未配对的闭合括号 '${char}'`,
151
+ line: lineNum + 1,
152
+ suggestion: `检查是否缺少对应的开放括号`
153
+ });
154
+ } else {
155
+ const last = stack.pop()!;
156
+ const expectedClose = brackets[last.char as keyof typeof brackets];
157
+
158
+ if (char !== expectedClose) {
159
+ errors.push({
160
+ type: 'syntax',
161
+ message: `括号不匹配: 期望 '${expectedClose}' 但得到 '${char}'`,
162
+ line: lineNum + 1,
163
+ suggestion: `检查第 ${last.line} 行的 '${last.char}' 对应的闭合括号`
164
+ });
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+
171
+ // 检查未闭合的括号
172
+ if (stack.length > 0) {
173
+ stack.forEach(bracket => {
174
+ errors.push({
175
+ type: 'syntax',
176
+ message: `未闭合的括号 '${bracket.char}'`,
177
+ line: bracket.line,
178
+ suggestion: `添加对应的闭合括号 '${brackets[bracket.char as keyof typeof brackets]}'`
179
+ });
180
+ });
181
+ }
182
+ }
183
+
184
+ /**
185
+ * 检查 Markdown 语法
186
+ */
187
+ private checkMarkdownSyntax(content: string, errors: ValidationError[]): void {
188
+ const lines = content.split('\n');
189
+ let inCodeBlock = false;
190
+ let codeBlockStart = 0;
191
+
192
+ for (let i = 0; i < lines.length; i++) {
193
+ const line = lines[i];
194
+
195
+ // 检查代码块标记
196
+ if (line.trim().startsWith('```')) {
197
+ if (inCodeBlock) {
198
+ inCodeBlock = false;
199
+ } else {
200
+ inCodeBlock = true;
201
+ codeBlockStart = i + 1;
202
+ }
203
+ }
204
+ }
205
+
206
+ // 如果代码块未闭合
207
+ if (inCodeBlock) {
208
+ errors.push({
209
+ type: 'syntax',
210
+ message: '未闭合的代码块',
211
+ line: codeBlockStart,
212
+ suggestion: '在代码块末尾添加 ``` 闭合标记'
213
+ });
214
+ }
215
+ }
216
+
217
+ /**
218
+ * 检查必要章节完整性
219
+ */
220
+ private checkRequiredSections(content: string, warnings: ValidationWarning[]): void {
221
+ const requiredSections = [
222
+ { pattern: /## ⚠️ 强制工作流/i, name: '强制工作流章节' },
223
+ { pattern: /## 📚 配置的 Agents/i, name: 'Agents 配置章节' }
224
+ ];
225
+
226
+ requiredSections.forEach(section => {
227
+ if (!section.pattern.test(content)) {
228
+ warnings.push({
229
+ type: 'completeness',
230
+ message: `缺少必要章节: ${section.name}`,
231
+ suggestion: '确保生成的配置文件包含所有必要的章节'
232
+ });
233
+ }
234
+ });
235
+ }
236
+
237
+ /**
238
+ * 检查自定义内容标记
239
+ */
240
+ private checkCustomContentMarkers(content: string, warnings: ValidationWarning[]): void {
241
+ const hasCustomStart = content.includes('<!-- CUSTOM_START -->');
242
+ const hasCustomEnd = content.includes('<!-- CUSTOM_END -->');
243
+
244
+ if (hasCustomStart !== hasCustomEnd) {
245
+ warnings.push({
246
+ type: 'completeness',
247
+ message: 'CUSTOM 标记不完整',
248
+ suggestion: '确保 CUSTOM_START 和 CUSTOM_END 成对出现'
249
+ });
250
+ }
251
+ }
252
+
253
+ /**
254
+ * 验证 Agent 内容
255
+ */
256
+ validateAgentContent(content: string, agentId: string): ValidationResult {
257
+ const errors: ValidationError[] = [];
258
+ const warnings: ValidationWarning[] = [];
259
+
260
+ // 检查 Agent 文件的特殊要求
261
+ if (!content.includes('⚠️ 强制工作流') && !content.includes('## 强制工作流')) {
262
+ warnings.push({
263
+ type: 'best-practice',
264
+ message: `Agent ${agentId} 缺少强制工作流说明`,
265
+ suggestion: '建议在 Agent 中包含 MCP 工具调用的强制说明'
266
+ });
267
+ }
268
+
269
+ // 基本语法检查
270
+ const syntaxValidation = this.validateConfigContent(content);
271
+ errors.push(...syntaxValidation.errors);
272
+ warnings.push(...syntaxValidation.warnings);
273
+
274
+ return {
275
+ isValid: errors.length === 0,
276
+ errors,
277
+ warnings
278
+ };
279
+ }
280
+
281
+ /**
282
+ * 生成验证报告
283
+ */
284
+ generateValidationReport(result: ValidationResult): string {
285
+ let report = '';
286
+
287
+ if (result.isValid && result.warnings.length === 0) {
288
+ report = '✅ 验证通过,未发现问题\n';
289
+ return report;
290
+ }
291
+
292
+ if (!result.isValid) {
293
+ report += '❌ 验证失败,发现以下错误:\n\n';
294
+ result.errors.forEach((error, index) => {
295
+ report += `${index + 1}. [${error.type}] ${error.message}\n`;
296
+ if (error.line) {
297
+ report += ` 位置: 第 ${error.line} 行\n`;
298
+ }
299
+ if (error.suggestion) {
300
+ report += ` 建议: ${error.suggestion}\n`;
301
+ }
302
+ report += '\n';
303
+ });
304
+ } else {
305
+ report += '✅ 验证通过\n\n';
306
+ }
307
+
308
+ if (result.warnings.length > 0) {
309
+ report += '⚠️ 发现以下警告:\n\n';
310
+ result.warnings.forEach((warning, index) => {
311
+ report += `${index + 1}. [${warning.type}] ${warning.message}\n`;
312
+ if (warning.suggestion) {
313
+ report += ` 建议: ${warning.suggestion}\n`;
314
+ }
315
+ report += '\n';
316
+ });
317
+ }
318
+
319
+ return report;
320
+ }
321
+
322
+ /**
323
+ * 尝试自动修复简单的语法错误
324
+ */
325
+ attemptAutoFix(content: string): { fixed: boolean; content: string; changes: string[] } {
326
+ let fixedContent = content;
327
+ const changes: string[] = [];
328
+
329
+ // 1. 修复重复的闭合标签
330
+ const tagPattern = /(<\/([\w-]+)>)\1+/g;
331
+ const tagMatches = content.match(tagPattern);
332
+ if (tagMatches) {
333
+ fixedContent = fixedContent.replace(tagPattern, '$1');
334
+ changes.push(`修复了重复的闭合标签: ${tagMatches.join(', ')}`);
335
+ }
336
+
337
+ // 2. 修复未闭合的代码块
338
+ const codeBlockCount = (fixedContent.match(/```/g) || []).length;
339
+ if (codeBlockCount % 2 !== 0) {
340
+ fixedContent += '\n```\n';
341
+ changes.push('添加了缺失的代码块闭合标记');
342
+ }
343
+
344
+ return {
345
+ fixed: changes.length > 0,
346
+ content: fixedContent,
347
+ changes
348
+ };
349
+ }
350
+ }
351
+
352
+ /**
353
+ * 创建默认验证器实例
354
+ */
355
+ export function createValidator(logger?: ConsoleLogger): CodeValidator {
356
+ return new CodeValidator(logger);
357
+ }
@@ -0,0 +1,64 @@
1
+ import axios from 'axios';
2
+ import { Logger } from './types.js';
3
+
4
+ /**
5
+ * GitHub 客户端(Node.js 版本,无 VS Code 依赖)
6
+ */
7
+ export class GitHubClient {
8
+ private readonly owner = 'ForLear';
9
+ private readonly repo = 'copilot-prompts';
10
+ private readonly branch = 'main';
11
+ private readonly baseUrl = 'https://api.github.com';
12
+ private readonly rawBaseUrl = 'https://raw.githubusercontent.com';
13
+
14
+ constructor(private logger?: Logger) {}
15
+
16
+ /**
17
+ * 列出目录中的文件
18
+ */
19
+ async listDirectoryFiles(dirPath: string): Promise<Array<{ name: string; path: string; type: string }>> {
20
+ const url = `${this.baseUrl}/repos/${this.owner}/${this.repo}/contents/${dirPath}?ref=${this.branch}`;
21
+
22
+ try {
23
+ const response = await axios.get(url, {
24
+ headers: {
25
+ 'Accept': 'application/vnd.github.v3+json',
26
+ 'User-Agent': 'Copilot-Prompts-MCP-Server'
27
+ }
28
+ });
29
+
30
+ if (Array.isArray(response.data)) {
31
+ return response.data.map((item: any) => ({
32
+ name: item.name,
33
+ path: item.path,
34
+ type: item.type
35
+ }));
36
+ }
37
+
38
+ return [];
39
+ } catch (error) {
40
+ this.logger?.error(`获取目录失败: ${error}`);
41
+ return [];
42
+ }
43
+ }
44
+
45
+ /**
46
+ * 获取文件内容
47
+ */
48
+ async fetchFileContent(filePath: string): Promise<string> {
49
+ const url = `${this.rawBaseUrl}/${this.owner}/${this.repo}/${this.branch}/${filePath}`;
50
+
51
+ try {
52
+ const response = await axios.get(url, {
53
+ headers: {
54
+ 'User-Agent': 'Copilot-Prompts-MCP-Server'
55
+ }
56
+ });
57
+
58
+ return response.data;
59
+ } catch (error) {
60
+ this.logger?.error(`获取文件失败: ${filePath}`);
61
+ throw error;
62
+ }
63
+ }
64
+ }