@juspay/neurolink 9.32.0 → 9.32.1

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 (467) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/auth/anthropicOAuth.js +1 -1
  3. package/dist/cli/commands/proxy.js +18 -5
  4. package/dist/client/aiSdkAdapter.js +1 -1
  5. package/dist/client/index.js +137 -501
  6. package/dist/core/factory.js +0 -1
  7. package/dist/core/redisConversationMemoryManager.js +1 -1
  8. package/dist/features/ppt/slideGenerator.js +0 -1
  9. package/dist/features/ppt/utils.js +0 -1
  10. package/dist/lib/server/routes/claudeProxyRoutes.js +45 -9
  11. package/dist/mcp/elicitationProtocol.js +1 -1
  12. package/dist/mcp/servers/agent/directToolsServer.js +0 -1
  13. package/dist/providers/azureOpenai.js +1 -1
  14. package/dist/providers/huggingFace.js +0 -1
  15. package/dist/providers/openaiCompatible.js +0 -1
  16. package/dist/sdk/toolRegistration.js +0 -1
  17. package/dist/server/openapi/generator.js +1 -1
  18. package/dist/server/routes/claudeProxyRoutes.js +45 -9
  19. package/dist/types/configTypes.js +0 -5
  20. package/dist/types/modelTypes.js +0 -1
  21. package/dist/types/tools.js +0 -1
  22. package/dist/types/typeAliases.js +0 -1
  23. package/dist/types/utilities.js +1 -1
  24. package/dist/types/workflowTypes.js +0 -1
  25. package/dist/utils/providerRetry.js +0 -1
  26. package/dist/utils/providerUtils.js +0 -1
  27. package/package.json +2 -2
  28. package/dist/client/adapters/providerImageAdapter.js +0 -588
  29. package/dist/client/adapters/tts/googleTTSHandler.js +0 -344
  30. package/dist/client/adapters/video/directorPipeline.js +0 -516
  31. package/dist/client/adapters/video/ffmpegAdapter.js +0 -206
  32. package/dist/client/adapters/video/frameExtractor.js +0 -143
  33. package/dist/client/adapters/video/vertexVideoHandler.js +0 -763
  34. package/dist/client/adapters/video/videoAnalyzer.js +0 -238
  35. package/dist/client/adapters/video/videoMerger.js +0 -171
  36. package/dist/client/agent/directTools.js +0 -840
  37. package/dist/client/auth/AuthProviderFactory.js +0 -111
  38. package/dist/client/auth/AuthProviderRegistry.js +0 -190
  39. package/dist/client/auth/RequestContext.js +0 -78
  40. package/dist/client/auth/accountPool.js +0 -178
  41. package/dist/client/auth/anthropicOAuth.js +0 -974
  42. package/dist/client/auth/authContext.js +0 -314
  43. package/dist/client/auth/errors.js +0 -39
  44. package/dist/client/auth/index.js +0 -61
  45. package/dist/client/auth/middleware/AuthMiddleware.js +0 -519
  46. package/dist/client/auth/middleware/rateLimitByUser.js +0 -554
  47. package/dist/client/auth/providers/BaseAuthProvider.js +0 -723
  48. package/dist/client/auth/providers/CognitoProvider.js +0 -304
  49. package/dist/client/auth/providers/KeycloakProvider.js +0 -393
  50. package/dist/client/auth/providers/auth0.js +0 -274
  51. package/dist/client/auth/providers/betterAuth.js +0 -182
  52. package/dist/client/auth/providers/clerk.js +0 -317
  53. package/dist/client/auth/providers/custom.js +0 -112
  54. package/dist/client/auth/providers/firebase.js +0 -226
  55. package/dist/client/auth/providers/jwt.js +0 -212
  56. package/dist/client/auth/providers/oauth2.js +0 -303
  57. package/dist/client/auth/providers/supabase.js +0 -259
  58. package/dist/client/auth/providers/workos.js +0 -284
  59. package/dist/client/auth/serverBridge.js +0 -25
  60. package/dist/client/auth/sessionManager.js +0 -437
  61. package/dist/client/auth/tokenStore.js +0 -799
  62. package/dist/client/client/aiSdkAdapter.js +0 -487
  63. package/dist/client/client/auth.js +0 -473
  64. package/dist/client/client/errors.js +0 -552
  65. package/dist/client/client/httpClient.js +0 -837
  66. package/dist/client/client/index.js +0 -172
  67. package/dist/client/client/interceptors.js +0 -601
  68. package/dist/client/client/sseClient.js +0 -545
  69. package/dist/client/client/streamingClient.js +0 -917
  70. package/dist/client/client/wsClient.js +0 -369
  71. package/dist/client/config/configManager.js +0 -303
  72. package/dist/client/config/conversationMemory.js +0 -86
  73. package/dist/client/config/taskClassificationConfig.js +0 -148
  74. package/dist/client/constants/contextWindows.js +0 -295
  75. package/dist/client/constants/enums.js +0 -853
  76. package/dist/client/constants/index.js +0 -207
  77. package/dist/client/constants/performance.js +0 -389
  78. package/dist/client/constants/retry.js +0 -266
  79. package/dist/client/constants/timeouts.js +0 -182
  80. package/dist/client/constants/tokens.js +0 -380
  81. package/dist/client/constants/videoErrors.js +0 -46
  82. package/dist/client/context/budgetChecker.js +0 -98
  83. package/dist/client/context/contextCompactor.js +0 -205
  84. package/dist/client/context/emergencyTruncation.js +0 -88
  85. package/dist/client/context/errorDetection.js +0 -171
  86. package/dist/client/context/errors.js +0 -21
  87. package/dist/client/context/fileTokenBudget.js +0 -127
  88. package/dist/client/context/prompts/summarizationPrompt.js +0 -117
  89. package/dist/client/context/stages/fileReadDeduplicator.js +0 -66
  90. package/dist/client/context/stages/slidingWindowTruncator.js +0 -190
  91. package/dist/client/context/stages/structuredSummarizer.js +0 -99
  92. package/dist/client/context/stages/toolOutputPruner.js +0 -52
  93. package/dist/client/context/summarizationEngine.js +0 -136
  94. package/dist/client/context/toolOutputLimits.js +0 -78
  95. package/dist/client/context/toolPairRepair.js +0 -66
  96. package/dist/client/core/analytics.js +0 -88
  97. package/dist/client/core/baseProvider.js +0 -1385
  98. package/dist/client/core/constants.js +0 -140
  99. package/dist/client/core/conversationMemoryFactory.js +0 -141
  100. package/dist/client/core/conversationMemoryInitializer.js +0 -128
  101. package/dist/client/core/conversationMemoryManager.js +0 -344
  102. package/dist/client/core/dynamicModels.js +0 -358
  103. package/dist/client/core/evaluation.js +0 -309
  104. package/dist/client/core/evaluationProviders.js +0 -248
  105. package/dist/client/core/factory.js +0 -412
  106. package/dist/client/core/infrastructure/baseError.js +0 -22
  107. package/dist/client/core/infrastructure/baseFactory.js +0 -54
  108. package/dist/client/core/infrastructure/baseRegistry.js +0 -53
  109. package/dist/client/core/infrastructure/index.js +0 -5
  110. package/dist/client/core/infrastructure/retry.js +0 -20
  111. package/dist/client/core/infrastructure/typedEventEmitter.js +0 -23
  112. package/dist/client/core/modelConfiguration.js +0 -851
  113. package/dist/client/core/modules/GenerationHandler.js +0 -588
  114. package/dist/client/core/modules/MessageBuilder.js +0 -273
  115. package/dist/client/core/modules/StreamHandler.js +0 -185
  116. package/dist/client/core/modules/TelemetryHandler.js +0 -203
  117. package/dist/client/core/modules/ToolsManager.js +0 -499
  118. package/dist/client/core/modules/Utilities.js +0 -331
  119. package/dist/client/core/redisConversationMemoryManager.js +0 -1435
  120. package/dist/client/core/streamAnalytics.js +0 -131
  121. package/dist/client/evaluation/contextBuilder.js +0 -134
  122. package/dist/client/evaluation/index.js +0 -61
  123. package/dist/client/evaluation/prompts.js +0 -73
  124. package/dist/client/evaluation/ragasEvaluator.js +0 -110
  125. package/dist/client/evaluation/retryManager.js +0 -78
  126. package/dist/client/evaluation/scoring.js +0 -61
  127. package/dist/client/factories/providerFactory.js +0 -166
  128. package/dist/client/factories/providerRegistry.js +0 -166
  129. package/dist/client/features/ppt/constants.js +0 -896
  130. package/dist/client/features/ppt/contentPlanner.js +0 -529
  131. package/dist/client/features/ppt/presentationOrchestrator.js +0 -236
  132. package/dist/client/features/ppt/slideGenerator.js +0 -532
  133. package/dist/client/features/ppt/slideRenderers.js +0 -2383
  134. package/dist/client/features/ppt/slideTypeInference.js +0 -405
  135. package/dist/client/features/ppt/types.js +0 -13
  136. package/dist/client/features/ppt/utils.js +0 -443
  137. package/dist/client/files/fileReferenceRegistry.js +0 -1543
  138. package/dist/client/files/fileTools.js +0 -450
  139. package/dist/client/files/streamingReader.js +0 -321
  140. package/dist/client/files/types.js +0 -23
  141. package/dist/client/hitl/hitlErrors.js +0 -54
  142. package/dist/client/hitl/hitlManager.js +0 -460
  143. package/dist/client/mcp/agentExposure.js +0 -356
  144. package/dist/client/mcp/auth/index.js +0 -11
  145. package/dist/client/mcp/auth/oauthClientProvider.js +0 -325
  146. package/dist/client/mcp/auth/tokenStorage.js +0 -134
  147. package/dist/client/mcp/batching/index.js +0 -10
  148. package/dist/client/mcp/batching/requestBatcher.js +0 -441
  149. package/dist/client/mcp/caching/index.js +0 -10
  150. package/dist/client/mcp/caching/toolCache.js +0 -433
  151. package/dist/client/mcp/elicitation/elicitationManager.js +0 -376
  152. package/dist/client/mcp/elicitation/index.js +0 -11
  153. package/dist/client/mcp/elicitation/types.js +0 -10
  154. package/dist/client/mcp/elicitationProtocol.js +0 -375
  155. package/dist/client/mcp/enhancedToolDiscovery.js +0 -481
  156. package/dist/client/mcp/externalServerManager.js +0 -1478
  157. package/dist/client/mcp/factory.js +0 -161
  158. package/dist/client/mcp/flexibleToolValidator.js +0 -161
  159. package/dist/client/mcp/httpRateLimiter.js +0 -391
  160. package/dist/client/mcp/httpRetryHandler.js +0 -178
  161. package/dist/client/mcp/index.js +0 -74
  162. package/dist/client/mcp/mcpCircuitBreaker.js +0 -427
  163. package/dist/client/mcp/mcpClientFactory.js +0 -708
  164. package/dist/client/mcp/mcpRegistryClient.js +0 -488
  165. package/dist/client/mcp/mcpServerBase.js +0 -373
  166. package/dist/client/mcp/multiServerManager.js +0 -579
  167. package/dist/client/mcp/registry.js +0 -158
  168. package/dist/client/mcp/routing/index.js +0 -10
  169. package/dist/client/mcp/routing/toolRouter.js +0 -416
  170. package/dist/client/mcp/serverCapabilities.js +0 -502
  171. package/dist/client/mcp/servers/agent/directToolsServer.js +0 -150
  172. package/dist/client/mcp/toolAnnotations.js +0 -239
  173. package/dist/client/mcp/toolConverter.js +0 -258
  174. package/dist/client/mcp/toolDiscoveryService.js +0 -798
  175. package/dist/client/mcp/toolIntegration.js +0 -334
  176. package/dist/client/mcp/toolRegistry.js +0 -729
  177. package/dist/client/memory/hippocampusInitializer.js +0 -19
  178. package/dist/client/memory/memoryRetrievalTools.js +0 -166
  179. package/dist/client/middleware/builtin/analytics.js +0 -132
  180. package/dist/client/middleware/builtin/autoEvaluation.js +0 -203
  181. package/dist/client/middleware/builtin/guardrails.js +0 -109
  182. package/dist/client/middleware/builtin/lifecycle.js +0 -168
  183. package/dist/client/middleware/factory.js +0 -327
  184. package/dist/client/middleware/registry.js +0 -295
  185. package/dist/client/middleware/utils/guardrailsUtils.js +0 -396
  186. package/dist/client/models/anthropicModels.js +0 -527
  187. package/dist/client/neurolink.js +0 -8233
  188. package/dist/client/observability/exporterRegistry.js +0 -413
  189. package/dist/client/observability/exporters/arizeExporter.js +0 -138
  190. package/dist/client/observability/exporters/baseExporter.js +0 -190
  191. package/dist/client/observability/exporters/braintrustExporter.js +0 -154
  192. package/dist/client/observability/exporters/datadogExporter.js +0 -196
  193. package/dist/client/observability/exporters/laminarExporter.js +0 -302
  194. package/dist/client/observability/exporters/langfuseExporter.js +0 -209
  195. package/dist/client/observability/exporters/langsmithExporter.js +0 -143
  196. package/dist/client/observability/exporters/otelExporter.js +0 -164
  197. package/dist/client/observability/exporters/posthogExporter.js +0 -287
  198. package/dist/client/observability/exporters/sentryExporter.js +0 -165
  199. package/dist/client/observability/index.js +0 -31
  200. package/dist/client/observability/metricsAggregator.js +0 -556
  201. package/dist/client/observability/otelBridge.js +0 -131
  202. package/dist/client/observability/retryPolicy.js +0 -383
  203. package/dist/client/observability/sampling/samplers.js +0 -216
  204. package/dist/client/observability/spanProcessor.js +0 -303
  205. package/dist/client/observability/tokenTracker.js +0 -413
  206. package/dist/client/observability/types/exporterTypes.js +0 -5
  207. package/dist/client/observability/types/index.js +0 -4
  208. package/dist/client/observability/types/spanTypes.js +0 -92
  209. package/dist/client/observability/utils/safeMetadata.js +0 -25
  210. package/dist/client/observability/utils/spanSerializer.js +0 -292
  211. package/dist/client/processors/archive/ArchiveProcessor.js +0 -1308
  212. package/dist/client/processors/base/BaseFileProcessor.js +0 -614
  213. package/dist/client/processors/base/types.js +0 -82
  214. package/dist/client/processors/config/fileTypes.js +0 -520
  215. package/dist/client/processors/config/index.js +0 -92
  216. package/dist/client/processors/config/languageMap.js +0 -410
  217. package/dist/client/processors/config/mimeTypes.js +0 -363
  218. package/dist/client/processors/config/sizeLimits.js +0 -258
  219. package/dist/client/processors/document/ExcelProcessor.js +0 -590
  220. package/dist/client/processors/document/OpenDocumentProcessor.js +0 -212
  221. package/dist/client/processors/document/PptxProcessor.js +0 -157
  222. package/dist/client/processors/document/RtfProcessor.js +0 -361
  223. package/dist/client/processors/document/WordProcessor.js +0 -353
  224. package/dist/client/processors/errors/FileErrorCode.js +0 -255
  225. package/dist/client/processors/errors/errorHelpers.js +0 -386
  226. package/dist/client/processors/errors/errorSerializer.js +0 -507
  227. package/dist/client/processors/errors/index.js +0 -49
  228. package/dist/client/processors/markup/SvgProcessor.js +0 -240
  229. package/dist/client/processors/media/AudioProcessor.js +0 -707
  230. package/dist/client/processors/media/VideoProcessor.js +0 -1045
  231. package/dist/client/providers/amazonBedrock.js +0 -1512
  232. package/dist/client/providers/amazonSagemaker.js +0 -162
  233. package/dist/client/providers/anthropic.js +0 -831
  234. package/dist/client/providers/azureOpenai.js +0 -143
  235. package/dist/client/providers/googleAiStudio.js +0 -1200
  236. package/dist/client/providers/googleNativeGemini3.js +0 -543
  237. package/dist/client/providers/googleVertex.js +0 -2936
  238. package/dist/client/providers/huggingFace.js +0 -315
  239. package/dist/client/providers/litellm.js +0 -488
  240. package/dist/client/providers/mistral.js +0 -157
  241. package/dist/client/providers/ollama.js +0 -1579
  242. package/dist/client/providers/openAI.js +0 -627
  243. package/dist/client/providers/openRouter.js +0 -543
  244. package/dist/client/providers/openaiCompatible.js +0 -290
  245. package/dist/client/providers/providerTypeUtils.js +0 -46
  246. package/dist/client/providers/sagemaker/adaptive-semaphore.js +0 -215
  247. package/dist/client/providers/sagemaker/client.js +0 -472
  248. package/dist/client/providers/sagemaker/config.js +0 -317
  249. package/dist/client/providers/sagemaker/detection.js +0 -606
  250. package/dist/client/providers/sagemaker/error-constants.js +0 -227
  251. package/dist/client/providers/sagemaker/errors.js +0 -299
  252. package/dist/client/providers/sagemaker/language-model.js +0 -775
  253. package/dist/client/providers/sagemaker/parsers.js +0 -634
  254. package/dist/client/providers/sagemaker/streaming.js +0 -331
  255. package/dist/client/providers/sagemaker/structured-parser.js +0 -625
  256. package/dist/client/proxy/accountQuota.js +0 -162
  257. package/dist/client/proxy/claudeFormat.js +0 -595
  258. package/dist/client/proxy/modelRouter.js +0 -29
  259. package/dist/client/proxy/oauthFetch.js +0 -367
  260. package/dist/client/proxy/proxyFetch.js +0 -586
  261. package/dist/client/proxy/requestLogger.js +0 -207
  262. package/dist/client/proxy/tokenRefresh.js +0 -124
  263. package/dist/client/proxy/usageStats.js +0 -74
  264. package/dist/client/proxy/utils/noProxyUtils.js +0 -149
  265. package/dist/client/rag/ChunkerFactory.js +0 -320
  266. package/dist/client/rag/ChunkerRegistry.js +0 -421
  267. package/dist/client/rag/chunkers/BaseChunker.js +0 -143
  268. package/dist/client/rag/chunkers/CharacterChunker.js +0 -28
  269. package/dist/client/rag/chunkers/HTMLChunker.js +0 -38
  270. package/dist/client/rag/chunkers/JSONChunker.js +0 -68
  271. package/dist/client/rag/chunkers/LaTeXChunker.js +0 -63
  272. package/dist/client/rag/chunkers/MarkdownChunker.js +0 -306
  273. package/dist/client/rag/chunkers/RecursiveChunker.js +0 -139
  274. package/dist/client/rag/chunkers/SemanticMarkdownChunker.js +0 -138
  275. package/dist/client/rag/chunkers/SentenceChunker.js +0 -66
  276. package/dist/client/rag/chunkers/TokenChunker.js +0 -61
  277. package/dist/client/rag/chunkers/index.js +0 -15
  278. package/dist/client/rag/chunking/characterChunker.js +0 -142
  279. package/dist/client/rag/chunking/chunkerRegistry.js +0 -194
  280. package/dist/client/rag/chunking/htmlChunker.js +0 -247
  281. package/dist/client/rag/chunking/index.js +0 -17
  282. package/dist/client/rag/chunking/jsonChunker.js +0 -281
  283. package/dist/client/rag/chunking/latexChunker.js +0 -251
  284. package/dist/client/rag/chunking/markdownChunker.js +0 -373
  285. package/dist/client/rag/chunking/recursiveChunker.js +0 -148
  286. package/dist/client/rag/chunking/semanticChunker.js +0 -306
  287. package/dist/client/rag/chunking/sentenceChunker.js +0 -230
  288. package/dist/client/rag/chunking/tokenChunker.js +0 -183
  289. package/dist/client/rag/document/MDocument.js +0 -392
  290. package/dist/client/rag/document/index.js +0 -5
  291. package/dist/client/rag/document/loaders.js +0 -500
  292. package/dist/client/rag/errors/RAGError.js +0 -274
  293. package/dist/client/rag/errors/index.js +0 -6
  294. package/dist/client/rag/graphRag/graphRAG.js +0 -401
  295. package/dist/client/rag/graphRag/index.js +0 -4
  296. package/dist/client/rag/index.js +0 -141
  297. package/dist/client/rag/metadata/MetadataExtractorFactory.js +0 -418
  298. package/dist/client/rag/metadata/MetadataExtractorRegistry.js +0 -362
  299. package/dist/client/rag/metadata/index.js +0 -9
  300. package/dist/client/rag/metadata/metadataExtractor.js +0 -280
  301. package/dist/client/rag/pipeline/RAGPipeline.js +0 -436
  302. package/dist/client/rag/pipeline/contextAssembly.js +0 -341
  303. package/dist/client/rag/pipeline/index.js +0 -5
  304. package/dist/client/rag/ragIntegration.js +0 -321
  305. package/dist/client/rag/reranker/RerankerFactory.js +0 -430
  306. package/dist/client/rag/reranker/RerankerRegistry.js +0 -402
  307. package/dist/client/rag/reranker/index.js +0 -9
  308. package/dist/client/rag/reranker/reranker.js +0 -277
  309. package/dist/client/rag/resilience/CircuitBreaker.js +0 -431
  310. package/dist/client/rag/resilience/RetryHandler.js +0 -304
  311. package/dist/client/rag/resilience/index.js +0 -7
  312. package/dist/client/rag/retrieval/hybridSearch.js +0 -335
  313. package/dist/client/rag/retrieval/index.js +0 -5
  314. package/dist/client/rag/retrieval/vectorQueryTool.js +0 -307
  315. package/dist/client/rag/types.js +0 -8
  316. package/dist/client/sdk/toolRegistration.js +0 -377
  317. package/dist/client/server/abstract/baseServerAdapter.js +0 -575
  318. package/dist/client/server/adapters/expressAdapter.js +0 -486
  319. package/dist/client/server/adapters/fastifyAdapter.js +0 -472
  320. package/dist/client/server/adapters/honoAdapter.js +0 -632
  321. package/dist/client/server/adapters/koaAdapter.js +0 -510
  322. package/dist/client/server/errors.js +0 -486
  323. package/dist/client/server/factory/serverAdapterFactory.js +0 -160
  324. package/dist/client/server/index.js +0 -108
  325. package/dist/client/server/middleware/abortSignal.js +0 -111
  326. package/dist/client/server/middleware/auth.js +0 -388
  327. package/dist/client/server/middleware/cache.js +0 -359
  328. package/dist/client/server/middleware/common.js +0 -281
  329. package/dist/client/server/middleware/deprecation.js +0 -190
  330. package/dist/client/server/middleware/mcpBodyAttachment.js +0 -63
  331. package/dist/client/server/middleware/rateLimit.js +0 -227
  332. package/dist/client/server/middleware/validation.js +0 -388
  333. package/dist/client/server/openapi/generator.js +0 -398
  334. package/dist/client/server/openapi/index.js +0 -36
  335. package/dist/client/server/openapi/schemas.js +0 -695
  336. package/dist/client/server/openapi/templates.js +0 -374
  337. package/dist/client/server/routes/agentRoutes.js +0 -189
  338. package/dist/client/server/routes/claudeProxyRoutes.js +0 -1600
  339. package/dist/client/server/routes/healthRoutes.js +0 -187
  340. package/dist/client/server/routes/index.js +0 -57
  341. package/dist/client/server/routes/mcpRoutes.js +0 -342
  342. package/dist/client/server/routes/memoryRoutes.js +0 -350
  343. package/dist/client/server/routes/openApiRoutes.js +0 -126
  344. package/dist/client/server/routes/toolRoutes.js +0 -199
  345. package/dist/client/server/streaming/dataStream.js +0 -486
  346. package/dist/client/server/streaming/index.js +0 -11
  347. package/dist/client/server/types.js +0 -67
  348. package/dist/client/server/utils/redaction.js +0 -334
  349. package/dist/client/server/utils/validation.js +0 -243
  350. package/dist/client/server/websocket/WebSocketHandler.js +0 -383
  351. package/dist/client/server/websocket/index.js +0 -4
  352. package/dist/client/services/server/ai/observability/instrumentation.js +0 -808
  353. package/dist/client/telemetry/attributes.js +0 -100
  354. package/dist/client/telemetry/index.js +0 -26
  355. package/dist/client/telemetry/telemetryService.js +0 -308
  356. package/dist/client/telemetry/tracers.js +0 -17
  357. package/dist/client/telemetry/withSpan.js +0 -34
  358. package/dist/client/types/actionTypes.js +0 -6
  359. package/dist/client/types/analytics.js +0 -5
  360. package/dist/client/types/authTypes.js +0 -9
  361. package/dist/client/types/circuitBreakerErrors.js +0 -34
  362. package/dist/client/types/cli.js +0 -21
  363. package/dist/client/types/clientTypes.js +0 -10
  364. package/dist/client/types/common.js +0 -51
  365. package/dist/client/types/configTypes.js +0 -49
  366. package/dist/client/types/content.js +0 -19
  367. package/dist/client/types/contextTypes.js +0 -400
  368. package/dist/client/types/conversation.js +0 -47
  369. package/dist/client/types/conversationMemoryInterface.js +0 -6
  370. package/dist/client/types/domainTypes.js +0 -5
  371. package/dist/client/types/errors.js +0 -167
  372. package/dist/client/types/evaluation.js +0 -5
  373. package/dist/client/types/evaluationProviders.js +0 -5
  374. package/dist/client/types/evaluationTypes.js +0 -1
  375. package/dist/client/types/externalMcp.js +0 -6
  376. package/dist/client/types/fileReferenceTypes.js +0 -8
  377. package/dist/client/types/fileTypes.js +0 -4
  378. package/dist/client/types/generateTypes.js +0 -1
  379. package/dist/client/types/guardrails.js +0 -1
  380. package/dist/client/types/hitlTypes.js +0 -8
  381. package/dist/client/types/index.js +0 -57
  382. package/dist/client/types/mcpTypes.js +0 -5
  383. package/dist/client/types/middlewareTypes.js +0 -1
  384. package/dist/client/types/modelTypes.js +0 -30
  385. package/dist/client/types/multimodal.js +0 -135
  386. package/dist/client/types/observability.js +0 -6
  387. package/dist/client/types/pptTypes.js +0 -82
  388. package/dist/client/types/providers.js +0 -111
  389. package/dist/client/types/proxyTypes.js +0 -16
  390. package/dist/client/types/ragTypes.js +0 -7
  391. package/dist/client/types/sdkTypes.js +0 -8
  392. package/dist/client/types/serviceTypes.js +0 -5
  393. package/dist/client/types/streamTypes.js +0 -1
  394. package/dist/client/types/subscriptionTypes.js +0 -9
  395. package/dist/client/types/taskClassificationTypes.js +0 -5
  396. package/dist/client/types/tools.js +0 -24
  397. package/dist/client/types/ttsTypes.js +0 -57
  398. package/dist/client/types/typeAliases.js +0 -48
  399. package/dist/client/types/utilities.js +0 -4
  400. package/dist/client/types/workflowTypes.js +0 -30
  401. package/dist/client/utils/async/withTimeout.js +0 -98
  402. package/dist/client/utils/asyncMutex.js +0 -60
  403. package/dist/client/utils/conversationMemory.js +0 -431
  404. package/dist/client/utils/csvProcessor.js +0 -846
  405. package/dist/client/utils/errorHandling.js +0 -936
  406. package/dist/client/utils/evaluationUtils.js +0 -131
  407. package/dist/client/utils/factoryProcessing.js +0 -589
  408. package/dist/client/utils/fileDetector.js +0 -2161
  409. package/dist/client/utils/imageCache.js +0 -376
  410. package/dist/client/utils/imageProcessor.js +0 -704
  411. package/dist/client/utils/logger.js +0 -491
  412. package/dist/client/utils/mcpDefaults.js +0 -134
  413. package/dist/client/utils/messageBuilder.js +0 -1653
  414. package/dist/client/utils/modelAliasResolver.js +0 -54
  415. package/dist/client/utils/modelDetection.js +0 -80
  416. package/dist/client/utils/modelRouter.js +0 -292
  417. package/dist/client/utils/multimodalOptionsBuilder.js +0 -65
  418. package/dist/client/utils/observabilityHelpers.js +0 -47
  419. package/dist/client/utils/parameterValidation.js +0 -966
  420. package/dist/client/utils/pdfProcessor.js +0 -410
  421. package/dist/client/utils/performance.js +0 -222
  422. package/dist/client/utils/pricing.js +0 -340
  423. package/dist/client/utils/promptRedaction.js +0 -62
  424. package/dist/client/utils/providerConfig.js +0 -1009
  425. package/dist/client/utils/providerHealth.js +0 -1237
  426. package/dist/client/utils/providerRetry.js +0 -112
  427. package/dist/client/utils/providerUtils.js +0 -434
  428. package/dist/client/utils/rateLimiter.js +0 -200
  429. package/dist/client/utils/redis.js +0 -368
  430. package/dist/client/utils/retryHandler.js +0 -269
  431. package/dist/client/utils/retryability.js +0 -22
  432. package/dist/client/utils/sanitizers/svg.js +0 -481
  433. package/dist/client/utils/schemaConversion.js +0 -255
  434. package/dist/client/utils/taskClassificationUtils.js +0 -149
  435. package/dist/client/utils/taskClassifier.js +0 -94
  436. package/dist/client/utils/thinkingConfig.js +0 -104
  437. package/dist/client/utils/timeout.js +0 -359
  438. package/dist/client/utils/tokenEstimation.js +0 -142
  439. package/dist/client/utils/tokenLimits.js +0 -125
  440. package/dist/client/utils/tokenUtils.js +0 -239
  441. package/dist/client/utils/toolUtils.js +0 -75
  442. package/dist/client/utils/transformationUtils.js +0 -554
  443. package/dist/client/utils/ttsProcessor.js +0 -286
  444. package/dist/client/utils/typeUtils.js +0 -97
  445. package/dist/client/utils/videoAnalysisProcessor.js +0 -67
  446. package/dist/client/workflow/config.js +0 -398
  447. package/dist/client/workflow/core/ensembleExecutor.js +0 -407
  448. package/dist/client/workflow/core/judgeScorer.js +0 -544
  449. package/dist/client/workflow/core/responseConditioner.js +0 -225
  450. package/dist/client/workflow/core/types/conditionerTypes.js +0 -7
  451. package/dist/client/workflow/core/types/ensembleTypes.js +0 -7
  452. package/dist/client/workflow/core/types/index.js +0 -7
  453. package/dist/client/workflow/core/types/judgeTypes.js +0 -7
  454. package/dist/client/workflow/core/types/layerTypes.js +0 -7
  455. package/dist/client/workflow/core/types/registryTypes.js +0 -7
  456. package/dist/client/workflow/core/workflowRegistry.js +0 -304
  457. package/dist/client/workflow/core/workflowRunner.js +0 -586
  458. package/dist/client/workflow/index.js +0 -50
  459. package/dist/client/workflow/types.js +0 -9
  460. package/dist/client/workflow/utils/types/index.js +0 -7
  461. package/dist/client/workflow/utils/workflowMetrics.js +0 -311
  462. package/dist/client/workflow/utils/workflowValidation.js +0 -420
  463. package/dist/client/workflow/workflows/adaptiveWorkflow.js +0 -366
  464. package/dist/client/workflow/workflows/consensusWorkflow.js +0 -192
  465. package/dist/client/workflow/workflows/fallbackWorkflow.js +0 -225
  466. package/dist/client/workflow/workflows/multiJudgeWorkflow.js +0 -351
  467. /package/dist/client/{client/reactHooks.js → reactHooks.js} +0 -0
