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,413 @@
1
+ import * as fs from 'fs';
2
+ import { StandardsManager } from '../core/standardsManager.js';
3
+ import { ConsoleLogger } from '../core/types.js';
4
+
5
+ /**
6
+ * 紧凑规范工具 - Token 优化版
7
+ *
8
+ * 优化策略:
9
+ * 1. 只返回规范摘要而非完整内容
10
+ * 2. 提供规范 URI 供按需加载
11
+ * 3. 针对特定场景返回精简的关键规则
12
+ */
13
+ export async function getCompactStandards(args: {
14
+ currentFile?: string;
15
+ fileContent?: string;
16
+ scenario?: string;
17
+ // 新增:返回模式
18
+ mode?: 'summary' | 'key-rules' | 'full';
19
+ }): Promise<{
20
+ content: Array<{ type: string; text: string }>;
21
+ }> {
22
+ const logger = new ConsoleLogger();
23
+ const manager = new StandardsManager();
24
+ const mode = args.mode || 'key-rules';
25
+
26
+ try {
27
+ // 检测上下文(复用智能检测逻辑)
28
+ const context = detectContext(args, logger);
29
+
30
+ // 获取相关规范 URI
31
+ const standardUris = manager.getRelevantStandards({
32
+ fileType: context.fileType,
33
+ imports: context.imports,
34
+ scenario: args.scenario || context.scenario
35
+ });
36
+
37
+ // 根据模式返回不同内容
38
+ let responseContent: any;
39
+
40
+ switch (mode) {
41
+ case 'summary':
42
+ // 只返回规范名称和描述,约 500 tokens
43
+ responseContent = buildSummaryResponse(standardUris, manager);
44
+ break;
45
+
46
+ case 'key-rules':
47
+ // 返回关键规则摘要,约 2000-3000 tokens
48
+ responseContent = buildKeyRulesResponse(standardUris, context, manager);
49
+ break;
50
+
51
+ case 'full':
52
+ // 完整内容(原有行为)
53
+ responseContent = buildFullResponse(standardUris, manager);
54
+ break;
55
+ }
56
+
57
+ return {
58
+ content: [{
59
+ type: 'text',
60
+ text: JSON.stringify(responseContent, null, 2)
61
+ }]
62
+ };
63
+ } catch (error) {
64
+ logger.error(`规范获取失败: ${error}`);
65
+ return {
66
+ content: [{
67
+ type: 'text',
68
+ text: JSON.stringify({
69
+ error: error instanceof Error ? error.message : String(error)
70
+ }, null, 2)
71
+ }]
72
+ };
73
+ }
74
+ }
75
+
76
+ /**
77
+ * 检测上下文
78
+ */
79
+ function detectContext(args: any, logger: ConsoleLogger): {
80
+ fileType: string;
81
+ imports: string[];
82
+ scenario: string;
83
+ } {
84
+ let fileType = 'unknown';
85
+ let imports: string[] = [];
86
+ let scenario = '';
87
+
88
+ // 从文件路径检测
89
+ if (args.currentFile && fs.existsSync(args.currentFile)) {
90
+ const ext = args.currentFile.split('.').pop()?.toLowerCase() || '';
91
+ const extMap: Record<string, string> = {
92
+ 'vue': 'vue', 'ts': 'ts', 'tsx': 'tsx',
93
+ 'js': 'js', 'jsx': 'jsx', 'dart': 'dart'
94
+ };
95
+ fileType = extMap[ext] || 'unknown';
96
+
97
+ try {
98
+ const content = fs.readFileSync(args.currentFile, 'utf-8');
99
+ imports = extractImports(content);
100
+ scenario = inferScenario(content, fileType);
101
+ } catch {
102
+ // 忽略读取错误
103
+ }
104
+ }
105
+
106
+ // 从内容检测
107
+ if (args.fileContent) {
108
+ imports = [...imports, ...extractImports(args.fileContent)];
109
+ if (fileType === 'unknown') {
110
+ if (args.fileContent.includes('<template>')) fileType = 'vue';
111
+ else if (args.fileContent.includes('interface ')) fileType = 'ts';
112
+ }
113
+ scenario = scenario || inferScenario(args.fileContent, fileType);
114
+ }
115
+
116
+ return { fileType, imports: [...new Set(imports)], scenario };
117
+ }
118
+
119
+ /**
120
+ * 构建摘要响应(约 500 tokens)
121
+ */
122
+ function buildSummaryResponse(uris: string[], manager: StandardsManager): any {
123
+ const standards = manager.getAvailableStandards();
124
+ const matched = uris.map(uri => {
125
+ const std = standards.find(s => s.uri === uri);
126
+ return {
127
+ uri,
128
+ name: std?.name || uri,
129
+ description: std?.description || ''
130
+ };
131
+ });
132
+
133
+ return {
134
+ success: true,
135
+ mode: 'summary',
136
+ message: '已识别相关规范,如需详细内容请使用 mode: "key-rules" 或 "full"',
137
+ standards: matched,
138
+ stats: {
139
+ count: matched.length,
140
+ estimatedTokens: 500
141
+ }
142
+ };
143
+ }
144
+
145
+ /**
146
+ * 构建关键规则响应(约 2000-3000 tokens)
147
+ * 针对不同场景提取关键规则
148
+ */
149
+ function buildKeyRulesResponse(
150
+ uris: string[],
151
+ context: { fileType: string; imports: string[]; scenario: string },
152
+ manager: StandardsManager
153
+ ): any {
154
+ const keyRules: string[] = [];
155
+
156
+ // 根据文件类型添加关键规则
157
+ if (context.fileType === 'vue') {
158
+ keyRules.push(...getVueKeyRules(context.imports));
159
+ } else if (context.fileType === 'dart') {
160
+ keyRules.push(...getFlutterKeyRules());
161
+ } else if (context.fileType === 'ts' || context.fileType === 'tsx') {
162
+ keyRules.push(...getTypeScriptKeyRules());
163
+ }
164
+
165
+ // 根据导入添加特定规则
166
+ if (context.imports.includes('element-plus')) {
167
+ keyRules.push(...getElementPlusKeyRules());
168
+ }
169
+ if (context.imports.some(i => i.includes('i18n') || i.includes('locale'))) {
170
+ keyRules.push(...getI18nKeyRules());
171
+ }
172
+ if (context.imports.includes('pinia')) {
173
+ keyRules.push(...getPiniaKeyRules());
174
+ }
175
+
176
+ return {
177
+ success: true,
178
+ mode: 'key-rules',
179
+ context: {
180
+ fileType: context.fileType,
181
+ detectedImports: context.imports,
182
+ scenario: context.scenario
183
+ },
184
+ keyRules: keyRules.join('\n\n'),
185
+ standardUris: uris, // 提供完整 URI 供按需加载
186
+ stats: {
187
+ rulesCount: keyRules.length,
188
+ estimatedTokens: Math.ceil(keyRules.join('').length / 4)
189
+ }
190
+ };
191
+ }
192
+
193
+ /**
194
+ * 构建完整响应(原有行为)
195
+ */
196
+ function buildFullResponse(uris: string[], manager: StandardsManager): any {
197
+ const content = manager.combineStandards(uris);
198
+ return {
199
+ success: true,
200
+ mode: 'full',
201
+ standards: uris,
202
+ content,
203
+ stats: {
204
+ standardsCount: uris.length,
205
+ contentLength: content.length,
206
+ estimatedTokens: Math.ceil(content.length / 4)
207
+ }
208
+ };
209
+ }
210
+
211
+ // ==================== 关键规则提取 ====================
212
+
213
+ function getVueKeyRules(imports: string[]): string[] {
214
+ return [
215
+ `## Vue 3 关键规则
216
+
217
+ 1. **使用 \`<script setup lang="ts">\`** - 必须使用 Composition API
218
+ 2. **Props/Emits 类型定义** - 必须使用 interface 定义类型
219
+ 3. **禁止内联样式** - 使用 scoped CSS 或 class
220
+ 4. **模板简洁** - 复杂逻辑提取到 computed 或方法
221
+ 5. **响应式** - 基本类型用 ref,对象用 reactive(不重新赋值)`,
222
+
223
+ `## 组件结构顺序
224
+ \`\`\`vue
225
+ <script setup lang="ts">
226
+ // 1. 类型导入
227
+ // 2. Props/Emits 定义
228
+ // 3. 响应式状态
229
+ // 4. 计算属性
230
+ // 5. 方法
231
+ // 6. 生命周期
232
+ </script>
233
+ \`\`\``
234
+ ];
235
+ }
236
+
237
+ function getElementPlusKeyRules(): string[] {
238
+ return [
239
+ `## Element Plus 关键规则
240
+
241
+ ### 表格规范
242
+ - **必须** \`border\` + \`highlight-current-row\`
243
+ - 操作列 \`fixed="right"\`,宽度:2按钮160px/3按钮240px/4按钮280px
244
+ - 使用 \`v-loading\` 显示加载状态
245
+
246
+ ### 表单规范
247
+ - 使用 \`label-position="top"\` 或 \`label-width="120px"\`
248
+ - 验证规则使用 \`FormRules<T>\` 类型
249
+ - 验证消息必须国际化
250
+
251
+ ### 弹窗规范
252
+ - 使用 \`destroy-on-close\` 重置状态
253
+ - 宽度:简单500px/标准700px/复杂900px
254
+
255
+ ### 消息提示
256
+ \`\`\`typescript
257
+ ElMessage.success($t('保存成功'))
258
+ ElMessageBox.confirm($t('确认删除?'), $t('警告'), { type: 'warning' })
259
+ \`\`\``,
260
+
261
+ `## 表格示例
262
+ \`\`\`vue
263
+ <el-table v-loading="listLoading" :data="list" border highlight-current-row>
264
+ <el-table-column type="index" :label="$t('序号')" width="70" />
265
+ <el-table-column prop="name" :label="$t('名称')" min-width="120" />
266
+ <el-table-column fixed="right" :label="$t('操作')" width="240">
267
+ <template #default="{ row }">
268
+ <el-button link type="primary" @click="handleEdit(row)">{{ $t('编辑') }}</el-button>
269
+ <el-button link type="danger" @click="handleDelete(row)">{{ $t('删除') }}</el-button>
270
+ </template>
271
+ </el-table-column>
272
+ </el-table>
273
+ \`\`\``
274
+ ];
275
+ }
276
+
277
+ function getI18nKeyRules(): string[] {
278
+ return [
279
+ `## 国际化关键规则
280
+
281
+ ### 必须国际化的内容
282
+ - 所有按钮文字:\`{{ $t('保存') }}\`
283
+ - 表单标签:\`:label="$t('客户名称')"\`
284
+ - 占位符:\`:placeholder="$t('请输入')"\`
285
+ - 表格列标题:\`:label="$t('订单编号')"\`
286
+ - 弹窗标题:\`:title="$t('新增客户')"\`
287
+ - 提示消息:\`ElMessage.success($t('保存成功'))\`
288
+ - 验证规则:\`message: $t('请输入用户名')\`
289
+
290
+ ### 禁止
291
+ - ❌ \`<el-button>新增</el-button>\` (硬编码)
292
+ - ❌ \`label="客户名称"\` (硬编码)
293
+ - ❌ \`ElMessage.success('保存成功')\` (硬编码)`
294
+ ];
295
+ }
296
+
297
+ function getPiniaKeyRules(): string[] {
298
+ return [
299
+ `## Pinia 关键规则
300
+
301
+ ### Setup Store 语法(推荐)
302
+ \`\`\`typescript
303
+ export const useUserStore = defineStore('user', () => {
304
+ const user = ref<User | null>(null)
305
+ const isLoggedIn = computed(() => !!user.value)
306
+
307
+ async function login(credentials: Credentials) {
308
+ user.value = await authApi.login(credentials)
309
+ }
310
+
311
+ return { user, isLoggedIn, login }
312
+ })
313
+ \`\`\`
314
+
315
+ ### 规范要求
316
+ - Store ID 使用小写短横线命名
317
+ - 使用 Setup Store 语法而非 Options Store
318
+ - 异步操作直接用 async/await
319
+ - 复杂状态操作使用 $patch`
320
+ ];
321
+ }
322
+
323
+ function getTypeScriptKeyRules(): string[] {
324
+ return [
325
+ `## TypeScript 关键规则
326
+
327
+ ### 类型定义
328
+ - 必须定义函数参数和返回类型
329
+ - 使用 interface 定义对象类型
330
+ - 避免使用 any,使用 unknown 替代
331
+
332
+ ### 命名规范
333
+ - 变量/函数:camelCase
334
+ - 类/接口/类型:PascalCase
335
+ - 常量:UPPER_SNAKE_CASE
336
+
337
+ ### 示例
338
+ \`\`\`typescript
339
+ interface User {
340
+ id: number
341
+ name: string
342
+ email?: string
343
+ }
344
+
345
+ async function fetchUser(id: number): Promise<User | null> {
346
+ // ...
347
+ }
348
+ \`\`\``
349
+ ];
350
+ }
351
+
352
+ function getFlutterKeyRules(): string[] {
353
+ return [
354
+ `## Flutter UI 系统关键规则
355
+
356
+ ### Design Token 快捷方式(必须使用)
357
+ | 快捷方式 | 用途 | 示例 |
358
+ |---------|------|------|
359
+ | \`$c\` | 颜色 | \`$c.primary\`, \`$c.text.primary\` |
360
+ | \`$s\` | 间距 | \`$s.sm\`, \`$s.md\`, \`$s.px(14)\` |
361
+ | \`$t\` | 排版 | \`$t.displayLarge\`, \`$t.bodyMedium\` |
362
+ | \`$r\` | 圆角 | \`$r.sm\`, \`$r.md\`, \`$r.full\` |
363
+
364
+ ### Flex 组件库(必须使用)
365
+ - \`FlexButton\` 替代 ElevatedButton/TextButton
366
+ - \`FlexCard\` 替代 Card/Container
367
+ - \`FlexInput\` 替代 TextField
368
+ - \`Gap\` 替代 SizedBox(间隔)
369
+
370
+ ### 禁止
371
+ - ❌ \`Color(0xFF3B82F6)\` 硬编码颜色
372
+ - ❌ \`EdgeInsets.all(16)\` 硬编码间距
373
+ - ❌ \`Colors.blue\` Material 颜色常量`
374
+ ];
375
+ }
376
+
377
+ // ==================== 辅助函数 ====================
378
+
379
+ function extractImports(content: string): string[] {
380
+ const imports: string[] = [];
381
+
382
+ // ES6 imports
383
+ const esImportRegex = /import\s+(?:(?:\{[^}]*\}|\*\s+as\s+\w+|\w+)\s+from\s+)?['"]([^'"]+)['"]/g;
384
+ let match;
385
+ while ((match = esImportRegex.exec(content)) !== null) {
386
+ imports.push(match[1]);
387
+ }
388
+
389
+ // require
390
+ const requireRegex = /require\(['"]([^'"]+)['"]\)/g;
391
+ while ((match = requireRegex.exec(content)) !== null) {
392
+ imports.push(match[1]);
393
+ }
394
+
395
+ return imports;
396
+ }
397
+
398
+ function inferScenario(content: string, fileType: string): string {
399
+ const scenarios: string[] = [];
400
+ const lower = content.toLowerCase();
401
+
402
+ if (lower.includes('el-table') || lower.includes('el-form')) {
403
+ scenarios.push('表格组件', '表单组件');
404
+ }
405
+ if (lower.includes('$t(') || lower.includes('i18n')) {
406
+ scenarios.push('国际化');
407
+ }
408
+ if (lower.includes('interface ') || lower.includes('type ')) {
409
+ scenarios.push('类型定义');
410
+ }
411
+
412
+ return scenarios.join('、');
413
+ }
@@ -0,0 +1,205 @@
1
+ import * as fs from 'fs';
2
+ import { StandardsManager } from '../core/standardsManager.js';
3
+ import { ConsoleLogger } from '../core/types.js';
4
+
5
+ /**
6
+ * 智能规范推荐工具
7
+ * 零参数,自动检测上下文并推荐规范
8
+ */
9
+ export async function getSmartStandards(args: {
10
+ currentFile?: string;
11
+ fileContent?: string;
12
+ }): Promise<{
13
+ content: Array<{ type: string; text: string }>;
14
+ }> {
15
+ const logger = new ConsoleLogger();
16
+ const manager = new StandardsManager();
17
+
18
+ try {
19
+ let detectedFileType = 'unknown';
20
+ let detectedImports: string[] = [];
21
+ let detectedScenario = '';
22
+ let analysisSource = 'none';
23
+
24
+ // 策略 1: 使用提供的文件路径
25
+ if (args.currentFile && fs.existsSync(args.currentFile)) {
26
+ analysisSource = 'file-path';
27
+ const ext = args.currentFile.split('.').pop()?.toLowerCase() || '';
28
+
29
+ const extMap: Record<string, string> = {
30
+ 'vue': 'vue',
31
+ 'ts': 'ts',
32
+ 'tsx': 'tsx',
33
+ 'js': 'js',
34
+ 'jsx': 'jsx'
35
+ };
36
+ detectedFileType = extMap[ext] || 'unknown';
37
+
38
+ // 读取文件内容分析
39
+ try {
40
+ const content = fs.readFileSync(args.currentFile, 'utf-8');
41
+ const imports = extractImports(content);
42
+ detectedImports = imports;
43
+ detectedScenario = inferScenario(content, detectedFileType);
44
+ } catch {
45
+ logger.log('无法读取文件内容,仅使用文件类型');
46
+ }
47
+ }
48
+
49
+ // 策略 2: 使用提供的文件内容
50
+ if (args.fileContent) {
51
+ analysisSource = 'file-content';
52
+ const imports = extractImports(args.fileContent);
53
+ detectedImports = [...detectedImports, ...imports];
54
+
55
+ // 从内容推断文件类型
56
+ if (detectedFileType === 'unknown') {
57
+ if (args.fileContent.includes('<template>')) {
58
+ detectedFileType = 'vue';
59
+ } else if (args.fileContent.includes('interface ') || args.fileContent.includes('type ')) {
60
+ detectedFileType = 'ts';
61
+ }
62
+ }
63
+
64
+ const scenario = inferScenario(args.fileContent, detectedFileType);
65
+ if (scenario) detectedScenario = scenario;
66
+ }
67
+
68
+ // 策略 3: 环境检测(进程当前目录)
69
+ if (detectedFileType === 'unknown') {
70
+ analysisSource = 'environment';
71
+ const cwd = process.cwd();
72
+ const packageJsonPath = `${cwd}/package.json`;
73
+
74
+ if (fs.existsSync(packageJsonPath)) {
75
+ try {
76
+ const pkg = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
77
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
78
+
79
+ if (deps['vue']) {
80
+ detectedFileType = 'vue';
81
+ detectedImports.push('vue');
82
+ }
83
+ if (deps['react']) {
84
+ detectedFileType = 'tsx';
85
+ detectedImports.push('react');
86
+ }
87
+ if (deps['element-plus']) detectedImports.push('element-plus');
88
+ if (deps['pinia']) detectedImports.push('pinia');
89
+ if (deps['vue-i18n']) detectedImports.push('vue-i18n');
90
+ } catch {
91
+ logger.log('无法解析 package.json');
92
+ }
93
+ }
94
+ }
95
+
96
+ // 去重
97
+ detectedImports = [...new Set(detectedImports)];
98
+
99
+ logger.log(`🔍 智能检测结果: fileType=${detectedFileType}, imports=${detectedImports.join(',')}, scenario=${detectedScenario}`);
100
+
101
+ // 获取相关规范
102
+ const standards = manager.getRelevantStandards({
103
+ fileType: detectedFileType !== 'unknown' ? detectedFileType : undefined,
104
+ imports: detectedImports.length > 0 ? detectedImports : undefined,
105
+ scenario: detectedScenario || undefined
106
+ });
107
+
108
+ const combinedContent = manager.combineStandards(standards);
109
+
110
+ return {
111
+ content: [{
112
+ type: 'text',
113
+ text: JSON.stringify({
114
+ success: true,
115
+ analysis: {
116
+ source: analysisSource,
117
+ fileType: detectedFileType,
118
+ imports: detectedImports,
119
+ scenario: detectedScenario
120
+ },
121
+ standards: standards,
122
+ content: combinedContent,
123
+ stats: {
124
+ standardsCount: standards.length,
125
+ contentLength: combinedContent.length,
126
+ estimatedTokens: Math.ceil(combinedContent.length / 4)
127
+ }
128
+ }, null, 2)
129
+ }]
130
+ };
131
+ } catch (error) {
132
+ logger.error(`智能规范推荐失败: ${error}`);
133
+ return {
134
+ content: [{
135
+ type: 'text',
136
+ text: JSON.stringify({
137
+ error: error instanceof Error ? error.message : String(error)
138
+ }, null, 2)
139
+ }]
140
+ };
141
+ }
142
+ }
143
+
144
+ /**
145
+ * 从代码中提取导入语句
146
+ */
147
+ function extractImports(content: string): string[] {
148
+ const imports: string[] = [];
149
+
150
+ // ES6 imports
151
+ const es6Regex = /import\s+.*?\s+from\s+['"]([^'"]+)['"]/g;
152
+ let match;
153
+ while ((match = es6Regex.exec(content)) !== null) {
154
+ const pkg = match[1];
155
+ if (!pkg.startsWith('.') && !pkg.startsWith('/')) {
156
+ imports.push(pkg.split('/')[0]);
157
+ }
158
+ }
159
+
160
+ // require statements
161
+ const requireRegex = /require\s*\(\s*['"]([^'"]+)['"]\s*\)/g;
162
+ while ((match = requireRegex.exec(content)) !== null) {
163
+ const pkg = match[1];
164
+ if (!pkg.startsWith('.') && !pkg.startsWith('/')) {
165
+ imports.push(pkg.split('/')[0]);
166
+ }
167
+ }
168
+
169
+ return [...new Set(imports)];
170
+ }
171
+
172
+ /**
173
+ * 从代码推断开发场景
174
+ */
175
+ function inferScenario(content: string, fileType: string): string {
176
+ const scenarios: string[] = [];
177
+
178
+ // Vue 相关
179
+ if (fileType === 'vue') {
180
+ if (content.includes('ElForm') || content.includes('<el-form')) {
181
+ scenarios.push('表单组件');
182
+ }
183
+ if (content.includes('ElTable') || content.includes('<el-table')) {
184
+ scenarios.push('表格组件');
185
+ }
186
+ if (content.includes('defineStore')) {
187
+ scenarios.push('状态管理');
188
+ }
189
+ if (content.includes('useI18n') || content.includes('$t(')) {
190
+ scenarios.push('国际化');
191
+ }
192
+ }
193
+
194
+ // API 调用
195
+ if (content.includes('fetch(') || content.includes('axios.')) {
196
+ scenarios.push('API 调用');
197
+ }
198
+
199
+ // TypeScript
200
+ if (content.includes('interface ') || content.includes('type ')) {
201
+ scenarios.push('类型定义');
202
+ }
203
+
204
+ return scenarios.join('、');
205
+ }