@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.
Files changed (61) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli/commands/config.d.ts +3 -3
  3. package/dist/cli/commands/mcp.js +25 -0
  4. package/dist/cli/factories/commandFactory.d.ts +1 -0
  5. package/dist/cli/factories/commandFactory.js +115 -21
  6. package/dist/cli/index.js +8 -0
  7. package/dist/core/factory.js +77 -4
  8. package/dist/factories/providerFactory.js +3 -0
  9. package/dist/factories/providerRegistry.js +2 -2
  10. package/dist/lib/core/factory.js +77 -4
  11. package/dist/lib/factories/providerFactory.js +3 -0
  12. package/dist/lib/factories/providerRegistry.js +2 -2
  13. package/dist/lib/mcp/externalServerManager.js +13 -14
  14. package/dist/lib/mcp/flexibleToolValidator.d.ts +50 -0
  15. package/dist/lib/mcp/flexibleToolValidator.js +161 -0
  16. package/dist/lib/mcp/toolRegistry.d.ts +2 -2
  17. package/dist/lib/mcp/toolRegistry.js +25 -50
  18. package/dist/lib/neurolink.d.ts +299 -4
  19. package/dist/lib/neurolink.js +434 -73
  20. package/dist/lib/providers/amazonBedrock.d.ts +47 -6
  21. package/dist/lib/providers/amazonBedrock.js +282 -23
  22. package/dist/lib/providers/aws/credentialProvider.d.ts +58 -0
  23. package/dist/lib/providers/aws/credentialProvider.js +267 -0
  24. package/dist/lib/providers/aws/credentialTester.d.ts +49 -0
  25. package/dist/lib/providers/aws/credentialTester.js +394 -0
  26. package/dist/lib/providers/googleVertex.js +13 -4
  27. package/dist/lib/proxy/awsProxyIntegration.d.ts +23 -0
  28. package/dist/lib/proxy/awsProxyIntegration.js +285 -0
  29. package/dist/lib/proxy/proxyFetch.d.ts +9 -5
  30. package/dist/lib/proxy/proxyFetch.js +232 -98
  31. package/dist/lib/proxy/utils/noProxyUtils.d.ts +39 -0
  32. package/dist/lib/proxy/utils/noProxyUtils.js +149 -0
  33. package/dist/lib/types/providers.d.ts +43 -0
  34. package/dist/lib/utils/providerConfig.d.ts +1 -0
  35. package/dist/lib/utils/providerConfig.js +2 -1
  36. package/dist/lib/utils/providerHealth.js +123 -5
  37. package/dist/mcp/externalServerManager.js +13 -14
  38. package/dist/mcp/flexibleToolValidator.d.ts +50 -0
  39. package/dist/mcp/flexibleToolValidator.js +161 -0
  40. package/dist/mcp/toolRegistry.d.ts +2 -2
  41. package/dist/mcp/toolRegistry.js +25 -50
  42. package/dist/neurolink.d.ts +299 -4
  43. package/dist/neurolink.js +434 -73
  44. package/dist/providers/amazonBedrock.d.ts +47 -6
  45. package/dist/providers/amazonBedrock.js +282 -23
  46. package/dist/providers/aws/credentialProvider.d.ts +58 -0
  47. package/dist/providers/aws/credentialProvider.js +267 -0
  48. package/dist/providers/aws/credentialTester.d.ts +49 -0
  49. package/dist/providers/aws/credentialTester.js +394 -0
  50. package/dist/providers/googleVertex.js +13 -4
  51. package/dist/proxy/awsProxyIntegration.d.ts +23 -0
  52. package/dist/proxy/awsProxyIntegration.js +285 -0
  53. package/dist/proxy/proxyFetch.d.ts +9 -5
  54. package/dist/proxy/proxyFetch.js +232 -98
  55. package/dist/proxy/utils/noProxyUtils.d.ts +39 -0
  56. package/dist/proxy/utils/noProxyUtils.js +149 -0
  57. package/dist/types/providers.d.ts +43 -0
  58. package/dist/utils/providerConfig.d.ts +1 -0
  59. package/dist/utils/providerConfig.js +2 -1
  60. package/dist/utils/providerHealth.js +123 -5
  61. package/package.json +5 -1