@@ -1,1512 +0,0 @@
1
- import { BedrockClient, ListFoundationModelsCommand, } from "@aws-sdk/client-bedrock";
2
- import { BedrockRuntimeClient, ConverseCommand, ConverseStreamCommand, ImageFormat, } from "@aws-sdk/client-bedrock-runtime";
3
- import path from "path";
4
- import { createAnalytics } from "../core/analytics.js";
5
- import { BaseProvider } from "../core/baseProvider.js";
6
- import { DEFAULT_MAX_STEPS } from "../core/constants.js";
7
- import { AuthenticationError, ProviderError } from "../types/errors.js";
8
- import { isAbortError, withTimeout } from "../utils/errorHandling.js";
9
- import { logger } from "../utils/logger.js";
10
- import { calculateCost } from "../utils/pricing.js";
11
- import { buildMultimodalMessagesArray } from "../utils/messageBuilder.js";
12
- import { buildMultimodalOptions } from "../utils/multimodalOptionsBuilder.js";
13
- import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
14
- import { trace, SpanKind, SpanStatusCode } from "@opentelemetry/api";
15
- const bedrockTracer = trace.getTracer("neurolink.bedrock");
16
- // Bedrock-specific types now imported from ../types/providerSpecific.js
17
- export class AmazonBedrockProvider extends BaseProvider {
18
- bedrockClient;
19
- conversationHistory = [];
20
- region;
21
- constructor(modelName, neurolink, region) {
22
- super(modelName, "bedrock", neurolink);
23
- this.region = region || process.env.AWS_REGION || "us-east-1";
24
- logger.debug("[AmazonBedrockProvider] Starting constructor with extensive logging for debugging");
25
- // Log environment variables for debugging
26
- logger.debug(`[AmazonBedrockProvider] Environment check: AWS_REGION=${process.env.AWS_REGION || "undefined"}, AWS_ACCESS_KEY_ID=${process.env.AWS_ACCESS_KEY_ID ? "SET" : "undefined"}, AWS_SECRET_ACCESS_KEY=${process.env.AWS_SECRET_ACCESS_KEY ? "SET" : "undefined"}`);
27
- try {
28
- // Create BedrockRuntimeClient with clean configuration like working Bedrock-MCP-Connector
29
- // Absolutely no proxy interference - let AWS SDK handle everything natively
30
- logger.debug("[AmazonBedrockProvider] Creating BedrockRuntimeClient with clean configuration");
31
- this.bedrockClient = new BedrockRuntimeClient({
32
- region: this.region,
33
- // Clean configuration - AWS SDK will handle credentials via:
34
- // 1. IAM roles (preferred in production)
35
- // 2. Environment variables
36
- // 3. AWS config files
37
- // 4. Instance metadata
38
- });
39
- logger.debug(`[AmazonBedrockProvider] Successfully created BedrockRuntimeClient with model: ${this.modelName}, region: ${this.region}`);
40
- }
41
- catch (error) {
42
- logger.error(`[AmazonBedrockProvider] CRITICAL: Failed to initialize BedrockRuntimeClient:`, error);
43
- throw error;
44
- }
45
- }
46
- /**
47
- * Perform initial health check to catch credential/connectivity issues early
48
- * This prevents the health check failure we saw in production logs
49
- */
50
- async performInitialHealthCheck() {
51
- const bedrockClient = new BedrockClient({
52
- region: this.region,
53
- });
54
- try {
55
- logger.debug("[AmazonBedrockProvider] Starting initial health check to validate credentials and connectivity");
56
- // Try to list foundation models as a lightweight health check
57
- const command = new ListFoundationModelsCommand({});
58
- const startTime = Date.now();
59
- await bedrockClient.send(command);
60
- const responseTime = Date.now() - startTime;
61
- logger.debug(`[AmazonBedrockProvider] Health check PASSED - credentials valid, connectivity good, responseTime: ${responseTime}ms`);
62
- }
63
- catch (error) {
64
- const errorMessage = error instanceof Error ? error.message : String(error);
65
- logger.error(`[AmazonBedrockProvider] Health check FAILED - this will cause production failures:`, {
66
- error: errorMessage,
67
- errorType: error instanceof Error ? error.constructor.name : "Unknown",
68
- region: process.env.AWS_REGION || "us-east-1",
69
- hasAccessKey: !!process.env.AWS_ACCESS_KEY_ID,
70
- hasSecretKey: !!process.env.AWS_SECRET_ACCESS_KEY,
71
- });
72
- // Don't throw here - let the actual usage fail with better context
73
- }
74
- finally {
75
- try {
76
- bedrockClient.destroy();
77
- }
78
- catch {
79
- // Ignore destroy errors during cleanup
80
- }
81
- }
82
- }
83
- // Not using AI SDK approach in conversation management
84
- getAISDKModel() {
85
- throw new Error("AmazonBedrockProvider does not use AI SDK models");
86
- }
87
- getProviderName() {
88
- return "bedrock";
89
- }
90
- getDefaultModel() {
91
- return process.env.BEDROCK_MODEL || "anthropic.claude-sonnet-4-6";
92
- }
93
- /**
94
- * Get the default embedding model for Amazon Bedrock
95
- * @returns The default Bedrock embedding model name
96
- */
97
- getDefaultEmbeddingModel() {
98
- return (process.env.BEDROCK_EMBEDDING_MODEL ||
99
- process.env.AWS_EMBEDDING_MODEL ||
100
- "amazon.titan-embed-text-v2:0");
101
- }
102
- // Override the main generate method to implement conversation management
103
- async generate(optionsOrPrompt) {
104
- logger.debug("[AmazonBedrockProvider] generate() called with conversation management");
105
- const options = typeof optionsOrPrompt === "string"
106
- ? { prompt: optionsOrPrompt }
107
- : optionsOrPrompt;
108
- // Clear conversation history for new generation
109
- this.conversationHistory = [];
110
- // Check for multimodal input (images, PDFs, CSVs, files)
111
- // Cast to any to access multimodal properties (runtime check is safe)
112
- const input = options.input;
113
- const hasMultimodalInput = !!(input?.images?.length ||
114
- input?.content?.length ||
115
- input?.files?.length ||
116
- input?.csvFiles?.length ||
117
- input?.pdfFiles?.length);
118
- if (hasMultimodalInput) {
119
- logger.debug(`[AmazonBedrockProvider] Detected multimodal input in generate(), using multimodal message builder`, {
120
- hasImages: !!input?.images?.length,
121
- imageCount: input?.images?.length || 0,
122
- hasContent: !!input?.content?.length,
123
- contentCount: input?.content?.length || 0,
124
- hasFiles: !!input?.files?.length,
125
- fileCount: input?.files?.length || 0,
126
- hasCSVFiles: !!input?.csvFiles?.length,
127
- csvFileCount: input?.csvFiles?.length || 0,
128
- hasPDFFiles: !!input?.pdfFiles?.length,
129
- pdfFileCount: input?.pdfFiles?.length || 0,
130
- });
131
- // Cast options to StreamOptions for multimodal processing
132
- const streamOptions = options;
133
- const multimodalOptions = buildMultimodalOptions(streamOptions, this.providerName, this.modelName);
134
- const multimodalMessages = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
135
- // Convert to Bedrock format
136
- this.conversationHistory =
137
- this.convertToBedrockMessages(multimodalMessages);
138
- }
139
- else {
140
- logger.debug(`[AmazonBedrockProvider] Text-only input in generate(), using simple message builder`);
141
- // Add user message to conversation - simple text-only case
142
- const userMessage = {
143
- role: "user",
144
- content: [{ text: options.prompt }],
145
- };
146
- this.conversationHistory.push(userMessage);
147
- }
148
- logger.debug(`[AmazonBedrockProvider] Starting conversation with ${this.conversationHistory.length} message(s)`);
149
- // Start conversation loop and return enhanced result
150
- const text = await this.conversationLoop(options);
151
- return {
152
- content: text, // CLI expects 'content' not 'text'
153
- usage: { total: 0, input: 0, output: 0 },
154
- model: this.modelName || this.getDefaultModel(),
155
- provider: this.getProviderName(),
156
- };
157
- }
158
- async conversationLoop(options) {
159
- const maxIterations = 10; // Prevent infinite loops
160
- let iteration = 0;
161
- while (iteration < maxIterations) {
162
- iteration++;
163
- logger.debug(`[AmazonBedrockProvider] Conversation iteration ${iteration}`);
164
- try {
165
- logger.debug(`[AmazonBedrockProvider] About to call Bedrock API`);
166
- const response = await this.callBedrock(options);
167
- logger.debug(`[AmazonBedrockProvider] Received Bedrock response`, JSON.stringify(response, null, 2));
168
- const result = await this.handleBedrockResponse(response);
169
- logger.debug(`[AmazonBedrockProvider] Handle response result:`, result);
170
- if (result.shouldContinue) {
171
- logger.debug(`[AmazonBedrockProvider] Continuing conversation loop...`);
172
- }
173
- else {
174
- logger.debug(`[AmazonBedrockProvider] Conversation completed with final text`);
175
- logger.debug(`[AmazonBedrockProvider] Returning final text: "${result.text}"`);
176
- return result.text || "";
177
- }
178
- }
179
- catch (error) {
180
- logger.error(`[AmazonBedrockProvider] Error in conversation loop:`, error);
181
- throw this.handleProviderError(error);
182
- }
183
- }
184
- throw new Error("Conversation loop exceeded maximum iterations");
185
- }
186
- async callBedrock(options) {
187
- const startTime = Date.now();
188
- return bedrockTracer.startActiveSpan("bedrock.generate", {
189
- kind: SpanKind.CLIENT,
190
- attributes: {
191
- "gen_ai.system": "aws.bedrock",
192
- "gen_ai.request.model": this.modelName || this.getDefaultModel(),
193
- "gen_ai.operation.name": "chat",
194
- },
195
- }, async (generateSpan) => {
196
- logger.info(`🚀 [AmazonBedrockProvider] Starting Bedrock API call at ${new Date().toISOString()}`);
197
- try {
198
- // Pre-call validation and logging
199
- let region = "unknown";
200
- try {
201
- region =
202
- typeof this.bedrockClient.config.region === "function"
203
- ? await this.bedrockClient.config.region()
204
- : (this.bedrockClient.config.region ?? "unknown");
205
- }
206
- catch {
207
- // Region lookup failed — not critical, only used for logging
208
- }
209
- logger.info(`🔧 [AmazonBedrockProvider] Client region: ${region}`);
210
- logger.info(`🔧 [AmazonBedrockProvider] Model: ${this.modelName || this.getDefaultModel()}`);
211
- logger.info(`🔧 [AmazonBedrockProvider] Conversation history length: ${this.conversationHistory.length}`);
212
- // Get all available tools
213
- const aiTools = await this.getAllTools();
214
- const allTools = this.convertAISDKToolsToToolDefinitions(aiTools);
215
- const toolConfig = this.formatToolsForBedrock(allTools);
216
- const commandInput = {
217
- modelId: this.modelName || this.getDefaultModel(),
218
- messages: this.convertToAWSMessages(this.conversationHistory),
219
- system: [
220
- {
221
- text: options.systemPrompt ||
222
- "You are a helpful assistant with access to external tools. Use tools when necessary to provide accurate information.",
223
- },
224
- ],
225
- inferenceConfig: {
226
- maxTokens: options.maxTokens, // No default limit - unlimited unless specified
227
- temperature: options.temperature || 0.7,
228
- },
229
- };
230
- if (toolConfig) {
231
- commandInput.toolConfig = toolConfig;
232
- logger.info(`🛠️ [AmazonBedrockProvider] Tools configured: ${toolConfig.tools?.length || 0}`);
233
- }
234
- // Log command details for debugging
235
- logger.info(`📋 [AmazonBedrockProvider] Command input summary:`);
236
- logger.info(` - Model ID: ${commandInput.modelId}`);
237
- logger.info(` - Messages count: ${commandInput.messages?.length || 0}`);
238
- logger.info(` - System prompts: ${commandInput.system?.length || 0}`);
239
- logger.info(` - Max tokens: ${commandInput.inferenceConfig?.maxTokens}`);
240
- logger.info(` - Temperature: ${commandInput.inferenceConfig?.temperature}`);
241
- logger.debug(`[AmazonBedrockProvider] Calling Bedrock with ${this.conversationHistory.length} messages and ${toolConfig?.tools?.length || 0} tools`);
242
- // Create command and attempt API call
243
- const command = new ConverseCommand(commandInput);
244
- logger.debug("[Observability] Bedrock API request", {
245
- model: commandInput.modelId,
246
- region: region,
247
- messageCount: commandInput.messages?.length || 0,
248
- toolCount: commandInput.toolConfig?.tools?.length || 0,
249
- maxTokens: commandInput.inferenceConfig?.maxTokens,
250
- });
251
- const apiCallStartTime = Date.now();
252
- const response = await withTimeout(this.bedrockClient.send(command), 120_000, new Error("Bedrock API call timed out"));
253
- const apiCallDuration = Date.now() - apiCallStartTime;
254
- logger.debug("[Observability] Bedrock API response", {
255
- model: commandInput.modelId,
256
- durationMs: apiCallDuration,
257
- hasContent: !!response.output?.message?.content?.length,
258
- stopReason: response.stopReason,
259
- usage: response.usage
260
- ? {
261
- inputTokens: response.usage.inputTokens,
262
- outputTokens: response.usage.outputTokens,
263
- totalTokens: (response.usage.inputTokens || 0) +
264
- (response.usage.outputTokens || 0),
265
- }
266
- : undefined,
267
- });
268
- logger.info(`[AmazonBedrockProvider] Bedrock API call successful`);
269
- logger.info(`[AmazonBedrockProvider] API call duration: ${apiCallDuration}ms`);
270
- const totalDuration = Date.now() - startTime;
271
- logger.info(`[AmazonBedrockProvider] Total callBedrock duration: ${totalDuration}ms`);
272
- generateSpan.setAttribute("gen_ai.response.stop_reason", response.stopReason ?? "");
273
- generateSpan.setAttribute("gen_ai.usage.input_tokens", response.usage?.inputTokens ?? 0);
274
- generateSpan.setAttribute("gen_ai.usage.output_tokens", response.usage?.outputTokens ?? 0);
275
- const cost = calculateCost(this.providerName, this.modelName, {
276
- input: response.usage?.inputTokens ?? 0,
277
- output: response.usage?.outputTokens ?? 0,
278
- total: (response.usage?.inputTokens ?? 0) +
279
- (response.usage?.outputTokens ?? 0),
280
- });
281
- if (cost && cost > 0) {
282
- generateSpan.setAttribute("neurolink.cost", cost);
283
- }
284
- generateSpan.setStatus({ code: SpanStatusCode.OK });
285
- generateSpan.end();
286
- return response;
287
- }
288
- catch (error) {
289
- const errorDuration = Date.now() - startTime;
290
- // Extract AWS metadata for structured logging
291
- const awsError = error && typeof error === "object"
292
- ? error
293
- : null;
294
- const metadata = awsError?.$metadata && typeof awsError.$metadata === "object"
295
- ? awsError.$metadata
296
- : null;
297
- logger.debug("[Observability] Bedrock API request failed", {
298
- model: this.modelName || this.getDefaultModel(),
299
- durationMs: errorDuration,
300
- error: error instanceof Error ? error.message : String(error),
301
- errorName: error instanceof Error ? error.name : undefined,
302
- httpStatus: metadata?.httpStatusCode,
303
- awsRequestId: metadata?.requestId,
304
- awsErrorCode: awsError?.Code,
305
- });
306
- logger.error(`[AmazonBedrockProvider] Bedrock API call failed after ${errorDuration}ms`);
307
- if (error instanceof Error) {
308
- logger.error(`[AmazonBedrockProvider] Error: ${error.name} - ${error.message}`);
309
- }
310
- if (metadata) {
311
- logger.error(`[AmazonBedrockProvider] AWS SDK metadata`, {
312
- httpStatus: metadata.httpStatusCode,
313
- requestId: metadata.requestId,
314
- attempts: metadata.attempts,
315
- totalRetryDelay: metadata.totalRetryDelay,
316
- });
317
- }
318
- generateSpan.setStatus({
319
- code: SpanStatusCode.ERROR,
320
- message: error instanceof Error ? error.message : String(error),
321
- });
322
- generateSpan.recordException(error instanceof Error ? error : new Error(String(error)));
323
- generateSpan.end();
324
- throw error;
325
- }
326
- }); // end bedrockTracer.startActiveSpan('bedrock.generate')
327
- }
328
- async handleBedrockResponse(response) {
329
- logger.debug(`[AmazonBedrockProvider] Received response with stopReason: ${response.stopReason}`);
330
- if (!response.output || !response.output.message) {
331
- throw new Error("Invalid response structure from Bedrock API");
332
- }
333
- const assistantMessage = response.output.message;
334
- const stopReason = response.stopReason;
335
- // Add assistant message to conversation history
336
- const bedrockAssistantMessage = {
337
- role: "assistant",
338
- content: (assistantMessage.content || []).map((item) => {
339
- const bedrockItem = {};
340
- if ("text" in item && item.text) {
341
- bedrockItem.text = item.text;
342
- }
343
- if ("toolUse" in item && item.toolUse) {
344
- bedrockItem.toolUse = {
345
- toolUseId: item.toolUse.toolUseId || "",
346
- name: item.toolUse.name || "",
347
- input: item.toolUse.input || {},
348
- };
349
- }
350
- if ("toolResult" in item && item.toolResult) {
351
- bedrockItem.toolResult = {
352
- toolUseId: item.toolResult.toolUseId || "",
353
- content: (item.toolResult.content || []).map((c) => ({
354
- text: typeof c === "object" && "text" in c
355
- ? c.text || ""
356
- : "",
357
- })),
358
- status: item.toolResult.status || "unknown",
359
- };
360
- }
361
- return bedrockItem;
362
- }),
363
- };
364
- this.conversationHistory.push(bedrockAssistantMessage);
365
- if (stopReason === "end_turn" || stopReason === "stop_sequence") {
366
- // Extract text from assistant message
367
- const textContent = bedrockAssistantMessage.content
368
- .filter((item) => item.text)
369
- .map((item) => item.text)
370
- .join(" ");
371
- return { shouldContinue: false, text: textContent };
372
- }
373
- else if (stopReason === "tool_use") {
374
- logger.debug(`[AmazonBedrockProvider] Tool use detected - executing tools immediately`);
375
- // Execute all tool uses in the message
376
- const toolResults = [];
377
- for (const contentItem of bedrockAssistantMessage.content) {
378
- if (contentItem.toolUse) {
379
- logger.debug(`[AmazonBedrockProvider] Executing tool: ${contentItem.toolUse.name}`);
380
- try {
381
- // Execute tool using BaseProvider's tool execution
382
- logger.debug(`[AmazonBedrockProvider] Debug toolUse.input:`, JSON.stringify(contentItem.toolUse.input, null, 2));
383
- const toolResult = await this.executeSingleTool(contentItem.toolUse.name, contentItem.toolUse.input || {}, contentItem.toolUse.toolUseId);
384
- logger.debug(`[AmazonBedrockProvider] Tool execution successful: ${contentItem.toolUse.name}`);
385
- toolResults.push({
386
- toolResult: {
387
- toolUseId: contentItem.toolUse.toolUseId,
388
- content: [{ text: String(toolResult) }],
389
- status: "success",
390
- },
391
- });
392
- }
393
- catch (error) {
394
- logger.error(`[AmazonBedrockProvider] Tool execution failed: ${contentItem.toolUse.name}`, error);
395
- const errorMessage = error instanceof Error ? error.message : String(error);
396
- // Still create toolResult for failed tools to maintain 1:1 mapping with toolUse blocks
397
- toolResults.push({
398
- toolResult: {
399
- toolUseId: contentItem.toolUse.toolUseId,
400
- content: [
401
- {
402
- text: `Error executing tool ${contentItem.toolUse.name}: ${errorMessage}`,
403
- },
404
- ],
405
- status: "error",
406
- },
407
- });
408
- }
409
- }
410
- }
411
- // Add tool results as user message
412
- if (toolResults.length > 0) {
413
- const userMessageWithToolResults = {
414
- role: "user",
415
- content: toolResults,
416
- };
417
- this.conversationHistory.push(userMessageWithToolResults);
418
- logger.debug(`[AmazonBedrockProvider] Added ${toolResults.length} tool results to conversation`);
419
- }
420
- return { shouldContinue: true };
421
- }
422
- else if (stopReason === "max_tokens") {
423
- // Max tokens reached — return what we have rather than continuing,
424
- // since the model hit the configured limit.
425
- const textContent = bedrockAssistantMessage.content
426
- .filter((item) => item.text)
427
- .map((item) => item.text)
428
- .join(" ");
429
- return { shouldContinue: false, text: textContent };
430
- }
431
- else {
432
- logger.warn(`[AmazonBedrockProvider] Unrecognized stop reason "${stopReason}", ending conversation.`);
433
- return { shouldContinue: false, text: "" };
434
- }
435
- }
436
- convertToAWSMessages(bedrockMessages) {
437
- return bedrockMessages.map((msg) => ({
438
- role: msg.role,
439
- content: msg.content.map((item) => {
440
- if (item.text) {
441
- return {
442
- text: item.text,
443
- };
444
- }
445
- if (item.image) {
446
- return {
447
- image: item.image,
448
- };
449
- }
450
- if (item.document) {
451
- return {
452
- document: item.document,
453
- };
454
- }
455
- if (item.toolUse) {
456
- return {
457
- toolUse: {
458
- toolUseId: item.toolUse.toolUseId,
459
- name: item.toolUse.name,
460
- input: item.toolUse.input,
461
- },
462
- };
463
- }
464
- if (item.toolResult) {
465
- return {
466
- toolResult: {
467
- toolUseId: item.toolResult.toolUseId,
468
- content: item.toolResult.content,
469
- status: item.toolResult.status,
470
- },
471
- };
472
- }
473
- return { text: "" };
474
- }),
475
- }));
476
- }
477
- async executeSingleTool(toolName, args, _toolUseId) {
478
- return bedrockTracer.startActiveSpan("bedrock.tool.execute", {
479
- kind: SpanKind.CLIENT,
480
- attributes: {
481
- "gen_ai.tool.name": toolName,
482
- "gen_ai.system": "aws.bedrock",
483
- },
484
- }, async (span) => {
485
- try {
486
- logger.debug(`[AmazonBedrockProvider] Executing single tool: ${toolName}`, {
487
- args,
488
- });
489
- // Use BaseProvider's tool execution mechanism
490
- const aiTools = await this.getAllTools();
491
- const tools = this.convertAISDKToolsToToolDefinitions(aiTools);
492
- if (!tools[toolName]) {
493
- throw new Error(`Tool not found: ${toolName}`);
494
- }
495
- const tool = tools[toolName];
496
- if (!tool || !tool.execute) {
497
- throw new Error(`Tool ${toolName} does not have execute method`);
498
- }
499
- // Apply robust parameter handling like Bedrock-MCP-Connector
500
- // Bedrock toolUse.input already contains the correct parameter structure
501
- const toolInput = args || {};
502
- // Add default parameters for common tools that Claude might call without required params
503
- if (toolName === "list_directory" && !toolInput.path) {
504
- toolInput.path = ".";
505
- logger.debug(`[AmazonBedrockProvider] Added default path '.' for list_directory tool`);
506
- }
507
- logger.debug(`[AmazonBedrockProvider] Tool input parameters:`, toolInput);
508
- // Convert Record<string, unknown> to ToolArgs by filtering out non-JsonValue types
509
- const toolArgs = {};
510
- for (const [key, value] of Object.entries(toolInput)) {
511
- // Only include values that are JsonValue compatible
512
- if (value === null ||
513
- typeof value === "string" ||
514
- typeof value === "number" ||
515
- typeof value === "boolean" ||
516
- (typeof value === "object" && value !== null)) {
517
- toolArgs[key] = value;
518
- }
519
- }
520
- const result = await tool.execute(toolArgs);
521
- logger.debug(`[AmazonBedrockProvider] Tool execution result:`, {
522
- toolName,
523
- result,
524
- });
525
- // Handle ToolResult type
526
- let finalResult;
527
- if (result && typeof result === "object" && "success" in result) {
528
- if (result.success && result.data !== undefined) {
529
- if (typeof result.data === "string") {
530
- finalResult = result.data;
531
- }
532
- else if (typeof result.data === "object") {
533
- finalResult = JSON.stringify(result.data, null, 2);
534
- }
535
- else {
536
- finalResult = String(result.data);
537
- }
538
- }
539
- else if (result.error) {
540
- const errorMessage = typeof result.error === "string"
541
- ? result.error
542
- : result.error.message || "Tool execution failed";
543
- throw new Error(errorMessage);
544
- }
545
- else {
546
- finalResult = "";
547
- }
548
- }
549
- else if (typeof result === "string") {
550
- // Fallback for non-ToolResult return types
551
- finalResult = result;
552
- }
553
- else if (typeof result === "object") {
554
- finalResult = JSON.stringify(result, null, 2);
555
- }
556
- else {
557
- finalResult = String(result);
558
- }
559
- span.setStatus({ code: SpanStatusCode.OK });
560
- return finalResult;
561
- }
562
- catch (error) {
563
- logger.error(`[AmazonBedrockProvider] Tool execution error:`, {
564
- toolName,
565
- error,
566
- });
567
- span.setStatus({
568
- code: SpanStatusCode.ERROR,
569
- message: error.message,
570
- });
571
- span.recordException(error);
572
- throw error;
573
- }
574
- finally {
575
- span.end();
576
- }
577
- });
578
- }
579
- convertAISDKToolsToToolDefinitions(aiTools) {
580
- const result = {};
581
- for (const [name, tool] of Object.entries(aiTools)) {
582
- if ("description" in tool && tool.description) {
583
- // Extract schema from legacy `parameters` (AI SDK v3/v4) or current `inputSchema` (v6)
584
- const legacyTool = tool;
585
- const extractedParams = legacyTool.parameters ??
586
- tool.inputSchema;
587
- result[name] = {
588
- description: tool.description,
589
- parameters: extractedParams,
590
- execute: async (params) => {
591
- if ("execute" in tool && tool.execute) {
592
- const result = await tool.execute(params, {
593
- toolCallId: `tool_${Date.now()}`,
594
- messages: [],
595
- });
596
- return {
597
- success: true,
598
- data: result,
599
- };
600
- }
601
- throw new Error(`Tool ${name} has no execute method`);
602
- },
603
- };
604
- }
605
- }
606
- return result;
607
- }
608
- formatToolsForBedrock(tools) {
609
- if (!tools || Object.keys(tools).length === 0) {
610
- return null;
611
- }
612
- const bedrockTools = Object.entries(tools).map(([name, tool]) => {
613
- // Handle Zod schema or plain object schema
614
- let schema;
615
- if (tool.parameters && typeof tool.parameters === "object") {
616
- // Check if it's a Zod schema
617
- if ("_def" in tool.parameters) {
618
- // It's a Zod schema, convert to JSON schema
619
- schema = convertZodToJsonSchema(tool.parameters);
620
- }
621
- else {
622
- // It's already a plain object schema
623
- schema = tool.parameters;
624
- }
625
- }
626
- else {
627
- schema = {
628
- type: "object",
629
- properties: {},
630
- required: [],
631
- };
632
- }
633
- // Ensure the schema always has type: "object" at the root level
634
- if (!schema.type || schema.type !== "object") {
635
- schema = {
636
- type: "object",
637
- properties: schema.properties || {},
638
- required: schema.required || [],
639
- };
640
- }
641
- const toolSpec = {
642
- name,
643
- description: tool.description,
644
- inputSchema: {
645
- json: schema,
646
- },
647
- };
648
- return {
649
- toolSpec,
650
- };
651
- });
652
- logger.debug(`[AmazonBedrockProvider] Formatted ${bedrockTools.length} tools for Bedrock`);
653
- return { tools: bedrockTools };
654
- }
655
- // Convert multimodal messages to Bedrock format
656
- convertToBedrockMessages(messages) {
657
- return messages.map((msg) => {
658
- const bedrockMessage = {
659
- role: msg.role === "system" ? "user" : msg.role,
660
- content: [],
661
- };
662
- if (typeof msg.content === "string") {
663
- bedrockMessage.content.push({ text: msg.content });
664
- }
665
- else {
666
- msg.content.forEach((contentItem) => {
667
- if (contentItem.type === "text" && contentItem.text) {
668
- bedrockMessage.content.push({ text: contentItem.text });
669
- }
670
- else if (contentItem.type === "image" && contentItem.image) {
671
- const imageData = typeof contentItem.image === "string"
672
- ? Buffer.from(contentItem.image.replace(/^data:image\/\w+;base64,/, ""), "base64")
673
- : contentItem.image;
674
- let format = contentItem.mimeType?.split("/")[1] || "png";
675
- if (format === "jpg") {
676
- format = "jpeg";
677
- }
678
- bedrockMessage.content.push({
679
- image: {
680
- format: format === "jpeg"
681
- ? ImageFormat.JPEG
682
- : format === "png"
683
- ? ImageFormat.PNG
684
- : format === "gif"
685
- ? ImageFormat.GIF
686
- : ImageFormat.WEBP,
687
- source: {
688
- bytes: imageData,
689
- },
690
- },
691
- });
692
- }
693
- else if (contentItem.type === "document" ||
694
- contentItem.type === "pdf" ||
695
- (contentItem.type === "file" &&
696
- contentItem.mimeType?.toLowerCase().startsWith("application/pdf"))) {
697
- let docData;
698
- if (typeof contentItem.data === "string") {
699
- const pdfString = contentItem.data.replace(/^data:application\/pdf;base64,/i, "");
700
- docData = Buffer.from(pdfString, "base64");
701
- }
702
- else {
703
- docData = contentItem.data;
704
- }
705
- // Extract basename and sanitize for Bedrock's filename requirements
706
- // Bedrock only allows: alphanumeric, whitespace, hyphens, parentheses, brackets
707
- // NOTE: Periods (.) are NOT allowed, so we remove the extension
708
- let filename = typeof contentItem.name === "string" && contentItem.name
709
- ? path.basename(contentItem.name)
710
- : "document-pdf";
711
- // Remove file extension
712
- filename = filename.replace(/\.[^.]+$/, "");
713
- // Replace all disallowed characters with hyphens
714
- // Bedrock constraint: only alphanumeric, whitespace, hyphens, parentheses, brackets allowed
715
- filename = filename.replace(/[^a-zA-Z0-9\s\-()[\]]/g, "-");
716
- // Clean up: remove multiple consecutive hyphens and trim
717
- filename = filename
718
- .replace(/-+/g, "-")
719
- .trim()
720
- .replace(/^-+|-+$/g, "");
721
- // Fallback if filename becomes empty after sanitization
722
- filename = filename || "document";
723
- bedrockMessage.content.push({
724
- document: {
725
- format: "pdf",
726
- name: filename,
727
- source: {
728
- bytes: docData,
729
- },
730
- },
731
- });
732
- }
733
- });
734
- }
735
- return bedrockMessage;
736
- });
737
- }
738
- // Bedrock-MCP-Connector compatibility
739
- getBedrockClient() {
740
- return this.bedrockClient;
741
- }
742
- async executeStream(options) {
743
- logger.debug("🟢 [TRACE] executeStream ENTRY - starting streaming attempt");
744
- logger.info("🚀 [AmazonBedrockProvider] Attempting real streaming with ConverseStreamCommand");
745
- return bedrockTracer.startActiveSpan("bedrock.stream", {
746
- kind: SpanKind.CLIENT,
747
- attributes: {
748
- "gen_ai.system": "aws.bedrock",
749
- "gen_ai.request.model": this.modelName || this.getDefaultModel(),
750
- "gen_ai.operation.name": "stream",
751
- },
752
- }, async (streamSpan) => {
753
- try {
754
- logger.debug("🟢 [TRACE] executeStream TRY block - about to call streamingConversationLoop");
755
- // Clear conversation history for new streaming session
756
- this.conversationHistory = [];
757
- // Check for multimodal input (images, PDFs, CSVs, files)
758
- const hasMultimodalInput = !!(options.input?.images?.length ||
759
- options.input?.content?.length ||
760
- options.input?.files?.length ||
761
- options.input?.csvFiles?.length ||
762
- options.input?.pdfFiles?.length);
763
- if (hasMultimodalInput) {
764
- logger.debug(`[AmazonBedrockProvider] Detected multimodal input, using multimodal message builder`, {
765
- hasImages: !!options.input?.images?.length,
766
- imageCount: options.input?.images?.length || 0,
767
- hasContent: !!options.input?.content?.length,
768
- contentCount: options.input?.content?.length || 0,
769
- hasFiles: !!options.input?.files?.length,
770
- fileCount: options.input?.files?.length || 0,
771
- hasCSVFiles: !!options.input?.csvFiles?.length,
772
- csvFileCount: options.input?.csvFiles?.length || 0,
773
- hasPDFFiles: !!options.input?.pdfFiles?.length,
774
- pdfFileCount: options.input?.pdfFiles?.length || 0,
775
- });
776
- const multimodalOptions = buildMultimodalOptions(options, this.providerName, this.modelName);
777
- const multimodalMessages = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
778
- // Convert to Bedrock format
779
- this.conversationHistory =
780
- this.convertToBedrockMessages(multimodalMessages);
781
- }
782
- else {
783
- logger.debug(`[AmazonBedrockProvider] Text-only input, using simple message builder`);
784
- // Add user message to conversation - simple text-only case
785
- const userMessage = {
786
- role: "user",
787
- content: [{ text: options.input.text }],
788
- };
789
- this.conversationHistory.push(userMessage);
790
- }
791
- logger.debug(`[AmazonBedrockProvider] Starting streaming conversation with ${this.conversationHistory.length} message(s)`);
792
- // Call the actual streaming implementation that already exists
793
- logger.debug("🟢 [TRACE] executeStream - calling streamingConversationLoop NOW");
794
- const result = await this.streamingConversationLoop(options, streamSpan);
795
- logger.debug("🟢 [TRACE] executeStream - streamingConversationLoop SUCCESS, returning result");
796
- streamSpan.setStatus({ code: SpanStatusCode.OK });
797
- streamSpan.end();
798
- return result;
799
- }
800
- catch (error) {
801
- logger.debug("🔴 [TRACE] executeStream CATCH - error caught from streamingConversationLoop");
802
- const errorObj = error;
803
- // Check if error is related to streaming permissions
804
- const isPermissionError = errorObj?.name ===
805
- "AccessDeniedException" ||
806
- errorObj?.name ===
807
- "UnauthorizedOperation" ||
808
- errorObj?.message?.includes("bedrock:InvokeModelWithResponseStream") ||
809
- errorObj?.message?.includes("streaming") ||
810
- errorObj?.message?.includes("ConverseStream");
811
- logger.debug("🔴 [TRACE] executeStream CATCH - checking if permission error");
812
- logger.debug(`🔴 [TRACE] executeStream CATCH - isPermissionError=${isPermissionError}`);
813
- if (isPermissionError) {
814
- logger.debug("🟡 [TRACE] executeStream CATCH - PERMISSION ERROR DETECTED, starting fallback");
815
- logger.warn(`[AmazonBedrockProvider] Streaming permissions not available, falling back to generate method: ${errorObj.message}`);
816
- streamSpan.addEvent("stream.fallback_to_generate", {
817
- reason: errorObj.message,
818
- });
819
- // Fallback to generate method and convert to streaming format
820
- const generateResult = await this.generate({
821
- prompt: options.input.text,
822
- input: options.input,
823
- maxTokens: options.maxTokens,
824
- temperature: options.temperature,
825
- systemPrompt: options.systemPrompt,
826
- });
827
- if (!generateResult) {
828
- streamSpan.setStatus({
829
- code: SpanStatusCode.ERROR,
830
- message: "Generate method returned null result",
831
- });
832
- streamSpan.end();
833
- // eslint-disable-next-line preserve-caught-error
834
- throw new Error("Generate method returned null result");
835
- }
836
- streamSpan.setAttribute("gen_ai.response.stop_reason", "fallback_end_turn");
837
- streamSpan.setStatus({ code: SpanStatusCode.OK });
838
- streamSpan.end();
839
- // Convert generate result to streaming format
840
- const stream = new ReadableStream({
841
- start(controller) {
842
- // Split the response into chunks for pseudo-streaming
843
- const responseText = generateResult.content || "";
844
- const chunks = responseText.split(" ");
845
- chunks.forEach((word, _index) => {
846
- controller.enqueue({ content: word + " " });
847
- });
848
- controller.enqueue({ content: "" });
849
- controller.close();
850
- },
851
- });
852
- // Convert ReadableStream to AsyncIterable like streamingConversationLoop does
853
- const asyncIterable = {
854
- async *[Symbol.asyncIterator]() {
855
- const reader = stream.getReader();
856
- try {
857
- while (true) {
858
- const { done, value } = await reader.read();
859
- if (done) {
860
- break;
861
- }
862
- yield value;
863
- }
864
- }
865
- finally {
866
- reader.releaseLock();
867
- }
868
- },
869
- };
870
- return {
871
- stream: asyncIterable,
872
- usage: { total: 0, input: 0, output: 0 },
873
- model: this.modelName || this.getDefaultModel(),
874
- provider: this.getProviderName(),
875
- metadata: {
876
- fallback: true,
877
- },
878
- };
879
- }
880
- // Re-throw non-permission errors
881
- streamSpan.setStatus({
882
- code: SpanStatusCode.ERROR,
883
- message: errorObj instanceof Error ? errorObj.message : String(errorObj),
884
- });
885
- streamSpan.recordException(errorObj instanceof Error ? errorObj : new Error(String(errorObj)));
886
- streamSpan.end();
887
- throw error;
888
- }
889
- });
890
- }
891
- async streamingConversationLoop(options, streamSpan) {
892
- logger.debug("🟦 [TRACE] streamingConversationLoop ENTRY");
893
- const startTime = Date.now();
894
- const maxIterations = options.maxSteps || DEFAULT_MAX_STEPS;
895
- let iteration = 0;
896
- // The REAL issue: ReadableStream errors don't bubble up to the caller
897
- // So we need to make the first streaming call synchronously to test permissions
898
- try {
899
- logger.debug("🟦 [TRACE] streamingConversationLoop - testing first streaming call");
900
- const commandInput = await this.prepareStreamCommand(options);
901
- const command = new ConverseStreamCommand(commandInput);
902
- logger.debug("[Observability] Bedrock streaming API request", {
903
- model: commandInput.modelId,
904
- messageCount: commandInput.messages?.length || 0,
905
- toolCount: commandInput.toolConfig?.tools?.length || 0,
906
- });
907
- streamSpan.addEvent("stream.api_call", {
908
- "bedrock.message_count": commandInput.messages?.length || 0,
909
- "bedrock.tool_count": commandInput.toolConfig?.tools?.length || 0,
910
- });
911
- const streamStartTime = Date.now();
912
- const response = await withTimeout(this.bedrockClient.send(command), 120_000, new Error("Bedrock streaming API call timed out"));
913
- logger.debug("[Observability] Bedrock streaming API connection established", {
914
- model: commandInput.modelId,
915
- durationMs: Date.now() - streamStartTime,
916
- hasStream: !!response.stream,
917
- });
918
- // Process the first response immediately to avoid waste
919
- const stream = new ReadableStream({
920
- start: async (controller) => {
921
- logger.debug("🟦 [TRACE] streamingConversationLoop - ReadableStream start() called");
922
- try {
923
- // Process the first response we already have, tracking all event types
924
- let firstStopReason = "";
925
- if (response.stream) {
926
- const firstMessageContent = [];
927
- let firstText = "";
928
- for await (const chunk of response.stream) {
929
- if (chunk.contentBlockStart) {
930
- firstMessageContent.push({});
931
- }
932
- if (chunk.contentBlockDelta?.delta?.text) {
933
- const textDelta = chunk.contentBlockDelta.delta.text;
934
- firstText += textDelta;
935
- controller.enqueue({ content: textDelta });
936
- }
937
- if (chunk.contentBlockStart?.start?.toolUse) {
938
- const currentBlock = firstMessageContent[firstMessageContent.length - 1];
939
- currentBlock.toolUse = {
940
- name: chunk.contentBlockStart.start.toolUse.name || "",
941
- input: {},
942
- toolUseId: chunk.contentBlockStart.start.toolUse.toolUseId ||
943
- `tool_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
944
- };
945
- }
946
- if (chunk.contentBlockDelta?.delta?.toolUse) {
947
- const currentBlock = firstMessageContent[firstMessageContent.length - 1];
948
- if (!currentBlock.toolUse) {
949
- currentBlock.toolUse = {
950
- name: "",
951
- input: {},
952
- toolUseId: `tool_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
953
- };
954
- }
955
- const deltaInput = chunk.contentBlockDelta.delta.toolUse.input;
956
- if (!deltaInput) {
957
- // no input delta
958
- }
959
- else if (typeof deltaInput === "string") {
960
- currentBlock._inputBuffer =
961
- (currentBlock._inputBuffer || "") + deltaInput;
962
- }
963
- else if (typeof deltaInput === "object" &&
964
- !Array.isArray(deltaInput)) {
965
- const currentInput = currentBlock.toolUse.input || {};
966
- currentBlock.toolUse.input = {
967
- ...currentInput,
968
- ...deltaInput,
969
- };
970
- }
971
- }
972
- if (chunk.contentBlockStop) {
973
- const currentBlock = firstMessageContent[firstMessageContent.length - 1];
974
- if (currentBlock?.toolUse && currentBlock._inputBuffer) {
975
- try {
976
- currentBlock.toolUse.input = JSON.parse(currentBlock._inputBuffer);
977
- }
978
- catch {
979
- currentBlock.toolUse.input = {};
980
- }
981
- delete currentBlock._inputBuffer;
982
- }
983
- if (firstText && currentBlock && !currentBlock.toolUse) {
984
- currentBlock.text = firstText;
985
- }
986
- firstText = "";
987
- }
988
- if (chunk.messageStop) {
989
- firstStopReason = chunk.messageStop.stopReason || "end_turn";
990
- break;
991
- }
992
- }
993
- // Add first assistant message to conversation history
994
- const firstAssistantMessage = {
995
- role: "assistant",
996
- content: firstMessageContent,
997
- };
998
- this.conversationHistory.push(firstAssistantMessage);
999
- streamSpan.addEvent("stream.turn_complete", {
1000
- iteration: 0,
1001
- stop_reason: firstStopReason,
1002
- });
1003
- if (firstStopReason === "tool_use") {
1004
- const toolNames = firstMessageContent
1005
- .filter((b) => b.toolUse?.name)
1006
- .map((b) => b.toolUse.name)
1007
- .join(", ");
1008
- streamSpan.addEvent("stream.tool_use", {
1009
- iteration: 0,
1010
- tool_names: toolNames,
1011
- });
1012
- }
1013
- // Handle the stop reason from the first response
1014
- const shouldContinue = await this.handleStreamStopReason(firstStopReason, firstAssistantMessage, controller, options);
1015
- if (!shouldContinue) {
1016
- streamSpan.setAttribute("gen_ai.response.stop_reason", firstStopReason);
1017
- return;
1018
- }
1019
- }
1020
- // Continue with normal iterations if needed
1021
- while (iteration < maxIterations) {
1022
- iteration++;
1023
- logger.debug(`[AmazonBedrockProvider] Streaming iteration ${iteration}`);
1024
- const commandInput = await this.prepareStreamCommand(options);
1025
- const { stopReason, assistantMessage } = await this.processStreamResponse(commandInput, controller);
1026
- streamSpan.addEvent("stream.turn_complete", {
1027
- iteration,
1028
- stop_reason: stopReason,
1029
- });
1030
- if (stopReason === "tool_use") {
1031
- const toolNames = assistantMessage.content
1032
- .filter((b) => b.toolUse?.name)
1033
- .map((b) => b.toolUse.name)
1034
- .join(", ");
1035
- streamSpan.addEvent("stream.tool_use", {
1036
- iteration,
1037
- tool_names: toolNames,
1038
- });
1039
- }
1040
- const shouldContinue = await this.handleStreamStopReason(stopReason, assistantMessage, controller, options);
1041
- if (!shouldContinue) {
1042
- streamSpan.setAttribute("gen_ai.response.stop_reason", stopReason);
1043
- break;
1044
- }
1045
- }
1046
- if (iteration >= maxIterations) {
1047
- streamSpan.setAttribute("gen_ai.response.stop_reason", "max_iterations");
1048
- controller.error(new Error("Streaming conversation exceeded maximum iterations"));
1049
- }
1050
- }
1051
- catch (error) {
1052
- logger.debug("🔴 [TRACE] streamingConversationLoop - CATCH block hit in ReadableStream");
1053
- controller.error(error);
1054
- }
1055
- },
1056
- });
1057
- // Create analytics promise (without token tracking for now due to AWS SDK limitations)
1058
- const analyticsPromise = Promise.resolve(createAnalytics(this.providerName, this.modelName || this.getDefaultModel(), { usage: { input: 0, output: 0, total: 0 } }, Date.now() - startTime, {
1059
- requestId: `bedrock-stream-${Date.now()}`,
1060
- streamingMode: true,
1061
- note: "Token usage not available from AWS SDK streaming responses",
1062
- }));
1063
- return {
1064
- stream: this.convertToAsyncIterable(stream),
1065
- usage: { total: 0, input: 0, output: 0 },
1066
- model: this.modelName || this.getDefaultModel(),
1067
- provider: this.getProviderName(),
1068
- analytics: analyticsPromise,
1069
- metadata: {
1070
- startTime,
1071
- streamId: `bedrock-${Date.now()}`,
1072
- },
1073
- };
1074
- }
1075
- catch (error) {
1076
- logger.debug("🔴 [TRACE] streamingConversationLoop - first streaming call FAILED, throwing");
1077
- throw error; // This will be caught by executeStream
1078
- }
1079
- }
1080
- convertToAsyncIterable(stream) {
1081
- return {
1082
- async *[Symbol.asyncIterator]() {
1083
- const reader = stream.getReader();
1084
- try {
1085
- while (true) {
1086
- const { done, value } = await reader.read();
1087
- if (done) {
1088
- break;
1089
- }
1090
- yield value;
1091
- }
1092
- }
1093
- finally {
1094
- reader.releaseLock();
1095
- }
1096
- },
1097
- };
1098
- }
1099
- async prepareStreamCommand(options) {
1100
- // CRITICAL DEBUG: Log conversation history before conversion
1101
- if (logger.shouldLog("debug")) {
1102
- logger.debug(`[AmazonBedrockProvider] BEFORE conversion - conversationHistory length: ${this.conversationHistory.length}`);
1103
- this.conversationHistory.forEach((msg, index) => {
1104
- logger.debug(`[AmazonBedrockProvider] Message ${index}: role=${msg.role}, content=${JSON.stringify(msg.content)}`);
1105
- });
1106
- }
1107
- // Get all available tools
1108
- // BaseProvider.stream() pre-merges base tools + external tools into options.tools
1109
- const aiTools = options.tools ||
1110
- (await this.getAllTools());
1111
- const allTools = this.convertAISDKToolsToToolDefinitions(aiTools);
1112
- const toolConfig = this.formatToolsForBedrock(allTools);
1113
- const convertedMessages = this.convertToAWSMessages(this.conversationHistory);
1114
- if (logger.shouldLog("debug")) {
1115
- logger.debug(`[AmazonBedrockProvider] AFTER conversion - messages length: ${convertedMessages.length}`);
1116
- convertedMessages.forEach((msg, index) => {
1117
- logger.debug(`[AmazonBedrockProvider] Converted Message ${index}: role=${msg.role}, content=${JSON.stringify(msg.content)}`);
1118
- });
1119
- }
1120
- const commandInput = {
1121
- modelId: this.modelName || this.getDefaultModel(),
1122
- messages: convertedMessages,
1123
- system: [
1124
- {
1125
- text: options.systemPrompt ||
1126
- "You are a helpful assistant with access to external tools. Use tools when necessary to provide accurate information.",
1127
- },
1128
- ],
1129
- inferenceConfig: {
1130
- maxTokens: options.maxTokens, // No default limit - unlimited unless specified
1131
- temperature: options.temperature || 0.7,
1132
- },
1133
- };
1134
- if (toolConfig) {
1135
- commandInput.toolConfig = toolConfig;
1136
- }
1137
- logger.debug(`[AmazonBedrockProvider] Calling Bedrock streaming with ${this.conversationHistory.length} messages`);
1138
- // DEBUG: Log exact conversation structure being sent to Bedrock
1139
- logger.debug(`[AmazonBedrockProvider] DEBUG - Conversation structure:`);
1140
- this.conversationHistory.forEach((msg, index) => {
1141
- logger.debug(` Message ${index} (${msg.role}): ${msg.content.length} content items`);
1142
- msg.content.forEach((item, itemIndex) => {
1143
- const keys = Object.keys(item);
1144
- logger.debug(` Content ${itemIndex}: ${keys.join(", ")}`);
1145
- });
1146
- });
1147
- return commandInput;
1148
- }
1149
- async processStreamResponse(commandInput, controller) {
1150
- const command = new ConverseStreamCommand(commandInput);
1151
- logger.debug("[Observability] Bedrock streaming API request (continuation)", {
1152
- model: commandInput.modelId,
1153
- messageCount: commandInput.messages?.length || 0,
1154
- });
1155
- const iterationStartTime = Date.now();
1156
- const response = await withTimeout(this.bedrockClient.send(command), 120_000, new Error("Bedrock streaming API call timed out"));
1157
- logger.debug("[Observability] Bedrock streaming API connection established (continuation)", {
1158
- model: commandInput.modelId,
1159
- durationMs: Date.now() - iterationStartTime,
1160
- });
1161
- if (!response.stream) {
1162
- throw new Error("No stream returned from Bedrock");
1163
- }
1164
- const currentMessageContent = [];
1165
- let stopReason = "";
1166
- let currentText = "";
1167
- // Process streaming chunks
1168
- for await (const chunk of response.stream) {
1169
- if (chunk.contentBlockStart) {
1170
- // Starting a new content block
1171
- currentMessageContent.push({});
1172
- }
1173
- if (chunk.contentBlockDelta?.delta?.text) {
1174
- // Text delta - stream it to user
1175
- const textDelta = chunk.contentBlockDelta.delta.text;
1176
- currentText += textDelta;
1177
- controller.enqueue({
1178
- content: textDelta,
1179
- });
1180
- }
1181
- if (chunk.contentBlockStart?.start?.toolUse) {
1182
- // Tool use block starting - initialize tool information
1183
- const currentBlock = currentMessageContent[currentMessageContent.length - 1];
1184
- currentBlock.toolUse = {
1185
- name: chunk.contentBlockStart.start.toolUse.name || "",
1186
- input: {}, // Initialize empty - will be populated by delta chunks
1187
- toolUseId: chunk.contentBlockStart.start.toolUse.toolUseId ||
1188
- `tool_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
1189
- };
1190
- }
1191
- if (chunk.contentBlockDelta?.delta?.toolUse) {
1192
- // Tool use delta - accumulate tool information
1193
- const currentBlock = currentMessageContent[currentMessageContent.length - 1];
1194
- if (!currentBlock.toolUse) {
1195
- currentBlock.toolUse = {
1196
- name: "",
1197
- input: {},
1198
- toolUseId: `tool_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`,
1199
- };
1200
- }
1201
- // Accumulate JSON string fragments into _inputBuffer.
1202
- // Bedrock sends toolUse.input as incremental JSON string fragments,
1203
- // not pre-parsed objects. We buffer them and parse at contentBlockStop.
1204
- if (chunk.contentBlockDelta.delta.toolUse.input) {
1205
- const deltaInput = chunk.contentBlockDelta.delta.toolUse.input;
1206
- if (typeof deltaInput === "string") {
1207
- currentBlock._inputBuffer =
1208
- (currentBlock._inputBuffer || "") + deltaInput;
1209
- }
1210
- else if (deltaInput &&
1211
- typeof deltaInput === "object" &&
1212
- !Array.isArray(deltaInput)) {
1213
- // Some SDK versions may deliver pre-parsed objects; merge directly
1214
- const currentInput = currentBlock.toolUse.input || {};
1215
- currentBlock.toolUse.input = {
1216
- ...currentInput,
1217
- ...deltaInput,
1218
- };
1219
- }
1220
- }
1221
- }
1222
- if (chunk.contentBlockStop) {
1223
- // Content block completed
1224
- const currentBlock = currentMessageContent[currentMessageContent.length - 1];
1225
- // Parse accumulated JSON input buffer for tool-use blocks
1226
- if (currentBlock?.toolUse && currentBlock._inputBuffer) {
1227
- try {
1228
- currentBlock.toolUse.input = JSON.parse(currentBlock._inputBuffer);
1229
- }
1230
- catch {
1231
- currentBlock.toolUse.input = {};
1232
- }
1233
- delete currentBlock._inputBuffer;
1234
- }
1235
- if (currentText && currentBlock && !currentBlock.toolUse) {
1236
- // Only add text to blocks that don't have toolUse
1237
- currentBlock.text = currentText;
1238
- }
1239
- currentText = "";
1240
- }
1241
- if (chunk.messageStop) {
1242
- stopReason = chunk.messageStop.stopReason || "end_turn";
1243
- break;
1244
- }
1245
- }
1246
- // Add assistant message to conversation history
1247
- const assistantMessage = {
1248
- role: "assistant",
1249
- content: currentMessageContent,
1250
- };
1251
- this.conversationHistory.push(assistantMessage);
1252
- return { stopReason, assistantMessage };
1253
- }
1254
- async handleStreamStopReason(stopReason, assistantMessage, controller, options) {
1255
- if (stopReason === "end_turn" || stopReason === "stop_sequence") {
1256
- // Conversation completed
1257
- controller.close();
1258
- return false;
1259
- }
1260
- else if (stopReason === "tool_use") {
1261
- logger.debug(`🛠️ [AmazonBedrockProvider] Tool use detected in streaming - executing tools`);
1262
- await this.executeStreamTools(assistantMessage.content, options);
1263
- return true; // Continue conversation loop
1264
- }
1265
- else if (stopReason === "max_tokens") {
1266
- // Max tokens reached — close the stream rather than continuing,
1267
- // since the model hit the configured limit.
1268
- controller.close();
1269
- return false;
1270
- }
1271
- else {
1272
- // Unknown stop reason - end conversation
1273
- controller.close();
1274
- return false;
1275
- }
1276
- }
1277
- async executeStreamTools(messageContent, options) {
1278
- // Execute all tool uses in the message - ensure 1:1 mapping like Bedrock-MCP-Connector
1279
- const toolResults = [];
1280
- let toolUseCount = 0;
1281
- // Track tool calls and results for storage (similar to Vertex onStepFinish)
1282
- const toolCalls = [];
1283
- const toolResultsForStorage = [];
1284
- // Count toolUse blocks first to ensure 1:1 mapping
1285
- for (const contentItem of messageContent) {
1286
- if (contentItem.toolUse) {
1287
- toolUseCount++;
1288
- }
1289
- }
1290
- logger.debug(`🔍 [AmazonBedrockProvider] Found ${toolUseCount} toolUse blocks in assistant message`);
1291
- for (const contentItem of messageContent) {
1292
- if (contentItem.toolUse) {
1293
- logger.debug(`🔧 [AmazonBedrockProvider] Executing tool: ${contentItem.toolUse.name}`);
1294
- // Track tool call
1295
- toolCalls.push({
1296
- type: "tool-call",
1297
- toolCallId: contentItem.toolUse.toolUseId,
1298
- toolName: contentItem.toolUse.name,
1299
- args: contentItem.toolUse.input || {},
1300
- });
1301
- try {
1302
- const toolResult = await this.executeSingleTool(contentItem.toolUse.name, contentItem.toolUse.input || {}, contentItem.toolUse.toolUseId);
1303
- logger.debug(`✅ [AmazonBedrockProvider] Tool execution successful: ${contentItem.toolUse.name}`);
1304
- // Track tool result for storage
1305
- toolResultsForStorage.push({
1306
- type: "tool-result",
1307
- toolCallId: contentItem.toolUse.toolUseId,
1308
- toolName: contentItem.toolUse.name,
1309
- result: toolResult,
1310
- });
1311
- // Ensure exact structure matching Bedrock-MCP-Connector
1312
- toolResults.push({
1313
- toolResult: {
1314
- toolUseId: contentItem.toolUse.toolUseId,
1315
- content: [{ text: String(toolResult) }],
1316
- status: "success",
1317
- },
1318
- });
1319
- }
1320
- catch (error) {
1321
- logger.error(`❌ [AmazonBedrockProvider] Tool execution failed: ${contentItem.toolUse.name}`, error);
1322
- const errorMessage = error instanceof Error ? error.message : String(error);
1323
- // Track failed tool result
1324
- toolResultsForStorage.push({
1325
- type: "tool-result",
1326
- toolCallId: contentItem.toolUse.toolUseId,
1327
- toolName: contentItem.toolUse.name,
1328
- result: { error: errorMessage },
1329
- });
1330
- toolResults.push({
1331
- toolResult: {
1332
- toolUseId: contentItem.toolUse.toolUseId,
1333
- content: [
1334
- {
1335
- text: `Error executing tool ${contentItem.toolUse.name}: ${errorMessage}`,
1336
- },
1337
- ],
1338
- status: "error",
1339
- },
1340
- });
1341
- }
1342
- }
1343
- }
1344
- logger.debug(`📊 [AmazonBedrockProvider] Created ${toolResults.length} toolResult blocks for ${toolUseCount} toolUse blocks`);
1345
- // Validate 1:1 mapping before adding to conversation
1346
- if (toolResults.length !== toolUseCount) {
1347
- logger.error(`❌ [AmazonBedrockProvider] Mismatch: ${toolResults.length} toolResults vs ${toolUseCount} toolUse blocks`);
1348
- throw new Error(`Tool mapping mismatch: ${toolResults.length} toolResults for ${toolUseCount} toolUse blocks`);
1349
- }
1350
- // Add tool results as user message - exact structure like Bedrock-MCP-Connector
1351
- if (toolResults.length > 0) {
1352
- const userMessageWithToolResults = {
1353
- role: "user",
1354
- content: toolResults,
1355
- };
1356
- this.conversationHistory.push(userMessageWithToolResults);
1357
- logger.debug(`📤 [AmazonBedrockProvider] Added ${toolResults.length} tool results to conversation (1:1 mapping validated)`);
1358
- // Store tool execution for analytics and debugging (similar to Vertex onStepFinish)
1359
- this.handleToolExecutionStorage(toolCalls, toolResultsForStorage, options, new Date()).catch((error) => {
1360
- logger.warn("[AmazonBedrockProvider] Failed to store tool executions", {
1361
- provider: this.providerName,
1362
- error: error instanceof Error ? error.message : String(error),
1363
- });
1364
- });
1365
- }
1366
- }
1367
- /**
1368
- * Health check for Amazon Bedrock service
1369
- * Uses ListFoundationModels API to validate connectivity and permissions
1370
- */
1371
- async checkBedrockHealth() {
1372
- const controller = new AbortController();
1373
- const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
1374
- // Create a separate BedrockClient for health checks (not BedrockRuntimeClient)
1375
- // Use simple configuration like working example - no custom proxy handler
1376
- const healthCheckClient = new BedrockClient({
1377
- region: process.env.AWS_REGION || "us-east-1",
1378
- });
1379
- try {
1380
- logger.debug("🔍 [AmazonBedrockProvider] Starting health check...");
1381
- const command = new ListFoundationModelsCommand({});
1382
- const response = await healthCheckClient.send(command, {
1383
- abortSignal: controller.signal,
1384
- });
1385
- const models = response.modelSummaries || [];
1386
- const activeModels = models.filter((model) => model.modelLifecycle?.status === "ACTIVE");
1387
- logger.debug(`✅ [AmazonBedrockProvider] Health check passed - Found ${activeModels.length} active models out of ${models.length} total models`);
1388
- if (activeModels.length === 0) {
1389
- throw new Error("No active foundation models available in the region");
1390
- }
1391
- }
1392
- catch (error) {
1393
- clearTimeout(timeoutId);
1394
- const errorObj = error;
1395
- if (isAbortError(error)) {
1396
- throw new Error("Bedrock health check timed out after 10 seconds", {
1397
- cause: error,
1398
- });
1399
- }
1400
- const errorMessage = typeof errorObj.message === "string" ? errorObj.message : "";
1401
- if (errorMessage.includes("UnauthorizedOperation") ||
1402
- errorMessage.includes("AccessDenied")) {
1403
- throw new Error("Bedrock access denied. Check your AWS credentials and IAM permissions for bedrock:ListFoundationModels", { cause: error });
1404
- }
1405
- if (errorObj.code === "ECONNREFUSED" || errorObj.code === "ENOTFOUND") {
1406
- throw new Error("Unable to connect to Bedrock service. Check your network connectivity and AWS region configuration", { cause: error });
1407
- }
1408
- logger.error("❌ [AmazonBedrockProvider] Health check failed:", error);
1409
- throw new Error(`Bedrock health check failed: ${errorMessage || "Unknown error"}`, { cause: error });
1410
- }
1411
- finally {
1412
- clearTimeout(timeoutId);
1413
- try {
1414
- healthCheckClient.destroy();
1415
- }
1416
- catch {
1417
- // Ignore destroy errors during cleanup
1418
- }
1419
- }
1420
- }
1421
- formatProviderError(error) {
1422
- // Handle AWS SDK specific errors
1423
- const message = error instanceof Error ? error.message : String(error);
1424
- if (message.includes("AccessDeniedException")) {
1425
- return new AuthenticationError("AWS Bedrock access denied. Check your credentials and permissions.", this.providerName);
1426
- }
1427
- if (message.includes("ValidationException")) {
1428
- return new ProviderError(`Validation error: ${message}`, this.providerName);
1429
- }
1430
- return new ProviderError(`AWS Bedrock error: ${message}`, this.providerName);
1431
- }
1432
- /**
1433
- * Generate embeddings for text using Amazon Bedrock embedding models
1434
- * Uses the native AWS SDK InvokeModel command for Titan embeddings
1435
- * @param text - The text to embed
1436
- * @param modelName - The embedding model to use (default: amazon.titan-embed-text-v2:0)
1437
- * @returns Promise resolving to the embedding vector
1438
- */
1439
- async embed(text, modelName) {
1440
- const embeddingModelName = modelName || "amazon.titan-embed-text-v2:0";
1441
- logger.debug("Generating embedding", {
1442
- provider: this.providerName,
1443
- model: embeddingModelName,
1444
- textLength: text.length,
1445
- });
1446
- try {
1447
- const { InvokeModelCommand } = await import("@aws-sdk/client-bedrock-runtime");
1448
- // Titan Embed models expect a specific input format
1449
- const requestBody = JSON.stringify({
1450
- inputText: text,
1451
- });
1452
- const command = new InvokeModelCommand({
1453
- modelId: embeddingModelName,
1454
- contentType: "application/json",
1455
- accept: "application/json",
1456
- body: requestBody,
1457
- });
1458
- const response = await withTimeout(this.bedrockClient.send(command), 60_000, new Error("Bedrock embedding API call timed out"));
1459
- // Parse the response
1460
- const responseBody = JSON.parse(new TextDecoder().decode(response.body));
1461
- if (!responseBody.embedding || !Array.isArray(responseBody.embedding)) {
1462
- throw new Error("Invalid embedding response from Bedrock");
1463
- }
1464
- logger.debug("Embedding generated successfully", {
1465
- provider: this.providerName,
1466
- model: embeddingModelName,
1467
- embeddingDimension: responseBody.embedding.length,
1468
- });
1469
- return responseBody.embedding;
1470
- }
1471
- catch (error) {
1472
- logger.error("Embedding generation failed", {
1473
- error: error instanceof Error ? error.message : String(error),
1474
- model: embeddingModelName,
1475
- textLength: text.length,
1476
- });
1477
- throw this.handleProviderError(error);
1478
- }
1479
- }
1480
- /**
1481
- * Generate embeddings for multiple texts in a single batch
1482
- * @param texts - The texts to embed
1483
- * @param modelName - The embedding model to use (default: amazon.titan-embed-text-v2:0)
1484
- * @returns Promise resolving to an array of embedding vectors
1485
- */
1486
- async embedMany(texts, modelName) {
1487
- const embeddingModelName = modelName || "amazon.titan-embed-text-v2:0";
1488
- logger.debug("Generating batch embeddings", {
1489
- provider: this.providerName,
1490
- model: embeddingModelName,
1491
- count: texts.length,
1492
- });
1493
- try {
1494
- const embeddings = await Promise.all(texts.map((text) => this.embed(text, embeddingModelName)));
1495
- logger.debug("Batch embeddings generated successfully", {
1496
- provider: this.providerName,
1497
- model: embeddingModelName,
1498
- count: embeddings.length,
1499
- embeddingDimension: embeddings[0]?.length,
1500
- });
1501
- return embeddings;
1502
- }
1503
- catch (error) {
1504
- logger.error("Batch embedding generation failed", {
1505
- error: error instanceof Error ? error.message : String(error),
1506
- model: embeddingModelName,
1507
- count: texts.length,
1508
- });
1509
- throw this.handleProviderError(error);
1510
- }
1511
- }
1512
- }