autosnippet 3.3.6 → 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 +8 -4
- package/dist/lib/agent/AgentRuntime.d.ts +2 -2
- package/dist/lib/agent/AgentRuntime.js +26 -18
- 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/domain/ChatAgentTasks.js +4 -0
- package/dist/lib/agent/forced-summary.js +7 -2
- 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 +8 -21
- 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/ConfigWatcher.d.ts +64 -0
- package/dist/lib/core/discovery/ConfigWatcher.js +336 -0
- package/dist/lib/core/discovery/CustomConfigDiscoverer.d.ts +28 -0
- package/dist/lib/core/discovery/CustomConfigDiscoverer.js +1303 -0
- package/dist/lib/core/discovery/DiscovererPreference.d.ts +44 -0
- package/dist/lib/core/discovery/DiscovererPreference.js +141 -0
- package/dist/lib/core/discovery/DiscovererRegistry.d.ts +10 -1
- package/dist/lib/core/discovery/DiscovererRegistry.js +42 -2
- package/dist/lib/core/discovery/ProjectDiscoverer.d.ts +19 -0
- package/dist/lib/core/discovery/index.d.ts +2 -0
- package/dist/lib/core/discovery/index.js +4 -0
- package/dist/lib/core/discovery/parsers/CMakeParser.d.ts +32 -0
- package/dist/lib/core/discovery/parsers/CMakeParser.js +148 -0
- package/dist/lib/core/discovery/parsers/GradleDslParser.d.ts +43 -0
- package/dist/lib/core/discovery/parsers/GradleDslParser.js +171 -0
- package/dist/lib/core/discovery/parsers/JsonConfigParser.d.ts +45 -0
- package/dist/lib/core/discovery/parsers/JsonConfigParser.js +122 -0
- package/dist/lib/core/discovery/parsers/RubyDslParser.d.ts +49 -0
- package/dist/lib/core/discovery/parsers/RubyDslParser.js +282 -0
- package/dist/lib/core/discovery/parsers/StarlarkParser.d.ts +33 -0
- package/dist/lib/core/discovery/parsers/StarlarkParser.js +229 -0
- package/dist/lib/core/discovery/parsers/YamlConfigParser.d.ts +37 -0
- package/dist/lib/core/discovery/parsers/YamlConfigParser.js +212 -0
- 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/KnowledgeEntry.d.ts +7 -1
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +17 -3
- 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/ai/AiProvider.d.ts +12 -0
- package/dist/lib/external/ai/AiProvider.js +24 -0
- package/dist/lib/external/ai/AiProviderManager.d.ts +101 -0
- package/dist/lib/external/ai/AiProviderManager.js +193 -0
- package/dist/lib/external/ai/providers/ClaudeProvider.js +11 -0
- package/dist/lib/external/ai/providers/GoogleGeminiProvider.js +18 -0
- package/dist/lib/external/ai/providers/MockProvider.d.ts +21 -3
- package/dist/lib/external/ai/providers/MockProvider.js +290 -14
- package/dist/lib/external/ai/providers/OpenAiProvider.js +16 -0
- package/dist/lib/external/lark/LarkTransport.d.ts +5 -1
- package/dist/lib/external/lark/LarkTransport.js +10 -2
- 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/mock-pipeline.d.ts +20 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/mock-pipeline.js +432 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -24
- package/dist/lib/external/mcp/handlers/bootstrap/refine.js +8 -0
- 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.d.ts +9 -0
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +3 -1
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/consolidated.js +2 -1
- package/dist/lib/external/mcp/handlers/dimension-complete-external.js +9 -4
- package/dist/lib/external/mcp/handlers/evolve-external.d.ts +1 -0
- package/dist/lib/external/mcp/handlers/evolve-external.js +18 -18
- package/dist/lib/external/mcp/handlers/guard.js +15 -24
- package/dist/lib/external/mcp/handlers/knowledge.js +5 -4
- 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 +109 -30
- package/dist/lib/http/routes/candidates.js +11 -4
- package/dist/lib/http/routes/commands.js +10 -1
- package/dist/lib/http/routes/guardReport.js +3 -5
- package/dist/lib/http/routes/health.js +11 -0
- package/dist/lib/http/routes/modules.js +27 -0
- package/dist/lib/http/routes/panorama.js +12 -12
- package/dist/lib/http/routes/recipes.js +66 -8
- package/dist/lib/http/routes/remote.js +3 -13
- package/dist/lib/http/routes/search.js +11 -8
- package/dist/lib/http/utils/routeHelpers.js +2 -1
- 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.d.ts +6 -5
- package/dist/lib/injection/ServiceContainer.js +18 -31
- package/dist/lib/injection/ServiceMap.d.ts +22 -0
- package/dist/lib/injection/modules/AiModule.d.ts +6 -9
- package/dist/lib/injection/modules/AiModule.js +82 -39
- 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.d.ts +54 -7
- package/dist/lib/service/cleanup/CleanupService.js +291 -40
- 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 +45 -63
- package/dist/lib/service/knowledge/CodeEntityGraph.js +418 -496
- 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 +97 -46
- 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/module/ModuleService.js +10 -19
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +14 -3
- package/dist/lib/service/panorama/CouplingAnalyzer.js +137 -32
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +7 -4
- package/dist/lib/service/panorama/DimensionAnalyzer.js +94 -33
- package/dist/lib/service/panorama/LayerInferrer.d.ts +16 -1
- package/dist/lib/service/panorama/LayerInferrer.js +118 -1
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +14 -4
- package/dist/lib/service/panorama/ModuleDiscoverer.js +209 -61
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +15 -4
- package/dist/lib/service/panorama/PanoramaAggregator.js +128 -62
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +5 -1
- package/dist/lib/service/panorama/PanoramaScanner.js +60 -31
- package/dist/lib/service/panorama/PanoramaService.d.ts +11 -8
- package/dist/lib/service/panorama/PanoramaService.js +49 -69
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +41 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +10 -5
- package/dist/lib/service/panorama/RoleRefiner.js +92 -282
- package/dist/lib/service/panorama/TechStackProfiler.d.ts +13 -0
- package/dist/lib/service/panorama/TechStackProfiler.js +79 -0
- 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 +6 -8
- package/dist/lib/service/skills/SignalCollector.js +34 -60
- package/dist/lib/service/skills/SkillAdvisor.d.ts +7 -13
- package/dist/lib/service/skills/SkillAdvisor.js +30 -79
- package/dist/lib/service/vector/ContextualEnricher.d.ts +1 -0
- package/dist/lib/service/vector/ContextualEnricher.js +4 -0
- 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 +19 -0
- package/dist/lib/shared/constants.d.ts +19 -19
- package/dist/lib/shared/constants.js +10 -10
- package/dist/lib/shared/developer-identity.d.ts +18 -0
- package/dist/lib/shared/developer-identity.js +62 -0
- package/dist/lib/shared/schemas/http-requests.d.ts +8 -17
- package/dist/lib/shared/schemas/http-requests.js +9 -6
- package/dist/lib/shared/schemas/mcp-tools.d.ts +1 -1
- package/dist/lib/types/knowledge-wire.d.ts +1 -0
- 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-D1aVZYFW.js +0 -1
- package/dashboard/dist/assets/index-CxHOu8Hd.css +0 -1
- package/dashboard/dist/assets/index-DDdAOpYT.js +0 -128
- package/dist/lib/repository/base/BaseRepository.d.ts +0 -53
- package/dist/lib/repository/base/BaseRepository.js +0 -226
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>AutoSnippet Dashboard</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DV8biUkH.js"></script>
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/yaml-qRaU8Ldn.js">
|
|
10
10
|
<link rel="modulepreload" crossorigin href="/assets/vendor-BZEJEVBn.js">
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/icons-
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/icons-BMNb0V6L.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/axios-42ANG6Sg.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/framer-motion-CZfOSYpP.js">
|
|
14
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-DHJ1Dj7u.css">
|
|
15
15
|
</head>
|
|
16
16
|
<body>
|
|
17
17
|
<div id="root"></div>
|
package/dist/bin/cli.js
CHANGED
|
@@ -753,8 +753,9 @@ program
|
|
|
753
753
|
const projectRoot = resolve(scanPath || '.');
|
|
754
754
|
const { bootstrap, container } = await initContainer({ projectRoot });
|
|
755
755
|
const panoramaService = container.get('panoramaService');
|
|
756
|
+
await panoramaService.ensureData();
|
|
756
757
|
if (opts.gaps) {
|
|
757
|
-
const gaps = panoramaService.getGaps();
|
|
758
|
+
const gaps = await panoramaService.getGaps();
|
|
758
759
|
if (opts.json) {
|
|
759
760
|
cli.log(JSON.stringify(gaps, null, 2));
|
|
760
761
|
}
|
|
@@ -772,7 +773,7 @@ program
|
|
|
772
773
|
return;
|
|
773
774
|
}
|
|
774
775
|
if (opts.health) {
|
|
775
|
-
const health = panoramaService.getHealth();
|
|
776
|
+
const health = await panoramaService.getHealth();
|
|
776
777
|
if (opts.json) {
|
|
777
778
|
cli.log(JSON.stringify(health, null, 2));
|
|
778
779
|
}
|
|
@@ -789,7 +790,7 @@ program
|
|
|
789
790
|
return;
|
|
790
791
|
}
|
|
791
792
|
// 默认: 全景概览
|
|
792
|
-
const overview = panoramaService.getOverview();
|
|
793
|
+
const overview = await panoramaService.getOverview();
|
|
793
794
|
if (opts.json) {
|
|
794
795
|
cli.log(JSON.stringify(overview, null, 2));
|
|
795
796
|
}
|
|
@@ -913,9 +914,12 @@ program
|
|
|
913
914
|
const { getRealtimeService } = await import('../lib/infrastructure/realtime/RealtimeService.js');
|
|
914
915
|
const db = container.get('database');
|
|
915
916
|
const agentFactory = container.get('agentFactory');
|
|
917
|
+
const knowledgeRepo = container.get('knowledgeRepository');
|
|
918
|
+
const auditRepo = container.get('auditRepository');
|
|
916
919
|
const signalCollector = new SignalCollector({
|
|
917
920
|
projectRoot,
|
|
918
|
-
|
|
921
|
+
knowledgeRepo: knowledgeRepo,
|
|
922
|
+
auditRepo: auditRepo,
|
|
919
923
|
agentFactory,
|
|
920
924
|
container,
|
|
921
925
|
mode: process.env.ASD_SIGNAL_MODE || 'auto',
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
*/
|
|
30
30
|
import { AgentEventBus } from './AgentEventBus.js';
|
|
31
31
|
import type { AgentMessage } from './AgentMessage.js';
|
|
32
|
-
import { type AgentResult, type FileCacheEntry, type
|
|
32
|
+
import { type AgentResult, type FileCacheEntry, type ReactLoopOpts, type RuntimeConfig, type ToolCallEntry, type ToolCallHook } from './AgentRuntimeTypes.js';
|
|
33
33
|
import { AgentState } from './AgentState.js';
|
|
34
34
|
import { Capability } from './capabilities.js';
|
|
35
35
|
import { PolicyEngine } from './policies.js';
|
|
@@ -50,7 +50,7 @@ export declare class AgentRuntime {
|
|
|
50
50
|
policies: PolicyEngine;
|
|
51
51
|
persona: Record<string, unknown>;
|
|
52
52
|
memoryConfig: Record<string, unknown>;
|
|
53
|
-
onProgress: ((event: ProgressEvent) => void) | null;
|
|
53
|
+
onProgress: ((event: import("./AgentRuntimeTypes.js").ProgressEvent) => void) | null;
|
|
54
54
|
lang: string | null;
|
|
55
55
|
logger: import("winston").Logger;
|
|
56
56
|
iterationCount: number;
|
|
@@ -739,25 +739,33 @@ export class AgentRuntime {
|
|
|
739
739
|
const recipeCount = ctx.toolCalls.filter((tc) => (tc.tool || tc.name) === 'collect_scan_recipe').length;
|
|
740
740
|
ctx.lastReply = `[scan complete: ${recipeCount} recipes collected]`;
|
|
741
741
|
}
|
|
742
|
-
// 强制摘要
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
if (forcedResult.tokenUsage) {
|
|
755
|
-
this.tokenUsage.input += forcedResult.tokenUsage.input || 0;
|
|
756
|
-
this.tokenUsage.output += forcedResult.tokenUsage.output || 0;
|
|
757
|
-
ctx.addTokenUsage({
|
|
758
|
-
inputTokens: forcedResult.tokenUsage.input || 0,
|
|
759
|
-
outputTokens: forcedResult.tokenUsage.output || 0,
|
|
742
|
+
// 强制摘要 — 循环结束后无文本回复时,生成摘要
|
|
743
|
+
// 覆盖所有场景: 系统管线、tracker 管线、用户对话(有/无工具调用)
|
|
744
|
+
if (!ctx.lastReply) {
|
|
745
|
+
if (ctx.toolCalls.length > 0 || ctx.tracker || ctx.isSystem) {
|
|
746
|
+
const forcedResult = await produceForcedSummary({
|
|
747
|
+
aiProvider: this.aiProvider,
|
|
748
|
+
source: ctx.source,
|
|
749
|
+
toolCalls: ctx.toolCalls,
|
|
750
|
+
tracker: ctx.tracker ?? undefined,
|
|
751
|
+
contextWindow: ctx.contextWindow,
|
|
752
|
+
prompt: ctx.prompt,
|
|
753
|
+
tokenUsage: this.tokenUsage,
|
|
760
754
|
});
|
|
755
|
+
ctx.lastReply = forcedResult.reply;
|
|
756
|
+
if (forcedResult.tokenUsage) {
|
|
757
|
+
this.tokenUsage.input += forcedResult.tokenUsage.input || 0;
|
|
758
|
+
this.tokenUsage.output += forcedResult.tokenUsage.output || 0;
|
|
759
|
+
ctx.addTokenUsage({
|
|
760
|
+
inputTokens: forcedResult.tokenUsage.input || 0,
|
|
761
|
+
outputTokens: forcedResult.tokenUsage.output || 0,
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
else {
|
|
766
|
+
// 兜底: 既无工具调用也无文本回复
|
|
767
|
+
ctx.lastReply = '抱歉,AI 未能生成有效回复。请重试或换个问题。';
|
|
768
|
+
this.logger.warn(`[AgentRuntime] ⚠ finalize: no reply, no tool calls (iter=${ctx.iteration}) — fallback message`);
|
|
761
769
|
}
|
|
762
770
|
}
|
|
763
771
|
return ctx.buildResult();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/** ChatAgentPrompts — Agent 提示词构建和文本处理方法 */
|
|
2
2
|
import fs from 'node:fs';
|
|
3
|
+
import { and, count, eq, inArray } from 'drizzle-orm';
|
|
4
|
+
import { knowledgeEntries } from '../../infrastructure/database/drizzle/schema.js';
|
|
3
5
|
/**
|
|
4
6
|
* 构建原生函数调用模式的系统提示词
|
|
5
7
|
*
|
|
@@ -82,31 +84,65 @@ submit_knowledge 的 code 字段必须是「项目特写」— 将技术的基
|
|
|
82
84
|
*/
|
|
83
85
|
export async function buildProjectBriefing({ container }) {
|
|
84
86
|
try {
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
+
const dbService = container?.get?.('database');
|
|
88
|
+
const drizzle = dbService?.getDrizzle?.();
|
|
89
|
+
if (!drizzle) {
|
|
87
90
|
return '';
|
|
88
91
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
.
|
|
106
|
-
|
|
92
|
+
const ruleTypes = ['code-standard', 'code-style', 'best-practice', 'boundary-constraint'];
|
|
93
|
+
const patternTypes = ['code-pattern', 'architecture', 'solution'];
|
|
94
|
+
const factTypes = [
|
|
95
|
+
'code-relation',
|
|
96
|
+
'inheritance',
|
|
97
|
+
'call-chain',
|
|
98
|
+
'data-flow',
|
|
99
|
+
'module-dependency',
|
|
100
|
+
];
|
|
101
|
+
const activeCondition = eq(knowledgeEntries.lifecycle, 'active');
|
|
102
|
+
const [recipeCount] = drizzle
|
|
103
|
+
.select({ value: count() })
|
|
104
|
+
.from(knowledgeEntries)
|
|
105
|
+
.where(activeCondition)
|
|
106
|
+
.all();
|
|
107
|
+
const [ruleCount] = drizzle
|
|
108
|
+
.select({ value: count() })
|
|
109
|
+
.from(knowledgeEntries)
|
|
110
|
+
.where(and(activeCondition, inArray(knowledgeEntries.knowledgeType, ruleTypes)))
|
|
111
|
+
.all();
|
|
112
|
+
const [patternCount] = drizzle
|
|
113
|
+
.select({ value: count() })
|
|
114
|
+
.from(knowledgeEntries)
|
|
115
|
+
.where(and(activeCondition, inArray(knowledgeEntries.knowledgeType, patternTypes)))
|
|
116
|
+
.all();
|
|
117
|
+
const [factCount] = drizzle
|
|
118
|
+
.select({ value: count() })
|
|
119
|
+
.from(knowledgeEntries)
|
|
120
|
+
.where(and(activeCondition, inArray(knowledgeEntries.knowledgeType, factTypes)))
|
|
121
|
+
.all();
|
|
122
|
+
const [guardRuleCount] = drizzle
|
|
123
|
+
.select({ value: count() })
|
|
124
|
+
.from(knowledgeEntries)
|
|
125
|
+
.where(and(activeCondition, eq(knowledgeEntries.knowledgeType, 'boundary-constraint')))
|
|
126
|
+
.all();
|
|
127
|
+
const [pendingCandidates] = drizzle
|
|
128
|
+
.select({ value: count() })
|
|
129
|
+
.from(knowledgeEntries)
|
|
130
|
+
.where(eq(knowledgeEntries.lifecycle, 'pending'))
|
|
131
|
+
.all();
|
|
132
|
+
const [totalCandidates] = drizzle.select({ value: count() }).from(knowledgeEntries).all();
|
|
133
|
+
const stats = {
|
|
134
|
+
recipeCount: recipeCount?.value ?? 0,
|
|
135
|
+
ruleCount: ruleCount?.value ?? 0,
|
|
136
|
+
patternCount: patternCount?.value ?? 0,
|
|
137
|
+
factCount: factCount?.value ?? 0,
|
|
138
|
+
guardRuleCount: guardRuleCount?.value ?? 0,
|
|
139
|
+
pendingCandidates: pendingCandidates?.value ?? 0,
|
|
140
|
+
totalCandidates: totalCandidates?.value ?? 0,
|
|
141
|
+
};
|
|
142
|
+
if (stats.recipeCount === 0) {
|
|
107
143
|
return '\n## 项目状态\n⚠️ 知识库为空。建议先执行冷启动(bootstrap_knowledge)。\n';
|
|
108
144
|
}
|
|
109
|
-
let section = `\n## 项目状态\n- 知识库: ${stats.recipeCount} 条 Recipe(${stats.ruleCount
|
|
145
|
+
let section = `\n## 项目状态\n- 知识库: ${stats.recipeCount} 条 Recipe(${stats.ruleCount} rule / ${stats.patternCount} pattern / ${stats.factCount} fact)\n- Guard 规则: ${stats.guardRuleCount} 条\n- 候选: ${stats.pendingCandidates} 条待审 / ${stats.totalCandidates} 条总计\n`;
|
|
110
146
|
if (stats.pendingCandidates > 10) {
|
|
111
147
|
section += `\n⚠️ 有 ${stats.pendingCandidates} 条候选积压,建议执行批量审核。\n`;
|
|
112
148
|
}
|
|
@@ -229,12 +229,25 @@ export const submitDedup = {
|
|
|
229
229
|
const isError = typeof result === 'object' && (resultObj?.error || resultObj?.status === 'error');
|
|
230
230
|
if (!isRejected && !isError && sharedState.submittedTitles) {
|
|
231
231
|
const normalizedTitle = title.toLowerCase().trim();
|
|
232
|
+
// ── trigger 去重 (防止不同 title 相同 trigger 的跨维度重复) ──
|
|
233
|
+
const trigger = String(call.args?.trigger || '')
|
|
234
|
+
.toLowerCase()
|
|
235
|
+
.trim();
|
|
236
|
+
if (trigger && sharedState.submittedTriggers?.has(trigger)) {
|
|
237
|
+
meta.dedupMessage = `⚠ 重复 trigger: "${trigger}" 已被其他候选占用。`;
|
|
238
|
+
ctx.runtime.logger.info(`[ToolPipeline] 🔁 duplicate trigger: "${trigger}"`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
232
241
|
if (sharedState.submittedTitles.has(normalizedTitle)) {
|
|
233
242
|
meta.dedupMessage = `⚠ 重复提交: "${title}" 已存在。`;
|
|
234
243
|
ctx.runtime.logger.info(`[ToolPipeline] 🔁 duplicate: "${title}"`);
|
|
235
244
|
}
|
|
236
245
|
else {
|
|
237
246
|
sharedState.submittedTitles.add(normalizedTitle);
|
|
247
|
+
// trigger 去重注册
|
|
248
|
+
if (trigger && sharedState.submittedTriggers) {
|
|
249
|
+
sharedState.submittedTriggers.add(trigger);
|
|
250
|
+
}
|
|
238
251
|
// 模式指纹去重
|
|
239
252
|
const contentObj = call.args?.content;
|
|
240
253
|
const pattern = String(contentObj?.pattern || '');
|
|
@@ -61,6 +61,10 @@ ${highSim.map((s) => `- ${s.title} (相似度: ${s.similarity})`).join('\n')}
|
|
|
61
61
|
export async function taskDiscoverAllRelations(context, { batchSize = 20 } = {}) {
|
|
62
62
|
const { container } = context;
|
|
63
63
|
const agentFactory = container.get('agentFactory');
|
|
64
|
+
// Mock 模式下跳过 AI 关系发现
|
|
65
|
+
if (agentFactory.getAiProviderInfo?.()?.name === 'mock') {
|
|
66
|
+
return { discovered: 0, message: 'AI Provider 未配置(Mock 模式),跳过关系发现。' };
|
|
67
|
+
}
|
|
64
68
|
return agentFactory.discoverRelations({ batchSize });
|
|
65
69
|
}
|
|
66
70
|
/** 任务: 批量 AI 补全候选语义字段 */
|
|
@@ -37,7 +37,7 @@ export async function produceForcedSummary({ aiProvider, source, toolCalls = [],
|
|
|
37
37
|
const candidateCount = toolCalls.filter((tc) => tc.tool === 'submit_knowledge' || tc.tool === 'submit_with_check').length;
|
|
38
38
|
let finalReply;
|
|
39
39
|
// 如果熔断器已打开,跳过 AI 调用直接合成摘要
|
|
40
|
-
const isCircuitOpen = aiProvider._circuitState === 'OPEN';
|
|
40
|
+
const isCircuitOpen = aiProvider._circuitState === 'OPEN' || aiProvider.name === 'mock';
|
|
41
41
|
if (isCircuitOpen) {
|
|
42
42
|
const outputType = isAnalyst ? 'analysis' : isSystem ? 'digest' : 'summary';
|
|
43
43
|
logger.warn(`[ForcedSummary] circuit breaker is OPEN — skipping AI summary, using synthetic ${outputType}`);
|
|
@@ -160,7 +160,7 @@ ${toolContextSummary}
|
|
|
160
160
|
.slice(0, 8);
|
|
161
161
|
const classesExplored = toolCalls
|
|
162
162
|
.filter((tc) => tc.tool === 'get_class_info' || tc.tool === 'get_class_hierarchy')
|
|
163
|
-
.map((tc) => (tc.args || tc.params
|
|
163
|
+
.map((tc) => (tc.args || tc.params)?.className)
|
|
164
164
|
.filter((v) => Boolean(v))
|
|
165
165
|
.slice(0, 10);
|
|
166
166
|
finalReply = `## 代码分析报告\n\n通过 **${toolCalls.length} 次工具调用**(${iterations} 轮迭代)探索了项目代码。\n\n`;
|
|
@@ -228,6 +228,11 @@ ${toolContextSummary}
|
|
|
228
228
|
finalReply += '> ⚠️ AI 服务异常,未能生成完整分析。请稍后重试或缩小分析范围。';
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
+
// 兜底: 确保 finalReply 始终非空
|
|
232
|
+
if (!finalReply) {
|
|
233
|
+
logger.warn('[ForcedSummary] ⚠ finalReply is empty after all paths — using fallback');
|
|
234
|
+
finalReply = `## 分析总结\n\n通过 **${toolCalls.length} 次工具调用**探索了项目代码,但未能生成完整分析。请重试或缩小分析范围。`;
|
|
235
|
+
}
|
|
231
236
|
logger.info(`[ForcedSummary] ✅ forced summary — ${finalReply.length} chars`);
|
|
232
237
|
return { reply: finalReply, tokenUsage: resultTokenUsage };
|
|
233
238
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ActiveContext — 合并 WorkingMemory + ReasoningTrace 为统一的会话工作记忆
|
|
3
3
|
*
|
|
4
|
-
* 设计来源: docs/copilot/memory-system-redesign.md §4.3, §6.2
|
|
5
|
-
*
|
|
6
4
|
* 三个内部子区:
|
|
7
5
|
* 1. Scratchpad — Agent 通过 note_finding 主动标记的发现 (不可压缩)
|
|
8
6
|
* 2. ObservationLog — 每轮 ReAct 记录 (合并原 RT.rounds + WM.observations,滑动窗口压缩)
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ActiveContext — 合并 WorkingMemory + ReasoningTrace 为统一的会话工作记忆
|
|
3
3
|
*
|
|
4
|
-
* 设计来源: docs/copilot/memory-system-redesign.md §4.3, §6.2
|
|
5
|
-
*
|
|
6
4
|
* 三个内部子区:
|
|
7
5
|
* 1. Scratchpad — Agent 通过 note_finding 主动标记的发现 (不可压缩)
|
|
8
6
|
* 2. ObservationLog — 每轮 ReAct 记录 (合并原 RT.rounds + WM.observations,滑动窗口压缩)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryEmbeddingStore — 向量嵌入的 JSON sidecar 存储
|
|
3
|
+
*
|
|
4
|
+
* 将 Agent Memory 的向量嵌入从 SQLite BLOB 迁移到独立 JSON 文件,
|
|
5
|
+
* 与 Knowledge 侧 HNSW `.asvec` 的设计理念对齐:
|
|
6
|
+
* **结构化数据存 SQLite,向量存独立文件。**
|
|
7
|
+
*
|
|
8
|
+
* 设计:
|
|
9
|
+
* - 内存 Map<id, number[]> 缓存,启动时一次性加载
|
|
10
|
+
* - 写入时更新内存 + debounced flush 到 JSON
|
|
11
|
+
* - 崩溃丢失可通过 embedAllMemories() backfill 恢复
|
|
12
|
+
*
|
|
13
|
+
* 文件位置: .autosnippet/context/memory_embeddings.json
|
|
14
|
+
*
|
|
15
|
+
* @module MemoryEmbeddingStore
|
|
16
|
+
*/
|
|
17
|
+
export declare class MemoryEmbeddingStore {
|
|
18
|
+
#private;
|
|
19
|
+
/**
|
|
20
|
+
* @param projectRoot 项目根目录
|
|
21
|
+
* @param opts.filePath 覆盖默认文件路径 (测试用)
|
|
22
|
+
*/
|
|
23
|
+
constructor(projectRoot: string, opts?: {
|
|
24
|
+
filePath?: string;
|
|
25
|
+
});
|
|
26
|
+
/** 获取单条 embedding */
|
|
27
|
+
get(id: string): number[] | null;
|
|
28
|
+
/** 设置单条 embedding */
|
|
29
|
+
set(id: string, embedding: number[]): void;
|
|
30
|
+
/** 批量设置 embeddings */
|
|
31
|
+
batchSet(entries: Array<{
|
|
32
|
+
id: string;
|
|
33
|
+
embedding: number[];
|
|
34
|
+
}>): number;
|
|
35
|
+
/** 删除单条 embedding */
|
|
36
|
+
delete(id: string): boolean;
|
|
37
|
+
/** 检查是否有 embedding */
|
|
38
|
+
has(id: string): boolean;
|
|
39
|
+
/** 返回所有缺少 embedding 的 ID (给定候选 ID 列表) */
|
|
40
|
+
getMissingIds(candidateIds: string[]): string[];
|
|
41
|
+
/** 缓存大小 */
|
|
42
|
+
get size(): number;
|
|
43
|
+
/** 清除所有 embeddings (用于重建) */
|
|
44
|
+
clear(): void;
|
|
45
|
+
/** 立即刷写到磁盘 (shutdown / 测试用) */
|
|
46
|
+
flushSync(): void;
|
|
47
|
+
/** GC: 移除不在给定 ID 集合中的 embeddings */
|
|
48
|
+
gc(activeIds: Set<string>): number;
|
|
49
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryEmbeddingStore — 向量嵌入的 JSON sidecar 存储
|
|
3
|
+
*
|
|
4
|
+
* 将 Agent Memory 的向量嵌入从 SQLite BLOB 迁移到独立 JSON 文件,
|
|
5
|
+
* 与 Knowledge 侧 HNSW `.asvec` 的设计理念对齐:
|
|
6
|
+
* **结构化数据存 SQLite,向量存独立文件。**
|
|
7
|
+
*
|
|
8
|
+
* 设计:
|
|
9
|
+
* - 内存 Map<id, number[]> 缓存,启动时一次性加载
|
|
10
|
+
* - 写入时更新内存 + debounced flush 到 JSON
|
|
11
|
+
* - 崩溃丢失可通过 embedAllMemories() backfill 恢复
|
|
12
|
+
*
|
|
13
|
+
* 文件位置: .autosnippet/context/memory_embeddings.json
|
|
14
|
+
*
|
|
15
|
+
* @module MemoryEmbeddingStore
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
18
|
+
import { dirname, join } from 'node:path';
|
|
19
|
+
/** debounce flush 延迟 (ms) */
|
|
20
|
+
const FLUSH_DELAY_MS = 2000;
|
|
21
|
+
export class MemoryEmbeddingStore {
|
|
22
|
+
/** 内存缓存: id → embedding vector */
|
|
23
|
+
#cache = new Map();
|
|
24
|
+
/** JSON 文件路径 */
|
|
25
|
+
#filePath;
|
|
26
|
+
/** debounce timer */
|
|
27
|
+
#flushTimer = null;
|
|
28
|
+
/** dirty flag */
|
|
29
|
+
#dirty = false;
|
|
30
|
+
/**
|
|
31
|
+
* @param projectRoot 项目根目录
|
|
32
|
+
* @param opts.filePath 覆盖默认文件路径 (测试用)
|
|
33
|
+
*/
|
|
34
|
+
constructor(projectRoot, opts) {
|
|
35
|
+
this.#filePath =
|
|
36
|
+
opts?.filePath ?? join(projectRoot, '.autosnippet', 'context', 'memory_embeddings.json');
|
|
37
|
+
this.#load();
|
|
38
|
+
}
|
|
39
|
+
/** 获取单条 embedding */
|
|
40
|
+
get(id) {
|
|
41
|
+
return this.#cache.get(id) ?? null;
|
|
42
|
+
}
|
|
43
|
+
/** 设置单条 embedding */
|
|
44
|
+
set(id, embedding) {
|
|
45
|
+
this.#cache.set(id, embedding);
|
|
46
|
+
this.#scheduleDirtyFlush();
|
|
47
|
+
}
|
|
48
|
+
/** 批量设置 embeddings */
|
|
49
|
+
batchSet(entries) {
|
|
50
|
+
let count = 0;
|
|
51
|
+
for (const { id, embedding } of entries) {
|
|
52
|
+
this.#cache.set(id, embedding);
|
|
53
|
+
count++;
|
|
54
|
+
}
|
|
55
|
+
if (count > 0) {
|
|
56
|
+
this.#scheduleDirtyFlush();
|
|
57
|
+
}
|
|
58
|
+
return count;
|
|
59
|
+
}
|
|
60
|
+
/** 删除单条 embedding */
|
|
61
|
+
delete(id) {
|
|
62
|
+
const existed = this.#cache.delete(id);
|
|
63
|
+
if (existed) {
|
|
64
|
+
this.#scheduleDirtyFlush();
|
|
65
|
+
}
|
|
66
|
+
return existed;
|
|
67
|
+
}
|
|
68
|
+
/** 检查是否有 embedding */
|
|
69
|
+
has(id) {
|
|
70
|
+
return this.#cache.has(id);
|
|
71
|
+
}
|
|
72
|
+
/** 返回所有缺少 embedding 的 ID (给定候选 ID 列表) */
|
|
73
|
+
getMissingIds(candidateIds) {
|
|
74
|
+
return candidateIds.filter((id) => !this.#cache.has(id));
|
|
75
|
+
}
|
|
76
|
+
/** 缓存大小 */
|
|
77
|
+
get size() {
|
|
78
|
+
return this.#cache.size;
|
|
79
|
+
}
|
|
80
|
+
/** 清除所有 embeddings (用于重建) */
|
|
81
|
+
clear() {
|
|
82
|
+
this.#cache.clear();
|
|
83
|
+
this.#scheduleDirtyFlush();
|
|
84
|
+
}
|
|
85
|
+
/** 立即刷写到磁盘 (shutdown / 测试用) */
|
|
86
|
+
flushSync() {
|
|
87
|
+
if (this.#flushTimer) {
|
|
88
|
+
clearTimeout(this.#flushTimer);
|
|
89
|
+
this.#flushTimer = null;
|
|
90
|
+
}
|
|
91
|
+
if (!this.#dirty) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
this.#writeFile();
|
|
95
|
+
this.#dirty = false;
|
|
96
|
+
}
|
|
97
|
+
/** GC: 移除不在给定 ID 集合中的 embeddings */
|
|
98
|
+
gc(activeIds) {
|
|
99
|
+
let removed = 0;
|
|
100
|
+
for (const id of this.#cache.keys()) {
|
|
101
|
+
if (!activeIds.has(id)) {
|
|
102
|
+
this.#cache.delete(id);
|
|
103
|
+
removed++;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (removed > 0) {
|
|
107
|
+
this.#scheduleDirtyFlush();
|
|
108
|
+
}
|
|
109
|
+
return removed;
|
|
110
|
+
}
|
|
111
|
+
// ═══════════════════════════════════════════════════════════
|
|
112
|
+
// Private
|
|
113
|
+
// ═══════════════════════════════════════════════════════════
|
|
114
|
+
#load() {
|
|
115
|
+
try {
|
|
116
|
+
if (existsSync(this.#filePath)) {
|
|
117
|
+
const raw = readFileSync(this.#filePath, 'utf-8');
|
|
118
|
+
const data = JSON.parse(raw);
|
|
119
|
+
for (const [id, vec] of Object.entries(data)) {
|
|
120
|
+
if (Array.isArray(vec)) {
|
|
121
|
+
this.#cache.set(id, vec);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// 文件不存在或解析失败 → 空缓存,后续 backfill 会重建
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
#writeFile() {
|
|
131
|
+
try {
|
|
132
|
+
const dir = dirname(this.#filePath);
|
|
133
|
+
if (!existsSync(dir)) {
|
|
134
|
+
mkdirSync(dir, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
const obj = {};
|
|
137
|
+
for (const [id, vec] of this.#cache) {
|
|
138
|
+
obj[id] = vec;
|
|
139
|
+
}
|
|
140
|
+
writeFileSync(this.#filePath, JSON.stringify(obj), 'utf-8');
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// 写入失败不阻塞运行时;下次 flush 或 backfill 会重试
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
#scheduleDirtyFlush() {
|
|
147
|
+
this.#dirty = true;
|
|
148
|
+
if (this.#flushTimer) {
|
|
149
|
+
return; // 已有 pending timer
|
|
150
|
+
}
|
|
151
|
+
this.#flushTimer = setTimeout(() => {
|
|
152
|
+
this.#flushTimer = null;
|
|
153
|
+
if (this.#dirty) {
|
|
154
|
+
this.#writeFile();
|
|
155
|
+
this.#dirty = false;
|
|
156
|
+
}
|
|
157
|
+
}, FLUSH_DELAY_MS);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module MemoryRetriever
|
|
12
12
|
*/
|
|
13
|
+
import type { MemoryEmbeddingStore } from './MemoryEmbeddingStore.js';
|
|
13
14
|
import type { DeserializedMemory } from './MemoryStore.js';
|
|
14
15
|
import { MemoryStore } from './MemoryStore.js';
|
|
15
16
|
/** 带评分的记忆检索结果 */
|
|
@@ -49,6 +50,7 @@ export declare class MemoryRetriever {
|
|
|
49
50
|
/** @param [opts.embeddingFn] 向量嵌入函数 (异步) */
|
|
50
51
|
constructor(store: MemoryStore, opts?: {
|
|
51
52
|
embeddingFn?: EmbeddingFn;
|
|
53
|
+
embeddingStore?: MemoryEmbeddingStore;
|
|
52
54
|
});
|
|
53
55
|
/**
|
|
54
56
|
* 综合检索: recency × importance × relevance
|
|
@@ -25,10 +25,13 @@ export class MemoryRetriever {
|
|
|
25
25
|
#store;
|
|
26
26
|
/** 向量嵌入函数 */
|
|
27
27
|
#embeddingFn;
|
|
28
|
+
/** 向量嵌入存储 (JSON sidecar) */
|
|
29
|
+
#embeddingStore;
|
|
28
30
|
/** @param [opts.embeddingFn] 向量嵌入函数 (异步) */
|
|
29
31
|
constructor(store, opts = {}) {
|
|
30
32
|
this.#store = store;
|
|
31
33
|
this.#embeddingFn = typeof opts.embeddingFn === 'function' ? opts.embeddingFn : null;
|
|
34
|
+
this.#embeddingStore = opts.embeddingStore ?? null;
|
|
32
35
|
}
|
|
33
36
|
// ═══════════════════════════════════════════════════════════
|
|
34
37
|
// 综合检索
|
|
@@ -71,14 +74,15 @@ export class MemoryRetriever {
|
|
|
71
74
|
const importance = (m.importance || 5) / 10;
|
|
72
75
|
// Relevance: 词汇相关性 (lexical)
|
|
73
76
|
const lexicalRelevance = MemoryRetriever.#computeRelevance(lowerQuery, queryTokens, m.content);
|
|
74
|
-
// 向量相关性:
|
|
77
|
+
// 向量相关性: 从 embeddingStore 查找 embedding 做余弦相似度
|
|
75
78
|
const deserialized = MemoryStore.deserialize(m);
|
|
76
79
|
let vectorRelevance = 0;
|
|
77
|
-
|
|
78
|
-
|
|
80
|
+
const storedEmbedding = this.#embeddingStore?.get(m.id) ?? null;
|
|
81
|
+
if (queryVec && storedEmbedding) {
|
|
82
|
+
vectorRelevance = Math.max(0, cosineSimilarity(queryVec, storedEmbedding));
|
|
79
83
|
}
|
|
80
84
|
// 混合相关性: 有向量时 0.6 * vector + 0.4 * lexical,否则纯 lexical
|
|
81
|
-
const relevance = queryVec &&
|
|
85
|
+
const relevance = queryVec && storedEmbedding
|
|
82
86
|
? 0.6 * vectorRelevance + 0.4 * lexicalRelevance
|
|
83
87
|
: lexicalRelevance;
|
|
84
88
|
const score = WEIGHT_RECENCY * recency + WEIGHT_IMPORTANCE * importance + WEIGHT_RELEVANCE * relevance;
|
|
@@ -199,18 +203,28 @@ export class MemoryRetriever {
|
|
|
199
203
|
* @returns 成功嵌入的记忆数
|
|
200
204
|
*/
|
|
201
205
|
async embedAllMemories(batchSize = 20) {
|
|
202
|
-
if (!this.#embeddingFn) {
|
|
206
|
+
if (!this.#embeddingFn || !this.#embeddingStore) {
|
|
203
207
|
return 0;
|
|
204
208
|
}
|
|
205
|
-
|
|
206
|
-
|
|
209
|
+
// 从 MemoryStore 获取所有活跃记忆 ID,找出 embeddingStore 中缺失的
|
|
210
|
+
const allActive = this.#store.getAllActive();
|
|
211
|
+
const allIds = allActive.map((m) => m.id);
|
|
212
|
+
const missingIds = this.#embeddingStore.getMissingIds(allIds);
|
|
213
|
+
if (missingIds.length === 0) {
|
|
207
214
|
return 0;
|
|
208
215
|
}
|
|
216
|
+
// 取前 batchSize 条
|
|
217
|
+
const batch = missingIds.slice(0, batchSize);
|
|
218
|
+
const contentMap = new Map(allActive.map((m) => [m.id, m.content]));
|
|
209
219
|
const entries = [];
|
|
210
|
-
for (const
|
|
220
|
+
for (const id of batch) {
|
|
221
|
+
const content = contentMap.get(id);
|
|
222
|
+
if (!content) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
211
225
|
try {
|
|
212
|
-
const vec = await this.#embeddingFn(
|
|
213
|
-
entries.push({ id
|
|
226
|
+
const vec = await this.#embeddingFn(content);
|
|
227
|
+
entries.push({ id, embedding: vec });
|
|
214
228
|
}
|
|
215
229
|
catch {
|
|
216
230
|
// 单条失败不阻塞
|
|
@@ -219,7 +233,7 @@ export class MemoryRetriever {
|
|
|
219
233
|
if (entries.length === 0) {
|
|
220
234
|
return 0;
|
|
221
235
|
}
|
|
222
|
-
return this.#
|
|
236
|
+
return this.#embeddingStore.batchSet(entries);
|
|
223
237
|
}
|
|
224
238
|
/**
|
|
225
239
|
* 使用嵌入函数计算语义相关性 (余弦相似度)
|