claudish 5.8.0 → 5.10.0
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/dist/index.js +559 -53
- package/package.json +1 -1
- package/recommended-models.json +7 -7
package/dist/index.js
CHANGED
|
@@ -28728,6 +28728,9 @@ function loadConfig() {
|
|
|
28728
28728
|
if (config3.telemetry !== undefined) {
|
|
28729
28729
|
merged.telemetry = config3.telemetry;
|
|
28730
28730
|
}
|
|
28731
|
+
if (config3.routing !== undefined) {
|
|
28732
|
+
merged.routing = config3.routing;
|
|
28733
|
+
}
|
|
28731
28734
|
return merged;
|
|
28732
28735
|
} catch (error46) {
|
|
28733
28736
|
console.error(`Warning: Failed to load config, using defaults: ${error46}`);
|
|
@@ -28762,11 +28765,15 @@ function loadLocalConfig() {
|
|
|
28762
28765
|
try {
|
|
28763
28766
|
const content = readFileSync5(localPath, "utf-8");
|
|
28764
28767
|
const config3 = JSON.parse(content);
|
|
28765
|
-
|
|
28768
|
+
const local = {
|
|
28766
28769
|
version: config3.version || DEFAULT_CONFIG.version,
|
|
28767
28770
|
defaultProfile: config3.defaultProfile || "",
|
|
28768
28771
|
profiles: config3.profiles || {}
|
|
28769
28772
|
};
|
|
28773
|
+
if (config3.routing !== undefined) {
|
|
28774
|
+
local.routing = config3.routing;
|
|
28775
|
+
}
|
|
28776
|
+
return local;
|
|
28770
28777
|
} catch (error46) {
|
|
28771
28778
|
console.error(`Warning: Failed to load local config: ${error46}`);
|
|
28772
28779
|
return null;
|
|
@@ -29458,7 +29465,7 @@ var getRemoteProviders = () => [
|
|
|
29458
29465
|
authScheme: "bearer",
|
|
29459
29466
|
capabilities: {
|
|
29460
29467
|
supportsTools: true,
|
|
29461
|
-
supportsVision:
|
|
29468
|
+
supportsVision: false,
|
|
29462
29469
|
supportsStreaming: true,
|
|
29463
29470
|
supportsJsonMode: false,
|
|
29464
29471
|
supportsReasoning: false
|
|
@@ -29941,9 +29948,7 @@ function checkApiKeyForProvider(nativeProvider, modelName) {
|
|
|
29941
29948
|
}
|
|
29942
29949
|
function getAutoRouteHint(modelName, nativeProvider) {
|
|
29943
29950
|
const hint = PROVIDER_HINT_MAP[nativeProvider];
|
|
29944
|
-
const lines = [
|
|
29945
|
-
`No credentials found for "${modelName}". Options:`
|
|
29946
|
-
];
|
|
29951
|
+
const lines = [`No credentials found for "${modelName}". Options:`];
|
|
29947
29952
|
let hasOption = false;
|
|
29948
29953
|
if (hint?.loginFlag) {
|
|
29949
29954
|
lines.push(` Run: claudish ${hint.loginFlag} (authenticate via OAuth)`);
|
|
@@ -30004,7 +30009,61 @@ function autoRoute(modelName, nativeProvider) {
|
|
|
30004
30009
|
}
|
|
30005
30010
|
return null;
|
|
30006
30011
|
}
|
|
30007
|
-
|
|
30012
|
+
function hasProviderCredentials(provider) {
|
|
30013
|
+
const keyInfo = API_KEY_ENV_VARS[provider];
|
|
30014
|
+
if (keyInfo?.envVar && process.env[keyInfo.envVar])
|
|
30015
|
+
return true;
|
|
30016
|
+
if (keyInfo?.aliases?.some((a) => process.env[a]))
|
|
30017
|
+
return true;
|
|
30018
|
+
return hasOAuthCredentials(provider);
|
|
30019
|
+
}
|
|
30020
|
+
function getFallbackChain(modelName, nativeProvider) {
|
|
30021
|
+
const routes = [];
|
|
30022
|
+
const litellmBaseUrl = process.env.LITELLM_BASE_URL;
|
|
30023
|
+
if (litellmBaseUrl && process.env.LITELLM_API_KEY) {
|
|
30024
|
+
routes.push({
|
|
30025
|
+
provider: "litellm",
|
|
30026
|
+
modelSpec: `litellm@${modelName}`,
|
|
30027
|
+
displayName: "LiteLLM"
|
|
30028
|
+
});
|
|
30029
|
+
}
|
|
30030
|
+
if (process.env.OPENCODE_API_KEY) {
|
|
30031
|
+
routes.push({
|
|
30032
|
+
provider: "opencode-zen",
|
|
30033
|
+
modelSpec: `zen@${modelName}`,
|
|
30034
|
+
displayName: "OpenCode Zen"
|
|
30035
|
+
});
|
|
30036
|
+
}
|
|
30037
|
+
const sub = SUBSCRIPTION_ALTERNATIVES[nativeProvider];
|
|
30038
|
+
if (sub && hasProviderCredentials(sub.subscriptionProvider)) {
|
|
30039
|
+
const subModelName = sub.modelName || modelName;
|
|
30040
|
+
routes.push({
|
|
30041
|
+
provider: sub.subscriptionProvider,
|
|
30042
|
+
modelSpec: `${sub.prefix}@${subModelName}`,
|
|
30043
|
+
displayName: sub.displayName
|
|
30044
|
+
});
|
|
30045
|
+
}
|
|
30046
|
+
if (nativeProvider !== "unknown" && nativeProvider !== "qwen" && nativeProvider !== "native-anthropic") {
|
|
30047
|
+
if (hasProviderCredentials(nativeProvider)) {
|
|
30048
|
+
const prefix = PROVIDER_TO_PREFIX[nativeProvider] || nativeProvider;
|
|
30049
|
+
routes.push({
|
|
30050
|
+
provider: nativeProvider,
|
|
30051
|
+
modelSpec: `${prefix}@${modelName}`,
|
|
30052
|
+
displayName: DISPLAY_NAMES[nativeProvider] || nativeProvider
|
|
30053
|
+
});
|
|
30054
|
+
}
|
|
30055
|
+
}
|
|
30056
|
+
if (process.env.OPENROUTER_API_KEY) {
|
|
30057
|
+
const resolution = resolveModelNameSync(modelName, "openrouter");
|
|
30058
|
+
routes.push({
|
|
30059
|
+
provider: "openrouter",
|
|
30060
|
+
modelSpec: resolution.resolvedId,
|
|
30061
|
+
displayName: "OpenRouter"
|
|
30062
|
+
});
|
|
30063
|
+
}
|
|
30064
|
+
return routes;
|
|
30065
|
+
}
|
|
30066
|
+
var API_KEY_ENV_VARS, PROVIDER_HINT_MAP, PROVIDER_TO_PREFIX, DISPLAY_NAMES, SUBSCRIPTION_ALTERNATIVES;
|
|
30008
30067
|
var init_auto_route = __esm(() => {
|
|
30009
30068
|
init_oauth_registry();
|
|
30010
30069
|
init_model_catalog_resolver();
|
|
@@ -30068,6 +30127,65 @@ var init_auto_route = __esm(() => {
|
|
|
30068
30127
|
apiKeyEnvVar: "OLLAMA_API_KEY"
|
|
30069
30128
|
}
|
|
30070
30129
|
};
|
|
30130
|
+
PROVIDER_TO_PREFIX = {
|
|
30131
|
+
google: "g",
|
|
30132
|
+
openai: "oai",
|
|
30133
|
+
minimax: "mm",
|
|
30134
|
+
"minimax-coding": "mmc",
|
|
30135
|
+
kimi: "kimi",
|
|
30136
|
+
"kimi-coding": "kc",
|
|
30137
|
+
glm: "glm",
|
|
30138
|
+
"glm-coding": "gc",
|
|
30139
|
+
zai: "zai",
|
|
30140
|
+
ollamacloud: "oc",
|
|
30141
|
+
"opencode-zen": "zen",
|
|
30142
|
+
"opencode-zen-go": "zengo",
|
|
30143
|
+
litellm: "ll",
|
|
30144
|
+
vertex: "v",
|
|
30145
|
+
"gemini-codeassist": "go"
|
|
30146
|
+
};
|
|
30147
|
+
DISPLAY_NAMES = {
|
|
30148
|
+
google: "Gemini",
|
|
30149
|
+
openai: "OpenAI",
|
|
30150
|
+
minimax: "MiniMax",
|
|
30151
|
+
"minimax-coding": "MiniMax Coding",
|
|
30152
|
+
kimi: "Kimi",
|
|
30153
|
+
"kimi-coding": "Kimi Coding",
|
|
30154
|
+
glm: "GLM",
|
|
30155
|
+
"glm-coding": "GLM Coding",
|
|
30156
|
+
zai: "Z.AI",
|
|
30157
|
+
ollamacloud: "OllamaCloud",
|
|
30158
|
+
"opencode-zen": "OpenCode Zen",
|
|
30159
|
+
"opencode-zen-go": "OpenCode Zen Go",
|
|
30160
|
+
litellm: "LiteLLM",
|
|
30161
|
+
openrouter: "OpenRouter"
|
|
30162
|
+
};
|
|
30163
|
+
SUBSCRIPTION_ALTERNATIVES = {
|
|
30164
|
+
kimi: {
|
|
30165
|
+
subscriptionProvider: "kimi-coding",
|
|
30166
|
+
modelName: "kimi-for-coding",
|
|
30167
|
+
prefix: "kc",
|
|
30168
|
+
displayName: "Kimi Coding"
|
|
30169
|
+
},
|
|
30170
|
+
minimax: {
|
|
30171
|
+
subscriptionProvider: "minimax-coding",
|
|
30172
|
+
modelName: null,
|
|
30173
|
+
prefix: "mmc",
|
|
30174
|
+
displayName: "MiniMax Coding"
|
|
30175
|
+
},
|
|
30176
|
+
glm: {
|
|
30177
|
+
subscriptionProvider: "glm-coding",
|
|
30178
|
+
modelName: null,
|
|
30179
|
+
prefix: "gc",
|
|
30180
|
+
displayName: "GLM Coding"
|
|
30181
|
+
},
|
|
30182
|
+
google: {
|
|
30183
|
+
subscriptionProvider: "gemini-codeassist",
|
|
30184
|
+
modelName: null,
|
|
30185
|
+
prefix: "go",
|
|
30186
|
+
displayName: "Gemini Code Assist"
|
|
30187
|
+
}
|
|
30188
|
+
};
|
|
30071
30189
|
});
|
|
30072
30190
|
|
|
30073
30191
|
// src/providers/provider-resolver.ts
|
|
@@ -31844,7 +31962,7 @@ async function fetchGLMCodingModels() {
|
|
|
31844
31962
|
return [];
|
|
31845
31963
|
}
|
|
31846
31964
|
}
|
|
31847
|
-
var __filename4, __dirname4, VERSION = "5.
|
|
31965
|
+
var __filename4, __dirname4, VERSION = "5.10.0", CACHE_MAX_AGE_DAYS2 = 2, MODELS_JSON_PATH, CLAUDISH_CACHE_DIR2, ALL_MODELS_JSON_PATH;
|
|
31848
31966
|
var init_cli = __esm(() => {
|
|
31849
31967
|
init_config();
|
|
31850
31968
|
init_model_loader();
|
|
@@ -34509,7 +34627,9 @@ async function fetchZenGoModels() {
|
|
|
34509
34627
|
return [];
|
|
34510
34628
|
const ZEN_GO_BASE = process.env.OPENCODE_BASE_URL ? process.env.OPENCODE_BASE_URL.replace("/zen", "/zen/go") : "https://opencode.ai/zen/go";
|
|
34511
34629
|
try {
|
|
34512
|
-
const mdevResp = await fetch("https://models.dev/api.json", {
|
|
34630
|
+
const mdevResp = await fetch("https://models.dev/api.json", {
|
|
34631
|
+
signal: AbortSignal.timeout(5000)
|
|
34632
|
+
});
|
|
34513
34633
|
if (!mdevResp.ok)
|
|
34514
34634
|
return [];
|
|
34515
34635
|
const mdevData = await mdevResp.json();
|
|
@@ -34521,7 +34641,11 @@ async function fetchZenGoModels() {
|
|
|
34521
34641
|
const r = await fetch(`${ZEN_GO_BASE}/v1/chat/completions`, {
|
|
34522
34642
|
method: "POST",
|
|
34523
34643
|
headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}` },
|
|
34524
|
-
body: JSON.stringify({
|
|
34644
|
+
body: JSON.stringify({
|
|
34645
|
+
model: modelId,
|
|
34646
|
+
messages: [{ role: "user", content: "hi" }],
|
|
34647
|
+
max_tokens: 1
|
|
34648
|
+
}),
|
|
34525
34649
|
signal: AbortSignal.timeout(8000)
|
|
34526
34650
|
});
|
|
34527
34651
|
if (!r.ok)
|
|
@@ -34982,7 +35106,10 @@ async function getAllModelsForSearch(forceUpdate = false) {
|
|
|
34982
35106
|
const litellmBaseUrl = process.env.LITELLM_BASE_URL;
|
|
34983
35107
|
const litellmApiKey = process.env.LITELLM_API_KEY;
|
|
34984
35108
|
const fetchEntries = [
|
|
34985
|
-
{
|
|
35109
|
+
{
|
|
35110
|
+
name: "OpenRouter",
|
|
35111
|
+
promise: fetchAllModels(forceUpdate).then((models) => models.map(toModelInfo))
|
|
35112
|
+
},
|
|
34986
35113
|
{ name: "xAI", promise: fetchXAIModels() },
|
|
34987
35114
|
{ name: "Gemini", promise: fetchGeminiModels() },
|
|
34988
35115
|
{ name: "OpenAI", promise: fetchOpenAIModels() },
|
|
@@ -34993,7 +35120,10 @@ async function getAllModelsForSearch(forceUpdate = false) {
|
|
|
34993
35120
|
{ name: "Zen Go", promise: fetchZenGoModels() }
|
|
34994
35121
|
];
|
|
34995
35122
|
if (litellmBaseUrl && litellmApiKey) {
|
|
34996
|
-
fetchEntries.push({
|
|
35123
|
+
fetchEntries.push({
|
|
35124
|
+
name: "LiteLLM",
|
|
35125
|
+
promise: fetchLiteLLMModels(litellmBaseUrl, litellmApiKey, forceUpdate)
|
|
35126
|
+
});
|
|
34997
35127
|
}
|
|
34998
35128
|
const settled = await Promise.allSettled(fetchEntries.map((e) => e.promise));
|
|
34999
35129
|
const fetchResults = {};
|
|
@@ -35205,9 +35335,24 @@ function getKnownModels(provider) {
|
|
|
35205
35335
|
{ id: "google@gemini-2.0-flash", name: "Gemini 2.0 Flash", context: "1M" }
|
|
35206
35336
|
],
|
|
35207
35337
|
openai: [
|
|
35208
|
-
{
|
|
35209
|
-
|
|
35210
|
-
|
|
35338
|
+
{
|
|
35339
|
+
id: "oai@gpt-5.3-codex",
|
|
35340
|
+
name: "GPT-5.3 Codex",
|
|
35341
|
+
context: "400K",
|
|
35342
|
+
description: "Latest coding model"
|
|
35343
|
+
},
|
|
35344
|
+
{
|
|
35345
|
+
id: "oai@gpt-5.2-codex",
|
|
35346
|
+
name: "GPT-5.2 Codex",
|
|
35347
|
+
context: "400K",
|
|
35348
|
+
description: "Coding model"
|
|
35349
|
+
},
|
|
35350
|
+
{
|
|
35351
|
+
id: "oai@gpt-5.1-codex-mini",
|
|
35352
|
+
name: "GPT-5.1 Codex Mini",
|
|
35353
|
+
context: "400K",
|
|
35354
|
+
description: "Fast coding model"
|
|
35355
|
+
},
|
|
35211
35356
|
{ id: "oai@o3", name: "o3", context: "200K", description: "Reasoning model" },
|
|
35212
35357
|
{ id: "oai@o4-mini", name: "o4-mini", context: "200K", description: "Fast reasoning model" },
|
|
35213
35358
|
{ id: "oai@gpt-4.1", name: "GPT-4.1", context: "1M", description: "Large context model" }
|
|
@@ -35215,39 +35360,102 @@ function getKnownModels(provider) {
|
|
|
35215
35360
|
xai: [
|
|
35216
35361
|
{ id: "xai@grok-4", name: "Grok 4", context: "256K" },
|
|
35217
35362
|
{ id: "xai@grok-4-fast", name: "Grok 4 Fast", context: "2M" },
|
|
35218
|
-
{
|
|
35363
|
+
{
|
|
35364
|
+
id: "xai@grok-code-fast-1",
|
|
35365
|
+
name: "Grok Code Fast 1",
|
|
35366
|
+
context: "256K",
|
|
35367
|
+
description: "Optimized for coding"
|
|
35368
|
+
}
|
|
35219
35369
|
],
|
|
35220
35370
|
minimax: [
|
|
35221
|
-
{
|
|
35371
|
+
{
|
|
35372
|
+
id: "mm@minimax-m2.1",
|
|
35373
|
+
name: "MiniMax M2.1",
|
|
35374
|
+
context: "196K",
|
|
35375
|
+
description: "Lightweight coding model"
|
|
35376
|
+
}
|
|
35222
35377
|
],
|
|
35223
35378
|
"minimax-coding": [
|
|
35224
|
-
{
|
|
35225
|
-
|
|
35379
|
+
{
|
|
35380
|
+
id: "mmc@minimax-m2.5",
|
|
35381
|
+
name: "MiniMax M2.5",
|
|
35382
|
+
context: "196K",
|
|
35383
|
+
description: "MiniMax Coding subscription model"
|
|
35384
|
+
},
|
|
35385
|
+
{
|
|
35386
|
+
id: "mmc@minimax-m2.1",
|
|
35387
|
+
name: "MiniMax M2.1",
|
|
35388
|
+
context: "196K",
|
|
35389
|
+
description: "MiniMax Coding subscription model"
|
|
35390
|
+
}
|
|
35226
35391
|
],
|
|
35227
35392
|
kimi: [
|
|
35228
35393
|
{ id: "kimi@kimi-k2-thinking-turbo", name: "Kimi K2 Thinking Turbo", context: "128K" },
|
|
35229
35394
|
{ id: "kimi@moonshot-v1-128k", name: "Moonshot V1 128K", context: "128K" }
|
|
35230
35395
|
],
|
|
35231
35396
|
"kimi-coding": [
|
|
35232
|
-
{
|
|
35397
|
+
{
|
|
35398
|
+
id: "kc@kimi-for-coding",
|
|
35399
|
+
name: "Kimi for Coding",
|
|
35400
|
+
context: "128K",
|
|
35401
|
+
description: "Kimi Coding subscription model"
|
|
35402
|
+
}
|
|
35233
35403
|
],
|
|
35234
35404
|
glm: [
|
|
35235
|
-
{
|
|
35236
|
-
|
|
35237
|
-
|
|
35405
|
+
{
|
|
35406
|
+
id: "glm@glm-5",
|
|
35407
|
+
name: "GLM-5",
|
|
35408
|
+
context: "200K",
|
|
35409
|
+
description: "Latest GLM model with reasoning"
|
|
35410
|
+
},
|
|
35411
|
+
{
|
|
35412
|
+
id: "glm@glm-4.7",
|
|
35413
|
+
name: "GLM-4.7",
|
|
35414
|
+
context: "200K",
|
|
35415
|
+
description: "GLM 4.7 with reasoning"
|
|
35416
|
+
},
|
|
35417
|
+
{
|
|
35418
|
+
id: "glm@glm-4.7-flash",
|
|
35419
|
+
name: "GLM-4.7 Flash",
|
|
35420
|
+
context: "200K",
|
|
35421
|
+
description: "Fast GLM 4.7"
|
|
35422
|
+
},
|
|
35238
35423
|
{ id: "glm@glm-4.6", name: "GLM-4.6", context: "200K" },
|
|
35239
35424
|
{ id: "glm@glm-4.5-flash", name: "GLM-4.5 Flash", context: "128K" }
|
|
35240
35425
|
],
|
|
35241
|
-
zai: [
|
|
35242
|
-
{ id: "zai@glm-4.7", name: "GLM 4.7 (Z.AI)", context: "128K" }
|
|
35243
|
-
],
|
|
35426
|
+
zai: [{ id: "zai@glm-4.7", name: "GLM 4.7 (Z.AI)", context: "128K" }],
|
|
35244
35427
|
ollamacloud: [
|
|
35245
35428
|
{ id: "oc@glm-5", name: "GLM-5", context: "203K", description: "GLM-5 on OllamaCloud" },
|
|
35246
|
-
{
|
|
35247
|
-
|
|
35248
|
-
|
|
35249
|
-
|
|
35250
|
-
|
|
35429
|
+
{
|
|
35430
|
+
id: "oc@deepseek-v3.2",
|
|
35431
|
+
name: "DeepSeek V3.2",
|
|
35432
|
+
context: "164K",
|
|
35433
|
+
description: "DeepSeek V3.2 on OllamaCloud"
|
|
35434
|
+
},
|
|
35435
|
+
{
|
|
35436
|
+
id: "oc@gemini-3-pro-preview",
|
|
35437
|
+
name: "Gemini 3 Pro Preview",
|
|
35438
|
+
context: "1M",
|
|
35439
|
+
description: "Gemini 3 Pro on OllamaCloud"
|
|
35440
|
+
},
|
|
35441
|
+
{
|
|
35442
|
+
id: "oc@kimi-k2.5",
|
|
35443
|
+
name: "Kimi K2.5",
|
|
35444
|
+
context: "262K",
|
|
35445
|
+
description: "Kimi K2.5 on OllamaCloud"
|
|
35446
|
+
},
|
|
35447
|
+
{
|
|
35448
|
+
id: "oc@qwen3-coder-next",
|
|
35449
|
+
name: "Qwen3 Coder Next",
|
|
35450
|
+
context: "262K",
|
|
35451
|
+
description: "Qwen3 Coder on OllamaCloud"
|
|
35452
|
+
},
|
|
35453
|
+
{
|
|
35454
|
+
id: "oc@minimax-m2.1",
|
|
35455
|
+
name: "MiniMax M2.1",
|
|
35456
|
+
context: "205K",
|
|
35457
|
+
description: "MiniMax M2.1 on OllamaCloud"
|
|
35458
|
+
}
|
|
35251
35459
|
]
|
|
35252
35460
|
};
|
|
35253
35461
|
const providerDisplay = provider.charAt(0).toUpperCase() + provider.slice(1);
|
|
@@ -35482,23 +35690,76 @@ var init_model_selector = __esm(() => {
|
|
|
35482
35690
|
ll: "LiteLLM"
|
|
35483
35691
|
};
|
|
35484
35692
|
ALL_PROVIDER_CHOICES = [
|
|
35485
|
-
{
|
|
35693
|
+
{
|
|
35694
|
+
name: "Skip (keep Claude default)",
|
|
35695
|
+
value: "skip",
|
|
35696
|
+
description: "Use native Claude model for this tier"
|
|
35697
|
+
},
|
|
35486
35698
|
{ name: "OpenRouter", value: "openrouter", description: "580+ models via unified API" },
|
|
35487
35699
|
{ name: "OpenCode Zen", value: "zen", description: "Free models, no API key needed" },
|
|
35488
|
-
{
|
|
35489
|
-
|
|
35490
|
-
|
|
35491
|
-
|
|
35492
|
-
|
|
35493
|
-
|
|
35494
|
-
{
|
|
35495
|
-
|
|
35496
|
-
|
|
35700
|
+
{
|
|
35701
|
+
name: "Google Gemini",
|
|
35702
|
+
value: "google",
|
|
35703
|
+
description: "Direct API (GEMINI_API_KEY)",
|
|
35704
|
+
envVar: "GEMINI_API_KEY"
|
|
35705
|
+
},
|
|
35706
|
+
{
|
|
35707
|
+
name: "OpenAI",
|
|
35708
|
+
value: "openai",
|
|
35709
|
+
description: "Direct API (OPENAI_API_KEY)",
|
|
35710
|
+
envVar: "OPENAI_API_KEY"
|
|
35711
|
+
},
|
|
35712
|
+
{
|
|
35713
|
+
name: "xAI / Grok",
|
|
35714
|
+
value: "xai",
|
|
35715
|
+
description: "Direct API (XAI_API_KEY)",
|
|
35716
|
+
envVar: "XAI_API_KEY"
|
|
35717
|
+
},
|
|
35718
|
+
{
|
|
35719
|
+
name: "MiniMax",
|
|
35720
|
+
value: "minimax",
|
|
35721
|
+
description: "Direct API (MINIMAX_API_KEY)",
|
|
35722
|
+
envVar: "MINIMAX_API_KEY"
|
|
35723
|
+
},
|
|
35724
|
+
{
|
|
35725
|
+
name: "MiniMax Coding",
|
|
35726
|
+
value: "minimax-coding",
|
|
35727
|
+
description: "MiniMax Coding subscription (MINIMAX_CODING_API_KEY)",
|
|
35728
|
+
envVar: "MINIMAX_CODING_API_KEY"
|
|
35729
|
+
},
|
|
35730
|
+
{
|
|
35731
|
+
name: "Kimi / Moonshot",
|
|
35732
|
+
value: "kimi",
|
|
35733
|
+
description: "Direct API (MOONSHOT_API_KEY)",
|
|
35734
|
+
envVar: "MOONSHOT_API_KEY"
|
|
35735
|
+
},
|
|
35736
|
+
{
|
|
35737
|
+
name: "Kimi Coding",
|
|
35738
|
+
value: "kimi-coding",
|
|
35739
|
+
description: "Kimi Coding subscription (KIMI_CODING_API_KEY)",
|
|
35740
|
+
envVar: "KIMI_CODING_API_KEY"
|
|
35741
|
+
},
|
|
35742
|
+
{
|
|
35743
|
+
name: "GLM / Zhipu",
|
|
35744
|
+
value: "glm",
|
|
35745
|
+
description: "Direct API (ZHIPU_API_KEY)",
|
|
35746
|
+
envVar: "ZHIPU_API_KEY"
|
|
35747
|
+
},
|
|
35748
|
+
{
|
|
35749
|
+
name: "GLM Coding Plan",
|
|
35750
|
+
value: "glm-coding",
|
|
35751
|
+
description: "GLM Coding subscription (GLM_CODING_API_KEY)",
|
|
35752
|
+
envVar: "GLM_CODING_API_KEY"
|
|
35753
|
+
},
|
|
35497
35754
|
{ name: "Z.AI", value: "zai", description: "Z.AI API (ZAI_API_KEY)", envVar: "ZAI_API_KEY" },
|
|
35498
35755
|
{ name: "OllamaCloud", value: "ollamacloud", description: "Cloud models (OLLAMA_API_KEY)" },
|
|
35499
35756
|
{ name: "Ollama (local)", value: "ollama", description: "Local Ollama instance" },
|
|
35500
35757
|
{ name: "LM Studio (local)", value: "lmstudio", description: "Local LM Studio instance" },
|
|
35501
|
-
{
|
|
35758
|
+
{
|
|
35759
|
+
name: "Enter custom model",
|
|
35760
|
+
value: "custom",
|
|
35761
|
+
description: "Type a provider@model specification"
|
|
35762
|
+
}
|
|
35502
35763
|
];
|
|
35503
35764
|
PROVIDER_MODEL_PREFIX = {
|
|
35504
35765
|
google: "google@",
|
|
@@ -41355,10 +41616,12 @@ var init_openai_adapter = __esm(() => {
|
|
|
41355
41616
|
result.push({
|
|
41356
41617
|
type: "message",
|
|
41357
41618
|
role: msg.role,
|
|
41358
|
-
content: [
|
|
41359
|
-
|
|
41360
|
-
|
|
41361
|
-
|
|
41619
|
+
content: [
|
|
41620
|
+
{
|
|
41621
|
+
type: msg.role === "user" ? "input_text" : "output_text",
|
|
41622
|
+
text: msg.content
|
|
41623
|
+
}
|
|
41624
|
+
]
|
|
41362
41625
|
});
|
|
41363
41626
|
continue;
|
|
41364
41627
|
}
|
|
@@ -62098,7 +62361,7 @@ class LocalTransport {
|
|
|
62098
62361
|
this.config = config3;
|
|
62099
62362
|
this.modelName = modelName;
|
|
62100
62363
|
this.name = config3.name;
|
|
62101
|
-
this.displayName =
|
|
62364
|
+
this.displayName = DISPLAY_NAMES2[config3.name] || "Local";
|
|
62102
62365
|
this.concurrency = options?.concurrency;
|
|
62103
62366
|
const envContextWindow = process.env.CLAUDISH_CONTEXT_WINDOW;
|
|
62104
62367
|
if (envContextWindow) {
|
|
@@ -62279,7 +62542,7 @@ class LocalTransport {
|
|
|
62279
62542
|
}
|
|
62280
62543
|
}
|
|
62281
62544
|
}
|
|
62282
|
-
var localProviderAgent,
|
|
62545
|
+
var localProviderAgent, DISPLAY_NAMES2;
|
|
62283
62546
|
var init_local = __esm(() => {
|
|
62284
62547
|
init_local_queue();
|
|
62285
62548
|
init_logger();
|
|
@@ -62290,7 +62553,7 @@ var init_local = __esm(() => {
|
|
|
62290
62553
|
keepAliveTimeout: 30000,
|
|
62291
62554
|
keepAliveMaxTimeout: 600000
|
|
62292
62555
|
});
|
|
62293
|
-
|
|
62556
|
+
DISPLAY_NAMES2 = {
|
|
62294
62557
|
ollama: "Ollama",
|
|
62295
62558
|
lmstudio: "LM Studio",
|
|
62296
62559
|
vllm: "vLLM",
|
|
@@ -63981,7 +64244,10 @@ data: ${JSON.stringify(data)}
|
|
|
63981
64244
|
}
|
|
63982
64245
|
if (part.text) {
|
|
63983
64246
|
if (thinkingStarted) {
|
|
63984
|
-
send("content_block_stop", {
|
|
64247
|
+
send("content_block_stop", {
|
|
64248
|
+
type: "content_block_stop",
|
|
64249
|
+
index: thinkingIdx
|
|
64250
|
+
});
|
|
63985
64251
|
thinkingStarted = false;
|
|
63986
64252
|
}
|
|
63987
64253
|
let cleanedText = part.text;
|
|
@@ -64011,7 +64277,10 @@ data: ${JSON.stringify(data)}
|
|
|
64011
64277
|
}
|
|
64012
64278
|
if (part.functionCall) {
|
|
64013
64279
|
if (thinkingStarted) {
|
|
64014
|
-
send("content_block_stop", {
|
|
64280
|
+
send("content_block_stop", {
|
|
64281
|
+
type: "content_block_stop",
|
|
64282
|
+
index: thinkingIdx
|
|
64283
|
+
});
|
|
64015
64284
|
thinkingStarted = false;
|
|
64016
64285
|
}
|
|
64017
64286
|
if (textStarted) {
|
|
@@ -64943,7 +65212,10 @@ var init_anthropic_passthrough_adapter = __esm(() => {
|
|
|
64943
65212
|
const filteredContent = message.content.map((block) => {
|
|
64944
65213
|
if (block.type === "tool_result" && Array.isArray(block.content)) {
|
|
64945
65214
|
const filtered = block.content.filter((c) => c.type !== "tool_reference");
|
|
64946
|
-
return {
|
|
65215
|
+
return {
|
|
65216
|
+
...block,
|
|
65217
|
+
content: filtered.length > 0 ? filtered : [{ type: "text", text: "" }]
|
|
65218
|
+
};
|
|
64947
65219
|
}
|
|
64948
65220
|
return block;
|
|
64949
65221
|
}).filter((block) => block.type !== "tool_reference");
|
|
@@ -65250,6 +65522,196 @@ var init_pricing_cache = __esm(() => {
|
|
|
65250
65522
|
};
|
|
65251
65523
|
});
|
|
65252
65524
|
|
|
65525
|
+
// src/handlers/fallback-handler.ts
|
|
65526
|
+
class FallbackHandler {
|
|
65527
|
+
candidates;
|
|
65528
|
+
constructor(candidates) {
|
|
65529
|
+
this.candidates = candidates;
|
|
65530
|
+
}
|
|
65531
|
+
async handle(c, payload) {
|
|
65532
|
+
const errors6 = [];
|
|
65533
|
+
for (let i = 0;i < this.candidates.length; i++) {
|
|
65534
|
+
const { name, handler } = this.candidates[i];
|
|
65535
|
+
const isLast = i === this.candidates.length - 1;
|
|
65536
|
+
try {
|
|
65537
|
+
const response = await handler.handle(c, payload);
|
|
65538
|
+
if (response.ok) {
|
|
65539
|
+
if (errors6.length > 0) {
|
|
65540
|
+
logStderr(`[Fallback] ${name} succeeded after ${errors6.length} failed attempt(s)`);
|
|
65541
|
+
}
|
|
65542
|
+
return response;
|
|
65543
|
+
}
|
|
65544
|
+
const errorBody = await response.clone().text();
|
|
65545
|
+
if (!isRetryableError(response.status, errorBody)) {
|
|
65546
|
+
if (errors6.length > 0) {
|
|
65547
|
+
errors6.push({ provider: name, status: response.status, message: errorBody });
|
|
65548
|
+
return this.formatCombinedError(c, errors6, payload.model);
|
|
65549
|
+
}
|
|
65550
|
+
return response;
|
|
65551
|
+
}
|
|
65552
|
+
errors6.push({ provider: name, status: response.status, message: errorBody });
|
|
65553
|
+
if (!isLast) {
|
|
65554
|
+
logStderr(`[Fallback] ${name} failed (HTTP ${response.status}), trying next provider...`);
|
|
65555
|
+
}
|
|
65556
|
+
} catch (err) {
|
|
65557
|
+
errors6.push({ provider: name, status: 0, message: err.message });
|
|
65558
|
+
if (!isLast) {
|
|
65559
|
+
logStderr(`[Fallback] ${name} error: ${err.message}, trying next provider...`);
|
|
65560
|
+
}
|
|
65561
|
+
}
|
|
65562
|
+
}
|
|
65563
|
+
return this.formatCombinedError(c, errors6, payload.model);
|
|
65564
|
+
}
|
|
65565
|
+
formatCombinedError(c, errors6, modelName) {
|
|
65566
|
+
const summary = errors6.map((e) => ` ${e.provider}: HTTP ${e.status || "ERR"} — ${truncate(parseErrorMessage(e.message), 150)}`).join(`
|
|
65567
|
+
`);
|
|
65568
|
+
logStderr(`[Fallback] All ${errors6.length} provider(s) failed for ${modelName || "model"}:
|
|
65569
|
+
${summary}`);
|
|
65570
|
+
return c.json({
|
|
65571
|
+
error: {
|
|
65572
|
+
type: "all_providers_failed",
|
|
65573
|
+
message: `All ${errors6.length} providers failed for model '${modelName || "unknown"}'`,
|
|
65574
|
+
attempts: errors6.map((e) => ({
|
|
65575
|
+
provider: e.provider,
|
|
65576
|
+
status: e.status,
|
|
65577
|
+
error: truncate(parseErrorMessage(e.message), 200)
|
|
65578
|
+
}))
|
|
65579
|
+
}
|
|
65580
|
+
}, 502);
|
|
65581
|
+
}
|
|
65582
|
+
async shutdown() {
|
|
65583
|
+
for (const { handler } of this.candidates) {
|
|
65584
|
+
if (typeof handler.shutdown === "function") {
|
|
65585
|
+
await handler.shutdown();
|
|
65586
|
+
}
|
|
65587
|
+
}
|
|
65588
|
+
}
|
|
65589
|
+
}
|
|
65590
|
+
function isRetryableError(status, errorBody) {
|
|
65591
|
+
if (status === 401 || status === 403)
|
|
65592
|
+
return true;
|
|
65593
|
+
if (status === 402)
|
|
65594
|
+
return true;
|
|
65595
|
+
if (status === 404)
|
|
65596
|
+
return true;
|
|
65597
|
+
if (status === 429)
|
|
65598
|
+
return true;
|
|
65599
|
+
const lower = errorBody.toLowerCase();
|
|
65600
|
+
if (status === 422) {
|
|
65601
|
+
if (lower.includes("not available") || lower.includes("model not found") || lower.includes("not supported")) {
|
|
65602
|
+
return true;
|
|
65603
|
+
}
|
|
65604
|
+
}
|
|
65605
|
+
if (status === 400) {
|
|
65606
|
+
if (lower.includes("model not found") || lower.includes("not registered") || lower.includes("does not exist") || lower.includes("unknown model") || lower.includes("unsupported model")) {
|
|
65607
|
+
return true;
|
|
65608
|
+
}
|
|
65609
|
+
}
|
|
65610
|
+
if (status === 500) {
|
|
65611
|
+
if (lower.includes("insufficient balance") || lower.includes("insufficient credit") || lower.includes("quota exceeded") || lower.includes("billing")) {
|
|
65612
|
+
return true;
|
|
65613
|
+
}
|
|
65614
|
+
}
|
|
65615
|
+
return false;
|
|
65616
|
+
}
|
|
65617
|
+
function parseErrorMessage(body) {
|
|
65618
|
+
try {
|
|
65619
|
+
const parsed = JSON.parse(body);
|
|
65620
|
+
if (typeof parsed.error === "string")
|
|
65621
|
+
return parsed.error;
|
|
65622
|
+
if (typeof parsed.error?.message === "string")
|
|
65623
|
+
return parsed.error.message;
|
|
65624
|
+
if (typeof parsed.message === "string")
|
|
65625
|
+
return parsed.message;
|
|
65626
|
+
} catch {}
|
|
65627
|
+
return body;
|
|
65628
|
+
}
|
|
65629
|
+
function truncate(s, max) {
|
|
65630
|
+
return s.length > max ? s.slice(0, max) + "..." : s;
|
|
65631
|
+
}
|
|
65632
|
+
var init_fallback_handler = __esm(() => {
|
|
65633
|
+
init_logger();
|
|
65634
|
+
});
|
|
65635
|
+
|
|
65636
|
+
// src/providers/routing-rules.ts
|
|
65637
|
+
function loadRoutingRules() {
|
|
65638
|
+
const local = loadLocalConfig();
|
|
65639
|
+
if (local?.routing && Object.keys(local.routing).length > 0) {
|
|
65640
|
+
validateRoutingRules(local.routing);
|
|
65641
|
+
return local.routing;
|
|
65642
|
+
}
|
|
65643
|
+
const global_ = loadConfig();
|
|
65644
|
+
if (global_.routing && Object.keys(global_.routing).length > 0) {
|
|
65645
|
+
validateRoutingRules(global_.routing);
|
|
65646
|
+
return global_.routing;
|
|
65647
|
+
}
|
|
65648
|
+
return null;
|
|
65649
|
+
}
|
|
65650
|
+
function validateRoutingRules(rules) {
|
|
65651
|
+
for (const key of Object.keys(rules)) {
|
|
65652
|
+
if (key !== "*" && (key.match(/\*/g) || []).length > 1) {
|
|
65653
|
+
console.error(`[claudish] Warning: routing pattern "${key}" has multiple wildcards — only single * is supported. This pattern may not match as expected.`);
|
|
65654
|
+
}
|
|
65655
|
+
const entries = rules[key];
|
|
65656
|
+
if (!Array.isArray(entries) || entries.length === 0) {
|
|
65657
|
+
console.error(`[claudish] Warning: routing rule "${key}" has no provider entries — models matching this pattern will have no fallback chain.`);
|
|
65658
|
+
}
|
|
65659
|
+
}
|
|
65660
|
+
}
|
|
65661
|
+
function matchRoutingRule(modelName, rules) {
|
|
65662
|
+
if (rules[modelName])
|
|
65663
|
+
return rules[modelName];
|
|
65664
|
+
const globKeys = Object.keys(rules).filter((k) => k !== "*" && k.includes("*")).sort((a, b) => b.length - a.length);
|
|
65665
|
+
for (const pattern of globKeys) {
|
|
65666
|
+
if (globMatch(pattern, modelName))
|
|
65667
|
+
return rules[pattern];
|
|
65668
|
+
}
|
|
65669
|
+
if (rules["*"])
|
|
65670
|
+
return rules["*"];
|
|
65671
|
+
return null;
|
|
65672
|
+
}
|
|
65673
|
+
function buildRoutingChain(entries, originalModelName) {
|
|
65674
|
+
const routes = [];
|
|
65675
|
+
for (const entry of entries) {
|
|
65676
|
+
const atIdx = entry.indexOf("@");
|
|
65677
|
+
let providerRaw;
|
|
65678
|
+
let modelName;
|
|
65679
|
+
if (atIdx !== -1) {
|
|
65680
|
+
providerRaw = entry.slice(0, atIdx);
|
|
65681
|
+
modelName = entry.slice(atIdx + 1);
|
|
65682
|
+
} else {
|
|
65683
|
+
providerRaw = entry;
|
|
65684
|
+
modelName = originalModelName;
|
|
65685
|
+
}
|
|
65686
|
+
const provider = PROVIDER_SHORTCUTS[providerRaw.toLowerCase()] ?? providerRaw.toLowerCase();
|
|
65687
|
+
let modelSpec;
|
|
65688
|
+
if (provider === "openrouter") {
|
|
65689
|
+
const resolution = resolveModelNameSync(modelName, "openrouter");
|
|
65690
|
+
modelSpec = resolution.resolvedId;
|
|
65691
|
+
} else {
|
|
65692
|
+
const prefix = PROVIDER_TO_PREFIX[provider] ?? provider;
|
|
65693
|
+
modelSpec = `${prefix}@${modelName}`;
|
|
65694
|
+
}
|
|
65695
|
+
const displayName = DISPLAY_NAMES[provider] ?? provider;
|
|
65696
|
+
routes.push({ provider, modelSpec, displayName });
|
|
65697
|
+
}
|
|
65698
|
+
return routes;
|
|
65699
|
+
}
|
|
65700
|
+
function globMatch(pattern, value) {
|
|
65701
|
+
const star = pattern.indexOf("*");
|
|
65702
|
+
if (star === -1)
|
|
65703
|
+
return pattern === value;
|
|
65704
|
+
const prefix = pattern.slice(0, star);
|
|
65705
|
+
const suffix = pattern.slice(star + 1);
|
|
65706
|
+
return value.startsWith(prefix) && value.endsWith(suffix) && value.length >= prefix.length + suffix.length;
|
|
65707
|
+
}
|
|
65708
|
+
var init_routing_rules = __esm(() => {
|
|
65709
|
+
init_profile_config();
|
|
65710
|
+
init_auto_route();
|
|
65711
|
+
init_model_parser();
|
|
65712
|
+
init_model_catalog_resolver();
|
|
65713
|
+
});
|
|
65714
|
+
|
|
65253
65715
|
// src/proxy-server.ts
|
|
65254
65716
|
var exports_proxy_server = {};
|
|
65255
65717
|
__export(exports_proxy_server, {
|
|
@@ -65267,7 +65729,10 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
|
|
|
65267
65729
|
if (!openRouterHandlers.has(modelId)) {
|
|
65268
65730
|
const orProvider = new OpenRouterProvider(openrouterApiKey || "");
|
|
65269
65731
|
const orAdapter = new OpenRouterAdapter(modelId);
|
|
65270
|
-
openRouterHandlers.set(modelId, new ComposedHandler(orProvider, modelId, modelId, port, {
|
|
65732
|
+
openRouterHandlers.set(modelId, new ComposedHandler(orProvider, modelId, modelId, port, {
|
|
65733
|
+
adapter: orAdapter,
|
|
65734
|
+
isInteractive: options.isInteractive
|
|
65735
|
+
}));
|
|
65271
65736
|
}
|
|
65272
65737
|
return openRouterHandlers.get(modelId);
|
|
65273
65738
|
};
|
|
@@ -65280,7 +65745,9 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
|
|
|
65280
65745
|
const modelId = targetModel.replace(/^poe:/, "");
|
|
65281
65746
|
if (!poeHandlers.has(modelId)) {
|
|
65282
65747
|
const poeTransport = new PoeProvider(poeApiKey);
|
|
65283
|
-
poeHandlers.set(modelId, new ComposedHandler(poeTransport, modelId, modelId, port, {
|
|
65748
|
+
poeHandlers.set(modelId, new ComposedHandler(poeTransport, modelId, modelId, port, {
|
|
65749
|
+
isInteractive: options.isInteractive
|
|
65750
|
+
}));
|
|
65284
65751
|
}
|
|
65285
65752
|
return poeHandlers.get(modelId);
|
|
65286
65753
|
};
|
|
@@ -65495,6 +65962,8 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
|
|
|
65495
65962
|
log("[Proxy] LiteLLM model cache pre-warmed for auto-routing");
|
|
65496
65963
|
}).catch(() => {});
|
|
65497
65964
|
}
|
|
65965
|
+
const customRoutingRules = loadRoutingRules();
|
|
65966
|
+
const fallbackHandlerCache = new Map;
|
|
65498
65967
|
const getHandlerForRequest = (requestedModel) => {
|
|
65499
65968
|
if (monitorMode)
|
|
65500
65969
|
return nativeHandler;
|
|
@@ -65522,6 +65991,40 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
|
|
|
65522
65991
|
}
|
|
65523
65992
|
}
|
|
65524
65993
|
}
|
|
65994
|
+
{
|
|
65995
|
+
const parsedForFallback = parseModelSpec(target);
|
|
65996
|
+
if (!parsedForFallback.isExplicitProvider && parsedForFallback.provider !== "native-anthropic" && !isPoeModel(target)) {
|
|
65997
|
+
const cacheKey2 = `fallback:${target}`;
|
|
65998
|
+
if (fallbackHandlerCache.has(cacheKey2)) {
|
|
65999
|
+
return fallbackHandlerCache.get(cacheKey2);
|
|
66000
|
+
}
|
|
66001
|
+
const matchedEntries = customRoutingRules ? matchRoutingRule(parsedForFallback.model, customRoutingRules) : null;
|
|
66002
|
+
const chain = matchedEntries ? buildRoutingChain(matchedEntries, parsedForFallback.model) : getFallbackChain(parsedForFallback.model, parsedForFallback.provider);
|
|
66003
|
+
if (chain.length > 0) {
|
|
66004
|
+
const candidates = [];
|
|
66005
|
+
for (const route of chain) {
|
|
66006
|
+
let handler = null;
|
|
66007
|
+
if (route.provider === "openrouter") {
|
|
66008
|
+
handler = getOpenRouterHandler(route.modelSpec);
|
|
66009
|
+
} else {
|
|
66010
|
+
handler = getRemoteProviderHandler(route.modelSpec);
|
|
66011
|
+
}
|
|
66012
|
+
if (handler) {
|
|
66013
|
+
candidates.push({ name: route.displayName, handler });
|
|
66014
|
+
}
|
|
66015
|
+
}
|
|
66016
|
+
if (candidates.length > 0) {
|
|
66017
|
+
const resultHandler = candidates.length > 1 ? new FallbackHandler(candidates) : candidates[0].handler;
|
|
66018
|
+
fallbackHandlerCache.set(cacheKey2, resultHandler);
|
|
66019
|
+
if (!options.quiet && candidates.length > 1) {
|
|
66020
|
+
const source = matchedEntries ? "[Custom]" : "[Fallback]";
|
|
66021
|
+
logStderr(`${source} ${candidates.length} providers for ${parsedForFallback.model}: ${candidates.map((c) => c.name).join(" → ")}`);
|
|
66022
|
+
}
|
|
66023
|
+
return resultHandler;
|
|
66024
|
+
}
|
|
66025
|
+
}
|
|
66026
|
+
}
|
|
66027
|
+
}
|
|
65525
66028
|
if (isPoeModel(target)) {
|
|
65526
66029
|
const poeHandler = getPoeHandler(target);
|
|
65527
66030
|
if (poeHandler) {
|
|
@@ -65633,6 +66136,9 @@ var init_proxy_server = __esm(() => {
|
|
|
65633
66136
|
init_pricing_cache();
|
|
65634
66137
|
init_model_loader();
|
|
65635
66138
|
init_model_catalog_resolver();
|
|
66139
|
+
init_fallback_handler();
|
|
66140
|
+
init_auto_route();
|
|
66141
|
+
init_routing_rules();
|
|
65636
66142
|
});
|
|
65637
66143
|
|
|
65638
66144
|
// src/index.ts
|
package/package.json
CHANGED
package/recommended-models.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.2.0",
|
|
3
|
-
"lastUpdated": "2026-03-
|
|
3
|
+
"lastUpdated": "2026-03-15",
|
|
4
4
|
"source": "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
|
|
5
5
|
"models": [
|
|
6
6
|
{
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"category": "programming",
|
|
13
13
|
"priority": 1,
|
|
14
14
|
"pricing": {
|
|
15
|
-
"input": "$0.
|
|
15
|
+
"input": "$0.25/1M",
|
|
16
16
|
"output": "$1.20/1M",
|
|
17
|
-
"average": "$0.
|
|
17
|
+
"average": "$0.72/1M"
|
|
18
18
|
},
|
|
19
19
|
"context": "196K",
|
|
20
20
|
"maxOutputTokens": 196608,
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
"category": "reasoning",
|
|
57
57
|
"priority": 3,
|
|
58
58
|
"pricing": {
|
|
59
|
-
"input": "$0.
|
|
60
|
-
"output": "$2.
|
|
61
|
-
"average": "$1.
|
|
59
|
+
"input": "$0.72/1M",
|
|
60
|
+
"output": "$2.30/1M",
|
|
61
|
+
"average": "$1.51/1M"
|
|
62
62
|
},
|
|
63
63
|
"context": "202K",
|
|
64
|
-
"maxOutputTokens":
|
|
64
|
+
"maxOutputTokens": 131072,
|
|
65
65
|
"modality": "text->text",
|
|
66
66
|
"supportsTools": true,
|
|
67
67
|
"supportsReasoning": true,
|