@juspay/neurolink 7.29.1 → 7.29.3

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 (234) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cli/commands/config.d.ts +86 -86
  3. package/dist/cli/commands/mcp.js +64 -9
  4. package/dist/cli/commands/models.js +25 -21
  5. package/dist/cli/commands/ollama.js +2 -2
  6. package/dist/cli/factories/commandFactory.d.ts +9 -0
  7. package/dist/cli/factories/commandFactory.js +177 -83
  8. package/dist/cli/factories/ollamaCommandFactory.js +3 -1
  9. package/dist/cli/factories/sagemakerCommandFactory.js +3 -2
  10. package/dist/cli/index.d.ts +1 -1
  11. package/dist/cli/index.js +19 -11
  12. package/dist/cli/utils/envManager.js +5 -5
  13. package/dist/cli/utils/ollamaUtils.d.ts +12 -0
  14. package/dist/cli/utils/ollamaUtils.js +58 -42
  15. package/dist/config/configManager.js +5 -2
  16. package/dist/core/analytics.d.ts +2 -24
  17. package/dist/core/analytics.js +12 -17
  18. package/dist/core/baseProvider.d.ts +30 -1
  19. package/dist/core/baseProvider.js +180 -198
  20. package/dist/core/dynamicModels.d.ts +4 -4
  21. package/dist/core/dynamicModels.js +7 -7
  22. package/dist/core/evaluation.d.ts +9 -9
  23. package/dist/core/evaluation.js +117 -65
  24. package/dist/core/evaluationProviders.d.ts +18 -2
  25. package/dist/core/evaluationProviders.js +15 -13
  26. package/dist/core/factory.js +77 -4
  27. package/dist/core/modelConfiguration.d.ts +63 -0
  28. package/dist/core/modelConfiguration.js +354 -290
  29. package/dist/core/streamAnalytics.d.ts +10 -5
  30. package/dist/core/streamAnalytics.js +10 -10
  31. package/dist/core/types.d.ts +19 -109
  32. package/dist/core/types.js +13 -0
  33. package/dist/factories/providerFactory.js +4 -1
  34. package/dist/factories/providerRegistry.js +2 -2
  35. package/dist/index.d.ts +2 -1
  36. package/dist/lib/config/configManager.js +5 -2
  37. package/dist/lib/core/analytics.d.ts +2 -24
  38. package/dist/lib/core/analytics.js +12 -17
  39. package/dist/lib/core/baseProvider.d.ts +30 -1
  40. package/dist/lib/core/baseProvider.js +180 -198
  41. package/dist/lib/core/dynamicModels.js +7 -7
  42. package/dist/lib/core/evaluation.d.ts +9 -9
  43. package/dist/lib/core/evaluation.js +117 -65
  44. package/dist/lib/core/evaluationProviders.d.ts +18 -2
  45. package/dist/lib/core/evaluationProviders.js +15 -13
  46. package/dist/lib/core/factory.js +77 -4
  47. package/dist/lib/core/modelConfiguration.d.ts +63 -0
  48. package/dist/lib/core/modelConfiguration.js +354 -290
  49. package/dist/lib/core/streamAnalytics.d.ts +10 -5
  50. package/dist/lib/core/streamAnalytics.js +10 -10
  51. package/dist/lib/core/types.d.ts +19 -109
  52. package/dist/lib/core/types.js +13 -0
  53. package/dist/lib/factories/providerFactory.js +4 -1
  54. package/dist/lib/factories/providerRegistry.js +2 -2
  55. package/dist/lib/index.d.ts +2 -1
  56. package/dist/lib/mcp/externalServerManager.js +14 -6
  57. package/dist/lib/mcp/factory.js +1 -1
  58. package/dist/lib/mcp/flexibleToolValidator.d.ts +50 -0
  59. package/dist/lib/mcp/flexibleToolValidator.js +161 -0
  60. package/dist/lib/mcp/index.d.ts +1 -1
  61. package/dist/lib/mcp/index.js +1 -1
  62. package/dist/lib/mcp/mcpCircuitBreaker.js +5 -1
  63. package/dist/lib/mcp/mcpClientFactory.js +3 -0
  64. package/dist/lib/mcp/registry.d.ts +3 -3
  65. package/dist/lib/mcp/registry.js +3 -3
  66. package/dist/lib/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
  67. package/dist/lib/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
  68. package/dist/lib/mcp/servers/utilities/utilityServer.js +1 -1
  69. package/dist/lib/mcp/toolDiscoveryService.js +8 -2
  70. package/dist/lib/mcp/toolRegistry.d.ts +2 -2
  71. package/dist/lib/mcp/toolRegistry.js +29 -54
  72. package/dist/lib/middleware/builtin/analytics.js +4 -4
  73. package/dist/lib/middleware/builtin/guardrails.js +2 -2
  74. package/dist/lib/middleware/registry.js +11 -2
  75. package/dist/lib/models/modelRegistry.d.ts +1 -1
  76. package/dist/lib/models/modelRegistry.js +3 -3
  77. package/dist/lib/models/modelResolver.d.ts +1 -1
  78. package/dist/lib/models/modelResolver.js +2 -2
  79. package/dist/lib/neurolink.d.ts +118 -0
  80. package/dist/lib/neurolink.js +814 -952
  81. package/dist/lib/providers/amazonBedrock.d.ts +47 -6
  82. package/dist/lib/providers/amazonBedrock.js +282 -23
  83. package/dist/lib/providers/amazonSagemaker.d.ts +1 -1
  84. package/dist/lib/providers/amazonSagemaker.js +12 -3
  85. package/dist/lib/providers/anthropic.d.ts +1 -1
  86. package/dist/lib/providers/anthropic.js +7 -6
  87. package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
  88. package/dist/lib/providers/anthropicBaseProvider.js +4 -3
  89. package/dist/lib/providers/aws/credentialProvider.d.ts +58 -0
  90. package/dist/lib/providers/aws/credentialProvider.js +267 -0
  91. package/dist/lib/providers/aws/credentialTester.d.ts +49 -0
  92. package/dist/lib/providers/aws/credentialTester.js +394 -0
  93. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  94. package/dist/lib/providers/azureOpenai.js +1 -1
  95. package/dist/lib/providers/googleAiStudio.d.ts +1 -1
  96. package/dist/lib/providers/googleAiStudio.js +2 -2
  97. package/dist/lib/providers/googleVertex.d.ts +40 -0
  98. package/dist/lib/providers/googleVertex.js +330 -274
  99. package/dist/lib/providers/huggingFace.js +1 -1
  100. package/dist/lib/providers/mistral.d.ts +1 -1
  101. package/dist/lib/providers/mistral.js +2 -2
  102. package/dist/lib/providers/ollama.d.ts +4 -0
  103. package/dist/lib/providers/ollama.js +38 -18
  104. package/dist/lib/providers/openAI.d.ts +1 -1
  105. package/dist/lib/providers/openAI.js +2 -2
  106. package/dist/lib/providers/sagemaker/adaptive-semaphore.js +7 -4
  107. package/dist/lib/providers/sagemaker/client.js +13 -3
  108. package/dist/lib/providers/sagemaker/config.js +5 -1
  109. package/dist/lib/providers/sagemaker/detection.js +19 -9
  110. package/dist/lib/providers/sagemaker/errors.d.ts +8 -1
  111. package/dist/lib/providers/sagemaker/errors.js +103 -20
  112. package/dist/lib/providers/sagemaker/language-model.d.ts +3 -3
  113. package/dist/lib/providers/sagemaker/language-model.js +4 -4
  114. package/dist/lib/providers/sagemaker/parsers.js +14 -6
  115. package/dist/lib/providers/sagemaker/streaming.js +14 -3
  116. package/dist/lib/providers/sagemaker/types.d.ts +1 -1
  117. package/dist/lib/proxy/awsProxyIntegration.d.ts +23 -0
  118. package/dist/lib/proxy/awsProxyIntegration.js +285 -0
  119. package/dist/lib/proxy/proxyFetch.d.ts +9 -5
  120. package/dist/lib/proxy/proxyFetch.js +232 -98
  121. package/dist/lib/proxy/utils/noProxyUtils.d.ts +39 -0
  122. package/dist/lib/proxy/utils/noProxyUtils.js +149 -0
  123. package/dist/lib/sdk/toolRegistration.d.ts +1 -1
  124. package/dist/lib/types/cli.d.ts +80 -8
  125. package/dist/lib/types/contextTypes.js +2 -2
  126. package/dist/lib/types/generateTypes.d.ts +4 -6
  127. package/dist/lib/types/providers.d.ts +124 -19
  128. package/dist/lib/types/providers.js +6 -6
  129. package/dist/lib/types/streamTypes.d.ts +4 -6
  130. package/dist/lib/types/typeAliases.d.ts +1 -1
  131. package/dist/lib/utils/analyticsUtils.d.ts +33 -0
  132. package/dist/lib/utils/analyticsUtils.js +76 -0
  133. package/dist/lib/utils/errorHandling.js +4 -1
  134. package/dist/lib/utils/evaluationUtils.d.ts +27 -0
  135. package/dist/lib/utils/evaluationUtils.js +131 -0
  136. package/dist/lib/utils/optionsUtils.js +10 -1
  137. package/dist/lib/utils/performance.d.ts +1 -1
  138. package/dist/lib/utils/performance.js +15 -3
  139. package/dist/lib/utils/providerConfig.d.ts +1 -0
  140. package/dist/lib/utils/providerConfig.js +2 -1
  141. package/dist/lib/utils/providerHealth.d.ts +48 -0
  142. package/dist/lib/utils/providerHealth.js +221 -158
  143. package/dist/lib/utils/providerUtils.js +2 -2
  144. package/dist/lib/utils/timeout.js +8 -3
  145. package/dist/mcp/externalServerManager.js +14 -6
  146. package/dist/mcp/factory.js +1 -1
  147. package/dist/mcp/flexibleToolValidator.d.ts +50 -0
  148. package/dist/mcp/flexibleToolValidator.js +161 -0
  149. package/dist/mcp/index.d.ts +1 -1
  150. package/dist/mcp/index.js +1 -1
  151. package/dist/mcp/mcpCircuitBreaker.js +5 -1
  152. package/dist/mcp/mcpClientFactory.js +3 -0
  153. package/dist/mcp/registry.d.ts +3 -3
  154. package/dist/mcp/registry.js +3 -3
  155. package/dist/mcp/servers/aiProviders/aiAnalysisTools.js +5 -5
  156. package/dist/mcp/servers/aiProviders/aiWorkflowTools.js +6 -6
  157. package/dist/mcp/servers/utilities/utilityServer.js +1 -1
  158. package/dist/mcp/toolDiscoveryService.js +8 -2
  159. package/dist/mcp/toolRegistry.d.ts +2 -2
  160. package/dist/mcp/toolRegistry.js +29 -54
  161. package/dist/middleware/builtin/analytics.js +4 -4
  162. package/dist/middleware/builtin/guardrails.js +2 -2
  163. package/dist/middleware/registry.js +11 -2
  164. package/dist/models/modelRegistry.d.ts +1 -1
  165. package/dist/models/modelRegistry.js +3 -3
  166. package/dist/models/modelResolver.d.ts +1 -1
  167. package/dist/models/modelResolver.js +2 -2
  168. package/dist/neurolink.d.ts +118 -0
  169. package/dist/neurolink.js +814 -952
  170. package/dist/providers/amazonBedrock.d.ts +47 -6
  171. package/dist/providers/amazonBedrock.js +282 -23
  172. package/dist/providers/amazonSagemaker.d.ts +1 -1
  173. package/dist/providers/amazonSagemaker.js +12 -3
  174. package/dist/providers/anthropic.d.ts +1 -1
  175. package/dist/providers/anthropic.js +7 -6
  176. package/dist/providers/anthropicBaseProvider.d.ts +1 -1
  177. package/dist/providers/anthropicBaseProvider.js +4 -3
  178. package/dist/providers/aws/credentialProvider.d.ts +58 -0
  179. package/dist/providers/aws/credentialProvider.js +267 -0
  180. package/dist/providers/aws/credentialTester.d.ts +49 -0
  181. package/dist/providers/aws/credentialTester.js +394 -0
  182. package/dist/providers/azureOpenai.d.ts +1 -1
  183. package/dist/providers/azureOpenai.js +1 -1
  184. package/dist/providers/googleAiStudio.d.ts +1 -1
  185. package/dist/providers/googleAiStudio.js +2 -2
  186. package/dist/providers/googleVertex.d.ts +40 -0
  187. package/dist/providers/googleVertex.js +330 -274
  188. package/dist/providers/huggingFace.js +1 -1
  189. package/dist/providers/mistral.d.ts +1 -1
  190. package/dist/providers/mistral.js +2 -2
  191. package/dist/providers/ollama.d.ts +4 -0
  192. package/dist/providers/ollama.js +38 -18
  193. package/dist/providers/openAI.d.ts +1 -1
  194. package/dist/providers/openAI.js +2 -2
  195. package/dist/providers/sagemaker/adaptive-semaphore.js +7 -4
  196. package/dist/providers/sagemaker/client.js +13 -3
  197. package/dist/providers/sagemaker/config.js +5 -1
  198. package/dist/providers/sagemaker/detection.js +19 -9
  199. package/dist/providers/sagemaker/errors.d.ts +8 -1
  200. package/dist/providers/sagemaker/errors.js +103 -20
  201. package/dist/providers/sagemaker/language-model.d.ts +3 -3
  202. package/dist/providers/sagemaker/language-model.js +4 -4
  203. package/dist/providers/sagemaker/parsers.js +14 -6
  204. package/dist/providers/sagemaker/streaming.js +14 -3
  205. package/dist/providers/sagemaker/types.d.ts +1 -1
  206. package/dist/proxy/awsProxyIntegration.d.ts +23 -0
  207. package/dist/proxy/awsProxyIntegration.js +285 -0
  208. package/dist/proxy/proxyFetch.d.ts +9 -5
  209. package/dist/proxy/proxyFetch.js +232 -98
  210. package/dist/proxy/utils/noProxyUtils.d.ts +39 -0
  211. package/dist/proxy/utils/noProxyUtils.js +149 -0
  212. package/dist/sdk/toolRegistration.d.ts +1 -1
  213. package/dist/types/cli.d.ts +80 -8
  214. package/dist/types/contextTypes.js +2 -2
  215. package/dist/types/generateTypes.d.ts +4 -6
  216. package/dist/types/providers.d.ts +124 -19
  217. package/dist/types/providers.js +6 -6
  218. package/dist/types/streamTypes.d.ts +4 -6
  219. package/dist/types/typeAliases.d.ts +1 -1
  220. package/dist/utils/analyticsUtils.d.ts +33 -0
  221. package/dist/utils/analyticsUtils.js +76 -0
  222. package/dist/utils/errorHandling.js +4 -1
  223. package/dist/utils/evaluationUtils.d.ts +27 -0
  224. package/dist/utils/evaluationUtils.js +131 -0
  225. package/dist/utils/optionsUtils.js +10 -1
  226. package/dist/utils/performance.d.ts +1 -1
  227. package/dist/utils/performance.js +15 -3
  228. package/dist/utils/providerConfig.d.ts +1 -0
  229. package/dist/utils/providerConfig.js +2 -1
  230. package/dist/utils/providerHealth.d.ts +48 -0
  231. package/dist/utils/providerHealth.js +221 -158
  232. package/dist/utils/providerUtils.js +2 -2
  233. package/dist/utils/timeout.js +8 -3
  234. package/package.json +5 -1
