@juspay/neurolink 7.29.1 → 7.29.3

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 (234) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli/commands/config.d.ts +86 -86
  3. package/dist/cli/commands/mcp.js +64 -9
  4. package/dist/cli/commands/models.js +25 -21
  5. package/dist/cli/commands/ollama.js +2 -2
  6. package/dist/cli/factories/commandFactory.d.ts +9 -0
  7. package/dist/cli/factories/commandFactory.js +177 -83
  8. package/dist/cli/factories/ollamaCommandFactory.js +3 -1
  9. package/dist/cli/factories/sagemakerCommandFactory.js +3 -2
  10. package/dist/cli/index.d.ts +1 -1
  11. package/dist/cli/index.js +19 -11
  12. package/dist/cli/utils/envManager.js +5 -5
  13. package/dist/cli/utils/ollamaUtils.d.ts +12 -0
  14. package/dist/cli/utils/ollamaUtils.js +58 -42
  15. package/dist/config/configManager.js +5 -2
  16. package/dist/core/analytics.d.ts +2 -24
  17. package/dist/core/analytics.js +12 -17
  18. package/dist/core/baseProvider.d.ts +30 -1
  19. package/dist/core/baseProvider.js +180 -198
  20. package/dist/core/dynamicModels.d.ts +4 -4
  21. package/dist/core/dynamicModels.js +7 -7
  22. package/dist/core/evaluation.d.ts +9 -9
  23. package/dist/core/evaluation.js +117 -65
  24. package/dist/core/evaluationProviders.d.ts +18 -2
  25. package/dist/core/evaluationProviders.js +15 -13
  26. package/dist/core/factory.js +77 -4
  27. package/dist/core/modelConfiguration.d.ts +63 -0
  28. package/dist/core/modelConfiguration.js +354 -290
  29. package/dist/core/streamAnalytics.d.ts +10 -5
  30. package/dist/core/streamAnalytics.js +10 -10
  31. package/dist/core/types.d.ts +19 -109
  32. package/dist/core/types.js +13 -0
  33. package/dist/factories/providerFactory.js +4 -1
  34. package/dist/factories/providerRegistry.js +2 -2
  35. package/dist/index.d.ts +2 -1
  36. package/dist/lib/config/configManager.js +5 -2
  37. package/dist/lib/core/analytics.d.ts +2 -24
  38. package/dist/lib/core/analytics.js +12 -17
  39. package/dist/lib/core/baseProvider.d.ts +30 -1
  40. package/dist/lib/core/baseProvider.js +180 -198
  41. package/dist/lib/core/dynamicModels.js +7 -7
  42. package/dist/lib/core/evaluation.d.ts +9 -9
  43. package/dist/lib/core/evaluation.js +117 -65
  44. package/dist/lib/core/evaluationProviders.d.ts +18 -2
  45. package/dist/lib/core/evaluationProviders.js +15 -13
  46. package/dist/lib/core/factory.js +77 -4
  47. package/dist/lib/core/modelConfiguration.d.ts +63 -0
  48. package/dist/lib/core/modelConfiguration.js +354 -290
  49. package/dist/lib/core/streamAnalytics.d.ts +10 -5
  50. package/dist/lib/core/streamAnalytics.js +10 -10
  51. package/dist/lib/core/types.d.ts +19 -109
  52. package/dist/lib/core/types.js +13 -0
  53. package/dist/lib/factories/providerFactory.js +4 -1
  54. package/dist/lib/factories/providerRegistry.js +2 -2
  55. package/dist/lib/index.d.ts +2 -1
  56. package/dist/lib/mcp/externalServerManager.js +14 -6
  57. package/dist/lib/mcp/factory.js +1 -1
  58. package/dist/lib/mcp/flexibleToolValidator.d.ts +50 -0
  59. package/dist/lib/mcp/flexibleToolValidator.js +161 -0
  60. package/dist/lib/mcp/index.d.ts +1 -1
  61. package/dist/lib/mcp/index.js +1 -1
  62. package/dist/lib/mcp/mcpCircuitBreaker.js +5 -1
  63. package/dist/lib/mcp/mcpClientFactory.js +3 -0
  64. package/dist/lib/mcp/registry.d.ts +3 -3
  65. package/dist/lib/mcp/registry.js +3 -3
  66. package/dist/lib/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
  67. package/dist/lib/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
  68. package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -1
  69. package/dist/lib/mcp/toolDiscoveryService.js +8 -2
  70. package/dist/lib/mcp/toolRegistry.d.ts +2 -2
  71. package/dist/lib/mcp/toolRegistry.js +29 -54
  72. package/dist/lib/middleware/builtin/analytics.js +4 -4
  73. package/dist/lib/middleware/builtin/guardrails.js +2 -2
  74. package/dist/lib/middleware/registry.js +11 -2
  75. package/dist/lib/models/modelRegistry.d.ts +1 -1
  76. package/dist/lib/models/modelRegistry.js +3 -3
  77. package/dist/lib/models/modelResolver.d.ts +1 -1
  78. package/dist/lib/models/modelResolver.js +2 -2
  79. package/dist/lib/neurolink.d.ts +118 -0
  80. package/dist/lib/neurolink.js +814 -952
  81. package/dist/lib/providers/amazonBedrock.d.ts +47 -6
  82. package/dist/lib/providers/amazonBedrock.js +282 -23
  83. package/dist/lib/providers/amazonSagemaker.d.ts +1 -1
  84. package/dist/lib/providers/amazonSagemaker.js +12 -3
  85. package/dist/lib/providers/anthropic.d.ts +1 -1
  86. package/dist/lib/providers/anthropic.js +7 -6
  87. package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
  88. package/dist/lib/providers/anthropicBaseProvider.js +4 -3
  89. package/dist/lib/providers/aws/credentialProvider.d.ts +58 -0
  90. package/dist/lib/providers/aws/credentialProvider.js +267 -0
  91. package/dist/lib/providers/aws/credentialTester.d.ts +49 -0
  92. package/dist/lib/providers/aws/credentialTester.js +394 -0
  93. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  94. package/dist/lib/providers/azureOpenai.js +1 -1
  95. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  96. package/dist/lib/providers/googleAiStudio.js +2 -2
  97. package/dist/lib/providers/googleVertex.d.ts +40 -0
  98. package/dist/lib/providers/googleVertex.js +330 -274
  99. package/dist/lib/providers/huggingFace.js +1 -1
  100. package/dist/lib/providers/mistral.d.ts +1 -1
  101. package/dist/lib/providers/mistral.js +2 -2
  102. package/dist/lib/providers/ollama.d.ts +4 -0
  103. package/dist/lib/providers/ollama.js +38 -18
  104. package/dist/lib/providers/openAI.d.ts +1 -1
  105. package/dist/lib/providers/openAI.js +2 -2
  106. package/dist/lib/providers/sagemaker/adaptive-semaphore.js +7 -4
  107. package/dist/lib/providers/sagemaker/client.js +13 -3
  108. package/dist/lib/providers/sagemaker/config.js +5 -1
  109. package/dist/lib/providers/sagemaker/detection.js +19 -9
  110. package/dist/lib/providers/sagemaker/errors.d.ts +8 -1
  111. package/dist/lib/providers/sagemaker/errors.js +103 -20
  112. package/dist/lib/providers/sagemaker/language-model.d.ts +3 -3
  113. package/dist/lib/providers/sagemaker/language-model.js +4 -4
  114. package/dist/lib/providers/sagemaker/parsers.js +14 -6
  115. package/dist/lib/providers/sagemaker/streaming.js +14 -3
  116. package/dist/lib/providers/sagemaker/types.d.ts +1 -1
  117. package/dist/lib/proxy/awsProxyIntegration.d.ts +23 -0
  118. package/dist/lib/proxy/awsProxyIntegration.js +285 -0
  119. package/dist/lib/proxy/proxyFetch.d.ts +9 -5
  120. package/dist/lib/proxy/proxyFetch.js +232 -98
  121. package/dist/lib/proxy/utils/noProxyUtils.d.ts +39 -0
  122. package/dist/lib/proxy/utils/noProxyUtils.js +149 -0
  123. package/dist/lib/sdk/toolRegistration.d.ts +1 -1
  124. package/dist/lib/types/cli.d.ts +80 -8
  125. package/dist/lib/types/contextTypes.js +2 -2
  126. package/dist/lib/types/generateTypes.d.ts +4 -6
  127. package/dist/lib/types/providers.d.ts +124 -19
  128. package/dist/lib/types/providers.js +6 -6
  129. package/dist/lib/types/streamTypes.d.ts +4 -6
  130. package/dist/lib/types/typeAliases.d.ts +1 -1
  131. package/dist/lib/utils/analyticsUtils.d.ts +33 -0
  132. package/dist/lib/utils/analyticsUtils.js +76 -0
  133. package/dist/lib/utils/errorHandling.js +4 -1
  134. package/dist/lib/utils/evaluationUtils.d.ts +27 -0
  135. package/dist/lib/utils/evaluationUtils.js +131 -0
  136. package/dist/lib/utils/optionsUtils.js +10 -1
  137. package/dist/lib/utils/performance.d.ts +1 -1
  138. package/dist/lib/utils/performance.js +15 -3
  139. package/dist/lib/utils/providerConfig.d.ts +1 -0
  140. package/dist/lib/utils/providerConfig.js +2 -1
  141. package/dist/lib/utils/providerHealth.d.ts +48 -0
  142. package/dist/lib/utils/providerHealth.js +221 -158
  143. package/dist/lib/utils/providerUtils.js +2 -2
  144. package/dist/lib/utils/timeout.js +8 -3
  145. package/dist/mcp/externalServerManager.js +14 -6
  146. package/dist/mcp/factory.js +1 -1
  147. package/dist/mcp/flexibleToolValidator.d.ts +50 -0
  148. package/dist/mcp/flexibleToolValidator.js +161 -0
  149. package/dist/mcp/index.d.ts +1 -1
  150. package/dist/mcp/index.js +1 -1
  151. package/dist/mcp/mcpCircuitBreaker.js +5 -1
  152. package/dist/mcp/mcpClientFactory.js +3 -0
  153. package/dist/mcp/registry.d.ts +3 -3
  154. package/dist/mcp/registry.js +3 -3
  155. package/dist/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
  156. package/dist/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
  157. package/dist/mcp/servers/utilities/utilityServer.js +1 -1
  158. package/dist/mcp/toolDiscoveryService.js +8 -2
  159. package/dist/mcp/toolRegistry.d.ts +2 -2
  160. package/dist/mcp/toolRegistry.js +29 -54
  161. package/dist/middleware/builtin/analytics.js +4 -4
  162. package/dist/middleware/builtin/guardrails.js +2 -2
  163. package/dist/middleware/registry.js +11 -2
  164. package/dist/models/modelRegistry.d.ts +1 -1
  165. package/dist/models/modelRegistry.js +3 -3
  166. package/dist/models/modelResolver.d.ts +1 -1
  167. package/dist/models/modelResolver.js +2 -2
  168. package/dist/neurolink.d.ts +118 -0
  169. package/dist/neurolink.js +814 -952
  170. package/dist/providers/amazonBedrock.d.ts +47 -6
  171. package/dist/providers/amazonBedrock.js +282 -23
  172. package/dist/providers/amazonSagemaker.d.ts +1 -1
  173. package/dist/providers/amazonSagemaker.js +12 -3
  174. package/dist/providers/anthropic.d.ts +1 -1
  175. package/dist/providers/anthropic.js +7 -6
  176. package/dist/providers/anthropicBaseProvider.d.ts +1 -1
  177. package/dist/providers/anthropicBaseProvider.js +4 -3
  178. package/dist/providers/aws/credentialProvider.d.ts +58 -0
  179. package/dist/providers/aws/credentialProvider.js +267 -0
  180. package/dist/providers/aws/credentialTester.d.ts +49 -0
  181. package/dist/providers/aws/credentialTester.js +394 -0
  182. package/dist/providers/azureOpenai.d.ts +1 -1
  183. package/dist/providers/azureOpenai.js +1 -1
  184. package/dist/providers/googleAiStudio.d.ts +1 -1
  185. package/dist/providers/googleAiStudio.js +2 -2
  186. package/dist/providers/googleVertex.d.ts +40 -0
  187. package/dist/providers/googleVertex.js +330 -274
  188. package/dist/providers/huggingFace.js +1 -1
  189. package/dist/providers/mistral.d.ts +1 -1
  190. package/dist/providers/mistral.js +2 -2
  191. package/dist/providers/ollama.d.ts +4 -0
  192. package/dist/providers/ollama.js +38 -18
  193. package/dist/providers/openAI.d.ts +1 -1
  194. package/dist/providers/openAI.js +2 -2
  195. package/dist/providers/sagemaker/adaptive-semaphore.js +7 -4
  196. package/dist/providers/sagemaker/client.js +13 -3
  197. package/dist/providers/sagemaker/config.js +5 -1
  198. package/dist/providers/sagemaker/detection.js +19 -9
  199. package/dist/providers/sagemaker/errors.d.ts +8 -1
  200. package/dist/providers/sagemaker/errors.js +103 -20
  201. package/dist/providers/sagemaker/language-model.d.ts +3 -3
  202. package/dist/providers/sagemaker/language-model.js +4 -4
  203. package/dist/providers/sagemaker/parsers.js +14 -6
  204. package/dist/providers/sagemaker/streaming.js +14 -3
  205. package/dist/providers/sagemaker/types.d.ts +1 -1
  206. package/dist/proxy/awsProxyIntegration.d.ts +23 -0
  207. package/dist/proxy/awsProxyIntegration.js +285 -0
  208. package/dist/proxy/proxyFetch.d.ts +9 -5
  209. package/dist/proxy/proxyFetch.js +232 -98
  210. package/dist/proxy/utils/noProxyUtils.d.ts +39 -0
  211. package/dist/proxy/utils/noProxyUtils.js +149 -0
  212. package/dist/sdk/toolRegistration.d.ts +1 -1
  213. package/dist/types/cli.d.ts +80 -8
  214. package/dist/types/contextTypes.js +2 -2
  215. package/dist/types/generateTypes.d.ts +4 -6
  216. package/dist/types/providers.d.ts +124 -19
  217. package/dist/types/providers.js +6 -6
  218. package/dist/types/streamTypes.d.ts +4 -6
  219. package/dist/types/typeAliases.d.ts +1 -1
  220. package/dist/utils/analyticsUtils.d.ts +33 -0
  221. package/dist/utils/analyticsUtils.js +76 -0
  222. package/dist/utils/errorHandling.js +4 -1
  223. package/dist/utils/evaluationUtils.d.ts +27 -0
  224. package/dist/utils/evaluationUtils.js +131 -0
  225. package/dist/utils/optionsUtils.js +10 -1
  226. package/dist/utils/performance.d.ts +1 -1
  227. package/dist/utils/performance.js +15 -3
  228. package/dist/utils/providerConfig.d.ts +1 -0
  229. package/dist/utils/providerConfig.js +2 -1
  230. package/dist/utils/providerHealth.d.ts +48 -0
  231. package/dist/utils/providerHealth.js +221 -158
  232. package/dist/utils/providerUtils.js +2 -2
  233. package/dist/utils/timeout.js +8 -3
  234. package/package.json +5 -1
package/dist/neurolink.js CHANGED
@@ -10,7 +10,7 @@ import { config as dotenvConfig } from "dotenv";
10
10
  try {
11
11
  dotenvConfig(); // Load .env from current working directory
12
12
  }
