@juspay/neurolink 7.29.2 → 7.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (226) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli/commands/config.d.ts +83 -83
  3. package/dist/cli/commands/mcp.js +39 -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 +8 -0
  7. package/dist/cli/factories/commandFactory.js +65 -65
  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 +11 -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/config/conversationMemoryConfig.js +5 -0
  17. package/dist/core/analytics.d.ts +2 -24
  18. package/dist/core/analytics.js +12 -17
  19. package/dist/core/baseProvider.d.ts +30 -1
  20. package/dist/core/baseProvider.js +180 -198
  21. package/dist/core/conversationMemoryManager.d.ts +9 -15
  22. package/dist/core/conversationMemoryManager.js +98 -57
  23. package/dist/core/dynamicModels.d.ts +4 -4
  24. package/dist/core/dynamicModels.js +7 -7
  25. package/dist/core/evaluation.d.ts +9 -9
  26. package/dist/core/evaluation.js +117 -65
  27. package/dist/core/evaluationProviders.d.ts +18 -2
  28. package/dist/core/evaluationProviders.js +15 -13
  29. package/dist/core/modelConfiguration.d.ts +63 -0
  30. package/dist/core/modelConfiguration.js +354 -290
  31. package/dist/core/streamAnalytics.d.ts +10 -5
  32. package/dist/core/streamAnalytics.js +10 -10
  33. package/dist/core/types.d.ts +22 -110
  34. package/dist/core/types.js +13 -0
  35. package/dist/factories/providerFactory.js +1 -1
  36. package/dist/index.d.ts +2 -1
  37. package/dist/lib/config/configManager.js +5 -2
  38. package/dist/lib/config/conversationMemoryConfig.js +5 -0
  39. package/dist/lib/core/analytics.d.ts +2 -24
  40. package/dist/lib/core/analytics.js +12 -17
  41. package/dist/lib/core/baseProvider.d.ts +30 -1
  42. package/dist/lib/core/baseProvider.js +180 -198
  43. package/dist/lib/core/conversationMemoryManager.d.ts +9 -15
  44. package/dist/lib/core/conversationMemoryManager.js +98 -57
  45. package/dist/lib/core/dynamicModels.js +7 -7
  46. package/dist/lib/core/evaluation.d.ts +9 -9
  47. package/dist/lib/core/evaluation.js +117 -65
  48. package/dist/lib/core/evaluationProviders.d.ts +18 -2
  49. package/dist/lib/core/evaluationProviders.js +15 -13
  50. package/dist/lib/core/modelConfiguration.d.ts +63 -0
  51. package/dist/lib/core/modelConfiguration.js +354 -290
  52. package/dist/lib/core/streamAnalytics.d.ts +10 -5
  53. package/dist/lib/core/streamAnalytics.js +10 -10
  54. package/dist/lib/core/types.d.ts +22 -110
  55. package/dist/lib/core/types.js +13 -0
  56. package/dist/lib/factories/providerFactory.js +1 -1
  57. package/dist/lib/index.d.ts +2 -1
  58. package/dist/lib/mcp/externalServerManager.js +15 -6
  59. package/dist/lib/mcp/factory.js +1 -1
  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.js +4 -4
  71. package/dist/lib/middleware/builtin/analytics.js +4 -4
  72. package/dist/lib/middleware/builtin/guardrails.js +2 -2
  73. package/dist/lib/middleware/registry.js +11 -2
  74. package/dist/lib/models/modelRegistry.d.ts +1 -1
  75. package/dist/lib/models/modelRegistry.js +3 -3
  76. package/dist/lib/models/modelResolver.d.ts +1 -1
  77. package/dist/lib/models/modelResolver.js +2 -2
  78. package/dist/lib/neurolink.d.ts +116 -9
  79. package/dist/lib/neurolink.js +718 -956
  80. package/dist/lib/providers/amazonSagemaker.d.ts +1 -1
  81. package/dist/lib/providers/amazonSagemaker.js +12 -3
  82. package/dist/lib/providers/anthropic.d.ts +1 -1
  83. package/dist/lib/providers/anthropic.js +7 -6
  84. package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
  85. package/dist/lib/providers/anthropicBaseProvider.js +4 -3
  86. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  87. package/dist/lib/providers/azureOpenai.js +1 -1
  88. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  89. package/dist/lib/providers/googleAiStudio.js +2 -2
  90. package/dist/lib/providers/googleVertex.d.ts +40 -0
  91. package/dist/lib/providers/googleVertex.js +330 -274
  92. package/dist/lib/providers/huggingFace.js +1 -1
  93. package/dist/lib/providers/mistral.d.ts +1 -1
  94. package/dist/lib/providers/mistral.js +2 -2
  95. package/dist/lib/providers/ollama.d.ts +4 -0
  96. package/dist/lib/providers/ollama.js +38 -18
  97. package/dist/lib/providers/openAI.d.ts +1 -1
  98. package/dist/lib/providers/openAI.js +2 -2
  99. package/dist/lib/providers/sagemaker/adaptive-semaphore.js +7 -4
  100. package/dist/lib/providers/sagemaker/client.js +13 -3
  101. package/dist/lib/providers/sagemaker/config.js +5 -1
  102. package/dist/lib/providers/sagemaker/detection.js +19 -9
  103. package/dist/lib/providers/sagemaker/errors.d.ts +8 -1
  104. package/dist/lib/providers/sagemaker/errors.js +103 -20
  105. package/dist/lib/providers/sagemaker/language-model.d.ts +3 -3
  106. package/dist/lib/providers/sagemaker/language-model.js +4 -4
  107. package/dist/lib/providers/sagemaker/parsers.js +14 -6
  108. package/dist/lib/providers/sagemaker/streaming.js +14 -3
  109. package/dist/lib/providers/sagemaker/types.d.ts +1 -1
  110. package/dist/lib/proxy/awsProxyIntegration.js +1 -1
  111. package/dist/lib/sdk/toolRegistration.d.ts +1 -1
  112. package/dist/lib/types/cli.d.ts +80 -8
  113. package/dist/lib/types/contextTypes.js +2 -2
  114. package/dist/lib/types/conversationTypes.d.ts +10 -0
  115. package/dist/lib/types/generateTypes.d.ts +2 -5
  116. package/dist/lib/types/providers.d.ts +81 -19
  117. package/dist/lib/types/providers.js +6 -6
  118. package/dist/lib/types/streamTypes.d.ts +4 -6
  119. package/dist/lib/types/typeAliases.d.ts +1 -1
  120. package/dist/lib/utils/analyticsUtils.d.ts +33 -0
  121. package/dist/lib/utils/analyticsUtils.js +76 -0
  122. package/dist/lib/utils/conversationMemoryUtils.d.ts +1 -2
  123. package/dist/lib/utils/conversationMemoryUtils.js +6 -7
  124. package/dist/lib/utils/errorHandling.js +4 -1
  125. package/dist/lib/utils/evaluationUtils.d.ts +27 -0
  126. package/dist/lib/utils/evaluationUtils.js +131 -0
  127. package/dist/lib/utils/optionsUtils.js +10 -1
  128. package/dist/lib/utils/performance.d.ts +1 -1
  129. package/dist/lib/utils/performance.js +15 -3
  130. package/dist/lib/utils/providerHealth.d.ts +48 -0
  131. package/dist/lib/utils/providerHealth.js +199 -254
  132. package/dist/lib/utils/providerUtils.js +2 -2
  133. package/dist/lib/utils/timeout.js +8 -3
  134. package/dist/mcp/externalServerManager.js +15 -6
  135. package/dist/mcp/factory.js +1 -1
  136. package/dist/mcp/index.d.ts +1 -1
  137. package/dist/mcp/index.js +1 -1
  138. package/dist/mcp/mcpCircuitBreaker.js +5 -1
  139. package/dist/mcp/mcpClientFactory.js +3 -0
  140. package/dist/mcp/registry.d.ts +3 -3
  141. package/dist/mcp/registry.js +3 -3
  142. package/dist/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
  143. package/dist/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
  144. package/dist/mcp/servers/utilities/utilityServer.js +1 -1
  145. package/dist/mcp/toolDiscoveryService.js +8 -2
  146. package/dist/mcp/toolRegistry.js +4 -4
  147. package/dist/middleware/builtin/analytics.js +4 -4
  148. package/dist/middleware/builtin/guardrails.js +2 -2
  149. package/dist/middleware/registry.js +11 -2
  150. package/dist/models/modelRegistry.d.ts +1 -1
  151. package/dist/models/modelRegistry.js +3 -3
  152. package/dist/models/modelResolver.d.ts +1 -1
  153. package/dist/models/modelResolver.js +2 -2
  154. package/dist/neurolink.d.ts +116 -9
  155. package/dist/neurolink.js +718 -956
  156. package/dist/providers/amazonSagemaker.d.ts +1 -1
  157. package/dist/providers/amazonSagemaker.js +12 -3
  158. package/dist/providers/anthropic.d.ts +1 -1
  159. package/dist/providers/anthropic.js +7 -6
  160. package/dist/providers/anthropicBaseProvider.d.ts +1 -1
  161. package/dist/providers/anthropicBaseProvider.js +4 -3
  162. package/dist/providers/azureOpenai.d.ts +1 -1
  163. package/dist/providers/azureOpenai.js +1 -1
  164. package/dist/providers/googleAiStudio.d.ts +1 -1
  165. package/dist/providers/googleAiStudio.js +2 -2
  166. package/dist/providers/googleVertex.d.ts +40 -0
  167. package/dist/providers/googleVertex.js +330 -274
  168. package/dist/providers/huggingFace.js +1 -1
  169. package/dist/providers/mistral.d.ts +1 -1
  170. package/dist/providers/mistral.js +2 -2
  171. package/dist/providers/ollama.d.ts +4 -0
  172. package/dist/providers/ollama.js +38 -18
  173. package/dist/providers/openAI.d.ts +1 -1
  174. package/dist/providers/openAI.js +2 -2
  175. package/dist/providers/sagemaker/adaptive-semaphore.js +7 -4
  176. package/dist/providers/sagemaker/client.js +13 -3
  177. package/dist/providers/sagemaker/config.js +5 -1
  178. package/dist/providers/sagemaker/detection.js +19 -9
  179. package/dist/providers/sagemaker/errors.d.ts +8 -1
  180. package/dist/providers/sagemaker/errors.js +103 -20
  181. package/dist/providers/sagemaker/language-model.d.ts +3 -3
  182. package/dist/providers/sagemaker/language-model.js +4 -4
  183. package/dist/providers/sagemaker/parsers.js +14 -6
  184. package/dist/providers/sagemaker/streaming.js +14 -3
  185. package/dist/providers/sagemaker/types.d.ts +1 -1
  186. package/dist/proxy/awsProxyIntegration.js +1 -1
  187. package/dist/sdk/toolRegistration.d.ts +1 -1
  188. package/dist/types/cli.d.ts +80 -8
  189. package/dist/types/contextTypes.js +2 -2
  190. package/dist/types/conversationTypes.d.ts +10 -0
  191. package/dist/types/generateTypes.d.ts +2 -5
  192. package/dist/types/providers.d.ts +81 -19
  193. package/dist/types/providers.js +6 -6
  194. package/dist/types/streamTypes.d.ts +4 -6
  195. package/dist/types/typeAliases.d.ts +1 -1
  196. package/dist/utils/analyticsUtils.d.ts +33 -0
  197. package/dist/utils/analyticsUtils.js +76 -0
  198. package/dist/utils/conversationMemoryUtils.d.ts +1 -2
  199. package/dist/utils/conversationMemoryUtils.js +6 -7
  200. package/dist/utils/errorHandling.js +4 -1
  201. package/dist/utils/evaluationUtils.d.ts +27 -0
  202. package/dist/utils/evaluationUtils.js +131 -0
  203. package/dist/utils/optionsUtils.js +10 -1
  204. package/dist/utils/performance.d.ts +1 -1
  205. package/dist/utils/performance.js +15 -3
  206. package/dist/utils/providerHealth.d.ts +48 -0
  207. package/dist/utils/providerHealth.js +199 -254
  208. package/dist/utils/providerUtils.js +2 -2
  209. package/dist/utils/timeout.js +8 -3
  210. package/package.json +1 -1
  211. package/dist/context/ContextManager.d.ts +0 -28
  212. package/dist/context/ContextManager.js +0 -113
  213. package/dist/context/config.d.ts +0 -5
  214. package/dist/context/config.js +0 -42
  215. package/dist/context/types.d.ts +0 -20
  216. package/dist/context/types.js +0 -1
  217. package/dist/context/utils.d.ts +0 -7
  218. package/dist/context/utils.js +0 -8
  219. package/dist/lib/context/ContextManager.d.ts +0 -28
  220. package/dist/lib/context/ContextManager.js +0 -113
  221. package/dist/lib/context/config.d.ts +0 -5
  222. package/dist/lib/context/config.js +0 -42
  223. package/dist/lib/context/types.d.ts +0 -20
  224. package/dist/lib/context/types.js +0 -1
  225. package/dist/lib/context/utils.d.ts +0 -7
  226. package/dist/lib/context/utils.js +0 -8
