@juspay/neurolink 9.22.0 → 9.22.2

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,15 @@
1
+ ## [9.22.2](https://github.com/juspay/neurolink/compare/v9.22.1...v9.22.2) (2026-03-12)
2
+
3
+ ### Bug Fixes
4
+
5
+ - **(observability):** prevent duplicate Langfuse traces from streaming by restricting trace attributes to root spans ([ddac782](https://github.com/juspay/neurolink/commit/ddac78229f7ed42a1d332c23e0a5e6d80418dd6a))
6
+
7
+ ## [9.22.1](https://github.com/juspay/neurolink/compare/v9.22.0...v9.22.1) (2026-03-12)
8
+
9
+ ### Bug Fixes
10
+
11
+ - **(vision):** allow unknown models for proxy providers in vision check ([b2c5b4e](https://github.com/juspay/neurolink/commit/b2c5b4edebd43545dee8ccb31cb5253302602936))
12
+
1
13
  ## [9.22.0](https://github.com/juspay/neurolink/compare/v9.21.0...v9.22.0) (2026-03-12)
2
14
 
3
15
  ### 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;
@@ -19,6 +19,7 @@ import { recordProviderPerformanceFromMetrics } from "../evaluationProviders.js"
19
19
  import { modelConfig } from "../modelConfiguration.js";
20
20
  import { TelemetryService } from "../../telemetry/telemetryService.js";
21
21
  import { calculateCost, hasPricing } from "../../utils/pricing.js";
22
+ import { getLangfuseContext } from "../../services/server/ai/observability/instrumentation.js";
22
23
  /**
23
24
  * TelemetryHandler class - Handles analytics and telemetry for AI providers
24
25
  */
@@ -143,8 +144,9 @@ export class TelemetryHandler {
143
144
  return undefined;
144
145
  }
145
146
  const context = options.context;
146
- const traceName = context?.traceName;
147
- const userId = context?.userId;
147
+ const langfuseContext = getLangfuseContext();
148
+ const traceName = context?.traceName ?? langfuseContext?.traceName;
149
+ const userId = context?.userId ?? langfuseContext?.userId;
148
150
  const functionId = traceName ? traceName : userId ? userId : "guest";
149
151
  const metadata = {
150
152
  ...(context?.metadata || {}),
@@ -168,7 +170,7 @@ export class TelemetryHandler {
168
170
  isEnabled: true,
169
171
  functionId,
170
172
  metadata,
171
- recordInputs: process.env.NEUROLINK_RECORD_INPUTS?.toLowerCase() === "true",
173
+ recordInputs: process.env.NEUROLINK_RECORD_INPUTS?.toLowerCase() !== "false",
172
174
  recordOutputs: true,
173
175
  };
174
176
  }
@@ -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;
@@ -19,6 +19,7 @@ import { recordProviderPerformanceFromMetrics } from "../evaluationProviders.js"
19
19
  import { modelConfig } from "../modelConfiguration.js";
20
20
  import { TelemetryService } from "../../telemetry/telemetryService.js";
21
21
  import { calculateCost, hasPricing } from "../../utils/pricing.js";
22
+ import { getLangfuseContext } from "../../services/server/ai/observability/instrumentation.js";
22
23
  /**
23
24
  * TelemetryHandler class - Handles analytics and telemetry for AI providers
24
25
  */
@@ -143,8 +144,9 @@ export class TelemetryHandler {
143
144
  return undefined;
144
145
  }
145
146
  const context = options.context;
146
- const traceName = context?.traceName;
147
- const userId = context?.userId;
147
+ const langfuseContext = getLangfuseContext();
148
+ const traceName = context?.traceName ?? langfuseContext?.traceName;
149
+ const userId = context?.userId ?? langfuseContext?.userId;
148
150
  const functionId = traceName ? traceName : userId ? userId : "guest";
149
151
  const metadata = {
150
152
  ...(context?.metadata || {}),
@@ -168,7 +170,7 @@ export class TelemetryHandler {
168
170
  isEnabled: true,
169
171
  functionId,
170
172
  metadata,
171
- recordInputs: process.env.NEUROLINK_RECORD_INPUTS?.toLowerCase() === "true",
173
+ recordInputs: process.env.NEUROLINK_RECORD_INPUTS?.toLowerCase() !== "false",
172
174
  recordOutputs: true,
173
175
  };
174
176
  }
@@ -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
@@ -81,7 +81,7 @@ class ContextEnricher {
81
81
  * operations here so we can update the trace name in onEnd().
82
82
  */
83
83
  detectedOperations = new Map();
84
- onStart(span) {
84
+ onStart(span, parentContext) {
85
85
  const context = contextStorage.getStore();
86
86
  const userId = context?.userId ?? currentConfig?.userId ?? "guest";
87
87
  const sessionId = context?.sessionId ?? currentConfig?.sessionId;
@@ -140,10 +140,10 @@ class ContextEnricher {
140
140
  if (context?.requestId) {
141
141
  span.setAttribute("request.id", context.requestId);
142
142
  }
143
- // Set trace name for Langfuse (using proper Langfuse attribute)
144
- if (traceName) {
143
+ const isRootSpan = !trace.getSpan(parentContext);
144
+ if (traceName && isRootSpan) {
145
145
  span.setAttribute("langfuse.trace.name", traceName);
146
- span.setAttribute("trace.name", traceName); // Keep for compatibility
146
+ span.setAttribute("trace.name", traceName);
147
147
  }
148
148
  // Set operation name as separate attribute for filtering/analytics
149
149
  if (operationName) {
@@ -158,14 +158,16 @@ class ContextEnricher {
158
158
  if (typeof value === "string" ||
159
159
  typeof value === "number" ||
160
160
  typeof value === "boolean") {
161
- span.setAttribute(`metadata.${key}`, value);
161
+ if (metadata && isRootSpan) {
162
+ span.setAttribute("langfuse.trace.metadata", JSON.stringify(metadata));
163
+ }
162
164
  }
163
165
  else if (Array.isArray(value) &&
164
166
  value.every((v) => typeof v === "string" ||
165
167
  typeof v === "number" ||
166
168
  typeof v === "boolean")) {
167
169
  // OTEL supports homogeneous arrays of primitives
168
- span.setAttribute(`metadata.${key}`, value);
170
+ span.setAttribute(`metadata.${key}`, JSON.stringify(value));
169
171
  }
170
172
  else {
171
173
  // Fall back to JSON string for complex types
@@ -18,29 +18,29 @@ declare const MODEL_CONFIGS: {
18
18
  };
19
19
  readonly fallback: {
20
20
  readonly provider: "vertex";
21
- readonly model: "gemini-2.5-pro";
21
+ readonly model: "claude-haiku-4-5@20251001";
22
22
  readonly capabilities: readonly ["speed", "general", "basic-reasoning"];
23
23
  readonly avgResponseTime: 1200;
24
24
  readonly costPerToken: 0.0002;
25
- readonly reasoning: "Vertex AI Gemini Pro fallback";
25
+ readonly reasoning: "Vertex AI Claude Haiku fallback";
26
26
  };
27
27
  };
28
28
  readonly reasoning: {
29
29
  readonly primary: {
30
30
  readonly provider: "vertex";
31
- readonly model: "claude-sonnet-4@20250514";
31
+ readonly model: "claude-sonnet-4-5@20250929";
32
32
  readonly capabilities: readonly ["reasoning", "analysis", "complex-logic", "code", "creativity"];
33
33
  readonly avgResponseTime: 3000;
34
34
  readonly costPerToken: 0.003;
35
- readonly reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI";
35
+ readonly reasoning: "Advanced reasoning and analysis via Claude Sonnet 4-5 on Vertex AI";
36
36
  };
37
37
  readonly fallback: {
38
38
  readonly provider: "vertex";
39
- readonly model: "claude-opus-4@20250514";
39
+ readonly model: "claude-opus-4-5@20251101";
40
40
  readonly capabilities: readonly ["reasoning", "analysis", "complex-logic", "code", "creativity", "agentic"];
41
41
  readonly avgResponseTime: 4000;
42
42
  readonly costPerToken: 0.005;
43
- readonly reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks";
43
+ readonly reasoning: "Claude Opus 4-5 fallback on Vertex AI for most complex tasks";
44
44
  };
45
45
  };
46
46
  };
@@ -22,23 +22,23 @@ const MODEL_CONFIGS = {
22
22
  provider: "vertex",
23
23
  model: "gemini-2.5-flash",
24
24
  capabilities: ["speed", "general", "code", "basic-reasoning"],
25
- avgResponseTime: 800, // ms
25
+ avgResponseTime: 800,
26
26
  costPerToken: 0.0001,
27
27
  reasoning: "Optimized for speed and efficiency via Vertex AI",
28
28
  },
29
29
  fallback: {
30
30
  provider: "vertex",
31
- model: "gemini-2.5-pro",
31
+ model: "claude-haiku-4-5@20251001",
32
32
  capabilities: ["speed", "general", "basic-reasoning"],
33
33
  avgResponseTime: 1200,
34
34
  costPerToken: 0.0002,
35
- reasoning: "Vertex AI Gemini Pro fallback",
35
+ reasoning: "Vertex AI Claude Haiku fallback",
36
36
  },
37
37
  },
38
38
  reasoning: {
39
39
  primary: {
40
40
  provider: "vertex",
41
- model: "claude-sonnet-4@20250514",
41
+ model: "claude-sonnet-4-5@20250929",
42
42
  capabilities: [
43
43
  "reasoning",
44
44
  "analysis",
@@ -46,13 +46,13 @@ const MODEL_CONFIGS = {
46
46
  "code",
47
47
  "creativity",
48
48
  ],
49
- avgResponseTime: 3000, // ms
49
+ avgResponseTime: 3000,
50
50
  costPerToken: 0.003,
51
- reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI",
51
+ reasoning: "Advanced reasoning and analysis via Claude Sonnet 4-5 on Vertex AI",
52
52
  },
53
53
  fallback: {
54
54
  provider: "vertex",
55
- model: "claude-opus-4@20250514",
55
+ model: "claude-opus-4-5@20251101",
56
56
  capabilities: [
57
57
  "reasoning",
58
58
  "analysis",
@@ -63,7 +63,7 @@ const MODEL_CONFIGS = {
63
63
  ],
64
64
  avgResponseTime: 4000,
65
65
  costPerToken: 0.005,
66
- reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks",
66
+ reasoning: "Claude Opus 4-5 fallback on Vertex AI for most complex tasks",
67
67
  },
68
68
  },
69
69
  };
@@ -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
@@ -81,7 +81,7 @@ class ContextEnricher {
81
81
  * operations here so we can update the trace name in onEnd().
82
82
  */
83
83
  detectedOperations = new Map();
84
- onStart(span) {
84
+ onStart(span, parentContext) {
85
85
  const context = contextStorage.getStore();
86
86
  const userId = context?.userId ?? currentConfig?.userId ?? "guest";
87
87
  const sessionId = context?.sessionId ?? currentConfig?.sessionId;
@@ -140,10 +140,10 @@ class ContextEnricher {
140
140
  if (context?.requestId) {
141
141
  span.setAttribute("request.id", context.requestId);
142
142
  }
143
- // Set trace name for Langfuse (using proper Langfuse attribute)
144
- if (traceName) {
143
+ const isRootSpan = !trace.getSpan(parentContext);
144
+ if (traceName && isRootSpan) {
145
145
  span.setAttribute("langfuse.trace.name", traceName);
146
- span.setAttribute("trace.name", traceName); // Keep for compatibility
146
+ span.setAttribute("trace.name", traceName);
147
147
  }
148
148
  // Set operation name as separate attribute for filtering/analytics
149
149
  if (operationName) {
@@ -158,14 +158,16 @@ class ContextEnricher {
158
158
  if (typeof value === "string" ||
159
159
  typeof value === "number" ||
160
160
  typeof value === "boolean") {
161
- span.setAttribute(`metadata.${key}`, value);
161
+ if (metadata && isRootSpan) {
162
+ span.setAttribute("langfuse.trace.metadata", JSON.stringify(metadata));
163
+ }
162
164
  }
163
165
  else if (Array.isArray(value) &&
164
166
  value.every((v) => typeof v === "string" ||
165
167
  typeof v === "number" ||
166
168
  typeof v === "boolean")) {
167
169
  // OTEL supports homogeneous arrays of primitives
168
- span.setAttribute(`metadata.${key}`, value);
170
+ span.setAttribute(`metadata.${key}`, JSON.stringify(value));
169
171
  }
170
172
  else {
171
173
  // Fall back to JSON string for complex types
@@ -18,29 +18,29 @@ declare const MODEL_CONFIGS: {
18
18
  };
19
19
  readonly fallback: {
20
20
  readonly provider: "vertex";
21
- readonly model: "gemini-2.5-pro";
21
+ readonly model: "claude-haiku-4-5@20251001";
22
22
  readonly capabilities: readonly ["speed", "general", "basic-reasoning"];
23
23
  readonly avgResponseTime: 1200;
24
24
  readonly costPerToken: 0.0002;
25
- readonly reasoning: "Vertex AI Gemini Pro fallback";
25
+ readonly reasoning: "Vertex AI Claude Haiku fallback";
26
26
  };
27
27
  };
28
28
  readonly reasoning: {
29
29
  readonly primary: {
30
30
  readonly provider: "vertex";
31
- readonly model: "claude-sonnet-4@20250514";
31
+ readonly model: "claude-sonnet-4-5@20250929";
32
32
  readonly capabilities: readonly ["reasoning", "analysis", "complex-logic", "code", "creativity"];
33
33
  readonly avgResponseTime: 3000;
34
34
  readonly costPerToken: 0.003;
35
- readonly reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI";
35
+ readonly reasoning: "Advanced reasoning and analysis via Claude Sonnet 4-5 on Vertex AI";
36
36
  };
37
37
  readonly fallback: {
38
38
  readonly provider: "vertex";
39
- readonly model: "claude-opus-4@20250514";
39
+ readonly model: "claude-opus-4-5@20251101";
40
40
  readonly capabilities: readonly ["reasoning", "analysis", "complex-logic", "code", "creativity", "agentic"];
41
41
  readonly avgResponseTime: 4000;
42
42
  readonly costPerToken: 0.005;
43
- readonly reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks";
43
+ readonly reasoning: "Claude Opus 4-5 fallback on Vertex AI for most complex tasks";
44
44
  };
45
45
  };
46
46
  };
@@ -22,23 +22,23 @@ const MODEL_CONFIGS = {
22
22
  provider: "vertex",
23
23
  model: "gemini-2.5-flash",
24
24
  capabilities: ["speed", "general", "code", "basic-reasoning"],
25
- avgResponseTime: 800, // ms
25
+ avgResponseTime: 800,
26
26
  costPerToken: 0.0001,
27
27
  reasoning: "Optimized for speed and efficiency via Vertex AI",
28
28
  },
29
29
  fallback: {
30
30
  provider: "vertex",
31
- model: "gemini-2.5-pro",
31
+ model: "claude-haiku-4-5@20251001",
32
32
  capabilities: ["speed", "general", "basic-reasoning"],
33
33
  avgResponseTime: 1200,
34
34
  costPerToken: 0.0002,
35
- reasoning: "Vertex AI Gemini Pro fallback",
35
+ reasoning: "Vertex AI Claude Haiku fallback",
36
36
  },
37
37
  },
38
38
  reasoning: {
39
39
  primary: {
40
40
  provider: "vertex",
41
- model: "claude-sonnet-4@20250514",
41
+ model: "claude-sonnet-4-5@20250929",
42
42
  capabilities: [
43
43
  "reasoning",
44
44
  "analysis",
@@ -46,13 +46,13 @@ const MODEL_CONFIGS = {
46
46
  "code",
47
47
  "creativity",
48
48
  ],
49
- avgResponseTime: 3000, // ms
49
+ avgResponseTime: 3000,
50
50
  costPerToken: 0.003,
51
- reasoning: "Advanced reasoning and analysis via Claude Sonnet 4 on Vertex AI",
51
+ reasoning: "Advanced reasoning and analysis via Claude Sonnet 4-5 on Vertex AI",
52
52
  },
53
53
  fallback: {
54
54
  provider: "vertex",
55
- model: "claude-opus-4@20250514",
55
+ model: "claude-opus-4-5@20251101",
56
56
  capabilities: [
57
57
  "reasoning",
58
58
  "analysis",
@@ -63,7 +63,7 @@ const MODEL_CONFIGS = {
63
63
  ],
64
64
  avgResponseTime: 4000,
65
65
  costPerToken: 0.005,
66
- reasoning: "Claude Opus 4 fallback on Vertex AI for most complex tasks",
66
+ reasoning: "Claude Opus 4-5 fallback on Vertex AI for most complex tasks",
67
67
  },
68
68
  },
69
69
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "9.22.0",
3
+ "version": "9.22.2",
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",