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
@@ -6,11 +6,46 @@
6
6
 
7
7
  // 场景权重配置
8
8
  const SCENARIO_WEIGHTS = {
9
- lint: { relevance: 0.40, authority: 0.25, recency: 0.15, popularity: 0.10, difficulty: 0.05, seasonality: 0.05 },
10
- generate: { relevance: 0.30, authority: 0.20, recency: 0.10, popularity: 0.20, difficulty: 0.10, seasonality: 0.10 },
11
- search: { relevance: 0.30, authority: 0.20, recency: 0.15, popularity: 0.15, difficulty: 0.10, seasonality: 0.10 },
12
- learning: { relevance: 0.20, authority: 0.15, recency: 0.05, popularity: 0.10, difficulty: 0.30, seasonality: 0.20 },
13
- default: { relevance: 0.30, authority: 0.20, recency: 0.15, popularity: 0.15, difficulty: 0.10, seasonality: 0.10 },
9
+ lint: {
10
+ relevance: 0.4,
11
+ authority: 0.25,
12
+ recency: 0.15,
13
+ popularity: 0.1,
14
+ difficulty: 0.05,
15
+ seasonality: 0.05,
16
+ },
17
+ generate: {
18
+ relevance: 0.3,
19
+ authority: 0.2,
20
+ recency: 0.1,
21
+ popularity: 0.2,
22
+ difficulty: 0.1,
23
+ seasonality: 0.1,
24
+ },
25
+ search: {
26
+ relevance: 0.3,
27
+ authority: 0.2,
28
+ recency: 0.15,
29
+ popularity: 0.15,
30
+ difficulty: 0.1,
31
+ seasonality: 0.1,
32
+ },
33
+ learning: {
34
+ relevance: 0.2,
35
+ authority: 0.15,
36
+ recency: 0.05,
37
+ popularity: 0.1,
38
+ difficulty: 0.3,
39
+ seasonality: 0.2,
40
+ },
41
+ default: {
42
+ relevance: 0.3,
43
+ authority: 0.2,
44
+ recency: 0.15,
45
+ popularity: 0.15,
46
+ difficulty: 0.1,
47
+ seasonality: 0.1,
48
+ },
14
49
  };
15
50
 
