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,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReportStore — 报告持久化服务
|
|
3
|
+
*
|
|
4
|
+
* 管道产物(governance / compliance / metrics / analysis)写入 JSONL,
|
|
5
|
+
* 供 API 查询历史报告。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/report/ReportStore
|
|
8
|
+
*/
|
|
9
|
+
import { randomBytes } from 'node:crypto';
|
|
10
|
+
import fs from 'node:fs';
|
|
11
|
+
import path from 'node:path';
|
|
12
|
+
// ── Constants ───────────────────────────────────────
|
|
13
|
+
const VALID_CATEGORIES = new Set([
|
|
14
|
+
'governance',
|
|
15
|
+
'compliance',
|
|
16
|
+
'metrics',
|
|
17
|
+
'analysis',
|
|
18
|
+
]);
|
|
19
|
+
// ── ReportStore ─────────────────────────────────────
|
|
20
|
+
export class ReportStore {
|
|
21
|
+
#baseDir;
|
|
22
|
+
constructor(baseDir) {
|
|
23
|
+
this.#baseDir = baseDir;
|
|
24
|
+
}
|
|
25
|
+
/** 写入一条报告(追加 JSONL) */
|
|
26
|
+
async write(entry) {
|
|
27
|
+
const id = ReportStore.#generateId(entry.timestamp);
|
|
28
|
+
const full = { id, ...entry };
|
|
29
|
+
const filePath = this.#resolveFile(entry.category, entry.timestamp);
|
|
30
|
+
const dir = path.dirname(filePath);
|
|
31
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
+
fs.appendFileSync(filePath, `${JSON.stringify(full)}\n`, 'utf8');
|
|
33
|
+
return full;
|
|
34
|
+
}
|
|
35
|
+
/** 查询报告列表 */
|
|
36
|
+
async query(opts = {}) {
|
|
37
|
+
const categories = opts.category?.length
|
|
38
|
+
? opts.category.filter((c) => VALID_CATEGORIES.has(c))
|
|
39
|
+
: [...VALID_CATEGORIES];
|
|
40
|
+
const all = [];
|
|
41
|
+
for (const cat of categories) {
|
|
42
|
+
const catDir = path.join(this.#baseDir, cat);
|
|
43
|
+
if (!fs.existsSync(catDir)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const files = fs
|
|
47
|
+
.readdirSync(catDir)
|
|
48
|
+
.filter((f) => f.endsWith('.jsonl'))
|
|
49
|
+
.sort()
|
|
50
|
+
.reverse();
|
|
51
|
+
for (const file of files) {
|
|
52
|
+
const entries = this.#readJsonl(path.join(catDir, file));
|
|
53
|
+
all.push(...entries);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 过滤
|
|
57
|
+
let filtered = all;
|
|
58
|
+
if (opts.type) {
|
|
59
|
+
filtered = filtered.filter((e) => e.type === opts.type);
|
|
60
|
+
}
|
|
61
|
+
if (opts.from) {
|
|
62
|
+
filtered = filtered.filter((e) => e.timestamp >= opts.from);
|
|
63
|
+
}
|
|
64
|
+
if (opts.to) {
|
|
65
|
+
filtered = filtered.filter((e) => e.timestamp <= opts.to);
|
|
66
|
+
}
|
|
67
|
+
// 按时间倒序
|
|
68
|
+
filtered.sort((a, b) => b.timestamp - a.timestamp);
|
|
69
|
+
const total = filtered.length;
|
|
70
|
+
const offset = opts.offset ?? 0;
|
|
71
|
+
const limit = opts.limit ?? 20;
|
|
72
|
+
const reports = filtered.slice(offset, offset + limit);
|
|
73
|
+
return { reports, total };
|
|
74
|
+
}
|
|
75
|
+
/** 分类统计 */
|
|
76
|
+
async stats(opts = {}) {
|
|
77
|
+
const result = {};
|
|
78
|
+
for (const cat of VALID_CATEGORIES) {
|
|
79
|
+
const catDir = path.join(this.#baseDir, cat);
|
|
80
|
+
if (!fs.existsSync(catDir)) {
|
|
81
|
+
result[cat] = 0;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const files = fs.readdirSync(catDir).filter((f) => f.endsWith('.jsonl'));
|
|
85
|
+
let count = 0;
|
|
86
|
+
for (const file of files) {
|
|
87
|
+
const entries = this.#readJsonl(path.join(catDir, file));
|
|
88
|
+
for (const e of entries) {
|
|
89
|
+
if (opts.from && e.timestamp < opts.from) {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (opts.to && e.timestamp > opts.to) {
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
count++;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
result[cat] = count;
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
// ── Private ───────────────────────────────────────
|
|
103
|
+
#resolveFile(category, timestamp) {
|
|
104
|
+
const d = new Date(timestamp);
|
|
105
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
106
|
+
return path.join(this.#baseDir, category, `${dateStr}.jsonl`);
|
|
107
|
+
}
|
|
108
|
+
#readJsonl(filePath) {
|
|
109
|
+
try {
|
|
110
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
111
|
+
const lines = content.split('\n').filter((l) => l.trim());
|
|
112
|
+
const entries = [];
|
|
113
|
+
for (const line of lines) {
|
|
114
|
+
try {
|
|
115
|
+
entries.push(JSON.parse(line));
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// 跳过损坏行
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return entries;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
static #generateId(timestamp) {
|
|
128
|
+
const d = new Date(timestamp);
|
|
129
|
+
const dateStr = `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;
|
|
130
|
+
const rand = randomBytes(4).toString('hex');
|
|
131
|
+
return `rpt-${dateStr}-${rand}`;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalAggregator — 滑窗统计 + 异常检测
|
|
3
|
+
*
|
|
4
|
+
* 订阅可聚合的事实型信号,周期性写入 Report(统计)并在异常时发射 Signal。
|
|
5
|
+
*
|
|
6
|
+
* @module infrastructure/signal/SignalAggregator
|
|
7
|
+
*/
|
|
8
|
+
import type { ReportStore } from '../report/ReportStore.js';
|
|
9
|
+
import type { SignalBus } from './SignalBus.js';
|
|
10
|
+
export declare class SignalAggregator {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(signalBus: SignalBus, reportStore: ReportStore, opts?: {
|
|
13
|
+
intervalMs?: number;
|
|
14
|
+
windowMs?: number;
|
|
15
|
+
});
|
|
16
|
+
start(): void;
|
|
17
|
+
stop(): void;
|
|
18
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalAggregator — 滑窗统计 + 异常检测
|
|
3
|
+
*
|
|
4
|
+
* 订阅可聚合的事实型信号,周期性写入 Report(统计)并在异常时发射 Signal。
|
|
5
|
+
*
|
|
6
|
+
* @module infrastructure/signal/SignalAggregator
|
|
7
|
+
*/
|
|
8
|
+
export class SignalAggregator {
|
|
9
|
+
#bus;
|
|
10
|
+
#reportStore;
|
|
11
|
+
#windows = new Map();
|
|
12
|
+
#intervalMs;
|
|
13
|
+
#windowMs;
|
|
14
|
+
#timer = null;
|
|
15
|
+
constructor(signalBus, reportStore, opts = {}) {
|
|
16
|
+
this.#bus = signalBus;
|
|
17
|
+
this.#reportStore = reportStore;
|
|
18
|
+
this.#intervalMs = opts.intervalMs ?? 60_000;
|
|
19
|
+
this.#windowMs = opts.windowMs ?? 300_000;
|
|
20
|
+
// 订阅可聚合的事实型信号
|
|
21
|
+
signalBus.subscribe('guard|search|usage|lifecycle|forge|decay|quality', (signal) => {
|
|
22
|
+
this.#record(signal);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
start() {
|
|
26
|
+
if (this.#timer) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.#timer = setInterval(() => {
|
|
30
|
+
void this.#flush();
|
|
31
|
+
}, this.#intervalMs);
|
|
32
|
+
}
|
|
33
|
+
stop() {
|
|
34
|
+
if (this.#timer) {
|
|
35
|
+
clearInterval(this.#timer);
|
|
36
|
+
this.#timer = null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
#record(signal) {
|
|
40
|
+
const key = signal.type;
|
|
41
|
+
if (!this.#windows.has(key)) {
|
|
42
|
+
this.#windows.set(key, { entries: [], baseline: 0 });
|
|
43
|
+
}
|
|
44
|
+
const win = this.#windows.get(key);
|
|
45
|
+
win.entries.push({ value: signal.value, ts: signal.timestamp });
|
|
46
|
+
}
|
|
47
|
+
async #flush() {
|
|
48
|
+
const now = Date.now();
|
|
49
|
+
for (const [type, win] of this.#windows) {
|
|
50
|
+
// 清理过期条目
|
|
51
|
+
win.entries = win.entries.filter((e) => now - e.ts < this.#windowMs);
|
|
52
|
+
if (win.entries.length === 0) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const count = win.entries.length;
|
|
56
|
+
const avg = win.entries.reduce((s, e) => s + e.value, 0) / count;
|
|
57
|
+
const max = Math.max(...win.entries.map((e) => e.value));
|
|
58
|
+
const min = Math.min(...win.entries.map((e) => e.value));
|
|
59
|
+
// 周期统计 → Report
|
|
60
|
+
await this.#reportStore.write({
|
|
61
|
+
category: 'metrics',
|
|
62
|
+
type: `aggregate_${type}`,
|
|
63
|
+
producer: 'SignalAggregator',
|
|
64
|
+
data: {
|
|
65
|
+
window: `${this.#windowMs / 1000}s`,
|
|
66
|
+
count,
|
|
67
|
+
avg,
|
|
68
|
+
max,
|
|
69
|
+
min,
|
|
70
|
+
baseline: win.baseline,
|
|
71
|
+
},
|
|
72
|
+
timestamp: now,
|
|
73
|
+
});
|
|
74
|
+
// 异常检测 → Signal(信号量突增 3 倍)
|
|
75
|
+
if (win.baseline > 0 && count > win.baseline * 3) {
|
|
76
|
+
this.#bus.send('anomaly', `Aggregator.${type}`, 1, {
|
|
77
|
+
metadata: { reason: 'spike', count, baseline: win.baseline },
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
// 更新 baseline(指数移动平均)
|
|
81
|
+
win.baseline = win.baseline === 0 ? count : win.baseline * 0.8 + count * 0.2;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalBridge — SignalBus → EventBus 单点桥接
|
|
3
|
+
*
|
|
4
|
+
* 将 SignalBus 信号转发到 EventBus,实现 SignalBus 纯内核化。
|
|
5
|
+
* HttpServer 等端口层只需监听 EventBus,不再直接消费 SignalBus。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/signal/SignalBridge
|
|
8
|
+
*/
|
|
9
|
+
import type { EventBus } from '../event/EventBus.js';
|
|
10
|
+
import type { SignalBus } from './SignalBus.js';
|
|
11
|
+
export declare class SignalBridge {
|
|
12
|
+
constructor(signalBus: SignalBus, eventBus: EventBus);
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalBridge — SignalBus → EventBus 单点桥接
|
|
3
|
+
*
|
|
4
|
+
* 将 SignalBus 信号转发到 EventBus,实现 SignalBus 纯内核化。
|
|
5
|
+
* HttpServer 等端口层只需监听 EventBus,不再直接消费 SignalBus。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/signal/SignalBridge
|
|
8
|
+
*/
|
|
9
|
+
export class SignalBridge {
|
|
10
|
+
constructor(signalBus, eventBus) {
|
|
11
|
+
// 全量转发
|
|
12
|
+
signalBus.subscribe('*', (signal) => {
|
|
13
|
+
eventBus.emit('signal:event', signal);
|
|
14
|
+
});
|
|
15
|
+
// Guard 专用通道
|
|
16
|
+
signalBus.subscribe('guard', (signal) => {
|
|
17
|
+
eventBus.emit('guard:updated', signal);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalBus — 统一信号总线
|
|
3
|
+
*
|
|
4
|
+
* Phase 0 核心基础设施。所有子系统(Guard、Search、Agent、Governance)
|
|
5
|
+
* 通过 Signal Bus 发射和消费结构化信号,替代各自为政的事件分发。
|
|
6
|
+
*
|
|
7
|
+
* 设计公理:
|
|
8
|
+
* - 同步分发,<0.1ms per emit(消费者自行决定是否 buffer)
|
|
9
|
+
* - 支持精确类型订阅和通配符 '*'
|
|
10
|
+
* - 支持 pattern 订阅 'guard|search|usage'
|
|
11
|
+
*
|
|
12
|
+
* @module infrastructure/signal/SignalBus
|
|
13
|
+
*/
|
|
14
|
+
/** 信号类型枚举 */
|
|
15
|
+
export type SignalType = 'guard' | 'guard_blind_spot' | 'search' | 'usage' | 'lifecycle' | 'exploration' | 'quality' | 'panorama' | 'decay' | 'forge' | 'intent' | 'anomaly';
|
|
16
|
+
/** 信号结构 */
|
|
17
|
+
export interface Signal {
|
|
18
|
+
/** 信号类别 */
|
|
19
|
+
type: SignalType;
|
|
20
|
+
/** 产出模块标识 */
|
|
21
|
+
source: string;
|
|
22
|
+
/** 关联 Recipe/Module ID(可选) */
|
|
23
|
+
target: string | null;
|
|
24
|
+
/** 标准化信号值 0-1 */
|
|
25
|
+
value: number;
|
|
26
|
+
/** 原始数据载荷 */
|
|
27
|
+
metadata: Record<string, unknown>;
|
|
28
|
+
/** 信号产生时间戳(ms) */
|
|
29
|
+
timestamp: number;
|
|
30
|
+
}
|
|
31
|
+
/** 信号处理器 */
|
|
32
|
+
export type SignalHandler = (signal: Signal) => void;
|
|
33
|
+
export declare class SignalBus {
|
|
34
|
+
#private;
|
|
35
|
+
/**
|
|
36
|
+
* 发射信号。同步分发给所有匹配的订阅者。
|
|
37
|
+
*
|
|
38
|
+
* @param signal 完整的 Signal 对象
|
|
39
|
+
*/
|
|
40
|
+
emit(signal: Signal): void;
|
|
41
|
+
/**
|
|
42
|
+
* 订阅信号。支持三种模式:
|
|
43
|
+
* - 精确类型: `subscribe('guard', handler)`
|
|
44
|
+
* - 多类型: `subscribe('guard|search|usage', handler)`
|
|
45
|
+
* - 通配符: `subscribe('*', handler)`
|
|
46
|
+
*
|
|
47
|
+
* @returns 取消订阅函数
|
|
48
|
+
*/
|
|
49
|
+
subscribe(pattern: string, handler: SignalHandler): () => void;
|
|
50
|
+
/**
|
|
51
|
+
* 创建并发射信号的便捷方法。自动填充 timestamp。
|
|
52
|
+
*/
|
|
53
|
+
send(type: SignalType, source: string, value: number, opts?: {
|
|
54
|
+
target?: string | null;
|
|
55
|
+
metadata?: Record<string, unknown>;
|
|
56
|
+
}): void;
|
|
57
|
+
/** 已发射的信号总数(诊断用) */
|
|
58
|
+
get emitCount(): number;
|
|
59
|
+
/** 活跃订阅者数量(诊断用) */
|
|
60
|
+
get listenerCount(): number;
|
|
61
|
+
/** 移除所有订阅者(测试用) */
|
|
62
|
+
clear(): void;
|
|
63
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalBus — 统一信号总线
|
|
3
|
+
*
|
|
4
|
+
* Phase 0 核心基础设施。所有子系统(Guard、Search、Agent、Governance)
|
|
5
|
+
* 通过 Signal Bus 发射和消费结构化信号,替代各自为政的事件分发。
|
|
6
|
+
*
|
|
7
|
+
* 设计公理:
|
|
8
|
+
* - 同步分发,<0.1ms per emit(消费者自行决定是否 buffer)
|
|
9
|
+
* - 支持精确类型订阅和通配符 '*'
|
|
10
|
+
* - 支持 pattern 订阅 'guard|search|usage'
|
|
11
|
+
*
|
|
12
|
+
* @module infrastructure/signal/SignalBus
|
|
13
|
+
*/
|
|
14
|
+
/** 通配符常量 */
|
|
15
|
+
const WILDCARD = '*';
|
|
16
|
+
// ── SignalBus ───────────────────────────────────────
|
|
17
|
+
export class SignalBus {
|
|
18
|
+
#listeners = new Map();
|
|
19
|
+
#emitCount = 0;
|
|
20
|
+
/**
|
|
21
|
+
* 发射信号。同步分发给所有匹配的订阅者。
|
|
22
|
+
*
|
|
23
|
+
* @param signal 完整的 Signal 对象
|
|
24
|
+
*/
|
|
25
|
+
emit(signal) {
|
|
26
|
+
this.#emitCount++;
|
|
27
|
+
// 精确类型匹配
|
|
28
|
+
const exact = this.#listeners.get(signal.type);
|
|
29
|
+
if (exact) {
|
|
30
|
+
for (const handler of exact) {
|
|
31
|
+
try {
|
|
32
|
+
handler(signal);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// 消费者异常不阻断信号分发
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 通配符匹配
|
|
40
|
+
const wildcard = this.#listeners.get(WILDCARD);
|
|
41
|
+
if (wildcard) {
|
|
42
|
+
for (const handler of wildcard) {
|
|
43
|
+
try {
|
|
44
|
+
handler(signal);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// 消费者异常不阻断信号分发
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* 订阅信号。支持三种模式:
|
|
54
|
+
* - 精确类型: `subscribe('guard', handler)`
|
|
55
|
+
* - 多类型: `subscribe('guard|search|usage', handler)`
|
|
56
|
+
* - 通配符: `subscribe('*', handler)`
|
|
57
|
+
*
|
|
58
|
+
* @returns 取消订阅函数
|
|
59
|
+
*/
|
|
60
|
+
subscribe(pattern, handler) {
|
|
61
|
+
const types = pattern === WILDCARD ? [WILDCARD] : pattern.split('|');
|
|
62
|
+
for (const type of types) {
|
|
63
|
+
let set = this.#listeners.get(type);
|
|
64
|
+
if (!set) {
|
|
65
|
+
set = new Set();
|
|
66
|
+
this.#listeners.set(type, set);
|
|
67
|
+
}
|
|
68
|
+
set.add(handler);
|
|
69
|
+
}
|
|
70
|
+
return () => {
|
|
71
|
+
for (const type of types) {
|
|
72
|
+
this.#listeners.get(type)?.delete(handler);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 创建并发射信号的便捷方法。自动填充 timestamp。
|
|
78
|
+
*/
|
|
79
|
+
send(type, source, value, opts = {}) {
|
|
80
|
+
this.emit({
|
|
81
|
+
type,
|
|
82
|
+
source,
|
|
83
|
+
target: opts.target ?? null,
|
|
84
|
+
value: Math.max(0, Math.min(1, value)),
|
|
85
|
+
metadata: opts.metadata ?? {},
|
|
86
|
+
timestamp: Date.now(),
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/** 已发射的信号总数(诊断用) */
|
|
90
|
+
get emitCount() {
|
|
91
|
+
return this.#emitCount;
|
|
92
|
+
}
|
|
93
|
+
/** 活跃订阅者数量(诊断用) */
|
|
94
|
+
get listenerCount() {
|
|
95
|
+
let count = 0;
|
|
96
|
+
for (const set of this.#listeners.values()) {
|
|
97
|
+
count += set.size;
|
|
98
|
+
}
|
|
99
|
+
return count;
|
|
100
|
+
}
|
|
101
|
+
/** 移除所有订阅者(测试用) */
|
|
102
|
+
clear() {
|
|
103
|
+
this.#listeners.clear();
|
|
104
|
+
this.#emitCount = 0;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalTraceWriter — 全类型信号 JSONL 留痕
|
|
3
|
+
*
|
|
4
|
+
* 订阅 SignalBus 全量信号,按类型分文件写入 JSONL。
|
|
5
|
+
* 替代 SignalModule 中 intent-only 的 JSONL 写入逻辑,统一处理全部类型。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/signal/SignalTraceWriter
|
|
8
|
+
*/
|
|
9
|
+
import type { Signal, SignalBus } from './SignalBus.js';
|
|
10
|
+
export interface SignalTraceQueryOptions {
|
|
11
|
+
type?: string[];
|
|
12
|
+
source?: string;
|
|
13
|
+
target?: string;
|
|
14
|
+
from?: number;
|
|
15
|
+
to?: number;
|
|
16
|
+
limit?: number;
|
|
17
|
+
offset?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class SignalTraceWriter {
|
|
20
|
+
#private;
|
|
21
|
+
constructor(signalBus: SignalBus, baseDir: string);
|
|
22
|
+
/** 查询历史信号 */
|
|
23
|
+
query(opts?: SignalTraceQueryOptions): Promise<{
|
|
24
|
+
signals: Signal[];
|
|
25
|
+
total: number;
|
|
26
|
+
}>;
|
|
27
|
+
/** 统计信息 */
|
|
28
|
+
stats(opts?: {
|
|
29
|
+
from?: number;
|
|
30
|
+
to?: number;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
total: number;
|
|
33
|
+
byType: Record<string, number>;
|
|
34
|
+
bySource: Record<string, number>;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SignalTraceWriter — 全类型信号 JSONL 留痕
|
|
3
|
+
*
|
|
4
|
+
* 订阅 SignalBus 全量信号,按类型分文件写入 JSONL。
|
|
5
|
+
* 替代 SignalModule 中 intent-only 的 JSONL 写入逻辑,统一处理全部类型。
|
|
6
|
+
*
|
|
7
|
+
* @module infrastructure/signal/SignalTraceWriter
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'node:fs';
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
export class SignalTraceWriter {
|
|
12
|
+
#baseDir;
|
|
13
|
+
constructor(signalBus, baseDir) {
|
|
14
|
+
this.#baseDir = baseDir;
|
|
15
|
+
fs.mkdirSync(baseDir, { recursive: true });
|
|
16
|
+
signalBus.subscribe('*', (signal) => {
|
|
17
|
+
this.#write(signal);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
#write(signal) {
|
|
21
|
+
try {
|
|
22
|
+
const fileName = this.#resolveFile(signal.type);
|
|
23
|
+
fs.appendFileSync(fileName, `${JSON.stringify({
|
|
24
|
+
type: signal.type,
|
|
25
|
+
source: signal.source,
|
|
26
|
+
value: signal.value,
|
|
27
|
+
target: signal.target,
|
|
28
|
+
metadata: signal.metadata,
|
|
29
|
+
timestamp: signal.timestamp,
|
|
30
|
+
})}\n`, 'utf8');
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// 写入失败不阻断信号分发
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/** 查询历史信号 */
|
|
37
|
+
async query(opts = {}) {
|
|
38
|
+
const types = opts.type?.length ? opts.type : this.#listTypes();
|
|
39
|
+
const all = [];
|
|
40
|
+
for (const t of types) {
|
|
41
|
+
const filePath = this.#resolveFile(t);
|
|
42
|
+
if (!fs.existsSync(filePath)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const entries = this.#readJsonl(filePath);
|
|
46
|
+
all.push(...entries);
|
|
47
|
+
}
|
|
48
|
+
// 过滤
|
|
49
|
+
let filtered = all;
|
|
50
|
+
if (opts.source) {
|
|
51
|
+
filtered = filtered.filter((s) => s.source === opts.source);
|
|
52
|
+
}
|
|
53
|
+
if (opts.target) {
|
|
54
|
+
filtered = filtered.filter((s) => s.target === opts.target);
|
|
55
|
+
}
|
|
56
|
+
if (opts.from) {
|
|
57
|
+
filtered = filtered.filter((s) => s.timestamp >= opts.from);
|
|
58
|
+
}
|
|
59
|
+
if (opts.to) {
|
|
60
|
+
filtered = filtered.filter((s) => s.timestamp <= opts.to);
|
|
61
|
+
}
|
|
62
|
+
// 按时间倒序
|
|
63
|
+
filtered.sort((a, b) => b.timestamp - a.timestamp);
|
|
64
|
+
const total = filtered.length;
|
|
65
|
+
const offset = opts.offset ?? 0;
|
|
66
|
+
const limit = opts.limit ?? 50;
|
|
67
|
+
const signals = filtered.slice(offset, offset + limit);
|
|
68
|
+
return { signals, total };
|
|
69
|
+
}
|
|
70
|
+
/** 统计信息 */
|
|
71
|
+
async stats(opts = {}) {
|
|
72
|
+
const types = this.#listTypes();
|
|
73
|
+
const byType = {};
|
|
74
|
+
const bySource = {};
|
|
75
|
+
let total = 0;
|
|
76
|
+
for (const t of types) {
|
|
77
|
+
const filePath = this.#resolveFile(t);
|
|
78
|
+
if (!fs.existsSync(filePath)) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const entries = this.#readJsonl(filePath);
|
|
82
|
+
for (const e of entries) {
|
|
83
|
+
if (opts.from && e.timestamp < opts.from) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (opts.to && e.timestamp > opts.to) {
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
total++;
|
|
90
|
+
byType[e.type] = (byType[e.type] ?? 0) + 1;
|
|
91
|
+
bySource[e.source] = (bySource[e.source] ?? 0) + 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return { total, byType, bySource };
|
|
95
|
+
}
|
|
96
|
+
// ── Private ───────────────────────────────────────
|
|
97
|
+
#resolveFile(type) {
|
|
98
|
+
return path.join(this.#baseDir, `${type}.jsonl`);
|
|
99
|
+
}
|
|
100
|
+
#listTypes() {
|
|
101
|
+
try {
|
|
102
|
+
return fs
|
|
103
|
+
.readdirSync(this.#baseDir)
|
|
104
|
+
.filter((f) => f.endsWith('.jsonl'))
|
|
105
|
+
.map((f) => f.replace('.jsonl', ''));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
#readJsonl(filePath) {
|
|
112
|
+
try {
|
|
113
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
114
|
+
const lines = content.split('\n').filter((l) => l.trim());
|
|
115
|
+
const entries = [];
|
|
116
|
+
for (const line of lines) {
|
|
117
|
+
try {
|
|
118
|
+
entries.push(JSON.parse(line));
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// 跳过损坏行
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return entries;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -121,8 +121,13 @@ export class HnswVectorAdapter extends VectorStore {
|
|
|
121
121
|
// 迁移完成, 数据已加载到内存
|
|
122
122
|
await this.#persist();
|
|
123
123
|
}
|
|
124
|
-
// 初始化 WAL (即使是空索引也创建, 以便后续操作写 WAL)
|
|
124
|
+
// 初始化 WAL + replay 未刷盘操作 (即使是空索引也创建, 以便后续操作写 WAL)
|
|
125
125
|
this.#initWal();
|
|
126
|
+
const { replayed } = this.#wal?.recover() || { replayed: 0 };
|
|
127
|
+
if (replayed > 0) {
|
|
128
|
+
this.#dirty = true;
|
|
129
|
+
await this.#persist();
|
|
130
|
+
}
|
|
126
131
|
}
|
|
127
132
|
/**
|
|
128
133
|
* 同步初始化 (兼容 JsonVectorAdapter)
|
|
@@ -171,8 +176,19 @@ export class HnswVectorAdapter extends VectorStore {
|
|
|
171
176
|
}
|
|
172
177
|
// 同步迁移: 读取 JSON 索引并加载到内存
|
|
173
178
|
this.#syncMigrateFromJson();
|
|
174
|
-
// 初始化 WAL
|
|
179
|
+
// 初始化 WAL + replay 未刷盘操作
|
|
175
180
|
this.#initWal();
|
|
181
|
+
const { replayed } = this.#wal?.recover() || { replayed: 0 };
|
|
182
|
+
if (replayed > 0) {
|
|
183
|
+
this.#dirty = true;
|
|
184
|
+
BinaryPersistence.save(this.#indexPath, {
|
|
185
|
+
index: this.#index,
|
|
186
|
+
quantizer: this.#quantizer,
|
|
187
|
+
metadata: this.#metadata,
|
|
188
|
+
contents: this.#contents,
|
|
189
|
+
});
|
|
190
|
+
this.#dirty = false;
|
|
191
|
+
}
|
|
176
192
|
}
|
|
177
193
|
/** 同步从 JSON 索引迁移 (用于 initSync 路径) */
|
|
178
194
|
#syncMigrateFromJson() {
|
|
@@ -15,6 +15,8 @@ import * as GuardModule from './modules/GuardModule.js';
|
|
|
15
15
|
// ─── DI Modules ──────────────────────────────────────
|
|
16
16
|
import * as InfraModule from './modules/InfraModule.js';
|
|
17
17
|
import * as KnowledgeModule from './modules/KnowledgeModule.js';
|
|
18
|
+
import { PanoramaModule } from './modules/PanoramaModule.js';
|
|
19
|
+
import * as SignalModule from './modules/SignalModule.js';
|
|
18
20
|
import * as VectorModule from './modules/VectorModule.js';
|
|
19
21
|
/**
|
|
20
22
|
* DependencyInjection 容器
|
|
@@ -107,12 +109,16 @@ export class ServiceContainer {
|
|
|
107
109
|
// ═══ 容器级语言偏好 ═══
|
|
108
110
|
this.singletons._lang = null;
|
|
109
111
|
// 注册模块 (顺序重要: AppModule 先注册 qualityScorer 等基础服务)
|
|
112
|
+
// SignalModule 优先注册并预热,确保后续模块可访问 signalBus
|
|
113
|
+
SignalModule.register(this);
|
|
114
|
+
this.get('signalBus'); // eager: 确保 singletons.signalBus 在后续工厂可用
|
|
110
115
|
AppModule.register(this);
|
|
111
116
|
KnowledgeModule.register(this);
|
|
112
117
|
VectorModule.register(this);
|
|
113
118
|
GuardModule.register(this);
|
|
114
119
|
AgentModule.register(this);
|
|
115
120
|
AiModule.register(this);
|
|
121
|
+
PanoramaModule.register(this);
|
|
116
122
|
// v3.1: 初始化 Enhancement Pack 注册表(异步加载所有框架增强包)
|
|
117
123
|
try {
|
|
118
124
|
await initEnhancementRegistry();
|
|
@@ -124,6 +130,8 @@ export class ServiceContainer {
|
|
|
124
130
|
}
|
|
125
131
|
// v3.3: 初始化 VectorService(绑定 EventBus 事件监听)
|
|
126
132
|
await VectorModule.initializeVectorService(this);
|
|
133
|
+
// v3.4: 初始化 Knowledge 服务(绑定 EventBus → SearchEngine.refreshIndex + sourceRefs)
|
|
134
|
+
KnowledgeModule.initializeKnowledgeServices(this);
|
|
127
135
|
this.logger.info('Service container initialized successfully');
|
|
128
136
|
}
|
|
129
137
|
catch (error) {
|