@@ -1,5 +1,8 @@
1
1
  import { NeuroLink } from "../../lib/neurolink.js";
2
2
  import { configManager } from "../commands/config.js";
3
+ import { handleError } from "../index.js";
4
+ import { normalizeEvaluationData } from "../../lib/utils/evaluationUtils.js";
5
+ // Use TokenUsage from standard types - no local interface needed
3
6
  import { ContextFactory, } from "../../lib/types/contextTypes.js";
4
7
  import { ModelsCommandFactory } from "../commands/models.js";
5
8
  import { MCPCommandFactory } from "../commands/mcp.js";
@@ -9,6 +12,7 @@ import ora from "ora";
9
12
  import chalk from "chalk";
10
13
  import { logger } from "../../lib/utils/logger.js";
11
14
  import fs from "fs";
15
+ // Use specific command interfaces from cli.ts instead of universal interface
12
16
  /**
13
17
  * CLI Command Factory for generate commands
14
18
  */
@@ -209,7 +213,9 @@ export class CLICommandFactory {
209
213
  }
210
214
  }
211
215
  return {
212
- provider: argv.provider === "auto" ? undefined : argv.provider,
216
+ provider: argv.provider === "auto"
217
+ ? undefined
218
+ : argv.provider,
213
219
  model: argv.model,
214
220
  temperature: argv.temperature,
215
221
  maxTokens: argv.maxTokens,
@@ -273,14 +279,53 @@ export class CLICommandFactory {
273
279
  logger.always(output);
274
280
  }
275
281
  }
