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
@@ -85,14 +85,16 @@ export class CodeEntityGraph {
85
85
  * @returns {GraphPopulateResult}
86
86
  */
87
87
  populateFromAst(astSummary) {
88
- if (!astSummary) return { entitiesUpserted: 0, edgesCreated: 0, durationMs: 0 };
88
+ if (!astSummary) {
89
+ return { entitiesUpserted: 0, edgesCreated: 0, durationMs: 0 };
90
+ }
89
91
  const t0 = Date.now();
90
92
  let entities = 0;
91
93
  let edges = 0;
92
94
 
93
95
  const run = this.db.transaction(() => {
94
96
  // ── 类 ──
95
- for (const cls of (astSummary.classes || [])) {
97
+ for (const cls of astSummary.classes || []) {
96
98
  this.#upsertEntity({
97
99
  entityId: cls.name,
98
100
  entityType: cls.isCategory ? 'category' : 'class',
@@ -110,7 +112,7 @@ export class CodeEntityGraph {
110
112
  }
111
113
 
112
114
  // ── 协议 ──
113
- for (const proto of (astSummary.protocols || [])) {
115
+ for (const proto of astSummary.protocols || []) {
114
116
  this.#upsertEntity({
115
117
  entityId: proto.name,
116
118
  entityType: 'protocol',
@@ -126,7 +128,7 @@ export class CodeEntityGraph {
126
128
  }
127
129
 
128
130
  // ── Category ──
129
- for (const cat of (astSummary.categories || [])) {
131
+ for (const cat of astSummary.categories || []) {
130
132
  const catId = `${cat.className}(${cat.categoryName})`;
131
133
  this.#upsertEntity({
132
134
  entityId: catId,
@@ -145,7 +147,7 @@ export class CodeEntityGraph {
145
147
  }
146
148
 
147
149
  // ── 继承/遵循/扩展 边 (从 AST inheritanceGraph) ──
148
- for (const edge of (astSummary.inheritanceGraph || [])) {
150
+ for (const edge of astSummary.inheritanceGraph || []) {
149
151
  const fromType = this.#inferEntityType(edge.from, astSummary);
150
152
  const toType = this.#inferEntityType(edge.to, astSummary);
151
153
  this.#addEdge(edge.from, fromType, edge.to, toType, edge.type, {
@@ -187,7 +189,9 @@ export class CodeEntityGraph {
187
189
  run();
188
190
 
189
191
  const result = { entitiesUpserted: entities, edgesCreated: edges, durationMs: Date.now() - t0 };
190
- this.log.info(`[CodeEntityGraph] AST populate: ${entities} entities, ${edges} edges (${result.durationMs}ms)`);
192
+ this.log.info(
193
+ `[CodeEntityGraph] AST populate: ${entities} entities, ${edges} edges (${result.durationMs}ms)`
194
+ );
191
195
  return result;
192
196
  }
193
197
 
@@ -201,12 +205,14 @@ export class CodeEntityGraph {
201
205
  * @returns {GraphPopulateResult}
202
206
  */
203
207
  populateFromSpm(depGraphData) {
204
- if (!depGraphData) return { entitiesUpserted: 0, edgesCreated: 0, durationMs: 0 };
208
+ if (!depGraphData) {
209
+ return { entitiesUpserted: 0, edgesCreated: 0, durationMs: 0 };
210
+ }
205
211
  const t0 = Date.now();
206
212
  let entities = 0;
207
213
 
208
214
  const run = this.db.transaction(() => {
209
- for (const node of (depGraphData.nodes || [])) {
215
+ for (const node of depGraphData.nodes || []) {
210
216
  this.#upsertEntity({
211
217
  entityId: node.id || node.label || node,
212
218
  entityType: 'module',
@@ -222,7 +228,9 @@ export class CodeEntityGraph {
222
228
  run();
223
229
 
224
230
  const result = { entitiesUpserted: entities, edgesCreated: 0, durationMs: Date.now() - t0 };
225
- this.log.info(`[CodeEntityGraph] SPM populate: ${entities} module entities (${result.durationMs}ms)`);
231
+ this.log.info(
232
+ `[CodeEntityGraph] SPM populate: ${entities} module entities (${result.durationMs}ms)`
233
+ );
226
234
  return result;
227
235
  }
228
236
 
@@ -233,14 +241,18 @@ export class CodeEntityGraph {
233
241
  * @returns {GraphPopulateResult}
234
242
  */
235
243
  populateFromCandidateRelations(candidates) {
236
- if (!candidates?.length) return { entitiesUpserted: 0, edgesCreated: 0, durationMs: 0 };
244
+ if (!candidates?.length) {
245
+ return { entitiesUpserted: 0, edgesCreated: 0, durationMs: 0 };
246
+ }
237
247
  const t0 = Date.now();
238
248
  let edges = 0;
239
249
 
240
250
  const run = this.db.transaction(() => {
241
251
  for (const candidate of candidates) {
242
252
  const title = candidate.title || candidate.id || '';
243
- if (!title) continue;
253
+ if (!title) {
254
+ continue;
255
+ }
244
256
 
245
257
  // 处理 Relations 对象或扁平数组
246
258
  let flatRelations;
@@ -252,7 +264,7 @@ export class CodeEntityGraph {
252
264
  // 桶结构 → 扁平
253
265
  flatRelations = [];
254
266
  for (const [type, list] of Object.entries(candidate.relations)) {
255
- for (const r of (Array.isArray(list) ? list : [])) {
267
+ for (const r of Array.isArray(list) ? list : []) {
256
268
  flatRelations.push({ type, target: r.target, description: r.description });
257
269
  }
258
270
  }
@@ -261,7 +273,9 @@ export class CodeEntityGraph {
261
273
  }
262
274
 
263
275
  for (const rel of flatRelations) {
264
- if (!rel.target) continue;
276
+ if (!rel.target) {
277
+ continue;
278
+ }
265
279
  // 映射关系类型到边类型
266
280
  const relation = this.#mapRelationType(rel.type);
267
281
  this.#addEdge(title, 'recipe', rel.target, 'recipe', relation, {
@@ -296,9 +310,9 @@ export class CodeEntityGraph {
296
310
  if (entityType) {
297
311
  row = this.stmts.getEntity.get(entityId, entityType, this.projectRoot);
298
312
  } else {
299
- row = this.db.prepare(
300
- `SELECT * FROM code_entities WHERE entity_id = ? AND project_root = ? LIMIT 1`
301
- ).get(entityId, this.projectRoot);
313
+ row = this.db
314
+ .prepare(`SELECT * FROM code_entities WHERE entity_id = ? AND project_root = ? LIMIT 1`)
315
+ .get(entityId, this.projectRoot);
302
316
  }
303
317
  return row ? this.#mapEntity(row) : null;
304
318
  }
@@ -311,7 +325,7 @@ export class CodeEntityGraph {
311
325
  */
312
326
  listEntities(entityType, limit = 200) {
313
327
  const rows = this.stmts.listByType.all(entityType, this.projectRoot, limit);
314
- return rows.map(r => this.#mapEntity(r));
328
+ return rows.map((r) => this.#mapEntity(r));
315
329
  }
316
330
 
317
331
  /**
@@ -332,7 +346,10 @@ export class CodeEntityGraph {
332
346
  }
333
347
  sql += ` ORDER BY name LIMIT ?`;
334
348
  params.push(options.limit || 20);
335
- return this.db.prepare(sql).all(...params).map(r => this.#mapEntity(r));
349
+ return this.db
350
+ .prepare(sql)
351
+ .all(...params)
352
+ .map((r) => this.#mapEntity(r));
336
353
  }
337
354
 
338
355
  /**
@@ -343,16 +360,20 @@ export class CodeEntityGraph {
343
360
  * @returns {{ outgoing: EntityEdge[], incoming: EntityEdge[] }}
344
361
  */
345
362
  getEntityEdges(entityId, entityType, direction = 'both') {
346
- const outgoing = (direction === 'both' || direction === 'out')
347
- ? this.db.prepare(
348
- `SELECT * FROM knowledge_edges WHERE from_id = ? AND from_type = ?`
349
- ).all(entityId, entityType).map(this.#mapEdge)
350
- : [];
351
- const incoming = (direction === 'both' || direction === 'in')
352
- ? this.db.prepare(
353
- `SELECT * FROM knowledge_edges WHERE to_id = ? AND to_type = ?`
354
- ).all(entityId, entityType).map(this.#mapEdge)
355
- : [];
363
+ const outgoing =
364
+ direction === 'both' || direction === 'out'
365
+ ? this.db
366
+ .prepare(`SELECT * FROM knowledge_edges WHERE from_id = ? AND from_type = ?`)
367
+ .all(entityId, entityType)
368
+ .map(this.#mapEdge)
369
+ : [];
370
+ const incoming =
371
+ direction === 'both' || direction === 'in'
372
+ ? this.db
373
+ .prepare(`SELECT * FROM knowledge_edges WHERE to_id = ? AND to_type = ?`)
374
+ .all(entityId, entityType)
375
+ .map(this.#mapEdge)
376
+ : [];
356
377
  return { outgoing, incoming };
357
378
  }
358
379
 
@@ -366,11 +387,15 @@ export class CodeEntityGraph {
366
387
  const chain = [className];
367
388
  let current = className;
368
389
  for (let i = 0; i < maxDepth; i++) {
369
- const parent = this.db.prepare(
370
- `SELECT to_id FROM knowledge_edges
390
+ const parent = this.db
391
+ .prepare(
392
+ `SELECT to_id FROM knowledge_edges
371
393
  WHERE from_id = ? AND from_type = 'class' AND relation = 'inherits' LIMIT 1`
372
- ).get(current);
373
- if (!parent) break;
394
+ )
395
+ .get(current);
396
+ if (!parent) {
397
+ break;
398
+ }
374
399
  chain.push(parent.to_id);
375
400
  current = parent.to_id;
376
401
  }
@@ -390,22 +415,27 @@ export class CodeEntityGraph {
390
415
  const queue = [{ id: entityId, type: entityType, depth: 0 }];
391
416
 
392
417
  // 类的子类/Category + 协议的遵循者
393
- const relations = entityType === 'protocol'
394
- ? ['conforms', 'inherits']
395
- : ['inherits', 'extends'];
418
+ const relations =
419
+ entityType === 'protocol' ? ['conforms', 'inherits'] : ['inherits', 'extends'];
396
420
 
397
421
  while (queue.length > 0) {
398
422
  const { id, type, depth } = queue.shift();
399
- if (depth >= maxDepth) continue;
423
+ if (depth >= maxDepth) {
424
+ continue;
425
+ }
400
426
  const key = `${type}:${id}`;
401
- if (visited.has(key)) continue;
427
+ if (visited.has(key)) {
428
+ continue;
429
+ }
402
430
  visited.add(key);
403
431
 
404
432
  for (const rel of relations) {
405
- const children = this.db.prepare(
406
- `SELECT from_id, from_type FROM knowledge_edges
433
+ const children = this.db
434
+ .prepare(
435
+ `SELECT from_id, from_type FROM knowledge_edges
407
436
  WHERE to_id = ? AND to_type = ? AND relation = ?`
408
- ).all(id, type, rel);
437
+ )
438
+ .all(id, type, rel);
409
439
 
410
440
  for (const child of children) {
411
441
  const childKey = `${child.from_type}:${child.from_id}`;
@@ -431,11 +461,13 @@ export class CodeEntityGraph {
431
461
  * @returns {string[]}
432
462
  */
433
463
  getConformances(className) {
434
- const rows = this.db.prepare(
435
- `SELECT to_id FROM knowledge_edges
464
+ const rows = this.db
465
+ .prepare(
466
+ `SELECT to_id FROM knowledge_edges
436
467
  WHERE from_id = ? AND from_type IN ('class', 'category') AND relation = 'conforms'`
437
- ).all(className);
438
- return rows.map(r => r.to_id);
468
+ )
469
+ .all(className);
470
+ return rows.map((r) => r.to_id);
439
471
  }
440
472
 
441
473
  /**
@@ -453,18 +485,28 @@ export class CodeEntityGraph {
453
485
 
454
486
  while (queue.length > 0) {
455
487
  const { id, type, path } = queue.shift();
456
- if (path.length >= maxDepth) continue;
488
+ if (path.length >= maxDepth) {
489
+ continue;
490
+ }
457
491
 
458
492
  const key = `${type}:${id}`;
459
- if (visited.has(key)) continue;
493
+ if (visited.has(key)) {
494
+ continue;
495
+ }
460
496
  visited.add(key);
461
497
 
462
- const neighbors = this.db.prepare(
463
- `SELECT to_id, to_type, relation, weight FROM knowledge_edges WHERE from_id = ? AND from_type = ?`
464
- ).all(id, type);
498
+ const neighbors = this.db
499
+ .prepare(
500
+ `SELECT to_id, to_type, relation, weight FROM knowledge_edges WHERE from_id = ? AND from_type = ?`
501
+ )
502
+ .all(id, type);
465
503
 
466
504
  for (const n of neighbors) {
467
- const step = { from: { id, type }, to: { id: n.to_id, type: n.to_type }, relation: n.relation };
505
+ const step = {
506
+ from: { id, type },
507
+ to: { id: n.to_id, type: n.to_type },
508
+ relation: n.relation,
509
+ };
468
510
  const newPath = [...path, step];
469
511
 
470
512
  if (n.to_id === toId && n.to_type === toType) {
@@ -491,17 +533,23 @@ export class CodeEntityGraph {
491
533
 
492
534
  while (queue.length > 0) {
493
535
  const { id, type, depth } = queue.shift();
494
- if (depth >= maxDepth) continue;
536
+ if (depth >= maxDepth) {
537
+ continue;
538
+ }
495
539
 
496
540
  const key = `${type}:${id}`;
497
- if (visited.has(key)) continue;
541
+ if (visited.has(key)) {
542
+ continue;
543
+ }
498
544
  visited.add(key);
499
545
 
500
546
  // 找出所有"依赖/引用此实体"的上游
501
- const dependents = this.db.prepare(
502
- `SELECT from_id, from_type, relation FROM knowledge_edges
547
+ const dependents = this.db
548
+ .prepare(
549
+ `SELECT from_id, from_type, relation FROM knowledge_edges
503
550
  WHERE to_id = ? AND to_type = ?`
504
- ).all(id, type);
551
+ )
552
+ .all(id, type);
505
553
 
506
554
  for (const dep of dependents) {
507
555
  const depKey = `${dep.from_type}:${dep.from_id}`;
@@ -525,29 +573,33 @@ export class CodeEntityGraph {
525
573
  * @returns {object}
526
574
  */
527
575
  getTopology() {
528
- const entityStats = this.db.prepare(
529
- `SELECT entity_type, COUNT(*) as count FROM code_entities
576
+ const entityStats = this.db
577
+ .prepare(
578
+ `SELECT entity_type, COUNT(*) as count FROM code_entities
530
579
  WHERE project_root = ? GROUP BY entity_type`
531
- ).all(this.projectRoot);
580
+ )
581
+ .all(this.projectRoot);
532
582
 
533
- const edgeStats = this.db.prepare(
534
- `SELECT relation, COUNT(*) as count FROM knowledge_edges GROUP BY relation`
535
- ).all();
583
+ const edgeStats = this.db
584
+ .prepare(`SELECT relation, COUNT(*) as count FROM knowledge_edges GROUP BY relation`)
585
+ .all();
536
586
 
537
587
  // 入度最高的实体 = 被依赖最多
538
- const hotNodes = this.db.prepare(
539
- `SELECT to_id, to_type, COUNT(*) as in_degree
588
+ const hotNodes = this.db
589
+ .prepare(
590
+ `SELECT to_id, to_type, COUNT(*) as in_degree
540
591
  FROM knowledge_edges
541
592
  GROUP BY to_id, to_type
542
593
  ORDER BY in_degree DESC LIMIT 15`
543
- ).all();
594
+ )
595
+ .all();
544
596
 
545
597
  return {
546
- entities: Object.fromEntries(entityStats.map(s => [s.entity_type, s.count])),
547
- edges: Object.fromEntries(edgeStats.map(s => [s.relation, s.count])),
598
+ entities: Object.fromEntries(entityStats.map((s) => [s.entity_type, s.count])),
599
+ edges: Object.fromEntries(edgeStats.map((s) => [s.relation, s.count])),
548
600
  totalEntities: entityStats.reduce((sum, s) => sum + s.count, 0),
549
601
  totalEdges: edgeStats.reduce((sum, s) => sum + s.count, 0),
550
- hotNodes: hotNodes.map(n => ({ id: n.to_id, type: n.to_type, inDegree: n.in_degree })),
602
+ hotNodes: hotNodes.map((n) => ({ id: n.to_id, type: n.to_type, inDegree: n.in_degree })),
551
603
  };
552
604
  }
553
605
 
@@ -560,10 +612,12 @@ export class CodeEntityGraph {
560
612
  */
561
613
  generateContextForAgent(options = {}) {
562
614
  const maxEntities = options.maxEntities || 30;
563
- const maxEdges = options.maxEdges || 50;
615
+ const _maxEdges = options.maxEdges || 50;
564
616
  const topo = this.getTopology();
565
617
 
566
- if (topo.totalEntities === 0) return '';
618
+ if (topo.totalEntities === 0) {
619
+ return '';
620
+ }
567
621
 
568
622
  const lines = [
569
623
  '## 代码实体图谱 (Code Entity Graph)',
@@ -602,8 +656,10 @@ export class CodeEntityGraph {
602
656
  lines.push('### 协议');
603
657
  for (const p of protocols) {
604
658
  const conformers = this.getDescendants(p.entityId, 'protocol', 1);
605
- const cNames = conformers.map(c => c.id).slice(0, 5);
606
- lines.push(`- \`${p.name}\` ← ${cNames.length > 0 ? cNames.map(n => '`' + n + '`').join(', ') : '(无遵循者)'}`);
659
+ const cNames = conformers.map((c) => c.id).slice(0, 5);
660
+ lines.push(
661
+ `- \`${p.name}\` ← ${cNames.length > 0 ? cNames.map((n) => `\`${n}\``).join(', ') : '(无遵循者)'}`
662
+ );
607
663
  }
608
664
  lines.push('');
609
665
  }
@@ -618,9 +674,11 @@ export class CodeEntityGraph {
618
674
  const run = this.db.transaction(() => {
619
675
  this.stmts.clearEntities.run(this.projectRoot);
620
676
  // 只清除 AST 产出的边 (保留 recipe/module 边)
621
- this.db.prepare(
622
- `DELETE FROM knowledge_edges WHERE metadata_json LIKE '%ast-bootstrap%' OR metadata_json LIKE '%ast-pattern-detection%'`
623
- ).run();
677
+ this.db
678
+ .prepare(
679
+ `DELETE FROM knowledge_edges WHERE metadata_json LIKE '%ast-bootstrap%' OR metadata_json LIKE '%ast-pattern-detection%'`
680
+ )
681
+ .run();
624
682
  });
625
683
  run();
626
684
  this.log.info(`[CodeEntityGraph] Cleared entities for project: ${this.projectRoot}`);
@@ -675,9 +733,7 @@ export class CodeEntityGraph {
675
733
  listByType: this.db.prepare(
676
734
  `SELECT * FROM code_entities WHERE entity_type = ? AND project_root = ? ORDER BY name LIMIT ?`
677
735
  ),
678
- clearEntities: this.db.prepare(
679
- `DELETE FROM code_entities WHERE project_root = ?`
680
- ),
736
+ clearEntities: this.db.prepare(`DELETE FROM code_entities WHERE project_root = ?`),
681
737
  addEdge: this.db.prepare(`
682
738
  INSERT OR REPLACE INTO knowledge_edges (from_id, from_type, to_id, to_type, relation, weight, metadata_json, created_at, updated_at)
683
739
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
@@ -702,7 +758,7 @@ export class CodeEntityGraph {
702
758
  JSON.stringify(entity.protocols || []),
703
759
  JSON.stringify(entity.metadata || {}),
704
760
  now,
705
- now,
761
+ now
706
762
  );
707
763
  }
708
764
 
@@ -710,10 +766,15 @@ export class CodeEntityGraph {
710
766
  const now = Math.floor(Date.now() / 1000);
711
767
  try {
712
768
  this.stmts.addEdge.run(
713
- fromId, fromType, toId, toType, relation,
769
+ fromId,
770
+ fromType,
771
+ toId,
772
+ toType,
773
+ relation,
714
774
  metadata.weight || 1.0,
715
775
  JSON.stringify(metadata),
716
- now, now,
776
+ now,
777
+ now
717
778
  );
718
779
  } catch (err) {
719
780
  // Ignore duplicate edge errors
@@ -727,8 +788,12 @@ export class CodeEntityGraph {
727
788
  * 从 AST 数据推断实体类型
728
789
  */
729
790
  #inferEntityType(name, astSummary) {
730
- if (astSummary.protocols?.some(p => p.name === name)) return 'protocol';
731
- if (name.includes('(') && name.includes(')')) return 'category';
791
+ if (astSummary.protocols?.some((p) => p.name === name)) {
792
+ return 'protocol';
793
+ }
794
+ if (name.includes('(') && name.includes(')')) {
795
+ return 'category';
796
+ }
732
797
  return 'class';
733
798
  }
734
799
 
@@ -91,15 +91,15 @@ export class ConfidenceRouter {
91
91
  if (this._qualityScorer) {
92
92
  try {
93
93
  const scorerInput = {
94
- title: entry.title,
95
- trigger: entry.trigger,
96
- code: entry.content?.pattern || entry.content?.markdown || '',
97
- language: entry.language,
98
- category: entry.category,
99
- summary: entry.summaryCn || entry.summaryEn || '',
94
+ title: entry.title,
95
+ trigger: entry.trigger,
96
+ code: entry.content?.pattern || entry.content?.markdown || '',
97
+ language: entry.language,
98
+ category: entry.category,
99
+ summary: entry.summaryCn || entry.summaryEn || '',
100
100
  usageGuide: entry.usageGuideCn || entry.usageGuideEn || '',
101
- headers: entry.headers || [],
102
- tags: entry.tags || [],
101
+ headers: entry.headers || [],
102
+ tags: entry.tags || [],
103
103
  };
104
104
  const result = this._qualityScorer.score(scorerInput);
105
105
  qualityScore = result.score;
@@ -143,13 +143,15 @@ export class ConfidenceRouter {
143
143
  */
144
144
  _estimateContentLength(entry) {
145
145
  const content = entry.content;
146
- if (!content) return 0;
146
+ if (!content) {
147
+ return 0;
148
+ }
147
149
 
148
150
  const parts = [
149
151
  content.pattern,
150
152
  content.rationale,
151
153
  content.markdown,
152
- ...(content.steps || []).map(s => typeof s === 'string' ? s : s?.description || ''),
154
+ ...(content.steps || []).map((s) => (typeof s === 'string' ? s : s?.description || '')),
153
155
  ].filter(Boolean);
154
156
 
155
157
  return parts.reduce((sum, p) => sum + p.length, 0);