@juspay/neurolink 7.29.2 → 7.29.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/cli/commands/config.d.ts +83 -83
- package/dist/cli/commands/mcp.js +39 -9
- package/dist/cli/commands/models.js +25 -21
- package/dist/cli/commands/ollama.js +2 -2
- package/dist/cli/factories/commandFactory.d.ts +8 -0
- package/dist/cli/factories/commandFactory.js +65 -65
- package/dist/cli/factories/ollamaCommandFactory.js +3 -1
- package/dist/cli/factories/sagemakerCommandFactory.js +3 -2
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +11 -11
- package/dist/cli/utils/envManager.js +5 -5
- package/dist/cli/utils/ollamaUtils.d.ts +12 -0
- package/dist/cli/utils/ollamaUtils.js +58 -42
- package/dist/config/configManager.js +5 -2
- package/dist/core/analytics.d.ts +2 -24
- package/dist/core/analytics.js +12 -17
- package/dist/core/baseProvider.d.ts +30 -1
- package/dist/core/baseProvider.js +180 -198
- package/dist/core/dynamicModels.d.ts +4 -4
- package/dist/core/dynamicModels.js +7 -7
- package/dist/core/evaluation.d.ts +9 -9
- package/dist/core/evaluation.js +117 -65
- package/dist/core/evaluationProviders.d.ts +18 -2
- package/dist/core/evaluationProviders.js +15 -13
- package/dist/core/modelConfiguration.d.ts +63 -0
- package/dist/core/modelConfiguration.js +354 -290
- package/dist/core/streamAnalytics.d.ts +10 -5
- package/dist/core/streamAnalytics.js +10 -10
- package/dist/core/types.d.ts +19 -109
- package/dist/core/types.js +13 -0
- package/dist/factories/providerFactory.js +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/lib/config/configManager.js +5 -2
- package/dist/lib/core/analytics.d.ts +2 -24
- package/dist/lib/core/analytics.js +12 -17
- package/dist/lib/core/baseProvider.d.ts +30 -1
- package/dist/lib/core/baseProvider.js +180 -198
- package/dist/lib/core/dynamicModels.js +7 -7
- package/dist/lib/core/evaluation.d.ts +9 -9
- package/dist/lib/core/evaluation.js +117 -65
- package/dist/lib/core/evaluationProviders.d.ts +18 -2
- package/dist/lib/core/evaluationProviders.js +15 -13
- package/dist/lib/core/modelConfiguration.d.ts +63 -0
- package/dist/lib/core/modelConfiguration.js +354 -290
- package/dist/lib/core/streamAnalytics.d.ts +10 -5
- package/dist/lib/core/streamAnalytics.js +10 -10
- package/dist/lib/core/types.d.ts +19 -109
- package/dist/lib/core/types.js +13 -0
- package/dist/lib/factories/providerFactory.js +1 -1
- package/dist/lib/index.d.ts +2 -1
- package/dist/lib/mcp/externalServerManager.js +15 -6
- package/dist/lib/mcp/factory.js +1 -1
- package/dist/lib/mcp/index.d.ts +1 -1
- package/dist/lib/mcp/index.js +1 -1
- package/dist/lib/mcp/mcpCircuitBreaker.js +5 -1
- package/dist/lib/mcp/mcpClientFactory.js +3 -0
- package/dist/lib/mcp/registry.d.ts +3 -3
- package/dist/lib/mcp/registry.js +3 -3
- package/dist/lib/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
- package/dist/lib/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
- package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -1
- package/dist/lib/mcp/toolDiscoveryService.js +8 -2
- package/dist/lib/mcp/toolRegistry.js +4 -4
- package/dist/lib/middleware/builtin/analytics.js +4 -4
- package/dist/lib/middleware/builtin/guardrails.js +2 -2
- package/dist/lib/middleware/registry.js +11 -2
- package/dist/lib/models/modelRegistry.d.ts +1 -1
- package/dist/lib/models/modelRegistry.js +3 -3
- package/dist/lib/models/modelResolver.d.ts +1 -1
- package/dist/lib/models/modelResolver.js +2 -2
- package/dist/lib/neurolink.d.ts +116 -0
- package/dist/lib/neurolink.js +716 -922
- package/dist/lib/providers/amazonSagemaker.d.ts +1 -1
- package/dist/lib/providers/amazonSagemaker.js +12 -3
- package/dist/lib/providers/anthropic.d.ts +1 -1
- package/dist/lib/providers/anthropic.js +7 -6
- package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
- package/dist/lib/providers/anthropicBaseProvider.js +4 -3
- package/dist/lib/providers/azureOpenai.d.ts +1 -1
- package/dist/lib/providers/azureOpenai.js +1 -1
- package/dist/lib/providers/googleAiStudio.d.ts +1 -1
- package/dist/lib/providers/googleAiStudio.js +2 -2
- package/dist/lib/providers/googleVertex.d.ts +40 -0
- package/dist/lib/providers/googleVertex.js +330 -274
- package/dist/lib/providers/huggingFace.js +1 -1
- package/dist/lib/providers/mistral.d.ts +1 -1
- package/dist/lib/providers/mistral.js +2 -2
- package/dist/lib/providers/ollama.d.ts +4 -0
- package/dist/lib/providers/ollama.js +38 -18
- package/dist/lib/providers/openAI.d.ts +1 -1
- package/dist/lib/providers/openAI.js +2 -2
- package/dist/lib/providers/sagemaker/adaptive-semaphore.js +7 -4
- package/dist/lib/providers/sagemaker/client.js +13 -3
- package/dist/lib/providers/sagemaker/config.js +5 -1
- package/dist/lib/providers/sagemaker/detection.js +19 -9
- package/dist/lib/providers/sagemaker/errors.d.ts +8 -1
- package/dist/lib/providers/sagemaker/errors.js +103 -20
- package/dist/lib/providers/sagemaker/language-model.d.ts +3 -3
- package/dist/lib/providers/sagemaker/language-model.js +4 -4
- package/dist/lib/providers/sagemaker/parsers.js +14 -6
- package/dist/lib/providers/sagemaker/streaming.js +14 -3
- package/dist/lib/providers/sagemaker/types.d.ts +1 -1
- package/dist/lib/proxy/awsProxyIntegration.js +1 -1
- package/dist/lib/sdk/toolRegistration.d.ts +1 -1
- package/dist/lib/types/cli.d.ts +80 -8
- package/dist/lib/types/contextTypes.js +2 -2
- package/dist/lib/types/generateTypes.d.ts +4 -6
- package/dist/lib/types/providers.d.ts +81 -19
- package/dist/lib/types/providers.js +6 -6
- package/dist/lib/types/streamTypes.d.ts +4 -6
- package/dist/lib/types/typeAliases.d.ts +1 -1
- package/dist/lib/utils/analyticsUtils.d.ts +33 -0
- package/dist/lib/utils/analyticsUtils.js +76 -0
- package/dist/lib/utils/errorHandling.js +4 -1
- package/dist/lib/utils/evaluationUtils.d.ts +27 -0
- package/dist/lib/utils/evaluationUtils.js +131 -0
- package/dist/lib/utils/optionsUtils.js +10 -1
- package/dist/lib/utils/performance.d.ts +1 -1
- package/dist/lib/utils/performance.js +15 -3
- package/dist/lib/utils/providerHealth.d.ts +48 -0
- package/dist/lib/utils/providerHealth.js +199 -254
- package/dist/lib/utils/providerUtils.js +2 -2
- package/dist/lib/utils/timeout.js +8 -3
- package/dist/mcp/externalServerManager.js +15 -6
- package/dist/mcp/factory.js +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/mcpCircuitBreaker.js +5 -1
- package/dist/mcp/mcpClientFactory.js +3 -0
- package/dist/mcp/registry.d.ts +3 -3
- package/dist/mcp/registry.js +3 -3
- package/dist/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
- package/dist/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
- package/dist/mcp/servers/utilities/utilityServer.js +1 -1
- package/dist/mcp/toolDiscoveryService.js +8 -2
- package/dist/mcp/toolRegistry.js +4 -4
- package/dist/middleware/builtin/analytics.js +4 -4
- package/dist/middleware/builtin/guardrails.js +2 -2
- package/dist/middleware/registry.js +11 -2
- package/dist/models/modelRegistry.d.ts +1 -1
- package/dist/models/modelRegistry.js +3 -3
- package/dist/models/modelResolver.d.ts +1 -1
- package/dist/models/modelResolver.js +2 -2
- package/dist/neurolink.d.ts +116 -0
- package/dist/neurolink.js +716 -922
- package/dist/providers/amazonSagemaker.d.ts +1 -1
- package/dist/providers/amazonSagemaker.js +12 -3
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +7 -6
- package/dist/providers/anthropicBaseProvider.d.ts +1 -1
- package/dist/providers/anthropicBaseProvider.js +4 -3
- package/dist/providers/azureOpenai.d.ts +1 -1
- package/dist/providers/azureOpenai.js +1 -1
- package/dist/providers/googleAiStudio.d.ts +1 -1
- package/dist/providers/googleAiStudio.js +2 -2
- package/dist/providers/googleVertex.d.ts +40 -0
- package/dist/providers/googleVertex.js +330 -274
- package/dist/providers/huggingFace.js +1 -1
- package/dist/providers/mistral.d.ts +1 -1
- package/dist/providers/mistral.js +2 -2
- package/dist/providers/ollama.d.ts +4 -0
- package/dist/providers/ollama.js +38 -18
- package/dist/providers/openAI.d.ts +1 -1
- package/dist/providers/openAI.js +2 -2
- package/dist/providers/sagemaker/adaptive-semaphore.js +7 -4
- package/dist/providers/sagemaker/client.js +13 -3
- package/dist/providers/sagemaker/config.js +5 -1
- package/dist/providers/sagemaker/detection.js +19 -9
- package/dist/providers/sagemaker/errors.d.ts +8 -1
- package/dist/providers/sagemaker/errors.js +103 -20
- package/dist/providers/sagemaker/language-model.d.ts +3 -3
- package/dist/providers/sagemaker/language-model.js +4 -4
- package/dist/providers/sagemaker/parsers.js +14 -6
- package/dist/providers/sagemaker/streaming.js +14 -3
- package/dist/providers/sagemaker/types.d.ts +1 -1
- package/dist/proxy/awsProxyIntegration.js +1 -1
- package/dist/sdk/toolRegistration.d.ts +1 -1
- package/dist/types/cli.d.ts +80 -8
- package/dist/types/contextTypes.js +2 -2
- package/dist/types/generateTypes.d.ts +4 -6
- package/dist/types/providers.d.ts +81 -19
- package/dist/types/providers.js +6 -6
- package/dist/types/streamTypes.d.ts +4 -6
- package/dist/types/typeAliases.d.ts +1 -1
- package/dist/utils/analyticsUtils.d.ts +33 -0
- package/dist/utils/analyticsUtils.js +76 -0
- package/dist/utils/errorHandling.js +4 -1
- package/dist/utils/evaluationUtils.d.ts +27 -0
- package/dist/utils/evaluationUtils.js +131 -0
- package/dist/utils/optionsUtils.js +10 -1
- package/dist/utils/performance.d.ts +1 -1
- package/dist/utils/performance.js +15 -3
- package/dist/utils/providerHealth.d.ts +48 -0
- package/dist/utils/providerHealth.js +199 -254
- package/dist/utils/providerUtils.js +2 -2
- package/dist/utils/timeout.js +8 -3
- package/package.json +1 -1
package/dist/neurolink.js
CHANGED
|
@@ -10,7 +10,7 @@ import { config as dotenvConfig } from "dotenv";
|
|
|
10
10
|
try {
|
|
11
11
|
dotenvConfig(); // Load .env from current working directory
|
|
12
12
|
}
|
|
13
|
-
catch
|
|
13
|
+
catch {
|
|
14
14
|
// Environment variables should be set externally in production
|
|
15
15
|
}
|
|
16
16
|
import { AIProviderFactory } from "./core/factory.js";
|
|
@@ -102,42 +102,50 @@ export class NeuroLink {
|
|
|
102
102
|
* @throws {Error} When external server manager initialization fails
|
|
103
103
|
*/
|
|
104
104
|
constructor(config) {
|
|
105
|
-
// 🚀 EXHAUSTIVE LOGGING POINT C001: CONSTRUCTOR ENTRY
|
|
106
105
|
const constructorStartTime = Date.now();
|
|
107
106
|
const constructorHrTimeStart = process.hrtime.bigint();
|
|
108
107
|
const constructorId = `neurolink-constructor-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
108
|
+
this.logConstructorStart(constructorId, constructorStartTime, constructorHrTimeStart, config);
|
|
109
|
+
this.initializeProviderRegistry(constructorId, constructorStartTime, constructorHrTimeStart);
|
|
110
|
+
this.initializeConversationMemory(config, constructorId, constructorStartTime, constructorHrTimeStart);
|
|
111
|
+
this.initializeExternalServerManager(constructorId, constructorStartTime, constructorHrTimeStart);
|
|
112
|
+
this.logConstructorComplete(constructorId, constructorStartTime, constructorHrTimeStart);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Log constructor start with comprehensive environment analysis
|
|
116
|
+
*/
|
|
117
|
+
logConstructorStart(constructorId, constructorStartTime, constructorHrTimeStart, config) {
|
|
109
118
|
logger.debug(`[NeuroLink] 🏗️ LOG_POINT_C001_CONSTRUCTOR_START`, {
|
|
110
119
|
logPoint: "C001_CONSTRUCTOR_START",
|
|
111
120
|
constructorId,
|
|
112
121
|
timestamp: new Date().toISOString(),
|
|
113
122
|
constructorStartTime,
|
|
114
123
|
constructorHrTimeStart: constructorHrTimeStart.toString(),
|
|
115
|
-
// Configuration analysis
|
|
116
124
|
hasConfig: !!config,
|
|
117
125
|
configType: typeof config,
|
|
118
126
|
configKeys: config ? Object.keys(config) : [],
|
|
119
127
|
configSize: config ? JSON.stringify(config).length : 0,
|
|
120
|
-
// Conversation memory config analysis
|
|
121
128
|
hasConversationMemoryConfig: !!config?.conversationMemory,
|
|
122
129
|
conversationMemoryEnabled: config?.conversationMemory?.enabled || false,
|
|
123
130
|
conversationMemoryKeys: config?.conversationMemory
|
|
124
131
|
? Object.keys(config.conversationMemory)
|
|
125
132
|
: [],
|
|
126
|
-
// Environment context
|
|
127
133
|
nodeVersion: process.version,
|
|
128
134
|
platform: process.platform,
|
|
129
135
|
arch: process.arch,
|
|
130
136
|
nodeEnv: process.env.NODE_ENV || "UNKNOWN",
|
|
131
|
-
// Memory and performance baseline
|
|
132
137
|
memoryUsage: process.memoryUsage(),
|
|
133
138
|
cpuUsage: process.cpuUsage(),
|
|
134
139
|
uptime: process.uptime(),
|
|
135
|
-
// Process PID and parent info
|
|
136
140
|
pid: process.pid,
|
|
137
141
|
ppid: process.ppid,
|
|
138
142
|
message: "NeuroLink constructor initialization starting with comprehensive environment analysis",
|
|
139
143
|
});
|
|
140
|
-
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Initialize provider registry with security settings
|
|
147
|
+
*/
|
|
148
|
+
initializeProviderRegistry(constructorId, constructorStartTime, constructorHrTimeStart) {
|
|
141
149
|
const registrySetupStartTime = process.hrtime.bigint();
|
|
142
150
|
logger.debug(`[NeuroLink] 🏗️ LOG_POINT_C002_PROVIDER_REGISTRY_SETUP_START`, {
|
|
143
151
|
logPoint: "C002_PROVIDER_REGISTRY_SETUP_START",
|
|
@@ -148,11 +156,8 @@ export class NeuroLink {
|
|
|
148
156
|
registrySetupStartTimeNs: registrySetupStartTime.toString(),
|
|
149
157
|
message: "Starting ProviderRegistry configuration for security",
|
|
150
158
|
});
|
|
151
|
-
// SDK always disables manual MCP config for security
|
|
152
159
|
try {
|
|
153
|
-
ProviderRegistry.setOptions({
|
|
154
|
-
enableManualMCP: false,
|
|
155
|
-
});
|
|
160
|
+
ProviderRegistry.setOptions({ enableManualMCP: false });
|
|
156
161
|
const registrySetupEndTime = process.hrtime.bigint();
|
|
157
162
|
const registrySetupDurationNs = registrySetupEndTime - registrySetupStartTime;
|
|
158
163
|
logger.debug(`[NeuroLink] ✅ LOG_POINT_C003_PROVIDER_REGISTRY_SETUP_SUCCESS`, {
|
|
@@ -185,7 +190,11 @@ export class NeuroLink {
|
|
|
185
190
|
});
|
|
186
191
|
throw error;
|
|
187
192
|
}
|
|
188
|
-
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Initialize conversation memory if enabled
|
|
196
|
+
*/
|
|
197
|
+
initializeConversationMemory(config, constructorId, constructorStartTime, constructorHrTimeStart) {
|
|
189
198
|
if (config?.conversationMemory?.enabled) {
|
|
190
199
|
const memoryInitStartTime = process.hrtime.bigint();
|
|
191
200
|
logger.debug(`[NeuroLink] 🧠 LOG_POINT_C005_MEMORY_INIT_START`, {
|
|
@@ -195,7 +204,6 @@ export class NeuroLink {
|
|
|
195
204
|
elapsedMs: Date.now() - constructorStartTime,
|
|
196
205
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
|
197
206
|
memoryInitStartTimeNs: memoryInitStartTime.toString(),
|
|
198
|
-
// Detailed memory config analysis
|
|
199
207
|
memoryConfig: {
|
|
200
208
|
enabled: config.conversationMemory.enabled,
|
|
201
209
|
maxSessions: config.conversationMemory.maxSessions,
|
|
@@ -222,12 +230,10 @@ export class NeuroLink {
|
|
|
222
230
|
memoryInitDurationMs: Number(memoryInitDurationNs) / 1000000,
|
|
223
231
|
memoryManagerCreateDurationNs: memoryManagerCreateDurationNs.toString(),
|
|
224
232
|
memoryManagerCreateDurationMs: Number(memoryManagerCreateDurationNs) / 1000000,
|
|
225
|
-
// Final memory configuration
|
|
226
233
|
finalMemoryConfig: {
|
|
227
234
|
maxSessions: memoryConfig.maxSessions,
|
|
228
235
|
maxTurnsPerSession: memoryConfig.maxTurnsPerSession,
|
|
229
236
|
},
|
|
230
|
-
// Memory usage after initialization
|
|
231
237
|
memoryUsageAfterInit: process.memoryUsage(),
|
|
232
238
|
message: "NeuroLink initialized with conversation memory successfully",
|
|
233
239
|
});
|
|
@@ -272,7 +278,11 @@ export class NeuroLink {
|
|
|
272
278
|
message: "Conversation memory not enabled - skipping initialization",
|
|
273
279
|
});
|
|
274
280
|
}
|
|
275
|
-
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Initialize external server manager with event handlers
|
|
284
|
+
*/
|
|
285
|
+
initializeExternalServerManager(constructorId, constructorStartTime, constructorHrTimeStart) {
|
|
276
286
|
const externalServerInitStartTime = process.hrtime.bigint();
|
|
277
287
|
logger.debug(`[NeuroLink] 🌐 LOG_POINT_C009_EXTERNAL_SERVER_INIT_START`, {
|
|
278
288
|
logPoint: "C009_EXTERNAL_SERVER_INIT_START",
|
|
@@ -293,14 +303,13 @@ export class NeuroLink {
|
|
|
293
303
|
message: "Starting external server manager initialization",
|
|
294
304
|
});
|
|
295
305
|
try {
|
|
296
|
-
// Initialize external server manager with main registry integration
|
|
297
306
|
this.externalServerManager = new ExternalServerManager({
|
|
298
307
|
maxServers: 20,
|
|
299
308
|
defaultTimeout: 15000,
|
|
300
309
|
enableAutoRestart: true,
|
|
301
310
|
enablePerformanceMonitoring: true,
|
|
302
311
|
}, {
|
|
303
|
-
enableMainRegistryIntegration: true,
|
|
312
|
+
enableMainRegistryIntegration: true,
|
|
304
313
|
});
|
|
305
314
|
const externalServerInitEndTime = process.hrtime.bigint();
|
|
306
315
|
const externalServerInitDurationNs = externalServerInitEndTime - externalServerInitStartTime;
|
|
@@ -315,93 +324,7 @@ export class NeuroLink {
|
|
|
315
324
|
hasExternalServerManager: !!this.externalServerManager,
|
|
316
325
|
message: "External server manager initialized successfully",
|
|
317
326
|
});
|
|
318
|
-
|
|
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
|
-
});
|
|
327
|
+
this.setupExternalServerEventHandlers(constructorId, constructorStartTime, constructorHrTimeStart);
|
|
405
328
|
}
|
|
406
329
|
catch (error) {
|
|
407
330
|
const externalServerInitErrorTime = process.hrtime.bigint();
|
|
@@ -421,7 +344,99 @@ export class NeuroLink {
|
|
|
421
344
|
});
|
|
422
345
|
throw error;
|
|
423
346
|
}
|
|
424
|
-
|
|
347
|
+
}
|
|
348
|
+
/**
|
|
349
|
+
* Setup event handlers for external server manager
|
|
350
|
+
*/
|
|
351
|
+
setupExternalServerEventHandlers(constructorId, constructorStartTime, constructorHrTimeStart) {
|
|
352
|
+
const eventHandlerSetupStartTime = process.hrtime.bigint();
|
|
353
|
+
logger.debug(`[NeuroLink] 🔗 LOG_POINT_C011_EVENT_HANDLER_SETUP_START`, {
|
|
354
|
+
logPoint: "C011_EVENT_HANDLER_SETUP_START",
|
|
355
|
+
constructorId,
|
|
356
|
+
timestamp: new Date().toISOString(),
|
|
357
|
+
elapsedMs: Date.now() - constructorStartTime,
|
|
358
|
+
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
|
359
|
+
eventHandlerSetupStartTimeNs: eventHandlerSetupStartTime.toString(),
|
|
360
|
+
message: "Setting up external server event handlers",
|
|
361
|
+
});
|
|
362
|
+
this.externalServerManager.on("connected", (event) => {
|
|
363
|
+
logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_CONNECTED`, {
|
|
364
|
+
constructorId,
|
|
365
|
+
eventType: "connected",
|
|
366
|
+
event,
|
|
367
|
+
timestamp: new Date().toISOString(),
|
|
368
|
+
message: "External MCP server connected event received",
|
|
369
|
+
});
|
|
370
|
+
this.emitter.emit("externalMCP:serverConnected", event);
|
|
371
|
+
});
|
|
372
|
+
this.externalServerManager.on("disconnected", (event) => {
|
|
373
|
+
logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_DISCONNECTED`, {
|
|
374
|
+
constructorId,
|
|
375
|
+
eventType: "disconnected",
|
|
376
|
+
event,
|
|
377
|
+
timestamp: new Date().toISOString(),
|
|
378
|
+
message: "External MCP server disconnected event received",
|
|
379
|
+
});
|
|
380
|
+
this.emitter.emit("externalMCP:serverDisconnected", event);
|
|
381
|
+
});
|
|
382
|
+
this.externalServerManager.on("failed", (event) => {
|
|
383
|
+
logger.warn(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_FAILED`, {
|
|
384
|
+
constructorId,
|
|
385
|
+
eventType: "failed",
|
|
386
|
+
event,
|
|
387
|
+
timestamp: new Date().toISOString(),
|
|
388
|
+
message: "External MCP server failed event received",
|
|
389
|
+
});
|
|
390
|
+
this.emitter.emit("externalMCP:serverFailed", event);
|
|
391
|
+
});
|
|
392
|
+
this.externalServerManager.on("toolDiscovered", (event) => {
|
|
393
|
+
logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_DISCOVERED`, {
|
|
394
|
+
constructorId,
|
|
395
|
+
eventType: "toolDiscovered",
|
|
396
|
+
toolName: event.toolName,
|
|
397
|
+
serverId: event.serverId,
|
|
398
|
+
timestamp: new Date().toISOString(),
|
|
399
|
+
message: "External MCP tool discovered event received",
|
|
400
|
+
});
|
|
401
|
+
this.emitter.emit("externalMCP:toolDiscovered", event);
|
|
402
|
+
});
|
|
403
|
+
this.externalServerManager.on("toolRemoved", (event) => {
|
|
404
|
+
logger.debug(`[NeuroLink] 🔗 EXTERNAL_SERVER_EVENT_TOOL_REMOVED`, {
|
|
405
|
+
constructorId,
|
|
406
|
+
eventType: "toolRemoved",
|
|
407
|
+
toolName: event.toolName,
|
|
408
|
+
serverId: event.serverId,
|
|
409
|
+
timestamp: new Date().toISOString(),
|
|
410
|
+
message: "External MCP tool removed event received",
|
|
411
|
+
});
|
|
412
|
+
this.emitter.emit("externalMCP:toolRemoved", event);
|
|
413
|
+
this.unregisterExternalMCPToolFromRegistry(event.toolName);
|
|
414
|
+
});
|
|
415
|
+
const eventHandlerSetupEndTime = process.hrtime.bigint();
|
|
416
|
+
const eventHandlerSetupDurationNs = eventHandlerSetupEndTime - eventHandlerSetupStartTime;
|
|
417
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_C012_EVENT_HANDLER_SETUP_SUCCESS`, {
|
|
418
|
+
logPoint: "C012_EVENT_HANDLER_SETUP_SUCCESS",
|
|
419
|
+
constructorId,
|
|
420
|
+
timestamp: new Date().toISOString(),
|
|
421
|
+
elapsedMs: Date.now() - constructorStartTime,
|
|
422
|
+
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
|
423
|
+
eventHandlerSetupDurationNs: eventHandlerSetupDurationNs.toString(),
|
|
424
|
+
eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) / 1000000,
|
|
425
|
+
eventHandlersCount: 5,
|
|
426
|
+
eventHandlerTypes: [
|
|
427
|
+
"connected",
|
|
428
|
+
"disconnected",
|
|
429
|
+
"failed",
|
|
430
|
+
"toolDiscovered",
|
|
431
|
+
"toolRemoved",
|
|
432
|
+
],
|
|
433
|
+
message: "Event handlers set up successfully",
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* Log constructor completion with final state summary
|
|
438
|
+
*/
|
|
439
|
+
logConstructorComplete(constructorId, constructorStartTime, constructorHrTimeStart) {
|
|
425
440
|
const constructorEndTime = process.hrtime.bigint();
|
|
426
441
|
const constructorDurationNs = constructorEndTime - constructorHrTimeStart;
|
|
427
442
|
logger.info(`[NeuroLink] 🏁 LOG_POINT_C014_CONSTRUCTOR_COMPLETE`, {
|
|
@@ -431,7 +446,6 @@ export class NeuroLink {
|
|
|
431
446
|
constructorDurationNs: constructorDurationNs.toString(),
|
|
432
447
|
constructorDurationMs: Number(constructorDurationNs) / 1000000,
|
|
433
448
|
totalElapsedMs: Date.now() - constructorStartTime,
|
|
434
|
-
// Final state summary
|
|
435
449
|
finalState: {
|
|
436
450
|
hasConversationMemory: !!this.conversationMemory,
|
|
437
451
|
hasExternalServerManager: !!this.externalServerManager,
|
|
@@ -440,7 +454,6 @@ export class NeuroLink {
|
|
|
440
454
|
toolCircuitBreakersCount: this.toolCircuitBreakers.size,
|
|
441
455
|
toolExecutionMetricsCount: this.toolExecutionMetrics.size,
|
|
442
456
|
},
|
|
443
|
-
// Final memory usage
|
|
444
457
|
finalMemoryUsage: process.memoryUsage(),
|
|
445
458
|
finalCpuUsage: process.cpuUsage(),
|
|
446
459
|
message: "NeuroLink constructor completed successfully with all components initialized",
|
|
@@ -451,10 +464,34 @@ export class NeuroLink {
|
|
|
451
464
|
* Uses isolated async context to prevent hanging
|
|
452
465
|
*/
|
|
453
466
|
async initializeMCP() {
|
|
454
|
-
// 🚀 EXHAUSTIVE LOGGING POINT M001: MCP INITIALIZATION ENTRY CHECK
|
|
455
467
|
const mcpInitId = `mcp-init-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
456
468
|
const mcpInitStartTime = Date.now();
|
|
457
469
|
const mcpInitHrTimeStart = process.hrtime.bigint();
|
|
470
|
+
this.logMCPInitStart(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
471
|
+
if (this.mcpInitialized) {
|
|
472
|
+
this.logMCPAlreadyInitialized(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
const MemoryManager = await this.importPerformanceManager(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
476
|
+
const startMemory = MemoryManager
|
|
477
|
+
? MemoryManager.getMemoryUsageMB()
|
|
478
|
+
: { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
|
|
479
|
+
try {
|
|
480
|
+
await this.performMCPInitialization(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart, startMemory);
|
|
481
|
+
this.mcpInitialized = true;
|
|
482
|
+
this.logMCPInitComplete(startMemory, MemoryManager, mcpInitStartTime);
|
|
483
|
+
}
|
|
484
|
+
catch (error) {
|
|
485
|
+
mcpLogger.warn("[NeuroLink] MCP initialization failed", {
|
|
486
|
+
error: error instanceof Error ? error.message : String(error),
|
|
487
|
+
});
|
|
488
|
+
// Continue without MCP - graceful degradation
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Log MCP initialization start
|
|
493
|
+
*/
|
|
494
|
+
logMCPInitStart(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
458
495
|
logger.debug(`[NeuroLink] 🔧 LOG_POINT_M001_MCP_INIT_ENTRY`, {
|
|
459
496
|
logPoint: "M001_MCP_INIT_ENTRY",
|
|
460
497
|
mcpInitId,
|
|
@@ -467,19 +504,25 @@ export class NeuroLink {
|
|
|
467
504
|
cpuUsage: process.cpuUsage(),
|
|
468
505
|
message: "MCP initialization entry point - checking if already initialized",
|
|
469
506
|
});
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Log MCP already initialized
|
|
510
|
+
*/
|
|
511
|
+
logMCPAlreadyInitialized(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
512
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_M002_MCP_ALREADY_INITIALIZED`, {
|
|
513
|
+
logPoint: "M002_MCP_ALREADY_INITIALIZED",
|
|
514
|
+
mcpInitId,
|
|
515
|
+
timestamp: new Date().toISOString(),
|
|
516
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
517
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
518
|
+
mcpInitialized: this.mcpInitialized,
|
|
519
|
+
message: "MCP already initialized - skipping initialization",
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Import performance manager with error handling
|
|
524
|
+
*/
|
|
525
|
+
async importPerformanceManager(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
483
526
|
const performanceImportStartTime = process.hrtime.bigint();
|
|
484
527
|
logger.debug(`[NeuroLink] 📊 LOG_POINT_M003_PERFORMANCE_IMPORT_START`, {
|
|
485
528
|
logPoint: "M003_PERFORMANCE_IMPORT_START",
|
|
@@ -490,13 +533,9 @@ export class NeuroLink {
|
|
|
490
533
|
performanceImportStartTimeNs: performanceImportStartTime.toString(),
|
|
491
534
|
message: "Starting MemoryManager import for performance tracking",
|
|
492
535
|
});
|
|
493
|
-
let MemoryManager;
|
|
494
|
-
let startMemory;
|
|
495
536
|
try {
|
|
496
|
-
// Track memory usage during MCP initialization
|
|
497
537
|
const moduleImport = await import("./utils/performance.js");
|
|
498
|
-
MemoryManager = moduleImport.MemoryManager;
|
|
499
|
-
startMemory = MemoryManager.getMemoryUsageMB();
|
|
538
|
+
const MemoryManager = moduleImport.MemoryManager;
|
|
500
539
|
const performanceImportEndTime = process.hrtime.bigint();
|
|
501
540
|
const performanceImportDurationNs = performanceImportEndTime - performanceImportStartTime;
|
|
502
541
|
logger.debug(`[NeuroLink] ✅ LOG_POINT_M004_PERFORMANCE_IMPORT_SUCCESS`, {
|
|
@@ -508,9 +547,9 @@ export class NeuroLink {
|
|
|
508
547
|
performanceImportDurationNs: performanceImportDurationNs.toString(),
|
|
509
548
|
performanceImportDurationMs: Number(performanceImportDurationNs) / 1000000,
|
|
510
549
|
hasMemoryManager: !!MemoryManager,
|
|
511
|
-
startMemory,
|
|
512
550
|
message: "MemoryManager imported successfully",
|
|
513
551
|
});
|
|
552
|
+
return MemoryManager;
|
|
514
553
|
}
|
|
515
554
|
catch (error) {
|
|
516
555
|
const performanceImportErrorTime = process.hrtime.bigint();
|
|
@@ -527,206 +566,218 @@ export class NeuroLink {
|
|
|
527
566
|
errorName: error instanceof Error ? error.name : "UnknownError",
|
|
528
567
|
message: "MemoryManager import failed - continuing without performance tracking",
|
|
529
568
|
});
|
|
530
|
-
|
|
531
|
-
startMemory = { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
|
|
569
|
+
return undefined;
|
|
532
570
|
}
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Perform main MCP initialization logic
|
|
574
|
+
*/
|
|
575
|
+
async performMCPInitialization(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart, startMemory) {
|
|
576
|
+
logger.info(`[NeuroLink] 🚀 LOG_POINT_M006_MCP_MAIN_INIT_START`, {
|
|
577
|
+
logPoint: "M006_MCP_MAIN_INIT_START",
|
|
578
|
+
mcpInitId,
|
|
579
|
+
timestamp: new Date().toISOString(),
|
|
580
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
581
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
582
|
+
startMemory,
|
|
583
|
+
message: "Starting isolated MCP initialization process",
|
|
584
|
+
});
|
|
585
|
+
mcpLogger.debug("[NeuroLink] Starting isolated MCP initialization...");
|
|
586
|
+
await this.initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
587
|
+
await this.initializeProviderRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
588
|
+
await this.registerDirectToolsServerInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
589
|
+
await this.loadMCPConfigurationInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart);
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Initialize tool registry with timeout protection
|
|
593
|
+
*/
|
|
594
|
+
async initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
595
|
+
const toolRegistryStartTime = process.hrtime.bigint();
|
|
596
|
+
const initTimeout = 3000;
|
|
597
|
+
logger.debug(`[NeuroLink] ⏱️ LOG_POINT_M007_TOOL_REGISTRY_TIMEOUT_SETUP`, {
|
|
598
|
+
logPoint: "M007_TOOL_REGISTRY_TIMEOUT_SETUP",
|
|
599
|
+
mcpInitId,
|
|
600
|
+
timestamp: new Date().toISOString(),
|
|
601
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
602
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
603
|
+
toolRegistryStartTimeNs: toolRegistryStartTime.toString(),
|
|
604
|
+
initTimeoutMs: initTimeout,
|
|
605
|
+
message: "Setting up tool registry initialization with timeout protection",
|
|
606
|
+
});
|
|
607
|
+
await Promise.race([
|
|
608
|
+
Promise.resolve(),
|
|
609
|
+
new Promise((_, reject) => {
|
|
610
|
+
setTimeout(() => reject(new Error("MCP initialization timeout")), initTimeout);
|
|
611
|
+
}),
|
|
612
|
+
]);
|
|
613
|
+
const toolRegistryEndTime = process.hrtime.bigint();
|
|
614
|
+
const toolRegistryDurationNs = toolRegistryEndTime - toolRegistryStartTime;
|
|
615
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_M008_TOOL_REGISTRY_SUCCESS`, {
|
|
616
|
+
logPoint: "M008_TOOL_REGISTRY_SUCCESS",
|
|
617
|
+
mcpInitId,
|
|
618
|
+
timestamp: new Date().toISOString(),
|
|
619
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
620
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
621
|
+
toolRegistryDurationNs: toolRegistryDurationNs.toString(),
|
|
622
|
+
toolRegistryDurationMs: Number(toolRegistryDurationNs) / 1000000,
|
|
623
|
+
message: "Tool registry initialization completed within timeout",
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Initialize provider registry
|
|
628
|
+
*/
|
|
629
|
+
async initializeProviderRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
630
|
+
const providerRegistryStartTime = process.hrtime.bigint();
|
|
631
|
+
logger.debug(`[NeuroLink] 🏭 LOG_POINT_M009_PROVIDER_REGISTRY_START`, {
|
|
632
|
+
logPoint: "M009_PROVIDER_REGISTRY_START",
|
|
633
|
+
mcpInitId,
|
|
634
|
+
timestamp: new Date().toISOString(),
|
|
635
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
636
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
637
|
+
providerRegistryStartTimeNs: providerRegistryStartTime.toString(),
|
|
638
|
+
message: "Starting provider registry registration with lazy loading",
|
|
639
|
+
});
|
|
640
|
+
await ProviderRegistry.registerAllProviders();
|
|
641
|
+
const providerRegistryEndTime = process.hrtime.bigint();
|
|
642
|
+
const providerRegistryDurationNs = providerRegistryEndTime - providerRegistryStartTime;
|
|
643
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_M010_PROVIDER_REGISTRY_SUCCESS`, {
|
|
644
|
+
logPoint: "M010_PROVIDER_REGISTRY_SUCCESS",
|
|
645
|
+
mcpInitId,
|
|
646
|
+
timestamp: new Date().toISOString(),
|
|
647
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
648
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
649
|
+
providerRegistryDurationNs: providerRegistryDurationNs.toString(),
|
|
650
|
+
providerRegistryDurationMs: Number(providerRegistryDurationNs) / 1000000,
|
|
651
|
+
message: "Provider registry registration completed successfully",
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
/**
|
|
655
|
+
* Register direct tools server
|
|
656
|
+
*/
|
|
657
|
+
async registerDirectToolsServerInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
658
|
+
const directToolsStartTime = process.hrtime.bigint();
|
|
659
|
+
logger.debug(`[NeuroLink] 🛠️ LOG_POINT_M011_DIRECT_TOOLS_START`, {
|
|
660
|
+
logPoint: "M011_DIRECT_TOOLS_START",
|
|
661
|
+
mcpInitId,
|
|
662
|
+
timestamp: new Date().toISOString(),
|
|
663
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
664
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
665
|
+
directToolsStartTimeNs: directToolsStartTime.toString(),
|
|
666
|
+
serverId: "neurolink-direct",
|
|
667
|
+
message: "Starting direct tools server registration",
|
|
668
|
+
});
|
|
533
669
|
try {
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
elapsedMs: Date.now() - mcpInitStartTime,
|
|
540
|
-
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
541
|
-
startMemory,
|
|
542
|
-
message: "Starting isolated MCP initialization process",
|
|
543
|
-
});
|
|
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",
|
|
670
|
+
await toolRegistry.registerServer("neurolink-direct", directToolsServer);
|
|
671
|
+
const directToolsSuccessTime = process.hrtime.bigint();
|
|
672
|
+
const directToolsDurationNs = directToolsSuccessTime - directToolsStartTime;
|
|
673
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_M012_DIRECT_TOOLS_SUCCESS`, {
|
|
674
|
+
logPoint: "M012_DIRECT_TOOLS_SUCCESS",
|
|
550
675
|
mcpInitId,
|
|
551
676
|
timestamp: new Date().toISOString(),
|
|
552
677
|
elapsedMs: Date.now() - mcpInitStartTime,
|
|
553
678
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
679
|
+
directToolsDurationNs: directToolsDurationNs.toString(),
|
|
680
|
+
directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
|
|
681
|
+
serverId: "neurolink-direct",
|
|
682
|
+
message: "Direct tools server registered successfully",
|
|
557
683
|
});
|
|
558
|
-
|
|
559
|
-
|
|
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",
|
|
569
|
-
mcpInitId,
|
|
570
|
-
timestamp: new Date().toISOString(),
|
|
571
|
-
elapsedMs: Date.now() - mcpInitStartTime,
|
|
572
|
-
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
573
|
-
toolRegistryDurationNs: toolRegistryDurationNs.toString(),
|
|
574
|
-
toolRegistryDurationMs: Number(toolRegistryDurationNs) / 1000000,
|
|
575
|
-
message: "Tool registry initialization completed within timeout",
|
|
684
|
+
mcpLogger.debug("[NeuroLink] Direct tools server registered successfully", {
|
|
685
|
+
serverId: "neurolink-direct",
|
|
576
686
|
});
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
687
|
+
}
|
|
688
|
+
catch (error) {
|
|
689
|
+
const directToolsErrorTime = process.hrtime.bigint();
|
|
690
|
+
const directToolsDurationNs = directToolsErrorTime - directToolsStartTime;
|
|
691
|
+
logger.warn(`[NeuroLink] ⚠️ LOG_POINT_M013_DIRECT_TOOLS_ERROR`, {
|
|
692
|
+
logPoint: "M013_DIRECT_TOOLS_ERROR",
|
|
581
693
|
mcpInitId,
|
|
582
694
|
timestamp: new Date().toISOString(),
|
|
583
695
|
elapsedMs: Date.now() - mcpInitStartTime,
|
|
584
696
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
585
|
-
|
|
586
|
-
|
|
697
|
+
directToolsDurationNs: directToolsDurationNs.toString(),
|
|
698
|
+
directToolsDurationMs: Number(directToolsDurationNs) / 1000000,
|
|
699
|
+
error: error instanceof Error ? error.message : String(error),
|
|
700
|
+
errorName: error instanceof Error ? error.name : "UnknownError",
|
|
701
|
+
errorStack: error instanceof Error ? error.stack : undefined,
|
|
702
|
+
serverId: "neurolink-direct",
|
|
703
|
+
message: "Direct tools server registration failed but continuing",
|
|
587
704
|
});
|
|
588
|
-
|
|
589
|
-
|
|
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",
|
|
594
|
-
mcpInitId,
|
|
595
|
-
timestamp: new Date().toISOString(),
|
|
596
|
-
elapsedMs: Date.now() - mcpInitStartTime,
|
|
597
|
-
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
598
|
-
providerRegistryDurationNs: providerRegistryDurationNs.toString(),
|
|
599
|
-
providerRegistryDurationMs: Number(providerRegistryDurationNs) / 1000000,
|
|
600
|
-
message: "Provider registry registration completed successfully",
|
|
705
|
+
mcpLogger.warn("[NeuroLink] Failed to register direct tools server", {
|
|
706
|
+
error: error instanceof Error ? error.message : String(error),
|
|
601
707
|
});
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Load MCP configuration from .mcp-config.json
|
|
712
|
+
*/
|
|
713
|
+
async loadMCPConfigurationInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
|
714
|
+
const mcpConfigStartTime = process.hrtime.bigint();
|
|
715
|
+
logger.debug(`[NeuroLink] 📄 LOG_POINT_M014_MCP_CONFIG_START`, {
|
|
716
|
+
logPoint: "M014_MCP_CONFIG_START",
|
|
717
|
+
mcpInitId,
|
|
718
|
+
timestamp: new Date().toISOString(),
|
|
719
|
+
elapsedMs: Date.now() - mcpInitStartTime,
|
|
720
|
+
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
721
|
+
mcpConfigStartTimeNs: mcpConfigStartTime.toString(),
|
|
722
|
+
hasExternalServerManager: !!this.externalServerManager,
|
|
723
|
+
message: "Starting MCP configuration loading from .mcp-config.json",
|
|
724
|
+
});
|
|
725
|
+
try {
|
|
726
|
+
const configResult = await this.externalServerManager.loadMCPConfiguration();
|
|
727
|
+
const mcpConfigSuccessTime = process.hrtime.bigint();
|
|
728
|
+
const mcpConfigDurationNs = mcpConfigSuccessTime - mcpConfigStartTime;
|
|
729
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_M015_MCP_CONFIG_SUCCESS`, {
|
|
730
|
+
logPoint: "M015_MCP_CONFIG_SUCCESS",
|
|
606
731
|
mcpInitId,
|
|
607
732
|
timestamp: new Date().toISOString(),
|
|
608
733
|
elapsedMs: Date.now() - mcpInitStartTime,
|
|
609
734
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
735
|
+
mcpConfigDurationNs: mcpConfigDurationNs.toString(),
|
|
736
|
+
mcpConfigDurationMs: Number(mcpConfigDurationNs) / 1000000,
|
|
737
|
+
serversLoaded: configResult.serversLoaded,
|
|
738
|
+
errorsCount: configResult.errors.length,
|
|
739
|
+
configResult: {
|
|
740
|
+
serversLoaded: configResult.serversLoaded,
|
|
741
|
+
errors: configResult.errors.map((err) => ({
|
|
742
|
+
message: err instanceof Error ? err.message : String(err),
|
|
743
|
+
name: err instanceof Error ? err.name : "UnknownError",
|
|
744
|
+
})),
|
|
745
|
+
},
|
|
746
|
+
message: "MCP configuration loaded successfully",
|
|
613
747
|
});
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
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",
|
|
633
|
-
});
|
|
634
|
-
}
|
|
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",
|
|
748
|
+
mcpLogger.debug("[NeuroLink] MCP configuration loaded successfully", {
|
|
749
|
+
serversLoaded: configResult.serversLoaded,
|
|
750
|
+
errors: configResult.errors.length,
|
|
667
751
|
});
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
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),
|
|
752
|
+
if (configResult.errors.length > 0) {
|
|
753
|
+
mcpLogger.warn("[NeuroLink] Some MCP servers failed to load", {
|
|
754
|
+
errors: configResult.errors,
|
|
707
755
|
});
|
|
708
756
|
}
|
|
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
757
|
}
|
|
725
|
-
catch (
|
|
726
|
-
mcpLogger.warn("[NeuroLink] MCP
|
|
727
|
-
error:
|
|
758
|
+
catch (configError) {
|
|
759
|
+
mcpLogger.warn("[NeuroLink] MCP configuration loading failed", {
|
|
760
|
+
error: configError instanceof Error
|
|
761
|
+
? configError.message
|
|
762
|
+
: String(configError),
|
|
728
763
|
});
|
|
729
|
-
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Log MCP initialization completion
|
|
768
|
+
*/
|
|
769
|
+
logMCPInitComplete(startMemory, MemoryManager, mcpInitStartTime) {
|
|
770
|
+
const endMemory = MemoryManager
|
|
771
|
+
? MemoryManager.getMemoryUsageMB()
|
|
772
|
+
: { heapUsed: 0, heapTotal: 0, rss: 0, external: 0 };
|
|
773
|
+
const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
|
|
774
|
+
const initTime = Date.now() - mcpInitStartTime;
|
|
775
|
+
mcpLogger.debug("[NeuroLink] MCP initialization completed successfully", {
|
|
776
|
+
initTime: `${initTime}ms`,
|
|
777
|
+
memoryUsed: `${memoryDelta}MB`,
|
|
778
|
+
});
|
|
779
|
+
if (memoryDelta > 30) {
|
|
780
|
+
mcpLogger.debug("💡 Memory cleanup suggestion: MCP initialization used significant memory. Consider calling MemoryManager.forceGC() after heavy operations.");
|
|
730
781
|
}
|
|
731
782
|
}
|
|
732
783
|
/**
|
|
@@ -894,9 +945,9 @@ export class NeuroLink {
|
|
|
894
945
|
model: textResult.model,
|
|
895
946
|
usage: textResult.usage
|
|
896
947
|
? {
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
948
|
+
input: textResult.usage.input || 0,
|
|
949
|
+
output: textResult.usage.output || 0,
|
|
950
|
+
total: textResult.usage.total || 0,
|
|
900
951
|
}
|
|
901
952
|
: undefined,
|
|
902
953
|
responseTime: textResult.responseTime,
|
|
@@ -910,9 +961,11 @@ export class NeuroLink {
|
|
|
910
961
|
...textResult.evaluation,
|
|
911
962
|
isOffTopic: textResult.evaluation
|
|
912
963
|
.isOffTopic ?? false,
|
|
913
|
-
alertSeverity: textResult.evaluation
|
|
914
|
-
|
|
915
|
-
"
|
|
964
|
+
alertSeverity: textResult.evaluation
|
|
965
|
+
.alertSeverity ??
|
|
966
|
+
"none",
|
|
967
|
+
reasoning: textResult.evaluation
|
|
968
|
+
.reasoning ?? "No evaluation provided",
|
|
916
969
|
evaluationModel: textResult.evaluation
|
|
917
970
|
.evaluationModel ?? "unknown",
|
|
918
971
|
evaluationTime: textResult.evaluation
|
|
@@ -957,18 +1010,46 @@ export class NeuroLink {
|
|
|
957
1010
|
* 5. Store conversation turn for future context
|
|
958
1011
|
*/
|
|
959
1012
|
async generateTextInternal(options) {
|
|
960
|
-
// 🚀 EXHAUSTIVE LOGGING POINT G001: GENERATE TEXT INTERNAL ENTRY
|
|
961
1013
|
const generateInternalId = `generate-internal-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
962
1014
|
const generateInternalStartTime = Date.now();
|
|
963
1015
|
const generateInternalHrTimeStart = process.hrtime.bigint();
|
|
964
1016
|
const functionTag = "NeuroLink.generateTextInternal";
|
|
1017
|
+
this.logGenerateTextInternalStart(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, options, functionTag);
|
|
1018
|
+
this.emitGenerationStartEvents(options);
|
|
1019
|
+
try {
|
|
1020
|
+
await this.initializeConversationMemoryForGeneration(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart);
|
|
1021
|
+
const mcpResult = await this.attemptMCPGeneration(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag);
|
|
1022
|
+
if (mcpResult) {
|
|
1023
|
+
await storeConversationTurn(this.conversationMemory, options, mcpResult);
|
|
1024
|
+
this.emitter.emit("response:end", mcpResult.content || "");
|
|
1025
|
+
return mcpResult;
|
|
1026
|
+
}
|
|
1027
|
+
const directResult = await this.directProviderGeneration(options);
|
|
1028
|
+
logger.debug(`[${functionTag}] Direct generation successful`);
|
|
1029
|
+
await storeConversationTurn(this.conversationMemory, options, directResult);
|
|
1030
|
+
this.emitter.emit("response:end", directResult.content || "");
|
|
1031
|
+
this.emitter.emit("message", `Text generation completed successfully`);
|
|
1032
|
+
return directResult;
|
|
1033
|
+
}
|
|
1034
|
+
catch (error) {
|
|
1035
|
+
logger.error(`[${functionTag}] All generation methods failed`, {
|
|
1036
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1037
|
+
});
|
|
1038
|
+
this.emitter.emit("response:end", "");
|
|
1039
|
+
this.emitter.emit("error", error instanceof Error ? error : new Error(String(error)));
|
|
1040
|
+
throw error;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Log generateTextInternal start with comprehensive analysis
|
|
1045
|
+
*/
|
|
1046
|
+
logGenerateTextInternalStart(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, options, functionTag) {
|
|
965
1047
|
logger.debug(`[NeuroLink] 🎯 LOG_POINT_G001_GENERATE_INTERNAL_START`, {
|
|
966
1048
|
logPoint: "G001_GENERATE_INTERNAL_START",
|
|
967
1049
|
generateInternalId,
|
|
968
1050
|
timestamp: new Date().toISOString(),
|
|
969
1051
|
generateInternalStartTime,
|
|
970
1052
|
generateInternalHrTimeStart: generateInternalHrTimeStart.toString(),
|
|
971
|
-
// 📊 Input analysis
|
|
972
1053
|
inputAnalysis: {
|
|
973
1054
|
provider: options.provider || "auto",
|
|
974
1055
|
providerType: typeof options.provider,
|
|
@@ -991,19 +1072,17 @@ export class NeuroLink {
|
|
|
991
1072
|
evaluationDomain: options.evaluationDomain || "NOT_SET",
|
|
992
1073
|
toolUsageContext: options.toolUsageContext || "NOT_SET",
|
|
993
1074
|
},
|
|
994
|
-
// 🧠 Memory and initialization state
|
|
995
1075
|
instanceState: {
|
|
996
1076
|
hasConversationMemory: !!this.conversationMemory,
|
|
997
1077
|
conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_SET",
|
|
998
1078
|
mcpInitialized: this.mcpInitialized,
|
|
999
1079
|
hasProviderRegistry: !!AIProviderFactory,
|
|
1000
|
-
providerRegistrySize: 0,
|
|
1080
|
+
providerRegistrySize: 0,
|
|
1001
1081
|
hasToolRegistry: !!toolRegistry,
|
|
1002
|
-
toolRegistrySize: 0,
|
|
1082
|
+
toolRegistrySize: 0,
|
|
1003
1083
|
hasExternalServerManager: !!this.externalServerManager,
|
|
1004
1084
|
hasContextManager: !!this.contextManager,
|
|
1005
1085
|
},
|
|
1006
|
-
// 🔧 Environment context
|
|
1007
1086
|
environmentContext: {
|
|
1008
1087
|
nodeVersion: process.version,
|
|
1009
1088
|
platform: process.platform,
|
|
@@ -1019,216 +1098,188 @@ export class NeuroLink {
|
|
|
1019
1098
|
promptLength: options.prompt?.length || 0,
|
|
1020
1099
|
hasConversationMemory: !!this.conversationMemory,
|
|
1021
1100
|
});
|
|
1022
|
-
|
|
1101
|
+
}
|
|
1102
|
+
/**
|
|
1103
|
+
* Emit generation start events
|
|
1104
|
+
*/
|
|
1105
|
+
emitGenerationStartEvents(options) {
|
|
1023
1106
|
this.emitter.emit("response:start");
|
|
1024
|
-
// ADD: Bedrock-compatible message event for generateTextInternal
|
|
1025
1107
|
this.emitter.emit("message", `Starting ${options.provider || "auto"} text generation (internal)...`);
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1108
|
+
}
|
|
1109
|
+
/**
|
|
1110
|
+
* Initialize conversation memory for generation
|
|
1111
|
+
*/
|
|
1112
|
+
async initializeConversationMemoryForGeneration(generateInternalId, generateInternalStartTime, generateInternalHrTimeStart) {
|
|
1113
|
+
const conversationMemoryStartTime = process.hrtime.bigint();
|
|
1114
|
+
logger.debug(`[NeuroLink] 🧠 LOG_POINT_G002_CONVERSATION_MEMORY_CHECK`, {
|
|
1115
|
+
logPoint: "G002_CONVERSATION_MEMORY_CHECK",
|
|
1116
|
+
generateInternalId,
|
|
1117
|
+
timestamp: new Date().toISOString(),
|
|
1118
|
+
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1119
|
+
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1120
|
+
conversationMemoryStartTimeNs: conversationMemoryStartTime.toString(),
|
|
1121
|
+
hasConversationMemory: !!this.conversationMemory,
|
|
1122
|
+
conversationMemoryEnabled: !!this.conversationMemory,
|
|
1123
|
+
conversationMemoryType: this.conversationMemory?.constructor?.name || "NOT_AVAILABLE",
|
|
1124
|
+
message: "Checking conversation memory initialization requirement",
|
|
1125
|
+
});
|
|
1126
|
+
if (this.conversationMemory) {
|
|
1127
|
+
logger.debug(`[NeuroLink] 🧠 LOG_POINT_G003_CONVERSATION_MEMORY_INIT_START`, {
|
|
1128
|
+
logPoint: "G003_CONVERSATION_MEMORY_INIT_START",
|
|
1031
1129
|
generateInternalId,
|
|
1032
1130
|
timestamp: new Date().toISOString(),
|
|
1033
1131
|
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1034
1132
|
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1133
|
+
message: "Starting conversation memory initialization",
|
|
1134
|
+
});
|
|
1135
|
+
await this.conversationMemory.initialize();
|
|
1136
|
+
const conversationMemoryEndTime = process.hrtime.bigint();
|
|
1137
|
+
const conversationMemoryDurationNs = conversationMemoryEndTime - conversationMemoryStartTime;
|
|
1138
|
+
logger.debug(`[NeuroLink] ✅ LOG_POINT_G004_CONVERSATION_MEMORY_INIT_SUCCESS`, {
|
|
1139
|
+
logPoint: "G004_CONVERSATION_MEMORY_INIT_SUCCESS",
|
|
1140
|
+
generateInternalId,
|
|
1141
|
+
timestamp: new Date().toISOString(),
|
|
1142
|
+
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1143
|
+
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1144
|
+
conversationMemoryDurationNs: conversationMemoryDurationNs.toString(),
|
|
1145
|
+
conversationMemoryDurationMs: Number(conversationMemoryDurationNs) / 1000000,
|
|
1146
|
+
message: "Conversation memory initialization completed successfully",
|
|
1040
1147
|
});
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
/**
|
|
1151
|
+
* Attempt MCP generation with retry logic
|
|
1152
|
+
*/
|
|
1153
|
+
async attemptMCPGeneration(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
|
|
1154
|
+
const mcpDecisionStartTime = process.hrtime.bigint();
|
|
1155
|
+
logger.debug(`[NeuroLink] 🔧 LOG_POINT_G005_MCP_DECISION_CHECK`, {
|
|
1156
|
+
logPoint: "G005_MCP_DECISION_CHECK",
|
|
1157
|
+
generateInternalId,
|
|
1158
|
+
timestamp: new Date().toISOString(),
|
|
1159
|
+
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1160
|
+
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1161
|
+
mcpDecisionStartTimeNs: mcpDecisionStartTime.toString(),
|
|
1162
|
+
mcpDecisionFactors: {
|
|
1163
|
+
disableTools: options.disableTools || false,
|
|
1164
|
+
toolsEnabled: !options.disableTools,
|
|
1165
|
+
mcpInitialized: this.mcpInitialized,
|
|
1166
|
+
hasExternalServerManager: !!this.externalServerManager,
|
|
1167
|
+
hasToolRegistry: !!toolRegistry,
|
|
1168
|
+
toolRegistrySize: 0,
|
|
1169
|
+
shouldTryMCP: !options.disableTools,
|
|
1170
|
+
},
|
|
1171
|
+
mcpReadinessAnalysis: {
|
|
1172
|
+
mcpAvailable: !options.disableTools && this.mcpInitialized,
|
|
1173
|
+
componentsReady: {
|
|
1174
|
+
externalServerManager: !!this.externalServerManager,
|
|
1175
|
+
toolRegistry: !!toolRegistry,
|
|
1176
|
+
providerRegistry: !!AIProviderFactory,
|
|
1177
|
+
},
|
|
1178
|
+
},
|
|
1179
|
+
message: "Analyzing MCP generation eligibility and readiness",
|
|
1180
|
+
});
|
|
1181
|
+
if (!options.disableTools) {
|
|
1182
|
+
return await this.performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag);
|
|
1183
|
+
}
|
|
1184
|
+
return null;
|
|
1185
|
+
}
|
|
1186
|
+
/**
|
|
1187
|
+
* Perform MCP generation with retry logic
|
|
1188
|
+
*/
|
|
1189
|
+
async performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
|
|
1190
|
+
const maxMcpRetries = 2;
|
|
1191
|
+
const mcpRetryLoopStartTime = process.hrtime.bigint();
|
|
1192
|
+
logger.debug(`[NeuroLink] 🔄 LOG_POINT_G006_MCP_RETRY_LOOP_START`, {
|
|
1193
|
+
logPoint: "G006_MCP_RETRY_LOOP_START",
|
|
1194
|
+
generateInternalId,
|
|
1195
|
+
timestamp: new Date().toISOString(),
|
|
1196
|
+
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1197
|
+
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1198
|
+
mcpRetryLoopStartTimeNs: mcpRetryLoopStartTime.toString(),
|
|
1199
|
+
maxMcpRetries,
|
|
1200
|
+
totalPossibleAttempts: maxMcpRetries + 1,
|
|
1201
|
+
message: "Starting MCP generation retry loop with failure tolerance",
|
|
1202
|
+
});
|
|
1203
|
+
const maxAttempts = maxMcpRetries + 1;
|
|
1204
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
1205
|
+
try {
|
|
1206
|
+
const mcpAttemptStartTime = process.hrtime.bigint();
|
|
1207
|
+
logger.debug(`[NeuroLink] 🎯 LOG_POINT_G007_MCP_ATTEMPT_START`, {
|
|
1208
|
+
logPoint: "G007_MCP_ATTEMPT_START",
|
|
1045
1209
|
generateInternalId,
|
|
1046
1210
|
timestamp: new Date().toISOString(),
|
|
1047
1211
|
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1048
1212
|
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1049
|
-
|
|
1213
|
+
mcpAttemptStartTimeNs: mcpAttemptStartTime.toString(),
|
|
1214
|
+
currentAttempt: attempt,
|
|
1215
|
+
maxAttempts,
|
|
1216
|
+
isFirstAttempt: attempt === 1,
|
|
1217
|
+
isLastAttempt: attempt === maxAttempts,
|
|
1218
|
+
attemptType: attempt === 1 ? "INITIAL" : "RETRY",
|
|
1219
|
+
message: `Attempting MCP generation (attempt ${attempt}/${maxAttempts})`,
|
|
1050
1220
|
});
|
|
1051
|
-
|
|
1052
|
-
const
|
|
1053
|
-
const
|
|
1054
|
-
|
|
1055
|
-
|
|
1221
|
+
logger.debug(`[${functionTag}] Attempting MCP generation (attempt ${attempt}/${maxAttempts})...`);
|
|
1222
|
+
const mcpResult = await this.tryMCPGeneration(options);
|
|
1223
|
+
const mcpAttemptEndTime = process.hrtime.bigint();
|
|
1224
|
+
const mcpAttemptDurationNs = mcpAttemptEndTime - mcpAttemptStartTime;
|
|
1225
|
+
logger.debug(`[NeuroLink] 📊 LOG_POINT_G008_MCP_ATTEMPT_RESULT`, {
|
|
1226
|
+
logPoint: "G008_MCP_ATTEMPT_RESULT",
|
|
1056
1227
|
generateInternalId,
|
|
1057
1228
|
timestamp: new Date().toISOString(),
|
|
1058
1229
|
elapsedMs: Date.now() - generateInternalStartTime,
|
|
1059
1230
|
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1231
|
+
mcpAttemptDurationNs: mcpAttemptDurationNs.toString(),
|
|
1232
|
+
mcpAttemptDurationMs: Number(mcpAttemptDurationNs) / 1000000,
|
|
1233
|
+
currentAttempt: attempt,
|
|
1234
|
+
resultAnalysis: {
|
|
1235
|
+
hasResult: !!mcpResult,
|
|
1236
|
+
resultType: typeof mcpResult,
|
|
1237
|
+
hasContent: !!(mcpResult && mcpResult.content),
|
|
1238
|
+
contentLength: mcpResult?.content?.length || 0,
|
|
1239
|
+
contentPreview: mcpResult?.content?.substring(0, 200) || "NO_CONTENT",
|
|
1240
|
+
hasToolExecutions: !!(mcpResult &&
|
|
1241
|
+
mcpResult.toolExecutions &&
|
|
1242
|
+
mcpResult.toolExecutions.length > 0),
|
|
1243
|
+
toolExecutionsCount: mcpResult?.toolExecutions?.length || 0,
|
|
1244
|
+
toolsUsedCount: mcpResult?.toolsUsed?.length || 0,
|
|
1245
|
+
provider: mcpResult?.provider || "NOT_SET",
|
|
1246
|
+
responseTime: mcpResult?.responseTime || 0,
|
|
1247
|
+
enhancedWithTools: mcpResult?.enhancedWithTools || false,
|
|
1248
|
+
},
|
|
1249
|
+
message: `MCP generation attempt ${attempt} completed - analyzing result`,
|
|
1063
1250
|
});
|
|
1251
|
+
if (mcpResult &&
|
|
1252
|
+
(mcpResult.content ||
|
|
1253
|
+
(mcpResult.toolExecutions && mcpResult.toolExecutions.length > 0))) {
|
|
1254
|
+
logger.debug(`[${functionTag}] MCP generation successful on attempt ${attempt}`, {
|
|
1255
|
+
contentLength: mcpResult.content?.length || 0,
|
|
1256
|
+
toolsUsed: mcpResult.toolsUsed?.length || 0,
|
|
1257
|
+
toolExecutions: mcpResult.toolExecutions?.length || 0,
|
|
1258
|
+
});
|
|
1259
|
+
return mcpResult;
|
|
1260
|
+
}
|
|
1261
|
+
else {
|
|
1262
|
+
logger.debug(`[${functionTag}] MCP generation returned empty result on attempt ${attempt}`, {
|
|
1263
|
+
hasResult: !!mcpResult,
|
|
1264
|
+
hasContent: !!(mcpResult && mcpResult.content),
|
|
1265
|
+
contentLength: mcpResult?.content?.length || 0,
|
|
1266
|
+
toolExecutions: mcpResult?.toolExecutions?.length || 0,
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1064
1269
|
}
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
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",
|
|
1270
|
+
catch (error) {
|
|
1271
|
+
logger.debug(`[${functionTag}] MCP generation failed on attempt ${attempt}/${maxAttempts}`, {
|
|
1272
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1273
|
+
willRetry: attempt < maxAttempts,
|
|
1112
1274
|
});
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
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
|
-
}
|
|
1275
|
+
if (attempt >= maxAttempts) {
|
|
1276
|
+
logger.debug(`[${functionTag}] All MCP attempts exhausted, falling back to direct generation`);
|
|
1277
|
+
break;
|
|
1209
1278
|
}
|
|
1279
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
1210
1280
|
}
|
|
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
1281
|
}
|
|
1282
|
+
return null;
|
|
1232
1283
|
}
|
|
1233
1284
|
/**
|
|
1234
1285
|
* Try MCP-enhanced generation (no fallback recursion)
|
|
@@ -1610,7 +1661,51 @@ export class NeuroLink {
|
|
|
1610
1661
|
const functionTag = "NeuroLink.stream";
|
|
1611
1662
|
const streamId = `neurolink-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1612
1663
|
const journeyStartTime = new Date().toISOString();
|
|
1613
|
-
|
|
1664
|
+
this.logStreamEntryPoint(streamId, journeyStartTime, functionTag, startTime, hrTimeStart, options);
|
|
1665
|
+
this.logPerformanceBaseline(streamId, startTime, hrTimeStart);
|
|
1666
|
+
await this.validateStreamInput(options, streamId, startTime, hrTimeStart);
|
|
1667
|
+
this.emitStreamStartEvents(options, startTime);
|
|
1668
|
+
let enhancedOptions;
|
|
1669
|
+
let factoryResult;
|
|
1670
|
+
try {
|
|
1671
|
+
await this.initializeMCP();
|
|
1672
|
+
const originalPrompt = options.input.text;
|
|
1673
|
+
if (this.contextManager) {
|
|
1674
|
+
options.input.text = this.contextManager.getContextForPrompt("user", options.input.text);
|
|
1675
|
+
}
|
|
1676
|
+
factoryResult = processStreamingFactoryOptions(options);
|
|
1677
|
+
enhancedOptions = createCleanStreamOptions(options);
|
|
1678
|
+
const { toolResults: _toolResults, enhancedPrompt } = await this.detectAndExecuteTools(options.input.text, undefined);
|
|
1679
|
+
if (enhancedPrompt !== options.input.text) {
|
|
1680
|
+
enhancedOptions.input.text = enhancedPrompt;
|
|
1681
|
+
}
|
|
1682
|
+
const { stream: mcpStream, provider: providerName } = await this.createMCPStream(enhancedOptions);
|
|
1683
|
+
const streamResult = await this.processStreamResult(mcpStream, enhancedOptions, factoryResult);
|
|
1684
|
+
const responseTime = Date.now() - startTime;
|
|
1685
|
+
if (this.contextManager) {
|
|
1686
|
+
await this.contextManager.addTurn("user", originalPrompt);
|
|
1687
|
+
if (streamResult.content) {
|
|
1688
|
+
await this.contextManager.addTurn("assistant", streamResult.content);
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
this.emitStreamEndEvents(streamResult);
|
|
1692
|
+
return this.createStreamResponse(streamResult, mcpStream, {
|
|
1693
|
+
providerName,
|
|
1694
|
+
options,
|
|
1695
|
+
startTime,
|
|
1696
|
+
responseTime,
|
|
1697
|
+
streamId,
|
|
1698
|
+
fallback: false,
|
|
1699
|
+
});
|
|
1700
|
+
}
|
|
1701
|
+
catch (error) {
|
|
1702
|
+
return this.handleStreamError(error, options, startTime, streamId, undefined, undefined);
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
/**
|
|
1706
|
+
* Log stream entry point with comprehensive analysis
|
|
1707
|
+
*/
|
|
1708
|
+
logStreamEntryPoint(streamId, journeyStartTime, functionTag, startTime, hrTimeStart, options) {
|
|
1614
1709
|
logger.debug(`[NeuroLink] 🎯 LOG_POINT_001_STREAM_ENTRY_START`, {
|
|
1615
1710
|
logPoint: "001_STREAM_ENTRY_START",
|
|
1616
1711
|
streamId,
|
|
@@ -1623,12 +1718,10 @@ export class NeuroLink {
|
|
|
1623
1718
|
arch: process.arch,
|
|
1624
1719
|
memoryUsage: process.memoryUsage(),
|
|
1625
1720
|
cpuUsage: process.cpuUsage(),
|
|
1626
|
-
// Comprehensive input validation
|
|
1627
1721
|
hasOptions: !!options,
|
|
1628
1722
|
optionsType: typeof options,
|
|
1629
1723
|
optionsKeys: options ? Object.keys(options) : [],
|
|
1630
1724
|
optionsSize: options ? JSON.stringify(options).length : 0,
|
|
1631
|
-
// Deep input analysis
|
|
1632
1725
|
hasInput: !!options?.input,
|
|
1633
1726
|
inputType: typeof options?.input,
|
|
1634
1727
|
inputKeys: options?.input ? Object.keys(options.input) : [],
|
|
@@ -1636,53 +1729,18 @@ export class NeuroLink {
|
|
|
1636
1729
|
inputTextType: typeof options?.input?.text,
|
|
1637
1730
|
inputTextLength: options?.input?.text?.length || 0,
|
|
1638
1731
|
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
1732
|
hasProvider: !!options?.provider,
|
|
1647
1733
|
providerValue: options?.provider || "NOT_SET",
|
|
1648
1734
|
isAutoProvider: options?.provider === "auto" || !options?.provider,
|
|
1649
|
-
// Model configuration analysis
|
|
1650
1735
|
hasModel: !!options?.model,
|
|
1651
1736
|
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
1737
|
message: "EXHAUSTIVE NeuroLink main stream method entry point with comprehensive environment analysis",
|
|
1684
1738
|
});
|
|
1685
|
-
|
|
1739
|
+
}
|
|
1740
|
+
/**
|
|
1741
|
+
* Log performance baseline
|
|
1742
|
+
*/
|
|
1743
|
+
logPerformanceBaseline(streamId, startTime, hrTimeStart) {
|
|
1686
1744
|
const memoryBaseline = process.memoryUsage();
|
|
1687
1745
|
const cpuBaseline = process.cpuUsage();
|
|
1688
1746
|
logger.debug(`[NeuroLink] 🎯 LOG_POINT_002_PERFORMANCE_BASELINE`, {
|
|
@@ -1708,14 +1766,18 @@ export class NeuroLink {
|
|
|
1708
1766
|
global.gc();
|
|
1709
1767
|
return process.memoryUsage();
|
|
1710
1768
|
}
|
|
1711
|
-
catch
|
|
1769
|
+
catch {
|
|
1712
1770
|
return null;
|
|
1713
1771
|
}
|
|
1714
1772
|
})()
|
|
1715
1773
|
: null,
|
|
1716
1774
|
message: "Performance baseline metrics captured for stream processing",
|
|
1717
1775
|
});
|
|
1718
|
-
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* Validate stream input with comprehensive error reporting
|
|
1779
|
+
*/
|
|
1780
|
+
async validateStreamInput(options, streamId, startTime, hrTimeStart) {
|
|
1719
1781
|
const validationStartTime = process.hrtime.bigint();
|
|
1720
1782
|
logger.debug(`[NeuroLink] 🎯 LOG_POINT_003_VALIDATION_START`, {
|
|
1721
1783
|
logPoint: "003_VALIDATION_START",
|
|
@@ -1726,45 +1788,6 @@ export class NeuroLink {
|
|
|
1726
1788
|
validationStartTimeNs: validationStartTime.toString(),
|
|
1727
1789
|
message: "Starting comprehensive input validation process",
|
|
1728
1790
|
});
|
|
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
1791
|
if (!options?.input?.text ||
|
|
1769
1792
|
typeof options.input.text !== "string" ||
|
|
1770
1793
|
options.input.text.trim() === "") {
|
|
@@ -1779,47 +1802,10 @@ export class NeuroLink {
|
|
|
1779
1802
|
validationDurationNs: validationDurationNs.toString(),
|
|
1780
1803
|
validationDurationMs: Number(validationDurationNs) / 1000000,
|
|
1781
1804
|
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
1805
|
message: "EXHAUSTIVE validation failure analysis with character-level debugging",
|
|
1819
1806
|
});
|
|
1820
1807
|
throw new Error("Stream options must include input.text as a non-empty string");
|
|
1821
1808
|
}
|
|
1822
|
-
// 🚀 EXHAUSTIVE LOGGING POINT 6: VALIDATION SUCCESS
|
|
1823
1809
|
const validationSuccessTime = process.hrtime.bigint();
|
|
1824
1810
|
const validationDurationNs = validationSuccessTime - validationStartTime;
|
|
1825
1811
|
logger.debug(`[NeuroLink] ✅ LOG_POINT_006_VALIDATION_SUCCESS`, {
|
|
@@ -1834,311 +1820,116 @@ export class NeuroLink {
|
|
|
1834
1820
|
inputTextLength: options.input.text.length,
|
|
1835
1821
|
inputTextTrimmedLength: options.input.text.trim().length,
|
|
1836
1822
|
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
1823
|
message: "EXHAUSTIVE validation success - proceeding with stream processing",
|
|
1848
1824
|
});
|
|
1849
|
-
|
|
1825
|
+
}
|
|
1826
|
+
/**
|
|
1827
|
+
* Emit stream start events
|
|
1828
|
+
*/
|
|
1829
|
+
emitStreamStartEvents(options, startTime) {
|
|
1850
1830
|
this.emitter.emit("stream:start", {
|
|
1851
1831
|
provider: options.provider || "auto",
|
|
1852
1832
|
timestamp: startTime,
|
|
1853
1833
|
});
|
|
1854
|
-
// ADD: Bedrock-compatible response:start event
|
|
1855
1834
|
this.emitter.emit("response:start");
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
}
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
:
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
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,
|
|
1835
|
+
this.emitter.emit("message", `Starting ${options.provider || "auto"} stream...`);
|
|
1836
|
+
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Create MCP stream
|
|
1839
|
+
*/
|
|
1840
|
+
async createMCPStream(options) {
|
|
1841
|
+
// Simplified placeholder - in the actual implementation this would contain the complex MCP stream logic
|
|
1842
|
+
const providerName = await getBestProvider(options.provider);
|
|
1843
|
+
const provider = await AIProviderFactory.createProvider(providerName, options.model, !options.disableTools, // Pass disableTools as inverse of enableMCP
|
|
1844
|
+
this);
|
|
1845
|
+
// Enable tool execution for the provider using BaseProvider method
|
|
1846
|
+
provider.setupToolExecutor({
|
|
1847
|
+
customTools: this.getCustomTools(),
|
|
1848
|
+
executeTool: this.executeTool.bind(this),
|
|
1849
|
+
}, "NeuroLink.createMCPStream");
|
|
1850
|
+
const streamResult = await provider.stream(options);
|
|
1851
|
+
return { stream: streamResult.stream, provider: providerName };
|
|
1852
|
+
}
|
|
1853
|
+
/**
|
|
1854
|
+
* Process stream result
|
|
1855
|
+
*/
|
|
1856
|
+
async processStreamResult(_stream, _options, _factoryResult) {
|
|
1857
|
+
// Simplified placeholder - in the actual implementation this would process the stream
|
|
1858
|
+
return {
|
|
1859
|
+
content: "",
|
|
1860
|
+
usage: undefined,
|
|
1861
|
+
finishReason: "stop",
|
|
1862
|
+
toolCalls: [],
|
|
1863
|
+
toolResults: [],
|
|
1864
|
+
analytics: undefined,
|
|
1865
|
+
evaluation: undefined,
|
|
1866
|
+
};
|
|
1867
|
+
}
|
|
1868
|
+
/**
|
|
1869
|
+
* Emit stream end events
|
|
1870
|
+
*/
|
|
1871
|
+
emitStreamEndEvents(streamResult) {
|
|
1872
|
+
this.emitter.emit("stream:end", {
|
|
1873
|
+
responseTime: Date.now(),
|
|
1874
|
+
timestamp: Date.now(),
|
|
1875
|
+
});
|
|
1876
|
+
this.emitter.emit("response:end", streamResult.content || "");
|
|
1877
|
+
}
|
|
1878
|
+
/**
|
|
1879
|
+
* Create stream response
|
|
1880
|
+
*/
|
|
1881
|
+
createStreamResponse(streamResult, stream, config) {
|
|
1882
|
+
return {
|
|
1883
|
+
stream,
|
|
1884
|
+
provider: config.providerName,
|
|
1885
|
+
model: config.options.model,
|
|
1886
|
+
usage: streamResult.usage,
|
|
1887
|
+
finishReason: streamResult.finishReason,
|
|
1888
|
+
toolCalls: streamResult.toolCalls,
|
|
1889
|
+
toolResults: streamResult.toolResults,
|
|
1890
|
+
analytics: streamResult.analytics,
|
|
1891
|
+
evaluation: streamResult.evaluation,
|
|
1892
|
+
metadata: {
|
|
1893
|
+
streamId: config.streamId,
|
|
1894
|
+
startTime: config.startTime,
|
|
1895
|
+
responseTime: config.responseTime,
|
|
1896
|
+
fallback: config.fallback || false,
|
|
1897
|
+
},
|
|
1898
|
+
};
|
|
1899
|
+
}
|
|
1900
|
+
/**
|
|
1901
|
+
* Handle stream error with fallback
|
|
1902
|
+
*/
|
|
1903
|
+
async handleStreamError(error, options, startTime, streamId, _enhancedOptions, _factoryResult) {
|
|
1904
|
+
logger.error("Stream generation failed, attempting fallback", {
|
|
1905
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1906
|
+
});
|
|
1907
|
+
const responseTime = Date.now() - startTime;
|
|
1908
|
+
const providerName = await getBestProvider(options.provider);
|
|
1909
|
+
const provider = await AIProviderFactory.createProvider(providerName, options.model, false);
|
|
1910
|
+
const fallbackStream = await provider.stream({
|
|
1911
|
+
input: { text: options.input.text },
|
|
1912
|
+
model: options.model,
|
|
1913
|
+
temperature: options.temperature,
|
|
1914
|
+
maxTokens: options.maxTokens,
|
|
1915
|
+
});
|
|
1916
|
+
return {
|
|
1917
|
+
stream: fallbackStream.stream,
|
|
1918
|
+
provider: providerName,
|
|
1919
|
+
model: options.model,
|
|
1920
|
+
usage: fallbackStream.usage,
|
|
1921
|
+
finishReason: fallbackStream.finishReason || "stop",
|
|
1922
|
+
toolCalls: fallbackStream.toolCalls || [],
|
|
1923
|
+
toolResults: fallbackStream.toolResults || [],
|
|
1924
|
+
analytics: fallbackStream.analytics,
|
|
1925
|
+
evaluation: fallbackStream.evaluation,
|
|
1926
|
+
metadata: {
|
|
1927
|
+
streamId,
|
|
1928
|
+
startTime,
|
|
2107
1929
|
responseTime,
|
|
2108
1930
|
fallback: true,
|
|
2109
|
-
|
|
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
|
-
}
|
|
1931
|
+
},
|
|
1932
|
+
};
|
|
2142
1933
|
}
|
|
2143
1934
|
/**
|
|
2144
1935
|
* Get the EventEmitter instance to listen to NeuroLink events for real-time monitoring and debugging.
|
|
@@ -2575,6 +2366,9 @@ export class NeuroLink {
|
|
|
2575
2366
|
circuitBreakerState: circuitBreaker?.getState(),
|
|
2576
2367
|
});
|
|
2577
2368
|
// Execute with circuit breaker, timeout, and retry logic
|
|
2369
|
+
if (!circuitBreaker) {
|
|
2370
|
+
throw new Error(`Circuit breaker not initialized for tool: ${toolName}`);
|
|
2371
|
+
}
|
|
2578
2372
|
const result = await circuitBreaker.execute(async () => {
|
|
2579
2373
|
return await withRetry(async () => {
|
|
2580
2374
|
return await withTimeout(this.executeToolInternal(toolName, params, finalOptions), finalOptions.timeout, ErrorFactory.toolTimeout(toolName, finalOptions.timeout));
|