@juspay/neurolink 7.50.0 → 7.51.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 (242) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +12 -9
  3. package/dist/adapters/providerImageAdapter.js +82 -10
  4. package/dist/agent/directTools.d.ts +10 -10
  5. package/dist/agent/directTools.js +5 -3
  6. package/dist/cli/commands/config.js +1 -0
  7. package/dist/cli/commands/mcp.js +1 -0
  8. package/dist/cli/commands/models.js +1 -0
  9. package/dist/cli/commands/ollama.js +1 -0
  10. package/dist/cli/commands/setup-anthropic.js +1 -0
  11. package/dist/cli/commands/setup-azure.js +1 -0
  12. package/dist/cli/commands/setup-bedrock.js +1 -0
  13. package/dist/cli/commands/setup-gcp.js +1 -0
  14. package/dist/cli/commands/setup-google-ai.js +1 -0
  15. package/dist/cli/commands/setup-huggingface.js +1 -0
  16. package/dist/cli/commands/setup-mistral.js +1 -0
  17. package/dist/cli/commands/setup-openai.js +1 -0
  18. package/dist/cli/commands/setup.js +1 -0
  19. package/dist/cli/errorHandler.js +1 -0
  20. package/dist/cli/factories/commandFactory.d.ts +1 -0
  21. package/dist/cli/factories/commandFactory.js +23 -6
  22. package/dist/cli/factories/ollamaCommandFactory.js +1 -0
  23. package/dist/cli/factories/sagemakerCommandFactory.js +1 -0
  24. package/dist/cli/factories/setupCommandFactory.js +1 -0
  25. package/dist/cli/index.js +1 -0
  26. package/dist/cli/loop/conversationSelector.js +1 -0
  27. package/dist/cli/loop/optionsSchema.js +1 -0
  28. package/dist/cli/loop/session.js +1 -0
  29. package/dist/cli/parser.js +1 -0
  30. package/dist/cli/utils/completeSetup.js +1 -0
  31. package/dist/cli/utils/envManager.js +1 -0
  32. package/dist/cli/utils/interactiveSetup.js +1 -0
  33. package/dist/cli/utils/ollamaUtils.js +1 -0
  34. package/dist/constants/index.js +1 -1
  35. package/dist/core/baseProvider.d.ts +5 -0
  36. package/dist/core/baseProvider.js +70 -20
  37. package/dist/index.d.ts +3 -3
  38. package/dist/lib/adapters/providerImageAdapter.js +83 -10
  39. package/dist/lib/agent/directTools.d.ts +10 -10
  40. package/dist/lib/agent/directTools.js +6 -3
  41. package/dist/lib/config/configManager.js +1 -0
  42. package/dist/lib/config/conversationMemory.js +1 -0
  43. package/dist/lib/config/taskClassificationConfig.js +1 -0
  44. package/dist/lib/constants/index.js +2 -1
  45. package/dist/lib/constants/performance.js +1 -0
  46. package/dist/lib/constants/retry.js +1 -0
  47. package/dist/lib/constants/timeouts.js +1 -0
  48. package/dist/lib/constants/tokens.js +1 -0
  49. package/dist/lib/core/analytics.js +1 -0
  50. package/dist/lib/core/baseProvider.d.ts +5 -0
  51. package/dist/lib/core/baseProvider.js +71 -20
  52. package/dist/lib/core/constants.js +1 -0
  53. package/dist/lib/core/conversationMemoryFactory.js +1 -0
  54. package/dist/lib/core/conversationMemoryInitializer.js +1 -0
  55. package/dist/lib/core/conversationMemoryManager.js +1 -0
  56. package/dist/lib/core/dynamicModels.js +1 -0
  57. package/dist/lib/core/evaluation.js +1 -0
  58. package/dist/lib/core/evaluationProviders.js +1 -0
  59. package/dist/lib/core/factory.js +1 -0
  60. package/dist/lib/core/modelConfiguration.js +1 -0
  61. package/dist/lib/core/redisConversationMemoryManager.js +1 -0
  62. package/dist/lib/core/serviceRegistry.js +1 -0
  63. package/dist/lib/core/streamAnalytics.js +1 -0
  64. package/dist/lib/evaluation/contextBuilder.js +1 -0
  65. package/dist/lib/evaluation/index.js +1 -0
  66. package/dist/lib/evaluation/prompts.js +1 -0
  67. package/dist/lib/evaluation/ragasEvaluator.js +1 -0
  68. package/dist/lib/evaluation/retryManager.js +1 -0
  69. package/dist/lib/evaluation/scoring.js +1 -0
  70. package/dist/lib/factories/providerFactory.js +1 -0
  71. package/dist/lib/factories/providerRegistry.js +1 -0
  72. package/dist/lib/hitl/hitlErrors.js +1 -0
  73. package/dist/lib/hitl/hitlManager.js +1 -0
  74. package/dist/lib/hitl/index.js +1 -0
  75. package/dist/lib/hitl/types.js +1 -0
  76. package/dist/lib/index.d.ts +3 -3
  77. package/dist/lib/index.js +1 -0
  78. package/dist/lib/mcp/externalServerManager.js +1 -0
  79. package/dist/lib/mcp/factory.js +1 -0
  80. package/dist/lib/mcp/flexibleToolValidator.js +1 -0
  81. package/dist/lib/mcp/index.js +1 -0
  82. package/dist/lib/mcp/mcpCircuitBreaker.js +1 -0
  83. package/dist/lib/mcp/mcpClientFactory.js +2 -1
  84. package/dist/lib/mcp/registry.js +1 -0
  85. package/dist/lib/mcp/servers/agent/directToolsServer.js +2 -0
  86. package/dist/lib/mcp/servers/aiProviders/aiAnalysisTools.js +1 -0
  87. package/dist/lib/mcp/servers/aiProviders/aiCoreServer.js +1 -0
  88. package/dist/lib/mcp/servers/aiProviders/aiWorkflowTools.js +1 -0
  89. package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -0
  90. package/dist/lib/mcp/toolDiscoveryService.js +1 -0
  91. package/dist/lib/mcp/toolRegistry.js +1 -0
  92. package/dist/lib/memory/mem0Initializer.js +1 -0
  93. package/dist/lib/middleware/builtin/analytics.js +1 -0
  94. package/dist/lib/middleware/builtin/autoEvaluation.js +1 -0
  95. package/dist/lib/middleware/builtin/guardrails.js +1 -0
  96. package/dist/lib/middleware/factory.js +1 -0
  97. package/dist/lib/middleware/index.js +1 -0
  98. package/dist/lib/middleware/registry.js +1 -0
  99. package/dist/lib/middleware/utils/guardrailsUtils.js +1 -0
  100. package/dist/lib/models/modelRegistry.js +1 -0
  101. package/dist/lib/models/modelResolver.js +2 -0
  102. package/dist/lib/neurolink.d.ts +6 -0
  103. package/dist/lib/neurolink.js +135 -5
  104. package/dist/lib/providers/amazonBedrock.d.ts +1 -0
  105. package/dist/lib/providers/amazonBedrock.js +166 -14
  106. package/dist/lib/providers/amazonSagemaker.js +1 -0
  107. package/dist/lib/providers/anthropic.js +7 -21
  108. package/dist/lib/providers/anthropicBaseProvider.js +1 -0
  109. package/dist/lib/providers/azureOpenai.js +5 -21
  110. package/dist/lib/providers/googleAiStudio.js +5 -21
  111. package/dist/lib/providers/googleVertex.js +8 -1
  112. package/dist/lib/providers/huggingFace.js +34 -3
  113. package/dist/lib/providers/index.js +1 -0
  114. package/dist/lib/providers/litellm.js +34 -3
  115. package/dist/lib/providers/mistral.js +32 -2
  116. package/dist/lib/providers/ollama.d.ts +37 -1
  117. package/dist/lib/providers/ollama.js +544 -58
  118. package/dist/lib/providers/openAI.js +5 -21
  119. package/dist/lib/providers/openaiCompatible.js +41 -4
  120. package/dist/lib/providers/sagemaker/adaptive-semaphore.js +1 -0
  121. package/dist/lib/providers/sagemaker/client.js +1 -0
  122. package/dist/lib/providers/sagemaker/config.js +1 -0
  123. package/dist/lib/providers/sagemaker/detection.js +1 -0
  124. package/dist/lib/providers/sagemaker/diagnostics.js +1 -0
  125. package/dist/lib/providers/sagemaker/error-constants.js +1 -0
  126. package/dist/lib/providers/sagemaker/errors.js +1 -0
  127. package/dist/lib/providers/sagemaker/index.js +1 -0
  128. package/dist/lib/providers/sagemaker/language-model.js +1 -0
  129. package/dist/lib/providers/sagemaker/parsers.js +1 -0
  130. package/dist/lib/providers/sagemaker/streaming.js +1 -0
  131. package/dist/lib/providers/sagemaker/structured-parser.js +1 -0
  132. package/dist/lib/proxy/awsProxyIntegration.js +1 -0
  133. package/dist/lib/proxy/proxyFetch.js +1 -0
  134. package/dist/lib/proxy/utils/noProxyUtils.js +1 -0
  135. package/dist/lib/sdk/toolRegistration.js +2 -0
  136. package/dist/lib/services/server/ai/observability/instrumentation.js +1 -0
  137. package/dist/lib/session/globalSessionState.js +1 -0
  138. package/dist/lib/telemetry/index.js +1 -0
  139. package/dist/lib/telemetry/telemetryService.js +1 -0
  140. package/dist/lib/types/analytics.js +1 -0
  141. package/dist/lib/types/cli.js +1 -0
  142. package/dist/lib/types/common.js +1 -0
  143. package/dist/lib/types/configTypes.js +1 -0
  144. package/dist/lib/types/content.d.ts +14 -1
  145. package/dist/lib/types/content.js +1 -0
  146. package/dist/lib/types/contextTypes.js +1 -0
  147. package/dist/lib/types/conversation.js +1 -0
  148. package/dist/lib/types/domainTypes.js +1 -0
  149. package/dist/lib/types/errors.js +1 -0
  150. package/dist/lib/types/evaluation.js +1 -0
  151. package/dist/lib/types/evaluationProviders.js +1 -0
  152. package/dist/lib/types/evaluationTypes.js +1 -0
  153. package/dist/lib/types/externalMcp.js +1 -0
  154. package/dist/lib/types/fileTypes.d.ts +44 -0
  155. package/dist/lib/types/fileTypes.js +1 -0
  156. package/dist/lib/types/generateTypes.d.ts +1 -0
  157. package/dist/lib/types/generateTypes.js +1 -0
  158. package/dist/lib/types/guardrails.js +1 -0
  159. package/dist/lib/types/index.js +1 -0
  160. package/dist/lib/types/mcpTypes.js +1 -0
  161. package/dist/lib/types/middlewareTypes.js +1 -0
  162. package/dist/lib/types/modelTypes.js +1 -0
  163. package/dist/lib/types/observability.js +1 -0
  164. package/dist/lib/types/providers.d.ts +44 -0
  165. package/dist/lib/types/providers.js +1 -0
  166. package/dist/lib/types/sdkTypes.js +1 -0
  167. package/dist/lib/types/serviceTypes.js +1 -0
  168. package/dist/lib/types/streamTypes.d.ts +1 -0
  169. package/dist/lib/types/streamTypes.js +1 -0
  170. package/dist/lib/types/taskClassificationTypes.js +1 -0
  171. package/dist/lib/types/tools.js +2 -0
  172. package/dist/lib/types/typeAliases.js +1 -0
  173. package/dist/lib/types/universalProviderOptions.js +1 -0
  174. package/dist/lib/utils/analyticsUtils.js +1 -0
  175. package/dist/lib/utils/conversationMemory.js +1 -0
  176. package/dist/lib/utils/conversationMemoryUtils.js +1 -0
  177. package/dist/lib/utils/csvProcessor.js +1 -0
  178. package/dist/lib/utils/errorHandling.js +1 -0
  179. package/dist/lib/utils/evaluationUtils.js +1 -0
  180. package/dist/lib/utils/factoryProcessing.js +1 -0
  181. package/dist/lib/utils/fileDetector.js +7 -3
  182. package/dist/lib/utils/imageProcessor.js +1 -0
  183. package/dist/lib/utils/logger.js +1 -0
  184. package/dist/lib/utils/loopUtils.js +1 -0
  185. package/dist/lib/utils/mcpDefaults.js +1 -0
  186. package/dist/lib/utils/messageBuilder.js +96 -9
  187. package/dist/lib/utils/modelRouter.js +1 -0
  188. package/dist/lib/utils/multimodalOptionsBuilder.d.ts +67 -0
  189. package/dist/lib/utils/multimodalOptionsBuilder.js +65 -0
  190. package/dist/lib/utils/optionsConversion.js +1 -0
  191. package/dist/lib/utils/optionsUtils.js +1 -0
  192. package/dist/lib/utils/parameterValidation.js +1 -0
  193. package/dist/lib/utils/pdfProcessor.d.ts +10 -0
  194. package/dist/lib/utils/pdfProcessor.js +199 -0
  195. package/dist/lib/utils/performance.js +1 -0
  196. package/dist/lib/utils/promptRedaction.js +1 -0
  197. package/dist/lib/utils/providerConfig.js +1 -0
  198. package/dist/lib/utils/providerHealth.js +1 -0
  199. package/dist/lib/utils/providerSetupMessages.js +1 -0
  200. package/dist/lib/utils/providerUtils.js +1 -0
  201. package/dist/lib/utils/redis.js +1 -0
  202. package/dist/lib/utils/retryHandler.js +1 -0
  203. package/dist/lib/utils/schemaConversion.js +1 -0
  204. package/dist/lib/utils/taskClassificationUtils.js +1 -0
  205. package/dist/lib/utils/taskClassifier.js +1 -0
  206. package/dist/lib/utils/timeout.js +1 -0
  207. package/dist/lib/utils/tokenLimits.js +1 -0
  208. package/dist/lib/utils/toolUtils.js +1 -0
  209. package/dist/lib/utils/transformationUtils.js +1 -0
  210. package/dist/lib/utils/typeUtils.js +1 -0
  211. package/dist/mcp/mcpClientFactory.js +1 -1
  212. package/dist/mcp/servers/agent/directToolsServer.js +1 -0
  213. package/dist/models/modelResolver.js +1 -0
  214. package/dist/neurolink.d.ts +6 -0
  215. package/dist/neurolink.js +134 -5
  216. package/dist/providers/amazonBedrock.d.ts +1 -0
  217. package/dist/providers/amazonBedrock.js +165 -14
  218. package/dist/providers/anthropic.js +6 -21
  219. package/dist/providers/azureOpenai.js +4 -21
  220. package/dist/providers/googleAiStudio.js +4 -21
  221. package/dist/providers/googleVertex.js +7 -1
  222. package/dist/providers/huggingFace.js +33 -3
  223. package/dist/providers/litellm.js +33 -3
  224. package/dist/providers/mistral.js +31 -2
  225. package/dist/providers/ollama.d.ts +37 -1
  226. package/dist/providers/ollama.js +543 -58
  227. package/dist/providers/openAI.js +4 -21
  228. package/dist/providers/openaiCompatible.js +40 -4
  229. package/dist/sdk/toolRegistration.js +1 -0
  230. package/dist/types/content.d.ts +14 -1
  231. package/dist/types/fileTypes.d.ts +44 -0
  232. package/dist/types/generateTypes.d.ts +1 -0
  233. package/dist/types/providers.d.ts +44 -0
  234. package/dist/types/streamTypes.d.ts +1 -0
  235. package/dist/types/tools.js +1 -0
  236. package/dist/utils/fileDetector.js +6 -3
  237. package/dist/utils/messageBuilder.js +95 -9
  238. package/dist/utils/multimodalOptionsBuilder.d.ts +67 -0
  239. package/dist/utils/multimodalOptionsBuilder.js +64 -0
  240. package/dist/utils/pdfProcessor.d.ts +10 -0
  241. package/dist/utils/pdfProcessor.js +198 -0
  242. package/package.json +11 -20