13
- catch (error) {
13
+ catch {
14
14
  // Environment variables should be set externally in production
15
15
  }
16
16
  import { AIProviderFactory } from "./core/factory.js";
@@ -24,6 +24,7 @@ import { ProviderRegistry } from "./factories/providerRegistry.js";
24
24
  import { createCustomToolServerInfo, detectCategory, } from "./utils/mcpDefaults.js";
25
25
  // Factory processing imports
26
26
  import { processFactoryOptions, enhanceTextGenerationOptions, validateFactoryConfig, processStreamingFactoryOptions, createCleanStreamOptions, } from "./utils/factoryProcessing.js";
27
+ // Tool detection and execution imports
27
28
  // Transformation utilities
28
29
  import { transformToolExecutions, transformToolExecutionsForMCP, transformAvailableTools, transformToolsForMCP, transformToolsToExpectedFormat, transformToolsToDescriptions, extractToolNames, transformParamsForLogging, optimizeToolForCollection, } from "./utils/transformationUtils.js";
29
30
  // Enhanced error handling imports
@@ -54,14 +55,21 @@ export class NeuroLink {
54
55
  * @param toolName - Name of the tool
55
56
  * @param startTime - Timestamp when tool execution started
56
57
  * @param success - Whether the tool execution was successful
58
+ * @param result - The result of the tool execution (optional)
59
+ * @param error - The error if execution failed (optional)
57
60
  */
58
- emitToolEndEvent(toolName, startTime, success) {
61
+ emitToolEndEvent(toolName, startTime, success, result, error) {
62
+ // Emit tool end event (NeuroLink format - enhanced with result/error)
59
63
  this.emitter.emit("tool:end", {
60
64
  toolName,
61
65
  responseTime: Date.now() - startTime,
62
66
  success,
63
67
  timestamp: Date.now(),
68
+ result: result, // Enhanced: include actual result
69
+ error: error, // Enhanced: include error if present
64
70
  });
71
+ // ADD: Bedrock-compatible tool:end event (positional parameters)
72
+ this.emitter.emit("tool:end", toolName, success ? result : error);
65
73
  }
66
74
  // Conversation memory support
67
75
  conversationMemory;
@@ -94,42 +102,50 @@ export class NeuroLink {
94
102
  * @throws {Error} When external server manager initialization fails
95
103
  */
96
104
  constructor(config) {
97
- // 🚀 EXHAUSTIVE LOGGING POINT C001: CONSTRUCTOR ENTRY
98
105
  const constructorStartTime = Date.now();
99
106
  const constructorHrTimeStart = process.hrtime.bigint();
100
107
  const constructorId = `neurolink-constructor-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
108
+ this.logConstructorStart(constructorId, constructorStartTime, constructorHrTimeStart, config);
109
+ this.initializeProviderRegistry(constructorId, constructorStartTime, constructorHrTimeStart);
110
+ this.initializeConversationMemory(config, constructorId, constructorStartTime, constructorHrTimeStart);
111
+ this.initializeExternalServerManager(constructorId, constructorStartTime, constructorHrTimeStart);
112
+ this.logConstructorComplete(constructorId, constructorStartTime, constructorHrTimeStart);
113
+ }
114
+ /**
115
+ * Log constructor start with comprehensive environment analysis
116
+ */
117
+ logConstructorStart(constructorId, constructorStartTime, constructorHrTimeStart, config) {
101
118
  logger.debug(`[NeuroLink] 🏗️ LOG_POINT_C001_CONSTRUCTOR_START`, {
102
119
  logPoint: "C001_CONSTRUCTOR_START",
103
120
  constructorId,
104
121
  timestamp: new Date().toISOString(),
105
122
  constructorStartTime,
106
123
  constructorHrTimeStart: constructorHrTimeStart.toString(),
107
- // Configuration analysis
108
124
  hasConfig: !!config,
109
125
  configType: typeof config,
110
126
  configKeys: config ? Object.keys(config) : [],
111
127
  configSize: config ? JSON.stringify(config).length : 0,
112
- // Conversation memory config analysis
113
128
  hasConversationMemoryConfig: !!config?.conversationMemory,
114
129
  conversationMemoryEnabled: config?.conversationMemory?.enabled || false,
115
130
  conversationMemoryKeys: config?.conversationMemory
116
131
  ? Object.keys(config.conversationMemory)
117
132
  : [],
118
- // Environment context
119
133
  nodeVersion: process.version,
120
134
  platform: process.platform,
121
135
  arch: process.arch,
122
136
  nodeEnv: process.env.NODE_ENV || "UNKNOWN",
123
- // Memory and performance baseline
124
137
  memoryUsage: process.memoryUsage(),
125
138
  cpuUsage: process.cpuUsage(),
126
139
  uptime: process.uptime(),
127
- // Process PID and parent info
128
140
  pid: process.pid,
129
141
  ppid: process.ppid,
130
142
  message: "NeuroLink constructor initialization starting with comprehensive environment analysis",
131
143
  });
132
- // 🚀 EXHAUSTIVE LOGGING POINT C002: PROVIDER REGISTRY SETUP
144
+ }
145
+ /**
146
+ * Initialize provider registry with security settings
147
+ */
148
+ initializeProviderRegistry(constructorId, constructorStartTime, constructorHrTimeStart) {
133
149
  const registrySetupStartTime = process.hrtime.bigint();
134
150
  logger.debug(`[NeuroLink] 🏗️ LOG_POINT_C002_PROVIDER_REGISTRY_SETUP_START`, {
135
151
  logPoint: "C002_PROVIDER_REGISTRY_SETUP_START",
@@ -140,11 +156,8 @@ export class NeuroLink {
140
156
  registrySetupStartTimeNs: registrySetupStartTime.toString(),
141
157
  message: "Starting ProviderRegistry configuration for security",
142
158
  });
143
- // SDK always disables manual MCP config for security
144
159
  try {
145
- ProviderRegistry.setOptions({
146
- enableManualMCP: false,
147
- });
160
+ ProviderRegistry.setOptions({ enableManualMCP: false });
148
161
  const registrySetupEndTime = process.hrtime.bigint();
149
162
  const registrySetupDurationNs = registrySetupEndTime - registrySetupStartTime;
150
163
  logger.debug(`[NeuroLink] ✅ LOG_POINT_C003_PROVIDER_REGISTRY_SETUP_SUCCESS`, {
@@ -177,7 +190,11 @@ export class NeuroLink {
177
190
  });
178
191
  throw error;
179
192
  }
180
- // 🚀 EXHAUSTIVE LOGGING POINT C005: CONVERSATION MEMORY INITIALIZATION
193
+ }
194
+ /**
195
+ * Initialize conversation memory if enabled
196
+ */
197
+ initializeConversationMemory(config, constructorId, constructorStartTime, constructorHrTimeStart) {
181
198
  if (config?.conversationMemory?.enabled) {
182
199
  const memoryInitStartTime = process.hrtime.bigint();
183
200
  logger.debug(`[NeuroLink] 🧠 LOG_POINT_C005_MEMORY_INIT_START`, {
@@ -187,7 +204,6 @@ export class NeuroLink {
187
204
  elapsedMs: Date.now() - constructorStartTime,
188
205
  elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
189
206
  memoryInitStartTimeNs: memoryInitStartTime.toString(),
190
- // Detailed memory config analysis
191
207
  memoryConfig: {
192
208
  enabled: config.conversationMemory.enabled,
193
209
  maxSessions: config.conversationMemory.maxSessions,
@@ -214,12 +230,10 @@ export class NeuroLink {
214
230
  memoryInitDurationMs: Number(memoryInitDurationNs) / 1000000,
215
231
  memoryManagerCreateDurationNs: memoryManagerCreateDurationNs.toString(),
216
232
  memoryManagerCreateDurationMs: Number(memoryManagerCreateDurationNs) / 1000000,
217
- // Final memory configuration
218
233
  finalMemoryConfig: {
219
234
  maxSessions: memoryConfig.maxSessions,
220
235
  maxTurnsPerSession: memoryConfig.maxTurnsPerSession,
221
236
  },
222
- // Memory usage after initialization
223
237
  memoryUsageAfterInit: process.memoryUsage(),
224
238
  message: "NeuroLink initialized with conversation memory successfully",
225
239
  });
@@ -264,7 +278,11 @@ export class NeuroLink {
264
278
  message: "Conversation memory not enabled - skipping initialization",
265
279
  });
266
280
  }
267
- // 🚀 EXHAUSTIVE LOGGING POINT C009: EXTERNAL SERVER MANAGER INITIALIZATION
281
+ }
282
+ /**
283
+ * Initialize external server manager with event handlers
284
+ */
285
+ initializeExternalServerManager(constructorId, constructorStartTime, constructorHrTimeStart) {
268
286
  const externalServerInitStartTime = process.hrtime.bigint();
269
287
  logger.debug(`[NeuroLink] 🌐 LOG_POINT_C009_EXTERNAL_SERVER_INIT_START`, {
270
288
  logPoint: "C009_EXTERNAL_SERVER_INIT_START",
@@ -285,14 +303,13 @@ export class NeuroLink {
285
303
  message: "Starting external server manager initialization",
286
304
  });
287
305
  try {
288
- // Initialize external server manager with main registry integration
289
306
  this.externalServerManager = new ExternalServerManager({
290
307
  maxServers: 20,
291
308
  defaultTimeout: 15000,
292
309
  enableAutoRestart: true,
293
310
  enablePerformanceMonitoring: true,
294
311
  }, {
295
- enableMainRegistryIntegration: true, // Enable integration with main toolRegistry
312
+ enableMainRegistryIntegration: true,
296
313
  });
297
314
  const externalServerInitEndTime = process.hrtime.bigint();
298
315
  const externalServerInitDurationNs = externalServerInitEndTime - externalServerInitStartTime;
@@ -307,93 +324,7 @@ export class NeuroLink {
307
324
  hasExternalServerManager: !!this.externalServerManager,
308
325
  message: "External server manager initialized successfully",
309
326
  });
310
- // 🚀 EXHAUSTIVE LOGGING POINT C011: EVENT HANDLER SETUP
311
- const eventHandlerSetupStartTime = process.hrtime.bigint();
312
- logger.debug(`[NeuroLink] 🔗 LOG_POINT_C011_EVENT_HANDLER_SETUP_START`, {
313
- logPoint: "C011_EVENT_HANDLER_SETUP_START",
314
- constructorId,
315
- timestamp: new Date().toISOString(),
316
- elapsedMs: Date.now() - constructorStartTime,
317
- elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
318
- eventHandlerSetupStartTimeNs: eventHandlerSetupStartTime.toString(),
319
- message: "Setting up external server event handlers",
320
- });
321
- // Forward external server events with detailed logging
322
- this.externalServerManager.on("connected", (event) => {
323
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_CONNECTED`, {
324
- constructorId,
325
- eventType: "connected",
326
- event,
327
- timestamp: new Date().toISOString(),
328
- message: "External MCP server connected event received",
329
- });
330
- this.emitter.emit("externalMCP:serverConnected", event);
331
- });
332
- this.externalServerManager.on("disconnected", (event) => {
333
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_DISCONNECTED`, {
334
- constructorId,
335
- eventType: "disconnected",
336
- event,
337
- timestamp: new Date().toISOString(),
338
- message: "External MCP server disconnected event received",
339
- });
340
- this.emitter.emit("externalMCP:serverDisconnected", event);
341
- });
342
- this.externalServerManager.on("failed", (event) => {
343
- logger.warn(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_FAILED`, {
344
- constructorId,
345
- eventType: "failed",
346
- event,
347
- timestamp: new Date().toISOString(),
348
- message: "External MCP server failed event received",
349
- });
350
- this.emitter.emit("externalMCP:serverFailed", event);
351
- });
352
- this.externalServerManager.on("toolDiscovered", (event) => {
353
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_DISCOVERED`, {
354
- constructorId,
355
- eventType: "toolDiscovered",
356
- toolName: event.toolName,
357
- serverId: event.serverId,
358
- timestamp: new Date().toISOString(),
359
- message: "External MCP tool discovered event received",
360
- });
361
- this.emitter.emit("externalMCP:toolDiscovered", event);
362
- // Tools are already registered on server connection, no need to duplicate here
363
- });
364
- this.externalServerManager.on("toolRemoved", (event) => {
365
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_REMOVED`, {
366
- constructorId,
367
- eventType: "toolRemoved",
368
- toolName: event.toolName,
369
- serverId: event.serverId,
370
- timestamp: new Date().toISOString(),
371
- message: "External MCP tool removed event received",
372
- });
373
- this.emitter.emit("externalMCP:toolRemoved", event);
374
- // Unregister removed tools from main tool registry
375
- this.unregisterExternalMCPToolFromRegistry(event.toolName);
376
- });
377
- const eventHandlerSetupEndTime = process.hrtime.bigint();
378
- const eventHandlerSetupDurationNs = eventHandlerSetupEndTime - eventHandlerSetupStartTime;
379
- logger.debug(`[NeuroLink] ✅ LOG_POINT_C012_EVENT_HANDLER_SETUP_SUCCESS`, {
380
- logPoint: "C012_EVENT_HANDLER_SETUP_SUCCESS",
381
- constructorId,
382
- timestamp: new Date().toISOString(),
383
- elapsedMs: Date.now() - constructorStartTime,
384
- elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
385
- eventHandlerSetupDurationNs: eventHandlerSetupDurationNs.toString(),
386
- eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) / 1000000,
387
- eventHandlersCount: 5,
388
- eventHandlerTypes: [
389
- "connected",
390
- "disconnected",
391
- "failed",
392
- "toolDiscovered",
393
- "toolRemoved",
394
- ],
395
- message: "Event handlers set up successfully",
396
- });
327
+ this.setupExternalServerEventHandlers(constructorId, constructorStartTime, constructorHrTimeStart);
397
328
  }
398
329
  catch (error) {
399
330
  const externalServerInitErrorTime = process.hrtime.bigint();
@@ -413,7 +344,99 @@ export class NeuroLink {
413
344
  });
414
345
  throw error;
415
346
  }
