@juspay/neurolink 7.1.0 → 7.3.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 (92) hide show
  1. package/CHANGELOG.md +15 -2
  2. package/README.md +16 -11
  3. package/dist/cli/commands/config.d.ts +2 -2
  4. package/dist/cli/commands/config.js +22 -21
  5. package/dist/cli/commands/mcp.d.ts +79 -0
  6. package/dist/cli/commands/mcp.js +916 -0
  7. package/dist/cli/commands/models.d.ts +63 -0
  8. package/dist/cli/commands/models.js +653 -0
  9. package/dist/cli/commands/ollama.js +56 -55
  10. package/dist/cli/factories/commandFactory.d.ts +14 -0
  11. package/dist/cli/factories/commandFactory.js +346 -47
  12. package/dist/cli/index.js +25 -10
  13. package/dist/cli/utils/completeSetup.js +9 -8
  14. package/dist/cli/utils/envManager.js +7 -6
  15. package/dist/cli/utils/interactiveSetup.js +20 -19
  16. package/dist/core/analytics.js +25 -38
  17. package/dist/core/baseProvider.d.ts +8 -0
  18. package/dist/core/baseProvider.js +177 -68
  19. package/dist/core/constants.d.ts +11 -0
  20. package/dist/core/constants.js +17 -0
  21. package/dist/core/evaluation.js +25 -14
  22. package/dist/core/factory.js +19 -18
  23. package/dist/core/streamAnalytics.d.ts +65 -0
  24. package/dist/core/streamAnalytics.js +125 -0
  25. package/dist/lib/core/analytics.js +25 -38
  26. package/dist/lib/core/baseProvider.d.ts +8 -0
  27. package/dist/lib/core/baseProvider.js +177 -68
  28. package/dist/lib/core/constants.d.ts +11 -0
  29. package/dist/lib/core/constants.js +17 -0
  30. package/dist/lib/core/evaluation.js +25 -14
  31. package/dist/lib/core/factory.js +19 -18
  32. package/dist/lib/core/streamAnalytics.d.ts +65 -0
  33. package/dist/lib/core/streamAnalytics.js +125 -0
  34. package/dist/lib/models/modelRegistry.d.ts +132 -0
  35. package/dist/lib/models/modelRegistry.js +483 -0
  36. package/dist/lib/models/modelResolver.d.ts +115 -0
  37. package/dist/lib/models/modelResolver.js +467 -0
  38. package/dist/lib/neurolink.d.ts +4 -1
  39. package/dist/lib/neurolink.js +101 -67
  40. package/dist/lib/providers/anthropic.js +3 -0
  41. package/dist/lib/providers/googleAiStudio.js +13 -0
  42. package/dist/lib/providers/huggingFace.js +15 -3
  43. package/dist/lib/providers/mistral.js +19 -7
  44. package/dist/lib/providers/ollama.js +31 -7
  45. package/dist/lib/providers/openAI.js +12 -0
  46. package/dist/lib/sdk/toolRegistration.js +2 -2
  47. package/dist/lib/types/cli.d.ts +56 -1
  48. package/dist/lib/types/contextTypes.d.ts +110 -0
  49. package/dist/lib/types/contextTypes.js +176 -0
  50. package/dist/lib/types/index.d.ts +4 -1
  51. package/dist/lib/types/mcpTypes.d.ts +118 -7
  52. package/dist/lib/types/providers.d.ts +81 -0
  53. package/dist/lib/types/streamTypes.d.ts +44 -7
  54. package/dist/lib/types/tools.d.ts +9 -0
  55. package/dist/lib/types/universalProviderOptions.d.ts +3 -1
  56. package/dist/lib/types/universalProviderOptions.js +2 -1
  57. package/dist/lib/utils/logger.d.ts +7 -0
  58. package/dist/lib/utils/logger.js +11 -0
  59. package/dist/lib/utils/performance.d.ts +105 -0
  60. package/dist/lib/utils/performance.js +210 -0
  61. package/dist/lib/utils/retryHandler.d.ts +89 -0
  62. package/dist/lib/utils/retryHandler.js +269 -0
  63. package/dist/models/modelRegistry.d.ts +132 -0
  64. package/dist/models/modelRegistry.js +483 -0
  65. package/dist/models/modelResolver.d.ts +115 -0
  66. package/dist/models/modelResolver.js +468 -0
  67. package/dist/neurolink.d.ts +4 -1
  68. package/dist/neurolink.js +101 -67
  69. package/dist/providers/anthropic.js +3 -0
  70. package/dist/providers/googleAiStudio.js +13 -0
  71. package/dist/providers/huggingFace.js +15 -3
  72. package/dist/providers/mistral.js +19 -7
  73. package/dist/providers/ollama.js +31 -7
  74. package/dist/providers/openAI.js +12 -0
  75. package/dist/sdk/toolRegistration.js +2 -2
  76. package/dist/types/cli.d.ts +56 -1
  77. package/dist/types/contextTypes.d.ts +110 -0
  78. package/dist/types/contextTypes.js +177 -0
  79. package/dist/types/index.d.ts +4 -1
  80. package/dist/types/mcpTypes.d.ts +118 -7
  81. package/dist/types/providers.d.ts +81 -0
  82. package/dist/types/streamTypes.d.ts +44 -7
  83. package/dist/types/tools.d.ts +9 -0
  84. package/dist/types/universalProviderOptions.d.ts +3 -1
  85. package/dist/types/universalProviderOptions.js +3 -1
  86. package/dist/utils/logger.d.ts +7 -0
  87. package/dist/utils/logger.js +11 -0
  88. package/dist/utils/performance.d.ts +105 -0
  89. package/dist/utils/performance.js +210 -0
  90. package/dist/utils/retryHandler.d.ts +89 -0
  91. package/dist/utils/retryHandler.js +269 -0
  92. package/package.json +2 -1
