@framers/agentos 0.1.120 → 0.1.121
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 +21 -0
- package/dist/api/agency.d.ts.map +1 -1
- package/dist/api/agency.js +227 -84
- package/dist/api/agency.js.map +1 -1
- package/dist/api/analyzeVideo.d.ts +127 -0
- package/dist/api/analyzeVideo.d.ts.map +1 -0
- package/dist/api/analyzeVideo.js +136 -0
- package/dist/api/analyzeVideo.js.map +1 -0
- package/dist/api/detectScenes.d.ts +82 -0
- package/dist/api/detectScenes.d.ts.map +1 -0
- package/dist/api/detectScenes.js +67 -0
- package/dist/api/detectScenes.js.map +1 -0
- package/dist/api/generateImage.d.ts +7 -0
- package/dist/api/generateImage.d.ts.map +1 -1
- package/dist/api/generateImage.js +133 -9
- package/dist/api/generateImage.js.map +1 -1
- package/dist/api/generateMusic.d.ts +98 -0
- package/dist/api/generateMusic.d.ts.map +1 -0
- package/dist/api/generateMusic.js +319 -0
- package/dist/api/generateMusic.js.map +1 -0
- package/dist/api/generateSFX.d.ts +96 -0
- package/dist/api/generateSFX.d.ts.map +1 -0
- package/dist/api/generateSFX.js +317 -0
- package/dist/api/generateSFX.js.map +1 -0
- package/dist/api/generateVideo.d.ts +113 -0
- package/dist/api/generateVideo.d.ts.map +1 -0
- package/dist/api/generateVideo.js +342 -0
- package/dist/api/generateVideo.js.map +1 -0
- package/dist/api/model.d.ts.map +1 -1
- package/dist/api/model.js +8 -4
- package/dist/api/model.js.map +1 -1
- package/dist/api/performOCR.d.ts +169 -0
- package/dist/api/performOCR.d.ts.map +1 -0
- package/dist/api/performOCR.js +198 -0
- package/dist/api/performOCR.js.map +1 -0
- package/dist/api/provider-defaults.d.ts +7 -5
- package/dist/api/provider-defaults.d.ts.map +1 -1
- package/dist/api/provider-defaults.js +32 -10
- package/dist/api/provider-defaults.js.map +1 -1
- package/dist/api/strategies/debate.d.ts.map +1 -1
- package/dist/api/strategies/debate.js +1 -0
- package/dist/api/strategies/debate.js.map +1 -1
- package/dist/api/strategies/graph.d.ts.map +1 -1
- package/dist/api/strategies/graph.js +69 -13
- package/dist/api/strategies/graph.js.map +1 -1
- package/dist/api/strategies/hierarchical.d.ts.map +1 -1
- package/dist/api/strategies/hierarchical.js +1 -0
- package/dist/api/strategies/hierarchical.js.map +1 -1
- package/dist/api/strategies/parallel.d.ts.map +1 -1
- package/dist/api/strategies/parallel.js +1 -0
- package/dist/api/strategies/parallel.js.map +1 -1
- package/dist/api/strategies/review-loop.d.ts.map +1 -1
- package/dist/api/strategies/review-loop.js +1 -0
- package/dist/api/strategies/review-loop.js.map +1 -1
- package/dist/api/strategies/sequential.d.ts.map +1 -1
- package/dist/api/strategies/sequential.js +54 -48
- package/dist/api/strategies/sequential.js.map +1 -1
- package/dist/api/streamBuffer.d.ts +20 -0
- package/dist/api/streamBuffer.d.ts.map +1 -0
- package/dist/api/streamBuffer.js +81 -0
- package/dist/api/streamBuffer.js.map +1 -0
- package/dist/api/types.d.ts +145 -5
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/types.js.map +1 -1
- package/dist/channels/adapters/RedditChannelAdapter.js.map +1 -1
- package/dist/core/audio/AudioProcessor.d.ts.map +1 -1
- package/dist/core/audio/AudioProcessor.js +1 -0
- package/dist/core/audio/AudioProcessor.js.map +1 -1
- package/dist/core/audio/EnvironmentalCalibrator.d.ts.map +1 -1
- package/dist/core/audio/EnvironmentalCalibrator.js +1 -0
- package/dist/core/audio/EnvironmentalCalibrator.js.map +1 -1
- package/dist/core/audio/FallbackAudioProxy.d.ts +169 -0
- package/dist/core/audio/FallbackAudioProxy.d.ts.map +1 -0
- package/dist/core/audio/FallbackAudioProxy.js +236 -0
- package/dist/core/audio/FallbackAudioProxy.js.map +1 -0
- package/dist/core/audio/IAudioGenerator.d.ts +103 -0
- package/dist/core/audio/IAudioGenerator.d.ts.map +1 -0
- package/dist/core/audio/IAudioGenerator.js +24 -0
- package/dist/core/audio/IAudioGenerator.js.map +1 -0
- package/dist/core/audio/index.d.ts +54 -0
- package/dist/core/audio/index.d.ts.map +1 -1
- package/dist/core/audio/index.js +93 -0
- package/dist/core/audio/index.js.map +1 -1
- package/dist/core/audio/providers/AudioGenLocalProvider.d.ts +136 -0
- package/dist/core/audio/providers/AudioGenLocalProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/AudioGenLocalProvider.js +235 -0
- package/dist/core/audio/providers/AudioGenLocalProvider.js.map +1 -0
- package/dist/core/audio/providers/ElevenLabsSFXProvider.d.ts +107 -0
- package/dist/core/audio/providers/ElevenLabsSFXProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/ElevenLabsSFXProvider.js +154 -0
- package/dist/core/audio/providers/ElevenLabsSFXProvider.js.map +1 -0
- package/dist/core/audio/providers/FalAudioProvider.d.ts +207 -0
- package/dist/core/audio/providers/FalAudioProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/FalAudioProvider.js +315 -0
- package/dist/core/audio/providers/FalAudioProvider.js.map +1 -0
- package/dist/core/audio/providers/MusicGenLocalProvider.d.ts +136 -0
- package/dist/core/audio/providers/MusicGenLocalProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/MusicGenLocalProvider.js +235 -0
- package/dist/core/audio/providers/MusicGenLocalProvider.js.map +1 -0
- package/dist/core/audio/providers/ReplicateAudioProvider.d.ts +200 -0
- package/dist/core/audio/providers/ReplicateAudioProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/ReplicateAudioProvider.js +346 -0
- package/dist/core/audio/providers/ReplicateAudioProvider.js.map +1 -0
- package/dist/core/audio/providers/StableAudioProvider.d.ts +138 -0
- package/dist/core/audio/providers/StableAudioProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/StableAudioProvider.js +192 -0
- package/dist/core/audio/providers/StableAudioProvider.js.map +1 -0
- package/dist/core/audio/providers/SunoProvider.d.ts +182 -0
- package/dist/core/audio/providers/SunoProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/SunoProvider.js +312 -0
- package/dist/core/audio/providers/SunoProvider.js.map +1 -0
- package/dist/core/audio/providers/UdioProvider.d.ts +177 -0
- package/dist/core/audio/providers/UdioProvider.d.ts.map +1 -0
- package/dist/core/audio/providers/UdioProvider.js +305 -0
- package/dist/core/audio/providers/UdioProvider.js.map +1 -0
- package/dist/core/audio/types.d.ts +257 -0
- package/dist/core/audio/types.d.ts.map +1 -0
- package/dist/core/audio/types.js +21 -0
- package/dist/core/audio/types.js.map +1 -0
- package/dist/core/images/FallbackImageProxy.d.ts +183 -0
- package/dist/core/images/FallbackImageProxy.d.ts.map +1 -0
- package/dist/core/images/FallbackImageProxy.js +283 -0
- package/dist/core/images/FallbackImageProxy.js.map +1 -0
- package/dist/core/images/IImageProvider.d.ts +1 -1
- package/dist/core/images/IImageProvider.d.ts.map +1 -1
- package/dist/core/images/index.d.ts +1 -0
- package/dist/core/images/index.d.ts.map +1 -1
- package/dist/core/images/index.js +1 -0
- package/dist/core/images/index.js.map +1 -1
- package/dist/core/llm/providers/AIModelProviderManager.d.ts +3 -1
- package/dist/core/llm/providers/AIModelProviderManager.d.ts.map +1 -1
- package/dist/core/llm/providers/AIModelProviderManager.js +8 -0
- package/dist/core/llm/providers/AIModelProviderManager.js.map +1 -1
- package/dist/core/llm/providers/errors/ClaudeCodeProviderError.d.ts +52 -0
- package/dist/core/llm/providers/errors/ClaudeCodeProviderError.d.ts.map +1 -0
- package/dist/core/llm/providers/errors/ClaudeCodeProviderError.js +36 -0
- package/dist/core/llm/providers/errors/ClaudeCodeProviderError.js.map +1 -0
- package/dist/core/llm/providers/errors/GeminiCLIProviderError.d.ts +32 -0
- package/dist/core/llm/providers/errors/GeminiCLIProviderError.d.ts.map +1 -0
- package/dist/core/llm/providers/errors/GeminiCLIProviderError.js +27 -0
- package/dist/core/llm/providers/errors/GeminiCLIProviderError.js.map +1 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.d.ts +38 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.d.ts.map +1 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.js +128 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeCLIBridge.js.map +1 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.d.ts +107 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.d.ts.map +1 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js +504 -0
- package/dist/core/llm/providers/implementations/ClaudeCodeProvider.js.map +1 -0
- package/dist/core/llm/providers/implementations/GeminiCLIBridge.d.ts +60 -0
- package/dist/core/llm/providers/implementations/GeminiCLIBridge.d.ts.map +1 -0
- package/dist/core/llm/providers/implementations/GeminiCLIBridge.js +177 -0
- package/dist/core/llm/providers/implementations/GeminiCLIBridge.js.map +1 -0
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts +55 -0
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.d.ts.map +1 -0
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.js +447 -0
- package/dist/core/llm/providers/implementations/GeminiCLIProvider.js.map +1 -0
- package/dist/core/media/ProviderPreferences.d.ts +158 -0
- package/dist/core/media/ProviderPreferences.d.ts.map +1 -0
- package/dist/core/media/ProviderPreferences.js +183 -0
- package/dist/core/media/ProviderPreferences.js.map +1 -0
- package/dist/core/subprocess/CLIRegistry.d.ts +71 -0
- package/dist/core/subprocess/CLIRegistry.d.ts.map +1 -0
- package/dist/core/subprocess/CLIRegistry.js +210 -0
- package/dist/core/subprocess/CLIRegistry.js.map +1 -0
- package/dist/core/subprocess/CLISubprocessBridge.d.ts +117 -0
- package/dist/core/subprocess/CLISubprocessBridge.d.ts.map +1 -0
- package/dist/core/subprocess/CLISubprocessBridge.js +199 -0
- package/dist/core/subprocess/CLISubprocessBridge.js.map +1 -0
- package/dist/core/subprocess/errors.d.ts +76 -0
- package/dist/core/subprocess/errors.d.ts.map +1 -0
- package/dist/core/subprocess/errors.js +75 -0
- package/dist/core/subprocess/errors.js.map +1 -0
- package/dist/core/subprocess/index.d.ts +11 -0
- package/dist/core/subprocess/index.d.ts.map +1 -0
- package/dist/core/subprocess/index.js +10 -0
- package/dist/core/subprocess/index.js.map +1 -0
- package/dist/core/subprocess/types.d.ts +100 -0
- package/dist/core/subprocess/types.d.ts.map +1 -0
- package/dist/core/subprocess/types.js +9 -0
- package/dist/core/subprocess/types.js.map +1 -0
- package/dist/core/video/FallbackVideoProxy.d.ts +166 -0
- package/dist/core/video/FallbackVideoProxy.d.ts.map +1 -0
- package/dist/core/video/FallbackVideoProxy.js +228 -0
- package/dist/core/video/FallbackVideoProxy.js.map +1 -0
- package/dist/core/video/IVideoAnalyzer.d.ts +29 -0
- package/dist/core/video/IVideoAnalyzer.d.ts.map +1 -0
- package/dist/core/video/IVideoAnalyzer.js +12 -0
- package/dist/core/video/IVideoAnalyzer.js.map +1 -0
- package/dist/core/video/IVideoGenerator.d.ts +76 -0
- package/dist/core/video/IVideoGenerator.d.ts.map +1 -0
- package/dist/core/video/IVideoGenerator.js +13 -0
- package/dist/core/video/IVideoGenerator.js.map +1 -0
- package/dist/core/video/VideoAnalyzer.d.ts +278 -0
- package/dist/core/video/VideoAnalyzer.d.ts.map +1 -0
- package/dist/core/video/VideoAnalyzer.js +648 -0
- package/dist/core/video/VideoAnalyzer.js.map +1 -0
- package/dist/core/video/index.d.ts +55 -0
- package/dist/core/video/index.d.ts.map +1 -0
- package/dist/core/video/index.js +78 -0
- package/dist/core/video/index.js.map +1 -0
- package/dist/core/video/providers/FalVideoProvider.d.ts +195 -0
- package/dist/core/video/providers/FalVideoProvider.d.ts.map +1 -0
- package/dist/core/video/providers/FalVideoProvider.js +322 -0
- package/dist/core/video/providers/FalVideoProvider.js.map +1 -0
- package/dist/core/video/providers/ReplicateVideoProvider.d.ts +194 -0
- package/dist/core/video/providers/ReplicateVideoProvider.d.ts.map +1 -0
- package/dist/core/video/providers/ReplicateVideoProvider.js +356 -0
- package/dist/core/video/providers/ReplicateVideoProvider.js.map +1 -0
- package/dist/core/video/providers/RunwayVideoProvider.d.ts +175 -0
- package/dist/core/video/providers/RunwayVideoProvider.d.ts.map +1 -0
- package/dist/core/video/providers/RunwayVideoProvider.js +293 -0
- package/dist/core/video/providers/RunwayVideoProvider.js.map +1 -0
- package/dist/core/video/types.d.ts +441 -0
- package/dist/core/video/types.d.ts.map +1 -0
- package/dist/core/video/types.js +10 -0
- package/dist/core/video/types.js.map +1 -0
- package/dist/core/vision/SceneDetector.d.ts +180 -0
- package/dist/core/vision/SceneDetector.d.ts.map +1 -0
- package/dist/core/vision/SceneDetector.js +366 -0
- package/dist/core/vision/SceneDetector.js.map +1 -0
- package/dist/core/vision/index.d.ts +2 -1
- package/dist/core/vision/index.d.ts.map +1 -1
- package/dist/core/vision/index.js +1 -0
- package/dist/core/vision/index.js.map +1 -1
- package/dist/core/vision/types.d.ts +125 -0
- package/dist/core/vision/types.d.ts.map +1 -1
- package/dist/discovery/CapabilityDiscoveryEngine.d.ts +32 -0
- package/dist/discovery/CapabilityDiscoveryEngine.d.ts.map +1 -1
- package/dist/discovery/CapabilityDiscoveryEngine.js +46 -0
- package/dist/discovery/CapabilityDiscoveryEngine.js.map +1 -1
- package/dist/extensions/MultiRegistryLoader.js.map +1 -1
- package/dist/index.d.ts +17 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -1
- package/dist/memory/CognitiveMemoryManager.d.ts +40 -0
- package/dist/memory/CognitiveMemoryManager.d.ts.map +1 -1
- package/dist/memory/CognitiveMemoryManager.js +54 -1
- package/dist/memory/CognitiveMemoryManager.js.map +1 -1
- package/dist/memory/facade/Memory.d.ts +4 -0
- package/dist/memory/facade/Memory.d.ts.map +1 -1
- package/dist/memory/facade/Memory.js +140 -4
- package/dist/memory/facade/Memory.js.map +1 -1
- package/dist/memory/facade/types.d.ts +30 -2
- package/dist/memory/facade/types.d.ts.map +1 -1
- package/dist/memory/index.d.ts +1 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +1 -0
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/types.d.ts +15 -0
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/query-router/QueryClassifier.d.ts +192 -21
- package/dist/query-router/QueryClassifier.d.ts.map +1 -1
- package/dist/query-router/QueryClassifier.js +604 -23
- package/dist/query-router/QueryClassifier.js.map +1 -1
- package/dist/query-router/QueryDispatcher.d.ts +106 -8
- package/dist/query-router/QueryDispatcher.d.ts.map +1 -1
- package/dist/query-router/QueryDispatcher.js +387 -8
- package/dist/query-router/QueryDispatcher.js.map +1 -1
- package/dist/query-router/QueryRouter.d.ts +198 -14
- package/dist/query-router/QueryRouter.d.ts.map +1 -1
- package/dist/query-router/QueryRouter.js +738 -50
- package/dist/query-router/QueryRouter.js.map +1 -1
- package/dist/query-router/index.d.ts +1 -1
- package/dist/query-router/index.d.ts.map +1 -1
- package/dist/query-router/index.js +1 -1
- package/dist/query-router/index.js.map +1 -1
- package/dist/query-router/types.d.ts +396 -3
- package/dist/query-router/types.d.ts.map +1 -1
- package/dist/query-router/types.js +35 -0
- package/dist/query-router/types.js.map +1 -1
- package/dist/rag/HydeRetriever.d.ts +108 -0
- package/dist/rag/HydeRetriever.d.ts.map +1 -1
- package/dist/rag/HydeRetriever.js +184 -0
- package/dist/rag/HydeRetriever.js.map +1 -1
- package/dist/rag/IRetrievalAugmentor.d.ts +15 -0
- package/dist/rag/IRetrievalAugmentor.d.ts.map +1 -1
- package/dist/rag/RetrievalAugmentor.d.ts +58 -0
- package/dist/rag/RetrievalAugmentor.d.ts.map +1 -1
- package/dist/rag/RetrievalAugmentor.js +200 -32
- package/dist/rag/RetrievalAugmentor.js.map +1 -1
- package/dist/rag/VectorStoreManager.js +1 -1
- package/dist/rag/audit/RAGAuditCollector.d.ts +7 -0
- package/dist/rag/audit/RAGAuditCollector.d.ts.map +1 -1
- package/dist/rag/audit/RAGAuditCollector.js +10 -0
- package/dist/rag/audit/RAGAuditCollector.js.map +1 -1
- package/dist/rag/audit/RAGAuditTypes.d.ts +10 -1
- package/dist/rag/audit/RAGAuditTypes.d.ts.map +1 -1
- package/dist/rag/chunking/SemanticChunker.d.ts +210 -0
- package/dist/rag/chunking/SemanticChunker.d.ts.map +1 -0
- package/dist/rag/chunking/SemanticChunker.js +460 -0
- package/dist/rag/chunking/SemanticChunker.js.map +1 -0
- package/dist/rag/chunking/index.d.ts +10 -0
- package/dist/rag/chunking/index.d.ts.map +1 -0
- package/dist/rag/chunking/index.js +10 -0
- package/dist/rag/chunking/index.js.map +1 -0
- package/dist/rag/implementations/vector_stores/PineconeVectorStore.d.ts +103 -0
- package/dist/rag/implementations/vector_stores/PineconeVectorStore.d.ts.map +1 -0
- package/dist/rag/implementations/vector_stores/PineconeVectorStore.js +315 -0
- package/dist/rag/implementations/vector_stores/PineconeVectorStore.js.map +1 -0
- package/dist/rag/implementations/vector_stores/PostgresVectorStore.d.ts +107 -0
- package/dist/rag/implementations/vector_stores/PostgresVectorStore.d.ts.map +1 -0
- package/dist/rag/implementations/vector_stores/PostgresVectorStore.js +438 -0
- package/dist/rag/implementations/vector_stores/PostgresVectorStore.js.map +1 -0
- package/dist/rag/index.d.ts +15 -1
- package/dist/rag/index.d.ts.map +1 -1
- package/dist/rag/index.js +32 -0
- package/dist/rag/index.js.map +1 -1
- package/dist/rag/migration/MigrationEngine.d.ts +47 -0
- package/dist/rag/migration/MigrationEngine.d.ts.map +1 -0
- package/dist/rag/migration/MigrationEngine.js +168 -0
- package/dist/rag/migration/MigrationEngine.js.map +1 -0
- package/dist/rag/migration/adapters/PineconeSourceAdapter.d.ts +23 -0
- package/dist/rag/migration/adapters/PineconeSourceAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/PineconeSourceAdapter.js +63 -0
- package/dist/rag/migration/adapters/PineconeSourceAdapter.js.map +1 -0
- package/dist/rag/migration/adapters/PostgresSourceAdapter.d.ts +30 -0
- package/dist/rag/migration/adapters/PostgresSourceAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/PostgresSourceAdapter.js +71 -0
- package/dist/rag/migration/adapters/PostgresSourceAdapter.js.map +1 -0
- package/dist/rag/migration/adapters/PostgresTargetAdapter.d.ts +38 -0
- package/dist/rag/migration/adapters/PostgresTargetAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/PostgresTargetAdapter.js +114 -0
- package/dist/rag/migration/adapters/PostgresTargetAdapter.js.map +1 -0
- package/dist/rag/migration/adapters/QdrantSourceAdapter.d.ts +36 -0
- package/dist/rag/migration/adapters/QdrantSourceAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/QdrantSourceAdapter.js +109 -0
- package/dist/rag/migration/adapters/QdrantSourceAdapter.js.map +1 -0
- package/dist/rag/migration/adapters/QdrantTargetAdapter.d.ts +35 -0
- package/dist/rag/migration/adapters/QdrantTargetAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/QdrantTargetAdapter.js +110 -0
- package/dist/rag/migration/adapters/QdrantTargetAdapter.js.map +1 -0
- package/dist/rag/migration/adapters/SqliteSourceAdapter.d.ts +37 -0
- package/dist/rag/migration/adapters/SqliteSourceAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/SqliteSourceAdapter.js +72 -0
- package/dist/rag/migration/adapters/SqliteSourceAdapter.js.map +1 -0
- package/dist/rag/migration/adapters/SqliteTargetAdapter.d.ts +47 -0
- package/dist/rag/migration/adapters/SqliteTargetAdapter.d.ts.map +1 -0
- package/dist/rag/migration/adapters/SqliteTargetAdapter.js +93 -0
- package/dist/rag/migration/adapters/SqliteTargetAdapter.js.map +1 -0
- package/dist/rag/migration/types.d.ts +108 -0
- package/dist/rag/migration/types.d.ts.map +1 -0
- package/dist/rag/migration/types.js +11 -0
- package/dist/rag/migration/types.js.map +1 -0
- package/dist/rag/multimodal/MultimodalIndexer.d.ts +35 -0
- package/dist/rag/multimodal/MultimodalIndexer.d.ts.map +1 -1
- package/dist/rag/multimodal/MultimodalIndexer.js +66 -1
- package/dist/rag/multimodal/MultimodalIndexer.js.map +1 -1
- package/dist/rag/multimodal/types.d.ts +24 -0
- package/dist/rag/multimodal/types.d.ts.map +1 -1
- package/dist/rag/raptor/RaptorTree.d.ts +268 -0
- package/dist/rag/raptor/RaptorTree.d.ts.map +1 -0
- package/dist/rag/raptor/RaptorTree.js +443 -0
- package/dist/rag/raptor/RaptorTree.js.map +1 -0
- package/dist/rag/raptor/index.d.ts +11 -0
- package/dist/rag/raptor/index.d.ts.map +1 -0
- package/dist/rag/raptor/index.js +11 -0
- package/dist/rag/raptor/index.js.map +1 -0
- package/dist/rag/reranking/providers/CohereReranker.js.map +1 -1
- package/dist/rag/search/BM25Index.d.ts +282 -0
- package/dist/rag/search/BM25Index.d.ts.map +1 -0
- package/dist/rag/search/BM25Index.js +344 -0
- package/dist/rag/search/BM25Index.js.map +1 -0
- package/dist/rag/search/HybridSearcher.d.ts +198 -0
- package/dist/rag/search/HybridSearcher.d.ts.map +1 -0
- package/dist/rag/search/HybridSearcher.js +316 -0
- package/dist/rag/search/HybridSearcher.js.map +1 -0
- package/dist/rag/search/index.d.ts +12 -0
- package/dist/rag/search/index.d.ts.map +1 -0
- package/dist/rag/search/index.js +12 -0
- package/dist/rag/search/index.js.map +1 -0
- package/dist/rag/setup/DockerDetector.d.ts +67 -0
- package/dist/rag/setup/DockerDetector.d.ts.map +1 -0
- package/dist/rag/setup/DockerDetector.js +125 -0
- package/dist/rag/setup/DockerDetector.js.map +1 -0
- package/dist/rag/setup/PostgresSetup.d.ts +20 -0
- package/dist/rag/setup/PostgresSetup.d.ts.map +1 -0
- package/dist/rag/setup/PostgresSetup.js +133 -0
- package/dist/rag/setup/PostgresSetup.js.map +1 -0
- package/dist/rag/setup/QdrantSetup.d.ts +26 -0
- package/dist/rag/setup/QdrantSetup.d.ts.map +1 -0
- package/dist/rag/setup/QdrantSetup.js +96 -0
- package/dist/rag/setup/QdrantSetup.js.map +1 -0
- package/dist/rag/setup/types.d.ts +55 -0
- package/dist/rag/setup/types.d.ts.map +1 -0
- package/dist/rag/setup/types.js +6 -0
- package/dist/rag/setup/types.js.map +1 -0
- package/dist/rag/unified/UnifiedRetriever.d.ts +472 -0
- package/dist/rag/unified/UnifiedRetriever.d.ts.map +1 -0
- package/dist/rag/unified/UnifiedRetriever.js +887 -0
- package/dist/rag/unified/UnifiedRetriever.js.map +1 -0
- package/dist/rag/unified/index.d.ts +24 -0
- package/dist/rag/unified/index.d.ts.map +1 -0
- package/dist/rag/unified/index.js +23 -0
- package/dist/rag/unified/index.js.map +1 -0
- package/dist/rag/unified/types.d.ts +546 -0
- package/dist/rag/unified/types.d.ts.map +1 -0
- package/dist/rag/unified/types.js +177 -0
- package/dist/rag/unified/types.js.map +1 -0
- package/dist/speech/providers/AssemblyAISTTProvider.js.map +1 -1
- package/dist/speech/providers/AzureSpeechSTTProvider.js.map +1 -1
- package/dist/speech/providers/BuiltInAdaptiveVadProvider.d.ts +1 -1
- package/dist/speech/providers/DeepgramBatchSTTProvider.js.map +1 -1
- package/package.json +5 -2
|
@@ -0,0 +1,887 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview UnifiedRetriever — single-entry-point retrieval orchestrator
|
|
3
|
+
* that executes a {@link RetrievalPlan} across ALL available sources in
|
|
4
|
+
* parallel, merges results via Reciprocal Rank Fusion (RRF), reranks, and
|
|
5
|
+
* feeds back into cognitive memory.
|
|
6
|
+
*
|
|
7
|
+
* This replaces the need to call RetrievalAugmentor, QueryDispatcher,
|
|
8
|
+
* CognitiveMemoryManager, and MultimodalIndexer separately. It is the
|
|
9
|
+
* canonical retrieval path for AgentOS v2.
|
|
10
|
+
*
|
|
11
|
+
* Architecture:
|
|
12
|
+
* ```
|
|
13
|
+
* RetrievalPlan
|
|
14
|
+
* │
|
|
15
|
+
* ▼
|
|
16
|
+
* ┌─────────────────────────┐
|
|
17
|
+
* │ 1. Memory-first check │ (episodic cache shortcut)
|
|
18
|
+
* └───────────┬─────────────┘
|
|
19
|
+
* ▼
|
|
20
|
+
* ┌─────────────────────────┐
|
|
21
|
+
* │ 2. Parallel sources │ Promise.allSettled across enabled sources
|
|
22
|
+
* │ • hybrid (vector+BM25) │
|
|
23
|
+
* │ • RAPTOR tree │
|
|
24
|
+
* │ • GraphRAG │
|
|
25
|
+
* │ • Cognitive memory │
|
|
26
|
+
* │ • Multimodal index │
|
|
27
|
+
* │ • HyDE hypotheses │
|
|
28
|
+
* └───────────┬─────────────┘
|
|
29
|
+
* ▼
|
|
30
|
+
* ┌─────────────────────────┐
|
|
31
|
+
* │ 3. RRF merge │ Reciprocal Rank Fusion across all source lists
|
|
32
|
+
* └───────────┬─────────────┘
|
|
33
|
+
* ▼
|
|
34
|
+
* ┌─────────────────────────┐
|
|
35
|
+
* │ 4. Temporal boosting │ Exponential decay boost for recent results
|
|
36
|
+
* └───────────┬─────────────┘
|
|
37
|
+
* ▼
|
|
38
|
+
* ┌─────────────────────────┐
|
|
39
|
+
* │ 5. Rerank │ Cross-encoder or LLM-based reranking
|
|
40
|
+
* └───────────┬─────────────┘
|
|
41
|
+
* ▼
|
|
42
|
+
* ┌─────────────────────────┐
|
|
43
|
+
* │ 6. Deep research │ (complex strategy only: decompose → recurse)
|
|
44
|
+
* └───────────┬─────────────┘
|
|
45
|
+
* ▼
|
|
46
|
+
* ┌─────────────────────────┐
|
|
47
|
+
* │ 7. Memory feedback │ Store retrieval as episodic memory + Hebbian
|
|
48
|
+
* └─────────────────────────┘
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* @module agentos/rag/unified/UnifiedRetriever
|
|
52
|
+
* @see RetrievalPlan for the plan specification
|
|
53
|
+
* @see buildDefaultPlan for creating default plans
|
|
54
|
+
*/
|
|
55
|
+
import { EventEmitter } from 'node:events';
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// UNIFIED RETRIEVER
|
|
58
|
+
// ============================================================================
|
|
59
|
+
/**
|
|
60
|
+
* Unified retrieval orchestrator that executes a {@link RetrievalPlan}
|
|
61
|
+
* across ALL available sources in parallel, merges results via RRF,
|
|
62
|
+
* reranks, and feeds back into cognitive memory.
|
|
63
|
+
*
|
|
64
|
+
* This is the single entry point for ALL retrieval in AgentOS. It replaces
|
|
65
|
+
* the need to call RetrievalAugmentor, QueryDispatcher, CognitiveMemoryManager,
|
|
66
|
+
* and MultimodalIndexer separately.
|
|
67
|
+
*
|
|
68
|
+
* All source queries are executed with `Promise.allSettled` so partial
|
|
69
|
+
* failures degrade gracefully — a failed GraphRAG query does not prevent
|
|
70
|
+
* vector results from being returned.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```typescript
|
|
74
|
+
* import { UnifiedRetriever } from '../../rag/unified/index.js';
|
|
75
|
+
* import { buildDefaultPlan } from '../../rag/unified/types.js';
|
|
76
|
+
*
|
|
77
|
+
* const retriever = new UnifiedRetriever({
|
|
78
|
+
* hybridSearcher,
|
|
79
|
+
* raptorTree,
|
|
80
|
+
* graphEngine,
|
|
81
|
+
* memoryManager,
|
|
82
|
+
* hydeRetriever,
|
|
83
|
+
* rerank: async (q, chunks, n) => reranker.rerank(q, chunks, n),
|
|
84
|
+
* });
|
|
85
|
+
*
|
|
86
|
+
* const plan = buildDefaultPlan('moderate');
|
|
87
|
+
* const result = await retriever.retrieve('How does authentication work?', plan);
|
|
88
|
+
* console.log(`Found ${result.chunks.length} chunks from ${Object.keys(result.sourceDiagnostics).length} sources`);
|
|
89
|
+
* ```
|
|
90
|
+
*
|
|
91
|
+
* @see RetrievalPlan for plan specification
|
|
92
|
+
* @see buildDefaultPlan for creating default plans
|
|
93
|
+
* @see UnifiedRetrieverDeps for dependency injection
|
|
94
|
+
*/
|
|
95
|
+
export class UnifiedRetriever extends EventEmitter {
|
|
96
|
+
/**
|
|
97
|
+
* Creates a new UnifiedRetriever.
|
|
98
|
+
*
|
|
99
|
+
* @param deps - Dependency injection container. All dependencies are optional;
|
|
100
|
+
* the retriever gracefully skips sources whose deps are not provided.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const retriever = new UnifiedRetriever({
|
|
105
|
+
* hybridSearcher: myHybridSearcher,
|
|
106
|
+
* raptorTree: myRaptorTree,
|
|
107
|
+
* graphEngine: myGraphEngine,
|
|
108
|
+
* memoryManager: myMemoryManager,
|
|
109
|
+
* rerank: myReranker,
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
constructor(deps) {
|
|
114
|
+
super();
|
|
115
|
+
this.deps = deps;
|
|
116
|
+
this.rrfK = deps.rrfK ?? 60;
|
|
117
|
+
this.defaultTopK = deps.defaultTopK ?? 10;
|
|
118
|
+
this.maxSubQueries = deps.maxSubQueries ?? 5;
|
|
119
|
+
this.memoryCacheThreshold = deps.memoryCacheThreshold ?? 0.85;
|
|
120
|
+
this.defaultMood = deps.defaultMood ?? { valence: 0, arousal: 0, dominance: 0 };
|
|
121
|
+
}
|
|
122
|
+
// --------------------------------------------------------------------------
|
|
123
|
+
// PUBLIC API
|
|
124
|
+
// --------------------------------------------------------------------------
|
|
125
|
+
/**
|
|
126
|
+
* Execute a retrieval plan across all enabled sources.
|
|
127
|
+
*
|
|
128
|
+
* Flow:
|
|
129
|
+
* 1. Check memory first — if episodic memory has a cached answer, fast-return
|
|
130
|
+
* 2. Execute all enabled sources in parallel (Promise.allSettled)
|
|
131
|
+
* 3. Merge results via Reciprocal Rank Fusion (RRF)
|
|
132
|
+
* 4. Apply temporal boosting if configured
|
|
133
|
+
* 5. Rerank merged results
|
|
134
|
+
* 6. For complex plans: decompose and recurse
|
|
135
|
+
* 7. Store retrieval event as episodic memory (feedback loop)
|
|
136
|
+
*
|
|
137
|
+
* @param query - The user's natural-language query.
|
|
138
|
+
* @param plan - The retrieval plan specifying which sources to query.
|
|
139
|
+
* @param topK - Maximum number of final results. Defaults to deps.defaultTopK (10).
|
|
140
|
+
* @returns Unified retrieval result with merged, reranked chunks and diagnostics.
|
|
141
|
+
*
|
|
142
|
+
* @throws Never — all source failures are caught and reported in diagnostics.
|
|
143
|
+
* The retriever always returns a result, even if empty.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```typescript
|
|
147
|
+
* const plan = buildDefaultPlan('moderate');
|
|
148
|
+
* const result = await retriever.retrieve('How does auth work?', plan);
|
|
149
|
+
* for (const chunk of result.chunks) {
|
|
150
|
+
* console.log(`[${chunk.matchType}] ${chunk.relevanceScore.toFixed(3)}: ${chunk.content.slice(0, 80)}`);
|
|
151
|
+
* }
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
async retrieve(query, plan, topK) {
|
|
155
|
+
const startTime = Date.now();
|
|
156
|
+
const resolvedTopK = topK ?? this.defaultTopK;
|
|
157
|
+
// Emit plan start event
|
|
158
|
+
this.emitEvent({ type: 'unified:plan-start', plan, timestamp: Date.now() });
|
|
159
|
+
// None strategy → immediate empty return
|
|
160
|
+
if (plan.strategy === 'none') {
|
|
161
|
+
return this.buildEmptyResult(plan, startTime);
|
|
162
|
+
}
|
|
163
|
+
// Initialize diagnostics accumulator
|
|
164
|
+
const diagnostics = this.emptyDiagnostics();
|
|
165
|
+
// ── Phase 1: Memory-first check ──────────────────────────────────────
|
|
166
|
+
const memoryCacheHit = await this.checkMemoryCache(query, plan, diagnostics);
|
|
167
|
+
if (memoryCacheHit) {
|
|
168
|
+
return this.buildResult(memoryCacheHit, plan, diagnostics, startTime, true);
|
|
169
|
+
}
|
|
170
|
+
// ── Phase 2: Parallel source execution ───────────────────────────────
|
|
171
|
+
const sourceResults = await this.executeSourcesInParallel(query, plan, diagnostics);
|
|
172
|
+
// ── Phase 3: RRF merge ───────────────────────────────────────────────
|
|
173
|
+
let merged = this.rrfMerge(sourceResults, plan);
|
|
174
|
+
this.emitEvent({
|
|
175
|
+
type: 'unified:merge-complete',
|
|
176
|
+
totalChunks: merged.length,
|
|
177
|
+
timestamp: Date.now(),
|
|
178
|
+
});
|
|
179
|
+
// ── Phase 4: Temporal boosting ───────────────────────────────────────
|
|
180
|
+
if (plan.temporal.preferRecent) {
|
|
181
|
+
merged = this.applyTemporalBoosting(merged, plan);
|
|
182
|
+
}
|
|
183
|
+
// ── Phase 5: Rerank ──────────────────────────────────────────────────
|
|
184
|
+
let reranked;
|
|
185
|
+
if (this.deps.rerank && merged.length > 0) {
|
|
186
|
+
const rerankStart = Date.now();
|
|
187
|
+
try {
|
|
188
|
+
reranked = await this.deps.rerank(query, merged, resolvedTopK);
|
|
189
|
+
diagnostics.rerank = {
|
|
190
|
+
inputCount: merged.length,
|
|
191
|
+
outputCount: reranked.length,
|
|
192
|
+
durationMs: Date.now() - rerankStart,
|
|
193
|
+
};
|
|
194
|
+
this.emitEvent({
|
|
195
|
+
type: 'unified:rerank-complete',
|
|
196
|
+
inputCount: merged.length,
|
|
197
|
+
outputCount: reranked.length,
|
|
198
|
+
durationMs: Date.now() - rerankStart,
|
|
199
|
+
timestamp: Date.now(),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
catch {
|
|
203
|
+
// Reranker failed — fall back to score-sorted merge
|
|
204
|
+
reranked = merged
|
|
205
|
+
.sort((a, b) => b.relevanceScore - a.relevanceScore)
|
|
206
|
+
.slice(0, resolvedTopK);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
reranked = merged
|
|
211
|
+
.sort((a, b) => b.relevanceScore - a.relevanceScore)
|
|
212
|
+
.slice(0, resolvedTopK);
|
|
213
|
+
}
|
|
214
|
+
// ── Phase 6: Deep research (complex strategy only) ───────────────────
|
|
215
|
+
let researchSynthesis;
|
|
216
|
+
if (plan.deepResearch && this.deps.deepResearch) {
|
|
217
|
+
const researchResult = await this.executeDeepResearch(query, plan, reranked, diagnostics);
|
|
218
|
+
if (researchResult) {
|
|
219
|
+
reranked = this.mergeChunks(reranked, researchResult.chunks);
|
|
220
|
+
researchSynthesis = researchResult.synthesis;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
// ── Phase 7: Memory feedback ─────────────────────────────────────────
|
|
224
|
+
await this.storeMemoryFeedback(query, reranked, plan);
|
|
225
|
+
return this.buildResult(reranked, plan, diagnostics, startTime, false, researchSynthesis);
|
|
226
|
+
}
|
|
227
|
+
// --------------------------------------------------------------------------
|
|
228
|
+
// PHASE 1: Memory-first check
|
|
229
|
+
// --------------------------------------------------------------------------
|
|
230
|
+
/**
|
|
231
|
+
* Checks episodic memory for a previous retrieval about the same topic.
|
|
232
|
+
*
|
|
233
|
+
* If a high-confidence cached retrieval is found, returns the cached chunks
|
|
234
|
+
* directly — avoiding the cost of external source queries.
|
|
235
|
+
*
|
|
236
|
+
* @param query - The user query.
|
|
237
|
+
* @param plan - The retrieval plan.
|
|
238
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
239
|
+
* @returns Cached chunks if a high-confidence match was found, null otherwise.
|
|
240
|
+
*/
|
|
241
|
+
async checkMemoryCache(query, plan, diagnostics) {
|
|
242
|
+
if (!plan.sources.memory ||
|
|
243
|
+
!plan.memoryTypes.includes('episodic') ||
|
|
244
|
+
!this.deps.memoryManager) {
|
|
245
|
+
return null;
|
|
246
|
+
}
|
|
247
|
+
const memStart = Date.now();
|
|
248
|
+
try {
|
|
249
|
+
const cached = await this.deps.memoryManager.retrieve(`Previous retrieval about: ${query}`, this.defaultMood, {
|
|
250
|
+
types: ['episodic'],
|
|
251
|
+
topK: 3,
|
|
252
|
+
});
|
|
253
|
+
if (cached.retrieved.length > 0 &&
|
|
254
|
+
cached.retrieved[0].retrievalScore > this.memoryCacheThreshold) {
|
|
255
|
+
const cacheAge = Date.now() - (cached.retrieved[0].createdAt ?? Date.now());
|
|
256
|
+
const chunks = cached.retrieved.map((trace, idx) => ({
|
|
257
|
+
id: trace.id,
|
|
258
|
+
content: trace.content,
|
|
259
|
+
heading: 'Memory',
|
|
260
|
+
sourcePath: 'memory://episodic',
|
|
261
|
+
relevanceScore: trace.retrievalScore,
|
|
262
|
+
matchType: 'vector',
|
|
263
|
+
}));
|
|
264
|
+
diagnostics.memory = {
|
|
265
|
+
chunkCount: chunks.length,
|
|
266
|
+
durationMs: Date.now() - memStart,
|
|
267
|
+
};
|
|
268
|
+
this.emitEvent({
|
|
269
|
+
type: 'unified:memory-cache-hit',
|
|
270
|
+
query,
|
|
271
|
+
cacheAge,
|
|
272
|
+
timestamp: Date.now(),
|
|
273
|
+
});
|
|
274
|
+
return chunks;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
catch {
|
|
278
|
+
// Memory lookup is non-critical — continue to external sources
|
|
279
|
+
}
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
// --------------------------------------------------------------------------
|
|
283
|
+
// PHASE 2: Parallel source execution
|
|
284
|
+
// --------------------------------------------------------------------------
|
|
285
|
+
/**
|
|
286
|
+
* Executes all enabled retrieval sources in parallel using Promise.allSettled.
|
|
287
|
+
*
|
|
288
|
+
* Sources that fail are silently skipped — their error is recorded in diagnostics
|
|
289
|
+
* and an event is emitted, but the overall retrieval continues with results from
|
|
290
|
+
* other sources.
|
|
291
|
+
*
|
|
292
|
+
* @param query - The user query.
|
|
293
|
+
* @param plan - The retrieval plan.
|
|
294
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
295
|
+
* @returns Map of source name to retrieved chunks.
|
|
296
|
+
*/
|
|
297
|
+
async executeSourcesInParallel(query, plan, diagnostics) {
|
|
298
|
+
const sourcePromises = new Map();
|
|
299
|
+
// --- Hybrid (vector + BM25) ---
|
|
300
|
+
if (plan.sources.vector || plan.sources.bm25) {
|
|
301
|
+
sourcePromises.set('hybrid', this.searchHybrid(query, diagnostics));
|
|
302
|
+
}
|
|
303
|
+
// --- RAPTOR ---
|
|
304
|
+
if (plan.sources.raptor && this.deps.raptorTree) {
|
|
305
|
+
sourcePromises.set('raptor', this.searchRaptor(query, plan, diagnostics));
|
|
306
|
+
}
|
|
307
|
+
// --- Memory ---
|
|
308
|
+
if (plan.sources.memory && this.deps.memoryManager) {
|
|
309
|
+
sourcePromises.set('memory', this.searchMemory(query, plan, diagnostics));
|
|
310
|
+
}
|
|
311
|
+
// --- Multimodal ---
|
|
312
|
+
if (plan.sources.multimodal && this.deps.multimodalIndexer) {
|
|
313
|
+
const nonTextModalities = plan.modalities.filter(m => m !== 'text');
|
|
314
|
+
if (nonTextModalities.length > 0) {
|
|
315
|
+
sourcePromises.set('multimodal', this.searchMultimodal(query, plan, diagnostics));
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// --- HyDE ---
|
|
319
|
+
if (plan.hyde.enabled && this.deps.hydeRetriever) {
|
|
320
|
+
sourcePromises.set('hyde', this.searchHyde(query, plan, diagnostics));
|
|
321
|
+
}
|
|
322
|
+
// Execute all sources in parallel
|
|
323
|
+
const entries = Array.from(sourcePromises.entries());
|
|
324
|
+
const settled = await Promise.allSettled(entries.map(([, p]) => p));
|
|
325
|
+
const results = new Map();
|
|
326
|
+
for (let i = 0; i < entries.length; i++) {
|
|
327
|
+
const [name] = entries[i];
|
|
328
|
+
const outcome = settled[i];
|
|
329
|
+
if (outcome.status === 'fulfilled') {
|
|
330
|
+
results.set(name, outcome.value);
|
|
331
|
+
this.emitEvent({
|
|
332
|
+
type: 'unified:source-complete',
|
|
333
|
+
source: name,
|
|
334
|
+
chunkCount: outcome.value.length,
|
|
335
|
+
durationMs: 0, // Already tracked per-source
|
|
336
|
+
timestamp: Date.now(),
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
else {
|
|
340
|
+
results.set(name, []);
|
|
341
|
+
this.emitEvent({
|
|
342
|
+
type: 'unified:source-error',
|
|
343
|
+
source: name,
|
|
344
|
+
error: outcome.reason?.message ?? 'Unknown error',
|
|
345
|
+
timestamp: Date.now(),
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// --- GraphRAG (depends on hybrid results for seed chunks) ---
|
|
350
|
+
if (plan.sources.graph && this.deps.graphEngine) {
|
|
351
|
+
const hybridChunks = results.get('hybrid') ?? [];
|
|
352
|
+
const graphChunks = await this.searchGraph(query, hybridChunks, plan, diagnostics);
|
|
353
|
+
results.set('graph', graphChunks);
|
|
354
|
+
}
|
|
355
|
+
return results;
|
|
356
|
+
}
|
|
357
|
+
// --------------------------------------------------------------------------
|
|
358
|
+
// Individual source searches
|
|
359
|
+
// --------------------------------------------------------------------------
|
|
360
|
+
/**
|
|
361
|
+
* Searches the hybrid dense+sparse index.
|
|
362
|
+
*
|
|
363
|
+
* @param query - The search query.
|
|
364
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
365
|
+
* @returns Retrieved chunks from hybrid search.
|
|
366
|
+
*/
|
|
367
|
+
async searchHybrid(query, diagnostics) {
|
|
368
|
+
const start = Date.now();
|
|
369
|
+
if (this.deps.hybridSearcher) {
|
|
370
|
+
const collectionName = this.deps.collectionName ?? 'knowledge-base';
|
|
371
|
+
const results = await this.deps.hybridSearcher.search(query, collectionName, 15);
|
|
372
|
+
const chunks = results.map((r) => ({
|
|
373
|
+
id: r.id,
|
|
374
|
+
content: r.textContent ?? '',
|
|
375
|
+
heading: r.metadata?.heading ?? '',
|
|
376
|
+
sourcePath: r.metadata?.sourcePath ?? '',
|
|
377
|
+
relevanceScore: r.score,
|
|
378
|
+
matchType: 'vector',
|
|
379
|
+
}));
|
|
380
|
+
diagnostics.hybrid = { chunkCount: chunks.length, durationMs: Date.now() - start };
|
|
381
|
+
return chunks;
|
|
382
|
+
}
|
|
383
|
+
if (this.deps.vectorSearch) {
|
|
384
|
+
const chunks = await this.deps.vectorSearch(query, 15);
|
|
385
|
+
diagnostics.hybrid = { chunkCount: chunks.length, durationMs: Date.now() - start };
|
|
386
|
+
return chunks;
|
|
387
|
+
}
|
|
388
|
+
return [];
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Searches the RAPTOR hierarchical summary tree.
|
|
392
|
+
*
|
|
393
|
+
* @param query - The search query.
|
|
394
|
+
* @param plan - The retrieval plan (for layer filtering).
|
|
395
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
396
|
+
* @returns Retrieved chunks from RAPTOR search.
|
|
397
|
+
*/
|
|
398
|
+
async searchRaptor(query, plan, diagnostics) {
|
|
399
|
+
const start = Date.now();
|
|
400
|
+
const results = await this.deps.raptorTree.search(query, 10);
|
|
401
|
+
// Filter by requested layers if specified
|
|
402
|
+
let filtered = results;
|
|
403
|
+
if (plan.raptorLayers.length > 0) {
|
|
404
|
+
const layerSet = new Set(plan.raptorLayers);
|
|
405
|
+
filtered = results.filter(r => layerSet.has(r.layer));
|
|
406
|
+
}
|
|
407
|
+
const chunks = filtered.map(r => ({
|
|
408
|
+
id: r.id,
|
|
409
|
+
content: r.text,
|
|
410
|
+
heading: r.isSummary ? `RAPTOR L${r.layer} Summary` : r.metadata?.heading ?? '',
|
|
411
|
+
sourcePath: r.metadata?.sourcePath ?? `raptor://layer-${r.layer}`,
|
|
412
|
+
relevanceScore: r.score,
|
|
413
|
+
matchType: 'vector',
|
|
414
|
+
}));
|
|
415
|
+
diagnostics.raptor = { chunkCount: chunks.length, durationMs: Date.now() - start };
|
|
416
|
+
return chunks;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Searches the GraphRAG engine using seed chunks from hybrid search.
|
|
420
|
+
*
|
|
421
|
+
* @param query - The search query.
|
|
422
|
+
* @param seedChunks - Seed chunks from hybrid search for entity extraction.
|
|
423
|
+
* @param plan - The retrieval plan (for graph traversal config).
|
|
424
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
425
|
+
* @returns Retrieved chunks from graph search.
|
|
426
|
+
*/
|
|
427
|
+
async searchGraph(query, seedChunks, plan, diagnostics) {
|
|
428
|
+
const start = Date.now();
|
|
429
|
+
try {
|
|
430
|
+
const result = await this.deps.graphEngine.localSearch(query, {
|
|
431
|
+
topK: 10,
|
|
432
|
+
});
|
|
433
|
+
const chunks = (result.entities ?? []).map((entity, idx) => ({
|
|
434
|
+
id: `graph-entity-${idx}`,
|
|
435
|
+
content: entity.description,
|
|
436
|
+
heading: `${entity.type}: ${entity.name}`,
|
|
437
|
+
sourcePath: 'graphrag://entities',
|
|
438
|
+
relevanceScore: entity.relevanceScore ?? 0.7,
|
|
439
|
+
matchType: 'graph',
|
|
440
|
+
}));
|
|
441
|
+
diagnostics.graph = { chunkCount: chunks.length, durationMs: Date.now() - start };
|
|
442
|
+
this.emitEvent({
|
|
443
|
+
type: 'unified:source-complete',
|
|
444
|
+
source: 'graph',
|
|
445
|
+
chunkCount: chunks.length,
|
|
446
|
+
durationMs: Date.now() - start,
|
|
447
|
+
timestamp: Date.now(),
|
|
448
|
+
});
|
|
449
|
+
return chunks;
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
diagnostics.graph = { chunkCount: 0, durationMs: Date.now() - start };
|
|
453
|
+
this.emitEvent({
|
|
454
|
+
type: 'unified:source-error',
|
|
455
|
+
source: 'graph',
|
|
456
|
+
error: 'GraphRAG search failed',
|
|
457
|
+
timestamp: Date.now(),
|
|
458
|
+
});
|
|
459
|
+
return [];
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Searches cognitive memory for relevant traces.
|
|
464
|
+
*
|
|
465
|
+
* @param query - The search query.
|
|
466
|
+
* @param plan - The retrieval plan (for memory type filtering).
|
|
467
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
468
|
+
* @returns Retrieved chunks from memory.
|
|
469
|
+
*/
|
|
470
|
+
async searchMemory(query, plan, diagnostics) {
|
|
471
|
+
const start = Date.now();
|
|
472
|
+
const result = await this.deps.memoryManager.retrieve(query, this.defaultMood, {
|
|
473
|
+
types: plan.memoryTypes,
|
|
474
|
+
topK: 5,
|
|
475
|
+
});
|
|
476
|
+
const chunks = result.retrieved.map(trace => ({
|
|
477
|
+
id: trace.id,
|
|
478
|
+
content: trace.content,
|
|
479
|
+
heading: `Memory (${trace.type})`,
|
|
480
|
+
sourcePath: `memory://${trace.type}`,
|
|
481
|
+
relevanceScore: trace.retrievalScore,
|
|
482
|
+
matchType: 'vector',
|
|
483
|
+
}));
|
|
484
|
+
diagnostics.memory = { chunkCount: chunks.length, durationMs: Date.now() - start };
|
|
485
|
+
return chunks;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Searches the multimodal index for non-text content.
|
|
489
|
+
*
|
|
490
|
+
* @param query - The search query.
|
|
491
|
+
* @param plan - The retrieval plan (for modality filtering).
|
|
492
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
493
|
+
* @returns Retrieved chunks from multimodal search.
|
|
494
|
+
*/
|
|
495
|
+
async searchMultimodal(query, plan, diagnostics) {
|
|
496
|
+
const start = Date.now();
|
|
497
|
+
const nonTextModalities = plan.modalities.filter(m => m !== 'text');
|
|
498
|
+
const results = await this.deps.multimodalIndexer.search(query, {
|
|
499
|
+
modalities: nonTextModalities,
|
|
500
|
+
topK: 5,
|
|
501
|
+
});
|
|
502
|
+
const chunks = results.map(r => ({
|
|
503
|
+
id: r.id,
|
|
504
|
+
content: r.content,
|
|
505
|
+
heading: `${r.modality} content`,
|
|
506
|
+
sourcePath: `multimodal://${r.modality}`,
|
|
507
|
+
relevanceScore: r.score,
|
|
508
|
+
matchType: 'vector',
|
|
509
|
+
}));
|
|
510
|
+
diagnostics.multimodal = { chunkCount: chunks.length, durationMs: Date.now() - start };
|
|
511
|
+
return chunks;
|
|
512
|
+
}
|
|
513
|
+
/**
|
|
514
|
+
* Generates HyDE hypotheses and searches with each hypothesis embedding.
|
|
515
|
+
*
|
|
516
|
+
* @param query - The search query.
|
|
517
|
+
* @param plan - The retrieval plan (for hypothesis count).
|
|
518
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
519
|
+
* @returns Retrieved chunks from HyDE search.
|
|
520
|
+
*/
|
|
521
|
+
async searchHyde(query, plan, diagnostics) {
|
|
522
|
+
const start = Date.now();
|
|
523
|
+
const retriever = this.deps.hydeRetriever;
|
|
524
|
+
const collectionName = this.deps.collectionName ?? 'knowledge-base';
|
|
525
|
+
// Use multi-hypothesis retrieval when count > 1
|
|
526
|
+
if (plan.hyde.hypothesisCount > 1) {
|
|
527
|
+
// We need a vector store to use HyDE's retrieveMulti.
|
|
528
|
+
// Since hybridSearcher wraps the vector store, we generate hypotheses
|
|
529
|
+
// and search with each one individually.
|
|
530
|
+
const { hypotheses } = await retriever.generateMultipleHypotheses(query, plan.hyde.hypothesisCount);
|
|
531
|
+
// For each hypothesis, do a hybrid search and merge
|
|
532
|
+
const allChunks = [];
|
|
533
|
+
for (const hypothesis of hypotheses) {
|
|
534
|
+
if (this.deps.hybridSearcher) {
|
|
535
|
+
const results = await this.deps.hybridSearcher.search(hypothesis, collectionName, 5);
|
|
536
|
+
for (const r of results) {
|
|
537
|
+
allChunks.push({
|
|
538
|
+
id: r.id,
|
|
539
|
+
content: r.textContent ?? '',
|
|
540
|
+
heading: r.metadata?.heading ?? '',
|
|
541
|
+
sourcePath: r.metadata?.sourcePath ?? '',
|
|
542
|
+
relevanceScore: r.score,
|
|
543
|
+
matchType: 'vector',
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
else if (this.deps.vectorSearch) {
|
|
548
|
+
const chunks = await this.deps.vectorSearch(hypothesis, 5);
|
|
549
|
+
allChunks.push(...chunks);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
// Deduplicate by ID, keeping highest score
|
|
553
|
+
const deduped = this.deduplicateChunks(allChunks);
|
|
554
|
+
diagnostics.hyde = {
|
|
555
|
+
chunkCount: deduped.length,
|
|
556
|
+
durationMs: Date.now() - start,
|
|
557
|
+
hypothesisCount: hypotheses.length,
|
|
558
|
+
};
|
|
559
|
+
return deduped;
|
|
560
|
+
}
|
|
561
|
+
// Single hypothesis path
|
|
562
|
+
const { hypothesis } = await retriever.generateHypothesis(query);
|
|
563
|
+
let chunks = [];
|
|
564
|
+
if (this.deps.hybridSearcher) {
|
|
565
|
+
const results = await this.deps.hybridSearcher.search(hypothesis, collectionName, 10);
|
|
566
|
+
chunks = results.map((r) => ({
|
|
567
|
+
id: r.id,
|
|
568
|
+
content: r.textContent ?? '',
|
|
569
|
+
heading: r.metadata?.heading ?? '',
|
|
570
|
+
sourcePath: r.metadata?.sourcePath ?? '',
|
|
571
|
+
relevanceScore: r.score,
|
|
572
|
+
matchType: 'vector',
|
|
573
|
+
}));
|
|
574
|
+
}
|
|
575
|
+
else if (this.deps.vectorSearch) {
|
|
576
|
+
chunks = await this.deps.vectorSearch(hypothesis, 10);
|
|
577
|
+
}
|
|
578
|
+
diagnostics.hyde = {
|
|
579
|
+
chunkCount: chunks.length,
|
|
580
|
+
durationMs: Date.now() - start,
|
|
581
|
+
hypothesisCount: 1,
|
|
582
|
+
};
|
|
583
|
+
return chunks;
|
|
584
|
+
}
|
|
585
|
+
// --------------------------------------------------------------------------
|
|
586
|
+
// PHASE 3: RRF Merge
|
|
587
|
+
// --------------------------------------------------------------------------
|
|
588
|
+
/**
|
|
589
|
+
* Merges results from multiple sources using Reciprocal Rank Fusion (RRF).
|
|
590
|
+
*
|
|
591
|
+
* RRF formula (Cormack et al. 2009):
|
|
592
|
+
* ```
|
|
593
|
+
* score(d) = sum_{i} 1 / (k + rank_i(d))
|
|
594
|
+
* ```
|
|
595
|
+
* where k is the RRF constant (default 60) and rank_i(d) is the 1-based
|
|
596
|
+
* rank of document d in source i's result list.
|
|
597
|
+
*
|
|
598
|
+
* Documents appearing in multiple sources naturally receive higher fused
|
|
599
|
+
* scores, boosting documents that are relevant across different retrieval
|
|
600
|
+
* methods.
|
|
601
|
+
*
|
|
602
|
+
* @param sourceResults - Map of source name to ranked chunk lists.
|
|
603
|
+
* @param plan - The retrieval plan (unused currently, reserved for future weighting).
|
|
604
|
+
* @returns Merged chunks with fused RRF scores, sorted descending.
|
|
605
|
+
*/
|
|
606
|
+
rrfMerge(sourceResults, plan) {
|
|
607
|
+
const k = this.rrfK;
|
|
608
|
+
const scoreMap = new Map();
|
|
609
|
+
for (const [_source, chunks] of sourceResults) {
|
|
610
|
+
for (let rank = 0; rank < chunks.length; rank++) {
|
|
611
|
+
const chunk = chunks[rank];
|
|
612
|
+
const rrfScore = 1 / (k + rank + 1);
|
|
613
|
+
const existing = scoreMap.get(chunk.id);
|
|
614
|
+
if (existing) {
|
|
615
|
+
existing.score += rrfScore;
|
|
616
|
+
// Keep the chunk with more content
|
|
617
|
+
if (chunk.content.length > existing.chunk.content.length) {
|
|
618
|
+
existing.chunk = { ...chunk, relevanceScore: existing.score };
|
|
619
|
+
}
|
|
620
|
+
else {
|
|
621
|
+
existing.chunk = { ...existing.chunk, relevanceScore: existing.score };
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
else {
|
|
625
|
+
scoreMap.set(chunk.id, {
|
|
626
|
+
chunk: { ...chunk, relevanceScore: rrfScore },
|
|
627
|
+
score: rrfScore,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
// Sort by fused score descending
|
|
633
|
+
return Array.from(scoreMap.values())
|
|
634
|
+
.sort((a, b) => b.score - a.score)
|
|
635
|
+
.map(entry => ({ ...entry.chunk, relevanceScore: entry.score }));
|
|
636
|
+
}
|
|
637
|
+
// --------------------------------------------------------------------------
|
|
638
|
+
// PHASE 4: Temporal Boosting
|
|
639
|
+
// --------------------------------------------------------------------------
|
|
640
|
+
/**
|
|
641
|
+
* Applies exponential decay temporal boosting to results.
|
|
642
|
+
*
|
|
643
|
+
* Recent results receive a multiplicative boost based on their age.
|
|
644
|
+
* The boost decays exponentially: `boost = exp(-age / maxAgeMs) * recencyBoost`.
|
|
645
|
+
*
|
|
646
|
+
* Also filters out results older than `maxAgeMs` when set.
|
|
647
|
+
*
|
|
648
|
+
* @param chunks - Chunks to boost.
|
|
649
|
+
* @param plan - The retrieval plan with temporal configuration.
|
|
650
|
+
* @returns Chunks with adjusted relevance scores.
|
|
651
|
+
*/
|
|
652
|
+
applyTemporalBoosting(chunks, plan) {
|
|
653
|
+
const now = Date.now();
|
|
654
|
+
const maxAge = plan.temporal.maxAgeMs;
|
|
655
|
+
const boostFactor = plan.temporal.recencyBoost;
|
|
656
|
+
return chunks
|
|
657
|
+
.filter(chunk => {
|
|
658
|
+
if (maxAge === null)
|
|
659
|
+
return true;
|
|
660
|
+
const timestamp = chunk.metadata?.timestamp ?? 0;
|
|
661
|
+
return timestamp === 0 || (now - timestamp) <= maxAge;
|
|
662
|
+
})
|
|
663
|
+
.map(chunk => {
|
|
664
|
+
const timestamp = chunk.metadata?.timestamp ?? 0;
|
|
665
|
+
if (timestamp === 0 || maxAge === null)
|
|
666
|
+
return chunk;
|
|
667
|
+
const age = now - timestamp;
|
|
668
|
+
const decay = Math.exp(-age / maxAge);
|
|
669
|
+
const boost = decay * boostFactor;
|
|
670
|
+
return {
|
|
671
|
+
...chunk,
|
|
672
|
+
relevanceScore: chunk.relevanceScore * (1 + boost),
|
|
673
|
+
};
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
// --------------------------------------------------------------------------
|
|
677
|
+
// PHASE 6: Deep Research
|
|
678
|
+
// --------------------------------------------------------------------------
|
|
679
|
+
/**
|
|
680
|
+
* Executes deep research by decomposing the query into sub-queries and
|
|
681
|
+
* recursing with moderate-level plans.
|
|
682
|
+
*
|
|
683
|
+
* @param query - The original query.
|
|
684
|
+
* @param plan - The retrieval plan.
|
|
685
|
+
* @param existingChunks - Chunks already gathered from other sources.
|
|
686
|
+
* @param diagnostics - Diagnostics accumulator.
|
|
687
|
+
* @returns Research synthesis and additional chunks, or null if research failed.
|
|
688
|
+
*/
|
|
689
|
+
async executeDeepResearch(query, plan, existingChunks, diagnostics) {
|
|
690
|
+
const start = Date.now();
|
|
691
|
+
const allChunks = [];
|
|
692
|
+
let synthesis;
|
|
693
|
+
// Sub-query decomposition and recursive retrieval
|
|
694
|
+
if (this.deps.decompose) {
|
|
695
|
+
try {
|
|
696
|
+
const subQueries = await this.deps.decompose(query, this.maxSubQueries);
|
|
697
|
+
this.emitEvent({
|
|
698
|
+
type: 'unified:decompose',
|
|
699
|
+
subQueries,
|
|
700
|
+
timestamp: Date.now(),
|
|
701
|
+
});
|
|
702
|
+
// Recurse with moderate plans for each sub-query (no further decomposition)
|
|
703
|
+
for (const subQuery of subQueries) {
|
|
704
|
+
const subPlan = {
|
|
705
|
+
...plan,
|
|
706
|
+
strategy: 'moderate',
|
|
707
|
+
deepResearch: false,
|
|
708
|
+
hyde: { enabled: plan.hyde.enabled, hypothesisCount: 1 },
|
|
709
|
+
};
|
|
710
|
+
const subResult = await this.retrieve(subQuery, subPlan, 5);
|
|
711
|
+
allChunks.push(...subResult.chunks);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
catch {
|
|
715
|
+
// Decomposition failed — skip sub-query recursion
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
// Deep research synthesis pass
|
|
719
|
+
if (this.deps.deepResearch) {
|
|
720
|
+
try {
|
|
721
|
+
const researchResult = await this.deps.deepResearch(query, ['docs', 'web']);
|
|
722
|
+
allChunks.push(...researchResult.sources);
|
|
723
|
+
synthesis = researchResult.synthesis;
|
|
724
|
+
}
|
|
725
|
+
catch {
|
|
726
|
+
// Research failed — continue with whatever we have
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
diagnostics.research = { chunkCount: allChunks.length, durationMs: Date.now() - start };
|
|
730
|
+
if (allChunks.length === 0 && !synthesis) {
|
|
731
|
+
return null;
|
|
732
|
+
}
|
|
733
|
+
return {
|
|
734
|
+
chunks: this.deduplicateChunks(allChunks),
|
|
735
|
+
synthesis: synthesis ?? '',
|
|
736
|
+
};
|
|
737
|
+
}
|
|
738
|
+
// --------------------------------------------------------------------------
|
|
739
|
+
// PHASE 7: Memory Feedback
|
|
740
|
+
// --------------------------------------------------------------------------
|
|
741
|
+
/**
|
|
742
|
+
* Stores the retrieval event as an episodic memory trace and strengthens
|
|
743
|
+
* memory traces for top-retrieved content (Hebbian learning).
|
|
744
|
+
*
|
|
745
|
+
* This creates a feedback loop where frequently retrieved information
|
|
746
|
+
* becomes easier to retrieve in the future, similar to how biological
|
|
747
|
+
* memory consolidation strengthens neural pathways through repeated access.
|
|
748
|
+
*
|
|
749
|
+
* @param query - The original query.
|
|
750
|
+
* @param chunks - The final reranked chunks.
|
|
751
|
+
* @param plan - The retrieval plan.
|
|
752
|
+
*/
|
|
753
|
+
async storeMemoryFeedback(query, chunks, plan) {
|
|
754
|
+
if (!this.deps.memoryManager || !plan.sources.memory) {
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
try {
|
|
758
|
+
// Store the retrieval event as an episodic memory
|
|
759
|
+
const topContent = chunks[0]?.content?.slice(0, 200) ?? 'No results';
|
|
760
|
+
await this.deps.memoryManager.encode(`Retrieved ${chunks.length} results for: "${query}". Top result: "${topContent}"`, this.defaultMood, 'neutral', {
|
|
761
|
+
type: 'episodic',
|
|
762
|
+
sourceType: 'reflection',
|
|
763
|
+
tags: ['retrieval', 'unified-retriever'],
|
|
764
|
+
});
|
|
765
|
+
// Strengthen memory traces for retrieved content (Hebbian learning)
|
|
766
|
+
const store = this.deps.memoryManager.getStore();
|
|
767
|
+
if (store) {
|
|
768
|
+
for (const chunk of chunks.slice(0, 3)) {
|
|
769
|
+
if (chunk.id.startsWith('mt_')) {
|
|
770
|
+
// This is a memory trace ID — record access to strengthen it
|
|
771
|
+
await store.recordAccess(chunk.id);
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
this.emitEvent({
|
|
776
|
+
type: 'unified:memory-feedback',
|
|
777
|
+
tracesStored: 1,
|
|
778
|
+
timestamp: Date.now(),
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
catch {
|
|
782
|
+
// Memory feedback is non-critical — never fail the retrieval
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
// --------------------------------------------------------------------------
|
|
786
|
+
// Utilities
|
|
787
|
+
// --------------------------------------------------------------------------
|
|
788
|
+
/**
|
|
789
|
+
* Deduplicates chunks by ID, keeping the one with the highest relevance score.
|
|
790
|
+
*
|
|
791
|
+
* @param chunks - Chunks to deduplicate.
|
|
792
|
+
* @returns Deduplicated chunks.
|
|
793
|
+
*/
|
|
794
|
+
deduplicateChunks(chunks) {
|
|
795
|
+
const seen = new Map();
|
|
796
|
+
for (const chunk of chunks) {
|
|
797
|
+
const existing = seen.get(chunk.id);
|
|
798
|
+
if (!existing || chunk.relevanceScore > existing.relevanceScore) {
|
|
799
|
+
seen.set(chunk.id, chunk);
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
return Array.from(seen.values());
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Merges two chunk arrays, deduplicating by ID.
|
|
806
|
+
*
|
|
807
|
+
* @param primary - Primary chunk array.
|
|
808
|
+
* @param secondary - Secondary chunk array.
|
|
809
|
+
* @returns Merged, deduplicated array.
|
|
810
|
+
*/
|
|
811
|
+
mergeChunks(primary, secondary) {
|
|
812
|
+
return this.deduplicateChunks([...primary, ...secondary]);
|
|
813
|
+
}
|
|
814
|
+
/**
|
|
815
|
+
* Emits a typed UnifiedRetriever event.
|
|
816
|
+
*
|
|
817
|
+
* Routes to both the injected deps.emit callback and the Node.js
|
|
818
|
+
* EventEmitter for maximum flexibility.
|
|
819
|
+
*
|
|
820
|
+
* @param event - The event to emit.
|
|
821
|
+
*/
|
|
822
|
+
emitEvent(event) {
|
|
823
|
+
if (this.deps.emit) {
|
|
824
|
+
this.deps.emit(event);
|
|
825
|
+
}
|
|
826
|
+
this.emit(event.type, event);
|
|
827
|
+
}
|
|
828
|
+
/**
|
|
829
|
+
* Creates an empty diagnostics object.
|
|
830
|
+
*
|
|
831
|
+
* @returns Fresh diagnostics with all counters at zero.
|
|
832
|
+
*/
|
|
833
|
+
emptyDiagnostics() {
|
|
834
|
+
return {
|
|
835
|
+
hybrid: { chunkCount: 0, durationMs: 0 },
|
|
836
|
+
raptor: { chunkCount: 0, durationMs: 0 },
|
|
837
|
+
graph: { chunkCount: 0, durationMs: 0 },
|
|
838
|
+
memory: { chunkCount: 0, durationMs: 0 },
|
|
839
|
+
multimodal: { chunkCount: 0, durationMs: 0 },
|
|
840
|
+
hyde: { chunkCount: 0, durationMs: 0, hypothesisCount: 0 },
|
|
841
|
+
rerank: { inputCount: 0, outputCount: 0, durationMs: 0 },
|
|
842
|
+
research: { chunkCount: 0, durationMs: 0 },
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* Builds an empty result for the 'none' strategy.
|
|
847
|
+
*
|
|
848
|
+
* @param plan - The retrieval plan.
|
|
849
|
+
* @param startTime - Pipeline start timestamp.
|
|
850
|
+
* @returns Empty unified retrieval result.
|
|
851
|
+
*/
|
|
852
|
+
buildEmptyResult(plan, startTime) {
|
|
853
|
+
const result = {
|
|
854
|
+
chunks: [],
|
|
855
|
+
plan,
|
|
856
|
+
sourceDiagnostics: this.emptyDiagnostics(),
|
|
857
|
+
durationMs: Date.now() - startTime,
|
|
858
|
+
memoryCacheHit: false,
|
|
859
|
+
};
|
|
860
|
+
this.emitEvent({ type: 'unified:complete', result, timestamp: Date.now() });
|
|
861
|
+
return result;
|
|
862
|
+
}
|
|
863
|
+
/**
|
|
864
|
+
* Builds the final unified retrieval result.
|
|
865
|
+
*
|
|
866
|
+
* @param chunks - The final merged, reranked chunks.
|
|
867
|
+
* @param plan - The retrieval plan that was executed.
|
|
868
|
+
* @param diagnostics - Per-source diagnostics.
|
|
869
|
+
* @param startTime - Pipeline start timestamp.
|
|
870
|
+
* @param memoryCacheHit - Whether a memory cache hit was used.
|
|
871
|
+
* @param researchSynthesis - Optional deep research synthesis.
|
|
872
|
+
* @returns Complete unified retrieval result.
|
|
873
|
+
*/
|
|
874
|
+
buildResult(chunks, plan, diagnostics, startTime, memoryCacheHit, researchSynthesis) {
|
|
875
|
+
const result = {
|
|
876
|
+
chunks,
|
|
877
|
+
plan,
|
|
878
|
+
sourceDiagnostics: diagnostics,
|
|
879
|
+
durationMs: Date.now() - startTime,
|
|
880
|
+
memoryCacheHit,
|
|
881
|
+
...(researchSynthesis ? { researchSynthesis } : {}),
|
|
882
|
+
};
|
|
883
|
+
this.emitEvent({ type: 'unified:complete', result, timestamp: Date.now() });
|
|
884
|
+
return result;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
//# sourceMappingURL=UnifiedRetriever.js.map
|