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
|
@@ -20,6 +20,25 @@ export interface BM25SearchResult {
|
|
|
20
20
|
score: number;
|
|
21
21
|
meta: Record<string, unknown>;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Scorer 通用接口 — BM25Scorer 与 FieldWeightedScorer 共同实现
|
|
25
|
+
*
|
|
26
|
+
* SearchEngine 通过此接口与具体评分器解耦,可在运行时切换。
|
|
27
|
+
*/
|
|
28
|
+
export interface Scorer {
|
|
29
|
+
totalDocs: number;
|
|
30
|
+
avgLength: number;
|
|
31
|
+
docFreq: Record<string, number>;
|
|
32
|
+
documents: ({
|
|
33
|
+
id: string;
|
|
34
|
+
} | null)[];
|
|
35
|
+
addDocument(id: string, text: string, meta: Record<string, unknown>): void;
|
|
36
|
+
removeDocument(id: string): boolean;
|
|
37
|
+
updateDocument(id: string, text: string, meta: Record<string, unknown>): void;
|
|
38
|
+
hasDocument(id: string): boolean;
|
|
39
|
+
search(query: string, limit?: number): BM25SearchResult[];
|
|
40
|
+
clear(): void;
|
|
41
|
+
}
|
|
23
42
|
/** Meta structure produced by _buildDocMeta */
|
|
24
43
|
export interface BM25DocMeta {
|
|
25
44
|
type: string;
|
|
@@ -56,7 +75,6 @@ export interface SearchResultItem {
|
|
|
56
75
|
headers?: string;
|
|
57
76
|
moduleName?: string;
|
|
58
77
|
knowledgeType?: string;
|
|
59
|
-
bm25Score?: number;
|
|
60
78
|
qualityScore?: number;
|
|
61
79
|
usageCount?: number;
|
|
62
80
|
authorityScore?: number;
|
|
@@ -178,6 +196,7 @@ export interface RrfHit {
|
|
|
178
196
|
[key: string]: unknown;
|
|
179
197
|
}
|
|
180
198
|
/** Cross-encoder reranker abstraction */
|
|
199
|
+
import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
|
|
181
200
|
export interface SearchCrossEncoder {
|
|
182
201
|
rerank(query: string, candidates: SearchResultItem[]): Promise<SearchResultItem[]>;
|
|
183
202
|
}
|
|
@@ -188,8 +207,9 @@ export interface SearchEngineOptions {
|
|
|
188
207
|
vectorService?: SearchVectorService | null;
|
|
189
208
|
hybridRetriever?: SearchHybridRetriever | null;
|
|
190
209
|
crossEncoderReranker?: SearchCrossEncoder | null;
|
|
210
|
+
signalBus?: SignalBus | null;
|
|
191
211
|
cacheMaxAge?: number;
|
|
192
|
-
|
|
212
|
+
fusionRecallWeight?: number;
|
|
193
213
|
fusionSemanticWeight?: number;
|
|
194
214
|
[key: string]: unknown;
|
|
195
215
|
}
|
|
@@ -208,12 +228,14 @@ export interface SlimSearchResult {
|
|
|
208
228
|
actionHint?: string;
|
|
209
229
|
/** 知识类型 (code-standard/code-pattern/...) — Bridge 场景需要 */
|
|
210
230
|
knowledgeType?: string;
|
|
231
|
+
/** 已验证的项目来源文件路径(可信度证据链) */
|
|
232
|
+
sourceRefs?: string[];
|
|
211
233
|
}
|
|
212
234
|
/**
|
|
213
235
|
* 统一投影函数 — 将 SearchResultItem 投影为 SlimSearchResult。
|
|
214
236
|
*
|
|
215
237
|
* 合并了 mcp/search.ts#_slimSearchItem() 和 TaskKnowledgeBridge#_projectItem() 的逻辑:
|
|
216
|
-
* - 去除内部信号 (
|
|
238
|
+
* - 去除内部信号 (recallScore, coarseScore, rankerScore, contextScore, content, code...)
|
|
217
239
|
* - description 截断 120 字符
|
|
218
240
|
* - 生成 actionHint (whenClause → doClause)
|
|
219
241
|
*
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* 统一投影函数 — 将 SearchResultItem 投影为 SlimSearchResult。
|
|
11
11
|
*
|
|
12
12
|
* 合并了 mcp/search.ts#_slimSearchItem() 和 TaskKnowledgeBridge#_projectItem() 的逻辑:
|
|
13
|
-
* - 去除内部信号 (
|
|
13
|
+
* - 去除内部信号 (recallScore, coarseScore, rankerScore, contextScore, content, code...)
|
|
14
14
|
* - description 截断 120 字符
|
|
15
15
|
* - 生成 actionHint (whenClause → doClause)
|
|
16
16
|
*
|
|
@@ -23,6 +23,10 @@ export function slimSearchResult(item) {
|
|
|
23
23
|
const actionHint = doText || whenText
|
|
24
24
|
? `${whenText ? `${whenText} → ` : ''}${doText}`.replace(/ → $/, '')
|
|
25
25
|
: undefined;
|
|
26
|
+
const rawRefs = item.sourceRefs;
|
|
27
|
+
const sourceRefs = Array.isArray(rawRefs) && rawRefs.length > 0
|
|
28
|
+
? rawRefs.filter((s) => typeof s === 'string' && s.length > 0)
|
|
29
|
+
: undefined;
|
|
26
30
|
return {
|
|
27
31
|
id: item.id,
|
|
28
32
|
title: item.title || '',
|
|
@@ -33,6 +37,7 @@ export function slimSearchResult(item) {
|
|
|
33
37
|
description: (item.description || '').slice(0, 120),
|
|
34
38
|
actionHint,
|
|
35
39
|
knowledgeType: item.knowledgeType || undefined,
|
|
40
|
+
sourceRefs,
|
|
36
41
|
};
|
|
37
42
|
}
|
|
38
43
|
/** items → byKind 分组(统一实现) */
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HitRecorder — 批量使用信号采集器
|
|
3
|
+
*
|
|
4
|
+
* Phase 0 核心服务。将高频使用事件(Guard 命中、搜索命中、采用等)
|
|
5
|
+
* 先写入内存 buffer,定时批量持久化到 Stats JSON,同时发射 SignalBus 信号。
|
|
6
|
+
*
|
|
7
|
+
* 设计要点:
|
|
8
|
+
* - 即时 emit Signal(信号不延迟)
|
|
9
|
+
* - buffer → 30s flush → 批量 UPDATE(减少 SQLite 写)
|
|
10
|
+
* - shutdown hook 保证进程退出前数据落盘
|
|
11
|
+
*
|
|
12
|
+
* @module service/signal/HitRecorder
|
|
13
|
+
*/
|
|
14
|
+
import type { SignalBus } from '#infra/signal/SignalBus.js';
|
|
15
|
+
/** better-sqlite3 兼容类型(与 GuardCheckEngine 相同模式) */
|
|
16
|
+
interface DatabaseLike {
|
|
17
|
+
prepare(sql: string): {
|
|
18
|
+
run(...params: unknown[]): unknown;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** 支持的命中事件类型 */
|
|
22
|
+
export type HitEventType = 'guardHit' | 'searchHit' | 'view' | 'adoption' | 'application';
|
|
23
|
+
/** HitRecorder 配置 */
|
|
24
|
+
export interface HitRecorderConfig {
|
|
25
|
+
/** flush 间隔(ms),默认 30000 */
|
|
26
|
+
flushIntervalMs?: number;
|
|
27
|
+
/** 立即 flush 的最大缓冲条目数,默认 100 */
|
|
28
|
+
maxBufferSize?: number;
|
|
29
|
+
}
|
|
30
|
+
export declare class HitRecorder {
|
|
31
|
+
#private;
|
|
32
|
+
constructor(bus: SignalBus, db: DatabaseLike | {
|
|
33
|
+
getDb(): DatabaseLike;
|
|
34
|
+
}, config?: HitRecorderConfig);
|
|
35
|
+
/**
|
|
36
|
+
* 启动定时 flush。通常在服务初始化时调用。
|
|
37
|
+
*/
|
|
38
|
+
start(): void;
|
|
39
|
+
/**
|
|
40
|
+
* 停止定时 flush 并执行最后一次 flush。
|
|
41
|
+
* 供 shutdown hook 调用。
|
|
42
|
+
*/
|
|
43
|
+
stop(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* 记录一次命中事件。
|
|
46
|
+
*
|
|
47
|
+
* 1. 立即通过 SignalBus 发射信号(信号不延迟)
|
|
48
|
+
* 2. 事件写入内存 buffer,等待 flush 批量持久化
|
|
49
|
+
*
|
|
50
|
+
* @param recipeId 关联的知识条目 ID
|
|
51
|
+
* @param eventType 事件类型
|
|
52
|
+
* @param value 信号强度 0-1(默认 1)
|
|
53
|
+
* @param metadata 附加元数据
|
|
54
|
+
*/
|
|
55
|
+
record(recipeId: string, eventType: HitEventType, value?: number, metadata?: Record<string, unknown>): void;
|
|
56
|
+
/**
|
|
57
|
+
* 批量持久化 buffer 到数据库。
|
|
58
|
+
* 使用 json_set 原子更新 Stats JSON 中对应字段。
|
|
59
|
+
*/
|
|
60
|
+
flush(): Promise<number>;
|
|
61
|
+
/** 当前 buffer 中的条目数(诊断用) */
|
|
62
|
+
get bufferSize(): number;
|
|
63
|
+
/** 累计记录次数 */
|
|
64
|
+
get totalRecorded(): number;
|
|
65
|
+
/** 累计已持久化次数 */
|
|
66
|
+
get totalFlushed(): number;
|
|
67
|
+
}
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HitRecorder — 批量使用信号采集器
|
|
3
|
+
*
|
|
4
|
+
* Phase 0 核心服务。将高频使用事件(Guard 命中、搜索命中、采用等)
|
|
5
|
+
* 先写入内存 buffer,定时批量持久化到 Stats JSON,同时发射 SignalBus 信号。
|
|
6
|
+
*
|
|
7
|
+
* 设计要点:
|
|
8
|
+
* - 即时 emit Signal(信号不延迟)
|
|
9
|
+
* - buffer → 30s flush → 批量 UPDATE(减少 SQLite 写)
|
|
10
|
+
* - shutdown hook 保证进程退出前数据落盘
|
|
11
|
+
*
|
|
12
|
+
* @module service/signal/HitRecorder
|
|
13
|
+
*/
|
|
14
|
+
/** 事件类型 → Stats JSON 字段 映射 */
|
|
15
|
+
const EVENT_TO_STATS_FIELD = {
|
|
16
|
+
guardHit: 'guardHits',
|
|
17
|
+
searchHit: 'searchHits',
|
|
18
|
+
view: 'views',
|
|
19
|
+
adoption: 'adoptions',
|
|
20
|
+
application: 'applications',
|
|
21
|
+
};
|
|
22
|
+
/** 事件类型 → SignalBus 信号类型 映射 */
|
|
23
|
+
const EVENT_TO_SIGNAL_TYPE = {
|
|
24
|
+
guardHit: 'guard',
|
|
25
|
+
searchHit: 'search',
|
|
26
|
+
view: 'usage',
|
|
27
|
+
adoption: 'usage',
|
|
28
|
+
application: 'usage',
|
|
29
|
+
};
|
|
30
|
+
// ── HitRecorder ─────────────────────────────────────
|
|
31
|
+
export class HitRecorder {
|
|
32
|
+
#bus;
|
|
33
|
+
#db;
|
|
34
|
+
#buffer = new Map();
|
|
35
|
+
#flushIntervalMs;
|
|
36
|
+
#maxBufferSize;
|
|
37
|
+
#timer = null;
|
|
38
|
+
#totalRecorded = 0;
|
|
39
|
+
#totalFlushed = 0;
|
|
40
|
+
constructor(bus, db, config = {}) {
|
|
41
|
+
this.#bus = bus;
|
|
42
|
+
this.#db =
|
|
43
|
+
'getDb' in db && typeof db.getDb === 'function'
|
|
44
|
+
? db.getDb()
|
|
45
|
+
: db;
|
|
46
|
+
this.#flushIntervalMs = config.flushIntervalMs ?? 30_000;
|
|
47
|
+
this.#maxBufferSize = config.maxBufferSize ?? 100;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 启动定时 flush。通常在服务初始化时调用。
|
|
51
|
+
*/
|
|
52
|
+
start() {
|
|
53
|
+
if (this.#timer) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
this.#timer = setInterval(() => {
|
|
57
|
+
void this.flush();
|
|
58
|
+
}, this.#flushIntervalMs);
|
|
59
|
+
this.#timer.unref(); // 不阻止进程退出
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 停止定时 flush 并执行最后一次 flush。
|
|
63
|
+
* 供 shutdown hook 调用。
|
|
64
|
+
*/
|
|
65
|
+
async stop() {
|
|
66
|
+
if (this.#timer) {
|
|
67
|
+
clearInterval(this.#timer);
|
|
68
|
+
this.#timer = null;
|
|
69
|
+
}
|
|
70
|
+
await this.flush();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 记录一次命中事件。
|
|
74
|
+
*
|
|
75
|
+
* 1. 立即通过 SignalBus 发射信号(信号不延迟)
|
|
76
|
+
* 2. 事件写入内存 buffer,等待 flush 批量持久化
|
|
77
|
+
*
|
|
78
|
+
* @param recipeId 关联的知识条目 ID
|
|
79
|
+
* @param eventType 事件类型
|
|
80
|
+
* @param value 信号强度 0-1(默认 1)
|
|
81
|
+
* @param metadata 附加元数据
|
|
82
|
+
*/
|
|
83
|
+
record(recipeId, eventType, value = 1, metadata = {}) {
|
|
84
|
+
this.#totalRecorded++;
|
|
85
|
+
// 1. 即时发射信号
|
|
86
|
+
this.#bus.send(EVENT_TO_SIGNAL_TYPE[eventType], `HitRecorder.${eventType}`, value, {
|
|
87
|
+
target: recipeId,
|
|
88
|
+
metadata: { ...metadata, eventType },
|
|
89
|
+
});
|
|
90
|
+
// 2. 聚合进 buffer
|
|
91
|
+
const key = `${recipeId}:${eventType}`;
|
|
92
|
+
const now = Date.now();
|
|
93
|
+
const existing = this.#buffer.get(key);
|
|
94
|
+
if (existing) {
|
|
95
|
+
existing.count++;
|
|
96
|
+
existing.lastAt = now;
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
this.#buffer.set(key, {
|
|
100
|
+
recipeId,
|
|
101
|
+
eventType,
|
|
102
|
+
count: 1,
|
|
103
|
+
firstAt: now,
|
|
104
|
+
lastAt: now,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// 3. buffer 满时立即 flush
|
|
108
|
+
if (this.#buffer.size >= this.#maxBufferSize) {
|
|
109
|
+
void this.flush();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* 批量持久化 buffer 到数据库。
|
|
114
|
+
* 使用 json_set 原子更新 Stats JSON 中对应字段。
|
|
115
|
+
*/
|
|
116
|
+
async flush() {
|
|
117
|
+
if (this.#buffer.size === 0) {
|
|
118
|
+
return 0;
|
|
119
|
+
}
|
|
120
|
+
// 取出当前 buffer 并清空(后续 record 写入新 buffer)
|
|
121
|
+
const entries = [...this.#buffer.values()];
|
|
122
|
+
this.#buffer.clear();
|
|
123
|
+
let flushed = 0;
|
|
124
|
+
const now = Math.floor(Date.now() / 1000);
|
|
125
|
+
try {
|
|
126
|
+
const stmt = this.#db.prepare(`UPDATE knowledge_entries
|
|
127
|
+
SET stats = json_set(
|
|
128
|
+
COALESCE(stats, '{}'),
|
|
129
|
+
'$.' || ?,
|
|
130
|
+
COALESCE(json_extract(stats, '$.' || ?), 0) + ?
|
|
131
|
+
),
|
|
132
|
+
updatedAt = ?
|
|
133
|
+
WHERE id = ?`);
|
|
134
|
+
for (const entry of entries) {
|
|
135
|
+
const field = EVENT_TO_STATS_FIELD[entry.eventType];
|
|
136
|
+
try {
|
|
137
|
+
stmt.run(field, field, entry.count, now, entry.recipeId);
|
|
138
|
+
flushed += entry.count;
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
// Recipe 可能已被删除,静默忽略
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// DB statement prepare 失败(表可能不存在),回填 buffer
|
|
147
|
+
for (const entry of entries) {
|
|
148
|
+
const key = `${entry.recipeId}:${entry.eventType}`;
|
|
149
|
+
const existing = this.#buffer.get(key);
|
|
150
|
+
if (existing) {
|
|
151
|
+
existing.count += entry.count;
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
this.#buffer.set(key, entry);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
this.#totalFlushed += flushed;
|
|
159
|
+
return flushed;
|
|
160
|
+
}
|
|
161
|
+
/** 当前 buffer 中的条目数(诊断用) */
|
|
162
|
+
get bufferSize() {
|
|
163
|
+
return this.#buffer.size;
|
|
164
|
+
}
|
|
165
|
+
/** 累计记录次数 */
|
|
166
|
+
get totalRecorded() {
|
|
167
|
+
return this.#totalRecorded;
|
|
168
|
+
}
|
|
169
|
+
/** 累计已持久化次数 */
|
|
170
|
+
get totalFlushed() {
|
|
171
|
+
return this.#totalFlushed;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -41,6 +41,7 @@ interface SignalCollectorOpts {
|
|
|
41
41
|
database?: DatabaseLike | null;
|
|
42
42
|
agentFactory?: AgentFactoryLike | null;
|
|
43
43
|
container?: ContainerLike | null;
|
|
44
|
+
signalBus?: import('../../infrastructure/signal/SignalBus.js').SignalBus | null;
|
|
44
45
|
mode?: string;
|
|
45
46
|
intervalMs?: number;
|
|
46
47
|
onSuggestions?: ((suggestions: Record<string, unknown>[]) => void) | null;
|
|
@@ -80,11 +81,12 @@ export declare class SignalCollector {
|
|
|
80
81
|
* @param [opts.database] better-sqlite3 实例
|
|
81
82
|
* @param [opts.agentFactory] AgentFactory 实例
|
|
82
83
|
* @param [opts.container] ServiceContainer 实例
|
|
84
|
+
* @param [opts.signalBus] SignalBus 实例(实时信号订阅)
|
|
83
85
|
* @param [opts.mode] 'off' | 'suggest' | 'auto'
|
|
84
86
|
* @param [opts.intervalMs] 初始收集间隔(毫秒),后续由 AI 动态调整
|
|
85
87
|
* @param [opts.onSuggestions] 新建议回调 (suggestions[]) => void
|
|
86
88
|
*/
|
|
87
|
-
constructor({ projectRoot, database, agentFactory, container, mode, intervalMs, onSuggestions, }: SignalCollectorOpts);
|
|
89
|
+
constructor({ projectRoot, database, agentFactory, container, signalBus, mode, intervalMs, onSuggestions, }: SignalCollectorOpts);
|
|
88
90
|
start(): void;
|
|
89
91
|
stop(): void;
|
|
90
92
|
/**
|
|
@@ -62,16 +62,19 @@ export class SignalCollector {
|
|
|
62
62
|
#onSuggestions;
|
|
63
63
|
/** 信号聚类引擎 */
|
|
64
64
|
#aggregator;
|
|
65
|
+
/** 各维度最新信号快照(由 SignalBus 实时更新) */
|
|
66
|
+
#dimensionSignals = {};
|
|
65
67
|
/**
|
|
66
68
|
* @param opts.projectRoot 用户项目根目录
|
|
67
69
|
* @param [opts.database] better-sqlite3 实例
|
|
68
70
|
* @param [opts.agentFactory] AgentFactory 实例
|
|
69
71
|
* @param [opts.container] ServiceContainer 实例
|
|
72
|
+
* @param [opts.signalBus] SignalBus 实例(实时信号订阅)
|
|
70
73
|
* @param [opts.mode] 'off' | 'suggest' | 'auto'
|
|
71
74
|
* @param [opts.intervalMs] 初始收集间隔(毫秒),后续由 AI 动态调整
|
|
72
75
|
* @param [opts.onSuggestions] 新建议回调 (suggestions[]) => void
|
|
73
76
|
*/
|
|
74
|
-
constructor({ projectRoot, database = null, agentFactory = null, container = null, mode = 'auto', intervalMs = DEFAULT_INTERVAL_MS, onSuggestions = null, }) {
|
|
77
|
+
constructor({ projectRoot, database = null, agentFactory = null, container = null, signalBus = null, mode = 'auto', intervalMs = DEFAULT_INTERVAL_MS, onSuggestions = null, }) {
|
|
75
78
|
this.#projectRoot = projectRoot;
|
|
76
79
|
this.#db = database;
|
|
77
80
|
this.#agentFactory = agentFactory;
|
|
@@ -94,6 +97,12 @@ export class SignalCollector {
|
|
|
94
97
|
this.#timer = setTimeout(() => this.#tick(), 3000); // 3 秒后执行,留出更多聚合时间
|
|
95
98
|
}
|
|
96
99
|
});
|
|
100
|
+
// Phase 2: 订阅 SignalBus 全量信号,维护维度快照
|
|
101
|
+
if (signalBus) {
|
|
102
|
+
signalBus.subscribe('*', (signal) => {
|
|
103
|
+
this.#updateDimension(signal);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
97
106
|
}
|
|
98
107
|
// ═══════════════════════════════════════════════════════
|
|
99
108
|
// 公共 API
|
|
@@ -144,6 +153,27 @@ export class SignalCollector {
|
|
|
144
153
|
getSnapshot() {
|
|
145
154
|
return { ...this.#snapshot };
|
|
146
155
|
}
|
|
156
|
+
/** 由 SignalBus 实时更新的维度信号快照 */
|
|
157
|
+
#updateDimension(signal) {
|
|
158
|
+
switch (signal.type) {
|
|
159
|
+
case 'guard':
|
|
160
|
+
case 'guard_blind_spot':
|
|
161
|
+
this.#dimensionSignals.compliance = signal;
|
|
162
|
+
break;
|
|
163
|
+
case 'usage':
|
|
164
|
+
this.#dimensionSignals.adoption = signal;
|
|
165
|
+
break;
|
|
166
|
+
case 'quality':
|
|
167
|
+
this.#dimensionSignals.quality = signal;
|
|
168
|
+
break;
|
|
169
|
+
case 'decay':
|
|
170
|
+
this.#dimensionSignals.decay = signal;
|
|
171
|
+
break;
|
|
172
|
+
case 'lifecycle':
|
|
173
|
+
this.#dimensionSignals.evolution = signal;
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
147
177
|
getMode() {
|
|
148
178
|
return this.#mode;
|
|
149
179
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IntentExtractor — Intake Layer
|
|
3
|
+
*
|
|
4
|
+
* Pure functions: extract intent signals from user query + active file.
|
|
5
|
+
* Builds multi-query set, infers language/module/scenario for search routing.
|
|
6
|
+
*
|
|
7
|
+
* @module service/task/IntentExtractor
|
|
8
|
+
*/
|
|
9
|
+
export type SearchScenario = 'lint' | 'generate' | 'search' | 'learning';
|
|
10
|
+
export interface ExtractedIntent {
|
|
11
|
+
/** Multi-query set: Q1 raw + Q2 tech terms + Q3 file context */
|
|
12
|
+
queries: string[];
|
|
13
|
+
/** Cross-language synonym queries (run in keyword mode to bypass semantic normalization) */
|
|
14
|
+
keywordQueries: string[];
|
|
15
|
+
/** Inferred language from activeFile or args */
|
|
16
|
+
language: string | null;
|
|
17
|
+
/** Inferred module path from activeFile */
|
|
18
|
+
module: string | null;
|
|
19
|
+
/** Search scenario for MultiSignalRanker routing */
|
|
20
|
+
scenario: SearchScenario;
|
|
21
|
+
/** Original inputs */
|
|
22
|
+
raw: {
|
|
23
|
+
userQuery: string;
|
|
24
|
+
activeFile?: string;
|
|
25
|
+
language?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export interface TechTermOptions {
|
|
29
|
+
/** Project-specific class prefixes, e.g. ['BD', 'BBA', 'KS'] */
|
|
30
|
+
projectPrefixes?: string[];
|
|
31
|
+
/** Language/platform common prefixes, e.g. ObjC: ['UI', 'NS', 'CA', 'AV'] */
|
|
32
|
+
platformPrefixes?: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract intent signals from user query and active file.
|
|
36
|
+
* Pure function — no side effects, no DI.
|
|
37
|
+
*/
|
|
38
|
+
export declare function extract(userQuery: string, activeFile?: string, language?: string, termOpts?: TechTermOptions): ExtractedIntent;
|
|
39
|
+
/**
|
|
40
|
+
* Build multi-query set from user query + active file.
|
|
41
|
+
* Q1: raw query, Q2: extracted tech terms, Q3: file context.
|
|
42
|
+
* Q1 is enriched with cross-language synonyms to bridge EN↔CJK matching.
|
|
43
|
+
*/
|
|
44
|
+
export declare function buildQueries(userQuery: string, activeFile?: string, termOpts?: TechTermOptions): string[];
|
|
45
|
+
/**
|
|
46
|
+
* Build keyword-mode queries for cross-language synonym matching.
|
|
47
|
+
* Uses keyword mode to preserve raw FWS scores without CoarseRanker semantic normalization.
|
|
48
|
+
*/
|
|
49
|
+
export declare function buildKeywordQueries(userQuery: string): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Extract tech terms from query using universal patterns + dynamic project prefixes.
|
|
52
|
+
*/
|
|
53
|
+
export declare function extractTechTerms(query: string, opts?: TechTermOptions): string[];
|
|
54
|
+
/**
|
|
55
|
+
* Infer file context string from file path for search augmentation.
|
|
56
|
+
* Returns module path + class name, e.g. "Services/Network BDNetworkManager"
|
|
57
|
+
*/
|
|
58
|
+
export declare function inferFileContext(filePath: string): string | null;
|
|
59
|
+
/**
|
|
60
|
+
* Infer language from file extension.
|
|
61
|
+
*/
|
|
62
|
+
export declare function inferLanguage(filePath: string): string | null;
|
|
63
|
+
/**
|
|
64
|
+
* Classify search scenario from user query (lightweight rule-based).
|
|
65
|
+
*/
|
|
66
|
+
export declare function classifyScenario(userQuery: string): SearchScenario;
|