claudish 4.6.1 → 4.6.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.
- package/dist/index.js +322 -267
- package/package.json +1 -1
- package/recommended-models.json +6 -6
package/dist/index.js
CHANGED
|
@@ -30888,6 +30888,217 @@ var init_dist8 = __esm(() => {
|
|
|
30888
30888
|
init_dist7();
|
|
30889
30889
|
});
|
|
30890
30890
|
|
|
30891
|
+
// src/model-loader.ts
|
|
30892
|
+
import { readFileSync as readFileSync5, existsSync as existsSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "node:fs";
|
|
30893
|
+
import { join as join6, dirname as dirname2 } from "node:path";
|
|
30894
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
30895
|
+
import { homedir as homedir5 } from "node:os";
|
|
30896
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
30897
|
+
function getRecommendedModelsPath() {
|
|
30898
|
+
return join6(__dirname3, "../recommended-models.json");
|
|
30899
|
+
}
|
|
30900
|
+
function loadRecommendedModelsJSON() {
|
|
30901
|
+
if (_cachedRecommendedModels) {
|
|
30902
|
+
return _cachedRecommendedModels;
|
|
30903
|
+
}
|
|
30904
|
+
const jsonPath = getRecommendedModelsPath();
|
|
30905
|
+
if (!existsSync6(jsonPath)) {
|
|
30906
|
+
throw new Error(`recommended-models.json not found at ${jsonPath}. ` + `Run 'claudish --update-models' to fetch the latest model list.`);
|
|
30907
|
+
}
|
|
30908
|
+
try {
|
|
30909
|
+
const jsonContent = readFileSync5(jsonPath, "utf-8");
|
|
30910
|
+
_cachedRecommendedModels = JSON.parse(jsonContent);
|
|
30911
|
+
return _cachedRecommendedModels;
|
|
30912
|
+
} catch (error46) {
|
|
30913
|
+
throw new Error(`Failed to parse recommended-models.json: ${error46}`);
|
|
30914
|
+
}
|
|
30915
|
+
}
|
|
30916
|
+
function loadModelInfo() {
|
|
30917
|
+
if (_cachedModelInfo) {
|
|
30918
|
+
return _cachedModelInfo;
|
|
30919
|
+
}
|
|
30920
|
+
const data = loadRecommendedModelsJSON();
|
|
30921
|
+
const modelInfo = {};
|
|
30922
|
+
for (const model of data.models) {
|
|
30923
|
+
modelInfo[model.id] = {
|
|
30924
|
+
name: model.name,
|
|
30925
|
+
description: model.description,
|
|
30926
|
+
priority: model.priority,
|
|
30927
|
+
provider: model.provider
|
|
30928
|
+
};
|
|
30929
|
+
}
|
|
30930
|
+
modelInfo.custom = {
|
|
30931
|
+
name: "Custom Model",
|
|
30932
|
+
description: "Enter any OpenRouter model ID manually",
|
|
30933
|
+
priority: 999,
|
|
30934
|
+
provider: "Custom"
|
|
30935
|
+
};
|
|
30936
|
+
_cachedModelInfo = modelInfo;
|
|
30937
|
+
return modelInfo;
|
|
30938
|
+
}
|
|
30939
|
+
function getAvailableModels() {
|
|
30940
|
+
if (_cachedModelIds) {
|
|
30941
|
+
return _cachedModelIds;
|
|
30942
|
+
}
|
|
30943
|
+
const data = loadRecommendedModelsJSON();
|
|
30944
|
+
const modelIds = data.models.sort((a, b) => a.priority - b.priority).map((m) => m.id);
|
|
30945
|
+
const result = [...modelIds, "custom"];
|
|
30946
|
+
_cachedModelIds = result;
|
|
30947
|
+
return result;
|
|
30948
|
+
}
|
|
30949
|
+
function getCachedOpenRouterModels() {
|
|
30950
|
+
return _cachedOpenRouterModels;
|
|
30951
|
+
}
|
|
30952
|
+
async function ensureOpenRouterModelsLoaded() {
|
|
30953
|
+
if (_cachedOpenRouterModels)
|
|
30954
|
+
return _cachedOpenRouterModels;
|
|
30955
|
+
try {
|
|
30956
|
+
const response = await fetch("https://openrouter.ai/api/v1/models");
|
|
30957
|
+
if (response.ok) {
|
|
30958
|
+
const data = await response.json();
|
|
30959
|
+
_cachedOpenRouterModels = data.data || [];
|
|
30960
|
+
return _cachedOpenRouterModels;
|
|
30961
|
+
}
|
|
30962
|
+
} catch {}
|
|
30963
|
+
return [];
|
|
30964
|
+
}
|
|
30965
|
+
async function fetchModelContextWindow(modelId) {
|
|
30966
|
+
if (_cachedOpenRouterModels) {
|
|
30967
|
+
const model = _cachedOpenRouterModels.find((m) => m.id === modelId);
|
|
30968
|
+
if (model) {
|
|
30969
|
+
return model.context_length || model.top_provider?.context_length || 200000;
|
|
30970
|
+
}
|
|
30971
|
+
}
|
|
30972
|
+
try {
|
|
30973
|
+
const response = await fetch("https://openrouter.ai/api/v1/models");
|
|
30974
|
+
if (response.ok) {
|
|
30975
|
+
const data = await response.json();
|
|
30976
|
+
_cachedOpenRouterModels = data.data;
|
|
30977
|
+
const model = _cachedOpenRouterModels?.find((m) => m.id === modelId);
|
|
30978
|
+
if (model) {
|
|
30979
|
+
return model.context_length || model.top_provider?.context_length || 200000;
|
|
30980
|
+
}
|
|
30981
|
+
}
|
|
30982
|
+
} catch (error46) {}
|
|
30983
|
+
try {
|
|
30984
|
+
const data = loadRecommendedModelsJSON();
|
|
30985
|
+
const model = data.models.find((m) => m.id === modelId);
|
|
30986
|
+
if (model && model.context) {
|
|
30987
|
+
const ctxStr = model.context.toUpperCase();
|
|
30988
|
+
if (ctxStr.includes("K")) {
|
|
30989
|
+
return parseFloat(ctxStr.replace("K", "")) * 1000;
|
|
30990
|
+
}
|
|
30991
|
+
if (ctxStr.includes("M")) {
|
|
30992
|
+
return parseFloat(ctxStr.replace("M", "")) * 1e6;
|
|
30993
|
+
}
|
|
30994
|
+
const val = parseInt(ctxStr);
|
|
30995
|
+
if (!isNaN(val))
|
|
30996
|
+
return val;
|
|
30997
|
+
}
|
|
30998
|
+
} catch (e) {}
|
|
30999
|
+
return 200000;
|
|
31000
|
+
}
|
|
31001
|
+
async function doesModelSupportReasoning(modelId) {
|
|
31002
|
+
if (!_cachedOpenRouterModels) {
|
|
31003
|
+
await fetchModelContextWindow(modelId);
|
|
31004
|
+
}
|
|
31005
|
+
if (_cachedOpenRouterModels) {
|
|
31006
|
+
const model = _cachedOpenRouterModels.find((m) => m.id === modelId);
|
|
31007
|
+
if (model && model.supported_parameters) {
|
|
31008
|
+
return model.supported_parameters.includes("include_reasoning") || model.supported_parameters.includes("reasoning") || model.id.includes("o1") || model.id.includes("o3") || model.id.includes("r1");
|
|
31009
|
+
}
|
|
31010
|
+
}
|
|
31011
|
+
return false;
|
|
31012
|
+
}
|
|
31013
|
+
async function fetchLiteLLMModels(baseUrl, apiKey) {
|
|
31014
|
+
const hash2 = createHash2("sha256").update(baseUrl).digest("hex").substring(0, 16);
|
|
31015
|
+
const cacheDir = join6(homedir5(), ".claudish");
|
|
31016
|
+
const cachePath = join6(cacheDir, `litellm-models-${hash2}.json`);
|
|
31017
|
+
if (existsSync6(cachePath)) {
|
|
31018
|
+
try {
|
|
31019
|
+
const cacheData = JSON.parse(readFileSync5(cachePath, "utf-8"));
|
|
31020
|
+
const timestamp = new Date(cacheData.timestamp);
|
|
31021
|
+
const now = new Date;
|
|
31022
|
+
const ageInHours = (now.getTime() - timestamp.getTime()) / (1000 * 60 * 60);
|
|
31023
|
+
if (ageInHours < LITELLM_CACHE_MAX_AGE_HOURS) {
|
|
31024
|
+
return cacheData.models;
|
|
31025
|
+
}
|
|
31026
|
+
} catch {}
|
|
31027
|
+
}
|
|
31028
|
+
try {
|
|
31029
|
+
const url2 = `${baseUrl.replace(/\/$/, "")}/model_group/info`;
|
|
31030
|
+
const response = await fetch(url2, {
|
|
31031
|
+
headers: {
|
|
31032
|
+
Authorization: `Bearer ${apiKey}`
|
|
31033
|
+
},
|
|
31034
|
+
signal: AbortSignal.timeout(1e4)
|
|
31035
|
+
});
|
|
31036
|
+
if (!response.ok) {
|
|
31037
|
+
console.error(`Failed to fetch LiteLLM models: ${response.status} ${response.statusText}`);
|
|
31038
|
+
if (existsSync6(cachePath)) {
|
|
31039
|
+
try {
|
|
31040
|
+
const cacheData2 = JSON.parse(readFileSync5(cachePath, "utf-8"));
|
|
31041
|
+
return cacheData2.models;
|
|
31042
|
+
} catch {
|
|
31043
|
+
return [];
|
|
31044
|
+
}
|
|
31045
|
+
}
|
|
31046
|
+
return [];
|
|
31047
|
+
}
|
|
31048
|
+
const responseData = await response.json();
|
|
31049
|
+
const rawModels = responseData.data || responseData;
|
|
31050
|
+
const transformedModels = rawModels.filter((m) => m.mode === "chat" && m.supports_function_calling).map((m) => {
|
|
31051
|
+
const inputCostPerM = (m.input_cost_per_token || 0) * 1e6;
|
|
31052
|
+
const outputCostPerM = (m.output_cost_per_token || 0) * 1e6;
|
|
31053
|
+
const avgCost = (inputCostPerM + outputCostPerM) / 2;
|
|
31054
|
+
const isFree = inputCostPerM === 0 && outputCostPerM === 0;
|
|
31055
|
+
const contextLength = m.max_input_tokens || 128000;
|
|
31056
|
+
const contextStr = contextLength >= 1e6 ? `${Math.round(contextLength / 1e6)}M` : `${Math.round(contextLength / 1000)}K`;
|
|
31057
|
+
return {
|
|
31058
|
+
id: `litellm@${m.model_group}`,
|
|
31059
|
+
name: m.model_group,
|
|
31060
|
+
description: `LiteLLM model (providers: ${m.providers.join(", ")})`,
|
|
31061
|
+
provider: "LiteLLM",
|
|
31062
|
+
pricing: {
|
|
31063
|
+
input: isFree ? "FREE" : `$${inputCostPerM.toFixed(2)}`,
|
|
31064
|
+
output: isFree ? "FREE" : `$${outputCostPerM.toFixed(2)}`,
|
|
31065
|
+
average: isFree ? "FREE" : `$${avgCost.toFixed(2)}/1M`
|
|
31066
|
+
},
|
|
31067
|
+
context: contextStr,
|
|
31068
|
+
contextLength,
|
|
31069
|
+
supportsTools: m.supports_function_calling || false,
|
|
31070
|
+
supportsReasoning: m.supports_reasoning || false,
|
|
31071
|
+
supportsVision: m.supports_vision || false,
|
|
31072
|
+
isFree,
|
|
31073
|
+
source: "LiteLLM"
|
|
31074
|
+
};
|
|
31075
|
+
});
|
|
31076
|
+
mkdirSync4(cacheDir, { recursive: true });
|
|
31077
|
+
const cacheData = {
|
|
31078
|
+
timestamp: new Date().toISOString(),
|
|
31079
|
+
models: transformedModels
|
|
31080
|
+
};
|
|
31081
|
+
writeFileSync4(cachePath, JSON.stringify(cacheData, null, 2), "utf-8");
|
|
31082
|
+
return transformedModels;
|
|
31083
|
+
} catch (error46) {
|
|
31084
|
+
console.error(`Failed to fetch LiteLLM models: ${error46}`);
|
|
31085
|
+
if (existsSync6(cachePath)) {
|
|
31086
|
+
try {
|
|
31087
|
+
const cacheData = JSON.parse(readFileSync5(cachePath, "utf-8"));
|
|
31088
|
+
return cacheData.models;
|
|
31089
|
+
} catch {
|
|
31090
|
+
return [];
|
|
31091
|
+
}
|
|
31092
|
+
}
|
|
31093
|
+
return [];
|
|
31094
|
+
}
|
|
31095
|
+
}
|
|
31096
|
+
var __filename3, __dirname3, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, _cachedOpenRouterModels = null, LITELLM_CACHE_MAX_AGE_HOURS = 24;
|
|
31097
|
+
var init_model_loader = __esm(() => {
|
|
31098
|
+
__filename3 = fileURLToPath2(import.meta.url);
|
|
31099
|
+
__dirname3 = dirname2(__filename3);
|
|
31100
|
+
});
|
|
31101
|
+
|
|
30891
31102
|
// src/model-selector.ts
|
|
30892
31103
|
var exports_model_selector = {};
|
|
30893
31104
|
__export(exports_model_selector, {
|
|
@@ -30899,14 +31110,14 @@ __export(exports_model_selector, {
|
|
|
30899
31110
|
promptForApiKey: () => promptForApiKey,
|
|
30900
31111
|
confirmAction: () => confirmAction
|
|
30901
31112
|
});
|
|
30902
|
-
import { readFileSync as
|
|
30903
|
-
import { join as
|
|
30904
|
-
import { homedir as
|
|
30905
|
-
import { fileURLToPath as
|
|
31113
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync5 } from "node:fs";
|
|
31114
|
+
import { join as join7, dirname as dirname3 } from "node:path";
|
|
31115
|
+
import { homedir as homedir6 } from "node:os";
|
|
31116
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
30906
31117
|
function loadRecommendedModels2() {
|
|
30907
|
-
if (
|
|
31118
|
+
if (existsSync7(RECOMMENDED_MODELS_JSON_PATH)) {
|
|
30908
31119
|
try {
|
|
30909
|
-
const content =
|
|
31120
|
+
const content = readFileSync6(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
|
|
30910
31121
|
const data = JSON.parse(content);
|
|
30911
31122
|
return (data.models || []).map((model) => ({
|
|
30912
31123
|
...model,
|
|
@@ -30920,9 +31131,9 @@ function loadRecommendedModels2() {
|
|
|
30920
31131
|
return [];
|
|
30921
31132
|
}
|
|
30922
31133
|
async function fetchAllModels(forceUpdate = false) {
|
|
30923
|
-
if (!forceUpdate &&
|
|
31134
|
+
if (!forceUpdate && existsSync7(ALL_MODELS_JSON_PATH)) {
|
|
30924
31135
|
try {
|
|
30925
|
-
const cacheData = JSON.parse(
|
|
31136
|
+
const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH, "utf-8"));
|
|
30926
31137
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
30927
31138
|
const now = new Date;
|
|
30928
31139
|
const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
|
|
@@ -30938,8 +31149,8 @@ async function fetchAllModels(forceUpdate = false) {
|
|
|
30938
31149
|
throw new Error(`API returned ${response.status}`);
|
|
30939
31150
|
const data = await response.json();
|
|
30940
31151
|
const models = data.data;
|
|
30941
|
-
|
|
30942
|
-
|
|
31152
|
+
mkdirSync5(CLAUDISH_CACHE_DIR2, { recursive: true });
|
|
31153
|
+
writeFileSync5(ALL_MODELS_JSON_PATH, JSON.stringify({
|
|
30943
31154
|
lastUpdated: new Date().toISOString(),
|
|
30944
31155
|
models
|
|
30945
31156
|
}), "utf-8");
|
|
@@ -31318,11 +31529,11 @@ async function fetchOllamaCloudModels() {
|
|
|
31318
31529
|
}
|
|
31319
31530
|
}
|
|
31320
31531
|
function shouldRefreshForFreeModels() {
|
|
31321
|
-
if (!
|
|
31532
|
+
if (!existsSync7(ALL_MODELS_JSON_PATH)) {
|
|
31322
31533
|
return true;
|
|
31323
31534
|
}
|
|
31324
31535
|
try {
|
|
31325
|
-
const cacheData = JSON.parse(
|
|
31536
|
+
const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH, "utf-8"));
|
|
31326
31537
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
31327
31538
|
const now = new Date;
|
|
31328
31539
|
const ageInHours = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60);
|
|
@@ -31362,7 +31573,9 @@ async function getFreeModels() {
|
|
|
31362
31573
|
return combined;
|
|
31363
31574
|
}
|
|
31364
31575
|
async function getAllModelsForSearch() {
|
|
31365
|
-
const
|
|
31576
|
+
const litellmBaseUrl = process.env.LITELLM_BASE_URL;
|
|
31577
|
+
const litellmApiKey = process.env.LITELLM_API_KEY;
|
|
31578
|
+
const fetchPromises = [
|
|
31366
31579
|
fetchAllModels().then((models) => models.map(toModelInfo)),
|
|
31367
31580
|
fetchXAIModels(),
|
|
31368
31581
|
fetchGeminiModels(),
|
|
@@ -31371,9 +31584,14 @@ async function getAllModelsForSearch() {
|
|
|
31371
31584
|
fetchGLMCodingModels(),
|
|
31372
31585
|
fetchOllamaCloudModels(),
|
|
31373
31586
|
fetchZenFreeModels()
|
|
31374
|
-
]
|
|
31587
|
+
];
|
|
31588
|
+
if (litellmBaseUrl && litellmApiKey) {
|
|
31589
|
+
fetchPromises.push(fetchLiteLLMModels(litellmBaseUrl, litellmApiKey));
|
|
31590
|
+
}
|
|
31591
|
+
const results = await Promise.all(fetchPromises);
|
|
31592
|
+
const [openRouterModels, xaiModels, geminiModels, openaiModels, glmDirectModels, glmCodingModels, ollamaCloudModels, zenModels, litellmModels = []] = results;
|
|
31375
31593
|
const directApiModels = [...xaiModels, ...geminiModels, ...openaiModels, ...glmDirectModels, ...glmCodingModels];
|
|
31376
|
-
const allModels = [...zenModels, ...ollamaCloudModels, ...directApiModels, ...openRouterModels];
|
|
31594
|
+
const allModels = [...zenModels, ...ollamaCloudModels, ...directApiModels, ...litellmModels, ...openRouterModels];
|
|
31377
31595
|
return allModels;
|
|
31378
31596
|
}
|
|
31379
31597
|
function formatModelChoice(model, showSource = false) {
|
|
@@ -31394,7 +31612,8 @@ function formatModelChoice(model, showSource = false) {
|
|
|
31394
31612
|
OpenAI: "OAI",
|
|
31395
31613
|
GLM: "GLM",
|
|
31396
31614
|
"GLM Coding": "GC",
|
|
31397
|
-
OllamaCloud: "OC"
|
|
31615
|
+
OllamaCloud: "OC",
|
|
31616
|
+
LiteLLM: "LL"
|
|
31398
31617
|
};
|
|
31399
31618
|
const sourceTag = sourceTagMap[model.source] || model.source;
|
|
31400
31619
|
return `${sourceTag} ${model.id} (${priceStr}, ${ctxStr}${capsStr})`;
|
|
@@ -31736,14 +31955,15 @@ async function selectProfile(profiles) {
|
|
|
31736
31955
|
async function confirmAction(message) {
|
|
31737
31956
|
return dist_default2({ message, default: false });
|
|
31738
31957
|
}
|
|
31739
|
-
var
|
|
31958
|
+
var __filename4, __dirname4, CLAUDISH_CACHE_DIR2, ALL_MODELS_JSON_PATH, RECOMMENDED_MODELS_JSON_PATH, CACHE_MAX_AGE_DAYS2 = 2, FREE_MODELS_CACHE_MAX_AGE_HOURS = 3, PROVIDER_CHOICES, PROVIDER_MODEL_PREFIX, PROVIDER_SOURCE_FILTER;
|
|
31740
31959
|
var init_model_selector = __esm(() => {
|
|
31741
31960
|
init_dist8();
|
|
31742
|
-
|
|
31743
|
-
|
|
31744
|
-
|
|
31745
|
-
|
|
31746
|
-
|
|
31961
|
+
init_model_loader();
|
|
31962
|
+
__filename4 = fileURLToPath3(import.meta.url);
|
|
31963
|
+
__dirname4 = dirname3(__filename4);
|
|
31964
|
+
CLAUDISH_CACHE_DIR2 = join7(homedir6(), ".claudish");
|
|
31965
|
+
ALL_MODELS_JSON_PATH = join7(CLAUDISH_CACHE_DIR2, "all-models.json");
|
|
31966
|
+
RECOMMENDED_MODELS_JSON_PATH = join7(__dirname4, "../recommended-models.json");
|
|
31747
31967
|
PROVIDER_CHOICES = [
|
|
31748
31968
|
{ name: "Skip (keep Claude default)", value: "skip", description: "Use native Claude model for this tier" },
|
|
31749
31969
|
{ name: "OpenRouter", value: "openrouter", description: "580+ models via unified API" },
|
|
@@ -32320,132 +32540,6 @@ var init_config = __esm(() => {
|
|
|
32320
32540
|
};
|
|
32321
32541
|
});
|
|
32322
32542
|
|
|
32323
|
-
// src/model-loader.ts
|
|
32324
|
-
import { readFileSync as readFileSync6, existsSync as existsSync7 } from "node:fs";
|
|
32325
|
-
import { join as join7, dirname as dirname3 } from "node:path";
|
|
32326
|
-
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
32327
|
-
function getRecommendedModelsPath() {
|
|
32328
|
-
return join7(__dirname4, "../recommended-models.json");
|
|
32329
|
-
}
|
|
32330
|
-
function loadRecommendedModelsJSON() {
|
|
32331
|
-
if (_cachedRecommendedModels) {
|
|
32332
|
-
return _cachedRecommendedModels;
|
|
32333
|
-
}
|
|
32334
|
-
const jsonPath = getRecommendedModelsPath();
|
|
32335
|
-
if (!existsSync7(jsonPath)) {
|
|
32336
|
-
throw new Error(`recommended-models.json not found at ${jsonPath}. ` + `Run 'claudish --update-models' to fetch the latest model list.`);
|
|
32337
|
-
}
|
|
32338
|
-
try {
|
|
32339
|
-
const jsonContent = readFileSync6(jsonPath, "utf-8");
|
|
32340
|
-
_cachedRecommendedModels = JSON.parse(jsonContent);
|
|
32341
|
-
return _cachedRecommendedModels;
|
|
32342
|
-
} catch (error46) {
|
|
32343
|
-
throw new Error(`Failed to parse recommended-models.json: ${error46}`);
|
|
32344
|
-
}
|
|
32345
|
-
}
|
|
32346
|
-
function loadModelInfo() {
|
|
32347
|
-
if (_cachedModelInfo) {
|
|
32348
|
-
return _cachedModelInfo;
|
|
32349
|
-
}
|
|
32350
|
-
const data = loadRecommendedModelsJSON();
|
|
32351
|
-
const modelInfo = {};
|
|
32352
|
-
for (const model of data.models) {
|
|
32353
|
-
modelInfo[model.id] = {
|
|
32354
|
-
name: model.name,
|
|
32355
|
-
description: model.description,
|
|
32356
|
-
priority: model.priority,
|
|
32357
|
-
provider: model.provider
|
|
32358
|
-
};
|
|
32359
|
-
}
|
|
32360
|
-
modelInfo.custom = {
|
|
32361
|
-
name: "Custom Model",
|
|
32362
|
-
description: "Enter any OpenRouter model ID manually",
|
|
32363
|
-
priority: 999,
|
|
32364
|
-
provider: "Custom"
|
|
32365
|
-
};
|
|
32366
|
-
_cachedModelInfo = modelInfo;
|
|
32367
|
-
return modelInfo;
|
|
32368
|
-
}
|
|
32369
|
-
function getAvailableModels() {
|
|
32370
|
-
if (_cachedModelIds) {
|
|
32371
|
-
return _cachedModelIds;
|
|
32372
|
-
}
|
|
32373
|
-
const data = loadRecommendedModelsJSON();
|
|
32374
|
-
const modelIds = data.models.sort((a, b) => a.priority - b.priority).map((m) => m.id);
|
|
32375
|
-
const result = [...modelIds, "custom"];
|
|
32376
|
-
_cachedModelIds = result;
|
|
32377
|
-
return result;
|
|
32378
|
-
}
|
|
32379
|
-
function getCachedOpenRouterModels() {
|
|
32380
|
-
return _cachedOpenRouterModels;
|
|
32381
|
-
}
|
|
32382
|
-
async function ensureOpenRouterModelsLoaded() {
|
|
32383
|
-
if (_cachedOpenRouterModels)
|
|
32384
|
-
return _cachedOpenRouterModels;
|
|
32385
|
-
try {
|
|
32386
|
-
const response = await fetch("https://openrouter.ai/api/v1/models");
|
|
32387
|
-
if (response.ok) {
|
|
32388
|
-
const data = await response.json();
|
|
32389
|
-
_cachedOpenRouterModels = data.data || [];
|
|
32390
|
-
return _cachedOpenRouterModels;
|
|
32391
|
-
}
|
|
32392
|
-
} catch {}
|
|
32393
|
-
return [];
|
|
32394
|
-
}
|
|
32395
|
-
async function fetchModelContextWindow(modelId) {
|
|
32396
|
-
if (_cachedOpenRouterModels) {
|
|
32397
|
-
const model = _cachedOpenRouterModels.find((m) => m.id === modelId);
|
|
32398
|
-
if (model) {
|
|
32399
|
-
return model.context_length || model.top_provider?.context_length || 200000;
|
|
32400
|
-
}
|
|
32401
|
-
}
|
|
32402
|
-
try {
|
|
32403
|
-
const response = await fetch("https://openrouter.ai/api/v1/models");
|
|
32404
|
-
if (response.ok) {
|
|
32405
|
-
const data = await response.json();
|
|
32406
|
-
_cachedOpenRouterModels = data.data;
|
|
32407
|
-
const model = _cachedOpenRouterModels?.find((m) => m.id === modelId);
|
|
32408
|
-
if (model) {
|
|
32409
|
-
return model.context_length || model.top_provider?.context_length || 200000;
|
|
32410
|
-
}
|
|
32411
|
-
}
|
|
32412
|
-
} catch (error46) {}
|
|
32413
|
-
try {
|
|
32414
|
-
const data = loadRecommendedModelsJSON();
|
|
32415
|
-
const model = data.models.find((m) => m.id === modelId);
|
|
32416
|
-
if (model && model.context) {
|
|
32417
|
-
const ctxStr = model.context.toUpperCase();
|
|
32418
|
-
if (ctxStr.includes("K")) {
|
|
32419
|
-
return parseFloat(ctxStr.replace("K", "")) * 1000;
|
|
32420
|
-
}
|
|
32421
|
-
if (ctxStr.includes("M")) {
|
|
32422
|
-
return parseFloat(ctxStr.replace("M", "")) * 1e6;
|
|
32423
|
-
}
|
|
32424
|
-
const val = parseInt(ctxStr);
|
|
32425
|
-
if (!isNaN(val))
|
|
32426
|
-
return val;
|
|
32427
|
-
}
|
|
32428
|
-
} catch (e) {}
|
|
32429
|
-
return 200000;
|
|
32430
|
-
}
|
|
32431
|
-
async function doesModelSupportReasoning(modelId) {
|
|
32432
|
-
if (!_cachedOpenRouterModels) {
|
|
32433
|
-
await fetchModelContextWindow(modelId);
|
|
32434
|
-
}
|
|
32435
|
-
if (_cachedOpenRouterModels) {
|
|
32436
|
-
const model = _cachedOpenRouterModels.find((m) => m.id === modelId);
|
|
32437
|
-
if (model && model.supported_parameters) {
|
|
32438
|
-
return model.supported_parameters.includes("include_reasoning") || model.supported_parameters.includes("reasoning") || model.id.includes("o1") || model.id.includes("o3") || model.id.includes("r1");
|
|
32439
|
-
}
|
|
32440
|
-
}
|
|
32441
|
-
return false;
|
|
32442
|
-
}
|
|
32443
|
-
var __filename4, __dirname4, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, _cachedOpenRouterModels = null;
|
|
32444
|
-
var init_model_loader = __esm(() => {
|
|
32445
|
-
__filename4 = fileURLToPath3(import.meta.url);
|
|
32446
|
-
__dirname4 = dirname3(__filename4);
|
|
32447
|
-
});
|
|
32448
|
-
|
|
32449
32543
|
// src/utils.ts
|
|
32450
32544
|
function fuzzyScore2(text, query) {
|
|
32451
32545
|
if (!text || !query)
|
|
@@ -33084,7 +33178,7 @@ __export(exports_provider_resolver, {
|
|
|
33084
33178
|
});
|
|
33085
33179
|
import { existsSync as existsSync8 } from "node:fs";
|
|
33086
33180
|
import { join as join8 } from "node:path";
|
|
33087
|
-
import { homedir as
|
|
33181
|
+
import { homedir as homedir7 } from "node:os";
|
|
33088
33182
|
function isApiKeyAvailable(info) {
|
|
33089
33183
|
if (!info.envVar) {
|
|
33090
33184
|
return true;
|
|
@@ -33101,7 +33195,7 @@ function isApiKeyAvailable(info) {
|
|
|
33101
33195
|
}
|
|
33102
33196
|
if (info.oauthFallback) {
|
|
33103
33197
|
try {
|
|
33104
|
-
const credPath = join8(
|
|
33198
|
+
const credPath = join8(homedir7(), ".claudish", info.oauthFallback);
|
|
33105
33199
|
if (existsSync8(credPath)) {
|
|
33106
33200
|
return true;
|
|
33107
33201
|
}
|
|
@@ -33201,45 +33295,6 @@ function resolveModelProvider(modelId) {
|
|
|
33201
33295
|
description: `${provider.name} API Key`,
|
|
33202
33296
|
url: ""
|
|
33203
33297
|
};
|
|
33204
|
-
if (isApiKeyAvailable(info)) {
|
|
33205
|
-
const providerDisplayName2 = PROVIDER_DISPLAY_NAMES[provider.name] || provider.name.charAt(0).toUpperCase() + provider.name.slice(1);
|
|
33206
|
-
return addCommonFields({
|
|
33207
|
-
category: "direct-api",
|
|
33208
|
-
providerName: providerDisplayName2,
|
|
33209
|
-
modelName: remoteResolved.modelName,
|
|
33210
|
-
fullModelId: modelId,
|
|
33211
|
-
requiredApiKeyEnvVar: info.envVar || null,
|
|
33212
|
-
apiKeyAvailable: isApiKeyAvailable(info),
|
|
33213
|
-
apiKeyDescription: info.envVar ? info.description : null,
|
|
33214
|
-
apiKeyUrl: info.envVar ? info.url : null
|
|
33215
|
-
});
|
|
33216
|
-
}
|
|
33217
|
-
if (isApiKeyAvailable(API_KEY_INFO.openrouter)) {
|
|
33218
|
-
const orInfo = API_KEY_INFO.openrouter;
|
|
33219
|
-
return addCommonFields({
|
|
33220
|
-
category: "openrouter",
|
|
33221
|
-
providerName: "OpenRouter (fallback)",
|
|
33222
|
-
modelName: modelId,
|
|
33223
|
-
fullModelId: modelId,
|
|
33224
|
-
requiredApiKeyEnvVar: orInfo.envVar,
|
|
33225
|
-
apiKeyAvailable: true,
|
|
33226
|
-
apiKeyDescription: orInfo.description,
|
|
33227
|
-
apiKeyUrl: orInfo.url
|
|
33228
|
-
});
|
|
33229
|
-
}
|
|
33230
|
-
if (isApiKeyAvailable(API_KEY_INFO.vertex)) {
|
|
33231
|
-
const vertexInfo = API_KEY_INFO.vertex;
|
|
33232
|
-
return addCommonFields({
|
|
33233
|
-
category: "direct-api",
|
|
33234
|
-
providerName: "Vertex AI (fallback)",
|
|
33235
|
-
modelName: modelId,
|
|
33236
|
-
fullModelId: modelId,
|
|
33237
|
-
requiredApiKeyEnvVar: vertexInfo.envVar,
|
|
33238
|
-
apiKeyAvailable: true,
|
|
33239
|
-
apiKeyDescription: vertexInfo.description,
|
|
33240
|
-
apiKeyUrl: vertexInfo.url
|
|
33241
|
-
});
|
|
33242
|
-
}
|
|
33243
33298
|
const providerDisplayName = PROVIDER_DISPLAY_NAMES[provider.name] || provider.name.charAt(0).toUpperCase() + provider.name.slice(1);
|
|
33244
33299
|
return addCommonFields({
|
|
33245
33300
|
category: "direct-api",
|
|
@@ -33247,7 +33302,7 @@ function resolveModelProvider(modelId) {
|
|
|
33247
33302
|
modelName: remoteResolved.modelName,
|
|
33248
33303
|
fullModelId: modelId,
|
|
33249
33304
|
requiredApiKeyEnvVar: info.envVar || null,
|
|
33250
|
-
apiKeyAvailable:
|
|
33305
|
+
apiKeyAvailable: isApiKeyAvailable(info),
|
|
33251
33306
|
apiKeyDescription: info.envVar ? info.description : null,
|
|
33252
33307
|
apiKeyUrl: info.envVar ? info.url : null
|
|
33253
33308
|
});
|
|
@@ -33475,10 +33530,10 @@ __export(exports_cli, {
|
|
|
33475
33530
|
getMissingKeyResolutions: () => getMissingKeyResolutions,
|
|
33476
33531
|
getMissingKeyError: () => getMissingKeyError
|
|
33477
33532
|
});
|
|
33478
|
-
import { readFileSync as readFileSync7, writeFileSync as
|
|
33533
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync9, mkdirSync as mkdirSync6, copyFileSync } from "node:fs";
|
|
33479
33534
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
33480
33535
|
import { dirname as dirname4, join as join9 } from "node:path";
|
|
33481
|
-
import { homedir as
|
|
33536
|
+
import { homedir as homedir8 } from "node:os";
|
|
33482
33537
|
function getVersion() {
|
|
33483
33538
|
return VERSION;
|
|
33484
33539
|
}
|
|
@@ -33755,8 +33810,8 @@ async function searchAndPrintModels(query, forceUpdate) {
|
|
|
33755
33810
|
throw new Error(`API returned ${response.status}`);
|
|
33756
33811
|
const data = await response.json();
|
|
33757
33812
|
models = data.data;
|
|
33758
|
-
|
|
33759
|
-
|
|
33813
|
+
mkdirSync6(CLAUDISH_CACHE_DIR3, { recursive: true });
|
|
33814
|
+
writeFileSync6(ALL_MODELS_JSON_PATH2, JSON.stringify({
|
|
33760
33815
|
lastUpdated: new Date().toISOString(),
|
|
33761
33816
|
models
|
|
33762
33817
|
}), "utf-8");
|
|
@@ -33916,8 +33971,8 @@ async function printAllModels(jsonOutput, forceUpdate) {
|
|
|
33916
33971
|
throw new Error(`API returned ${response.status}`);
|
|
33917
33972
|
const data = await response.json();
|
|
33918
33973
|
models = data.data;
|
|
33919
|
-
|
|
33920
|
-
|
|
33974
|
+
mkdirSync6(CLAUDISH_CACHE_DIR3, { recursive: true });
|
|
33975
|
+
writeFileSync6(ALL_MODELS_JSON_PATH2, JSON.stringify({
|
|
33921
33976
|
lastUpdated: new Date().toISOString(),
|
|
33922
33977
|
models
|
|
33923
33978
|
}), "utf-8");
|
|
@@ -34182,7 +34237,7 @@ async function updateModelsFromOpenRouter() {
|
|
|
34182
34237
|
source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
|
|
34183
34238
|
models: recommendations
|
|
34184
34239
|
};
|
|
34185
|
-
|
|
34240
|
+
writeFileSync6(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
|
|
34186
34241
|
console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
|
|
34187
34242
|
} catch (error46) {
|
|
34188
34243
|
console.error(`❌ Failed to update models: ${error46 instanceof Error ? error46.message : String(error46)}`);
|
|
@@ -34543,15 +34598,15 @@ async function initializeClaudishSkill() {
|
|
|
34543
34598
|
}
|
|
34544
34599
|
try {
|
|
34545
34600
|
if (!existsSync9(claudeDir)) {
|
|
34546
|
-
|
|
34601
|
+
mkdirSync6(claudeDir, { recursive: true });
|
|
34547
34602
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
34548
34603
|
}
|
|
34549
34604
|
if (!existsSync9(skillsDir)) {
|
|
34550
|
-
|
|
34605
|
+
mkdirSync6(skillsDir, { recursive: true });
|
|
34551
34606
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
34552
34607
|
}
|
|
34553
34608
|
if (!existsSync9(claudishSkillDir)) {
|
|
34554
|
-
|
|
34609
|
+
mkdirSync6(claudishSkillDir, { recursive: true });
|
|
34555
34610
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
34556
34611
|
}
|
|
34557
34612
|
copyFileSync(sourceSkillPath, skillFile);
|
|
@@ -34741,7 +34796,7 @@ async function fetchGLMCodingModels2() {
|
|
|
34741
34796
|
return [];
|
|
34742
34797
|
}
|
|
34743
34798
|
}
|
|
34744
|
-
var __filename5, __dirname5, VERSION = "4.6.
|
|
34799
|
+
var __filename5, __dirname5, VERSION = "4.6.3", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, CLAUDISH_CACHE_DIR3, ALL_MODELS_JSON_PATH2;
|
|
34745
34800
|
var init_cli = __esm(() => {
|
|
34746
34801
|
init_config();
|
|
34747
34802
|
init_model_loader();
|
|
@@ -34754,7 +34809,7 @@ var init_cli = __esm(() => {
|
|
|
34754
34809
|
VERSION = packageJson.version;
|
|
34755
34810
|
} catch {}
|
|
34756
34811
|
MODELS_JSON_PATH = join9(__dirname5, "../recommended-models.json");
|
|
34757
|
-
CLAUDISH_CACHE_DIR3 = join9(
|
|
34812
|
+
CLAUDISH_CACHE_DIR3 = join9(homedir8(), ".claudish");
|
|
34758
34813
|
ALL_MODELS_JSON_PATH2 = join9(CLAUDISH_CACHE_DIR3, "all-models.json");
|
|
34759
34814
|
});
|
|
34760
34815
|
|
|
@@ -34765,8 +34820,8 @@ __export(exports_claude_runner, {
|
|
|
34765
34820
|
checkClaudeInstalled: () => checkClaudeInstalled
|
|
34766
34821
|
});
|
|
34767
34822
|
import { spawn } from "node:child_process";
|
|
34768
|
-
import { writeFileSync as
|
|
34769
|
-
import { tmpdir, homedir as
|
|
34823
|
+
import { writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, mkdirSync as mkdirSync7, existsSync as existsSync10 } from "node:fs";
|
|
34824
|
+
import { tmpdir, homedir as homedir9 } from "node:os";
|
|
34770
34825
|
import { join as join10 } from "node:path";
|
|
34771
34826
|
function isWindows() {
|
|
34772
34827
|
return process.platform === "win32";
|
|
@@ -34855,14 +34910,14 @@ process.stdin.on('end', () => {
|
|
|
34855
34910
|
}
|
|
34856
34911
|
});
|
|
34857
34912
|
`;
|
|
34858
|
-
|
|
34913
|
+
writeFileSync7(scriptPath, script, "utf-8");
|
|
34859
34914
|
return scriptPath;
|
|
34860
34915
|
}
|
|
34861
34916
|
function createTempSettingsFile(modelDisplay, port) {
|
|
34862
34917
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
|
|
34863
34918
|
const claudishDir = join10(homeDir, ".claudish");
|
|
34864
34919
|
try {
|
|
34865
|
-
|
|
34920
|
+
mkdirSync7(claudishDir, { recursive: true });
|
|
34866
34921
|
} catch {}
|
|
34867
34922
|
const timestamp = Date.now();
|
|
34868
34923
|
const tempPath = join10(claudishDir, `settings-${timestamp}.json`);
|
|
@@ -34889,7 +34944,7 @@ function createTempSettingsFile(modelDisplay, port) {
|
|
|
34889
34944
|
padding: 0
|
|
34890
34945
|
}
|
|
34891
34946
|
};
|
|
34892
|
-
|
|
34947
|
+
writeFileSync7(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
34893
34948
|
return tempPath;
|
|
34894
34949
|
}
|
|
34895
34950
|
async function runClaudeWithProxy(config3, proxyUrl) {
|
|
@@ -34971,7 +35026,7 @@ async function runClaudeWithProxy(config3, proxyUrl) {
|
|
|
34971
35026
|
console.error("Install it from: https://claude.com/claude-code");
|
|
34972
35027
|
console.error(`
|
|
34973
35028
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
34974
|
-
const home =
|
|
35029
|
+
const home = homedir9();
|
|
34975
35030
|
const localPath = isWindows() ? join10(home, ".claude", "local", "claude.exe") : join10(home, ".claude", "local", "claude");
|
|
34976
35031
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
34977
35032
|
process.exit(1);
|
|
@@ -35015,7 +35070,7 @@ async function findClaudeBinary() {
|
|
|
35015
35070
|
return process.env.CLAUDE_PATH;
|
|
35016
35071
|
}
|
|
35017
35072
|
}
|
|
35018
|
-
const home =
|
|
35073
|
+
const home = homedir9();
|
|
35019
35074
|
const localPath = isWindows2 ? join10(home, ".claude", "local", "claude.exe") : join10(home, ".claude", "local", "claude");
|
|
35020
35075
|
if (existsSync10(localPath)) {
|
|
35021
35076
|
return localPath;
|
|
@@ -39525,8 +39580,8 @@ var init_remote_provider_types = __esm(() => {
|
|
|
39525
39580
|
});
|
|
39526
39581
|
|
|
39527
39582
|
// src/handlers/openrouter-handler.ts
|
|
39528
|
-
import { writeFileSync as
|
|
39529
|
-
import { homedir as
|
|
39583
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "node:fs";
|
|
39584
|
+
import { homedir as homedir10 } from "node:os";
|
|
39530
39585
|
import { join as join11 } from "node:path";
|
|
39531
39586
|
|
|
39532
39587
|
class OpenRouterHandler {
|
|
@@ -39579,9 +39634,9 @@ class OpenRouterHandler {
|
|
|
39579
39634
|
updated_at: Date.now(),
|
|
39580
39635
|
is_free: isFreeModel
|
|
39581
39636
|
};
|
|
39582
|
-
const claudishDir = join11(
|
|
39583
|
-
|
|
39584
|
-
|
|
39637
|
+
const claudishDir = join11(homedir10(), ".claudish");
|
|
39638
|
+
mkdirSync8(claudishDir, { recursive: true });
|
|
39639
|
+
writeFileSync8(join11(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
39585
39640
|
} catch (e) {}
|
|
39586
39641
|
}
|
|
39587
39642
|
async handle(c, payload) {
|
|
@@ -60588,8 +60643,8 @@ var init_local_queue = __esm(() => {
|
|
|
60588
60643
|
});
|
|
60589
60644
|
|
|
60590
60645
|
// src/handlers/local-provider-handler.ts
|
|
60591
|
-
import { writeFileSync as
|
|
60592
|
-
import { homedir as
|
|
60646
|
+
import { writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
|
|
60647
|
+
import { homedir as homedir11 } from "node:os";
|
|
60593
60648
|
import { join as join12 } from "node:path";
|
|
60594
60649
|
|
|
60595
60650
|
class LocalProviderHandler {
|
|
@@ -60769,9 +60824,9 @@ class LocalProviderHandler {
|
|
|
60769
60824
|
provider_name: providerNameMap[this.provider.name] || "Local",
|
|
60770
60825
|
updated_at: Date.now()
|
|
60771
60826
|
};
|
|
60772
|
-
const claudishDir = join12(
|
|
60773
|
-
|
|
60774
|
-
|
|
60827
|
+
const claudishDir = join12(homedir11(), ".claudish");
|
|
60828
|
+
mkdirSync9(claudishDir, { recursive: true });
|
|
60829
|
+
writeFileSync9(join12(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
60775
60830
|
} catch (e) {}
|
|
60776
60831
|
}
|
|
60777
60832
|
async handle(c, payload) {
|
|
@@ -61361,8 +61416,8 @@ var init_gemini_retry = __esm(() => {
|
|
|
61361
61416
|
});
|
|
61362
61417
|
|
|
61363
61418
|
// src/handlers/base-gemini-handler.ts
|
|
61364
|
-
import { writeFileSync as
|
|
61365
|
-
import { homedir as
|
|
61419
|
+
import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
|
|
61420
|
+
import { homedir as homedir12 } from "node:os";
|
|
61366
61421
|
import { join as join13 } from "node:path";
|
|
61367
61422
|
|
|
61368
61423
|
class BaseGeminiHandler {
|
|
@@ -61403,9 +61458,9 @@ class BaseGeminiHandler {
|
|
|
61403
61458
|
provider_name: this.getProviderName(),
|
|
61404
61459
|
updated_at: Date.now()
|
|
61405
61460
|
};
|
|
61406
|
-
const claudishDir = join13(
|
|
61407
|
-
|
|
61408
|
-
|
|
61461
|
+
const claudishDir = join13(homedir12(), ".claudish");
|
|
61462
|
+
mkdirSync10(claudishDir, { recursive: true });
|
|
61463
|
+
writeFileSync10(join13(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
61409
61464
|
} catch (e) {
|
|
61410
61465
|
log(`[BaseGeminiHandler] Error writing token file: ${e}`);
|
|
61411
61466
|
}
|
|
@@ -61946,8 +62001,8 @@ var init_gemini_handler = __esm(() => {
|
|
|
61946
62001
|
});
|
|
61947
62002
|
|
|
61948
62003
|
// src/handlers/gemini-codeassist-handler.ts
|
|
61949
|
-
import { writeFileSync as
|
|
61950
|
-
import { homedir as
|
|
62004
|
+
import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync11 } from "node:fs";
|
|
62005
|
+
import { homedir as homedir13 } from "node:os";
|
|
61951
62006
|
import { join as join14 } from "node:path";
|
|
61952
62007
|
import { randomUUID } from "node:crypto";
|
|
61953
62008
|
|
|
@@ -61996,9 +62051,9 @@ class GeminiCodeAssistHandler {
|
|
|
61996
62051
|
provider_name: "Gemini Free",
|
|
61997
62052
|
updated_at: Date.now()
|
|
61998
62053
|
};
|
|
61999
|
-
const claudishDir = join14(
|
|
62000
|
-
|
|
62001
|
-
|
|
62054
|
+
const claudishDir = join14(homedir13(), ".claudish");
|
|
62055
|
+
mkdirSync11(claudishDir, { recursive: true });
|
|
62056
|
+
writeFileSync11(join14(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
62002
62057
|
} catch (e) {
|
|
62003
62058
|
log(`[GeminiCodeAssistHandler] Error writing token file: ${e}`);
|
|
62004
62059
|
}
|
|
@@ -62413,8 +62468,8 @@ var init_gemini_codeassist_handler = __esm(() => {
|
|
|
62413
62468
|
});
|
|
62414
62469
|
|
|
62415
62470
|
// src/handlers/openai-handler.ts
|
|
62416
|
-
import { writeFileSync as
|
|
62417
|
-
import { homedir as
|
|
62471
|
+
import { writeFileSync as writeFileSync12, mkdirSync as mkdirSync12 } from "node:fs";
|
|
62472
|
+
import { homedir as homedir14 } from "node:os";
|
|
62418
62473
|
import { join as join15 } from "node:path";
|
|
62419
62474
|
|
|
62420
62475
|
class OpenAIHandler {
|
|
@@ -62529,9 +62584,9 @@ class OpenAIHandler {
|
|
|
62529
62584
|
is_free: isFreeModel,
|
|
62530
62585
|
is_estimated: isEstimate || false
|
|
62531
62586
|
};
|
|
62532
|
-
const claudishDir = join15(
|
|
62533
|
-
|
|
62534
|
-
|
|
62587
|
+
const claudishDir = join15(homedir14(), ".claudish");
|
|
62588
|
+
mkdirSync12(claudishDir, { recursive: true });
|
|
62589
|
+
writeFileSync12(join15(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
62535
62590
|
} catch (e) {
|
|
62536
62591
|
log(`[OpenAIHandler] Error writing token file: ${e}`);
|
|
62537
62592
|
}
|
|
@@ -63139,8 +63194,8 @@ var init_openai_handler = __esm(() => {
|
|
|
63139
63194
|
});
|
|
63140
63195
|
|
|
63141
63196
|
// src/handlers/anthropic-compat-handler.ts
|
|
63142
|
-
import { mkdirSync as
|
|
63143
|
-
import { homedir as
|
|
63197
|
+
import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "node:fs";
|
|
63198
|
+
import { homedir as homedir15 } from "node:os";
|
|
63144
63199
|
import { join as join16 } from "node:path";
|
|
63145
63200
|
|
|
63146
63201
|
class AnthropicCompatHandler {
|
|
@@ -63203,9 +63258,9 @@ class AnthropicCompatHandler {
|
|
|
63203
63258
|
provider_name: providerDisplayName,
|
|
63204
63259
|
updated_at: Date.now()
|
|
63205
63260
|
};
|
|
63206
|
-
const claudishDir = join16(
|
|
63207
|
-
|
|
63208
|
-
|
|
63261
|
+
const claudishDir = join16(homedir15(), ".claudish");
|
|
63262
|
+
mkdirSync13(claudishDir, { recursive: true });
|
|
63263
|
+
writeFileSync13(join16(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
63209
63264
|
} catch (e) {
|
|
63210
63265
|
log(`[AnthropicCompatHandler] Error writing token file: ${e}`);
|
|
63211
63266
|
}
|
|
@@ -63244,8 +63299,8 @@ class AnthropicCompatHandler {
|
|
|
63244
63299
|
try {
|
|
63245
63300
|
const { existsSync: existsSync11, readFileSync: readFileSync8 } = await import("node:fs");
|
|
63246
63301
|
const { join: join17 } = await import("node:path");
|
|
63247
|
-
const { homedir:
|
|
63248
|
-
const credPath = join17(
|
|
63302
|
+
const { homedir: homedir16 } = await import("node:os");
|
|
63303
|
+
const credPath = join17(homedir16(), ".claudish", "kimi-oauth.json");
|
|
63249
63304
|
if (existsSync11(credPath)) {
|
|
63250
63305
|
const data2 = JSON.parse(readFileSync8(credPath, "utf-8"));
|
|
63251
63306
|
if (data2.access_token && data2.refresh_token) {
|
|
@@ -63354,7 +63409,7 @@ var init_anthropic_compat_handler = __esm(() => {
|
|
|
63354
63409
|
import { exec as exec4 } from "node:child_process";
|
|
63355
63410
|
import { promisify as promisify3 } from "node:util";
|
|
63356
63411
|
import { existsSync as existsSync11 } from "node:fs";
|
|
63357
|
-
import { homedir as
|
|
63412
|
+
import { homedir as homedir16 } from "node:os";
|
|
63358
63413
|
import { join as join17 } from "node:path";
|
|
63359
63414
|
|
|
63360
63415
|
class VertexAuthManager {
|
|
@@ -63409,7 +63464,7 @@ class VertexAuthManager {
|
|
|
63409
63464
|
}
|
|
63410
63465
|
async tryADC() {
|
|
63411
63466
|
try {
|
|
63412
|
-
const adcPath = join17(
|
|
63467
|
+
const adcPath = join17(homedir16(), ".config/gcloud/application_default_credentials.json");
|
|
63413
63468
|
if (!existsSync11(adcPath)) {
|
|
63414
63469
|
log("[VertexAuth] ADC credentials file not found");
|
|
63415
63470
|
return null;
|
|
@@ -63473,7 +63528,7 @@ function validateVertexOAuthConfig() {
|
|
|
63473
63528
|
` + ` export VERTEX_PROJECT='your-gcp-project-id'
|
|
63474
63529
|
` + " export VERTEX_LOCATION='us-central1' # optional";
|
|
63475
63530
|
}
|
|
63476
|
-
const adcPath = join17(
|
|
63531
|
+
const adcPath = join17(homedir16(), ".config/gcloud/application_default_credentials.json");
|
|
63477
63532
|
const hasADC = existsSync11(adcPath);
|
|
63478
63533
|
const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
63479
63534
|
if (!hasADC && !hasServiceAccount) {
|
|
@@ -63510,8 +63565,8 @@ var init_vertex_auth = __esm(() => {
|
|
|
63510
63565
|
});
|
|
63511
63566
|
|
|
63512
63567
|
// src/handlers/vertex-oauth-handler.ts
|
|
63513
|
-
import { writeFileSync as
|
|
63514
|
-
import { homedir as
|
|
63568
|
+
import { writeFileSync as writeFileSync14, mkdirSync as mkdirSync14 } from "node:fs";
|
|
63569
|
+
import { homedir as homedir17 } from "node:os";
|
|
63515
63570
|
import { join as join18 } from "node:path";
|
|
63516
63571
|
function parseVertexModel(modelId) {
|
|
63517
63572
|
const parts = modelId.split("/");
|
|
@@ -63568,9 +63623,9 @@ class VertexOAuthHandler {
|
|
|
63568
63623
|
provider_name: "Vertex AI",
|
|
63569
63624
|
updated_at: Date.now()
|
|
63570
63625
|
};
|
|
63571
|
-
const claudishDir = join18(
|
|
63572
|
-
|
|
63573
|
-
|
|
63626
|
+
const claudishDir = join18(homedir17(), ".claudish");
|
|
63627
|
+
mkdirSync14(claudishDir, { recursive: true });
|
|
63628
|
+
writeFileSync14(join18(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
63574
63629
|
} catch (e) {
|
|
63575
63630
|
log(`[VertexOAuth] Error writing token file: ${e}`);
|
|
63576
63631
|
}
|
|
@@ -64275,7 +64330,7 @@ var init_vertex_oauth_handler = __esm(() => {
|
|
|
64275
64330
|
});
|
|
64276
64331
|
|
|
64277
64332
|
// src/handlers/poe-handler.ts
|
|
64278
|
-
import { createHash as
|
|
64333
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
64279
64334
|
|
|
64280
64335
|
class SSEParser {
|
|
64281
64336
|
buffer = "";
|
|
@@ -64509,7 +64564,7 @@ class PoeHandler {
|
|
|
64509
64564
|
headers;
|
|
64510
64565
|
constructor(apiKey) {
|
|
64511
64566
|
this.apiKey = apiKey;
|
|
64512
|
-
this.apiKeySha =
|
|
64567
|
+
this.apiKeySha = createHash3("sha256").update(apiKey).digest("hex").substring(0, 16);
|
|
64513
64568
|
this.headers = {
|
|
64514
64569
|
"Content-Type": "application/json",
|
|
64515
64570
|
Authorization: `Bearer ${apiKey}`
|
|
@@ -64944,8 +64999,8 @@ var init_poe_handler = __esm(() => {
|
|
|
64944
64999
|
});
|
|
64945
65000
|
|
|
64946
65001
|
// src/handlers/ollamacloud-handler.ts
|
|
64947
|
-
import { writeFileSync as
|
|
64948
|
-
import { homedir as
|
|
65002
|
+
import { writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "node:fs";
|
|
65003
|
+
import { homedir as homedir18 } from "node:os";
|
|
64949
65004
|
import { join as join19 } from "node:path";
|
|
64950
65005
|
|
|
64951
65006
|
class OllamaCloudHandler {
|
|
@@ -65031,9 +65086,9 @@ class OllamaCloudHandler {
|
|
|
65031
65086
|
provider_name: "OllamaCloud",
|
|
65032
65087
|
updated_at: Date.now()
|
|
65033
65088
|
};
|
|
65034
|
-
const claudishDir = join19(
|
|
65035
|
-
|
|
65036
|
-
|
|
65089
|
+
const claudishDir = join19(homedir18(), ".claudish");
|
|
65090
|
+
mkdirSync15(claudishDir, { recursive: true });
|
|
65091
|
+
writeFileSync15(join19(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
|
|
65037
65092
|
} catch (e) {}
|
|
65038
65093
|
}
|
|
65039
65094
|
async handle(c, payload) {
|
|
@@ -65246,8 +65301,8 @@ var init_ollamacloud_handler = __esm(() => {
|
|
|
65246
65301
|
});
|
|
65247
65302
|
|
|
65248
65303
|
// src/services/pricing-cache.ts
|
|
65249
|
-
import { readFileSync as readFileSync9, writeFileSync as
|
|
65250
|
-
import { homedir as
|
|
65304
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync16, existsSync as existsSync12, mkdirSync as mkdirSync16, statSync } from "node:fs";
|
|
65305
|
+
import { homedir as homedir19 } from "node:os";
|
|
65251
65306
|
import { join as join20 } from "node:path";
|
|
65252
65307
|
function getDynamicPricingSync(provider, modelName) {
|
|
65253
65308
|
if (provider === "openrouter") {
|
|
@@ -65330,12 +65385,12 @@ function loadDiskCache() {
|
|
|
65330
65385
|
}
|
|
65331
65386
|
function saveDiskCache() {
|
|
65332
65387
|
try {
|
|
65333
|
-
|
|
65388
|
+
mkdirSync16(CACHE_DIR, { recursive: true });
|
|
65334
65389
|
const data = {};
|
|
65335
65390
|
for (const [key, pricing] of pricingMap) {
|
|
65336
65391
|
data[key] = pricing;
|
|
65337
65392
|
}
|
|
65338
|
-
|
|
65393
|
+
writeFileSync16(CACHE_FILE, JSON.stringify(data), "utf-8");
|
|
65339
65394
|
} catch (error46) {
|
|
65340
65395
|
log(`[PricingCache] Error saving disk cache: ${error46}`);
|
|
65341
65396
|
}
|
|
@@ -65365,7 +65420,7 @@ var init_pricing_cache = __esm(() => {
|
|
|
65365
65420
|
init_model_loader();
|
|
65366
65421
|
init_remote_provider_types();
|
|
65367
65422
|
pricingMap = new Map;
|
|
65368
|
-
CACHE_DIR = join20(
|
|
65423
|
+
CACHE_DIR = join20(homedir19(), ".claudish");
|
|
65369
65424
|
CACHE_FILE = join20(CACHE_DIR, "pricing-cache.json");
|
|
65370
65425
|
CACHE_TTL_MS = 24 * 60 * 60 * 1000;
|
|
65371
65426
|
PROVIDER_TO_OR_PREFIX = {
|
|
@@ -65639,8 +65694,8 @@ __export(exports_update_checker, {
|
|
|
65639
65694
|
checkForUpdates: () => checkForUpdates
|
|
65640
65695
|
});
|
|
65641
65696
|
import { execSync } from "node:child_process";
|
|
65642
|
-
import { existsSync as existsSync13, mkdirSync as
|
|
65643
|
-
import { homedir as
|
|
65697
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync17, readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync17 } from "node:fs";
|
|
65698
|
+
import { homedir as homedir20, platform as platform2, tmpdir as tmpdir2 } from "node:os";
|
|
65644
65699
|
import { join as join21 } from "node:path";
|
|
65645
65700
|
import { createInterface as createInterface2 } from "node:readline";
|
|
65646
65701
|
function getUpdateCommand() {
|
|
@@ -65653,14 +65708,14 @@ function getUpdateCommand() {
|
|
|
65653
65708
|
function getCacheFilePath() {
|
|
65654
65709
|
let cacheDir;
|
|
65655
65710
|
if (isWindows2) {
|
|
65656
|
-
const localAppData = process.env.LOCALAPPDATA || join21(
|
|
65711
|
+
const localAppData = process.env.LOCALAPPDATA || join21(homedir20(), "AppData", "Local");
|
|
65657
65712
|
cacheDir = join21(localAppData, "claudish");
|
|
65658
65713
|
} else {
|
|
65659
|
-
cacheDir = join21(
|
|
65714
|
+
cacheDir = join21(homedir20(), ".cache", "claudish");
|
|
65660
65715
|
}
|
|
65661
65716
|
try {
|
|
65662
65717
|
if (!existsSync13(cacheDir)) {
|
|
65663
|
-
|
|
65718
|
+
mkdirSync17(cacheDir, { recursive: true });
|
|
65664
65719
|
}
|
|
65665
65720
|
return join21(cacheDir, "update-check.json");
|
|
65666
65721
|
} catch {
|
|
@@ -65686,7 +65741,7 @@ function writeCache(latestVersion) {
|
|
|
65686
65741
|
lastCheck: Date.now(),
|
|
65687
65742
|
latestVersion
|
|
65688
65743
|
};
|
|
65689
|
-
|
|
65744
|
+
writeFileSync17(cachePath, JSON.stringify(data), "utf-8");
|
|
65690
65745
|
} catch {}
|
|
65691
65746
|
}
|
|
65692
65747
|
function isCacheValid(cache) {
|
package/package.json
CHANGED
package/recommended-models.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": "1.2.0",
|
|
3
|
-
"lastUpdated": "2026-02-
|
|
3
|
+
"lastUpdated": "2026-02-13",
|
|
4
4
|
"source": "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
|
|
5
5
|
"models": [
|
|
6
6
|
{
|
|
@@ -137,12 +137,12 @@
|
|
|
137
137
|
"category": "vision",
|
|
138
138
|
"priority": 7,
|
|
139
139
|
"pricing": {
|
|
140
|
-
"input": "
|
|
141
|
-
"output": "
|
|
142
|
-
"average": "
|
|
140
|
+
"input": "FREE",
|
|
141
|
+
"output": "FREE",
|
|
142
|
+
"average": "FREE"
|
|
143
143
|
},
|
|
144
|
-
"context": "
|
|
145
|
-
"maxOutputTokens":
|
|
144
|
+
"context": "131K",
|
|
145
|
+
"maxOutputTokens": 32768,
|
|
146
146
|
"modality": "text+image->text",
|
|
147
147
|
"supportsTools": true,
|
|
148
148
|
"supportsReasoning": true,
|