@@ -138,3 +138,4 @@ export function convertJsonSchemaToZod(jsonSchema) {
138
138
  return z.object({}).passthrough();
139
139
  }
140
140
  }
141
+ //# sourceMappingURL=schemaConversion.js.map
@@ -147,3 +147,4 @@ export function analyzePrompt(prompt) {
147
147
  reasoningScore += domainScores.reasoningScore;
148
148
  return { fastScore, reasoningScore, reasons };
149
149
  }
150
+ //# sourceMappingURL=taskClassificationUtils.js.map
@@ -92,3 +92,4 @@ export class BinaryTaskClassifier {
92
92
  return { correct, classification };
93
93
  }
94
94
  }
95
+ //# sourceMappingURL=taskClassifier.js.map
@@ -342,3 +342,4 @@ export function mergeAbortSignals(signals) {
342
342
  }
343
343
  return controller;
344
344
  }
345
+ //# sourceMappingURL=timeout.js.map
@@ -123,3 +123,4 @@ export function getAllProviderLimits() {
123
123
  }
124
124
  return result;
125
125
  }
126
+ //# sourceMappingURL=tokenLimits.js.map
@@ -58,3 +58,4 @@ export function getMaxToolsPerProvider(toolConfig) {
58
58
  }
59
59
  return 100; // Default