@@ -0,0 +1,394 @@
1
+ /**
2
+ * AWS Credential Testing Utilities for NeuroLink
3
+ *
4
+ * Provides comprehensive validation and debugging capabilities for AWS credentials
5
+ * to ensure compatibility with Bedrock-MCP-Connector authentication patterns.
6
+ */
7
+ import { BedrockClient, ListFoundationModelsCommand, } from "@aws-sdk/client-bedrock";
8
+ import { logger } from "../../utils/logger.js";
9
+ /**
10
+ * Helper function to safely extract comprehensive error information from AWS errors
11
+ * This centralizes error extraction and captures AWS SDK v3 name, statusCode, and requestId
12
+ * Enhanced to handle multiple AWS SDK error formats and edge cases
13
+ */
14
+ function extractAwsErrorInfo(error) {
15
+ const result = {};
16
+ if (typeof error === "object" && error !== null) {
17
+ const awsError = error; // Use AWSError interface to handle various error shapes
18
+ // Extract error code with comprehensive fallbacks
19
+ // AWS SDK v2: error.code, error.Code
20
+ // AWS SDK v3: error.name, error.Code, error.code
21
+ // Some services: error.errorCode, error.ErrorCode
22
+ result.code =
23
+ awsError.Code ||
24
+ awsError.code ||
25
+ awsError.errorCode ||
26
+ awsError.ErrorCode ||
27
+ awsError.name; // AWS SDK v3 often uses name as error code
28
+ // Extract error name with fallbacks
29
+ // AWS SDK v3: error.name is primary
30
+ // Some errors: error.errorType, error.ErrorType
31
+ // Fallback to constructor name
32
+ result.name =
33
+ awsError.name ||
34
+ awsError.errorType ||
35
+ awsError.ErrorType ||
36
+ awsError.constructor?.name;
37
+ // Extract error message with fallbacks
38
+ // Standard: error.message
39
+ // Some services: error.Message, error.errorMessage
40
+ result.message =
41
+ awsError.message ||
42
+ awsError.Message ||
43
+ awsError.errorMessage ||
44
+ String(error); // Last resort stringification
45
+ // Extract metadata with multiple patterns
46
+ // AWS SDK v3: error.$metadata
47
+ // Some services: error.metadata, error.$response
48
+ const metadata = awsError.$metadata || awsError.metadata || awsError.$response;
49
+ if (metadata && typeof metadata === "object") {
50
+ const metadataObj = metadata;
51
+ result.statusCode =
52
+ metadataObj.httpStatusCode ||
53
+ metadataObj.statusCode ||
54
+ metadataObj.status;
55
+ result.requestId =
56
+ metadataObj.requestId ||
57
+ metadataObj.RequestId ||
58
+ metadataObj.request_id ||
59
+ metadataObj["x-amzn-requestid"]; // Common response header
60
+ }
61
+ // Handle wrapped errors (common in AWS SDK v3)
62
+ // Sometimes the actual error is nested in error.cause or error.$fault
63
+ if (!result.code && (awsError.cause || awsError.$fault)) {
64
+ const nestedError = awsError.cause || awsError.$fault;
65
+ const nestedInfo = extractAwsErrorInfo(nestedError);
66
+ // Merge nested error info, preferring current level
67
+ result.code = result.code || nestedInfo.code;
68
+ result.name = result.name || nestedInfo.name;
69
+ result.message = result.message || nestedInfo.message;
70
+ result.statusCode = result.statusCode || nestedInfo.statusCode;
71
+ result.requestId = result.requestId || nestedInfo.requestId;
72
+ }
73
+ }
74
+ // Handle primitive error types (strings, etc.)
75
+ if (!result.message && error) {
76
+ result.message = String(error);
77
+ }
78
+ return result;
79
+ }
80
+ /**
81
+ * Credential testing and validation utility class
82
+ */
83
+ export class CredentialTester {
84
+ /**
85
+ * Validate AWS credentials and detect their source
86
+ */
87
+ static async validateCredentials(provider) {
88
+ const startTime = Date.now();
89
+ try {
90
+ // Get credentials from provider
91
+ const credentials = await provider.getCredentials();
92
+ const config = provider.getConfig();
93
+ // Detect credential source based on available information
94
+ const credentialSource = await this.detectCredentialSource(credentials, config);
95
+ const result = {
96
+ isValid: true,
97
+ credentialSource,
98
+ region: config.region,
99
+ hasExpiration: !!credentials.expiration,
100
+ expirationTime: credentials.expiration,
101
+ debugInfo: {
102
+ accessKeyId: credentials.accessKeyId.substring(0, 8) + "***",
103
+ hasSessionToken: !!credentials.sessionToken,
104
+ providerConfig: config,
105
+ },
106
+ };
107
+ logger.debug("Credential validation successful", {
108
+ source: credentialSource,
109
+ region: config.region,
110
+ validationTimeMs: Date.now() - startTime,
111
+ });
112
+ return result;
113
+ }
114
+ catch (error) {
115
+ const errorMessage = error instanceof Error ? error.message : String(error);
116
+ logger.error("Credential validation failed", {
117
+ error: errorMessage,
118
+ validationTimeMs: Date.now() - startTime,
119
+ });
120
+ return {
121
+ isValid: false,
122
+ credentialSource: "unknown",
123
+ region: provider.getConfig().region,
124
+ hasExpiration: false,
125
+ error: errorMessage,
126
+ debugInfo: {
127
+ accessKeyId: "unavailable",
128
+ hasSessionToken: false,
129
+ providerConfig: provider.getConfig(),
130
+ },
131
+ };
132
+ }
133
+ }
134
+ /**
135
+ * Test AWS Bedrock service connectivity
136
+ */
137
+ static async testBedrockConnectivity(provider, region) {
138
+ const startTime = Date.now();
139
+ const testRegion = region || provider.getConfig().region;
140
+ logger.debug("Starting Bedrock connectivity test", {
141
+ region: testRegion,
142
+ providerConfig: provider.getConfig(),
143
+ });
144
+ try {
145
+ // First, get credentials to see what we're working with
146
+ const credentials = await provider.getCredentials();
147
+ logger.debug("Got credentials for Bedrock test", {
148
+ accessKeyId: credentials.accessKeyId.substring(0, 8) + "***",
149
+ hasSessionToken: !!credentials.sessionToken,
150
+ hasExpiration: !!credentials.expiration,
151
+ expiration: credentials.expiration?.toISOString(),
152
+ credentialType: credentials.accessKeyId?.startsWith("ASIA")
153
+ ? "temporary"
154
+ : "long-term",
155
+ });
156
+ // Create Bedrock client with credential provider (use BedrockClient for listing models)
157
+ logger.debug("Creating BedrockClient", {
158
+ region: testRegion,
159
+ credentialProviderType: typeof provider.getCredentialProvider(),
160
+ });
161
+ const bedrockClient = new BedrockClient({
162
+ region: testRegion,
163
+ credentials: provider.getCredentialProvider(),
164
+ maxAttempts: provider.getConfig().maxAttempts || 3,
165
+ });
166
+ logger.debug("BedrockClient created, sending ListFoundationModelsCommand");
167
+ // Test connectivity by listing foundation models
168
+ const command = new ListFoundationModelsCommand({});
169
+ const ctrl = new AbortController();
170
+ const timeoutId = setTimeout(() => ctrl.abort(), provider.getConfig().timeout || 15000);
171
+ let response;
172
+ try {
173
+ response = await bedrockClient.send(command, {
174
+ abortSignal: ctrl.signal,
175
+ });
176
+ }
177
+ finally {
178
+ clearTimeout(timeoutId);
179
+ }
180
+ logger.debug("ListFoundationModelsCommand response received", {
181
+ hasModelSummaries: !!response.modelSummaries,
182
+ modelCount: response.modelSummaries?.length || 0,
183
+ responseMetadata: response.$metadata,
184
+ });
185
+ const models = response.modelSummaries || [];
186
+ const responseTime = Date.now() - startTime;
187
+ const result = {
188
+ bedrockAccessible: true,
189
+ availableModels: models.length,
190
+ responseTimeMs: responseTime,
191
+ sampleModels: models
192
+ .slice(0, 5)
193
+ .map((model) => model.modelId || "unknown"),
194
+ };
195
+ logger.debug("Bedrock connectivity test successful", {
196
+ region: testRegion,
197
+ modelsFound: models.length,
198
+ responseTimeMs: responseTime,
199
+ sampleModels: result.sampleModels,
200
+ });
201
+ return result;
202
+ }
203
+ catch (error) {
204
+ const errorMessage = error instanceof Error ? error.message : String(error);
205
+ const responseTime = Date.now() - startTime;
206
+ const { code, statusCode, requestId } = extractAwsErrorInfo(error);
207
+ logger.error("Bedrock connectivity test failed", {
208
+ region: testRegion,
209
+ error: errorMessage,
210
+ errorType: error instanceof Error ? error.constructor.name : "unknown",
211
+ errorCode: code,
212
+ statusCode,
213
+ requestId,
214
+ stack: error instanceof Error ? error.stack : "no stack trace",
215
+ responseTimeMs: responseTime,
216
+ });
217
+ return {
218
+ bedrockAccessible: false,
219
+ availableModels: 0,
220
+ responseTimeMs: responseTime,
221
+ error: errorMessage,
222
+ sampleModels: [],
223
+ };
224
+ }
225
+ }
226
+ /**
227
+ * Perform comprehensive credential and service testing
228
+ */
229
+ static async runComprehensiveTest(provider, testRegions = ["us-east-1", "us-west-2"]) {
230
+ logger.debug("Starting comprehensive AWS credential and connectivity test");
231
+ // Test credential validation
232
+ const credentialValidation = await this.validateCredentials(provider);
233
+ // Test connectivity across multiple regions (in parallel)
234
+ const connectivityTests = await Promise.all(testRegions.map(async (region) => {
235
+ try {
236
+ const result = await this.testBedrockConnectivity(provider, region);
237
+ return { region, result };
238
+ }
239
+ catch (error) {
240
+ const errorMessage = error instanceof Error ? error.message : String(error);
241
+ return {
242
+ region,
243
+ result: {
244
+ bedrockAccessible: false,
245
+ availableModels: 0,
246
+ responseTimeMs: 0,
247
+ error: errorMessage,
248
+ sampleModels: [],
249
+ },
250
+ };
251
+ }
252
+ }));
253
+ // Determine overall status
254
+ let overallStatus;
255
+ let summary;
256
+ if (!credentialValidation.isValid) {
257
+ overallStatus = "failed";
258
+ summary = `Credential validation failed: ${credentialValidation.error}`;
259
+ }
260
+ else {
261
+ const successfulConnections = connectivityTests.filter((test) => test.result.bedrockAccessible).length;
262
+ if (successfulConnections === testRegions.length) {
263
+ overallStatus = "success";
264
+ summary = `All tests passed. Credentials valid, Bedrock accessible in ${successfulConnections}/${testRegions.length} regions.`;
265
+ }
266
+ else if (successfulConnections > 0) {
267
+ overallStatus = "partial";
268
+ summary = `Partial success. Credentials valid, Bedrock accessible in ${successfulConnections}/${testRegions.length} regions.`;
269
+ }
270
+ else {
271
+ overallStatus = "failed";
272
+ summary = `Credentials valid but Bedrock inaccessible in all tested regions.`;
273
+ }
274
+ }
275
+ logger.info("Comprehensive test completed", {
276
+ overallStatus,
277
+ credentialSource: credentialValidation.credentialSource,
278
+ successfulConnections: connectivityTests.filter((test) => test.result.bedrockAccessible).length,
279
+ totalRegionsTested: testRegions.length,
280
+ });
281
+ return {
282
+ credentialValidation,
283
+ connectivityTests,
284
+ overallStatus,
285
+ summary,
286
+ };
287
+ }
288
+ /**
289
+ * Detect the source of AWS credentials based on credential properties and environment
290
+ */
291
+ static async detectCredentialSource(credentials, config) {
292
+ // Check for environment variables (static creds)
293
+ if (process.env.AWS_ACCESS_KEY_ID && process.env.AWS_SECRET_ACCESS_KEY) {
294
+ return credentials.sessionToken
295
+ ? "Environment Variables (with session token)"
296
+ : "Environment Variables";
297
+ }
298
+ // Explicit env‐based sources first
299
+ if (process.env.AWS_WEB_IDENTITY_TOKEN_FILE) {
300
+ return "Web Identity Token";
301
+ }
302
+ if (process.env.AWS_CREDENTIAL_PROCESS) {
303
+ return "Credential Process";
304
+ }
305
+ // Check for role‐based credentials (temporary credentials with session token)
306
+ if (credentials.sessionToken && credentials.expiration) {
307
+ // Prefer explicit hints first
308
+ if (config.roleArn) {
309
+ return "STS Assume Role";
310
+ }
311
+ // Enhanced container detection
312
+ if (process.env.AWS_CONTAINER_CREDENTIALS_RELATIVE_URI ||
313
+ process.env.AWS_CONTAINER_CREDENTIALS_FULL_URI) {
314
+ // Detect specific container environments
315
+ if (process.env.AWS_EXECUTION_ENV === "AWS_ECS_FARGATE") {
316
+ return "Container Credentials (ECS Fargate)";
317
+ }
318
+ if (process.env.AWS_EXECUTION_ENV === "AWS_ECS_EC2") {
319
+ return "Container Credentials (ECS)";
320
+ }
321
+ return "Container Credentials (ECS)";
322
+ }
323
+ // Enhanced Lambda detection
324
+ if (process.env.AWS_LAMBDA_FUNCTION_NAME) {
325
+ return "Lambda Execution Role";
326
+ }
327
+ // Enhanced EC2 detection
328
+ if (process.env.AWS_EXECUTION_ENV?.includes("EC2")) {
329
+ return "Instance Metadata (EC2)";
330
+ }
331
+ // Enhanced EKS detection
332
+ if (process.env.KUBERNETES_SERVICE_HOST) {
333
+ return "Service Account (EKS)";
334
+ }
335
+ return "Temporary Credentials (IAM Role)";
336
+ }
337
+ // SSO (env‐configured)
338
+ if (process.env.AWS_SSO_START_URL || process.env.AWS_SSO_REGION) {
339
+ return "AWS SSO";
340
+ }
341
+ // Check for profile‐based credentials
342
+ if (config.profile !== "default") {
343
+ return `AWS Profile (${config.profile})`;
344
+ }
345
+ if (process.env.AWS_PROFILE) {
346
+ return `AWS Profile (${process.env.AWS_PROFILE})`;
347
+ }
348
+ // Default fallback
349
+ return "AWS Credentials File";
350
+ }
351
+ /**
352
+ * Get credential source name for debugging
353
+ */
354
+ static async getCredentialSource(provider) {
355
+ try {
356
+ const credentials = await provider.getCredentials();
357
+ const config = provider.getConfig();
358
+ return await this.detectCredentialSource(credentials, config);
359
+ }
360
+ catch {
361
+ return "Unable to determine credential source";
362
+ }
363
+ }
364
+ /**
365
+ * Test credential refresh functionality
366
+ */
367
+ static async testCredentialRefresh(provider) {
368
+ const startTime = Date.now();
369
+ try {
370
+ await provider.refreshCredentials();
371
+ const refreshTime = Date.now() - startTime;
372
+ logger.debug("Credential refresh test successful", {
373
+ refreshTimeMs: refreshTime,
374
+ });
375
+ return {
376
+ refreshSuccessful: true,
377
+ refreshTimeMs: refreshTime,
378
+ };
379
+ }
380
+ catch (error) {
381
+ const errorMessage = error instanceof Error ? error.message : String(error);
382
+ const refreshTime = Date.now() - startTime;
383
+ logger.error("Credential refresh test failed", {
384
+ error: errorMessage,
385
+ refreshTimeMs: refreshTime,
386
+ });
387
+ return {
388
+ refreshSuccessful: false,
389
+ refreshTimeMs: refreshTime,
390
+ error: errorMessage,
391
+ };
392
+ }
393
+ }
394
+ }
@@ -105,10 +105,10 @@ const createVertexSettings = async () => {
105
105
  // Silent error handling for runtime credentials file creation
106
106
  }
