@juspay/neurolink 7.33.4 → 7.35.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.
Files changed (115) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +101 -7
  3. package/dist/cli/commands/setup-anthropic.d.ts +16 -0
  4. package/dist/cli/commands/setup-anthropic.js +414 -0
  5. package/dist/cli/commands/setup-azure.d.ts +17 -0
  6. package/dist/cli/commands/setup-azure.js +415 -0
  7. package/dist/cli/commands/setup-bedrock.d.ts +13 -0
  8. package/dist/cli/commands/setup-bedrock.js +487 -0
  9. package/dist/cli/commands/setup-gcp.d.ts +18 -0
  10. package/dist/cli/commands/setup-gcp.js +569 -0
  11. package/dist/cli/commands/setup-google-ai.d.ts +16 -0
  12. package/dist/cli/commands/setup-google-ai.js +369 -0
  13. package/dist/cli/commands/setup-huggingface.d.ts +8 -0
  14. package/dist/cli/commands/setup-huggingface.js +200 -0
  15. package/dist/cli/commands/setup-mistral.d.ts +8 -0
  16. package/dist/cli/commands/setup-mistral.js +233 -0
  17. package/dist/cli/commands/setup-openai.d.ts +16 -0
  18. package/dist/cli/commands/setup-openai.js +402 -0
  19. package/dist/cli/commands/setup.d.ts +19 -0
  20. package/dist/cli/commands/setup.js +539 -0
  21. package/dist/cli/errorHandler.d.ts +1 -0
  22. package/dist/cli/errorHandler.js +28 -0
  23. package/dist/cli/factories/commandFactory.d.ts +27 -0
  24. package/dist/cli/factories/commandFactory.js +416 -60
  25. package/dist/cli/factories/ollamaCommandFactory.js +7 -1
  26. package/dist/cli/factories/setupCommandFactory.d.ts +18 -0
  27. package/dist/cli/factories/setupCommandFactory.js +137 -0
  28. package/dist/cli/index.d.ts +1 -1
  29. package/dist/cli/index.js +9 -164
  30. package/dist/cli/loop/optionsSchema.d.ts +15 -0
  31. package/dist/cli/loop/optionsSchema.js +59 -0
  32. package/dist/cli/loop/session.d.ts +15 -0
  33. package/dist/cli/loop/session.js +252 -0
  34. package/dist/cli/parser.d.ts +1 -0
  35. package/dist/cli/parser.js +161 -0
  36. package/dist/cli/utils/envManager.d.ts +3 -2
  37. package/dist/cli/utils/envManager.js +18 -4
  38. package/dist/cli/utils/ollamaUtils.js +6 -0
  39. package/dist/config/{conversationMemoryConfig.d.ts → conversationMemory.d.ts} +1 -1
  40. package/dist/core/baseProvider.js +17 -3
  41. package/dist/core/conversationMemoryFactory.d.ts +23 -0
  42. package/dist/core/conversationMemoryFactory.js +144 -0
  43. package/dist/core/conversationMemoryInitializer.d.ts +14 -0
  44. package/dist/core/conversationMemoryInitializer.js +127 -0
  45. package/dist/core/conversationMemoryManager.d.ts +3 -2
  46. package/dist/core/conversationMemoryManager.js +4 -3
  47. package/dist/core/redisConversationMemoryManager.d.ts +73 -0
  48. package/dist/core/redisConversationMemoryManager.js +483 -0
  49. package/dist/core/types.d.ts +1 -1
  50. package/dist/lib/config/{conversationMemoryConfig.d.ts → conversationMemory.d.ts} +1 -1
  51. package/dist/lib/core/baseProvider.js +17 -3
  52. package/dist/lib/core/conversationMemoryFactory.d.ts +23 -0
  53. package/dist/lib/core/conversationMemoryFactory.js +144 -0
  54. package/dist/lib/core/conversationMemoryInitializer.d.ts +14 -0
  55. package/dist/lib/core/conversationMemoryInitializer.js +127 -0
  56. package/dist/lib/core/conversationMemoryManager.d.ts +3 -2
  57. package/dist/lib/core/conversationMemoryManager.js +4 -3
  58. package/dist/lib/core/redisConversationMemoryManager.d.ts +73 -0
  59. package/dist/lib/core/redisConversationMemoryManager.js +483 -0
  60. package/dist/lib/core/types.d.ts +1 -1
  61. package/dist/lib/neurolink.d.ts +15 -9
  62. package/dist/lib/neurolink.js +218 -67
  63. package/dist/lib/providers/amazonBedrock.d.ts +4 -4
  64. package/dist/lib/providers/anthropic.d.ts +4 -4
  65. package/dist/lib/providers/azureOpenai.d.ts +4 -4
  66. package/dist/lib/providers/googleAiStudio.d.ts +4 -4
  67. package/dist/lib/providers/googleAiStudio.js +1 -1
  68. package/dist/lib/providers/huggingFace.d.ts +4 -4
  69. package/dist/lib/providers/litellm.d.ts +1 -1
  70. package/dist/lib/providers/mistral.d.ts +4 -4
  71. package/dist/lib/providers/mistral.js +2 -2
  72. package/dist/lib/providers/openAI.d.ts +4 -4
  73. package/dist/lib/session/globalSessionState.d.ts +27 -0
  74. package/dist/lib/session/globalSessionState.js +77 -0
  75. package/dist/lib/types/{conversationTypes.d.ts → conversation.d.ts} +32 -0
  76. package/dist/lib/types/generateTypes.d.ts +1 -1
  77. package/dist/lib/types/streamTypes.d.ts +1 -1
  78. package/dist/lib/utils/conversationMemory.d.ts +22 -0
  79. package/dist/lib/utils/conversationMemory.js +121 -0
  80. package/dist/lib/utils/conversationMemoryUtils.d.ts +1 -1
  81. package/dist/lib/utils/conversationMemoryUtils.js +2 -2
  82. package/dist/lib/utils/messageBuilder.d.ts +1 -1
  83. package/dist/lib/utils/messageBuilder.js +1 -1
  84. package/dist/lib/utils/redis.d.ts +42 -0
  85. package/dist/lib/utils/redis.js +263 -0
  86. package/dist/neurolink.d.ts +15 -9
  87. package/dist/neurolink.js +218 -67
  88. package/dist/providers/amazonBedrock.d.ts +4 -4
  89. package/dist/providers/anthropic.d.ts +4 -4
  90. package/dist/providers/azureOpenai.d.ts +4 -4
  91. package/dist/providers/googleAiStudio.d.ts +4 -4
  92. package/dist/providers/googleAiStudio.js +1 -1
  93. package/dist/providers/huggingFace.d.ts +4 -4
  94. package/dist/providers/litellm.d.ts +1 -1
  95. package/dist/providers/mistral.d.ts +4 -4
  96. package/dist/providers/mistral.js +2 -2
  97. package/dist/providers/openAI.d.ts +4 -4
  98. package/dist/session/globalSessionState.d.ts +27 -0
  99. package/dist/session/globalSessionState.js +77 -0
  100. package/dist/types/{conversationTypes.d.ts → conversation.d.ts} +32 -0
  101. package/dist/types/generateTypes.d.ts +1 -1
  102. package/dist/types/streamTypes.d.ts +1 -1
  103. package/dist/utils/conversationMemory.d.ts +22 -0
  104. package/dist/utils/conversationMemory.js +121 -0
  105. package/dist/utils/conversationMemoryUtils.d.ts +1 -1
  106. package/dist/utils/conversationMemoryUtils.js +2 -2
  107. package/dist/utils/messageBuilder.d.ts +1 -1
  108. package/dist/utils/messageBuilder.js +1 -1
  109. package/dist/utils/redis.d.ts +42 -0
  110. package/dist/utils/redis.js +263 -0
  111. package/package.json +3 -1
  112. /package/dist/config/{conversationMemoryConfig.js → conversationMemory.js} +0 -0
  113. /package/dist/lib/config/{conversationMemoryConfig.js → conversationMemory.js} +0 -0
  114. /package/dist/lib/types/{conversationTypes.js → conversation.js} +0 -0
  115. /package/dist/types/{conversationTypes.js → conversation.js} +0 -0