416
- // 🚀 EXHAUSTIVE LOGGING POINT C014: CONSTRUCTOR COMPLETION
347
+ }
348
+ /**
349
+ * Setup event handlers for external server manager
350
+ */
351
+ setupExternalServerEventHandlers(constructorId, constructorStartTime, constructorHrTimeStart) {
352
+ const eventHandlerSetupStartTime = process.hrtime.bigint();
353
+ logger.debug(`[NeuroLink] 🔗 LOG_POINT_C011_EVENT_HANDLER_SETUP_START`, {
354
+ logPoint: "C011_EVENT_HANDLER_SETUP_START",
355
+ constructorId,
356
+ timestamp: new Date().toISOString(),
357
+ elapsedMs: Date.now() - constructorStartTime,
358
+ elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
359
+ eventHandlerSetupStartTimeNs: eventHandlerSetupStartTime.toString(),
360
+ message: "Setting up external server event handlers",
361
+ });
362
+ this.externalServerManager.on("connected", (event) => {
363
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_CONNECTED`, {
364
+ constructorId,
365
+ eventType: "connected",
366
+ event,
367
+ timestamp: new Date().toISOString(),
368
+ message: "External MCP server connected event received",
369
+ });
370
+ this.emitter.emit("externalMCP:serverConnected", event);
371
+ });
372
+ this.externalServerManager.on("disconnected", (event) => {
373
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_DISCONNECTED`, {
374
+ constructorId,
375
+ eventType: "disconnected",
376
+ event,
377
+ timestamp: new Date().toISOString(),
378
+ message: "External MCP server disconnected event received",
379
+ });
380
+ this.emitter.emit("externalMCP:serverDisconnected", event);
381
+ });
382
+ this.externalServerManager.on("failed", (event) => {
383
+ logger.warn(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_FAILED`, {
384
+ constructorId,
385
+ eventType: "failed",
386
+ event,
387
+ timestamp: new Date().toISOString(),
388
+ message: "External MCP server failed event received",
389
+ });
390
+ this.emitter.emit("externalMCP:serverFailed", event);
391
+ });
392
+ this.externalServerManager.on("toolDiscovered", (event) => {
393
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_DISCOVERED`, {
394
+ constructorId,
395
+ eventType: "toolDiscovered",
396
+ toolName: event.toolName,
397
+ serverId: event.serverId,
398
+ timestamp: new Date().toISOString(),
399
+ message: "External MCP tool discovered event received",
400
+ });
401
+ this.emitter.emit("externalMCP:toolDiscovered", event);
402
+ });
403
+ this.externalServerManager.on("toolRemoved", (event) => {
404
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_REMOVED`, {
405
+ constructorId,
406
+ eventType: "toolRemoved",
407
+ toolName: event.toolName,
408
+ serverId: event.serverId,
409
+ timestamp: new Date().toISOString(),
410
+ message: "External MCP tool removed event received",
411
+ });
412
+ this.emitter.emit("externalMCP:toolRemoved", event);
413
+ this.unregisterExternalMCPToolFromRegistry(event.toolName);
414
+ });
415
+ const eventHandlerSetupEndTime = process.hrtime.bigint();
416
+ const eventHandlerSetupDurationNs = eventHandlerSetupEndTime - eventHandlerSetupStartTime;
417
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_C012_EVENT_HANDLER_SETUP_SUCCESS`, {
418
+ logPoint: "C012_EVENT_HANDLER_SETUP_SUCCESS",
419
+ constructorId,
420
+ timestamp: new Date().toISOString(),
421
+ elapsedMs: Date.now() - constructorStartTime,
422
+ elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
423
+ eventHandlerSetupDurationNs: eventHandlerSetupDurationNs.toString(),
424
+ eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) / 1000000,
425
+ eventHandlersCount: 5,
426
+ eventHandlerTypes: [
427
+ "connected",
428
+ "disconnected",
429
+ "failed",
430
+ "toolDiscovered",
431
+ "toolRemoved",
432
+ ],
433
+ message: "Event handlers set up successfully",
434
+ });
435
+ }
436
+ /**
437
+ * Log constructor completion with final state summary
438
+ */
439
+ logConstructorComplete(constructorId, constructorStartTime, constructorHrTimeStart) {
417
440
  const constructorEndTime = process.hrtime.bigint();
418
441
  const constructorDurationNs = constructorEndTime - constructorHrTimeStart;
419
442
  logger.info(`[NeuroLink] 🏁 LOG_POINT_C014_CONSTRUCTOR_COMPLETE`, {
@@ -423,7 +446,6 @@ export class NeuroLink {
423
446
  constructorDurationNs: constructorDurationNs.toString(),
424
447
  constructorDurationMs: Number(constructorDurationNs) / 1000000,
425
448
  totalElapsedMs: Date.now() - constructorStartTime,
426
- // Final state summary
427
449
  finalState: {
428
450
  hasConversationMemory: !!this.conversationMemory,
429
451
  hasExternalServerManager: !!this.externalServerManager,
@@ -432,7 +454,6 @@ export class NeuroLink {
432
454
  toolCircuitBreakersCount: this.toolCircuitBreakers.size,
433
455
  toolExecutionMetricsCount: this.toolExecutionMetrics.size,
434
456
  },
435
- // Final memory usage
436
457
  finalMemoryUsage: process.memoryUsage(),
437
458
  finalCpuUsage: process.cpuUsage(),
438
459
  message: "NeuroLink constructor completed successfully with all components initialized",
@@ -443,10 +464,34 @@ export class NeuroLink {
443
464
  * Uses isolated async context to prevent hanging
444
465
  */
445
466
  async initializeMCP() {
446
- // 🚀 EXHAUSTIVE LOGGING POINT M001: MCP INITIALIZATION ENTRY CHECK
447
467
  const mcpInitId = `mcp-init-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
448
468
  const mcpInitStartTime = Date.now();
449
469
  const mcpInitHrTimeStart = process.hrtime.bigint();
470
+ this.logMCPInitStart(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
471
+ if (this.mcpInitialized) {
472
+ this.logMCPAlreadyInitialized(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
473
+ return;
474
+ }
475
+ const MemoryManager = await this.importPerformanceManager(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
476
+ const startMemory = MemoryManager
477
+ ? MemoryManager.getMemoryUsageMB()
478
+ : { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
479
+ try {
480
+ await this.performMCPInitialization(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart, startMemory);
481
+ this.mcpInitialized = true;
482
+ this.logMCPInitComplete(startMemory, MemoryManager, mcpInitStartTime);
483
+ }
484
+ catch (error) {
485
+ mcpLogger.warn("[NeuroLink] MCP initialization failed", {
486
+ error: error instanceof Error ? error.message : String(error),
487
+ });
488
+ // Continue without MCP - graceful degradation
489
+ }
490
+ }
491
+ /**
492
+ * Log MCP initialization start
493
+ */
494
+ logMCPInitStart(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
450
495
  logger.debug(`[NeuroLink] 🔧 LOG_POINT_M001_MCP_INIT_ENTRY`, {
451
496
  logPoint: "M001_MCP_INIT_ENTRY",
452
497
  mcpInitId,
@@ -459,19 +504,25 @@ export class NeuroLink {
459
504
  cpuUsage: process.cpuUsage(),
460
505
  message: "MCP initialization entry point - checking if already initialized",
461
506
  });
462
- if (this.mcpInitialized) {
463
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M002_MCP_ALREADY_INITIALIZED`, {
464
- logPoint: "M002_MCP_ALREADY_INITIALIZED",
465
- mcpInitId,
466
- timestamp: new Date().toISOString(),
467
- elapsedMs: Date.now() - mcpInitStartTime,
468
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
469
- mcpInitialized: this.mcpInitialized,
470
- message: "MCP already initialized - skipping initialization",
471
- });
472
- return;
473
- }
474
- // 🚀 EXHAUSTIVE LOGGING POINT M003: PERFORMANCE MANAGER IMPORT
507
+ }
508
+ /**
509
+ * Log MCP already initialized
510
+ */
511
+ logMCPAlreadyInitialized(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
512
+ logger.debug(`[NeuroLink] LOG_POINT_M002_MCP_ALREADY_INITIALIZED`, {
513
+ logPoint: "M002_MCP_ALREADY_INITIALIZED",
514
+ mcpInitId,
515
+ timestamp: new Date().toISOString(),
516
+ elapsedMs: Date.now() - mcpInitStartTime,
517
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
518
+ mcpInitialized: this.mcpInitialized,
519
+ message: "MCP already initialized - skipping initialization",
520
+ });
521
+ }
522
+ /**
523
+ * Import performance manager with error handling
524
+ */
525
+ async importPerformanceManager(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
475
526
  const performanceImportStartTime = process.hrtime.bigint();
476
527
  logger.debug(`[NeuroLink] 📊 LOG_POINT_M003_PERFORMANCE_IMPORT_START`, {
477
528
  logPoint: "M003_PERFORMANCE_IMPORT_START",
@@ -482,13 +533,9 @@ export class NeuroLink {
482
533
  performanceImportStartTimeNs: performanceImportStartTime.toString(),
483
534
  message: "Starting MemoryManager import for performance tracking",
484
535
  });
485
- let MemoryManager;
486
- let startMemory;
487
536
  try {
488
- // Track memory usage during MCP initialization
489
537
  const moduleImport = await import("./utils/performance.js");
490
- MemoryManager = moduleImport.MemoryManager;
491
- startMemory = MemoryManager.getMemoryUsageMB();
538
+ const MemoryManager = moduleImport.MemoryManager;
492
539
  const performanceImportEndTime = process.hrtime.bigint();
493
540
  const performanceImportDurationNs = performanceImportEndTime - performanceImportStartTime;
494
541
  logger.debug(`[NeuroLink] ✅ LOG_POINT_M004_PERFORMANCE_IMPORT_SUCCESS`, {
@@ -500,9 +547,9 @@ export class NeuroLink {
500
547
  performanceImportDurationNs: performanceImportDurationNs.toString(),
501
548
  performanceImportDurationMs: Number(performanceImportDurationNs) / 1000000,
502
549
  hasMemoryManager: !!MemoryManager,
503
- startMemory,
504
550
  message: "MemoryManager imported successfully",
505
551
  });
552
+ return MemoryManager;
506
553
  }
507
554
  catch (error) {
508
555
  const performanceImportErrorTime = process.hrtime.bigint();
@@ -519,206 +566,218 @@ export class NeuroLink {
519
566
  errorName: error instanceof Error ? error.name : "UnknownError",
520
567
  message: "MemoryManager import failed - continuing without performance tracking",
521
568
  });
522
- // Continue without performance tracking
523
- startMemory = { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
569
+ return undefined;
524
570
  }
571
+ }
572
+ /**
573
+ * Perform main MCP initialization logic
574
+ */
575
+ async performMCPInitialization(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart, startMemory) {
576
+ logger.info(`[NeuroLink] 🚀 LOG_POINT_M006_MCP_MAIN_INIT_START`, {
577
+ logPoint: "M006_MCP_MAIN_INIT_START",
578
+ mcpInitId,
579
+ timestamp: new Date().toISOString(),
580
+ elapsedMs: Date.now() - mcpInitStartTime,
581
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
582
+ startMemory,
583
+ message: "Starting isolated MCP initialization process",
584
+ });
585
+ mcpLogger.debug("[NeuroLink] Starting isolated MCP initialization...");
586
+ await this.initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
587
+ await this.initializeProviderRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
588
+ await this.registerDirectToolsServerInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
589
+ await this.loadMCPConfigurationInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
590
+ }
591
+ /**
592
+ * Initialize tool registry with timeout protection
593
+ */
594
+ async initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
595
+ const toolRegistryStartTime = process.hrtime.bigint();
596
+ const initTimeout = 3000;
597
+ logger.debug(`[NeuroLink] ⏱️ LOG_POINT_M007_TOOL_REGISTRY_TIMEOUT_SETUP`, {
598
+ logPoint: "M007_TOOL_REGISTRY_TIMEOUT_SETUP",
599
+ mcpInitId,
600
+ timestamp: new Date().toISOString(),
601
+ elapsedMs: Date.now() - mcpInitStartTime,
602
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
603
+ toolRegistryStartTimeNs: toolRegistryStartTime.toString(),
604
+ initTimeoutMs: initTimeout,
605
+ message: "Setting up tool registry initialization with timeout protection",
606
+ });
607
+ await Promise.race([
608
+ Promise.resolve(),
609
+ new Promise((_, reject) => {
610
+ setTimeout(() => reject(new Error("MCP initialization timeout")), initTimeout);
611
+ }),
612
+ ]);
613
+ const toolRegistryEndTime = process.hrtime.bigint();
614
+ const toolRegistryDurationNs = toolRegistryEndTime - toolRegistryStartTime;
615
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M008_TOOL_REGISTRY_SUCCESS`, {
616
+ logPoint: "M008_TOOL_REGISTRY_SUCCESS",
617
+ mcpInitId,
618
+ timestamp: new Date().toISOString(),
619
+ elapsedMs: Date.now() - mcpInitStartTime,
620
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
621
+ toolRegistryDurationNs: toolRegistryDurationNs.toString(),
622
+ toolRegistryDurationMs: Number(toolRegistryDurationNs) / 1000000,
623
+ message: "Tool registry initialization completed within timeout",
624
+ });
625
+ }
626
+ /**
627
+ * Initialize provider registry
628
+ */
629
+ async initializeProviderRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
630
+ const providerRegistryStartTime = process.hrtime.bigint();
631
+ logger.debug(`[NeuroLink] 🏭 LOG_POINT_M009_PROVIDER_REGISTRY_START`, {
632
+ logPoint: "M009_PROVIDER_REGISTRY_START",
633
+ mcpInitId,
634
+ timestamp: new Date().toISOString(),
635
+ elapsedMs: Date.now() - mcpInitStartTime,
636
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
637
+ providerRegistryStartTimeNs: providerRegistryStartTime.toString(),
638
+ message: "Starting provider registry registration with lazy loading",
639
+ });
640
+ await ProviderRegistry.registerAllProviders();
641
+ const providerRegistryEndTime = process.hrtime.bigint();
642
+ const providerRegistryDurationNs = providerRegistryEndTime - providerRegistryStartTime;
643
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M010_PROVIDER_REGISTRY_SUCCESS`, {
644
+ logPoint: "M010_PROVIDER_REGISTRY_SUCCESS",
645
+ mcpInitId,
646
+ timestamp: new Date().toISOString(),
647
+ elapsedMs: Date.now() - mcpInitStartTime,
648
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
649
+ providerRegistryDurationNs: providerRegistryDurationNs.toString(),
650
+ providerRegistryDurationMs: Number(providerRegistryDurationNs) / 1000000,
651
+ message: "Provider registry registration completed successfully",
652
+ });
653
+ }
654
+ /**
655
+ * Register direct tools server
656
+ */
657
+ async registerDirectToolsServerInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
658
+ const directToolsStartTime = process.hrtime.bigint();
659
+ logger.debug(`[NeuroLink] 🛠️ LOG_POINT_M011_DIRECT_TOOLS_START`, {
660
+ logPoint: "M011_DIRECT_TOOLS_START",
661
+ mcpInitId,
662
+ timestamp: new Date().toISOString(),
663
+ elapsedMs: Date.now() - mcpInitStartTime,
664
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
665
+ directToolsStartTimeNs: directToolsStartTime.toString(),
666
+ serverId: "neurolink-direct",
667
+ message: "Starting direct tools server registration",
668
+ });
525
669
  try {
526
- // 🚀 EXHAUSTIVE LOGGING POINT M006: MAIN MCP INITIALIZATION START
527
- logger.info(`[NeuroLink] 🚀 LOG_POINT_M006_MCP_MAIN_INIT_START`, {
528
- logPoint: "M006_MCP_MAIN_INIT_START",
670
+ await toolRegistry.registerServer("neurolink-direct", directToolsServer);
671
+ const directToolsSuccessTime = process.hrtime.bigint();
672
+ const directToolsDurationNs = directToolsSuccessTime - directToolsStartTime;
673
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M012_DIRECT_TOOLS_SUCCESS`, {
674
+ logPoint: "M012_DIRECT_TOOLS_SUCCESS",
529
675
  mcpInitId,
530
676
  timestamp: new Date().toISOString(),
531
677
  elapsedMs: Date.now() - mcpInitStartTime,
532
678
  elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
533
- startMemory,
534
- message: "Starting isolated MCP initialization process",
679
+ directToolsDurationNs: directToolsDurationNs.toString(),
680
+ directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
681
+ serverId: "neurolink-direct",
682
+ message: "Direct tools server registered successfully",
535
683
  });
536
- mcpLogger.debug("[NeuroLink] Starting isolated MCP initialization...");
537
- // 🚀 EXHAUSTIVE LOGGING POINT M007: TOOL REGISTRY TIMEOUT SETUP
538
- const toolRegistryStartTime = process.hrtime.bigint();
539
- const initTimeout = 3000; // 3 second timeout
540
- logger.debug(`[NeuroLink] ⏱️ LOG_POINT_M007_TOOL_REGISTRY_TIMEOUT_SETUP`, {
541
- logPoint: "M007_TOOL_REGISTRY_TIMEOUT_SETUP",
542
- mcpInitId,
543
- timestamp: new Date().toISOString(),
544
- elapsedMs: Date.now() - mcpInitStartTime,
545
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
546
- toolRegistryStartTimeNs: toolRegistryStartTime.toString(),
547
- initTimeoutMs: initTimeout,
548
- message: "Setting up tool registry initialization with timeout protection",
684
+ mcpLogger.debug("[NeuroLink] Direct tools server registered successfully", {
685
+ serverId: "neurolink-direct",
549
686
  });
550
- // Initialize tool registry with timeout protection
551
- await Promise.race([
552
- Promise.resolve(), // toolRegistry doesn't need explicit initialization
553
- new Promise((_, reject) => {
554
- setTimeout(() => reject(new Error("MCP initialization timeout")), initTimeout);
555
- }),
556
- ]);
557
- const toolRegistryEndTime = process.hrtime.bigint();
558
- const toolRegistryDurationNs = toolRegistryEndTime - toolRegistryStartTime;
559
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M008_TOOL_REGISTRY_SUCCESS`, {
560
- logPoint: "M008_TOOL_REGISTRY_SUCCESS",
687
+ }
688
+ catch (error) {
689
+ const directToolsErrorTime = process.hrtime.bigint();
690
+ const directToolsDurationNs = directToolsErrorTime - directToolsStartTime;
691
+ logger.warn(`[NeuroLink] ⚠️ LOG_POINT_M013_DIRECT_TOOLS_ERROR`, {
692
+ logPoint: "M013_DIRECT_TOOLS_ERROR",
561
693
  mcpInitId,
562
694
  timestamp: new Date().toISOString(),
563
695
  elapsedMs: Date.now() - mcpInitStartTime,
564
696
  elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
565
- toolRegistryDurationNs: toolRegistryDurationNs.toString(),
566
- toolRegistryDurationMs: Number(toolRegistryDurationNs) / 1000000,
567
- message: "Tool registry initialization completed within timeout",
697
+ directToolsDurationNs: directToolsDurationNs.toString(),
698
+ directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
699
+ error: error instanceof Error ? error.message : String(error),
700
+ errorName: error instanceof Error ? error.name : "UnknownError",
701
+ errorStack: error instanceof Error ? error.stack : undefined,
702
+ serverId: "neurolink-direct",
703
+ message: "Direct tools server registration failed but continuing",
568
704
  });
569
- // 🚀 EXHAUSTIVE LOGGING POINT M009: PROVIDER REGISTRY START
570
- const providerRegistryStartTime = process.hrtime.bigint();
571
- logger.debug(`[NeuroLink] 🏭 LOG_POINT_M009_PROVIDER_REGISTRY_START`, {
572
- logPoint: "M009_PROVIDER_REGISTRY_START",
573
- mcpInitId,
574
- timestamp: new Date().toISOString(),
575
- elapsedMs: Date.now() - mcpInitStartTime,
576
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
577
- providerRegistryStartTimeNs: providerRegistryStartTime.toString(),
578
- message: "Starting provider registry registration with lazy loading",
705
+ mcpLogger.warn("[NeuroLink] Failed to register direct tools server", {
706
+ error: error instanceof Error ? error.message : String(error),
579
707
  });
580
- // Register all providers with lazy loading support
581
- await ProviderRegistry.registerAllProviders();
582
- const providerRegistryEndTime = process.hrtime.bigint();
583
- const providerRegistryDurationNs = providerRegistryEndTime - providerRegistryStartTime;
584
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M010_PROVIDER_REGISTRY_SUCCESS`, {
585
- logPoint: "M010_PROVIDER_REGISTRY_SUCCESS",
708
+ }
709
+ }
710
+ /**
711
+ * Load MCP configuration from .mcp-config.json
712
+ */
713
+ async loadMCPConfigurationInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
714
+ const mcpConfigStartTime = process.hrtime.bigint();
715
+ logger.debug(`[NeuroLink] 📄 LOG_POINT_M014_MCP_CONFIG_START`, {
716
+ logPoint: "M014_MCP_CONFIG_START",
717
+ mcpInitId,
718
+ timestamp: new Date().toISOString(),
719
+ elapsedMs: Date.now() - mcpInitStartTime,
720
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
721
+ mcpConfigStartTimeNs: mcpConfigStartTime.toString(),
722
+ hasExternalServerManager: !!this.externalServerManager,
723
+ message: "Starting MCP configuration loading from .mcp-config.json",
724
+ });
725
+ try {
726
+ const configResult = await this.externalServerManager.loadMCPConfiguration();
727
+ const mcpConfigSuccessTime = process.hrtime.bigint();
728
+ const mcpConfigDurationNs = mcpConfigSuccessTime - mcpConfigStartTime;
729
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M015_MCP_CONFIG_SUCCESS`, {
730
+ logPoint: "M015_MCP_CONFIG_SUCCESS",
586
731
  mcpInitId,
587
732
  timestamp: new Date().toISOString(),
588
733
  elapsedMs: Date.now() - mcpInitStartTime,
589
734
  elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
590
- providerRegistryDurationNs: providerRegistryDurationNs.toString(),
591
- providerRegistryDurationMs: Number(providerRegistryDurationNs) / 1000000,
592
- message: "Provider registry registration completed successfully",
735
+ mcpConfigDurationNs: mcpConfigDurationNs.toString(),
736
+ mcpConfigDurationMs: Number(mcpConfigDurationNs) / 1000000,
737
+ serversLoaded: configResult.serversLoaded,
738
+ errorsCount: configResult.errors.length,
739
+ configResult: {
740
+ serversLoaded: configResult.serversLoaded,
741
+ errors: configResult.errors.map((err) => ({
742
+ message: err instanceof Error ? err.message : String(err),
743
+ name: err instanceof Error ? err.name : "UnknownError",
744
+ })),
745
+ },
746
+ message: "MCP configuration loaded successfully",
593
747
  });
594
- // 🚀 EXHAUSTIVE LOGGING POINT M011: DIRECT TOOLS SERVER REGISTRATION
595
- const directToolsStartTime = process.hrtime.bigint();
596
- logger.debug(`[NeuroLink] 🛠️ LOG_POINT_M011_DIRECT_TOOLS_START`, {
597
- logPoint: "M011_DIRECT_TOOLS_START",
598
- mcpInitId,
599
- timestamp: new Date().toISOString(),
600
- elapsedMs: Date.now() - mcpInitStartTime,
601
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
602
- directToolsStartTimeNs: directToolsStartTime.toString(),
603
- serverId: "neurolink-direct",
604
- message: "Starting direct tools server registration",
748
+ mcpLogger.debug("[NeuroLink] MCP configuration loaded successfully", {
749
+ serversLoaded: configResult.serversLoaded,
750
+ errors: configResult.errors.length,
605
751
  });
606
- // Register the direct tools server to make websearch and other tools available
607
- try {
608
- // Use the server ID string for registration instead of the server object
609
- await toolRegistry.registerServer("neurolink-direct", directToolsServer);
610
- const directToolsSuccessTime = process.hrtime.bigint();
611
- const directToolsDurationNs = directToolsSuccessTime - directToolsStartTime;
612
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M012_DIRECT_TOOLS_SUCCESS`, {
613
- logPoint: "M012_DIRECT_TOOLS_SUCCESS",
614
- mcpInitId,
615
- timestamp: new Date().toISOString(),
616
- elapsedMs: Date.now() - mcpInitStartTime,
617
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
618
- directToolsDurationNs: directToolsDurationNs.toString(),
619
- directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
620
- serverId: "neurolink-direct",
621
- message: "Direct tools server registered successfully",
622
- });
623
- mcpLogger.debug("[NeuroLink] Direct tools server registered successfully", {
624
- serverId: "neurolink-direct",
625
- });
626
- }
627
- catch (error) {
628
- const directToolsErrorTime = process.hrtime.bigint();
629
- const directToolsDurationNs = directToolsErrorTime - directToolsStartTime;
630
- logger.warn(`[NeuroLink] ⚠️ LOG_POINT_M013_DIRECT_TOOLS_ERROR`, {
631
- logPoint: "M013_DIRECT_TOOLS_ERROR",
632
- mcpInitId,
633
- timestamp: new Date().toISOString(),
634
- elapsedMs: Date.now() - mcpInitStartTime,
635
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
636
- directToolsDurationNs: directToolsDurationNs.toString(),
637
- directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
638
- error: error instanceof Error ? error.message : String(error),
639
- errorName: error instanceof Error ? error.name : "UnknownError",
640
- errorStack: error instanceof Error ? error.stack : undefined,
641
- serverId: "neurolink-direct",
642
- message: "Direct tools server registration failed but continuing",
643
- });
644
- mcpLogger.warn("[NeuroLink] Failed to register direct tools server", {
645
- error: error instanceof Error ? error.message : String(error),
646
- });
647
- }
648
- // 🚀 EXHAUSTIVE LOGGING POINT M014: MCP CONFIG LOADING START
649
- const mcpConfigStartTime = process.hrtime.bigint();
650
- logger.debug(`[NeuroLink] 📄 LOG_POINT_M014_MCP_CONFIG_START`, {
651
- logPoint: "M014_MCP_CONFIG_START",
652
- mcpInitId,
653
- timestamp: new Date().toISOString(),
654
- elapsedMs: Date.now() - mcpInitStartTime,
655
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
656
- mcpConfigStartTimeNs: mcpConfigStartTime.toString(),
657
- hasExternalServerManager: !!this.externalServerManager,
658
- message: "Starting MCP configuration loading from .mcp-config.json",
659
- });
660
- // Load MCP configuration from .mcp-config.json using ExternalServerManager
661
- try {
662
- const configResult = await this.externalServerManager.loadMCPConfiguration();
663
- const mcpConfigSuccessTime = process.hrtime.bigint();
664
- const mcpConfigDurationNs = mcpConfigSuccessTime - mcpConfigStartTime;
665
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M015_MCP_CONFIG_SUCCESS`, {
666
- logPoint: "M015_MCP_CONFIG_SUCCESS",
667
- mcpInitId,
668
- timestamp: new Date().toISOString(),
669
- elapsedMs: Date.now() - mcpInitStartTime,
670
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
671
- mcpConfigDurationNs: mcpConfigDurationNs.toString(),
672
- mcpConfigDurationMs: Number(mcpConfigDurationNs) / 1000000,
673
- serversLoaded: configResult.serversLoaded,
674
- errorsCount: configResult.errors.length,
675
- configResult: {
676
- serversLoaded: configResult.serversLoaded,
677
- errors: configResult.errors.map((err) => ({
678
- message: err instanceof Error ? err.message : String(err),
679
- name: err instanceof Error ? err.name : "UnknownError",
680
- })),
681
- },
682
- message: "MCP configuration loaded successfully",
683
- });
684
- mcpLogger.debug("[NeuroLink] MCP configuration loaded successfully", {
685
- serversLoaded: configResult.serversLoaded,
686
- errors: configResult.errors.length,
687
- });
688
- if (configResult.errors.length > 0) {
689
- mcpLogger.warn("[NeuroLink] Some MCP servers failed to load", {
690
- errors: configResult.errors,
691
- });
692
- }
693
- }
694
- catch (configError) {
695
- mcpLogger.warn("[NeuroLink] MCP configuration loading failed", {
696
- error: configError instanceof Error
697
- ? configError.message
698
- : String(configError),
752
+ if (configResult.errors.length > 0) {
753
+ mcpLogger.warn("[NeuroLink] Some MCP servers failed to load", {
754
+ errors: configResult.errors,
699
755
  });
700
756
  }
701
- this.mcpInitialized = true;
702
- // Monitor memory usage and provide cleanup suggestions
703
- const endMemory = MemoryManager
704
- ? MemoryManager.getMemoryUsageMB()
705
- : { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
706
- const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
707
- const initTime = Date.now() - mcpInitStartTime;
708
- mcpLogger.debug("[NeuroLink] MCP initialization completed successfully", {
709
- initTime: `${initTime}ms`,
710
- memoryUsed: `${memoryDelta}MB`,
711
- });
712
- // Suggest cleanup if initialization used significant memory
713
- if (memoryDelta > 30) {
714
- mcpLogger.debug("💡 Memory cleanup suggestion: MCP initialization used significant memory. Consider calling MemoryManager.forceGC() after heavy operations.");
715
- }
716
757
  }
717
- catch (error) {
718
- mcpLogger.warn("[NeuroLink] MCP initialization failed", {
719
- error: error instanceof Error ? error.message : String(error),
758
+ catch (configError) {
759
+ mcpLogger.warn("[NeuroLink] MCP configuration loading failed", {
760
+ error: configError instanceof Error
761
+ ? configError.message
762
+ : String(configError),
720
763
  });
721
- // Continue without MCP - graceful degradation
764
+ }
765
+ }
766
+ /**
767
+ * Log MCP initialization completion
768
+ */
769
+ logMCPInitComplete(startMemory, MemoryManager, mcpInitStartTime) {
770
+ const endMemory = MemoryManager
771
+ ? MemoryManager.getMemoryUsageMB()
772
+ : { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
773
+ const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
774
+ const initTime = Date.now() - mcpInitStartTime;
775
+ mcpLogger.debug("[NeuroLink] MCP initialization completed successfully", {
776
+ initTime: `${initTime}ms`,
777
+ memoryUsed: `${memoryDelta}MB`,
778
+ });
779
+ if (memoryDelta > 30) {
780
+ mcpLogger.debug("💡 Memory cleanup suggestion: MCP initialization used significant memory. Consider calling MemoryManager.forceGC() after heavy operations.");
722
781
  }
723
782
  }
724
783
  /**
@@ -816,11 +875,15 @@ export class NeuroLink {
816
875
  options.input.text = this.contextManager.getContextForPrompt("user", options.input.text);
817
876
  }
818
877
  const startTime = Date.now();
819
- // Emit generation start event
878
+ // Emit generation start event (NeuroLink format - keep existing)
820
879
  this.emitter.emit("generation:start", {
821
880
  provider: options.provider || "auto",
822
881
  timestamp: startTime,
823
882
  });
883
+ // ADD: Bedrock-compatible response:start event
884
+ this.emitter.emit("response:start");
885
+ // ADD: Bedrock-compatible message event
886
+ this.emitter.emit("message", `Starting ${options.provider || "auto"} text generation...`);
824
887
  // Process factory configuration
825
888
  const factoryResult = processFactoryOptions(options);
826
889
  // Validate factory configuration if present
@@ -863,13 +926,18 @@ export class NeuroLink {
863
926
  }
864
927
  // Use redesigned generation logic
865
928
  const textResult = await this.generateTextInternal(textOptions);
866
- // Emit generation completion event
929
+ // Emit generation completion event (NeuroLink format - enhanced with content)
867
930
  this.emitter.emit("generation:end", {
868
931
  provider: textResult.provider,
869
932
  responseTime: Date.now() - startTime,
870
933
  toolsUsed: textResult.toolsUsed,
871
934
  timestamp: Date.now(),
935
+ result: textResult, // Enhanced: include full result
872
936
  });
937
+ // ADD: Bedrock-compatible response:end event with content
938
+ this.emitter.emit("response:end", textResult.content || "");
939
+ // ADD: Bedrock-compatible message event
940
+ this.emitter.emit("message", `Generation completed in ${Date.now() - startTime}ms`);
873
941
  // Convert back to GenerateResult
874
942
  const generateResult = {
875
943
  content: textResult.content,
@@ -877,9 +945,9 @@ export class NeuroLink {
877
945
  model: textResult.model,
878
946
  usage: textResult.usage
879
947
  ? {
880
- inputTokens: textResult.usage.promptTokens || 0,
881
- outputTokens: textResult.usage.completionTokens || 0,
882
- totalTokens: textResult.usage.totalTokens || 0,
948
+ input: textResult.usage.input || 0,
949
+ output: textResult.usage.output || 0,
950
+ total: textResult.usage.total || 0,
883
951
  }
884
952
  : undefined,
885
953
  responseTime: textResult.responseTime,
@@ -893,9 +961,11 @@ export class NeuroLink {
893
961
  ...textResult.evaluation,
894
962
  isOffTopic: textResult.evaluation
895
963
  .isOffTopic ?? false,
896
- alertSeverity: textResult.evaluation.alertSeverity ?? "none",
897
- reasoning: textResult.evaluation.reasoning ??
898
- "No evaluation provided",
964
+ alertSeverity: textResult.evaluation
965
+ .alertSeverity ??
966
+ "none",
967
+ reasoning: textResult.evaluation
968
+ .reasoning ?? "No evaluation provided",
899
969
  evaluationModel: textResult.evaluation
900
970
  .evaluationModel ?? "unknown",
901
971
  evaluationTime: textResult.evaluation
@@ -940,18 +1010,46 @@ export class NeuroLink {
940
1010
  * 5. Store conversation turn for future context
941
1011
  */
942
1012
  async generateTextInternal(options) {
943
- // 🚀 EXHAUSTIVE LOGGING POINT G001: GENERATE TEXT INTERNAL ENTRY
944
1013
  const generateInternalId = `generate-internal-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
945
1014
  const generateInternalStartTime = Date.now();
946
1015
  const generateInternalHrTimeStart = process.hrtime.bigint();
947
1016
  const functionTag = "NeuroLink.generateTextInternal";
1017
+ this.logGenerateTextInternalStart(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, options, functionTag);
1018
+ this.emitGenerationStartEvents(options);
1019
+ try {
1020
+ await this.initializeConversationMemoryForGeneration(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart);
1021
+ const mcpResult = await this.attemptMCPGeneration(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag);
1022
+ if (mcpResult) {
1023
+ await storeConversationTurn(this.conversationMemory, options, mcpResult);
1024
+ this.emitter.emit("response:end", mcpResult.content || "");
1025
+ return mcpResult;
1026
+ }
1027
+ const directResult = await this.directProviderGeneration(options);
1028
+ logger.debug(`[${functionTag}] Direct generation successful`);
1029
+ await storeConversationTurn(this.conversationMemory, options, directResult);
1030
+ this.emitter.emit("response:end", directResult.content || "");
1031
+ this.emitter.emit("message", `Text generation completed successfully`);
1032
+ return directResult;
1033
+ }
1034
+ catch (error) {
1035
+ logger.error(`[${functionTag}] All generation methods failed`, {
1036
+ error: error instanceof Error ? error.message : String(error),
1037
+ });
1038
+ this.emitter.emit("response:end", "");
1039
+ this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
1040
+ throw error;
1041
+ }
1042
+ }
1043
+ /**
1044
+ * Log generateTextInternal start with comprehensive analysis
1045
+ */
1046
+ logGenerateTextInternalStart(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, options, functionTag) {
948
1047
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_G001_GENERATE_INTERNAL_START`, {
949
1048
  logPoint: "G001_GENERATE_INTERNAL_START",
950
1049
  generateInternalId,
951
1050
  timestamp: new Date().toISOString(),
952
1051
  generateInternalStartTime,
953
1052
  generateInternalHrTimeStart: generateInternalHrTimeStart.toString(),
954
- // 📊 Input analysis
955
1053
  inputAnalysis: {
956
1054
  provider: options.provider || "auto",
957
1055
  providerType: typeof options.provider,
@@ -974,19 +1072,17 @@ export class NeuroLink {
974
1072
  evaluationDomain: options.evaluationDomain || "NOT_SET",
975
1073
  toolUsageContext: options.toolUsageContext || "NOT_SET",
976
1074
  },
977
- // 🧠 Memory and initialization state
978
1075
  instanceState: {
979
1076
  hasConversationMemory: !!this.conversationMemory,
980
1077
  conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_SET",
981
1078
  mcpInitialized: this.mcpInitialized,
982
1079
  hasProviderRegistry: !!AIProviderFactory,
983
- providerRegistrySize: 0, // Not accessible as size property
1080
+ providerRegistrySize: 0,
984
1081
  hasToolRegistry: !!toolRegistry,
985
- toolRegistrySize: 0, // Not accessible as size property
1082
+ toolRegistrySize: 0,
986
1083
  hasExternalServerManager: !!this.externalServerManager,
987
1084
  hasContextManager: !!this.contextManager,
988
1085
  },
989
- // 🔧 Environment context
990
1086
  environmentContext: {
991
1087
  nodeVersion: process.version,
992
1088
  platform: process.platform,
@@ -1002,200 +1098,188 @@ export class NeuroLink {
1002
1098
  promptLength: options.prompt?.length || 0,
1003
1099
  hasConversationMemory: !!this.conversationMemory,
1004
1100
  });
1005
- try {
1006
- // 🚀 EXHAUSTIVE LOGGING POINT G002: CONVERSATION MEMORY INITIALIZATION
1007
- const conversationMemoryStartTime = process.hrtime.bigint();
1008
- logger.debug(`[NeuroLink] 🧠 LOG_POINT_G002_CONVERSATION_MEMORY_CHECK`, {
1009
- logPoint: "G002_CONVERSATION_MEMORY_CHECK",
1101
+ }
1102
+ /**
1103
+ * Emit generation start events
1104
+ */
1105
+ emitGenerationStartEvents(options) {
1106
+ this.emitter.emit("response:start");
1107
+ this.emitter.emit("message", `Starting ${options.provider || "auto"} text generation (internal)...`);
1108
+ }
1109
+ /**
1110
+ * Initialize conversation memory for generation
1111
+ */
1112
+ async initializeConversationMemoryForGeneration(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart) {
1113
+ const conversationMemoryStartTime = process.hrtime.bigint();
1114
+ logger.debug(`[NeuroLink] 🧠 LOG_POINT_G002_CONVERSATION_MEMORY_CHECK`, {
1115
+ logPoint: "G002_CONVERSATION_MEMORY_CHECK",
1116
+ generateInternalId,
1117
+ timestamp: new Date().toISOString(),
1118
+ elapsedMs: Date.now() - generateInternalStartTime,
1119
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1120
+ conversationMemoryStartTimeNs: conversationMemoryStartTime.toString(),
1121
+ hasConversationMemory: !!this.conversationMemory,
1122
+ conversationMemoryEnabled: !!this.conversationMemory,
1123
+ conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_AVAILABLE",
1124
+ message: "Checking conversation memory initialization requirement",
1125
+ });
1126
+ if (this.conversationMemory) {
1127
+ logger.debug(`[NeuroLink] 🧠 LOG_POINT_G003_CONVERSATION_MEMORY_INIT_START`, {
1128
+ logPoint: "G003_CONVERSATION_MEMORY_INIT_START",
1010
1129
  generateInternalId,
1011
1130
  timestamp: new Date().toISOString(),
1012
1131
  elapsedMs: Date.now() - generateInternalStartTime,
1013
1132
  elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1014
- conversationMemoryStartTimeNs: conversationMemoryStartTime.toString(),
1015
- hasConversationMemory: !!this.conversationMemory,
1016
- conversationMemoryEnabled: !!this.conversationMemory,
1017
- conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_AVAILABLE",
1018
- message: "Checking conversation memory initialization requirement",
1133
+ message: "Starting conversation memory initialization",
1134
+ });
1135
+ await this.conversationMemory.initialize();
1136
+ const conversationMemoryEndTime = process.hrtime.bigint();
1137
+ const conversationMemoryDurationNs = conversationMemoryEndTime - conversationMemoryStartTime;
1138
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_G004_CONVERSATION_MEMORY_INIT_SUCCESS`, {
1139
+ logPoint: "G004_CONVERSATION_MEMORY_INIT_SUCCESS",
1140
+ generateInternalId,
1141
+ timestamp: new Date().toISOString(),
1142
+ elapsedMs: Date.now() - generateInternalStartTime,
1143
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1144
+ conversationMemoryDurationNs: conversationMemoryDurationNs.toString(),
1145
+ conversationMemoryDurationMs: Number(conversationMemoryDurationNs) / 1000000,
1146
+ message: "Conversation memory initialization completed successfully",
1019
1147
  });
1020
- // Initialize conversation memory if enabled
1021
- if (this.conversationMemory) {
1022
- logger.debug(`[NeuroLink] 🧠 LOG_POINT_G003_CONVERSATION_MEMORY_INIT_START`, {
1023
- logPoint: "G003_CONVERSATION_MEMORY_INIT_START",
1148
+ }
1149
+ }
1150
+ /**
1151
+ * Attempt MCP generation with retry logic
1152
+ */
1153
+ async attemptMCPGeneration(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
1154
+ const mcpDecisionStartTime = process.hrtime.bigint();
1155
+ logger.debug(`[NeuroLink] 🔧 LOG_POINT_G005_MCP_DECISION_CHECK`, {
1156
+ logPoint: "G005_MCP_DECISION_CHECK",
1157
+ generateInternalId,
1158
+ timestamp: new Date().toISOString(),
1159
+ elapsedMs: Date.now() - generateInternalStartTime,
1160
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1161
+ mcpDecisionStartTimeNs: mcpDecisionStartTime.toString(),
1162
+ mcpDecisionFactors: {
1163
+ disableTools: options.disableTools || false,
1164
+ toolsEnabled: !options.disableTools,
1165
+ mcpInitialized: this.mcpInitialized,
1166
+ hasExternalServerManager: !!this.externalServerManager,
1167
+ hasToolRegistry: !!toolRegistry,
1168
+ toolRegistrySize: 0,
1169
+ shouldTryMCP: !options.disableTools,
1170
+ },
1171
+ mcpReadinessAnalysis: {
1172
+ mcpAvailable: !options.disableTools && this.mcpInitialized,
1173
+ componentsReady: {
1174
+ externalServerManager: !!this.externalServerManager,
1175
+ toolRegistry: !!toolRegistry,
1176
+ providerRegistry: !!AIProviderFactory,
1177
+ },
1178
+ },
1179
+ message: "Analyzing MCP generation eligibility and readiness",
1180
+ });
1181
+ if (!options.disableTools) {
1182
+ return await this.performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag);
1183
+ }
1184
+ return null;
1185
+ }
1186
+ /**
1187
+ * Perform MCP generation with retry logic
1188
+ */
1189
+ async performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
1190
+ const maxMcpRetries = 2;
1191
+ const mcpRetryLoopStartTime = process.hrtime.bigint();
1192
+ logger.debug(`[NeuroLink] 🔄 LOG_POINT_G006_MCP_RETRY_LOOP_START`, {
1193
+ logPoint: "G006_MCP_RETRY_LOOP_START",
1194
+ generateInternalId,
1195
+ timestamp: new Date().toISOString(),
1196
+ elapsedMs: Date.now() - generateInternalStartTime,
1197
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1198
+ mcpRetryLoopStartTimeNs: mcpRetryLoopStartTime.toString(),
1199
+ maxMcpRetries,
1200
+ totalPossibleAttempts: maxMcpRetries + 1,
1201
+ message: "Starting MCP generation retry loop with failure tolerance",
1202
+ });
1203
+ const maxAttempts = maxMcpRetries + 1;
1204
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1205
+ try {
1206
+ const mcpAttemptStartTime = process.hrtime.bigint();
1207
+ logger.debug(`[NeuroLink] 🎯 LOG_POINT_G007_MCP_ATTEMPT_START`, {
1208
+ logPoint: "G007_MCP_ATTEMPT_START",
1024
1209
  generateInternalId,
1025
1210
  timestamp: new Date().toISOString(),
1026
1211
  elapsedMs: Date.now() - generateInternalStartTime,
1027
1212
  elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1028
- message: "Starting conversation memory initialization",
1213
+ mcpAttemptStartTimeNs: mcpAttemptStartTime.toString(),
1214
+ currentAttempt: attempt,
1215
+ maxAttempts,
1216
+ isFirstAttempt: attempt === 1,
1217
+ isLastAttempt: attempt === maxAttempts,
1218
+ attemptType: attempt === 1 ? "INITIAL" : "RETRY",
1219
+ message: `Attempting MCP generation (attempt ${attempt}/${maxAttempts})`,
1029
1220
  });
1030
- await this.conversationMemory.initialize();
1031
- const conversationMemoryEndTime = process.hrtime.bigint();
1032
- const conversationMemoryDurationNs = conversationMemoryEndTime - conversationMemoryStartTime;
1033
- logger.debug(`[NeuroLink] LOG_POINT_G004_CONVERSATION_MEMORY_INIT_SUCCESS`, {
1034
- logPoint: "G004_CONVERSATION_MEMORY_INIT_SUCCESS",
1221
+ logger.debug(`[${functionTag}] Attempting MCP generation (attempt ${attempt}/${maxAttempts})...`);
1222
+ const mcpResult = await this.tryMCPGeneration(options);
1223
+ const mcpAttemptEndTime = process.hrtime.bigint();
1224
+ const mcpAttemptDurationNs = mcpAttemptEndTime - mcpAttemptStartTime;
1225
+ logger.debug(`[NeuroLink] 📊 LOG_POINT_G008_MCP_ATTEMPT_RESULT`, {
1226
+ logPoint: "G008_MCP_ATTEMPT_RESULT",
1035
1227
  generateInternalId,
1036
1228
  timestamp: new Date().toISOString(),
1037
1229
  elapsedMs: Date.now() - generateInternalStartTime,
1038
1230
  elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1039
- conversationMemoryDurationNs: conversationMemoryDurationNs.toString(),
1040
- conversationMemoryDurationMs: Number(conversationMemoryDurationNs) / 1000000,
1041
- message: "Conversation memory initialization completed successfully",
1231
+ mcpAttemptDurationNs: mcpAttemptDurationNs.toString(),
1232
+ mcpAttemptDurationMs: Number(mcpAttemptDurationNs) / 1000000,
1233
+ currentAttempt: attempt,
1234
+ resultAnalysis: {
1235
+ hasResult: !!mcpResult,
1236
+ resultType: typeof mcpResult,
1237
+ hasContent: !!(mcpResult && mcpResult.content),
1238
+ contentLength: mcpResult?.content?.length || 0,
1239
+ contentPreview: mcpResult?.content?.substring(0, 200) || "NO_CONTENT",
1240
+ hasToolExecutions: !!(mcpResult &&
1241
+ mcpResult.toolExecutions &&
1242
+ mcpResult.toolExecutions.length > 0),
1243
+ toolExecutionsCount: mcpResult?.toolExecutions?.length || 0,
1244
+ toolsUsedCount: mcpResult?.toolsUsed?.length || 0,
1245
+ provider: mcpResult?.provider || "NOT_SET",
1246
+ responseTime: mcpResult?.responseTime || 0,
1247
+ enhancedWithTools: mcpResult?.enhancedWithTools || false,
1248
+ },
1249
+ message: `MCP generation attempt ${attempt} completed - analyzing result`,
1042
1250
  });
1251
+ if (mcpResult &&
1252
+ (mcpResult.content ||
1253
+ (mcpResult.toolExecutions && mcpResult.toolExecutions.length > 0))) {
1254
+ logger.debug(`[${functionTag}] MCP generation successful on attempt ${attempt}`, {
1255
+ contentLength: mcpResult.content?.length || 0,
1256
+ toolsUsed: mcpResult.toolsUsed?.length || 0,
1257
+ toolExecutions: mcpResult.toolExecutions?.length || 0,
1258
+ });
1259
+ return mcpResult;
1260
+ }
1261
+ else {
1262
+ logger.debug(`[${functionTag}] MCP generation returned empty result on attempt ${attempt}`, {
1263
+ hasResult: !!mcpResult,
1264
+ hasContent: !!(mcpResult && mcpResult.content),
1265
+ contentLength: mcpResult?.content?.length || 0,
1266
+ toolExecutions: mcpResult?.toolExecutions?.length || 0,
1267
+ });
1268
+ }
1043
1269
  }
1044
- // 🚀 EXHAUSTIVE LOGGING POINT G005: MCP GENERATION BRANCH DECISION
1045
- const mcpDecisionStartTime = process.hrtime.bigint();
1046
- logger.debug(`[NeuroLink] 🔧 LOG_POINT_G005_MCP_DECISION_CHECK`, {
1047
- logPoint: "G005_MCP_DECISION_CHECK",
1048
- generateInternalId,
1049
- timestamp: new Date().toISOString(),
1050
- elapsedMs: Date.now() - generateInternalStartTime,
1051
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1052
- mcpDecisionStartTimeNs: mcpDecisionStartTime.toString(),
1053
- // 🎯 MCP decision factors
1054
- mcpDecisionFactors: {
1055
- disableTools: options.disableTools || false,
1056
- toolsEnabled: !options.disableTools,
1057
- mcpInitialized: this.mcpInitialized,
1058
- hasExternalServerManager: !!this.externalServerManager,
1059
- hasToolRegistry: !!toolRegistry,
1060
- toolRegistrySize: 0, // Not accessible as size property
1061
- shouldTryMCP: !options.disableTools,
1062
- },
1063
- // 🔍 MCP readiness analysis
1064
- mcpReadinessAnalysis: {
1065
- mcpAvailable: !options.disableTools && this.mcpInitialized,
1066
- componentsReady: {
1067
- externalServerManager: !!this.externalServerManager,
1068
- toolRegistry: !!toolRegistry,
1069
- providerRegistry: !!AIProviderFactory,
1070
- },
1071
- },
1072
- message: "Analyzing MCP generation eligibility and readiness",
1073
- });
1074
- // Try MCP-enhanced generation first (if not explicitly disabled)
1075
- if (!options.disableTools) {
1076
- // 🚀 EXHAUSTIVE LOGGING POINT G006: MCP RETRY LOOP INITIALIZATION
1077
- const mcpAttempts = 0;
1078
- const maxMcpRetries = 2; // Allow retries for tool-related failures
1079
- const mcpRetryLoopStartTime = process.hrtime.bigint();
1080
- logger.debug(`[NeuroLink] 🔄 LOG_POINT_G006_MCP_RETRY_LOOP_START`, {
1081
- logPoint: "G006_MCP_RETRY_LOOP_START",
1082
- generateInternalId,
1083
- timestamp: new Date().toISOString(),
1084
- elapsedMs: Date.now() - generateInternalStartTime,
1085
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1086
- mcpRetryLoopStartTimeNs: mcpRetryLoopStartTime.toString(),
1087
- maxMcpRetries,
1088
- totalPossibleAttempts: maxMcpRetries + 1,
1089
- currentAttempt: mcpAttempts + 1,
1090
- message: "Starting MCP generation retry loop with failure tolerance",
1270
+ catch (error) {
1271
+ logger.debug(`[${functionTag}] MCP generation failed on attempt ${attempt}/${maxAttempts}`, {
1272
+ error: error instanceof Error ? error.message : String(error),
1273
+ willRetry: attempt < maxAttempts,
1091
1274
  });
1092
- const maxAttempts = maxMcpRetries + 1;
1093
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1094
- try {
1095
- // 🚀 EXHAUSTIVE LOGGING POINT G007: MCP GENERATION ATTEMPT
1096
- const mcpAttemptStartTime = process.hrtime.bigint();
1097
- logger.debug(`[NeuroLink] 🎯 LOG_POINT_G007_MCP_ATTEMPT_START`, {
1098
- logPoint: "G007_MCP_ATTEMPT_START",
1099
- generateInternalId,
1100
- timestamp: new Date().toISOString(),
1101
- elapsedMs: Date.now() - generateInternalStartTime,
1102
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1103
- mcpAttemptStartTimeNs: mcpAttemptStartTime.toString(),
1104
- currentAttempt: attempt,
1105
- maxAttempts,
1106
- isFirstAttempt: attempt === 1,
1107
- isLastAttempt: attempt === maxAttempts,
1108
- attemptType: attempt === 1 ? "INITIAL" : "RETRY",
1109
- message: `Attempting MCP generation (attempt ${attempt}/${maxAttempts})`,
1110
- });
1111
- logger.debug(`[${functionTag}] Attempting MCP generation (attempt ${attempt}/${maxAttempts})...`);
1112
- const mcpResult = await this.tryMCPGeneration(options);
1113
- // 🚀 EXHAUSTIVE LOGGING POINT G008: MCP GENERATION ATTEMPT RESULT
1114
- const mcpAttemptEndTime = process.hrtime.bigint();
1115
- const mcpAttemptDurationNs = mcpAttemptEndTime - mcpAttemptStartTime;
1116
- logger.debug(`[NeuroLink] 📊 LOG_POINT_G008_MCP_ATTEMPT_RESULT`, {
1117
- logPoint: "G008_MCP_ATTEMPT_RESULT",
1118
- generateInternalId,
1119
- timestamp: new Date().toISOString(),
1120
- elapsedMs: Date.now() - generateInternalStartTime,
1121
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1122
- mcpAttemptDurationNs: mcpAttemptDurationNs.toString(),
1123
- mcpAttemptDurationMs: Number(mcpAttemptDurationNs) / 1000000,
1124
- currentAttempt: attempt,
1125
- // 🎯 Result analysis
1126
- resultAnalysis: {
1127
- hasResult: !!mcpResult,
1128
- resultType: typeof mcpResult,
1129
- hasContent: !!(mcpResult && mcpResult.content),
1130
- contentLength: mcpResult?.content?.length || 0,
1131
- contentPreview: mcpResult?.content?.substring(0, 200) || "NO_CONTENT",
1132
- hasToolExecutions: !!(mcpResult &&
1133
- mcpResult.toolExecutions &&
1134
- mcpResult.toolExecutions.length > 0),
1135
- toolExecutionsCount: mcpResult?.toolExecutions?.length || 0,
1136
- toolsUsedCount: mcpResult?.toolsUsed?.length || 0,
1137
- provider: mcpResult?.provider || "NOT_SET",
1138
- responseTime: mcpResult?.responseTime || 0,
1139
- enhancedWithTools: mcpResult?.enhancedWithTools || false,
1140
- },
1141
- message: `MCP generation attempt ${attempt} completed - analyzing result`,
1142
- });
1143
- if (mcpResult && mcpResult.content) {
1144
- logger.debug(`[${functionTag}] MCP generation successful on attempt ${attempt}`, {
1145
- contentLength: mcpResult.content.length,
1146
- toolsUsed: mcpResult.toolsUsed?.length || 0,
1147
- toolExecutions: mcpResult.toolExecutions?.length || 0,
1148
- });
1149
- // Store conversation turn
1150
- await storeConversationTurn(this.conversationMemory, options, mcpResult);
1151
- return mcpResult;
1152
- }
1153
- else {
1154
- logger.debug(`[${functionTag}] MCP generation returned empty result on attempt ${attempt}:`, {
1155
- hasResult: !!mcpResult,
1156
- hasContent: !!(mcpResult && mcpResult.content),
1157
- contentLength: mcpResult?.content?.length || 0,
1158
- toolExecutions: mcpResult?.toolExecutions?.length || 0,
1159
- });
1160
- // If we got a result but no content, and we have tool executions, this might be a tool success case
1161
- if (mcpResult &&
1162
- mcpResult.toolExecutions &&
1163
- mcpResult.toolExecutions.length > 0) {
1164
- logger.debug(`[${functionTag}] Found tool executions but no content, continuing with result`);
1165
- // Store conversation turn even with empty content if tools executed
1166
- await storeConversationTurn(this.conversationMemory, options, mcpResult);
1167
- return mcpResult;
1168
- }
1169
- }
1170
- }
1171
- catch (error) {
1172
- logger.debug(`[${functionTag}] MCP generation failed on attempt ${attempt}/${maxAttempts}`, {
1173
- error: error instanceof Error ? error.message : String(error),
1174
- willRetry: attempt < maxAttempts,
1175
- });
1176
- // If this was the last attempt, break and fall back
1177
- if (attempt >= maxAttempts) {
1178
- logger.debug(`[${functionTag}] All MCP attempts exhausted, falling back to direct generation`);
1179
- break;
1180
- }
1181
- // Small delay before retry to allow transient issues to resolve
1182
- await new Promise((resolve) => setTimeout(resolve, 500));
1183
- }
1275
+ if (attempt >= maxAttempts) {
1276
+ logger.debug(`[${functionTag}] All MCP attempts exhausted, falling back to direct generation`);
1277
+ break;
1184
1278
  }
1279
+ await new Promise((resolve) => setTimeout(resolve, 500));
1185
1280
  }
1186
- // Fall back to direct provider generation
1187
- const directResult = await this.directProviderGeneration(options);
1188
- logger.debug(`[${functionTag}] Direct generation successful`);
1189
- // Store conversation turn
1190
- await storeConversationTurn(this.conversationMemory, options, directResult);
1191
- return directResult;
1192
- }
1193
- catch (error) {
1194
- logger.error(`[${functionTag}] All generation methods failed`, {
1195
- error: error instanceof Error ? error.message : String(error),
1196
- });
1197
- throw error;
1198
1281
  }
1282
+ return null;
1199
1283
  }
1200
1284
  /**
1201
1285
  * Try MCP-enhanced generation (no fallback recursion)
@@ -1299,6 +1383,9 @@ export class NeuroLink {
1299
1383
  // Create provider and generate
1300
1384
  const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
1301
1385
  this);
1386
+ // ADD: Emit connection events for all providers (Bedrock-compatible)
1387
+ this.emitter.emit("connected");
1388
+ this.emitter.emit("message", `${providerName} provider initialized successfully`);
1302
1389
  // Enable tool execution for the provider using BaseProvider method
1303
1390
  provider.setupToolExecutor({
1304
1391
  customTools: this.getCustomTools(),
@@ -1393,6 +1480,9 @@ export class NeuroLink {
1393
1480
  const conversationMessages = await getConversationMessages(this.conversationMemory, options);
1394
1481
  const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
1395
1482
  this);
1483
+ // ADD: Emit connection events for successful provider creation (Bedrock-compatible)
1484
+ this.emitter.emit("connected");
1485
+ this.emitter.emit("message", `${providerName} provider initialized successfully`);
1396
1486
  // Enable tool execution for direct provider generation using BaseProvider method
1397
1487
  provider.setupToolExecutor({
1398
1488
  customTools: this.getCustomTools(),
@@ -1454,7 +1544,7 @@ export class NeuroLink {
1454
1544
  * Execute tools if available through centralized registry
1455
1545
  * Simplified approach without domain detection - relies on tool registry
1456
1546
  */
1457
- async detectAndExecuteTools(prompt, domainType) {
1547
+ async detectAndExecuteTools(prompt, _domainType) {
1458
1548
  const functionTag = "NeuroLink.detectAndExecuteTools";
1459
1549
  try {
1460
1550
  // Simplified: Just return original prompt without complex detection
@@ -1571,7 +1661,51 @@ export class NeuroLink {
1571
1661
  const functionTag = "NeuroLink.stream";
1572
1662
  const streamId = `neurolink-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1573
1663
  const journeyStartTime = new Date().toISOString();
1574
- // 🚀 EXHAUSTIVE LOGGING POINT 1: MAIN NEUROLINK STREAM ENTRY POINT
1664
+ this.logStreamEntryPoint(streamId, journeyStartTime, functionTag, startTime, hrTimeStart, options);
1665
+ this.logPerformanceBaseline(streamId, startTime, hrTimeStart);
1666
+ await this.validateStreamInput(options, streamId, startTime, hrTimeStart);
1667
+ this.emitStreamStartEvents(options, startTime);
1668
+ let enhancedOptions;
1669
+ let factoryResult;
1670
+ try {
1671
+ await this.initializeMCP();
1672
+ const originalPrompt = options.input.text;
1673
+ if (this.contextManager) {
1674
+ options.input.text = this.contextManager.getContextForPrompt("user", options.input.text);
1675
+ }
1676
+ factoryResult = processStreamingFactoryOptions(options);
1677
+ enhancedOptions = createCleanStreamOptions(options);
1678
+ const { toolResults: _toolResults, enhancedPrompt } = await this.detectAndExecuteTools(options.input.text, undefined);
1679
+ if (enhancedPrompt !== options.input.text) {
1680
+ enhancedOptions.input.text = enhancedPrompt;
1681
+ }
1682
+ const { stream: mcpStream, provider: providerName } = await this.createMCPStream(enhancedOptions);
1683
+ const streamResult = await this.processStreamResult(mcpStream, enhancedOptions, factoryResult);
1684
+ const responseTime = Date.now() - startTime;
1685
+ if (this.contextManager) {
1686
+ await this.contextManager.addTurn("user", originalPrompt);
1687
+ if (streamResult.content) {
1688
+ await this.contextManager.addTurn("assistant", streamResult.content);
1689
+ }
1690
+ }
1691
+ this.emitStreamEndEvents(streamResult);
1692
+ return this.createStreamResponse(streamResult, mcpStream, {
1693
+ providerName,
1694
+ options,
1695
+ startTime,
1696
+ responseTime,
1697
+ streamId,
1698
+ fallback: false,
1699
+ });
1700
+ }
1701
+ catch (error) {
1702
+ return this.handleStreamError(error, options, startTime, streamId, undefined, undefined);
1703
+ }
1704
+ }
1705
+ /**
1706
+ * Log stream entry point with comprehensive analysis
1707
+ */
1708
+ logStreamEntryPoint(streamId, journeyStartTime, functionTag, startTime, hrTimeStart, options) {
1575
1709
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_001_STREAM_ENTRY_START`, {
1576
1710
  logPoint: "001_STREAM_ENTRY_START",
1577
1711
  streamId,
@@ -1584,12 +1718,10 @@ export class NeuroLink {
1584
1718
  arch: process.arch,
1585
1719
  memoryUsage: process.memoryUsage(),
1586
1720
  cpuUsage: process.cpuUsage(),
1587
- // Comprehensive input validation
1588
1721
  hasOptions: !!options,
1589
1722
  optionsType: typeof options,
1590
1723
  optionsKeys: options ? Object.keys(options) : [],
1591
1724
  optionsSize: options ? JSON.stringify(options).length : 0,
1592
- // Deep input analysis
1593
1725
  hasInput: !!options?.input,
1594
1726
  inputType: typeof options?.input,
1595
1727
  inputKeys: options?.input ? Object.keys(options.input) : [],
@@ -1597,53 +1729,18 @@ export class NeuroLink {
1597
1729
  inputTextType: typeof options?.input?.text,
1598
1730
  inputTextLength: options?.input?.text?.length || 0,
1599
1731
  inputTextPreview: options?.input?.text?.substring(0, 200) || "NO_TEXT",
1600
- inputTextHash: options?.input?.text
1601
- ? "hash-" +
1602
- options.input.text.length +
1603
- "-" +
1604
- Math.random().toString(36).substr(2, 8)
1605
- : "NO_HASH",
1606
- // Provider configuration analysis
1607
1732
  hasProvider: !!options?.provider,
1608
1733
  providerValue: options?.provider || "NOT_SET",
1609
1734
  isAutoProvider: options?.provider === "auto" || !options?.provider,
1610
- // Model configuration analysis
1611
1735
  hasModel: !!options?.model,
1612
1736
  modelValue: options?.model || "NOT_SET",
1613
- isDefaultModel: !options?.model,
1614
- // Advanced configuration analysis
1615
- hasSystemPrompt: !!options?.systemPrompt,
1616
- systemPromptLength: options?.systemPrompt?.length || 0,
1617
- systemPromptPreview: options?.systemPrompt?.substring(0, 100) || "NO_SYSTEM_PROMPT",
1618
- hasTemperature: !!options?.temperature,
1619
- temperatureValue: options?.temperature || "NOT_SET",
1620
- isValidTemperature: typeof options?.temperature === "number" &&
1621
- options.temperature >= 0 &&
1622
- options.temperature <= 2,
1623
- hasMaxTokens: !!options?.maxTokens,
1624
- maxTokensValue: options?.maxTokens || "NOT_SET",
1625
- isValidMaxTokens: typeof options?.maxTokens === "number" && options.maxTokens > 0,
1626
- hasDisableTools: options?.disableTools !== undefined,
1627
- disableToolsValue: options?.disableTools || false,
1628
- hasContext: !!options?.context,
1629
- contextKeys: options?.context ? Object.keys(options.context) : [],
1630
- contextSize: options?.context
1631
- ? JSON.stringify(options.context).length
1632
- : 0,
1633
- // Environment analysis
1634
- nodeEnv: process.env.NODE_ENV || "UNKNOWN",
1635
- hasProxyConfig: !!(process.env.HTTP_PROXY ||
1636
- process.env.HTTPS_PROXY ||
1637
- process.env.http_proxy ||
1638
- process.env.https_proxy),
1639
- httpProxy: process.env.HTTP_PROXY || process.env.http_proxy || "NOT_SET",
1640
- httpsProxy: process.env.HTTPS_PROXY || process.env.https_proxy || "NOT_SET",
1641
- hasGoogleCredentials: !!(process.env.GOOGLE_APPLICATION_CREDENTIALS ||
1642
- process.env.GOOGLE_SERVICE_ACCOUNT_KEY),
1643
- googleCredentialsPath: process.env.GOOGLE_APPLICATION_CREDENTIALS || "NOT_SET",
1644
1737
  message: "EXHAUSTIVE NeuroLink main stream method entry point with comprehensive environment analysis",
1645
1738
  });
1646
- // 🚀 EXHAUSTIVE LOGGING POINT 2: MEMORY AND PERFORMANCE BASELINE
1739
+ }
1740
+ /**
1741
+ * Log performance baseline
1742
+ */
1743
+ logPerformanceBaseline(streamId, startTime, hrTimeStart) {
1647
1744
  const memoryBaseline = process.memoryUsage();
1648
1745
  const cpuBaseline = process.cpuUsage();
1649
1746
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_002_PERFORMANCE_BASELINE`, {
@@ -1669,14 +1766,18 @@ export class NeuroLink {
1669
1766
  global.gc();
1670
1767
  return process.memoryUsage();
1671
1768
  }
1672
- catch (e) {
1769
+ catch {
1673
1770
  return null;
1674
1771
  }
1675
1772
  })()
1676
1773
  : null,
1677
1774
  message: "Performance baseline metrics captured for stream processing",
1678
1775
  });
1679
- // 🚀 EXHAUSTIVE LOGGING POINT 3: INPUT VALIDATION START
1776
+ }
1777
+ /**
1778
+ * Validate stream input with comprehensive error reporting
1779
+ */
1780
+ async validateStreamInput(options, streamId, startTime, hrTimeStart) {
1680
1781
  const validationStartTime = process.hrtime.bigint();
1681
1782
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_003_VALIDATION_START`, {
1682
1783
  logPoint: "003_VALIDATION_START",
@@ -1687,45 +1788,6 @@ export class NeuroLink {
1687
1788
  validationStartTimeNs: validationStartTime.toString(),
1688
1789
  message: "Starting comprehensive input validation process",
1689
1790
  });
1690
- // 🚀 EXHAUSTIVE LOGGING POINT 4: DETAILED VALIDATION CHECKS
1691
- logger.debug(`[NeuroLink] 🎯 LOG_POINT_004_VALIDATION_CHECKS`, {
1692
- logPoint: "004_VALIDATION_CHECKS",
1693
- streamId,
1694
- timestamp: new Date().toISOString(),
1695
- elapsedMs: Date.now() - startTime,
1696
- checks: {
1697
- hasOptions: !!options,
1698
- optionsIsObject: typeof options === "object" && options !== null,
1699
- hasInput: !!(options && options.input),
1700
- inputIsObject: !!(options &&
1701
- options.input &&
1702
- typeof options.input === "object"),
1703
- hasInputText: !!(options && options.input && options.input.text),
1704
- inputTextIsString: !!(options &&
1705
- options.input &&
1706
- typeof options.input.text === "string"),
1707
- inputTextNotEmpty: !!(options &&
1708
- options.input &&
1709
- options.input.text &&
1710
- options.input.text.trim() !== ""),
1711
- inputTextLength: options?.input?.text?.length || 0,
1712
- inputTextTrimmedLength: options?.input?.text?.trim()?.length || 0,
1713
- },
1714
- optionsStructure: options
1715
- ? {
1716
- keys: Object.keys(options),
1717
- inputKeys: options.input ? Object.keys(options.input) : null,
1718
- inputTextType: typeof options.input?.text,
1719
- inputTextValue: options.input?.text?.substring(0, 50) +
1720
- (options.input?.text?.length > 50 ? "..." : ""),
1721
- inputTextCharCodes: options.input?.text
1722
- ? Array.from(options.input.text.substring(0, 10)).map((c) => c.charCodeAt(0))
1723
- : null,
1724
- }
1725
- : null,
1726
- message: "Detailed validation checks performed",
1727
- });
1728
- // Validate input with comprehensive error reporting
1729
1791
  if (!options?.input?.text ||
1730
1792
  typeof options.input.text !== "string" ||
1731
1793
  options.input.text.trim() === "") {
@@ -1740,47 +1802,10 @@ export class NeuroLink {
1740
1802
  validationDurationNs: validationDurationNs.toString(),
1741
1803
  validationDurationMs: Number(validationDurationNs) / 1000000,
1742
1804
  validationError: "Stream options must include input.text as a non-empty string",
1743
- // Detailed failure analysis
1744
- failureReason: !options
1745
- ? "NO_OPTIONS"
1746
- : !options.input
1747
- ? "NO_INPUT"
1748
- : !options.input.text
1749
- ? "NO_INPUT_TEXT"
1750
- : typeof options.input.text !== "string"
1751
- ? "INPUT_TEXT_NOT_STRING"
1752
- : options.input.text.trim() === ""
1753
- ? "INPUT_TEXT_EMPTY_OR_WHITESPACE"
1754
- : "UNKNOWN",
1755
- // Deep analysis for debugging
1756
- hasOptions: !!options,
1757
- optionsType: typeof options,
1758
- hasInput: !!options?.input,
1759
- inputType: typeof options?.input,
1760
- hasInputText: !!options?.input?.text,
1761
- inputTextType: typeof options?.input?.text,
1762
- inputTextValue: options?.input?.text,
1763
- inputTextLength: options?.input?.text?.length || 0,
1764
- inputTextTrimmed: options?.input?.text?.trim(),
1765
- inputTextTrimmedLength: options?.input?.text?.trim()?.length || 0,
1766
- // Character analysis for whitespace debugging
1767
- inputTextCharacters: options?.input?.text
1768
- ? Array.from(options.input.text)
1769
- .map((char, index) => ({
1770
- index,
1771
- char,
1772
- charCode: char.charCodeAt(0),
1773
- isWhitespace: /\s/.test(char),
1774
- }))
1775
- .slice(0, 20)
1776
- : null,
1777
- memoryAtFailure: process.memoryUsage(),
1778
- cpuAtFailure: process.cpuUsage(),
1779
1805
  message: "EXHAUSTIVE validation failure analysis with character-level debugging",
1780
1806
  });
1781
1807
  throw new Error("Stream options must include input.text as a non-empty string");
1782
1808
  }
1783
- // 🚀 EXHAUSTIVE LOGGING POINT 6: VALIDATION SUCCESS
1784
1809
  const validationSuccessTime = process.hrtime.bigint();
1785
1810
  const validationDurationNs = validationSuccessTime - validationStartTime;
1786
1811
  logger.debug(`[NeuroLink] ✅ LOG_POINT_006_VALIDATION_SUCCESS`, {
@@ -1795,289 +1820,116 @@ export class NeuroLink {
1795
1820
  inputTextLength: options.input.text.length,
1796
1821
  inputTextTrimmedLength: options.input.text.trim().length,
1797
1822
  inputTextPreview: options.input.text.substring(0, 100),
1798
- inputTextHash: "hash-" +
1799
- options.input.text.length +
1800
- "-" +
1801
- Math.random().toString(36).substr(2, 8),
1802
- inputTextWordCount: options.input.text
1803
- .split(/\s+/)
1804
- .filter((word) => word.length > 0).length,
1805
- inputTextLineCount: options.input.text.split(/\n/).length,
1806
- memoryAfterValidation: process.memoryUsage(),
1807
- cpuAfterValidation: process.cpuUsage(),
1808
1823
  message: "EXHAUSTIVE validation success - proceeding with stream processing",
1809
1824
  });
1810
- // Emit stream start event
1825
+ }
1826
+ /**
1827
+ * Emit stream start events
1828
+ */
1829
+ emitStreamStartEvents(options, startTime) {
1811
1830
  this.emitter.emit("stream:start", {
1812
1831
  provider: options.provider || "auto",
1813
1832
  timestamp: startTime,
1814
1833
  });
1815
- // Process factory configuration for streaming
1816
- const factoryResult = processFactoryOptions(options);
1817
- const streamingResult = processStreamingFactoryOptions(options);
1818
- // Validate factory configuration if present
1819
- if (factoryResult.hasFactoryConfig && options.factoryConfig) {
1820
- const validation = validateFactoryConfig(options.factoryConfig);
1821
- if (!validation.isValid) {
1822
- mcpLogger.warn("Invalid factory configuration detected in stream", {
1823
- errors: validation.errors,
1824
- });
1825
- // Continue with warning rather than throwing - graceful degradation
1826
- }
1827
- }
1828
- // Log factory processing results
1829
- if (factoryResult.hasFactoryConfig) {
1830
- mcpLogger.debug(`[${functionTag}] Factory configuration detected`, {
1831
- domainType: factoryResult.domainType,
1832
- enhancementType: factoryResult.enhancementType,
1833
- hasStreamingConfig: streamingResult.hasStreamingConfig,
1834
- });
1835
- }
1836
- // Initialize MCP if needed
1837
- await this.initializeMCP();
1838
- // Context creation removed - was never used
1839
- // Determine provider to use
1840
- const providerName = options.provider === "auto" || !options.provider
1841
- ? await getBestProvider()
1842
- : options.provider;
1843
- // Prepare enhanced options for both success and fallback paths
1844
- let enhancedOptions = options;
1845
- if (factoryResult.hasFactoryConfig) {
1846
- enhancedOptions = {
1847
- ...options,
1848
- // Merge contexts instead of overriding to preserve provider-required context
1849
- context: {
1850
- ...(options.context || {}),
1851
- ...(factoryResult.processedContext || {}),
1852
- },
1853
- // Ensure evaluation is enabled when using factory patterns
1854
- enableEvaluation: options.enableEvaluation ?? true,
1855
- // Use domain type for evaluation if available
1856
- evaluationDomain: factoryResult.domainType || options.evaluationDomain,
1857
- };
1858
- mcpLogger.debug(`[${functionTag}] Enhanced stream options with factory config`, {
1859
- domainType: factoryResult.domainType,
1860
- enhancementType: factoryResult.enhancementType,
1861
- hasProcessedContext: !!factoryResult.processedContext,
1862
- });
1863
- }
1864
- try {
1865
- mcpLogger.debug(`[${functionTag}] Starting MCP-enabled streaming`, {
1866
- provider: providerName,
1867
- prompt: (options.input.text?.substring(0, 100) || "No text") + "...",
1868
- });
1869
- // Initialize conversation memory if enabled (same as generate function)
1870
- if (this.conversationMemory) {
1871
- await this.conversationMemory.initialize();
1872
- }
1873
- // Get conversation messages for context injection (same as generate function)
1874
- const conversationMessages = await getConversationMessages(this.conversationMemory, {
1875
- prompt: options.input.text,
1876
- context: enhancedOptions.context,
1877
- });
1878
- // Create provider using the same factory pattern as generate
1879
- const provider = await AIProviderFactory.createBestProvider(providerName, options.model, true, this);
1880
- // Enable tool execution for streaming using BaseProvider method
1881
- provider.setupToolExecutor({
1882
- customTools: this.getCustomTools(),
1883
- executeTool: this.executeTool.bind(this),
1884
- }, functionTag);
1885
- // Create clean options for provider (remove factoryConfig) and inject conversation history
1886
- const cleanOptions = createCleanStreamOptions(enhancedOptions);
1887
- const optionsWithHistory = {
1888
- ...cleanOptions,
1889
- conversationMessages, // Inject conversation history like in generate function
1890
- };
1891
- // Call the provider's stream method with conversation history
1892
- const streamResult = await provider.stream(optionsWithHistory);
1893
- // Extract the stream from the result
1894
- const originalStream = streamResult.stream;
1895
- // Create a proper tee pattern that accumulates content and stores memory after consumption
1896
- let accumulatedContent = "";
1897
- const processedStream = (async function* (self) {
1898
- try {
1899
- for await (const chunk of originalStream) {
1900
- // Enhanced chunk validation and content handling
1901
- let processedChunk = chunk;
1902
- if (chunk && typeof chunk === "object") {
1903
- // Ensure chunk has content property and it's a string
1904
- if (typeof chunk.content === "string") {
1905
- accumulatedContent += chunk.content;
1906
- }
1907
- else if (chunk.content === undefined ||
1908
- chunk.content === null) {
1909
- // Handle undefined/null content gracefully - create a new chunk object
1910
- processedChunk = { ...chunk, content: "" };
1911
- }
1912
- else if (typeof chunk.content !== "string") {
1913
- // Convert non-string content to string - create a new chunk object
1914
- const stringContent = String(chunk.content || "");
1915
- processedChunk = { ...chunk, content: stringContent };
1916
- accumulatedContent += stringContent;
1917
- }
1918
- }
1919
- else if (chunk === null || chunk === undefined) {
1920
- // Create a safe empty chunk if chunk is null/undefined
1921
- processedChunk = { content: "" };
1922
- }
1923
- yield processedChunk; // Preserve original streaming behavior with safe content
1924
- }
1925
- }
1926
- finally {
1927
- // Store memory after stream consumption
1928
- if (self.conversationMemory) {
1929
- try {
1930
- await self.conversationMemory.storeConversationTurn(enhancedOptions.context
1931
- ?.sessionId, enhancedOptions.context
1932
- ?.userId, options.input.text, accumulatedContent);
1933
- logger.debug("Stream conversation turn stored", {
1934
- sessionId: enhancedOptions.context
1935
- ?.sessionId,
1936
- userInputLength: options.input.text.length,
1937
- responseLength: accumulatedContent.length,
1938
- });
1939
- }
1940
- catch (error) {
1941
- logger.warn("Failed to store stream conversation turn", {
1942
- error: error instanceof Error ? error.message : String(error),
1943
- });
1944
- }
1945
- }
1946
- }
1947
- })(this);
1948
- const responseTime = Date.now() - startTime;
1949
- mcpLogger.debug(`[${functionTag}] MCP-enabled streaming completed`, {
1950
- responseTime,
1951
- provider: providerName,
1952
- });
1953
- // Emit stream completion event
1954
- this.emitter.emit("stream:end", {
1955
- provider: providerName,
1956
- responseTime,
1957
- });
1958
- // Convert to StreamResult format - Include analytics and evaluation from provider
1959
- return {
1960
- stream: processedStream,
1961
- provider: providerName,
1962
- model: options.model,
1963
- usage: streamResult.usage,
1964
- finishReason: streamResult.finishReason,
1965
- toolCalls: streamResult.toolCalls,
1966
- toolResults: streamResult.toolResults,
1967
- analytics: streamResult.analytics,
1968
- evaluation: streamResult.evaluation
1969
- ? {
1970
- ...streamResult.evaluation,
1971
- // Include evaluationDomain from factory configuration
1972
- evaluationDomain: streamResult.evaluation
1973
- ?.evaluationDomain ??
1974
- enhancedOptions.evaluationDomain ??
1975
- factoryResult.domainType,
1976
- }
1977
- : undefined,
1978
- metadata: {
1979
- streamId: `neurolink-${Date.now()}`,
1980
- startTime,
1981
- responseTime,
1982
- },
1983
- };
1984
- }
1985
- catch (error) {
1986
- // Fall back to regular streaming if MCP fails
1987
- mcpLogger.warn(`[${functionTag}] MCP streaming failed, falling back to regular`, {
1988
- error: error instanceof Error ? error.message : String(error),
1989
- });
1990
- // Initialize conversation memory for fallback path (same as success path)
1991
- if (this.conversationMemory) {
1992
- await this.conversationMemory.initialize();
1993
- }
1994
- // Get conversation messages for fallback context injection
1995
- const fallbackConversationMessages = await getConversationMessages(this.conversationMemory, {
1996
- prompt: options.input.text,
1997
- context: enhancedOptions.context,
1998
- });
1999
- // Use factory to create provider without MCP
2000
- const provider = await AIProviderFactory.createBestProvider(providerName, options.model, false, // Disable MCP for fallback
2001
- this);
2002
- // Enable tool execution for fallback streaming using BaseProvider method
2003
- provider.setupToolExecutor({
2004
- customTools: this.getCustomTools(),
2005
- executeTool: this.executeTool.bind(this),
2006
- }, functionTag);
2007
- // Create clean options for fallback provider and inject conversation history
2008
- const cleanOptions = createCleanStreamOptions(enhancedOptions);
2009
- const fallbackOptionsWithHistory = {
2010
- ...cleanOptions,
2011
- conversationMessages: fallbackConversationMessages, // Inject conversation history in fallback
2012
- };
2013
- const streamResult = await provider.stream(fallbackOptionsWithHistory);
2014
- // Create a proper tee pattern for fallback that accumulates content and stores memory after consumption
2015
- let fallbackAccumulatedContent = "";
2016
- const fallbackProcessedStream = (async function* (self) {
2017
- try {
2018
- for await (const chunk of streamResult.stream) {
2019
- if (chunk && typeof chunk.content === "string") {
2020
- fallbackAccumulatedContent += chunk.content;
2021
- }
2022
- yield chunk; // Preserve original streaming behavior
2023
- }
2024
- }
2025
- finally {
2026
- // Store memory after fallback stream consumption
2027
- if (self.conversationMemory) {
2028
- try {
2029
- await self.conversationMemory.storeConversationTurn(enhancedOptions.context
2030
- ?.sessionId, enhancedOptions.context
2031
- ?.userId, options.input.text, fallbackAccumulatedContent);
2032
- logger.debug("Fallback stream conversation turn stored", {
2033
- sessionId: enhancedOptions.context
2034
- ?.sessionId,
2035
- userInputLength: options.input.text.length,
2036
- responseLength: fallbackAccumulatedContent.length,
2037
- });
2038
- }
2039
- catch (error) {
2040
- logger.warn("Failed to store fallback stream conversation turn", {
2041
- error: error instanceof Error ? error.message : String(error),
2042
- });
2043
- }
2044
- }
2045
- }
2046
- })(this);
2047
- const responseTime = Date.now() - startTime;
2048
- // Emit stream completion event for fallback
2049
- this.emitter.emit("stream:end", {
2050
- provider: providerName,
1834
+ this.emitter.emit("response:start");
1835
+ this.emitter.emit("message", `Starting ${options.provider || "auto"} stream...`);
1836
+ }
1837
+ /**
1838
+ * Create MCP stream
1839
+ */
1840
+ async createMCPStream(options) {
1841
+ // Simplified placeholder - in the actual implementation this would contain the complex MCP stream logic
1842
+ const providerName = await getBestProvider(options.provider);
1843
+ const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
1844
+ this);
1845
+ // Enable tool execution for the provider using BaseProvider method
1846
+ provider.setupToolExecutor({
1847
+ customTools: this.getCustomTools(),
1848
+ executeTool: this.executeTool.bind(this),
1849
+ }, "NeuroLink.createMCPStream");
1850
+ const streamResult = await provider.stream(options);
1851
+ return { stream: streamResult.stream, provider: providerName };
1852
+ }
1853
+ /**
1854
+ * Process stream result
1855
+ */
1856
+ async processStreamResult(_stream, _options, _factoryResult) {
1857
+ // Simplified placeholder - in the actual implementation this would process the stream
1858
+ return {
1859
+ content: "",
1860
+ usage: undefined,
1861
+ finishReason: "stop",
1862
+ toolCalls: [],
1863
+ toolResults: [],
1864
+ analytics: undefined,
1865
+ evaluation: undefined,
1866
+ };
1867
+ }
1868
+ /**
1869
+ * Emit stream end events
1870
+ */
1871
+ emitStreamEndEvents(streamResult) {
1872
+ this.emitter.emit("stream:end", {
1873
+ responseTime: Date.now(),
1874
+ timestamp: Date.now(),
1875
+ });
1876
+ this.emitter.emit("response:end", streamResult.content || "");
1877
+ }
1878
+ /**
1879
+ * Create stream response
1880
+ */
1881
+ createStreamResponse(streamResult, stream, config) {
1882
+ return {
1883
+ stream,
1884
+ provider: config.providerName,
1885
+ model: config.options.model,
1886
+ usage: streamResult.usage,
1887
+ finishReason: streamResult.finishReason,
1888
+ toolCalls: streamResult.toolCalls,
1889
+ toolResults: streamResult.toolResults,
1890
+ analytics: streamResult.analytics,
1891
+ evaluation: streamResult.evaluation,
1892
+ metadata: {
1893
+ streamId: config.streamId,
1894
+ startTime: config.startTime,
1895
+ responseTime: config.responseTime,
1896
+ fallback: config.fallback || false,
1897
+ },
1898
+ };
1899
+ }
1900
+ /**
1901
+ * Handle stream error with fallback
1902
+ */
1903
+ async handleStreamError(error, options, startTime, streamId, _enhancedOptions, _factoryResult) {
1904
+ logger.error("Stream generation failed, attempting fallback", {
1905
+ error: error instanceof Error ? error.message : String(error),
1906
+ });
1907
+ const responseTime = Date.now() - startTime;
1908
+ const providerName = await getBestProvider(options.provider);
1909
+ const provider = await AIProviderFactory.createProvider(providerName, options.model, false);
1910
+ const fallbackStream = await provider.stream({
1911
+ input: { text: options.input.text },
1912
+ model: options.model,
1913
+ temperature: options.temperature,
1914
+ maxTokens: options.maxTokens,
1915
+ });
1916
+ return {
1917
+ stream: fallbackStream.stream,
1918
+ provider: providerName,
1919
+ model: options.model,
1920
+ usage: fallbackStream.usage,
1921
+ finishReason: fallbackStream.finishReason || "stop",
1922
+ toolCalls: fallbackStream.toolCalls || [],
1923
+ toolResults: fallbackStream.toolResults || [],
1924
+ analytics: fallbackStream.analytics,
1925
+ evaluation: fallbackStream.evaluation,
1926
+ metadata: {
1927
+ streamId,
1928
+ startTime,
2051
1929
  responseTime,
2052
1930
  fallback: true,
2053
- });
2054
- return {
2055
- stream: fallbackProcessedStream,
2056
- provider: providerName,
2057
- model: options.model,
2058
- usage: streamResult.usage,
2059
- finishReason: streamResult.finishReason,
2060
- toolCalls: streamResult.toolCalls,
2061
- toolResults: streamResult.toolResults,
2062
- analytics: streamResult.analytics,
2063
- evaluation: streamResult.evaluation
2064
- ? {
2065
- ...streamResult.evaluation,
2066
- // Include evaluationDomain in fallback stream
2067
- evaluationDomain: streamResult.evaluation
2068
- ?.evaluationDomain ??
2069
- enhancedOptions.evaluationDomain ??
2070
- factoryResult.domainType,
2071
- }
2072
- : undefined,
2073
- metadata: {
2074
- streamId: `neurolink-${Date.now()}`,
2075
- startTime,
2076
- responseTime,
2077
- fallback: true,
2078
- },
2079
- };
2080
- }
1931
+ },
1932
+ };
2081
1933
  }
2082
1934
  /**
2083
1935
  * Get the EventEmitter instance to listen to NeuroLink events for real-time monitoring and debugging.
@@ -2271,7 +2123,7 @@ export class NeuroLink {
2271
2123
  timestamp: Date.now(),
2272
2124
  });
2273
2125
  try {
2274
- // --- Start: Added Validation Logic ---
2126
+ // --- Start: Enhanced Validation Logic with FlexibleToolValidator ---
2275
2127
  if (!name || typeof name !== "string") {
2276
2128
  throw new Error("Invalid tool name");
2277
2129
  }
@@ -2281,55 +2133,36 @@ export class NeuroLink {
2281
2133
  if (typeof tool.execute !== "function") {
2282
2134
  throw new Error(`Tool '${name}' must have an execute method.`);
2283
2135
  }
2284
- // --- End: Added Validation Logic ---
2285
- // Import validation functions synchronously - they are pure functions
2286
- let validateTool;
2287
- let isToolNameAvailable;
2288
- let suggestToolNames;
2136
+ // Use FlexibleToolValidator for consistent validation across SDK and toolRegistry
2289
2137
  try {
2290
- // Try ES module import first
2291
- const toolRegistrationModule = require("./sdk/toolRegistration.js");
2292
- ({ validateTool, isToolNameAvailable, suggestToolNames } =
2293
- toolRegistrationModule);
2138
+ const flexibleValidatorModule = require("./mcp/flexibleToolValidator.js");
2139
+ const FlexibleToolValidator = flexibleValidatorModule.FlexibleToolValidator;
2140
+ // Use the same validation logic as toolRegistry (static method)
2141
+ const validationResult = FlexibleToolValidator.validateToolName(name);
2142
+ if (!validationResult.isValid) {
2143
+ throw new Error(`Tool validation failed: ${validationResult.error}`);
2144
+ }
2294
2145
  }
2295
2146
  catch (error) {
2296
- // Fallback: skip validation if import fails (graceful degradation)
2297
- logger.warn("Tool validation module not available, skipping advanced validation", {
2147
+ // If FlexibleToolValidator import fails, use basic safety checks
2148
+ logger.warn("FlexibleToolValidator not available, using basic validation", {
2298
2149
  error: error instanceof Error ? error.message : String(error),
2299
2150
  });
2300
- // Create minimal validation functions
2301
- validateTool = () => { }; // No-op
2302
- isToolNameAvailable = () => true; // Allow all names
2303
- suggestToolNames = () => ["alternative_tool"];
2304
- }
2305
- // Check if tool name is available (not reserved)
2306
- if (!isToolNameAvailable(name)) {
2307
- const suggestions = suggestToolNames(name);
2308
- throw new Error(`Tool name '${name}' is not available (reserved or invalid format). ` +
2309
- `Suggested alternatives: ${suggestions.slice(0, 3).join(", ")}`);
2310
- }
2311
- // Create a simplified tool object for validation
2312
- const toolForValidation = {
2313
- description: tool.description || "",
2314
- execute: async (params) => {
2315
- if (tool.execute) {
2316
- const result = await tool.execute(params);
2317
- return result;
2318
- }
2319
- return "";
2320
- },
2321
- parameters: tool.inputSchema,
2322
- metadata: {
2323
- category: "custom",
2324
- },
2325
- };
2326
- // Use comprehensive validation logic
2327
- try {
2328
- validateTool(name, toolForValidation);
2329
- }
2330
- catch (error) {
2331
- throw new Error(`Tool registration failed: ${error instanceof Error ? error.message : String(error)}`);
2151
+ // Basic safety checks to prevent obvious issues
2152
+ if (name.trim() === "") {
2153
+ throw new Error("Tool name cannot be empty");
2154
+ }
2155
+ if (name.length > 100) {
2156
+ throw new Error("Tool name is too long (maximum 100 characters)");
2157
+ }
2158
+ // eslint-disable-next-line no-control-regex
2159
+ if (/[\x00-\x1F\x7F]/.test(name)) {
2160
+ throw new Error("Tool name contains invalid control characters");
2161
+ }
2332
2162
  }
2163
+ // --- End: Enhanced Validation Logic ---
2164
+ // Tool object validation is now handled by FlexibleToolValidator above
2165
+ // Proceed with tool registration since validation passed
2333
2166
  // SMART DEFAULTS: Use utility to eliminate boilerplate creation
2334
2167
  const mcpServerInfo = createCustomToolServerInfo(name, tool);
2335
2168
  // Register with toolRegistry using MCPServerInfo directly
@@ -2489,11 +2322,14 @@ export class NeuroLink {
2489
2322
  : params,
2490
2323
  hasExternalManager: !!this.externalServerManager,
2491
2324
  });
2492
- // Emit tool start event
2325
+ // Emit tool start event (NeuroLink format - keep existing)
2493
2326
  this.emitter.emit("tool:start", {
2494
2327
  toolName,
2495
2328
  timestamp: executionStartTime,
2329
+ input: params, // Enhanced: add input parameters
2496
2330
  });
2331
+ // ADD: Bedrock-compatible tool:start event (positional parameters)
2332
+ this.emitter.emit("tool:start", toolName, params);
2497
2333
  // Set default options
2498
2334
  const finalOptions = {
2499
2335
  timeout: options?.timeout || 30000, // 30 second default timeout
@@ -2519,15 +2355,20 @@ export class NeuroLink {
2519
2355
  });
2520
2356
  }
2521
2357
  const metrics = this.toolExecutionMetrics.get(toolName);
2522
- metrics.totalExecutions++;
2358
+ if (metrics) {
2359
+ metrics.totalExecutions++;
2360
+ }
2523
2361
  try {
2524
2362
  mcpLogger.debug(`[${functionTag}] Executing tool: ${toolName}`, {
2525
2363
  toolName,
2526
2364
  params,
2527
2365
  options: finalOptions,
2528
- circuitBreakerState: circuitBreaker.getState(),
2366
+ circuitBreakerState: circuitBreaker?.getState(),
2529
2367
  });
2530
2368
  // Execute with circuit breaker, timeout, and retry logic
2369
+ if (!circuitBreaker) {
2370
+ throw new Error(`Circuit breaker not initialized for tool: ${toolName}`);
2371
+ }
2531
2372
  const result = await circuitBreaker.execute(async () => {
2532
2373
  return await withRetry(async () => {
2533
2374
  return await withTimeout(this.executeToolInternal(toolName, params, finalOptions), finalOptions.timeout, ErrorFactory.toolTimeout(toolName, finalOptions.timeout));
@@ -2546,12 +2387,14 @@ export class NeuroLink {
2546
2387
  });
2547
2388
  // Update success metrics
2548
2389
  const executionTime = Date.now() - executionStartTime;
2549
- metrics.successfulExecutions++;
2550
- metrics.lastExecutionTime = executionTime;
2551
- metrics.averageExecutionTime =
2552
- (metrics.averageExecutionTime * (metrics.successfulExecutions - 1) +
2553
- executionTime) /
2554
- metrics.successfulExecutions;
2390
+ if (metrics) {
2391
+ metrics.successfulExecutions++;
2392
+ metrics.lastExecutionTime = executionTime;
2393
+ metrics.averageExecutionTime =
2394
+ (metrics.averageExecutionTime * (metrics.successfulExecutions - 1) +
2395
+ executionTime) /
2396
+ metrics.successfulExecutions;
2397
+ }
2555
2398
  // Track memory usage
2556
2399
  const endMemory = MemoryManager.getMemoryUsageMB();
2557
2400
  const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
@@ -2566,15 +2409,17 @@ export class NeuroLink {
2566
2409
  toolName,
2567
2410
  executionTime,
2568
2411
  memoryDelta,
2569
- circuitBreakerState: circuitBreaker.getState(),
2412
+ circuitBreakerState: circuitBreaker?.getState(),
2570
2413
  });
2571
2414
  // Emit tool end event using the helper method
2572
- this.emitToolEndEvent(toolName, executionStartTime, true);
2415
+ this.emitToolEndEvent(toolName, executionStartTime, true, result);
2573
2416
  return result;
2574
2417
  }
2575
2418
  catch (error) {
2576
2419
  // Update failure metrics
2577
- metrics.failedExecutions++;
2420
+ if (metrics) {
2421
+ metrics.failedExecutions++;
2422
+ }
2578
2423
  const executionTime = Date.now() - executionStartTime;
2579
2424
  // Create structured error
2580
2425
  let structuredError;
@@ -2605,8 +2450,10 @@ export class NeuroLink {
2605
2450
  else {
2606
2451
  structuredError = ErrorFactory.toolExecutionFailed(toolName, new Error(String(error)));
2607
2452
  }
2453
+ // ADD: Centralized error event emission
2454
+ this.emitter.emit("error", structuredError);
2608
2455
  // Emit tool end event using the helper method
2609
- this.emitToolEndEvent(toolName, executionStartTime, false);
2456
+ this.emitToolEndEvent(toolName, executionStartTime, false, undefined, structuredError);
2610
2457
  // Add execution context to structured error
2611
2458
  structuredError = new NeuroLinkError({
2612
2459
  ...structuredError,
@@ -2615,8 +2462,8 @@ export class NeuroLink {
2615
2462
  executionTime,
2616
2463
  params,
2617
2464
  options: finalOptions,
2618
- circuitBreakerState: circuitBreaker.getState(),
2619
- circuitBreakerFailures: circuitBreaker.getFailureCount(),
2465
+ circuitBreakerState: circuitBreaker?.getState(),
2466
+ circuitBreakerFailures: circuitBreaker?.getFailureCount(),
2620
2467
  metrics: { ...metrics },
2621
2468
  },
2622
2469
  });
@@ -2667,9 +2514,21 @@ export class NeuroLink {
2667
2514
  userId: "neurolink-user",
2668
2515
  };
2669
2516
  const result = (await toolRegistry.executeTool(toolName, params, context));
2517
+ // ADD: Check if result indicates a failure and emit error event
2518
+ if (result &&
2519
+ typeof result === "object" &&
2520
+ "success" in result &&
2521
+ result.success === false) {
2522
+ const errorMessage = result.error || "Tool execution failed";
2523
+ const errorToEmit = new Error(errorMessage);
2524
+ this.emitter.emit("error", errorToEmit);
2525
+ }
2670
2526
  return result;
2671
2527
  }
2672
2528
  catch (error) {
2529
+ // ADD: Emergency error event emission (fallback)
2530
+ const errorToEmit = error instanceof Error ? error : new Error(String(error));
2531
+ this.emitter.emit("error", errorToEmit);
2673
2532
  // Check if tool was not found
2674
2533
  if (error instanceof Error && error.message.includes("not found")) {
2675
2534
  const availableTools = await this.getAllAvailableTools();
@@ -2841,6 +2700,9 @@ export class NeuroLink {
2841
2700
  }
2842
2701
  const { AIProviderFactory } = await import("./core/factory.js");
2843
2702
  const { hasProviderEnvVars } = await import("./utils/providerUtils.js");
2703
+ // Keep references to prevent unused variable warnings
2704
+ void AIProviderFactory;
2705
+ void hasProviderEnvVars;
2844
2706
  const providers = [
2845
2707
  "openai",
2846
2708
  "bedrock",
@@ -3103,7 +2965,7 @@ export class NeuroLink {
3103
2965
  const inMemoryServers = this.getInMemoryServers();
3104
2966
  if (inMemoryServers.has(serverId)) {
3105
2967
  const serverInfo = inMemoryServers.get(serverId);
3106
- return !!(serverInfo.tools && serverInfo.tools.length > 0);
2968
+ return !!(serverInfo?.tools && serverInfo.tools.length > 0);
3107
2969
  }
3108
2970
  // Test external MCP servers
3109
2971
  const externalServer = this.externalServerManager.getServer(serverId);
@@ -3610,7 +3472,7 @@ export class NeuroLink {
3610
3472
  * Convert JSON Schema to AI SDK compatible format
3611
3473
  * For now, we'll skip schema validation and let the AI SDK handle parameters dynamically
3612
3474
  */
3613
- convertJSONSchemaToAISDKFormat(inputSchema) {
3475
+ convertJSONSchemaToAISDKFormat(_inputSchema) {
3614
3476
  // The simplest approach: don't provide parameters schema
3615
3477
  // This lets the AI SDK handle the tool without schema validation
3616
3478
  // Tools will still work, they just won't have strict parameter validation