16
51
  /**
@@ -20,22 +55,30 @@ export class RelevanceSignal {
20
55
  compute(candidate, context) {
21
56
  let score = candidate.bm25Score || candidate.score || 0;
22
57
  const query = (context.query || '').toLowerCase();
23
- if (!query) return Math.min(score, 1.0);
58
+ if (!query) {
59
+ return Math.min(score, 1.0);
60
+ }
24
61
 
25
62
  const title = (candidate.title || '').toLowerCase();
26
63
  const trigger = (candidate.trigger || '').toLowerCase();
27
64
  const content = (candidate.content || candidate.code || '').toLowerCase();
28
65
 
29
66
  // trigger 精确匹配 boost(最高优先级)
30
- if (trigger && trigger.includes(query)) score += 0.4;
67
+ if (trigger?.includes(query)) {
68
+ score += 0.4;
69
+ }
31
70
  // 标题精确匹配 boost
32
- if (title.includes(query)) score += 0.3;
71
+ if (title.includes(query)) {
72
+ score += 0.3;
73
+ }
33
74
  // 标题单词匹配
34
75
  const queryWords = query.split(/\s+/);
35
- const titleHits = queryWords.filter(w => title.includes(w)).length;
76
+ const titleHits = queryWords.filter((w) => title.includes(w)).length;
36
77
  score += (titleHits / queryWords.length) * 0.2;
37
78
  // 内容匹配
38
- if (content.includes(query)) score += 0.1;
79
+ if (content.includes(query)) {
80
+ score += 0.1;
81
+ }
39
82
 
40
83
  return Math.min(score, 1.0);
41
84
  }
@@ -47,9 +90,15 @@ export class RelevanceSignal {
47
90
  export class AuthoritySignal {
48
91
  compute(candidate) {
49
92
  let score = 0;
50
- if (candidate.qualityScore) score += (candidate.qualityScore / 100) * 0.5;
51
- if (candidate.authorityScore) score += candidate.authorityScore * 0.3;
52
- if (candidate.usageCount > 0) score += Math.min(candidate.usageCount / 100, 1) * 0.2;
93
+ if (candidate.qualityScore) {
94
+ score += (candidate.qualityScore / 100) * 0.5;
95
+ }
96
+ if (candidate.authorityScore) {
97
+ score += candidate.authorityScore * 0.3;
98
+ }
99
+ if (candidate.usageCount > 0) {
100
+ score += Math.min(candidate.usageCount / 100, 1) * 0.2;
101
+ }
53
102
  return Math.min(score || 0.5, 1.0);
54
103
  }
55
104
  }
@@ -60,16 +109,23 @@ export class AuthoritySignal {
60
109
  export class RecencySignal {
61
110
  compute(candidate) {
62
111
  const updated = candidate.updatedAt || candidate.lastModified || candidate.createdAt;
63
- if (!updated) return 0.5;
112
+ if (!updated) {
113
+ return 0.5;
114
+ }
64
115
  // 自动识别秒级/毫秒级 Unix 时间戳 (秒级 ≤ 9999999999 即 2286 年)
65
- const ts = typeof updated === 'number' && updated > 0 && updated <= 9999999999
66
- ? updated * 1000
67
- : (typeof updated === 'number' ? updated : new Date(updated).getTime());
116
+ const ts =
117
+ typeof updated === 'number' && updated > 0 && updated <= 9999999999
118
+ ? updated * 1000
119
+ : typeof updated === 'number'
120
+ ? updated
121
+ : new Date(updated).getTime();
68
122
  const ageMs = Date.now() - ts;
69
- if (ageMs < 0) return 1.0; // 未来时间戳视为最新
123
+ if (ageMs < 0) {
124
+ return 1.0; // 未来时间戳视为最新
125
+ }
70
126
  const ageDays = ageMs / (1000 * 60 * 60 * 24);
71
127
  // 指数衰减:半衰期 90 天
72
- return Math.exp(-0.693 * ageDays / 90);
128
+ return Math.exp((-Math.LN2 * ageDays) / 90);
73
129
  }
74
130
  }
75
131
 
@@ -106,8 +162,12 @@ export class DifficultySignal {
106
162
  export class SeasonalitySignal {
107
163
  compute(candidate, context) {
108
164
  // 简单实现:语言/框架匹配加分
109
- if (context.language && candidate.language === context.language) return 0.8;
110
- if (context.category && candidate.category === context.category) return 0.6;
165
+ if (context.language && candidate.language === context.language) {
166
+ return 0.8;
167
+ }
168
+ if (context.category && candidate.category === context.category) {
169
+ return 0.6;
170
+ }
111
171
  return 0.5;
112
172
  }
113
173
  }
@@ -121,11 +181,11 @@ export class MultiSignalRanker {
121
181
 
122
182
  constructor(options = {}) {
123
183
  this.#signals = {
124
- relevance: new RelevanceSignal(),
125
- authority: new AuthoritySignal(),
126
- recency: new RecencySignal(),
127
- popularity: new PopularitySignal(),
128
- difficulty: new DifficultySignal(),
184
+ relevance: new RelevanceSignal(),
185
+ authority: new AuthoritySignal(),
186
+ recency: new RecencySignal(),
187
+ popularity: new PopularitySignal(),
188
+ difficulty: new DifficultySignal(),
129
189
  seasonality: new SeasonalitySignal(),
130
190
  };
131
191
  this.#scenarioWeights = { ...SCENARIO_WEIGHTS, ...options.scenarioWeights };
@@ -138,12 +198,14 @@ export class MultiSignalRanker {
138
198
  * @returns {Array} — sorted candidates with rankerScore
139
199
  */