60
60
  }
61
+ //# sourceMappingURL=toolUtils.js.map
@@ -563,3 +563,4 @@ export function optimizeToolForCollection(tool, defaults) {
563
563
  }
564
564
  return optimizedTool;
565
565
  }
566
+ //# sourceMappingURL=transformationUtils.js.map
@@ -95,3 +95,4 @@ export function isNullish(value) {
95
95
  export function isDefined(value) {
96
96
  return value !== undefined;
97
97
  }
98
+ //# sourceMappingURL=typeUtils.js.map
@@ -7,7 +7,7 @@ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
7
7
  import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
8
8
  import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
9
9
  import { WebSocketClientTransport } from "@modelcontextprotocol/sdk/client/websocket.js";
10
- import { spawn } from "child_process";
10
+ import { spawn, ChildProcess } from "child_process";
11
11
  import { mcpLogger } from "../utils/logger.js";
12
12
  import { globalCircuitBreakerManager } from "./mcpCircuitBreaker.js";
13
13
  /**
@@ -2,6 +2,7 @@
2
2
  * NeuroLink Direct Tools Server
3
3
  * Wraps the agent direct tools as an MCP server for proper registration
4
4
  */
5
+ import { z } from "zod";
5
6
  import { createMCPServer } from "../../factory.js";
6
7
  import { directAgentTools } from "../../../agent/directTools.js";
7
8
  import { logger } from "../../../utils/logger.js";
@@ -3,6 +3,7 @@
3
3
  * Provides model resolution, search, and recommendation functionality
4
4
  * Part of Phase 4.1 - Models Command System
5
5
  */
6
+ import { AIProviderName } from "../types/index.js";
6
7
  import { MODEL_REGISTRY, MODEL_ALIASES, USE_CASE_RECOMMENDATIONS, getAllModels, getModelById, getModelsByProvider, getAvailableProviders, calculateCost, formatModelForDisplay, } from "./modelRegistry.js";
7
8
  import { isNonNullObject } from "../utils/typeUtils.js";
8
9
  /**
@@ -1076,6 +1076,12 @@ export declare class NeuroLink {
1076
1076
  * Unregister all external MCP tools from the main registry
1077
1077
  */
1078
1078
  private unregisterAllExternalMCPToolsFromRegistry;
1079
+ /**
1080
+ * Dispose of all resources and cleanup connections
1081
+ * Call this method when done using the NeuroLink instance to prevent resource leaks
1082
+ * Especially important in test environments where multiple instances are created
1083
+ */
1084
+ dispose(): Promise<void>;
1079
1085
  }
