@juspay/neurolink 9.22.0 → 9.22.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## [9.22.1](https://github.com/juspay/neurolink/compare/v9.22.0...v9.22.1) (2026-03-12)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **(vision):** allow unknown models for proxy providers in vision check ([b2c5b4e](https://github.com/juspay/neurolink/commit/b2c5b4edebd43545dee8ccb31cb5253302602936))
6
+
1
7
  ## [9.22.0](https://github.com/juspay/neurolink/compare/v9.21.0...v9.22.0) (2026-03-12)
2
8
 
3
9
  ### Features
@@ -39,6 +39,24 @@ const IMAGE_LIMITS = {
39
39
  bedrock: 20, // Same as Anthropic for Claude models on Bedrock
40
40
  openrouter: 10, // Conservative limit, routes to various underlying providers
41
41
  };
42
+ /**
43
+ * Proxy providers that route to arbitrary underlying models.
44
+ * Vision capability cannot be statically determined for these — pass requests
45
+ * through and let the underlying provider surface errors if needed.
46
+ */
47
+ const PROXY_PROVIDERS = new Set(["litellm", "openrouter"]);
48
+ /**
49
+ * Normalize provider name/alias to its canonical form for vision checks.
50
+ */
51
+ function normalizeVisionProvider(provider) {
52
+ const lower = provider.toLowerCase();
53
+ switch (lower) {
54
+ case "or":
55
+ return "openrouter";
56
+ default:
57
+ return lower;
58
+ }
59
+ }
42
60
  /**
43
61
  * Vision capability definitions for each provider
44
62
  */
