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