@@ -1,4 +1,7 @@
1
1
  import { NeuroLink } from "../../lib/neurolink.js";
2
+ import { ContextFactory, } from "../../lib/types/contextTypes.js";
3
+ import { ModelsCommandFactory } from "../commands/models.js";
4
+ import { MCPCommandFactory } from "../commands/mcp.js";
2
5
  import ora from "ora";
3
6
  import chalk from "chalk";
4
7
  import { logger } from "../../lib/utils/logger.js";
@@ -26,24 +29,29 @@ export class CLICommandFactory {
26
29
  ],
27
30
  default: "auto",
28
31
  description: "AI provider to use (auto-selects best available)",
32
+ alias: "p",
29
33
  },
30
34
  model: {
31
35
  type: "string",
32
36
  description: "Specific model to use (e.g. gemini-2.5-pro, gemini-2.5-flash)",
37
+ alias: "m",
33
38
  },
34
39
  temperature: {
35
40
  type: "number",
36
41
  default: 0.7,
37
42
  description: "Creativity level (0.0 = focused, 1.0 = creative)",
43
+ alias: "t",
38
44
  },
39
45
  maxTokens: {
40
46
  type: "number",
41
47
  default: 1000,
42
48
  description: "Maximum tokens to generate",
49
+ alias: "max",
43
50
  },
44
51
  system: {
45
52
  type: "string",
46
53
  description: "System prompt to guide AI behavior",
54
+ alias: "s",
47
55
  },
48
56
  // Output control options
