@juspay/neurolink 7.6.1 → 7.7.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.
Files changed (138) hide show
  1. package/CHANGELOG.md +15 -4
  2. package/README.md +78 -3
  3. package/dist/cli/commands/config.d.ts +275 -3
  4. package/dist/cli/commands/config.js +121 -0
  5. package/dist/cli/commands/mcp.js +77 -28
  6. package/dist/cli/factories/commandFactory.js +359 -6
  7. package/dist/core/analytics.js +7 -27
  8. package/dist/core/baseProvider.js +43 -4
  9. package/dist/core/constants.d.ts +46 -0
  10. package/dist/core/constants.js +47 -0
  11. package/dist/core/dynamicModels.d.ts +16 -4
  12. package/dist/core/dynamicModels.js +130 -26
  13. package/dist/core/evaluation.js +5 -1
  14. package/dist/core/evaluationProviders.d.ts +6 -2
  15. package/dist/core/evaluationProviders.js +41 -125
  16. package/dist/core/factory.d.ts +5 -0
  17. package/dist/core/factory.js +62 -50
  18. package/dist/core/modelConfiguration.d.ts +246 -0
  19. package/dist/core/modelConfiguration.js +775 -0
  20. package/dist/core/types.d.ts +22 -3
  21. package/dist/core/types.js +5 -1
  22. package/dist/factories/providerRegistry.js +3 -3
  23. package/dist/index.d.ts +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/lib/core/analytics.js +7 -27
  26. package/dist/lib/core/baseProvider.js +43 -4
  27. package/dist/lib/core/constants.d.ts +46 -0
  28. package/dist/lib/core/constants.js +47 -0
  29. package/dist/lib/core/dynamicModels.d.ts +16 -4
  30. package/dist/lib/core/dynamicModels.js +130 -26
  31. package/dist/lib/core/evaluation.js +5 -1
  32. package/dist/lib/core/evaluationProviders.d.ts +6 -2
  33. package/dist/lib/core/evaluationProviders.js +41 -125
  34. package/dist/lib/core/factory.d.ts +5 -0
  35. package/dist/lib/core/factory.js +63 -50
  36. package/dist/lib/core/modelConfiguration.d.ts +246 -0
  37. package/dist/lib/core/modelConfiguration.js +775 -0
  38. package/dist/lib/core/types.d.ts +22 -3
  39. package/dist/lib/core/types.js +5 -1
  40. package/dist/lib/factories/providerRegistry.js +3 -3
  41. package/dist/lib/index.d.ts +1 -1
  42. package/dist/lib/index.js +1 -1
  43. package/dist/lib/mcp/factory.d.ts +5 -5
  44. package/dist/lib/mcp/factory.js +2 -2
  45. package/dist/lib/mcp/servers/utilities/utilityServer.d.ts +1 -1
  46. package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -1
  47. package/dist/lib/mcp/toolRegistry.js +2 -2
  48. package/dist/lib/neurolink.d.ts +168 -12
  49. package/dist/lib/neurolink.js +685 -123
  50. package/dist/lib/providers/anthropic.js +52 -2
  51. package/dist/lib/providers/googleAiStudio.js +4 -0
  52. package/dist/lib/providers/googleVertex.d.ts +75 -9
  53. package/dist/lib/providers/googleVertex.js +365 -46
  54. package/dist/lib/providers/huggingFace.d.ts +52 -11
  55. package/dist/lib/providers/huggingFace.js +180 -42
  56. package/dist/lib/providers/litellm.d.ts +9 -9
  57. package/dist/lib/providers/litellm.js +103 -16
  58. package/dist/lib/providers/ollama.d.ts +52 -17
  59. package/dist/lib/providers/ollama.js +276 -68
  60. package/dist/lib/sdk/toolRegistration.d.ts +42 -0
  61. package/dist/lib/sdk/toolRegistration.js +269 -27
  62. package/dist/lib/telemetry/telemetryService.d.ts +6 -0
  63. package/dist/lib/telemetry/telemetryService.js +38 -3
  64. package/dist/lib/types/contextTypes.d.ts +75 -11
  65. package/dist/lib/types/contextTypes.js +227 -1
  66. package/dist/lib/types/domainTypes.d.ts +62 -0
  67. package/dist/lib/types/domainTypes.js +5 -0
  68. package/dist/lib/types/generateTypes.d.ts +52 -0
  69. package/dist/lib/types/index.d.ts +1 -0
  70. package/dist/lib/types/mcpTypes.d.ts +1 -1
  71. package/dist/lib/types/mcpTypes.js +1 -1
  72. package/dist/lib/types/streamTypes.d.ts +14 -0
  73. package/dist/lib/types/universalProviderOptions.d.ts +1 -1
  74. package/dist/lib/utils/errorHandling.d.ts +142 -0
  75. package/dist/lib/utils/errorHandling.js +316 -0
  76. package/dist/lib/utils/factoryProcessing.d.ts +74 -0
  77. package/dist/lib/utils/factoryProcessing.js +588 -0
  78. package/dist/lib/utils/optionsConversion.d.ts +54 -0
  79. package/dist/lib/utils/optionsConversion.js +126 -0
  80. package/dist/lib/utils/optionsUtils.d.ts +246 -0
  81. package/dist/lib/utils/optionsUtils.js +960 -0
  82. package/dist/lib/utils/providerConfig.js +6 -2
  83. package/dist/lib/utils/providerHealth.d.ts +107 -0
  84. package/dist/lib/utils/providerHealth.js +543 -0
  85. package/dist/lib/utils/providerUtils.d.ts +17 -0
  86. package/dist/lib/utils/providerUtils.js +271 -16
  87. package/dist/lib/utils/timeout.js +1 -1
  88. package/dist/lib/utils/tokenLimits.d.ts +33 -0
  89. package/dist/lib/utils/tokenLimits.js +118 -0
  90. package/dist/mcp/factory.d.ts +5 -5
  91. package/dist/mcp/factory.js +2 -2
  92. package/dist/mcp/servers/utilities/utilityServer.d.ts +1 -1
  93. package/dist/mcp/servers/utilities/utilityServer.js +1 -1
  94. package/dist/mcp/toolRegistry.js +2 -2
  95. package/dist/neurolink.d.ts +168 -12
  96. package/dist/neurolink.js +685 -123
  97. package/dist/providers/anthropic.js +52 -2
  98. package/dist/providers/googleAiStudio.js +4 -0
  99. package/dist/providers/googleVertex.d.ts +75 -9
  100. package/dist/providers/googleVertex.js +365 -46
  101. package/dist/providers/huggingFace.d.ts +52 -11
  102. package/dist/providers/huggingFace.js +181 -43
  103. package/dist/providers/litellm.d.ts +9 -9
  104. package/dist/providers/litellm.js +103 -16
  105. package/dist/providers/ollama.d.ts +52 -17
  106. package/dist/providers/ollama.js +276 -68
  107. package/dist/sdk/toolRegistration.d.ts +42 -0
  108. package/dist/sdk/toolRegistration.js +269 -27
  109. package/dist/telemetry/telemetryService.d.ts +6 -0
  110. package/dist/telemetry/telemetryService.js +38 -3
  111. package/dist/types/contextTypes.d.ts +75 -11
  112. package/dist/types/contextTypes.js +227 -2
  113. package/dist/types/domainTypes.d.ts +62 -0
  114. package/dist/types/domainTypes.js +5 -0
  115. package/dist/types/generateTypes.d.ts +52 -0
  116. package/dist/types/index.d.ts +1 -0
  117. package/dist/types/mcpTypes.d.ts +1 -1
  118. package/dist/types/mcpTypes.js +1 -1
  119. package/dist/types/streamTypes.d.ts +14 -0
  120. package/dist/types/universalProviderOptions.d.ts +1 -1
  121. package/dist/types/universalProviderOptions.js +0 -1
  122. package/dist/utils/errorHandling.d.ts +142 -0
  123. package/dist/utils/errorHandling.js +316 -0
  124. package/dist/utils/factoryProcessing.d.ts +74 -0
  125. package/dist/utils/factoryProcessing.js +588 -0
  126. package/dist/utils/optionsConversion.d.ts +54 -0
  127. package/dist/utils/optionsConversion.js +126 -0
  128. package/dist/utils/optionsUtils.d.ts +246 -0
  129. package/dist/utils/optionsUtils.js +960 -0
  130. package/dist/utils/providerConfig.js +6 -2
  131. package/dist/utils/providerHealth.d.ts +107 -0
  132. package/dist/utils/providerHealth.js +543 -0
  133. package/dist/utils/providerUtils.d.ts +17 -0
  134. package/dist/utils/providerUtils.js +271 -16
  135. package/dist/utils/timeout.js +1 -1
  136. package/dist/utils/tokenLimits.d.ts +33 -0
  137. package/dist/utils/tokenLimits.js +118 -0
  138. package/package.json +2 -2