276
- // Helper method to validate token usage data
282
+ // Helper method to validate token usage data with fallback handling
277
283
  static isValidTokenUsage(tokens) {
278
- return !!(tokens &&
279
- typeof tokens === "object" &&
280
- tokens !== null &&
281
- typeof tokens.input === "number" &&
282
- typeof tokens.output === "number" &&
283
- typeof tokens.total === "number");
284
+ if (!tokens || typeof tokens !== "object" || tokens === null) {
285
+ return false;
286
+ }
287
+ const tokensObj = tokens;
288
+ // Check primary format: analytics.tokens {input, output, total}
289
+ if (typeof tokensObj.input === "number" &&
290
+ typeof tokensObj.output === "number" &&
291
+ typeof tokensObj.total === "number") {
292
+ return true;
293
+ }
294
+ // Check fallback format: tokenUsage {inputTokens, outputTokens, totalTokens}
295
+ if (typeof tokensObj.inputTokens === "number" &&
296
+ typeof tokensObj.outputTokens === "number" &&
297
+ typeof tokensObj.totalTokens === "number") {
298
+ return true;
299
+ }
300
+ return false;
301
+ }
302
+ // Helper method to normalize token usage data to standard format
303
+ static normalizeTokenUsage(tokens) {
304
+ if (!this.isValidTokenUsage(tokens)) {
305
+ return null;
306
+ }
307
+ const tokensObj = tokens;
308
+ // Primary format: analytics.tokens {input, output, total}
309
+ if (typeof tokensObj.input === "number" &&
310
+ typeof tokensObj.output === "number" &&
311
+ typeof tokensObj.total === "number") {
312
+ return {
313
+ input: tokensObj.input,
314
+ output: tokensObj.output,
315
+ total: tokensObj.total,
316
+ };
317
+ }
318
+ // Fallback format: tokenUsage {inputTokens, outputTokens, totalTokens}
319
+ if (typeof tokensObj.inputTokens === "number" &&
320
+ typeof tokensObj.outputTokens === "number" &&
321
+ typeof tokensObj.totalTokens === "number") {
322
+ return {
323
+ input: tokensObj.inputTokens,
324
+ output: tokensObj.outputTokens,
325
+ total: tokensObj.totalTokens,
326
+ };
327
+ }
328
+ return null;
284
329
  }