107
107
  }
108
- // 🎯 OPTION 1: Check for principal account authentication (existing flow with debug logs)
108
+ // 🎯 OPTION 1: Check for principal account authentication (Accept any valid GOOGLE_APPLICATION_CREDENTIALS file (service account OR ADC))
109
109
  if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
110
110
  const credentialsPath = process.env.GOOGLE_APPLICATION_CREDENTIALS;
111
- // 🚨 CRITICAL FIX: Check if the credentials file actually exists
111
+ // Check if the credentials file exists
112
112
  let fileExists = false;
113
113
  try {
114
114
  fileExists = fs.existsSync(credentialsPath);
@@ -1115,8 +1115,9 @@ export class GoogleVertexProvider extends BaseProvider {
1115
1115
  method: authValidation.method,
1116
1116
  issues: authValidation.issues,
1117
1117
  solutions: [
1118
- "Option 1: Set GOOGLE_APPLICATION_CREDENTIALS to valid service account file",
1118
+ "Option 1: Set GOOGLE_APPLICATION_CREDENTIALS to valid service account OR ADC file",
1119
1119
  "Option 2: Set individual env vars: GOOGLE_AUTH_CLIENT_EMAIL, GOOGLE_AUTH_PRIVATE_KEY",
1120
+ "Option 3: Use gcloud auth application-default login for ADC",
1120
1121
  "Documentation: https://cloud.google.com/docs/authentication/provide-credentials-adc",
1121
1122
  ],
1122
1123
  });
