@juspay/neurolink 7.9.0 ā 7.10.1
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 +18 -6
- package/README.md +21 -7
- package/dist/agent/directTools.d.ts +23 -843
- package/dist/agent/directTools.js +1 -3
- package/dist/cli/commands/mcp.js +66 -27
- package/dist/cli/commands/ollama.js +7 -3
- package/dist/cli/commands/sagemaker.js +145 -144
- package/dist/cli/factories/commandFactory.js +4 -4
- package/dist/core/dynamicModels.js +6 -0
- package/dist/lib/agent/directTools.d.ts +23 -843
- package/dist/lib/agent/directTools.js +1 -3
- package/dist/lib/core/dynamicModels.js +6 -0
- package/dist/lib/providers/googleVertex.js +1 -1
- package/dist/lib/utils/providerHealth.js +1 -1
- package/dist/mcp/servers/agent/directToolsServer.js +0 -1
- package/dist/mcp/servers/aiProviders/aiCoreServer.js +0 -1
- package/dist/models/modelResolver.js +0 -1
- package/dist/providers/amazonBedrock.js +2 -2
- package/dist/providers/anthropic.js +2 -2
- package/dist/providers/anthropicBaseProvider.js +2 -2
- package/dist/providers/googleAiStudio.js +2 -3
- package/dist/providers/googleVertex.js +1 -1
- package/dist/providers/litellm.js +4 -4
- package/dist/providers/ollama.js +1 -2
- package/dist/providers/openAI.js +2 -2
- package/dist/providers/openaiCompatible.js +1 -2
- package/dist/providers/sagemaker/errors.js +1 -1
- package/dist/providers/sagemaker/language-model.js +1 -1
- package/dist/sdk/toolRegistration.js +0 -1
- package/dist/telemetry/telemetryService.js +0 -2
- package/dist/types/tools.js +0 -1
- package/dist/utils/providerHealth.js +1 -1
- package/package.json +40 -5
|
@@ -8,6 +8,7 @@ import chalk from "chalk";
|
|
|
8
8
|
import ora from "ora";
|
|
9
9
|
import inquirer from "inquirer";
|
|
10
10
|
import { SageMakerClient, ListEndpointsCommand, } from "@aws-sdk/client-sagemaker";
|
|
11
|
+
import { logger } from "../../lib/utils/logger.js";
|
|
11
12
|
import { checkSageMakerConfiguration, getSageMakerConfig, getConfigurationSummary, clearConfigurationCache, } from "../../lib/providers/sagemaker/config.js";
|
|
12
13
|
import { AmazonSageMakerProvider } from "../../lib/providers/sagemaker/index.js";
|
|
13
14
|
import { runQuickDiagnostics, formatDiagnosticReport, } from "../../lib/providers/sagemaker/diagnostics.js";
|
|
@@ -176,35 +177,35 @@ async function statusHandler() {
|
|
|
176
177
|
try {
|
|
177
178
|
const status = checkSageMakerConfiguration();
|
|
178
179
|
spinner.stop();
|
|
179
|
-
|
|
180
|
+
logger.always(chalk.blue("\nš SageMaker Configuration Status\n"));
|
|
180
181
|
if (status.configured) {
|
|
181
|
-
|
|
182
|
+
logger.always(chalk.green("ā
Configuration: Valid"));
|
|
182
183
|
}
|
|
183
184
|
else {
|
|
184
|
-
|
|
185
|
+
logger.always(chalk.red("ā Configuration: Invalid"));
|
|
185
186
|
}
|
|
186
187
|
if (status.issues.length > 0) {
|
|
187
|
-
|
|
188
|
+
logger.always(chalk.yellow("\nā ļø Issues found:"));
|
|
188
189
|
status.issues.forEach((issue) => {
|
|
189
|
-
|
|
190
|
+
logger.always(` ⢠${issue}`);
|
|
190
191
|
});
|
|
191
192
|
}
|
|
192
193
|
// Show configuration summary (safe for display)
|
|
193
194
|
if (status.summary) {
|
|
194
|
-
|
|
195
|
+
logger.always(chalk.blue("\nš Configuration Summary:"));
|
|
195
196
|
if (typeof status.summary === "object" && status.summary.aws) {
|
|
196
197
|
const aws = status.summary.aws;
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
198
|
+
logger.always(` Region: ${aws.region}`);
|
|
199
|
+
logger.always(` Access Key: ${aws.accessKeyId}`);
|
|
200
|
+
logger.always(` Timeout: ${aws.timeout}ms`);
|
|
201
|
+
logger.always(` Max Retries: ${aws.maxRetries}`);
|
|
201
202
|
}
|
|
202
203
|
}
|
|
203
204
|
process.exit(status.configured ? 0 : 1);
|
|
204
205
|
}
|
|
205
206
|
catch (error) {
|
|
206
207
|
spinner.fail("Failed to check SageMaker configuration");
|
|
207
|
-
|
|
208
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
208
209
|
process.exit(1);
|
|
209
210
|
}
|
|
210
211
|
}
|
|
@@ -219,7 +220,7 @@ async function testEndpointHandler(argv) {
|
|
|
219
220
|
const status = checkSageMakerConfiguration();
|
|
220
221
|
if (!status.configured) {
|
|
221
222
|
spinner.fail("SageMaker configuration is invalid");
|
|
222
|
-
|
|
223
|
+
logger.error(chalk.red("Please run 'neurolink sagemaker setup' first"));
|
|
223
224
|
process.exit(1);
|
|
224
225
|
}
|
|
225
226
|
// Create provider and test connectivity
|
|
@@ -244,26 +245,26 @@ async function testEndpointHandler(argv) {
|
|
|
244
245
|
maxTokens: 50,
|
|
245
246
|
});
|
|
246
247
|
spinner.succeed("ā
Text generation test successful");
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
248
|
+
logger.always(chalk.blue("\nš Test Response:"));
|
|
249
|
+
logger.always(` Input: "${prompt}"`);
|
|
250
|
+
logger.always(` Output: "${result.text?.substring(0, 100)}${result.text && result.text.length > 100 ? "..." : ""}"`);
|
|
251
|
+
logger.always(` Tokens: ${result.usage.promptTokens} ā ${result.usage.completionTokens} (${result.usage.totalTokens ?? result.usage.promptTokens + result.usage.completionTokens} total)`);
|
|
252
|
+
logger.always(` Finish Reason: ${result.finishReason}`);
|
|
252
253
|
}
|
|
253
254
|
catch (genError) {
|
|
254
255
|
spinner.fail("ā Text generation test failed");
|
|
255
|
-
|
|
256
|
+
logger.error(chalk.red(`Generation Error: ${genError instanceof Error ? genError.message : String(genError)}`));
|
|
256
257
|
}
|
|
257
258
|
}
|
|
258
259
|
else {
|
|
259
260
|
spinner.fail(`ā Endpoint '${endpoint}' is not accessible`);
|
|
260
|
-
|
|
261
|
+
logger.error(chalk.red(`Error: ${testResult.error}`));
|
|
261
262
|
process.exit(1);
|
|
262
263
|
}
|
|
263
264
|
}
|
|
264
265
|
catch (error) {
|
|
265
266
|
spinner.fail("Failed to test SageMaker endpoint");
|
|
266
|
-
|
|
267
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
267
268
|
process.exit(1);
|
|
268
269
|
}
|
|
269
270
|
}
|
|
@@ -290,34 +291,34 @@ async function listEndpointsHandler() {
|
|
|
290
291
|
const endpoints = { Endpoints: response.Endpoints || [] };
|
|
291
292
|
spinner.stop();
|
|
292
293
|
if (endpoints.Endpoints && endpoints.Endpoints.length > 0) {
|
|
293
|
-
|
|
294
|
+
logger.always(chalk.blue("\nš Available SageMaker Endpoints:\n"));
|
|
294
295
|
endpoints.Endpoints.forEach((endpoint, index) => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
logger.always(`${index + 1}. ${chalk.green(endpoint.EndpointName)}`);
|
|
297
|
+
logger.always(` Status: ${endpoint.EndpointStatus}`);
|
|
298
|
+
logger.always(` Created: ${endpoint.CreationTime?.toLocaleDateString() ?? "Unknown"}`);
|
|
298
299
|
if (endpoint.LastModifiedTime) {
|
|
299
|
-
|
|
300
|
+
logger.always(` Modified: ${endpoint.LastModifiedTime.toLocaleDateString()}`);
|
|
300
301
|
}
|
|
301
|
-
|
|
302
|
+
logger.always();
|
|
302
303
|
});
|
|
303
304
|
}
|
|
304
305
|
else {
|
|
305
|
-
|
|
306
|
+
logger.always(chalk.yellow("No SageMaker endpoints found"));
|
|
306
307
|
}
|
|
307
308
|
}
|
|
308
|
-
catch (
|
|
309
|
+
catch (_awsError) {
|
|
309
310
|
spinner.fail("Failed to list endpoints");
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
311
|
+
logger.error(chalk.red("AWS SDK credentials error or insufficient permissions"));
|
|
312
|
+
logger.always(chalk.yellow("\nTo list endpoints, please:"));
|
|
313
|
+
logger.always("1. Set AWS_ACCESS_KEY_ID environment variable");
|
|
314
|
+
logger.always("2. Set AWS_SECRET_ACCESS_KEY environment variable");
|
|
315
|
+
logger.always("3. Set AWS_REGION environment variable (or use default)");
|
|
316
|
+
logger.always("4. Ensure you have sagemaker:ListEndpoints permission");
|
|
316
317
|
}
|
|
317
318
|
}
|
|
318
319
|
catch (error) {
|
|
319
320
|
spinner.fail("Failed to list SageMaker endpoints");
|
|
320
|
-
|
|
321
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
321
322
|
process.exit(1);
|
|
322
323
|
}
|
|
323
324
|
}
|
|
@@ -330,9 +331,9 @@ async function configHandler(args) {
|
|
|
330
331
|
try {
|
|
331
332
|
const summary = getConfigurationSummary();
|
|
332
333
|
spinner.stop();
|
|
333
|
-
|
|
334
|
+
logger.always(chalk.blue("\nāļø SageMaker Configuration\n"));
|
|
334
335
|
if (format === "json") {
|
|
335
|
-
|
|
336
|
+
logger.always(JSON.stringify(summary, null, 2));
|
|
336
337
|
}
|
|
337
338
|
else if (format === "yaml") {
|
|
338
339
|
// Simple YAML-like output
|
|
@@ -340,11 +341,11 @@ async function configHandler(args) {
|
|
|
340
341
|
const spaces = " ".repeat(indent);
|
|
341
342
|
for (const [key, value] of Object.entries(obj)) {
|
|
342
343
|
if (typeof value === "object" && value !== null) {
|
|
343
|
-
|
|
344
|
+
logger.always(`${spaces}${key}:`);
|
|
344
345
|
printYaml(value, indent + 2);
|
|
345
346
|
}
|
|
346
347
|
else {
|
|
347
|
-
|
|
348
|
+
logger.always(`${spaces}${key}: ${value}`);
|
|
348
349
|
}
|
|
349
350
|
}
|
|
350
351
|
}
|
|
@@ -358,33 +359,33 @@ async function configHandler(args) {
|
|
|
358
359
|
{});
|
|
359
360
|
const environment = (summary.environment ||
|
|
360
361
|
{});
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
362
|
+
logger.always(chalk.green("AWS Configuration:"));
|
|
363
|
+
logger.always(` Region: ${aws.region}`);
|
|
364
|
+
logger.always(` Access Key: ${aws.accessKeyId}`);
|
|
365
|
+
logger.always(` Secret Key: ${aws.secretAccessKey}`);
|
|
366
|
+
logger.always(` Session Token: ${aws.sessionToken}`);
|
|
367
|
+
logger.always(` Timeout: ${aws.timeout}ms`);
|
|
368
|
+
logger.always(` Max Retries: ${aws.maxRetries}`);
|
|
369
|
+
logger.always(` Custom Endpoint: ${aws.endpoint || "None"}`);
|
|
370
|
+
logger.always(chalk.blue("\nSageMaker Configuration:"));
|
|
371
|
+
logger.always(` Default Endpoint: ${sagemaker.defaultEndpoint}`);
|
|
372
|
+
logger.always(` Model Name: ${sagemaker.model}`);
|
|
372
373
|
if (sagemaker.modelConfig) {
|
|
373
374
|
const modelConfig = sagemaker.modelConfig;
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
375
|
+
logger.always(` Model Type: ${modelConfig.modelType}`);
|
|
376
|
+
logger.always(` Content Type: ${modelConfig.contentType}`);
|
|
377
|
+
logger.always(` Accept: ${modelConfig.accept}`);
|
|
377
378
|
}
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
379
|
+
logger.always(chalk.yellow("\nEnvironment:"));
|
|
380
|
+
logger.always(` Node Environment: ${environment.nodeEnv}`);
|
|
381
|
+
logger.always(` SageMaker Configured: ${environment.sagemakerConfigured ? "Yes" : "No"}`);
|
|
382
|
+
logger.always(` AWS Configured: ${environment.awsConfigured ? "Yes" : "No"}`);
|
|
382
383
|
}
|
|
383
384
|
}
|
|
384
385
|
}
|
|
385
386
|
catch (error) {
|
|
386
387
|
spinner.fail("Failed to load SageMaker configuration");
|
|
387
|
-
|
|
388
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
388
389
|
process.exit(1);
|
|
389
390
|
}
|
|
390
391
|
}
|
|
@@ -392,9 +393,9 @@ async function configHandler(args) {
|
|
|
392
393
|
* Handler for interactive setup
|
|
393
394
|
*/
|
|
394
395
|
async function setupHandler() {
|
|
395
|
-
|
|
396
|
+
logger.always(chalk.blue("\nš SageMaker Interactive Setup\n"));
|
|
396
397
|
// Pre-setup security advisory
|
|
397
|
-
|
|
398
|
+
logger.always(chalk.yellow.bold("š SECURITY NOTICE: You will be prompted to enter AWS credentials.\n" +
|
|
398
399
|
"These credentials will be stored temporarily in memory only.\n" +
|
|
399
400
|
"For production use, consider using AWS credential files or IAM roles.\n"));
|
|
400
401
|
// Ask for user confirmation before proceeding
|
|
@@ -407,11 +408,11 @@ async function setupHandler() {
|
|
|
407
408
|
},
|
|
408
409
|
]);
|
|
409
410
|
if (!confirmSetup) {
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
411
|
+
logger.always(chalk.blue("\nSetup cancelled. Consider using alternative credential methods:"));
|
|
412
|
+
logger.always("⢠AWS credential files: ~/.aws/credentials");
|
|
413
|
+
logger.always("⢠Environment variables in .env file");
|
|
414
|
+
logger.always("⢠AWS CLI configuration: aws configure");
|
|
415
|
+
logger.always("⢠IAM roles for production environments");
|
|
415
416
|
return;
|
|
416
417
|
}
|
|
417
418
|
try {
|
|
@@ -456,8 +457,8 @@ async function setupHandler() {
|
|
|
456
457
|
const spinner = ora("Setting up SageMaker configuration...").start();
|
|
457
458
|
// Enhanced security warnings for credential handling
|
|
458
459
|
spinner.stop();
|
|
459
|
-
|
|
460
|
-
|
|
460
|
+
logger.always(chalk.red.bold("\nš CRITICAL SECURITY WARNINGS\n"));
|
|
461
|
+
logger.always(chalk.yellow.bold("ā ļø CREDENTIAL PERSISTENCE: AWS credentials will only be set for this session.\n" +
|
|
461
462
|
" They will NOT persist after you exit the CLI.\n\n" +
|
|
462
463
|
"š SECURE STORAGE OPTIONS:\n" +
|
|
463
464
|
" ⢠Use environment variables in a secure .env file (never commit to git)\n" +
|
|
@@ -495,17 +496,17 @@ async function setupHandler() {
|
|
|
495
496
|
try {
|
|
496
497
|
validateSecureConfiguration(secureConfig); // Validate configuration is loadable
|
|
497
498
|
spinner.succeed("ā
Configuration validated successfully");
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
499
|
+
logger.always(chalk.green("\nš SageMaker setup complete!"));
|
|
500
|
+
logger.always(chalk.yellow("\nš” Next steps:"));
|
|
501
|
+
logger.always("1. Test your endpoint: neurolink sagemaker test <endpoint-name>");
|
|
502
|
+
logger.always("2. Check status: neurolink sagemaker status");
|
|
503
|
+
logger.always("3. List endpoints: neurolink sagemaker list-endpoints");
|
|
504
|
+
logger.always(chalk.blue("\nš Secure configuration validated:"));
|
|
505
|
+
logger.always(" ā AWS credentials verified");
|
|
506
|
+
logger.always(" ā AWS region validated");
|
|
507
|
+
logger.always(" ā SageMaker endpoint configured");
|
|
508
|
+
logger.always(" ā Timeout and retry settings applied");
|
|
509
|
+
logger.always(chalk.yellow("\nā ļø For persistent configuration, add these to your .env file:\n" +
|
|
509
510
|
" AWS_ACCESS_KEY_ID=your_access_key\n" +
|
|
510
511
|
" AWS_SECRET_ACCESS_KEY=your_secret_key\n" +
|
|
511
512
|
" AWS_REGION=" +
|
|
@@ -525,14 +526,14 @@ async function setupHandler() {
|
|
|
525
526
|
}
|
|
526
527
|
catch (configError) {
|
|
527
528
|
spinner.fail("ā Configuration validation failed");
|
|
528
|
-
|
|
529
|
+
logger.error(chalk.red(`Error: ${configError instanceof Error ? configError.message : String(configError)}`));
|
|
529
530
|
// Clear secure credentials from memory on error
|
|
530
531
|
clearSecureCredentials(secureConfig.sessionId);
|
|
531
532
|
process.exit(1);
|
|
532
533
|
}
|
|
533
534
|
}
|
|
534
535
|
catch (error) {
|
|
535
|
-
|
|
536
|
+
logger.error(chalk.red(`Setup failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
536
537
|
process.exit(1);
|
|
537
538
|
}
|
|
538
539
|
}
|
|
@@ -544,27 +545,27 @@ async function validateHandler() {
|
|
|
544
545
|
try {
|
|
545
546
|
const status = checkSageMakerConfiguration();
|
|
546
547
|
spinner.stop();
|
|
547
|
-
|
|
548
|
+
logger.always(chalk.blue("\nš Configuration Validation Results\n"));
|
|
548
549
|
if (status.configured) {
|
|
549
|
-
|
|
550
|
-
|
|
550
|
+
logger.always(chalk.green("ā
All checks passed"));
|
|
551
|
+
logger.always(chalk.blue("š SageMaker is ready to use"));
|
|
551
552
|
}
|
|
552
553
|
else {
|
|
553
|
-
|
|
554
|
+
logger.always(chalk.red("ā Configuration validation failed"));
|
|
554
555
|
if (status.issues.length > 0) {
|
|
555
|
-
|
|
556
|
+
logger.always(chalk.yellow("\nš§ Issues to fix:"));
|
|
556
557
|
status.issues.forEach((issue, index) => {
|
|
557
|
-
|
|
558
|
+
logger.always(`${index + 1}. ${issue}`);
|
|
558
559
|
});
|
|
559
560
|
}
|
|
560
|
-
|
|
561
|
-
|
|
561
|
+
logger.always(chalk.blue("\nš” How to fix:"));
|
|
562
|
+
logger.always("Run: neurolink sagemaker setup");
|
|
562
563
|
process.exit(1);
|
|
563
564
|
}
|
|
564
565
|
}
|
|
565
566
|
catch (error) {
|
|
566
567
|
spinner.fail("Validation failed");
|
|
567
|
-
|
|
568
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
568
569
|
process.exit(1);
|
|
569
570
|
}
|
|
570
571
|
}
|
|
@@ -573,18 +574,18 @@ async function validateHandler() {
|
|
|
573
574
|
*/
|
|
574
575
|
async function benchmarkHandler(argv) {
|
|
575
576
|
const { endpoint, requests = 10, concurrency = 2, maxTokens = 100 } = argv;
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
577
|
+
logger.always(chalk.blue(`\nā” SageMaker Performance Benchmark\n`));
|
|
578
|
+
logger.always(`Endpoint: ${endpoint}`);
|
|
579
|
+
logger.always(`Requests: ${requests}`);
|
|
580
|
+
logger.always(`Concurrency: ${concurrency}`);
|
|
581
|
+
logger.always(`Max Tokens: ${maxTokens}\n`);
|
|
581
582
|
const spinner = ora("Setting up benchmark...").start();
|
|
582
583
|
try {
|
|
583
584
|
// Check configuration first
|
|
584
585
|
const status = checkSageMakerConfiguration();
|
|
585
586
|
if (!status.configured) {
|
|
586
587
|
spinner.fail("SageMaker configuration is invalid");
|
|
587
|
-
|
|
588
|
+
logger.error(chalk.red("Please run 'neurolink sagemaker setup' first"));
|
|
588
589
|
process.exit(1);
|
|
589
590
|
}
|
|
590
591
|
const provider = new AmazonSageMakerProvider(undefined, endpoint);
|
|
@@ -593,7 +594,7 @@ async function benchmarkHandler(argv) {
|
|
|
593
594
|
const connectivityTest = await provider.testConnectivity();
|
|
594
595
|
if (!connectivityTest.success) {
|
|
595
596
|
spinner.fail(`Endpoint '${endpoint}' is not accessible`);
|
|
596
|
-
|
|
597
|
+
logger.error(chalk.red(`Error: ${connectivityTest.error}`));
|
|
597
598
|
process.exit(1);
|
|
598
599
|
}
|
|
599
600
|
spinner.text = "Starting benchmark...";
|
|
@@ -651,35 +652,35 @@ async function benchmarkHandler(argv) {
|
|
|
651
652
|
const failed = results.filter((r) => !r.success);
|
|
652
653
|
const durations = successful.map((r) => r.duration);
|
|
653
654
|
const totalTokens = successful.reduce((sum, r) => sum + r.tokens, 0);
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
655
|
+
logger.always(chalk.green("\nš Benchmark Results\n"));
|
|
656
|
+
logger.always(`Total Time: ${totalTime}ms`);
|
|
657
|
+
logger.always(`Successful Requests: ${successful.length}/${requests}`);
|
|
658
|
+
logger.always(`Failed Requests: ${failed.length}`);
|
|
659
|
+
logger.always(`Success Rate: ${((successful.length / requests) * 100).toFixed(1)}%`);
|
|
659
660
|
if (successful.length > 0) {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
661
|
+
logger.always(`\nLatency Statistics:`);
|
|
662
|
+
logger.always(` Average: ${(durations.reduce((a, b) => a + b, 0) / durations.length).toFixed(0)}ms`);
|
|
663
|
+
logger.always(` Minimum: ${Math.min(...durations)}ms`);
|
|
664
|
+
logger.always(` Maximum: ${Math.max(...durations)}ms`);
|
|
665
|
+
logger.always(` Median: ${durations.sort((a, b) => a - b)[Math.floor(durations.length / 2)]}ms`);
|
|
666
|
+
logger.always(`\nThroughput:`);
|
|
667
|
+
logger.always(` Requests/sec: ${(successful.length / (totalTime / 1000)).toFixed(2)}`);
|
|
668
|
+
logger.always(` Tokens/sec: ${(totalTokens / (totalTime / 1000)).toFixed(2)}`);
|
|
669
|
+
logger.always(` Average tokens/request: ${(totalTokens / successful.length).toFixed(1)}`);
|
|
669
670
|
}
|
|
670
671
|
if (failed.length > 0) {
|
|
671
|
-
|
|
672
|
+
logger.always(chalk.red(`\nā Failed Requests (${failed.length}):`));
|
|
672
673
|
failed.slice(0, 5).forEach((failure, index) => {
|
|
673
|
-
|
|
674
|
+
logger.always(` ${index + 1}. ${failure.error}`);
|
|
674
675
|
});
|
|
675
676
|
if (failed.length > 5) {
|
|
676
|
-
|
|
677
|
+
logger.always(` ... and ${failed.length - 5} more`);
|
|
677
678
|
}
|
|
678
679
|
}
|
|
679
680
|
}
|
|
680
681
|
catch (error) {
|
|
681
682
|
spinner.fail("Benchmark failed");
|
|
682
|
-
|
|
683
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
683
684
|
process.exit(1);
|
|
684
685
|
}
|
|
685
686
|
}
|
|
@@ -691,11 +692,11 @@ async function clearCacheHandler() {
|
|
|
691
692
|
try {
|
|
692
693
|
clearConfigurationCache();
|
|
693
694
|
spinner.succeed("ā
Configuration cache cleared");
|
|
694
|
-
|
|
695
|
+
logger.always(chalk.blue("Configuration will be reloaded on next use"));
|
|
695
696
|
}
|
|
696
697
|
catch (error) {
|
|
697
698
|
spinner.fail("Failed to clear cache");
|
|
698
|
-
|
|
699
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
699
700
|
process.exit(1);
|
|
700
701
|
}
|
|
701
702
|
}
|
|
@@ -704,15 +705,15 @@ async function clearCacheHandler() {
|
|
|
704
705
|
*/
|
|
705
706
|
async function diagnoseHandler(argv) {
|
|
706
707
|
const { endpoint, quick, full, timeout } = argv;
|
|
707
|
-
|
|
708
|
+
logger.always(chalk.blue(`\nš SageMaker Streaming Diagnostics\n`));
|
|
708
709
|
if (endpoint) {
|
|
709
|
-
|
|
710
|
+
logger.always(`Endpoint: ${endpoint}`);
|
|
710
711
|
}
|
|
711
712
|
else {
|
|
712
|
-
|
|
713
|
+
logger.always("Endpoint: Not specified (configuration tests only)");
|
|
713
714
|
}
|
|
714
|
-
|
|
715
|
-
|
|
715
|
+
logger.always(`Mode: ${quick ? "Quick" : full ? "Full" : "Standard"}`);
|
|
716
|
+
logger.always(`Timeout: ${timeout}ms\n`);
|
|
716
717
|
const spinner = ora("Starting diagnostics...").start();
|
|
717
718
|
try {
|
|
718
719
|
// Run diagnostics (simplified - advanced streaming diagnostics removed)
|
|
@@ -720,59 +721,59 @@ async function diagnoseHandler(argv) {
|
|
|
720
721
|
spinner.stop();
|
|
721
722
|
// Display results
|
|
722
723
|
const formatted = formatDiagnosticReport(report);
|
|
723
|
-
|
|
724
|
+
logger.always(formatted);
|
|
724
725
|
// Additional insights based on results
|
|
725
726
|
if (report.overallStatus === "critical") {
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
727
|
+
logger.always(chalk.red("šØ Critical Issues Detected"));
|
|
728
|
+
logger.always(chalk.red(" Your streaming configuration has serious problems that need immediate attention."));
|
|
729
|
+
logger.always(chalk.yellow(" See the recommendations above for resolution steps.\n"));
|
|
729
730
|
}
|
|
730
731
|
else if (report.overallStatus === "issues") {
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
732
|
+
logger.always(chalk.yellow("ā ļø Issues Detected"));
|
|
733
|
+
logger.always(chalk.yellow(" Your streaming setup works but has some issues that could affect performance."));
|
|
734
|
+
logger.always(chalk.blue(" Consider addressing the recommendations above.\n"));
|
|
734
735
|
}
|
|
735
736
|
else {
|
|
736
|
-
|
|
737
|
-
|
|
737
|
+
logger.always(chalk.green("ā
All Systems Go"));
|
|
738
|
+
logger.always(chalk.green(" Your SageMaker streaming configuration looks healthy!"));
|
|
738
739
|
if (endpoint) {
|
|
739
|
-
|
|
740
|
-
|
|
740
|
+
logger.always(chalk.blue(" You can now use streaming features with confidence.\n"));
|
|
741
|
+
logger.always(chalk.dim(" Try: neurolink sagemaker stream " + endpoint));
|
|
741
742
|
}
|
|
742
743
|
}
|
|
743
744
|
// Show additional help based on findings
|
|
744
745
|
const failedTests = report.results.filter((r) => r.status === "fail");
|
|
745
746
|
if (failedTests.length > 0) {
|
|
746
|
-
|
|
747
|
+
logger.always(chalk.blue("š Additional Resources:"));
|
|
747
748
|
const hasConnectivityIssues = failedTests.some((t) => t.category === "connectivity");
|
|
748
749
|
const hasStreamingIssues = failedTests.some((t) => t.category === "streaming");
|
|
749
750
|
const hasConfigIssues = failedTests.some((t) => t.category === "configuration");
|
|
750
751
|
if (hasConfigIssues) {
|
|
751
|
-
|
|
752
|
+
logger.always(" ⢠Configuration: neurolink sagemaker setup");
|
|
752
753
|
}
|
|
753
754
|
if (hasConnectivityIssues) {
|
|
754
|
-
|
|
755
|
+
logger.always(" ⢠Connectivity: neurolink sagemaker test " +
|
|
755
756
|
(endpoint || "your-endpoint"));
|
|
756
757
|
}
|
|
757
758
|
if (hasStreamingIssues) {
|
|
758
|
-
|
|
759
|
+
logger.always(" ⢠Streaming Guide: docs/providers/sagemaker/streaming-troubleshooting.md");
|
|
759
760
|
}
|
|
760
|
-
|
|
761
|
+
logger.always(" ⢠Full Diagnostics: neurolink sagemaker diagnose " +
|
|
761
762
|
(endpoint || "") +
|
|
762
763
|
" --full");
|
|
763
|
-
|
|
764
|
+
logger.always();
|
|
764
765
|
}
|
|
765
766
|
// Exit with appropriate code
|
|
766
767
|
process.exit(report.overallStatus === "critical" ? 1 : 0);
|
|
767
768
|
}
|
|
768
769
|
catch (error) {
|
|
769
770
|
spinner.fail("Diagnostics failed");
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
771
|
+
logger.error(chalk.red(`Error: ${error instanceof Error ? error.message : String(error)}`));
|
|
772
|
+
logger.always(chalk.yellow("\nš” Diagnostic troubleshooting:"));
|
|
773
|
+
logger.always(" ⢠Check your SageMaker configuration: neurolink sagemaker status");
|
|
774
|
+
logger.always(" ⢠Verify AWS credentials and permissions");
|
|
775
|
+
logger.always(" ⢠Try with a specific endpoint: neurolink sagemaker diagnose your-endpoint");
|
|
776
|
+
logger.always(" ⢠Run quick mode: neurolink sagemaker diagnose --quick");
|
|
776
777
|
process.exit(1);
|
|
777
778
|
}
|
|
778
779
|
}
|
|
@@ -452,15 +452,15 @@ export class CLICommandFactory {
|
|
|
452
452
|
describe: "Manage NeuroLink configuration",
|
|
453
453
|
builder: (yargs) => {
|
|
454
454
|
return yargs
|
|
455
|
-
.command("init", "Interactive configuration setup wizard", (y) => this.buildOptions(y), async (
|
|
455
|
+
.command("init", "Interactive configuration setup wizard", (y) => this.buildOptions(y), async (_argv) => {
|
|
456
456
|
const { configManager } = await import("../commands/config.js");
|
|
457
457
|
await configManager.initInteractive();
|
|
458
458
|
})
|
|
459
|
-
.command("show", "Display current configuration", (y) => this.buildOptions(y), async (
|
|
459
|
+
.command("show", "Display current configuration", (y) => this.buildOptions(y), async (_argv) => {
|
|
460
460
|
const { configManager } = await import("../commands/config.js");
|
|
461
461
|
configManager.showConfig();
|
|
462
462
|
})
|
|
463
|
-
.command("validate", "Validate current configuration", (y) => this.buildOptions(y), async (
|
|
463
|
+
.command("validate", "Validate current configuration", (y) => this.buildOptions(y), async (_argv) => {
|
|
464
464
|
const { configManager } = await import("../commands/config.js");
|
|
465
465
|
const result = configManager.validateConfig();
|
|
466
466
|
if (result.valid) {
|
|
@@ -472,7 +472,7 @@ export class CLICommandFactory {
|
|
|
472
472
|
process.exit(1);
|
|
473
473
|
}
|
|
474
474
|
})
|
|
475
|
-
.command("reset", "Reset configuration to defaults", (y) => this.buildOptions(y), async (
|
|
475
|
+
.command("reset", "Reset configuration to defaults", (y) => this.buildOptions(y), async (_argv) => {
|
|
476
476
|
const { configManager } = await import("../commands/config.js");
|
|
477
477
|
configManager.resetConfig();
|
|
478
478
|
})
|
|
@@ -100,6 +100,12 @@ export class DynamicModelProvider {
|
|
|
100
100
|
// Setup timeout and abort controller
|
|
101
101
|
const controller = new AbortController();
|
|
102
102
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
103
|
+
// Load from URL
|
|
104
|
+
const response = await fetch(source, {
|
|
105
|
+
headers: {
|
|
106
|
+
"User-Agent": "NeuroLink/1.0 (+https://github.com/juspay/neurolink)",
|
|
107
|
+
},
|
|
108
|
+
});
|
|
103
109
|
try {
|
|
104
110
|
// Add health check for localhost before attempting full request
|
|
105
111
|
if (source.includes("localhost") || source.includes("127.0.0.1")) {
|