@@ -1,7 +1,9 @@
1
- import { NeuroLink } from "../../lib/neurolink.js";
1
+ import { globalSession } from "../../lib/session/globalSessionState.js";
2
2
  import { configManager } from "../commands/config.js";
3
- import { handleError } from "../index.js";
3
+ import { handleError } from "../errorHandler.js";
4
4
  import { normalizeEvaluationData } from "../../lib/utils/evaluationUtils.js";
5
+ import { LoopSession } from "../loop/session.js";
6
+ import { initializeCliParser } from "../parser.js";
5
7
  // Use TokenUsage from standard types - no local interface needed
6
8
  import { ContextFactory, } from "../../lib/types/contextTypes.js";
7
9
  import { ModelsCommandFactory } from "../commands/models.js";
@@ -12,6 +14,7 @@ import ora from "ora";
12
14
  import chalk from "chalk";
13
15
  import { logger } from "../../lib/utils/logger.js";
14
16
  import fs from "fs";
17
+ import { handleSetup } from "../commands/setup.js";
15
18
  // Use specific command interfaces from cli.ts instead of universal interface
16
19
  /**
17
20
  * CLI Command Factory for generate commands
@@ -189,8 +192,7 @@ export class CLICommandFactory {
189
192
  const truncatedJson = contextStr.length > 100
190
193
  ? `${contextStr.slice(0, 100)}...`
191
194
  : contextStr;
192
- logger.error(`Invalid JSON in --context parameter: ${err.message}. Received: ${truncatedJson}`);
193
- process.exit(1);
195
+ handleError(new Error(`Invalid JSON in --context parameter: ${err.message}. Received: ${truncatedJson}`), "Context parsing");
194
196
  }
195
197
  }
196
198
  else {
@@ -494,6 +496,39 @@ export class CLICommandFactory {
494
496
  static createDiscoverCommand() {
495
497
  return MCPCommandFactory.createDiscoverCommand();
496
498
  }
499
+ /**
500
+ * Create memory commands
501
+ */
502
+ static createMemoryCommands() {
503
+ return {
504
+ command: "memory <subcommand>",
505
+ describe: "Manage conversation memory",
506
+ builder: (yargs) => {
507
+ return yargs
508
+ .command("stats", "Show conversation memory statistics", (y) => this.buildOptions(y)
509
+ .example("$0 memory stats", "Show memory usage statistics")
510
+ .example("$0 memory stats --format json", "Export stats as JSON"), async (argv) => await this.executeMemoryStats(argv))
511
+ .command("history <sessionId>", "Show conversation history for a session", (y) => this.buildOptions(y)
512
+ .positional("sessionId", {
513
+ type: "string",
514
+ description: "Session ID to retrieve history for",
515
+ demandOption: true,
516
+ })
517
+ .example("$0 memory history session-123", "Show conversation history")
518
+ .example("$0 memory history session-123 --format json", "Export history as JSON"), async (argv) => await this.executeMemoryHistory(argv))
519
+ .command("clear [sessionId]", "Clear conversation history", (y) => this.buildOptions(y)
520
+ .positional("sessionId", {
521
+ type: "string",
522
+ description: "Session ID to clear (omit to clear all sessions)",
523
+ demandOption: false,
524
+ })
525
+ .example("$0 memory clear", "Clear all conversation history")
526
+ .example("$0 memory clear session-123", "Clear specific session"), async (argv) => await this.executeMemoryClear(argv))
527
+ .demandCommand(1, "Please specify a memory subcommand");
528
+ },
529
+ handler: () => { }, // No-op handler as subcommands handle everything
530
+ };
531
+ }
497
532
  /**
498
533
  * Create config commands
499
534
  */
