@juspay/neurolink 10.8.4 → 10.8.6
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 +8 -0
- package/dist/browser/neurolink.min.js +497 -478
- package/dist/factories/providerRegistry.js +11 -11
- package/dist/lib/factories/providerRegistry.js +11 -11
- package/dist/lib/providers/{amazonBedrock.d.ts → amazonBedrock/client.d.ts} +4 -4
- package/dist/{providers/amazonBedrock.js → lib/providers/amazonBedrock/client.js} +15 -18
- package/dist/lib/providers/amazonBedrock/constants.d.ts +1 -0
- package/dist/lib/providers/amazonBedrock/constants.js +3 -0
- package/dist/lib/providers/amazonBedrock/index.d.ts +3 -0
- package/dist/lib/providers/amazonBedrock/index.js +4 -0
- package/dist/lib/providers/amazonBedrock/utils.d.ts +1 -0
- package/dist/lib/providers/amazonBedrock/utils.js +4 -0
- package/dist/{providers/anthropic.d.ts → lib/providers/anthropic/client.d.ts} +6 -21
- package/dist/{providers/anthropic.js → lib/providers/anthropic/client.js} +28 -45
- package/dist/lib/providers/anthropic/constants.d.ts +4 -0
- package/dist/lib/providers/anthropic/constants.js +9 -0
- package/dist/lib/providers/anthropic/index.d.ts +3 -0
- package/dist/lib/providers/anthropic/index.js +4 -0
- package/dist/lib/providers/anthropic/utils.d.ts +7 -0
- package/dist/lib/providers/anthropic/utils.js +150 -0
- package/dist/lib/providers/{googleAiStudio.d.ts → googleAiStudio/client.d.ts} +4 -4
- package/dist/{providers/googleAiStudio.js → lib/providers/googleAiStudio/client.js} +16 -15
- package/dist/lib/providers/googleAiStudio/index.d.ts +2 -0
- package/dist/lib/providers/googleAiStudio/index.js +3 -0
- package/dist/lib/providers/googleAiStudio/utils.d.ts +2 -0
- package/dist/lib/providers/googleAiStudio/utils.js +19 -0
- package/dist/lib/providers/googleNativeGemini3/constants.d.ts +1 -0
- package/dist/lib/providers/googleNativeGemini3/constants.js +2 -0
- package/dist/lib/providers/googleNativeGemini3/index.d.ts +2 -0
- package/dist/lib/providers/googleNativeGemini3/index.js +3 -0
- package/dist/lib/providers/{googleNativeGemini3.d.ts → googleNativeGemini3/utils.d.ts} +2 -2
- package/dist/lib/providers/{googleNativeGemini3.js → googleNativeGemini3/utils.js} +8 -8
- package/dist/{providers/googleVertex.d.ts → lib/providers/googleVertex/client.d.ts} +4 -4
- package/dist/lib/providers/{googleVertex.js → googleVertex/client.js} +32 -32
- package/dist/lib/providers/googleVertex/constants.d.ts +5 -0
- package/dist/lib/providers/googleVertex/constants.js +27 -0
- package/dist/lib/providers/googleVertex/index.d.ts +3 -0
- package/dist/lib/providers/googleVertex/index.js +4 -0
- package/dist/lib/providers/googleVertex/utils.d.ts +12 -0
- package/dist/lib/providers/googleVertex/utils.js +287 -0
- package/dist/lib/providers/{huggingFace.d.ts → huggingFace/client.d.ts} +3 -3
- package/dist/lib/providers/{huggingFace.js → huggingFace/client.js} +7 -7
- package/dist/lib/providers/huggingFace/index.d.ts +2 -0
- package/dist/lib/providers/huggingFace/index.js +3 -0
- package/dist/lib/providers/huggingFace/utils.d.ts +2 -0
- package/dist/lib/providers/huggingFace/utils.js +8 -0
- package/dist/lib/providers/index.d.ts +10 -10
- package/dist/lib/providers/index.js +10 -10
- package/dist/{providers/litellm.d.ts → lib/providers/litellm/client.d.ts} +3 -3
- package/dist/lib/providers/{litellm.js → litellm/client.js} +13 -13
- package/dist/lib/providers/litellm/constants.d.ts +1 -0
- package/dist/lib/providers/litellm/constants.js +3 -0
- package/dist/lib/providers/litellm/index.d.ts +3 -0
- package/dist/lib/providers/litellm/index.js +4 -0
- package/dist/lib/providers/litellm/utils.d.ts +5 -0
- package/dist/lib/providers/litellm/utils.js +11 -0
- package/dist/{providers/nvidiaNim.d.ts → lib/providers/nvidiaNim/client.d.ts} +3 -3
- package/dist/lib/providers/{nvidiaNim.js → nvidiaNim/client.js} +8 -8
- package/dist/lib/providers/nvidiaNim/constants.d.ts +1 -0
- package/dist/lib/providers/nvidiaNim/constants.js +2 -0
- package/dist/lib/providers/nvidiaNim/index.d.ts +3 -0
- package/dist/lib/providers/nvidiaNim/index.js +4 -0
- package/dist/lib/providers/nvidiaNim/utils.d.ts +9 -0
- package/dist/lib/providers/nvidiaNim/utils.js +101 -0
- package/dist/{providers/ollama.d.ts → lib/providers/ollama/client.d.ts} +3 -3
- package/dist/{providers/ollama.js → lib/providers/ollama/client.js} +10 -13
- package/dist/lib/providers/ollama/constants.d.ts +4 -0
- package/dist/lib/providers/ollama/constants.js +6 -0
- package/dist/lib/providers/ollama/index.d.ts +3 -0
- package/dist/lib/providers/ollama/index.js +4 -0
- package/dist/lib/providers/ollama/utils.d.ts +8 -0
- package/dist/lib/providers/ollama/utils.js +43 -0
- package/dist/lib/providers/{openAI.d.ts → openAI/client.d.ts} +3 -3
- package/dist/lib/providers/{openAI.js → openAI/client.js} +13 -13
- package/dist/lib/providers/openAI/constants.d.ts +1 -0
- package/dist/lib/providers/openAI/constants.js +3 -0
- package/dist/lib/providers/openAI/index.d.ts +3 -0
- package/dist/lib/providers/openAI/index.js +4 -0
- package/dist/lib/providers/openAI/utils.d.ts +2 -0
- package/dist/lib/providers/openAI/utils.js +8 -0
- package/dist/lib/providers/{openRouter.d.ts → openRouter/client.d.ts} +3 -3
- package/dist/{providers/openRouter.js → lib/providers/openRouter/client.js} +13 -29
- package/dist/lib/providers/openRouter/constants.d.ts +1 -0
- package/dist/lib/providers/openRouter/constants.js +2 -0
- package/dist/lib/providers/openRouter/index.d.ts +3 -0
- package/dist/lib/providers/openRouter/index.js +4 -0
- package/dist/lib/providers/openRouter/utils.d.ts +3 -0
- package/dist/lib/providers/openRouter/utils.js +18 -0
- package/dist/lib/providers/{openaiCompatible.d.ts → openaiCompatible/client.d.ts} +2 -2
- package/dist/{providers/openaiCompatible.js → lib/providers/openaiCompatible/client.js} +8 -22
- package/dist/lib/providers/openaiCompatible/constants.d.ts +1 -0
- package/dist/lib/providers/openaiCompatible/constants.js +2 -0
- package/dist/lib/providers/openaiCompatible/index.d.ts +3 -0
- package/dist/lib/providers/openaiCompatible/index.js +4 -0
- package/dist/lib/providers/openaiCompatible/utils.d.ts +5 -0
- package/dist/lib/providers/openaiCompatible/utils.js +17 -0
- package/dist/lib/proxy/modelRouter.d.ts +10 -0
- package/dist/lib/proxy/modelRouter.js +17 -0
- package/dist/lib/proxy/proxyConfig.js +46 -0
- package/dist/lib/proxy/routingPolicy.d.ts +4 -2
- package/dist/lib/proxy/routingPolicy.js +8 -5
- package/dist/lib/proxy/runtimeConfig.js +2 -0
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +52 -1
- package/dist/lib/server/routes/claudeProxyRoutes.js +467 -221
- package/dist/lib/server/routes/openaiProxyRoutes.js +1 -1
- package/dist/lib/types/errors.d.ts +5 -0
- package/dist/lib/types/proxy.d.ts +24 -0
- package/dist/lib/types/subscription.d.ts +4 -0
- package/dist/lib/utils/providerHealth.js +2 -1
- package/dist/lib/utils/providerUtils.js +2 -1
- package/dist/providers/{amazonBedrock.d.ts → amazonBedrock/client.d.ts} +4 -4
- package/dist/{lib/providers/amazonBedrock.js → providers/amazonBedrock/client.js} +14 -19
- package/dist/providers/amazonBedrock/constants.d.ts +1 -0
- package/dist/providers/amazonBedrock/constants.js +2 -0
- package/dist/providers/amazonBedrock/index.d.ts +3 -0
- package/dist/providers/amazonBedrock/index.js +3 -0
- package/dist/providers/amazonBedrock/utils.d.ts +1 -0
- package/dist/providers/amazonBedrock/utils.js +3 -0
- package/dist/{lib/providers/anthropic.d.ts → providers/anthropic/client.d.ts} +6 -21
- package/dist/{lib/providers/anthropic.js → providers/anthropic/client.js} +27 -46
- package/dist/providers/anthropic/constants.d.ts +4 -0
- package/dist/providers/anthropic/constants.js +8 -0
- package/dist/providers/anthropic/index.d.ts +3 -0
- package/dist/providers/anthropic/index.js +3 -0
- package/dist/providers/anthropic/utils.d.ts +7 -0
- package/dist/providers/anthropic/utils.js +149 -0
- package/dist/providers/{googleAiStudio.d.ts → googleAiStudio/client.d.ts} +4 -4
- package/dist/{lib/providers/googleAiStudio.js → providers/googleAiStudio/client.js} +15 -16
- package/dist/providers/googleAiStudio/index.d.ts +2 -0
- package/dist/providers/googleAiStudio/index.js +2 -0
- package/dist/providers/googleAiStudio/utils.d.ts +2 -0
- package/dist/providers/googleAiStudio/utils.js +18 -0
- package/dist/providers/googleNativeGemini3/constants.d.ts +1 -0
- package/dist/providers/googleNativeGemini3/constants.js +1 -0
- package/dist/providers/googleNativeGemini3/index.d.ts +2 -0
- package/dist/providers/googleNativeGemini3/index.js +2 -0
- package/dist/providers/{googleNativeGemini3.d.ts → googleNativeGemini3/utils.d.ts} +2 -2
- package/dist/providers/{googleNativeGemini3.js → googleNativeGemini3/utils.js} +7 -7
- package/dist/{lib/providers/googleVertex.d.ts → providers/googleVertex/client.d.ts} +4 -4
- package/dist/providers/{googleVertex.js → googleVertex/client.js} +31 -31
- package/dist/providers/googleVertex/constants.d.ts +5 -0
- package/dist/providers/googleVertex/constants.js +26 -0
- package/dist/providers/googleVertex/index.d.ts +3 -0
- package/dist/providers/googleVertex/index.js +3 -0
- package/dist/providers/googleVertex/utils.d.ts +12 -0
- package/dist/providers/googleVertex/utils.js +286 -0
- package/dist/providers/{huggingFace.d.ts → huggingFace/client.d.ts} +3 -3
- package/dist/providers/{huggingFace.js → huggingFace/client.js} +6 -6
- package/dist/providers/huggingFace/index.d.ts +2 -0
- package/dist/providers/huggingFace/index.js +2 -0
- package/dist/providers/huggingFace/utils.d.ts +2 -0
- package/dist/providers/huggingFace/utils.js +7 -0
- package/dist/providers/index.d.ts +10 -10
- package/dist/providers/index.js +10 -10
- package/dist/{lib/providers/litellm.d.ts → providers/litellm/client.d.ts} +3 -3
- package/dist/providers/{litellm.js → litellm/client.js} +12 -12
- package/dist/providers/litellm/constants.d.ts +1 -0
- package/dist/providers/litellm/constants.js +2 -0
- package/dist/providers/litellm/index.d.ts +3 -0
- package/dist/providers/litellm/index.js +3 -0
- package/dist/providers/litellm/utils.d.ts +5 -0
- package/dist/providers/litellm/utils.js +10 -0
- package/dist/{lib/providers/nvidiaNim.d.ts → providers/nvidiaNim/client.d.ts} +3 -3
- package/dist/providers/{nvidiaNim.js → nvidiaNim/client.js} +7 -7
- package/dist/providers/nvidiaNim/constants.d.ts +1 -0
- package/dist/providers/nvidiaNim/constants.js +1 -0
- package/dist/providers/nvidiaNim/index.d.ts +3 -0
- package/dist/providers/nvidiaNim/index.js +3 -0
- package/dist/providers/nvidiaNim/utils.d.ts +9 -0
- package/dist/providers/nvidiaNim/utils.js +100 -0
- package/dist/{lib/providers/ollama.d.ts → providers/ollama/client.d.ts} +3 -3
- package/dist/{lib/providers/ollama.js → providers/ollama/client.js} +9 -14
- package/dist/providers/ollama/constants.d.ts +4 -0
- package/dist/providers/ollama/constants.js +5 -0
- package/dist/providers/ollama/index.d.ts +3 -0
- package/dist/providers/ollama/index.js +3 -0
- package/dist/providers/ollama/utils.d.ts +8 -0
- package/dist/providers/ollama/utils.js +42 -0
- package/dist/providers/{openAI.d.ts → openAI/client.d.ts} +3 -3
- package/dist/providers/{openAI.js → openAI/client.js} +12 -12
- package/dist/providers/openAI/constants.d.ts +1 -0
- package/dist/providers/openAI/constants.js +2 -0
- package/dist/providers/openAI/index.d.ts +3 -0
- package/dist/providers/openAI/index.js +3 -0
- package/dist/providers/openAI/utils.d.ts +2 -0
- package/dist/providers/openAI/utils.js +7 -0
- package/dist/providers/{openRouter.d.ts → openRouter/client.d.ts} +3 -3
- package/dist/{lib/providers/openRouter.js → providers/openRouter/client.js} +12 -30
- package/dist/providers/openRouter/constants.d.ts +1 -0
- package/dist/providers/openRouter/constants.js +1 -0
- package/dist/providers/openRouter/index.d.ts +3 -0
- package/dist/providers/openRouter/index.js +3 -0
- package/dist/providers/openRouter/utils.d.ts +3 -0
- package/dist/providers/openRouter/utils.js +17 -0
- package/dist/providers/{openaiCompatible.d.ts → openaiCompatible/client.d.ts} +2 -2
- package/dist/{lib/providers/openaiCompatible.js → providers/openaiCompatible/client.js} +7 -23
- package/dist/providers/openaiCompatible/constants.d.ts +1 -0
- package/dist/providers/openaiCompatible/constants.js +1 -0
- package/dist/providers/openaiCompatible/index.d.ts +3 -0
- package/dist/providers/openaiCompatible/index.js +3 -0
- package/dist/providers/openaiCompatible/utils.d.ts +5 -0
- package/dist/providers/openaiCompatible/utils.js +16 -0
- package/dist/proxy/modelRouter.d.ts +10 -0
- package/dist/proxy/modelRouter.js +17 -0
- package/dist/proxy/proxyConfig.js +46 -0
- package/dist/proxy/routingPolicy.d.ts +4 -2
- package/dist/proxy/routingPolicy.js +8 -5
- package/dist/proxy/runtimeConfig.js +2 -0
- package/dist/server/routes/claudeProxyRoutes.d.ts +52 -1
- package/dist/server/routes/claudeProxyRoutes.js +467 -221
- package/dist/server/routes/openaiProxyRoutes.js +1 -1
- package/dist/types/errors.d.ts +5 -0
- package/dist/types/proxy.d.ts +24 -0
- package/dist/types/subscription.d.ts +4 -0
- package/dist/utils/providerHealth.js +2 -1
- package/dist/utils/providerUtils.js +2 -1
- package/package.json +3 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { OpenRouterModels } from "../../constants/enums.js";
|
|
2
|
+
import { getProviderModel } from "../../utils/providerConfig.js";
|
|
3
|
+
export const getOpenRouterConfig = () => {
|
|
4
|
+
const apiKey = process.env.OPENROUTER_API_KEY;
|
|
5
|
+
if (!apiKey) {
|
|
6
|
+
throw new Error("OPENROUTER_API_KEY environment variable is required. " +
|
|
7
|
+
"Get your API key at https://openrouter.ai/keys");
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
apiKey,
|
|
11
|
+
referer: process.env.OPENROUTER_REFERER,
|
|
12
|
+
appName: process.env.OPENROUTER_APP_NAME,
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
export const getDefaultOpenRouterModel = () => {
|
|
16
|
+
return getProviderModel("OPENROUTER_MODEL", OpenRouterModels.CLAUDE_SONNET_4_5);
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AIProviderName } from "
|
|
2
|
-
import { OpenAIChatCompletionsProvider } from "
|
|
1
|
+
import type { AIProviderName } from "../../constants/enums.js";
|
|
2
|
+
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
3
3
|
/**
|
|
4
4
|
* OpenAI Compatible Provider — direct HTTP, no AI SDK.
|
|
5
5
|
*
|
|
@@ -1,25 +1,10 @@
|
|
|
1
|
-
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "
|
|
2
|
-
import { logger } from "
|
|
3
|
-
import { redactUrlCredentials } from "
|
|
4
|
-
import { TimeoutError } from "
|
|
5
|
-
import { OpenAIChatCompletionsProvider } from "
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const baseURL = process.env.OPENAI_COMPATIBLE_BASE_URL;
|
|
9
|
-
const apiKey = process.env.OPENAI_COMPATIBLE_API_KEY;
|
|
10
|
-
if (!baseURL) {
|
|
11
|
-
throw new Error("OPENAI_COMPATIBLE_BASE_URL environment variable is required. " +
|
|
12
|
-
"Please set it to your OpenAI-compatible endpoint (e.g., https://api.openrouter.ai/api/v1)");
|
|
13
|
-
}
|
|
14
|
-
if (!apiKey) {
|
|
15
|
-
throw new Error("OPENAI_COMPATIBLE_API_KEY environment variable is required. " +
|
|
16
|
-
"Please set it to your API key for the OpenAI-compatible service.");
|
|
17
|
-
}
|
|
18
|
-
return { baseURL, apiKey };
|
|
19
|
-
};
|
|
20
|
-
const getDefaultOpenAICompatibleModel = () => {
|
|
21
|
-
return process.env.OPENAI_COMPATIBLE_MODEL || undefined;
|
|
22
|
-
};
|
|
1
|
+
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
2
|
+
import { logger } from "../../utils/logger.js";
|
|
3
|
+
import { redactUrlCredentials } from "../../utils/logSanitize.js";
|
|
4
|
+
import { TimeoutError } from "../../utils/timeout.js";
|
|
5
|
+
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
6
|
+
import { FALLBACK_OPENAI_COMPATIBLE_MODEL } from "./constants.js";
|
|
7
|
+
import { getDefaultOpenAICompatibleModel, getOpenAICompatibleConfig, } from "./utils.js";
|
|
23
8
|
/**
|
|
24
9
|
* OpenAI Compatible Provider — direct HTTP, no AI SDK.
|
|
25
10
|
*
|
|
@@ -99,3 +84,4 @@ export class OpenAICompatibleProvider extends OpenAIChatCompletionsProvider {
|
|
|
99
84
|
return new ProviderError(`OpenAI Compatible error: ${errorRecord?.message || "Unknown error"}`, "openai-compatible");
|
|
100
85
|
}
|
|
101
86
|
}
|
|
87
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const FALLBACK_OPENAI_COMPATIBLE_MODEL = "gpt-3.5-turbo";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const getOpenAICompatibleConfig = () => {
|
|
2
|
+
const baseURL = process.env.OPENAI_COMPATIBLE_BASE_URL;
|
|
3
|
+
const apiKey = process.env.OPENAI_COMPATIBLE_API_KEY;
|
|
4
|
+
if (!baseURL) {
|
|
5
|
+
throw new Error("OPENAI_COMPATIBLE_BASE_URL environment variable is required. " +
|
|
6
|
+
"Please set it to your OpenAI-compatible endpoint (e.g., https://api.openrouter.ai/api/v1)");
|
|
7
|
+
}
|
|
8
|
+
if (!apiKey) {
|
|
9
|
+
throw new Error("OPENAI_COMPATIBLE_API_KEY environment variable is required. " +
|
|
10
|
+
"Please set it to your API key for the OpenAI-compatible service.");
|
|
11
|
+
}
|
|
12
|
+
return { baseURL, apiKey };
|
|
13
|
+
};
|
|
14
|
+
export const getDefaultOpenAICompatibleModel = () => {
|
|
15
|
+
return process.env.OPENAI_COMPATIBLE_MODEL || undefined;
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import type { FallbackEntry, ModelMapping, ProxyRoutingConfig, RouteResult } from "../types/index.js";
|
|
2
|
+
/** Default and accepted range for concurrent upstream requests per OAuth account. */
|
|
3
|
+
export declare const MIN_MAX_INFLIGHT_PER_ACCOUNT = 1;
|
|
4
|
+
export declare const MAX_MAX_INFLIGHT_PER_ACCOUNT = 20;
|
|
5
|
+
export declare const DEFAULT_MAX_INFLIGHT_PER_ACCOUNT = 2;
|
|
2
6
|
export declare class ModelRouter {
|
|
3
7
|
private readonly mappings;
|
|
4
8
|
private readonly passthrough;
|
|
5
9
|
private readonly fallback;
|
|
10
|
+
private readonly autoFallback;
|
|
11
|
+
private readonly maxInflightPerAccount;
|
|
6
12
|
constructor(config: ProxyRoutingConfig);
|
|
7
13
|
resolve(requestedModel: string): RouteResult;
|
|
8
14
|
isClaudeTarget(requestedModel: string): boolean;
|
|
9
15
|
getFallbackChain(): FallbackEntry[];
|
|
16
|
+
/** Whether translation-layer auto-provider fallback is explicitly enabled. */
|
|
17
|
+
isAutoFallbackEnabled(): boolean;
|
|
18
|
+
/** Maximum concurrent upstream requests admitted for each OAuth account. */
|
|
19
|
+
getMaxInflightPerAccount(): number;
|
|
10
20
|
/** Return the raw model mapping entries (used by /v1/models). */
|
|
11
21
|
getModelMappings(): ModelMapping[];
|
|
12
22
|
/** Return models configured for passthrough (used by /v1/models). */
|
|
@@ -1,11 +1,20 @@
|
|
|
1
|
+
/** Default and accepted range for concurrent upstream requests per OAuth account. */
|
|
2
|
+
export const MIN_MAX_INFLIGHT_PER_ACCOUNT = 1;
|
|
3
|
+
export const MAX_MAX_INFLIGHT_PER_ACCOUNT = 20;
|
|
4
|
+
export const DEFAULT_MAX_INFLIGHT_PER_ACCOUNT = 2;
|
|
1
5
|
export class ModelRouter {
|
|
2
6
|
mappings;
|
|
3
7
|
passthrough;
|
|
4
8
|
fallback;
|
|
9
|
+
autoFallback;
|
|
10
|
+
maxInflightPerAccount;
|
|
5
11
|
constructor(config) {
|
|
6
12
|
this.mappings = new Map(config.modelMappings.map((m) => [m.from, m]));
|
|
7
13
|
this.passthrough = new Set(config.passthroughModels ?? []);
|
|
8
14
|
this.fallback = config.fallbackChain;
|
|
15
|
+
this.autoFallback = config.autoFallback === true;
|
|
16
|
+
this.maxInflightPerAccount =
|
|
17
|
+
config.maxInflightPerAccount ?? DEFAULT_MAX_INFLIGHT_PER_ACCOUNT;
|
|
9
18
|
}
|
|
10
19
|
resolve(requestedModel) {
|
|
11
20
|
const mapping = this.mappings.get(requestedModel);
|
|
@@ -29,6 +38,14 @@ export class ModelRouter {
|
|
|
29
38
|
getFallbackChain() {
|
|
30
39
|
return this.fallback;
|
|
31
40
|
}
|
|
41
|
+
/** Whether translation-layer auto-provider fallback is explicitly enabled. */
|
|
42
|
+
isAutoFallbackEnabled() {
|
|
43
|
+
return this.autoFallback;
|
|
44
|
+
}
|
|
45
|
+
/** Maximum concurrent upstream requests admitted for each OAuth account. */
|
|
46
|
+
getMaxInflightPerAccount() {
|
|
47
|
+
return this.maxInflightPerAccount;
|
|
48
|
+
}
|
|
32
49
|
/** Return the raw model mapping entries (used by /v1/models). */
|
|
33
50
|
getModelMappings() {
|
|
34
51
|
return Array.from(this.mappings.values());
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { readFile } from "node:fs/promises";
|
|
14
14
|
import { extname } from "node:path";
|
|
15
|
+
import { MAX_MAX_INFLIGHT_PER_ACCOUNT, MIN_MAX_INFLIGHT_PER_ACCOUNT, } from "./modelRouter.js";
|
|
15
16
|
import { logger } from "../utils/logger.js";
|
|
16
17
|
// ---------------------------------------------------------------------------
|
|
17
18
|
// Environment variable resolution
|
|
@@ -237,6 +238,24 @@ export function validateProxyConfig(config) {
|
|
|
237
238
|
normalizedQuotaRouting !== "false") {
|
|
238
239
|
errors.push("routing.quota-routing must be a boolean");
|
|
239
240
|
}
|
|
241
|
+
const rawAutoFallback = routing["auto-fallback"] ?? routing.autoFallback;
|
|
242
|
+
const normalizedAutoFallback = typeof rawAutoFallback === "string"
|
|
243
|
+
? rawAutoFallback.trim().toLowerCase()
|
|
244
|
+
: undefined;
|
|
245
|
+
if (rawAutoFallback !== undefined &&
|
|
246
|
+
typeof rawAutoFallback !== "boolean" &&
|
|
247
|
+
normalizedAutoFallback !== "true" &&
|
|
248
|
+
normalizedAutoFallback !== "false") {
|
|
249
|
+
errors.push("routing.auto-fallback must be a boolean");
|
|
250
|
+
}
|
|
251
|
+
const rawMaxInflight = routing["max-inflight-per-account"] ?? routing.maxInflightPerAccount;
|
|
252
|
+
if (rawMaxInflight !== undefined &&
|
|
253
|
+
(typeof rawMaxInflight !== "number" ||
|
|
254
|
+
!Number.isInteger(rawMaxInflight) ||
|
|
255
|
+
rawMaxInflight < MIN_MAX_INFLIGHT_PER_ACCOUNT ||
|
|
256
|
+
rawMaxInflight > MAX_MAX_INFLIGHT_PER_ACCOUNT)) {
|
|
257
|
+
errors.push("routing.max-inflight-per-account must be an integer between 1 and 20");
|
|
258
|
+
}
|
|
240
259
|
const rawSessionSoftLimit = routing["session-soft-limit"] ?? routing.sessionSoftLimit;
|
|
241
260
|
if (rawSessionSoftLimit !== undefined) {
|
|
242
261
|
const sessionSoftLimit = Number(rawSessionSoftLimit);
|
|
@@ -322,6 +341,8 @@ function warnPlaintextApiKeys(accounts) {
|
|
|
322
341
|
* - `strategy` ("round-robin" | "fill-first")
|
|
323
342
|
* - `model-mappings` / `modelMappings` — array of {from, to, provider}
|
|
324
343
|
* - `fallback-chain` / `fallbackChain` — array of {provider, model}
|
|
344
|
+
* - `auto-fallback` / `autoFallback` — opt in to an unspecified provider
|
|
345
|
+
* - `max-inflight-per-account` / `maxInflightPerAccount` — concurrency cap
|
|
325
346
|
* - `passthroughModels` / `passthrough-models` — array of model IDs
|
|
326
347
|
* - `quota-routing` / `quotaRouting` — quota-aware fill-first ordering
|
|
327
348
|
* - `session-soft-limit` / `sessionSoftLimit` — proactive handoff threshold
|
|
@@ -396,6 +417,31 @@ function parseRoutingConfig(raw) {
|
|
|
396
417
|
logger.warn(`[proxy-config] Ignoring routing.quotaRouting: expected boolean, got ${typeof rawQuotaRouting}`);
|
|
397
418
|
}
|
|
398
419
|
}
|
|
420
|
+
const rawAutoFallback = raw["auto-fallback"] ?? raw.autoFallback;
|
|
421
|
+
if (rawAutoFallback !== undefined) {
|
|
422
|
+
if (typeof rawAutoFallback === "boolean") {
|
|
423
|
+
result.autoFallback = rawAutoFallback;
|
|
424
|
+
}
|
|
425
|
+
else if (typeof rawAutoFallback === "string" &&
|
|
426
|
+
["true", "false"].includes(rawAutoFallback.trim().toLowerCase())) {
|
|
427
|
+
result.autoFallback = rawAutoFallback.trim().toLowerCase() === "true";
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
logger.warn(`[proxy-config] Ignoring routing.autoFallback: expected boolean, got ${typeof rawAutoFallback}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
const rawMaxInflight = raw["max-inflight-per-account"] ?? raw.maxInflightPerAccount;
|
|
434
|
+
if (rawMaxInflight !== undefined) {
|
|
435
|
+
if (typeof rawMaxInflight === "number" &&
|
|
436
|
+
Number.isInteger(rawMaxInflight) &&
|
|
437
|
+
rawMaxInflight >= MIN_MAX_INFLIGHT_PER_ACCOUNT &&
|
|
438
|
+
rawMaxInflight <= MAX_MAX_INFLIGHT_PER_ACCOUNT) {
|
|
439
|
+
result.maxInflightPerAccount = rawMaxInflight;
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
logger.warn(`[proxy-config] Ignoring routing.maxInflightPerAccount: expected integer between 1 and 20, got ${String(rawMaxInflight)}`);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
399
445
|
const rawSessionSoftLimit = raw["session-soft-limit"] ?? raw.sessionSoftLimit;
|
|
400
446
|
if (rawSessionSoftLimit !== undefined) {
|
|
401
447
|
const sessionSoftLimit = Number(rawSessionSoftLimit);
|
|
@@ -4,12 +4,14 @@ export declare function inferClaudeProxyModelTier(modelName: string): ClaudeProx
|
|
|
4
4
|
* Build a translation plan for a Claude-compatible proxy request.
|
|
5
5
|
* The plan lists the primary provider followed by eligible fallback targets.
|
|
6
6
|
* All configured fallback entries are always eligible — no contract-based gating.
|
|
7
|
-
*
|
|
7
|
+
* An "auto-provider" entry is appended only when explicitly enabled by the
|
|
8
|
+
* caller. This keeps an empty fallback chain from silently escaping to an
|
|
9
|
+
* unrelated provider.
|
|
8
10
|
*/
|
|
9
11
|
export declare function buildProxyTranslationPlan(primary: {
|
|
10
12
|
provider: string;
|
|
11
13
|
model?: string;
|
|
12
|
-
}, fallbackChain: FallbackEntry[], requestedModel: string, _parsed: ParsedClaudeRequest): ProxyTranslationPlan;
|
|
14
|
+
}, fallbackChain: FallbackEntry[], requestedModel: string, _parsed: ParsedClaudeRequest, allowAutoFallback?: boolean): ProxyTranslationPlan;
|
|
13
15
|
/**
|
|
14
16
|
* Parse the retry-after header from an upstream 429 response.
|
|
15
17
|
* Returns milliseconds to wait, or 0 if no valid header present.
|
|
@@ -15,9 +15,11 @@ export function inferClaudeProxyModelTier(modelName) {
|
|
|
15
15
|
* Build a translation plan for a Claude-compatible proxy request.
|
|
16
16
|
* The plan lists the primary provider followed by eligible fallback targets.
|
|
17
17
|
* All configured fallback entries are always eligible — no contract-based gating.
|
|
18
|
-
*
|
|
18
|
+
* An "auto-provider" entry is appended only when explicitly enabled by the
|
|
19
|
+
* caller. This keeps an empty fallback chain from silently escaping to an
|
|
20
|
+
* unrelated provider.
|
|
19
21
|
*/
|
|
20
|
-
export function buildProxyTranslationPlan(primary, fallbackChain, requestedModel, _parsed) {
|
|
22
|
+
export function buildProxyTranslationPlan(primary, fallbackChain, requestedModel, _parsed, allowAutoFallback = false) {
|
|
21
23
|
const attempts = [
|
|
22
24
|
{
|
|
23
25
|
provider: primary.provider,
|
|
@@ -36,9 +38,10 @@ export function buildProxyTranslationPlan(primary, fallbackChain, requestedModel
|
|
|
36
38
|
label: `${fallback.provider}/${fallback.model}`,
|
|
37
39
|
});
|
|
38
40
|
}
|
|
39
|
-
//
|
|
40
|
-
//
|
|
41
|
-
if (
|
|
41
|
+
// A provider chosen by the translation layer is an explicit opt-in. It is
|
|
42
|
+
// intentionally not a default when configured entries are absent or deduped.
|
|
43
|
+
if (allowAutoFallback &&
|
|
44
|
+
(fallbackChain.length === 0 || attempts.length === 1)) {
|
|
42
45
|
attempts.push({ label: "auto-provider" });
|
|
43
46
|
}
|
|
44
47
|
return {
|
|
@@ -212,6 +212,8 @@ async function buildCandidate(options, generation, allowMissingConfig, allowMiss
|
|
|
212
212
|
strategy,
|
|
213
213
|
modelMappings: routing.modelMappings ?? [],
|
|
214
214
|
fallbackChain: routing.fallbackChain ?? [],
|
|
215
|
+
autoFallback: routing.autoFallback,
|
|
216
|
+
maxInflightPerAccount: routing.maxInflightPerAccount,
|
|
215
217
|
passthroughModels: routing.passthroughModels,
|
|
216
218
|
quotaRouting: routing.quotaRouting,
|
|
217
219
|
sessionSoftLimit: routing.sessionSoftLimit,
|
|
@@ -12,7 +12,13 @@
|
|
|
12
12
|
import { buildTranslationOptions } from "../../proxy/proxyTranslationEngine.js";
|
|
13
13
|
import { ProxyTracer } from "../../proxy/proxyTracer.js";
|
|
14
14
|
import { isPermanentRefreshFailure } from "../../proxy/tokenRefresh.js";
|
|
15
|
-
import type { AccountAllowlist, AccountCooldownPlan, AccountQuota, AnthropicAttemptLogger, AnthropicAuthRetryResult, AnthropicLoopState, AnthropicSuccessResult, AnthropicUpstreamFetchResult, ClaudeFinalRequestLogger, ClaudeLoggedErrorBuilder, ClaudeRequest, ClaudeProxyRouteRuntimeOptions, ModelRouterInterface, ParsedClaudeError, ProxyAccountRoutingDecision, ProxyAccountSortMetrics, ProxyBodyCaptureLogger, ProxyPassthroughAccount, RouteGroup, RuntimeAccountState, ServerContext, StreamTerminalOutcome } from "../../types/index.js";
|
|
15
|
+
import type { AccountAllowlist, AccountAdmissionLease, AccountCooldownPlan, AccountQuota, AnthropicAttemptLogger, AnthropicAuthRetryResult, AnthropicLoopState, AnthropicNonOkResult, AnthropicSuccessResult, AnthropicUpstreamFetchResult, ClaudeFinalRequestLogger, ClaudeLoggedErrorBuilder, ClaudeRequest, ClaudeProxyRouteRuntimeOptions, ModelRouterInterface, ParsedClaudeError, ProxyAccountRoutingDecision, ProxyAccountSortMetrics, ProxyBodyCaptureLogger, ProxyPassthroughAccount, RouteGroup, RuntimeAccountState, ServerContext, StreamTerminalOutcome } from "../../types/index.js";
|
|
16
|
+
declare function tryAcquireAccountAdmission(accountKey: string, capacity: number): AccountAdmissionLease | undefined;
|
|
17
|
+
declare function acquireAccountAdmission(accountKey: string, capacity: number, abortSignal?: AbortSignal, timeoutMs?: number): Promise<AccountAdmissionLease | undefined>;
|
|
18
|
+
declare function acquireFirstAvailableAccountAdmission(accountKeys: string[], capacity: number, abortSignal?: AbortSignal, timeoutMs?: number): Promise<{
|
|
19
|
+
accountKey: string;
|
|
20
|
+
lease: AccountAdmissionLease;
|
|
21
|
+
} | undefined>;
|
|
16
22
|
/** Resolve the configured primary's stable key to its current index in the
|
|
17
23
|
* request's enabledAccounts list. Returns 0 (insertion-order fallback) when
|
|
18
24
|
* no key is configured or the key cannot be matched (account disabled/
|
|
@@ -158,6 +164,7 @@ declare function handleAnthropicStreamingSuccessResponse(args: {
|
|
|
158
164
|
upstreamSpan?: import("@opentelemetry/api").Span;
|
|
159
165
|
logAttempt: AnthropicAttemptLogger;
|
|
160
166
|
logProxyBody: ProxyBodyCaptureLogger;
|
|
167
|
+
onStreamTerminal?: () => void;
|
|
161
168
|
logFinalRequest: (status: number, accountLabel: string, accountType: string, errorType?: string, errorMessage?: string, extra?: {
|
|
162
169
|
inputTokens?: number;
|
|
163
170
|
outputTokens?: number;
|
|
@@ -189,6 +196,7 @@ declare function handleAnthropicAuthRetry(args: {
|
|
|
189
196
|
upstreamSpan?: import("@opentelemetry/api").Span;
|
|
190
197
|
logAttempt: AnthropicAttemptLogger;
|
|
191
198
|
logProxyBody: ProxyBodyCaptureLogger;
|
|
199
|
+
onStreamTerminal?: () => void;
|
|
192
200
|
logFinalRequest: (status: number, accountLabel: string, accountType: string, errorType?: string, errorMessage?: string, extra?: {
|
|
193
201
|
inputTokens?: number;
|
|
194
202
|
outputTokens?: number;
|
|
@@ -210,6 +218,33 @@ declare function finalizeAnthropicTerminalFetchError(args: {
|
|
|
210
218
|
logProxyBody: ProxyBodyCaptureLogger;
|
|
211
219
|
logFinalRequest: ClaudeFinalRequestLogger;
|
|
212
220
|
}): Response | unknown;
|
|
221
|
+
declare function handleAnthropicNonOkResponse(args: {
|
|
222
|
+
response: Response;
|
|
223
|
+
account: ProxyPassthroughAccount;
|
|
224
|
+
accountState: RuntimeAccountState;
|
|
225
|
+
enabledAccounts: ProxyPassthroughAccount[];
|
|
226
|
+
orderedAccounts: ProxyPassthroughAccount[];
|
|
227
|
+
tracer?: ProxyTracer;
|
|
228
|
+
requestStartTime: number;
|
|
229
|
+
fetchStartMs: number;
|
|
230
|
+
attemptNumber: number;
|
|
231
|
+
logAttempt: AnthropicAttemptLogger;
|
|
232
|
+
logProxyBody: ProxyBodyCaptureLogger;
|
|
233
|
+
logFinalRequest: (status: number, accountLabel: string, accountType: string, errorType?: string, errorMessage?: string, extra?: {
|
|
234
|
+
inputTokens?: number;
|
|
235
|
+
outputTokens?: number;
|
|
236
|
+
cacheCreationTokens?: number;
|
|
237
|
+
cacheReadTokens?: number;
|
|
238
|
+
}) => void;
|
|
239
|
+
lastError: unknown;
|
|
240
|
+
authFailureMessage: string | null;
|
|
241
|
+
sawTransientFailure: boolean;
|
|
242
|
+
invalidRequestFailure: {
|
|
243
|
+
status: number;
|
|
244
|
+
body: string;
|
|
245
|
+
contentType?: string;
|
|
246
|
+
} | null;
|
|
247
|
+
}): Promise<AnthropicNonOkResult>;
|
|
213
248
|
/**
|
|
214
249
|
* Detect Anthropic's anti-abuse / request-construction 429.
|
|
215
250
|
*
|
|
@@ -284,6 +319,12 @@ export declare const buildProxyFallbackOptions: typeof buildTranslationOptions;
|
|
|
284
319
|
* carry transient HTML responses (e.g. 520 pages) inside `error.message`.
|
|
285
320
|
*/
|
|
286
321
|
export declare function isTransientHttpFailure(status: number, errBody: string): boolean;
|
|
322
|
+
/**
|
|
323
|
+
* An upstream overload is already a capacity signal. Retrying it on the same
|
|
324
|
+
* OAuth account only consumes its remaining concurrency and delays rotation.
|
|
325
|
+
*/
|
|
326
|
+
export declare function isUpstreamOverload(status: number, errBody: string): boolean;
|
|
327
|
+
export declare function redactProviderErrorMessage(message: string): string;
|
|
287
328
|
export declare const __testHooks: {
|
|
288
329
|
resolveHomeIndex: typeof resolveHomeIndex;
|
|
289
330
|
maybeResetPrimaryToHome: typeof maybeResetPrimaryToHome;
|
|
@@ -309,12 +350,22 @@ export declare const __testHooks: {
|
|
|
309
350
|
isAntiAbuseConstruction429: typeof isAntiAbuseConstruction429;
|
|
310
351
|
fetchAnthropicAccountResponse: typeof fetchAnthropicAccountResponse;
|
|
311
352
|
finalizeAnthropicTerminalFetchError: typeof finalizeAnthropicTerminalFetchError;
|
|
353
|
+
handleAnthropicNonOkResponse: typeof handleAnthropicNonOkResponse;
|
|
312
354
|
handleAnthropicAuthRetry: typeof handleAnthropicAuthRetry;
|
|
313
355
|
handleAnthropicStreamingSuccessResponse: typeof handleAnthropicStreamingSuccessResponse;
|
|
314
356
|
claimTransientRateLimitRetry: typeof claimTransientRateLimitRetry;
|
|
315
357
|
claimTransientCooldownAdmission: typeof claimTransientCooldownAdmission;
|
|
316
358
|
waitForTransientAccountAvailability: typeof waitForTransientAccountAvailability;
|
|
359
|
+
acquireAccountAdmission: typeof acquireAccountAdmission;
|
|
360
|
+
acquireFirstAvailableAccountAdmission: typeof acquireFirstAvailableAccountAdmission;
|
|
361
|
+
tryAcquireAccountAdmission: typeof tryAcquireAccountAdmission;
|
|
362
|
+
getAccountAdmissionSnapshot: (accountKey: string) => {
|
|
363
|
+
active: number;
|
|
364
|
+
waiting: number;
|
|
365
|
+
};
|
|
317
366
|
describeTransportError: typeof describeTransportError;
|
|
367
|
+
redactProviderErrorMessage: typeof redactProviderErrorMessage;
|
|
368
|
+
isUpstreamOverload: typeof isUpstreamOverload;
|
|
318
369
|
shouldAttemptClaudeFallback: typeof shouldAttemptClaudeFallback;
|
|
319
370
|
executeClaudeFallbackWithRetry: typeof executeClaudeFallbackWithRetry;
|
|
320
371
|
buildClaudeAnthropicFailureResponse: typeof buildClaudeAnthropicFailureResponse;
|