@@ -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";
@@ -35,14 +35,11 @@ import { applyConversationMemoryDefaults, getConversationMessages, storeConversa
35
35
  import { ExternalServerManager } from "./mcp/externalServerManager.js";
36
36
  // Import direct tools server for automatic registration
37
37
  import { directToolsServer } from "./mcp/servers/agent/directToolsServer.js";
38
- import { ContextManager } from "./context/ContextManager.js";
39
- import { defaultContextConfig } from "./context/config.js";
40
38
  import { isNonNullObject } from "./utils/typeUtils.js";
41
39
  // Core types imported from core/types.js
42
40
  export class NeuroLink {
43
41
  mcpInitialized = false;
44
42
  emitter = new EventEmitter();
45
- contextManager = null;
46
43
  autoDiscoveredServerInfos = [];
47
44
  // External MCP server management
48
45
  externalServerManager;
@@ -102,42 +99,50 @@ export class NeuroLink {
102
99
  * @throws {Error} When external server manager initialization fails
103
100
  */
104
101
  constructor(config) {
105
- // 🚀 EXHAUSTIVE LOGGING POINT C001: CONSTRUCTOR ENTRY
106
102
  const constructorStartTime = Date.now();
107
103
  const constructorHrTimeStart = process.hrtime.bigint();
108
104
  const constructorId = `neurolink-constructor-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
105
+ this.logConstructorStart(constructorId, constructorStartTime, constructorHrTimeStart, config);
106
+ this.initializeProviderRegistry(constructorId, constructorStartTime, constructorHrTimeStart);
107
+ this.initializeConversationMemory(config, constructorId, constructorStartTime, constructorHrTimeStart);
108
+ this.initializeExternalServerManager(constructorId, constructorStartTime, constructorHrTimeStart);
109
+ this.logConstructorComplete(constructorId, constructorStartTime, constructorHrTimeStart);
110
+ }
111
+ /**
112
+ * Log constructor start with comprehensive environment analysis
113
+ */
114
+ logConstructorStart(constructorId, constructorStartTime, constructorHrTimeStart, config) {
109
115
  logger.debug(`[NeuroLink] 🏗️ LOG_POINT_C001_CONSTRUCTOR_START`, {
110
116
  logPoint: "C001_CONSTRUCTOR_START",
111
117
  constructorId,
112
118
  timestamp: new Date().toISOString(),
113
119
  constructorStartTime,
114
120
  constructorHrTimeStart: constructorHrTimeStart.toString(),
115
- // Configuration analysis
116
121
  hasConfig: !!config,
117
122
  configType: typeof config,
118
123
  configKeys: config ? Object.keys(config) : [],
119
124
  configSize: config ? JSON.stringify(config).length : 0,
120
- // Conversation memory config analysis
121
125
  hasConversationMemoryConfig: !!config?.conversationMemory,
122
126
  conversationMemoryEnabled: config?.conversationMemory?.enabled || false,
123
127
  conversationMemoryKeys: config?.conversationMemory
124
128
  ? Object.keys(config.conversationMemory)
125
129
  : [],
126
- // Environment context
127
130
  nodeVersion: process.version,
128
131
  platform: process.platform,
129
132
  arch: process.arch,
130
133
  nodeEnv: process.env.NODE_ENV || "UNKNOWN",
131
- // Memory and performance baseline
132
134
  memoryUsage: process.memoryUsage(),
133
135
  cpuUsage: process.cpuUsage(),
134
136
  uptime: process.uptime(),
135
- // Process PID and parent info
136
137
  pid: process.pid,
137
138
  ppid: process.ppid,
138
139
  message: "NeuroLink constructor initialization starting with comprehensive environment analysis",
139
140
  });
140
- // 🚀 EXHAUSTIVE LOGGING POINT C002: PROVIDER REGISTRY SETUP
141
+ }
142
+ /**
143
+ * Initialize provider registry with security settings
144
+ */
145
+ initializeProviderRegistry(constructorId, constructorStartTime, constructorHrTimeStart) {
141
146
  const registrySetupStartTime = process.hrtime.bigint();
142
147
  logger.debug(`[NeuroLink] 🏗️ LOG_POINT_C002_PROVIDER_REGISTRY_SETUP_START`, {
143
148
  logPoint: "C002_PROVIDER_REGISTRY_SETUP_START",
@@ -148,11 +153,8 @@ export class NeuroLink {
148
153
  registrySetupStartTimeNs: registrySetupStartTime.toString(),
149
154
  message: "Starting ProviderRegistry configuration for security",
150
155
  });
151
- // SDK always disables manual MCP config for security
152
156
  try {
153
- ProviderRegistry.setOptions({
154
- enableManualMCP: false,
155
- });
157
+ ProviderRegistry.setOptions({ enableManualMCP: false });
156
158
  const registrySetupEndTime = process.hrtime.bigint();
157
159
  const registrySetupDurationNs = registrySetupEndTime - registrySetupStartTime;
158
160
  logger.debug(`[NeuroLink] ✅ LOG_POINT_C003_PROVIDER_REGISTRY_SETUP_SUCCESS`, {
@@ -185,7 +187,11 @@ export class NeuroLink {
185
187
  });
186
188
  throw error;
187
189
  }
188
- // 🚀 EXHAUSTIVE LOGGING POINT C005: CONVERSATION MEMORY INITIALIZATION
190
+ }
191
+ /**
192
+ * Initialize conversation memory if enabled
193
+ */
194
+ initializeConversationMemory(config, constructorId, constructorStartTime, constructorHrTimeStart) {
189
195
  if (config?.conversationMemory?.enabled) {
190
196
  const memoryInitStartTime = process.hrtime.bigint();
191
197
  logger.debug(`[NeuroLink] 🧠 LOG_POINT_C005_MEMORY_INIT_START`, {
@@ -195,7 +201,6 @@ export class NeuroLink {
195
201
  elapsedMs: Date.now() - constructorStartTime,
196
202
  elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
197
203
  memoryInitStartTimeNs: memoryInitStartTime.toString(),
198
- // Detailed memory config analysis
199
204
  memoryConfig: {
200
205
  enabled: config.conversationMemory.enabled,
201
206
  maxSessions: config.conversationMemory.maxSessions,
@@ -222,12 +227,10 @@ export class NeuroLink {
222
227
  memoryInitDurationMs: Number(memoryInitDurationNs) / 1000000,
223
228
  memoryManagerCreateDurationNs: memoryManagerCreateDurationNs.toString(),
224
229
  memoryManagerCreateDurationMs: Number(memoryManagerCreateDurationNs) / 1000000,
225
- // Final memory configuration
226
230
  finalMemoryConfig: {
227
231
  maxSessions: memoryConfig.maxSessions,
228
232
  maxTurnsPerSession: memoryConfig.maxTurnsPerSession,
229
233
  },
230
- // Memory usage after initialization
231
234
  memoryUsageAfterInit: process.memoryUsage(),
232
235
  message: "NeuroLink initialized with conversation memory successfully",
233
236
  });
@@ -272,7 +275,11 @@ export class NeuroLink {
272
275
  message: "Conversation memory not enabled - skipping initialization",
273
276
  });
274
277
  }
275
- // 🚀 EXHAUSTIVE LOGGING POINT C009: EXTERNAL SERVER MANAGER INITIALIZATION
278
+ }
279
+ /**
280
+ * Initialize external server manager with event handlers
281
+ */
282
+ initializeExternalServerManager(constructorId, constructorStartTime, constructorHrTimeStart) {
276
283
  const externalServerInitStartTime = process.hrtime.bigint();
277
284
  logger.debug(`[NeuroLink] 🌐 LOG_POINT_C009_EXTERNAL_SERVER_INIT_START`, {
278
285
  logPoint: "C009_EXTERNAL_SERVER_INIT_START",
@@ -293,14 +300,13 @@ export class NeuroLink {
293
300
  message: "Starting external server manager initialization",
294
301
  });
295
302
  try {
296
- // Initialize external server manager with main registry integration
297
303
  this.externalServerManager = new ExternalServerManager({
298
304
  maxServers: 20,
299
305
  defaultTimeout: 15000,
300
306
  enableAutoRestart: true,
301
307
  enablePerformanceMonitoring: true,
302
308
  }, {
303
- enableMainRegistryIntegration: true, // Enable integration with main toolRegistry
309
+ enableMainRegistryIntegration: true,
304
310
  });
305
311
  const externalServerInitEndTime = process.hrtime.bigint();
306
312
  const externalServerInitDurationNs = externalServerInitEndTime - externalServerInitStartTime;
@@ -315,93 +321,7 @@ export class NeuroLink {
315
321
  hasExternalServerManager: !!this.externalServerManager,
316
322
  message: "External server manager initialized successfully",
317
323
  });
318
- // 🚀 EXHAUSTIVE LOGGING POINT C011: EVENT HANDLER SETUP
319
- const eventHandlerSetupStartTime = process.hrtime.bigint();
320
- logger.debug(`[NeuroLink] 🔗 LOG_POINT_C011_EVENT_HANDLER_SETUP_START`, {
321
- logPoint: "C011_EVENT_HANDLER_SETUP_START",
322
- constructorId,
323
- timestamp: new Date().toISOString(),
324
- elapsedMs: Date.now() - constructorStartTime,
325
- elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
326
- eventHandlerSetupStartTimeNs: eventHandlerSetupStartTime.toString(),
327
- message: "Setting up external server event handlers",
328
- });
329
- // Forward external server events with detailed logging
330
- this.externalServerManager.on("connected", (event) => {
331
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_CONNECTED`, {
332
- constructorId,
333
- eventType: "connected",
334
- event,
335
- timestamp: new Date().toISOString(),
336
- message: "External MCP server connected event received",
337
- });
338
- this.emitter.emit("externalMCP:serverConnected", event);
339
- });
340
- this.externalServerManager.on("disconnected", (event) => {
341
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_DISCONNECTED`, {
342
- constructorId,
343
- eventType: "disconnected",
344
- event,
345
- timestamp: new Date().toISOString(),
346
- message: "External MCP server disconnected event received",
347
- });
348
- this.emitter.emit("externalMCP:serverDisconnected", event);
349
- });
350
- this.externalServerManager.on("failed", (event) => {
351
- logger.warn(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_FAILED`, {
352
- constructorId,
353
- eventType: "failed",
354
- event,
355
- timestamp: new Date().toISOString(),
356
- message: "External MCP server failed event received",
357
- });
358
- this.emitter.emit("externalMCP:serverFailed", event);
359
- });
360
- this.externalServerManager.on("toolDiscovered", (event) => {
361
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_DISCOVERED`, {
362
- constructorId,
363
- eventType: "toolDiscovered",
364
- toolName: event.toolName,
365
- serverId: event.serverId,
366
- timestamp: new Date().toISOString(),
367
- message: "External MCP tool discovered event received",
368
- });
369
- this.emitter.emit("externalMCP:toolDiscovered", event);
370
- // Tools are already registered on server connection, no need to duplicate here
371
- });
372
- this.externalServerManager.on("toolRemoved", (event) => {
373
- logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_REMOVED`, {
374
- constructorId,
375
- eventType: "toolRemoved",
376
- toolName: event.toolName,
377
- serverId: event.serverId,
378
- timestamp: new Date().toISOString(),
379
- message: "External MCP tool removed event received",
380
- });
381
- this.emitter.emit("externalMCP:toolRemoved", event);
382
- // Unregister removed tools from main tool registry
383
- this.unregisterExternalMCPToolFromRegistry(event.toolName);
384
- });
385
- const eventHandlerSetupEndTime = process.hrtime.bigint();
386
- const eventHandlerSetupDurationNs = eventHandlerSetupEndTime - eventHandlerSetupStartTime;
387
- logger.debug(`[NeuroLink] ✅ LOG_POINT_C012_EVENT_HANDLER_SETUP_SUCCESS`, {
388
- logPoint: "C012_EVENT_HANDLER_SETUP_SUCCESS",
389
- constructorId,
390
- timestamp: new Date().toISOString(),
391
- elapsedMs: Date.now() - constructorStartTime,
392
- elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
393
- eventHandlerSetupDurationNs: eventHandlerSetupDurationNs.toString(),
394
- eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) / 1000000,
395
- eventHandlersCount: 5,
396
- eventHandlerTypes: [
397
- "connected",
398
- "disconnected",
399
- "failed",
400
- "toolDiscovered",
401
- "toolRemoved",
402
- ],
403
- message: "Event handlers set up successfully",
404
- });
324
+ this.setupExternalServerEventHandlers(constructorId, constructorStartTime, constructorHrTimeStart);
405
325
  }
406
326
  catch (error) {
407
327
  const externalServerInitErrorTime = process.hrtime.bigint();
@@ -421,7 +341,99 @@ export class NeuroLink {
421
341
  });
422
342
  throw error;
423
343
  }
