autosnippet 3.3.0 → 3.3.3
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.
- package/dashboard/dist/assets/icons-BJ2mUBi8.js +1 -0
- package/dashboard/dist/assets/index-B659K9t5.js +128 -0
- package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.d.ts +1 -0
- package/dist/bin/cli.js +284 -142
- package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
- package/dist/lib/agent/context/ExplorationTracker.js +21 -3
- package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
- package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
- package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
- package/dist/lib/agent/forge/DynamicComposer.js +99 -0
- package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
- package/dist/lib/agent/forge/SandboxRunner.js +251 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
- package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
- package/dist/lib/agent/forge/ToolForge.js +239 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
- package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
- package/dist/lib/agent/tools/ToolRegistry.js +4 -0
- package/dist/lib/agent/tools/composite.js +0 -1
- package/dist/lib/agent/tools/index.d.ts +2 -50
- package/dist/lib/agent/tools/index.js +2 -3
- package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
- package/dist/lib/agent/tools/lifecycle.js +2 -75
- package/dist/lib/cli/KnowledgeSyncService.d.ts +26 -0
- package/dist/lib/cli/KnowledgeSyncService.js +33 -1
- package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
- package/dist/lib/cli/deploy/FileManifest.js +0 -11
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
- package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
- package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
- package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
- package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
- package/dist/lib/domain/knowledge/values/Stats.js +41 -0
- package/dist/lib/external/mcp/McpServer.d.ts +19 -38
- package/dist/lib/external/mcp/McpServer.js +145 -117
- package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
- package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/browse.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/browse.js +2 -1
- package/dist/lib/external/mcp/handlers/consolidated.d.ts +117 -6
- package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
- package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
- package/dist/lib/external/mcp/handlers/guard.js +239 -5
- package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
- package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
- package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
- package/dist/lib/external/mcp/handlers/panorama.js +156 -0
- package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
- package/dist/lib/external/mcp/handlers/system.js +3 -113
- package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
- package/dist/lib/external/mcp/handlers/task.js +218 -557
- package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
- package/dist/lib/external/mcp/handlers/types.js +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
- package/dist/lib/external/mcp/tools.d.ts +18 -24
- package/dist/lib/external/mcp/tools.js +132 -159
- package/dist/lib/http/HttpServer.js +52 -0
- package/dist/lib/http/middleware/validate.js +7 -3
- package/dist/lib/http/routes/audit.d.ts +8 -0
- package/dist/lib/http/routes/audit.js +51 -0
- package/dist/lib/http/routes/guardReport.d.ts +10 -0
- package/dist/lib/http/routes/guardReport.js +143 -0
- package/dist/lib/http/routes/knowledge.js +32 -1
- package/dist/lib/http/routes/panorama.d.ts +11 -0
- package/dist/lib/http/routes/panorama.js +322 -0
- package/dist/lib/http/routes/signals.d.ts +10 -0
- package/dist/lib/http/routes/signals.js +104 -0
- package/dist/lib/http/routes/task.d.ts +2 -3
- package/dist/lib/http/routes/task.js +17 -347
- package/dist/lib/http/routes/violations.js +1 -1
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
- package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +202 -504
- package/dist/lib/infrastructure/database/drizzle/schema.js +38 -69
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
- package/dist/lib/infrastructure/database/migrations/005_recipe_source_refs.d.ts +9 -0
- package/dist/lib/infrastructure/database/migrations/005_recipe_source_refs.js +24 -0
- package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
- package/dist/lib/infrastructure/logging/Logger.js +34 -7
- package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
- package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
- package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
- package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
- package/dist/lib/infrastructure/report/ReportStore.js +133 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
- package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
- package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
- package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
- package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
- package/dist/lib/infrastructure/vector/HnswVectorAdapter.js +18 -2
- package/dist/lib/injection/ServiceContainer.js +8 -0
- package/dist/lib/injection/ServiceMap.d.ts +16 -10
- package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
- package/dist/lib/injection/modules/AgentModule.js +7 -1
- package/dist/lib/injection/modules/AppModule.d.ts +1 -1
- package/dist/lib/injection/modules/AppModule.js +4 -13
- package/dist/lib/injection/modules/GuardModule.js +27 -2
- package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
- package/dist/lib/injection/modules/InfraModule.js +9 -7
- package/dist/lib/injection/modules/KnowledgeModule.d.ts +5 -0
- package/dist/lib/injection/modules/KnowledgeModule.js +131 -0
- package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
- package/dist/lib/injection/modules/PanoramaModule.js +76 -0
- package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
- package/dist/lib/injection/modules/SignalModule.js +84 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
- package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
- package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
- package/dist/lib/service/bootstrap/UiStartupTasks.d.ts +45 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +101 -0
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
- package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
- package/dist/lib/service/delivery/RulesGenerator.js +3 -2
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
- package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
- package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
- package/dist/lib/service/evolution/DecayDetector.js +244 -0
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
- package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
- package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
- package/dist/lib/service/evolution/StagingManager.js +201 -0
- package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
- package/dist/lib/service/guard/ComplianceReporter.js +43 -5
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
- package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +42 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +465 -14
- package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
- package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
- package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
- package/dist/lib/service/guard/ReverseGuard.js +256 -0
- package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
- package/dist/lib/service/guard/RuleLearner.js +38 -0
- package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
- package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
- package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
- package/dist/lib/service/guard/ViolationsStore.js +33 -3
- package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
- package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
- package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
- package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +68 -0
- package/dist/lib/service/knowledge/SourceRefReconciler.js +309 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
- package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
- package/dist/lib/service/panorama/LayerInferrer.js +182 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
- package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
- package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
- package/dist/lib/service/panorama/PanoramaService.d.ts +125 -0
- package/dist/lib/service/panorama/PanoramaService.js +363 -0
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
- package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
- package/dist/lib/service/panorama/RoleRefiner.js +535 -0
- package/dist/lib/service/search/BM25Scorer.d.ts +2 -2
- package/dist/lib/service/search/CoarseRanker.d.ts +7 -6
- package/dist/lib/service/search/CoarseRanker.js +11 -10
- package/dist/lib/service/search/FieldWeightedScorer.d.ts +81 -0
- package/dist/lib/service/search/FieldWeightedScorer.js +318 -0
- package/dist/lib/service/search/MultiSignalRanker.d.ts +3 -2
- package/dist/lib/service/search/MultiSignalRanker.js +17 -1
- package/dist/lib/service/search/SearchEngine.d.ts +9 -7
- package/dist/lib/service/search/SearchEngine.js +67 -10
- package/dist/lib/service/search/SearchTypes.d.ts +25 -3
- package/dist/lib/service/search/SearchTypes.js +6 -1
- package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
- package/dist/lib/service/signal/HitRecorder.js +173 -0
- package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
- package/dist/lib/service/skills/SignalCollector.js +31 -1
- package/dist/lib/service/task/IntentExtractor.d.ts +66 -0
- package/dist/lib/service/task/IntentExtractor.js +256 -0
- package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
- package/dist/lib/service/task/PrimeSearchPipeline.js +113 -0
- package/dist/lib/service/vector/VectorService.d.ts +3 -0
- package/dist/lib/service/vector/VectorService.js +38 -4
- package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
- package/dist/lib/shared/schemas/mcp-tools.js +59 -119
- package/dist/scripts/analyze-signals.d.ts +20 -0
- package/dist/scripts/analyze-signals.js +155 -0
- package/dist/scripts/diagnose-mcp.js +1 -1
- package/package.json +1 -1
- package/skills/autosnippet-create/SKILL.md +98 -89
- package/skills/autosnippet-devdocs/SKILL.md +55 -57
- package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
- package/templates/cursor-hooks/hooks/session-start.sh +1 -1
- package/templates/guard-ci.yml +2 -2
- package/templates/instructions/agent-static.md +2 -1
- package/templates/instructions/conventions.md +5 -6
- package/templates/recipes-setup/README.md +1 -2
- package/templates/recipes-setup/_template.md +39 -39
- package/dashboard/dist/assets/icons-BofcEZ3f.js +0 -1
- package/dashboard/dist/assets/index-D0whuycy.css +0 -1
- package/dashboard/dist/assets/index-SiN1GChm.js +0 -128
- package/dist/lib/domain/task/Task.d.ts +0 -140
- package/dist/lib/domain/task/Task.js +0 -254
- package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
- package/dist/lib/domain/task/TaskDependency.js +0 -34
- package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
- package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
- package/dist/lib/domain/task/index.d.ts +0 -4
- package/dist/lib/domain/task/index.js +0 -4
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
- package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
- package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
- package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
- package/dist/lib/service/task/TaskGraphService.js +0 -597
- package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
- package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
- package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
- package/dist/lib/service/task/TaskReadyEngine.js +0 -115
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RoleRefiner — 四重信号融合角色精化
|
|
3
|
+
*
|
|
4
|
+
* 将 TargetClassifier 的正则推断 (~65% 准确率) 提升到 ≥90%,
|
|
5
|
+
* 通过融合 AST 结构、CallGraph 行为、DataFlow 数据流、EntityGraph 拓扑四重信号。
|
|
6
|
+
*
|
|
7
|
+
* 信号权重:
|
|
8
|
+
* AST 结构 0.30 继承链/协议/import/后缀
|
|
9
|
+
* CallGraph 行为 0.30 被调用分析/扇入扇出比/调用类型
|
|
10
|
+
* DataFlow 数据流 0.15 源汇分析/转换检测
|
|
11
|
+
* EntityGraph 拓扑 0.10 入度分析/模式检测
|
|
12
|
+
* 正则基线 0.15 TargetClassifier 结果
|
|
13
|
+
*
|
|
14
|
+
* @module RoleRefiner
|
|
15
|
+
*/
|
|
16
|
+
/* ═══ Constants ═══════════════════════════════════════════ */
|
|
17
|
+
const WEIGHTS = {
|
|
18
|
+
ast: 0.3,
|
|
19
|
+
callGraph: 0.3,
|
|
20
|
+
dataFlow: 0.15,
|
|
21
|
+
entityGraph: 0.1,
|
|
22
|
+
regex: 0.15,
|
|
23
|
+
};
|
|
24
|
+
/** primary_lang / LanguageService 输出 → 语言族 */
|
|
25
|
+
const LANG_TO_FAMILY = {
|
|
26
|
+
swift: 'apple',
|
|
27
|
+
objectivec: 'apple',
|
|
28
|
+
java: 'jvm',
|
|
29
|
+
kotlin: 'jvm',
|
|
30
|
+
dart: 'dart',
|
|
31
|
+
python: 'python',
|
|
32
|
+
typescript: 'web',
|
|
33
|
+
javascript: 'web',
|
|
34
|
+
tsx: 'web',
|
|
35
|
+
go: 'go',
|
|
36
|
+
rust: 'rust',
|
|
37
|
+
};
|
|
38
|
+
/* ─── 按语言族分区的超类映射 ─────────────────────────────── */
|
|
39
|
+
const SUPERCLASS_BY_FAMILY = {
|
|
40
|
+
apple: {
|
|
41
|
+
UIViewController: 'ui',
|
|
42
|
+
UIView: 'ui',
|
|
43
|
+
UITableViewCell: 'ui',
|
|
44
|
+
UICollectionViewCell: 'ui',
|
|
45
|
+
UINavigationController: 'routing',
|
|
46
|
+
UITabBarController: 'routing',
|
|
47
|
+
UIApplication: 'app',
|
|
48
|
+
NSObject: 'core',
|
|
49
|
+
NSManagedObject: 'storage',
|
|
50
|
+
},
|
|
51
|
+
jvm: {
|
|
52
|
+
Activity: 'ui',
|
|
53
|
+
AppCompatActivity: 'ui',
|
|
54
|
+
Fragment: 'ui',
|
|
55
|
+
DialogFragment: 'ui',
|
|
56
|
+
View: 'ui',
|
|
57
|
+
RecyclerViewAdapter: 'ui',
|
|
58
|
+
Service: 'service',
|
|
59
|
+
IntentService: 'service',
|
|
60
|
+
BroadcastReceiver: 'service',
|
|
61
|
+
ContentProvider: 'storage',
|
|
62
|
+
ViewModel: 'ui',
|
|
63
|
+
AndroidViewModel: 'ui',
|
|
64
|
+
Application: 'app',
|
|
65
|
+
},
|
|
66
|
+
dart: {
|
|
67
|
+
StatefulWidget: 'ui',
|
|
68
|
+
StatelessWidget: 'ui',
|
|
69
|
+
State: 'ui',
|
|
70
|
+
ChangeNotifier: 'service',
|
|
71
|
+
Cubit: 'service',
|
|
72
|
+
Bloc: 'service',
|
|
73
|
+
},
|
|
74
|
+
python: {
|
|
75
|
+
BaseModel: 'model',
|
|
76
|
+
Model: 'model',
|
|
77
|
+
APIView: 'service',
|
|
78
|
+
ViewSet: 'service',
|
|
79
|
+
TestCase: 'test',
|
|
80
|
+
},
|
|
81
|
+
web: {
|
|
82
|
+
Component: 'ui',
|
|
83
|
+
Controller: 'service',
|
|
84
|
+
Module: 'app',
|
|
85
|
+
},
|
|
86
|
+
go: {},
|
|
87
|
+
rust: {},
|
|
88
|
+
};
|
|
89
|
+
/* ─── 按语言族分区的协议/接口映射 ────────────────────────── */
|
|
90
|
+
const PROTOCOL_BY_FAMILY = {
|
|
91
|
+
apple: {
|
|
92
|
+
UITableViewDataSource: 'ui',
|
|
93
|
+
UITableViewDelegate: 'ui',
|
|
94
|
+
UICollectionViewDataSource: 'ui',
|
|
95
|
+
UIApplicationDelegate: 'app',
|
|
96
|
+
UISceneDelegate: 'app',
|
|
97
|
+
UIWindowSceneDelegate: 'app',
|
|
98
|
+
URLSessionDelegate: 'networking',
|
|
99
|
+
Codable: 'model',
|
|
100
|
+
Decodable: 'model',
|
|
101
|
+
Encodable: 'model',
|
|
102
|
+
},
|
|
103
|
+
jvm: {
|
|
104
|
+
Serializable: 'model',
|
|
105
|
+
Parcelable: 'model',
|
|
106
|
+
Runnable: 'core',
|
|
107
|
+
Callable: 'core',
|
|
108
|
+
OnClickListener: 'ui',
|
|
109
|
+
Adapter: 'ui',
|
|
110
|
+
Repository: 'storage',
|
|
111
|
+
},
|
|
112
|
+
dart: {
|
|
113
|
+
Widget: 'ui',
|
|
114
|
+
},
|
|
115
|
+
web: {
|
|
116
|
+
OnInit: 'ui',
|
|
117
|
+
OnDestroy: 'ui',
|
|
118
|
+
CanActivate: 'routing',
|
|
119
|
+
NestMiddleware: 'service',
|
|
120
|
+
},
|
|
121
|
+
go: {
|
|
122
|
+
Handler: 'service',
|
|
123
|
+
ReadWriter: 'core',
|
|
124
|
+
Reader: 'core',
|
|
125
|
+
Writer: 'core',
|
|
126
|
+
Stringer: 'utility',
|
|
127
|
+
},
|
|
128
|
+
rust: {
|
|
129
|
+
Display: 'utility',
|
|
130
|
+
Debug: 'utility',
|
|
131
|
+
Serialize: 'model',
|
|
132
|
+
Deserialize: 'model',
|
|
133
|
+
Future: 'core',
|
|
134
|
+
Stream: 'core',
|
|
135
|
+
Service: 'service',
|
|
136
|
+
},
|
|
137
|
+
python: {},
|
|
138
|
+
};
|
|
139
|
+
const IMPORT_PATTERNS_BY_FAMILY = {
|
|
140
|
+
apple: [
|
|
141
|
+
{ regex: /alamofire|urlsession|afnetworking|moya/i, role: 'networking' },
|
|
142
|
+
{ regex: /\buikit\b|swiftui|rx.*cocoa|snapkit|masonry/i, role: 'ui' },
|
|
143
|
+
{ regex: /realm|coredata|fmdb|grdb/i, role: 'storage' },
|
|
144
|
+
{ regex: /xctest/i, role: 'test' },
|
|
145
|
+
],
|
|
146
|
+
jvm: [
|
|
147
|
+
{ regex: /retrofit|okhttp|volley/i, role: 'networking' },
|
|
148
|
+
{ regex: /android\.widget|jetpack.*compose|recyclerview/i, role: 'ui' },
|
|
149
|
+
{ regex: /room|hibernate|greendao/i, role: 'storage' },
|
|
150
|
+
{ regex: /junit|espresso|mockito/i, role: 'test' },
|
|
151
|
+
],
|
|
152
|
+
dart: [
|
|
153
|
+
{ regex: /\bdio\b|http_client/i, role: 'networking' },
|
|
154
|
+
{ regex: /flutter|cupertino|material/i, role: 'ui' },
|
|
155
|
+
{ regex: /sqflite|hive|objectbox/i, role: 'storage' },
|
|
156
|
+
{ regex: /flutter_test/i, role: 'test' },
|
|
157
|
+
],
|
|
158
|
+
python: [
|
|
159
|
+
{ regex: /requests|aiohttp|httpx|urllib/i, role: 'networking' },
|
|
160
|
+
{ regex: /tkinter|pyqt|kivy/i, role: 'ui' },
|
|
161
|
+
{ regex: /sqlalchemy|django\.db|peewee|tortoise/i, role: 'storage' },
|
|
162
|
+
{ regex: /pytest|unittest/i, role: 'test' },
|
|
163
|
+
],
|
|
164
|
+
web: [
|
|
165
|
+
{ regex: /axios|fetch|got|superagent/i, role: 'networking' },
|
|
166
|
+
{ regex: /react|angular|vue|svelte|next|nuxt/i, role: 'ui' },
|
|
167
|
+
{ regex: /typeorm|prisma|sequelize|mongoose|knex/i, role: 'storage' },
|
|
168
|
+
{ regex: /jest|mocha|vitest|cypress|playwright/i, role: 'test' },
|
|
169
|
+
{ regex: /express|fastify|nestjs|koa/i, role: 'routing' },
|
|
170
|
+
],
|
|
171
|
+
go: [
|
|
172
|
+
{ regex: /net\/http|resty/i, role: 'networking' },
|
|
173
|
+
{ regex: /gin|echo|fiber|mux|chi/i, role: 'routing' },
|
|
174
|
+
{ regex: /gorm|sqlx|ent/i, role: 'storage' },
|
|
175
|
+
{ regex: /testing/i, role: 'test' },
|
|
176
|
+
],
|
|
177
|
+
rust: [
|
|
178
|
+
{ regex: /reqwest|hyper|surf/i, role: 'networking' },
|
|
179
|
+
{ regex: /actix|axum|warp|rocket/i, role: 'routing' },
|
|
180
|
+
{ regex: /diesel|sqlx|sea-orm/i, role: 'storage' },
|
|
181
|
+
{ regex: /tokio-test/i, role: 'test' },
|
|
182
|
+
],
|
|
183
|
+
};
|
|
184
|
+
/** 通用 import 模式(任何语言都适用) */
|
|
185
|
+
const UNIVERSAL_IMPORT_PATTERNS = [
|
|
186
|
+
{ regex: /network/i, role: 'networking' },
|
|
187
|
+
{ regex: /sqlite/i, role: 'storage' },
|
|
188
|
+
{ regex: /router|routing|navigation/i, role: 'routing' },
|
|
189
|
+
];
|
|
190
|
+
/* ═══ RoleRefiner Class ═══════════════════════════════════ */
|
|
191
|
+
export class RoleRefiner {
|
|
192
|
+
#db;
|
|
193
|
+
#projectRoot;
|
|
194
|
+
#families = null;
|
|
195
|
+
#superclassMap = null;
|
|
196
|
+
#protocolMap = null;
|
|
197
|
+
#importPatterns = null;
|
|
198
|
+
constructor(db, projectRoot) {
|
|
199
|
+
this.#db = db;
|
|
200
|
+
this.#projectRoot = projectRoot;
|
|
201
|
+
}
|
|
202
|
+
/** 检测项目语言族,基于 bootstrap_snapshots.primary_lang */
|
|
203
|
+
#detectFamilies() {
|
|
204
|
+
if (this.#families) {
|
|
205
|
+
return this.#families;
|
|
206
|
+
}
|
|
207
|
+
const row = this.#db
|
|
208
|
+
.prepare(`SELECT primary_lang FROM bootstrap_snapshots
|
|
209
|
+
WHERE project_root = ? ORDER BY created_at DESC LIMIT 1`)
|
|
210
|
+
.get(this.#projectRoot);
|
|
211
|
+
const primaryLang = row?.primary_lang;
|
|
212
|
+
if (primaryLang && LANG_TO_FAMILY[primaryLang]) {
|
|
213
|
+
this.#families = [LANG_TO_FAMILY[primaryLang]];
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// 无 bootstrap 数据时回退:使用所有语言族
|
|
217
|
+
this.#families = Object.keys(SUPERCLASS_BY_FAMILY);
|
|
218
|
+
}
|
|
219
|
+
return this.#families;
|
|
220
|
+
}
|
|
221
|
+
/** 构建当前项目语言族的超类合并映射 */
|
|
222
|
+
#getSuperclassMap() {
|
|
223
|
+
if (this.#superclassMap) {
|
|
224
|
+
return this.#superclassMap;
|
|
225
|
+
}
|
|
226
|
+
const merged = {};
|
|
227
|
+
for (const fam of this.#detectFamilies()) {
|
|
228
|
+
Object.assign(merged, SUPERCLASS_BY_FAMILY[fam]);
|
|
229
|
+
}
|
|
230
|
+
this.#superclassMap = merged;
|
|
231
|
+
return merged;
|
|
232
|
+
}
|
|
233
|
+
/** 构建当前项目语言族的协议合并映射 */
|
|
234
|
+
#getProtocolMap() {
|
|
235
|
+
if (this.#protocolMap) {
|
|
236
|
+
return this.#protocolMap;
|
|
237
|
+
}
|
|
238
|
+
const merged = {};
|
|
239
|
+
for (const fam of this.#detectFamilies()) {
|
|
240
|
+
Object.assign(merged, PROTOCOL_BY_FAMILY[fam]);
|
|
241
|
+
}
|
|
242
|
+
this.#protocolMap = merged;
|
|
243
|
+
return merged;
|
|
244
|
+
}
|
|
245
|
+
/** 构建当前项目语言族的 import 模式列表 */
|
|
246
|
+
#getImportPatterns() {
|
|
247
|
+
if (this.#importPatterns) {
|
|
248
|
+
return this.#importPatterns;
|
|
249
|
+
}
|
|
250
|
+
const patterns = [...UNIVERSAL_IMPORT_PATTERNS];
|
|
251
|
+
for (const fam of this.#detectFamilies()) {
|
|
252
|
+
patterns.push(...IMPORT_PATTERNS_BY_FAMILY[fam]);
|
|
253
|
+
}
|
|
254
|
+
this.#importPatterns = patterns;
|
|
255
|
+
return patterns;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* 精化单个模块的角色
|
|
259
|
+
*/
|
|
260
|
+
refineRole(module) {
|
|
261
|
+
const signals = [];
|
|
262
|
+
// 1. AST 结构信号 (0.30)
|
|
263
|
+
signals.push(...this.#extractAstSignals(module));
|
|
264
|
+
// 2. CallGraph 行为信号 (0.30)
|
|
265
|
+
signals.push(...this.#extractCallSignals(module));
|
|
266
|
+
// 3. DataFlow 数据流信号 (0.15)
|
|
267
|
+
signals.push(...this.#extractFlowSignals(module));
|
|
268
|
+
// 4. EntityGraph 拓扑信号 (0.10)
|
|
269
|
+
signals.push(...this.#extractTopoSignals(module));
|
|
270
|
+
// 5. 正则基线 (0.15)
|
|
271
|
+
signals.push({
|
|
272
|
+
role: module.inferredRole,
|
|
273
|
+
confidence: 0.5,
|
|
274
|
+
weight: WEIGHTS.regex,
|
|
275
|
+
source: 'regex-baseline',
|
|
276
|
+
});
|
|
277
|
+
// 加权投票
|
|
278
|
+
const roleScores = {};
|
|
279
|
+
for (const signal of signals) {
|
|
280
|
+
roleScores[signal.role] = (roleScores[signal.role] ?? 0) + signal.confidence * signal.weight;
|
|
281
|
+
}
|
|
282
|
+
const sorted = Object.entries(roleScores).sort((a, b) => b[1] - a[1]);
|
|
283
|
+
if (sorted.length === 0) {
|
|
284
|
+
return {
|
|
285
|
+
refinedRole: module.inferredRole,
|
|
286
|
+
confidence: 0,
|
|
287
|
+
resolution: 'fallback',
|
|
288
|
+
signals,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
const [topRole, topScore] = sorted[0];
|
|
292
|
+
const secondScore = sorted[1]?.[1] ?? 0;
|
|
293
|
+
// 冲突解决
|
|
294
|
+
if (topScore > 0.7) {
|
|
295
|
+
return {
|
|
296
|
+
refinedRole: topRole,
|
|
297
|
+
confidence: Math.min(topScore, 1),
|
|
298
|
+
resolution: 'clear',
|
|
299
|
+
signals,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
if (topScore - secondScore < 0.1) {
|
|
303
|
+
return {
|
|
304
|
+
refinedRole: topRole,
|
|
305
|
+
confidence: Math.min(topScore, 1),
|
|
306
|
+
resolution: 'uncertain',
|
|
307
|
+
alternatives: sorted.slice(0, 3),
|
|
308
|
+
signals,
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
return {
|
|
312
|
+
refinedRole: topRole,
|
|
313
|
+
confidence: Math.min(topScore, 1),
|
|
314
|
+
resolution: topScore > 0.4 ? 'clear' : 'fallback',
|
|
315
|
+
signals,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* 批量精化所有模块
|
|
320
|
+
*/
|
|
321
|
+
refineAll(modules) {
|
|
322
|
+
const result = new Map();
|
|
323
|
+
for (const m of modules) {
|
|
324
|
+
result.set(m.name, this.refineRole(m));
|
|
325
|
+
}
|
|
326
|
+
return result;
|
|
327
|
+
}
|
|
328
|
+
/* ─── Signal Extractors ──────────────────────────── */
|
|
329
|
+
/** AST 结构信号: 继承链、协议、import */
|
|
330
|
+
#extractAstSignals(module) {
|
|
331
|
+
const signals = [];
|
|
332
|
+
const filePaths = module.files;
|
|
333
|
+
if (filePaths.length === 0) {
|
|
334
|
+
return signals;
|
|
335
|
+
}
|
|
336
|
+
// 查询模块内实体的继承关系
|
|
337
|
+
const placeholders = filePaths.map(() => '?').join(',');
|
|
338
|
+
const entities = this.#db
|
|
339
|
+
.prepare(`SELECT entity_id, entity_type, superclass, protocols, file_path
|
|
340
|
+
FROM code_entities
|
|
341
|
+
WHERE project_root = ? AND file_path IN (${placeholders})`)
|
|
342
|
+
.all(this.#projectRoot, ...filePaths);
|
|
343
|
+
const roleCounts = {};
|
|
344
|
+
const superclassMap = this.#getSuperclassMap();
|
|
345
|
+
const protocolMap = this.#getProtocolMap();
|
|
346
|
+
for (const entity of entities) {
|
|
347
|
+
// 继承链推断
|
|
348
|
+
const superclass = entity.superclass;
|
|
349
|
+
if (superclass && superclassMap[superclass]) {
|
|
350
|
+
const role = superclassMap[superclass];
|
|
351
|
+
roleCounts[role] = (roleCounts[role] ?? 0) + 1;
|
|
352
|
+
}
|
|
353
|
+
// 协议推断
|
|
354
|
+
try {
|
|
355
|
+
const protocols = JSON.parse(entity.protocols || '[]');
|
|
356
|
+
for (const proto of protocols) {
|
|
357
|
+
if (protocolMap[proto]) {
|
|
358
|
+
const role = protocolMap[proto];
|
|
359
|
+
roleCounts[role] = (roleCounts[role] ?? 0) + 0.5;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
// ignore malformed JSON
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
// import 模式推断
|
|
368
|
+
const imports = this.#db
|
|
369
|
+
.prepare(`SELECT DISTINCT to_id FROM knowledge_edges
|
|
370
|
+
WHERE from_type = 'module' AND from_id = ? AND relation = 'depends_on'`)
|
|
371
|
+
.all(module.name);
|
|
372
|
+
for (const imp of imports) {
|
|
373
|
+
const depName = imp.to_id.toLowerCase();
|
|
374
|
+
for (const pat of this.#getImportPatterns()) {
|
|
375
|
+
if (pat.regex.test(depName)) {
|
|
376
|
+
roleCounts[pat.role] = (roleCounts[pat.role] ?? 0) + 0.5;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
// 转换为信号
|
|
381
|
+
const totalSignals = Object.values(roleCounts).reduce((a, b) => a + b, 0);
|
|
382
|
+
if (totalSignals > 0) {
|
|
383
|
+
for (const [role, count] of Object.entries(roleCounts)) {
|
|
384
|
+
signals.push({
|
|
385
|
+
role: role,
|
|
386
|
+
confidence: Math.min(count / totalSignals, 1),
|
|
387
|
+
weight: WEIGHTS.ast,
|
|
388
|
+
source: 'ast-structure',
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return signals;
|
|
393
|
+
}
|
|
394
|
+
/** CallGraph 行为信号: 调用流向分析 */
|
|
395
|
+
#extractCallSignals(module) {
|
|
396
|
+
const signals = [];
|
|
397
|
+
// 查模块实体的 call edge 统计
|
|
398
|
+
const filePaths = module.files;
|
|
399
|
+
if (filePaths.length === 0) {
|
|
400
|
+
return signals;
|
|
401
|
+
}
|
|
402
|
+
const placeholders = filePaths.map(() => '?').join(',');
|
|
403
|
+
// fan-out: 模块内实体调用外部
|
|
404
|
+
const outEdges = this.#db
|
|
405
|
+
.prepare(`SELECT COUNT(*) as cnt FROM knowledge_edges ke
|
|
406
|
+
JOIN code_entities ce ON ke.from_id = ce.entity_id AND ke.from_type = ce.entity_type
|
|
407
|
+
WHERE ce.project_root = ? AND ce.file_path IN (${placeholders})
|
|
408
|
+
AND ke.relation = 'calls'`)
|
|
409
|
+
.get(this.#projectRoot, ...filePaths);
|
|
410
|
+
// fan-in: 外部调用模块内实体
|
|
411
|
+
const inEdges = this.#db
|
|
412
|
+
.prepare(`SELECT COUNT(*) as cnt FROM knowledge_edges ke
|
|
413
|
+
JOIN code_entities ce ON ke.to_id = ce.entity_id AND ke.to_type = ce.entity_type
|
|
414
|
+
WHERE ce.project_root = ? AND ce.file_path IN (${placeholders})
|
|
415
|
+
AND ke.relation = 'calls'`)
|
|
416
|
+
.get(this.#projectRoot, ...filePaths);
|
|
417
|
+
const fanOut = Number(outEdges?.cnt ?? 0);
|
|
418
|
+
const fanIn = Number(inEdges?.cnt ?? 0);
|
|
419
|
+
if (fanIn + fanOut === 0) {
|
|
420
|
+
return signals;
|
|
421
|
+
}
|
|
422
|
+
const ratio = fanIn / (fanIn + fanOut);
|
|
423
|
+
// 高被调用 → 偏 core/service (被依赖)
|
|
424
|
+
// 高调用 → 偏 app/ui (消费者)
|
|
425
|
+
if (ratio > 0.7) {
|
|
426
|
+
signals.push({
|
|
427
|
+
role: 'core',
|
|
428
|
+
confidence: ratio * 0.8,
|
|
429
|
+
weight: WEIGHTS.callGraph,
|
|
430
|
+
source: 'call-fanin-heavy',
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
else if (ratio < 0.3) {
|
|
434
|
+
signals.push({
|
|
435
|
+
role: 'ui',
|
|
436
|
+
confidence: (1 - ratio) * 0.6,
|
|
437
|
+
weight: WEIGHTS.callGraph,
|
|
438
|
+
source: 'call-fanout-heavy',
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
signals.push({
|
|
443
|
+
role: 'service',
|
|
444
|
+
confidence: 0.5,
|
|
445
|
+
weight: WEIGHTS.callGraph,
|
|
446
|
+
source: 'call-balanced',
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
return signals;
|
|
450
|
+
}
|
|
451
|
+
/** DataFlow 数据流信号: 源/汇分析 */
|
|
452
|
+
#extractFlowSignals(module) {
|
|
453
|
+
const signals = [];
|
|
454
|
+
const filePaths = module.files;
|
|
455
|
+
if (filePaths.length === 0) {
|
|
456
|
+
return signals;
|
|
457
|
+
}
|
|
458
|
+
const placeholders = filePaths.map(() => '?').join(',');
|
|
459
|
+
// data_flow out (data producer)
|
|
460
|
+
const outFlow = this.#db
|
|
461
|
+
.prepare(`SELECT COUNT(*) as cnt FROM knowledge_edges ke
|
|
462
|
+
JOIN code_entities ce ON ke.from_id = ce.entity_id AND ke.from_type = ce.entity_type
|
|
463
|
+
WHERE ce.project_root = ? AND ce.file_path IN (${placeholders})
|
|
464
|
+
AND ke.relation = 'data_flow'`)
|
|
465
|
+
.get(this.#projectRoot, ...filePaths);
|
|
466
|
+
// data_flow in (data consumer)
|
|
467
|
+
const inFlow = this.#db
|
|
468
|
+
.prepare(`SELECT COUNT(*) as cnt FROM knowledge_edges ke
|
|
469
|
+
JOIN code_entities ce ON ke.to_id = ce.entity_id AND ke.to_type = ce.entity_type
|
|
470
|
+
WHERE ce.project_root = ? AND ce.file_path IN (${placeholders})
|
|
471
|
+
AND ke.relation = 'data_flow'`)
|
|
472
|
+
.get(this.#projectRoot, ...filePaths);
|
|
473
|
+
const out = Number(outFlow?.cnt ?? 0);
|
|
474
|
+
const _in = Number(inFlow?.cnt ?? 0);
|
|
475
|
+
if (out + _in === 0) {
|
|
476
|
+
return signals;
|
|
477
|
+
}
|
|
478
|
+
// 大量产出数据 → model/networking
|
|
479
|
+
if (out > _in * 2) {
|
|
480
|
+
signals.push({
|
|
481
|
+
role: 'model',
|
|
482
|
+
confidence: 0.6,
|
|
483
|
+
weight: WEIGHTS.dataFlow,
|
|
484
|
+
source: 'dataflow-producer',
|
|
485
|
+
});
|
|
486
|
+
}
|
|
487
|
+
// 大量消费数据 → ui
|
|
488
|
+
if (_in > out * 2) {
|
|
489
|
+
signals.push({
|
|
490
|
+
role: 'ui',
|
|
491
|
+
confidence: 0.5,
|
|
492
|
+
weight: WEIGHTS.dataFlow,
|
|
493
|
+
source: 'dataflow-consumer',
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
return signals;
|
|
497
|
+
}
|
|
498
|
+
/** EntityGraph 拓扑信号: 入度分析/模式检测 */
|
|
499
|
+
#extractTopoSignals(module) {
|
|
500
|
+
const signals = [];
|
|
501
|
+
// 查模块下是否有 singleton / delegate 等设计模式
|
|
502
|
+
const patterns = this.#db
|
|
503
|
+
.prepare(`SELECT ke.to_id as pattern_name FROM knowledge_edges ke
|
|
504
|
+
JOIN code_entities ce ON ke.from_id = ce.entity_id
|
|
505
|
+
WHERE ce.project_root = ? AND ke.relation = 'uses_pattern'
|
|
506
|
+
AND ce.entity_id IN (
|
|
507
|
+
SELECT entity_id FROM code_entities
|
|
508
|
+
WHERE project_root = ? AND file_path IN (${module.files.map(() => '?').join(',')})
|
|
509
|
+
)`)
|
|
510
|
+
.all(this.#projectRoot, this.#projectRoot, ...module.files);
|
|
511
|
+
for (const p of patterns) {
|
|
512
|
+
const name = p.pattern_name?.toLowerCase();
|
|
513
|
+
if (!name) {
|
|
514
|
+
continue;
|
|
515
|
+
}
|
|
516
|
+
if (name === 'singleton') {
|
|
517
|
+
signals.push({
|
|
518
|
+
role: 'service',
|
|
519
|
+
confidence: 0.6,
|
|
520
|
+
weight: WEIGHTS.entityGraph,
|
|
521
|
+
source: 'pattern-singleton',
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
if (name === 'delegate') {
|
|
525
|
+
signals.push({
|
|
526
|
+
role: 'ui',
|
|
527
|
+
confidence: 0.4,
|
|
528
|
+
weight: WEIGHTS.entityGraph,
|
|
529
|
+
source: 'pattern-delegate',
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
return signals;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @module BM25Scorer
|
|
8
8
|
*/
|
|
9
|
-
import type { BM25Document, BM25SearchResult } from './SearchTypes.js';
|
|
9
|
+
import type { BM25Document, BM25SearchResult, Scorer } from './SearchTypes.js';
|
|
10
10
|
/** BM25 评分器 */
|
|
11
|
-
export declare class BM25Scorer {
|
|
11
|
+
export declare class BM25Scorer implements Scorer {
|
|
12
12
|
_idIndex: Map<string, number>;
|
|
13
13
|
_totalLength: number;
|
|
14
14
|
avgLength: number;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CoarseRanker — 粗排器
|
|
3
|
-
*
|
|
3
|
+
* 多维加权排序(Recall + Semantic + Freshness + Popularity)
|
|
4
|
+
* Quality 维度保留但默认权重 0 — 待场景化区分后按需启用
|
|
4
5
|
*/
|
|
5
6
|
interface RankerCandidate {
|
|
6
|
-
|
|
7
|
+
recallScore?: number;
|
|
7
8
|
score?: number;
|
|
8
9
|
semanticScore?: number;
|
|
9
10
|
title?: string;
|
|
@@ -23,7 +24,7 @@ interface RankerCandidate {
|
|
|
23
24
|
export declare class CoarseRanker {
|
|
24
25
|
#private;
|
|
25
26
|
constructor(options?: {
|
|
26
|
-
|
|
27
|
+
recallWeight?: number;
|
|
27
28
|
semanticWeight?: number;
|
|
28
29
|
qualityWeight?: number;
|
|
29
30
|
freshnessWeight?: number;
|
|
@@ -31,19 +32,19 @@ export declare class CoarseRanker {
|
|
|
31
32
|
});
|
|
32
33
|
/**
|
|
33
34
|
* 粗排
|
|
34
|
-
* @param candidates 需有
|
|
35
|
+
* @param candidates 需有 recallScore、semanticScore 等字段
|
|
35
36
|
* @returns sorted with coarseScore
|
|
36
37
|
*/
|
|
37
38
|
rank(candidates: RankerCandidate[]): {
|
|
38
39
|
coarseScore: number;
|
|
39
40
|
coarseSignals: {
|
|
40
|
-
|
|
41
|
+
recall: number;
|
|
41
42
|
semantic: number;
|
|
42
43
|
quality: number;
|
|
43
44
|
freshness: number;
|
|
44
45
|
popularity: number;
|
|
45
46
|
};
|
|
46
|
-
|
|
47
|
+
recallScore?: number;
|
|
47
48
|
score?: number;
|
|
48
49
|
semanticScore?: number;
|
|
49
50
|
title?: string;
|
|
@@ -1,21 +1,22 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CoarseRanker — 粗排器
|
|
3
|
-
*
|
|
3
|
+
* 多维加权排序(Recall + Semantic + Freshness + Popularity)
|
|
4
|
+
* Quality 维度保留但默认权重 0 — 待场景化区分后按需启用
|
|
4
5
|
*/
|
|
5
6
|
export class CoarseRanker {
|
|
6
7
|
#weights;
|
|
7
8
|
constructor(options = {}) {
|
|
8
9
|
this.#weights = {
|
|
9
|
-
|
|
10
|
+
recall: options.recallWeight ?? 0.45,
|
|
10
11
|
semantic: options.semanticWeight ?? 0.3,
|
|
11
|
-
quality: options.qualityWeight ?? 0
|
|
12
|
-
freshness: options.freshnessWeight ?? 0.
|
|
12
|
+
quality: options.qualityWeight ?? 0,
|
|
13
|
+
freshness: options.freshnessWeight ?? 0.15,
|
|
13
14
|
popularity: options.popularityWeight ?? 0.1,
|
|
14
15
|
};
|
|
15
16
|
}
|
|
16
17
|
/**
|
|
17
18
|
* 粗排
|
|
18
|
-
* @param candidates 需有
|
|
19
|
+
* @param candidates 需有 recallScore、semanticScore 等字段
|
|
19
20
|
* @returns sorted with coarseScore
|
|
20
21
|
*/
|
|
21
22
|
rank(candidates) {
|
|
@@ -38,16 +39,16 @@ export class CoarseRanker {
|
|
|
38
39
|
}
|
|
39
40
|
effectiveWeights.semantic = 0;
|
|
40
41
|
}
|
|
41
|
-
//
|
|
42
|
-
const
|
|
42
|
+
// 召回分数 max-based 归一化(保留相对排序,避免 clamp 截断高分差异)
|
|
43
|
+
const maxRecall = candidates.reduce((m, c) => Math.max(m, c.recallScore || c.score || 0), 0) || 1;
|
|
43
44
|
return candidates
|
|
44
45
|
.map((c) => {
|
|
45
|
-
const
|
|
46
|
+
const recall = Math.min((c.recallScore || c.score || 0) / maxRecall, 1.0);
|
|
46
47
|
const semantic = this.#normalize(c.semanticScore || 0);
|
|
47
48
|
const quality = this.#computeQuality(c);
|
|
48
49
|
const freshness = this.#computeFreshness(c);
|
|
49
50
|
const popularity = this.#computePopularity(c);
|
|
50
|
-
const coarseScore =
|
|
51
|
+
const coarseScore = recall * effectiveWeights.recall +
|
|
51
52
|
semantic * effectiveWeights.semantic +
|
|
52
53
|
quality * effectiveWeights.quality +
|
|
53
54
|
freshness * effectiveWeights.freshness +
|
|
@@ -55,7 +56,7 @@ export class CoarseRanker {
|
|
|
55
56
|
return {
|
|
56
57
|
...c,
|
|
57
58
|
coarseScore,
|
|
58
|
-
coarseSignals: {
|
|
59
|
+
coarseSignals: { recall, semantic, quality, freshness, popularity },
|
|
59
60
|
};
|
|
60
61
|
})
|
|
61
62
|
.sort((a, b) => b.coarseScore - a.coarseScore);
|