285
330
  // Helper method to format analytics for text mode display
286
331
  static formatAnalyticsForTextMode(result) {
@@ -299,10 +344,10 @@ export class CLICommandFactory {
299
344
  analyticsText += ` (${modelName})`;
300
345
  }
301
346
  analyticsText += "\n";
302
- // Token usage
303
- if (this.isValidTokenUsage(analytics.tokens)) {
304
- const tokens = analytics.tokens;
305
- analyticsText += ` Tokens: ${tokens.input} input + ${tokens.output} output = ${tokens.total} total\n`;
347
+ // Token usage with fallback handling
348
+ const normalizedTokens = this.normalizeTokenUsage(analytics.tokenUsage);
349
+ if (normalizedTokens) {
350
+ analyticsText += ` Tokens: ${normalizedTokens.input} input + ${normalizedTokens.output} output = ${normalizedTokens.total} total\n`;
306
351
  }
307
352
  // Cost information
308
353
  if (analytics.cost !== undefined &&
@@ -310,9 +355,12 @@ export class CLICommandFactory {
310
355
  typeof analytics.cost === "number") {
311
356
  analyticsText += ` Cost: $${analytics.cost.toFixed(5)}\n`;
312
357
  }
313
- // Response time
314
- if (analytics.responseTime && typeof analytics.responseTime === "number") {
315
- const timeInSeconds = (analytics.responseTime / 1000).toFixed(1);
358
+ // Response time with fallback handling for requestDuration vs responseTime
359
+ const duration = analytics.requestDuration ||
360
+ analytics.responseTime ||
361
+ analytics.duration;
362
+ if (duration && typeof duration === "number") {
363
+ const timeInSeconds = (duration / 1000).toFixed(1);
316
364
  analyticsText += ` Time: ${timeInSeconds}s\n`;
317
365
  }
318
366
  // Tools used
@@ -561,21 +609,21 @@ export class CLICommandFactory {
561
609
  provider: "google-ai",
562
610
  status: "working",
563
611
  configured: true,
564
- responseTime: 150,
612
+ requestDuration: 150,
565
613
  model: "gemini-2.5-flash",
566
614
  },
567
615
  {
568
616
  provider: "openai",
569
617
  status: "working",
570
618
  configured: true,
571
- responseTime: 200,
619
+ requestDuration: 200,
572
620
  model: "gpt-4o-mini",
573
621
  },
574
622
  {
575
623
  provider: "anthropic",
576
624
  status: "working",
577
625
  configured: true,
578
- responseTime: 180,
626
+ requestDuration: 180,
579
627
  model: "claude-3-haiku",
580
628
  },
581
629
  { provider: "bedrock", status: "not configured", configured: false },
@@ -591,7 +639,9 @@ export class CLICommandFactory {
591
639
  : result.status === "failed"
592
640
  ? chalk.red("❌ Failed")
593
641
  : chalk.gray("⚪ Not configured");
594
- const time = result.responseTime ? ` (${result.responseTime}ms)` : "";
642
+ const time = result.requestDuration
643
+ ? ` (${result.requestDuration}ms)`
644
+ : "";
595
645
  const model = result.model ? ` [${result.model}]` : "";
596
646
  logger.always(`${result.provider}: ${status}${time}${model}`);
597
647
  }
@@ -692,33 +742,31 @@ export class CLICommandFactory {
692
742
  provider: options.provider || "auto",
693
743
  model: options.model || "test-model",
694
744
  usage: {
695
- inputTokens: 10,
696
- outputTokens: 15,
697
- totalTokens: 25,
745
+ input: 10,
746
+ output: 15,
747
+ total: 25,
698
748
  },
699
749
  responseTime: 150,
700
750
  analytics: options.enableAnalytics
701
751
  ? {
702
752
  provider: options.provider || "auto",
703
753
  model: options.model || "test-model",
704
- tokens: { input: 10, output: 15, total: 25 },
754
+ tokenUsage: { input: 10, output: 15, total: 25 },
705
755
  cost: 0.00025,
706
- responseTime: 150,
756
+ requestDuration: 150,
707
757
  context: contextMetadata,
708
758
  }
709
759
  : undefined,
710
760
  evaluation: options.enableEvaluation
711
- ? {
761
+ ? normalizeEvaluationData({
712
762
  relevance: 8,
713
763
  accuracy: 9,
714
764
  completeness: 8,
715
765
  overall: 8.3,
716
- isOffTopic: false,
717
- alertSeverity: "none",
718
766
  reasoning: "Test evaluation response",
719
767
  evaluationModel: "test-evaluator",
720
768
  evaluationTime: 50,
721
- }
769
+ })
722
770
  : undefined,
723
771
  };
724
772
  if (spinner) {
@@ -732,7 +780,6 @@ export class CLICommandFactory {
732
780
  logger.debug("Mode: DRY-RUN (no actual API calls made)");
733
781
  }
734
782
  process.exit(0);
735
- return;
736
783
  }
737
784
  const sdk = new NeuroLink();
738
785
  if (options.debug) {
@@ -785,18 +832,36 @@ export class CLICommandFactory {
785
832
  if (spinner) {
786
833
  spinner.fail();
787
834
  }
788
- logger.error(chalk.red(`❌ Generation failed: ${error.message}`));
789
- if (options.debug) {
790
- logger.error(chalk.gray(error.stack));
791
- }
792
- process.exit(1);
835
+ handleError(error, "Generation");
793
836
  }
794
837
  }
795
838
  /**
796
- * Execute the stream command
839
+ * Log debug information for stream result
797
840
  */
798
- static async executeStream(argv) {
799
- // Handle stdin input if no input provided
841
+ static async logStreamDebugInfo(stream) {
842
+ logger.debug("\n" + chalk.yellow("Debug Information (Streaming):"));
843
+ logger.debug("Provider:", stream.provider);
844
+ logger.debug("Model:", stream.model);
845
+ if (stream.analytics) {
846
+ const resolvedAnalytics = await (stream.analytics instanceof Promise
847
+ ? stream.analytics
848
+ : Promise.resolve(stream.analytics));
849
+ logger.debug("Analytics:", JSON.stringify(resolvedAnalytics, null, 2));
850
+ }
851
+ if (stream.evaluation) {
852
+ const resolvedEvaluation = await (stream.evaluation instanceof Promise
853
+ ? stream.evaluation
854
+ : Promise.resolve(stream.evaluation));
855
+ logger.debug("Evaluation:", JSON.stringify(resolvedEvaluation, null, 2));
856
+ }
857
+ if (stream.metadata) {
858
+ logger.debug("Metadata:", JSON.stringify(stream.metadata, null, 2));
859
+ }
860
+ }
861
+ /**
862
+ * Handle stdin input for stream command
863
+ */
864
+ static async handleStdinInput(argv) {
800
865
  if (!argv.input && !process.stdin.isTTY) {
801
866
  let stdinData = "";
802
867
  process.stdin.setEncoding("utf8");
@@ -811,6 +876,12 @@ export class CLICommandFactory {
811
876
  else if (!argv.input) {
812
877
  throw new Error('Input required. Use: neurolink stream "your prompt" or echo "prompt" | neurolink stream');
813
878
  }
879
+ }
880
+ /**
881
+ * Execute the stream command
882
+ */
883
+ static async executeStream(argv) {
884
+ await this.handleStdinInput(argv);
814
885
  const options = this.processOptions(argv);
815
886
  if (!options.quiet) {
816
887
  logger.always(chalk.blue("🔄 Streaming..."));
@@ -873,11 +944,11 @@ export class CLICommandFactory {
873
944
  model: options.model || "test-model",
874
945
  requestDuration: 300,
875
946
  tokenUsage: {
876
- inputTokens: 10,
877
- outputTokens: 15,
878
- totalTokens: 25,
947
+ input: 10,
948
+ output: 15,
949
+ total: 25,
879
950
  },
880
- timestamp: Date.now(),
951
+ timestamp: new Date().toISOString(),
881
952
  context: contextMetadata,
882
953
  };
883
954
  const mockGenerateResult = {
@@ -911,7 +982,6 @@ export class CLICommandFactory {
911
982
  logger.debug("Mode: DRY-RUN (no actual API calls made)");
912
983
  }
913
984
  process.exit(0);
914
- return;
915
985
  }
916
986
  const sdk = new NeuroLink();
917
987
  const stream = await sdk.stream({
@@ -935,14 +1005,66 @@ export class CLICommandFactory {
935
1005
  : undefined,
936
1006
  });
937
1007
  let fullContent = "";
938
- // Process the stream
939
- for await (const chunk of stream.stream) {
940
- if (options.delay && options.delay > 0) {
941
- // Demo mode - add delay between chunks
942
- await new Promise((resolve) => setTimeout(resolve, options.delay));
1008
+ let contentReceived = false;
1009
+ const abortController = new AbortController();
1010
+ // Create timeout promise for stream consumption (30 seconds)
1011
+ const timeoutPromise = new Promise((_, reject) => {
1012
+ const timeoutId = setTimeout(() => {
1013
+ if (!contentReceived) {
1014
+ const timeoutError = new Error("\n❌ Stream timeout - no content received within 30 seconds\n" +
1015
+ "This usually indicates authentication or network issues\n\n" +
1016
+ "🔧 Try these steps:\n" +
1017
+ "1. Check your provider credentials are configured correctly\n" +
1018
+ `2. Test generate mode: neurolink generate "test" --provider ${options.provider}\n` +
1019
+ `3. Use debug mode: neurolink stream "test" --provider ${options.provider} --debug`);
1020
+ reject(timeoutError);
1021
+ }
1022
+ }, 30000);
1023
+ // Clean up timeout when aborted
1024
+ abortController.signal.addEventListener("abort", () => {
1025
+ clearTimeout(timeoutId);
1026
+ });
1027
+ });
1028
+ try {
1029
+ // Process the stream with timeout handling
1030
+ const streamIterator = stream.stream[Symbol.asyncIterator]();
1031
+ let timeoutActive = true;
1032
+ while (true) {
1033
+ let nextResult;
1034
+ if (timeoutActive && !contentReceived) {
1035
+ // Race between next chunk and timeout for first chunk only
1036
+ nextResult = await Promise.race([
1037
+ streamIterator.next(),
1038
+ timeoutPromise,
1039
+ ]);
1040
+ }
1041
+ else {
1042
+ // No timeout for subsequent chunks
1043
+ nextResult = await streamIterator.next();
1044
+ }
1045
+ if (nextResult.done) {
1046
+ break;
1047
+ }
1048
+ if (!contentReceived) {
1049
+ contentReceived = true;
1050
+ timeoutActive = false;
1051
+ abortController.abort(); // Cancel timeout
1052
+ }
1053
+ if (options.delay && options.delay > 0) {
1054
+ // Demo mode - add delay between chunks
1055
+ await new Promise((resolve) => setTimeout(resolve, options.delay));
1056
+ }
1057
+ process.stdout.write(nextResult.value.content);
1058
+ fullContent += nextResult.value.content;
943
1059
  }
944
- process.stdout.write(chunk.content);
945
- fullContent += chunk.content;
1060
+ }
1061
+ catch (error) {
1062
+ abortController.abort(); // Clean up timeout
1063
+ throw error;
1064
+ }
1065
+ if (!contentReceived) {
1066
+ throw new Error("\n❌ No content received from stream\n" +
1067
+ "Check your credentials and provider configuration");
946
1068
  }
947
1069
  if (!options.quiet) {
948
1070
  process.stdout.write("\n");
@@ -985,33 +1107,12 @@ export class CLICommandFactory {
985
1107
  }
986
1108
  // 🔧 NEW: Debug output for streaming (similar to generate command)
987
1109
  if (options.debug) {
988
- logger.debug("\n" + chalk.yellow("Debug Information (Streaming):"));
989
- logger.debug("Provider:", stream.provider);
990
- logger.debug("Model:", stream.model);
991
- if (stream.analytics) {
992
- const resolvedAnalytics = await (stream.analytics instanceof Promise
993
- ? stream.analytics
994
- : Promise.resolve(stream.analytics));
995
- logger.debug("Analytics:", JSON.stringify(resolvedAnalytics, null, 2));
996
- }
997
- if (stream.evaluation) {
998
- const resolvedEvaluation = await (stream.evaluation instanceof Promise
999
- ? stream.evaluation
1000
- : Promise.resolve(stream.evaluation));
1001
- logger.debug("Evaluation:", JSON.stringify(resolvedEvaluation, null, 2));
1002
- }
1003
- if (stream.metadata) {
1004
- logger.debug("Metadata:", JSON.stringify(stream.metadata, null, 2));
1005
- }
1110
+ await this.logStreamDebugInfo(stream);
1006
1111
  }
1007
1112
  process.exit(0);
1008
1113
  }
1009
1114
  catch (error) {
1010
- logger.error(chalk.red(`❌ Streaming failed: ${error.message}`));
1011
- if (options.debug) {
1012
- logger.error(chalk.gray(error.stack));
1013
- }
1014
- process.exit(1);
1115
+ handleError(error, "Streaming");
1015
1116
  }
1016
1117
  }
1017
1118
  /**
@@ -1125,11 +1226,7 @@ export class CLICommandFactory {
1125
1226
  if (spinner) {
1126
1227
  spinner.fail();
1127
1228
  }
1128
- logger.error(chalk.red(`❌ Batch processing failed: ${error.message}`));
1129
- if (options.debug) {
1130
- logger.error(chalk.gray(error.stack));
1131
- }
1132
- process.exit(1);
1229
+ handleError(error, "Batch processing");
1133
1230
  }
1134
1231
  }
1135
1232
  /**
@@ -1158,8 +1255,7 @@ export class CLICommandFactory {
1158
1255
  this.handleOutput(config, options);
1159
1256
  }
1160
1257
  catch (error) {
1161
- logger.error(chalk.red(`❌ Configuration export failed: ${error.message}`));
1162
- process.exit(1);
1258
+ handleError(error, "Configuration export");
1163
1259
  }
1164
1260
  }
1165
1261
  /**
@@ -1183,8 +1279,7 @@ export class CLICommandFactory {
1183
1279
  }
1184
1280
  }
1185
1281
  catch (error) {
1186
- logger.error(chalk.red(`❌ Provider selection failed: ${error.message}`));
1187
- process.exit(1);
1282
+ handleError(error, "Provider selection");
1188
1283
  }
1189
1284
  }
1190
1285
  /**
@@ -1323,8 +1418,7 @@ export class CLICommandFactory {
1323
1418
  }
1324
1419
  }
1325
1420
  catch (error) {
1326
- logger.error(chalk.red(`❌ Completion generation failed: ${error.message}`));
1327
- process.exit(1);
1421
+ handleError(error, "Completion generation");
1328
1422
  }
1329
1423
  }
1330
1424
  }
@@ -183,7 +183,9 @@ export class OllamaCommandFactory {
183
183
  logger.always(chalk.green(`\n${modelsData.models.length} models available`));
184
184
  }
185
185
  }
186
- catch (_error) {
186
+ catch (error) {
187
+ const errorMessage = error instanceof Error ? error.message : String(error);
188
+ logger.debug("Error:", errorMessage);
187
189
  spinner.fail("Ollama service is not running");
188
190
  logger.always(chalk.yellow("\nStart Ollama with: ollama serve"));
189
191
  logger.always(chalk.blue("Or restart the Ollama app if using the desktop version"));
@@ -309,9 +309,10 @@ export class SageMakerCommandFactory {
309
309
  logger.always(chalk.yellow("No SageMaker endpoints found"));
310
310
  }
311
311
  }
312
- catch (_awsError) {
312
+ catch (error) {
313
313
  spinner.fail("Failed to list endpoints");
314
- logger.error(chalk.red("AWS SDK credentials error or insufficient permissions"));
314
+ const errorMessage = error instanceof Error ? error.message : String(error);
315
+ logger.error(chalk.red("Error:", errorMessage));
315
316
  logger.always(chalk.yellow("\nTo list endpoints, please:"));
316
317
  logger.always("1. Set AWS_ACCESS_KEY_ID environment variable");
317
318
  logger.always("2. Set AWS_SECRET_ACCESS_KEY environment variable");
@@ -5,4 +5,4 @@
5
5
  * Professional CLI experience with minimal maintenance overhead.
6
6
  * Features: Spinners, colors, batch processing, provider testing, rich help
7
7
  */
8
- export {};
8
+ export declare function handleError(_error: Error, context: string): void;
package/dist/cli/index.js CHANGED
@@ -14,6 +14,14 @@ import { fileURLToPath } from "url";
14
14
  import { CLICommandFactory } from "./factories/commandFactory.js";
15
15
  import { AuthenticationError, AuthorizationError, NetworkError, RateLimitError, } from "../lib/types/errors.js";
16
16
  import { logger } from "../lib/utils/logger.js";
17
+ // Clean up pnpm-specific environment variables that cause npm warnings
18
+ // These variables are set by pnpm but cause "Unknown env config" warnings in npm
19
+ if (process.env.npm_config_verify_deps_before_run) {
20
+ delete process.env.npm_config_verify_deps_before_run;
21
+ }
22
+ if (process.env.npm_config__jsr_registry) {
23
+ delete process.env.npm_config__jsr_registry;
24
+ }
17
25
  // Get version from package.json
18
26
  const __filename = fileURLToPath(import.meta.url);
19
27
  const __dirname = path.dirname(__filename);
@@ -25,14 +33,14 @@ try {
25
33
  const { config } = await import("dotenv");
26
34
  config(); // Load .env from current working directory
27
35
  }
28
- catch (error) {
36
+ catch {
29
37
  // dotenv is not available (dev dependency only) - this is fine for production
30
38
  // Environment variables should be set externally in production
31
39
  }
32
40
  // Utility Functions (Simple, Zero Maintenance)
33
- function handleError(error, context) {
34
- logger.error(chalk.red(`❌ ${context} failed: ${error.message}`));
35
- if (error instanceof AuthenticationError) {
41
+ export function handleError(_error, context) {
42
+ logger.error(chalk.red(`❌ ${context} failed: ${_error.message}`));
43
+ if (_error instanceof AuthenticationError) {
36
44
  logger.error(chalk.yellow("💡 Set Google AI Studio API key (RECOMMENDED): export GOOGLE_AI_API_KEY=AIza-..."));
37
45
  logger.error(chalk.yellow("💡 Or set OpenAI API key: export OPENAI_API_KEY=sk-..."));
38
46
  logger.error(chalk.yellow("💡 Or set AWS Bedrock credentials: export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... AWS_REGION=us-east-1"));
@@ -40,14 +48,14 @@ function handleError(error, context) {
40
48
  logger.error(chalk.yellow("💡 Or set Anthropic API key: export ANTHROPIC_API_KEY=sk-ant-..."));
41
49
  logger.error(chalk.yellow("💡 Or set Azure OpenAI credentials: export AZURE_OPENAI_API_KEY=... AZURE_OPENAI_ENDPOINT=..."));
42
50
  }
43
- else if (error instanceof RateLimitError) {
51
+ else if (_error instanceof RateLimitError) {
44
52
  logger.error(chalk.yellow("💡 Try again in a few moments or use --provider vertex"));
45
53
  }
46
- else if (error instanceof AuthorizationError) {
54
+ else if (_error instanceof AuthorizationError) {
47
55
  logger.error(chalk.yellow("💡 Check your account permissions for the selected model/service."));
48
56
  logger.error(chalk.yellow("💡 For AWS Bedrock, ensure you have permissions for the specific model and consider using inference profile ARNs."));
49
57
  }
50
- else if (error instanceof NetworkError) {
58
+ else if (_error instanceof NetworkError) {
51
59
  logger.error(chalk.yellow("💡 Check your internet connection and the provider's status page."));
52
60
  }
53
61
  process.exit(1);
@@ -97,9 +105,9 @@ const cli = yargs(args)
97
105
  }
98
106
  };
99
107
  if (err) {
100
- // Error likely from an async command handler (e.g., via handleError)
101
- // handleError already prints and calls process.exit(1).
102
- // If we're here, it means handleError's process.exit might not have been caught by the top-level async IIFE.
108
+ // Error likely from an async command handler (e.g., via _handleError)
109
+ // _handleError already prints and calls process.exit(1).
110
+ // If we're here, it means _handleError's process.exit might not have been caught by the top-level async IIFE.
103
111
  // Or, it's a synchronous yargs error during parsing that yargs itself throws.
104
112
  const alreadyExitedByHandleError = err?.exitCode !== undefined;
105
113
  // A simple heuristic: if the error message doesn't look like one of our handled generic messages,
@@ -189,7 +197,7 @@ const cli = yargs(args)
189
197
  }
190
198
  catch (error) {
191
199
  // Global error handler - should not reach here due to fail() handler
192
- process.stderr.write(chalk.red(`Unexpected CLI error: ${error.message}\n`));
200
+ process.stderr.write(chalk.red(`Unexpected CLI _error: ${error.message}\n`));
193
201
  process.exit(1);
194
202
  }
195
203
  })();
@@ -61,7 +61,7 @@ export function parseEnvFile(content) {
61
61
  */
62
62
  export function generateEnvContent(envVars, existingContent) {
63
63
  const lines = [];
64
- const existingVars = existingContent ? parseEnvFile(existingContent) : {};
64
+ const _existingVars = existingContent ? parseEnvFile(existingContent) : {};
65
65
  const processedKeys = new Set();
66
66
  // If we have existing content, preserve its structure and comments
67
67
  if (existingContent) {
@@ -121,15 +121,15 @@ export function updateEnvFile(newVars, envPath = ".env", createBackup = true) {
121
121
  }
122
122
  // Read existing content
123
123
  let existingContent = "";
124
- let existingVars = {};
124
+ let _existingVars = {};
125
125
  if (fs.existsSync(envPath)) {
126
126
  existingContent = fs.readFileSync(envPath, "utf8");
127
- existingVars = parseEnvFile(existingContent);
127
+ _existingVars = parseEnvFile(existingContent);
128
128
  }
129
129
  // Categorize changes
130
130
  for (const [key, value] of Object.entries(newVars)) {
131
- if (Object.prototype.hasOwnProperty.call(existingVars, key)) {
132
- if (existingVars[key] !== value) {
131
+ if (Object.prototype.hasOwnProperty.call(_existingVars, key)) {
132
+ if (_existingVars[key] !== value) {
133
133
  result.updated.push(key);
134
134
  }
135
135
  else {
@@ -8,6 +8,18 @@ export declare class OllamaUtils {
8
8
  * Secure wrapper around spawnSync to prevent command injection.
9
9
  */
10
10
  static safeSpawn(command: AllowedCommand, args: string[], options?: SpawnSyncOptions): SpawnSyncReturns<string>;
11
+ /**
12
+ * Check if Ollama command line is available
13
+ */
14
+ private static isOllamaCommandReady;
15
+ /**
16
+ * Validate HTTP API response from Ollama
17
+ */
18
+ private static validateApiResponse;
19
+ /**
20
+ * Check if Ollama HTTP API is ready
21
+ */
22
+ private static isOllamaApiReady;
11
23
  /**
12
24
  * Wait for Ollama service to become ready with exponential backoff
13
25
  */