autosnippet 3.3.7 → 3.3.8
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/README.md +1 -0
- package/dashboard/dist/assets/icons-BMNb0V6L.js +1 -0
- package/dashboard/dist/assets/index-DHJ1Dj7u.css +1 -0
- package/dashboard/dist/assets/index-DV8biUkH.js +112 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.js +7 -4
- package/dist/lib/agent/core/ChatAgentPrompts.js +57 -21
- package/dist/lib/agent/core/LoopContext.d.ts +1 -0
- package/dist/lib/agent/core/ToolExecutionPipeline.js +13 -0
- package/dist/lib/agent/memory/ActiveContext.d.ts +0 -2
- package/dist/lib/agent/memory/ActiveContext.js +0 -2
- package/dist/lib/agent/memory/MemoryEmbeddingStore.d.ts +49 -0
- package/dist/lib/agent/memory/MemoryEmbeddingStore.js +159 -0
- package/dist/lib/agent/memory/MemoryRetriever.d.ts +2 -0
- package/dist/lib/agent/memory/MemoryRetriever.js +25 -11
- package/dist/lib/agent/memory/MemoryStore.d.ts +8 -41
- package/dist/lib/agent/memory/MemoryStore.js +196 -261
- package/dist/lib/agent/memory/PersistentMemory.d.ts +2 -0
- package/dist/lib/agent/memory/PersistentMemory.js +4 -5
- package/dist/lib/agent/memory/SessionStore.d.ts +0 -2
- package/dist/lib/agent/memory/SessionStore.js +0 -2
- package/dist/lib/agent/tools/ast-graph.js +21 -19
- package/dist/lib/agent/tools/infrastructure.js +3 -2
- package/dist/lib/agent/tools/project-access.d.ts +2 -2
- package/dist/lib/agent/tools/project-access.js +5 -4
- package/dist/lib/bootstrap.js +2 -1
- package/dist/lib/cli/AiScanService.js +4 -17
- package/dist/lib/cli/KnowledgeSyncService.d.ts +7 -37
- package/dist/lib/cli/KnowledgeSyncService.js +23 -51
- package/dist/lib/core/ast/ProjectGraph.js +5 -27
- package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +0 -2
- package/dist/lib/core/discovery/CustomConfigDiscoverer.js +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.d.ts +0 -2
- package/dist/lib/domain/dimension/DimensionRegistry.js +0 -2
- package/dist/lib/domain/dimension/DimensionSop.js +44 -33
- package/dist/lib/domain/dimension/UnifiedDimension.d.ts +0 -2
- package/dist/lib/domain/dimension/UnifiedDimension.js +0 -2
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +26 -0
- package/dist/lib/domain/knowledge/Lifecycle.js +42 -0
- package/dist/lib/domain/knowledge/index.d.ts +2 -1
- package/dist/lib/domain/knowledge/index.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.d.ts +2 -1
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +102 -153
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +33 -16
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +41 -37
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -1
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +7 -3
- package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/evolve-external.js +13 -16
- package/dist/lib/external/mcp/handlers/guard.js +15 -24
- package/dist/lib/external/mcp/handlers/panorama.js +9 -9
- package/dist/lib/external/mcp/handlers/rescan-external.js +7 -6
- package/dist/lib/external/mcp/handlers/rescan-internal.js +9 -5
- package/dist/lib/external/mcp/handlers/search.js +3 -1
- package/dist/lib/external/mcp/handlers/skill.js +4 -4
- package/dist/lib/external/mcp/handlers/structure.js +8 -12
- package/dist/lib/external/mcp/handlers/system.js +10 -34
- package/dist/lib/http/routes/ai.js +11 -13
- package/dist/lib/http/routes/guardReport.js +3 -5
- package/dist/lib/http/routes/panorama.js +12 -12
- package/dist/lib/http/routes/recipes.js +59 -8
- package/dist/lib/http/routes/remote.js +3 -13
- package/dist/lib/http/routes/search.js +11 -8
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +20 -3
- package/dist/lib/infrastructure/audit/AuditStore.d.ts +28 -29
- package/dist/lib/infrastructure/audit/AuditStore.js +81 -88
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +180 -2
- package/dist/lib/infrastructure/database/drizzle/schema.js +23 -3
- package/dist/lib/injection/ServiceContainer.js +7 -4
- package/dist/lib/injection/ServiceMap.d.ts +20 -0
- package/dist/lib/injection/modules/AppModule.js +2 -1
- package/dist/lib/injection/modules/GuardModule.js +5 -5
- package/dist/lib/injection/modules/InfraModule.js +60 -0
- package/dist/lib/injection/modules/KnowledgeModule.js +86 -51
- package/dist/lib/injection/modules/PanoramaModule.js +16 -10
- package/dist/lib/injection/modules/VectorModule.js +3 -0
- package/dist/lib/repository/audit/AuditRepository.d.ts +107 -0
- package/dist/lib/repository/audit/AuditRepository.js +272 -0
- package/dist/lib/repository/base/RepositoryBase.d.ts +46 -0
- package/dist/lib/repository/base/RepositoryBase.js +32 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.d.ts +94 -0
- package/dist/lib/repository/bootstrap/BootstrapRepository.js +246 -0
- package/dist/lib/repository/code/CodeEntityRepository.d.ts +91 -0
- package/dist/lib/repository/code/CodeEntityRepository.js +361 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.d.ts +39 -0
- package/dist/lib/repository/delivery/DeliveryRepoAdapter.js +23 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.d.ts +51 -0
- package/dist/lib/repository/evolution/LifecycleEventRepository.js +119 -0
- package/dist/lib/repository/evolution/ProposalRepository.d.ts +9 -12
- package/dist/lib/repository/evolution/ProposalRepository.js +114 -57
- package/dist/lib/repository/guard/GuardViolationRepository.d.ts +104 -0
- package/dist/lib/repository/guard/GuardViolationRepository.js +217 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.d.ts +129 -0
- package/dist/lib/repository/knowledge/KnowledgeEdgeRepository.js +475 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.d.ts +39 -0
- package/dist/lib/repository/knowledge/KnowledgeFileStore.js +12 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +295 -11
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +608 -13
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.d.ts +61 -0
- package/dist/lib/repository/knowledge/KnowledgeUnitOfWork.js +156 -0
- package/dist/lib/repository/memory/MemoryRepository.d.ts +90 -0
- package/dist/lib/repository/memory/MemoryRepository.js +260 -0
- package/dist/lib/repository/search/SearchRepoAdapter.d.ts +92 -0
- package/dist/lib/repository/search/SearchRepoAdapter.js +124 -0
- package/dist/lib/repository/session/SessionRepository.d.ts +46 -0
- package/dist/lib/repository/session/SessionRepository.js +110 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.d.ts +66 -0
- package/dist/lib/repository/sourceref/RecipeSourceRefRepository.js +182 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.d.ts +58 -0
- package/dist/lib/repository/sync/SyncRepoAdapter.js +58 -0
- package/dist/lib/service/bootstrap/UiStartupTasks.js +5 -6
- package/dist/lib/service/bootstrap/bootstrap-event-types.d.ts +0 -1
- package/dist/lib/service/bootstrap/bootstrap-event-types.js +0 -1
- package/dist/lib/service/cleanup/CleanupService.js +8 -4
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +6 -8
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +4 -9
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +34 -70
- package/dist/lib/service/evolution/ContentPatcher.d.ts +4 -12
- package/dist/lib/service/evolution/ContentPatcher.js +48 -19
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +3 -7
- package/dist/lib/service/evolution/ContradictionDetector.js +17 -24
- package/dist/lib/service/evolution/DecayDetector.d.ts +10 -9
- package/dist/lib/service/evolution/DecayDetector.js +63 -57
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +3 -9
- package/dist/lib/service/evolution/EnhancementSuggester.js +42 -86
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +4 -4
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +102 -71
- package/dist/lib/service/evolution/ProposalExecutor.d.ts +5 -12
- package/dist/lib/service/evolution/ProposalExecutor.js +64 -69
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.d.ts +9 -14
- package/dist/lib/service/evolution/RecipeLifecycleSupervisor.js +94 -155
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.d.ts +4 -1
- package/dist/lib/service/evolution/RecipeRelevanceAuditor.js +50 -49
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +3 -7
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +15 -22
- package/dist/lib/service/evolution/StagingManager.d.ts +6 -15
- package/dist/lib/service/evolution/StagingManager.js +37 -95
- package/dist/lib/service/evolution/createSupersedeProposal.d.ts +1 -1
- package/dist/lib/service/evolution/createSupersedeProposal.js +7 -8
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +3 -7
- package/dist/lib/service/guard/CoverageAnalyzer.js +9 -11
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +3 -0
- package/dist/lib/service/guard/GuardCheckEngine.js +14 -22
- package/dist/lib/service/guard/ReverseGuard.d.ts +4 -7
- package/dist/lib/service/guard/ReverseGuard.js +21 -31
- package/dist/lib/service/guard/ViolationsStore.d.ts +15 -21
- package/dist/lib/service/guard/ViolationsStore.js +75 -69
- package/dist/lib/service/knowledge/CodeEntityGraph.d.ts +39 -63
- package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -512
- package/dist/lib/service/knowledge/ConfidenceRouter.js +18 -9
- package/dist/lib/service/knowledge/KnowledgeFileWriter.d.ts +2 -1
- package/dist/lib/service/knowledge/KnowledgeGraphService.d.ts +18 -60
- package/dist/lib/service/knowledge/KnowledgeGraphService.js +58 -109
- package/dist/lib/service/knowledge/KnowledgeService.d.ts +15 -1
- package/dist/lib/service/knowledge/KnowledgeService.js +76 -38
- package/dist/lib/service/knowledge/RecipeProductionGateway.d.ts +0 -2
- package/dist/lib/service/knowledge/RecipeProductionGateway.js +0 -2
- package/dist/lib/service/knowledge/SourceRefReconciler.d.ts +5 -13
- package/dist/lib/service/knowledge/SourceRefReconciler.js +58 -78
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +5 -3
- package/dist/lib/service/panorama/CouplingAnalyzer.js +102 -39
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
- package/dist/lib/service/panorama/DimensionAnalyzer.js +72 -25
- package/dist/lib/service/panorama/LayerInferrer.js +1 -1
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +7 -6
- package/dist/lib/service/panorama/ModuleDiscoverer.js +174 -82
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +10 -3
- package/dist/lib/service/panorama/PanoramaAggregator.js +67 -79
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
- package/dist/lib/service/panorama/PanoramaScanner.js +32 -31
- package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
- package/dist/lib/service/panorama/PanoramaService.js +41 -66
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +3 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +8 -5
- package/dist/lib/service/panorama/RoleRefiner.js +52 -283
- package/dist/lib/service/panorama/TechStackProfiler.js +7 -119
- package/dist/lib/service/quality/QualityScorer.d.ts +45 -26
- package/dist/lib/service/quality/QualityScorer.js +157 -83
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +32 -37
- package/dist/lib/service/signal/HitRecorder.js +5 -5
- package/dist/lib/service/skills/RuleRecallStrategy.js +7 -3
- package/dist/lib/service/skills/SignalCollector.d.ts +5 -8
- package/dist/lib/service/skills/SignalCollector.js +28 -55
- package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
- package/dist/lib/service/skills/SkillAdvisor.js +30 -79
- package/dist/lib/service/vector/SyncCoordinator.d.ts +3 -1
- package/dist/lib/service/vector/SyncCoordinator.js +25 -3
- package/dist/lib/service/vector/VectorService.d.ts +2 -0
- package/dist/lib/service/vector/VectorService.js +3 -0
- package/dist/lib/service/wiki/WikiGenerator.js +1 -1
- package/dist/lib/shared/LanguageProfiles.d.ts +109 -0
- package/dist/lib/shared/LanguageProfiles.js +939 -0
- package/dist/lib/shared/LanguageService.d.ts +6 -0
- package/dist/lib/shared/LanguageService.js +16 -0
- package/dist/lib/shared/constants.d.ts +19 -19
- package/dist/lib/shared/constants.js +10 -10
- package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
- package/dist/lib/types/project-snapshot-builder.d.ts +0 -1
- package/dist/lib/types/project-snapshot-builder.js +0 -1
- package/dist/lib/types/project-snapshot.d.ts +0 -1
- package/dist/lib/types/project-snapshot.js +0 -1
- package/dist/lib/types/snapshot-views.d.ts +0 -2
- package/dist/lib/types/snapshot-views.js +0 -1
- package/package.json +2 -1
- package/dashboard/dist/assets/icons-FHns2ypa.js +0 -1
- package/dashboard/dist/assets/index-BRJv5Y3r.js +0 -135
- package/dashboard/dist/assets/index-DzoB7kxK.css +0 -1
- package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
- package/dist/lib/repository/base/BaseRepository.js +0 -226
|
@@ -20,27 +20,24 @@ const SILENT_LOGGER = {
|
|
|
20
20
|
export class PanoramaScanner {
|
|
21
21
|
#projectRoot;
|
|
22
22
|
#container;
|
|
23
|
+
#entityRepo;
|
|
24
|
+
#edgeRepo;
|
|
23
25
|
#logger;
|
|
24
26
|
#hasScanned = false;
|
|
25
27
|
constructor(opts) {
|
|
26
28
|
this.#projectRoot = opts.projectRoot;
|
|
27
29
|
this.#container = opts.container;
|
|
30
|
+
this.#entityRepo = opts.entityRepo;
|
|
31
|
+
this.#edgeRepo = opts.edgeRepo;
|
|
28
32
|
this.#logger = opts.logger ?? SILENT_LOGGER;
|
|
29
33
|
}
|
|
30
34
|
/**
|
|
31
35
|
* 检测 DB 中是否已有该项目的 code_entities 数据
|
|
32
36
|
*/
|
|
33
|
-
hasData() {
|
|
37
|
+
async hasData() {
|
|
34
38
|
try {
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
if (!rawDb?.prepare) {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
const row = rawDb
|
|
41
|
-
.prepare(`SELECT COUNT(*) as cnt FROM code_entities WHERE project_root = ?`)
|
|
42
|
-
.get(this.#projectRoot);
|
|
43
|
-
return (row?.cnt ?? 0) > 0;
|
|
39
|
+
const cnt = await this.#entityRepo.getEntityCount(this.#projectRoot);
|
|
40
|
+
return cnt > 0;
|
|
44
41
|
}
|
|
45
42
|
catch {
|
|
46
43
|
return false;
|
|
@@ -51,7 +48,7 @@ export class PanoramaScanner {
|
|
|
51
48
|
* 幂等:扫描过一次后不再重复(重启进程或手动 reset 可重新触发)。
|
|
52
49
|
*/
|
|
53
50
|
async ensureData() {
|
|
54
|
-
if (this.#hasScanned || this.hasData()) {
|
|
51
|
+
if (this.#hasScanned || (await this.hasData())) {
|
|
55
52
|
return null;
|
|
56
53
|
}
|
|
57
54
|
return this.scan();
|
|
@@ -135,7 +132,7 @@ export class PanoramaScanner {
|
|
|
135
132
|
// 当 Phase 2.1 未产出 module 实体时(无 Package.swift / build.gradle 等),
|
|
136
133
|
// 从已有 code_entities 按顶层目录分组写入 module 实体
|
|
137
134
|
if (modules === 0 && entities > 0) {
|
|
138
|
-
modules = this.#inferModulesFromDirectories();
|
|
135
|
+
modules = await this.#inferModulesFromDirectories();
|
|
139
136
|
}
|
|
140
137
|
}
|
|
141
138
|
catch (err) {
|
|
@@ -157,25 +154,17 @@ export class PanoramaScanner {
|
|
|
157
154
|
* 从 code_entities 中按顶层目录分组写入 module 实体 + is_part_of 边。
|
|
158
155
|
* 仅在 Phase 2.1 未产出 module 时调用。
|
|
159
156
|
*/
|
|
160
|
-
#inferModulesFromDirectories() {
|
|
157
|
+
async #inferModulesFromDirectories() {
|
|
161
158
|
try {
|
|
162
|
-
const db = this.#container.get('database');
|
|
163
|
-
const rawDb = db?.getDb ? db.getDb() : db;
|
|
164
|
-
if (!rawDb?.prepare) {
|
|
165
|
-
return 0;
|
|
166
|
-
}
|
|
167
159
|
// 查询所有非 module 实体的文件路径
|
|
168
|
-
const rows =
|
|
169
|
-
.prepare(`SELECT DISTINCT entity_id, file_path FROM code_entities
|
|
170
|
-
WHERE project_root = ? AND file_path IS NOT NULL AND entity_type != 'module'`)
|
|
171
|
-
.all(this.#projectRoot);
|
|
160
|
+
const rows = await this.#entityRepo.findDistinctEntityIdsWithFilePath(this.#projectRoot);
|
|
172
161
|
if (rows.length === 0) {
|
|
173
162
|
return 0;
|
|
174
163
|
}
|
|
175
164
|
// 按顶层目录分组
|
|
176
165
|
const groups = new Map();
|
|
177
166
|
for (const row of rows) {
|
|
178
|
-
const filePath = row.
|
|
167
|
+
const filePath = row.filePath;
|
|
179
168
|
if (!filePath) {
|
|
180
169
|
continue;
|
|
181
170
|
}
|
|
@@ -189,22 +178,34 @@ export class PanoramaScanner {
|
|
|
189
178
|
if (!groups.has(firstDir)) {
|
|
190
179
|
groups.set(firstDir, []);
|
|
191
180
|
}
|
|
192
|
-
groups.get(firstDir).push(row.
|
|
181
|
+
groups.get(firstDir).push(row.entityId);
|
|
193
182
|
}
|
|
194
183
|
if (groups.size === 0) {
|
|
195
184
|
return 0;
|
|
196
185
|
}
|
|
197
|
-
// 写入 module 实体
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
186
|
+
// 写入 module 实体
|
|
187
|
+
const moduleEntities = [...groups.keys()].map((dirName) => ({
|
|
188
|
+
entityId: dirName,
|
|
189
|
+
name: dirName,
|
|
190
|
+
entityType: 'module',
|
|
191
|
+
projectRoot: this.#projectRoot,
|
|
192
|
+
}));
|
|
193
|
+
await this.#entityRepo.batchInsertIgnore(moduleEntities);
|
|
194
|
+
// 写入 is_part_of 边
|
|
195
|
+
const edges = [];
|
|
202
196
|
for (const [dirName, entityIds] of groups) {
|
|
203
|
-
insertEntity.run(dirName, dirName, this.#projectRoot);
|
|
204
197
|
for (const entityId of entityIds) {
|
|
205
|
-
|
|
198
|
+
edges.push({
|
|
199
|
+
fromId: entityId,
|
|
200
|
+
fromType: 'entity',
|
|
201
|
+
toId: dirName,
|
|
202
|
+
toType: 'module',
|
|
203
|
+
relation: 'is_part_of',
|
|
204
|
+
weight: 1.0,
|
|
205
|
+
});
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
+
await this.#edgeRepo.bulkInsertIgnore(edges);
|
|
208
209
|
this.#logger.info(`[PanoramaScanner] Directory fallback: inferred ${groups.size} modules from top-level dirs`);
|
|
209
210
|
return groups.size;
|
|
210
211
|
}
|
|
@@ -13,13 +13,16 @@
|
|
|
13
13
|
* @module PanoramaService
|
|
14
14
|
*/
|
|
15
15
|
import type { SignalBus } from '../../infrastructure/signal/SignalBus.js';
|
|
16
|
-
import {
|
|
16
|
+
import type { KnowledgeEdgeRepositoryImpl } from '../../repository/knowledge/KnowledgeEdgeRepository.js';
|
|
17
|
+
import type { KnowledgeRepositoryImpl } from '../../repository/knowledge/KnowledgeRepository.impl.js';
|
|
18
|
+
import type { ModuleDiscoverer } from './ModuleDiscoverer.js';
|
|
17
19
|
import type { PanoramaAggregator } from './PanoramaAggregator.js';
|
|
18
20
|
import type { PanoramaScanner } from './PanoramaScanner.js';
|
|
19
|
-
import type {
|
|
21
|
+
import type { HealthRadar, KnowledgeGap, PanoramaModule, PanoramaResult } from './PanoramaTypes.js';
|
|
20
22
|
export interface PanoramaServiceOptions {
|
|
21
23
|
aggregator: PanoramaAggregator;
|
|
22
|
-
|
|
24
|
+
edgeRepo: KnowledgeEdgeRepositoryImpl;
|
|
25
|
+
knowledgeRepo: KnowledgeRepositoryImpl;
|
|
23
26
|
projectRoot: string;
|
|
24
27
|
scanner?: PanoramaScanner;
|
|
25
28
|
moduleDiscoverer?: ModuleDiscoverer;
|
|
@@ -92,23 +95,23 @@ export declare class PanoramaService {
|
|
|
92
95
|
/**
|
|
93
96
|
* 获取项目全景概览
|
|
94
97
|
*/
|
|
95
|
-
getOverview(): PanoramaOverview
|
|
98
|
+
getOverview(): Promise<PanoramaOverview>;
|
|
96
99
|
/**
|
|
97
100
|
* 获取单模块详情 (enriched with file groups, recipes, and summary)
|
|
98
101
|
*/
|
|
99
|
-
getModule(moduleName: string): PanoramaModuleDetail | null
|
|
102
|
+
getModule(moduleName: string): Promise<PanoramaModuleDetail | null>;
|
|
100
103
|
/**
|
|
101
104
|
* 获取知识空白区
|
|
102
105
|
*/
|
|
103
|
-
getGaps(): KnowledgeGap[]
|
|
106
|
+
getGaps(): Promise<KnowledgeGap[]>;
|
|
104
107
|
/**
|
|
105
108
|
* 获取全景健康度
|
|
106
109
|
*/
|
|
107
|
-
getHealth(): PanoramaHealth
|
|
110
|
+
getHealth(): Promise<PanoramaHealth>;
|
|
108
111
|
/**
|
|
109
112
|
* 获取完整 PanoramaResult(内部使用或 Bootstrap 注入)
|
|
110
113
|
*/
|
|
111
|
-
getResult(): PanoramaResult
|
|
114
|
+
getResult(): Promise<PanoramaResult>;
|
|
112
115
|
/**
|
|
113
116
|
* 确保全景数据已就绪(无数据时自动扫描)
|
|
114
117
|
* MCP handler / HTTP route 应在返回数据前调用此方法
|
|
@@ -12,13 +12,14 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @module PanoramaService
|
|
14
14
|
*/
|
|
15
|
-
import {
|
|
15
|
+
import { COUNTABLE_LIFECYCLES } from '../../domain/knowledge/Lifecycle.js';
|
|
16
16
|
/* ═══ Constants ═══════════════════════════════════════════ */
|
|
17
17
|
const STALE_THRESHOLD_MS = 24 * 60 * 60 * 1000; // 24h
|
|
18
18
|
/* ═══ PanoramaService Class ═══════════════════════════════ */
|
|
19
19
|
export class PanoramaService {
|
|
20
20
|
#aggregator;
|
|
21
|
-
#
|
|
21
|
+
#edgeRepo;
|
|
22
|
+
#knowledgeRepo;
|
|
22
23
|
#projectRoot;
|
|
23
24
|
#scanner;
|
|
24
25
|
#moduleDiscoverer;
|
|
@@ -28,11 +29,15 @@ export class PanoramaService {
|
|
|
28
29
|
#lastOverview = null;
|
|
29
30
|
constructor(opts) {
|
|
30
31
|
this.#aggregator = opts.aggregator;
|
|
31
|
-
this.#
|
|
32
|
+
this.#edgeRepo = opts.edgeRepo;
|
|
33
|
+
this.#knowledgeRepo = opts.knowledgeRepo;
|
|
32
34
|
this.#projectRoot = opts.projectRoot;
|
|
33
35
|
this.#scanner = opts.scanner ?? null;
|
|
34
36
|
this.#moduleDiscoverer =
|
|
35
|
-
opts.moduleDiscoverer ??
|
|
37
|
+
opts.moduleDiscoverer ??
|
|
38
|
+
(() => {
|
|
39
|
+
throw new Error('moduleDiscoverer is required');
|
|
40
|
+
})();
|
|
36
41
|
this.#signalBus = opts.signalBus ?? null;
|
|
37
42
|
// Phase 2: 订阅信号标记缓存失效
|
|
38
43
|
if (this.#signalBus) {
|
|
@@ -45,8 +50,8 @@ export class PanoramaService {
|
|
|
45
50
|
/**
|
|
46
51
|
* 获取项目全景概览
|
|
47
52
|
*/
|
|
48
|
-
getOverview() {
|
|
49
|
-
const result = this.#getOrCompute();
|
|
53
|
+
async getOverview() {
|
|
54
|
+
const result = await this.#getOrCompute();
|
|
50
55
|
const isStale = Date.now() - result.computedAt > STALE_THRESHOLD_MS;
|
|
51
56
|
let totalFiles = 0;
|
|
52
57
|
for (const [, mod] of result.modules) {
|
|
@@ -98,8 +103,8 @@ export class PanoramaService {
|
|
|
98
103
|
/**
|
|
99
104
|
* 获取单模块详情 (enriched with file groups, recipes, and summary)
|
|
100
105
|
*/
|
|
101
|
-
getModule(moduleName) {
|
|
102
|
-
const result = this.#getOrCompute();
|
|
106
|
+
async getModule(moduleName) {
|
|
107
|
+
const result = await this.#getOrCompute();
|
|
103
108
|
const mod = result.modules.get(moduleName);
|
|
104
109
|
if (!mod) {
|
|
105
110
|
return null;
|
|
@@ -109,33 +114,27 @@ export class PanoramaService {
|
|
|
109
114
|
// File groups: group by immediate subdirectory within the module
|
|
110
115
|
const fileGroups = PanoramaService.#groupFilesBySubdir(mod.files);
|
|
111
116
|
// Matched recipes from DB
|
|
112
|
-
const recipes = this.#findModuleRecipes(moduleName, mod);
|
|
117
|
+
const recipes = await this.#findModuleRecipes(moduleName, mod);
|
|
113
118
|
// Uncovered file count estimate
|
|
114
119
|
const coveredFileCount = Math.min(recipes.length * 2, mod.fileCount); // rough heuristic
|
|
115
120
|
const uncoveredFileCount = Math.max(0, mod.fileCount - coveredFileCount);
|
|
116
|
-
// Neighbors from
|
|
121
|
+
// Neighbors from edge repo
|
|
117
122
|
const neighbors = [];
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
.
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
direction: 'out',
|
|
126
|
-
weight: Number(n.weight ?? 1),
|
|
127
|
-
});
|
|
123
|
+
const outEdges = await this.#edgeRepo.findOutgoingByRelation(moduleName, 'depends_on');
|
|
124
|
+
const seenOut = new Set();
|
|
125
|
+
for (const e of outEdges) {
|
|
126
|
+
if (!seenOut.has(e.toId)) {
|
|
127
|
+
seenOut.add(e.toId);
|
|
128
|
+
neighbors.push({ name: e.toId, direction: 'out', weight: e.weight });
|
|
129
|
+
}
|
|
128
130
|
}
|
|
129
|
-
const
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
.
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
direction: 'in',
|
|
137
|
-
weight: Number(n.weight ?? 1),
|
|
138
|
-
});
|
|
131
|
+
const inEdges = await this.#edgeRepo.findIncomingByRelation(moduleName, 'depends_on');
|
|
132
|
+
const seenIn = new Set();
|
|
133
|
+
for (const e of inEdges) {
|
|
134
|
+
if (!seenIn.has(e.fromId)) {
|
|
135
|
+
seenIn.add(e.fromId);
|
|
136
|
+
neighbors.push({ name: e.fromId, direction: 'in', weight: e.weight });
|
|
137
|
+
}
|
|
139
138
|
}
|
|
140
139
|
// Generate summary
|
|
141
140
|
const summary = PanoramaService.#generateModuleSummary(mod, layerName, fileGroups, recipes, neighbors);
|
|
@@ -199,7 +198,7 @@ export class PanoramaService {
|
|
|
199
198
|
return prefix;
|
|
200
199
|
}
|
|
201
200
|
/** Find recipes related to this module by category, trigger, or title match */
|
|
202
|
-
#findModuleRecipes(moduleName, mod) {
|
|
201
|
+
async #findModuleRecipes(moduleName, mod) {
|
|
203
202
|
try {
|
|
204
203
|
// Map refined role to typical recipe categories
|
|
205
204
|
const roleCategories = {
|
|
@@ -213,31 +212,7 @@ export class PanoramaService {
|
|
|
213
212
|
feature: ['Feature'],
|
|
214
213
|
};
|
|
215
214
|
const categories = roleCategories[mod.refinedRole] ?? [];
|
|
216
|
-
|
|
217
|
-
const conditions = [];
|
|
218
|
-
const params = [];
|
|
219
|
-
// Match by module name in title or trigger
|
|
220
|
-
conditions.push('(title LIKE ? OR trigger LIKE ?)');
|
|
221
|
-
params.push(`%${moduleName}%`, `%${moduleName}%`);
|
|
222
|
-
// Match by category
|
|
223
|
-
for (const cat of categories) {
|
|
224
|
-
conditions.push('category = ?');
|
|
225
|
-
params.push(cat);
|
|
226
|
-
}
|
|
227
|
-
const whereClause = conditions.join(' OR ');
|
|
228
|
-
const rows = this.#db
|
|
229
|
-
.prepare(`SELECT id, title, trigger, kind FROM knowledge_entries
|
|
230
|
-
WHERE lifecycle IN ('active', 'staging', 'pending')
|
|
231
|
-
AND (${whereClause})
|
|
232
|
-
ORDER BY lifecycle ASC
|
|
233
|
-
LIMIT 20`)
|
|
234
|
-
.all(...params);
|
|
235
|
-
return rows.map((r) => ({
|
|
236
|
-
id: String(r.id ?? ''),
|
|
237
|
-
title: String(r.title ?? ''),
|
|
238
|
-
trigger: String(r.trigger ?? ''),
|
|
239
|
-
kind: String(r.kind ?? ''),
|
|
240
|
-
}));
|
|
215
|
+
return await this.#knowledgeRepo.findModuleRecipes(COUNTABLE_LIFECYCLES, moduleName, categories, 20);
|
|
241
216
|
}
|
|
242
217
|
catch {
|
|
243
218
|
return [];
|
|
@@ -280,15 +255,15 @@ export class PanoramaService {
|
|
|
280
255
|
/**
|
|
281
256
|
* 获取知识空白区
|
|
282
257
|
*/
|
|
283
|
-
getGaps() {
|
|
284
|
-
const result = this.#getOrCompute();
|
|
258
|
+
async getGaps() {
|
|
259
|
+
const result = await this.#getOrCompute();
|
|
285
260
|
return result.gaps;
|
|
286
261
|
}
|
|
287
262
|
/**
|
|
288
263
|
* 获取全景健康度
|
|
289
264
|
*/
|
|
290
|
-
getHealth() {
|
|
291
|
-
const result = this.#getOrCompute();
|
|
265
|
+
async getHealth() {
|
|
266
|
+
const result = await this.#getOrCompute();
|
|
292
267
|
let totalCoupling = 0;
|
|
293
268
|
let count = 0;
|
|
294
269
|
for (const [, mod] of result.modules) {
|
|
@@ -318,8 +293,8 @@ export class PanoramaService {
|
|
|
318
293
|
/**
|
|
319
294
|
* 获取完整 PanoramaResult(内部使用或 Bootstrap 注入)
|
|
320
295
|
*/
|
|
321
|
-
getResult() {
|
|
322
|
-
return this.#getOrCompute();
|
|
296
|
+
async getResult() {
|
|
297
|
+
return await this.#getOrCompute();
|
|
323
298
|
}
|
|
324
299
|
/**
|
|
325
300
|
* 确保全景数据已就绪(无数据时自动扫描)
|
|
@@ -356,13 +331,13 @@ export class PanoramaService {
|
|
|
356
331
|
}
|
|
357
332
|
}
|
|
358
333
|
/* ─── Cache + Compute ───────────────────────────── */
|
|
359
|
-
#getOrCompute() {
|
|
334
|
+
async #getOrCompute() {
|
|
360
335
|
if (this.#cache) {
|
|
361
336
|
return this.#cache;
|
|
362
337
|
}
|
|
363
|
-
const candidates = this.#moduleDiscoverer.discover();
|
|
364
|
-
const configLayers = this.#moduleDiscoverer.readConfigLayers();
|
|
365
|
-
this.#cache = this.#aggregator.compute(candidates, { configLayers });
|
|
338
|
+
const candidates = await this.#moduleDiscoverer.discover();
|
|
339
|
+
const configLayers = await this.#moduleDiscoverer.readConfigLayers();
|
|
340
|
+
this.#cache = await this.#aggregator.compute(candidates, { configLayers });
|
|
366
341
|
return this.#cache;
|
|
367
342
|
}
|
|
368
343
|
}
|
|
@@ -83,6 +83,8 @@ export interface LayerViolation {
|
|
|
83
83
|
export interface LayerHierarchy {
|
|
84
84
|
levels: LayerLevel[];
|
|
85
85
|
violations: LayerViolation[];
|
|
86
|
+
/** 是否基于配置文件(如 Boxfile)声明的层级推断(而非纯拓扑) */
|
|
87
|
+
configBased?: boolean;
|
|
86
88
|
}
|
|
87
89
|
export interface CyclicDependency {
|
|
88
90
|
cycle: string[];
|
|
@@ -154,6 +156,7 @@ export interface CallFlowSummary {
|
|
|
154
156
|
dataProducers: string[];
|
|
155
157
|
dataConsumers: string[];
|
|
156
158
|
}
|
|
159
|
+
export type { ModuleRole } from '#shared/LanguageProfiles.js';
|
|
157
160
|
export interface PanoramaResult {
|
|
158
161
|
modules: Map<string, PanoramaModule>;
|
|
159
162
|
layers: LayerHierarchy;
|
|
@@ -13,8 +13,11 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @module RoleRefiner
|
|
15
15
|
*/
|
|
16
|
-
import type {
|
|
17
|
-
|
|
16
|
+
import type { BootstrapRepositoryImpl } from '../../repository/bootstrap/BootstrapRepository.js';
|
|
17
|
+
import type { CodeEntityRepositoryImpl } from '../../repository/code/CodeEntityRepository.js';
|
|
18
|
+
import type { KnowledgeEdgeRepositoryImpl } from '../../repository/knowledge/KnowledgeEdgeRepository.js';
|
|
19
|
+
import type { ModuleRole } from './PanoramaTypes.js';
|
|
20
|
+
export type { ModuleRole } from './PanoramaTypes.js';
|
|
18
21
|
export interface RoleSignal {
|
|
19
22
|
role: ModuleRole;
|
|
20
23
|
confidence: number;
|
|
@@ -38,13 +41,13 @@ export interface ModuleCandidate {
|
|
|
38
41
|
}
|
|
39
42
|
export declare class RoleRefiner {
|
|
40
43
|
#private;
|
|
41
|
-
constructor(
|
|
44
|
+
constructor(bootstrapRepo: BootstrapRepositoryImpl, entityRepo: CodeEntityRepositoryImpl, edgeRepo: KnowledgeEdgeRepositoryImpl, projectRoot: string);
|
|
42
45
|
/**
|
|
43
46
|
* 精化单个模块的角色
|
|
44
47
|
*/
|
|
45
|
-
refineRole(module: ModuleCandidate): RefinedRole
|
|
48
|
+
refineRole(module: ModuleCandidate): Promise<RefinedRole>;
|
|
46
49
|
/**
|
|
47
50
|
* 批量精化所有模块
|
|
48
51
|
*/
|
|
49
|
-
refineAll(modules: ModuleCandidate[]): Map<string, RefinedRole
|
|
52
|
+
refineAll(modules: ModuleCandidate[]): Promise<Map<string, RefinedRole>>;
|
|
50
53
|
}
|