@@ -705,31 +705,63 @@ export class MCPCommandFactory {
705
705
  }
706
706
  process.exit(1);
707
707
  }
708
- // Execute the tool (This would need actual MCP execution logic)
709
- // For now, showing a placeholder implementation
710
- const result = {
711
- tool: toolName,
712
- server: serverName,
713
- params,
714
- result: "Tool execution not yet implemented in NeuroLink SDK",
715
- timestamp: new Date().toISOString(),
716
- };
717
- if (spinner) {
718
- spinner.succeed(chalk.green("āœ… Tool executed successfully"));
719
- }
720
- // Display results
721
- if (argv.format === "json") {
722
- logger.always(JSON.stringify(result, null, 2));
708
+ // Execute the tool using the NeuroLink MCP tool registry
709
+ try {
710
+ const { toolRegistry } = await import("../../lib/mcp/toolRegistry.js");
711
+ const executionResult = await toolRegistry.executeTool(toolName, params, {
712
+ sessionId: `cli-${Date.now()}`,
713
+ userId: process.env.USER || "cli-user",
714
+ config: {
715
+ domainType: "cli-execution",
716
+ customData: { serverName },
717
+ },
718
+ });
719
+ const result = {
720
+ tool: toolName,
721
+ server: serverName,
722
+ params,
723
+ result: executionResult,
724
+ success: true,
725
+ timestamp: new Date().toISOString(),
726
+ };
727
+ if (spinner) {
728
+ spinner.succeed(chalk.green("āœ… Tool executed successfully"));
729
+ }
730
+ // Display results
731
+ if (argv.format === "json") {
732
+ logger.always(JSON.stringify(result, null, 2));
733
+ }
734
+ else {
735
+ logger.always(chalk.green("šŸ”§ Tool Execution Results:"));
736
+ logger.always(` Tool: ${chalk.cyan(toolName)}`);
737
+ logger.always(` Server: ${chalk.cyan(serverName)}`);
738
+ logger.always(` Result: ${JSON.stringify(executionResult, null, 2)}`);
739
+ logger.always(` Timestamp: ${result.timestamp}`);
740
+ }
723
741
  }
724
- else {
725
- logger.always(chalk.bold("\nšŸ› ļø Tool Execution Result:\n"));
726
- logger.always(`Tool: ${toolName}`);
727
- logger.always(`Server: ${serverName}`);
728
- if (Object.keys(params).length > 0) {
729
- logger.always(`Params: ${JSON.stringify(params)}`);
742
+ catch (toolError) {
743
+ const errorMessage = toolError instanceof Error ? toolError.message : String(toolError);
744
+ if (spinner) {
745
+ spinner.fail(chalk.red("āŒ Tool execution failed"));
730
746
  }
731
- logger.always(`Result: ${result.result}`);
732
- logger.always(`Time: ${result.timestamp}`);
747
+ const result = {
748
+ tool: toolName,
749
+ server: serverName,
750
+ params,
751
+ error: errorMessage,
752
+ success: false,
753
+ timestamp: new Date().toISOString(),
754
+ };
755
+ if (argv.format === "json") {
756
+ logger.always(JSON.stringify(result, null, 2));
757
+ }
758
+ else {
759
+ logger.error(chalk.red("šŸ”§ Tool Execution Failed:"));
760
+ logger.error(` Tool: ${chalk.cyan(toolName)}`);
761
+ logger.error(` Server: ${chalk.cyan(serverName)}`);
762
+ logger.error(` Error: ${chalk.red(errorMessage)}`);
763
+ }
764
+ process.exit(1);
733
765
  }
734
766
  }
735
767
  catch (error) {
@@ -760,11 +792,28 @@ export class MCPCommandFactory {
760
792
  const spinner = argv.quiet
761
793
  ? null
762
794
  : ora(`Removing MCP server: ${serverName}...`).start();
763
- // Remove server (This would need actual removal logic in NeuroLink SDK)
764
- // For now, showing a placeholder
765
- logger.always(chalk.yellow("āš ļø Server removal not yet implemented in NeuroLink SDK"));
766
- if (spinner) {
767
- spinner.succeed(chalk.green(`āœ… Server ${serverName} removed successfully`));
795
+ // Remove server using the NeuroLink MCP tool registry
796
+ try {
797
+ const { toolRegistry } = await import("../../lib/mcp/toolRegistry.js");
798
+ const removed = toolRegistry.unregisterServer(serverName);
799
+ if (!removed) {
800
+ throw new Error(`Failed to remove server ${serverName} from registry`);
801
+ }
802
+ if (spinner) {
803
+ spinner.succeed(chalk.green(`āœ… Server ${serverName} removed successfully`));
804
+ }
805
+ logger.always(chalk.green(`šŸ—‘ļø Successfully removed MCP server: ${serverName}`));
806
+ logger.always(chalk.gray(" All associated tools have been unregistered"));
807
+ }
808
+ catch (removalError) {
809
+ const errorMessage = removalError instanceof Error
810
+ ? removalError.message
811
+ : String(removalError);
812
+ if (spinner) {
813
+ spinner.fail(chalk.red(`āŒ Failed to remove server ${serverName}`));
814
+ }
815
+ logger.error(chalk.red(`āŒ Server removal failed: ${errorMessage}`));
816
+ process.exit(1);
768
817
  }
769
818
  }
770
819
  catch (error) {
@@ -93,6 +93,22 @@ export class CLICommandFactory {
93
93
  default: false,
94
94
  description: "Enable AI response quality evaluation",
95
95
  },
96
+ domain: {
97
+ type: "string",
98
+ choices: [
99
+ "healthcare",
100
+ "finance",
101
+ "analytics",
102
+ "ecommerce",
103
+ "education",
104
+ "legal",
105
+ "technology",
106
+ "generic",
107
+ "auto",
108
+ ],
109
+ description: "Domain type for specialized processing and optimization",
110
+ alias: "d",
111
+ },
96
112
  evaluationDomain: {
97
113
  type: "string",
98
114
  description: "Domain expertise for evaluation (e.g., 'AI coding assistant', 'Customer service expert')",
@@ -101,10 +117,10 @@ export class CLICommandFactory {
101
117
  type: "string",
102
118
  description: "Tool usage context for evaluation (e.g., 'Used sales-data MCP tools')",
103
119
  },
104
- lighthouseStyle: {
120
+ domainAware: {
105
121
  type: "boolean",
106
122
  default: false,
107
- description: "Use Lighthouse-compatible domain-aware evaluation",
123
+ description: "Use domain-aware evaluation",
108
124
  },
109
125
  context: {
110
126
  type: "string",
@@ -132,6 +148,11 @@ export class CLICommandFactory {
132
148
  type: "string",
133
149
  description: "Path to custom configuration file",
134
150
  },
151
+ dryRun: {
152
+ type: "boolean",
153
+ default: false,
154
+ description: "Test command without making actual API calls (for testing)",
155
+ },
135
156
  };
136
157
  // Helper method to build options for commands
137
158
  static buildOptions(yargs, additionalOptions = {}) {
@@ -193,9 +214,10 @@ export class CLICommandFactory {
193
214
  disableTools: argv.disableTools,
194
215
  enableAnalytics: argv.enableAnalytics,
195
216
  enableEvaluation: argv.enableEvaluation,
217
+ domain: argv.domain,
196
218
  evaluationDomain: argv.evaluationDomain,
197
219
  toolUsageContext: argv.toolUsageContext,
198
- lighthouseStyle: argv.lighthouseStyle,
220
+ domainAware: argv.domainAware,
199
221
  context: processedContext,
200
222
  contextConfig,
201
223
  debug: argv.debug,
@@ -205,6 +227,7 @@ export class CLICommandFactory {
205
227
  delay: argv.delay,
206
228
  noColor: argv.noColor,
207
229
  configFile: argv.configFile,
230
+ dryRun: argv.dryRun,
208
231
  };
209
232
  }
210
233
  // Helper method to handle output
@@ -494,6 +517,53 @@ export class CLICommandFactory {
494
517
  ? null
495
518
  : ora("šŸ” Checking AI provider status...\n").start();
496
519
  try {
520
+ // Handle dry-run mode for provider status
521
+ if (argv.dryRun) {
522
+ const mockResults = [
523
+ {
524
+ provider: "google-ai",
525
+ status: "working",
526
+ configured: true,
527
+ responseTime: 150,
528
+ model: "gemini-2.5-flash",
529
+ },
530
+ {
531
+ provider: "openai",
532
+ status: "working",
533
+ configured: true,
534
+ responseTime: 200,
535
+ model: "gpt-4o-mini",
536
+ },
537
+ {
538
+ provider: "anthropic",
539
+ status: "working",
540
+ configured: true,
541
+ responseTime: 180,
542
+ model: "claude-3-haiku",
543
+ },
544
+ { provider: "bedrock", status: "not configured", configured: false },
545
+ { provider: "vertex", status: "not configured", configured: false },
546
+ ];
547
+ if (spinner) {
548
+ spinner.succeed("Provider check complete (dry-run): 3/3 providers working");
549
+ }
550
+ // Display mock results
551
+ for (const result of mockResults) {
552
+ const status = result.status === "working"
553
+ ? chalk.green("āœ… Working")
554
+ : result.status === "failed"
555
+ ? chalk.red("āŒ Failed")
556
+ : chalk.gray("⚪ Not configured");
557
+ const time = result.responseTime ? ` (${result.responseTime}ms)` : "";
558
+ const model = result.model ? ` [${result.model}]` : "";
559
+ logger.always(`${result.provider}: ${status}${time}${model}`);
560
+ }
561
+ if (argv.verbose && !argv.quiet) {
562
+ logger.always(chalk.blue("\nšŸ“‹ Detailed Results (Dry-run):"));
563
+ logger.always(JSON.stringify(mockResults, null, 2));
564
+ }
565
+ return;
566
+ }
497
567
  // Use SDK's provider diagnostic method instead of manual testing
498
568
  const sdk = new NeuroLink();
499
569
  const results = await sdk.getProviderStatus({ quiet: !!argv.quiet });
@@ -578,6 +648,55 @@ export class CLICommandFactory {
578
648
  });
579
649
  }
580
650
  }
651
+ // Handle dry-run mode for testing
652
+ if (options.dryRun) {
653
+ const mockResult = {
654
+ content: "Mock response for testing purposes",
655
+ provider: options.provider || "auto",
656
+ model: options.model || "test-model",
657
+ usage: {
658
+ inputTokens: 10,
659
+ outputTokens: 15,
660
+ totalTokens: 25,
661
+ },
662
+ responseTime: 150,
663
+ analytics: options.enableAnalytics
664
+ ? {
665
+ provider: options.provider || "auto",
666
+ model: options.model || "test-model",
667
+ tokens: { input: 10, output: 15, total: 25 },
668
+ cost: 0.00025,
669
+ responseTime: 150,
670
+ context: contextMetadata,
671
+ }
672
+ : undefined,
673
+ evaluation: options.enableEvaluation
674
+ ? {
675
+ relevance: 8,
676
+ accuracy: 9,
677
+ completeness: 8,
678
+ overall: 8.3,
679
+ isOffTopic: false,
680
+ alertSeverity: "none",
681
+ reasoning: "Test evaluation response",
682
+ evaluationModel: "test-evaluator",
683
+ evaluationTime: 50,
684
+ }
685
+ : undefined,
686
+ };
687
+ if (spinner) {
688
+ spinner.succeed(chalk.green("āœ… Dry-run completed successfully!"));
689
+ }
690
+ this.handleOutput(mockResult, options);
691
+ if (options.debug) {
692
+ logger.debug("\n" + chalk.yellow("Debug Information (Dry-run):"));
693
+ logger.debug("Provider:", mockResult.provider);
694
+ logger.debug("Model:", mockResult.model);
695
+ logger.debug("Mode: DRY-RUN (no actual API calls made)");
696
+ }
697
+ process.exit(0);
698
+ return;
699
+ }
581
700
  const sdk = new NeuroLink();
582
701
  const result = await sdk.generate({
583
702
  input: { text: inputText },
@@ -593,6 +712,13 @@ export class CLICommandFactory {
593
712
  evaluationDomain: options.evaluationDomain,
594
713
  toolUsageContext: options.toolUsageContext,
595
714
  context: contextMetadata,
715
+ factoryConfig: options.domain
716
+ ? {
717
+ domainType: options.domain,
718
+ enhancementType: "domain-configuration",
719
+ validateDomainData: true,
720
+ }
721
+ : undefined,
596
722
  });
597
723
  if (spinner) {
598
724
  spinner.succeed(chalk.green("āœ… Text generated successfully!"));
@@ -674,6 +800,76 @@ export class CLICommandFactory {
674
800
  });
675
801
  }
676
802
  }
803
+ // Handle dry-run mode for testing
804
+ if (options.dryRun) {
805
+ if (!options.quiet) {
806
+ logger.always(chalk.blue("šŸ”„ Dry-run streaming..."));
807
+ }
808
+ // Simulate streaming output
809
+ const chunks = [
810
+ "Mock ",
811
+ "streaming ",
812
+ "response ",
813
+ "for ",
814
+ "testing ",
815
+ "purposes",
816
+ ];
817
+ let fullContent = "";
818
+ for (const chunk of chunks) {
819
+ process.stdout.write(chunk);
820
+ fullContent += chunk;
821
+ await new Promise((resolve) => setTimeout(resolve, 50)); // Simulate streaming delay
822
+ }
823
+ if (!options.quiet) {
824
+ process.stdout.write("\n");
825
+ }
826
+ // Mock analytics and evaluation for dry-run
827
+ if (options.enableAnalytics) {
828
+ const mockAnalytics = {
829
+ provider: options.provider || "auto",
830
+ model: options.model || "test-model",
831
+ requestDuration: 300,
832
+ tokenUsage: {
833
+ inputTokens: 10,
834
+ outputTokens: 15,
835
+ totalTokens: 25,
836
+ },
837
+ timestamp: Date.now(),
838
+ context: contextMetadata,
839
+ };
840
+ const mockGenerateResult = {
841
+ success: true,
842
+ content: fullContent,
843
+ analytics: mockAnalytics,
844
+ model: mockAnalytics.model,
845
+ toolsUsed: [],
846
+ };
847
+ const analyticsDisplay = this.formatAnalyticsForTextMode(mockGenerateResult);
848
+ logger.always(analyticsDisplay);
849
+ }
850
+ if (options.enableEvaluation) {
851
+ logger.always(chalk.blue("\nšŸ“Š Response Evaluation (Dry-run):"));
852
+ logger.always(` Relevance: 8/10`);
853
+ logger.always(` Accuracy: 9/10`);
854
+ logger.always(` Completeness: 8/10`);
855
+ logger.always(` Overall: 8.3/10`);
856
+ logger.always(` Reasoning: Test evaluation response`);
857
+ }
858
+ if (options.output) {
859
+ fs.writeFileSync(options.output, fullContent);
860
+ if (!options.quiet) {
861
+ logger.always(`\nOutput saved to ${options.output}`);
862
+ }
863
+ }
864
+ if (options.debug) {
865
+ logger.debug("\n" + chalk.yellow("Debug Information (Dry-run Streaming):"));
866
+ logger.debug("Provider:", options.provider || "auto");
867
+ logger.debug("Model:", options.model || "test-model");
868
+ logger.debug("Mode: DRY-RUN (no actual API calls made)");
869
+ }
870
+ process.exit(0);
871
+ return;
872
+ }
677
873
  const sdk = new NeuroLink();
678
874
  const stream = await sdk.stream({
679
875
  input: { text: inputText },
@@ -687,6 +883,13 @@ export class CLICommandFactory {
687
883
  enableAnalytics: options.enableAnalytics,
688
884
  enableEvaluation: options.enableEvaluation,
689
885
  context: contextMetadata,
886
+ factoryConfig: options.domain
887
+ ? {
888
+ domainType: options.domain,
889
+ enhancementType: "domain-configuration",
890
+ validateDomainData: true,
891
+ }
892
+ : undefined,
690
893
  });
691
894
  let fullContent = "";
692
895
  // Process the stream
@@ -803,6 +1006,17 @@ export class CLICommandFactory {
803
1006
  spinner.text = `Processing ${i + 1}/${prompts.length}: ${prompts[i].substring(0, 30)}...`;
804
1007
  }
805
1008
  try {
1009
+ // Handle dry-run mode for batch processing
1010
+ if (options.dryRun) {
1011
+ results.push({
1012
+ prompt: prompts[i],
1013
+ response: `Mock batch response ${i + 1} for testing purposes`,
1014
+ });
1015
+ if (spinner) {
1016
+ spinner.render();
1017
+ }
1018
+ continue;
1019
+ }
806
1020
  // Process context for each batch item
807
1021
  let inputText = prompts[i];
808
1022
  let contextMetadata;
@@ -830,6 +1044,13 @@ export class CLICommandFactory {
830
1044
  enableAnalytics: options.enableAnalytics,
831
1045
  enableEvaluation: options.enableEvaluation,
832
1046
  context: contextMetadata,
1047
+ factoryConfig: options.domain
1048
+ ? {
1049
+ domainType: options.domain,
1050
+ enhancementType: "domain-configuration",
1051
+ validateDomainData: true,
1052
+ }
1053
+ : undefined,
833
1054
  });
834
1055
  results.push({ prompt: prompts[i], response: result.content });
835
1056
  if (spinner) {
@@ -927,8 +1148,140 @@ export class CLICommandFactory {
927
1148
  * Execute completion command
928
1149
  */
929
1150
  static async executeCompletion(argv) {
930
- // This would need to be implemented with the actual CLI instance
931
- logger.always("# Completion script would be generated here");
932
- logger.always("# This requires access to the yargs CLI instance");
1151
+ try {
1152
+ // Generate shell completion script as concatenated strings to avoid template literal issues
1153
+ const completionScript = "#!/usr/bin/env bash\n\n" +
1154
+ "# NeuroLink CLI Bash Completion Script\n" +
1155
+ "# Generated by: neurolink completion\n" +
1156
+ "# \n" +
1157
+ "# Installation instructions:\n" +
1158
+ "# 1. Save this script to a file (e.g., ~/.neurolink-completion.sh)\n" +
1159
+ "# 2. Add to your shell profile: source ~/.neurolink-completion.sh\n" +
1160
+ "# 3. Restart your shell or run: source ~/.bashrc\n\n" +
1161
+ "_neurolink_completion() {\n" +
1162
+ " local cur prev opts base\n" +
1163
+ " COMPREPLY=()\n" +
1164
+ ' cur="${COMP_WORDS[COMP_CWORD]}"\n' +
1165
+ ' prev="${COMP_WORDS[COMP_CWORD - 1]}"\n\n' +
1166
+ " # Main commands\n" +
1167
+ " if [[ ${COMP_CWORD} -eq 1 ]]; then\n" +
1168
+ ' opts="generate gen stream batch provider status models mcp discover config get-best-provider completion"\n' +
1169
+ ' COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n' +
1170
+ " return 0\n" +
1171
+ " fi\n\n" +
1172
+ " # Subcommand completion\n" +
1173
+ ' case "${COMP_WORDS[1]}" in\n' +
1174
+ " generate|gen)\n" +
1175
+ ' case "${prev}" in\n' +
1176
+ " --provider|-p)\n" +
1177
+ ' COMPREPLY=( $(compgen -W "auto openai bedrock vertex googleVertex anthropic azure google-ai huggingface ollama mistral litellm" -- ${cur}) )\n' +
1178
+ " return 0\n" +
1179
+ " ;;\n" +
1180
+ " --format|-f|--output-format)\n" +
1181
+ ' COMPREPLY=( $(compgen -W "text json table" -- ${cur}) )\n' +
1182
+ " return 0\n" +
1183
+ " ;;\n" +
1184
+ " --model|-m)\n" +
1185
+ ' COMPREPLY=( $(compgen -W "gemini-2.5-pro gemini-2.5-flash gpt-4o gpt-4o-mini claude-3-5-sonnet" -- ${cur}) )\n' +
1186
+ " return 0\n" +
1187
+ " ;;\n" +
1188
+ " *)\n" +
1189
+ ' opts="--provider --model --temperature --maxTokens --system --format --output --timeout --delay --disableTools --enableAnalytics --enableEvaluation --debug --quiet --noColor --configFile --dryRun"\n' +
1190
+ ' COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n' +
1191
+ " return 0\n" +
1192
+ " ;;\n" +
1193
+ " esac\n" +
1194
+ " ;;\n" +
1195
+ " mcp)\n" +
1196
+ ' case "${COMP_WORDS[2]}" in\n' +
1197
+ " install)\n" +
1198
+ " if [[ ${COMP_CWORD} -eq 3 ]]; then\n" +
1199
+ ' COMPREPLY=( $(compgen -W "filesystem github postgres sqlite brave puppeteer git memory bitbucket" -- ${cur}) )\n' +
1200
+ " return 0\n" +
1201
+ " fi\n" +
1202
+ " ;;\n" +
1203
+ " *)\n" +
1204
+ " if [[ ${COMP_CWORD} -eq 2 ]]; then\n" +
1205
+ ' opts="list install add test exec remove"\n' +
1206
+ ' COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n' +
1207
+ " return 0\n" +
1208
+ " fi\n" +
1209
+ " ;;\n" +
1210
+ " esac\n" +
1211
+ " ;;\n" +
1212
+ " provider)\n" +
1213
+ " if [[ ${COMP_CWORD} -eq 2 ]]; then\n" +
1214
+ ' COMPREPLY=( $(compgen -W "status" -- ${cur}) )\n' +
1215
+ " return 0\n" +
1216
+ " fi\n" +
1217
+ " ;;\n" +
1218
+ " models)\n" +
1219
+ " if [[ ${COMP_CWORD} -eq 2 ]]; then\n" +
1220
+ ' COMPREPLY=( $(compgen -W "list test" -- ${cur}) )\n' +
1221
+ " return 0\n" +
1222
+ " fi\n" +
1223
+ " ;;\n" +
1224
+ " config)\n" +
1225
+ " if [[ ${COMP_CWORD} -eq 2 ]]; then\n" +
1226
+ ' COMPREPLY=( $(compgen -W "init show validate reset export" -- ${cur}) )\n' +
1227
+ " return 0\n" +
1228
+ " fi\n" +
1229
+ " ;;\n" +
1230
+ " *)\n" +
1231
+ " # Global options for all commands\n" +
1232
+ ' opts="--help --version --debug --quiet --noColor --configFile"\n' +
1233
+ ' COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n' +
1234
+ " return 0\n" +
1235
+ " ;;\n" +
1236
+ " esac\n\n" +
1237
+ " # File completion for certain options\n" +
1238
+ ' case "${prev}" in\n' +
1239
+ " --output|-o|--configFile)\n" +
1240
+ " COMPREPLY=( $(compgen -f -- ${cur}) )\n" +
1241
+ " return 0\n" +
1242
+ " ;;\n" +
1243
+ " batch)\n" +
1244
+ " COMPREPLY=( $(compgen -f -- ${cur}) )\n" +
1245
+ " return 0\n" +
1246
+ " ;;\n" +
1247
+ " esac\n\n" +
1248
+ " return 0\n" +
1249
+ "}\n\n" +
1250
+ "# Register the completion function\n" +
1251
+ "complete -F _neurolink_completion neurolink\n\n" +
1252
+ "# Zsh completion (if running zsh)\n" +
1253
+ 'if [[ -n "${ZSH_VERSION}" ]]; then\n' +
1254
+ " autoload -U +X bashcompinit && bashcompinit\n" +
1255
+ " complete -F _neurolink_completion neurolink\n" +
1256
+ "fi\n\n" +
1257
+ 'echo "NeuroLink CLI completion script loaded successfully!"\n' +
1258
+ 'echo "Available commands: generate, stream, batch, provider, status, models, mcp, discover, config, get-best-provider, completion"';
1259
+ // Handle output options
1260
+ if (argv.output) {
1261
+ const fs = await import("fs");
1262
+ fs.writeFileSync(argv.output, completionScript);
1263
+ if (!argv.quiet) {
1264
+ logger.always(`āœ… Completion script saved to ${argv.output}`);
1265
+ logger.always(`šŸ’” Run: source ${argv.output}`);
1266
+ }
1267
+ }
1268
+ else {
1269
+ logger.always(completionScript);
1270
+ }
1271
+ if (!argv.quiet) {
1272
+ logger.always(chalk.blue("\nšŸ“‹ Installation Instructions:"));
1273
+ logger.always("1. Save the output to a file:");
1274
+ logger.always(" neurolink completion > ~/.neurolink-completion.sh");
1275
+ logger.always("2. Add to your shell profile:");
1276
+ logger.always(" echo 'source ~/.neurolink-completion.sh' >> ~/.bashrc");
1277
+ logger.always("3. Restart your shell or run:");
1278
+ logger.always(" source ~/.bashrc");
1279
+ logger.always(chalk.green("\nšŸŽ‰ Then enjoy tab completion for NeuroLink commands!"));
1280
+ }
1281
+ }
1282
+ catch (error) {
1283
+ logger.error(chalk.red(`āŒ Completion generation failed: ${error.message}`));
1284
+ process.exit(1);
1285
+ }
933
1286
  }
934
1287
  }
@@ -5,6 +5,7 @@
5
5
  * including tokens, costs, performance metrics, and custom context.
6
6
  */
7
7
  import { logger } from "../utils/logger.js";
8
+ import { modelConfig } from "./modelConfiguration.js";
8
9
  /**
9
10
  * Create analytics data structure from AI response
10
11
  */
@@ -89,35 +90,14 @@ function extractTokenUsage(result) {
89
90
  */
90
91
  function estimateCost(provider, model, tokens) {
91
92
  try {
92
- // Cost per 1K tokens (USD) - approximate rates as of 2024
93
- const costMap = {
94
- openai: {
95
- "gpt-4": { input: 0.03, output: 0.06 },
96
- "gpt-4-turbo": { input: 0.01, output: 0.03 },
97
- "gpt-3.5-turbo": { input: 0.0015, output: 0.002 },
98
- },
99
- anthropic: {
100
- "claude-3-opus": { input: 0.015, output: 0.075 },
101
- "claude-3-sonnet": { input: 0.003, output: 0.015 },
102
- "claude-3-haiku": { input: 0.00025, output: 0.00125 },
103
- },
104
- "google-ai": {
105
- "gemini-pro": { input: 0.00035, output: 0.00105 },
106
- "gemini-2.5-flash": { input: 0.000075, output: 0.0003 },
107
- },
108
- };
109
- const providerCosts = costMap[provider.toLowerCase()];
110
- if (!providerCosts) {
111
- return undefined;
112
- }
113
- // Find best matching model
114
- const modelKey = Object.keys(providerCosts).find((key) => model.toLowerCase().includes(key) || key.includes(model.toLowerCase()));
115
- if (!modelKey) {
93
+ // Use the new configuration system instead of hardcoded costs
94
+ const costInfo = modelConfig.getCostInfo(provider.toLowerCase(), model);
95
+ if (!costInfo) {
116
96
  return undefined;
117
97
  }
118
- const rates = providerCosts[modelKey];
119
- const inputCost = (tokens.input / 1000) * rates.input;
120
- const outputCost = (tokens.output / 1000) * rates.output;
98
+ // Calculate cost using the configuration system
99
+ const inputCost = (tokens.input / 1000) * costInfo.input;
100
+ const outputCost = (tokens.output / 1000) * costInfo.output;
121
101
  return Math.round((inputCost + outputCost) * 100000) / 100000; // Round to 5 decimal places
122
102
  }
123
103
  catch (error) {