49
57
  format: {
@@ -55,6 +63,7 @@ export class CLICommandFactory {
55
63
  output: {
56
64
  type: "string",
57
65
  description: "Save output to file",
66
+ alias: "o",
58
67
  },
59
68
  // Behavior control options
60
69
  timeout: {
@@ -112,6 +121,15 @@ export class CLICommandFactory {
112
121
  default: false,
113
122
  description: "Suppress non-essential output",
114
123
  },
124
+ noColor: {
125
+ type: "boolean",
126
+ default: false,
127
+ description: "Disable colored output (useful for CI/scripts)",
128
+ },
129
+ configFile: {
130
+ type: "string",
131
+ description: "Path to custom configuration file",
132
+ },
115
133
  };
116
134
  // Helper method to build options for commands
117
135
  static buildOptions(yargs, additionalOptions = {}) {
@@ -122,6 +140,47 @@ export class CLICommandFactory {
122
140
  }
123
141
  // Helper method to process common options
124
142
  static processOptions(argv) {
143
+ // Handle noColor option by disabling chalk
144
+ if (argv.noColor) {
145
+ process.env.FORCE_COLOR = "0";
146
+ }
147
+ // Process context using ContextFactory for type-safe integration
148
+ let processedContext;
149
+ let contextConfig;
150
+ if (argv.context) {
151
+ let rawContext;
152
+ if (typeof argv.context === "string") {
153
+ try {
154
+ rawContext = JSON.parse(argv.context);
155
+ }
156
+ catch (err) {
157
+ const contextStr = argv.context;
158
+ const truncatedJson = contextStr.length > 100
159
+ ? `${contextStr.slice(0, 100)}...`
160
+ : contextStr;
161
+ logger.error(`Invalid JSON in --context parameter: ${err.message}. Received: ${truncatedJson}`);
162
+ process.exit(1);
163
+ }
164
+ }
165
+ else {
166
+ rawContext = argv.context;
167
+ }
168
+ const validatedContext = ContextFactory.validateContext(rawContext);
169
+ if (validatedContext) {
170
+ processedContext = validatedContext;
171
+ // Configure context integration based on CLI usage
172
+ contextConfig = {
173
+ mode: "prompt_prefix", // Add context as prompt prefix for CLI usage
174
+ includeInPrompt: true,
175
+ includeInAnalytics: true,
176
+ includeInEvaluation: true,
177
+ maxLength: 500, // Reasonable limit for CLI context
178
+ };
179
+ }
180
+ else if (argv.debug) {
181
+ logger.debug("Invalid context provided, skipping context integration");
182
+ }
183
+ }
125
184
  return {
126
185
  provider: argv.provider === "auto" ? undefined : argv.provider,
127
186
  model: argv.model,
@@ -135,16 +194,15 @@ export class CLICommandFactory {
135
194
  evaluationDomain: argv.evaluationDomain,
136
195
  toolUsageContext: argv.toolUsageContext,
137
196
  lighthouseStyle: argv.lighthouseStyle,
138
- context: argv.context
139
- ? typeof argv.context === "string"
140
- ? JSON.parse(argv.context)
141
- : argv.context
142
- : undefined,
197
+ context: processedContext,
198
+ contextConfig,
143
199
  debug: argv.debug,
144
200
  quiet: argv.quiet,
145
201
  format: argv.format,
146
202
  output: argv.output,
147
203
  delay: argv.delay,
204
+ noColor: argv.noColor,
205
+ configFile: argv.configFile,
148
206
  };
149
207
  }
150
208
  // Helper method to handle output
@@ -154,7 +212,7 @@ export class CLICommandFactory {
154
212
  output = JSON.stringify(result, null, 2);
155
213
  }
156
214
  else if (options.format === "table" && Array.isArray(result)) {
157
- console.table(result);
215
+ logger.table(result);
158
216
  return;
159
217
  }
160
218
  else {
@@ -162,7 +220,12 @@ export class CLICommandFactory {
162
220
  output = result;
163
221
  }
164
222
  else if (result && typeof result === "object" && "content" in result) {
165
- output = result.content;
223
+ const generateResult = result;
224
+ output = generateResult.content;
225
+ // Add analytics display for text mode when enabled
226
+ if (options.enableAnalytics && generateResult.analytics) {
227
+ output += this.formatAnalyticsForTextMode(generateResult);
228
+ }
166
229
  }
167
230
  else if (result && typeof result === "object" && "text" in result) {
168
231
  output = result.text;
@@ -174,13 +237,67 @@ export class CLICommandFactory {
174
237
  if (options.output) {
175
238
  fs.writeFileSync(options.output, output);
176
239
  if (!options.quiet) {
177
- console.log(`Output saved to ${options.output}`);
240
+ logger.always(`Output saved to ${options.output}`);
178
241
  }
179
242
  }
180
243
  else {
181
- console.log(output);
244
+ logger.always(output);
182
245
  }
183
246
  }
247
+ // Helper method to validate token usage data
248
+ static isValidTokenUsage(tokens) {
249
+ return !!(tokens &&
250
+ typeof tokens === "object" &&
251
+ tokens !== null &&
252
+ typeof tokens.input === "number" &&
253
+ typeof tokens.output === "number" &&
254
+ typeof tokens.total === "number");
255
+ }
256
+ // Helper method to format analytics for text mode display
257
+ static formatAnalyticsForTextMode(result) {
258
+ if (!result.analytics) {
259
+ return "";
260
+ }
261
+ const analytics = result.analytics;
262
+ let analyticsText = "\n\nšŸ“Š Analytics:\n";
263
+ // Provider and model info
264
+ analyticsText += ` Provider: ${analytics.provider}`;
265
+ if (result.model) {
266
+ analyticsText += ` (${result.model})`;
267
+ }
268
+ analyticsText += "\n";
269
+ // Token usage
270
+ if (this.isValidTokenUsage(analytics.tokens)) {
271
+ const tokens = analytics.tokens;
272
+ analyticsText += ` Tokens: ${tokens.input} input + ${tokens.output} output = ${tokens.total} total\n`;
273
+ }
274
+ // Cost information
275
+ if (analytics.cost !== undefined &&
276
+ analytics.cost !== null &&
277
+ typeof analytics.cost === "number") {
278
+ analyticsText += ` Cost: $${analytics.cost.toFixed(5)}\n`;
279
+ }
280
+ // Response time
281
+ if (analytics.responseTime && typeof analytics.responseTime === "number") {
282
+ const timeInSeconds = (analytics.responseTime / 1000).toFixed(1);
283
+ analyticsText += ` Time: ${timeInSeconds}s\n`;
284
+ }
285
+ // Tools used
286
+ if (result.toolsUsed && result.toolsUsed.length > 0) {
287
+ analyticsText += ` Tools: ${result.toolsUsed.join(", ")}\n`;
288
+ }
289
+ // Context information
290
+ if (analytics.context &&
291
+ typeof analytics.context === "object" &&
292
+ analytics.context !== null) {
293
+ const contextEntries = Object.entries(analytics.context);
294
+ if (contextEntries.length > 0) {
295
+ const contextItems = contextEntries.map(([key, value]) => `${key}=${value}`);
296
+ analyticsText += ` Context: ${contextItems.join(", ")}\n`;
297
+ }
298
+ }
299
+ return analyticsText;
300
+ }
184
301
  /**
185
302
  * Create the new primary 'generate' command
186
303
  */
@@ -189,10 +306,16 @@ export class CLICommandFactory {
189
306
  command: ["generate <input>", "gen <input>"],
190
307
  describe: "Generate content using AI providers",
191
308
  builder: (yargs) => {
192
- return this.buildOptions(yargs.positional("input", {
309
+ return this.buildOptions(yargs
310
+ .positional("input", {
193
311
  type: "string",
194
312
  description: "Text prompt for AI generation (or read from stdin)",
195
- }));
313
+ })
314
+ .example('$0 generate "Explain quantum computing"', "Basic generation")
315
+ .example('$0 gen "Write a Python function" --provider openai', "Use specific provider")
316
+ .example('$0 generate "Code review" -m gpt-4 -t 0.3', "Use specific model and temperature")
317
+ .example('echo "Summarize this" | $0 generate', "Use stdin input")
318
+ .example('$0 generate "Analyze data" --enable-analytics', "Enable usage analytics"));
196
319
  },
197
320
  handler: async (argv) => await this.executeGenerate(argv),
198
321
  };
@@ -205,10 +328,15 @@ export class CLICommandFactory {
205
328
  command: "stream <input>",
206
329
  describe: "Stream generation in real-time",
207
330
  builder: (yargs) => {
208
- return this.buildOptions(yargs.positional("input", {
331
+ return this.buildOptions(yargs
332
+ .positional("input", {
209
333
  type: "string",
210
334
  description: "Text prompt for streaming (or read from stdin)",
211
- }));
335
+ })
336
+ .example('$0 stream "Write a story about space"', "Stream a creative story")
337
+ .example('$0 stream "Explain machine learning" -p anthropic', "Stream with specific provider")
338
+ .example('$0 stream "Code walkthrough" --output story.txt', "Stream to file")
339
+ .example('echo "Live demo" | $0 stream', "Stream from stdin"));
212
340
  },
213
341
  handler: async (argv) => await this.executeStream(argv),
214
342
  };
@@ -221,11 +349,16 @@ export class CLICommandFactory {
221
349
  command: "batch <file>",
222
350
  describe: "Process multiple prompts from a file",
223
351
  builder: (yargs) => {
224
- return this.buildOptions(yargs.positional("file", {
352
+ return this.buildOptions(yargs
353
+ .positional("file", {
225
354
  type: "string",
226
355
  description: "File with prompts (one per line)",
227
356
  demandOption: true,
228
- }));
357
+ })
358
+ .example("$0 batch prompts.txt", "Process prompts from file")
359
+ .example("$0 batch questions.txt --format json", "Export results as JSON")
360
+ .example("$0 batch tasks.txt -p vertex --delay 2000", "Use Vertex AI with 2s delay")
361
+ .example("$0 batch batch.txt --output results.json", "Save results to file"));
229
362
  },
230
363
  handler: async (argv) => await this.executeBatch(argv),
231
364
  };
@@ -239,8 +372,11 @@ export class CLICommandFactory {
239
372
  describe: "Manage AI provider configurations and status",
240
373
  builder: (yargs) => {
241
374
  return yargs
242
- .command("status", "Check status of all configured AI providers", (y) => this.buildOptions(y), (argv) => CLICommandFactory.executeProviderStatus(argv))
243
- .demandCommand(1, "");
375
+ .command("status", "Check status of all configured AI providers", (y) => this.buildOptions(y)
376
+ .example("$0 provider status", "Check all provider status")
377
+ .example("$0 provider status --verbose", "Detailed provider diagnostics")
378
+ .example("$0 provider status --quiet", "Minimal status output"), (argv) => CLICommandFactory.executeProviderStatus(argv))
379
+ .demandCommand(1, "Please specify a provider subcommand");
244
380
  },
245
381
  handler: () => { }, // No-op handler as subcommands handle everything
246
382
  };
@@ -252,10 +388,31 @@ export class CLICommandFactory {
252
388
  return {
253
389
  command: "status",
254
390
  describe: "Check AI provider connectivity and performance (alias for provider status)",
255
- builder: (yargs) => this.buildOptions(yargs),
391
+ builder: (yargs) => this.buildOptions(yargs)
392
+ .example("$0 status", "Quick provider status check")
393
+ .example("$0 status --verbose", "Detailed connectivity diagnostics")
394
+ .example("$0 status --format json", "Export status as JSON"),
256
395
  handler: async (argv) => await CLICommandFactory.executeProviderStatus(argv),
257
396
  };
258
397
  }
398
+ /**
399
+ * Create models commands
400
+ */
401
+ static createModelsCommands() {
402
+ return ModelsCommandFactory.createModelsCommands();
403
+ }
404
+ /**
405
+ * Create MCP commands
406
+ */
407
+ static createMCPCommands() {
408
+ return MCPCommandFactory.createMCPCommands();
409
+ }
410
+ /**
411
+ * Create discover command
412
+ */
413
+ static createDiscoverCommand() {
414
+ return MCPCommandFactory.createDiscoverCommand();
415
+ }
259
416
  /**
260
417
  * Create config commands
261
418
  */
@@ -265,6 +422,30 @@ export class CLICommandFactory {
265
422
  describe: "Manage NeuroLink configuration",
266
423
  builder: (yargs) => {
267
424
  return yargs
425
+ .command("init", "Interactive configuration setup wizard", (y) => this.buildOptions(y), async (argv) => {
426
+ const { configManager } = await import("../commands/config.js");
427
+ await configManager.initInteractive();
428
+ })
429
+ .command("show", "Display current configuration", (y) => this.buildOptions(y), async (argv) => {
430
+ const { configManager } = await import("../commands/config.js");
431
+ configManager.showConfig();
432
+ })
433
+ .command("validate", "Validate current configuration", (y) => this.buildOptions(y), async (argv) => {
434
+ const { configManager } = await import("../commands/config.js");
435
+ const result = configManager.validateConfig();
436
+ if (result.valid) {
437
+ logger.always(chalk.green("āœ… Configuration is valid"));
438
+ }
439
+ else {
440
+ logger.always(chalk.red("āŒ Configuration has errors:"));
441
+ result.errors.forEach((error) => logger.always(` • ${error}`));
442
+ process.exit(1);
443
+ }
444
+ })
445
+ .command("reset", "Reset configuration to defaults", (y) => this.buildOptions(y), async (argv) => {
446
+ const { configManager } = await import("../commands/config.js");
447
+ configManager.resetConfig();
448
+ })
268
449
  .command("export", "Export current configuration", (y) => this.buildOptions(y), (argv) => this.executeConfigExport(argv))
269
450
  .demandCommand(1, "");
270
451
  },
@@ -278,7 +459,10 @@ export class CLICommandFactory {
278
459
  return {
279
460
  command: "get-best-provider",
280
461
  describe: "Show the best available AI provider",
281
- builder: (yargs) => this.buildOptions(yargs),
462
+ builder: (yargs) => this.buildOptions(yargs)
463
+ .example("$0 get-best-provider", "Get best available provider")
464
+ .example("$0 get-best-provider --format json", "Get provider as JSON")
465
+ .example("$0 get-best-provider --quiet", "Just the provider name"),
282
466
  handler: async (argv) => await this.executeGetBestProvider(argv),
283
467
  };
284
468
  }
@@ -289,7 +473,11 @@ export class CLICommandFactory {
289
473
  return {
290
474
  command: "completion",
291
475
  describe: "Generate shell completion script",
292
- builder: (yargs) => this.buildOptions(yargs),
476
+ builder: (yargs) => this.buildOptions(yargs)
477
+ .example("$0 completion", "Generate shell completion")
478
+ .example("$0 completion > ~/.neurolink-completion.sh", "Save completion script")
479
+ .example("source ~/.neurolink-completion.sh", "Enable completions (bash)")
480
+ .epilogue("Add the completion script to your shell profile for persistent completions"),
293
481
  handler: async (argv) => await this.executeCompletion(argv),
294
482
  };
295
483
  }
@@ -298,7 +486,7 @@ export class CLICommandFactory {
298
486
  */
299
487
  static async executeProviderStatus(argv) {
300
488
  if (argv.verbose && !argv.quiet) {
301
- console.log(chalk.yellow("ā„¹ļø Verbose mode enabled. Displaying detailed status.\n"));
489
+ logger.always(chalk.yellow("ā„¹ļø Verbose mode enabled. Displaying detailed status.\n"));
302
490
  }
303
491
  const spinner = argv.quiet
304
492
  ? null
@@ -306,7 +494,7 @@ export class CLICommandFactory {
306
494
  try {
307
495
  // Use SDK's provider diagnostic method instead of manual testing
308
496
  const sdk = new NeuroLink();
309
- const results = await sdk.getProviderStatus();
497
+ const results = await sdk.getProviderStatus({ quiet: !!argv.quiet });
310
498
  if (spinner) {
311
499
  const working = results.filter((r) => r.status === "working").length;
312
500
  const configured = results.filter((r) => r.configured).length;
@@ -321,21 +509,21 @@ export class CLICommandFactory {
321
509
  : chalk.gray("⚪ Not configured");
322
510
  const time = result.responseTime ? ` (${result.responseTime}ms)` : "";
323
511
  const model = result.model ? ` [${result.model}]` : "";
324
- console.log(`${result.provider}: ${status}${time}${model}`);
512
+ logger.always(`${result.provider}: ${status}${time}${model}`);
325
513
  if (argv.verbose && result.error) {
326
- console.log(` Error: ${chalk.red(result.error)}`);
514
+ logger.always(` Error: ${chalk.red(result.error)}`);
327
515
  }
328
516
  }
329
517
  if (argv.verbose && !argv.quiet) {
330
- console.log(chalk.blue("\nšŸ“‹ Detailed Results:"));
331
- console.log(JSON.stringify(results, null, 2));
518
+ logger.always(chalk.blue("\nšŸ“‹ Detailed Results:"));
519
+ logger.always(JSON.stringify(results, null, 2));
332
520
  }
333
521
  }
334
522
  catch (error) {
335
523
  if (spinner) {
336
524
  spinner.fail("Provider status check failed");
337
525
  }
338
- console.error(chalk.red("Error checking provider status:"), error);
526
+ logger.error(chalk.red("Error checking provider status:"), error);
339
527
  process.exit(1);
340
528
  }
341
529
  }
@@ -365,9 +553,32 @@ export class CLICommandFactory {
365
553
  if (options.delay) {
366
554
  await new Promise((resolve) => setTimeout(resolve, options.delay));
367
555
  }
556
+ // Process context if provided
557
+ let inputText = argv.input;
558
+ let contextMetadata;
559
+ if (options.context && options.contextConfig) {
560
+ const processedContextResult = ContextFactory.processContext(options.context, options.contextConfig);
561
+ // Integrate context into prompt if configured
562
+ if (processedContextResult.processedContext) {
563
+ inputText = processedContextResult.processedContext + inputText;
564
+ }
565
+ // Add context metadata for analytics
566
+ contextMetadata = {
567
+ ...ContextFactory.extractAnalyticsContext(options.context),
568
+ contextMode: processedContextResult.config.mode,
569
+ contextTruncated: processedContextResult.metadata.truncated,
570
+ };
571
+ if (options.debug) {
572
+ logger.debug("Context processed:", {
573
+ mode: processedContextResult.config.mode,
574
+ truncated: processedContextResult.metadata.truncated,
575
+ processingTime: processedContextResult.metadata.processingTime,
576
+ });
577
+ }
578
+ }
368
579
  const sdk = new NeuroLink();
369
580
  const result = await sdk.generate({
370
- input: { text: argv.input },
581
+ input: { text: inputText },
371
582
  provider: options.provider,
372
583
  model: options.model,
373
584
  temperature: options.temperature,
@@ -379,7 +590,7 @@ export class CLICommandFactory {
379
590
  enableEvaluation: options.enableEvaluation,
380
591
  evaluationDomain: options.evaluationDomain,
381
592
  toolUsageContext: options.toolUsageContext,
382
- context: options.context,
593
+ context: contextMetadata,
383
594
  });
384
595
  if (spinner) {
385
596
  spinner.succeed(chalk.green("āœ… Text generated successfully!"));
@@ -403,9 +614,9 @@ export class CLICommandFactory {
403
614
  if (spinner) {
404
615
  spinner.fail();
405
616
  }
406
- console.error(chalk.red(`āŒ Generation failed: ${error.message}`));
617
+ logger.error(chalk.red(`āŒ Generation failed: ${error.message}`));
407
618
  if (options.debug) {
408
- console.error(chalk.gray(error.stack));
619
+ logger.error(chalk.gray(error.stack));
409
620
  }
410
621
  process.exit(1);
411
622
  }
@@ -431,16 +642,39 @@ export class CLICommandFactory {
431
642
  }
432
643
  const options = this.processOptions(argv);
433
644
  if (!options.quiet) {
434
- console.log(chalk.blue("šŸ”„ Streaming..."));
645
+ logger.always(chalk.blue("šŸ”„ Streaming..."));
435
646
  }
436
647
  try {
437
648
  // Add delay if specified
438
649
  if (options.delay) {
439
650
  await new Promise((resolve) => setTimeout(resolve, options.delay));
440
651
  }
652
+ // Process context if provided (same as generate command)
653
+ let inputText = argv.input;
654
+ let contextMetadata;
655
+ if (options.context && options.contextConfig) {
656
+ const processedContextResult = ContextFactory.processContext(options.context, options.contextConfig);
657
+ // Integrate context into prompt if configured
658
+ if (processedContextResult.processedContext) {
659
+ inputText = processedContextResult.processedContext + inputText;
660
+ }
661
+ // Add context metadata for analytics
662
+ contextMetadata = {
663
+ ...ContextFactory.extractAnalyticsContext(options.context),
664
+ contextMode: processedContextResult.config.mode,
665
+ contextTruncated: processedContextResult.metadata.truncated,
666
+ };
667
+ if (options.debug) {
668
+ logger.debug("Context processed for streaming:", {
669
+ mode: processedContextResult.config.mode,
670
+ truncated: processedContextResult.metadata.truncated,
671
+ processingTime: processedContextResult.metadata.processingTime,
672
+ });
673
+ }
674
+ }
441
675
  const sdk = new NeuroLink();
442
676
  const stream = await sdk.stream({
443
- input: { text: argv.input },
677
+ input: { text: inputText },
444
678
  provider: options.provider,
445
679
  model: options.model,
446
680
  temperature: options.temperature,
@@ -450,7 +684,7 @@ export class CLICommandFactory {
450
684
  disableTools: options.disableTools,
451
685
  enableAnalytics: options.enableAnalytics,
452
686
  enableEvaluation: options.enableEvaluation,
453
- context: options.context,
687
+ context: contextMetadata,
454
688
  });
455
689
  let fullContent = "";
456
690
  // Process the stream
@@ -465,19 +699,69 @@ export class CLICommandFactory {
465
699
  if (!options.quiet) {
466
700
  process.stdout.write("\n");
467
701
  }
702
+ // šŸ”§ NEW: Display analytics and evaluation after streaming (similar to generate command)
703
+ if (options.enableAnalytics && stream.analytics) {
704
+ const resolvedAnalytics = await (stream.analytics instanceof Promise
705
+ ? stream.analytics
706
+ : Promise.resolve(stream.analytics));
707
+ const streamAnalytics = {
708
+ success: true,
709
+ content: fullContent,
710
+ analytics: resolvedAnalytics,
711
+ model: stream.model,
712
+ toolsUsed: stream.toolCalls?.map((tc) => tc.toolName) || [],
713
+ };
714
+ const analyticsDisplay = this.formatAnalyticsForTextMode(streamAnalytics);
715
+ logger.always(analyticsDisplay);
716
+ }
717
+ // šŸ”§ NEW: Display evaluation after streaming
718
+ if (options.enableEvaluation && stream.evaluation) {
719
+ const resolvedEvaluation = await (stream.evaluation instanceof Promise
720
+ ? stream.evaluation
721
+ : Promise.resolve(stream.evaluation));
722
+ logger.always(chalk.blue("\nšŸ“Š Response Evaluation:"));
723
+ logger.always(` Relevance: ${resolvedEvaluation.relevance}/10`);
724
+ logger.always(` Accuracy: ${resolvedEvaluation.accuracy}/10`);
725
+ logger.always(` Completeness: ${resolvedEvaluation.completeness}/10`);
726
+ logger.always(` Overall: ${resolvedEvaluation.overall}/10`);
727
+ if (resolvedEvaluation.reasoning) {
728
+ logger.always(` Reasoning: ${resolvedEvaluation.reasoning}`);
729
+ }
730
+ }
468
731
  // Handle output file if specified
469
732
  if (options.output) {
470
733
  fs.writeFileSync(options.output, fullContent);
471
734
  if (!options.quiet) {
472
- console.log(`\nOutput saved to ${options.output}`);
735
+ logger.always(`\nOutput saved to ${options.output}`);
736
+ }
737
+ }
738
+ // šŸ”§ NEW: Debug output for streaming (similar to generate command)
739
+ if (options.debug) {
740
+ logger.debug("\n" + chalk.yellow("Debug Information (Streaming):"));
741
+ logger.debug("Provider:", stream.provider);
742
+ logger.debug("Model:", stream.model);
743
+ if (stream.analytics) {
744
+ const resolvedAnalytics = await (stream.analytics instanceof Promise
745
+ ? stream.analytics
746
+ : Promise.resolve(stream.analytics));
747
+ logger.debug("Analytics:", JSON.stringify(resolvedAnalytics, null, 2));
748
+ }
749
+ if (stream.evaluation) {
750
+ const resolvedEvaluation = await (stream.evaluation instanceof Promise
751
+ ? stream.evaluation
752
+ : Promise.resolve(stream.evaluation));
753
+ logger.debug("Evaluation:", JSON.stringify(resolvedEvaluation, null, 2));
754
+ }
755
+ if (stream.metadata) {
756
+ logger.debug("Metadata:", JSON.stringify(stream.metadata, null, 2));
473
757
  }
474
758
  }
475
759
  process.exit(0);
476
760
  }
477
761
  catch (error) {
478
- console.error(chalk.red(`āŒ Streaming failed: ${error.message}`));
762
+ logger.error(chalk.red(`āŒ Streaming failed: ${error.message}`));
479
763
  if (options.debug) {
480
- console.error(chalk.gray(error.stack));
764
+ logger.error(chalk.gray(error.stack));
481
765
  }
482
766
  process.exit(1);
483
767
  }
@@ -508,7 +792,7 @@ export class CLICommandFactory {
508
792
  spinner.text = `šŸ“¦ Processing ${prompts.length} prompts...`;
509
793
  }
510
794
  else if (!options.quiet) {
511
- console.log(chalk.blue(`šŸ“¦ Processing ${prompts.length} prompts...\n`));
795
+ logger.always(chalk.blue(`šŸ“¦ Processing ${prompts.length} prompts...\n`));
512
796
  }
513
797
  const results = [];
514
798
  const sdk = new NeuroLink();
@@ -517,8 +801,23 @@ export class CLICommandFactory {
517
801
  spinner.text = `Processing ${i + 1}/${prompts.length}: ${prompts[i].substring(0, 30)}...`;
518
802
  }
519
803
  try {
804
+ // Process context for each batch item
805
+ let inputText = prompts[i];
806
+ let contextMetadata;
807
+ if (options.context && options.contextConfig) {
808
+ const processedContextResult = ContextFactory.processContext(options.context, options.contextConfig);
809
+ if (processedContextResult.processedContext) {
810
+ inputText = processedContextResult.processedContext + inputText;
811
+ }
812
+ contextMetadata = {
813
+ ...ContextFactory.extractAnalyticsContext(options.context),
814
+ contextMode: processedContextResult.config.mode,
815
+ contextTruncated: processedContextResult.metadata.truncated,
816
+ batchIndex: i,
817
+ };
818
+ }
520
819
  const result = await sdk.generate({
521
- input: { text: prompts[i] },
820
+ input: { text: inputText },
522
821
  provider: options.provider,
523
822
  model: options.model,
524
823
  temperature: options.temperature,
@@ -528,7 +827,7 @@ export class CLICommandFactory {
528
827
  disableTools: options.disableTools,
529
828
  enableAnalytics: options.enableAnalytics,
530
829
  enableEvaluation: options.enableEvaluation,
531
- context: options.context,
830
+ context: contextMetadata,
532
831
  });
533
832
  results.push({ prompt: prompts[i], response: result.content });
534
833
  if (spinner) {
@@ -560,9 +859,9 @@ export class CLICommandFactory {
560
859
  if (spinner) {
561
860
  spinner.fail();
562
861
  }
563
- console.error(chalk.red(`āŒ Batch processing failed: ${error.message}`));
862
+ logger.error(chalk.red(`āŒ Batch processing failed: ${error.message}`));
564
863
  if (options.debug) {
565
- console.error(chalk.gray(error.stack));
864
+ logger.error(chalk.gray(error.stack));
566
865
  }
567
866
  process.exit(1);
568
867
  }
@@ -593,7 +892,7 @@ export class CLICommandFactory {
593
892
  this.handleOutput(config, options);
594
893
  }
595
894
  catch (error) {
596
- console.error(chalk.red(`āŒ Configuration export failed: ${error.message}`));
895
+ logger.error(chalk.red(`āŒ Configuration export failed: ${error.message}`));
597
896
  process.exit(1);
598
897
  }
599
898
  }
@@ -610,7 +909,7 @@ export class CLICommandFactory {
610
909
  }
611
910
  else {
612
911
  if (!options.quiet) {
613
- console.log(chalk.green(`šŸŽÆ Best available provider: ${bestProvider}`));
912
+ logger.always(chalk.green(`šŸŽÆ Best available provider: ${bestProvider}`));
614
913
  }
615
914
  else {
616
915
  this.handleOutput(bestProvider, options);
@@ -618,7 +917,7 @@ export class CLICommandFactory {
618
917
  }
619
918
  }
620
919
  catch (error) {
621
- console.error(chalk.red(`āŒ Provider selection failed: ${error.message}`));
920
+ logger.error(chalk.red(`āŒ Provider selection failed: ${error.message}`));
622
921
  process.exit(1);
623
922
  }
624
923
  }
@@ -627,7 +926,7 @@ export class CLICommandFactory {
627
926
  */
628
927
  static async executeCompletion(argv) {
629
928
  // This would need to be implemented with the actual CLI instance
630
- console.log("# Completion script would be generated here");
631
- console.log("# This requires access to the yargs CLI instance");
929
+ logger.always("# Completion script would be generated here");
930
+ logger.always("# This requires access to the yargs CLI instance");
632
931
  }
633
932
  }