autosnippet 3.0.0 → 3.0.2

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 (290) hide show
  1. package/README.md +230 -324
  2. package/bin/api-server.js +1 -1
  3. package/bin/cli.js +204 -244
  4. package/bin/mcp-server.js +5 -3
  5. package/config/knowledge-base.config.js +132 -132
  6. package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
  7. package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
  8. package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
  9. package/dashboard/dist/index.html +3 -3
  10. package/lib/bootstrap.js +8 -8
  11. package/lib/cli/AiScanService.js +86 -40
  12. package/lib/cli/KnowledgeSyncService.js +113 -74
  13. package/lib/cli/SetupService.js +439 -277
  14. package/lib/cli/UpgradeService.js +63 -100
  15. package/lib/core/AstAnalyzer.js +276 -597
  16. package/lib/core/ast/ProjectGraph.js +101 -40
  17. package/lib/core/ast/ensure-grammars.js +232 -0
  18. package/lib/core/ast/index.js +115 -0
  19. package/lib/core/ast/lang-dart.js +661 -0
  20. package/lib/core/ast/lang-go.js +530 -0
  21. package/lib/core/ast/lang-java.js +435 -0
  22. package/lib/core/ast/lang-javascript.js +272 -0
  23. package/lib/core/ast/lang-kotlin.js +423 -0
  24. package/lib/core/ast/lang-objc.js +388 -0
  25. package/lib/core/ast/lang-python.js +371 -0
  26. package/lib/core/ast/lang-swift.js +337 -0
  27. package/lib/core/ast/lang-typescript.js +503 -0
  28. package/lib/core/capability/CapabilityProbe.js +18 -9
  29. package/lib/core/constitution/Constitution.js +2 -3
  30. package/lib/core/constitution/ConstitutionValidator.js +65 -24
  31. package/lib/core/discovery/DartDiscoverer.js +534 -0
  32. package/lib/core/discovery/DiscovererRegistry.js +83 -0
  33. package/lib/core/discovery/GenericDiscoverer.js +225 -0
  34. package/lib/core/discovery/GoDiscoverer.js +541 -0
  35. package/lib/core/discovery/JvmDiscoverer.js +506 -0
  36. package/lib/core/discovery/NodeDiscoverer.js +466 -0
  37. package/lib/core/discovery/ProjectDiscoverer.js +93 -0
  38. package/lib/core/discovery/PythonDiscoverer.js +338 -0
  39. package/lib/core/discovery/SpmDiscoverer.js +5 -0
  40. package/lib/core/discovery/index.js +53 -0
  41. package/lib/core/enhancement/EnhancementPack.js +71 -0
  42. package/lib/core/enhancement/EnhancementRegistry.js +47 -0
  43. package/lib/core/enhancement/android-enhancement.js +102 -0
  44. package/lib/core/enhancement/django-enhancement.js +70 -0
  45. package/lib/core/enhancement/fastapi-enhancement.js +63 -0
  46. package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
  47. package/lib/core/enhancement/go-web-enhancement.js +201 -0
  48. package/lib/core/enhancement/index.js +65 -0
  49. package/lib/core/enhancement/node-server-enhancement.js +88 -0
  50. package/lib/core/enhancement/react-enhancement.js +86 -0
  51. package/lib/core/enhancement/spring-enhancement.js +112 -0
  52. package/lib/core/enhancement/vue-enhancement.js +96 -0
  53. package/lib/core/gateway/Gateway.js +8 -9
  54. package/lib/core/gateway/GatewayActionRegistry.js +1 -1
  55. package/lib/core/permission/PermissionManager.js +12 -8
  56. package/lib/domain/index.js +13 -9
  57. package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
  58. package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
  59. package/lib/domain/knowledge/Lifecycle.js +22 -22
  60. package/lib/domain/knowledge/index.js +9 -12
  61. package/lib/domain/knowledge/values/Constraints.js +31 -21
  62. package/lib/domain/knowledge/values/Content.js +21 -13
  63. package/lib/domain/knowledge/values/Quality.js +31 -18
  64. package/lib/domain/knowledge/values/Reasoning.js +20 -12
  65. package/lib/domain/knowledge/values/Relations.js +37 -25
  66. package/lib/domain/knowledge/values/Stats.js +18 -12
  67. package/lib/domain/knowledge/values/index.js +4 -3
  68. package/lib/domain/snippet/Snippet.js +35 -10
  69. package/lib/external/ai/AiFactory.js +48 -16
  70. package/lib/external/ai/AiProvider.js +184 -90
  71. package/lib/external/ai/providers/ClaudeProvider.js +25 -12
  72. package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
  73. package/lib/external/ai/providers/MockProvider.js +9 -3
  74. package/lib/external/ai/providers/OpenAiProvider.js +51 -29
  75. package/lib/external/mcp/McpServer.js +66 -36
  76. package/lib/external/mcp/errorHandler.js +23 -11
  77. package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
  78. package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
  79. package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
  80. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
  81. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
  82. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
  83. package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
  84. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
  85. package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
  86. package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
  87. package/lib/external/mcp/handlers/bootstrap.js +691 -168
  88. package/lib/external/mcp/handlers/browse.js +66 -22
  89. package/lib/external/mcp/handlers/candidate.js +118 -35
  90. package/lib/external/mcp/handlers/consolidated.js +49 -17
  91. package/lib/external/mcp/handlers/guard.js +104 -39
  92. package/lib/external/mcp/handlers/knowledge.js +60 -36
  93. package/lib/external/mcp/handlers/search.js +43 -14
  94. package/lib/external/mcp/handlers/skill.js +120 -45
  95. package/lib/external/mcp/handlers/structure.js +240 -86
  96. package/lib/external/mcp/handlers/system.js +42 -12
  97. package/lib/external/mcp/handlers/wiki.js +58 -33
  98. package/lib/external/mcp/tools.js +306 -123
  99. package/lib/http/HttpServer.js +72 -47
  100. package/lib/http/middleware/RateLimiter.js +5 -3
  101. package/lib/http/middleware/errorHandler.js +6 -1
  102. package/lib/http/middleware/requestLogger.js +14 -3
  103. package/lib/http/middleware/roleResolver.js +30 -23
  104. package/lib/http/routes/ai.js +387 -265
  105. package/lib/http/routes/auth.js +81 -61
  106. package/lib/http/routes/candidates.js +430 -320
  107. package/lib/http/routes/commands.js +289 -189
  108. package/lib/http/routes/extract.js +158 -125
  109. package/lib/http/routes/guardRules.js +309 -217
  110. package/lib/http/routes/knowledge.js +213 -154
  111. package/lib/http/routes/modules.js +578 -0
  112. package/lib/http/routes/monitoring.js +6 -6
  113. package/lib/http/routes/recipes.js +104 -93
  114. package/lib/http/routes/search.js +361 -305
  115. package/lib/http/routes/skills.js +145 -98
  116. package/lib/http/routes/snippets.js +42 -30
  117. package/lib/http/routes/spm.js +3 -405
  118. package/lib/http/routes/violations.js +113 -93
  119. package/lib/http/routes/wiki.js +211 -170
  120. package/lib/http/utils/routeHelpers.js +3 -1
  121. package/lib/http/utils/sse-sessions.js +16 -6
  122. package/lib/http/utils/sse.js +15 -5
  123. package/lib/infrastructure/audit/AuditLogger.js +5 -2
  124. package/lib/infrastructure/audit/AuditStore.js +10 -7
  125. package/lib/infrastructure/cache/CacheService.js +3 -1
  126. package/lib/infrastructure/cache/GraphCache.js +8 -4
  127. package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
  128. package/lib/infrastructure/config/ConfigLoader.js +9 -5
  129. package/lib/infrastructure/config/Defaults.js +30 -10
  130. package/lib/infrastructure/config/Paths.js +28 -8
  131. package/lib/infrastructure/config/TriggerSymbol.js +22 -10
  132. package/lib/infrastructure/database/DatabaseConnection.js +15 -10
  133. package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
  134. package/lib/infrastructure/external/ClipboardManager.js +6 -2
  135. package/lib/infrastructure/external/NativeUi.js +50 -43
  136. package/lib/infrastructure/external/OpenBrowser.js +14 -17
  137. package/lib/infrastructure/external/XcodeAutomation.js +14 -258
  138. package/lib/infrastructure/logging/Logger.js +46 -30
  139. package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
  140. package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
  141. package/lib/infrastructure/paths/HeaderResolver.js +25 -9
  142. package/lib/infrastructure/paths/PathFinder.js +34 -12
  143. package/lib/infrastructure/plugin/PluginManager.js +26 -8
  144. package/lib/infrastructure/realtime/RealtimeService.js +2 -2
  145. package/lib/infrastructure/vector/Chunker.js +22 -7
  146. package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
  147. package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
  148. package/lib/infrastructure/vector/VectorStore.js +28 -10
  149. package/lib/injection/ServiceContainer.js +247 -93
  150. package/lib/platform/ios/index.js +63 -0
  151. package/lib/platform/ios/routes/spm.js +437 -0
  152. package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
  153. package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
  154. package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
  155. package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
  156. package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
  157. package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
  158. package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
  159. package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
  160. package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
  161. package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
  162. package/lib/repository/base/BaseRepository.js +7 -9
  163. package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
  164. package/lib/repository/token/TokenUsageStore.js +4 -2
  165. package/lib/service/automation/ActionPipeline.js +1 -1
  166. package/lib/service/automation/AutomationOrchestrator.js +8 -4
  167. package/lib/service/automation/ContextCollector.js +7 -5
  168. package/lib/service/automation/DirectiveDetector.js +23 -16
  169. package/lib/service/automation/FileWatcher.js +112 -56
  170. package/lib/service/automation/TriggerResolver.js +6 -4
  171. package/lib/service/automation/handlers/AlinkHandler.js +24 -12
  172. package/lib/service/automation/handlers/CreateHandler.js +19 -20
  173. package/lib/service/automation/handlers/DraftHandler.js +14 -8
  174. package/lib/service/automation/handlers/GuardHandler.js +93 -63
  175. package/lib/service/automation/handlers/HeaderHandler.js +1 -6
  176. package/lib/service/automation/handlers/SearchHandler.js +155 -88
  177. package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
  178. package/lib/service/candidate/SimilarityService.js +25 -9
  179. package/lib/service/chat/AnalystAgent.js +50 -24
  180. package/lib/service/chat/CandidateGuardrail.js +143 -17
  181. package/lib/service/chat/ChatAgent.js +759 -243
  182. package/lib/service/chat/ContextWindow.js +116 -71
  183. package/lib/service/chat/ConversationStore.js +77 -36
  184. package/lib/service/chat/EpisodicConsolidator.js +47 -23
  185. package/lib/service/chat/HandoffProtocol.js +98 -22
  186. package/lib/service/chat/Memory.js +34 -14
  187. package/lib/service/chat/ProducerAgent.js +40 -20
  188. package/lib/service/chat/ProjectSemanticMemory.js +109 -78
  189. package/lib/service/chat/ReasoningLayer.js +148 -70
  190. package/lib/service/chat/ReasoningTrace.js +44 -32
  191. package/lib/service/chat/TaskPipeline.js +39 -19
  192. package/lib/service/chat/ToolRegistry.js +48 -29
  193. package/lib/service/chat/WorkingMemory.js +44 -18
  194. package/lib/service/chat/tools.js +1096 -494
  195. package/lib/service/context/RecipeExtractor.js +132 -51
  196. package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
  197. package/lib/service/cursor/KnowledgeCompressor.js +25 -22
  198. package/lib/service/cursor/RulesGenerator.js +13 -7
  199. package/lib/service/cursor/SkillsSyncer.js +77 -27
  200. package/lib/service/cursor/TokenBudget.js +2 -2
  201. package/lib/service/cursor/TopicClassifier.js +54 -20
  202. package/lib/service/guard/ComplianceReporter.js +55 -43
  203. package/lib/service/guard/ExclusionManager.js +67 -29
  204. package/lib/service/guard/GuardCheckEngine.js +381 -86
  205. package/lib/service/guard/GuardFeedbackLoop.js +22 -10
  206. package/lib/service/guard/GuardService.js +29 -19
  207. package/lib/service/guard/RuleLearner.js +55 -23
  208. package/lib/service/guard/SourceFileCollector.js +27 -20
  209. package/lib/service/guard/ViolationsStore.js +43 -38
  210. package/lib/service/knowledge/CodeEntityGraph.js +147 -82
  211. package/lib/service/knowledge/ConfidenceRouter.js +12 -10
  212. package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
  213. package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
  214. package/lib/service/knowledge/KnowledgeService.js +222 -112
  215. package/lib/service/module/ModuleService.js +969 -0
  216. package/lib/service/quality/FeedbackCollector.js +27 -15
  217. package/lib/service/quality/QualityScorer.js +78 -24
  218. package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
  219. package/lib/service/recipe/RecipeParser.js +78 -45
  220. package/lib/service/search/CoarseRanker.js +43 -28
  221. package/lib/service/search/CrossEncoderReranker.js +32 -21
  222. package/lib/service/search/InvertedIndex.js +21 -7
  223. package/lib/service/search/MultiSignalRanker.js +90 -28
  224. package/lib/service/search/RetrievalFunnel.js +45 -24
  225. package/lib/service/search/SearchEngine.js +255 -103
  226. package/lib/service/skills/EventAggregator.js +32 -15
  227. package/lib/service/skills/SignalCollector.js +140 -64
  228. package/lib/service/skills/SkillAdvisor.js +79 -42
  229. package/lib/service/skills/SkillHooks.js +16 -14
  230. package/lib/service/snippet/PlaceholderConverter.js +5 -0
  231. package/lib/service/snippet/SnippetFactory.js +116 -99
  232. package/lib/service/snippet/SnippetInstaller.js +234 -62
  233. package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
  234. package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
  235. package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
  236. package/lib/service/wiki/WikiGenerator.js +637 -263
  237. package/lib/shared/DimensionCopyRegistry.js +472 -0
  238. package/lib/shared/LanguageService.js +399 -0
  239. package/lib/shared/PathGuard.js +45 -28
  240. package/lib/shared/RecipeReadinessChecker.js +72 -12
  241. package/lib/shared/constants.js +41 -41
  242. package/lib/shared/errors/BaseError.js +2 -2
  243. package/lib/shared/errors/index.js +4 -4
  244. package/lib/shared/similarity.js +25 -8
  245. package/lib/shared/token-utils.js +6 -2
  246. package/lib/shared/utils/common.js +12 -4
  247. package/package.json +49 -13
  248. package/scripts/bench-real-projects.mjs +256 -0
  249. package/scripts/build-native-ui.js +30 -30
  250. package/scripts/clear-old-vector-index.js +5 -35
  251. package/scripts/clear-vector-cache.js +7 -37
  252. package/scripts/collect-test-project-stats.mjs +160 -0
  253. package/scripts/diagnose-mcp.js +41 -32
  254. package/scripts/ensure-parse-package.js +6 -9
  255. package/scripts/generate-recipe-drafts.js +116 -77
  256. package/scripts/init-db.js +3 -20
  257. package/scripts/init-snippets.js +305 -0
  258. package/scripts/init-vector-db.js +173 -170
  259. package/scripts/install-cursor-skill.js +148 -104
  260. package/scripts/install-full.js +8 -21
  261. package/scripts/install-vscode-copilot.js +146 -145
  262. package/scripts/migrate-md-to-knowledge.mjs +139 -151
  263. package/scripts/postinstall-safe.js +5 -17
  264. package/scripts/recipe-audit.js +106 -82
  265. package/scripts/release.js +283 -323
  266. package/scripts/setup-mcp-config.js +60 -52
  267. package/scripts/verify-context-api.js +20 -20
  268. package/skills/autosnippet-analysis/SKILL.md +10 -6
  269. package/skills/autosnippet-candidates/SKILL.md +27 -26
  270. package/skills/autosnippet-coldstart/SKILL.md +555 -38
  271. package/skills/autosnippet-concepts/SKILL.md +349 -337
  272. package/skills/autosnippet-create/SKILL.md +5 -5
  273. package/skills/autosnippet-reference-dart/SKILL.md +543 -0
  274. package/skills/autosnippet-reference-go/SKILL.md +539 -0
  275. package/skills/autosnippet-reference-java/SKILL.md +534 -0
  276. package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
  277. package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
  278. package/skills/autosnippet-reference-objc/SKILL.md +29 -6
  279. package/skills/autosnippet-reference-python/SKILL.md +800 -0
  280. package/skills/autosnippet-reference-swift/SKILL.md +70 -14
  281. package/skills/autosnippet-structure/SKILL.md +4 -4
  282. package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
  283. package/templates/recipes-setup/README.md +2 -2
  284. package/templates/recipes-setup/_template.md +1 -1
  285. package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
  286. package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
  287. package/resources/asd-entry/main.swift +0 -159
  288. package/scripts/build-asd-entry.js +0 -51
  289. package/scripts/init-xcode-snippets.js +0 -311
  290. package/template.json +0 -39