@@ -645,13 +663,18 @@ export class ProviderImageAdapter {
645
663
  * Validate that provider and model support vision
646
664
  */
647
665
  static validateVisionSupport(provider, model) {
648
- const normalizedProvider = provider.toLowerCase();
666
+ const normalizedProvider = normalizeVisionProvider(provider);
649
667
  const supportedModels = VISION_CAPABILITIES[normalizedProvider];
650
668
  if (!supportedModels) {
651
669
  throw new Error(`Provider ${provider} does not support vision processing. ` +
652
670
  `Supported providers: ${Object.keys(VISION_CAPABILITIES).join(", ")}`);
653
671
  }
654
672
  const isSupported = supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
673
+ // Proxy providers route to arbitrary underlying models — skip the allowlist
674
+ // check for unknown models and let the underlying provider error if needed.
675
+ if (!isSupported && PROXY_PROVIDERS.has(normalizedProvider)) {
676
+ return;
677
+ }
655
678
  if (!isSupported) {
656
679
  throw new Error(`Provider ${provider} with model ${model} does not support vision processing. ` +
657
680
  `Supported models for ${provider}: ${supportedModels.join(", ")}`);
@@ -692,7 +715,7 @@ export class ProviderImageAdapter {
692
715
  */
693
716
  static supportsVision(provider, model) {
694
717
  try {
695
- const normalizedProvider = provider.toLowerCase();
718
+ const normalizedProvider = normalizeVisionProvider(provider);
696
719
  const supportedModels = VISION_CAPABILITIES[normalizedProvider];
697
720
  if (!supportedModels) {
698
721
  return false;
@@ -700,7 +723,13 @@ export class ProviderImageAdapter {
700
723
  if (!model) {
701
724
  return true; // Provider supports vision, but need to check specific model
702
725
  }
703
- return supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
726
+ const modelMatched = supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
727
+ // Proxy providers route to arbitrary underlying models — pass through if
728
+ // the model isn't in the known allowlist.
729
+ if (!modelMatched && PROXY_PROVIDERS.has(normalizedProvider)) {
730
+ return true;
731
+ }
732
+ return modelMatched;
704
733
  }
705
734
  catch {
706
735
  return false;
@@ -39,6 +39,24 @@ const IMAGE_LIMITS = {
39
39
  bedrock: 20, // Same as Anthropic for Claude models on Bedrock
40
40
  openrouter: 10, // Conservative limit, routes to various underlying providers
41
41
  };
42
+ /**
43
+ * Proxy providers that route to arbitrary underlying models.
44
+ * Vision capability cannot be statically determined for these — pass requests
45
+ * through and let the underlying provider surface errors if needed.
46
+ */
47
+ const PROXY_PROVIDERS = new Set(["litellm", "openrouter"]);
48
+ /**
49
+ * Normalize provider name/alias to its canonical form for vision checks.
50
+ */
51
+ function normalizeVisionProvider(provider) {
52
+ const lower = provider.toLowerCase();
53
+ switch (lower) {
54
+ case "or":
55
+ return "openrouter";
56
+ default:
57
+ return lower;
58
+ }
59
+ }
42
60
  /**
43
61
  * Vision capability definitions for each provider
44
62
  */
@@ -645,13 +663,18 @@ export class ProviderImageAdapter {
645
663
  * Validate that provider and model support vision
646
664
  */
647
665
  static validateVisionSupport(provider, model) {
648
- const normalizedProvider = provider.toLowerCase();
666
+ const normalizedProvider = normalizeVisionProvider(provider);
649
667
  const supportedModels = VISION_CAPABILITIES[normalizedProvider];
650
668
  if (!supportedModels) {
651
669
  throw new Error(`Provider ${provider} does not support vision processing. ` +
652
670
  `Supported providers: ${Object.keys(VISION_CAPABILITIES).join(", ")}`);
653
671
  }
654
672
  const isSupported = supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
673
+ // Proxy providers route to arbitrary underlying models — skip the allowlist
674
+ // check for unknown models and let the underlying provider error if needed.
675
+ if (!isSupported && PROXY_PROVIDERS.has(normalizedProvider)) {
676
+ return;
677
+ }
655
678
  if (!isSupported) {
656
679
  throw new Error(`Provider ${provider} with model ${model} does not support vision processing. ` +
657
680
  `Supported models for ${provider}: ${supportedModels.join(", ")}`);
@@ -692,7 +715,7 @@ export class ProviderImageAdapter {
692
715
  */
693
716
  static supportsVision(provider, model) {
694
717
  try {
695
- const normalizedProvider = provider.toLowerCase();
718
+ const normalizedProvider = normalizeVisionProvider(provider);
696
719
  const supportedModels = VISION_CAPABILITIES[normalizedProvider];
697
720
  if (!supportedModels) {
698
721
  return false;
@@ -700,7 +723,13 @@ export class ProviderImageAdapter {
700
723
  if (!model) {
701
724
  return true; // Provider supports vision, but need to check specific model
702
725
  }
703
- return supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
726
+ const modelMatched = supportedModels.some((supportedModel) => model.toLowerCase().includes(supportedModel.toLowerCase()));
727
+ // Proxy providers route to arbitrary underlying models — pass through if
728
+ // the model isn't in the known allowlist.
729
+ if (!modelMatched && PROXY_PROVIDERS.has(normalizedProvider)) {
730
+ return true;
731
+ }
732
+ return modelMatched;
704
733
  }
705
734
  catch {
706
735
  return false;
@@ -464,9 +464,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
464
464
  logger.warn(`[GoogleAIStudio] Dropped ${sanitized.dropped.length} incompatible tool(s): ${sanitized.dropped.join(", ")}`);
465
465
  }
466
466
  tools =
467
- Object.keys(sanitized.tools).length > 0
468
- ? sanitized.tools
469
- : undefined;
467
+ Object.keys(sanitized.tools).length > 0 ? sanitized.tools : undefined;
470
468
  }
471
469
  else {
472
470
  tools = undefined;
@@ -831,9 +831,7 @@ export class GoogleVertexProvider extends BaseProvider {
831
831
  logger.warn(`[GoogleVertex] Dropped ${sanitized.dropped.length} incompatible tool(s): ${sanitized.dropped.join(", ")}`);
832
832
  }
833
833
  tools =
834
- Object.keys(sanitized.tools).length > 0
835
- ? sanitized.tools
836
- : undefined;
834
+ Object.keys(sanitized.tools).length > 0 ? sanitized.tools : undefined;
837
835
  }
838
836
  else if (isAnthropic && Object.keys(rawTools).length > 0) {
839
837
  // Anthropic models don't need Gemini sanitization — pass tools through
@@ -464,9 +464,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
464
464
  logger.warn(`[GoogleAIStudio] Dropped ${sanitized.dropped.length} incompatible tool(s): ${sanitized.dropped.join(", ")}`);
465
465
  }
466
466
  tools =
467
- Object.keys(sanitized.tools).length > 0
468
- ? sanitized.tools
469
- : undefined;
467
+ Object.keys(sanitized.tools).length > 0 ? sanitized.tools : undefined;
470
468
  }
471
469
  else {
472
470
  tools = undefined;
@@ -831,9 +831,7 @@ export class GoogleVertexProvider extends BaseProvider {
831
831
  logger.warn(`[GoogleVertex] Dropped ${sanitized.dropped.length} incompatible tool(s): ${sanitized.dropped.join(", ")}`);
832
832
  }
833
833
  tools =
834
- Object.keys(sanitized.tools).length > 0
835
- ? sanitized.tools
836
- : undefined;
834
+ Object.keys(sanitized.tools).length > 0 ? sanitized.tools : undefined;
837
835
  }
838
836
  else if (isAnthropic && Object.keys(rawTools).length > 0) {
839
837
  // Anthropic models don't need Gemini sanitization — pass tools through
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "9.22.0",
3
+ "version": "9.22.1",
4
4
  "description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 13 providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
5
5
  "author": {
6
6
  "name": "Juspay Technologies",