autosnippet 3.0.13 → 3.1.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 (100) hide show
  1. package/bin/api-server.js +2 -0
  2. package/bin/cli.js +24 -19
  3. package/config/default.json +1 -1
  4. package/lib/bootstrap.js +4 -4
  5. package/lib/cli/SetupService.js +29 -29
  6. package/lib/cli/UpgradeService.js +3 -2
  7. package/lib/core/AstAnalyzer.js +1 -1
  8. package/lib/core/ast/ensure-grammars.js +1 -1
  9. package/lib/core/ast/index.js +62 -11
  10. package/lib/core/ast/lang-dart.js +27 -21
  11. package/lib/core/ast/lang-go.js +6 -20
  12. package/lib/core/ast/lang-rust.js +53 -28
  13. package/lib/core/ast/parser-init.js +9 -5
  14. package/lib/core/discovery/DartDiscoverer.js +4 -10
  15. package/lib/core/discovery/GoDiscoverer.js +45 -25
  16. package/lib/core/discovery/NodeDiscoverer.js +1 -3
  17. package/lib/core/discovery/PythonDiscoverer.js +7 -1
  18. package/lib/core/discovery/RustDiscoverer.js +111 -38
  19. package/lib/core/discovery/index.js +2 -2
  20. package/lib/core/enhancement/django-enhancement.js +10 -4
  21. package/lib/core/enhancement/fastapi-enhancement.js +16 -9
  22. package/lib/core/enhancement/go-grpc-enhancement.js +2 -1
  23. package/lib/core/enhancement/go-web-enhancement.js +3 -6
  24. package/lib/core/enhancement/ml-enhancement.js +6 -3
  25. package/lib/core/enhancement/nextjs-enhancement.js +17 -7
  26. package/lib/core/enhancement/node-server-enhancement.js +4 -2
  27. package/lib/core/enhancement/react-enhancement.js +6 -3
  28. package/lib/core/enhancement/rust-tokio-enhancement.js +6 -2
  29. package/lib/core/enhancement/rust-web-enhancement.js +13 -7
  30. package/lib/core/enhancement/vue-enhancement.js +10 -5
  31. package/lib/external/ai/AiFactory.js +3 -1
  32. package/lib/external/ai/AiProvider.js +3 -1
  33. package/lib/external/mcp/McpServer.js +2 -0
  34. package/lib/external/mcp/handlers/bootstrap/base-dimensions.js +1 -2
  35. package/lib/external/mcp/handlers/bootstrap/pipeline/checkpoint.js +7 -1
  36. package/lib/external/mcp/handlers/bootstrap/pipeline/noAiFallback.js +55 -26
  37. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +8 -8
  38. package/lib/external/mcp/handlers/bootstrap/refine.js +3 -1
  39. package/lib/external/mcp/handlers/bootstrap.js +4 -10
  40. package/lib/external/mcp/handlers/browse.js +6 -2
  41. package/lib/external/mcp/handlers/guard.js +6 -2
  42. package/lib/external/mcp/handlers/skill.js +6 -2
  43. package/lib/http/HttpServer.js +1 -1
  44. package/lib/http/routes/candidates.js +3 -1
  45. package/lib/http/routes/extract.js +4 -5
  46. package/lib/http/routes/guardRules.js +1 -1
  47. package/lib/http/routes/modules.js +9 -3
  48. package/lib/http/routes/skills.js +54 -6
  49. package/lib/http/routes/violations.js +4 -3
  50. package/lib/infrastructure/external/ClipboardManager.js +24 -7
  51. package/lib/infrastructure/external/NativeUi.js +3 -1
  52. package/lib/infrastructure/external/OpenBrowser.js +1 -0
  53. package/lib/infrastructure/external/XcodeAutomation.js +5 -5
  54. package/lib/infrastructure/vector/IndexingPipeline.js +14 -5
  55. package/lib/injection/ServiceContainer.js +34 -11
  56. package/lib/platform/ios/index.js +20 -25
  57. package/lib/platform/ios/routes/spm.js +6 -3
  58. package/lib/platform/ios/snippet/PlaceholderConverter.js +6 -2
  59. package/lib/platform/ios/snippet/XcodeCodec.js +4 -2
  60. package/lib/platform/ios/spm/SpmDiscoverer.js +1 -1
  61. package/lib/platform/ios/spm/SpmService.js +3 -1
  62. package/lib/platform/ios/xcode/XcodeIntegration.js +10 -12
  63. package/lib/platform/ios/xcode/XcodeWriteUtils.js +6 -1
  64. package/lib/service/automation/FileWatcher.js +1 -3
  65. package/lib/service/automation/handlers/CreateHandler.js +3 -5
  66. package/lib/service/automation/handlers/GuardHandler.js +11 -32
  67. package/lib/service/automation/handlers/SearchHandler.js +9 -9
  68. package/lib/service/chat/CandidateGuardrail.js +11 -6
  69. package/lib/service/chat/ChatAgent.js +31 -22
  70. package/lib/service/chat/HandoffProtocol.js +5 -2
  71. package/lib/service/chat/tools/composite.js +3 -2
  72. package/lib/service/chat/tools/index.js +60 -71
  73. package/lib/service/chat/tools/infrastructure.js +9 -4
  74. package/lib/service/chat/tools/lifecycle.js +22 -5
  75. package/lib/service/chat/tools/project-access.js +5 -9
  76. package/lib/service/chat/tools.js +1 -2
  77. package/lib/service/cursor/AgentInstructionsGenerator.js +33 -15
  78. package/lib/service/cursor/CursorDeliveryPipeline.js +2 -1
  79. package/lib/service/cursor/KnowledgeCompressor.js +16 -7
  80. package/lib/service/guard/ComplianceReporter.js +5 -2
  81. package/lib/service/guard/GuardCheckEngine.js +53 -26
  82. package/lib/service/guard/GuardCodeChecks.js +217 -188
  83. package/lib/service/guard/GuardCrossFileChecks.js +203 -184
  84. package/lib/service/guard/GuardPatternUtils.js +17 -10
  85. package/lib/service/module/ModuleService.js +180 -56
  86. package/lib/service/recipe/RecipeCandidateValidator.js +11 -8
  87. package/lib/service/snippet/SnippetFactory.js +3 -3
  88. package/lib/service/snippet/SnippetInstaller.js +35 -11
  89. package/lib/service/snippet/codecs/VSCodeCodec.js +2 -2
  90. package/lib/service/wiki/WikiGenerator.js +67 -40
  91. package/lib/service/wiki/WikiRenderers.js +105 -80
  92. package/lib/service/wiki/WikiUtils.js +217 -80
  93. package/lib/shared/LanguageService.js +111 -53
  94. package/lib/shared/PathGuard.js +0 -8
  95. package/package.json +3 -9
  96. package/scripts/bench-real-projects.mjs +29 -29
  97. package/scripts/generate-recipe-drafts.js +17 -27
  98. package/scripts/init-snippets.js +43 -24
  99. package/scripts/install-vscode-copilot.js +3 -19
  100. package/scripts/setup-mcp-config.js +0 -4