@@ -515,9 +550,8 @@ export class CLICommandFactory {
515
550
  logger.always(chalk.green("✅ Configuration is valid"));
516
551
  }
517
552
  else {
518
- logger.always(chalk.red(" Configuration has errors:"));
519
- result.errors.forEach((error) => logger.always(` • ${error}`));
520
- process.exit(1);
553
+ const errorMessages = result.errors.join("\n • ");
554
+ handleError(new Error(`Configuration has errors:\n • ${errorMessages}`), "Configuration validation");
521
555
  }
522
556
  })
523
557
  .command("reset", "Reset configuration to defaults", (y) => this.buildOptions(y), async (_argv) => {
@@ -543,9 +577,8 @@ export class CLICommandFactory {
543
577
  logger.always(chalk.green("✅ Configuration is valid"));
544
578
  }
545
579
  else {
546
- logger.always(chalk.red(" Configuration has errors:"));
547
- result.errors.forEach((error) => logger.always(` • ${error}`));
548
- throw new Error("Configuration is invalid. See errors above.");
580
+ const errorMessages = result.errors.join("\n • ");
581
+ handleError(new Error(`Configuration has errors:\n • ${errorMessages}`), "Configuration validation");
549
582
  }
550
583
  },
551
584
  };
@@ -570,12 +603,99 @@ export class CLICommandFactory {
570
603
  static createOllamaCommands() {
571
604
  return OllamaCommandFactory.createOllamaCommands();
572
605
  }
606
+ /**
607
+ * Create setup command
608
+ */
609
+ static createSetupCommand() {
610
+ return {
611
+ command: ["setup [provider]", "s [provider]"],
612
+ describe: "Interactive AI provider setup wizard",
613
+ builder: (yargs) => {
614
+ return this.buildOptions(yargs
615
+ .positional("provider", {
616
+ type: "string",
617
+ description: "Specific provider to set up",
618
+ choices: [
619
+ "google-ai",
620
+ "openai",
621
+ "anthropic",
622
+ "azure",
623
+ "bedrock",
624
+ "vertex",
625
+ "huggingface",
626
+ "mistral",
627
+ ],
628
+ })
629
+ .option("list", {
630
+ type: "boolean",
631
+ description: "List all available providers",
632
+ alias: "l",
633
+ })
634
+ .option("status", {
635
+ type: "boolean",
636
+ description: "Show provider configuration status",
637
+ })
638
+ .example("$0 setup", "Interactive setup wizard")
639
+ .example("$0 setup --provider openai", "Setup specific provider")
640
+ .example("$0 setup --list", "List all providers")
641
+ .example("$0 setup --status", "Check provider status"));
642
+ },
643
+ handler: async (argv) => await handleSetup(argv),
644
+ };
645
+ }
573
646
  /**
574
647
  * Create SageMaker commands
575
648
  */
576
649
  static createSageMakerCommands() {
577
650
  return SageMakerCommandFactory.createSageMakerCommands();
578
651
  }
652
+ /**
653
+ * Create completion command
654
+ */
655
+ /**
656
+ * Create loop command
657
+ */
658
+ static createLoopCommand() {
659
+ return {
660
+ command: "loop",
661
+ describe: "Start an interactive loop session",
662
+ builder: (yargs) => yargs
663
+ .option("enable-conversation-memory", {
664
+ type: "boolean",
665
+ description: "Enable conversation memory for the loop session",
666
+ default: false,
667
+ })
668
+ .option("max-sessions", {
669
+ type: "number",
670
+ description: "Maximum number of conversation sessions to keep",
671
+ default: 50,
672
+ })
673
+ .option("max-turns-per-session", {
674
+ type: "number",
675
+ description: "Maximum turns per conversation session",
676
+ default: 20,
677
+ })
678
+ .example("$0 loop", "Start interactive session")
679
+ .example("$0 loop --enable-conversation-memory", "Start loop with memory"),
680
+ handler: async (argv) => {
681
+ if (globalSession.getCurrentSessionId()) {
682
+ logger.error("A loop session is already active. Cannot start a new one.");
683
+ return;
684
+ }
685
+ let conversationMemoryConfig;
686
+ const { enableConversationMemory, maxSessions, maxTurnsPerSession } = argv;
687
+ if (enableConversationMemory) {
688
+ conversationMemoryConfig = {
689
+ enabled: true,
690
+ maxSessions: maxSessions,
691
+ maxTurnsPerSession: maxTurnsPerSession,
692
+ };
693
+ }
694
+ const session = new LoopSession(initializeCliParser, conversationMemoryConfig);
695
+ await session.start();
696
+ },
697
+ };
698
+ }
579
699
  /**
580
700
  * Create completion command
581
701
  */
@@ -601,6 +721,7 @@ export class CLICommandFactory {
601
721
  const spinner = argv.quiet
602
722
  ? null
603
723
  : ora("🔍 Checking AI provider status...\n").start();
724
+ const sdk = globalSession.getOrCreateNeuroLink();
604
725
  try {
605
726
  // Handle dry-run mode for provider status
606
727
  if (argv.dryRun) {
@@ -652,7 +773,6 @@ export class CLICommandFactory {
652
773
  return;
653
774
  }
654
775
  // Use SDK's provider diagnostic method instead of manual testing
655
- const sdk = new NeuroLink();
656
776
  const results = await sdk.getProviderStatus({ quiet: !!argv.quiet });
657
777
  if (spinner) {
658
778
  const working = results.filter((r) => r.status === "working").length;
@@ -682,8 +802,19 @@ export class CLICommandFactory {
682
802
  if (spinner) {
683
803
  spinner.fail("Provider status check failed");
684
804
  }
685
- logger.error(chalk.red("Error checking provider status:"), error);
686
- process.exit(1);
805
+ handleError(error, "Provider status check");
806
+ }
807
+ finally {
808
+ // Ensure all background processes are terminated
809
+ try {
810
+ await sdk.shutdownExternalMCPServers();
811
+ }
812
+ catch (shutdownError) {
813
+ logger.error("Error during SDK shutdown:", shutdownError);
814
+ }
815
+ if (!globalSession.getCurrentSessionId()) {
816
+ process.exit();
817
+ }
687
818
  }
688
819
  }
689
820
  /**
@@ -779,9 +910,17 @@ export class CLICommandFactory {
779
910
  logger.debug("Model:", mockResult.model);
780
911
  logger.debug("Mode: DRY-RUN (no actual API calls made)");
781
912
  }
782
- process.exit(0);
913
+ if (!globalSession.getCurrentSessionId()) {
914
+ process.exit(0);
915
+ }
783
916
  }
784
- const sdk = new NeuroLink();
917
+ const sdk = globalSession.getOrCreateNeuroLink();
918
+ const sessionVariables = globalSession.getSessionVariables();
919
+ const enhancedOptions = { ...options, ...sessionVariables };
920
+ const sessionId = globalSession.getCurrentSessionId();
921
+ const context = sessionId
922
+ ? { ...options.context, sessionId }
923
+ : options.context;
785
924
  if (options.debug) {
786
925
  logger.debug("CLI Tools configuration:", {
787
926
  disableTools: options.disableTools,
@@ -790,21 +929,21 @@ export class CLICommandFactory {
790
929
  }
791
930
  const result = await sdk.generate({
792
931
  input: { text: inputText },
793
- provider: options.provider,
794
- model: options.model,
795
- temperature: options.temperature,
796
- maxTokens: options.maxTokens,
797
- systemPrompt: options.systemPrompt,
798
- timeout: options.timeout,
799
- disableTools: options.disableTools,
800
- enableAnalytics: options.enableAnalytics,
801
- enableEvaluation: options.enableEvaluation,
802
- evaluationDomain: options.evaluationDomain,
803
- toolUsageContext: options.toolUsageContext,
804
- context: contextMetadata,
805
- factoryConfig: options.domain
932
+ provider: enhancedOptions.provider,
933
+ model: enhancedOptions.model,
934
+ temperature: enhancedOptions.temperature,
935
+ maxTokens: enhancedOptions.maxTokens,
936
+ systemPrompt: enhancedOptions.systemPrompt,
937
+ timeout: enhancedOptions.timeout,
938
+ disableTools: enhancedOptions.disableTools,
939
+ enableAnalytics: enhancedOptions.enableAnalytics,
940
+ enableEvaluation: enhancedOptions.enableEvaluation,
941
+ evaluationDomain: enhancedOptions.evaluationDomain,
942
+ toolUsageContext: enhancedOptions.toolUsageContext,
943
+ context: context,
944
+ factoryConfig: enhancedOptions.domain
806
945
  ? {
807
- domainType: options.domain,
946
+ domainType: enhancedOptions.domain,
808
947
  enhancementType: "domain-configuration",
809
948
  validateDomainData: true,
810
949
  }
@@ -813,6 +952,12 @@ export class CLICommandFactory {
813
952
  if (spinner) {
814
953
  spinner.succeed(chalk.green("✅ Text generated successfully!"));
815
954
  }
955
+ // Display provider and model info by default (unless quiet mode)
956
+ if (!options.quiet) {
957
+ const providerInfo = result.provider || "auto";
958
+ const modelInfo = result.model || "default";
959
+ logger.always(chalk.gray(`🔧 Provider: ${providerInfo} | Model: ${modelInfo}`));
960
+ }
816
961
  // Handle output with universal formatting
817
962
  this.handleOutput(result, options);
818
963
  if (options.debug) {
@@ -826,7 +971,9 @@ export class CLICommandFactory {
826
971
  logger.debug("Evaluation:", JSON.stringify(result.evaluation, null, 2));
827
972
  }
828
973
  }
829
- process.exit(0);
974
+ if (!globalSession.getCurrentSessionId()) {
975
+ process.exit(0);
976
+ }
830
977
  }
831
978
  catch (error) {
832
979
  if (spinner) {
@@ -981,24 +1128,34 @@ export class CLICommandFactory {
981
1128
  logger.debug("Model:", options.model || "test-model");
982
1129
  logger.debug("Mode: DRY-RUN (no actual API calls made)");
983
1130
  }
984
- process.exit(0);
1131
+ if (!globalSession.getCurrentSessionId()) {
1132
+ process.exit(0);
1133
+ }
985
1134
  }
986
- const sdk = new NeuroLink();
1135
+ const sdk = globalSession.getOrCreateNeuroLink();
1136
+ const sessionVariables = globalSession.getSessionVariables();
1137
+ const enhancedOptions = { ...options, ...sessionVariables };
1138
+ const sessionId = globalSession.getCurrentSessionId();
1139
+ const context = sessionId
1140
+ ? { ...contextMetadata, sessionId }
1141
+ : contextMetadata;
987
1142
  const stream = await sdk.stream({
988
1143
  input: { text: inputText },
989
- provider: options.provider,
990
- model: options.model,
991
- temperature: options.temperature,
992
- maxTokens: options.maxTokens,
993
- systemPrompt: options.systemPrompt,
994
- timeout: options.timeout,
995
- disableTools: options.disableTools,
996
- enableAnalytics: options.enableAnalytics,
997
- enableEvaluation: options.enableEvaluation,
998
- context: contextMetadata,
999
- factoryConfig: options.domain
1144
+ provider: enhancedOptions.provider,
1145
+ model: enhancedOptions.model,
1146
+ temperature: enhancedOptions.temperature,
1147
+ maxTokens: enhancedOptions.maxTokens,
1148
+ systemPrompt: enhancedOptions.systemPrompt,
1149
+ timeout: enhancedOptions.timeout,
1150
+ disableTools: enhancedOptions.disableTools,
1151
+ enableAnalytics: enhancedOptions.enableAnalytics,
1152
+ enableEvaluation: enhancedOptions.enableEvaluation,
1153
+ evaluationDomain: enhancedOptions.evaluationDomain,
1154
+ toolUsageContext: enhancedOptions.toolUsageContext,
1155
+ context: context,
1156
+ factoryConfig: enhancedOptions.domain
1000
1157
  ? {
1001
- domainType: options.domain,
1158
+ domainType: enhancedOptions.domain,
1002
1159
  enhancementType: "domain-configuration",
1003
1160
  validateDomainData: true,
1004
1161
  }
@@ -1123,7 +1280,9 @@ export class CLICommandFactory {
1123
1280
  if (options.debug) {
1124
1281
  await this.logStreamDebugInfo(stream);
1125
1282
  }
1126
- process.exit(0);
1283
+ if (!globalSession.getCurrentSessionId()) {
1284
+ process.exit(0);
1285
+ }
1127
1286
  }
1128
1287
  catch (error) {
1129
1288
  handleError(error, "Streaming");
@@ -1158,7 +1317,10 @@ export class CLICommandFactory {
1158
1317
  logger.always(chalk.blue(`📦 Processing ${prompts.length} prompts...\n`));
1159
1318
  }
1160
1319
  const results = [];
1161
- const sdk = new NeuroLink();
1320
+ const sdk = globalSession.getOrCreateNeuroLink();
1321
+ const sessionVariables = globalSession.getSessionVariables();
1322
+ const enhancedOptions = { ...options, ...sessionVariables };
1323
+ const sessionId = globalSession.getCurrentSessionId();
1162
1324
  for (let i = 0; i < prompts.length; i++) {
1163
1325
  if (spinner) {
1164
1326
  spinner.text = `Processing ${i + 1}/${prompts.length}: ${prompts[i].substring(0, 30)}...`;
@@ -1190,21 +1352,24 @@ export class CLICommandFactory {
1190
1352
  batchIndex: i,
1191
1353
  };
1192
1354
  }
1355
+ const context = sessionId
1356
+ ? { ...contextMetadata, sessionId }
1357
+ : contextMetadata;
1193
1358
  const result = await sdk.generate({
1194
1359
  input: { text: inputText },
1195
- provider: options.provider,
1196
- model: options.model,
1197
- temperature: options.temperature,
1198
- maxTokens: options.maxTokens,
1199
- systemPrompt: options.systemPrompt,
1200
- timeout: options.timeout,
1201
- disableTools: options.disableTools,
1202
- enableAnalytics: options.enableAnalytics,
1203
- enableEvaluation: options.enableEvaluation,
1204
- context: contextMetadata,
1205
- factoryConfig: options.domain
1360
+ provider: enhancedOptions.provider,
1361
+ model: enhancedOptions.model,
1362
+ temperature: enhancedOptions.temperature,
1363
+ maxTokens: enhancedOptions.maxTokens,
1364
+ systemPrompt: enhancedOptions.systemPrompt,
1365
+ timeout: enhancedOptions.timeout,
1366
+ disableTools: enhancedOptions.disableTools,
1367
+ evaluationDomain: enhancedOptions.evaluationDomain,
1368
+ toolUsageContext: enhancedOptions.toolUsageContext,
1369
+ context: context,
1370
+ factoryConfig: enhancedOptions.domain
1206
1371
  ? {
1207
- domainType: options.domain,
1372
+ domainType: enhancedOptions.domain,
1208
1373
  enhancementType: "domain-configuration",
1209
1374
  validateDomainData: true,
1210
1375
  }
@@ -1234,7 +1399,9 @@ export class CLICommandFactory {
1234
1399
  }
1235
1400
  // Handle output with universal formatting
1236
1401
  this.handleOutput(results, options);
1237
- process.exit(0);
1402
+ if (!globalSession.getCurrentSessionId()) {
1403
+ process.exit(0);
1404
+ }
1238
1405
  }
1239
1406
  catch (error) {
1240
1407
  if (spinner) {
@@ -1296,6 +1463,189 @@ export class CLICommandFactory {
1296
1463
  handleError(error, "Provider selection");
1297
1464
  }
1298
1465
  }
1466
+ /**
1467
+ * Execute memory stats command
1468
+ */
1469
+ static async executeMemoryStats(argv) {
1470
+ const options = this.processOptions(argv);
1471
+ const spinner = options.quiet
1472
+ ? null
1473
+ : ora("🧠 Getting memory stats...").start();
1474
+ try {
1475
+ const sdk = globalSession.getOrCreateNeuroLink();
1476
+ // Handle dry-run mode
1477
+ if (options.dryRun) {
1478
+ const mockStats = {
1479
+ totalSessions: 5,
1480
+ totalTurns: 47,
1481
+ memoryUsage: "Active",
1482
+ };
1483
+ if (spinner) {
1484
+ spinner.succeed(chalk.green("✅ Memory stats retrieved (dry-run)"));
1485
+ }
1486
+ this.handleOutput(mockStats, options);
1487
+ return;
1488
+ }
1489
+ const stats = await sdk.getConversationStats();
1490
+ if (spinner) {
1491
+ spinner.succeed(chalk.green("✅ Memory stats retrieved"));
1492
+ }
1493
+ if (options.format === "json") {
1494
+ this.handleOutput(stats, options);
1495
+ }
1496
+ else {
1497
+ logger.always(chalk.blue("📊 Conversation Memory Stats:"));
1498
+ logger.always(` Total Sessions: ${stats.totalSessions}`);
1499
+ logger.always(` Total Turns: ${stats.totalTurns}`);
1500
+ logger.always(` Memory Status: ${stats.totalSessions > 0 ? "Active" : "Empty"}`);
1501
+ }
1502
+ }
1503
+ catch (error) {
1504
+ if (spinner) {
1505
+ spinner.fail("Memory stats failed");
1506
+ }
1507
+ if (error.message.includes("not enabled")) {
1508
+ logger.always(chalk.yellow("⚠️ Conversation memory is not enabled"));
1509
+ logger.always("Enable it by using --enable-conversation-memory with loop mode");
1510
+ }
1511
+ else {
1512
+ handleError(error, "Memory stats");
1513
+ }
1514
+ }
1515
+ }
1516
+ /**
1517
+ * Execute memory history command
1518
+ */
1519
+ static async executeMemoryHistory(argv) {
1520
+ const options = this.processOptions(argv);
1521
+ const spinner = options.quiet
1522
+ ? null
1523
+ : ora(`🧠 Getting history for ${argv.sessionId}...`).start();
1524
+ try {
1525
+ const sdk = globalSession.getOrCreateNeuroLink();
1526
+ // Handle dry-run mode
1527
+ if (options.dryRun) {
1528
+ const mockHistory = [
1529
+ { role: "user", content: "Hello, how are you?" },
1530
+ {
1531
+ role: "assistant",
1532
+ content: "I'm doing well, thank you! How can I help you today?",
1533
+ },
1534
+ { role: "user", content: "Can you explain quantum computing?" },
1535
+ {
1536
+ role: "assistant",
1537
+ content: "Quantum computing is a revolutionary technology...",
1538
+ },
1539
+ ];
1540
+ if (spinner) {
1541
+ spinner.succeed(chalk.green(`✅ History retrieved for ${argv.sessionId} (dry-run)`));
1542
+ }
1543
+ this.handleOutput(mockHistory, options);
1544
+ return;
1545
+ }
1546
+ const history = await sdk.getConversationHistory(argv.sessionId);
1547
+ if (spinner) {
1548
+ spinner.succeed(chalk.green(`✅ History retrieved for ${argv.sessionId}`));
1549
+ }
1550
+ if (history.length === 0) {
1551
+ logger.always(chalk.yellow(`⚠️ No conversation history found for session: ${argv.sessionId}`));
1552
+ return;
1553
+ }
1554
+ if (options.format === "json") {
1555
+ this.handleOutput(history, options);
1556
+ }
1557
+ else {
1558
+ logger.always(chalk.blue(`💬 Conversation History (${argv.sessionId}):`));
1559
+ for (const message of history) {
1560
+ const roleColor = message.role === "user" ? chalk.cyan : chalk.green;
1561
+ const roleLabel = message.role === "user" ? "User" : "Assistant";
1562
+ logger.always(` [${roleColor(roleLabel)}]: ${message.content}`);
1563
+ }
1564
+ }
1565
+ }
1566
+ catch (error) {
1567
+ if (spinner) {
1568
+ spinner.fail("Memory history failed");
1569
+ }
1570
+ if (error.message.includes("not enabled")) {
1571
+ logger.always(chalk.yellow("⚠️ Conversation memory is not enabled"));
1572
+ logger.always("Enable it by using --enable-conversation-memory with loop mode");
1573
+ }
1574
+ else {
1575
+ handleError(error, "Memory history");
1576
+ }
1577
+ }
1578
+ }
1579
+ /**
1580
+ * Execute memory clear command
1581
+ */
1582
+ static async executeMemoryClear(argv) {
1583
+ const options = this.processOptions(argv);
1584
+ const isAllSessions = !argv.sessionId;
1585
+ const target = isAllSessions ? "all sessions" : `session ${argv.sessionId}`;
1586
+ const spinner = options.quiet
1587
+ ? null
1588
+ : ora(`🧠 Clearing ${target}...`).start();
1589
+ try {
1590
+ const sdk = globalSession.getOrCreateNeuroLink();
1591
+ // Handle dry-run mode
1592
+ if (options.dryRun) {
1593
+ if (spinner) {
1594
+ spinner.succeed(chalk.green(`✅ ${isAllSessions ? "All sessions" : "Session"} cleared (dry-run)`));
1595
+ }
1596
+ const result = {
1597
+ success: true,
1598
+ action: isAllSessions ? "clear_all" : "clear_session",
1599
+ sessionId: argv.sessionId || null,
1600
+ message: `${isAllSessions ? "All sessions" : "Session"} would be cleared`,
1601
+ };
1602
+ this.handleOutput(result, options);
1603
+ return;
1604
+ }
1605
+ let success;
1606
+ if (isAllSessions) {
1607
+ await sdk.clearAllConversations();
1608
+ success = true;
1609
+ }
1610
+ else {
1611
+ success = await sdk.clearConversationSession(argv.sessionId);
1612
+ }
1613
+ if (spinner) {
1614
+ if (success) {
1615
+ spinner.succeed(chalk.green(`✅ ${isAllSessions ? "All sessions" : "Session"} cleared successfully`));
1616
+ }
1617
+ else {
1618
+ spinner.warn(chalk.yellow(`⚠️ Session ${argv.sessionId} not found or already empty`));
1619
+ }
1620
+ }
1621
+ if (options.format === "json") {
1622
+ const result = {
1623
+ success,
1624
+ action: isAllSessions ? "clear_all" : "clear_session",
1625
+ sessionId: argv.sessionId || null,
1626
+ };
1627
+ this.handleOutput(result, options);
1628
+ }
1629
+ else if (!success && !isAllSessions) {
1630
+ logger.always(chalk.yellow(`⚠️ Session ${argv.sessionId} not found or already empty`));
1631
+ }
1632
+ else if (!options.quiet) {
1633
+ logger.always(chalk.green(`✅ ${isAllSessions ? "All conversation history" : `Session ${argv.sessionId}`} cleared`));
1634
+ }
1635
+ }
1636
+ catch (error) {
1637
+ if (spinner) {
1638
+ spinner.fail("Memory clear failed");
1639
+ }
1640
+ if (error.message.includes("not enabled")) {
1641
+ logger.always(chalk.yellow("⚠️ Conversation memory is not enabled"));
1642
+ logger.always("Enable it by using --enable-conversation-memory with loop mode");
1643
+ }
1644
+ else {
1645
+ handleError(error, "Memory clear");
1646
+ }
1647
+ }
1648
+ }
1299
1649
  /**
1300
1650
  * Execute completion command
1301
1651
  */
@@ -1317,7 +1667,7 @@ export class CLICommandFactory {
1317
1667
  ' prev="${COMP_WORDS[COMP_CWORD - 1]}"\n\n' +
1318
1668
  " # Main commands\n" +
1319
1669
  " if [[ ${COMP_CWORD} -eq 1 ]]; then\n" +
1320
- ' opts="generate gen stream batch provider status models mcp discover config get-best-provider completion"\n' +
1670
+ ' opts="generate gen stream batch provider status models mcp discover memory config get-best-provider completion"\n' +
1321
1671
  ' COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )\n' +
1322
1672
  " return 0\n" +
1323
1673
  " fi\n\n" +
@@ -1379,6 +1729,12 @@ export class CLICommandFactory {
1379
1729
  " return 0\n" +
1380
1730
  " fi\n" +
1381
1731
  " ;;\n" +
1732
+ " memory)\n" +
1733
+ " if [[ ${COMP_CWORD} -eq 2 ]]; then\n" +
1734
+ ' COMPREPLY=( $(compgen -W "stats history clear" -- ${cur}) )\n' +
1735
+ " return 0\n" +
1736
+ " fi\n" +
1737
+ " ;;\n" +
1382
1738
  " *)\n" +
1383
1739
  " # Global options for all commands\n" +
1384
1740
  ' opts="--help --version --debug --quiet --noColor --configFile"\n' +
@@ -196,7 +196,13 @@ export class OllamaCommandFactory {
196
196
  * Handler for starting Ollama service
197
197
  */
198
198
  static async startHandler() {
199
- await OllamaUtils.startOllamaService();
199
+ try {
200
+ await OllamaUtils.startOllamaService();
201
+ }
202
+ catch (error) {
203
+ logger.error("Failed to start Ollama service:", error);
204
+ throw error;
205
+ }
200
206
  }
201
207
  /**
202
208
  * Handler for stopping Ollama service
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Setup Command Factory for NeuroLink
3
+ * Consolidates all provider setup commands into a unified interface
4
+ */
5
+ import type { CommandModule } from "yargs";
6
+ /**
7
+ * Setup Command Factory
8
+ */
9
+ export declare class SetupCommandFactory {
10
+ /**
11
+ * Create the main setup command with all provider subcommands
12
+ */
13
+ static createSetupCommands(): CommandModule;
14
+ /**
15
+ * Build common options for provider setup commands
16
+ */
17
+ private static buildProviderOptions;
18
+ }