@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 +6 -0
- package/dist/adapters/providerImageAdapter.js +32 -3
- package/dist/lib/adapters/providerImageAdapter.js +32 -3
- package/dist/lib/providers/googleAiStudio.js +1 -3
- package/dist/lib/providers/googleVertex.js +1 -3
- package/dist/providers/googleAiStudio.js +1 -3
- package/dist/providers/googleVertex.js +1 -3
- package/package.json +1 -1
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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",
|