@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,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summarization Prompt Builder
|
|
3
|
+
*
|
|
4
|
+
* Builds prompts for summarizing conversation context into a 9-section structure.
|
|
5
|
+
* Supports both initial summarization and incremental merging with existing summaries.
|
|
6
|
+
*/
|
|
7
|
+
const NINE_SECTIONS = [
|
|
8
|
+
"Primary Request and Intent",
|
|
9
|
+
"Key Technical Concepts",
|
|
10
|
+
"Files and Code Sections",
|
|
11
|
+
"Problem Solving",
|
|
12
|
+
"Pending Tasks",
|
|
13
|
+
"Task Evolution",
|
|
14
|
+
"Current Work",
|
|
15
|
+
"Next Step",
|
|
16
|
+
"Required Files",
|
|
17
|
+
];
|
|
18
|
+
function buildFileContextSection(filesRead, filesModified) {
|
|
19
|
+
const hasFiles = (filesRead && filesRead.length > 0) ||
|
|
20
|
+
(filesModified && filesModified.length > 0);
|
|
21
|
+
if (!hasFiles) {
|
|
22
|
+
return "";
|
|
23
|
+
}
|
|
24
|
+
let section = "\n\nFile Context:\n";
|
|
25
|
+
if (filesRead && filesRead.length > 0) {
|
|
26
|
+
section += "Files Read:\n";
|
|
27
|
+
for (const file of filesRead) {
|
|
28
|
+
section += `- ${file}\n`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (filesModified && filesModified.length > 0) {
|
|
32
|
+
section += "Files Modified:\n";
|
|
33
|
+
for (const file of filesModified) {
|
|
34
|
+
section += `- ${file}\n`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return section;
|
|
38
|
+
}
|
|
39
|
+
function buildInitialPrompt(options) {
|
|
40
|
+
const fileContext = buildFileContextSection(options.filesRead, options.filesModified);
|
|
41
|
+
return `You are a context summarization assistant. Your task is to analyze the conversation and create a structured summary following a 9-section format.
|
|
42
|
+
|
|
43
|
+
Create a summary with the following sections:
|
|
44
|
+
|
|
45
|
+
### 1. Primary Request and Intent
|
|
46
|
+
What is the user's main goal or request? What are they trying to accomplish?
|
|
47
|
+
|
|
48
|
+
### 2. Key Technical Concepts
|
|
49
|
+
What technologies, frameworks, patterns, or concepts are central to this conversation?
|
|
50
|
+
|
|
51
|
+
### 3. Files and Code Sections
|
|
52
|
+
What specific files, functions, or code sections have been discussed or modified?
|
|
53
|
+
|
|
54
|
+
### 4. Problem Solving
|
|
55
|
+
What problems were identified? What solutions were attempted or implemented?
|
|
56
|
+
|
|
57
|
+
### 5. Pending Tasks
|
|
58
|
+
What tasks remain incomplete or need follow-up?
|
|
59
|
+
|
|
60
|
+
### 6. Task Evolution
|
|
61
|
+
How has the task changed or evolved during the conversation?
|
|
62
|
+
|
|
63
|
+
### 7. Current Work
|
|
64
|
+
What is being actively worked on right now?
|
|
65
|
+
|
|
66
|
+
### 8. Next Step
|
|
67
|
+
What is the immediate next action to take?
|
|
68
|
+
|
|
69
|
+
### 9. Required Files
|
|
70
|
+
What files will need to be accessed or modified to continue?${fileContext}
|
|
71
|
+
|
|
72
|
+
Analyze the conversation thoroughly and fill in each section with relevant information. If a section is not applicable, write "N/A" for that section.`;
|
|
73
|
+
}
|
|
74
|
+
function buildIncrementalPrompt(options) {
|
|
75
|
+
const fileContext = buildFileContextSection(options.filesRead, options.filesModified);
|
|
76
|
+
return `You are a context summarization assistant. Your task is to MERGE new conversation content with an existing summary.
|
|
77
|
+
|
|
78
|
+
Existing Summary:
|
|
79
|
+
---
|
|
80
|
+
${options.previousSummary}
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
Update sections with new information while preserving important context from the existing summary. Maintain the same 9-section structure.
|
|
84
|
+
|
|
85
|
+
Instructions:
|
|
86
|
+
1. Review the existing summary above
|
|
87
|
+
2. Analyze the new conversation content
|
|
88
|
+
3. MERGE the new information into the appropriate sections
|
|
89
|
+
4. Update sections with relevant new information
|
|
90
|
+
5. Remove information that is no longer relevant
|
|
91
|
+
6. Keep the summary concise but comprehensive
|
|
92
|
+
7. Maintain the 9-section format${fileContext}
|
|
93
|
+
|
|
94
|
+
Output the updated summary following the same 9-section structure.`;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Builds a summarization prompt based on the provided options.
|
|
98
|
+
*
|
|
99
|
+
* @param options - Configuration for the prompt builder
|
|
100
|
+
* @returns The constructed prompt string
|
|
101
|
+
*/
|
|
102
|
+
export function buildSummarizationPrompt(options) {
|
|
103
|
+
// For incremental mode, we need a previous summary to merge with
|
|
104
|
+
// If no previous summary is provided, fall back to initial prompt
|
|
105
|
+
if (options.isIncremental && options.previousSummary) {
|
|
106
|
+
return buildIncrementalPrompt(options);
|
|
107
|
+
}
|
|
108
|
+
return buildInitialPrompt(options);
|
|
109
|
+
}
|
|
110
|
+
export { NINE_SECTIONS };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 2: File Read Deduplication
|
|
3
|
+
*
|
|
4
|
+
* Detect multiple reads of the same file path, keep only the latest,
|
|
5
|
+
* replace earlier reads with a notice.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChatMessage } from "../../types/conversation.js";
|
|
8
|
+
import type { DeduplicationResult } from "../../types/contextTypes.js";
|
|
9
|
+
export type { DeduplicationResult } from "../../types/contextTypes.js";
|
|
10
|
+
export declare function deduplicateFileReads(messages: ChatMessage[]): DeduplicationResult;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 2: File Read Deduplication
|
|
3
|
+
*
|
|
4
|
+
* Detect multiple reads of the same file path, keep only the latest,
|
|
5
|
+
* replace earlier reads with a notice.
|
|
6
|
+
*/
|
|
7
|
+
const FILE_READ_PATTERN = /(?:read|reading|read_file|readFile|Read file|cat)\s+['"`]?([^\s'"`\n]+)/i;
|
|
8
|
+
const DEDUP_NOTICE = (filePath) => `[File ${filePath} - refer to latest read below]`;
|
|
9
|
+
const DEDUP_THRESHOLD = 0.3; // Need 30% savings to declare success
|
|
10
|
+
export function deduplicateFileReads(messages) {
|
|
11
|
+
// Track file read positions: filePath -> array of message indices
|
|
12
|
+
const fileReadMap = new Map();
|
|
13
|
+
for (let i = 0; i < messages.length; i++) {
|
|
14
|
+
const msg = messages[i];
|
|
15
|
+
if (msg.role !== "tool_result" && msg.role !== "assistant") {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const match = msg.content.match(FILE_READ_PATTERN);
|
|
19
|
+
if (match) {
|
|
20
|
+
const filePath = match[1];
|
|
21
|
+
const existing = fileReadMap.get(filePath) || [];
|
|
22
|
+
existing.push(i);
|
|
23
|
+
fileReadMap.set(filePath, existing);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Find files read multiple times
|
|
27
|
+
const duplicates = new Map();
|
|
28
|
+
for (const [filePath, indices] of fileReadMap) {
|
|
29
|
+
if (indices.length > 1) {
|
|
30
|
+
duplicates.set(filePath, indices);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (duplicates.size === 0) {
|
|
34
|
+
return { deduplicated: false, messages, filesDeduped: 0 };
|
|
35
|
+
}
|
|
36
|
+
const result = [...messages];
|
|
37
|
+
let totalOriginalChars = 0;
|
|
38
|
+
let totalReplacedChars = 0;
|
|
39
|
+
for (const [filePath, indices] of duplicates) {
|
|
40
|
+
// Keep the latest (last index), replace all earlier ones
|
|
41
|
+
const latestIndex = indices[indices.length - 1];
|
|
42
|
+
for (const idx of indices) {
|
|
43
|
+
if (idx === latestIndex) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const original = result[idx];
|
|
47
|
+
totalOriginalChars += original.content.length;
|
|
48
|
+
const notice = DEDUP_NOTICE(filePath);
|
|
49
|
+
totalReplacedChars += notice.length;
|
|
50
|
+
result[idx] = {
|
|
51
|
+
...original,
|
|
52
|
+
content: notice,
|
|
53
|
+
metadata: { ...original.metadata, truncated: true },
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
const savings = totalOriginalChars > 0
|
|
58
|
+
? (totalOriginalChars - totalReplacedChars) / totalOriginalChars
|
|
59
|
+
: 0;
|
|
60
|
+
const deduplicated = savings >= DEDUP_THRESHOLD;
|
|
61
|
+
return {
|
|
62
|
+
deduplicated,
|
|
63
|
+
messages: deduplicated ? result : messages,
|
|
64
|
+
filesDeduped: deduplicated ? duplicates.size : 0,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 4: Sliding Window Truncation
|
|
3
|
+
*
|
|
4
|
+
* Non-destructive fallback: tags oldest messages as truncated
|
|
5
|
+
* instead of deleting them. Always preserves first message pair.
|
|
6
|
+
* Removes messages in pairs to maintain role alternation.
|
|
7
|
+
*/
|
|
8
|
+
import type { ChatMessage } from "../../types/conversation.js";
|
|
9
|
+
import type { TruncationConfig, TruncationResult } from "../../types/contextTypes.js";
|
|
10
|
+
export type { TruncationConfig, TruncationResult, } from "../../types/contextTypes.js";
|
|
11
|
+
export declare function truncateWithSlidingWindow(messages: ChatMessage[], config?: TruncationConfig): TruncationResult;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 4: Sliding Window Truncation
|
|
3
|
+
*
|
|
4
|
+
* Non-destructive fallback: tags oldest messages as truncated
|
|
5
|
+
* instead of deleting them. Always preserves first message pair.
|
|
6
|
+
* Removes messages in pairs to maintain role alternation.
|
|
7
|
+
*/
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
9
|
+
const TRUNCATION_MARKER_CONTENT = "[Earlier conversation history was truncated to fit within context limits]";
|
|
10
|
+
export function truncateWithSlidingWindow(messages, config) {
|
|
11
|
+
const fraction = config?.fraction ?? 0.5;
|
|
12
|
+
if (messages.length <= 4) {
|
|
13
|
+
return { truncated: false, messages, messagesRemoved: 0 };
|
|
14
|
+
}
|
|
15
|
+
// Always preserve first user-assistant pair
|
|
16
|
+
const firstPair = messages.slice(0, 2);
|
|
17
|
+
// Calculate how many messages to remove from the middle
|
|
18
|
+
const remainingMessages = messages.slice(2);
|
|
19
|
+
const removeCount = Math.floor(remainingMessages.length * fraction);
|
|
20
|
+
// Ensure we remove an even number to maintain role alternation
|
|
21
|
+
const evenRemoveCount = removeCount - (removeCount % 2);
|
|
22
|
+
if (evenRemoveCount <= 0) {
|
|
23
|
+
return { truncated: false, messages, messagesRemoved: 0 };
|
|
24
|
+
}
|
|
25
|
+
const keptAfterTruncation = remainingMessages.slice(evenRemoveCount);
|
|
26
|
+
// Create truncation marker
|
|
27
|
+
const truncationMarker = {
|
|
28
|
+
id: `truncation-${randomUUID()}`,
|
|
29
|
+
role: "system",
|
|
30
|
+
content: TRUNCATION_MARKER_CONTENT,
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
metadata: {
|
|
33
|
+
isSummary: false,
|
|
34
|
+
truncated: true,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
truncated: true,
|
|
39
|
+
messages: [...firstPair, truncationMarker, ...keptAfterTruncation],
|
|
40
|
+
messagesRemoved: evenRemoveCount,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 3: Structured LLM Summarization
|
|
3
|
+
*
|
|
4
|
+
* Uses the structured 9-section prompt to summarize older messages
|
|
5
|
+
* while preserving recent ones.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChatMessage } from "../../types/conversation.js";
|
|
8
|
+
import type { SummarizeConfig, SummarizeResult } from "../../types/contextTypes.js";
|
|
9
|
+
export type { SummarizeConfig, SummarizeResult, } from "../../types/contextTypes.js";
|
|
10
|
+
export declare function summarizeMessages(messages: ChatMessage[], config?: SummarizeConfig): Promise<SummarizeResult>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 3: Structured LLM Summarization
|
|
3
|
+
*
|
|
4
|
+
* Uses the structured 9-section prompt to summarize older messages
|
|
5
|
+
* while preserving recent ones.
|
|
6
|
+
*/
|
|
7
|
+
import { generateSummary } from "../../utils/conversationMemory.js";
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
9
|
+
export async function summarizeMessages(messages, config) {
|
|
10
|
+
const keepRecentRatio = config?.keepRecentRatio ?? 0.3;
|
|
11
|
+
if (messages.length <= 4) {
|
|
12
|
+
return { summarized: false, messages };
|
|
13
|
+
}
|
|
14
|
+
// Keep the most recent messages unsummarized
|
|
15
|
+
const keepCount = Math.max(4, Math.ceil(messages.length * keepRecentRatio));
|
|
16
|
+
const splitIndex = messages.length - keepCount;
|
|
17
|
+
if (splitIndex <= 0) {
|
|
18
|
+
return { summarized: false, messages };
|
|
19
|
+
}
|
|
20
|
+
const messagesToSummarize = messages.slice(0, splitIndex);
|
|
21
|
+
const recentMessages = messages.slice(splitIndex);
|
|
22
|
+
// Find previous summary if exists
|
|
23
|
+
const previousSummary = messagesToSummarize.find((m) => m.metadata?.isSummary)?.content;
|
|
24
|
+
// Use memory config for summarization if available
|
|
25
|
+
if (config?.memoryConfig) {
|
|
26
|
+
const summaryText = await generateSummary(messagesToSummarize, config.memoryConfig, "[ContextCompactor]", previousSummary);
|
|
27
|
+
if (!summaryText) {
|
|
28
|
+
return { summarized: false, messages };
|
|
29
|
+
}
|
|
30
|
+
const summaryMessage = {
|
|
31
|
+
id: `summary-${randomUUID()}`,
|
|
32
|
+
role: "system",
|
|
33
|
+
content: `Previous conversation summary:\n\n${summaryText}`,
|
|
34
|
+
timestamp: new Date().toISOString(),
|
|
35
|
+
metadata: {
|
|
36
|
+
isSummary: true,
|
|
37
|
+
summarizesFrom: messagesToSummarize[0]?.id,
|
|
38
|
+
summarizesTo: messagesToSummarize[messagesToSummarize.length - 1]?.id,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
return {
|
|
42
|
+
summarized: true,
|
|
43
|
+
messages: [summaryMessage, ...recentMessages],
|
|
44
|
+
summaryText,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Without memory config, we can't call LLM
|
|
48
|
+
return { summarized: false, messages };
|
|
49
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 1: Tool Output Pruning
|
|
3
|
+
*
|
|
4
|
+
* Walk messages backwards, protect recent tool output tokens,
|
|
5
|
+
* replace older tool results with "[Tool result cleared]".
|
|
6
|
+
*/
|
|
7
|
+
import type { ChatMessage } from "../../types/conversation.js";
|
|
8
|
+
import type { PruneConfig, PruneResult } from "../../types/contextTypes.js";
|
|
9
|
+
export type { PruneConfig, PruneResult } from "../../types/contextTypes.js";
|
|
10
|
+
export declare function pruneToolOutputs(messages: ChatMessage[], config?: PruneConfig): PruneResult;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stage 1: Tool Output Pruning
|
|
3
|
+
*
|
|
4
|
+
* Walk messages backwards, protect recent tool output tokens,
|
|
5
|
+
* replace older tool results with "[Tool result cleared]".
|
|
6
|
+
*/
|
|
7
|
+
import { estimateTokens } from "../../utils/tokenEstimation.js";
|
|
8
|
+
const CLEARED_PLACEHOLDER = "[Tool result cleared]";
|
|
9
|
+
const DEFAULT_PROTECT_TOKENS = 40_000;
|
|
10
|
+
const DEFAULT_MINIMUM_SAVINGS = 20_000;
|
|
11
|
+
export function pruneToolOutputs(messages, config) {
|
|
12
|
+
const protectTokens = config?.protectTokens ?? DEFAULT_PROTECT_TOKENS;
|
|
13
|
+
const minimumSavings = config?.minimumSavings ?? DEFAULT_MINIMUM_SAVINGS;
|
|
14
|
+
const protectedTools = new Set(config?.protectedTools ?? ["skill"]);
|
|
15
|
+
const provider = config?.provider;
|
|
16
|
+
const result = [...messages];
|
|
17
|
+
let recentToolTokens = 0;
|
|
18
|
+
let totalSaved = 0;
|
|
19
|
+
// Walk backwards to protect recent tool outputs
|
|
20
|
+
for (let i = result.length - 1; i >= 0; i--) {
|
|
21
|
+
const msg = result[i];
|
|
22
|
+
if (msg.role !== "tool_result") {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
// Skip protected tools
|
|
26
|
+
if (msg.tool && protectedTools.has(msg.tool)) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const contentTokens = estimateTokens(msg.content, provider);
|
|
30
|
+
if (recentToolTokens < protectTokens) {
|
|
31
|
+
// This tool output is within the protection window
|
|
32
|
+
recentToolTokens += contentTokens;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
// This tool output is old enough to prune
|
|
36
|
+
if (msg.content !== CLEARED_PLACEHOLDER) {
|
|
37
|
+
totalSaved +=
|
|
38
|
+
contentTokens - estimateTokens(CLEARED_PLACEHOLDER, provider);
|
|
39
|
+
result[i] = {
|
|
40
|
+
...msg,
|
|
41
|
+
content: CLEARED_PLACEHOLDER,
|
|
42
|
+
metadata: { ...msg.metadata, truncated: true },
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
const pruned = totalSaved >= minimumSavings;
|
|
47
|
+
return {
|
|
48
|
+
pruned,
|
|
49
|
+
messages: pruned ? result : messages,
|
|
50
|
+
tokensSaved: pruned ? totalSaved : 0,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Summarization Engine
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ConversationMemoryManager and RedisConversationMemoryManager
|
|
5
|
+
* to eliminate code duplication. Both managers delegate to this engine.
|
|
6
|
+
*/
|
|
7
|
+
import type { ChatMessage, ConversationMemoryConfig, SessionMemory } from "../types/conversation.js";
|
|
8
|
+
/**
|
|
9
|
+
* Centralized summarization engine for conversation memory.
|
|
10
|
+
* Handles token counting, threshold checking, and summary generation.
|
|
11
|
+
*/
|
|
12
|
+
export declare class SummarizationEngine {
|
|
13
|
+
/**
|
|
14
|
+
* Check if a session needs summarization and perform it if so.
|
|
15
|
+
* @param session - Session memory to check and potentially summarize
|
|
16
|
+
* @param threshold - Token threshold that triggers summarization
|
|
17
|
+
* @param config - Conversation memory configuration (partial allowed)
|
|
18
|
+
* @param logPrefix - Prefix for log messages
|
|
19
|
+
* @returns True if summarization was performed
|
|
20
|
+
*/
|
|
21
|
+
checkAndSummarize(session: SessionMemory, threshold: number, config: Partial<ConversationMemoryConfig>, logPrefix?: string): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* Perform token-based summarization on a session.
|
|
24
|
+
* Uses pointer-based, non-destructive approach.
|
|
25
|
+
* @param session - Session memory to summarize
|
|
26
|
+
* @param threshold - Token threshold for calculating split point
|
|
27
|
+
* @param config - Conversation memory configuration (partial allowed)
|
|
28
|
+
* @param logPrefix - Prefix for log messages
|
|
29
|
+
*/
|
|
30
|
+
summarizeSession(session: SessionMemory, threshold: number, config: Partial<ConversationMemoryConfig>, logPrefix?: string): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* Estimate total tokens for a message array.
|
|
33
|
+
* @param messages - Array of chat messages
|
|
34
|
+
* @returns Estimated token count
|
|
35
|
+
*/
|
|
36
|
+
estimateTokens(messages: ChatMessage[]): number;
|
|
37
|
+
/**
|
|
38
|
+
* Find split index to keep recent messages within target token count.
|
|
39
|
+
* Works backwards from the most recent message to find the split point.
|
|
40
|
+
* @param messages - Array of messages to analyze
|
|
41
|
+
* @param targetRecentTokens - Target token count for recent messages
|
|
42
|
+
* @returns Index at which to split (messages before this index will be summarized)
|
|
43
|
+
*/
|
|
44
|
+
findSplitIndexByTokens(messages: ChatMessage[], targetRecentTokens: number): number;
|
|
45
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Summarization Engine
|
|
3
|
+
*
|
|
4
|
+
* Extracted from ConversationMemoryManager and RedisConversationMemoryManager
|
|
5
|
+
* to eliminate code duplication. Both managers delegate to this engine.
|
|
6
|
+
*/
|
|
7
|
+
import { TokenUtils } from "../constants/tokens.js";
|
|
8
|
+
import { buildContextFromPointer, generateSummary, } from "../utils/conversationMemory.js";
|
|
9
|
+
import { RECENT_MESSAGES_RATIO } from "../config/conversationMemory.js";
|
|
10
|
+
import { logger } from "../utils/logger.js";
|
|
11
|
+
/**
|
|
12
|
+
* Centralized summarization engine for conversation memory.
|
|
13
|
+
* Handles token counting, threshold checking, and summary generation.
|
|
14
|
+
*/
|
|
15
|
+
export class SummarizationEngine {
|
|
16
|
+
/**
|
|
17
|
+
* Check if a session needs summarization and perform it if so.
|
|
18
|
+
* @param session - Session memory to check and potentially summarize
|
|
19
|
+
* @param threshold - Token threshold that triggers summarization
|
|
20
|
+
* @param config - Conversation memory configuration (partial allowed)
|
|
21
|
+
* @param logPrefix - Prefix for log messages
|
|
22
|
+
* @returns True if summarization was performed
|
|
23
|
+
*/
|
|
24
|
+
async checkAndSummarize(session, threshold, config, logPrefix = "[SummarizationEngine]") {
|
|
25
|
+
const contextMessages = buildContextFromPointer(session);
|
|
26
|
+
const tokenCount = this.estimateTokens(contextMessages);
|
|
27
|
+
session.lastTokenCount = tokenCount;
|
|
28
|
+
session.lastCountedAt = Date.now();
|
|
29
|
+
logger.debug(`${logPrefix} Token count check`, {
|
|
30
|
+
sessionId: session.sessionId,
|
|
31
|
+
tokenCount,
|
|
32
|
+
threshold,
|
|
33
|
+
needsSummarization: tokenCount >= threshold,
|
|
34
|
+
});
|
|
35
|
+
if (tokenCount >= threshold) {
|
|
36
|
+
await this.summarizeSession(session, threshold, config, logPrefix);
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Perform token-based summarization on a session.
|
|
43
|
+
* Uses pointer-based, non-destructive approach.
|
|
44
|
+
* @param session - Session memory to summarize
|
|
45
|
+
* @param threshold - Token threshold for calculating split point
|
|
46
|
+
* @param config - Conversation memory configuration (partial allowed)
|
|
47
|
+
* @param logPrefix - Prefix for log messages
|
|
48
|
+
*/
|
|
49
|
+
async summarizeSession(session, threshold, config, logPrefix = "[SummarizationEngine]") {
|
|
50
|
+
const startIndex = session.summarizedUpToMessageId
|
|
51
|
+
? session.messages.findIndex((m) => m.id === session.summarizedUpToMessageId) + 1
|
|
52
|
+
: 0;
|
|
53
|
+
const recentMessages = session.messages.slice(startIndex);
|
|
54
|
+
if (recentMessages.length === 0) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const targetRecentTokens = threshold * RECENT_MESSAGES_RATIO;
|
|
58
|
+
const splitIndex = this.findSplitIndexByTokens(recentMessages, targetRecentTokens);
|
|
59
|
+
const messagesToSummarize = recentMessages.slice(0, splitIndex);
|
|
60
|
+
if (messagesToSummarize.length === 0) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const summary = await generateSummary(messagesToSummarize, config, logPrefix, session.summarizedMessage);
|
|
64
|
+
if (!summary) {
|
|
65
|
+
logger.warn(`${logPrefix} Summary generation failed`, {
|
|
66
|
+
sessionId: session.sessionId,
|
|
67
|
+
});
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const lastSummarized = messagesToSummarize[messagesToSummarize.length - 1];
|
|
71
|
+
session.summarizedUpToMessageId = lastSummarized.id;
|
|
72
|
+
session.summarizedMessage = summary;
|
|
73
|
+
logger.info(`${logPrefix} Summarization complete`, {
|
|
74
|
+
sessionId: session.sessionId,
|
|
75
|
+
summarizedCount: messagesToSummarize.length,
|
|
76
|
+
totalMessages: session.messages.length,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Estimate total tokens for a message array.
|
|
81
|
+
* @param messages - Array of chat messages
|
|
82
|
+
* @returns Estimated token count
|
|
83
|
+
*/
|
|
84
|
+
estimateTokens(messages) {
|
|
85
|
+
return messages.reduce((total, msg) => {
|
|
86
|
+
return total + TokenUtils.estimateTokenCount(msg.content);
|
|
87
|
+
}, 0);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Find split index to keep recent messages within target token count.
|
|
91
|
+
* Works backwards from the most recent message to find the split point.
|
|
92
|
+
* @param messages - Array of messages to analyze
|
|
93
|
+
* @param targetRecentTokens - Target token count for recent messages
|
|
94
|
+
* @returns Index at which to split (messages before this index will be summarized)
|
|
95
|
+
*/
|
|
96
|
+
findSplitIndexByTokens(messages, targetRecentTokens) {
|
|
97
|
+
let recentTokens = 0;
|
|
98
|
+
let splitIndex = messages.length;
|
|
99
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
100
|
+
const msgTokens = TokenUtils.estimateTokenCount(messages[i].content);
|
|
101
|
+
if (recentTokens + msgTokens > targetRecentTokens) {
|
|
102
|
+
splitIndex = i + 1;
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
recentTokens += msgTokens;
|
|
106
|
+
}
|
|
107
|
+
// Ensure at least one message is summarized
|
|
108
|
+
return Math.max(1, splitIndex);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Output Size Limits
|
|
3
|
+
*
|
|
4
|
+
* Truncates tool outputs exceeding size limits.
|
|
5
|
+
* Can save full output to disk with a pointer.
|
|
6
|
+
* Modeled on OpenCode's approach.
|
|
7
|
+
*/
|
|
8
|
+
/** Maximum tool output size in bytes (50KB) */
|
|
9
|
+
export declare const MAX_TOOL_OUTPUT_BYTES: number;
|
|
10
|
+
/** Maximum tool output lines */
|
|
11
|
+
export declare const MAX_TOOL_OUTPUT_LINES = 2000;
|
|
12
|
+
import type { TruncateOptions, TruncateResult } from "../types/contextTypes.js";
|
|
13
|
+
export type { TruncateOptions, TruncateResult } from "../types/contextTypes.js";
|
|
14
|
+
/**
|
|
15
|
+
* Truncate tool output if it exceeds size limits.
|
|
16
|
+
*/
|
|
17
|
+
export declare function truncateToolOutput(output: string, options?: TruncateOptions): TruncateResult;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool Output Size Limits
|
|
3
|
+
*
|
|
4
|
+
* Truncates tool outputs exceeding size limits.
|
|
5
|
+
* Can save full output to disk with a pointer.
|
|
6
|
+
* Modeled on OpenCode's approach.
|
|
7
|
+
*/
|
|
8
|
+
import { writeFileSync, mkdirSync } from "fs";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
import { randomUUID } from "crypto";
|
|
11
|
+
import { tmpdir } from "os";
|
|
12
|
+
/** Maximum tool output size in bytes (50KB) */
|
|
13
|
+
export const MAX_TOOL_OUTPUT_BYTES = 50 * 1024;
|
|
14
|
+
/** Maximum tool output lines */
|
|
15
|
+
export const MAX_TOOL_OUTPUT_LINES = 2_000;
|
|
16
|
+
/**
|
|
17
|
+
* Truncate tool output if it exceeds size limits.
|
|
18
|
+
*/
|
|
19
|
+
export function truncateToolOutput(output, options) {
|
|
20
|
+
const maxBytes = options?.maxBytes ?? MAX_TOOL_OUTPUT_BYTES;
|
|
21
|
+
const maxLines = options?.maxLines ?? MAX_TOOL_OUTPUT_LINES;
|
|
22
|
+
const direction = options?.direction ?? "tail";
|
|
23
|
+
const saveToDisk = options?.saveToDisk ?? false;
|
|
24
|
+
const originalSize = Buffer.byteLength(output, "utf-8");
|
|
25
|
+
// Check byte limit
|
|
26
|
+
const exceedsBytes = originalSize > maxBytes;
|
|
27
|
+
// Check line limit
|
|
28
|
+
const lines = output.split("\n");
|
|
29
|
+
const exceedsLines = lines.length > maxLines;
|
|
30
|
+
if (!exceedsBytes && !exceedsLines) {
|
|
31
|
+
return { content: output, truncated: false, originalSize };
|
|
32
|
+
}
|
|
33
|
+
// Save to disk if requested
|
|
34
|
+
let savedPath;
|
|
35
|
+
if (saveToDisk) {
|
|
36
|
+
try {
|
|
37
|
+
const saveDir = options?.saveDir ?? join(tmpdir(), "neurolink-tool-output");
|
|
38
|
+
mkdirSync(saveDir, { recursive: true });
|
|
39
|
+
savedPath = join(saveDir, `tool-output-${randomUUID()}.txt`);
|
|
40
|
+
writeFileSync(savedPath, output, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// Silently fail disk save
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Apply truncation
|
|
47
|
+
let truncated;
|
|
48
|
+
if (exceedsLines) {
|
|
49
|
+
if (direction === "head") {
|
|
50
|
+
truncated = lines.slice(0, maxLines).join("\n");
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
truncated = lines.slice(-maxLines).join("\n");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
truncated = output;
|
|
58
|
+
}
|
|
59
|
+
// Apply byte limit
|
|
60
|
+
if (Buffer.byteLength(truncated, "utf-8") > maxBytes) {
|
|
61
|
+
if (direction === "head") {
|
|
62
|
+
truncated = truncated.slice(0, maxBytes);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
truncated = truncated.slice(-maxBytes);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Add truncation notice
|
|
69
|
+
const notice = savedPath
|
|
70
|
+
? `\n\n[Output truncated from ${originalSize} bytes to ${Buffer.byteLength(truncated, "utf-8")} bytes. Full output saved to: ${savedPath}]`
|
|
71
|
+
: `\n\n[Output truncated from ${originalSize} bytes to ${Buffer.byteLength(truncated, "utf-8")} bytes]`;
|
|
72
|
+
if (direction === "head") {
|
|
73
|
+
truncated = truncated + notice;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
truncated = notice + "\n" + truncated;
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
content: truncated,
|
|
80
|
+
truncated: true,
|
|
81
|
+
savedPath,
|
|
82
|
+
originalSize,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
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 type { ChatMessage } from "../types/conversation.js";
|
|
9
|
+
import type { RepairResult } from "../types/contextTypes.js";
|
|
10
|
+
export type { RepairResult } from "../types/contextTypes.js";
|
|
11
|
+
/**
|
|
12
|
+
* Repair orphaned tool_use/tool_result pairs in a message array.
|
|
13
|
+
*
|
|
14
|
+
* Ensures every tool_call has a following tool_result and vice versa.
|
|
15
|
+
*/
|
|
16
|
+
export declare function repairToolPairs(messages: ChatMessage[]): RepairResult;
|