@@ -65,10 +65,14 @@ export class TaskPipeline {
65
65
  // ─── 公共 API ─────────────────────────────────────────
66
66
 
67
67
  /** 管线 ID */
68
- get id() { return this.#id; }
68
+ get id() {
69
+ return this.#id;
70
+ }
69
71
 
70
72
  /** 步骤数 */
71
- get size() { return this.#steps.length; }
73
+ get size() {
74
+ return this.#steps.length;
75
+ }
72
76
 
73
77
  /**
74
78
  * 执行管线
@@ -97,12 +101,12 @@ export class TaskPipeline {
97
101
  // 拓扑排序 → 按层并行
98
102
  const phases = this.#topologicalSort();
99
103
 
100
- this.#logger.info(`[TaskPipeline] "${this.#id}" start — ${this.#steps.length} steps, ${phases.length} phases`);
104
+ this.#logger.info(
105
+ `[TaskPipeline] "${this.#id}" start — ${this.#steps.length} steps, ${phases.length} phases`
106
+ );
101
107
 
102
108
  for (const phase of phases) {
103
- const promises = phase.map(stepName =>
104
- this.#executeStep(stepName, executor, ctx, trace),
105
- );
109
+ const promises = phase.map((stepName) => this.#executeStep(stepName, executor, ctx, trace));
106
110
  const results = await Promise.allSettled(promises);
107
111
 
108
112
  // 检查是否有 fail 策略的步骤失败
@@ -137,7 +141,7 @@ export class TaskPipeline {
137
141
  * 执行单个步骤(含 when 判断、重试、erorrStrategy)
138
142
  */
139
143
  async #executeStep(stepName, executor, ctx, trace) {
140
- const step = this.#steps.find(s => s.name === stepName);
144
+ const step = this.#steps.find((s) => s.name === stepName);
141
145
  const t0 = Date.now();
142
146
 
143
147
  // ── when 条件 ──
@@ -172,14 +176,20 @@ export class TaskPipeline {
172
176
  } catch (err) {
173
177
  lastError = err;
174
178
  if (attempt < maxAttempts && step.retryDelay) {
175
- await new Promise(r => setTimeout(r, step.retryDelay));
179
+ await new Promise((r) => setTimeout(r, step.retryDelay));
176
180
  }
177
181
  }
178
182
  }
179
183
 
180
184
  // ── 全部重试失败 ──
181
185
  const errorMsg = lastError?.message || 'unknown error';
182
- trace.push({ step: stepName, status: 'failed', durationMs: Date.now() - t0, error: errorMsg, attempts: maxAttempts });
186
+ trace.push({
187
+ step: stepName,
188
+ status: 'failed',
189
+ durationMs: Date.now() - t0,
190
+ error: errorMsg,
191
+ attempts: maxAttempts,
192
+ });
183
193
  ctx._results[stepName] = { _error: errorMsg };
184
194
 
185
195
  if ((step.errorStrategy || 'fail') === 'fail') {
@@ -227,7 +237,9 @@ export class TaskPipeline {
227
237
  * 嵌套取值: 'a.b.c' → obj.a.b.c
228
238
  */
229
239
  #getNestedValue(obj, path) {
230
- if (obj == null) return undefined;
240
+ if (obj == null) {
241
+ return undefined;
242
+ }
231
243
  return path.split('.').reduce((acc, key) => acc?.[key], obj);
232
244
  }
233
245
 
@@ -247,12 +259,14 @@ export class TaskPipeline {
247
259
  const sorted = [];
248
260
 
249
261
  const visit = (name) => {
250
- if (visited.has(name)) return;
262
+ if (visited.has(name)) {
263
+ return;
264
+ }
251
265
  if (visiting.has(name)) {
252
266
  throw new Error(`[TaskPipeline] Circular dependency: ${name}`);
253
267
  }
254
268
  visiting.add(name);
255
- for (const dep of (graph.get(name) || [])) {
269
+ for (const dep of graph.get(name) || []) {
256
270
  visit(dep);
257
271
  }
258
272
  visiting.delete(name);
@@ -268,7 +282,7 @@ export class TaskPipeline {
268
282
  const depth = new Map();
269
283
  for (const name of sorted) {
270
284
  const deps = graph.get(name) || [];
271
- const d = deps.length === 0 ? 0 : Math.max(...deps.map(dep => (depth.get(dep) || 0) + 1));
285
+ const d = deps.length === 0 ? 0 : Math.max(...deps.map((dep) => (depth.get(dep) || 0) + 1));
272
286
  depth.set(name, d);
273
287
  }
274
288
 
@@ -278,7 +292,7 @@ export class TaskPipeline {
278
292
  phases[d].push(name);
279
293
  }
280
294
 
281
- return phases.filter(p => p.length > 0);
295
+ return phases.filter((p) => p.length > 0);
282
296
  }
283
297
 
284
298
  /**
@@ -287,14 +301,20 @@ export class TaskPipeline {
287
301
  #validate() {
288
302
  const names = new Set();
289
303
  for (const step of this.#steps) {
290
- if (!step.name) throw new Error('[TaskPipeline] Step must have a name');
291
- if (!step.tool) throw new Error(`[TaskPipeline] Step "${step.name}" must have a tool`);
292
- if (names.has(step.name)) throw new Error(`[TaskPipeline] Duplicate step name: "${step.name}"`);
304
+ if (!step.name) {
305
+ throw new Error('[TaskPipeline] Step must have a name');
306
+ }
307
+ if (!step.tool) {
308
+ throw new Error(`[TaskPipeline] Step "${step.name}" must have a tool`);
309
+ }
310
+ if (names.has(step.name)) {
311
+ throw new Error(`[TaskPipeline] Duplicate step name: "${step.name}"`);
312
+ }
293
313
  names.add(step.name);
294
314
  }
295
315
  // 检查 dependsOn 引用是否存在
296
316
  for (const step of this.#steps) {
297
- for (const dep of (step.dependsOn || [])) {
317
+ for (const dep of step.dependsOn || []) {
298
318
  if (!names.has(dep)) {
299
319
  throw new Error(`[TaskPipeline] Step "${step.name}" depends on unknown step "${dep}"`);
300
320
  }
@@ -309,7 +329,7 @@ export class TaskPipeline {
309
329
  const phases = this.#topologicalSort();
310
330
  return {
311
331
  id: this.#id,
312
- steps: this.#steps.map(s => ({
332
+ steps: this.#steps.map((s) => ({
313
333
  name: s.name,
314
334
  tool: s.tool,
315
335
  dependsOn: s.dependsOn || [],
@@ -18,30 +18,30 @@ import Logger from '../../infrastructure/logging/Logger.js';
18
18
  */
19
19
  const PARAM_ALIASES = {
20
20
  // read_project_file 变体
21
- file: 'filePath',
22
- filename: 'filePath',
23
- file_name: 'filePath',
24
- filepath: 'filePath',
25
- file_path: 'filePath',
26
- path: 'filePath',
21
+ file: 'filePath',
22
+ filename: 'filePath',
23
+ file_name: 'filePath',
24
+ filepath: 'filePath',
25
+ file_path: 'filePath',
26
+ path: 'filePath',
27
27
  // search_project_code 变体
28
- query: 'pattern',
29
- search: 'pattern',
30
- keyword: 'pattern',
31
- search_query: 'pattern',
32
- search_text: 'pattern',
33
- regex: 'pattern',
28
+ query: 'pattern',
29
+ search: 'pattern',
30
+ keyword: 'pattern',
31
+ search_query: 'pattern',
32
+ search_text: 'pattern',
33
+ regex: 'pattern',
34
34
  // 通用变体
35
- is_regex: 'isRegex',
36
- file_filter: 'fileFilter',
35
+ is_regex: 'isRegex',
36
+ file_filter: 'fileFilter',
37
37
  context_lines: 'contextLines',
38
- max_results: 'maxResults',
39
- start_line: 'startLine',
40
- end_line: 'endLine',
41
- max_lines: 'maxLines',
42
- candidate_id: 'candidateId',
43
- recipe_id: 'recipeId',
44
- skill_name: 'skillName',
38
+ max_results: 'maxResults',
39
+ start_line: 'startLine',
40
+ end_line: 'endLine',
41
+ max_lines: 'maxLines',
42
+ candidate_id: 'candidateId',
43
+ recipe_id: 'recipeId',
44
+ skill_name: 'skillName',
45
45
  };
46
46
 
47
47
  export class ToolRegistry {
@@ -62,7 +62,9 @@ export class ToolRegistry {
62
62
  */
63
63
  register(toolDef) {
64
64
  const { name, description, handler, parameters = {} } = toolDef;
65
- if (!name || !handler) throw new Error('Tool must have name and handler');
65
+ if (!name || !handler) {
66
+ throw new Error('Tool must have name and handler');
67
+ }
66
68
  this.#tools.set(name, { name, description, parameters, handler });
67
69
  }
68
70
 
@@ -71,7 +73,9 @@ export class ToolRegistry {
71
73
  * @param {Array<object>} defs
72
74
  */
73
75
  registerAll(defs) {
74
- for (const def of defs) this.register(def);
76
+ for (const def of defs) {
77
+ this.register(def);
78
+ }
75
79
  this.#logger.info(`[ToolRegistry] ${defs.length} tools registered`);
76
80
  }
77
81
 
@@ -83,7 +87,9 @@ export class ToolRegistry {
83
87
  getToolSchemas(allowedTools) {
84
88
  const schemas = [];
85
89
  for (const [name, tool] of this.#tools) {
86
- if (allowedTools && !allowedTools.includes(name)) continue;
90
+ if (allowedTools && !allowedTools.includes(name)) {
91
+ continue;
92
+ }
87
93
  schemas.push({
88
94
  name: tool.name,
89
95
  description: tool.description,
@@ -102,7 +108,9 @@ export class ToolRegistry {
102
108
  */
103
109
  async execute(name, params, context = {}) {
104
110
  const tool = this.#tools.get(name);
105
- if (!tool) throw new Error(`Tool '${name}' not found`);
111
+ if (!tool) {
112
+ throw new Error(`Tool '${name}' not found`);
113
+ }
106
114
 
107
115
  // 参数归一化: AI 可能用 snake_case / 不同命名传参,
108
116
  // 将其映射到 tool schema 中定义的 camelCase 参数名
@@ -113,7 +121,12 @@ export class ToolRegistry {
113
121
  const result = await tool.handler(normalized, context);
114
122
  return result;
115
123
  } catch (err) {
116
- this.#logger.error(`Tool '${name}' failed`, { error: err.message });
124
+ // API Key 缺失为配置问题,降为 info 级别
125
+ if (err.code === 'API_KEY_MISSING') {
126
+ this.#logger.info(`Tool '${name}' 跳过: ${err.message}`);
127
+ } else {
128
+ this.#logger.error(`Tool '${name}' failed`, { error: err.message });
129
+ }
117
130
  return { error: err.message };
118
131
  }
119
132
  }
@@ -130,10 +143,14 @@ export class ToolRegistry {
130
143
  * 3. 常用别名表兜底
131
144
  */
132
145
  #normalizeParams(params, schema) {
133
- if (!params || typeof params !== 'object') return params || {};
146
+ if (!params || typeof params !== 'object') {
147
+ return params || {};
148
+ }
134
149
  const properties = schema?.properties || {};
135
150
  const schemaKeys = new Set(Object.keys(properties));
136
- if (schemaKeys.size === 0) return params;
151
+ if (schemaKeys.size === 0) {
152
+ return params;
153
+ }
137
154
 
138
155
  const result = {};
139
156
  const unmatched = [];
@@ -165,7 +182,9 @@ export class ToolRegistry {
165
182
  }
166
183
 
167
184
  if (unmatched.length > 0) {
168
- this.#logger.debug(`[ToolRegistry] param normalization: unmatched keys [${unmatched.join(', ')}]`);
185
+ this.#logger.debug(
186
+ `[ToolRegistry] param normalization: unmatched keys [${unmatched.join(', ')}]`
187
+ );
169
188
  }
170
189
 
171
190
  return result;
@@ -22,7 +22,9 @@ import Logger from '../../infrastructure/logging/Logger.js';
22
22
  */
23
23
  const TOOL_COMPRESS_STRATEGIES = {
24
24
  search_project_code(result) {
25
- if (typeof result !== 'object') return String(result).substring(0, 600);
25
+ if (typeof result !== 'object') {
26
+ return String(result).substring(0, 600);
27
+ }
26
28
  const matches = result.matches || [];
27
29
  const batchResults = result.batchResults || {};
28
30
 
@@ -32,7 +34,9 @@ const TOOL_COMPRESS_STRATEGIES = {
32
34
  lines.push(`搜索到 ${matches.length} 个匹配`);
33
35
  const fileGroups = {};
34
36
  for (const m of matches) {
35
- if (!fileGroups[m.file]) fileGroups[m.file] = [];
37
+ if (!fileGroups[m.file]) {
38
+ fileGroups[m.file] = [];
39
+ }
36
40
  fileGroups[m.file].push(m.line);
37
41
  }
38
42
  for (const [file, lineNums] of Object.entries(fileGroups).slice(0, 8)) {
@@ -51,7 +55,9 @@ const TOOL_COMPRESS_STRATEGIES = {
51
55
  },
52
56
 
53
57
  read_project_file(result) {
54
- if (typeof result !== 'object') return String(result).substring(0, 600);
58
+ if (typeof result !== 'object') {
59
+ return String(result).substring(0, 600);
60
+ }
55
61
  // 批量读取结果
56
62
  if (result.files) {
57
63
  const lines = [`读取 ${result.files.length} 个文件`];
@@ -68,28 +74,44 @@ const TOOL_COMPRESS_STRATEGIES = {
68
74
  },
69
75
 
70
76
  get_class_info(result) {
71
- if (typeof result !== 'object') return String(result).substring(0, 600);
77
+ if (typeof result !== 'object') {
78
+ return String(result).substring(0, 600);
79
+ }
72
80
  const lines = [`类 ${result.className || '?'}`];
73
- if (result.superClass) lines.push(` 继承: ${result.superClass}`);
74
- if (result.protocols?.length) lines.push(` 协议: ${result.protocols.join(', ')}`);
75
- if (result.methods?.length) lines.push(` 方法数: ${result.methods.length}`);
76
- if (result.properties?.length) lines.push(` 属性数: ${result.properties.length}`);
81
+ if (result.superClass) {
82
+ lines.push(` 继承: ${result.superClass}`);
83
+ }
84
+ if (result.protocols?.length) {
85
+ lines.push(` 协议: ${result.protocols.join(', ')}`);
86
+ }
87
+ if (result.methods?.length) {
88
+ lines.push(` 方法数: ${result.methods.length}`);
89
+ }
90
+ if (result.properties?.length) {
91
+ lines.push(` 属性数: ${result.properties.length}`);
92
+ }
77
93
  return lines.join('\n');
78
94
  },
79
95
 
80
96
  get_class_hierarchy(result) {
81
- if (typeof result !== 'object') return String(result).substring(0, 600);
97
+ if (typeof result !== 'object') {
98
+ return String(result).substring(0, 600);
99
+ }
82
100
  const classes = result.classes || result.hierarchy || [];
83
101
  return `类层级: ${Array.isArray(classes) ? classes.length : 0} 个类`;
84
102
  },
85
103
 
86
104
  get_project_overview(result) {
87
- if (typeof result !== 'object') return String(result).substring(0, 800);
105
+ if (typeof result !== 'object') {
106
+ return String(result).substring(0, 800);
107
+ }
88
108
  return JSON.stringify(result).substring(0, 800);
89
109
  },
90
110
 
91
111
  list_project_structure(result) {
92
- if (typeof result !== 'object') return String(result).substring(0, 600);
112
+ if (typeof result !== 'object') {
113
+ return String(result).substring(0, 600);
114
+ }
93
115
  const entries = result.entries || result.children || [];
94
116
  return `目录结构: ${Array.isArray(entries) ? entries.length : 0} 个条目`;
95
117
  },
@@ -100,8 +122,10 @@ const TOOL_COMPRESS_STRATEGIES = {
100
122
  */
101
123
  function defaultCompress(result, maxChars = 600) {
102
124
  const str = typeof result === 'string' ? result : JSON.stringify(result);
103
- if (str.length <= maxChars) return str;
104
- return str.substring(0, maxChars) + '…(truncated)';
125
+ if (str.length <= maxChars) {
126
+ return str;
127
+ }
128
+ return `${str.substring(0, maxChars)}…(truncated)`;
105
129
  }
106
130
 
107
131
  export class WorkingMemory {
@@ -205,7 +229,9 @@ export class WorkingMemory {
205
229
  for (const f of sorted) {
206
230
  const badge = f.importance >= 8 ? '⚠️' : f.importance >= 5 ? '📋' : '💡';
207
231
  let line = `- ${badge} [${f.importance}/10] ${f.finding}`;
208
- if (f.evidence) line += ` (${f.evidence})`;
232
+ if (f.evidence) {
233
+ line += ` (${f.evidence})`;
234
+ }
209
235
  parts.push(line);
210
236
  }
211
237
  }
@@ -242,13 +268,13 @@ export class WorkingMemory {
242
268
  */
243
269
  distill() {
244
270
  return {
245
- keyFindings: this.#scratchpad.map(f => ({
271
+ keyFindings: this.#scratchpad.map((f) => ({
246
272
  finding: f.finding,
247
273
  evidence: f.evidence,
248
274
  importance: f.importance,
249
275
  })),
250
- toolCallSummary: this.#compressedObservations.map(s =>
251
- `[${s.toolName}] ${s.summary.substring(0, 150)}`
276
+ toolCallSummary: this.#compressedObservations.map(
277
+ (s) => `[${s.toolName}] ${s.summary.substring(0, 150)}`
252
278
  ),
253
279
  totalObservations: this.#totalObservations,
254
280
  compressedCount: this.#compressedObservations.length,
@@ -280,7 +306,7 @@ export class WorkingMemory {
280
306
  */
281
307
  getHighPriorityFindings(minImportance = 7) {
282
308
  return this.#scratchpad
283
- .filter(f => f.importance >= minImportance)
309
+ .filter((f) => f.importance >= minImportance)
284
310
  .sort((a, b) => b.importance - a.importance);
285
311
  }
286
312