@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.
Files changed (356) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +29 -25
  3. package/dist/agent/directTools.d.ts +5 -5
  4. package/dist/cli/commands/config.d.ts +9 -9
  5. package/dist/cli/commands/serve.d.ts +37 -0
  6. package/dist/cli/commands/serve.js +302 -229
  7. package/dist/cli/commands/setup-anthropic.d.ts +2 -2
  8. package/dist/cli/commands/setup-azure.d.ts +2 -2
  9. package/dist/cli/commands/setup-bedrock.d.ts +2 -2
  10. package/dist/cli/commands/setup-gcp.d.ts +2 -2
  11. package/dist/cli/commands/setup-google-ai.d.ts +2 -2
  12. package/dist/cli/commands/setup-huggingface.d.ts +2 -2
  13. package/dist/cli/commands/setup-mistral.d.ts +2 -2
  14. package/dist/cli/commands/setup-openai.d.ts +2 -2
  15. package/dist/cli/commands/setup.d.ts +2 -2
  16. package/dist/cli/factories/commandFactory.js +16 -2
  17. package/dist/cli/loop/optionsSchema.d.ts +2 -2
  18. package/dist/cli/loop/session.d.ts +4 -0
  19. package/dist/cli/loop/session.js +49 -4
  20. package/dist/cli/utils/interactiveSetup.d.ts +4 -4
  21. package/dist/config/conversationMemory.d.ts +2 -0
  22. package/dist/config/conversationMemory.js +5 -5
  23. package/dist/constants/contextWindows.d.ts +46 -0
  24. package/dist/constants/contextWindows.js +156 -0
  25. package/dist/context/budgetChecker.d.ts +18 -0
  26. package/dist/context/budgetChecker.js +71 -0
  27. package/dist/context/contextCompactor.d.ts +22 -0
  28. package/dist/context/contextCompactor.js +106 -0
  29. package/dist/context/effectiveHistory.d.ts +52 -0
  30. package/dist/context/effectiveHistory.js +105 -0
  31. package/dist/context/errorDetection.d.ts +14 -0
  32. package/dist/context/errorDetection.js +124 -0
  33. package/dist/context/fileSummarizationService.d.ts +54 -0
  34. package/dist/context/fileSummarizationService.js +255 -0
  35. package/dist/context/fileSummarizer.d.ts +56 -0
  36. package/dist/context/fileSummarizer.js +145 -0
  37. package/dist/context/fileTokenBudget.d.ts +53 -0
  38. package/dist/context/fileTokenBudget.js +127 -0
  39. package/dist/context/prompts/summarizationPrompt.d.ts +17 -0
  40. package/dist/context/prompts/summarizationPrompt.js +110 -0
  41. package/dist/context/stages/fileReadDeduplicator.d.ts +10 -0
  42. package/dist/context/stages/fileReadDeduplicator.js +66 -0
  43. package/dist/context/stages/slidingWindowTruncator.d.ts +11 -0
  44. package/dist/context/stages/slidingWindowTruncator.js +42 -0
  45. package/dist/context/stages/structuredSummarizer.d.ts +10 -0
  46. package/dist/context/stages/structuredSummarizer.js +49 -0
  47. package/dist/context/stages/toolOutputPruner.d.ts +10 -0
  48. package/dist/context/stages/toolOutputPruner.js +52 -0
  49. package/dist/context/summarizationEngine.d.ts +45 -0
  50. package/dist/context/summarizationEngine.js +110 -0
  51. package/dist/context/toolOutputLimits.d.ts +17 -0
  52. package/dist/context/toolOutputLimits.js +84 -0
  53. package/dist/context/toolPairRepair.d.ts +16 -0
  54. package/dist/context/toolPairRepair.js +66 -0
  55. package/dist/core/conversationMemoryManager.d.ts +5 -15
  56. package/dist/core/conversationMemoryManager.js +15 -75
  57. package/dist/core/modules/MessageBuilder.d.ts +1 -1
  58. package/dist/core/modules/MessageBuilder.js +2 -0
  59. package/dist/core/modules/TelemetryHandler.d.ts +2 -3
  60. package/dist/core/modules/TelemetryHandler.js +3 -3
  61. package/dist/core/modules/ToolsManager.d.ts +2 -2
  62. package/dist/core/redisConversationMemoryManager.d.ts +8 -14
  63. package/dist/core/redisConversationMemoryManager.js +69 -78
  64. package/dist/factories/providerFactory.d.ts +2 -2
  65. package/dist/files/fileReferenceRegistry.d.ts +276 -0
  66. package/dist/files/fileReferenceRegistry.js +1543 -0
  67. package/dist/files/fileTools.d.ts +423 -0
  68. package/dist/files/fileTools.js +449 -0
  69. package/dist/files/index.d.ts +14 -0
  70. package/dist/files/index.js +13 -0
  71. package/dist/files/streamingReader.d.ts +93 -0
  72. package/dist/files/streamingReader.js +321 -0
  73. package/dist/files/types.d.ts +23 -0
  74. package/dist/files/types.js +23 -0
  75. package/dist/image-gen/imageGenTools.d.ts +2 -2
  76. package/dist/image-gen/types.d.ts +12 -12
  77. package/dist/lib/agent/directTools.d.ts +7 -7
  78. package/dist/lib/config/conversationMemory.d.ts +2 -0
  79. package/dist/lib/config/conversationMemory.js +5 -5
  80. package/dist/lib/constants/contextWindows.d.ts +46 -0
  81. package/dist/lib/constants/contextWindows.js +157 -0
  82. package/dist/lib/context/budgetChecker.d.ts +18 -0
  83. package/dist/lib/context/budgetChecker.js +72 -0
  84. package/dist/lib/context/contextCompactor.d.ts +22 -0
  85. package/dist/lib/context/contextCompactor.js +107 -0
  86. package/dist/lib/context/effectiveHistory.d.ts +52 -0
  87. package/dist/lib/context/effectiveHistory.js +106 -0
  88. package/dist/lib/context/errorDetection.d.ts +14 -0
  89. package/dist/lib/context/errorDetection.js +125 -0
  90. package/dist/lib/context/fileSummarizationService.d.ts +54 -0
  91. package/dist/lib/context/fileSummarizationService.js +256 -0
  92. package/dist/lib/context/fileSummarizer.d.ts +56 -0
  93. package/dist/lib/context/fileSummarizer.js +146 -0
  94. package/dist/lib/context/fileTokenBudget.d.ts +53 -0
  95. package/dist/lib/context/fileTokenBudget.js +128 -0
  96. package/dist/lib/context/prompts/summarizationPrompt.d.ts +17 -0
  97. package/dist/lib/context/prompts/summarizationPrompt.js +111 -0
  98. package/dist/lib/context/stages/fileReadDeduplicator.d.ts +10 -0
  99. package/dist/lib/context/stages/fileReadDeduplicator.js +67 -0
  100. package/dist/lib/context/stages/slidingWindowTruncator.d.ts +11 -0
  101. package/dist/lib/context/stages/slidingWindowTruncator.js +43 -0
  102. package/dist/lib/context/stages/structuredSummarizer.d.ts +10 -0
  103. package/dist/lib/context/stages/structuredSummarizer.js +50 -0
  104. package/dist/lib/context/stages/toolOutputPruner.d.ts +10 -0
  105. package/dist/lib/context/stages/toolOutputPruner.js +53 -0
  106. package/dist/lib/context/summarizationEngine.d.ts +45 -0
  107. package/dist/lib/context/summarizationEngine.js +111 -0
  108. package/dist/lib/context/toolOutputLimits.d.ts +17 -0
  109. package/dist/lib/context/toolOutputLimits.js +85 -0
  110. package/dist/lib/context/toolPairRepair.d.ts +16 -0
  111. package/dist/lib/context/toolPairRepair.js +67 -0
  112. package/dist/lib/core/conversationMemoryManager.d.ts +5 -15
  113. package/dist/lib/core/conversationMemoryManager.js +15 -75
  114. package/dist/lib/core/modules/MessageBuilder.d.ts +1 -1
  115. package/dist/lib/core/modules/MessageBuilder.js +2 -0
  116. package/dist/lib/core/modules/TelemetryHandler.d.ts +2 -3
  117. package/dist/lib/core/modules/TelemetryHandler.js +3 -3
  118. package/dist/lib/core/modules/ToolsManager.d.ts +2 -2
  119. package/dist/lib/core/redisConversationMemoryManager.d.ts +8 -14
  120. package/dist/lib/core/redisConversationMemoryManager.js +69 -78
  121. package/dist/lib/factories/providerFactory.d.ts +2 -2
  122. package/dist/lib/files/fileReferenceRegistry.d.ts +276 -0
  123. package/dist/lib/files/fileReferenceRegistry.js +1544 -0
  124. package/dist/lib/files/fileTools.d.ts +423 -0
  125. package/dist/lib/files/fileTools.js +450 -0
  126. package/dist/lib/files/index.d.ts +14 -0
  127. package/dist/lib/files/index.js +14 -0
  128. package/dist/lib/files/streamingReader.d.ts +93 -0
  129. package/dist/lib/files/streamingReader.js +322 -0
  130. package/dist/lib/files/types.d.ts +23 -0
  131. package/dist/lib/files/types.js +24 -0
  132. package/dist/lib/image-gen/imageGenTools.d.ts +2 -2
  133. package/dist/lib/image-gen/types.d.ts +12 -12
  134. package/dist/lib/memory/mem0Initializer.d.ts +2 -2
  135. package/dist/lib/neurolink.d.ts +61 -2
  136. package/dist/lib/neurolink.js +619 -307
  137. package/dist/lib/processors/archive/ArchiveProcessor.d.ts +327 -0
  138. package/dist/lib/processors/archive/ArchiveProcessor.js +1309 -0
  139. package/dist/lib/processors/archive/index.d.ts +33 -0
  140. package/dist/lib/processors/archive/index.js +43 -0
  141. package/dist/lib/processors/base/types.d.ts +70 -64
  142. package/dist/lib/processors/base/types.js +6 -0
  143. package/dist/lib/processors/cli/fileProcessorCli.d.ts +8 -8
  144. package/dist/lib/processors/cli/fileProcessorCli.js +5 -5
  145. package/dist/lib/processors/config/mimeTypes.js +25 -0
  146. package/dist/lib/processors/config/sizeLimits.d.ts +52 -40
  147. package/dist/lib/processors/config/sizeLimits.js +56 -44
  148. package/dist/lib/processors/document/ExcelProcessor.d.ts +14 -0
  149. package/dist/lib/processors/document/ExcelProcessor.js +72 -1
  150. package/dist/lib/processors/document/PptxProcessor.d.ts +63 -0
  151. package/dist/lib/processors/document/PptxProcessor.js +158 -0
  152. package/dist/lib/processors/document/index.d.ts +1 -0
  153. package/dist/lib/processors/document/index.js +6 -0
  154. package/dist/lib/processors/errors/FileErrorCode.d.ts +2 -2
  155. package/dist/lib/processors/errors/errorHelpers.d.ts +2 -2
  156. package/dist/lib/processors/errors/errorSerializer.d.ts +4 -4
  157. package/dist/lib/processors/index.d.ts +8 -2
  158. package/dist/lib/processors/index.js +5 -2
  159. package/dist/lib/processors/integration/FileProcessorIntegration.d.ts +8 -8
  160. package/dist/lib/processors/integration/FileProcessorIntegration.js +7 -7
  161. package/dist/lib/processors/media/AudioProcessor.d.ts +328 -0
  162. package/dist/lib/processors/media/AudioProcessor.js +708 -0
  163. package/dist/lib/processors/media/VideoProcessor.d.ts +350 -0
  164. package/dist/lib/processors/media/VideoProcessor.js +992 -0
  165. package/dist/lib/processors/media/index.d.ts +27 -0
  166. package/dist/lib/processors/media/index.js +37 -0
  167. package/dist/lib/processors/registry/ProcessorRegistry.d.ts +19 -5
  168. package/dist/lib/processors/registry/ProcessorRegistry.js +103 -8
  169. package/dist/lib/processors/registry/index.d.ts +1 -1
  170. package/dist/lib/processors/registry/index.js +1 -1
  171. package/dist/lib/processors/registry/types.d.ts +2 -2
  172. package/dist/lib/providers/googleAiStudio.d.ts +34 -0
  173. package/dist/lib/providers/googleAiStudio.js +267 -397
  174. package/dist/lib/providers/googleVertex.d.ts +55 -1
  175. package/dist/lib/providers/googleVertex.js +452 -719
  176. package/dist/lib/providers/sagemaker/detection.d.ts +6 -6
  177. package/dist/lib/providers/sagemaker/diagnostics.d.ts +4 -4
  178. package/dist/lib/providers/sagemaker/parsers.d.ts +4 -4
  179. package/dist/lib/rag/chunkers/RecursiveChunker.js +2 -2
  180. package/dist/lib/rag/document/loaders.d.ts +6 -71
  181. package/dist/lib/rag/document/loaders.js +5 -5
  182. package/dist/lib/rag/graphRag/graphRAG.js +26 -9
  183. package/dist/lib/rag/metadata/MetadataExtractorFactory.d.ts +5 -55
  184. package/dist/lib/rag/metadata/metadataExtractor.js +6 -3
  185. package/dist/lib/rag/pipeline/RAGPipeline.d.ts +8 -126
  186. package/dist/lib/rag/pipeline/RAGPipeline.js +11 -11
  187. package/dist/lib/rag/pipeline/contextAssembly.d.ts +3 -42
  188. package/dist/lib/rag/pipeline/contextAssembly.js +6 -3
  189. package/dist/lib/rag/reranker/RerankerFactory.d.ts +5 -60
  190. package/dist/lib/rag/resilience/CircuitBreaker.d.ts +3 -33
  191. package/dist/lib/rag/resilience/RetryHandler.d.ts +2 -21
  192. package/dist/lib/rag/retrieval/hybridSearch.d.ts +3 -41
  193. package/dist/lib/rag/retrieval/vectorQueryTool.d.ts +2 -13
  194. package/dist/lib/rag/retrieval/vectorQueryTool.js +4 -3
  195. package/dist/lib/rag/types.d.ts +3 -3
  196. package/dist/lib/sdk/toolRegistration.d.ts +2 -2
  197. package/dist/lib/server/middleware/cache.d.ts +2 -2
  198. package/dist/lib/server/middleware/rateLimit.d.ts +2 -2
  199. package/dist/lib/server/routes/mcpRoutes.js +277 -249
  200. package/dist/lib/server/routes/memoryRoutes.js +287 -281
  201. package/dist/lib/server/utils/validation.d.ts +10 -10
  202. package/dist/lib/session/globalSessionState.d.ts +2 -2
  203. package/dist/lib/telemetry/telemetryService.d.ts +2 -2
  204. package/dist/lib/types/common.d.ts +39 -0
  205. package/dist/lib/types/contextTypes.d.ts +255 -0
  206. package/dist/lib/types/contextTypes.js +0 -2
  207. package/dist/lib/types/conversation.d.ts +62 -0
  208. package/dist/lib/types/conversationMemoryInterface.d.ts +27 -0
  209. package/dist/lib/types/conversationMemoryInterface.js +7 -0
  210. package/dist/lib/types/fileReferenceTypes.d.ts +222 -0
  211. package/dist/lib/types/fileReferenceTypes.js +9 -0
  212. package/dist/lib/types/fileTypes.d.ts +26 -3
  213. package/dist/lib/types/generateTypes.d.ts +22 -1
  214. package/dist/lib/types/index.d.ts +4 -5
  215. package/dist/lib/types/index.js +8 -10
  216. package/dist/lib/types/modelTypes.d.ts +2 -2
  217. package/dist/lib/types/processorTypes.d.ts +597 -0
  218. package/dist/lib/types/processorTypes.js +91 -0
  219. package/dist/lib/types/ragTypes.d.ts +481 -0
  220. package/dist/lib/types/ragTypes.js +8 -0
  221. package/dist/lib/types/sdkTypes.d.ts +17 -18
  222. package/dist/lib/types/streamTypes.d.ts +11 -1
  223. package/dist/lib/utils/async/retry.d.ts +2 -2
  224. package/dist/lib/utils/async/withTimeout.js +3 -1
  225. package/dist/lib/utils/conversationMemory.d.ts +12 -6
  226. package/dist/lib/utils/conversationMemory.js +76 -36
  227. package/dist/lib/utils/fileDetector.d.ts +62 -0
  228. package/dist/lib/utils/fileDetector.js +1014 -14
  229. package/dist/lib/utils/json/safeParse.d.ts +2 -2
  230. package/dist/lib/utils/messageBuilder.js +806 -153
  231. package/dist/lib/utils/modelChoices.d.ts +2 -2
  232. package/dist/lib/utils/multimodalOptionsBuilder.d.ts +2 -1
  233. package/dist/lib/utils/multimodalOptionsBuilder.js +1 -0
  234. package/dist/lib/utils/rateLimiter.d.ts +2 -2
  235. package/dist/lib/utils/sanitizers/filename.d.ts +4 -4
  236. package/dist/lib/utils/sanitizers/svg.d.ts +2 -2
  237. package/dist/lib/utils/thinkingConfig.d.ts +6 -6
  238. package/dist/lib/utils/tokenEstimation.d.ts +68 -0
  239. package/dist/lib/utils/tokenEstimation.js +113 -0
  240. package/dist/lib/utils/tokenUtils.d.ts +4 -4
  241. package/dist/lib/utils/ttsProcessor.d.ts +2 -2
  242. package/dist/lib/workflow/config.d.ts +150 -150
  243. package/dist/memory/mem0Initializer.d.ts +2 -2
  244. package/dist/neurolink.d.ts +61 -2
  245. package/dist/neurolink.js +619 -307
  246. package/dist/processors/archive/ArchiveProcessor.d.ts +327 -0
  247. package/dist/processors/archive/ArchiveProcessor.js +1308 -0
  248. package/dist/processors/archive/index.d.ts +33 -0
  249. package/dist/processors/archive/index.js +42 -0
  250. package/dist/processors/base/types.d.ts +70 -64
  251. package/dist/processors/base/types.js +6 -0
  252. package/dist/processors/cli/fileProcessorCli.d.ts +8 -8
  253. package/dist/processors/cli/fileProcessorCli.js +5 -5
  254. package/dist/processors/config/mimeTypes.js +25 -0
  255. package/dist/processors/config/sizeLimits.d.ts +52 -40
  256. package/dist/processors/config/sizeLimits.js +56 -44
  257. package/dist/processors/document/ExcelProcessor.d.ts +14 -0
  258. package/dist/processors/document/ExcelProcessor.js +72 -1
  259. package/dist/processors/document/PptxProcessor.d.ts +63 -0
  260. package/dist/processors/document/PptxProcessor.js +157 -0
  261. package/dist/processors/document/index.d.ts +1 -0
  262. package/dist/processors/document/index.js +6 -0
  263. package/dist/processors/errors/FileErrorCode.d.ts +2 -2
  264. package/dist/processors/errors/errorHelpers.d.ts +2 -2
  265. package/dist/processors/errors/errorSerializer.d.ts +4 -4
  266. package/dist/processors/index.d.ts +8 -2
  267. package/dist/processors/index.js +5 -2
  268. package/dist/processors/integration/FileProcessorIntegration.d.ts +8 -8
  269. package/dist/processors/integration/FileProcessorIntegration.js +7 -7
  270. package/dist/processors/media/AudioProcessor.d.ts +328 -0
  271. package/dist/processors/media/AudioProcessor.js +707 -0
  272. package/dist/processors/media/VideoProcessor.d.ts +350 -0
  273. package/dist/processors/media/VideoProcessor.js +991 -0
  274. package/dist/processors/media/ffprobe-static.d.ts +4 -0
  275. package/dist/processors/media/index.d.ts +27 -0
  276. package/dist/processors/media/index.js +36 -0
  277. package/dist/processors/registry/ProcessorRegistry.d.ts +19 -5
  278. package/dist/processors/registry/ProcessorRegistry.js +103 -8
  279. package/dist/processors/registry/index.d.ts +1 -1
  280. package/dist/processors/registry/index.js +1 -1
  281. package/dist/processors/registry/types.d.ts +2 -2
  282. package/dist/providers/googleAiStudio.d.ts +34 -0
  283. package/dist/providers/googleAiStudio.js +267 -397
  284. package/dist/providers/googleVertex.d.ts +55 -1
  285. package/dist/providers/googleVertex.js +452 -719
  286. package/dist/providers/sagemaker/detection.d.ts +6 -6
  287. package/dist/providers/sagemaker/diagnostics.d.ts +4 -4
  288. package/dist/providers/sagemaker/parsers.d.ts +4 -4
  289. package/dist/rag/chunkers/RecursiveChunker.js +2 -2
  290. package/dist/rag/document/loaders.d.ts +6 -71
  291. package/dist/rag/document/loaders.js +5 -5
  292. package/dist/rag/graphRag/graphRAG.js +26 -9
  293. package/dist/rag/metadata/MetadataExtractorFactory.d.ts +5 -55
  294. package/dist/rag/metadata/metadataExtractor.js +6 -3
  295. package/dist/rag/pipeline/RAGPipeline.d.ts +8 -126
  296. package/dist/rag/pipeline/RAGPipeline.js +11 -11
  297. package/dist/rag/pipeline/contextAssembly.d.ts +3 -42
  298. package/dist/rag/pipeline/contextAssembly.js +6 -3
  299. package/dist/rag/reranker/RerankerFactory.d.ts +5 -60
  300. package/dist/rag/resilience/CircuitBreaker.d.ts +3 -33
  301. package/dist/rag/resilience/RetryHandler.d.ts +2 -21
  302. package/dist/rag/retrieval/hybridSearch.d.ts +3 -41
  303. package/dist/rag/retrieval/vectorQueryTool.d.ts +2 -13
  304. package/dist/rag/retrieval/vectorQueryTool.js +4 -3
  305. package/dist/rag/types.d.ts +3 -3
  306. package/dist/sdk/toolRegistration.d.ts +2 -2
  307. package/dist/server/middleware/cache.d.ts +2 -2
  308. package/dist/server/middleware/rateLimit.d.ts +2 -2
  309. package/dist/server/routes/mcpRoutes.js +277 -249
  310. package/dist/server/routes/memoryRoutes.js +287 -281
  311. package/dist/server/utils/validation.d.ts +4 -4
  312. package/dist/session/globalSessionState.d.ts +2 -2
  313. package/dist/telemetry/telemetryService.d.ts +2 -2
  314. package/dist/types/common.d.ts +39 -0
  315. package/dist/types/contextTypes.d.ts +255 -0
  316. package/dist/types/contextTypes.js +0 -2
  317. package/dist/types/conversation.d.ts +62 -0
  318. package/dist/types/conversationMemoryInterface.d.ts +27 -0
  319. package/dist/types/conversationMemoryInterface.js +6 -0
  320. package/dist/types/fileReferenceTypes.d.ts +222 -0
  321. package/dist/types/fileReferenceTypes.js +8 -0
  322. package/dist/types/fileTypes.d.ts +26 -3
  323. package/dist/types/generateTypes.d.ts +22 -1
  324. package/dist/types/index.d.ts +4 -5
  325. package/dist/types/index.js +8 -10
  326. package/dist/types/processorTypes.d.ts +597 -0
  327. package/dist/types/processorTypes.js +90 -0
  328. package/dist/types/ragTypes.d.ts +481 -0
  329. package/dist/types/ragTypes.js +7 -0
  330. package/dist/types/sdkTypes.d.ts +17 -18
  331. package/dist/types/streamTypes.d.ts +11 -1
  332. package/dist/utils/async/retry.d.ts +2 -2
  333. package/dist/utils/async/withTimeout.js +3 -1
  334. package/dist/utils/conversationMemory.d.ts +12 -6
  335. package/dist/utils/conversationMemory.js +76 -36
  336. package/dist/utils/fileDetector.d.ts +62 -0
  337. package/dist/utils/fileDetector.js +1014 -14
  338. package/dist/utils/json/safeParse.d.ts +2 -2
  339. package/dist/utils/messageBuilder.js +806 -153
  340. package/dist/utils/modelChoices.d.ts +2 -2
  341. package/dist/utils/multimodalOptionsBuilder.d.ts +2 -1
  342. package/dist/utils/multimodalOptionsBuilder.js +1 -0
  343. package/dist/utils/rateLimiter.d.ts +2 -2
  344. package/dist/utils/sanitizers/filename.d.ts +4 -4
  345. package/dist/utils/sanitizers/svg.d.ts +2 -2
  346. package/dist/utils/thinkingConfig.d.ts +6 -6
  347. package/dist/utils/tokenEstimation.d.ts +68 -0
  348. package/dist/utils/tokenEstimation.js +112 -0
  349. package/dist/utils/tokenUtils.d.ts +4 -4
  350. package/dist/utils/ttsProcessor.d.ts +2 -2
  351. package/dist/workflow/config.d.ts +104 -104
  352. package/package.json +18 -6
  353. package/dist/lib/utils/conversationMemoryUtils.d.ts +0 -25
  354. package/dist/lib/utils/conversationMemoryUtils.js +0 -138
  355. package/dist/utils/conversationMemoryUtils.d.ts +0 -25
  356. 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;