@@ -110,15 +110,12 @@ export async function handleGuard(watcher, fullPath, code, guardLine) {
110
110
  }
111
111
 
112
112
  const scopeLabel = scope === 'project' ? '整个项目' : '当前目录';
113
- console.log(`\n🔍 Guard 审计 — ${scopeLabel} (${scanRoot})`);
114
113
  const sourcePaths = await collectSourceFiles(scanRoot);
115
114
 
116
115
  if (sourcePaths.length === 0) {
117
- console.log(' ℹ️ 未找到可审计的源文件');
118
116
  watcher._notify?.('未找到可审计的源文件');
119
117
  return;
120
118
  }
121
- console.log(` 📁 扫描到 ${sourcePaths.length} 个源文件`);
122
119
 
123
120
  // 读取所有文件内容
124
121
  const fileEntries = [];
@@ -140,47 +137,36 @@ export async function handleGuard(watcher, fullPath, code, guardLine) {
140
137
  const { summary } = report;
141
138
 
142
139
  if (summary.totalViolations === 0) {
143
- console.log(`\n ✅ 审计通过 — ${fileEntries.length} 个文件,无违规`);
144
140
  watcher._notify?.(`${scopeLabel}审计通过 ✅ ${fileEntries.length} 个文件,无违规`);
145
141
  } else {
146
- // 按文件输出详情(限制输出前 10 个有问题的文件)
147
- console.log(`\n ❌ 审计发现 ${summary.totalViolations} 个问题 (${summary.errors ?? 0} 错误, ${summary.warnings ?? 0} 警告)`);
148
- watcher._notify?.(`${scopeLabel}审计: ${summary.totalViolations} 个问题 (${summary.errors ?? 0} 错误, ${summary.warnings ?? 0} 警告)`);
142
+ watcher._notify?.(
143
+ `${scopeLabel}审计: ${summary.totalViolations} 个问题 (${summary.errors ?? 0} 错误, ${summary.warnings ?? 0} 警告)`
144
+ );
149
145
  const filesWithIssues = report.files.filter((f) => f.summary.total > 0);
150
146
  for (const file of filesWithIssues.slice(0, 10)) {
151
- const rel = file.filePath.replace(`${scanRoot}/`, '');
147
+ const _rel = file.filePath.replace(`${scanRoot}/`, '');
152
148
  const errors = file.violations.filter((v) => v.severity === 'error');
153
149
  const warnings = file.violations.filter((v) => v.severity === 'warning');
154
- console.log(`\n 📄 ${rel} (${errors.length} 错误, ${warnings.length} 警告)`);
155
- for (const v of errors.slice(0, 5)) {
156
- console.log(` 🔴 [${v.ruleId || 'unknown'}] ${v.message}${v.line ? ` (行 ${v.line})` : ''}`);
150
+ for (const _v of errors.slice(0, 5)) {
157
151
  }
158
152
  if (errors.length > 5) {
159
- console.log(` ... 还有 ${errors.length - 5} 个错误`);
160
153
  }
161
- for (const v of warnings.slice(0, 3)) {
162
- console.log(` 🟡 [${v.ruleId || 'unknown'}] ${v.message}${v.line ? ` (行 ${v.line})` : ''}`);
154
+ for (const _v of warnings.slice(0, 3)) {
163
155
  }
164
156
  if (warnings.length > 3) {
165
- console.log(` ... 还有 ${warnings.length - 3} 个警告`);
166
157
  }
167
158
  }
168
159
  if (filesWithIssues.length > 10) {
169
- console.log(`\n ... 还有 ${filesWithIssues.length - 10} 个文件有问题`);
170
160
  }
171
161
 
172
162
  // 跨文件问题汇总
173
163
  if (report.crossFileViolations?.length > 0) {
174
- console.log(`\n 🔗 跨文件问题 (${report.crossFileViolations.length} 个):`);
175
164
  for (const v of report.crossFileViolations.slice(0, 10)) {
176
- console.log(` ⚠️ [${v.ruleId || 'cross-file'}] ${v.message}`);
177
165
  if (v.locations) {
178
166
  for (const loc of v.locations.slice(0, 5)) {
179
- const relLoc = loc.filePath.replace(`${scanRoot}/`, '');
180
- console.log(` 📍 ${relLoc}${loc.line ? `:${loc.line}` : ''}`);
167
+ const _relLoc = loc.filePath.replace(`${scanRoot}/`, '');
181
168
  }
182
169
  if (v.locations.length > 5) {
183
- console.log(` ... 还有 ${v.locations.length - 5} 个位置`);
184
170
  }
185
171
  }
186
172
  }
@@ -197,9 +183,7 @@ export async function handleGuard(watcher, fullPath, code, guardLine) {
197
183
  const results = await searchEngine.search(rest, { limit: 3, mode: 'keyword' });
198
184
  const items = Array.isArray(results) ? results : results.items || [];
199
185
  if (items.length > 0) {
200
- console.log(`\n 📚 相关规范 ("${rest}"):`);
201
- for (const r of items) {
202
- console.log(` • ${r.title || r.name || r.id}`);
186
+ for (const _r of items) {
203
187
  }
204
188
  }
205
189
  } catch {
@@ -219,27 +203,22 @@ function _auditSingleFile(watcher, engine, fullPath, code, detectLanguage, scope
219
203
  const violations = engine.checkCode(code, language, { scope });
220
204
 
221
205
  if (violations.length === 0) {
222
- console.log(`\n ✅ Guard 审计通过 — 无违规 (${fullPath.split('/').pop()})`);
223
206
  watcher._notify?.('审计通过 ✅ 无违规');
224
207
  } else {
225
208
  const errors = violations.filter((v) => v.severity === 'error');
226
209
  const warnings = violations.filter((v) => v.severity === 'warning');
227
- console.log(`\n ❌ 发现 ${violations.length} 个问题 (${errors.length} 错误, ${warnings.length} 警告)`);
228
- watcher._notify?.(`审计: ${violations.length} 个问题 (${errors.length} 错误, ${warnings.length} 警告)`);
210
+ watcher._notify?.(
211
+ `审计: ${violations.length} 个问题 (${errors.length} 错误, ${warnings.length} 警告)`
212
+ );
229
213
  for (const v of errors) {
230
- console.log(` 🔴 [${v.ruleId || 'unknown'}] ${v.message}${v.line ? ` (行 ${v.line})` : ''}`);
231
214
  if (v.fixSuggestion) {
232
- console.log(` 💡 建议: ${v.fixSuggestion}`);
233
215
  }
234
216
  }
235
217
  for (const v of warnings.slice(0, 5)) {
236
- console.log(` 🟡 [${v.ruleId || 'unknown'}] ${v.message}${v.line ? ` (行 ${v.line})` : ''}`);
237
218
  if (v.fixSuggestion) {
238
- console.log(` 💡 建议: ${v.fixSuggestion}`);
239
219
  }
240
220
  }
241
221
  if (warnings.length > 5) {
242
- console.log(` ... 还有 ${warnings.length - 5} 个警告`);
243
222
  }
244
223
  }
245
224
 
@@ -292,14 +292,14 @@ function _stripMarkdownFormatting(md) {
292
292
  return '';
293
293
  }
294
294
  return md
295
- .replace(/```[\w]*\n[\s\S]*?```/g, '') // 移除代码块
296
- .replace(/^#{1,6}\s+/gm, '') // 移除标题标记
297
- .replace(/\*\*([^*]+)\*\*/g, '$1') // 移除粗体
298
- .replace(/\*([^*]+)\*/g, '$1') // 移除斜体
299
- .replace(/`([^`]+)`/g, '$1') // 移除行内代码
300
- .replace(/^\s*[-*+]\s+/gm, '') // 移除列表标记
301
- .replace(/^\s*\d+\.\s+/gm, '') // 移除有序列表
302
- .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // 移除链接,保留文字
303
- .replace(/\n{3,}/g, '\n\n') // 压缩多余空行
295
+ .replace(/```[\w]*\n[\s\S]*?```/g, '') // 移除代码块
296
+ .replace(/^#{1,6}\s+/gm, '') // 移除标题标记
297
+ .replace(/\*\*([^*]+)\*\*/g, '$1') // 移除粗体
298
+ .replace(/\*([^*]+)\*/g, '$1') // 移除斜体
299
+ .replace(/`([^`]+)`/g, '$1') // 移除行内代码
300
+ .replace(/^\s*[-*+]\s+/gm, '') // 移除列表标记
301
+ .replace(/^\s*\d+\.\s+/gm, '') // 移除有序列表
302
+ .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1') // 移除链接,保留文字
303
+ .replace(/\n{3,}/g, '\n\n') // 压缩多余空行
304
304
  .trim();
305
305
  }
@@ -16,9 +16,9 @@
16
16
  */
17
17
  function codeFingerprint(code) {
18
18
  return (code || '')
19
- .replace(/\/\/[^\n]*/g, '') // 移除单行注释
19
+ .replace(/\/\/[^\n]*/g, '') // 移除单行注释
20
20
  .replace(/\/\*[\s\S]*?\*\//g, '') // 移除多行注释
21
- .replace(/[\s]+/g, '') // 移除所有空白
21
+ .replace(/[\s]+/g, '') // 移除所有空白
22
22
  .toLowerCase()
23
23
  .slice(0, 200);
24
24
  }
@@ -101,7 +101,10 @@ export class CandidateGuardrail {
101
101
 
102
102
  // headers 必填(数组,空项目也需传 [])
103
103
  if (!Array.isArray(candidate.headers)) {
104
- return { valid: false, error: '缺少必填字段: headers — 需为 import 语句数组,无 import 时传 []' };
104
+ return {
105
+ valid: false,
106
+ error: '缺少必填字段: headers — 需为 import 语句数组,无 import 时传 []',
107
+ };
105
108
  }
106
109
 
107
110
  // knowledgeType 约束 — 自动修正为允许列表中第一个类型
@@ -114,7 +117,10 @@ export class CandidateGuardrail {
114
117
 
115
118
  // reasoning 必填
116
119
  if (!candidate.reasoning || typeof candidate.reasoning !== 'object') {
117
- return { valid: false, error: '缺少必填字段: reasoning — 需包含 whyStandard + sources + confidence' };
120
+ return {
121
+ valid: false,
122
+ error: '缺少必填字段: reasoning — 需包含 whyStandard + sources + confidence',
123
+ };
118
124
  }
119
125
  if (!candidate.reasoning.whyStandard?.trim()) {
120
126
  return { valid: false, error: '缺少必填字段: reasoning.whyStandard' };
@@ -173,8 +179,7 @@ export class CandidateGuardrail {
173
179
  }
174
180
 
175
181
  // 检查是否包含代码引用或文件路径
176
- const hasCodeBlock =
177
- /```[\s\S]*?```/.test(content) || /\.\w{1,10}(:\d+)?/.test(content);
182
+ const hasCodeBlock = /```[\s\S]*?```/.test(content) || /\.\w{1,10}(:\d+)?/.test(content);
178
183
  const hasSourceRef =
179
184
  /来源[::]|[Ss]ource[::]|\(\w+\.\w+:\d+\)/.test(content) ||
180
185
  /[A-Z]\w+\.(?:m|h|swift|java|kt|js|ts|go|py|rs|rb|cs|cpp|c)/.test(content);
@@ -26,23 +26,23 @@ import fs from 'node:fs';
26
26
  import path from 'node:path';
27
27
  import { fileURLToPath } from 'node:url';
28
28
  import Logger from '../../infrastructure/logging/Logger.js';
29
- import { ContextWindow, limitToolResult, PhaseRouter } from './ContextWindow.js';
30
- import { ConversationStore } from './ConversationStore.js';
31
- import { Memory } from './Memory.js';
32
- import { ReasoningLayer } from './ReasoningLayer.js';
33
- import { TaskPipeline } from './TaskPipeline.js';
29
+ import {
30
+ buildNativeToolSystemPrompt,
31
+ buildProjectBriefing,
32
+ cleanFinalAnswer,
33
+ } from './ChatAgentPrompts.js';
34
34
  import {
35
35
  taskCheckAndSubmit,
36
36
  taskDiscoverAllRelations,
37
37
  taskFullEnrich,
38
- taskQualityAudit,
39
38
  taskGuardFullScan,
39
+ taskQualityAudit,
40
40
  } from './ChatAgentTasks.js';
41
- import {
42
- buildNativeToolSystemPrompt,
43
- buildProjectBriefing,
44
- cleanFinalAnswer,
45
- } from './ChatAgentPrompts.js';
41
+ import { ContextWindow, limitToolResult, PhaseRouter } from './ContextWindow.js';
42
+ import { ConversationStore } from './ConversationStore.js';
43
+ import { Memory } from './Memory.js';
44
+ import { ReasoningLayer } from './ReasoningLayer.js';
45
+ import { TaskPipeline } from './TaskPipeline.js';
46
46
 
47
47
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
48
48
  const PROJECT_ROOT = path.resolve(__dirname, '../../..');
@@ -420,21 +420,25 @@ export class ChatAgent {
420
420
  isSystem && !disablePhaseRouter ? new PhaseRouter(budget, isSkillOnly) : null;
421
421
 
422
422
  // ── 系统提示词 (支持外部覆盖) ──
423
- let baseSystemPrompt = systemPromptOverride || buildNativeToolSystemPrompt({
424
- currentSource: this.#currentSource,
425
- projectBriefingCache: this.#projectBriefingCache,
426
- memory: this.#memory,
427
- semanticMemory: this.#semanticMemory,
428
- budget,
429
- soulPath: SOUL_PATH,
430
- });
423
+ let baseSystemPrompt =
424
+ systemPromptOverride ||
425
+ buildNativeToolSystemPrompt({
426
+ currentSource: this.#currentSource,
427
+ projectBriefingCache: this.#projectBriefingCache,
428
+ memory: this.#memory,
429
+ semanticMemory: this.#semanticMemory,
430
+ budget,
431
+ soulPath: SOUL_PATH,
432
+ });
431
433
 
432
434
  // ── 统一注入语言指令(对所有来源生效: user 对话 / system bootstrap / analyst / producer)──
433
435
  const effectiveLang = this.#currentLang;
434
436
  if (effectiveLang === 'en') {
435
- baseSystemPrompt += '\n\n## Language\nYou MUST respond in English. All output text, analysis, titles and descriptions must be in English.';
437
+ baseSystemPrompt +=
438
+ '\n\n## Language\nYou MUST respond in English. All output text, analysis, titles and descriptions must be in English.';
436
439
  } else if (effectiveLang === 'zh') {
437
- baseSystemPrompt += '\n\n## 语言\n你必须使用中文回复。所有输出文本、分析、标题和描述都必须是中文。';
440
+ baseSystemPrompt +=
441
+ '\n\n## 语言\n你必须使用中文回复。所有输出文本、分析、标题和描述都必须是中文。';
438
442
  }
439
443
 
440
444
  // 统一注入轮次预算,确保 AI 始终知道具体数字和节奏
@@ -1008,7 +1012,12 @@ export class ChatAgent {
1008
1012
  // 记录代码模式指纹用于跨维度去重
1009
1013
  const pattern = fc.args?.content?.pattern || '';
1010
1014
  if (pattern.length >= 30) {
1011
- const fp = pattern.replace(/\/\/[^\n]*/g, '').replace(/\/\*[\s\S]*?\*\//g, '').replace(/[\s]+/g, '').toLowerCase().slice(0, 200);
1015
+ const fp = pattern
1016
+ .replace(/\/\/[^\n]*/g, '')
1017
+ .replace(/\/\*[\s\S]*?\*\//g, '')
1018
+ .replace(/[\s]+/g, '')
1019
+ .toLowerCase()
1020
+ .slice(0, 200);
1012
1021
  if (fp.length >= 20) {
1013
1022
  this.#globalSubmittedPatterns.add(fp);
1014
1023
  }
@@ -129,7 +129,9 @@ export function buildAnalysisReport(analystResult, dimensionId, projectGraph = n
129
129
  }
130
130
  // 从搜索结果中提取文件路径
131
131
  if (typeof result === 'string') {
132
- const fileMatches = result.match(/(?:^|\n)([\w/.-]+\.(?:go|mod|sum|py|pyi|java|kt|kts|js|ts|jsx|tsx|mjs|cjs|swift|m|h|c|cpp|cc|hpp|cs|rb|rs|sql|json|yaml|yml|toml|xml|html|css|scss|less|sh|md|txt|gradle|properties|proto|vue|svelte|graphql|cfg|conf|ini|env|lock|rst))(?::\d+)?/gi);
132
+ const fileMatches = result.match(
133
+ /(?:^|\n)([\w/.-]+\.(?:go|mod|sum|py|pyi|java|kt|kts|js|ts|jsx|tsx|mjs|cjs|swift|m|h|c|cpp|cc|hpp|cs|rb|rs|sql|json|yaml|yml|toml|xml|html|css|scss|less|sh|md|txt|gradle|properties|proto|vue|svelte|graphql|cfg|conf|ini|env|lock|rst))(?::\d+)?/gi
134
+ );
133
135
  if (fileMatches) {
134
136
  for (const m of fileMatches) {
135
137
  const clean = m.trim().replace(/:\d+$/, '').replace(/^\n/, '');
@@ -170,7 +172,8 @@ export function buildAnalysisReport(analystResult, dimensionId, projectGraph = n
170
172
 
171
173
  // 从分析文本中提取文件路径(支持多语言项目)
172
174
  const text = sanitizeAnalysisText(analystResult.reply || '');
173
- const FILE_EXT_RE = /[\w/.-]+\.(?:go|mod|sum|py|pyi|java|kt|kts|js|ts|jsx|tsx|mjs|cjs|swift|m|h|c|cpp|cc|hpp|cs|rb|rs|sql|json|yaml|yml|toml|xml|html|css|scss|less|sh|md|txt|gradle|properties|proto|vue|svelte|graphql|cfg|conf|ini|env|lock|rst)\b/gi;
175
+ const FILE_EXT_RE =
176
+ /[\w/.-]+\.(?:go|mod|sum|py|pyi|java|kt|kts|js|ts|jsx|tsx|mjs|cjs|swift|m|h|c|cpp|cc|hpp|cs|rb|rs|sql|json|yaml|yml|toml|xml|html|css|scss|less|sh|md|txt|gradle|properties|proto|vue|svelte|graphql|cfg|conf|ini|env|lock|rst)\b/gi;
174
177
  const textFileRefs = text.match(FILE_EXT_RE);
175
178
  if (textFileRefs) {
176
179
  for (const f of textFileRefs) {
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import { findSimilarRecipes } from '../../candidate/SimilarityService.js';
13
- import { DIMENSION_DISPLAY_GROUP, checkDimensionType } from './_shared.js';
13
+ import { checkDimensionType, DIMENSION_DISPLAY_GROUP } from './_shared.js';
14
14
 
15
15
  // ────────────────────────────────────────────────────────────
16
16
  // 34. analyze_code — 组合工具 (Guard + Recipe 搜索)
@@ -157,7 +157,8 @@ export const submitWithCheck = {
157
157
  properties: {
158
158
  content: {
159
159
  type: 'object',
160
- description: '{ markdown: "项目特写 Markdown", pattern: "核心代码 3-8 行,必须语法完整(括号配对、不能以 } 开头或 { 结尾)" }',
160
+ description:
161
+ '{ markdown: "项目特写 Markdown", pattern: "核心代码 3-8 行,必须语法完整(括号配对、不能以 } 开头或 { 结尾)" }',
161
162
  },
162
163
  title: { type: 'string', description: '候选标题' },
163
164
  description: { type: 'string', description: '中文简述 ≤80 字' },
@@ -4,99 +4,88 @@
4
4
  * 从各子模块导入所有工具,按原始顺序组装 ALL_TOOLS 数组并导出。
5
5
  */
6
6
 
7
- // ── 项目数据访问 (5) ──
8
- import {
9
- searchProjectCode,
10
- readProjectFile,
11
- listProjectStructure,
12
- getFileSummary,
13
- semanticSearchCode,
14
- } from './project-access.js';
15
-
16
- // ── 查询类 (6) ──
17
- import {
18
- searchRecipes,
19
- searchCandidates,
20
- getRecipeDetail,
21
- getProjectStats,
22
- searchKnowledge,
23
- getRelatedRecipes,
24
- } from './query.js';
25
-
26
7
  // ── AI 分析类 (4) ──
27
8
  import {
28
- summarizeCode,
29
- extractRecipes,
30
9
  enrichCandidate,
10
+ extractRecipes,
31
11
  refineBootstrapCandidates,
12
+ summarizeCode,
32
13
  } from './ai-analysis.js';
14
+ // ── AST 结构化分析 + Agent Memory (10) ──
15
+ import {
16
+ getCategoryMap,
17
+ getClassHierarchy,
18
+ getClassInfo,
19
+ getMethodOverrides,
20
+ getPreviousAnalysis,
21
+ getPreviousEvidence,
22
+ getProjectOverview,
23
+ getProtocolInfo,
24
+ noteFinding,
25
+ queryCodeGraph,
26
+ } from './ast-graph.js';
27
+ // ── 组合工具 + 元工具 (6) ──
28
+ import {
29
+ analyzeCode,
30
+ getToolDetails,
31
+ knowledgeOverview,
32
+ planTask,
33
+ reviewMyOutput,
34
+ submitWithCheck,
35
+ } from './composite.js';
33
36
 
34
37
  // ── Guard 安全类 (6) ──
35
38
  import {
36
- listGuardRules,
37
- getRecommendations,
38
39
  aiTranslate,
40
+ generateGuardRule,
41
+ getRecommendations,
39
42
  guardCheckCode,
43
+ listGuardRules,
40
44
  queryViolations,
41
- generateGuardRule,
42
45
  } from './guard.js';
43
-
44
- // ── 知识图谱类 (3) ──
46
+ // ── 基础设施类 (7) ──
45
47
  import {
46
- checkDuplicate,
47
- discoverRelations,
48
- addGraphEdge,
49
- } from './knowledge-graph.js';
50
-
48
+ bootstrapKnowledgeTool,
49
+ createSkillTool,
50
+ graphImpactAnalysis,
51
+ loadSkill,
52
+ queryAuditLog,
53
+ rebuildIndex,
54
+ suggestSkills,
55
+ } from './infrastructure.js';
56
+ // ── 知识图谱类 (3) ──
57
+ import { addGraphEdge, checkDuplicate, discoverRelations } from './knowledge-graph.js';
51
58
  // ── 生命周期操作类 (11) ──
52
59
  import {
53
- submitCandidate,
54
- saveDocument,
55
60
  approveCandidate,
56
- rejectCandidate,
57
- publishRecipe,
58
61
  deprecateRecipe,
59
- updateRecipe,
60
- recordUsage,
62
+ getFeedbackStats,
63
+ publishRecipe,
61
64
  qualityScore,
65
+ recordUsage,
66
+ rejectCandidate,
67
+ saveDocument,
68
+ submitCandidate,
69
+ updateRecipe,
62
70
  validateCandidate,
63
- getFeedbackStats,
64
71
  } from './lifecycle.js';
65
-
66
- // ── 基础设施类 (7) ──
67
- import {
68
- graphImpactAnalysis,
69
- rebuildIndex,
70
- queryAuditLog,
71
- loadSkill,
72
- createSkillTool,
73
- suggestSkills,
74
- bootstrapKnowledgeTool,
75
- } from './infrastructure.js';
76
-
77
- // ── 组合工具 + 元工具 (6) ──
72
+ // ── 项目数据访问 (5) ──
78
73
  import {
79
- analyzeCode,
80
- knowledgeOverview,
81
- submitWithCheck,
82
- getToolDetails,
83
- planTask,
84
- reviewMyOutput,
85
- } from './composite.js';
86
-
87
- // ── AST 结构化分析 + Agent Memory (10) ──
74
+ getFileSummary,
75
+ listProjectStructure,
76
+ readProjectFile,
77
+ searchProjectCode,
78
+ semanticSearchCode,
79
+ } from './project-access.js';
80
+ // ── 查询类 (6) ──
88
81
  import {
89
- getProjectOverview,
90
- getClassHierarchy,
91
- getClassInfo,
92
- getProtocolInfo,
93
- getMethodOverrides,
94
- getCategoryMap,
95
- getPreviousAnalysis,
96
- noteFinding,
97
- getPreviousEvidence,
98
- queryCodeGraph,
99
- } from './ast-graph.js';
82
+ getProjectStats,
83
+ getRecipeDetail,
84
+ getRelatedRecipes,
85
+ searchCandidates,
86
+ searchKnowledge,
87
+ searchRecipes,
88
+ } from './query.js';
100
89
 
101
90
  // ── Re-export 所有工具 ──
102
91
  export {
@@ -13,7 +13,7 @@
13
13
  import fs from 'node:fs';
14
14
  import path from 'node:path';
15
15
  import Logger from '../../../infrastructure/logging/Logger.js';
16
- import { SKILLS_DIR, PROJECT_SKILLS_DIR } from './_shared.js';
16
+ import { PROJECT_SKILLS_DIR, SKILLS_DIR } from './_shared.js';
17
17
 
18
18
  // ────────────────────────────────────────────────────────────
19
19
  // 29. graph_impact_analysis
@@ -99,7 +99,8 @@ export const loadSkill = {
99
99
  properties: {
100
100
  skillName: {
101
101
  type: 'string',
102
- description: 'Skill 目录名(如 autosnippet-coldstart, autosnippet-reference-swift, autosnippet-reference-go 等)',
102
+ description:
103
+ 'Skill 目录名(如 autosnippet-coldstart, autosnippet-reference-swift, autosnippet-reference-go 等)',
103
104
  },
104
105
  },
105
106
  required: ['skillName'],
@@ -119,12 +120,16 @@ export const loadSkill = {
119
120
  fs.readdirSync(SKILLS_DIR, { withFileTypes: true })
120
121
  .filter((d) => d.isDirectory())
121
122
  .forEach((d) => available.add(d.name));
122
- } catch {}
123
+ } catch {
124
+ /* skip: SKILLS_DIR may not exist */
125
+ }
123
126
  try {
124
127
  fs.readdirSync(PROJECT_SKILLS_DIR, { withFileTypes: true })
125
128
  .filter((d) => d.isDirectory())
126
129
  .forEach((d) => available.add(d.name));
127
- } catch {}
130
+ } catch {
131
+ /* skip: project skills dir may not exist */
132
+ }
128
133
  return { error: `Skill "${params.skillName}" not found`, availableSkills: [...available] };
129
134
  }
130
135
  },
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  import { CandidateGuardrail } from '../CandidateGuardrail.js';
18
- import { DIMENSION_DISPLAY_GROUP, checkDimensionType } from './_shared.js';
18
+ import { checkDimensionType, DIMENSION_DISPLAY_GROUP } from './_shared.js';
19
19
 
20
20
  // ────────────────────────────────────────────────────────────
21
21
  // 16. submit_knowledge
@@ -29,7 +29,8 @@ export const submitCandidate = {
29
29
  // ── 内容(V3 content 子对象) ──
30
30
  content: {
31
31
  type: 'object',
32
- description: '{ markdown: "项目特写 Markdown(≥200字)", pattern: "核心代码 3-8 行", rationale: "设计原理" }',
32
+ description:
33
+ '{ markdown: "项目特写 Markdown(≥200字)", pattern: "核心代码 3-8 行", rationale: "设计原理" }',
33
34
  },
34
35
 
35
36
  // ── 基本信息 ──
@@ -71,11 +72,23 @@ export const submitCandidate = {
71
72
  items: { type: 'string' },
72
73
  description: '依赖的 import/require 行(无 import 时传 [])',
73
74
  },
74
- knowledgeType: { type: 'string', description: '知识维度:code-pattern / architecture / best-practice 等' },
75
+ knowledgeType: {
76
+ type: 'string',
77
+ description: '知识维度:code-pattern / architecture / best-practice 等',
78
+ },
75
79
  usageGuide: { type: 'string', description: '使用指南 Markdown(### 章节格式)' },
76
80
  sourceFile: { type: 'string', description: '来源文件相对路径' },
77
81
  },
78
- required: ['content', 'title', 'trigger', 'kind', 'doClause', 'description', 'headers', 'reasoning'],
82
+ required: [
83
+ 'content',
84
+ 'title',
85
+ 'trigger',
86
+ 'kind',
87
+ 'doClause',
88
+ 'description',
89
+ 'headers',
90
+ 'reasoning',
91
+ ],
79
92
  },
80
93
  handler: async (params, ctx) => {
81
94
  const knowledgeService = ctx.container.get('knowledgeService');
@@ -103,7 +116,11 @@ export const submitCandidate = {
103
116
  params._category = DIMENSION_DISPLAY_GROUP[dimMeta.id] || dimMeta.id;
104
117
 
105
118
  // ── CandidateGuardrail 质量验证 ──
106
- const guardrail = new CandidateGuardrail(ctx._submittedTitles || new Set(), dimMeta, ctx._submittedPatterns || new Set());
119
+ const guardrail = new CandidateGuardrail(
120
+ ctx._submittedTitles || new Set(),
121
+ dimMeta,
122
+ ctx._submittedPatterns || new Set()
123
+ );
107
124
  const guardResult = guardrail.validate(params);
108
125
  if (!guardResult.valid) {
109
126
  ctx.logger?.info(`[submit_knowledge] ✗ guardrail rejected: ${guardResult.error}`);
@@ -646,24 +646,21 @@ const SUMMARY_EXTRACTORS = {
646
646
  },
647
647
  go: {
648
648
  imports: /^\s*(?:import\s+"[^"]+"|import\s+\w+\s+"[^"]+")/gm,
649
- declarations:
650
- /^\s*(?:type\s+\w+\s+(?:struct|interface|func)\b.*)/gm,
651
- methods:
652
- /^\s*func\s+(?:\(\s*\w+\s+\*?\w+\s*\)\s+)?\w+\s*\([^)]*\)[^{]*/gm,
649
+ declarations: /^\s*(?:type\s+\w+\s+(?:struct|interface|func)\b.*)/gm,
650
+ methods: /^\s*func\s+(?:\(\s*\w+\s+\*?\w+\s*\)\s+)?\w+\s*\([^)]*\)[^{]*/gm,
653
651
  },
654
652
  java: {
655
653
  imports: /^\s*import\s+(?:static\s+)?[\w.]+\*?;/gm,
656
654
  declarations:
657
655
  /^\s*(?:public|private|protected)?\s*(?:abstract|final|static)?\s*(?:class|interface|enum|record|@interface)\s+\w+/gm,
658
656
  methods:
659
- /^\s*(?:public|private|protected)?\s*(?:abstract|static|final|synchronized|default)?\s*(?:<[^>]+>\s+)?\w[\w<>\[\],\s]*\s+\w+\s*\([^)]*\)/gm,
657
+ /^\s*(?:public|private|protected)?\s*(?:abstract|static|final|synchronized|default)?\s*(?:<[^>]+>\s+)?\w[\w<>[\],\s]*\s+\w+\s*\([^)]*\)/gm,
660
658
  },
661
659
  kotlin: {
662
660
  imports: /^\s*import\s+[\w.]+/gm,
663
661
  declarations:
664
662
  /^\s*(?:open|abstract|data|sealed|inner|value|inline)?\s*(?:class|interface|object|enum\s+class|fun\s+interface)\s+\w+/gm,
665
- methods:
666
- /^\s*(?:override\s+)?(?:suspend\s+)?(?:fun|val|var)\s+(?:<[^>]+>\s+)?\w+/gm,
663
+ methods: /^\s*(?:override\s+)?(?:suspend\s+)?(?:fun|val|var)\s+(?:<[^>]+>\s+)?\w+/gm,
667
664
  },
668
665
  dart: {
669
666
  imports: /^\s*import\s+['"][^'"]+['"];?/gm,
@@ -671,8 +668,7 @@ const SUMMARY_EXTRACTORS = {
671
668
  /^\s*(?:abstract\s+|sealed\s+)?(?:class|mixin|extension|enum|typedef)\s+\w+[^{]*/gm,
672
669
  methods:
673
670
  /^\s*(?:@override\s+)?(?:static\s+)?(?:Future|Stream|void|\w[\w<>?]*)?\s+\w+\s*\([^)]*\)/gm,
674
- properties:
675
- /^\s*(?:static\s+)?(?:final\s+|late\s+|const\s+)?(?:\w[\w<>?]*)\s+\w+\s*[;=]/gm,
671
+ properties: /^\s*(?:static\s+)?(?:final\s+|late\s+|const\s+)?(?:\w[\w<>?]*)\s+\w+\s*[;=]/gm,
676
672
  },
677
673
  };
678
674
  SUMMARY_EXTRACTORS['objectivec++'] = SUMMARY_EXTRACTORS.objectivec;
@@ -15,5 +15,4 @@
15
15
  * 本文件仅做 re-export,保持向后兼容。
16
16
  */
17
17
 
18
- export { ALL_TOOLS } from './tools/index.js';
19
- export { default } from './tools/index.js';
18
+ export { ALL_TOOLS, default } from './tools/index.js';