424
- // 🚀 EXHAUSTIVE LOGGING POINT C014: CONSTRUCTOR COMPLETION
344
+ }
345
+ /**
346
+ * Setup event handlers for external server manager
347
+ */
348
+ setupExternalServerEventHandlers(constructorId, constructorStartTime, constructorHrTimeStart) {
349
+ const eventHandlerSetupStartTime = process.hrtime.bigint();
350
+ logger.debug(`[NeuroLink] 🔗 LOG_POINT_C011_EVENT_HANDLER_SETUP_START`, {
351
+ logPoint: "C011_EVENT_HANDLER_SETUP_START",
352
+ constructorId,
353
+ timestamp: new Date().toISOString(),
354
+ elapsedMs: Date.now() - constructorStartTime,
355
+ elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
356
+ eventHandlerSetupStartTimeNs: eventHandlerSetupStartTime.toString(),
357
+ message: "Setting up external server event handlers",
358
+ });
359
+ this.externalServerManager.on("connected", (event) => {
360
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_CONNECTED`, {
361
+ constructorId,
362
+ eventType: "connected",
363
+ event,
364
+ timestamp: new Date().toISOString(),
365
+ message: "External MCP server connected event received",
366
+ });
367
+ this.emitter.emit("externalMCP:serverConnected", event);
368
+ });
369
+ this.externalServerManager.on("disconnected", (event) => {
370
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_DISCONNECTED`, {
371
+ constructorId,
372
+ eventType: "disconnected",
373
+ event,
374
+ timestamp: new Date().toISOString(),
375
+ message: "External MCP server disconnected event received",
376
+ });
377
+ this.emitter.emit("externalMCP:serverDisconnected", event);
378
+ });
379
+ this.externalServerManager.on("failed", (event) => {
380
+ logger.warn(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_FAILED`, {
381
+ constructorId,
382
+ eventType: "failed",
383
+ event,
384
+ timestamp: new Date().toISOString(),
385
+ message: "External MCP server failed event received",
386
+ });
387
+ this.emitter.emit("externalMCP:serverFailed", event);
388
+ });
389
+ this.externalServerManager.on("toolDiscovered", (event) => {
390
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_DISCOVERED`, {
391
+ constructorId,
392
+ eventType: "toolDiscovered",
393
+ toolName: event.toolName,
394
+ serverId: event.serverId,
395
+ timestamp: new Date().toISOString(),
396
+ message: "External MCP tool discovered event received",
397
+ });
398
+ this.emitter.emit("externalMCP:toolDiscovered", event);
399
+ });
400
+ this.externalServerManager.on("toolRemoved", (event) => {
401
+ logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_REMOVED`, {
402
+ constructorId,
403
+ eventType: "toolRemoved",
404
+ toolName: event.toolName,
405
+ serverId: event.serverId,
406
+ timestamp: new Date().toISOString(),
407
+ message: "External MCP tool removed event received",
408
+ });
409
+ this.emitter.emit("externalMCP:toolRemoved", event);
410
+ this.unregisterExternalMCPToolFromRegistry(event.toolName);
411
+ });
412
+ const eventHandlerSetupEndTime = process.hrtime.bigint();
413
+ const eventHandlerSetupDurationNs = eventHandlerSetupEndTime - eventHandlerSetupStartTime;
414
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_C012_EVENT_HANDLER_SETUP_SUCCESS`, {
415
+ logPoint: "C012_EVENT_HANDLER_SETUP_SUCCESS",
416
+ constructorId,
417
+ timestamp: new Date().toISOString(),
418
+ elapsedMs: Date.now() - constructorStartTime,
419
+ elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
420
+ eventHandlerSetupDurationNs: eventHandlerSetupDurationNs.toString(),
421
+ eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) / 1000000,
422
+ eventHandlersCount: 5,
423
+ eventHandlerTypes: [
424
+ "connected",
425
+ "disconnected",
426
+ "failed",
427
+ "toolDiscovered",
428
+ "toolRemoved",
429
+ ],
430
+ message: "Event handlers set up successfully",
431
+ });
432
+ }
433
+ /**
434
+ * Log constructor completion with final state summary
435
+ */
436
+ logConstructorComplete(constructorId, constructorStartTime, constructorHrTimeStart) {
425
437
  const constructorEndTime = process.hrtime.bigint();
426
438
  const constructorDurationNs = constructorEndTime - constructorHrTimeStart;
427
439
  logger.info(`[NeuroLink] 🏁 LOG_POINT_C014_CONSTRUCTOR_COMPLETE`, {
@@ -431,7 +443,6 @@ export class NeuroLink {
431
443
  constructorDurationNs: constructorDurationNs.toString(),
432
444
  constructorDurationMs: Number(constructorDurationNs) / 1000000,
433
445
  totalElapsedMs: Date.now() - constructorStartTime,
434
- // Final state summary
435
446
  finalState: {
436
447
  hasConversationMemory: !!this.conversationMemory,
437
448
  hasExternalServerManager: !!this.externalServerManager,
@@ -440,7 +451,6 @@ export class NeuroLink {
440
451
  toolCircuitBreakersCount: this.toolCircuitBreakers.size,
441
452
  toolExecutionMetricsCount: this.toolExecutionMetrics.size,
442
453
  },
443
- // Final memory usage
444
454
  finalMemoryUsage: process.memoryUsage(),
445
455
  finalCpuUsage: process.cpuUsage(),
446
456
  message: "NeuroLink constructor completed successfully with all components initialized",
@@ -451,10 +461,34 @@ export class NeuroLink {
451
461
  * Uses isolated async context to prevent hanging
452
462
  */
453
463
  async initializeMCP() {
454
- // 🚀 EXHAUSTIVE LOGGING POINT M001: MCP INITIALIZATION ENTRY CHECK
455
464
  const mcpInitId = `mcp-init-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
456
465
  const mcpInitStartTime = Date.now();
457
466
  const mcpInitHrTimeStart = process.hrtime.bigint();
467
+ this.logMCPInitStart(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
468
+ if (this.mcpInitialized) {
469
+ this.logMCPAlreadyInitialized(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
470
+ return;
471
+ }
472
+ const MemoryManager = await this.importPerformanceManager(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
473
+ const startMemory = MemoryManager
474
+ ? MemoryManager.getMemoryUsageMB()
475
+ : { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
476
+ try {
477
+ await this.performMCPInitialization(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart, startMemory);
478
+ this.mcpInitialized = true;
479
+ this.logMCPInitComplete(startMemory, MemoryManager, mcpInitStartTime);
480
+ }
481
+ catch (error) {
482
+ mcpLogger.warn("[NeuroLink] MCP initialization failed", {
483
+ error: error instanceof Error ? error.message : String(error),
484
+ });
485
+ // Continue without MCP - graceful degradation
486
+ }
487
+ }
488
+ /**
489
+ * Log MCP initialization start
490
+ */
491
+ logMCPInitStart(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
458
492
  logger.debug(`[NeuroLink] 🔧 LOG_POINT_M001_MCP_INIT_ENTRY`, {
459
493
  logPoint: "M001_MCP_INIT_ENTRY",
460
494
  mcpInitId,
@@ -467,19 +501,25 @@ export class NeuroLink {
467
501
  cpuUsage: process.cpuUsage(),
468
502
  message: "MCP initialization entry point - checking if already initialized",
469
503
  });
470
- if (this.mcpInitialized) {
471
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M002_MCP_ALREADY_INITIALIZED`, {
472
- logPoint: "M002_MCP_ALREADY_INITIALIZED",
473
- mcpInitId,
474
- timestamp: new Date().toISOString(),
475
- elapsedMs: Date.now() - mcpInitStartTime,
476
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
477
- mcpInitialized: this.mcpInitialized,
478
- message: "MCP already initialized - skipping initialization",
479
- });
480
- return;
481
- }
482
- // 🚀 EXHAUSTIVE LOGGING POINT M003: PERFORMANCE MANAGER IMPORT
504
+ }
505
+ /**
506
+ * Log MCP already initialized
507
+ */
508
+ logMCPAlreadyInitialized(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
509
+ logger.debug(`[NeuroLink] LOG_POINT_M002_MCP_ALREADY_INITIALIZED`, {
510
+ logPoint: "M002_MCP_ALREADY_INITIALIZED",
511
+ mcpInitId,
512
+ timestamp: new Date().toISOString(),
513
+ elapsedMs: Date.now() - mcpInitStartTime,
514
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
515
+ mcpInitialized: this.mcpInitialized,
516
+ message: "MCP already initialized - skipping initialization",
517
+ });
518
+ }
519
+ /**
520
+ * Import performance manager with error handling
521
+ */
522
+ async importPerformanceManager(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
483
523
  const performanceImportStartTime = process.hrtime.bigint();
484
524
  logger.debug(`[NeuroLink] 📊 LOG_POINT_M003_PERFORMANCE_IMPORT_START`, {
485
525
  logPoint: "M003_PERFORMANCE_IMPORT_START",
@@ -490,13 +530,9 @@ export class NeuroLink {
490
530
  performanceImportStartTimeNs: performanceImportStartTime.toString(),
491
531
  message: "Starting MemoryManager import for performance tracking",
492
532
  });
493
- let MemoryManager;
494
- let startMemory;
495
533
  try {
496
- // Track memory usage during MCP initialization
497
534
  const moduleImport = await import("./utils/performance.js");
498
- MemoryManager = moduleImport.MemoryManager;
499
- startMemory = MemoryManager.getMemoryUsageMB();
535
+ const MemoryManager = moduleImport.MemoryManager;
500
536
  const performanceImportEndTime = process.hrtime.bigint();
501
537
  const performanceImportDurationNs = performanceImportEndTime - performanceImportStartTime;
502
538
  logger.debug(`[NeuroLink] ✅ LOG_POINT_M004_PERFORMANCE_IMPORT_SUCCESS`, {
@@ -508,9 +544,9 @@ export class NeuroLink {
508
544
  performanceImportDurationNs: performanceImportDurationNs.toString(),
509
545
  performanceImportDurationMs: Number(performanceImportDurationNs) / 1000000,
510
546
  hasMemoryManager: !!MemoryManager,
511
- startMemory,
512
547
  message: "MemoryManager imported successfully",
513
548
  });
549
+ return MemoryManager;
514
550
  }
515
551
  catch (error) {
516
552
  const performanceImportErrorTime = process.hrtime.bigint();
@@ -527,206 +563,218 @@ export class NeuroLink {
527
563
  errorName: error instanceof Error ? error.name : "UnknownError",
528
564
  message: "MemoryManager import failed - continuing without performance tracking",
529
565
  });
530
- // Continue without performance tracking
531
- startMemory = { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
566
+ return undefined;
532
567
  }
568
+ }
569
+ /**
570
+ * Perform main MCP initialization logic
571
+ */
572
+ async performMCPInitialization(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart, startMemory) {
573
+ logger.info(`[NeuroLink] 🚀 LOG_POINT_M006_MCP_MAIN_INIT_START`, {
574
+ logPoint: "M006_MCP_MAIN_INIT_START",
575
+ mcpInitId,
576
+ timestamp: new Date().toISOString(),
577
+ elapsedMs: Date.now() - mcpInitStartTime,
578
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
579
+ startMemory,
580
+ message: "Starting isolated MCP initialization process",
581
+ });
582
+ mcpLogger.debug("[NeuroLink] Starting isolated MCP initialization...");
583
+ await this.initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
584
+ await this.initializeProviderRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
585
+ await this.registerDirectToolsServerInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
586
+ await this.loadMCPConfigurationInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
587
+ }
588
+ /**
589
+ * Initialize tool registry with timeout protection
590
+ */
591
+ async initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
592
+ const toolRegistryStartTime = process.hrtime.bigint();
593
+ const initTimeout = 3000;
594
+ logger.debug(`[NeuroLink] ⏱️ LOG_POINT_M007_TOOL_REGISTRY_TIMEOUT_SETUP`, {
595
+ logPoint: "M007_TOOL_REGISTRY_TIMEOUT_SETUP",
596
+ mcpInitId,
597
+ timestamp: new Date().toISOString(),
598
+ elapsedMs: Date.now() - mcpInitStartTime,
599
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
600
+ toolRegistryStartTimeNs: toolRegistryStartTime.toString(),
601
+ initTimeoutMs: initTimeout,
602
+ message: "Setting up tool registry initialization with timeout protection",
603
+ });
604
+ await Promise.race([
605
+ Promise.resolve(),
606
+ new Promise((_, reject) => {
607
+ setTimeout(() => reject(new Error("MCP initialization timeout")), initTimeout);
608
+ }),
609
+ ]);
610
+ const toolRegistryEndTime = process.hrtime.bigint();
611
+ const toolRegistryDurationNs = toolRegistryEndTime - toolRegistryStartTime;
612
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M008_TOOL_REGISTRY_SUCCESS`, {
613
+ logPoint: "M008_TOOL_REGISTRY_SUCCESS",
614
+ mcpInitId,
615
+ timestamp: new Date().toISOString(),
616
+ elapsedMs: Date.now() - mcpInitStartTime,
617
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
618
+ toolRegistryDurationNs: toolRegistryDurationNs.toString(),
619
+ toolRegistryDurationMs: Number(toolRegistryDurationNs) / 1000000,
620
+ message: "Tool registry initialization completed within timeout",
621
+ });
622
+ }
623
+ /**
624
+ * Initialize provider registry
625
+ */
626
+ async initializeProviderRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
627
+ const providerRegistryStartTime = process.hrtime.bigint();
628
+ logger.debug(`[NeuroLink] 🏭 LOG_POINT_M009_PROVIDER_REGISTRY_START`, {
629
+ logPoint: "M009_PROVIDER_REGISTRY_START",
630
+ mcpInitId,
631
+ timestamp: new Date().toISOString(),
632
+ elapsedMs: Date.now() - mcpInitStartTime,
633
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
634
+ providerRegistryStartTimeNs: providerRegistryStartTime.toString(),
635
+ message: "Starting provider registry registration with lazy loading",
636
+ });
637
+ await ProviderRegistry.registerAllProviders();
638
+ const providerRegistryEndTime = process.hrtime.bigint();
639
+ const providerRegistryDurationNs = providerRegistryEndTime - providerRegistryStartTime;
640
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M010_PROVIDER_REGISTRY_SUCCESS`, {
641
+ logPoint: "M010_PROVIDER_REGISTRY_SUCCESS",
642
+ mcpInitId,
643
+ timestamp: new Date().toISOString(),
644
+ elapsedMs: Date.now() - mcpInitStartTime,
645
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
646
+ providerRegistryDurationNs: providerRegistryDurationNs.toString(),
647
+ providerRegistryDurationMs: Number(providerRegistryDurationNs) / 1000000,
648
+ message: "Provider registry registration completed successfully",
649
+ });
650
+ }
651
+ /**
652
+ * Register direct tools server
653
+ */
654
+ async registerDirectToolsServerInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
655
+ const directToolsStartTime = process.hrtime.bigint();
656
+ logger.debug(`[NeuroLink] 🛠️ LOG_POINT_M011_DIRECT_TOOLS_START`, {
657
+ logPoint: "M011_DIRECT_TOOLS_START",
658
+ mcpInitId,
659
+ timestamp: new Date().toISOString(),
660
+ elapsedMs: Date.now() - mcpInitStartTime,
661
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
662
+ directToolsStartTimeNs: directToolsStartTime.toString(),
663
+ serverId: "neurolink-direct",
664
+ message: "Starting direct tools server registration",
665
+ });
533
666
  try {
534
- // 🚀 EXHAUSTIVE LOGGING POINT M006: MAIN MCP INITIALIZATION START
535
- logger.info(`[NeuroLink] 🚀 LOG_POINT_M006_MCP_MAIN_INIT_START`, {
536
- logPoint: "M006_MCP_MAIN_INIT_START",
667
+ await toolRegistry.registerServer("neurolink-direct", directToolsServer);
668
+ const directToolsSuccessTime = process.hrtime.bigint();
669
+ const directToolsDurationNs = directToolsSuccessTime - directToolsStartTime;
670
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M012_DIRECT_TOOLS_SUCCESS`, {
671
+ logPoint: "M012_DIRECT_TOOLS_SUCCESS",
537
672
  mcpInitId,
538
673
  timestamp: new Date().toISOString(),
539
674
  elapsedMs: Date.now() - mcpInitStartTime,
540
675
  elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
541
- startMemory,
542
- message: "Starting isolated MCP initialization process",
676
+ directToolsDurationNs: directToolsDurationNs.toString(),
677
+ directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
678
+ serverId: "neurolink-direct",
679
+ message: "Direct tools server registered successfully",
543
680
  });
544
- mcpLogger.debug("[NeuroLink] Starting isolated MCP initialization...");
545
- // 🚀 EXHAUSTIVE LOGGING POINT M007: TOOL REGISTRY TIMEOUT SETUP
546
- const toolRegistryStartTime = process.hrtime.bigint();
547
- const initTimeout = 3000; // 3 second timeout
548
- logger.debug(`[NeuroLink] ⏱️ LOG_POINT_M007_TOOL_REGISTRY_TIMEOUT_SETUP`, {
549
- logPoint: "M007_TOOL_REGISTRY_TIMEOUT_SETUP",
550
- mcpInitId,
551
- timestamp: new Date().toISOString(),
552
- elapsedMs: Date.now() - mcpInitStartTime,
553
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
554
- toolRegistryStartTimeNs: toolRegistryStartTime.toString(),
555
- initTimeoutMs: initTimeout,
556
- message: "Setting up tool registry initialization with timeout protection",
681
+ mcpLogger.debug("[NeuroLink] Direct tools server registered successfully", {
682
+ serverId: "neurolink-direct",
557
683
  });
558
- // Initialize tool registry with timeout protection
559
- await Promise.race([
560
- Promise.resolve(), // toolRegistry doesn't need explicit initialization
561
- new Promise((_, reject) => {
562
- setTimeout(() => reject(new Error("MCP initialization timeout")), initTimeout);
563
- }),
564
- ]);
565
- const toolRegistryEndTime = process.hrtime.bigint();
566
- const toolRegistryDurationNs = toolRegistryEndTime - toolRegistryStartTime;
567
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M008_TOOL_REGISTRY_SUCCESS`, {
568
- logPoint: "M008_TOOL_REGISTRY_SUCCESS",
684
+ }
685
+ catch (error) {
686
+ const directToolsErrorTime = process.hrtime.bigint();
687
+ const directToolsDurationNs = directToolsErrorTime - directToolsStartTime;
688
+ logger.warn(`[NeuroLink] ⚠️ LOG_POINT_M013_DIRECT_TOOLS_ERROR`, {
689
+ logPoint: "M013_DIRECT_TOOLS_ERROR",
569
690
  mcpInitId,
570
691
  timestamp: new Date().toISOString(),
571
692
  elapsedMs: Date.now() - mcpInitStartTime,
572
693
  elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
573
- toolRegistryDurationNs: toolRegistryDurationNs.toString(),
574
- toolRegistryDurationMs: Number(toolRegistryDurationNs) / 1000000,
575
- message: "Tool registry initialization completed within timeout",
694
+ directToolsDurationNs: directToolsDurationNs.toString(),
695
+ directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
696
+ error: error instanceof Error ? error.message : String(error),
697
+ errorName: error instanceof Error ? error.name : "UnknownError",
698
+ errorStack: error instanceof Error ? error.stack : undefined,
699
+ serverId: "neurolink-direct",
700
+ message: "Direct tools server registration failed but continuing",
576
701
  });
577
- // 🚀 EXHAUSTIVE LOGGING POINT M009: PROVIDER REGISTRY START
578
- const providerRegistryStartTime = process.hrtime.bigint();
579
- logger.debug(`[NeuroLink] 🏭 LOG_POINT_M009_PROVIDER_REGISTRY_START`, {
580
- logPoint: "M009_PROVIDER_REGISTRY_START",
581
- mcpInitId,
582
- timestamp: new Date().toISOString(),
583
- elapsedMs: Date.now() - mcpInitStartTime,
584
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
585
- providerRegistryStartTimeNs: providerRegistryStartTime.toString(),
586
- message: "Starting provider registry registration with lazy loading",
702
+ mcpLogger.warn("[NeuroLink] Failed to register direct tools server", {
703
+ error: error instanceof Error ? error.message : String(error),
587
704
  });
588
- // Register all providers with lazy loading support
589
- await ProviderRegistry.registerAllProviders();
590
- const providerRegistryEndTime = process.hrtime.bigint();
591
- const providerRegistryDurationNs = providerRegistryEndTime - providerRegistryStartTime;
592
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M010_PROVIDER_REGISTRY_SUCCESS`, {
593
- logPoint: "M010_PROVIDER_REGISTRY_SUCCESS",
705
+ }
706
+ }
707
+ /**
708
+ * Load MCP configuration from .mcp-config.json
709
+ */
710
+ async loadMCPConfigurationInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
711
+ const mcpConfigStartTime = process.hrtime.bigint();
712
+ logger.debug(`[NeuroLink] 📄 LOG_POINT_M014_MCP_CONFIG_START`, {
713
+ logPoint: "M014_MCP_CONFIG_START",
714
+ mcpInitId,
715
+ timestamp: new Date().toISOString(),
716
+ elapsedMs: Date.now() - mcpInitStartTime,
717
+ elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
718
+ mcpConfigStartTimeNs: mcpConfigStartTime.toString(),
719
+ hasExternalServerManager: !!this.externalServerManager,
720
+ message: "Starting MCP configuration loading from .mcp-config.json",
721
+ });
722
+ try {
723
+ const configResult = await this.externalServerManager.loadMCPConfiguration();
724
+ const mcpConfigSuccessTime = process.hrtime.bigint();
725
+ const mcpConfigDurationNs = mcpConfigSuccessTime - mcpConfigStartTime;
726
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_M015_MCP_CONFIG_SUCCESS`, {
727
+ logPoint: "M015_MCP_CONFIG_SUCCESS",
594
728
  mcpInitId,
595
729
  timestamp: new Date().toISOString(),
596
730
  elapsedMs: Date.now() - mcpInitStartTime,
597
731
  elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
598
- providerRegistryDurationNs: providerRegistryDurationNs.toString(),
599
- providerRegistryDurationMs: Number(providerRegistryDurationNs) / 1000000,
600
- message: "Provider registry registration completed successfully",
732
+ mcpConfigDurationNs: mcpConfigDurationNs.toString(),
733
+ mcpConfigDurationMs: Number(mcpConfigDurationNs) / 1000000,
734
+ serversLoaded: configResult.serversLoaded,
735
+ errorsCount: configResult.errors.length,
736
+ configResult: {
737
+ serversLoaded: configResult.serversLoaded,
738
+ errors: configResult.errors.map((err) => ({
739
+ message: err instanceof Error ? err.message : String(err),
740
+ name: err instanceof Error ? err.name : "UnknownError",
741
+ })),
742
+ },
743
+ message: "MCP configuration loaded successfully",
601
744
  });
602
- // 🚀 EXHAUSTIVE LOGGING POINT M011: DIRECT TOOLS SERVER REGISTRATION
603
- const directToolsStartTime = process.hrtime.bigint();
604
- logger.debug(`[NeuroLink] 🛠️ LOG_POINT_M011_DIRECT_TOOLS_START`, {
605
- logPoint: "M011_DIRECT_TOOLS_START",
606
- mcpInitId,
607
- timestamp: new Date().toISOString(),
608
- elapsedMs: Date.now() - mcpInitStartTime,
609
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
610
- directToolsStartTimeNs: directToolsStartTime.toString(),
611
- serverId: "neurolink-direct",
612
- message: "Starting direct tools server registration",
745
+ mcpLogger.debug("[NeuroLink] MCP configuration loaded successfully", {
746
+ serversLoaded: configResult.serversLoaded,
747
+ errors: configResult.errors.length,
613
748
  });
614
- // Register the direct tools server to make websearch and other tools available
615
- try {
616
- // Use the server ID string for registration instead of the server object
617
- await toolRegistry.registerServer("neurolink-direct", directToolsServer);
618
- const directToolsSuccessTime = process.hrtime.bigint();
619
- const directToolsDurationNs = directToolsSuccessTime - directToolsStartTime;
620
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M012_DIRECT_TOOLS_SUCCESS`, {
621
- logPoint: "M012_DIRECT_TOOLS_SUCCESS",
622
- mcpInitId,
623
- timestamp: new Date().toISOString(),
624
- elapsedMs: Date.now() - mcpInitStartTime,
625
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
626
- directToolsDurationNs: directToolsDurationNs.toString(),
627
- directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
628
- serverId: "neurolink-direct",
629
- message: "Direct tools server registered successfully",
630
- });
631
- mcpLogger.debug("[NeuroLink] Direct tools server registered successfully", {
632
- serverId: "neurolink-direct",
749
+ if (configResult.errors.length > 0) {
750
+ mcpLogger.warn("[NeuroLink] Some MCP servers failed to load", {
751
+ errors: configResult.errors,
633
752
  });
634
753
  }
635
- catch (error) {
636
- const directToolsErrorTime = process.hrtime.bigint();
637
- const directToolsDurationNs = directToolsErrorTime - directToolsStartTime;
638
- logger.warn(`[NeuroLink] ⚠️ LOG_POINT_M013_DIRECT_TOOLS_ERROR`, {
639
- logPoint: "M013_DIRECT_TOOLS_ERROR",
640
- mcpInitId,
641
- timestamp: new Date().toISOString(),
642
- elapsedMs: Date.now() - mcpInitStartTime,
643
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
644
- directToolsDurationNs: directToolsDurationNs.toString(),
645
- directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
646
- error: error instanceof Error ? error.message : String(error),
647
- errorName: error instanceof Error ? error.name : "UnknownError",
648
- errorStack: error instanceof Error ? error.stack : undefined,
649
- serverId: "neurolink-direct",
650
- message: "Direct tools server registration failed but continuing",
651
- });
652
- mcpLogger.warn("[NeuroLink] Failed to register direct tools server", {
653
- error: error instanceof Error ? error.message : String(error),
654
- });
655
- }
656
- // 🚀 EXHAUSTIVE LOGGING POINT M014: MCP CONFIG LOADING START
657
- const mcpConfigStartTime = process.hrtime.bigint();
658
- logger.debug(`[NeuroLink] 📄 LOG_POINT_M014_MCP_CONFIG_START`, {
659
- logPoint: "M014_MCP_CONFIG_START",
660
- mcpInitId,
661
- timestamp: new Date().toISOString(),
662
- elapsedMs: Date.now() - mcpInitStartTime,
663
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
664
- mcpConfigStartTimeNs: mcpConfigStartTime.toString(),
665
- hasExternalServerManager: !!this.externalServerManager,
666
- message: "Starting MCP configuration loading from .mcp-config.json",
667
- });
668
- // Load MCP configuration from .mcp-config.json using ExternalServerManager
669
- try {
670
- const configResult = await this.externalServerManager.loadMCPConfiguration();
671
- const mcpConfigSuccessTime = process.hrtime.bigint();
672
- const mcpConfigDurationNs = mcpConfigSuccessTime - mcpConfigStartTime;
673
- logger.debug(`[NeuroLink] ✅ LOG_POINT_M015_MCP_CONFIG_SUCCESS`, {
674
- logPoint: "M015_MCP_CONFIG_SUCCESS",
675
- mcpInitId,
676
- timestamp: new Date().toISOString(),
677
- elapsedMs: Date.now() - mcpInitStartTime,
678
- elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
679
- mcpConfigDurationNs: mcpConfigDurationNs.toString(),
680
- mcpConfigDurationMs: Number(mcpConfigDurationNs) / 1000000,
681
- serversLoaded: configResult.serversLoaded,
682
- errorsCount: configResult.errors.length,
683
- configResult: {
684
- serversLoaded: configResult.serversLoaded,
685
- errors: configResult.errors.map((err) => ({
686
- message: err instanceof Error ? err.message : String(err),
687
- name: err instanceof Error ? err.name : "UnknownError",
688
- })),
689
- },
690
- message: "MCP configuration loaded successfully",
691
- });
692
- mcpLogger.debug("[NeuroLink] MCP configuration loaded successfully", {
693
- serversLoaded: configResult.serversLoaded,
694
- errors: configResult.errors.length,
695
- });
696
- if (configResult.errors.length > 0) {
697
- mcpLogger.warn("[NeuroLink] Some MCP servers failed to load", {
698
- errors: configResult.errors,
699
- });
700
- }
701
- }
702
- catch (configError) {
703
- mcpLogger.warn("[NeuroLink] MCP configuration loading failed", {
704
- error: configError instanceof Error
705
- ? configError.message
706
- : String(configError),
707
- });
708
- }
709
- this.mcpInitialized = true;
710
- // Monitor memory usage and provide cleanup suggestions
711
- const endMemory = MemoryManager
712
- ? MemoryManager.getMemoryUsageMB()
713
- : { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
714
- const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
715
- const initTime = Date.now() - mcpInitStartTime;
716
- mcpLogger.debug("[NeuroLink] MCP initialization completed successfully", {
717
- initTime: `${initTime}ms`,
718
- memoryUsed: `${memoryDelta}MB`,
719
- });
720
- // Suggest cleanup if initialization used significant memory
721
- if (memoryDelta > 30) {
722
- mcpLogger.debug("💡 Memory cleanup suggestion: MCP initialization used significant memory. Consider calling MemoryManager.forceGC() after heavy operations.");
723
- }
724
754
  }
725
- catch (error) {
726
- mcpLogger.warn("[NeuroLink] MCP initialization failed", {
727
- error: error instanceof Error ? error.message : String(error),
755
+ catch (configError) {
756
+ mcpLogger.warn("[NeuroLink] MCP configuration loading failed", {
757
+ error: configError instanceof Error
758
+ ? configError.message
759
+ : String(configError),
728
760
  });
729
- // Continue without MCP - graceful degradation
761
+ }
762
+ }
763
+ /**
764
+ * Log MCP initialization completion
765
+ */
766
+ logMCPInitComplete(startMemory, MemoryManager, mcpInitStartTime) {
767
+ const endMemory = MemoryManager
768
+ ? MemoryManager.getMemoryUsageMB()
769
+ : { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
770
+ const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
771
+ const initTime = Date.now() - mcpInitStartTime;
772
+ mcpLogger.debug("[NeuroLink] MCP initialization completed successfully", {
773
+ initTime: `${initTime}ms`,
774
+ memoryUsed: `${memoryDelta}MB`,
775
+ });
776
+ if (memoryDelta > 30) {
777
+ mcpLogger.debug("💡 Memory cleanup suggestion: MCP initialization used significant memory. Consider calling MemoryManager.forceGC() after heavy operations.");
730
778
  }
731
779
  }
732
780
  /**
@@ -745,21 +793,6 @@ export class NeuroLink {
745
793
  ? optionsOrPrompt
746
794
  : optionsOrPrompt.input.text;
747
795
  }
748
- /**
749
- * Enables automatic context summarization for the NeuroLink instance.
750
- * Once enabled, the instance will maintain conversation history and
751
- * automatically summarize it when it exceeds token limits.
752
- * @param config Optional configuration to override default summarization settings.
753
- */
754
- enableContextSummarization(config) {
755
- const contextConfig = {
756
- ...defaultContextConfig,
757
- ...config,
758
- };
759
- // Pass the internal generator function directly, bound to the correct `this` context.
760
- this.contextManager = new ContextManager(this.generateTextInternal.bind(this), contextConfig);
761
- logger.info("[NeuroLink] Automatic context summarization enabled.");
762
- }
763
796
  /**
764
797
  * Generate AI content using the best available provider with MCP tool integration.
765
798
  * This is the primary method for text generation with full feature support.
@@ -818,11 +851,6 @@ export class NeuroLink {
818
851
  if (!options.input?.text || typeof options.input.text !== "string") {
819
852
  throw new Error("Input text is required and must be a non-empty string");
820
853
  }
821
- // Handle Context Management if enabled
822
- if (this.contextManager) {
823
- // Get the full context for the prompt without permanently adding the user's turn yet
824
- options.input.text = this.contextManager.getContextForPrompt("user", options.input.text);
825
- }
826
854
  const startTime = Date.now();
827
855
  // Emit generation start event (NeuroLink format - keep existing)
828
856
  this.emitter.emit("generation:start", {
@@ -862,6 +890,12 @@ export class NeuroLink {
862
890
  };
863
891
  // Apply factory enhancement using centralized utilities
864
892
  const textOptions = enhanceTextGenerationOptions(baseOptions, factoryResult);
893
+ // Pass conversation memory config if available
894
+ if (this.conversationMemory) {
895
+ textOptions.conversationMemoryConfig = this.conversationMemory.config;
896
+ // Include original prompt for context summarization
897
+ textOptions.originalPrompt = originalPrompt;
898
+ }
865
899
  // Detect and execute domain-specific tools
866
900
  const { toolResults, enhancedPrompt } = await this.detectAndExecuteTools(textOptions.prompt || options.input.text, factoryResult.domainType);
867
901
  // Update prompt with tool results if available
@@ -894,9 +928,9 @@ export class NeuroLink {
894
928
  model: textResult.model,
895
929
  usage: textResult.usage
896
930
  ? {
897
- inputTokens: textResult.usage.promptTokens || 0,
898
- outputTokens: textResult.usage.completionTokens || 0,
899
- totalTokens: textResult.usage.totalTokens || 0,
931
+ input: textResult.usage.input || 0,
932
+ output: textResult.usage.output || 0,
933
+ total: textResult.usage.total || 0,
900
934
  }
901
935
  : undefined,
902
936
  responseTime: textResult.responseTime,
@@ -910,9 +944,11 @@ export class NeuroLink {
910
944
  ...textResult.evaluation,
911
945
  isOffTopic: textResult.evaluation
912
946
  .isOffTopic ?? false,
913
- alertSeverity: textResult.evaluation.alertSeverity ?? "none",
914
- reasoning: textResult.evaluation.reasoning ??
915
- "No evaluation provided",
947
+ alertSeverity: textResult.evaluation
948
+ .alertSeverity ??
949
+ "none",
950
+ reasoning: textResult.evaluation
951
+ .reasoning ?? "No evaluation provided",
916
952
  evaluationModel: textResult.evaluation
917
953
  .evaluationModel ?? "unknown",
918
954
  evaluationTime: textResult.evaluation
@@ -925,11 +961,6 @@ export class NeuroLink {
925
961
  }
926
962
  : undefined,
927
963
  };
928
- // Add both the user's turn and the AI's response to the permanent history
929
- if (this.contextManager) {
930
- await this.contextManager.addTurn("user", originalPrompt);
931
- await this.contextManager.addTurn("assistant", generateResult.content);
932
- }
933
964
  return generateResult;
934
965
  }
935
966
  /**
@@ -956,19 +987,47 @@ export class NeuroLink {
956
987
  * 4. Fall back to direct provider generation
957
988
  * 5. Store conversation turn for future context
958
989
  */
959
- async generateTextInternal(options) {
960
- // 🚀 EXHAUSTIVE LOGGING POINT G001: GENERATE TEXT INTERNAL ENTRY
961
- const generateInternalId = `generate-internal-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
962
- const generateInternalStartTime = Date.now();
963
- const generateInternalHrTimeStart = process.hrtime.bigint();
964
- const functionTag = "NeuroLink.generateTextInternal";
990
+ async generateTextInternal(options) {
991
+ const generateInternalId = `generate-internal-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
992
+ const generateInternalStartTime = Date.now();
993
+ const generateInternalHrTimeStart = process.hrtime.bigint();
994
+ const functionTag = "NeuroLink.generateTextInternal";
995
+ this.logGenerateTextInternalStart(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, options, functionTag);
996
+ this.emitGenerationStartEvents(options);
997
+ try {
998
+ await this.initializeConversationMemoryForGeneration(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart);
999
+ const mcpResult = await this.attemptMCPGeneration(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag);
1000
+ if (mcpResult) {
1001
+ await storeConversationTurn(this.conversationMemory, options, mcpResult);
1002
+ this.emitter.emit("response:end", mcpResult.content || "");
1003
+ return mcpResult;
1004
+ }
1005
+ const directResult = await this.directProviderGeneration(options);
1006
+ logger.debug(`[${functionTag}] Direct generation successful`);
1007
+ await storeConversationTurn(this.conversationMemory, options, directResult);
1008
+ this.emitter.emit("response:end", directResult.content || "");
1009
+ this.emitter.emit("message", `Text generation completed successfully`);
1010
+ return directResult;
1011
+ }
1012
+ catch (error) {
1013
+ logger.error(`[${functionTag}] All generation methods failed`, {
1014
+ error: error instanceof Error ? error.message : String(error),
1015
+ });
1016
+ this.emitter.emit("response:end", "");
1017
+ this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
1018
+ throw error;
1019
+ }
1020
+ }
1021
+ /**
1022
+ * Log generateTextInternal start with comprehensive analysis
1023
+ */
1024
+ logGenerateTextInternalStart(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, options, functionTag) {
965
1025
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_G001_GENERATE_INTERNAL_START`, {
966
1026
  logPoint: "G001_GENERATE_INTERNAL_START",
967
1027
  generateInternalId,
968
1028
  timestamp: new Date().toISOString(),
969
1029
  generateInternalStartTime,
970
1030
  generateInternalHrTimeStart: generateInternalHrTimeStart.toString(),
971
- // 📊 Input analysis
972
1031
  inputAnalysis: {
973
1032
  provider: options.provider || "auto",
974
1033
  providerType: typeof options.provider,
@@ -991,19 +1050,16 @@ export class NeuroLink {
991
1050
  evaluationDomain: options.evaluationDomain || "NOT_SET",
992
1051
  toolUsageContext: options.toolUsageContext || "NOT_SET",
993
1052
  },
994
- // 🧠 Memory and initialization state
995
1053
  instanceState: {
996
1054
  hasConversationMemory: !!this.conversationMemory,
997
1055
  conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_SET",
998
1056
  mcpInitialized: this.mcpInitialized,
999
1057
  hasProviderRegistry: !!AIProviderFactory,
1000
- providerRegistrySize: 0, // Not accessible as size property
1058
+ providerRegistrySize: 0,
1001
1059
  hasToolRegistry: !!toolRegistry,
1002
- toolRegistrySize: 0, // Not accessible as size property
1060
+ toolRegistrySize: 0,
1003
1061
  hasExternalServerManager: !!this.externalServerManager,
1004
- hasContextManager: !!this.contextManager,
1005
1062
  },
1006
- // 🔧 Environment context
1007
1063
  environmentContext: {
1008
1064
  nodeVersion: process.version,
1009
1065
  platform: process.platform,
@@ -1019,216 +1075,188 @@ export class NeuroLink {
1019
1075
  promptLength: options.prompt?.length || 0,
1020
1076
  hasConversationMemory: !!this.conversationMemory,
1021
1077
  });
1022
- // ADD: Bedrock-compatible response:start event for generateTextInternal
1078
+ }
1079
+ /**
1080
+ * Emit generation start events
1081
+ */
1082
+ emitGenerationStartEvents(options) {
1023
1083
  this.emitter.emit("response:start");
1024
- // ADD: Bedrock-compatible message event for generateTextInternal
1025
1084
  this.emitter.emit("message", `Starting ${options.provider || "auto"} text generation (internal)...`);
1026
- try {
1027
- // 🚀 EXHAUSTIVE LOGGING POINT G002: CONVERSATION MEMORY INITIALIZATION
1028
- const conversationMemoryStartTime = process.hrtime.bigint();
1029
- logger.debug(`[NeuroLink] 🧠 LOG_POINT_G002_CONVERSATION_MEMORY_CHECK`, {
1030
- logPoint: "G002_CONVERSATION_MEMORY_CHECK",
1085
+ }
1086
+ /**
1087
+ * Initialize conversation memory for generation
1088
+ */
1089
+ async initializeConversationMemoryForGeneration(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart) {
1090
+ const conversationMemoryStartTime = process.hrtime.bigint();
1091
+ logger.debug(`[NeuroLink] 🧠 LOG_POINT_G002_CONVERSATION_MEMORY_CHECK`, {
1092
+ logPoint: "G002_CONVERSATION_MEMORY_CHECK",
1093
+ generateInternalId,
1094
+ timestamp: new Date().toISOString(),
1095
+ elapsedMs: Date.now() - generateInternalStartTime,
1096
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1097
+ conversationMemoryStartTimeNs: conversationMemoryStartTime.toString(),
1098
+ hasConversationMemory: !!this.conversationMemory,
1099
+ conversationMemoryEnabled: !!this.conversationMemory,
1100
+ conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_AVAILABLE",
1101
+ message: "Checking conversation memory initialization requirement",
1102
+ });
1103
+ if (this.conversationMemory) {
1104
+ logger.debug(`[NeuroLink] 🧠 LOG_POINT_G003_CONVERSATION_MEMORY_INIT_START`, {
1105
+ logPoint: "G003_CONVERSATION_MEMORY_INIT_START",
1031
1106
  generateInternalId,
1032
1107
  timestamp: new Date().toISOString(),
1033
1108
  elapsedMs: Date.now() - generateInternalStartTime,
1034
1109
  elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1035
- conversationMemoryStartTimeNs: conversationMemoryStartTime.toString(),
1036
- hasConversationMemory: !!this.conversationMemory,
1037
- conversationMemoryEnabled: !!this.conversationMemory,
1038
- conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_AVAILABLE",
1039
- message: "Checking conversation memory initialization requirement",
1110
+ message: "Starting conversation memory initialization",
1111
+ });
1112
+ await this.conversationMemory.initialize();
1113
+ const conversationMemoryEndTime = process.hrtime.bigint();
1114
+ const conversationMemoryDurationNs = conversationMemoryEndTime - conversationMemoryStartTime;
1115
+ logger.debug(`[NeuroLink] ✅ LOG_POINT_G004_CONVERSATION_MEMORY_INIT_SUCCESS`, {
1116
+ logPoint: "G004_CONVERSATION_MEMORY_INIT_SUCCESS",
1117
+ generateInternalId,
1118
+ timestamp: new Date().toISOString(),
1119
+ elapsedMs: Date.now() - generateInternalStartTime,
1120
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1121
+ conversationMemoryDurationNs: conversationMemoryDurationNs.toString(),
1122
+ conversationMemoryDurationMs: Number(conversationMemoryDurationNs) / 1000000,
1123
+ message: "Conversation memory initialization completed successfully",
1040
1124
  });
1041
- // Initialize conversation memory if enabled
1042
- if (this.conversationMemory) {
1043
- logger.debug(`[NeuroLink] 🧠 LOG_POINT_G003_CONVERSATION_MEMORY_INIT_START`, {
1044
- logPoint: "G003_CONVERSATION_MEMORY_INIT_START",
1125
+ }
1126
+ }
1127
+ /**
1128
+ * Attempt MCP generation with retry logic
1129
+ */
1130
+ async attemptMCPGeneration(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
1131
+ const mcpDecisionStartTime = process.hrtime.bigint();
1132
+ logger.debug(`[NeuroLink] 🔧 LOG_POINT_G005_MCP_DECISION_CHECK`, {
1133
+ logPoint: "G005_MCP_DECISION_CHECK",
1134
+ generateInternalId,
1135
+ timestamp: new Date().toISOString(),
1136
+ elapsedMs: Date.now() - generateInternalStartTime,
1137
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1138
+ mcpDecisionStartTimeNs: mcpDecisionStartTime.toString(),
1139
+ mcpDecisionFactors: {
1140
+ disableTools: options.disableTools || false,
1141
+ toolsEnabled: !options.disableTools,
1142
+ mcpInitialized: this.mcpInitialized,
1143
+ hasExternalServerManager: !!this.externalServerManager,
1144
+ hasToolRegistry: !!toolRegistry,
1145
+ toolRegistrySize: 0,
1146
+ shouldTryMCP: !options.disableTools,
1147
+ },
1148
+ mcpReadinessAnalysis: {
1149
+ mcpAvailable: !options.disableTools && this.mcpInitialized,
1150
+ componentsReady: {
1151
+ externalServerManager: !!this.externalServerManager,
1152
+ toolRegistry: !!toolRegistry,
1153
+ providerRegistry: !!AIProviderFactory,
1154
+ },
1155
+ },
1156
+ message: "Analyzing MCP generation eligibility and readiness",
1157
+ });
1158
+ if (!options.disableTools) {
1159
+ return await this.performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag);
1160
+ }
1161
+ return null;
1162
+ }
1163
+ /**
1164
+ * Perform MCP generation with retry logic
1165
+ */
1166
+ async performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
1167
+ const maxMcpRetries = 2;
1168
+ const mcpRetryLoopStartTime = process.hrtime.bigint();
1169
+ logger.debug(`[NeuroLink] 🔄 LOG_POINT_G006_MCP_RETRY_LOOP_START`, {
1170
+ logPoint: "G006_MCP_RETRY_LOOP_START",
1171
+ generateInternalId,
1172
+ timestamp: new Date().toISOString(),
1173
+ elapsedMs: Date.now() - generateInternalStartTime,
1174
+ elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1175
+ mcpRetryLoopStartTimeNs: mcpRetryLoopStartTime.toString(),
1176
+ maxMcpRetries,
1177
+ totalPossibleAttempts: maxMcpRetries + 1,
1178
+ message: "Starting MCP generation retry loop with failure tolerance",
1179
+ });
1180
+ const maxAttempts = maxMcpRetries + 1;
1181
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1182
+ try {
1183
+ const mcpAttemptStartTime = process.hrtime.bigint();
1184
+ logger.debug(`[NeuroLink] 🎯 LOG_POINT_G007_MCP_ATTEMPT_START`, {
1185
+ logPoint: "G007_MCP_ATTEMPT_START",
1045
1186
  generateInternalId,
1046
1187
  timestamp: new Date().toISOString(),
1047
1188
  elapsedMs: Date.now() - generateInternalStartTime,
1048
1189
  elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1049
- message: "Starting conversation memory initialization",
1190
+ mcpAttemptStartTimeNs: mcpAttemptStartTime.toString(),
1191
+ currentAttempt: attempt,
1192
+ maxAttempts,
1193
+ isFirstAttempt: attempt === 1,
1194
+ isLastAttempt: attempt === maxAttempts,
1195
+ attemptType: attempt === 1 ? "INITIAL" : "RETRY",
1196
+ message: `Attempting MCP generation (attempt ${attempt}/${maxAttempts})`,
1050
1197
  });
1051
- await this.conversationMemory.initialize();
1052
- const conversationMemoryEndTime = process.hrtime.bigint();
1053
- const conversationMemoryDurationNs = conversationMemoryEndTime - conversationMemoryStartTime;
1054
- logger.debug(`[NeuroLink] LOG_POINT_G004_CONVERSATION_MEMORY_INIT_SUCCESS`, {
1055
- logPoint: "G004_CONVERSATION_MEMORY_INIT_SUCCESS",
1198
+ logger.debug(`[${functionTag}] Attempting MCP generation (attempt ${attempt}/${maxAttempts})...`);
1199
+ const mcpResult = await this.tryMCPGeneration(options);
1200
+ const mcpAttemptEndTime = process.hrtime.bigint();
1201
+ const mcpAttemptDurationNs = mcpAttemptEndTime - mcpAttemptStartTime;
1202
+ logger.debug(`[NeuroLink] 📊 LOG_POINT_G008_MCP_ATTEMPT_RESULT`, {
1203
+ logPoint: "G008_MCP_ATTEMPT_RESULT",
1056
1204
  generateInternalId,
1057
1205
  timestamp: new Date().toISOString(),
1058
1206
  elapsedMs: Date.now() - generateInternalStartTime,
1059
1207
  elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1060
- conversationMemoryDurationNs: conversationMemoryDurationNs.toString(),
1061
- conversationMemoryDurationMs: Number(conversationMemoryDurationNs) / 1000000,
1062
- message: "Conversation memory initialization completed successfully",
1208
+ mcpAttemptDurationNs: mcpAttemptDurationNs.toString(),
1209
+ mcpAttemptDurationMs: Number(mcpAttemptDurationNs) / 1000000,
1210
+ currentAttempt: attempt,
1211
+ resultAnalysis: {
1212
+ hasResult: !!mcpResult,
1213
+ resultType: typeof mcpResult,
1214
+ hasContent: !!(mcpResult && mcpResult.content),
1215
+ contentLength: mcpResult?.content?.length || 0,
1216
+ contentPreview: mcpResult?.content?.substring(0, 200) || "NO_CONTENT",
1217
+ hasToolExecutions: !!(mcpResult &&
1218
+ mcpResult.toolExecutions &&
1219
+ mcpResult.toolExecutions.length > 0),
1220
+ toolExecutionsCount: mcpResult?.toolExecutions?.length || 0,
1221
+ toolsUsedCount: mcpResult?.toolsUsed?.length || 0,
1222
+ provider: mcpResult?.provider || "NOT_SET",
1223
+ responseTime: mcpResult?.responseTime || 0,
1224
+ enhancedWithTools: mcpResult?.enhancedWithTools || false,
1225
+ },
1226
+ message: `MCP generation attempt ${attempt} completed - analyzing result`,
1063
1227
  });
1228
+ if (mcpResult &&
1229
+ (mcpResult.content ||
1230
+ (mcpResult.toolExecutions && mcpResult.toolExecutions.length > 0))) {
1231
+ logger.debug(`[${functionTag}] MCP generation successful on attempt ${attempt}`, {
1232
+ contentLength: mcpResult.content?.length || 0,
1233
+ toolsUsed: mcpResult.toolsUsed?.length || 0,
1234
+ toolExecutions: mcpResult.toolExecutions?.length || 0,
1235
+ });
1236
+ return mcpResult;
1237
+ }
1238
+ else {
1239
+ logger.debug(`[${functionTag}] MCP generation returned empty result on attempt ${attempt}`, {
1240
+ hasResult: !!mcpResult,
1241
+ hasContent: !!(mcpResult && mcpResult.content),
1242
+ contentLength: mcpResult?.content?.length || 0,
1243
+ toolExecutions: mcpResult?.toolExecutions?.length || 0,
1244
+ });
1245
+ }
1064
1246
  }
1065
- // 🚀 EXHAUSTIVE LOGGING POINT G005: MCP GENERATION BRANCH DECISION
1066
- const mcpDecisionStartTime = process.hrtime.bigint();
1067
- logger.debug(`[NeuroLink] 🔧 LOG_POINT_G005_MCP_DECISION_CHECK`, {
1068
- logPoint: "G005_MCP_DECISION_CHECK",
1069
- generateInternalId,
1070
- timestamp: new Date().toISOString(),
1071
- elapsedMs: Date.now() - generateInternalStartTime,
1072
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1073
- mcpDecisionStartTimeNs: mcpDecisionStartTime.toString(),
1074
- // 🎯 MCP decision factors
1075
- mcpDecisionFactors: {
1076
- disableTools: options.disableTools || false,
1077
- toolsEnabled: !options.disableTools,
1078
- mcpInitialized: this.mcpInitialized,
1079
- hasExternalServerManager: !!this.externalServerManager,
1080
- hasToolRegistry: !!toolRegistry,
1081
- toolRegistrySize: 0, // Not accessible as size property
1082
- shouldTryMCP: !options.disableTools,
1083
- },
1084
- // 🔍 MCP readiness analysis
1085
- mcpReadinessAnalysis: {
1086
- mcpAvailable: !options.disableTools && this.mcpInitialized,
1087
- componentsReady: {
1088
- externalServerManager: !!this.externalServerManager,
1089
- toolRegistry: !!toolRegistry,
1090
- providerRegistry: !!AIProviderFactory,
1091
- },
1092
- },
1093
- message: "Analyzing MCP generation eligibility and readiness",
1094
- });
1095
- // Try MCP-enhanced generation first (if not explicitly disabled)
1096
- if (!options.disableTools) {
1097
- // 🚀 EXHAUSTIVE LOGGING POINT G006: MCP RETRY LOOP INITIALIZATION
1098
- const mcpAttempts = 0;
1099
- const maxMcpRetries = 2; // Allow retries for tool-related failures
1100
- const mcpRetryLoopStartTime = process.hrtime.bigint();
1101
- logger.debug(`[NeuroLink] 🔄 LOG_POINT_G006_MCP_RETRY_LOOP_START`, {
1102
- logPoint: "G006_MCP_RETRY_LOOP_START",
1103
- generateInternalId,
1104
- timestamp: new Date().toISOString(),
1105
- elapsedMs: Date.now() - generateInternalStartTime,
1106
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1107
- mcpRetryLoopStartTimeNs: mcpRetryLoopStartTime.toString(),
1108
- maxMcpRetries,
1109
- totalPossibleAttempts: maxMcpRetries + 1,
1110
- currentAttempt: mcpAttempts + 1,
1111
- message: "Starting MCP generation retry loop with failure tolerance",
1247
+ catch (error) {
1248
+ logger.debug(`[${functionTag}] MCP generation failed on attempt ${attempt}/${maxAttempts}`, {
1249
+ error: error instanceof Error ? error.message : String(error),
1250
+ willRetry: attempt < maxAttempts,
1112
1251
  });
1113
- const maxAttempts = maxMcpRetries + 1;
1114
- for (let attempt = 1; attempt <= maxAttempts; attempt++) {
1115
- try {
1116
- // 🚀 EXHAUSTIVE LOGGING POINT G007: MCP GENERATION ATTEMPT
1117
- const mcpAttemptStartTime = process.hrtime.bigint();
1118
- logger.debug(`[NeuroLink] 🎯 LOG_POINT_G007_MCP_ATTEMPT_START`, {
1119
- logPoint: "G007_MCP_ATTEMPT_START",
1120
- generateInternalId,
1121
- timestamp: new Date().toISOString(),
1122
- elapsedMs: Date.now() - generateInternalStartTime,
1123
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1124
- mcpAttemptStartTimeNs: mcpAttemptStartTime.toString(),
1125
- currentAttempt: attempt,
1126
- maxAttempts,
1127
- isFirstAttempt: attempt === 1,
1128
- isLastAttempt: attempt === maxAttempts,
1129
- attemptType: attempt === 1 ? "INITIAL" : "RETRY",
1130
- message: `Attempting MCP generation (attempt ${attempt}/${maxAttempts})`,
1131
- });
1132
- logger.debug(`[${functionTag}] Attempting MCP generation (attempt ${attempt}/${maxAttempts})...`);
1133
- const mcpResult = await this.tryMCPGeneration(options);
1134
- // 🚀 EXHAUSTIVE LOGGING POINT G008: MCP GENERATION ATTEMPT RESULT
1135
- const mcpAttemptEndTime = process.hrtime.bigint();
1136
- const mcpAttemptDurationNs = mcpAttemptEndTime - mcpAttemptStartTime;
1137
- logger.debug(`[NeuroLink] 📊 LOG_POINT_G008_MCP_ATTEMPT_RESULT`, {
1138
- logPoint: "G008_MCP_ATTEMPT_RESULT",
1139
- generateInternalId,
1140
- timestamp: new Date().toISOString(),
1141
- elapsedMs: Date.now() - generateInternalStartTime,
1142
- elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
1143
- mcpAttemptDurationNs: mcpAttemptDurationNs.toString(),
1144
- mcpAttemptDurationMs: Number(mcpAttemptDurationNs) / 1000000,
1145
- currentAttempt: attempt,
1146
- // 🎯 Result analysis
1147
- resultAnalysis: {
1148
- hasResult: !!mcpResult,
1149
- resultType: typeof mcpResult,
1150
- hasContent: !!(mcpResult && mcpResult.content),
1151
- contentLength: mcpResult?.content?.length || 0,
1152
- contentPreview: mcpResult?.content?.substring(0, 200) || "NO_CONTENT",
1153
- hasToolExecutions: !!(mcpResult &&
1154
- mcpResult.toolExecutions &&
1155
- mcpResult.toolExecutions.length > 0),
1156
- toolExecutionsCount: mcpResult?.toolExecutions?.length || 0,
1157
- toolsUsedCount: mcpResult?.toolsUsed?.length || 0,
1158
- provider: mcpResult?.provider || "NOT_SET",
1159
- responseTime: mcpResult?.responseTime || 0,
1160
- enhancedWithTools: mcpResult?.enhancedWithTools || false,
1161
- },
1162
- message: `MCP generation attempt ${attempt} completed - analyzing result`,
1163
- });
1164
- if (mcpResult && mcpResult.content) {
1165
- logger.debug(`[${functionTag}] MCP generation successful on attempt ${attempt}`, {
1166
- contentLength: mcpResult.content.length,
1167
- toolsUsed: mcpResult.toolsUsed?.length || 0,
1168
- toolExecutions: mcpResult.toolExecutions?.length || 0,
1169
- });
1170
- // Store conversation turn
1171
- await storeConversationTurn(this.conversationMemory, options, mcpResult);
1172
- // ADD: Bedrock-compatible response:end event for MCP success path
1173
- this.emitter.emit("response:end", mcpResult.content || "");
1174
- return mcpResult;
1175
- }
1176
- else {
1177
- logger.debug(`[${functionTag}] MCP generation returned empty result on attempt ${attempt}:`, {
1178
- hasResult: !!mcpResult,
1179
- hasContent: !!(mcpResult && mcpResult.content),
1180
- contentLength: mcpResult?.content?.length || 0,
1181
- toolExecutions: mcpResult?.toolExecutions?.length || 0,
1182
- });
1183
- // If we got a result but no content, and we have tool executions, this might be a tool success case
1184
- if (mcpResult &&
1185
- mcpResult.toolExecutions &&
1186
- mcpResult.toolExecutions.length > 0) {
1187
- logger.debug(`[${functionTag}] Found tool executions but no content, continuing with result`);
1188
- // Store conversation turn even with empty content if tools executed
1189
- await storeConversationTurn(this.conversationMemory, options, mcpResult);
1190
- // ADD: Bedrock-compatible response:end event for MCP tool execution success path
1191
- this.emitter.emit("response:end", mcpResult.content || "");
1192
- return mcpResult;
1193
- }
1194
- }
1195
- }
1196
- catch (error) {
1197
- logger.debug(`[${functionTag}] MCP generation failed on attempt ${attempt}/${maxAttempts}`, {
1198
- error: error instanceof Error ? error.message : String(error),
1199
- willRetry: attempt < maxAttempts,
1200
- });
1201
- // If this was the last attempt, break and fall back
1202
- if (attempt >= maxAttempts) {
1203
- logger.debug(`[${functionTag}] All MCP attempts exhausted, falling back to direct generation`);
1204
- break;
1205
- }
1206
- // Small delay before retry to allow transient issues to resolve
1207
- await new Promise((resolve) => setTimeout(resolve, 500));
1208
- }
1252
+ if (attempt >= maxAttempts) {
1253
+ logger.debug(`[${functionTag}] All MCP attempts exhausted, falling back to direct generation`);
1254
+ break;
1209
1255
  }
1256
+ await new Promise((resolve) => setTimeout(resolve, 500));
1210
1257
  }
1211
- // Fall back to direct provider generation
1212
- const directResult = await this.directProviderGeneration(options);
1213
- logger.debug(`[${functionTag}] Direct generation successful`);
1214
- // Store conversation turn
1215
- await storeConversationTurn(this.conversationMemory, options, directResult);
1216
- // ADD: Bedrock-compatible response:end event for generateTextInternal
1217
- this.emitter.emit("response:end", directResult.content || "");
1218
- // ADD: Bedrock-compatible message event for generateTextInternal completion
1219
- this.emitter.emit("message", `Text generation completed successfully`);
1220
- return directResult;
1221
- }
1222
- catch (error) {
1223
- logger.error(`[${functionTag}] All generation methods failed`, {
1224
- error: error instanceof Error ? error.message : String(error),
1225
- });
1226
- // ADD: Bedrock-compatible response:end event for error path (empty content)
1227
- this.emitter.emit("response:end", "");
1228
- // ADD: Centralized error event emission
1229
- this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
1230
- throw error;
1231
1258
  }
1259
+ return null;
1232
1260
  }
1233
1261
  /**
1234
1262
  * Try MCP-enhanced generation (no fallback recursion)
@@ -1610,7 +1638,42 @@ export class NeuroLink {
1610
1638
  const functionTag = "NeuroLink.stream";
1611
1639
  const streamId = `neurolink-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
1612
1640
  const journeyStartTime = new Date().toISOString();
1613
- // 🚀 EXHAUSTIVE LOGGING POINT 1: MAIN NEUROLINK STREAM ENTRY POINT
1641
+ this.logStreamEntryPoint(streamId, journeyStartTime, functionTag, startTime, hrTimeStart, options);
1642
+ this.logPerformanceBaseline(streamId, startTime, hrTimeStart);
1643
+ await this.validateStreamInput(options, streamId, startTime, hrTimeStart);
1644
+ this.emitStreamStartEvents(options, startTime);
1645
+ let enhancedOptions;
1646
+ let factoryResult;
1647
+ try {
1648
+ await this.initializeMCP();
1649
+ const _originalPrompt = options.input.text;
1650
+ factoryResult = processStreamingFactoryOptions(options);
1651
+ enhancedOptions = createCleanStreamOptions(options);
1652
+ const { toolResults: _toolResults, enhancedPrompt } = await this.detectAndExecuteTools(options.input.text, undefined);
1653
+ if (enhancedPrompt !== options.input.text) {
1654
+ enhancedOptions.input.text = enhancedPrompt;
1655
+ }
1656
+ const { stream: mcpStream, provider: providerName } = await this.createMCPStream(enhancedOptions);
1657
+ const streamResult = await this.processStreamResult(mcpStream, enhancedOptions, factoryResult);
1658
+ const responseTime = Date.now() - startTime;
1659
+ this.emitStreamEndEvents(streamResult);
1660
+ return this.createStreamResponse(streamResult, mcpStream, {
1661
+ providerName,
1662
+ options,
1663
+ startTime,
1664
+ responseTime,
1665
+ streamId,
1666
+ fallback: false,
1667
+ });
1668
+ }
1669
+ catch (error) {
1670
+ return this.handleStreamError(error, options, startTime, streamId, undefined, undefined);
1671
+ }
1672
+ }
1673
+ /**
1674
+ * Log stream entry point with comprehensive analysis
1675
+ */
1676
+ logStreamEntryPoint(streamId, journeyStartTime, functionTag, startTime, hrTimeStart, options) {
1614
1677
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_001_STREAM_ENTRY_START`, {
1615
1678
  logPoint: "001_STREAM_ENTRY_START",
1616
1679
  streamId,
@@ -1623,12 +1686,10 @@ export class NeuroLink {
1623
1686
  arch: process.arch,
1624
1687
  memoryUsage: process.memoryUsage(),
1625
1688
  cpuUsage: process.cpuUsage(),
1626
- // Comprehensive input validation
1627
1689
  hasOptions: !!options,
1628
1690
  optionsType: typeof options,
1629
1691
  optionsKeys: options ? Object.keys(options) : [],
1630
1692
  optionsSize: options ? JSON.stringify(options).length : 0,
1631
- // Deep input analysis
1632
1693
  hasInput: !!options?.input,
1633
1694
  inputType: typeof options?.input,
1634
1695
  inputKeys: options?.input ? Object.keys(options.input) : [],
@@ -1636,53 +1697,18 @@ export class NeuroLink {
1636
1697
  inputTextType: typeof options?.input?.text,
1637
1698
  inputTextLength: options?.input?.text?.length || 0,
1638
1699
  inputTextPreview: options?.input?.text?.substring(0, 200) || "NO_TEXT",
1639
- inputTextHash: options?.input?.text
1640
- ? "hash-" +
1641
- options.input.text.length +
1642
- "-" +
1643
- Math.random().toString(36).substr(2, 8)
1644
- : "NO_HASH",
1645
- // Provider configuration analysis
1646
1700
  hasProvider: !!options?.provider,
1647
1701
  providerValue: options?.provider || "NOT_SET",
1648
1702
  isAutoProvider: options?.provider === "auto" || !options?.provider,
1649
- // Model configuration analysis
1650
1703
  hasModel: !!options?.model,
1651
1704
  modelValue: options?.model || "NOT_SET",
1652
- isDefaultModel: !options?.model,
1653
- // Advanced configuration analysis
1654
- hasSystemPrompt: !!options?.systemPrompt,
1655
- systemPromptLength: options?.systemPrompt?.length || 0,
1656
- systemPromptPreview: options?.systemPrompt?.substring(0, 100) || "NO_SYSTEM_PROMPT",
1657
- hasTemperature: !!options?.temperature,
1658
- temperatureValue: options?.temperature || "NOT_SET",
1659
- isValidTemperature: typeof options?.temperature === "number" &&
1660
- options.temperature >= 0 &&
1661
- options.temperature <= 2,
1662
- hasMaxTokens: !!options?.maxTokens,
1663
- maxTokensValue: options?.maxTokens || "NOT_SET",
1664
- isValidMaxTokens: typeof options?.maxTokens === "number" && options.maxTokens > 0,
1665
- hasDisableTools: options?.disableTools !== undefined,
1666
- disableToolsValue: options?.disableTools || false,
1667
- hasContext: !!options?.context,
1668
- contextKeys: options?.context ? Object.keys(options.context) : [],
1669
- contextSize: options?.context
1670
- ? JSON.stringify(options.context).length
1671
- : 0,
1672
- // Environment analysis
1673
- nodeEnv: process.env.NODE_ENV || "UNKNOWN",
1674
- hasProxyConfig: !!(process.env.HTTP_PROXY ||
1675
- process.env.HTTPS_PROXY ||
1676
- process.env.http_proxy ||
1677
- process.env.https_proxy),
1678
- httpProxy: process.env.HTTP_PROXY || process.env.http_proxy || "NOT_SET",
1679
- httpsProxy: process.env.HTTPS_PROXY || process.env.https_proxy || "NOT_SET",
1680
- hasGoogleCredentials: !!(process.env.GOOGLE_APPLICATION_CREDENTIALS ||
1681
- process.env.GOOGLE_SERVICE_ACCOUNT_KEY),
1682
- googleCredentialsPath: process.env.GOOGLE_APPLICATION_CREDENTIALS || "NOT_SET",
1683
1705
  message: "EXHAUSTIVE NeuroLink main stream method entry point with comprehensive environment analysis",
1684
1706
  });
1685
- // 🚀 EXHAUSTIVE LOGGING POINT 2: MEMORY AND PERFORMANCE BASELINE
1707
+ }
1708
+ /**
1709
+ * Log performance baseline
1710
+ */
1711
+ logPerformanceBaseline(streamId, startTime, hrTimeStart) {
1686
1712
  const memoryBaseline = process.memoryUsage();
1687
1713
  const cpuBaseline = process.cpuUsage();
1688
1714
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_002_PERFORMANCE_BASELINE`, {
@@ -1708,14 +1734,18 @@ export class NeuroLink {
1708
1734
  global.gc();
1709
1735
  return process.memoryUsage();
1710
1736
  }
1711
- catch (_e) {
1737
+ catch {
1712
1738
  return null;
1713
1739
  }
1714
1740
  })()
1715
1741
  : null,
1716
1742
  message: "Performance baseline metrics captured for stream processing",
1717
1743
  });
1718
- // 🚀 EXHAUSTIVE LOGGING POINT 3: INPUT VALIDATION START
1744
+ }
1745
+ /**
1746
+ * Validate stream input with comprehensive error reporting
1747
+ */
1748
+ async validateStreamInput(options, streamId, startTime, hrTimeStart) {
1719
1749
  const validationStartTime = process.hrtime.bigint();
1720
1750
  logger.debug(`[NeuroLink] 🎯 LOG_POINT_003_VALIDATION_START`, {
1721
1751
  logPoint: "003_VALIDATION_START",
@@ -1726,45 +1756,6 @@ export class NeuroLink {
1726
1756
  validationStartTimeNs: validationStartTime.toString(),
1727
1757
  message: "Starting comprehensive input validation process",
1728
1758
  });
1729
- // 🚀 EXHAUSTIVE LOGGING POINT 4: DETAILED VALIDATION CHECKS
1730
- logger.debug(`[NeuroLink] 🎯 LOG_POINT_004_VALIDATION_CHECKS`, {
1731
- logPoint: "004_VALIDATION_CHECKS",
1732
- streamId,
1733
- timestamp: new Date().toISOString(),
1734
- elapsedMs: Date.now() - startTime,
1735
- checks: {
1736
- hasOptions: !!options,
1737
- optionsIsObject: typeof options === "object" && options !== null,
1738
- hasInput: !!(options && options.input),
1739
- inputIsObject: !!(options &&
1740
- options.input &&
1741
- typeof options.input === "object"),
1742
- hasInputText: !!(options && options.input && options.input.text),
1743
- inputTextIsString: !!(options &&
1744
- options.input &&
1745
- typeof options.input.text === "string"),
1746
- inputTextNotEmpty: !!(options &&
1747
- options.input &&
1748
- options.input.text &&
1749
- options.input.text.trim() !== ""),
1750
- inputTextLength: options?.input?.text?.length || 0,
1751
- inputTextTrimmedLength: options?.input?.text?.trim()?.length || 0,
1752
- },
1753
- optionsStructure: options
1754
- ? {
1755
- keys: Object.keys(options),
1756
- inputKeys: options.input ? Object.keys(options.input) : null,
1757
- inputTextType: typeof options.input?.text,
1758
- inputTextValue: options.input?.text?.substring(0, 50) +
1759
- (options.input?.text?.length > 50 ? "..." : ""),
1760
- inputTextCharCodes: options.input?.text
1761
- ? Array.from(options.input.text.substring(0, 10)).map((c) => c.charCodeAt(0))
1762
- : null,
1763
- }
1764
- : null,
1765
- message: "Detailed validation checks performed",
1766
- });
1767
- // Validate input with comprehensive error reporting
1768
1759
  if (!options?.input?.text ||
1769
1760
  typeof options.input.text !== "string" ||
1770
1761
  options.input.text.trim() === "") {
@@ -1779,47 +1770,10 @@ export class NeuroLink {
1779
1770
  validationDurationNs: validationDurationNs.toString(),
1780
1771
  validationDurationMs: Number(validationDurationNs) / 1000000,
1781
1772
  validationError: "Stream options must include input.text as a non-empty string",
1782
- // Detailed failure analysis
1783
- failureReason: !options
1784
- ? "NO_OPTIONS"
1785
- : !options.input
1786
- ? "NO_INPUT"
1787
- : !options.input.text
1788
- ? "NO_INPUT_TEXT"
1789
- : typeof options.input.text !== "string"
1790
- ? "INPUT_TEXT_NOT_STRING"
1791
- : options.input.text.trim() === ""
1792
- ? "INPUT_TEXT_EMPTY_OR_WHITESPACE"
1793
- : "UNKNOWN",
1794
- // Deep analysis for debugging
1795
- hasOptions: !!options,
1796
- optionsType: typeof options,
1797
- hasInput: !!options?.input,
1798
- inputType: typeof options?.input,
1799
- hasInputText: !!options?.input?.text,
1800
- inputTextType: typeof options?.input?.text,
1801
- inputTextValue: options?.input?.text,
1802
- inputTextLength: options?.input?.text?.length || 0,
1803
- inputTextTrimmed: options?.input?.text?.trim(),
1804
- inputTextTrimmedLength: options?.input?.text?.trim()?.length || 0,
1805
- // Character analysis for whitespace debugging
1806
- inputTextCharacters: options?.input?.text
1807
- ? Array.from(options.input.text)
1808
- .map((char, index) => ({
1809
- index,
1810
- char,
1811
- charCode: char.charCodeAt(0),
1812
- isWhitespace: /\s/.test(char),
1813
- }))
1814
- .slice(0, 20)
1815
- : null,
1816
- memoryAtFailure: process.memoryUsage(),
1817
- cpuAtFailure: process.cpuUsage(),
1818
1773
  message: "EXHAUSTIVE validation failure analysis with character-level debugging",
1819
1774
  });
1820
1775
  throw new Error("Stream options must include input.text as a non-empty string");
1821
1776
  }
1822
- // 🚀 EXHAUSTIVE LOGGING POINT 6: VALIDATION SUCCESS
1823
1777
  const validationSuccessTime = process.hrtime.bigint();
1824
1778
  const validationDurationNs = validationSuccessTime - validationStartTime;
1825
1779
  logger.debug(`[NeuroLink] ✅ LOG_POINT_006_VALIDATION_SUCCESS`, {
@@ -1834,311 +1788,116 @@ export class NeuroLink {
1834
1788
  inputTextLength: options.input.text.length,
1835
1789
  inputTextTrimmedLength: options.input.text.trim().length,
1836
1790
  inputTextPreview: options.input.text.substring(0, 100),
1837
- inputTextHash: "hash-" +
1838
- options.input.text.length +
1839
- "-" +
1840
- Math.random().toString(36).substr(2, 8),
1841
- inputTextWordCount: options.input.text
1842
- .split(/\s+/)
1843
- .filter((word) => word.length > 0).length,
1844
- inputTextLineCount: options.input.text.split(/\n/).length,
1845
- memoryAfterValidation: process.memoryUsage(),
1846
- cpuAfterValidation: process.cpuUsage(),
1847
1791
  message: "EXHAUSTIVE validation success - proceeding with stream processing",
1848
1792
  });
1849
- // Emit stream start event (NeuroLink format - keep existing)
1793
+ }
1794
+ /**
1795
+ * Emit stream start events
1796
+ */
1797
+ emitStreamStartEvents(options, startTime) {
1850
1798
  this.emitter.emit("stream:start", {
1851
1799
  provider: options.provider || "auto",
1852
1800
  timestamp: startTime,
1853
1801
  });
1854
- // ADD: Bedrock-compatible response:start event
1855
1802
  this.emitter.emit("response:start");
1856
- // ADD: Bedrock-compatible message event
1857
- this.emitter.emit("message", `Starting ${options.provider || "auto"} stream generation...`);
1858
- // Process factory configuration for streaming
1859
- const factoryResult = processFactoryOptions(options);
1860
- const streamingResult = processStreamingFactoryOptions(options);
1861
- // Validate factory configuration if present
1862
- if (factoryResult.hasFactoryConfig && options.factoryConfig) {
1863
- const validation = validateFactoryConfig(options.factoryConfig);
1864
- if (!validation.isValid) {
1865
- mcpLogger.warn("Invalid factory configuration detected in stream", {
1866
- errors: validation.errors,
1867
- });
1868
- // Continue with warning rather than throwing - graceful degradation
1869
- }
1870
- }
1871
- // Log factory processing results
1872
- if (factoryResult.hasFactoryConfig) {
1873
- mcpLogger.debug(`[${functionTag}] Factory configuration detected`, {
1874
- domainType: factoryResult.domainType,
1875
- enhancementType: factoryResult.enhancementType,
1876
- hasStreamingConfig: streamingResult.hasStreamingConfig,
1877
- });
1878
- }
1879
- // Initialize MCP if needed
1880
- await this.initializeMCP();
1881
- // Context creation removed - was never used
1882
- // Determine provider to use
1883
- const providerName = options.provider === "auto" || !options.provider
1884
- ? await getBestProvider()
1885
- : options.provider;
1886
- // Prepare enhanced options for both success and fallback paths
1887
- let enhancedOptions = options;
1888
- if (factoryResult.hasFactoryConfig) {
1889
- enhancedOptions = {
1890
- ...options,
1891
- // Merge contexts instead of overriding to preserve provider-required context
1892
- context: {
1893
- ...(options.context || {}),
1894
- ...(factoryResult.processedContext || {}),
1895
- },
1896
- // Ensure evaluation is enabled when using factory patterns
1897
- enableEvaluation: options.enableEvaluation ?? true,
1898
- // Use domain type for evaluation if available
1899
- evaluationDomain: factoryResult.domainType || options.evaluationDomain,
1900
- };
1901
- mcpLogger.debug(`[${functionTag}] Enhanced stream options with factory config`, {
1902
- domainType: factoryResult.domainType,
1903
- enhancementType: factoryResult.enhancementType,
1904
- hasProcessedContext: !!factoryResult.processedContext,
1905
- });
1906
- }
1907
- try {
1908
- mcpLogger.debug(`[${functionTag}] Starting MCP-enabled streaming`, {
1909
- provider: providerName,
1910
- prompt: (options.input.text?.substring(0, 100) || "No text") + "...",
1911
- });
1912
- // Initialize conversation memory if enabled (same as generate function)
1913
- if (this.conversationMemory) {
1914
- await this.conversationMemory.initialize();
1915
- }
1916
- // Get conversation messages for context injection (same as generate function)
1917
- const conversationMessages = await getConversationMessages(this.conversationMemory, {
1918
- prompt: options.input.text,
1919
- context: enhancedOptions.context,
1920
- });
1921
- // Create provider using the same factory pattern as generate
1922
- const provider = await AIProviderFactory.createBestProvider(providerName, options.model, true, this);
1923
- // Enable tool execution for streaming using BaseProvider method
1924
- provider.setupToolExecutor({
1925
- customTools: this.getCustomTools(),
1926
- executeTool: this.executeTool.bind(this),
1927
- }, functionTag);
1928
- // Create clean options for provider (remove factoryConfig) and inject conversation history
1929
- const cleanOptions = createCleanStreamOptions(enhancedOptions);
1930
- const optionsWithHistory = {
1931
- ...cleanOptions,
1932
- conversationMessages, // Inject conversation history like in generate function
1933
- };
1934
- // Call the provider's stream method with conversation history
1935
- const streamResult = await provider.stream(optionsWithHistory);
1936
- // Extract the stream from the result
1937
- const originalStream = streamResult.stream;
1938
- // Create a proper tee pattern that accumulates content and stores memory after consumption
1939
- let accumulatedContent = "";
1940
- const processedStream = (async function* (self) {
1941
- try {
1942
- for await (const chunk of originalStream) {
1943
- // Enhanced chunk validation and content handling
1944
- let processedChunk = chunk;
1945
- if (chunk && typeof chunk === "object") {
1946
- // Ensure chunk has content property and it's a string
1947
- if (typeof chunk.content === "string") {
1948
- accumulatedContent += chunk.content;
1949
- // ADD: Bedrock-compatible response:chunk event
1950
- self.emitter.emit("response:chunk", chunk.content);
1951
- }
1952
- else if (chunk.content === undefined ||
1953
- chunk.content === null) {
1954
- // Handle undefined/null content gracefully - create a new chunk object
1955
- processedChunk = { ...chunk, content: "" };
1956
- }
1957
- else if (typeof chunk.content !== "string") {
1958
- // Convert non-string content to string - create a new chunk object
1959
- const stringContent = String(chunk.content || "");
1960
- processedChunk = { ...chunk, content: stringContent };
1961
- accumulatedContent += stringContent;
1962
- // ADD: Bedrock-compatible response:chunk event
1963
- self.emitter.emit("response:chunk", stringContent);
1964
- }
1965
- }
1966
- else if (chunk === null || chunk === undefined) {
1967
- // Create a safe empty chunk if chunk is null/undefined
1968
- processedChunk = { content: "" };
1969
- }
1970
- yield processedChunk; // Preserve original streaming behavior with safe content
1971
- }
1972
- }
1973
- finally {
1974
- // Store memory after stream consumption
1975
- if (self.conversationMemory) {
1976
- try {
1977
- await self.conversationMemory.storeConversationTurn(enhancedOptions.context
1978
- ?.sessionId, enhancedOptions.context
1979
- ?.userId, options.input.text, accumulatedContent);
1980
- logger.debug("Stream conversation turn stored", {
1981
- sessionId: enhancedOptions.context
1982
- ?.sessionId,
1983
- userInputLength: options.input.text.length,
1984
- responseLength: accumulatedContent.length,
1985
- });
1986
- }
1987
- catch (error) {
1988
- logger.warn("Failed to store stream conversation turn", {
1989
- error: error instanceof Error ? error.message : String(error),
1990
- });
1991
- }
1992
- }
1993
- }
1994
- })(this);
1995
- const responseTime = Date.now() - startTime;
1996
- mcpLogger.debug(`[${functionTag}] MCP-enabled streaming completed`, {
1997
- responseTime,
1998
- provider: providerName,
1999
- });
2000
- // Emit stream completion event (NeuroLink format - enhanced with content)
2001
- this.emitter.emit("stream:end", {
2002
- provider: providerName,
2003
- responseTime,
2004
- result: { content: accumulatedContent }, // Enhanced: include accumulated content
2005
- });
2006
- // ADD: Bedrock-compatible response:end event with full response
2007
- this.emitter.emit("response:end", accumulatedContent);
2008
- // ADD: Bedrock-compatible message event
2009
- this.emitter.emit("message", `Stream completed in ${responseTime}ms (${accumulatedContent.length} chars)`);
2010
- // Convert to StreamResult format - Include analytics and evaluation from provider
2011
- return {
2012
- stream: processedStream,
2013
- provider: providerName,
2014
- model: options.model,
2015
- usage: streamResult.usage,
2016
- finishReason: streamResult.finishReason,
2017
- toolCalls: streamResult.toolCalls,
2018
- toolResults: streamResult.toolResults,
2019
- analytics: streamResult.analytics,
2020
- evaluation: streamResult.evaluation
2021
- ? {
2022
- ...streamResult.evaluation,
2023
- // Include evaluationDomain from factory configuration
2024
- evaluationDomain: streamResult.evaluation
2025
- ?.evaluationDomain ??
2026
- enhancedOptions.evaluationDomain ??
2027
- factoryResult.domainType,
2028
- }
2029
- : undefined,
2030
- metadata: {
2031
- streamId: `neurolink-${Date.now()}`,
2032
- startTime,
2033
- responseTime,
2034
- },
2035
- };
2036
- }
2037
- catch (error) {
2038
- // ADD: Error event emission for MCP streaming failure
2039
- this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
2040
- // Fall back to regular streaming if MCP fails
2041
- mcpLogger.warn(`[${functionTag}] MCP streaming failed, falling back to regular`, {
2042
- error: error instanceof Error ? error.message : String(error),
2043
- });
2044
- // Initialize conversation memory for fallback path (same as success path)
2045
- if (this.conversationMemory) {
2046
- await this.conversationMemory.initialize();
2047
- }
2048
- // Get conversation messages for fallback context injection
2049
- const fallbackConversationMessages = await getConversationMessages(this.conversationMemory, {
2050
- prompt: options.input.text,
2051
- context: enhancedOptions.context,
2052
- });
2053
- // Use factory to create provider without MCP
2054
- const provider = await AIProviderFactory.createBestProvider(providerName, options.model, false, // Disable MCP for fallback
2055
- this);
2056
- // Enable tool execution for fallback streaming using BaseProvider method
2057
- provider.setupToolExecutor({
2058
- customTools: this.getCustomTools(),
2059
- executeTool: this.executeTool.bind(this),
2060
- }, functionTag);
2061
- // Create clean options for fallback provider and inject conversation history
2062
- const cleanOptions = createCleanStreamOptions(enhancedOptions);
2063
- const fallbackOptionsWithHistory = {
2064
- ...cleanOptions,
2065
- conversationMessages: fallbackConversationMessages, // Inject conversation history in fallback
2066
- };
2067
- const streamResult = await provider.stream(fallbackOptionsWithHistory);
2068
- // Create a proper tee pattern for fallback that accumulates content and stores memory after consumption
2069
- let fallbackAccumulatedContent = "";
2070
- const fallbackProcessedStream = (async function* (self) {
2071
- try {
2072
- for await (const chunk of streamResult.stream) {
2073
- if (chunk && typeof chunk.content === "string") {
2074
- fallbackAccumulatedContent += chunk.content;
2075
- // ADD: Bedrock-compatible response:chunk event for fallback
2076
- self.emitter.emit("response:chunk", chunk.content);
2077
- }
2078
- yield chunk; // Preserve original streaming behavior
2079
- }
2080
- }
2081
- finally {
2082
- // Store memory after fallback stream consumption
2083
- if (self.conversationMemory) {
2084
- try {
2085
- await self.conversationMemory.storeConversationTurn(enhancedOptions.context
2086
- ?.sessionId, enhancedOptions.context
2087
- ?.userId, options.input.text, fallbackAccumulatedContent);
2088
- logger.debug("Fallback stream conversation turn stored", {
2089
- sessionId: enhancedOptions.context
2090
- ?.sessionId,
2091
- userInputLength: options.input.text.length,
2092
- responseLength: fallbackAccumulatedContent.length,
2093
- });
2094
- }
2095
- catch (error) {
2096
- logger.warn("Failed to store fallback stream conversation turn", {
2097
- error: error instanceof Error ? error.message : String(error),
2098
- });
2099
- }
2100
- }
2101
- }
2102
- })(this);
2103
- const responseTime = Date.now() - startTime;
2104
- // Emit stream completion event for fallback (NeuroLink format - enhanced with content)
2105
- this.emitter.emit("stream:end", {
2106
- provider: providerName,
1803
+ this.emitter.emit("message", `Starting ${options.provider || "auto"} stream...`);
1804
+ }
1805
+ /**
1806
+ * Create MCP stream
1807
+ */
1808
+ async createMCPStream(options) {
1809
+ // Simplified placeholder - in the actual implementation this would contain the complex MCP stream logic
1810
+ const providerName = await getBestProvider(options.provider);
1811
+ const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
1812
+ this);
1813
+ // Enable tool execution for the provider using BaseProvider method
1814
+ provider.setupToolExecutor({
1815
+ customTools: this.getCustomTools(),
1816
+ executeTool: this.executeTool.bind(this),
1817
+ }, "NeuroLink.createMCPStream");
1818
+ const streamResult = await provider.stream(options);
1819
+ return { stream: streamResult.stream, provider: providerName };
1820
+ }
1821
+ /**
1822
+ * Process stream result
1823
+ */
1824
+ async processStreamResult(_stream, _options, _factoryResult) {
1825
+ // Simplified placeholder - in the actual implementation this would process the stream
1826
+ return {
1827
+ content: "",
1828
+ usage: undefined,
1829
+ finishReason: "stop",
1830
+ toolCalls: [],
1831
+ toolResults: [],
1832
+ analytics: undefined,
1833
+ evaluation: undefined,
1834
+ };
1835
+ }
1836
+ /**
1837
+ * Emit stream end events
1838
+ */
1839
+ emitStreamEndEvents(streamResult) {
1840
+ this.emitter.emit("stream:end", {
1841
+ responseTime: Date.now(),
1842
+ timestamp: Date.now(),
1843
+ });
1844
+ this.emitter.emit("response:end", streamResult.content || "");
1845
+ }
1846
+ /**
1847
+ * Create stream response
1848
+ */
1849
+ createStreamResponse(streamResult, stream, config) {
1850
+ return {
1851
+ stream,
1852
+ provider: config.providerName,
1853
+ model: config.options.model,
1854
+ usage: streamResult.usage,
1855
+ finishReason: streamResult.finishReason,
1856
+ toolCalls: streamResult.toolCalls,
1857
+ toolResults: streamResult.toolResults,
1858
+ analytics: streamResult.analytics,
1859
+ evaluation: streamResult.evaluation,
1860
+ metadata: {
1861
+ streamId: config.streamId,
1862
+ startTime: config.startTime,
1863
+ responseTime: config.responseTime,
1864
+ fallback: config.fallback || false,
1865
+ },
1866
+ };
1867
+ }
1868
+ /**
1869
+ * Handle stream error with fallback
1870
+ */
1871
+ async handleStreamError(error, options, startTime, streamId, _enhancedOptions, _factoryResult) {
1872
+ logger.error("Stream generation failed, attempting fallback", {
1873
+ error: error instanceof Error ? error.message : String(error),
1874
+ });
1875
+ const responseTime = Date.now() - startTime;
1876
+ const providerName = await getBestProvider(options.provider);
1877
+ const provider = await AIProviderFactory.createProvider(providerName, options.model, false);
1878
+ const fallbackStream = await provider.stream({
1879
+ input: { text: options.input.text },
1880
+ model: options.model,
1881
+ temperature: options.temperature,
1882
+ maxTokens: options.maxTokens,
1883
+ });
1884
+ return {
1885
+ stream: fallbackStream.stream,
1886
+ provider: providerName,
1887
+ model: options.model,
1888
+ usage: fallbackStream.usage,
1889
+ finishReason: fallbackStream.finishReason || "stop",
1890
+ toolCalls: fallbackStream.toolCalls || [],
1891
+ toolResults: fallbackStream.toolResults || [],
1892
+ analytics: fallbackStream.analytics,
1893
+ evaluation: fallbackStream.evaluation,
1894
+ metadata: {
1895
+ streamId,
1896
+ startTime,
2107
1897
  responseTime,
2108
1898
  fallback: true,
2109
- result: { content: fallbackAccumulatedContent }, // Enhanced: include accumulated content
2110
- });
2111
- // ADD: Bedrock-compatible response:end event with full response
2112
- this.emitter.emit("response:end", fallbackAccumulatedContent);
2113
- // ADD: Bedrock-compatible message event
2114
- this.emitter.emit("message", `Fallback stream completed in ${responseTime}ms (${fallbackAccumulatedContent.length} chars)`);
2115
- return {
2116
- stream: fallbackProcessedStream,
2117
- provider: providerName,
2118
- model: options.model,
2119
- usage: streamResult.usage,
2120
- finishReason: streamResult.finishReason,
2121
- toolCalls: streamResult.toolCalls,
2122
- toolResults: streamResult.toolResults,
2123
- analytics: streamResult.analytics,
2124
- evaluation: streamResult.evaluation
2125
- ? {
2126
- ...streamResult.evaluation,
2127
- // Include evaluationDomain in fallback stream
2128
- evaluationDomain: streamResult.evaluation
2129
- ?.evaluationDomain ??
2130
- enhancedOptions.evaluationDomain ??
2131
- factoryResult.domainType,
2132
- }
2133
- : undefined,
2134
- metadata: {
2135
- streamId: `neurolink-${Date.now()}`,
2136
- startTime,
2137
- responseTime,
2138
- fallback: true,
2139
- },
2140
- };
2141
- }
1899
+ },
1900
+ };
2142
1901
  }
2143
1902
  /**
2144
1903
  * Get the EventEmitter instance to listen to NeuroLink events for real-time monitoring and debugging.
@@ -2575,6 +2334,9 @@ export class NeuroLink {
2575
2334
  circuitBreakerState: circuitBreaker?.getState(),
2576
2335
  });
2577
2336
  // Execute with circuit breaker, timeout, and retry logic
2337
+ if (!circuitBreaker) {
2338
+ throw new Error(`Circuit breaker not initialized for tool: ${toolName}`);
2339
+ }
2578
2340
  const result = await circuitBreaker.execute(async () => {
2579
2341
  return await withRetry(async () => {
2580
2342
  return await withTimeout(this.executeToolInternal(toolName, params, finalOptions), finalOptions.timeout, ErrorFactory.toolTimeout(toolName, finalOptions.timeout));