@juspay/neurolink 9.41.0 → 9.42.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 (189) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +7 -1
  3. package/dist/auth/anthropicOAuth.d.ts +18 -3
  4. package/dist/auth/anthropicOAuth.js +137 -4
  5. package/dist/auth/providers/firebase.js +5 -1
  6. package/dist/auth/providers/jwt.js +5 -1
  7. package/dist/auth/providers/workos.js +5 -1
  8. package/dist/auth/sessionManager.d.ts +1 -1
  9. package/dist/auth/sessionManager.js +58 -27
  10. package/dist/browser/neurolink.min.js +337 -318
  11. package/dist/cli/commands/mcp.js +3 -0
  12. package/dist/cli/commands/proxy.d.ts +2 -1
  13. package/dist/cli/commands/proxy.js +279 -16
  14. package/dist/cli/commands/task.js +3 -0
  15. package/dist/cli/factories/commandFactory.d.ts +2 -0
  16. package/dist/cli/factories/commandFactory.js +38 -0
  17. package/dist/cli/parser.js +4 -3
  18. package/dist/client/aiSdkAdapter.js +3 -0
  19. package/dist/client/streamingClient.js +30 -10
  20. package/dist/core/modules/GenerationHandler.js +3 -2
  21. package/dist/core/redisConversationMemoryManager.js +7 -3
  22. package/dist/evaluation/BatchEvaluator.js +4 -1
  23. package/dist/evaluation/hooks/observabilityHooks.js +5 -3
  24. package/dist/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  25. package/dist/evaluation/pipeline/evaluationPipeline.js +20 -8
  26. package/dist/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  27. package/dist/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  28. package/dist/lib/auth/anthropicOAuth.d.ts +18 -3
  29. package/dist/lib/auth/anthropicOAuth.js +137 -4
  30. package/dist/lib/auth/providers/firebase.js +5 -1
  31. package/dist/lib/auth/providers/jwt.js +5 -1
  32. package/dist/lib/auth/providers/workos.js +5 -1
  33. package/dist/lib/auth/sessionManager.d.ts +1 -1
  34. package/dist/lib/auth/sessionManager.js +58 -27
  35. package/dist/lib/client/aiSdkAdapter.js +3 -0
  36. package/dist/lib/client/streamingClient.js +30 -10
  37. package/dist/lib/core/modules/GenerationHandler.js +3 -2
  38. package/dist/lib/core/redisConversationMemoryManager.js +7 -3
  39. package/dist/lib/evaluation/BatchEvaluator.js +4 -1
  40. package/dist/lib/evaluation/hooks/observabilityHooks.js +5 -3
  41. package/dist/lib/evaluation/pipeline/evaluationPipeline.d.ts +3 -2
  42. package/dist/lib/evaluation/pipeline/evaluationPipeline.js +20 -8
  43. package/dist/lib/evaluation/pipeline/strategies/batchStrategy.js +6 -3
  44. package/dist/lib/evaluation/pipeline/strategies/samplingStrategy.js +18 -10
  45. package/dist/lib/neurolink.d.ts +3 -2
  46. package/dist/lib/neurolink.js +260 -494
  47. package/dist/lib/observability/otelBridge.d.ts +2 -2
  48. package/dist/lib/observability/otelBridge.js +12 -3
  49. package/dist/lib/providers/amazonBedrock.js +2 -4
  50. package/dist/lib/providers/anthropic.d.ts +9 -5
  51. package/dist/lib/providers/anthropic.js +19 -14
  52. package/dist/lib/providers/anthropicBaseProvider.d.ts +3 -3
  53. package/dist/lib/providers/anthropicBaseProvider.js +5 -4
  54. package/dist/lib/providers/azureOpenai.d.ts +1 -1
  55. package/dist/lib/providers/azureOpenai.js +5 -4
  56. package/dist/lib/providers/googleAiStudio.js +30 -1
  57. package/dist/lib/providers/googleVertex.js +28 -6
  58. package/dist/lib/providers/huggingFace.d.ts +3 -3
  59. package/dist/lib/providers/huggingFace.js +6 -8
  60. package/dist/lib/providers/litellm.js +41 -29
  61. package/dist/lib/providers/mistral.js +2 -1
  62. package/dist/lib/providers/ollama.js +80 -23
  63. package/dist/lib/providers/openAI.js +3 -2
  64. package/dist/lib/providers/openRouter.js +2 -1
  65. package/dist/lib/providers/openaiCompatible.d.ts +4 -4
  66. package/dist/lib/providers/openaiCompatible.js +4 -4
  67. package/dist/lib/proxy/claudeFormat.d.ts +3 -2
  68. package/dist/lib/proxy/claudeFormat.js +25 -20
  69. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  70. package/dist/lib/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  71. package/dist/lib/proxy/modelRouter.js +3 -0
  72. package/dist/lib/proxy/oauthFetch.d.ts +1 -1
  73. package/dist/lib/proxy/oauthFetch.js +65 -72
  74. package/dist/lib/proxy/proxyConfig.js +44 -24
  75. package/dist/lib/proxy/proxyEnv.d.ts +19 -0
  76. package/dist/lib/proxy/proxyEnv.js +73 -0
  77. package/dist/lib/proxy/proxyFetch.js +50 -4
  78. package/dist/lib/proxy/proxyTracer.d.ts +133 -0
  79. package/dist/lib/proxy/proxyTracer.js +645 -0
  80. package/dist/lib/proxy/rawStreamCapture.d.ts +10 -0
  81. package/dist/lib/proxy/rawStreamCapture.js +83 -0
  82. package/dist/lib/proxy/requestLogger.d.ts +32 -5
  83. package/dist/lib/proxy/requestLogger.js +406 -37
  84. package/dist/lib/proxy/sseInterceptor.d.ts +97 -0
  85. package/dist/lib/proxy/sseInterceptor.js +402 -0
  86. package/dist/lib/proxy/usageStats.d.ts +4 -3
  87. package/dist/lib/proxy/usageStats.js +25 -12
  88. package/dist/lib/rag/chunkers/MarkdownChunker.js +13 -5
  89. package/dist/lib/rag/chunking/markdownChunker.js +15 -6
  90. package/dist/lib/server/routes/claudeProxyRoutes.d.ts +7 -2
  91. package/dist/lib/server/routes/claudeProxyRoutes.js +1737 -508
  92. package/dist/lib/services/server/ai/observability/instrumentation.d.ts +7 -1
  93. package/dist/lib/services/server/ai/observability/instrumentation.js +240 -40
  94. package/dist/lib/tasks/backends/bullmqBackend.d.ts +1 -0
  95. package/dist/lib/tasks/backends/bullmqBackend.js +14 -7
  96. package/dist/lib/tasks/store/redisTaskStore.d.ts +1 -0
  97. package/dist/lib/tasks/store/redisTaskStore.js +34 -26
  98. package/dist/lib/tasks/taskManager.d.ts +3 -0
  99. package/dist/lib/tasks/taskManager.js +63 -30
  100. package/dist/lib/telemetry/index.d.ts +2 -1
  101. package/dist/lib/telemetry/index.js +2 -1
  102. package/dist/lib/telemetry/telemetryService.d.ts +3 -0
  103. package/dist/lib/telemetry/telemetryService.js +65 -5
  104. package/dist/lib/types/cli.d.ts +10 -0
  105. package/dist/lib/types/proxyTypes.d.ts +37 -5
  106. package/dist/lib/types/streamTypes.d.ts +25 -3
  107. package/dist/lib/utils/messageBuilder.js +3 -2
  108. package/dist/lib/utils/providerHealth.d.ts +18 -0
  109. package/dist/lib/utils/providerHealth.js +240 -9
  110. package/dist/lib/utils/providerUtils.js +14 -8
  111. package/dist/lib/utils/toolChoice.d.ts +4 -0
  112. package/dist/lib/utils/toolChoice.js +7 -0
  113. package/dist/neurolink.d.ts +3 -2
  114. package/dist/neurolink.js +260 -494
  115. package/dist/observability/otelBridge.d.ts +2 -2
  116. package/dist/observability/otelBridge.js +12 -3
  117. package/dist/providers/amazonBedrock.js +2 -4
  118. package/dist/providers/anthropic.d.ts +9 -5
  119. package/dist/providers/anthropic.js +19 -14
  120. package/dist/providers/anthropicBaseProvider.d.ts +3 -3
  121. package/dist/providers/anthropicBaseProvider.js +5 -4
  122. package/dist/providers/azureOpenai.d.ts +1 -1
  123. package/dist/providers/azureOpenai.js +5 -4
  124. package/dist/providers/googleAiStudio.js +30 -1
  125. package/dist/providers/googleVertex.js +28 -6
  126. package/dist/providers/huggingFace.d.ts +3 -3
  127. package/dist/providers/huggingFace.js +6 -7
  128. package/dist/providers/litellm.js +41 -29
  129. package/dist/providers/mistral.js +2 -1
  130. package/dist/providers/ollama.js +80 -23
  131. package/dist/providers/openAI.js +3 -2
  132. package/dist/providers/openRouter.js +2 -1
  133. package/dist/providers/openaiCompatible.d.ts +4 -4
  134. package/dist/providers/openaiCompatible.js +4 -3
  135. package/dist/proxy/claudeFormat.d.ts +3 -2
  136. package/dist/proxy/claudeFormat.js +25 -20
  137. package/dist/proxy/cloaking/plugins/sessionIdentity.d.ts +2 -6
  138. package/dist/proxy/cloaking/plugins/sessionIdentity.js +9 -33
  139. package/dist/proxy/modelRouter.js +3 -0
  140. package/dist/proxy/oauthFetch.d.ts +1 -1
  141. package/dist/proxy/oauthFetch.js +65 -72
  142. package/dist/proxy/proxyConfig.js +44 -24
  143. package/dist/proxy/proxyEnv.d.ts +19 -0
  144. package/dist/proxy/proxyEnv.js +72 -0
  145. package/dist/proxy/proxyFetch.js +50 -4
  146. package/dist/proxy/proxyTracer.d.ts +133 -0
  147. package/dist/proxy/proxyTracer.js +644 -0
  148. package/dist/proxy/rawStreamCapture.d.ts +10 -0
  149. package/dist/proxy/rawStreamCapture.js +82 -0
  150. package/dist/proxy/requestLogger.d.ts +32 -5
  151. package/dist/proxy/requestLogger.js +406 -37
  152. package/dist/proxy/sseInterceptor.d.ts +97 -0
  153. package/dist/proxy/sseInterceptor.js +401 -0
  154. package/dist/proxy/usageStats.d.ts +4 -3
  155. package/dist/proxy/usageStats.js +25 -12
  156. package/dist/rag/chunkers/MarkdownChunker.js +13 -5
  157. package/dist/rag/chunking/markdownChunker.js +15 -6
  158. package/dist/server/routes/claudeProxyRoutes.d.ts +7 -2
  159. package/dist/server/routes/claudeProxyRoutes.js +1737 -508
  160. package/dist/services/server/ai/observability/instrumentation.d.ts +7 -1
  161. package/dist/services/server/ai/observability/instrumentation.js +240 -40
  162. package/dist/tasks/backends/bullmqBackend.d.ts +1 -0
  163. package/dist/tasks/backends/bullmqBackend.js +14 -7
  164. package/dist/tasks/store/redisTaskStore.d.ts +1 -0
  165. package/dist/tasks/store/redisTaskStore.js +34 -26
  166. package/dist/tasks/taskManager.d.ts +3 -0
  167. package/dist/tasks/taskManager.js +63 -30
  168. package/dist/telemetry/index.d.ts +2 -1
  169. package/dist/telemetry/index.js +2 -1
  170. package/dist/telemetry/telemetryService.d.ts +3 -0
  171. package/dist/telemetry/telemetryService.js +65 -5
  172. package/dist/types/cli.d.ts +10 -0
  173. package/dist/types/proxyTypes.d.ts +37 -5
  174. package/dist/types/streamTypes.d.ts +25 -3
  175. package/dist/utils/messageBuilder.js +3 -2
  176. package/dist/utils/providerHealth.d.ts +18 -0
  177. package/dist/utils/providerHealth.js +240 -9
  178. package/dist/utils/providerUtils.js +14 -8
  179. package/dist/utils/toolChoice.d.ts +4 -0
  180. package/dist/utils/toolChoice.js +6 -0
  181. package/docs/assets/dashboards/neurolink-proxy-observability-dashboard.json +6609 -0
  182. package/docs/changelog.md +252 -0
  183. package/package.json +17 -1
  184. package/scripts/observability/check-proxy-telemetry.mjs +235 -0
  185. package/scripts/observability/docker-compose.proxy-observability.yaml +55 -0
  186. package/scripts/observability/import-openobserve-dashboard.mjs +240 -0
  187. package/scripts/observability/manage-local-openobserve.sh +184 -0
  188. package/scripts/observability/otel-collector.proxy-observability.yaml +78 -0
  189. package/scripts/observability/proxy-observability.env.example +23 -0