140
200
  rank(candidates, context = {}) {
141
- if (!candidates || candidates.length === 0) return [];
201
+ if (!candidates || candidates.length === 0) {
202
+ return [];
203
+ }
142
204
 
143
205
  const scenario = context.scenario || context.intent || 'default';
144
206
  const weights = this.#scenarioWeights[scenario] || this.#scenarioWeights.default;
145
207
 
146
- const scored = candidates.map(candidate => {
208
+ const scored = candidates.map((candidate) => {
147
209
  const signals = {};
148
210
  let totalScore = 0;
149
211
 
@@ -6,10 +6,10 @@
6
6
  * Layer 4: Context-Aware Reranking (对话历史提升)
7
7
  */
8
8
 
9
- import { buildInvertedIndex, lookup, tokenize } from './InvertedIndex.js';
10
- import { MultiSignalRanker } from './MultiSignalRanker.js';
11
9
  import { CoarseRanker } from './CoarseRanker.js';
12
10
  import { CrossEncoderReranker } from './CrossEncoderReranker.js';
11
+ import { buildInvertedIndex, lookup, tokenize } from './InvertedIndex.js';
12
+ import { MultiSignalRanker } from './MultiSignalRanker.js';
13
13
 
14
14
  export class RetrievalFunnel {
15
15
  #multiSignalRanker;
@@ -37,14 +37,20 @@ export class RetrievalFunnel {
37
37
  * @returns {Array} — ranked results
38
38
  */
39
39
  async execute(query, candidates, context = {}) {
40
- if (!candidates || candidates.length === 0) return [];
41
- if (!query) return candidates;
40
+ if (!candidates || candidates.length === 0) {
41
+ return [];
42
+ }
43
+ if (!query) {
44
+ return candidates;
45
+ }
42
46
 
43
47
  // Layer 1: Keyword Filter — 倒排索引快速召回
44
48
  let results = this.#keywordFilter(query, candidates);
45
49
 
46
50
  // 如果关键词无结果,退回全量
47
- if (results.length === 0) results = [...candidates];
51
+ if (results.length === 0) {
52
+ results = [...candidates];
53
+ }
48
54
 
49
55
  // Layer 2: Semantic Rerank — 向量/Jaccard 相似度重排
50
56
  results = await this.#semanticRerank(query, results);
@@ -68,8 +74,10 @@ export class RetrievalFunnel {
68
74
  const index = buildInvertedIndex(candidates);
69
75
  const matchedIndices = lookup(index, query);
70
76
 
71
- if (matchedIndices.length === 0) return [];
72
- return matchedIndices.map(idx => candidates[idx]);
77
+ if (matchedIndices.length === 0) {
78
+ return [];
79
+ }
80
+ return matchedIndices.map((idx) => candidates[idx]);
73
81
  }
74
82
 
75
83
  /**
@@ -85,29 +93,42 @@ export class RetrievalFunnel {
85
93
  * - 语言匹配 +10%
86
94
  */
87
95
  #contextAwareRerank(candidates, context) {
88
- if (!context.sessionHistory || context.sessionHistory.length === 0) return candidates;
96
+ if (!context.sessionHistory || context.sessionHistory.length === 0) {
97
+ return candidates;
98
+ }
89
99
 
90
100
  // 收集会话中的关键词
91
101
  const sessionKeywords = new Set();
92
102
  for (const turn of context.sessionHistory) {
93
103
  const tokens = tokenize(turn.content || turn.rawInput || '');
94
- for (const t of tokens) sessionKeywords.add(t);
104
+ for (const t of tokens) {
105
+ sessionKeywords.add(t);
106
+ }
95
107
  }
96
108
 
97
- return candidates.map(candidate => {
98
- let boost = 0;
99
- const text = [candidate.title, candidate.trigger, candidate.content].filter(Boolean).join(' ').toLowerCase();
100
-
101
- // 会话上下文匹配
102
- const textTokens = tokenize(text);
103
- const sessionOverlap = textTokens.filter(t => sessionKeywords.has(t)).length;
104
- if (sessionOverlap > 0) boost += 0.2 * Math.min(sessionOverlap / 5, 1);
105
-
106
- // 语言匹配
107
- if (context.language && candidate.language === context.language) boost += 0.1;
108
-
109
- const contextScore = (candidate.rankerScore || candidate.coarseScore || 0) * (1 + boost);
110
- return { ...candidate, contextScore, contextBoost: boost };
111
- }).sort((a, b) => b.contextScore - a.contextScore);
109
+ return candidates
110
+ .map((candidate) => {
111
+ let boost = 0;
112
+ const text = [candidate.title, candidate.trigger, candidate.content]
113
+ .filter(Boolean)
114
+ .join(' ')
115
+ .toLowerCase();
116
+
117
+ // 会话上下文匹配
118
+ const textTokens = tokenize(text);
119
+ const sessionOverlap = textTokens.filter((t) => sessionKeywords.has(t)).length;
120
+ if (sessionOverlap > 0) {
121
+ boost += 0.2 * Math.min(sessionOverlap / 5, 1);
122
+ }
123
+
124
+ // 语言匹配
125
+ if (context.language && candidate.language === context.language) {
126
+ boost += 0.1;
127
+ }
128
+
129
+ const contextScore = (candidate.rankerScore || candidate.coarseScore || 0) * (1 + boost);
130
+ return { ...candidate, contextScore, contextBoost: boost };
131
+ })
132
+ .sort((a, b) => b.contextScore - a.contextScore);
112
133
  }
113
134
  }