@juspay/neurolink 12.12.2 → 12.12.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.
@@ -118,6 +118,10 @@ export const textGenerationOptionsSchema = {
118
118
  type: "boolean",
119
119
  description: "Disable tool result caching for this request (overrides global mcp.cache.enabled).",
120
120
  },
121
+ disableInternalFallback: {
122
+ type: "boolean",
123
+ description: "Own fallback order yourself: skip NeuroLink's provider-priority walk and the catalog model fallback, so an invalid model or unavailable provider surfaces as its own error.",
124
+ },
121
125
  disableToolCallRepair: {
122
126
  type: "boolean",
123
127
  description: "Disable the schema-driven tool call repair mechanism (near-miss tool names, mis-typed arguments). Repair is enabled by default.",
@@ -1299,11 +1299,10 @@ export class BaseProvider {
1299
1299
  const otelSpanState = { ended: false };
1300
1300
  return await context.with(activeCtx, async () => this.runGenerateInActiveContext(options, startTime, otelSpan, otelSpanState));
1301
1301
  };
1302
- // TextGenerationOptions does not declare the flag (it lives on
1303
- // StreamOptions), but callers that own fallback order pass it on both
1304
- // paths, so honour it here as well.
1305
- const callerOwnsFallback = "disableInternalFallback" in options &&
1306
- options.disableInternalFallback === true;
1302
+ // Callers that own fallback order (providerFallback / modelChain callers,
1303
+ // or a router that retries on its own) pass the flag on both paths;
1304
+ // TextGenerationOptions declares it, so a plain read is enough here.
1305
+ const callerOwnsFallback = options.disableInternalFallback === true;
1307
1306
  return await this.runGenerateWithModelFallback(attempt, callerOwnsFallback);
1308
1307
  }
1309
1308
  /**
package/dist/neurolink.js CHANGED
@@ -4121,6 +4121,11 @@ Current user's request: ${currentInput}`;
4121
4121
  disableTools: options.disableTools,
4122
4122
  toolFilter: options.toolFilter,
4123
4123
  excludeTools: options.excludeTools,
4124
+ // This explicit field list is the only road into the provider, so a
4125
+ // flag left out here never reaches BaseProvider — which is exactly how
4126
+ // disableInternalFallback was dropped on generate() while stream()
4127
+ // (which spreads its options) honoured it.
4128
+ disableInternalFallback: options.disableInternalFallback,
4124
4129
  maxSteps: options.maxSteps,
4125
4130
  toolChoice: options.toolChoice,
4126
4131
  prepareStep: options.prepareStep,
@@ -5930,11 +5935,23 @@ Current user's request: ${currentInput}`;
5930
5935
  : requestedProvider
5931
5936
  ? [requestedProvider]
5932
5937
  : providerPriority;
5938
+ // The caller owns fallback order (a providerFallback / modelChain caller,
5939
+ // or a router that retries on its own): bound the walk to its first
5940
+ // candidate so an unavailable provider surfaces as its own error instead
5941
+ // of a silent switch. An explicit provider is already a one-element
5942
+ // list; this only changes the "auto" and orchestrated-preference walks.
5943
+ const providersToTry = options.disableInternalFallback === true
5944
+ ? tryProviders.slice(0, 1)
5945
+ : tryProviders;
5946
+ // Caller-owned fallback never enters tryProviders: providerFallback and
5947
+ // modelChain are walked by runWithFallbackOrchestration around the public
5948
+ // generate() call, and a configured ModelPool is consumed by the block
5949
+ // above. Slicing here therefore never clips a caller's own list.
5933
5950
  logger.debug(`[${functionTag}] Starting direct generation`, {
5934
5951
  requestedProvider: requestedProvider || "auto",
5935
5952
  preferredOrchestrated: preferredOrchestrated || "none",
5936
- tryProviders,
5937
- allowFallback: !requestedProvider || !!preferredOrchestrated,
5953
+ tryProviders: providersToTry,
5954
+ allowFallback: providersToTry.length > 1,
5938
5955
  });
5939
5956
  // ─── ModelPool path ──────────────────────────────────────────────────────
5940
5957
  // When a ModelPool is configured, source the candidate sequence from the
@@ -6080,7 +6097,7 @@ Current user's request: ${currentInput}`;
6080
6097
  // ─── End ModelPool path ───────────────────────────────────────────────────
6081
6098
  let lastError = null;
6082
6099
  // Try each provider in order
6083
- for (const providerName of tryProviders) {
6100
+ for (const providerName of providersToTry) {
6084
6101
  if (options.abortSignal?.aborted) {
6085
6102
  throw new DOMException("The operation was aborted", "AbortError");
6086
6103
  }
@@ -6437,7 +6454,7 @@ Current user's request: ${currentInput}`;
6437
6454
  // All providers failed
6438
6455
  const responseTime = Date.now() - startTime;
6439
6456
  logger.error(`[${functionTag}] All providers failed`, {
6440
- triedProviders: tryProviders,
6457
+ triedProviders: providersToTry,
6441
6458
  lastError: lastError?.message,
6442
6459
  responseTime,
6443
6460
  });
@@ -459,6 +459,19 @@ export type GenerateOptions = {
459
459
  skipToolPromptInjection?: boolean;
460
460
  /** Disable tool result caching for this request (overrides global mcp.cache.enabled) */
461
461
  disableToolCache?: boolean;
462
+ /**
463
+ * Disable NeuroLink's internal fallback for this request: the static
464
+ * provider-priority walk that runs when no provider was requested, and the
465
+ * catalog model-fallback walk a provider performs when its model is
466
+ * rejected as invalid. Callers that own fallback order (a caller-supplied
467
+ * `providerFallback` / `modelChain`, or a router that retries on its own,
468
+ * as the Claude proxy does for its streams) set this so an invalid model
469
+ * or an unavailable provider surfaces as exactly that.
470
+ * A configured `ModelPool`, `providerFallback` and `modelChain` are the
471
+ * caller's own fallback and are unaffected. Mirrors the same flag on
472
+ * `StreamOptions`.
473
+ */
474
+ disableInternalFallback?: boolean;
462
475
  /** Maximum number of tool execution steps (default: 200) */
463
476
  maxSteps?: number;
464
477
  /**
@@ -1204,6 +1217,14 @@ export type TextGenerationOptions = {
1204
1217
  excludeTools?: string[];
1205
1218
  /** Disable tool result caching for this request (overrides global mcp.cache.enabled) */
1206
1219
  disableToolCache?: boolean;
1220
+ /**
1221
+ * Caller owns fallback order. Read in two places: `directProviderGeneration`
1222
+ * bounds its static provider-priority walk to one candidate, and
1223
+ * `BaseProvider.generate()` skips the catalog model-fallback walk so an
1224
+ * invalid-model error surfaces as itself. Mapped from
1225
+ * `GenerateOptions.disableInternalFallback`.
1226
+ */
1227
+ disableInternalFallback?: boolean;
1207
1228
  /**
1208
1229
  * Tool choice configuration for the generation.
1209
1230
  * Controls whether and which tools the model must call.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.12.2",
3
+ "version": "12.12.3",
4
4
  "packageManager": "pnpm@10.15.1",
5
5
  "description": "TypeScript AI SDK with 24+ LLM providers behind one consistent API. MCP-native (connect any MCP server), voice TTS/STT/realtime, RAG, agents, memory, context compaction. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · DeepSeek · NVIDIA NIM and more.",
6
6
  "author": {