@@ -1268,8 +1269,16 @@ export class GoogleVertexProvider extends BaseProvider {
1268
1269
  result.method = "service_account_file";
1269
1270
  return result;
1270
1271
  }
1272
+ else if (credentials.client_id &&
1273
+ credentials.client_secret &&
1274
+ credentials.refresh_token &&
1275
+ credentials.type !== "service_account") {
1276
+ result.isValid = true;
1277
+ result.method = "application_default_credentials";
1278
+ return result;
1279
+ }
1271
1280
  else {
1272
- result.issues.push("Service account file missing required fields");
1281
+ result.issues.push("Credentials file missing required fields (not service account or ADC format)");
1273
1282
  }
1274
1283
  }
1275
1284
  else {
@@ -0,0 +1,23 @@
1
+ /**
2
+ * AWS SDK Global Agent Configuration for Proxy Support
3
+ * Configures Node.js global HTTP/HTTPS agents to work with AWS SDK
4
+ * Ensures BedrockRuntimeClient and other AWS services respect proxy settings
5
+ */
6
+ /**
7
+ * Configure global Node.js agents for AWS SDK proxy support
8
+ * This ensures BedrockRuntimeClient and other AWS SDK clients respect proxy settings
9
+ */
10
+ export declare function configureAWSProxySupport(): Promise<void>;
11
+ /**
12
+ * Create a proxy-aware HTTP handler for AWS SDK clients
13
+ * This is the proper way to inject proxy support into AWS SDK v3 clients
14
+ */
15
+ export declare function createAWSProxyHandler(targetUrl?: string): Promise<unknown | null>;
16
+ /**
17
+ * Clean up global agents (for testing or shutdown)
18
+ */
19
+ export declare function cleanupAWSProxySupport(): Promise<void>;
20
+ /**
21
+ * Test AWS endpoint connectivity through proxy
22
+ */
23
+ export declare function testAWSProxyConnectivity(): Promise<boolean>;