@@ -228,7 +228,8 @@ export class ProviderHealthChecker {
228
228
  }
229
229
  // Providers that don't use API keys directly
230
230
  if (providerName === AIProviderName.OLLAMA ||
231
- providerName === AIProviderName.BEDROCK) {
231
+ providerName === AIProviderName.BEDROCK ||
232
+ providerName === AIProviderName.LITELLM) {
232
233
  healthStatus.hasApiKey = true;
233
234
  return;
234
235
  }
@@ -368,6 +369,8 @@ export class ProviderHealthChecker {
368
369
  return [];
369
370
  case AIProviderName.AZURE:
370
371
  return ["AZURE_OPENAI_API_KEY", "AZURE_OPENAI_ENDPOINT"];
372
+ case AIProviderName.LITELLM:
373
+ return [];
371
374
  case AIProviderName.OLLAMA:
372
375
  return []; // Ollama typically doesn't require API keys
373
376
  default:
@@ -391,8 +394,10 @@ export class ProviderHealthChecker {
391
394
  return "AWS_ACCESS_KEY_ID";
392
395
  case AIProviderName.AZURE:
393
396
  return "AZURE_OPENAI_API_KEY";
397
+ case AIProviderName.LITELLM:
398
+ return "LITELLM_API_KEY";
394
399
  case AIProviderName.OLLAMA:
395
- return "OLLAMA_API_BASE";
400
+ return "OLLAMA_BASE_URL";
396
401
  default:
397
402
  return "";
398
403
  }
@@ -416,6 +421,8 @@ export class ProviderHealthChecker {
416
421
  return apiKey.length >= API_KEY_LENGTHS.AWS_ACCESS_KEY; // AWS access key length
417
422
  case AIProviderName.AZURE:
418
423
  return apiKey.length >= API_KEY_LENGTHS.AZURE_MIN; // Azure OpenAI API key length
424
+ case AIProviderName.LITELLM:
425
+ return apiKey.length > 0;
419
426
  case AIProviderName.OLLAMA:
420
427
  return true; // Ollama usually doesn't require specific format
421
428
  default:
@@ -437,8 +444,10 @@ export class ProviderHealthChecker {
437
444
  return null; // Complex authentication required
438
445
  case AIProviderName.BEDROCK:
439
446
  return null; // AWS endpoints vary by region
447
+ case AIProviderName.LITELLM:
448
+ return this.getLiteLLMModelsUrl();
440
449
  case AIProviderName.OLLAMA:
441
- return "http://localhost:11434/api/version";
450
+ return this.getOllamaTagsUrl();
442
451
  default:
443
452
  return null;
444
453
  }
@@ -457,6 +466,9 @@ export class ProviderHealthChecker {
457
466
  case AIProviderName.AZURE:
458
467
  await this.checkAzureConfig(healthStatus);
459
468
  break;
469
+ case AIProviderName.LITELLM:
470
+ await this.checkLiteLLMConfig(healthStatus);
471
+ break;
460
472
  case AIProviderName.OLLAMA:
461
473
  await this.checkOllamaConfig(healthStatus);
462
474
  break;
@@ -648,15 +660,177 @@ export class ProviderHealthChecker {
648
660
  healthStatus.recommendations.push("Set one of: AZURE_OPENAI_MODEL, AZURE_OPENAI_DEPLOYMENT, or AZURE_OPENAI_DEPLOYMENT_ID");
649
661
  }
650
662
  }
663
+ static getLiteLLMBaseUrl() {
664
+ return process.env.LITELLM_BASE_URL || "http://localhost:4000";
665
+ }
666
+ static getLiteLLMModelsUrl() {
667
+ return new URL("/v1/models", this.getLiteLLMBaseUrl()).toString();
668
+ }
669
+ static getConfiguredLiteLLMModel() {
670
+ return process.env.LITELLM_MODEL || "openai/gpt-4o-mini";
671
+ }
672
+ static getOllamaBaseUrl() {
673
+ return (process.env.OLLAMA_BASE_URL ||
674
+ process.env.OLLAMA_API_BASE ||
675
+ "http://localhost:11434");
676
+ }
677
+ static getOllamaTagsUrl() {
678
+ return new URL("/api/tags", this.getOllamaBaseUrl()).toString();
679
+ }
680
+ static getConfiguredOllamaModel() {
681
+ return process.env.OLLAMA_MODEL || "llama3.1:8b";
682
+ }
683
+ static async fetchJsonWithTimeout(url, options = {}) {
684
+ const controller = new AbortController();
685
+ const timeoutId = setTimeout(() => controller.abort(), options.timeout ?? this.DEFAULT_TIMEOUT);
686
+ try {
687
+ const proxyFetch = createProxyFetch();
688
+ const response = await proxyFetch(url, {
689
+ method: "GET",
690
+ headers: options.headers,
691
+ signal: controller.signal,
692
+ });
693
+ if (!response.ok) {
694
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
695
+ }
696
+ return await response.json();
697
+ }
698
+ finally {
699
+ clearTimeout(timeoutId);
700
+ }
701
+ }
702
+ static normalizeModelList(models) {
703
+ return models
704
+ .map((entry) => {
705
+ if (typeof entry === "string") {
706
+ return entry;
707
+ }
708
+ if (entry &&
709
+ typeof entry === "object" &&
710
+ "id" in entry &&
711
+ typeof entry.id === "string") {
712
+ return entry.id;
713
+ }
714
+ if (entry &&
715
+ typeof entry === "object" &&
716
+ "name" in entry &&
717
+ typeof entry.name === "string") {
718
+ return entry.name;
719
+ }
720
+ return null;
721
+ })
722
+ .filter((model) => typeof model === "string");
723
+ }
724
+ static hasRequestedModel(availableModels, requestedModel) {
725
+ return availableModels.some((model) => model === requestedModel ||
726
+ model.startsWith(`${requestedModel}:`) ||
727
+ requestedModel.startsWith(`${model}:`));
728
+ }
729
+ static async getOllamaAvailableModels(timeout = 2000) {
730
+ const payload = (await this.fetchJsonWithTimeout(this.getOllamaTagsUrl(), {
731
+ timeout,
732
+ }));
733
+ return this.normalizeModelList(payload.models ?? []);
734
+ }
735
+ static async getLiteLLMAvailableModels(timeout = 2000) {
736
+ const payload = (await this.fetchJsonWithTimeout(this.getLiteLLMModelsUrl(), {
737
+ timeout,
738
+ headers: {
739
+ Authorization: `Bearer ${process.env.LITELLM_API_KEY || "sk-anything"}`,
740
+ "Content-Type": "application/json",
741
+ },
742
+ }));
743
+ return this.normalizeModelList(payload.data ?? []);
744
+ }
745
+ static async checkOllamaAvailability(options) {
746
+ try {
747
+ const models = await this.getOllamaAvailableModels(options.timeout);
748
+ if (!this.hasRequestedModel(models, options.model)) {
749
+ return {
750
+ available: false,
751
+ reason: `Configured Ollama model '${options.model}' is not installed`,
752
+ models,
753
+ };
754
+ }
755
+ return { available: true, models };
756
+ }
757
+ catch (error) {
758
+ return {
759
+ available: false,
760
+ reason: error instanceof Error ? error.message : String(error),
761
+ models: [],
762
+ };
763
+ }
764
+ }
765
+ static async checkLiteLLMAvailability(options) {
766
+ try {
767
+ const models = await this.getLiteLLMAvailableModels(options.timeout);
768
+ if (models.length === 0) {
769
+ return {
770
+ available: false,
771
+ reason: "LiteLLM returned an empty model list",
772
+ models,
773
+ };
774
+ }
775
+ if (!this.hasRequestedModel(models, options.model)) {
776
+ return {
777
+ available: false,
778
+ reason: `Configured LiteLLM model '${options.model}' is not exposed by the proxy`,
779
+ models,
780
+ };
781
+ }
782
+ return { available: true, models };
783
+ }
784
+ catch (error) {
785
+ return {
786
+ available: false,
787
+ reason: error instanceof Error ? error.message : String(error),
788
+ models: [],
789
+ };
790
+ }
791
+ }
792
+ static async checkLiteLLMConfig(healthStatus) {
793
+ const liteLLMBase = this.getLiteLLMBaseUrl();
794
+ if (!liteLLMBase.startsWith("http")) {
795
+ healthStatus.isConfigured = false;
796
+ healthStatus.configurationIssues.push("Invalid LITELLM_BASE_URL format");
797
+ healthStatus.recommendations.push("Set LITELLM_BASE_URL to a valid URL (e.g., http://localhost:4000)");
798
+ return;
799
+ }
800
+ const availability = await this.checkLiteLLMAvailability({
801
+ model: this.getConfiguredLiteLLMModel(),
802
+ timeout: 2000,
803
+ });
804
+ if (!availability.available) {
805
+ healthStatus.isConfigured = false;
806
+ healthStatus.configurationIssues.push(`LiteLLM runtime check failed: ${availability.reason ?? "unknown error"}`);
807
+ healthStatus.recommendations.push("Start the LiteLLM proxy and ensure the configured model is available from /v1/models");
808
+ return;
809
+ }
810
+ healthStatus.isConfigured = true;
811
+ }
651
812
  /**
652
813
  * Check Ollama configuration
653
814
  */
654
815
  static async checkOllamaConfig(healthStatus) {
655
- const ollamaBase = process.env.OLLAMA_API_BASE || "http://localhost:11434";
816
+ const ollamaBase = this.getOllamaBaseUrl();
656
817
  if (!ollamaBase.startsWith("http")) {
657
- healthStatus.configurationIssues.push("Invalid OLLAMA_API_BASE format");
658
- healthStatus.recommendations.push("Set OLLAMA_API_BASE to a valid URL (e.g., http://localhost:11434)");
818
+ healthStatus.isConfigured = false;
819
+ healthStatus.configurationIssues.push("Invalid OLLAMA_BASE_URL format (OLLAMA_API_BASE is still accepted as a legacy alias)");
820
+ healthStatus.recommendations.push("Set OLLAMA_BASE_URL to a valid URL (e.g., http://localhost:11434). OLLAMA_API_BASE remains supported as a legacy alias.");
821
+ return;
659
822
  }
823
+ const availability = await this.checkOllamaAvailability({
824
+ model: this.getConfiguredOllamaModel(),
825
+ timeout: 2000,
826
+ });
827
+ if (!availability.available) {
828
+ healthStatus.isConfigured = false;
829
+ healthStatus.configurationIssues.push(`Ollama runtime check failed: ${availability.reason ?? "unknown error"}`);
830
+ healthStatus.recommendations.push("Start Ollama and install the configured model before using Ollama as a fallback provider");
831
+ return;
832
+ }
833
+ healthStatus.isConfigured = true;
660
834
  }
661
835
  /**
662
836
  * Get common models for a provider
@@ -703,8 +877,21 @@ export class ProviderHealthChecker {
703
877
  return [BedrockModels.CLAUDE_3_SONNET, BedrockModels.CLAUDE_3_HAIKU];
704
878
  case AIProviderName.AZURE:
705
879
  return [OpenAIModels.GPT_4O, OpenAIModels.GPT_4O_MINI, "gpt-35-turbo"];
706
- case AIProviderName.OLLAMA:
707
- return ["llama3.2:latest", "llama3.1:latest", "mistral:latest"];
880
+ case AIProviderName.LITELLM:
881
+ return [
882
+ "openai/gpt-4o-mini",
883
+ "anthropic/claude-3-haiku",
884
+ "google/gemini-2.5-flash",
885
+ ];
886
+ case AIProviderName.OLLAMA: {
887
+ const envModel = process.env.OLLAMA_MODEL;
888
+ const defaults = [
889
+ "llama3.2:latest",
890
+ "llama3.1:latest",
891
+ "mistral:latest",
892
+ ];
893
+ return envModel ? [envModel, ...defaults] : defaults;
894
+ }
708
895
  default:
709
896
  return [];
710
897
  }
@@ -1139,18 +1326,61 @@ export class ProviderHealthChecker {
1139
1326
  this.consecutiveFailures.clear();
1140
1327
  }
1141
1328
  }
1329
+ static async checkFallbackProviderAvailability(providerName, model) {
1330
+ const provider = providerName;
1331
+ if (provider === AIProviderName.OLLAMA) {
1332
+ const availability = await this.checkOllamaAvailability({
1333
+ model,
1334
+ timeout: 2000,
1335
+ });
1336
+ return {
1337
+ available: availability.available,
1338
+ reason: availability.reason,
1339
+ };
1340
+ }
1341
+ if (provider === AIProviderName.LITELLM) {
1342
+ const availability = await this.checkLiteLLMAvailability({
1343
+ model,
1344
+ timeout: 2000,
1345
+ });
1346
+ return {
1347
+ available: availability.available,
1348
+ reason: availability.reason,
1349
+ };
1350
+ }
1351
+ try {
1352
+ const health = await this.checkProviderHealth(provider, {
1353
+ includeConnectivityTest: false,
1354
+ cacheResults: true,
1355
+ maxCacheAge: 15_000,
1356
+ timeout: 2000,
1357
+ });
1358
+ return {
1359
+ available: health.isHealthy,
1360
+ reason: health.error || health.configurationIssues[0] || health.warning,
1361
+ };
1362
+ }
1363
+ catch (error) {
1364
+ return {
1365
+ available: false,
1366
+ reason: error instanceof Error ? error.message : String(error),
1367
+ };
1368
+ }
1369
+ }
1142
1370
  /**
1143
1371
  * Get the best healthy provider from a list of options (NON-BLOCKING)
1144
1372
  * Prioritizes healthy providers over configured but unhealthy ones
1145
1373
  * Uses fast, cached health checks to avoid blocking initialization
1146
1374
  */
1147
1375
  static async getBestHealthyProvider(preferredProviders = [
1376
+ "litellm",
1377
+ "ollama",
1148
1378
  "openai",
1149
1379
  "anthropic",
1150
1380
  "vertex",
1381
+ "google-ai",
1151
1382
  "bedrock",
1152
1383
  "azure",
1153
- "google-ai",
1154
1384
  ]) {
1155
1385
  const healthStatuses = await this.checkAllProvidersHealth({
1156
1386
  includeConnectivityTest: false, // Quick config check only
@@ -1191,6 +1421,7 @@ export class ProviderHealthChecker {
1191
1421
  AIProviderName.OPENAI,
1192
1422
  AIProviderName.BEDROCK,
1193
1423
  AIProviderName.AZURE,
1424
+ AIProviderName.LITELLM,
1194
1425
  AIProviderName.OLLAMA,
1195
1426
  ];
1196
1427
  const healthChecks = providers.map((provider) => this.checkProviderHealth(provider, options));
@@ -63,15 +63,18 @@ export async function getBestProvider(requestedProvider) {
63
63
  }
64
64
  /**
65
65
  * Provider priority order rationale:
66
- * - Vertex (Google Cloud AI) is prioritized first for its enterprise-grade reliability and advanced model capabilities.
67
- * - Google AI follows as second priority for comprehensive Google AI ecosystem support.
66
+ * - LiteLLM and Ollama are prioritized first for local/self-hosted deployments,
67
+ * avoiding cloud quota/rate-limit issues during fallback scenarios.
68
+ * - Vertex (Google Cloud AI) follows for enterprise-grade reliability.
69
+ * - Google AI follows as second cloud priority for comprehensive Google AI ecosystem support.
68
70
  * - OpenAI maintains high priority due to its consistent reliability and broad model support.
69
- * - Other providers are ordered based on a combination of reliability, feature set, and historical performance in our use cases.
70
- * - Ollama is kept as a fallback for local deployments when available.
71
+ * - Other providers are ordered based on a combination of reliability, feature set, and historical performance.
71
72
  * Please update this comment if the order is changed in the future, and document the rationale for maintainability.
72
73
  */
73
74
  const providers = [
74
- "vertex", // Prioritize Google Cloud AI (Vertex) first
75
+ "litellm", // Prioritize self-hosted/proxy (no rate limits)
76
+ "ollama", // Local models (no rate limits)
77
+ "vertex", // Google Cloud AI (enterprise)
75
78
  "google-ai", // Google AI ecosystem support
76
79
  "openai", // Reliable with broad model support
77
80
  "anthropic",
@@ -79,7 +82,6 @@ export async function getBestProvider(requestedProvider) {
79
82
  "azure",
80
83
  "mistral",
81
84
  "huggingface",
82
- "ollama", // Keep as fallback
83
85
  ];
84
86
  for (const provider of providers) {
85
87
  if (await isProviderAvailable(provider)) {
@@ -107,8 +109,11 @@ async function isProviderAvailable(providerName) {
107
109
  });
108
110
  if (response.ok) {
109
111
  const { models } = await response.json();
110
- const defaultOllamaModel = "llama3.2:latest";
111
- return models.some((m) => m.name === defaultOllamaModel);
112
+ const defaultOllamaModel = process.env.OLLAMA_MODEL || "llama3.1:8b";
113
+ // Check for exact match first, then prefix match (e.g. "gemma3:27b" matches "gemma3:27b-fp16")
114
+ return models.some((m) => m.name === defaultOllamaModel ||
115
+ (typeof m.name === "string" &&
116
+ m.name.startsWith(defaultOllamaModel.split(":")[0] + ":")));
112
117
  }
113
118
  return false;
114
119
  }
@@ -414,6 +419,7 @@ export function getAvailableProviders() {
414
419
  "anthropic",
415
420
  "azure",
416
421
  "google-ai",
422
+ "litellm",
417
423
  "huggingface",
418
424
  "ollama",
419
425
  "mistral",
@@ -0,0 +1,4 @@
1
+ import type { Tool, ToolChoice } from "ai";
2
+ export declare function resolveToolChoice(options: {
3
+ toolChoice?: ToolChoice<Record<string, Tool>>;
4
+ }, tools: Record<string, Tool> | undefined, shouldUseTools: boolean): ToolChoice<Record<string, Tool>> | "none";
@@ -0,0 +1,7 @@
1
+ export function resolveToolChoice(options, tools, shouldUseTools) {
2
+ if (!shouldUseTools || !tools || Object.keys(tools).length === 0) {
3
+ return "none";
4
+ }
5
+ return options.toolChoice ?? "auto";
6
+ }
7
+ //# sourceMappingURL=toolChoice.js.map
@@ -13,8 +13,9 @@ import type { MCPToolAnnotations } from "./mcp/toolAnnotations.js";
13
13
  import { MCPToolRegistry } from "./mcp/toolRegistry.js";
14
14
  import type { MetricsSummary, TraceView } from "./observability/metricsAggregator.js";
15
15
  import type { SpanData } from "./observability/types/spanTypes.js";
16
- import type { JsonObject, NeuroLinkEvents, TypedEventEmitter } from "./types/common.js";
16
+ import { TaskManager } from "./tasks/taskManager.js";
17
17
  import type { AuthenticatedContext, MastraAuthProvider } from "./types/authTypes.js";
18
+ import type { JsonObject, NeuroLinkEvents, TypedEventEmitter } from "./types/common.js";
18
19
  import type { MCPEnhancementsConfig, NeuroLinkAuthConfig, NeurolinkConstructorConfig } from "./types/configTypes.js";
19
20
  import type { ChatMessage } from "./types/conversation.js";
20
21
  import type { ExternalMCPOperationResult, ExternalMCPServerInstance, ExternalMCPToolInfo } from "./types/externalMcp.js";
@@ -25,7 +26,6 @@ import type { ObservabilityConfig } from "./types/observability.js";
25
26
  import type { StreamOptions, StreamResult } from "./types/streamTypes.js";
26
27
  import type { ToolExecutionContext, ToolExecutionSummary, ToolInfo, ToolRegistrationOptions } from "./types/tools.js";
27
28
  import type { BatchOperationResult } from "./types/typeAliases.js";
28
- import { TaskManager } from "./tasks/taskManager.js";
29
29
  export declare class NeuroLink {
30
30
  private mcpInitialized;
31
31
  private mcpSkipped;
@@ -1909,6 +1909,7 @@ export declare class NeuroLink {
1909
1909
  * @param config - Auth provider or configuration to create one
1910
1910
  */
1911
1911
  setAuthProvider(config: NeuroLinkAuthConfig): Promise<void>;
1912
+ private initializeAuthProviderFromConfig;
1912
1913
  /**
1913
1914
  * Get the currently configured authentication provider
1914
1915
  */