@juspay/neurolink 7.6.0 → 7.7.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 +14 -2
- package/README.md +79 -4
- package/dist/cli/commands/config.d.ts +275 -3
- package/dist/cli/commands/config.js +121 -0
- package/dist/cli/commands/mcp.js +77 -28
- package/dist/cli/factories/commandFactory.js +359 -6
- package/dist/core/analytics.js +7 -27
- package/dist/core/baseProvider.js +43 -4
- package/dist/core/constants.d.ts +46 -0
- package/dist/core/constants.js +47 -0
- package/dist/core/dynamicModels.d.ts +16 -4
- package/dist/core/dynamicModels.js +130 -26
- package/dist/core/evaluation.js +5 -1
- package/dist/core/evaluationProviders.d.ts +6 -2
- package/dist/core/evaluationProviders.js +41 -125
- package/dist/core/factory.d.ts +5 -0
- package/dist/core/factory.js +62 -50
- package/dist/core/modelConfiguration.d.ts +246 -0
- package/dist/core/modelConfiguration.js +775 -0
- package/dist/core/types.d.ts +22 -3
- package/dist/core/types.js +5 -1
- package/dist/factories/providerRegistry.js +3 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/core/analytics.js +7 -27
- package/dist/lib/core/baseProvider.js +43 -4
- package/dist/lib/core/constants.d.ts +46 -0
- package/dist/lib/core/constants.js +47 -0
- package/dist/lib/core/dynamicModels.d.ts +16 -4
- package/dist/lib/core/dynamicModels.js +130 -26
- package/dist/lib/core/evaluation.js +5 -1
- package/dist/lib/core/evaluationProviders.d.ts +6 -2
- package/dist/lib/core/evaluationProviders.js +41 -125
- package/dist/lib/core/factory.d.ts +5 -0
- package/dist/lib/core/factory.js +63 -50
- package/dist/lib/core/modelConfiguration.d.ts +246 -0
- package/dist/lib/core/modelConfiguration.js +775 -0
- package/dist/lib/core/types.d.ts +22 -3
- package/dist/lib/core/types.js +5 -1
- package/dist/lib/factories/providerRegistry.js +3 -3
- package/dist/lib/index.d.ts +1 -1
- package/dist/lib/index.js +1 -1
- package/dist/lib/mcp/factory.d.ts +5 -5
- package/dist/lib/mcp/factory.js +2 -2
- package/dist/lib/mcp/servers/utilities/utilityServer.d.ts +1 -1
- package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -1
- package/dist/lib/mcp/toolRegistry.js +2 -2
- package/dist/lib/neurolink.d.ts +168 -12
- package/dist/lib/neurolink.js +685 -123
- package/dist/lib/providers/anthropic.js +52 -2
- package/dist/lib/providers/googleAiStudio.js +4 -0
- package/dist/lib/providers/googleVertex.d.ts +75 -9
- package/dist/lib/providers/googleVertex.js +365 -46
- package/dist/lib/providers/huggingFace.d.ts +52 -11
- package/dist/lib/providers/huggingFace.js +180 -42
- package/dist/lib/providers/litellm.d.ts +9 -9
- package/dist/lib/providers/litellm.js +103 -16
- package/dist/lib/providers/ollama.d.ts +52 -17
- package/dist/lib/providers/ollama.js +276 -68
- package/dist/lib/sdk/toolRegistration.d.ts +42 -0
- package/dist/lib/sdk/toolRegistration.js +269 -27
- package/dist/lib/telemetry/telemetryService.d.ts +6 -0
- package/dist/lib/telemetry/telemetryService.js +38 -3
- package/dist/lib/types/contextTypes.d.ts +75 -11
- package/dist/lib/types/contextTypes.js +227 -1
- package/dist/lib/types/domainTypes.d.ts +62 -0
- package/dist/lib/types/domainTypes.js +5 -0
- package/dist/lib/types/generateTypes.d.ts +52 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/mcpTypes.d.ts +1 -1
- package/dist/lib/types/mcpTypes.js +1 -1
- package/dist/lib/types/streamTypes.d.ts +14 -0
- package/dist/lib/types/universalProviderOptions.d.ts +1 -1
- package/dist/lib/utils/errorHandling.d.ts +142 -0
- package/dist/lib/utils/errorHandling.js +316 -0
- package/dist/lib/utils/factoryProcessing.d.ts +74 -0
- package/dist/lib/utils/factoryProcessing.js +588 -0
- package/dist/lib/utils/optionsConversion.d.ts +54 -0
- package/dist/lib/utils/optionsConversion.js +126 -0
- package/dist/lib/utils/optionsUtils.d.ts +246 -0
- package/dist/lib/utils/optionsUtils.js +960 -0
- package/dist/lib/utils/providerHealth.d.ts +107 -0
- package/dist/lib/utils/providerHealth.js +507 -0
- package/dist/lib/utils/providerUtils.d.ts +17 -0
- package/dist/lib/utils/providerUtils.js +271 -16
- package/dist/lib/utils/timeout.js +1 -1
- package/dist/lib/utils/tokenLimits.d.ts +33 -0
- package/dist/lib/utils/tokenLimits.js +118 -0
- package/dist/mcp/factory.d.ts +5 -5
- package/dist/mcp/factory.js +2 -2
- package/dist/mcp/servers/utilities/utilityServer.d.ts +1 -1
- package/dist/mcp/servers/utilities/utilityServer.js +1 -1
- package/dist/mcp/toolRegistry.js +2 -2
- package/dist/neurolink.d.ts +168 -12
- package/dist/neurolink.js +685 -123
- package/dist/providers/anthropic.js +52 -2
- package/dist/providers/googleAiStudio.js +4 -0
- package/dist/providers/googleVertex.d.ts +75 -9
- package/dist/providers/googleVertex.js +365 -46
- package/dist/providers/huggingFace.d.ts +52 -11
- package/dist/providers/huggingFace.js +181 -43
- package/dist/providers/litellm.d.ts +9 -9
- package/dist/providers/litellm.js +103 -16
- package/dist/providers/ollama.d.ts +52 -17
- package/dist/providers/ollama.js +276 -68
- package/dist/sdk/toolRegistration.d.ts +42 -0
- package/dist/sdk/toolRegistration.js +269 -27
- package/dist/telemetry/telemetryService.d.ts +6 -0
- package/dist/telemetry/telemetryService.js +38 -3
- package/dist/types/contextTypes.d.ts +75 -11
- package/dist/types/contextTypes.js +227 -2
- package/dist/types/domainTypes.d.ts +62 -0
- package/dist/types/domainTypes.js +5 -0
- package/dist/types/generateTypes.d.ts +52 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/mcpTypes.d.ts +1 -1
- package/dist/types/mcpTypes.js +1 -1
- package/dist/types/streamTypes.d.ts +14 -0
- package/dist/types/universalProviderOptions.d.ts +1 -1
- package/dist/types/universalProviderOptions.js +0 -1
- package/dist/utils/errorHandling.d.ts +142 -0
- package/dist/utils/errorHandling.js +316 -0
- package/dist/utils/factoryProcessing.d.ts +74 -0
- package/dist/utils/factoryProcessing.js +588 -0
- package/dist/utils/optionsConversion.d.ts +54 -0
- package/dist/utils/optionsConversion.js +126 -0
- package/dist/utils/optionsUtils.d.ts +246 -0
- package/dist/utils/optionsUtils.js +960 -0
- package/dist/utils/providerHealth.d.ts +107 -0
- package/dist/utils/providerHealth.js +507 -0
- package/dist/utils/providerUtils.d.ts +17 -0
- package/dist/utils/providerUtils.js +271 -16
- package/dist/utils/timeout.js +1 -1
- package/dist/utils/tokenLimits.d.ts +33 -0
- package/dist/utils/tokenLimits.js +118 -0
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { AIProviderFactory } from "../core/factory.js";
|
|
6
6
|
import { logger } from "./logger.js";
|
|
7
|
+
import { ProviderHealthChecker } from "./providerHealth.js";
|
|
7
8
|
/**
|
|
8
9
|
* Get the best available provider based on real-time availability checks
|
|
9
10
|
* Enhanced version consolidated from providerUtils-fixed.ts
|
|
@@ -11,12 +12,39 @@ import { logger } from "./logger.js";
|
|
|
11
12
|
* @returns The best provider name to use
|
|
12
13
|
*/
|
|
13
14
|
export async function getBestProvider(requestedProvider) {
|
|
14
|
-
//
|
|
15
|
+
// Check requested provider FIRST - explicit user choice overrides defaults
|
|
16
|
+
if (requestedProvider && requestedProvider !== "auto") {
|
|
17
|
+
// For explicit provider requests, check health first
|
|
18
|
+
try {
|
|
19
|
+
const health = await ProviderHealthChecker.checkProviderHealth(requestedProvider, { includeConnectivityTest: false, cacheResults: true });
|
|
20
|
+
if (health.isHealthy) {
|
|
21
|
+
logger.debug(`[getBestProvider] Using healthy explicitly requested provider: ${requestedProvider}`);
|
|
22
|
+
return requestedProvider;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
logger.warn(`[getBestProvider] Requested provider ${requestedProvider} is unhealthy, finding alternative`, { error: health.error });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
logger.warn(`[getBestProvider] Health check failed for ${requestedProvider}, using anyway`, { error: error instanceof Error ? error.message : String(error) });
|
|
30
|
+
return requestedProvider; // Return anyway for explicit requests
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
// Use health checker to get best available provider
|
|
34
|
+
const healthyProvider = await ProviderHealthChecker.getBestHealthyProvider();
|
|
35
|
+
if (healthyProvider) {
|
|
36
|
+
logger.debug(`[getBestProvider] Selected healthy provider: ${healthyProvider}`);
|
|
37
|
+
return healthyProvider;
|
|
38
|
+
}
|
|
39
|
+
// Fallback to legacy provider checking if health system fails
|
|
40
|
+
logger.warn("[getBestProvider] Health system failed, falling back to legacy checking");
|
|
41
|
+
// Check for explicit default provider in env (only when no provider requested)
|
|
15
42
|
if (process.env.DEFAULT_PROVIDER &&
|
|
16
43
|
(await isProviderAvailable(process.env.DEFAULT_PROVIDER))) {
|
|
44
|
+
logger.debug(`[getBestProvider] Using default provider from env: ${process.env.DEFAULT_PROVIDER}`);
|
|
17
45
|
return process.env.DEFAULT_PROVIDER;
|
|
18
46
|
}
|
|
19
|
-
//
|
|
47
|
+
// Special case for Ollama - prioritize local when available
|
|
20
48
|
if (process.env.OLLAMA_BASE_URL && process.env.OLLAMA_MODEL) {
|
|
21
49
|
try {
|
|
22
50
|
if (await isProviderAvailable("ollama")) {
|
|
@@ -28,26 +56,26 @@ export async function getBestProvider(requestedProvider) {
|
|
|
28
56
|
// Fall through to cloud providers
|
|
29
57
|
}
|
|
30
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* Provider priority order rationale:
|
|
61
|
+
* - Vertex (Google Cloud AI) is prioritized first for its enterprise-grade reliability and advanced model capabilities.
|
|
62
|
+
* - Google AI follows as second priority for comprehensive Google AI ecosystem support.
|
|
63
|
+
* - OpenAI maintains high priority due to its consistent reliability and broad model support.
|
|
64
|
+
* - Other providers are ordered based on a combination of reliability, feature set, and historical performance in our use cases.
|
|
65
|
+
* - Ollama is kept as a fallback for local deployments when available.
|
|
66
|
+
* Please update this comment if the order is changed in the future, and document the rationale for maintainability.
|
|
67
|
+
*/
|
|
31
68
|
const providers = [
|
|
32
|
-
"
|
|
69
|
+
"vertex", // Prioritize Google Cloud AI (Vertex) first
|
|
70
|
+
"google-ai", // Google AI ecosystem support
|
|
71
|
+
"openai", // Reliable with broad model support
|
|
33
72
|
"anthropic",
|
|
34
|
-
"
|
|
35
|
-
"mistral",
|
|
36
|
-
"vertex",
|
|
73
|
+
"bedrock",
|
|
37
74
|
"azure",
|
|
75
|
+
"mistral",
|
|
38
76
|
"huggingface",
|
|
39
|
-
"bedrock",
|
|
40
77
|
"ollama", // Keep as fallback
|
|
41
78
|
];
|
|
42
|
-
if (requestedProvider && requestedProvider !== "auto") {
|
|
43
|
-
if (await isProviderAvailable(requestedProvider)) {
|
|
44
|
-
logger.debug(`[getBestProvider] Using requested provider: ${requestedProvider}`);
|
|
45
|
-
return requestedProvider;
|
|
46
|
-
}
|
|
47
|
-
else {
|
|
48
|
-
logger.warn(`[getBestProvider] Requested provider '${requestedProvider}' is not available. Falling back to auto-selection.`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
79
|
for (const provider of providers) {
|
|
52
80
|
if (await isProviderAvailable(provider)) {
|
|
53
81
|
logger.debug(`[getBestProvider] Selected provider: ${provider}`);
|
|
@@ -92,9 +120,236 @@ async function isProviderAvailable(providerName) {
|
|
|
92
120
|
return false;
|
|
93
121
|
}
|
|
94
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Google Cloud Project ID validation regex
|
|
125
|
+
* Format requirements:
|
|
126
|
+
* - Must start with a lowercase letter
|
|
127
|
+
* - Can contain lowercase letters, numbers, and hyphens
|
|
128
|
+
* - Must end with a lowercase letter or number
|
|
129
|
+
* - Total length must be 6-30 characters
|
|
130
|
+
*/
|
|
131
|
+
const GOOGLE_CLOUD_PROJECT_ID_REGEX = /^[a-z][a-z0-9-]{4,28}[a-z0-9]$/;
|
|
132
|
+
/**
|
|
133
|
+
* Validate environment variable values for a provider
|
|
134
|
+
* Addresses GitHub Copilot comment about adding environment variable validation
|
|
135
|
+
* @param provider - Provider name to validate
|
|
136
|
+
* @returns Validation result with detailed information
|
|
137
|
+
*/
|
|
138
|
+
export function validateProviderEnvVars(provider) {
|
|
139
|
+
const result = {
|
|
140
|
+
isValid: true,
|
|
141
|
+
missingVars: [],
|
|
142
|
+
invalidVars: [],
|
|
143
|
+
warnings: [],
|
|
144
|
+
};
|
|
145
|
+
switch (provider.toLowerCase()) {
|
|
146
|
+
case "bedrock":
|
|
147
|
+
case "amazon":
|
|
148
|
+
case "aws":
|
|
149
|
+
validateAwsCredentials(result);
|
|
150
|
+
break;
|
|
151
|
+
case "vertex":
|
|
152
|
+
case "googlevertex":
|
|
153
|
+
case "google":
|
|
154
|
+
case "gemini":
|
|
155
|
+
validateVertexCredentials(result);
|
|
156
|
+
break;
|
|
157
|
+
case "openai":
|
|
158
|
+
case "gpt":
|
|
159
|
+
validateOpenAICredentials(result);
|
|
160
|
+
break;
|
|
161
|
+
case "anthropic":
|
|
162
|
+
case "claude":
|
|
163
|
+
validateAnthropicCredentials(result);
|
|
164
|
+
break;
|
|
165
|
+
case "azure":
|
|
166
|
+
case "azureOpenai":
|
|
167
|
+
validateAzureCredentials(result);
|
|
168
|
+
break;
|
|
169
|
+
case "google-ai":
|
|
170
|
+
case "google-studio":
|
|
171
|
+
validateGoogleAICredentials(result);
|
|
172
|
+
break;
|
|
173
|
+
case "huggingface":
|
|
174
|
+
case "hugging-face":
|
|
175
|
+
case "hf":
|
|
176
|
+
validateHuggingFaceCredentials(result);
|
|
177
|
+
break;
|
|
178
|
+
case "mistral":
|
|
179
|
+
case "mistral-ai":
|
|
180
|
+
case "mistralai":
|
|
181
|
+
validateMistralCredentials(result);
|
|
182
|
+
break;
|
|
183
|
+
case "ollama":
|
|
184
|
+
case "local":
|
|
185
|
+
case "local-ollama":
|
|
186
|
+
// Ollama doesn't require environment variables
|
|
187
|
+
break;
|
|
188
|
+
case "litellm":
|
|
189
|
+
// LiteLLM validation can be added if needed
|
|
190
|
+
break;
|
|
191
|
+
default:
|
|
192
|
+
result.isValid = false;
|
|
193
|
+
result.warnings.push(`Unknown provider: ${provider}`);
|
|
194
|
+
}
|
|
195
|
+
result.isValid =
|
|
196
|
+
result.missingVars.length === 0 && result.invalidVars.length === 0;
|
|
197
|
+
return result;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Validate AWS credentials with flexible validation
|
|
201
|
+
* Note: AWS credential formats can vary, so validation is kept reasonably flexible
|
|
202
|
+
*/
|
|
203
|
+
function validateAwsCredentials(result) {
|
|
204
|
+
const accessKeyId = process.env.AWS_ACCESS_KEY_ID;
|
|
205
|
+
const secretAccessKey = process.env.AWS_SECRET_ACCESS_KEY;
|
|
206
|
+
const region = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
|
|
207
|
+
if (!accessKeyId) {
|
|
208
|
+
result.missingVars.push("AWS_ACCESS_KEY_ID");
|
|
209
|
+
}
|
|
210
|
+
else if (!/^[A-Z0-9]{16,}$/.test(accessKeyId)) {
|
|
211
|
+
// Flexible validation: at least 16 uppercase alphanumeric characters
|
|
212
|
+
result.invalidVars.push("AWS_ACCESS_KEY_ID (should be uppercase alphanumeric characters, typically 20 chars)");
|
|
213
|
+
}
|
|
214
|
+
if (!secretAccessKey) {
|
|
215
|
+
result.missingVars.push("AWS_SECRET_ACCESS_KEY");
|
|
216
|
+
}
|
|
217
|
+
else if (!/^[A-Za-z0-9+/]{30,}$/.test(secretAccessKey)) {
|
|
218
|
+
// Flexible validation: at least 30 base64 characters (can vary in length)
|
|
219
|
+
result.invalidVars.push("AWS_SECRET_ACCESS_KEY (should be base64 characters, typically 40+ chars)");
|
|
220
|
+
}
|
|
221
|
+
if (!region) {
|
|
222
|
+
result.warnings.push("AWS_REGION not set, will use default region");
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Validate Google Vertex credentials
|
|
227
|
+
*/
|
|
228
|
+
function validateVertexCredentials(result) {
|
|
229
|
+
const projectId = process.env.GOOGLE_CLOUD_PROJECT_ID ||
|
|
230
|
+
process.env.VERTEX_PROJECT_ID ||
|
|
231
|
+
process.env.GOOGLE_VERTEX_PROJECT ||
|
|
232
|
+
process.env.GOOGLE_CLOUD_PROJECT;
|
|
233
|
+
const hasCredentials = process.env.GOOGLE_APPLICATION_CREDENTIALS ||
|
|
234
|
+
process.env.GOOGLE_SERVICE_ACCOUNT_KEY ||
|
|
235
|
+
(process.env.GOOGLE_AUTH_CLIENT_EMAIL &&
|
|
236
|
+
process.env.GOOGLE_AUTH_PRIVATE_KEY);
|
|
237
|
+
if (!projectId) {
|
|
238
|
+
result.missingVars.push("GOOGLE_CLOUD_PROJECT_ID (or variant)");
|
|
239
|
+
}
|
|
240
|
+
else if (!GOOGLE_CLOUD_PROJECT_ID_REGEX.test(projectId)) {
|
|
241
|
+
result.invalidVars.push("Project ID format invalid (must be 6-30 lowercase letters, digits, hyphens)");
|
|
242
|
+
}
|
|
243
|
+
if (!hasCredentials) {
|
|
244
|
+
result.missingVars.push("Google credentials (GOOGLE_APPLICATION_CREDENTIALS or explicit auth)");
|
|
245
|
+
}
|
|
246
|
+
if (process.env.GOOGLE_AUTH_CLIENT_EMAIL &&
|
|
247
|
+
!isValidEmail(process.env.GOOGLE_AUTH_CLIENT_EMAIL)) {
|
|
248
|
+
result.invalidVars.push("GOOGLE_AUTH_CLIENT_EMAIL (invalid email format)");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Validate OpenAI credentials
|
|
253
|
+
*/
|
|
254
|
+
function validateOpenAICredentials(result) {
|
|
255
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
256
|
+
if (!apiKey) {
|
|
257
|
+
result.missingVars.push("OPENAI_API_KEY");
|
|
258
|
+
}
|
|
259
|
+
else if (!/^sk-[A-Za-z0-9]{48,}$/.test(apiKey)) {
|
|
260
|
+
result.invalidVars.push("OPENAI_API_KEY (should start with 'sk-' followed by 48+ characters)");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Validate Anthropic credentials
|
|
265
|
+
*/
|
|
266
|
+
function validateAnthropicCredentials(result) {
|
|
267
|
+
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
268
|
+
if (!apiKey) {
|
|
269
|
+
result.missingVars.push("ANTHROPIC_API_KEY");
|
|
270
|
+
}
|
|
271
|
+
else if (!/^sk-ant-[A-Za-z0-9-_]{95,}$/.test(apiKey)) {
|
|
272
|
+
result.invalidVars.push("ANTHROPIC_API_KEY (should start with 'sk-ant-' followed by 95+ characters)");
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Validate Azure credentials
|
|
277
|
+
*/
|
|
278
|
+
function validateAzureCredentials(result) {
|
|
279
|
+
const apiKey = process.env.AZURE_OPENAI_API_KEY;
|
|
280
|
+
const endpoint = process.env.AZURE_OPENAI_ENDPOINT;
|
|
281
|
+
if (!apiKey) {
|
|
282
|
+
result.missingVars.push("AZURE_OPENAI_API_KEY");
|
|
283
|
+
}
|
|
284
|
+
else if (!/^[a-f0-9]{32}$/.test(apiKey)) {
|
|
285
|
+
result.invalidVars.push("AZURE_OPENAI_API_KEY (should be 32 hexadecimal characters)");
|
|
286
|
+
}
|
|
287
|
+
if (!endpoint) {
|
|
288
|
+
result.missingVars.push("AZURE_OPENAI_ENDPOINT");
|
|
289
|
+
}
|
|
290
|
+
else if (!isValidUrl(endpoint)) {
|
|
291
|
+
result.invalidVars.push("AZURE_OPENAI_ENDPOINT (should be a valid HTTPS URL)");
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Validate Google AI credentials
|
|
296
|
+
*/
|
|
297
|
+
function validateGoogleAICredentials(result) {
|
|
298
|
+
const apiKey = process.env.GOOGLE_AI_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY;
|
|
299
|
+
if (!apiKey) {
|
|
300
|
+
result.missingVars.push("GOOGLE_AI_API_KEY (or GOOGLE_GENERATIVE_AI_API_KEY)");
|
|
301
|
+
}
|
|
302
|
+
else if (!/^[A-Za-z0-9_-]{39}$/.test(apiKey)) {
|
|
303
|
+
result.invalidVars.push("GOOGLE_AI_API_KEY (should be 39 alphanumeric characters with dashes/underscores)");
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Validate HuggingFace credentials
|
|
308
|
+
*/
|
|
309
|
+
function validateHuggingFaceCredentials(result) {
|
|
310
|
+
const apiKey = process.env.HUGGINGFACE_API_KEY || process.env.HF_TOKEN;
|
|
311
|
+
if (!apiKey) {
|
|
312
|
+
result.missingVars.push("HUGGINGFACE_API_KEY (or HF_TOKEN)");
|
|
313
|
+
}
|
|
314
|
+
else if (!/^hf_[A-Za-z0-9]{37}$/.test(apiKey)) {
|
|
315
|
+
result.invalidVars.push("HUGGINGFACE_API_KEY (should start with 'hf_' followed by 37 characters)");
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Validate Mistral credentials
|
|
320
|
+
*/
|
|
321
|
+
function validateMistralCredentials(result) {
|
|
322
|
+
const apiKey = process.env.MISTRAL_API_KEY;
|
|
323
|
+
if (!apiKey) {
|
|
324
|
+
result.missingVars.push("MISTRAL_API_KEY");
|
|
325
|
+
}
|
|
326
|
+
else if (!/^[A-Za-z0-9]{32,}$/.test(apiKey)) {
|
|
327
|
+
result.invalidVars.push("MISTRAL_API_KEY (should be 32+ alphanumeric characters)");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Helper function to validate email format
|
|
332
|
+
*/
|
|
333
|
+
function isValidEmail(email) {
|
|
334
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
335
|
+
return emailRegex.test(email);
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Helper function to validate URL format
|
|
339
|
+
*/
|
|
340
|
+
function isValidUrl(url) {
|
|
341
|
+
try {
|
|
342
|
+
const parsedUrl = new URL(url);
|
|
343
|
+
return parsedUrl.protocol === "https:";
|
|
344
|
+
}
|
|
345
|
+
catch {
|
|
346
|
+
return false;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
95
349
|
/**
|
|
96
350
|
* Check if a provider has the minimum required environment variables
|
|
97
351
|
* NOTE: This only checks if variables exist, not if they're valid
|
|
352
|
+
* For validation, use validateProviderEnvVars instead
|
|
98
353
|
* @param provider - Provider name to check
|
|
99
354
|
* @returns True if the provider has required environment variables
|
|
100
355
|
*/
|
package/dist/utils/timeout.js
CHANGED
|
@@ -82,7 +82,7 @@ export const DEFAULT_TIMEOUTS = {
|
|
|
82
82
|
openai: "30s", // OpenAI typically responds quickly
|
|
83
83
|
bedrock: "45s", // AWS can be slower, especially for cold starts
|
|
84
84
|
vertex: "60s", // Google Cloud can be slower
|
|
85
|
-
anthropic: "
|
|
85
|
+
anthropic: "60s", // Increased timeout for Anthropic API stability
|
|
86
86
|
azure: "30s", // Azure OpenAI similar to OpenAI
|
|
87
87
|
"google-ai": "30s", // Google AI Studio is fast
|
|
88
88
|
huggingface: "2m", // Open source models vary significantly
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-specific token limit utilities
|
|
3
|
+
* Provides safe maxTokens values based on provider and model capabilities
|
|
4
|
+
*/
|
|
5
|
+
import { PROVIDER_MAX_TOKENS } from "../core/constants.js";
|
|
6
|
+
/**
|
|
7
|
+
* Get the safe maximum tokens for a provider and model
|
|
8
|
+
*/
|
|
9
|
+
export declare function getSafeMaxTokens(provider: keyof typeof PROVIDER_MAX_TOKENS | string, model?: string, requestedMaxTokens?: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* Validate if maxTokens is safe for a provider/model combination
|
|
12
|
+
*/
|
|
13
|
+
export declare function validateMaxTokens(provider: keyof typeof PROVIDER_MAX_TOKENS | string, model?: string, maxTokens?: number): {
|
|
14
|
+
isValid: boolean;
|
|
15
|
+
recommendedMaxTokens: number;
|
|
16
|
+
warning?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Get provider-specific token limit recommendations
|
|
20
|
+
*/
|
|
21
|
+
export declare function getTokenLimitRecommendations(provider: string): {
|
|
22
|
+
conservative: number;
|
|
23
|
+
balanced: number;
|
|
24
|
+
maximum: number;
|
|
25
|
+
models: Record<string, number>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Get all provider limits summary
|
|
29
|
+
*/
|
|
30
|
+
export declare function getAllProviderLimits(): Record<string, {
|
|
31
|
+
default: number;
|
|
32
|
+
models: Record<string, number>;
|
|
33
|
+
}>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider-specific token limit utilities
|
|
3
|
+
* Provides safe maxTokens values based on provider and model capabilities
|
|
4
|
+
*/
|
|
5
|
+
import { PROVIDER_MAX_TOKENS, DEFAULT_MAX_TOKENS } from "../core/constants.js";
|
|
6
|
+
import { logger } from "./logger.js";
|
|
7
|
+
/**
|
|
8
|
+
* Get the safe maximum tokens for a provider and model
|
|
9
|
+
*/
|
|
10
|
+
export function getSafeMaxTokens(provider, model, requestedMaxTokens) {
|
|
11
|
+
// Get provider-specific limits
|
|
12
|
+
const providerLimits = PROVIDER_MAX_TOKENS[provider];
|
|
13
|
+
if (!providerLimits) {
|
|
14
|
+
logger.warn(`Unknown provider ${provider}, using default maxTokens limit`);
|
|
15
|
+
return Math.min(requestedMaxTokens || DEFAULT_MAX_TOKENS, PROVIDER_MAX_TOKENS.default);
|
|
16
|
+
}
|
|
17
|
+
// Get model-specific limit or provider default
|
|
18
|
+
let maxLimit;
|
|
19
|
+
if (model &&
|
|
20
|
+
typeof providerLimits === "object" &&
|
|
21
|
+
providerLimits[model]) {
|
|
22
|
+
maxLimit = providerLimits[model];
|
|
23
|
+
}
|
|
24
|
+
else if (typeof providerLimits === "object" &&
|
|
25
|
+
providerLimits.default) {
|
|
26
|
+
maxLimit = providerLimits.default;
|
|
27
|
+
}
|
|
28
|
+
else if (typeof providerLimits === "number") {
|
|
29
|
+
maxLimit = providerLimits;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
maxLimit = PROVIDER_MAX_TOKENS.default;
|
|
33
|
+
}
|
|
34
|
+
// If no specific maxTokens requested, return the provider limit
|
|
35
|
+
if (!requestedMaxTokens) {
|
|
36
|
+
return maxLimit;
|
|
37
|
+
}
|
|
38
|
+
// If requested maxTokens exceeds the limit, use the limit and warn
|
|
39
|
+
if (requestedMaxTokens > maxLimit) {
|
|
40
|
+
logger.warn(`Requested maxTokens ${requestedMaxTokens} exceeds ${provider}/${model} limit of ${maxLimit}. Using ${maxLimit} instead.`);
|
|
41
|
+
return maxLimit;
|
|
42
|
+
}
|
|
43
|
+
// Use the requested value if it's within limits
|
|
44
|
+
return requestedMaxTokens;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validate if maxTokens is safe for a provider/model combination
|
|
48
|
+
*/
|
|
49
|
+
export function validateMaxTokens(provider, model, maxTokens) {
|
|
50
|
+
const safeMaxTokens = getSafeMaxTokens(provider, model, maxTokens);
|
|
51
|
+
if (!maxTokens) {
|
|
52
|
+
return {
|
|
53
|
+
isValid: true,
|
|
54
|
+
recommendedMaxTokens: safeMaxTokens,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const isValid = maxTokens <= safeMaxTokens;
|
|
58
|
+
return {
|
|
59
|
+
isValid,
|
|
60
|
+
recommendedMaxTokens: safeMaxTokens,
|
|
61
|
+
warning: !isValid
|
|
62
|
+
? `maxTokens ${maxTokens} exceeds ${provider}/${model} limit of ${safeMaxTokens}`
|
|
63
|
+
: undefined,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get provider-specific token limit recommendations
|
|
68
|
+
*/
|
|
69
|
+
export function getTokenLimitRecommendations(provider) {
|
|
70
|
+
const providerLimits = PROVIDER_MAX_TOKENS[provider];
|
|
71
|
+
if (!providerLimits || typeof providerLimits === "number") {
|
|
72
|
+
const limit = typeof providerLimits === "number"
|
|
73
|
+
? providerLimits
|
|
74
|
+
: PROVIDER_MAX_TOKENS.default;
|
|
75
|
+
return {
|
|
76
|
+
conservative: Math.floor(limit * 0.5),
|
|
77
|
+
balanced: Math.floor(limit * 0.75),
|
|
78
|
+
maximum: limit,
|
|
79
|
+
models: {},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const modelLimits = Object.entries(providerLimits)
|
|
83
|
+
.filter(([key]) => key !== "default")
|
|
84
|
+
.map(([_, limit]) => limit);
|
|
85
|
+
const maxLimit = Math.max(...modelLimits, providerLimits.default || 0);
|
|
86
|
+
const minLimit = Math.min(...modelLimits, providerLimits.default || maxLimit);
|
|
87
|
+
return {
|
|
88
|
+
conservative: Math.floor(minLimit * 0.5),
|
|
89
|
+
balanced: Math.floor(((minLimit + maxLimit) / 2) * 0.75),
|
|
90
|
+
maximum: maxLimit,
|
|
91
|
+
models: Object.fromEntries(Object.entries(providerLimits).filter(([key]) => key !== "default")),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get all provider limits summary
|
|
96
|
+
*/
|
|
97
|
+
export function getAllProviderLimits() {
|
|
98
|
+
const result = {};
|
|
99
|
+
for (const [provider, limits] of Object.entries(PROVIDER_MAX_TOKENS)) {
|
|
100
|
+
if (provider === "default") {
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
if (typeof limits === "number") {
|
|
104
|
+
result[provider] = {
|
|
105
|
+
default: limits,
|
|
106
|
+
models: {},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const { default: defaultLimit, ...models } = limits;
|
|
111
|
+
result[provider] = {
|
|
112
|
+
default: defaultLimit || PROVIDER_MAX_TOKENS.default,
|
|
113
|
+
models: models,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.7.0",
|
|
4
4
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 9 major providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Juspay Technologies",
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"@opentelemetry/sdk-metrics": "^1.30.1",
|
|
149
149
|
"@opentelemetry/sdk-node": "^0.54.2",
|
|
150
150
|
"@opentelemetry/semantic-conventions": "^1.34.0",
|
|
151
|
-
"ai": "
|
|
151
|
+
"ai": "4.3.16",
|
|
152
152
|
"chalk": "^5.3.0",
|
|
153
153
|
"dotenv": "^16.5.0",
|
|
154
154
|
"inquirer": "^9.2.15",
|