1080
1086
  export declare const neurolink: NeuroLink;
1081
1087
  export default neurolink;
package/dist/neurolink.js CHANGED
@@ -31,6 +31,8 @@ import { transformToolExecutions, transformToolExecutionsForMCP, transformAvaila
31
31
  // Enhanced error handling imports
32
32
  import { ErrorFactory, NeuroLinkError, withTimeout, withRetry, isRetriableError, logStructuredError, CircuitBreaker, } from "./utils/errorHandling.js";
33
33
  import { EventEmitter } from "events";
34
+ import { ConversationMemoryManager } from "./core/conversationMemoryManager.js";
35
+ import { RedisConversationMemoryManager } from "./core/redisConversationMemoryManager.js";
34
36
  import { getConversationMessages, storeConversationTurn, } from "./utils/conversationMemory.js";
35
37
  import { ExternalServerManager } from "./mcp/externalServerManager.js";
36
38
  import { HITLManager } from "./hitl/hitlManager.js";
@@ -2051,15 +2053,16 @@ export class NeuroLink {
2051
2053
  customTools: this.getCustomTools(),
2052
2054
  executeTool: this.executeTool.bind(this),
2053
2055
  }, "NeuroLink.createMCPStream");
2054
- // Get conversation messages for context by creating a minimal TextGenerationOptions object
2056
+ // Get conversation messages for context
2055
2057
  const conversationMessages = await getConversationMessages(this.conversationMemory, {
2056
2058
  prompt: options.input.text,
2057
2059
  context: options.context,
2058
2060
  });
2059
- // Pass conversation history to stream just like in generate method
2061
+ // Let provider handle tools and system prompt automatically via Vercel AI SDK
2062
+ // This ensures proper tool integration in stream mode
2060
2063
  const streamResult = await provider.stream({
2061
2064
  ...options,
2062
- conversationMessages, // Inject conversation history
2065
+ conversationMessages,
2063
2066
  });
2064
2067
  return { stream: streamResult.stream, provider: providerName };
2065
2068
  }
