@juspay/neurolink 9.5.2 → 9.6.0
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/CHANGELOG.md +16 -0
- package/README.md +29 -25
- package/dist/agent/directTools.d.ts +5 -5
- package/dist/cli/commands/config.d.ts +9 -9
- package/dist/cli/commands/serve.d.ts +37 -0
- package/dist/cli/commands/serve.js +302 -229
- package/dist/cli/commands/setup-anthropic.d.ts +2 -2
- package/dist/cli/commands/setup-azure.d.ts +2 -2
- package/dist/cli/commands/setup-bedrock.d.ts +2 -2
- package/dist/cli/commands/setup-gcp.d.ts +2 -2
- package/dist/cli/commands/setup-google-ai.d.ts +2 -2
- package/dist/cli/commands/setup-huggingface.d.ts +2 -2
- package/dist/cli/commands/setup-mistral.d.ts +2 -2
- package/dist/cli/commands/setup-openai.d.ts +2 -2
- package/dist/cli/commands/setup.d.ts +2 -2
- package/dist/cli/factories/commandFactory.js +16 -2
- package/dist/cli/loop/optionsSchema.d.ts +2 -2
- package/dist/cli/loop/session.d.ts +4 -0
- package/dist/cli/loop/session.js +49 -4
- package/dist/cli/utils/interactiveSetup.d.ts +4 -4
- package/dist/config/conversationMemory.d.ts +2 -0
- package/dist/config/conversationMemory.js +5 -5
- package/dist/constants/contextWindows.d.ts +46 -0
- package/dist/constants/contextWindows.js +156 -0
- package/dist/context/budgetChecker.d.ts +18 -0
- package/dist/context/budgetChecker.js +71 -0
- package/dist/context/contextCompactor.d.ts +22 -0
- package/dist/context/contextCompactor.js +106 -0
- package/dist/context/effectiveHistory.d.ts +52 -0
- package/dist/context/effectiveHistory.js +105 -0
- package/dist/context/errorDetection.d.ts +14 -0
- package/dist/context/errorDetection.js +124 -0
- package/dist/context/fileSummarizationService.d.ts +54 -0
- package/dist/context/fileSummarizationService.js +255 -0
- package/dist/context/fileSummarizer.d.ts +56 -0
- package/dist/context/fileSummarizer.js +145 -0
- package/dist/context/fileTokenBudget.d.ts +53 -0
- package/dist/context/fileTokenBudget.js +127 -0
- package/dist/context/prompts/summarizationPrompt.d.ts +17 -0
- package/dist/context/prompts/summarizationPrompt.js +110 -0
- package/dist/context/stages/fileReadDeduplicator.d.ts +10 -0
- package/dist/context/stages/fileReadDeduplicator.js +66 -0
- package/dist/context/stages/slidingWindowTruncator.d.ts +11 -0
- package/dist/context/stages/slidingWindowTruncator.js +42 -0
- package/dist/context/stages/structuredSummarizer.d.ts +10 -0
- package/dist/context/stages/structuredSummarizer.js +49 -0
- package/dist/context/stages/toolOutputPruner.d.ts +10 -0
- package/dist/context/stages/toolOutputPruner.js +52 -0
- package/dist/context/summarizationEngine.d.ts +45 -0
- package/dist/context/summarizationEngine.js +110 -0
- package/dist/context/toolOutputLimits.d.ts +17 -0
- package/dist/context/toolOutputLimits.js +84 -0
- package/dist/context/toolPairRepair.d.ts +16 -0
- package/dist/context/toolPairRepair.js +66 -0
- package/dist/core/conversationMemoryManager.d.ts +5 -15
- package/dist/core/conversationMemoryManager.js +15 -75
- package/dist/core/modules/MessageBuilder.d.ts +1 -1
- package/dist/core/modules/MessageBuilder.js +2 -0
- package/dist/core/modules/TelemetryHandler.d.ts +2 -3
- package/dist/core/modules/TelemetryHandler.js +3 -3
- package/dist/core/modules/ToolsManager.d.ts +2 -2
- package/dist/core/redisConversationMemoryManager.d.ts +8 -14
- package/dist/core/redisConversationMemoryManager.js +69 -78
- package/dist/factories/providerFactory.d.ts +2 -2
- package/dist/files/fileReferenceRegistry.d.ts +276 -0
- package/dist/files/fileReferenceRegistry.js +1543 -0
- package/dist/files/fileTools.d.ts +423 -0
- package/dist/files/fileTools.js +449 -0
- package/dist/files/index.d.ts +14 -0
- package/dist/files/index.js +13 -0
- package/dist/files/streamingReader.d.ts +93 -0
- package/dist/files/streamingReader.js +321 -0
- package/dist/files/types.d.ts +23 -0
- package/dist/files/types.js +23 -0
- package/dist/image-gen/imageGenTools.d.ts +2 -2
- package/dist/image-gen/types.d.ts +12 -12
- package/dist/lib/agent/directTools.d.ts +7 -7
- package/dist/lib/config/conversationMemory.d.ts +2 -0
- package/dist/lib/config/conversationMemory.js +5 -5
- package/dist/lib/constants/contextWindows.d.ts +46 -0
- package/dist/lib/constants/contextWindows.js +157 -0
- package/dist/lib/context/budgetChecker.d.ts +18 -0
- package/dist/lib/context/budgetChecker.js +72 -0
- package/dist/lib/context/contextCompactor.d.ts +22 -0
- package/dist/lib/context/contextCompactor.js +107 -0
- package/dist/lib/context/effectiveHistory.d.ts +52 -0
- package/dist/lib/context/effectiveHistory.js +106 -0
- package/dist/lib/context/errorDetection.d.ts +14 -0
- package/dist/lib/context/errorDetection.js +125 -0
- package/dist/lib/context/fileSummarizationService.d.ts +54 -0
- package/dist/lib/context/fileSummarizationService.js +256 -0
- package/dist/lib/context/fileSummarizer.d.ts +56 -0
- package/dist/lib/context/fileSummarizer.js +146 -0
- package/dist/lib/context/fileTokenBudget.d.ts +53 -0
- package/dist/lib/context/fileTokenBudget.js +128 -0
- package/dist/lib/context/prompts/summarizationPrompt.d.ts +17 -0
- package/dist/lib/context/prompts/summarizationPrompt.js +111 -0
- package/dist/lib/context/stages/fileReadDeduplicator.d.ts +10 -0
- package/dist/lib/context/stages/fileReadDeduplicator.js +67 -0
- package/dist/lib/context/stages/slidingWindowTruncator.d.ts +11 -0
- package/dist/lib/context/stages/slidingWindowTruncator.js +43 -0
- package/dist/lib/context/stages/structuredSummarizer.d.ts +10 -0
- package/dist/lib/context/stages/structuredSummarizer.js +50 -0
- package/dist/lib/context/stages/toolOutputPruner.d.ts +10 -0
- package/dist/lib/context/stages/toolOutputPruner.js +53 -0
- package/dist/lib/context/summarizationEngine.d.ts +45 -0
- package/dist/lib/context/summarizationEngine.js +111 -0
- package/dist/lib/context/toolOutputLimits.d.ts +17 -0
- package/dist/lib/context/toolOutputLimits.js +85 -0
- package/dist/lib/context/toolPairRepair.d.ts +16 -0
- package/dist/lib/context/toolPairRepair.js +67 -0
- package/dist/lib/core/conversationMemoryManager.d.ts +5 -15
- package/dist/lib/core/conversationMemoryManager.js +15 -75
- package/dist/lib/core/modules/MessageBuilder.d.ts +1 -1
- package/dist/lib/core/modules/MessageBuilder.js +2 -0
- package/dist/lib/core/modules/TelemetryHandler.d.ts +2 -3
- package/dist/lib/core/modules/TelemetryHandler.js +3 -3
- package/dist/lib/core/modules/ToolsManager.d.ts +2 -2
- package/dist/lib/core/redisConversationMemoryManager.d.ts +8 -14
- package/dist/lib/core/redisConversationMemoryManager.js +69 -78
- package/dist/lib/factories/providerFactory.d.ts +2 -2
- package/dist/lib/files/fileReferenceRegistry.d.ts +276 -0
- package/dist/lib/files/fileReferenceRegistry.js +1544 -0
- package/dist/lib/files/fileTools.d.ts +423 -0
- package/dist/lib/files/fileTools.js +450 -0
- package/dist/lib/files/index.d.ts +14 -0
- package/dist/lib/files/index.js +14 -0
- package/dist/lib/files/streamingReader.d.ts +93 -0
- package/dist/lib/files/streamingReader.js +322 -0
- package/dist/lib/files/types.d.ts +23 -0
- package/dist/lib/files/types.js +24 -0
- package/dist/lib/image-gen/imageGenTools.d.ts +2 -2
- package/dist/lib/image-gen/types.d.ts +12 -12
- package/dist/lib/memory/mem0Initializer.d.ts +2 -2
- package/dist/lib/neurolink.d.ts +61 -2
- package/dist/lib/neurolink.js +619 -307
- package/dist/lib/processors/archive/ArchiveProcessor.d.ts +327 -0
- package/dist/lib/processors/archive/ArchiveProcessor.js +1309 -0
- package/dist/lib/processors/archive/index.d.ts +33 -0
- package/dist/lib/processors/archive/index.js +43 -0
- package/dist/lib/processors/base/types.d.ts +70 -64
- package/dist/lib/processors/base/types.js +6 -0
- package/dist/lib/processors/cli/fileProcessorCli.d.ts +8 -8
- package/dist/lib/processors/cli/fileProcessorCli.js +5 -5
- package/dist/lib/processors/config/mimeTypes.js +25 -0
- package/dist/lib/processors/config/sizeLimits.d.ts +52 -40
- package/dist/lib/processors/config/sizeLimits.js +56 -44
- package/dist/lib/processors/document/ExcelProcessor.d.ts +14 -0
- package/dist/lib/processors/document/ExcelProcessor.js +72 -1
- package/dist/lib/processors/document/PptxProcessor.d.ts +63 -0
- package/dist/lib/processors/document/PptxProcessor.js +158 -0
- package/dist/lib/processors/document/index.d.ts +1 -0
- package/dist/lib/processors/document/index.js +6 -0
- package/dist/lib/processors/errors/FileErrorCode.d.ts +2 -2
- package/dist/lib/processors/errors/errorHelpers.d.ts +2 -2
- package/dist/lib/processors/errors/errorSerializer.d.ts +4 -4
- package/dist/lib/processors/index.d.ts +8 -2
- package/dist/lib/processors/index.js +5 -2
- package/dist/lib/processors/integration/FileProcessorIntegration.d.ts +8 -8
- package/dist/lib/processors/integration/FileProcessorIntegration.js +7 -7
- package/dist/lib/processors/media/AudioProcessor.d.ts +328 -0
- package/dist/lib/processors/media/AudioProcessor.js +708 -0
- package/dist/lib/processors/media/VideoProcessor.d.ts +350 -0
- package/dist/lib/processors/media/VideoProcessor.js +992 -0
- package/dist/lib/processors/media/index.d.ts +27 -0
- package/dist/lib/processors/media/index.js +37 -0
- package/dist/lib/processors/registry/ProcessorRegistry.d.ts +19 -5
- package/dist/lib/processors/registry/ProcessorRegistry.js +103 -8
- package/dist/lib/processors/registry/index.d.ts +1 -1
- package/dist/lib/processors/registry/index.js +1 -1
- package/dist/lib/processors/registry/types.d.ts +2 -2
- package/dist/lib/providers/googleAiStudio.d.ts +34 -0
- package/dist/lib/providers/googleAiStudio.js +267 -397
- package/dist/lib/providers/googleVertex.d.ts +55 -1
- package/dist/lib/providers/googleVertex.js +452 -719
- package/dist/lib/providers/sagemaker/detection.d.ts +6 -6
- package/dist/lib/providers/sagemaker/diagnostics.d.ts +4 -4
- package/dist/lib/providers/sagemaker/parsers.d.ts +4 -4
- package/dist/lib/rag/chunkers/RecursiveChunker.js +2 -2
- package/dist/lib/rag/document/loaders.d.ts +6 -71
- package/dist/lib/rag/document/loaders.js +5 -5
- package/dist/lib/rag/graphRag/graphRAG.js +26 -9
- package/dist/lib/rag/metadata/MetadataExtractorFactory.d.ts +5 -55
- package/dist/lib/rag/metadata/metadataExtractor.js +6 -3
- package/dist/lib/rag/pipeline/RAGPipeline.d.ts +8 -126
- package/dist/lib/rag/pipeline/RAGPipeline.js +11 -11
- package/dist/lib/rag/pipeline/contextAssembly.d.ts +3 -42
- package/dist/lib/rag/pipeline/contextAssembly.js +6 -3
- package/dist/lib/rag/reranker/RerankerFactory.d.ts +5 -60
- package/dist/lib/rag/resilience/CircuitBreaker.d.ts +3 -33
- package/dist/lib/rag/resilience/RetryHandler.d.ts +2 -21
- package/dist/lib/rag/retrieval/hybridSearch.d.ts +3 -41
- package/dist/lib/rag/retrieval/vectorQueryTool.d.ts +2 -13
- package/dist/lib/rag/retrieval/vectorQueryTool.js +4 -3
- package/dist/lib/rag/types.d.ts +3 -3
- package/dist/lib/sdk/toolRegistration.d.ts +2 -2
- package/dist/lib/server/middleware/cache.d.ts +2 -2
- package/dist/lib/server/middleware/rateLimit.d.ts +2 -2
- package/dist/lib/server/routes/mcpRoutes.js +277 -249
- package/dist/lib/server/routes/memoryRoutes.js +287 -281
- package/dist/lib/server/utils/validation.d.ts +10 -10
- package/dist/lib/session/globalSessionState.d.ts +2 -2
- package/dist/lib/telemetry/telemetryService.d.ts +2 -2
- package/dist/lib/types/common.d.ts +39 -0
- package/dist/lib/types/contextTypes.d.ts +255 -0
- package/dist/lib/types/contextTypes.js +0 -2
- package/dist/lib/types/conversation.d.ts +62 -0
- package/dist/lib/types/conversationMemoryInterface.d.ts +27 -0
- package/dist/lib/types/conversationMemoryInterface.js +7 -0
- package/dist/lib/types/fileReferenceTypes.d.ts +222 -0
- package/dist/lib/types/fileReferenceTypes.js +9 -0
- package/dist/lib/types/fileTypes.d.ts +26 -3
- package/dist/lib/types/generateTypes.d.ts +22 -1
- package/dist/lib/types/index.d.ts +4 -5
- package/dist/lib/types/index.js +8 -10
- package/dist/lib/types/modelTypes.d.ts +2 -2
- package/dist/lib/types/processorTypes.d.ts +597 -0
- package/dist/lib/types/processorTypes.js +91 -0
- package/dist/lib/types/ragTypes.d.ts +481 -0
- package/dist/lib/types/ragTypes.js +8 -0
- package/dist/lib/types/sdkTypes.d.ts +17 -18
- package/dist/lib/types/streamTypes.d.ts +11 -1
- package/dist/lib/utils/async/retry.d.ts +2 -2
- package/dist/lib/utils/async/withTimeout.js +3 -1
- package/dist/lib/utils/conversationMemory.d.ts +12 -6
- package/dist/lib/utils/conversationMemory.js +76 -36
- package/dist/lib/utils/fileDetector.d.ts +62 -0
- package/dist/lib/utils/fileDetector.js +1014 -14
- package/dist/lib/utils/json/safeParse.d.ts +2 -2
- package/dist/lib/utils/messageBuilder.js +806 -153
- package/dist/lib/utils/modelChoices.d.ts +2 -2
- package/dist/lib/utils/multimodalOptionsBuilder.d.ts +2 -1
- package/dist/lib/utils/multimodalOptionsBuilder.js +1 -0
- package/dist/lib/utils/rateLimiter.d.ts +2 -2
- package/dist/lib/utils/sanitizers/filename.d.ts +4 -4
- package/dist/lib/utils/sanitizers/svg.d.ts +2 -2
- package/dist/lib/utils/thinkingConfig.d.ts +6 -6
- package/dist/lib/utils/tokenEstimation.d.ts +68 -0
- package/dist/lib/utils/tokenEstimation.js +113 -0
- package/dist/lib/utils/tokenUtils.d.ts +4 -4
- package/dist/lib/utils/ttsProcessor.d.ts +2 -2
- package/dist/lib/workflow/config.d.ts +150 -150
- package/dist/memory/mem0Initializer.d.ts +2 -2
- package/dist/neurolink.d.ts +61 -2
- package/dist/neurolink.js +619 -307
- package/dist/processors/archive/ArchiveProcessor.d.ts +327 -0
- package/dist/processors/archive/ArchiveProcessor.js +1308 -0
- package/dist/processors/archive/index.d.ts +33 -0
- package/dist/processors/archive/index.js +42 -0
- package/dist/processors/base/types.d.ts +70 -64
- package/dist/processors/base/types.js +6 -0
- package/dist/processors/cli/fileProcessorCli.d.ts +8 -8
- package/dist/processors/cli/fileProcessorCli.js +5 -5
- package/dist/processors/config/mimeTypes.js +25 -0
- package/dist/processors/config/sizeLimits.d.ts +52 -40
- package/dist/processors/config/sizeLimits.js +56 -44
- package/dist/processors/document/ExcelProcessor.d.ts +14 -0
- package/dist/processors/document/ExcelProcessor.js +72 -1
- package/dist/processors/document/PptxProcessor.d.ts +63 -0
- package/dist/processors/document/PptxProcessor.js +157 -0
- package/dist/processors/document/index.d.ts +1 -0
- package/dist/processors/document/index.js +6 -0
- package/dist/processors/errors/FileErrorCode.d.ts +2 -2
- package/dist/processors/errors/errorHelpers.d.ts +2 -2
- package/dist/processors/errors/errorSerializer.d.ts +4 -4
- package/dist/processors/index.d.ts +8 -2
- package/dist/processors/index.js +5 -2
- package/dist/processors/integration/FileProcessorIntegration.d.ts +8 -8
- package/dist/processors/integration/FileProcessorIntegration.js +7 -7
- package/dist/processors/media/AudioProcessor.d.ts +328 -0
- package/dist/processors/media/AudioProcessor.js +707 -0
- package/dist/processors/media/VideoProcessor.d.ts +350 -0
- package/dist/processors/media/VideoProcessor.js +991 -0
- package/dist/processors/media/ffprobe-static.d.ts +4 -0
- package/dist/processors/media/index.d.ts +27 -0
- package/dist/processors/media/index.js +36 -0
- package/dist/processors/registry/ProcessorRegistry.d.ts +19 -5
- package/dist/processors/registry/ProcessorRegistry.js +103 -8
- package/dist/processors/registry/index.d.ts +1 -1
- package/dist/processors/registry/index.js +1 -1
- package/dist/processors/registry/types.d.ts +2 -2
- package/dist/providers/googleAiStudio.d.ts +34 -0
- package/dist/providers/googleAiStudio.js +267 -397
- package/dist/providers/googleVertex.d.ts +55 -1
- package/dist/providers/googleVertex.js +452 -719
- package/dist/providers/sagemaker/detection.d.ts +6 -6
- package/dist/providers/sagemaker/diagnostics.d.ts +4 -4
- package/dist/providers/sagemaker/parsers.d.ts +4 -4
- package/dist/rag/chunkers/RecursiveChunker.js +2 -2
- package/dist/rag/document/loaders.d.ts +6 -71
- package/dist/rag/document/loaders.js +5 -5
- package/dist/rag/graphRag/graphRAG.js +26 -9
- package/dist/rag/metadata/MetadataExtractorFactory.d.ts +5 -55
- package/dist/rag/metadata/metadataExtractor.js +6 -3
- package/dist/rag/pipeline/RAGPipeline.d.ts +8 -126
- package/dist/rag/pipeline/RAGPipeline.js +11 -11
- package/dist/rag/pipeline/contextAssembly.d.ts +3 -42
- package/dist/rag/pipeline/contextAssembly.js +6 -3
- package/dist/rag/reranker/RerankerFactory.d.ts +5 -60
- package/dist/rag/resilience/CircuitBreaker.d.ts +3 -33
- package/dist/rag/resilience/RetryHandler.d.ts +2 -21
- package/dist/rag/retrieval/hybridSearch.d.ts +3 -41
- package/dist/rag/retrieval/vectorQueryTool.d.ts +2 -13
- package/dist/rag/retrieval/vectorQueryTool.js +4 -3
- package/dist/rag/types.d.ts +3 -3
- package/dist/sdk/toolRegistration.d.ts +2 -2
- package/dist/server/middleware/cache.d.ts +2 -2
- package/dist/server/middleware/rateLimit.d.ts +2 -2
- package/dist/server/routes/mcpRoutes.js +277 -249
- package/dist/server/routes/memoryRoutes.js +287 -281
- package/dist/server/utils/validation.d.ts +4 -4
- package/dist/session/globalSessionState.d.ts +2 -2
- package/dist/telemetry/telemetryService.d.ts +2 -2
- package/dist/types/common.d.ts +39 -0
- package/dist/types/contextTypes.d.ts +255 -0
- package/dist/types/contextTypes.js +0 -2
- package/dist/types/conversation.d.ts +62 -0
- package/dist/types/conversationMemoryInterface.d.ts +27 -0
- package/dist/types/conversationMemoryInterface.js +6 -0
- package/dist/types/fileReferenceTypes.d.ts +222 -0
- package/dist/types/fileReferenceTypes.js +8 -0
- package/dist/types/fileTypes.d.ts +26 -3
- package/dist/types/generateTypes.d.ts +22 -1
- package/dist/types/index.d.ts +4 -5
- package/dist/types/index.js +8 -10
- package/dist/types/processorTypes.d.ts +597 -0
- package/dist/types/processorTypes.js +90 -0
- package/dist/types/ragTypes.d.ts +481 -0
- package/dist/types/ragTypes.js +7 -0
- package/dist/types/sdkTypes.d.ts +17 -18
- package/dist/types/streamTypes.d.ts +11 -1
- package/dist/utils/async/retry.d.ts +2 -2
- package/dist/utils/async/withTimeout.js +3 -1
- package/dist/utils/conversationMemory.d.ts +12 -6
- package/dist/utils/conversationMemory.js +76 -36
- package/dist/utils/fileDetector.d.ts +62 -0
- package/dist/utils/fileDetector.js +1014 -14
- package/dist/utils/json/safeParse.d.ts +2 -2
- package/dist/utils/messageBuilder.js +806 -153
- package/dist/utils/modelChoices.d.ts +2 -2
- package/dist/utils/multimodalOptionsBuilder.d.ts +2 -1
- package/dist/utils/multimodalOptionsBuilder.js +1 -0
- package/dist/utils/rateLimiter.d.ts +2 -2
- package/dist/utils/sanitizers/filename.d.ts +4 -4
- package/dist/utils/sanitizers/svg.d.ts +2 -2
- package/dist/utils/thinkingConfig.d.ts +6 -6
- package/dist/utils/tokenEstimation.d.ts +68 -0
- package/dist/utils/tokenEstimation.js +112 -0
- package/dist/utils/tokenUtils.d.ts +4 -4
- package/dist/utils/ttsProcessor.d.ts +2 -2
- package/dist/workflow/config.d.ts +104 -104
- package/package.json +18 -6
- package/dist/lib/utils/conversationMemoryUtils.d.ts +0 -25
- package/dist/lib/utils/conversationMemoryUtils.js +0 -138
- package/dist/utils/conversationMemoryUtils.d.ts +0 -25
- package/dist/utils/conversationMemoryUtils.js +0 -137
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Use/Result Pair Repair
|
|
3
|
+
*
|
|
4
|
+
* After compaction, validates that every tool_use (tool_call) has a
|
|
5
|
+
* corresponding tool_result and vice versa. Inserts synthetic
|
|
6
|
+
* placeholders for orphaned entries.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
9
|
+
/**
|
|
10
|
+
* Repair orphaned tool_use/tool_result pairs in a message array.
|
|
11
|
+
*
|
|
12
|
+
* Ensures every tool_call has a following tool_result and vice versa.
|
|
13
|
+
*/
|
|
14
|
+
export function repairToolPairs(messages) {
|
|
15
|
+
const result = [];
|
|
16
|
+
let orphanedCallsFixed = 0;
|
|
17
|
+
let orphanedResultsFixed = 0;
|
|
18
|
+
for (let i = 0; i < messages.length; i++) {
|
|
19
|
+
const msg = messages[i];
|
|
20
|
+
const nextMsg = i + 1 < messages.length ? messages[i + 1] : undefined;
|
|
21
|
+
if (msg.role === "tool_call") {
|
|
22
|
+
result.push(msg);
|
|
23
|
+
// Check if next message is the corresponding tool_result
|
|
24
|
+
if (!nextMsg || nextMsg.role !== "tool_result") {
|
|
25
|
+
// Insert synthetic tool_result
|
|
26
|
+
result.push({
|
|
27
|
+
id: `repair-result-${randomUUID()}`,
|
|
28
|
+
role: "tool_result",
|
|
29
|
+
content: "[Tool result unavailable - conversation was compacted]",
|
|
30
|
+
tool: msg.tool,
|
|
31
|
+
timestamp: msg.timestamp,
|
|
32
|
+
metadata: { truncated: true },
|
|
33
|
+
});
|
|
34
|
+
orphanedCallsFixed++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else if (msg.role === "tool_result") {
|
|
38
|
+
// Check if previous message was the corresponding tool_call
|
|
39
|
+
const prevMsg = result.length > 0 ? result[result.length - 1] : undefined;
|
|
40
|
+
if (!prevMsg ||
|
|
41
|
+
(prevMsg.role !== "tool_call" && prevMsg.role !== "tool_result")) {
|
|
42
|
+
// Insert synthetic tool_call before this result
|
|
43
|
+
result.push({
|
|
44
|
+
id: `repair-call-${randomUUID()}`,
|
|
45
|
+
role: "tool_call",
|
|
46
|
+
content: `[Tool call for ${msg.tool || "unknown"} - conversation was compacted]`,
|
|
47
|
+
tool: msg.tool,
|
|
48
|
+
timestamp: msg.timestamp,
|
|
49
|
+
metadata: { truncated: true },
|
|
50
|
+
});
|
|
51
|
+
orphanedResultsFixed++;
|
|
52
|
+
}
|
|
53
|
+
result.push(msg);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
result.push(msg);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const repaired = orphanedCallsFixed > 0 || orphanedResultsFixed > 0;
|
|
60
|
+
return {
|
|
61
|
+
repaired,
|
|
62
|
+
messages: repaired ? result : messages,
|
|
63
|
+
orphanedCallsFixed,
|
|
64
|
+
orphanedResultsFixed,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* Conversation Memory Manager for NeuroLink
|
|
3
3
|
* Handles in-memory conversation storage, session management, and context injection
|
|
4
4
|
*/
|
|
5
|
-
import type {
|
|
6
|
-
|
|
5
|
+
import type { ChatMessage, ConversationMemoryConfig, ConversationMemoryStats, SessionMemory, StoreConversationTurnOptions } from "../types/conversation.js";
|
|
6
|
+
import type { IConversationMemoryManager } from "../types/conversationMemoryInterface.js";
|
|
7
|
+
export declare class ConversationMemoryManager implements IConversationMemoryManager {
|
|
7
8
|
private sessions;
|
|
8
9
|
config: ConversationMemoryConfig;
|
|
9
10
|
private isInitialized;
|
|
11
|
+
private summarizationEngine;
|
|
10
12
|
/**
|
|
11
13
|
* Track sessions currently being summarized to prevent race conditions
|
|
12
14
|
*/
|
|
@@ -30,26 +32,14 @@ export declare class ConversationMemoryManager {
|
|
|
30
32
|
* Check if summarization is needed based on token count
|
|
31
33
|
*/
|
|
32
34
|
private checkAndSummarize;
|
|
33
|
-
/**
|
|
34
|
-
* Estimate total tokens for a list of messages
|
|
35
|
-
*/
|
|
36
|
-
private estimateTokens;
|
|
37
35
|
/**
|
|
38
36
|
* Build context messages for AI prompt injection (TOKEN-BASED)
|
|
39
37
|
* Returns messages from pointer onwards (or all if no pointer)
|
|
40
38
|
* Now consistently async to match Redis implementation
|
|
41
39
|
*/
|
|
42
40
|
buildContextMessages(sessionId: string): Promise<ChatMessage[]>;
|
|
43
|
-
getSession(sessionId: string): SessionMemory | undefined;
|
|
41
|
+
getSession(sessionId: string, _userId?: string): SessionMemory | undefined;
|
|
44
42
|
createSummarySystemMessage(content: string, summarizesFrom?: string, summarizesTo?: string): ChatMessage;
|
|
45
|
-
/**
|
|
46
|
-
* Token-based summarization (pointer-based, non-destructive)
|
|
47
|
-
*/
|
|
48
|
-
private summarizeSessionTokenBased;
|
|
49
|
-
/**
|
|
50
|
-
* Find split index to keep recent messages within target token count
|
|
51
|
-
*/
|
|
52
|
-
private findSplitIndexByTokens;
|
|
53
43
|
private ensureInitialized;
|
|
54
44
|
private createNewSession;
|
|
55
45
|
private enforceSessionLimit;
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
* Conversation Memory Manager for NeuroLink
|
|
3
3
|
* Handles in-memory conversation storage, session management, and context injection
|
|
4
4
|
*/
|
|
5
|
-
import { ConversationMemoryError } from "../types/conversation.js";
|
|
6
|
-
import { DEFAULT_MAX_SESSIONS, MEMORY_THRESHOLD_PERCENTAGE, RECENT_MESSAGES_RATIO, MESSAGES_PER_TURN, } from "../config/conversationMemory.js";
|
|
7
|
-
import { logger } from "../utils/logger.js";
|
|
8
5
|
import { randomUUID } from "crypto";
|
|
6
|
+
import { DEFAULT_MAX_SESSIONS, MEMORY_THRESHOLD_PERCENTAGE, MESSAGES_PER_TURN, } from "../config/conversationMemory.js";
|
|
9
7
|
import { TokenUtils } from "../constants/tokens.js";
|
|
10
|
-
import {
|
|
8
|
+
import { SummarizationEngine } from "../context/summarizationEngine.js";
|
|
9
|
+
import { ConversationMemoryError } from "../types/conversation.js";
|
|
10
|
+
import { buildContextFromPointer, getEffectiveTokenThreshold, } from "../utils/conversationMemory.js";
|
|
11
|
+
import { logger } from "../utils/logger.js";
|
|
11
12
|
export class ConversationMemoryManager {
|
|
12
13
|
sessions = new Map();
|
|
13
14
|
config;
|
|
14
15
|
isInitialized = false;
|
|
16
|
+
summarizationEngine = new SummarizationEngine();
|
|
15
17
|
/**
|
|
16
18
|
* Track sessions currently being summarized to prevent race conditions
|
|
17
19
|
*/
|
|
@@ -35,7 +37,9 @@ export class ConversationMemoryManager {
|
|
|
35
37
|
});
|
|
36
38
|
}
|
|
37
39
|
catch (error) {
|
|
38
|
-
throw new ConversationMemoryError("Failed to initialize conversation memory", "CONFIG_ERROR", {
|
|
40
|
+
throw new ConversationMemoryError("Failed to initialize conversation memory", "CONFIG_ERROR", {
|
|
41
|
+
error: error instanceof Error ? error.message : String(error),
|
|
42
|
+
});
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
/**
|
|
@@ -61,6 +65,10 @@ export class ConversationMemoryManager {
|
|
|
61
65
|
}
|
|
62
66
|
session.messages.push(userMsg, assistantMsg);
|
|
63
67
|
session.lastActivity = Date.now();
|
|
68
|
+
// Store API-reported token counts if available
|
|
69
|
+
if (options.tokenUsage) {
|
|
70
|
+
session.lastApiTokenCount = options.tokenUsage;
|
|
71
|
+
}
|
|
64
72
|
const shouldSummarize = options.enableSummarization !== undefined
|
|
65
73
|
? options.enableSummarization
|
|
66
74
|
: this.config.enableSummarization;
|
|
@@ -141,19 +149,7 @@ export class ConversationMemoryManager {
|
|
|
141
149
|
}
|
|
142
150
|
this.summarizationInProgress.add(session.sessionId);
|
|
143
151
|
try {
|
|
144
|
-
|
|
145
|
-
const tokenCount = this.estimateTokens(contextMessages);
|
|
146
|
-
session.lastTokenCount = tokenCount;
|
|
147
|
-
session.lastCountedAt = Date.now();
|
|
148
|
-
logger.debug("Token count check", {
|
|
149
|
-
sessionId: session.sessionId,
|
|
150
|
-
tokenCount,
|
|
151
|
-
threshold,
|
|
152
|
-
needsSummarization: tokenCount >= threshold,
|
|
153
|
-
});
|
|
154
|
-
if (tokenCount >= threshold) {
|
|
155
|
-
await this.summarizeSessionTokenBased(session, threshold);
|
|
156
|
-
}
|
|
152
|
+
await this.summarizationEngine.checkAndSummarize(session, threshold, this.config, "[ConversationMemory]");
|
|
157
153
|
}
|
|
158
154
|
catch (error) {
|
|
159
155
|
logger.error("Token counting or summarization failed", {
|
|
@@ -166,14 +162,6 @@ export class ConversationMemoryManager {
|
|
|
166
162
|
this.summarizationInProgress.delete(session.sessionId);
|
|
167
163
|
}
|
|
168
164
|
}
|
|
169
|
-
/**
|
|
170
|
-
* Estimate total tokens for a list of messages
|
|
171
|
-
*/
|
|
172
|
-
estimateTokens(messages) {
|
|
173
|
-
return messages.reduce((total, msg) => {
|
|
174
|
-
return total + TokenUtils.estimateTokenCount(msg.content);
|
|
175
|
-
}, 0);
|
|
176
|
-
}
|
|
177
165
|
/**
|
|
178
166
|
* Build context messages for AI prompt injection (TOKEN-BASED)
|
|
179
167
|
* Returns messages from pointer onwards (or all if no pointer)
|
|
@@ -183,7 +171,7 @@ export class ConversationMemoryManager {
|
|
|
183
171
|
const session = this.sessions.get(sessionId);
|
|
184
172
|
return session ? buildContextFromPointer(session) : [];
|
|
185
173
|
}
|
|
186
|
-
getSession(sessionId) {
|
|
174
|
+
getSession(sessionId, _userId) {
|
|
187
175
|
return this.sessions.get(sessionId);
|
|
188
176
|
}
|
|
189
177
|
createSummarySystemMessage(content, summarizesFrom, summarizesTo) {
|
|
@@ -199,54 +187,6 @@ export class ConversationMemoryManager {
|
|
|
199
187
|
},
|
|
200
188
|
};
|
|
201
189
|
}
|
|
202
|
-
/**
|
|
203
|
-
* Token-based summarization (pointer-based, non-destructive)
|
|
204
|
-
*/
|
|
205
|
-
async summarizeSessionTokenBased(session, threshold) {
|
|
206
|
-
const startIndex = session.summarizedUpToMessageId
|
|
207
|
-
? session.messages.findIndex((m) => m.id === session.summarizedUpToMessageId) + 1
|
|
208
|
-
: 0;
|
|
209
|
-
const recentMessages = session.messages.slice(startIndex);
|
|
210
|
-
if (recentMessages.length === 0) {
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
const targetRecentTokens = threshold * RECENT_MESSAGES_RATIO;
|
|
214
|
-
const splitIndex = await this.findSplitIndexByTokens(recentMessages, targetRecentTokens);
|
|
215
|
-
const messagesToSummarize = recentMessages.slice(0, splitIndex);
|
|
216
|
-
if (messagesToSummarize.length === 0) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const summary = await generateSummary(messagesToSummarize, this.config, "[ConversationMemory]", session.summarizedMessage);
|
|
220
|
-
if (!summary) {
|
|
221
|
-
logger.warn(`[ConversationMemory] Summary generation failed for session ${session.sessionId}`);
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
const lastSummarized = messagesToSummarize[messagesToSummarize.length - 1];
|
|
225
|
-
session.summarizedUpToMessageId = lastSummarized.id;
|
|
226
|
-
session.summarizedMessage = summary; // Store summary separately
|
|
227
|
-
logger.info(`[ConversationMemory] Summarization complete for session ${session.sessionId}`, {
|
|
228
|
-
summarizedCount: messagesToSummarize.length,
|
|
229
|
-
totalMessages: session.messages.length,
|
|
230
|
-
pointer: session.summarizedUpToMessageId,
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Find split index to keep recent messages within target token count
|
|
235
|
-
*/
|
|
236
|
-
async findSplitIndexByTokens(messages, targetRecentTokens) {
|
|
237
|
-
let recentTokens = 0;
|
|
238
|
-
let splitIndex = messages.length;
|
|
239
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
240
|
-
const msgTokens = TokenUtils.estimateTokenCount(messages[i].content);
|
|
241
|
-
if (recentTokens + msgTokens > targetRecentTokens) {
|
|
242
|
-
splitIndex = i + 1;
|
|
243
|
-
break;
|
|
244
|
-
}
|
|
245
|
-
recentTokens += msgTokens;
|
|
246
|
-
}
|
|
247
|
-
// To ensure at least one message is summarized
|
|
248
|
-
return Math.max(1, splitIndex);
|
|
249
|
-
}
|
|
250
190
|
async ensureInitialized() {
|
|
251
191
|
if (!this.isInitialized) {
|
|
252
192
|
await this.initialize();
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* @module core/modules/MessageBuilder
|
|
14
14
|
*/
|
|
15
15
|
import type { CoreMessage } from "ai";
|
|
16
|
-
import type {
|
|
16
|
+
import type { AIProviderName, TextGenerationOptions } from "../../types/index.js";
|
|
17
17
|
import type { StreamOptions } from "../../types/streamTypes.js";
|
|
18
18
|
/**
|
|
19
19
|
* MessageBuilder class - Handles message construction for AI providers
|
|
@@ -65,6 +65,7 @@ export class MessageBuilder {
|
|
|
65
65
|
conversationHistory: options.conversationMessages,
|
|
66
66
|
schema: options.schema,
|
|
67
67
|
output: options.output,
|
|
68
|
+
fileRegistry: options.fileRegistry,
|
|
68
69
|
};
|
|
69
70
|
messages = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
|
|
70
71
|
}
|
|
@@ -147,6 +148,7 @@ export class MessageBuilder {
|
|
|
147
148
|
.conversationMessages,
|
|
148
149
|
schema: options.schema,
|
|
149
150
|
output: options.output,
|
|
151
|
+
fileRegistry: options.fileRegistry,
|
|
150
152
|
};
|
|
151
153
|
messages = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
|
|
152
154
|
}
|
|
@@ -13,10 +13,9 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @module core/modules/TelemetryHandler
|
|
15
15
|
*/
|
|
16
|
-
import type { AIProviderName, EnhancedGenerateResult, TextGenerationOptions, AnalyticsData } from "../../types/index.js";
|
|
17
|
-
import type { EvaluationData } from "../../types/index.js";
|
|
18
|
-
import type { StreamOptions } from "../../types/streamTypes.js";
|
|
19
16
|
import type { NeuroLink } from "../../neurolink.js";
|
|
17
|
+
import type { AIProviderName, AnalyticsData, EnhancedGenerateResult, EvaluationData, TextGenerationOptions } from "../../types/index.js";
|
|
18
|
+
import type { StreamOptions } from "../../types/streamTypes.js";
|
|
20
19
|
/**
|
|
21
20
|
* TelemetryHandler class - Handles analytics and telemetry for AI providers
|
|
22
21
|
*/
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
*
|
|
14
14
|
* @module core/modules/TelemetryHandler
|
|
15
15
|
*/
|
|
16
|
-
import { logger } from "../../utils/logger.js";
|
|
17
16
|
import { nanoid } from "nanoid";
|
|
17
|
+
import { logger } from "../../utils/logger.js";
|
|
18
|
+
import { getPerformanceOptimizedProvider, recordProviderPerformanceFromMetrics, } from "../evaluationProviders.js";
|
|
18
19
|
import { modelConfig } from "../modelConfiguration.js";
|
|
19
|
-
import { recordProviderPerformanceFromMetrics, getPerformanceOptimizedProvider, } from "../evaluationProviders.js";
|
|
20
20
|
/**
|
|
21
21
|
* TelemetryHandler class - Handles analytics and telemetry for AI providers
|
|
22
22
|
*/
|
|
@@ -147,7 +147,7 @@ export class TelemetryHandler {
|
|
|
147
147
|
isEnabled: true,
|
|
148
148
|
functionId,
|
|
149
149
|
metadata,
|
|
150
|
-
recordInputs:
|
|
150
|
+
recordInputs: false,
|
|
151
151
|
recordOutputs: true,
|
|
152
152
|
};
|
|
153
153
|
}
|
|
@@ -21,12 +21,12 @@ import type { NeuroLink } from "../../neurolink.js";
|
|
|
21
21
|
/**
|
|
22
22
|
* Utility functions interface for ToolsManager
|
|
23
23
|
*/
|
|
24
|
-
export
|
|
24
|
+
export type ToolUtilities = {
|
|
25
25
|
isZodSchema?: (schema: unknown) => boolean;
|
|
26
26
|
convertToolResult?: (result: unknown) => Promise<unknown>;
|
|
27
27
|
createPermissiveZodSchema?: () => z.ZodSchema;
|
|
28
28
|
fixSchemaForOpenAIStrictMode?: (schema: Record<string, unknown>) => Record<string, unknown>;
|
|
29
|
-
}
|
|
29
|
+
};
|
|
30
30
|
/**
|
|
31
31
|
* ToolsManager class - Handles all tool management operations
|
|
32
32
|
*/
|
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
* Redis Conversation Memory Manager for NeuroLink
|
|
3
3
|
* Redis-based implementation of conversation storage with same interface as ConversationMemoryManager
|
|
4
4
|
*/
|
|
5
|
-
import type { ConversationMemoryConfig, ConversationMemoryStats,
|
|
5
|
+
import type { ChatMessage, ConversationMemoryConfig, ConversationMemoryStats, RedisConversationObject, RedisStorageConfig, SessionMemory, SessionMetadata, StoreConversationTurnOptions } from "../types/conversation.js";
|
|
6
|
+
import type { IConversationMemoryManager } from "../types/conversationMemoryInterface.js";
|
|
6
7
|
/**
|
|
7
8
|
* Redis-based implementation of the ConversationMemoryManager
|
|
8
9
|
* Uses the same interface but stores data in Redis
|
|
9
10
|
*/
|
|
10
|
-
export declare class RedisConversationMemoryManager {
|
|
11
|
+
export declare class RedisConversationMemoryManager implements IConversationMemoryManager {
|
|
11
12
|
config: ConversationMemoryConfig;
|
|
12
13
|
private isInitialized;
|
|
14
|
+
private summarizationEngine;
|
|
13
15
|
private redisConfig;
|
|
14
16
|
private redisClient;
|
|
15
17
|
/**
|
|
@@ -32,6 +34,10 @@ export declare class RedisConversationMemoryManager {
|
|
|
32
34
|
* Initialize the memory manager with Redis connection
|
|
33
35
|
*/
|
|
34
36
|
initialize(): Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Get session by ID, reconstructing a SessionMemory from Redis storage.
|
|
39
|
+
*/
|
|
40
|
+
getSession(sessionId: string, userId?: string): Promise<SessionMemory | undefined>;
|
|
35
41
|
/**
|
|
36
42
|
* Get all sessions for a specific user
|
|
37
43
|
*/
|
|
@@ -70,18 +76,6 @@ export declare class RedisConversationMemoryManager {
|
|
|
70
76
|
* Check if summarization is needed based on token count
|
|
71
77
|
*/
|
|
72
78
|
private checkAndSummarize;
|
|
73
|
-
/**
|
|
74
|
-
* Estimate total tokens for a list of messages
|
|
75
|
-
*/
|
|
76
|
-
private estimateTokens;
|
|
77
|
-
/**
|
|
78
|
-
* Token-based summarization (pointer-based, non-destructive)
|
|
79
|
-
*/
|
|
80
|
-
private summarizeSessionTokenBased;
|
|
81
|
-
/**
|
|
82
|
-
* Find split index to keep recent messages within target token count
|
|
83
|
-
*/
|
|
84
|
-
private findSplitIndexByTokens;
|
|
85
79
|
/**
|
|
86
80
|
* Build context messages for AI prompt injection (TOKEN-BASED)
|
|
87
81
|
* Returns messages from pointer onwards (or all if no pointer)
|
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* Redis-based implementation of conversation storage with same interface as ConversationMemoryManager
|
|
4
4
|
*/
|
|
5
5
|
import { randomUUID } from "crypto";
|
|
6
|
+
import { MESSAGES_PER_TURN } from "../config/conversationMemory.js";
|
|
7
|
+
import { SummarizationEngine } from "../context/summarizationEngine.js";
|
|
8
|
+
import { NeuroLink } from "../neurolink.js";
|
|
6
9
|
import { ConversationMemoryError } from "../types/conversation.js";
|
|
7
|
-
import {
|
|
10
|
+
import { buildContextFromPointer, getEffectiveTokenThreshold, } from "../utils/conversationMemory.js";
|
|
8
11
|
import { logger } from "../utils/logger.js";
|
|
9
|
-
import {
|
|
10
|
-
import { createRedisClient, getSessionKey, getUserSessionsKey, getNormalizedConfig, serializeConversation, deserializeConversation, scanKeys, } from "../utils/redis.js";
|
|
11
|
-
import { TokenUtils } from "../constants/tokens.js";
|
|
12
|
-
import { buildContextFromPointer, getEffectiveTokenThreshold, generateSummary, } from "../utils/conversationMemory.js";
|
|
12
|
+
import { createRedisClient, deserializeConversation, getNormalizedConfig, getSessionKey, getUserSessionsKey, scanKeys, serializeConversation, } from "../utils/redis.js";
|
|
13
13
|
/**
|
|
14
14
|
* Redis-based implementation of the ConversationMemoryManager
|
|
15
15
|
* Uses the same interface but stores data in Redis
|
|
@@ -17,6 +17,7 @@ import { buildContextFromPointer, getEffectiveTokenThreshold, generateSummary, }
|
|
|
17
17
|
export class RedisConversationMemoryManager {
|
|
18
18
|
config;
|
|
19
19
|
isInitialized = false;
|
|
20
|
+
summarizationEngine = new SummarizationEngine();
|
|
20
21
|
redisConfig;
|
|
21
22
|
redisClient = null;
|
|
22
23
|
/**
|
|
@@ -76,7 +77,47 @@ export class RedisConversationMemoryManager {
|
|
|
76
77
|
port: this.redisConfig.port,
|
|
77
78
|
},
|
|
78
79
|
});
|
|
79
|
-
throw new ConversationMemoryError("Failed to initialize Redis conversation memory", "CONFIG_ERROR", {
|
|
80
|
+
throw new ConversationMemoryError("Failed to initialize Redis conversation memory", "CONFIG_ERROR", {
|
|
81
|
+
error: error instanceof Error ? error.message : String(error),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get session by ID, reconstructing a SessionMemory from Redis storage.
|
|
87
|
+
*/
|
|
88
|
+
async getSession(sessionId, userId) {
|
|
89
|
+
await this.ensureInitialized();
|
|
90
|
+
if (!this.redisClient) {
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
|
|
95
|
+
const conversationData = await this.redisClient.get(redisKey);
|
|
96
|
+
const conversation = deserializeConversation(conversationData || null);
|
|
97
|
+
if (!conversation) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
sessionId: conversation.sessionId,
|
|
102
|
+
userId: conversation.userId,
|
|
103
|
+
messages: conversation.messages,
|
|
104
|
+
summarizedUpToMessageId: conversation.summarizedUpToMessageId,
|
|
105
|
+
summarizedMessage: conversation.summarizedMessage,
|
|
106
|
+
tokenThreshold: conversation.tokenThreshold,
|
|
107
|
+
lastTokenCount: conversation.lastTokenCount,
|
|
108
|
+
lastCountedAt: conversation.lastCountedAt,
|
|
109
|
+
lastApiTokenCount: conversation.lastApiTokenCount,
|
|
110
|
+
createdAt: new Date(conversation.createdAt).getTime(),
|
|
111
|
+
lastActivity: new Date(conversation.updatedAt).getTime(),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
logger.error("[RedisConversationMemoryManager] Failed to get session", {
|
|
116
|
+
sessionId,
|
|
117
|
+
userId,
|
|
118
|
+
error: error instanceof Error ? error.message : String(error),
|
|
119
|
+
});
|
|
120
|
+
return undefined;
|
|
80
121
|
}
|
|
81
122
|
}
|
|
82
123
|
/**
|
|
@@ -300,6 +341,10 @@ export class RedisConversationMemoryManager {
|
|
|
300
341
|
events: options.events || undefined,
|
|
301
342
|
};
|
|
302
343
|
conversation.messages.push(assistantMsg);
|
|
344
|
+
// Store API-reported token counts if available
|
|
345
|
+
if (options.tokenUsage) {
|
|
346
|
+
conversation.lastApiTokenCount = options.tokenUsage;
|
|
347
|
+
}
|
|
303
348
|
logger.info("[RedisConversationMemoryManager] Added new messages", {
|
|
304
349
|
sessionId: conversation.sessionId,
|
|
305
350
|
userId: conversation.userId,
|
|
@@ -359,7 +404,6 @@ export class RedisConversationMemoryManager {
|
|
|
359
404
|
async checkAndSummarize(conversation, threshold, sessionId, userId) {
|
|
360
405
|
const normalizedUserId = userId || "randomUser";
|
|
361
406
|
const summarizationKey = `${sessionId}:${normalizedUserId}`;
|
|
362
|
-
// Acquire lock - if already in progress, skip
|
|
363
407
|
if (this.summarizationInProgress.has(summarizationKey)) {
|
|
364
408
|
logger.debug("[RedisConversationMemoryManager] Summarization already in progress, skipping", {
|
|
365
409
|
sessionId,
|
|
@@ -381,12 +425,20 @@ export class RedisConversationMemoryManager {
|
|
|
381
425
|
createdAt: new Date(conversation.createdAt).getTime(),
|
|
382
426
|
lastActivity: new Date(conversation.updatedAt).getTime(),
|
|
383
427
|
};
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
conversation.
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
428
|
+
const summarized = await this.summarizationEngine.checkAndSummarize(session, threshold, this.config, "[RedisConversationMemoryManager]");
|
|
429
|
+
conversation.lastTokenCount = session.lastTokenCount;
|
|
430
|
+
conversation.lastCountedAt = session.lastCountedAt;
|
|
431
|
+
if (summarized) {
|
|
432
|
+
conversation.summarizedUpToMessageId = session.summarizedUpToMessageId;
|
|
433
|
+
conversation.summarizedMessage = session.summarizedMessage;
|
|
434
|
+
if (this.redisClient) {
|
|
435
|
+
const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
|
|
436
|
+
const serializedData = serializeConversation(conversation);
|
|
437
|
+
await this.redisClient.set(redisKey, serializedData);
|
|
438
|
+
if (this.redisConfig.ttl > 0) {
|
|
439
|
+
await this.redisClient.expire(redisKey, this.redisConfig.ttl);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
390
442
|
}
|
|
391
443
|
}
|
|
392
444
|
catch (error) {
|
|
@@ -396,71 +448,9 @@ export class RedisConversationMemoryManager {
|
|
|
396
448
|
});
|
|
397
449
|
}
|
|
398
450
|
finally {
|
|
399
|
-
// Release lock when done
|
|
400
451
|
this.summarizationInProgress.delete(summarizationKey);
|
|
401
452
|
}
|
|
402
453
|
}
|
|
403
|
-
/**
|
|
404
|
-
* Estimate total tokens for a list of messages
|
|
405
|
-
*/
|
|
406
|
-
estimateTokens(messages) {
|
|
407
|
-
return messages.reduce((total, msg) => {
|
|
408
|
-
return total + TokenUtils.estimateTokenCount(msg.content);
|
|
409
|
-
}, 0);
|
|
410
|
-
}
|
|
411
|
-
/**
|
|
412
|
-
* Token-based summarization (pointer-based, non-destructive)
|
|
413
|
-
*/
|
|
414
|
-
async summarizeSessionTokenBased(conversation, threshold, sessionId, userId) {
|
|
415
|
-
const startIndex = conversation.summarizedUpToMessageId
|
|
416
|
-
? conversation.messages.findIndex((m) => m.id === conversation.summarizedUpToMessageId) + 1
|
|
417
|
-
: 0;
|
|
418
|
-
const recentMessages = conversation.messages.slice(startIndex);
|
|
419
|
-
if (recentMessages.length === 0) {
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
// We only want to include user, assistant, and system messages in summarization
|
|
423
|
-
const filteredRecentMessages = recentMessages.filter((msg) => msg.role !== "tool_call" && msg.role !== "tool_result");
|
|
424
|
-
const targetRecentTokens = threshold * RECENT_MESSAGES_RATIO;
|
|
425
|
-
const splitIndex = await this.findSplitIndexByTokens(filteredRecentMessages, targetRecentTokens);
|
|
426
|
-
const messagesToSummarize = filteredRecentMessages.slice(0, splitIndex);
|
|
427
|
-
if (messagesToSummarize.length === 0) {
|
|
428
|
-
return;
|
|
429
|
-
}
|
|
430
|
-
const summary = await generateSummary(messagesToSummarize, this.config, "[RedisConversationMemoryManager]", conversation.summarizedMessage);
|
|
431
|
-
if (!summary) {
|
|
432
|
-
logger.warn(`[RedisConversationMemoryManager] Summary generation failed for session ${conversation.sessionId}`);
|
|
433
|
-
return;
|
|
434
|
-
}
|
|
435
|
-
const lastSummarized = messagesToSummarize[messagesToSummarize.length - 1];
|
|
436
|
-
conversation.summarizedUpToMessageId = lastSummarized.id;
|
|
437
|
-
conversation.summarizedMessage = summary;
|
|
438
|
-
if (this.redisClient) {
|
|
439
|
-
const redisKey = getSessionKey(this.redisConfig, sessionId, userId);
|
|
440
|
-
const serializedData = serializeConversation(conversation);
|
|
441
|
-
await this.redisClient.set(redisKey, serializedData);
|
|
442
|
-
if (this.redisConfig.ttl > 0) {
|
|
443
|
-
await this.redisClient.expire(redisKey, this.redisConfig.ttl);
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
/**
|
|
448
|
-
* Find split index to keep recent messages within target token count
|
|
449
|
-
*/
|
|
450
|
-
async findSplitIndexByTokens(messages, targetRecentTokens) {
|
|
451
|
-
let recentTokens = 0;
|
|
452
|
-
let splitIndex = messages.length;
|
|
453
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
454
|
-
const msgTokens = TokenUtils.estimateTokenCount(messages[i].content);
|
|
455
|
-
if (recentTokens + msgTokens > targetRecentTokens) {
|
|
456
|
-
splitIndex = i + 1;
|
|
457
|
-
break;
|
|
458
|
-
}
|
|
459
|
-
recentTokens += msgTokens;
|
|
460
|
-
}
|
|
461
|
-
// Ensure we're summarizing at least something
|
|
462
|
-
return Math.max(1, splitIndex);
|
|
463
|
-
}
|
|
464
454
|
/**
|
|
465
455
|
* Build context messages for AI prompt injection (TOKEN-BASED)
|
|
466
456
|
* Returns messages from pointer onwards (or all if no pointer)
|
|
@@ -625,7 +615,10 @@ export class RedisConversationMemoryManager {
|
|
|
625
615
|
}
|
|
626
616
|
await this.ensureInitialized();
|
|
627
617
|
if (!this.redisClient) {
|
|
628
|
-
logger.warn("[RedisConversationMemoryManager] Redis client not available for getUserSessionObject", {
|
|
618
|
+
logger.warn("[RedisConversationMemoryManager] Redis client not available for getUserSessionObject", {
|
|
619
|
+
userId,
|
|
620
|
+
sessionId,
|
|
621
|
+
});
|
|
629
622
|
return null;
|
|
630
623
|
}
|
|
631
624
|
try {
|
|
@@ -903,8 +896,6 @@ User message: "${userMessage}`;
|
|
|
903
896
|
? sessionError.message
|
|
904
897
|
: String(sessionError),
|
|
905
898
|
});
|
|
906
|
-
// Continue with other sessions even if one fails
|
|
907
|
-
continue;
|
|
908
899
|
}
|
|
909
900
|
}
|
|
910
901
|
return results;
|
|
@@ -10,11 +10,11 @@ type ProviderConstructor = {
|
|
|
10
10
|
/**
|
|
11
11
|
* Provider registration entry
|
|
12
12
|
*/
|
|
13
|
-
|
|
13
|
+
type ProviderRegistration = {
|
|
14
14
|
constructor: ProviderConstructor;
|
|
15
15
|
defaultModel?: string;
|
|
16
16
|
aliases?: string[];
|
|
17
|
-
}
|
|
17
|
+
};
|
|
18
18
|
/**
|
|
19
19
|
* True Factory Pattern implementation for AI Providers
|
|
20
20
|
* Uses registration-based approach to eliminate switch statements
|