@juspay/neurolink 9.32.0 → 9.33.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 (475) hide show
  1. package/CHANGELOG.md +12 -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/neurolink.d.ts +10 -0
  11. package/dist/lib/neurolink.js +41 -7
  12. package/dist/lib/server/routes/claudeProxyRoutes.js +45 -9
  13. package/dist/lib/types/generateTypes.d.ts +16 -0
  14. package/dist/lib/types/streamTypes.d.ts +15 -0
  15. package/dist/mcp/elicitationProtocol.js +1 -1
  16. package/dist/mcp/servers/agent/directToolsServer.js +0 -1
  17. package/dist/neurolink.d.ts +10 -0
  18. package/dist/neurolink.js +41 -7
  19. package/dist/providers/azureOpenai.js +1 -1
  20. package/dist/providers/huggingFace.js +0 -1
  21. package/dist/providers/openaiCompatible.js +0 -1
  22. package/dist/sdk/toolRegistration.js +0 -1
  23. package/dist/server/openapi/generator.js +1 -1
  24. package/dist/server/routes/claudeProxyRoutes.js +45 -9
  25. package/dist/types/configTypes.js +0 -5
  26. package/dist/types/generateTypes.d.ts +16 -0
  27. package/dist/types/modelTypes.js +0 -1
  28. package/dist/types/streamTypes.d.ts +15 -0
  29. package/dist/types/tools.js +0 -1
  30. package/dist/types/typeAliases.js +0 -1
  31. package/dist/types/utilities.js +1 -1
  32. package/dist/types/workflowTypes.js +0 -1
  33. package/dist/utils/providerRetry.js +0 -1
  34. package/dist/utils/providerUtils.js +0 -1
  35. package/package.json +2 -2
  36. package/dist/client/adapters/providerImageAdapter.js +0 -588
  37. package/dist/client/adapters/tts/googleTTSHandler.js +0 -344
  38. package/dist/client/adapters/video/directorPipeline.js +0 -516
  39. package/dist/client/adapters/video/ffmpegAdapter.js +0 -206
  40. package/dist/client/adapters/video/frameExtractor.js +0 -143
  41. package/dist/client/adapters/video/vertexVideoHandler.js +0 -763
  42. package/dist/client/adapters/video/videoAnalyzer.js +0 -238
  43. package/dist/client/adapters/video/videoMerger.js +0 -171
  44. package/dist/client/agent/directTools.js +0 -840
  45. package/dist/client/auth/AuthProviderFactory.js +0 -111
  46. package/dist/client/auth/AuthProviderRegistry.js +0 -190
  47. package/dist/client/auth/RequestContext.js +0 -78
  48. package/dist/client/auth/accountPool.js +0 -178
  49. package/dist/client/auth/anthropicOAuth.js +0 -974
  50. package/dist/client/auth/authContext.js +0 -314
  51. package/dist/client/auth/errors.js +0 -39
  52. package/dist/client/auth/index.js +0 -61
  53. package/dist/client/auth/middleware/AuthMiddleware.js +0 -519
  54. package/dist/client/auth/middleware/rateLimitByUser.js +0 -554
  55. package/dist/client/auth/providers/BaseAuthProvider.js +0 -723
  56. package/dist/client/auth/providers/CognitoProvider.js +0 -304
  57. package/dist/client/auth/providers/KeycloakProvider.js +0 -393
  58. package/dist/client/auth/providers/auth0.js +0 -274
  59. package/dist/client/auth/providers/betterAuth.js +0 -182
  60. package/dist/client/auth/providers/clerk.js +0 -317
  61. package/dist/client/auth/providers/custom.js +0 -112
  62. package/dist/client/auth/providers/firebase.js +0 -226
  63. package/dist/client/auth/providers/jwt.js +0 -212
  64. package/dist/client/auth/providers/oauth2.js +0 -303
  65. package/dist/client/auth/providers/supabase.js +0 -259
  66. package/dist/client/auth/providers/workos.js +0 -284
  67. package/dist/client/auth/serverBridge.js +0 -25
  68. package/dist/client/auth/sessionManager.js +0 -437
  69. package/dist/client/auth/tokenStore.js +0 -799
  70. package/dist/client/client/aiSdkAdapter.js +0 -487
  71. package/dist/client/client/auth.js +0 -473
  72. package/dist/client/client/errors.js +0 -552
  73. package/dist/client/client/httpClient.js +0 -837
  74. package/dist/client/client/index.js +0 -172
  75. package/dist/client/client/interceptors.js +0 -601
  76. package/dist/client/client/sseClient.js +0 -545
  77. package/dist/client/client/streamingClient.js +0 -917
  78. package/dist/client/client/wsClient.js +0 -369
  79. package/dist/client/config/configManager.js +0 -303
  80. package/dist/client/config/conversationMemory.js +0 -86
  81. package/dist/client/config/taskClassificationConfig.js +0 -148
  82. package/dist/client/constants/contextWindows.js +0 -295
  83. package/dist/client/constants/enums.js +0 -853
  84. package/dist/client/constants/index.js +0 -207
  85. package/dist/client/constants/performance.js +0 -389
  86. package/dist/client/constants/retry.js +0 -266
  87. package/dist/client/constants/timeouts.js +0 -182
  88. package/dist/client/constants/tokens.js +0 -380
  89. package/dist/client/constants/videoErrors.js +0 -46
  90. package/dist/client/context/budgetChecker.js +0 -98
  91. package/dist/client/context/contextCompactor.js +0 -205
  92. package/dist/client/context/emergencyTruncation.js +0 -88
  93. package/dist/client/context/errorDetection.js +0 -171
  94. package/dist/client/context/errors.js +0 -21
  95. package/dist/client/context/fileTokenBudget.js +0 -127
  96. package/dist/client/context/prompts/summarizationPrompt.js +0 -117
  97. package/dist/client/context/stages/fileReadDeduplicator.js +0 -66
  98. package/dist/client/context/stages/slidingWindowTruncator.js +0 -190
  99. package/dist/client/context/stages/structuredSummarizer.js +0 -99
  100. package/dist/client/context/stages/toolOutputPruner.js +0 -52
  101. package/dist/client/context/summarizationEngine.js +0 -136
  102. package/dist/client/context/toolOutputLimits.js +0 -78
  103. package/dist/client/context/toolPairRepair.js +0 -66
  104. package/dist/client/core/analytics.js +0 -88
  105. package/dist/client/core/baseProvider.js +0 -1385
  106. package/dist/client/core/constants.js +0 -140
  107. package/dist/client/core/conversationMemoryFactory.js +0 -141
  108. package/dist/client/core/conversationMemoryInitializer.js +0 -128
  109. package/dist/client/core/conversationMemoryManager.js +0 -344
  110. package/dist/client/core/dynamicModels.js +0 -358
  111. package/dist/client/core/evaluation.js +0 -309
  112. package/dist/client/core/evaluationProviders.js +0 -248
  113. package/dist/client/core/factory.js +0 -412
  114. package/dist/client/core/infrastructure/baseError.js +0 -22
  115. package/dist/client/core/infrastructure/baseFactory.js +0 -54
  116. package/dist/client/core/infrastructure/baseRegistry.js +0 -53
  117. package/dist/client/core/infrastructure/index.js +0 -5
  118. package/dist/client/core/infrastructure/retry.js +0 -20
  119. package/dist/client/core/infrastructure/typedEventEmitter.js +0 -23
  120. package/dist/client/core/modelConfiguration.js +0 -851
  121. package/dist/client/core/modules/GenerationHandler.js +0 -588
  122. package/dist/client/core/modules/MessageBuilder.js +0 -273
  123. package/dist/client/core/modules/StreamHandler.js +0 -185
  124. package/dist/client/core/modules/TelemetryHandler.js +0 -203
  125. package/dist/client/core/modules/ToolsManager.js +0 -499
  126. package/dist/client/core/modules/Utilities.js +0 -331
  127. package/dist/client/core/redisConversationMemoryManager.js +0 -1435
  128. package/dist/client/core/streamAnalytics.js +0 -131
  129. package/dist/client/evaluation/contextBuilder.js +0 -134
  130. package/dist/client/evaluation/index.js +0 -61
  131. package/dist/client/evaluation/prompts.js +0 -73
  132. package/dist/client/evaluation/ragasEvaluator.js +0 -110
  133. package/dist/client/evaluation/retryManager.js +0 -78
  134. package/dist/client/evaluation/scoring.js +0 -61
  135. package/dist/client/factories/providerFactory.js +0 -166
  136. package/dist/client/factories/providerRegistry.js +0 -166
  137. package/dist/client/features/ppt/constants.js +0 -896
  138. package/dist/client/features/ppt/contentPlanner.js +0 -529
  139. package/dist/client/features/ppt/presentationOrchestrator.js +0 -236
  140. package/dist/client/features/ppt/slideGenerator.js +0 -532
  141. package/dist/client/features/ppt/slideRenderers.js +0 -2383
  142. package/dist/client/features/ppt/slideTypeInference.js +0 -405
  143. package/dist/client/features/ppt/types.js +0 -13
  144. package/dist/client/features/ppt/utils.js +0 -443
  145. package/dist/client/files/fileReferenceRegistry.js +0 -1543
  146. package/dist/client/files/fileTools.js +0 -450
  147. package/dist/client/files/streamingReader.js +0 -321
  148. package/dist/client/files/types.js +0 -23
  149. package/dist/client/hitl/hitlErrors.js +0 -54
  150. package/dist/client/hitl/hitlManager.js +0 -460
  151. package/dist/client/mcp/agentExposure.js +0 -356
  152. package/dist/client/mcp/auth/index.js +0 -11
  153. package/dist/client/mcp/auth/oauthClientProvider.js +0 -325
  154. package/dist/client/mcp/auth/tokenStorage.js +0 -134
  155. package/dist/client/mcp/batching/index.js +0 -10
  156. package/dist/client/mcp/batching/requestBatcher.js +0 -441
  157. package/dist/client/mcp/caching/index.js +0 -10
  158. package/dist/client/mcp/caching/toolCache.js +0 -433
  159. package/dist/client/mcp/elicitation/elicitationManager.js +0 -376
  160. package/dist/client/mcp/elicitation/index.js +0 -11
  161. package/dist/client/mcp/elicitation/types.js +0 -10
  162. package/dist/client/mcp/elicitationProtocol.js +0 -375
  163. package/dist/client/mcp/enhancedToolDiscovery.js +0 -481
  164. package/dist/client/mcp/externalServerManager.js +0 -1478
  165. package/dist/client/mcp/factory.js +0 -161
  166. package/dist/client/mcp/flexibleToolValidator.js +0 -161
  167. package/dist/client/mcp/httpRateLimiter.js +0 -391
  168. package/dist/client/mcp/httpRetryHandler.js +0 -178
  169. package/dist/client/mcp/index.js +0 -74
  170. package/dist/client/mcp/mcpCircuitBreaker.js +0 -427
  171. package/dist/client/mcp/mcpClientFactory.js +0 -708
  172. package/dist/client/mcp/mcpRegistryClient.js +0 -488
  173. package/dist/client/mcp/mcpServerBase.js +0 -373
  174. package/dist/client/mcp/multiServerManager.js +0 -579
  175. package/dist/client/mcp/registry.js +0 -158
  176. package/dist/client/mcp/routing/index.js +0 -10
  177. package/dist/client/mcp/routing/toolRouter.js +0 -416
  178. package/dist/client/mcp/serverCapabilities.js +0 -502
  179. package/dist/client/mcp/servers/agent/directToolsServer.js +0 -150
  180. package/dist/client/mcp/toolAnnotations.js +0 -239
  181. package/dist/client/mcp/toolConverter.js +0 -258
  182. package/dist/client/mcp/toolDiscoveryService.js +0 -798
  183. package/dist/client/mcp/toolIntegration.js +0 -334
  184. package/dist/client/mcp/toolRegistry.js +0 -729
  185. package/dist/client/memory/hippocampusInitializer.js +0 -19
  186. package/dist/client/memory/memoryRetrievalTools.js +0 -166
  187. package/dist/client/middleware/builtin/analytics.js +0 -132
  188. package/dist/client/middleware/builtin/autoEvaluation.js +0 -203
  189. package/dist/client/middleware/builtin/guardrails.js +0 -109
  190. package/dist/client/middleware/builtin/lifecycle.js +0 -168
  191. package/dist/client/middleware/factory.js +0 -327
  192. package/dist/client/middleware/registry.js +0 -295
  193. package/dist/client/middleware/utils/guardrailsUtils.js +0 -396
  194. package/dist/client/models/anthropicModels.js +0 -527
  195. package/dist/client/neurolink.js +0 -8233
  196. package/dist/client/observability/exporterRegistry.js +0 -413
  197. package/dist/client/observability/exporters/arizeExporter.js +0 -138
  198. package/dist/client/observability/exporters/baseExporter.js +0 -190
  199. package/dist/client/observability/exporters/braintrustExporter.js +0 -154
  200. package/dist/client/observability/exporters/datadogExporter.js +0 -196
  201. package/dist/client/observability/exporters/laminarExporter.js +0 -302
  202. package/dist/client/observability/exporters/langfuseExporter.js +0 -209
  203. package/dist/client/observability/exporters/langsmithExporter.js +0 -143
  204. package/dist/client/observability/exporters/otelExporter.js +0 -164
  205. package/dist/client/observability/exporters/posthogExporter.js +0 -287
  206. package/dist/client/observability/exporters/sentryExporter.js +0 -165
  207. package/dist/client/observability/index.js +0 -31
  208. package/dist/client/observability/metricsAggregator.js +0 -556
  209. package/dist/client/observability/otelBridge.js +0 -131
  210. package/dist/client/observability/retryPolicy.js +0 -383
  211. package/dist/client/observability/sampling/samplers.js +0 -216
  212. package/dist/client/observability/spanProcessor.js +0 -303
  213. package/dist/client/observability/tokenTracker.js +0 -413
  214. package/dist/client/observability/types/exporterTypes.js +0 -5
  215. package/dist/client/observability/types/index.js +0 -4
  216. package/dist/client/observability/types/spanTypes.js +0 -92
  217. package/dist/client/observability/utils/safeMetadata.js +0 -25
  218. package/dist/client/observability/utils/spanSerializer.js +0 -292
  219. package/dist/client/processors/archive/ArchiveProcessor.js +0 -1308
  220. package/dist/client/processors/base/BaseFileProcessor.js +0 -614
  221. package/dist/client/processors/base/types.js +0 -82
  222. package/dist/client/processors/config/fileTypes.js +0 -520
  223. package/dist/client/processors/config/index.js +0 -92
  224. package/dist/client/processors/config/languageMap.js +0 -410
  225. package/dist/client/processors/config/mimeTypes.js +0 -363
  226. package/dist/client/processors/config/sizeLimits.js +0 -258
  227. package/dist/client/processors/document/ExcelProcessor.js +0 -590
  228. package/dist/client/processors/document/OpenDocumentProcessor.js +0 -212
  229. package/dist/client/processors/document/PptxProcessor.js +0 -157
  230. package/dist/client/processors/document/RtfProcessor.js +0 -361
  231. package/dist/client/processors/document/WordProcessor.js +0 -353
  232. package/dist/client/processors/errors/FileErrorCode.js +0 -255
  233. package/dist/client/processors/errors/errorHelpers.js +0 -386
  234. package/dist/client/processors/errors/errorSerializer.js +0 -507
  235. package/dist/client/processors/errors/index.js +0 -49
  236. package/dist/client/processors/markup/SvgProcessor.js +0 -240
  237. package/dist/client/processors/media/AudioProcessor.js +0 -707
  238. package/dist/client/processors/media/VideoProcessor.js +0 -1045
  239. package/dist/client/providers/amazonBedrock.js +0 -1512
  240. package/dist/client/providers/amazonSagemaker.js +0 -162
  241. package/dist/client/providers/anthropic.js +0 -831
  242. package/dist/client/providers/azureOpenai.js +0 -143
  243. package/dist/client/providers/googleAiStudio.js +0 -1200
  244. package/dist/client/providers/googleNativeGemini3.js +0 -543
  245. package/dist/client/providers/googleVertex.js +0 -2936
  246. package/dist/client/providers/huggingFace.js +0 -315
  247. package/dist/client/providers/litellm.js +0 -488
  248. package/dist/client/providers/mistral.js +0 -157
  249. package/dist/client/providers/ollama.js +0 -1579
  250. package/dist/client/providers/openAI.js +0 -627
  251. package/dist/client/providers/openRouter.js +0 -543
  252. package/dist/client/providers/openaiCompatible.js +0 -290
  253. package/dist/client/providers/providerTypeUtils.js +0 -46
  254. package/dist/client/providers/sagemaker/adaptive-semaphore.js +0 -215
  255. package/dist/client/providers/sagemaker/client.js +0 -472
  256. package/dist/client/providers/sagemaker/config.js +0 -317
  257. package/dist/client/providers/sagemaker/detection.js +0 -606
  258. package/dist/client/providers/sagemaker/error-constants.js +0 -227
  259. package/dist/client/providers/sagemaker/errors.js +0 -299
  260. package/dist/client/providers/sagemaker/language-model.js +0 -775
  261. package/dist/client/providers/sagemaker/parsers.js +0 -634
  262. package/dist/client/providers/sagemaker/streaming.js +0 -331
  263. package/dist/client/providers/sagemaker/structured-parser.js +0 -625
  264. package/dist/client/proxy/accountQuota.js +0 -162
  265. package/dist/client/proxy/claudeFormat.js +0 -595
  266. package/dist/client/proxy/modelRouter.js +0 -29
  267. package/dist/client/proxy/oauthFetch.js +0 -367
  268. package/dist/client/proxy/proxyFetch.js +0 -586
  269. package/dist/client/proxy/requestLogger.js +0 -207
  270. package/dist/client/proxy/tokenRefresh.js +0 -124
  271. package/dist/client/proxy/usageStats.js +0 -74
  272. package/dist/client/proxy/utils/noProxyUtils.js +0 -149
  273. package/dist/client/rag/ChunkerFactory.js +0 -320
  274. package/dist/client/rag/ChunkerRegistry.js +0 -421
  275. package/dist/client/rag/chunkers/BaseChunker.js +0 -143
  276. package/dist/client/rag/chunkers/CharacterChunker.js +0 -28
  277. package/dist/client/rag/chunkers/HTMLChunker.js +0 -38
  278. package/dist/client/rag/chunkers/JSONChunker.js +0 -68
  279. package/dist/client/rag/chunkers/LaTeXChunker.js +0 -63
  280. package/dist/client/rag/chunkers/MarkdownChunker.js +0 -306
  281. package/dist/client/rag/chunkers/RecursiveChunker.js +0 -139
  282. package/dist/client/rag/chunkers/SemanticMarkdownChunker.js +0 -138
  283. package/dist/client/rag/chunkers/SentenceChunker.js +0 -66
  284. package/dist/client/rag/chunkers/TokenChunker.js +0 -61
  285. package/dist/client/rag/chunkers/index.js +0 -15
  286. package/dist/client/rag/chunking/characterChunker.js +0 -142
  287. package/dist/client/rag/chunking/chunkerRegistry.js +0 -194
  288. package/dist/client/rag/chunking/htmlChunker.js +0 -247
  289. package/dist/client/rag/chunking/index.js +0 -17
  290. package/dist/client/rag/chunking/jsonChunker.js +0 -281
  291. package/dist/client/rag/chunking/latexChunker.js +0 -251
  292. package/dist/client/rag/chunking/markdownChunker.js +0 -373
  293. package/dist/client/rag/chunking/recursiveChunker.js +0 -148
  294. package/dist/client/rag/chunking/semanticChunker.js +0 -306
  295. package/dist/client/rag/chunking/sentenceChunker.js +0 -230
  296. package/dist/client/rag/chunking/tokenChunker.js +0 -183
  297. package/dist/client/rag/document/MDocument.js +0 -392
  298. package/dist/client/rag/document/index.js +0 -5
  299. package/dist/client/rag/document/loaders.js +0 -500
  300. package/dist/client/rag/errors/RAGError.js +0 -274
  301. package/dist/client/rag/errors/index.js +0 -6
  302. package/dist/client/rag/graphRag/graphRAG.js +0 -401
  303. package/dist/client/rag/graphRag/index.js +0 -4
  304. package/dist/client/rag/index.js +0 -141
  305. package/dist/client/rag/metadata/MetadataExtractorFactory.js +0 -418
  306. package/dist/client/rag/metadata/MetadataExtractorRegistry.js +0 -362
  307. package/dist/client/rag/metadata/index.js +0 -9
  308. package/dist/client/rag/metadata/metadataExtractor.js +0 -280
  309. package/dist/client/rag/pipeline/RAGPipeline.js +0 -436
  310. package/dist/client/rag/pipeline/contextAssembly.js +0 -341
  311. package/dist/client/rag/pipeline/index.js +0 -5
  312. package/dist/client/rag/ragIntegration.js +0 -321
  313. package/dist/client/rag/reranker/RerankerFactory.js +0 -430
  314. package/dist/client/rag/reranker/RerankerRegistry.js +0 -402
  315. package/dist/client/rag/reranker/index.js +0 -9
  316. package/dist/client/rag/reranker/reranker.js +0 -277
  317. package/dist/client/rag/resilience/CircuitBreaker.js +0 -431
  318. package/dist/client/rag/resilience/RetryHandler.js +0 -304
  319. package/dist/client/rag/resilience/index.js +0 -7
  320. package/dist/client/rag/retrieval/hybridSearch.js +0 -335
  321. package/dist/client/rag/retrieval/index.js +0 -5
  322. package/dist/client/rag/retrieval/vectorQueryTool.js +0 -307
  323. package/dist/client/rag/types.js +0 -8
  324. package/dist/client/sdk/toolRegistration.js +0 -377
  325. package/dist/client/server/abstract/baseServerAdapter.js +0 -575
  326. package/dist/client/server/adapters/expressAdapter.js +0 -486
  327. package/dist/client/server/adapters/fastifyAdapter.js +0 -472
  328. package/dist/client/server/adapters/honoAdapter.js +0 -632
  329. package/dist/client/server/adapters/koaAdapter.js +0 -510
  330. package/dist/client/server/errors.js +0 -486
  331. package/dist/client/server/factory/serverAdapterFactory.js +0 -160
  332. package/dist/client/server/index.js +0 -108
  333. package/dist/client/server/middleware/abortSignal.js +0 -111
  334. package/dist/client/server/middleware/auth.js +0 -388
  335. package/dist/client/server/middleware/cache.js +0 -359
  336. package/dist/client/server/middleware/common.js +0 -281
  337. package/dist/client/server/middleware/deprecation.js +0 -190
  338. package/dist/client/server/middleware/mcpBodyAttachment.js +0 -63
  339. package/dist/client/server/middleware/rateLimit.js +0 -227
  340. package/dist/client/server/middleware/validation.js +0 -388
  341. package/dist/client/server/openapi/generator.js +0 -398
  342. package/dist/client/server/openapi/index.js +0 -36
  343. package/dist/client/server/openapi/schemas.js +0 -695
  344. package/dist/client/server/openapi/templates.js +0 -374
  345. package/dist/client/server/routes/agentRoutes.js +0 -189
  346. package/dist/client/server/routes/claudeProxyRoutes.js +0 -1600
  347. package/dist/client/server/routes/healthRoutes.js +0 -187
  348. package/dist/client/server/routes/index.js +0 -57
  349. package/dist/client/server/routes/mcpRoutes.js +0 -342
  350. package/dist/client/server/routes/memoryRoutes.js +0 -350
  351. package/dist/client/server/routes/openApiRoutes.js +0 -126
  352. package/dist/client/server/routes/toolRoutes.js +0 -199
  353. package/dist/client/server/streaming/dataStream.js +0 -486
  354. package/dist/client/server/streaming/index.js +0 -11
  355. package/dist/client/server/types.js +0 -67
  356. package/dist/client/server/utils/redaction.js +0 -334
  357. package/dist/client/server/utils/validation.js +0 -243
  358. package/dist/client/server/websocket/WebSocketHandler.js +0 -383
  359. package/dist/client/server/websocket/index.js +0 -4
  360. package/dist/client/services/server/ai/observability/instrumentation.js +0 -808
  361. package/dist/client/telemetry/attributes.js +0 -100
  362. package/dist/client/telemetry/index.js +0 -26
  363. package/dist/client/telemetry/telemetryService.js +0 -308
  364. package/dist/client/telemetry/tracers.js +0 -17
  365. package/dist/client/telemetry/withSpan.js +0 -34
  366. package/dist/client/types/actionTypes.js +0 -6
  367. package/dist/client/types/analytics.js +0 -5
  368. package/dist/client/types/authTypes.js +0 -9
  369. package/dist/client/types/circuitBreakerErrors.js +0 -34
  370. package/dist/client/types/cli.js +0 -21
  371. package/dist/client/types/clientTypes.js +0 -10
  372. package/dist/client/types/common.js +0 -51
  373. package/dist/client/types/configTypes.js +0 -49
  374. package/dist/client/types/content.js +0 -19
  375. package/dist/client/types/contextTypes.js +0 -400
  376. package/dist/client/types/conversation.js +0 -47
  377. package/dist/client/types/conversationMemoryInterface.js +0 -6
  378. package/dist/client/types/domainTypes.js +0 -5
  379. package/dist/client/types/errors.js +0 -167
  380. package/dist/client/types/evaluation.js +0 -5
  381. package/dist/client/types/evaluationProviders.js +0 -5
  382. package/dist/client/types/evaluationTypes.js +0 -1
  383. package/dist/client/types/externalMcp.js +0 -6
  384. package/dist/client/types/fileReferenceTypes.js +0 -8
  385. package/dist/client/types/fileTypes.js +0 -4
  386. package/dist/client/types/generateTypes.js +0 -1
  387. package/dist/client/types/guardrails.js +0 -1
  388. package/dist/client/types/hitlTypes.js +0 -8
  389. package/dist/client/types/index.js +0 -57
  390. package/dist/client/types/mcpTypes.js +0 -5
  391. package/dist/client/types/middlewareTypes.js +0 -1
  392. package/dist/client/types/modelTypes.js +0 -30
  393. package/dist/client/types/multimodal.js +0 -135
  394. package/dist/client/types/observability.js +0 -6
  395. package/dist/client/types/pptTypes.js +0 -82
  396. package/dist/client/types/providers.js +0 -111
  397. package/dist/client/types/proxyTypes.js +0 -16
  398. package/dist/client/types/ragTypes.js +0 -7
  399. package/dist/client/types/sdkTypes.js +0 -8
  400. package/dist/client/types/serviceTypes.js +0 -5
  401. package/dist/client/types/streamTypes.js +0 -1
  402. package/dist/client/types/subscriptionTypes.js +0 -9
  403. package/dist/client/types/taskClassificationTypes.js +0 -5
  404. package/dist/client/types/tools.js +0 -24
  405. package/dist/client/types/ttsTypes.js +0 -57
  406. package/dist/client/types/typeAliases.js +0 -48
  407. package/dist/client/types/utilities.js +0 -4
  408. package/dist/client/types/workflowTypes.js +0 -30
  409. package/dist/client/utils/async/withTimeout.js +0 -98
  410. package/dist/client/utils/asyncMutex.js +0 -60
  411. package/dist/client/utils/conversationMemory.js +0 -431
  412. package/dist/client/utils/csvProcessor.js +0 -846
  413. package/dist/client/utils/errorHandling.js +0 -936
  414. package/dist/client/utils/evaluationUtils.js +0 -131
  415. package/dist/client/utils/factoryProcessing.js +0 -589
  416. package/dist/client/utils/fileDetector.js +0 -2161
  417. package/dist/client/utils/imageCache.js +0 -376
  418. package/dist/client/utils/imageProcessor.js +0 -704
  419. package/dist/client/utils/logger.js +0 -491
  420. package/dist/client/utils/mcpDefaults.js +0 -134
  421. package/dist/client/utils/messageBuilder.js +0 -1653
  422. package/dist/client/utils/modelAliasResolver.js +0 -54
  423. package/dist/client/utils/modelDetection.js +0 -80
  424. package/dist/client/utils/modelRouter.js +0 -292
  425. package/dist/client/utils/multimodalOptionsBuilder.js +0 -65
  426. package/dist/client/utils/observabilityHelpers.js +0 -47
  427. package/dist/client/utils/parameterValidation.js +0 -966
  428. package/dist/client/utils/pdfProcessor.js +0 -410
  429. package/dist/client/utils/performance.js +0 -222
  430. package/dist/client/utils/pricing.js +0 -340
  431. package/dist/client/utils/promptRedaction.js +0 -62
  432. package/dist/client/utils/providerConfig.js +0 -1009
  433. package/dist/client/utils/providerHealth.js +0 -1237
  434. package/dist/client/utils/providerRetry.js +0 -112
  435. package/dist/client/utils/providerUtils.js +0 -434
  436. package/dist/client/utils/rateLimiter.js +0 -200
  437. package/dist/client/utils/redis.js +0 -368
  438. package/dist/client/utils/retryHandler.js +0 -269
  439. package/dist/client/utils/retryability.js +0 -22
  440. package/dist/client/utils/sanitizers/svg.js +0 -481
  441. package/dist/client/utils/schemaConversion.js +0 -255
  442. package/dist/client/utils/taskClassificationUtils.js +0 -149
  443. package/dist/client/utils/taskClassifier.js +0 -94
  444. package/dist/client/utils/thinkingConfig.js +0 -104
  445. package/dist/client/utils/timeout.js +0 -359
  446. package/dist/client/utils/tokenEstimation.js +0 -142
  447. package/dist/client/utils/tokenLimits.js +0 -125
  448. package/dist/client/utils/tokenUtils.js +0 -239
  449. package/dist/client/utils/toolUtils.js +0 -75
  450. package/dist/client/utils/transformationUtils.js +0 -554
  451. package/dist/client/utils/ttsProcessor.js +0 -286
  452. package/dist/client/utils/typeUtils.js +0 -97
  453. package/dist/client/utils/videoAnalysisProcessor.js +0 -67
  454. package/dist/client/workflow/config.js +0 -398
  455. package/dist/client/workflow/core/ensembleExecutor.js +0 -407
  456. package/dist/client/workflow/core/judgeScorer.js +0 -544
  457. package/dist/client/workflow/core/responseConditioner.js +0 -225
  458. package/dist/client/workflow/core/types/conditionerTypes.js +0 -7
  459. package/dist/client/workflow/core/types/ensembleTypes.js +0 -7
  460. package/dist/client/workflow/core/types/index.js +0 -7
  461. package/dist/client/workflow/core/types/judgeTypes.js +0 -7
  462. package/dist/client/workflow/core/types/layerTypes.js +0 -7
  463. package/dist/client/workflow/core/types/registryTypes.js +0 -7
  464. package/dist/client/workflow/core/workflowRegistry.js +0 -304
  465. package/dist/client/workflow/core/workflowRunner.js +0 -586
  466. package/dist/client/workflow/index.js +0 -50
  467. package/dist/client/workflow/types.js +0 -9
  468. package/dist/client/workflow/utils/types/index.js +0 -7
  469. package/dist/client/workflow/utils/workflowMetrics.js +0 -311
  470. package/dist/client/workflow/utils/workflowValidation.js +0 -420
  471. package/dist/client/workflow/workflows/adaptiveWorkflow.js +0 -366
  472. package/dist/client/workflow/workflows/consensusWorkflow.js +0 -192
  473. package/dist/client/workflow/workflows/fallbackWorkflow.js +0 -225
  474. package/dist/client/workflow/workflows/multiJudgeWorkflow.js +0 -351
  475. /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
- }