@juspay/neurolink 7.33.2 → 7.33.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -0
- package/dist/constants/index.d.ts +192 -0
- package/dist/constants/index.js +195 -0
- package/dist/constants/performance.d.ts +366 -0
- package/dist/constants/performance.js +389 -0
- package/dist/constants/retry.d.ts +224 -0
- package/dist/constants/retry.js +266 -0
- package/dist/constants/timeouts.d.ts +225 -0
- package/dist/constants/timeouts.js +182 -0
- package/dist/constants/tokens.d.ts +234 -0
- package/dist/constants/tokens.js +314 -0
- package/dist/core/types.d.ts +268 -0
- package/dist/core/types.js +153 -0
- package/dist/lib/constants/index.d.ts +192 -0
- package/dist/lib/constants/index.js +195 -0
- package/dist/lib/constants/performance.d.ts +366 -0
- package/dist/lib/constants/performance.js +389 -0
- package/dist/lib/constants/retry.d.ts +224 -0
- package/dist/lib/constants/retry.js +266 -0
- package/dist/lib/constants/timeouts.d.ts +225 -0
- package/dist/lib/constants/timeouts.js +182 -0
- package/dist/lib/constants/tokens.d.ts +234 -0
- package/dist/lib/constants/tokens.js +314 -0
- package/dist/lib/core/types.d.ts +268 -0
- package/dist/lib/core/types.js +153 -0
- package/dist/lib/models/modelRegistry.d.ts +1 -1
- package/dist/lib/models/modelRegistry.js +63 -37
- package/dist/lib/neurolink.js +35 -34
- package/dist/lib/providers/azureOpenai.d.ts +1 -1
- package/dist/lib/providers/azureOpenai.js +2 -1
- package/dist/lib/utils/providerConfig.d.ts +25 -0
- package/dist/lib/utils/providerConfig.js +24 -3
- package/dist/lib/utils/providerHealth.d.ts +1 -1
- package/dist/lib/utils/providerHealth.js +40 -33
- package/dist/lib/utils/providerSetupMessages.js +7 -6
- package/dist/lib/utils/providerUtils.js +16 -24
- package/dist/models/modelRegistry.d.ts +1 -1
- package/dist/models/modelRegistry.js +63 -37
- package/dist/neurolink.js +35 -34
- package/dist/providers/azureOpenai.d.ts +1 -1
- package/dist/providers/azureOpenai.js +2 -1
- package/dist/utils/providerConfig.d.ts +25 -0
- package/dist/utils/providerConfig.js +24 -3
- package/dist/utils/providerHealth.d.ts +1 -1
- package/dist/utils/providerHealth.js +40 -33
- package/dist/utils/providerSetupMessages.js +7 -6
- package/dist/utils/providerUtils.js +16 -24
- package/package.json +1 -1
package/dist/lib/neurolink.js
CHANGED
@@ -16,6 +16,7 @@ catch {
|
|
16
16
|
import { AIProviderFactory } from "./core/factory.js";
|
17
17
|
import { mcpLogger } from "./utils/logger.js";
|
18
18
|
import { SYSTEM_LIMITS } from "./core/constants.js";
|
19
|
+
import { NANOSECOND_TO_MS_DIVISOR, MCP_TIMEOUTS, SERVER_CONFIG, TOOL_TIMEOUTS, RETRY_ATTEMPTS, RETRY_DELAYS, CIRCUIT_BREAKER, CIRCUIT_BREAKER_RESET_MS, MEMORY_THRESHOLDS, PROVIDER_TIMEOUTS, PERFORMANCE_THRESHOLDS, } from "./constants/index.js";
|
19
20
|
import pLimit from "p-limit";
|
20
21
|
import { toolRegistry } from "./mcp/toolRegistry.js";
|
21
22
|
import { logger } from "./utils/logger.js";
|
@@ -164,7 +165,7 @@ export class NeuroLink {
|
|
164
165
|
elapsedMs: Date.now() - constructorStartTime,
|
165
166
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
166
167
|
registrySetupDurationNs: registrySetupDurationNs.toString(),
|
167
|
-
registrySetupDurationMs: Number(registrySetupDurationNs) /
|
168
|
+
registrySetupDurationMs: Number(registrySetupDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
168
169
|
enableManualMCP: false,
|
169
170
|
message: "ProviderRegistry configured successfully with security settings",
|
170
171
|
});
|
@@ -179,7 +180,7 @@ export class NeuroLink {
|
|
179
180
|
elapsedMs: Date.now() - constructorStartTime,
|
180
181
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
181
182
|
registrySetupDurationNs: registrySetupDurationNs.toString(),
|
182
|
-
registrySetupDurationMs: Number(registrySetupDurationNs) /
|
183
|
+
registrySetupDurationMs: Number(registrySetupDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
183
184
|
error: error instanceof Error ? error.message : String(error),
|
184
185
|
errorName: error instanceof Error ? error.name : "UnknownError",
|
185
186
|
errorStack: error instanceof Error ? error.stack : undefined,
|
@@ -224,9 +225,9 @@ export class NeuroLink {
|
|
224
225
|
elapsedMs: Date.now() - constructorStartTime,
|
225
226
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
226
227
|
memoryInitDurationNs: memoryInitDurationNs.toString(),
|
227
|
-
memoryInitDurationMs: Number(memoryInitDurationNs) /
|
228
|
+
memoryInitDurationMs: Number(memoryInitDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
228
229
|
memoryManagerCreateDurationNs: memoryManagerCreateDurationNs.toString(),
|
229
|
-
memoryManagerCreateDurationMs: Number(memoryManagerCreateDurationNs) /
|
230
|
+
memoryManagerCreateDurationMs: Number(memoryManagerCreateDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
230
231
|
finalMemoryConfig: {
|
231
232
|
maxSessions: memoryConfig.maxSessions,
|
232
233
|
maxTurnsPerSession: memoryConfig.maxTurnsPerSession,
|
@@ -245,7 +246,7 @@ export class NeuroLink {
|
|
245
246
|
elapsedMs: Date.now() - constructorStartTime,
|
246
247
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
247
248
|
memoryInitDurationNs: memoryInitDurationNs.toString(),
|
248
|
-
memoryInitDurationMs: Number(memoryInitDurationNs) /
|
249
|
+
memoryInitDurationMs: Number(memoryInitDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
249
250
|
error: error instanceof Error ? error.message : String(error),
|
250
251
|
errorName: error instanceof Error ? error.name : "UnknownError",
|
251
252
|
errorStack: error instanceof Error ? error.stack : undefined,
|
@@ -289,8 +290,8 @@ export class NeuroLink {
|
|
289
290
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
290
291
|
externalServerInitStartTimeNs: externalServerInitStartTime.toString(),
|
291
292
|
serverManagerConfig: {
|
292
|
-
maxServers:
|
293
|
-
defaultTimeout:
|
293
|
+
maxServers: SERVER_CONFIG.MAX_MCP_SERVERS,
|
294
|
+
defaultTimeout: MCP_TIMEOUTS.EXTERNAL_SERVER_STARTUP_MS,
|
294
295
|
enableAutoRestart: true,
|
295
296
|
enablePerformanceMonitoring: true,
|
296
297
|
},
|
@@ -317,7 +318,7 @@ export class NeuroLink {
|
|
317
318
|
elapsedMs: Date.now() - constructorStartTime,
|
318
319
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
319
320
|
externalServerInitDurationNs: externalServerInitDurationNs.toString(),
|
320
|
-
externalServerInitDurationMs: Number(externalServerInitDurationNs) /
|
321
|
+
externalServerInitDurationMs: Number(externalServerInitDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
321
322
|
hasExternalServerManager: !!this.externalServerManager,
|
322
323
|
message: "External server manager initialized successfully",
|
323
324
|
});
|
@@ -333,7 +334,7 @@ export class NeuroLink {
|
|
333
334
|
elapsedMs: Date.now() - constructorStartTime,
|
334
335
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
335
336
|
externalServerInitDurationNs: externalServerInitDurationNs.toString(),
|
336
|
-
externalServerInitDurationMs: Number(externalServerInitDurationNs) /
|
337
|
+
externalServerInitDurationMs: Number(externalServerInitDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
337
338
|
error: error instanceof Error ? error.message : String(error),
|
338
339
|
errorName: error instanceof Error ? error.name : "UnknownError",
|
339
340
|
errorStack: error instanceof Error ? error.stack : undefined,
|
@@ -418,7 +419,7 @@ export class NeuroLink {
|
|
418
419
|
elapsedMs: Date.now() - constructorStartTime,
|
419
420
|
elapsedNs: (process.hrtime.bigint() - constructorHrTimeStart).toString(),
|
420
421
|
eventHandlerSetupDurationNs: eventHandlerSetupDurationNs.toString(),
|
421
|
-
eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) /
|
422
|
+
eventHandlerSetupDurationMs: Number(eventHandlerSetupDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
422
423
|
eventHandlersCount: 5,
|
423
424
|
eventHandlerTypes: [
|
424
425
|
"connected",
|
@@ -441,7 +442,7 @@ export class NeuroLink {
|
|
441
442
|
constructorId,
|
442
443
|
timestamp: new Date().toISOString(),
|
443
444
|
constructorDurationNs: constructorDurationNs.toString(),
|
444
|
-
constructorDurationMs: Number(constructorDurationNs) /
|
445
|
+
constructorDurationMs: Number(constructorDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
445
446
|
totalElapsedMs: Date.now() - constructorStartTime,
|
446
447
|
finalState: {
|
447
448
|
hasConversationMemory: !!this.conversationMemory,
|
@@ -542,7 +543,7 @@ export class NeuroLink {
|
|
542
543
|
elapsedMs: Date.now() - mcpInitStartTime,
|
543
544
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
544
545
|
performanceImportDurationNs: performanceImportDurationNs.toString(),
|
545
|
-
performanceImportDurationMs: Number(performanceImportDurationNs) /
|
546
|
+
performanceImportDurationMs: Number(performanceImportDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
546
547
|
hasMemoryManager: !!MemoryManager,
|
547
548
|
message: "MemoryManager imported successfully",
|
548
549
|
});
|
@@ -558,7 +559,7 @@ export class NeuroLink {
|
|
558
559
|
elapsedMs: Date.now() - mcpInitStartTime,
|
559
560
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
560
561
|
performanceImportDurationNs: performanceImportDurationNs.toString(),
|
561
|
-
performanceImportDurationMs: Number(performanceImportDurationNs) /
|
562
|
+
performanceImportDurationMs: Number(performanceImportDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
562
563
|
error: error instanceof Error ? error.message : String(error),
|
563
564
|
errorName: error instanceof Error ? error.name : "UnknownError",
|
564
565
|
message: "MemoryManager import failed - continuing without performance tracking",
|
@@ -590,7 +591,7 @@ export class NeuroLink {
|
|
590
591
|
*/
|
591
592
|
async initializeToolRegistryInternal(mcpInitId, mcpInitStartTime, mcpInitHrTimeStart) {
|
592
593
|
const toolRegistryStartTime = process.hrtime.bigint();
|
593
|
-
const initTimeout =
|
594
|
+
const initTimeout = MCP_TIMEOUTS.INITIALIZATION_MS;
|
594
595
|
logger.debug(`[NeuroLink] ⏱️ LOG_POINT_M007_TOOL_REGISTRY_TIMEOUT_SETUP`, {
|
595
596
|
logPoint: "M007_TOOL_REGISTRY_TIMEOUT_SETUP",
|
596
597
|
mcpInitId,
|
@@ -616,7 +617,7 @@ export class NeuroLink {
|
|
616
617
|
elapsedMs: Date.now() - mcpInitStartTime,
|
617
618
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
618
619
|
toolRegistryDurationNs: toolRegistryDurationNs.toString(),
|
619
|
-
toolRegistryDurationMs: Number(toolRegistryDurationNs) /
|
620
|
+
toolRegistryDurationMs: Number(toolRegistryDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
620
621
|
message: "Tool registry initialization completed within timeout",
|
621
622
|
});
|
622
623
|
}
|
@@ -644,7 +645,7 @@ export class NeuroLink {
|
|
644
645
|
elapsedMs: Date.now() - mcpInitStartTime,
|
645
646
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
646
647
|
providerRegistryDurationNs: providerRegistryDurationNs.toString(),
|
647
|
-
providerRegistryDurationMs: Number(providerRegistryDurationNs) /
|
648
|
+
providerRegistryDurationMs: Number(providerRegistryDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
648
649
|
message: "Provider registry registration completed successfully",
|
649
650
|
});
|
650
651
|
}
|
@@ -674,7 +675,7 @@ export class NeuroLink {
|
|
674
675
|
elapsedMs: Date.now() - mcpInitStartTime,
|
675
676
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
676
677
|
directToolsDurationNs: directToolsDurationNs.toString(),
|
677
|
-
directToolsDurationMs: Number(directToolsDurationNs) /
|
678
|
+
directToolsDurationMs: Number(directToolsDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
678
679
|
serverId: "neurolink-direct",
|
679
680
|
message: "Direct tools server registered successfully",
|
680
681
|
});
|
@@ -692,7 +693,7 @@ export class NeuroLink {
|
|
692
693
|
elapsedMs: Date.now() - mcpInitStartTime,
|
693
694
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
694
695
|
directToolsDurationNs: directToolsDurationNs.toString(),
|
695
|
-
directToolsDurationMs: Number(directToolsDurationNs) /
|
696
|
+
directToolsDurationMs: Number(directToolsDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
696
697
|
error: error instanceof Error ? error.message : String(error),
|
697
698
|
errorName: error instanceof Error ? error.name : "UnknownError",
|
698
699
|
errorStack: error instanceof Error ? error.stack : undefined,
|
@@ -731,7 +732,7 @@ export class NeuroLink {
|
|
731
732
|
elapsedMs: Date.now() - mcpInitStartTime,
|
732
733
|
elapsedNs: (process.hrtime.bigint() - mcpInitHrTimeStart).toString(),
|
733
734
|
mcpConfigDurationNs: mcpConfigDurationNs.toString(),
|
734
|
-
mcpConfigDurationMs: Number(mcpConfigDurationNs) /
|
735
|
+
mcpConfigDurationMs: Number(mcpConfigDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
735
736
|
serversLoaded: configResult.serversLoaded,
|
736
737
|
errorsCount: configResult.errors.length,
|
737
738
|
configResult: {
|
@@ -774,7 +775,7 @@ export class NeuroLink {
|
|
774
775
|
initTime: `${initTime}ms`,
|
775
776
|
memoryUsed: `${memoryDelta}MB`,
|
776
777
|
});
|
777
|
-
if (memoryDelta >
|
778
|
+
if (memoryDelta > MEMORY_THRESHOLDS.MODERATE_USAGE_MB) {
|
778
779
|
mcpLogger.debug("💡 Memory cleanup suggestion: MCP initialization used significant memory. Consider calling MemoryManager.forceGC() after heavy operations.");
|
779
780
|
}
|
780
781
|
}
|
@@ -1120,7 +1121,7 @@ export class NeuroLink {
|
|
1120
1121
|
elapsedMs: Date.now() - generateInternalStartTime,
|
1121
1122
|
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
1122
1123
|
conversationMemoryDurationNs: conversationMemoryDurationNs.toString(),
|
1123
|
-
conversationMemoryDurationMs: Number(conversationMemoryDurationNs) /
|
1124
|
+
conversationMemoryDurationMs: Number(conversationMemoryDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
1124
1125
|
message: "Conversation memory initialization completed successfully",
|
1125
1126
|
});
|
1126
1127
|
}
|
@@ -1165,7 +1166,7 @@ export class NeuroLink {
|
|
1165
1166
|
* Perform MCP generation with retry logic
|
1166
1167
|
*/
|
1167
1168
|
async performMCPGenerationRetries(options, generateInternalId, generateInternalStartTime, generateInternalHrTimeStart, functionTag) {
|
1168
|
-
const maxMcpRetries =
|
1169
|
+
const maxMcpRetries = RETRY_ATTEMPTS.QUICK;
|
1169
1170
|
const mcpRetryLoopStartTime = process.hrtime.bigint();
|
1170
1171
|
logger.debug(`[NeuroLink] 🔄 LOG_POINT_G006_MCP_RETRY_LOOP_START`, {
|
1171
1172
|
logPoint: "G006_MCP_RETRY_LOOP_START",
|
@@ -1207,7 +1208,7 @@ export class NeuroLink {
|
|
1207
1208
|
elapsedMs: Date.now() - generateInternalStartTime,
|
1208
1209
|
elapsedNs: (process.hrtime.bigint() - generateInternalHrTimeStart).toString(),
|
1209
1210
|
mcpAttemptDurationNs: mcpAttemptDurationNs.toString(),
|
1210
|
-
mcpAttemptDurationMs: Number(mcpAttemptDurationNs) /
|
1211
|
+
mcpAttemptDurationMs: Number(mcpAttemptDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
1211
1212
|
currentAttempt: attempt,
|
1212
1213
|
resultAnalysis: {
|
1213
1214
|
hasResult: !!mcpResult,
|
@@ -1326,7 +1327,7 @@ export class NeuroLink {
|
|
1326
1327
|
elapsedMs: Date.now() - tryMCPStartTime,
|
1327
1328
|
elapsedNs: (process.hrtime.bigint() - tryMCPHrTimeStart).toString(),
|
1328
1329
|
mcpInitCheckDurationNs: mcpInitCheckDurationNs.toString(),
|
1329
|
-
mcpInitCheckDurationMs: Number(mcpInitCheckDurationNs) /
|
1330
|
+
mcpInitCheckDurationMs: Number(mcpInitCheckDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
1330
1331
|
mcpInitializedAfter: this.mcpInitialized,
|
1331
1332
|
initializationSuccessful: this.mcpInitialized,
|
1332
1333
|
message: "MCP initialization check completed",
|
@@ -1782,7 +1783,7 @@ export class NeuroLink {
|
|
1782
1783
|
elapsedMs: Date.now() - startTime,
|
1783
1784
|
elapsedNs: (process.hrtime.bigint() - hrTimeStart).toString(),
|
1784
1785
|
validationDurationNs: validationDurationNs.toString(),
|
1785
|
-
validationDurationMs: Number(validationDurationNs) /
|
1786
|
+
validationDurationMs: Number(validationDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
1786
1787
|
validationError: "Stream options must include either input.text or input.audio",
|
1787
1788
|
message: "EXHAUSTIVE validation failure analysis with character-level debugging",
|
1788
1789
|
});
|
@@ -1797,7 +1798,7 @@ export class NeuroLink {
|
|
1797
1798
|
elapsedMs: Date.now() - startTime,
|
1798
1799
|
elapsedNs: (process.hrtime.bigint() - hrTimeStart).toString(),
|
1799
1800
|
validationDurationNs: validationDurationNs.toString(),
|
1800
|
-
validationDurationMs: Number(validationDurationNs) /
|
1801
|
+
validationDurationMs: Number(validationDurationNs) / NANOSECOND_TO_MS_DIVISOR,
|
1801
1802
|
inputTextValid: hasText,
|
1802
1803
|
inputAudioPresent: hasAudio,
|
1803
1804
|
inputTextLength: hasText ? options.input.text.length : 0,
|
@@ -2315,16 +2316,16 @@ export class NeuroLink {
|
|
2315
2316
|
this.emitter.emit("tool:start", toolName, params);
|
2316
2317
|
// Set default options
|
2317
2318
|
const finalOptions = {
|
2318
|
-
timeout: options?.timeout ||
|
2319
|
-
maxRetries: options?.maxRetries ||
|
2320
|
-
retryDelayMs: options?.retryDelayMs ||
|
2319
|
+
timeout: options?.timeout || TOOL_TIMEOUTS.EXECUTION_DEFAULT_MS, // 30 second default timeout
|
2320
|
+
maxRetries: options?.maxRetries || RETRY_ATTEMPTS.DEFAULT, // Default 2 retries for retriable errors
|
2321
|
+
retryDelayMs: options?.retryDelayMs || RETRY_DELAYS.BASE_MS, // 1 second delay between retries
|
2321
2322
|
};
|
2322
2323
|
// Track memory usage for tool execution
|
2323
2324
|
const { MemoryManager } = await import("./utils/performance.js");
|
2324
2325
|
const startMemory = MemoryManager.getMemoryUsageMB();
|
2325
2326
|
// Get or create circuit breaker for this tool
|
2326
2327
|
if (!this.toolCircuitBreakers.has(toolName)) {
|
2327
|
-
this.toolCircuitBreakers.set(toolName, new CircuitBreaker(
|
2328
|
+
this.toolCircuitBreakers.set(toolName, new CircuitBreaker(CIRCUIT_BREAKER.FAILURE_THRESHOLD, CIRCUIT_BREAKER_RESET_MS));
|
2328
2329
|
}
|
2329
2330
|
const circuitBreaker = this.toolCircuitBreakers.get(toolName);
|
2330
2331
|
// Initialize metrics for this tool if not exists
|
@@ -2647,10 +2648,10 @@ export class NeuroLink {
|
|
2647
2648
|
// Check memory usage after tool enumeration
|
2648
2649
|
const endMemory = MemoryManager.getMemoryUsageMB();
|
2649
2650
|
const memoryDelta = endMemory.heapUsed - startMemory.heapUsed;
|
2650
|
-
if (memoryDelta >
|
2651
|
+
if (memoryDelta > MEMORY_THRESHOLDS.LOW_USAGE_MB) {
|
2651
2652
|
mcpLogger.debug(`🔍 Tool listing used ${memoryDelta}MB memory (large tool registry detected)`);
|
2652
2653
|
// Optimized collection patterns should reduce memory usage significantly
|
2653
|
-
if (uniqueTools.length >
|
2654
|
+
if (uniqueTools.length > PERFORMANCE_THRESHOLDS.LARGE_TOOL_COLLECTION) {
|
2654
2655
|
mcpLogger.debug("💡 Tool collection optimized for large sets. Memory usage reduced through efficient object reuse.");
|
2655
2656
|
}
|
2656
2657
|
}
|
@@ -2722,7 +2723,7 @@ export class NeuroLink {
|
|
2722
2723
|
try {
|
2723
2724
|
const response = await fetch("http://localhost:11434/api/tags", {
|
2724
2725
|
method: "GET",
|
2725
|
-
signal: AbortSignal.timeout(
|
2726
|
+
signal: AbortSignal.timeout(PROVIDER_TIMEOUTS.AUTH_MS),
|
2726
2727
|
});
|
2727
2728
|
if (!response.ok) {
|
2728
2729
|
throw new Error("Ollama service not responding");
|
@@ -3099,7 +3100,7 @@ export class NeuroLink {
|
|
3099
3100
|
resetToolCircuitBreaker(toolName) {
|
3100
3101
|
if (this.toolCircuitBreakers.has(toolName)) {
|
3101
3102
|
// Create a new circuit breaker (effectively resets it)
|
3102
|
-
this.toolCircuitBreakers.set(toolName, new CircuitBreaker(
|
3103
|
+
this.toolCircuitBreakers.set(toolName, new CircuitBreaker(CIRCUIT_BREAKER.FAILURE_THRESHOLD, CIRCUIT_BREAKER_RESET_MS));
|
3103
3104
|
mcpLogger.info(`Circuit breaker reset for tool: ${toolName}`);
|
3104
3105
|
}
|
3105
3106
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { type LanguageModelV1 } from "ai";
|
2
2
|
import { BaseProvider } from "../core/baseProvider.js";
|
3
|
-
import type { AIProviderName } from "../types
|
3
|
+
import type { AIProviderName } from "../core/types.js";
|
4
4
|
import type { StreamOptions, StreamResult } from "../types/streamTypes.js";
|
5
5
|
export declare class AzureOpenAIProvider extends BaseProvider {
|
6
6
|
private apiKey;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { createAzure } from "@ai-sdk/azure";
|
2
2
|
import { streamText } from "ai";
|
3
3
|
import { BaseProvider } from "../core/baseProvider.js";
|
4
|
+
import { APIVersions } from "../core/types.js";
|
4
5
|
import { validateApiKey, createAzureAPIKeyConfig, createAzureEndpointConfig, } from "../utils/providerConfig.js";
|
5
6
|
import { logger } from "../utils/logger.js";
|
6
7
|
import { buildMessagesArray } from "../utils/messageBuilder.js";
|
@@ -24,7 +25,7 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
24
25
|
process.env.AZURE_OPENAI_DEPLOYMENT ||
|
25
26
|
process.env.AZURE_OPENAI_DEPLOYMENT_ID ||
|
26
27
|
"gpt-4o";
|
27
|
-
this.apiVersion = process.env.AZURE_API_VERSION ||
|
28
|
+
this.apiVersion = process.env.AZURE_API_VERSION || APIVersions.AZURE_LATEST;
|
28
29
|
// Configuration validation - now using consolidated utility
|
29
30
|
if (!this.apiKey) {
|
30
31
|
validateApiKey(createAzureAPIKeyConfig());
|
@@ -15,6 +15,31 @@ export interface ProviderConfigOptions {
|
|
15
15
|
instructions: string[];
|
16
16
|
fallbackEnvVars?: string[];
|
17
17
|
}
|
18
|
+
/**
|
19
|
+
* API key format validation patterns (extracted from advanced validation system)
|
20
|
+
* Exported for use across the codebase to replace scattered regex patterns
|
21
|
+
*/
|
22
|
+
export declare const API_KEY_FORMATS: Record<string, RegExp>;
|
23
|
+
/**
|
24
|
+
* API key length constants to replace scattered magic numbers
|
25
|
+
*/
|
26
|
+
export declare const API_KEY_LENGTHS: {
|
27
|
+
readonly OPENAI_MIN: 48;
|
28
|
+
readonly ANTHROPIC_MIN: 95;
|
29
|
+
readonly HUGGINGFACE_EXACT: 37;
|
30
|
+
readonly AZURE_MIN: 32;
|
31
|
+
readonly MISTRAL_EXACT: 32;
|
32
|
+
readonly AWS_ACCESS_KEY: 20;
|
33
|
+
readonly GOOGLE_AI_EXACT: 39;
|
34
|
+
};
|
35
|
+
/**
|
36
|
+
* Project ID format validation (for Google Cloud)
|
37
|
+
*/
|
38
|
+
export declare const PROJECT_ID_FORMAT: {
|
39
|
+
readonly MIN_LENGTH: 6;
|
40
|
+
readonly MAX_LENGTH: 30;
|
41
|
+
readonly PATTERN: RegExp;
|
42
|
+
};
|
18
43
|
/**
|
19
44
|
* Enhanced validation result with format checking
|
20
45
|
*/
|
@@ -6,16 +6,37 @@
|
|
6
6
|
*/
|
7
7
|
/**
|
8
8
|
* API key format validation patterns (extracted from advanced validation system)
|
9
|
+
* Exported for use across the codebase to replace scattered regex patterns
|
9
10
|
*/
|
10
|
-
const API_KEY_FORMATS = {
|
11
|
+
export const API_KEY_FORMATS = {
|
11
12
|
openai: /^sk-[A-Za-z0-9]{48,}$/,
|
12
13
|
anthropic: /^sk-ant-[A-Za-z0-9\-_]{95,}$/,
|
13
14
|
"google-ai": /^AIza[A-Za-z0-9\-_]{35}$/,
|
14
15
|
huggingface: /^hf_[A-Za-z0-9]{37}$/,
|
15
16
|
mistral: /^[A-Za-z0-9]{32}$/,
|
16
|
-
azure: /^[A-Za-z0-9]{32
|
17
|
+
azure: /^[A-Za-z0-9]{32}$/,
|
17
18
|
aws: /^[A-Z0-9]{20}$/, // Access Key ID format
|
18
|
-
|
19
|
+
bedrock: /^[A-Z0-9]{20}$/, // AWS access key ID: 20 uppercase alphanumerics
|
20
|
+
};
|
21
|
+
/**
|
22
|
+
* API key length constants to replace scattered magic numbers
|
23
|
+
*/
|
24
|
+
export const API_KEY_LENGTHS = {
|
25
|
+
OPENAI_MIN: 48, // OpenAI API keys minimum length
|
26
|
+
ANTHROPIC_MIN: 95, // Anthropic API keys minimum length
|
27
|
+
HUGGINGFACE_EXACT: 37, // HuggingFace tokens exact length
|
28
|
+
AZURE_MIN: 32, // Azure OpenAI API keys minimum length
|
29
|
+
MISTRAL_EXACT: 32, // Mistral API keys exact length
|
30
|
+
AWS_ACCESS_KEY: 20, // AWS access key ID exact length
|
31
|
+
GOOGLE_AI_EXACT: 39, // Google AI Studio keys exact length (with AIza prefix)
|
32
|
+
};
|
33
|
+
/**
|
34
|
+
* Project ID format validation (for Google Cloud)
|
35
|
+
*/
|
36
|
+
export const PROJECT_ID_FORMAT = {
|
37
|
+
MIN_LENGTH: 6, // Minimum project ID length
|
38
|
+
MAX_LENGTH: 30, // Maximum project ID length
|
39
|
+
PATTERN: /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/, // Google Cloud project ID format
|
19
40
|
};
|
20
41
|
/**
|
21
42
|
* Validates API key format for a specific provider
|
@@ -2,7 +2,7 @@
|
|
2
2
|
* Provider Health Checking System
|
3
3
|
* Prevents 500 errors by validating provider availability and configuration
|
4
4
|
*/
|
5
|
-
import { AIProviderName } from "../types
|
5
|
+
import { AIProviderName } from "../core/types.js";
|
6
6
|
export interface ProviderHealthStatus {
|
7
7
|
provider: AIProviderName;
|
8
8
|
isHealthy: boolean;
|
@@ -3,7 +3,8 @@
|
|
3
3
|
* Prevents 500 errors by validating provider availability and configuration
|
4
4
|
*/
|
5
5
|
import { logger } from "./logger.js";
|
6
|
-
import { AIProviderName } from "../types
|
6
|
+
import { AIProviderName, OpenAIModels, GoogleAIModels, AnthropicModels, BedrockModels, } from "../core/types.js";
|
7
|
+
import { API_KEY_LENGTHS, PROJECT_ID_FORMAT } from "./providerConfig.js";
|
7
8
|
import { basename } from "path";
|
8
9
|
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
9
10
|
export class ProviderHealthChecker {
|
@@ -402,17 +403,19 @@ export class ProviderHealthChecker {
|
|
402
403
|
static validateApiKeyFormat(providerName, apiKey) {
|
403
404
|
switch (providerName) {
|
404
405
|
case AIProviderName.ANTHROPIC:
|
405
|
-
return apiKey.startsWith("sk-ant-") &&
|
406
|
+
return (apiKey.startsWith("sk-ant-") &&
|
407
|
+
apiKey.length >= API_KEY_LENGTHS.ANTHROPIC_MIN);
|
406
408
|
case AIProviderName.OPENAI:
|
407
|
-
return apiKey.startsWith("sk-") &&
|
409
|
+
return (apiKey.startsWith("sk-") &&
|
410
|
+
apiKey.length >= API_KEY_LENGTHS.OPENAI_MIN);
|
408
411
|
case AIProviderName.GOOGLE_AI:
|
409
|
-
return apiKey.length
|
412
|
+
return apiKey.length >= API_KEY_LENGTHS.GOOGLE_AI_EXACT; // Basic length check
|
410
413
|
case AIProviderName.VERTEX:
|
411
414
|
return apiKey.endsWith(".json") || apiKey.includes("type"); // JSON key format
|
412
415
|
case AIProviderName.BEDROCK:
|
413
|
-
return apiKey.length >=
|
416
|
+
return apiKey.length >= API_KEY_LENGTHS.AWS_ACCESS_KEY; // AWS access key length
|
414
417
|
case AIProviderName.AZURE:
|
415
|
-
return apiKey.length >=
|
418
|
+
return apiKey.length >= API_KEY_LENGTHS.AZURE_MIN; // Azure OpenAI API key length
|
416
419
|
case AIProviderName.OLLAMA:
|
417
420
|
return true; // Ollama usually doesn't require specific format
|
418
421
|
default:
|
@@ -604,14 +607,14 @@ export class ProviderHealthChecker {
|
|
604
607
|
static checkBedrockModels(healthStatus) {
|
605
608
|
const bedrockModel = process.env.BEDROCK_MODEL || process.env.BEDROCK_MODEL_ID;
|
606
609
|
const supportedModels = [
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
+
BedrockModels.CLAUDE_3_SONNET,
|
611
|
+
BedrockModels.CLAUDE_3_HAIKU,
|
612
|
+
BedrockModels.CLAUDE_3_5_SONNET,
|
610
613
|
"anthropic.claude-v2:1",
|
611
614
|
"amazon.titan-text-express-v1",
|
612
615
|
];
|
613
616
|
if (!bedrockModel) {
|
614
|
-
healthStatus.recommendations.push(
|
617
|
+
healthStatus.recommendations.push(`Set BEDROCK_MODEL or BEDROCK_MODEL_ID for faster startup (e.g., ${BedrockModels.CLAUDE_3_SONNET})`);
|
615
618
|
}
|
616
619
|
else if (!supportedModels.includes(bedrockModel)) {
|
617
620
|
healthStatus.recommendations.push(`Consider using a popular Bedrock model: ${supportedModels.slice(0, 3).join(", ")}`);
|
@@ -658,39 +661,44 @@ export class ProviderHealthChecker {
|
|
658
661
|
switch (providerName) {
|
659
662
|
case AIProviderName.ANTHROPIC:
|
660
663
|
return [
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
+
AnthropicModels.CLAUDE_3_5_SONNET,
|
665
|
+
AnthropicModels.CLAUDE_3_HAIKU,
|
666
|
+
AnthropicModels.CLAUDE_3_OPUS,
|
664
667
|
];
|
665
668
|
case AIProviderName.OPENAI:
|
666
|
-
return [
|
669
|
+
return [
|
670
|
+
OpenAIModels.GPT_4O,
|
671
|
+
OpenAIModels.GPT_4O_MINI,
|
672
|
+
OpenAIModels.GPT_3_5_TURBO,
|
673
|
+
];
|
667
674
|
case AIProviderName.GOOGLE_AI:
|
668
|
-
return [
|
675
|
+
return [
|
676
|
+
GoogleAIModels.GEMINI_1_5_PRO,
|
677
|
+
GoogleAIModels.GEMINI_1_5_FLASH,
|
678
|
+
GoogleAIModels.GEMINI_2_5_PRO,
|
679
|
+
];
|
669
680
|
case AIProviderName.VERTEX:
|
670
681
|
return [
|
671
682
|
// Google models (via vertex provider)
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
683
|
+
GoogleAIModels.GEMINI_2_5_PRO,
|
684
|
+
GoogleAIModels.GEMINI_2_5_FLASH,
|
685
|
+
GoogleAIModels.GEMINI_2_5_FLASH_LITE,
|
686
|
+
GoogleAIModels.GEMINI_2_0_FLASH_001,
|
687
|
+
GoogleAIModels.GEMINI_1_5_PRO,
|
688
|
+
GoogleAIModels.GEMINI_1_5_FLASH,
|
678
689
|
// Anthropic models (via vertexAnthropic provider)
|
679
690
|
"claude-sonnet-4@20250514",
|
680
691
|
"claude-opus-4@20250514",
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
|
692
|
+
AnthropicModels.CLAUDE_3_5_SONNET,
|
693
|
+
AnthropicModels.CLAUDE_3_5_HAIKU,
|
694
|
+
AnthropicModels.CLAUDE_3_SONNET,
|
695
|
+
AnthropicModels.CLAUDE_3_HAIKU,
|
696
|
+
AnthropicModels.CLAUDE_3_OPUS,
|
686
697
|
];
|
687
698
|
case AIProviderName.BEDROCK:
|
688
|
-
return [
|
689
|
-
"anthropic.claude-3-sonnet-20240229-v1:0",
|
690
|
-
"anthropic.claude-3-haiku-20240307-v1:0",
|
691
|
-
];
|
699
|
+
return [BedrockModels.CLAUDE_3_SONNET, BedrockModels.CLAUDE_3_HAIKU];
|
692
700
|
case AIProviderName.AZURE:
|
693
|
-
return [
|
701
|
+
return [OpenAIModels.GPT_4O, OpenAIModels.GPT_4O_MINI, "gpt-35-turbo"];
|
694
702
|
case AIProviderName.OLLAMA:
|
695
703
|
return ["llama3.2:latest", "llama3.1:latest", "mistral:latest"];
|
696
704
|
default:
|
@@ -951,8 +959,7 @@ export class ProviderHealthChecker {
|
|
951
959
|
if (projectId) {
|
952
960
|
result.projectId = projectId;
|
953
961
|
// Validate project ID format
|
954
|
-
|
955
|
-
if (projectIdPattern.test(projectId)) {
|
962
|
+
if (PROJECT_ID_FORMAT.PATTERN.test(projectId)) {
|
956
963
|
result.isValid = true;
|
957
964
|
}
|
958
965
|
else {
|
@@ -2,6 +2,7 @@
|
|
2
2
|
* Enhanced Provider Setup Messages
|
3
3
|
* Provides detailed setup instructions for AI providers
|
4
4
|
*/
|
5
|
+
import { OpenAIModels, GoogleAIModels, AnthropicModels, APIVersions, } from "../core/types.js";
|
5
6
|
/**
|
6
7
|
* Generate enhanced error message with setup instructions
|
7
8
|
*/
|
@@ -12,7 +13,7 @@ export function getProviderSetupMessage(provider, missingVars) {
|
|
12
13
|
envVars: [
|
13
14
|
'OPENAI_API_KEY="sk-proj-your-openai-api-key"',
|
14
15
|
"# Optional:",
|
15
|
-
|
16
|
+
`OPENAI_MODEL="${OpenAIModels.GPT_4O}"`,
|
16
17
|
'OPENAI_BASE_URL="https://api.openai.com"',
|
17
18
|
],
|
18
19
|
},
|
@@ -21,7 +22,7 @@ export function getProviderSetupMessage(provider, missingVars) {
|
|
21
22
|
envVars: [
|
22
23
|
'ANTHROPIC_API_KEY="sk-ant-api03-your-anthropic-key"',
|
23
24
|
"# Optional:",
|
24
|
-
|
25
|
+
`ANTHROPIC_MODEL="${AnthropicModels.CLAUDE_3_5_SONNET}"`,
|
25
26
|
],
|
26
27
|
},
|
27
28
|
"google-ai": {
|
@@ -29,7 +30,7 @@ export function getProviderSetupMessage(provider, missingVars) {
|
|
29
30
|
envVars: [
|
30
31
|
'GOOGLE_AI_API_KEY="AIza-your-google-ai-api-key"',
|
31
32
|
"# Optional:",
|
32
|
-
|
33
|
+
`GOOGLE_AI_MODEL="${GoogleAIModels.GEMINI_2_5_PRO}"`,
|
33
34
|
],
|
34
35
|
},
|
35
36
|
vertex: {
|
@@ -39,7 +40,7 @@ export function getProviderSetupMessage(provider, missingVars) {
|
|
39
40
|
'GOOGLE_VERTEX_PROJECT="your-gcp-project-id"',
|
40
41
|
'GOOGLE_VERTEX_LOCATION="us-central1"',
|
41
42
|
"# Optional:",
|
42
|
-
|
43
|
+
`VERTEX_MODEL="${GoogleAIModels.GEMINI_2_5_PRO}"`,
|
43
44
|
],
|
44
45
|
},
|
45
46
|
bedrock: {
|
@@ -61,8 +62,8 @@ export function getProviderSetupMessage(provider, missingVars) {
|
|
61
62
|
'AZURE_OPENAI_ENDPOINT="https://your-resource.openai.azure.com/"',
|
62
63
|
'AZURE_OPENAI_DEPLOYMENT_ID="your-deployment-name"',
|
63
64
|
"# Optional:",
|
64
|
-
|
65
|
-
|
65
|
+
`AZURE_MODEL="${OpenAIModels.GPT_4O}"`,
|
66
|
+
`AZURE_API_VERSION="${APIVersions.AZURE_STABLE}"`,
|
66
67
|
],
|
67
68
|
},
|
68
69
|
huggingface: {
|