@@ -2120,7 +2123,7 @@ export class NeuroLink {
2120
2123
  const originalPrompt = options.input.text;
2121
2124
  const responseTime = Date.now() - startTime;
2122
2125
  const providerName = await getBestProvider(options.provider);
2123
- const provider = await AIProviderFactory.createProvider(providerName, options.model, false);
2126
+ const provider = await AIProviderFactory.createProvider(providerName, options.model);
2124
2127
  const fallbackStreamResult = await provider.stream({
2125
2128
  input: { text: options.input.text },
2126
2129
  model: options.model,
@@ -3330,7 +3333,7 @@ export class NeuroLink {
3330
3333
  */
3331
3334
  async testProviderConnection(providerName) {
3332
3335
  const { AIProviderFactory } = await import("./core/factory.js");
3333
- const provider = await AIProviderFactory.createProvider(providerName, null, false);
3336
+ const provider = await AIProviderFactory.createProvider(providerName, null);
3334
3337
  await provider.generate({
3335
3338
  prompt: "test",
3336
3339
  maxTokens: 1,
@@ -4132,6 +4135,132 @@ export class NeuroLink {
4132
4135
  mcpLogger.error("[NeuroLink] Failed to unregister all external MCP tools from registry:", error);
4133
4136
  }
4134
4137
  }
4138
+ /**
4139
+ * Dispose of all resources and cleanup connections
4140
+ * Call this method when done using the NeuroLink instance to prevent resource leaks
4141
+ * Especially important in test environments where multiple instances are created
4142
+ */
4143
+ async dispose() {
4144
+ logger.debug("[NeuroLink] Starting disposal of resources...");
4145
+ const cleanupErrors = [];
4146
+ try {
4147
+ // 1. Flush and shutdown OpenTelemetry
4148
+ try {
4149
+ logger.debug("[NeuroLink] Flushing and shutting down OpenTelemetry...");
4150
+ await flushOpenTelemetry();
4151
+ await shutdownOpenTelemetry();
4152
+ logger.debug("[NeuroLink] OpenTelemetry shutdown successfully");
4153
+ }
4154
+ catch (error) {
4155
+ const err = error instanceof Error
4156
+ ? error
4157
+ : new Error(`OpenTelemetry shutdown error: ${String(error)}`);
4158
+ cleanupErrors.push(err);
4159
+ logger.warn("[NeuroLink] Error shutting down OpenTelemetry:", error);
4160
+ }
4161
+ // 2. Shutdown external MCP server connections
4162
+ if (this.externalServerManager) {
4163
+ try {
4164
+ logger.debug("[NeuroLink] Shutting down external MCP servers...");
4165
+ await this.externalServerManager.shutdown();
4166
+ logger.debug("[NeuroLink] External MCP servers shutdown successfully");
4167
+ }
4168
+ catch (error) {
4169
+ const err = error instanceof Error
4170
+ ? error
4171
+ : new Error(`External server shutdown error: ${String(error)}`);
4172
+ cleanupErrors.push(err);
4173
+ logger.warn("[NeuroLink] Error shutting down external MCP servers:", error);
4174
+ }
4175
+ }
4176
+ // 3. Clear all event listeners to prevent memory leaks
4177
+ if (this.emitter) {
4178
+ try {
4179
+ logger.debug("[NeuroLink] Removing all event listeners...");
4180
+ this.emitter.removeAllListeners();
4181
+ logger.debug("[NeuroLink] Event listeners removed successfully");
4182
+ }
4183
+ catch (error) {
4184
+ const err = error instanceof Error
4185
+ ? error
4186
+ : new Error(`Event emitter cleanup error: ${String(error)}`);
4187
+ cleanupErrors.push(err);
4188
+ logger.warn("[NeuroLink] Error removing event listeners:", error);
4189
+ }
4190
+ }
4191
+ // 4. Clear all circuit breakers
4192
+ if (this.toolCircuitBreakers && this.toolCircuitBreakers.size > 0) {
4193
+ try {
4194
+ logger.debug(`[NeuroLink] Clearing ${this.toolCircuitBreakers.size} circuit breakers...`);
4195
+ this.toolCircuitBreakers.clear();
4196
+ logger.debug("[NeuroLink] Circuit breakers cleared successfully");
4197
+ }
4198
+ catch (error) {
4199
+ const err = error instanceof Error
4200
+ ? error
4201
+ : new Error(`Circuit breaker cleanup error: ${String(error)}`);
4202
+ cleanupErrors.push(err);
4203
+ logger.warn("[NeuroLink] Error clearing circuit breakers:", error);
4204
+ }
4205
+ }
4206
+ // 5. Clear all Maps and caches
4207
+ try {
4208
+ logger.debug("[NeuroLink] Clearing maps and caches...");
4209
+ if (this.toolExecutionMetrics) {
4210
+ this.toolExecutionMetrics.clear();
4211
+ }
4212
+ if (this.activeToolExecutions) {
4213
+ this.activeToolExecutions.clear();
4214
+ }
4215
+ if (this.currentStreamToolExecutions) {
4216
+ this.currentStreamToolExecutions.length = 0;
4217
+ }
4218
+ if (this.toolExecutionHistory) {
4219
+ this.toolExecutionHistory.length = 0;
4220
+ }
4221
+ // Clear tool cache
4222
+ if (this.toolCache) {
4223
+ this.toolCache.tools = [];
4224
+ this.toolCache.timestamp = 0;
4225
+ }
4226
+ logger.debug("[NeuroLink] Maps and caches cleared successfully");
4227
+ }
4228
+ catch (error) {
4229
+ const err = error instanceof Error
4230
+ ? error
4231
+ : new Error(`Cache cleanup error: ${String(error)}`);
4232
+ cleanupErrors.push(err);
4233
+ logger.warn("[NeuroLink] Error clearing caches:", error);
4234
+ }
4235
+ // 6. Reset initialization flags
4236
+ try {
4237
+ logger.debug("[NeuroLink] Resetting initialization state...");
4238
+ this.mcpInitialized = false;
4239
+ this.conversationMemoryNeedsInit = false;
4240
+ logger.debug("[NeuroLink] Initialization state reset successfully");
4241
+ }
4242
+ catch (error) {
4243
+ const err = error instanceof Error
4244
+ ? error
4245
+ : new Error(`State reset error: ${String(error)}`);
4246
+ cleanupErrors.push(err);
4247
+ logger.warn("[NeuroLink] Error resetting state:", error);
4248
+ }
4249
+ // 6. Log completion
4250
+ if (cleanupErrors.length === 0) {
4251
+ logger.debug("[NeuroLink] ✅ Resource disposal completed successfully");
4252
+ }
4253
+ else {
4254
+ logger.warn(`[NeuroLink] ⚠️ Resource disposal completed with ${cleanupErrors.length} errors`, {
4255
+ errors: cleanupErrors.map((e) => e.message),
4256
+ });
4257
+ }
4258
+ }
4259
+ catch (error) {
4260
+ logger.error("[NeuroLink] Critical error during disposal:", error);
4261
+ throw error;
4262
+ }
4263
+ }
4135
4264
  }
4136
4265
  // Create default instance
4137
4266
  export const neurolink = new NeuroLink();
@@ -24,6 +24,7 @@ export declare class AmazonBedrockProvider extends BaseProvider {
24
24
  private executeSingleTool;
25
25
  private convertAISDKToolsToToolDefinitions;
26
26
  private formatToolsForBedrock;
27
+ private convertToBedrockMessages;
27
28
  getBedrockClient(): BedrockRuntimeClient;
28
29
  protected executeStream(options: StreamOptions): Promise<StreamResult>;
29
30
  private streamingConversationLoop;
@@ -1,8 +1,12 @@
1
- import { BedrockRuntimeClient, ConverseCommand, ConverseStreamCommand, } from "@aws-sdk/client-bedrock-runtime";
1
+ import { BedrockRuntimeClient, ConverseCommand, ConverseStreamCommand, ImageFormat, } from "@aws-sdk/client-bedrock-runtime";
2
2
  import { BedrockClient, ListFoundationModelsCommand, } from "@aws-sdk/client-bedrock";
3
3
  import { BaseProvider } from "../core/baseProvider.js";
4
4
  import { logger } from "../utils/logger.js";
5
5
  import { convertZodToJsonSchema } from "../utils/schemaConversion.js";
6
+ import { buildMultimodalMessagesArray } from "../utils/messageBuilder.js";
7
+ import { buildMultimodalOptions } from "../utils/multimodalOptionsBuilder.js";
8
+ import { DEFAULT_MAX_STEPS } from "../core/constants.js";
9
+ import { createAnalytics } from "../core/analytics.js";
6
10
  // Bedrock-specific types now imported from ../types/providerSpecific.js
7
11
  export class AmazonBedrockProvider extends BaseProvider {
8
12
  bedrockClient;
@@ -349,6 +353,16 @@ export class AmazonBedrockProvider extends BaseProvider {
349
353
  text: item.text,
350
354
  };
351
355
  }
356
+ if (item.image) {
357
+ return {
358
+ image: item.image,
359
+ };
360
+ }
361
+ if (item.document) {
362
+ return {
363
+ document: item.document,
364
+ };
365
+ }
352
366
  if (item.toolUse) {
353
367
  return {
354
368
  toolUse: {
@@ -520,6 +534,73 @@ export class AmazonBedrockProvider extends BaseProvider {
520
534
  logger.debug(`[AmazonBedrockProvider] Formatted ${bedrockTools.length} tools for Bedrock`);
521
535
  return { tools: bedrockTools };
522
536
  }
537
+ // Convert multimodal messages to Bedrock format
538
+ convertToBedrockMessages(messages) {
539
+ return messages.map((msg) => {
540
+ const bedrockMessage = {
541
+ role: msg.role === "system" ? "user" : msg.role,
542
+ content: [],
543
+ };
544
+ if (typeof msg.content === "string") {
545
+ bedrockMessage.content.push({ text: msg.content });
546
+ }
547
+ else {
548
+ msg.content.forEach((contentItem) => {
549
+ if (contentItem.type === "text" && contentItem.text) {
550
+ bedrockMessage.content.push({ text: contentItem.text });
551
+ }
552
+ else if (contentItem.type === "image" && contentItem.image) {
553
+ const imageData = typeof contentItem.image === "string"
554
+ ? Buffer.from(contentItem.image.replace(/^data:image\/\w+;base64,/, ""), "base64")
555
+ : contentItem.image;
556
+ let format = contentItem.mimeType?.split("/")[1] || "png";
557
+ if (format === "jpg") {
558
+ format = "jpeg";
559
+ }
560
+ bedrockMessage.content.push({
561
+ image: {
562
+ format: format === "jpeg"
563
+ ? ImageFormat.JPEG
564
+ : format === "png"
565
+ ? ImageFormat.PNG
566
+ : format === "gif"
567
+ ? ImageFormat.GIF
568
+ : ImageFormat.WEBP,
569
+ source: {
570
+ bytes: imageData,
571
+ },
572
+ },
573
+ });
574
+ }
575
+ else if (contentItem.type === "document" ||
576
+ contentItem.type === "pdf" ||
577
+ (contentItem.type === "file" &&
578
+ contentItem.mimeType?.toLowerCase().startsWith("application/pdf"))) {
579
+ let docData;
580
+ if (typeof contentItem.data === "string") {
581
+ const pdfString = contentItem.data.replace(/^data:application\/pdf;base64,/i, "");
582
+ docData = Buffer.from(pdfString, "base64");
583
+ }
584
+ else {
585
+ docData = contentItem.data;
586
+ }
587
+ bedrockMessage.content.push({
588
+ document: {
589
+ format: "pdf",
590
+ name: typeof contentItem.name === "string" && contentItem.name
591
+ ? contentItem.name
592
+ : "document.pdf",
593
+ source: {
594
+ bytes: docData,
595
+ },
596
+ },
597
+ });
598
+ }
599
+ });
600
+ }
601
+ return bedrockMessage;
602
+ });
603
+ }
523
604
  // Bedrock-MCP-Connector compatibility
524
605
  getBedrockClient() {
525
606
  return this.bedrockClient;
@@ -529,16 +610,43 @@ export class AmazonBedrockProvider extends BaseProvider {
529
610
  logger.info("🚀 [AmazonBedrockProvider] Attempting real streaming with ConverseStreamCommand");
530
611
  try {
531
612
  logger.debug("🟢 [TRACE] executeStream TRY block - about to call streamingConversationLoop");
532
- // CRITICAL FIX: Initialize conversation history like generate() does
533
613
  // Clear conversation history for new streaming session
534
614
  this.conversationHistory = [];
535
- // Add user message to conversation - exactly like generate() does
536
- const userMessage = {
537
- role: "user",
538
- content: [{ text: options.input.text }],
539
- };
540
- this.conversationHistory.push(userMessage);
541
- logger.debug(`[AmazonBedrockProvider] Starting streaming conversation with prompt: ${options.input.text}`);
615
+ // Check for multimodal input (images, PDFs, CSVs, files)
616
+ const hasMultimodalInput = !!(options.input?.images?.length ||
617
+ options.input?.content?.length ||
618
+ options.input?.files?.length ||
619
+ options.input?.csvFiles?.length ||
620
+ options.input?.pdfFiles?.length);
621
+ if (hasMultimodalInput) {
622
+ logger.debug(`[AmazonBedrockProvider] Detected multimodal input, using multimodal message builder`, {
623
+ hasImages: !!options.input?.images?.length,
624
+ imageCount: options.input?.images?.length || 0,
625
+ hasContent: !!options.input?.content?.length,
626
+ contentCount: options.input?.content?.length || 0,
627
+ hasFiles: !!options.input?.files?.length,
628
+ fileCount: options.input?.files?.length || 0,
629
+ hasCSVFiles: !!options.input?.csvFiles?.length,
630
+ csvFileCount: options.input?.csvFiles?.length || 0,
631
+ hasPDFFiles: !!options.input?.pdfFiles?.length,
632
+ pdfFileCount: options.input?.pdfFiles?.length || 0,
633
+ });
634
+ const multimodalOptions = buildMultimodalOptions(options, this.providerName, this.modelName);
635
+ const multimodalMessages = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
636
+ // Convert to Bedrock format
637
+ this.conversationHistory =
638
+ this.convertToBedrockMessages(multimodalMessages);
639
+ }
640
+ else {
641
+ logger.debug(`[AmazonBedrockProvider] Text-only input, using simple message builder`);
642
+ // Add user message to conversation - simple text-only case
643
+ const userMessage = {
644
+ role: "user",
645
+ content: [{ text: options.input.text }],
646
+ };
647
+ this.conversationHistory.push(userMessage);
648
+ }
649
+ logger.debug(`[AmazonBedrockProvider] Starting streaming conversation with ${this.conversationHistory.length} message(s)`);
542
650
  // Call the actual streaming implementation that already exists
543
651
  logger.debug("🟢 [TRACE] executeStream - calling streamingConversationLoop NOW");
544
652
  const result = await this.streamingConversationLoop(options);
@@ -615,7 +723,8 @@ export class AmazonBedrockProvider extends BaseProvider {
615
723
  }
616
724
  async streamingConversationLoop(options) {
617
725
  logger.debug("🟦 [TRACE] streamingConversationLoop ENTRY");
618
- const maxIterations = 10;
726
+ const startTime = Date.now();
727
+ const maxIterations = options.maxSteps || DEFAULT_MAX_STEPS;
619
728
  let iteration = 0;
620
729
  // The REAL issue: ReadableStream errors don't bubble up to the caller
621
730
  // So we need to make the first streaming call synchronously to test permissions
@@ -650,7 +759,7 @@ export class AmazonBedrockProvider extends BaseProvider {
650
759
  logger.debug(`[AmazonBedrockProvider] Streaming iteration ${iteration}`);
651
760
  const commandInput = await this.prepareStreamCommand(options);
652
761
  const { stopReason, assistantMessage } = await this.processStreamResponse(commandInput, controller);
653
- const shouldContinue = await this.handleStreamStopReason(stopReason, assistantMessage, controller);
762
+ const shouldContinue = await this.handleStreamStopReason(stopReason, assistantMessage, controller, options);
654
763
  if (!shouldContinue) {
655
764
  break;
656
765
  }
@@ -665,11 +774,22 @@ export class AmazonBedrockProvider extends BaseProvider {
665
774
  }
666
775
  },
667
776
  });
777
+ // Create analytics promise (without token tracking for now due to AWS SDK limitations)
778
+ const analyticsPromise = Promise.resolve(createAnalytics(this.providerName, this.modelName || this.getDefaultModel(), { usage: { input: 0, output: 0, total: 0 } }, Date.now() - startTime, {
779
+ requestId: `bedrock-stream-${Date.now()}`,
780
+ streamingMode: true,
781
+ note: "Token usage not available from AWS SDK streaming responses",
782
+ }));
668
783
  return {
669
784
  stream: this.convertToAsyncIterable(stream),
670
785
  usage: { total: 0, input: 0, output: 0 },
671
786
  model: this.modelName || this.getDefaultModel(),
672
787
  provider: this.getProviderName(),
788
+ analytics: analyticsPromise,
789
+ metadata: {
790
+ startTime,
791
+ streamId: `bedrock-${Date.now()}`,
792
+ },
673
793
  };
674
794
  }
675
795
  catch (error) {
@@ -825,7 +945,7 @@ export class AmazonBedrockProvider extends BaseProvider {
825
945
  this.conversationHistory.push(assistantMessage);
826
946
  return { stopReason, assistantMessage };
827
947
  }
828
- async handleStreamStopReason(stopReason, assistantMessage, controller) {
948
+ async handleStreamStopReason(stopReason, assistantMessage, controller, options) {
829
949
  if (stopReason === "end_turn" || stopReason === "stop_sequence") {
830
950
  // Conversation completed
831
951
  controller.close();
@@ -833,7 +953,7 @@ export class AmazonBedrockProvider extends BaseProvider {
833
953
  }
834
954
  else if (stopReason === "tool_use") {
835
955
  logger.debug(`🛠️ [AmazonBedrockProvider] Tool use detected in streaming - executing tools`);
836
- await this.executeStreamTools(assistantMessage.content);
956
+ await this.executeStreamTools(assistantMessage.content, options);
837
957
  return true; // Continue conversation loop
838
958
  }
839
959
  else if (stopReason === "max_tokens") {
@@ -851,10 +971,13 @@ export class AmazonBedrockProvider extends BaseProvider {
851
971
  return false;
852
972
  }
853
973
  }
854
- async executeStreamTools(messageContent) {
974
+ async executeStreamTools(messageContent, options) {
855
975
  // Execute all tool uses in the message - ensure 1:1 mapping like Bedrock-MCP-Connector
856
976
  const toolResults = [];
857
977
  let toolUseCount = 0;
978
+ // Track tool calls and results for storage (similar to Vertex onStepFinish)
979
+ const toolCalls = [];
980
+ const toolResultsForStorage = [];
858
981
  // Count toolUse blocks first to ensure 1:1 mapping
859
982
  for (const contentItem of messageContent) {
860
983
  if (contentItem.toolUse) {
@@ -865,9 +988,23 @@ export class AmazonBedrockProvider extends BaseProvider {
865
988
  for (const contentItem of messageContent) {
866
989
  if (contentItem.toolUse) {
867
990
  logger.debug(`🔧 [AmazonBedrockProvider] Executing tool: ${contentItem.toolUse.name}`);
991
+ // Track tool call
992
+ toolCalls.push({
993
+ type: "tool-call",
994
+ toolCallId: contentItem.toolUse.toolUseId,
995
+ toolName: contentItem.toolUse.name,
996
+ args: contentItem.toolUse.input || {},
997
+ });
868
998
  try {
869
999
  const toolResult = await this.executeSingleTool(contentItem.toolUse.name, contentItem.toolUse.input || {}, contentItem.toolUse.toolUseId);
870
1000
  logger.debug(`✅ [AmazonBedrockProvider] Tool execution successful: ${contentItem.toolUse.name}`);
1001
+ // Track tool result for storage
1002
+ toolResultsForStorage.push({
1003
+ type: "tool-result",
1004
+ toolCallId: contentItem.toolUse.toolUseId,
1005
+ toolName: contentItem.toolUse.name,
1006
+ result: toolResult,
1007
+ });
871
1008
  // Ensure exact structure matching Bedrock-MCP-Connector
872
1009
  toolResults.push({
873
1010
  toolResult: {
@@ -880,6 +1017,13 @@ export class AmazonBedrockProvider extends BaseProvider {
880
1017
  catch (error) {
881
1018
  logger.error(`❌ [AmazonBedrockProvider] Tool execution failed: ${contentItem.toolUse.name}`, error);
882
1019
  const errorMessage = error instanceof Error ? error.message : String(error);
1020
+ // Track failed tool result
1021
+ toolResultsForStorage.push({
1022
+ type: "tool-result",
1023
+ toolCallId: contentItem.toolUse.toolUseId,
1024
+ toolName: contentItem.toolUse.name,
1025
+ result: { error: errorMessage },
1026
+ });
883
1027
  toolResults.push({
884
1028
  toolResult: {
885
1029
  toolUseId: contentItem.toolUse.toolUseId,
@@ -908,6 +1052,13 @@ export class AmazonBedrockProvider extends BaseProvider {
908
1052
  };
909
1053
  this.conversationHistory.push(userMessageWithToolResults);
910
1054
  logger.debug(`📤 [AmazonBedrockProvider] Added ${toolResults.length} tool results to conversation (1:1 mapping validated)`);
1055
+ // Store tool execution for analytics and debugging (similar to Vertex onStepFinish)
1056
+ this.handleToolExecutionStorage(toolCalls, toolResultsForStorage, options, new Date()).catch((error) => {
1057
+ logger.warn("[AmazonBedrockProvider] Failed to store tool executions", {
1058
+ provider: this.providerName,
1059
+ error: error instanceof Error ? error.message : String(error),
1060
+ });
1061
+ });
911
1062
  }
912
1063
  }
913
1064
  /**
@@ -8,6 +8,7 @@ import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } fro
8
8
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
9
9
  import { validateApiKey, createAnthropicConfig, getProviderModel, } from "../utils/providerConfig.js";
10
10
  import { buildMessagesArray, buildMultimodalMessagesArray, convertToCoreMessages, } from "../utils/messageBuilder.js";
11
+ import { buildMultimodalOptions } from "../utils/multimodalOptionsBuilder.js";
11
12
  import { createProxyFetch } from "../proxy/proxyFetch.js";
12
13
  // Configuration helpers - now using consolidated utility
13
14
  const getAnthropicApiKey = () => {
@@ -96,7 +97,8 @@ export class AnthropicProvider extends BaseProvider {
96
97
  const hasMultimodalInput = !!(options.input?.images?.length ||
97
98
  options.input?.content?.length ||
98
99
  options.input?.files?.length ||
99
- options.input?.csvFiles?.length);
100
+ options.input?.csvFiles?.length ||
101
+ options.input?.pdfFiles?.length);
100
102
  let messages;
101
103
  if (hasMultimodalInput) {
102
104
  logger.debug(`Anthropic: Detected multimodal input, using multimodal message builder`, {
@@ -108,27 +110,10 @@ export class AnthropicProvider extends BaseProvider {
108
110
  fileCount: options.input?.files?.length || 0,
109
111
  hasCSVFiles: !!options.input?.csvFiles?.length,
110
112
  csvFileCount: options.input?.csvFiles?.length || 0,
113
+ hasPDFFiles: !!options.input?.pdfFiles?.length,
114
+ pdfFileCount: options.input?.pdfFiles?.length || 0,
111
115
  });
112
- // Create multimodal options for buildMultimodalMessagesArray
113
- const multimodalOptions = {
114
- input: {
115
- text: options.input?.text || "",
116
- images: options.input?.images,
117
- content: options.input?.content,
118
- files: options.input?.files,
119
- csvFiles: options.input?.csvFiles,
120
- },
121
- csvOptions: options.csvOptions,
122
- systemPrompt: options.systemPrompt,
123
- conversationHistory: options.conversationMessages,
124
- provider: this.providerName,
125
- model: this.modelName,
126
- temperature: options.temperature,
127
- maxTokens: options.maxTokens,
128
- enableAnalytics: options.enableAnalytics,
129
- enableEvaluation: options.enableEvaluation,
130
- context: options.context,
131
- };
116
+ const multimodalOptions = buildMultimodalOptions(options, this.providerName, this.modelName);
132
117
  const mm = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
133
118
  // Convert multimodal messages to Vercel AI SDK format (CoreMessage[])
134
119
  messages = convertToCoreMessages(mm);
@@ -5,6 +5,7 @@ import { APIVersions } from "../types/providers.js";
5
5
  import { validateApiKey, createAzureAPIKeyConfig, createAzureEndpointConfig, } from "../utils/providerConfig.js";
6
6
  import { logger } from "../utils/logger.js";
7
7
  import { buildMessagesArray, buildMultimodalMessagesArray, convertToCoreMessages, } from "../utils/messageBuilder.js";
8
+ import { buildMultimodalOptions } from "../utils/multimodalOptionsBuilder.js";
8
9
  import { createProxyFetch } from "../proxy/proxyFetch.js";
9
10
  import { DEFAULT_MAX_STEPS } from "../core/constants.js";
10
11
  export class AzureOpenAIProvider extends BaseProvider {
@@ -113,7 +114,8 @@ export class AzureOpenAIProvider extends BaseProvider {
113
114
  const hasMultimodalInput = !!(options.input?.images?.length ||
114
115
  options.input?.content?.length ||
115
116
  options.input?.files?.length ||
116
- options.input?.csvFiles?.length);
117
+ options.input?.csvFiles?.length ||
118
+ options.input?.pdfFiles?.length);
117
119
  let messages;
118
120
  if (hasMultimodalInput) {
119
121
  logger.debug(`Azure OpenAI: Detected multimodal input, using multimodal message builder`, {
@@ -122,26 +124,7 @@ export class AzureOpenAIProvider extends BaseProvider {
122
124
  hasContent: !!options.input?.content?.length,
123
125
  contentCount: options.input?.content?.length || 0,
124
126
  });
125
- // Create multimodal options for buildMultimodalMessagesArray
126
- const multimodalOptions = {
127
- input: {
128
- text: options.input?.text || "",
129
- images: options.input?.images,
130
- content: options.input?.content,
131
- files: options.input?.files,
132
- csvFiles: options.input?.csvFiles,
133
- },
134
- csvOptions: options.csvOptions,
135
- systemPrompt: options.systemPrompt,
136
- conversationHistory: options.conversationMessages,
137
- provider: this.providerName,
138
- model: this.modelName,
139
- temperature: options.temperature,
140
- maxTokens: options.maxTokens,
141
- enableAnalytics: options.enableAnalytics,
142
- enableEvaluation: options.enableEvaluation,
143
- context: options.context,
144
- };
127
+ const multimodalOptions = buildMultimodalOptions(options, this.providerName, this.modelName);
145
128
  const mm = await buildMultimodalMessagesArray(multimodalOptions, this.providerName, this.modelName);
146
129
  // Convert multimodal messages to Vercel AI SDK format (CoreMessage[])
147
130
  messages = convertToCoreMessages(mm);