@juspay/neurolink 7.29.0 → 7.29.2
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 +3 -3
- package/dist/cli/commands/mcp.js +25 -0
- package/dist/cli/factories/commandFactory.d.ts +1 -0
- package/dist/cli/factories/commandFactory.js +115 -21
- package/dist/cli/index.js +8 -0
- package/dist/core/factory.js +77 -4
- package/dist/factories/providerFactory.js +3 -0
- package/dist/factories/providerRegistry.js +2 -2
- package/dist/lib/core/factory.js +77 -4
- package/dist/lib/factories/providerFactory.js +3 -0
- package/dist/lib/factories/providerRegistry.js +2 -2
- package/dist/lib/mcp/externalServerManager.js +13 -14
- package/dist/lib/mcp/flexibleToolValidator.d.ts +50 -0
- package/dist/lib/mcp/flexibleToolValidator.js +161 -0
- package/dist/lib/mcp/toolRegistry.d.ts +2 -2
- package/dist/lib/mcp/toolRegistry.js +25 -50
- package/dist/lib/neurolink.d.ts +299 -4
- package/dist/lib/neurolink.js +434 -73
- package/dist/lib/providers/amazonBedrock.d.ts +47 -6
- package/dist/lib/providers/amazonBedrock.js +282 -23
- package/dist/lib/providers/aws/credentialProvider.d.ts +58 -0
- package/dist/lib/providers/aws/credentialProvider.js +267 -0
- package/dist/lib/providers/aws/credentialTester.d.ts +49 -0
- package/dist/lib/providers/aws/credentialTester.js +394 -0
- package/dist/lib/providers/googleVertex.js +13 -4
- package/dist/lib/proxy/awsProxyIntegration.d.ts +23 -0
- package/dist/lib/proxy/awsProxyIntegration.js +285 -0
- package/dist/lib/proxy/proxyFetch.d.ts +9 -5
- package/dist/lib/proxy/proxyFetch.js +232 -98
- package/dist/lib/proxy/utils/noProxyUtils.d.ts +39 -0
- package/dist/lib/proxy/utils/noProxyUtils.js +149 -0
- package/dist/lib/types/providers.d.ts +43 -0
- package/dist/lib/utils/providerConfig.d.ts +1 -0
- package/dist/lib/utils/providerConfig.js +2 -1
- package/dist/lib/utils/providerHealth.js +123 -5
- package/dist/mcp/externalServerManager.js +13 -14
- package/dist/mcp/flexibleToolValidator.d.ts +50 -0
- package/dist/mcp/flexibleToolValidator.js +161 -0
- package/dist/mcp/toolRegistry.d.ts +2 -2
- package/dist/mcp/toolRegistry.js +25 -50
- package/dist/neurolink.d.ts +299 -4
- package/dist/neurolink.js +434 -73
- package/dist/providers/amazonBedrock.d.ts +47 -6
- package/dist/providers/amazonBedrock.js +282 -23
- package/dist/providers/aws/credentialProvider.d.ts +58 -0
- package/dist/providers/aws/credentialProvider.js +267 -0
- package/dist/providers/aws/credentialTester.d.ts +49 -0
- package/dist/providers/aws/credentialTester.js +394 -0
- package/dist/providers/googleVertex.js +13 -4
- package/dist/proxy/awsProxyIntegration.d.ts +23 -0
- package/dist/proxy/awsProxyIntegration.js +285 -0
- package/dist/proxy/proxyFetch.d.ts +9 -5
- package/dist/proxy/proxyFetch.js +232 -98
- package/dist/proxy/utils/noProxyUtils.d.ts +39 -0
- package/dist/proxy/utils/noProxyUtils.js +149 -0
- package/dist/types/providers.d.ts +43 -0
- package/dist/utils/providerConfig.d.ts +1 -0
- package/dist/utils/providerConfig.js +2 -1
- package/dist/utils/providerHealth.js +123 -5
- package/package.json +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## [7.29.2](https://github.com/juspay/neurolink/compare/v7.29.1...v7.29.2) (2025-08-29)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **(providers):** enable drop-in replacement for bedrock-mcp-connector ([9b67d23](https://github.com/juspay/neurolink/commit/9b67d233c2e8400a401759e34ffaf46a9a9c77a8))
|
|
6
|
+
|
|
7
|
+
## [7.29.1](https://github.com/juspay/neurolink/compare/v7.29.0...v7.29.1) (2025-08-28)
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **(vertex):** restored support for adc ([238666a](https://github.com/juspay/neurolink/commit/238666ab907fc16945d5de6c5f79637be128f4e6))
|
|
12
|
+
|
|
1
13
|
## [7.29.0](https://github.com/juspay/neurolink/compare/v7.28.1...v7.29.0) (2025-08-26)
|
|
2
14
|
|
|
3
15
|
### Features
|
|
@@ -60,8 +60,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
60
60
|
}, {
|
|
61
61
|
model?: string | undefined;
|
|
62
62
|
projectId?: string | undefined;
|
|
63
|
-
location?: string | undefined;
|
|
64
63
|
credentials?: string | undefined;
|
|
64
|
+
location?: string | undefined;
|
|
65
65
|
serviceAccountKey?: string | undefined;
|
|
66
66
|
clientEmail?: string | undefined;
|
|
67
67
|
privateKey?: string | undefined;
|
|
@@ -201,8 +201,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
201
201
|
vertex?: {
|
|
202
202
|
model?: string | undefined;
|
|
203
203
|
projectId?: string | undefined;
|
|
204
|
-
location?: string | undefined;
|
|
205
204
|
credentials?: string | undefined;
|
|
205
|
+
location?: string | undefined;
|
|
206
206
|
serviceAccountKey?: string | undefined;
|
|
207
207
|
clientEmail?: string | undefined;
|
|
208
208
|
privateKey?: string | undefined;
|
|
@@ -570,8 +570,8 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
570
570
|
vertex?: {
|
|
571
571
|
model?: string | undefined;
|
|
572
572
|
projectId?: string | undefined;
|
|
573
|
-
location?: string | undefined;
|
|
574
573
|
credentials?: string | undefined;
|
|
574
|
+
location?: string | undefined;
|
|
575
575
|
serviceAccountKey?: string | undefined;
|
|
576
576
|
clientEmail?: string | undefined;
|
|
577
577
|
privateKey?: string | undefined;
|
package/dist/cli/commands/mcp.js
CHANGED
|
@@ -10,6 +10,31 @@ import chalk from "chalk";
|
|
|
10
10
|
import ora from "ora";
|
|
11
11
|
import fs from "fs";
|
|
12
12
|
import path from "path";
|
|
13
|
+
// Using MCPCommandArgs from types/cli.ts
|
|
14
|
+
/**
|
|
15
|
+
* Response interface for MCP status information returned from the NeuroLink SDK.
|
|
16
|
+
* This interface represents the raw status data that gets converted to CLI-friendly format.
|
|
17
|
+
*
|
|
18
|
+
* @interface MCPStatusResponse
|
|
19
|
+
* @since 7.6.1
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const status: MCPStatusResponse = {
|
|
24
|
+
* autoDiscoveredServers: [
|
|
25
|
+
* {
|
|
26
|
+
* name: "filesystem",
|
|
27
|
+
* id: "fs-server-001",
|
|
28
|
+
* status: "connected",
|
|
29
|
+
* source: "claude-desktop"
|
|
30
|
+
* }
|
|
31
|
+
* ],
|
|
32
|
+
* mcpInitialized: true,
|
|
33
|
+
* totalServers: 3,
|
|
34
|
+
* availableServers: 2
|
|
35
|
+
* };
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
13
38
|
/**
|
|
14
39
|
* Popular MCP servers registry
|
|
15
40
|
*/
|
|
@@ -8,6 +8,7 @@ export declare class CLICommandFactory {
|
|
|
8
8
|
private static processOptions;
|
|
9
9
|
private static handleOutput;
|
|
10
10
|
private static isValidTokenUsage;
|
|
11
|
+
private static normalizeTokenUsage;
|
|
11
12
|
private static formatAnalyticsForTextMode;
|
|
12
13
|
/**
|
|
13
14
|
* Create the new primary 'generate' command
|
|
@@ -273,14 +273,53 @@ export class CLICommandFactory {
|
|
|
273
273
|
logger.always(output);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
276
|
-
// Helper method to validate token usage data
|
|
276
|
+
// Helper method to validate token usage data with fallback handling
|
|
277
277
|
static isValidTokenUsage(tokens) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
278
|
+
if (!tokens || typeof tokens !== "object" || tokens === null) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
const tokensObj = tokens;
|
|
282
|
+
// Check primary format: analytics.tokens {input, output, total}
|
|
283
|
+
if (typeof tokensObj.input === "number" &&
|
|
284
|
+
typeof tokensObj.output === "number" &&
|
|
285
|
+
typeof tokensObj.total === "number") {
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
// Check fallback format: tokenUsage {inputTokens, outputTokens, totalTokens}
|
|
289
|
+
if (typeof tokensObj.inputTokens === "number" &&
|
|
290
|
+
typeof tokensObj.outputTokens === "number" &&
|
|
291
|
+
typeof tokensObj.totalTokens === "number") {
|
|
292
|
+
return true;
|
|
293
|
+
}
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
// Helper method to normalize token usage data to standard format
|
|
297
|
+
static normalizeTokenUsage(tokens) {
|
|
298
|
+
if (!this.isValidTokenUsage(tokens)) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const tokensObj = tokens;
|
|
302
|
+
// Primary format: analytics.tokens {input, output, total}
|
|
303
|
+
if (typeof tokensObj.input === "number" &&
|
|
304
|
+
typeof tokensObj.output === "number" &&
|
|
305
|
+
typeof tokensObj.total === "number") {
|
|
306
|
+
return {
|
|
307
|
+
input: tokensObj.input,
|
|
308
|
+
output: tokensObj.output,
|
|
309
|
+
total: tokensObj.total,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
// Fallback format: tokenUsage {inputTokens, outputTokens, totalTokens}
|
|
313
|
+
if (typeof tokensObj.inputTokens === "number" &&
|
|
314
|
+
typeof tokensObj.outputTokens === "number" &&
|
|
315
|
+
typeof tokensObj.totalTokens === "number") {
|
|
316
|
+
return {
|
|
317
|
+
input: tokensObj.inputTokens,
|
|
318
|
+
output: tokensObj.outputTokens,
|
|
319
|
+
total: tokensObj.totalTokens,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
return null;
|
|
284
323
|
}
|
|
285
324
|
// Helper method to format analytics for text mode display
|
|
286
325
|
static formatAnalyticsForTextMode(result) {
|
|
@@ -299,10 +338,10 @@ export class CLICommandFactory {
|
|
|
299
338
|
analyticsText += ` (${modelName})`;
|
|
300
339
|
}
|
|
301
340
|
analyticsText += "\n";
|
|
302
|
-
// Token usage
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
analyticsText += ` Tokens: ${
|
|
341
|
+
// Token usage with fallback handling
|
|
342
|
+
const normalizedTokens = this.normalizeTokenUsage(analytics.tokens);
|
|
343
|
+
if (normalizedTokens) {
|
|
344
|
+
analyticsText += ` Tokens: ${normalizedTokens.input} input + ${normalizedTokens.output} output = ${normalizedTokens.total} total\n`;
|
|
306
345
|
}
|
|
307
346
|
// Cost information
|
|
308
347
|
if (analytics.cost !== undefined &&
|
|
@@ -310,9 +349,12 @@ export class CLICommandFactory {
|
|
|
310
349
|
typeof analytics.cost === "number") {
|
|
311
350
|
analyticsText += ` Cost: $${analytics.cost.toFixed(5)}\n`;
|
|
312
351
|
}
|
|
313
|
-
// Response time
|
|
314
|
-
|
|
315
|
-
|
|
352
|
+
// Response time with fallback handling for requestDuration vs responseTime
|
|
353
|
+
const duration = analytics.responseTime ||
|
|
354
|
+
analytics.requestDuration ||
|
|
355
|
+
analytics.duration;
|
|
356
|
+
if (duration && typeof duration === "number") {
|
|
357
|
+
const timeInSeconds = (duration / 1000).toFixed(1);
|
|
316
358
|
analyticsText += ` Time: ${timeInSeconds}s\n`;
|
|
317
359
|
}
|
|
318
360
|
// Tools used
|
|
@@ -935,14 +977,66 @@ export class CLICommandFactory {
|
|
|
935
977
|
: undefined,
|
|
936
978
|
});
|
|
937
979
|
let fullContent = "";
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
980
|
+
let contentReceived = false;
|
|
981
|
+
const abortController = new AbortController();
|
|
982
|
+
// Create timeout promise for stream consumption (30 seconds)
|
|
983
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
984
|
+
const timeoutId = setTimeout(() => {
|
|
985
|
+
if (!contentReceived) {
|
|
986
|
+
const timeoutError = new Error("\n❌ Stream timeout - no content received within 30 seconds\n" +
|
|
987
|
+
"This usually indicates authentication or network issues\n\n" +
|
|
988
|
+
"🔧 Try these steps:\n" +
|
|
989
|
+
"1. Check your provider credentials are configured correctly\n" +
|
|
990
|
+
`2. Test generate mode: neurolink generate "test" --provider ${options.provider}\n` +
|
|
991
|
+
`3. Use debug mode: neurolink stream "test" --provider ${options.provider} --debug`);
|
|
992
|
+
reject(timeoutError);
|
|
993
|
+
}
|
|
994
|
+
}, 30000);
|
|
995
|
+
// Clean up timeout when aborted
|
|
996
|
+
abortController.signal.addEventListener("abort", () => {
|
|
997
|
+
clearTimeout(timeoutId);
|
|
998
|
+
});
|
|
999
|
+
});
|
|
1000
|
+
try {
|
|
1001
|
+
// Process the stream with timeout handling
|
|
1002
|
+
const streamIterator = stream.stream[Symbol.asyncIterator]();
|
|
1003
|
+
let timeoutActive = true;
|
|
1004
|
+
while (true) {
|
|
1005
|
+
let nextResult;
|
|
1006
|
+
if (timeoutActive && !contentReceived) {
|
|
1007
|
+
// Race between next chunk and timeout for first chunk only
|
|
1008
|
+
nextResult = await Promise.race([
|
|
1009
|
+
streamIterator.next(),
|
|
1010
|
+
timeoutPromise,
|
|
1011
|
+
]);
|
|
1012
|
+
}
|
|
1013
|
+
else {
|
|
1014
|
+
// No timeout for subsequent chunks
|
|
1015
|
+
nextResult = await streamIterator.next();
|
|
1016
|
+
}
|
|
1017
|
+
if (nextResult.done) {
|
|
1018
|
+
break;
|
|
1019
|
+
}
|
|
1020
|
+
if (!contentReceived) {
|
|
1021
|
+
contentReceived = true;
|
|
1022
|
+
timeoutActive = false;
|
|
1023
|
+
abortController.abort(); // Cancel timeout
|
|
1024
|
+
}
|
|
1025
|
+
if (options.delay && options.delay > 0) {
|
|
1026
|
+
// Demo mode - add delay between chunks
|
|
1027
|
+
await new Promise((resolve) => setTimeout(resolve, options.delay));
|
|
1028
|
+
}
|
|
1029
|
+
process.stdout.write(nextResult.value.content);
|
|
1030
|
+
fullContent += nextResult.value.content;
|
|
943
1031
|
}
|
|
944
|
-
|
|
945
|
-
|
|
1032
|
+
}
|
|
1033
|
+
catch (error) {
|
|
1034
|
+
abortController.abort(); // Clean up timeout
|
|
1035
|
+
throw error;
|
|
1036
|
+
}
|
|
1037
|
+
if (!contentReceived) {
|
|
1038
|
+
throw new Error("\n❌ No content received from stream\n" +
|
|
1039
|
+
"Check your credentials and provider configuration");
|
|
946
1040
|
}
|
|
947
1041
|
if (!options.quiet) {
|
|
948
1042
|
process.stdout.write("\n");
|
package/dist/cli/index.js
CHANGED
|
@@ -14,6 +14,14 @@ import { fileURLToPath } from "url";
|
|
|
14
14
|
import { CLICommandFactory } from "./factories/commandFactory.js";
|
|
15
15
|
import { AuthenticationError, AuthorizationError, NetworkError, RateLimitError, } from "../lib/types/errors.js";
|
|
16
16
|
import { logger } from "../lib/utils/logger.js";
|
|
17
|
+
// Clean up pnpm-specific environment variables that cause npm warnings
|
|
18
|
+
// These variables are set by pnpm but cause "Unknown env config" warnings in npm
|
|
19
|
+
if (process.env.npm_config_verify_deps_before_run) {
|
|
20
|
+
delete process.env.npm_config_verify_deps_before_run;
|
|
21
|
+
}
|
|
22
|
+
if (process.env.npm_config__jsr_registry) {
|
|
23
|
+
delete process.env.npm_config__jsr_registry;
|
|
24
|
+
}
|
|
17
25
|
// Get version from package.json
|
|
18
26
|
const __filename = fileURLToPath(import.meta.url);
|
|
19
27
|
const __dirname = path.dirname(__filename);
|
package/dist/core/factory.js
CHANGED
|
@@ -55,12 +55,18 @@ export class AIProviderFactory {
|
|
|
55
55
|
* @returns AIProvider instance
|
|
56
56
|
*/
|
|
57
57
|
static async createProvider(providerName, modelName, enableMCP = true, sdk) {
|
|
58
|
-
const functionTag = "
|
|
58
|
+
const functionTag = "AIProviderFactory.createProvider";
|
|
59
59
|
// Providers are registered via ProviderFactory.initialize() on first use
|
|
60
60
|
logger.debug(`[${functionTag}] Provider creation started`, {
|
|
61
61
|
providerName,
|
|
62
62
|
modelName: modelName || "default",
|
|
63
63
|
enableMCP,
|
|
64
|
+
environmentVariables: {
|
|
65
|
+
BEDROCK_MODEL: process.env.BEDROCK_MODEL || "not set",
|
|
66
|
+
BEDROCK_MODEL_ID: process.env.BEDROCK_MODEL_ID || "not set",
|
|
67
|
+
VERTEX_MODEL: process.env.VERTEX_MODEL || "not set",
|
|
68
|
+
OPENAI_MODEL: process.env.OPENAI_MODEL || "not set",
|
|
69
|
+
},
|
|
64
70
|
});
|
|
65
71
|
try {
|
|
66
72
|
// DYNAMIC MODEL PROVIDER STATUS (2025): Enhanced with timeout handling
|
|
@@ -73,12 +79,57 @@ export class AIProviderFactory {
|
|
|
73
79
|
//
|
|
74
80
|
// The dynamic model provider now provides reliable functionality without hanging
|
|
75
81
|
let resolvedModelName = modelName;
|
|
76
|
-
//
|
|
82
|
+
// PRIORITY 1: Check environment variables BEFORE dynamic resolution
|
|
77
83
|
if (!modelName || modelName === "default") {
|
|
84
|
+
logger.debug(`[${functionTag}] Checking environment variables for provider: ${providerName}`);
|
|
85
|
+
// Check for provider-specific environment variables first
|
|
86
|
+
if (providerName.toLowerCase().includes("bedrock")) {
|
|
87
|
+
const envModel = process.env.BEDROCK_MODEL || process.env.BEDROCK_MODEL_ID;
|
|
88
|
+
if (envModel) {
|
|
89
|
+
resolvedModelName = envModel;
|
|
90
|
+
logger.debug(`[${functionTag}] Environment variable found for Bedrock`, {
|
|
91
|
+
envVariable: process.env.BEDROCK_MODEL
|
|
92
|
+
? "BEDROCK_MODEL"
|
|
93
|
+
: "BEDROCK_MODEL_ID",
|
|
94
|
+
resolvedModel: envModel,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
logger.debug(`[${functionTag}] No Bedrock environment variables found (BEDROCK_MODEL, BEDROCK_MODEL_ID)`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (providerName.toLowerCase().includes("vertex")) {
|
|
102
|
+
const envModel = process.env.VERTEX_MODEL;
|
|
103
|
+
if (envModel) {
|
|
104
|
+
resolvedModelName = envModel;
|
|
105
|
+
logger.debug(`[${functionTag}] Environment variable found for Vertex`, {
|
|
106
|
+
envVariable: "VERTEX_MODEL",
|
|
107
|
+
resolvedModel: envModel,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
logger.debug(`[${functionTag}] No Vertex environment variables found (VERTEX_MODEL)`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
logger.debug(`[${functionTag}] Provider ${providerName} - no environment variable check implemented`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
logger.debug(`[${functionTag}] Skipping environment variable check - explicit model provided: ${modelName}`);
|
|
120
|
+
}
|
|
121
|
+
// PRIORITY 2: Enable dynamic model resolution only if no env var found
|
|
122
|
+
if ((!resolvedModelName || resolvedModelName === "default") &&
|
|
123
|
+
(!modelName || modelName === "default")) {
|
|
124
|
+
logger.debug(`[${functionTag}] Attempting dynamic model resolution`, {
|
|
125
|
+
currentResolvedModel: resolvedModelName || "none",
|
|
126
|
+
reason: "No environment variable found and no explicit model provided",
|
|
127
|
+
});
|
|
78
128
|
try {
|
|
79
129
|
const normalizedProvider = this.normalizeProviderName(providerName);
|
|
80
130
|
// Initialize with timeout protection - won't hang anymore
|
|
81
131
|
if (dynamicModelProvider.needsRefresh()) {
|
|
132
|
+
logger.debug(`[${functionTag}] Dynamic model provider needs refresh - initializing`);
|
|
82
133
|
await this.initializeDynamicProviderWithTimeout();
|
|
83
134
|
}
|
|
84
135
|
const dynamicModel = dynamicModelProvider.resolveModel(normalizedProvider, modelName || undefined);
|
|
@@ -92,6 +143,12 @@ export class AIProviderFactory {
|
|
|
92
143
|
pricing: dynamicModel.pricing.input,
|
|
93
144
|
});
|
|
94
145
|
}
|
|
146
|
+
else {
|
|
147
|
+
logger.debug(`[${functionTag}] Dynamic model resolution returned null`, {
|
|
148
|
+
provider: normalizedProvider,
|
|
149
|
+
requestedModel: modelName || "default",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
95
152
|
}
|
|
96
153
|
catch (resolveError) {
|
|
97
154
|
logger.debug(`[${functionTag}] Dynamic model resolution failed, using static fallback`, {
|
|
@@ -102,6 +159,12 @@ export class AIProviderFactory {
|
|
|
102
159
|
// Continue with static model name - no functionality loss
|
|
103
160
|
}
|
|
104
161
|
}
|
|
162
|
+
else {
|
|
163
|
+
logger.debug(`[${functionTag}] Skipping dynamic model resolution`, {
|
|
164
|
+
resolvedModelName: resolvedModelName || "none",
|
|
165
|
+
reason: "Model already resolved from environment variables or explicit parameter",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
105
168
|
// CRITICAL FIX: Initialize providers before using them
|
|
106
169
|
await ProviderRegistry.registerAllProviders();
|
|
107
170
|
// PURE FACTORY PATTERN: No switch statements - use ProviderFactory exclusively
|
|
@@ -109,8 +172,18 @@ export class AIProviderFactory {
|
|
|
109
172
|
const finalModelName = resolvedModelName === "default" || resolvedModelName === null
|
|
110
173
|
? undefined
|
|
111
174
|
: resolvedModelName;
|
|
175
|
+
logger.debug(`[${functionTag}] Final provider configuration`, {
|
|
176
|
+
originalProviderName: providerName,
|
|
177
|
+
normalizedProviderName: normalizedName,
|
|
178
|
+
originalModelName: modelName || "not provided",
|
|
179
|
+
resolvedModelName: resolvedModelName || "not resolved",
|
|
180
|
+
finalModelName: finalModelName || "using provider default",
|
|
181
|
+
});
|
|
112
182
|
// Create provider with enhanced SDK
|
|
113
183
|
const provider = await ProviderFactory.createProvider(normalizedName, finalModelName, sdk);
|
|
184
|
+
// Summary logging in format expected by debugging tools
|
|
185
|
+
logger.debug(`[AIProviderFactory] Provider creation completed { providerName: '${normalizedName}', modelName: '${finalModelName}' }`);
|
|
186
|
+
logger.debug(`[AIProviderFactory] Resolved model: ${finalModelName}`);
|
|
114
187
|
logger.debug(componentIdentifier, "Pure factory pattern provider created", {
|
|
115
188
|
providerName: normalizedName,
|
|
116
189
|
modelName: finalModelName,
|
|
@@ -153,7 +226,7 @@ export class AIProviderFactory {
|
|
|
153
226
|
* @returns AIProvider instance
|
|
154
227
|
*/
|
|
155
228
|
static async createProviderWithModel(provider, model) {
|
|
156
|
-
const functionTag = "
|
|
229
|
+
const functionTag = "AIProviderFactory.createProviderWithModel";
|
|
157
230
|
logger.debug(`[${functionTag}] Provider model creation started`, {
|
|
158
231
|
provider,
|
|
159
232
|
model,
|
|
@@ -214,7 +287,7 @@ export class AIProviderFactory {
|
|
|
214
287
|
* @returns Object with primary and fallback providers
|
|
215
288
|
*/
|
|
216
289
|
static async createProviderWithFallback(primaryProvider, fallbackProvider, modelName, enableMCP = true) {
|
|
217
|
-
const functionTag = "
|
|
290
|
+
const functionTag = "AIProviderFactory.createProviderWithFallback";
|
|
218
291
|
logger.debug(`[${functionTag}] Fallback provider setup started`, {
|
|
219
292
|
primaryProvider,
|
|
220
293
|
fallbackProvider,
|
|
@@ -42,6 +42,9 @@ export class ProviderFactory {
|
|
|
42
42
|
if (providerName.toLowerCase().includes("vertex")) {
|
|
43
43
|
model = process.env.VERTEX_MODEL;
|
|
44
44
|
}
|
|
45
|
+
else if (providerName.toLowerCase().includes("bedrock")) {
|
|
46
|
+
model = process.env.BEDROCK_MODEL || process.env.BEDROCK_MODEL_ID;
|
|
47
|
+
}
|
|
45
48
|
// Fallback to registry default if no env var
|
|
46
49
|
model = model || registration.defaultModel;
|
|
47
50
|
}
|
|
@@ -39,9 +39,9 @@ export class ProviderRegistry {
|
|
|
39
39
|
return new AnthropicProvider(modelName, sdk);
|
|
40
40
|
}, "claude-3-5-sonnet-20241022", ["claude", "anthropic"]);
|
|
41
41
|
// Register Amazon Bedrock provider
|
|
42
|
-
ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName) => {
|
|
42
|
+
ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName, _providerName, sdk) => {
|
|
43
43
|
const { AmazonBedrockProvider } = await import("../providers/amazonBedrock.js");
|
|
44
|
-
return new AmazonBedrockProvider(modelName);
|
|
44
|
+
return new AmazonBedrockProvider(modelName, undefined, sdk);
|
|
45
45
|
}, undefined, // Let provider read BEDROCK_MODEL from .env
|
|
46
46
|
["bedrock", "aws"]);
|
|
47
47
|
// Register Azure OpenAI provider
|
package/dist/lib/core/factory.js
CHANGED
|
@@ -55,12 +55,18 @@ export class AIProviderFactory {
|
|
|
55
55
|
* @returns AIProvider instance
|
|
56
56
|
*/
|
|
57
57
|
static async createProvider(providerName, modelName, enableMCP = true, sdk) {
|
|
58
|
-
const functionTag = "
|
|
58
|
+
const functionTag = "AIProviderFactory.createProvider";
|
|
59
59
|
// Providers are registered via ProviderFactory.initialize() on first use
|
|
60
60
|
logger.debug(`[${functionTag}] Provider creation started`, {
|
|
61
61
|
providerName,
|
|
62
62
|
modelName: modelName || "default",
|
|
63
63
|
enableMCP,
|
|
64
|
+
environmentVariables: {
|
|
65
|
+
BEDROCK_MODEL: process.env.BEDROCK_MODEL || "not set",
|
|
66
|
+
BEDROCK_MODEL_ID: process.env.BEDROCK_MODEL_ID || "not set",
|
|
67
|
+
VERTEX_MODEL: process.env.VERTEX_MODEL || "not set",
|
|
68
|
+
OPENAI_MODEL: process.env.OPENAI_MODEL || "not set",
|
|
69
|
+
},
|
|
64
70
|
});
|
|
65
71
|
try {
|
|
66
72
|
// DYNAMIC MODEL PROVIDER STATUS (2025): Enhanced with timeout handling
|
|
@@ -73,12 +79,57 @@ export class AIProviderFactory {
|
|
|
73
79
|
//
|
|
74
80
|
// The dynamic model provider now provides reliable functionality without hanging
|
|
75
81
|
let resolvedModelName = modelName;
|
|
76
|
-
//
|
|
82
|
+
// PRIORITY 1: Check environment variables BEFORE dynamic resolution
|
|
77
83
|
if (!modelName || modelName === "default") {
|
|
84
|
+
logger.debug(`[${functionTag}] Checking environment variables for provider: ${providerName}`);
|
|
85
|
+
// Check for provider-specific environment variables first
|
|
86
|
+
if (providerName.toLowerCase().includes("bedrock")) {
|
|
87
|
+
const envModel = process.env.BEDROCK_MODEL || process.env.BEDROCK_MODEL_ID;
|
|
88
|
+
if (envModel) {
|
|
89
|
+
resolvedModelName = envModel;
|
|
90
|
+
logger.debug(`[${functionTag}] Environment variable found for Bedrock`, {
|
|
91
|
+
envVariable: process.env.BEDROCK_MODEL
|
|
92
|
+
? "BEDROCK_MODEL"
|
|
93
|
+
: "BEDROCK_MODEL_ID",
|
|
94
|
+
resolvedModel: envModel,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
logger.debug(`[${functionTag}] No Bedrock environment variables found (BEDROCK_MODEL, BEDROCK_MODEL_ID)`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else if (providerName.toLowerCase().includes("vertex")) {
|
|
102
|
+
const envModel = process.env.VERTEX_MODEL;
|
|
103
|
+
if (envModel) {
|
|
104
|
+
resolvedModelName = envModel;
|
|
105
|
+
logger.debug(`[${functionTag}] Environment variable found for Vertex`, {
|
|
106
|
+
envVariable: "VERTEX_MODEL",
|
|
107
|
+
resolvedModel: envModel,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
logger.debug(`[${functionTag}] No Vertex environment variables found (VERTEX_MODEL)`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
logger.debug(`[${functionTag}] Provider ${providerName} - no environment variable check implemented`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
logger.debug(`[${functionTag}] Skipping environment variable check - explicit model provided: ${modelName}`);
|
|
120
|
+
}
|
|
121
|
+
// PRIORITY 2: Enable dynamic model resolution only if no env var found
|
|
122
|
+
if ((!resolvedModelName || resolvedModelName === "default") &&
|
|
123
|
+
(!modelName || modelName === "default")) {
|
|
124
|
+
logger.debug(`[${functionTag}] Attempting dynamic model resolution`, {
|
|
125
|
+
currentResolvedModel: resolvedModelName || "none",
|
|
126
|
+
reason: "No environment variable found and no explicit model provided",
|
|
127
|
+
});
|
|
78
128
|
try {
|
|
79
129
|
const normalizedProvider = this.normalizeProviderName(providerName);
|
|
80
130
|
// Initialize with timeout protection - won't hang anymore
|
|
81
131
|
if (dynamicModelProvider.needsRefresh()) {
|
|
132
|
+
logger.debug(`[${functionTag}] Dynamic model provider needs refresh - initializing`);
|
|
82
133
|
await this.initializeDynamicProviderWithTimeout();
|
|
83
134
|
}
|
|
84
135
|
const dynamicModel = dynamicModelProvider.resolveModel(normalizedProvider, modelName || undefined);
|
|
@@ -92,6 +143,12 @@ export class AIProviderFactory {
|
|
|
92
143
|
pricing: dynamicModel.pricing.input,
|
|
93
144
|
});
|
|
94
145
|
}
|
|
146
|
+
else {
|
|
147
|
+
logger.debug(`[${functionTag}] Dynamic model resolution returned null`, {
|
|
148
|
+
provider: normalizedProvider,
|
|
149
|
+
requestedModel: modelName || "default",
|
|
150
|
+
});
|
|
151
|
+
}
|
|
95
152
|
}
|
|
96
153
|
catch (resolveError) {
|
|
97
154
|
logger.debug(`[${functionTag}] Dynamic model resolution failed, using static fallback`, {
|
|
@@ -102,6 +159,12 @@ export class AIProviderFactory {
|
|
|
102
159
|
// Continue with static model name - no functionality loss
|
|
103
160
|
}
|
|
104
161
|
}
|
|
162
|
+
else {
|
|
163
|
+
logger.debug(`[${functionTag}] Skipping dynamic model resolution`, {
|
|
164
|
+
resolvedModelName: resolvedModelName || "none",
|
|
165
|
+
reason: "Model already resolved from environment variables or explicit parameter",
|
|
166
|
+
});
|
|
167
|
+
}
|
|
105
168
|
// CRITICAL FIX: Initialize providers before using them
|
|
106
169
|
await ProviderRegistry.registerAllProviders();
|
|
107
170
|
// PURE FACTORY PATTERN: No switch statements - use ProviderFactory exclusively
|
|
@@ -109,8 +172,18 @@ export class AIProviderFactory {
|
|
|
109
172
|
const finalModelName = resolvedModelName === "default" || resolvedModelName === null
|
|
110
173
|
? undefined
|
|
111
174
|
: resolvedModelName;
|
|
175
|
+
logger.debug(`[${functionTag}] Final provider configuration`, {
|
|
176
|
+
originalProviderName: providerName,
|
|
177
|
+
normalizedProviderName: normalizedName,
|
|
178
|
+
originalModelName: modelName || "not provided",
|
|
179
|
+
resolvedModelName: resolvedModelName || "not resolved",
|
|
180
|
+
finalModelName: finalModelName || "using provider default",
|
|
181
|
+
});
|
|
112
182
|
// Create provider with enhanced SDK
|
|
113
183
|
const provider = await ProviderFactory.createProvider(normalizedName, finalModelName, sdk);
|
|
184
|
+
// Summary logging in format expected by debugging tools
|
|
185
|
+
logger.debug(`[AIProviderFactory] Provider creation completed { providerName: '${normalizedName}', modelName: '${finalModelName}' }`);
|
|
186
|
+
logger.debug(`[AIProviderFactory] Resolved model: ${finalModelName}`);
|
|
114
187
|
logger.debug(componentIdentifier, "Pure factory pattern provider created", {
|
|
115
188
|
providerName: normalizedName,
|
|
116
189
|
modelName: finalModelName,
|
|
@@ -153,7 +226,7 @@ export class AIProviderFactory {
|
|
|
153
226
|
* @returns AIProvider instance
|
|
154
227
|
*/
|
|
155
228
|
static async createProviderWithModel(provider, model) {
|
|
156
|
-
const functionTag = "
|
|
229
|
+
const functionTag = "AIProviderFactory.createProviderWithModel";
|
|
157
230
|
logger.debug(`[${functionTag}] Provider model creation started`, {
|
|
158
231
|
provider,
|
|
159
232
|
model,
|
|
@@ -214,7 +287,7 @@ export class AIProviderFactory {
|
|
|
214
287
|
* @returns Object with primary and fallback providers
|
|
215
288
|
*/
|
|
216
289
|
static async createProviderWithFallback(primaryProvider, fallbackProvider, modelName, enableMCP = true) {
|
|
217
|
-
const functionTag = "
|
|
290
|
+
const functionTag = "AIProviderFactory.createProviderWithFallback";
|
|
218
291
|
logger.debug(`[${functionTag}] Fallback provider setup started`, {
|
|
219
292
|
primaryProvider,
|
|
220
293
|
fallbackProvider,
|
|
@@ -42,6 +42,9 @@ export class ProviderFactory {
|
|
|
42
42
|
if (providerName.toLowerCase().includes("vertex")) {
|
|
43
43
|
model = process.env.VERTEX_MODEL;
|
|
44
44
|
}
|
|
45
|
+
else if (providerName.toLowerCase().includes("bedrock")) {
|
|
46
|
+
model = process.env.BEDROCK_MODEL || process.env.BEDROCK_MODEL_ID;
|
|
47
|
+
}
|
|
45
48
|
// Fallback to registry default if no env var
|
|
46
49
|
model = model || registration.defaultModel;
|
|
47
50
|
}
|
|
@@ -39,9 +39,9 @@ export class ProviderRegistry {
|
|
|
39
39
|
return new AnthropicProvider(modelName, sdk);
|
|
40
40
|
}, "claude-3-5-sonnet-20241022", ["claude", "anthropic"]);
|
|
41
41
|
// Register Amazon Bedrock provider
|
|
42
|
-
ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName) => {
|
|
42
|
+
ProviderFactory.registerProvider(AIProviderName.BEDROCK, async (modelName, _providerName, sdk) => {
|
|
43
43
|
const { AmazonBedrockProvider } = await import("../providers/amazonBedrock.js");
|
|
44
|
-
return new AmazonBedrockProvider(modelName);
|
|
44
|
+
return new AmazonBedrockProvider(modelName, undefined, sdk);
|
|
45
45
|
}, undefined, // Let provider read BEDROCK_MODEL from .env
|
|
46
46
|
["bedrock", "aws"]);
|
|
47
47
|
// Register Azure OpenAI provider
|
|
@@ -664,6 +664,9 @@ export class ExternalServerManager extends EventEmitter {
|
|
|
664
664
|
const delay = Math.min(1000 *
|
|
665
665
|
Math.pow(this.config.restartBackoffMultiplier, instance.reconnectAttempts - 1), 30000);
|
|
666
666
|
mcpLogger.info(`[ExternalServerManager] Scheduling restart for ${serverId} in ${delay}ms (attempt ${instance.reconnectAttempts})`);
|
|
667
|
+
if (instance.restartTimer) {
|
|
668
|
+
return;
|
|
669
|
+
} // already scheduled
|
|
667
670
|
instance.restartTimer = setTimeout(async () => {
|
|
668
671
|
try {
|
|
669
672
|
await this.stopServer(serverId);
|
|
@@ -914,6 +917,7 @@ export class ExternalServerManager extends EventEmitter {
|
|
|
914
917
|
}
|
|
915
918
|
try {
|
|
916
919
|
mcpLogger.debug(`[ExternalServerManager] Registering ${instance.toolsMap.size} tools with main registry for server: ${serverId}`);
|
|
920
|
+
const registrations = [];
|
|
917
921
|
for (const [toolName, tool] of instance.toolsMap.entries()) {
|
|
918
922
|
const toolId = `${serverId}.${toolName}`;
|
|
919
923
|
const toolInfo = {
|
|
@@ -923,21 +927,16 @@ export class ExternalServerManager extends EventEmitter {
|
|
|
923
927
|
serverId: serverId,
|
|
924
928
|
category: detectCategory({ isExternal: true, serverId }),
|
|
925
929
|
};
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
return await this.executeTool(serverId, toolName, params, { timeout: this.config.defaultTimeout });
|
|
932
|
-
},
|
|
933
|
-
});
|
|
934
|
-
mcpLogger.debug(`[ExternalServerManager] Registered tool with main registry: ${toolId}`);
|
|
935
|
-
}
|
|
936
|
-
catch (registrationError) {
|
|
937
|
-
mcpLogger.warn(`[ExternalServerManager] Failed to register tool ${toolId} with main registry:`, registrationError);
|
|
938
|
-
}
|
|
930
|
+
registrations.push(toolRegistry.registerTool(toolId, toolInfo, {
|
|
931
|
+
execute: async (params) => await this.executeTool(serverId, toolName, params, {
|
|
932
|
+
timeout: this.config.defaultTimeout,
|
|
933
|
+
}),
|
|
934
|
+
}));
|
|
939
935
|
}
|
|
940
|
-
|
|
936
|
+
const results = await Promise.allSettled(registrations);
|
|
937
|
+
const ok = results.filter((r) => r.status === "fulfilled").length;
|
|
938
|
+
const failed = results.length - ok;
|
|
939
|
+
mcpLogger.info(`[ExternalServerManager] Registered ${ok}/${results.length} tools with main registry for ${serverId}${failed ? ` (${failed} failed)` : ""}`);
|
|
941
940
|
}
|
|
942
941
|
catch (error) {
|
|
943
942
|
mcpLogger.error(`[ExternalServerManager] Failed to register tools with main registry for ${serverId}:`, error);
|