claudish 4.6.0 → 4.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -30888,6 +30888,216 @@ 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(/\/$/, "")}/public/model_hub`;
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 rawModels = await response.json();
31049
+ const transformedModels = rawModels.filter((m) => m.mode === "chat" && m.supports_function_calling).map((m) => {
31050
+ const inputCostPerM = (m.input_cost_per_token || 0) * 1e6;
31051
+ const outputCostPerM = (m.output_cost_per_token || 0) * 1e6;
31052
+ const avgCost = (inputCostPerM + outputCostPerM) / 2;
31053
+ const isFree = inputCostPerM === 0 && outputCostPerM === 0;
31054
+ const contextLength = m.max_input_tokens || 128000;
31055
+ const contextStr = contextLength >= 1e6 ? `${Math.round(contextLength / 1e6)}M` : `${Math.round(contextLength / 1000)}K`;
31056
+ return {
31057
+ id: `litellm@${m.model_group}`,
31058
+ name: m.model_group,
31059
+ description: `LiteLLM model (providers: ${m.providers.join(", ")})`,
31060
+ provider: "LiteLLM",
31061
+ pricing: {
31062
+ input: isFree ? "FREE" : `$${inputCostPerM.toFixed(2)}`,
31063
+ output: isFree ? "FREE" : `$${outputCostPerM.toFixed(2)}`,
31064
+ average: isFree ? "FREE" : `$${avgCost.toFixed(2)}/1M`
31065
+ },
31066
+ context: contextStr,
31067
+ contextLength,
31068
+ supportsTools: m.supports_function_calling || false,
31069
+ supportsReasoning: m.supports_reasoning || false,
31070
+ supportsVision: m.supports_vision || false,
31071
+ isFree,
31072
+ source: "LiteLLM"
31073
+ };
31074
+ });
31075
+ mkdirSync4(cacheDir, { recursive: true });
31076
+ const cacheData = {
31077
+ timestamp: new Date().toISOString(),
31078
+ models: transformedModels
31079
+ };
31080
+ writeFileSync4(cachePath, JSON.stringify(cacheData, null, 2), "utf-8");
31081
+ return transformedModels;
31082
+ } catch (error46) {
31083
+ console.error(`Failed to fetch LiteLLM models: ${error46}`);
31084
+ if (existsSync6(cachePath)) {
31085
+ try {
31086
+ const cacheData = JSON.parse(readFileSync5(cachePath, "utf-8"));
31087
+ return cacheData.models;
31088
+ } catch {
31089
+ return [];
31090
+ }
31091
+ }
31092
+ return [];
31093
+ }
31094
+ }
31095
+ var __filename3, __dirname3, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, _cachedOpenRouterModels = null, LITELLM_CACHE_MAX_AGE_HOURS = 24;
31096
+ var init_model_loader = __esm(() => {
31097
+ __filename3 = fileURLToPath2(import.meta.url);
31098
+ __dirname3 = dirname2(__filename3);
31099
+ });
31100
+
30891
31101
  // src/model-selector.ts
30892
31102
  var exports_model_selector = {};
30893
31103
  __export(exports_model_selector, {
@@ -30899,14 +31109,14 @@ __export(exports_model_selector, {
30899
31109
  promptForApiKey: () => promptForApiKey,
30900
31110
  confirmAction: () => confirmAction
30901
31111
  });
30902
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "node:fs";
30903
- import { join as join6, dirname as dirname2 } from "node:path";
30904
- import { homedir as homedir5 } from "node:os";
30905
- import { fileURLToPath as fileURLToPath2 } from "node:url";
31112
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync5 } from "node:fs";
31113
+ import { join as join7, dirname as dirname3 } from "node:path";
31114
+ import { homedir as homedir6 } from "node:os";
31115
+ import { fileURLToPath as fileURLToPath3 } from "node:url";
30906
31116
  function loadRecommendedModels2() {
30907
- if (existsSync6(RECOMMENDED_MODELS_JSON_PATH)) {
31117
+ if (existsSync7(RECOMMENDED_MODELS_JSON_PATH)) {
30908
31118
  try {
30909
- const content = readFileSync5(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
31119
+ const content = readFileSync6(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
30910
31120
  const data = JSON.parse(content);
30911
31121
  return (data.models || []).map((model) => ({
30912
31122
  ...model,
@@ -30920,9 +31130,9 @@ function loadRecommendedModels2() {
30920
31130
  return [];
30921
31131
  }
30922
31132
  async function fetchAllModels(forceUpdate = false) {
30923
- if (!forceUpdate && existsSync6(ALL_MODELS_JSON_PATH)) {
31133
+ if (!forceUpdate && existsSync7(ALL_MODELS_JSON_PATH)) {
30924
31134
  try {
30925
- const cacheData = JSON.parse(readFileSync5(ALL_MODELS_JSON_PATH, "utf-8"));
31135
+ const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH, "utf-8"));
30926
31136
  const lastUpdated = new Date(cacheData.lastUpdated);
30927
31137
  const now = new Date;
30928
31138
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -30938,8 +31148,8 @@ async function fetchAllModels(forceUpdate = false) {
30938
31148
  throw new Error(`API returned ${response.status}`);
30939
31149
  const data = await response.json();
30940
31150
  const models = data.data;
30941
- mkdirSync4(CLAUDISH_CACHE_DIR2, { recursive: true });
30942
- writeFileSync4(ALL_MODELS_JSON_PATH, JSON.stringify({
31151
+ mkdirSync5(CLAUDISH_CACHE_DIR2, { recursive: true });
31152
+ writeFileSync5(ALL_MODELS_JSON_PATH, JSON.stringify({
30943
31153
  lastUpdated: new Date().toISOString(),
30944
31154
  models
30945
31155
  }), "utf-8");
@@ -31318,11 +31528,11 @@ async function fetchOllamaCloudModels() {
31318
31528
  }
31319
31529
  }
31320
31530
  function shouldRefreshForFreeModels() {
31321
- if (!existsSync6(ALL_MODELS_JSON_PATH)) {
31531
+ if (!existsSync7(ALL_MODELS_JSON_PATH)) {
31322
31532
  return true;
31323
31533
  }
31324
31534
  try {
31325
- const cacheData = JSON.parse(readFileSync5(ALL_MODELS_JSON_PATH, "utf-8"));
31535
+ const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH, "utf-8"));
31326
31536
  const lastUpdated = new Date(cacheData.lastUpdated);
31327
31537
  const now = new Date;
31328
31538
  const ageInHours = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60);
@@ -31362,7 +31572,9 @@ async function getFreeModels() {
31362
31572
  return combined;
31363
31573
  }
31364
31574
  async function getAllModelsForSearch() {
31365
- const [openRouterModels, xaiModels, geminiModels, openaiModels, glmDirectModels, glmCodingModels, ollamaCloudModels, zenModels] = await Promise.all([
31575
+ const litellmBaseUrl = process.env.LITELLM_BASE_URL;
31576
+ const litellmApiKey = process.env.LITELLM_API_KEY;
31577
+ const fetchPromises = [
31366
31578
  fetchAllModels().then((models) => models.map(toModelInfo)),
31367
31579
  fetchXAIModels(),
31368
31580
  fetchGeminiModels(),
@@ -31371,9 +31583,14 @@ async function getAllModelsForSearch() {
31371
31583
  fetchGLMCodingModels(),
31372
31584
  fetchOllamaCloudModels(),
31373
31585
  fetchZenFreeModels()
31374
- ]);
31586
+ ];
31587
+ if (litellmBaseUrl && litellmApiKey) {
31588
+ fetchPromises.push(fetchLiteLLMModels(litellmBaseUrl, litellmApiKey));
31589
+ }
31590
+ const results = await Promise.all(fetchPromises);
31591
+ const [openRouterModels, xaiModels, geminiModels, openaiModels, glmDirectModels, glmCodingModels, ollamaCloudModels, zenModels, litellmModels = []] = results;
31375
31592
  const directApiModels = [...xaiModels, ...geminiModels, ...openaiModels, ...glmDirectModels, ...glmCodingModels];
31376
- const allModels = [...zenModels, ...ollamaCloudModels, ...directApiModels, ...openRouterModels];
31593
+ const allModels = [...zenModels, ...ollamaCloudModels, ...directApiModels, ...litellmModels, ...openRouterModels];
31377
31594
  return allModels;
31378
31595
  }
31379
31596
  function formatModelChoice(model, showSource = false) {
@@ -31394,7 +31611,8 @@ function formatModelChoice(model, showSource = false) {
31394
31611
  OpenAI: "OAI",
31395
31612
  GLM: "GLM",
31396
31613
  "GLM Coding": "GC",
31397
- OllamaCloud: "OC"
31614
+ OllamaCloud: "OC",
31615
+ LiteLLM: "LL"
31398
31616
  };
31399
31617
  const sourceTag = sourceTagMap[model.source] || model.source;
31400
31618
  return `${sourceTag} ${model.id} (${priceStr}, ${ctxStr}${capsStr})`;
@@ -31736,14 +31954,15 @@ async function selectProfile(profiles) {
31736
31954
  async function confirmAction(message) {
31737
31955
  return dist_default2({ message, default: false });
31738
31956
  }
31739
- var __filename3, __dirname3, 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;
31957
+ 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
31958
  var init_model_selector = __esm(() => {
31741
31959
  init_dist8();
31742
- __filename3 = fileURLToPath2(import.meta.url);
31743
- __dirname3 = dirname2(__filename3);
31744
- CLAUDISH_CACHE_DIR2 = join6(homedir5(), ".claudish");
31745
- ALL_MODELS_JSON_PATH = join6(CLAUDISH_CACHE_DIR2, "all-models.json");
31746
- RECOMMENDED_MODELS_JSON_PATH = join6(__dirname3, "../recommended-models.json");
31960
+ init_model_loader();
31961
+ __filename4 = fileURLToPath3(import.meta.url);
31962
+ __dirname4 = dirname3(__filename4);
31963
+ CLAUDISH_CACHE_DIR2 = join7(homedir6(), ".claudish");
31964
+ ALL_MODELS_JSON_PATH = join7(CLAUDISH_CACHE_DIR2, "all-models.json");
31965
+ RECOMMENDED_MODELS_JSON_PATH = join7(__dirname4, "../recommended-models.json");
31747
31966
  PROVIDER_CHOICES = [
31748
31967
  { name: "Skip (keep Claude default)", value: "skip", description: "Use native Claude model for this tier" },
31749
31968
  { name: "OpenRouter", value: "openrouter", description: "580+ models via unified API" },
@@ -32320,132 +32539,6 @@ var init_config = __esm(() => {
32320
32539
  };
32321
32540
  });
32322
32541
 
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
32542
  // src/utils.ts
32450
32543
  function fuzzyScore2(text, query) {
32451
32544
  if (!text || !query)
@@ -33084,7 +33177,7 @@ __export(exports_provider_resolver, {
33084
33177
  });
33085
33178
  import { existsSync as existsSync8 } from "node:fs";
33086
33179
  import { join as join8 } from "node:path";
33087
- import { homedir as homedir6 } from "node:os";
33180
+ import { homedir as homedir7 } from "node:os";
33088
33181
  function isApiKeyAvailable(info) {
33089
33182
  if (!info.envVar) {
33090
33183
  return true;
@@ -33101,7 +33194,7 @@ function isApiKeyAvailable(info) {
33101
33194
  }
33102
33195
  if (info.oauthFallback) {
33103
33196
  try {
33104
- const credPath = join8(homedir6(), ".claudish", info.oauthFallback);
33197
+ const credPath = join8(homedir7(), ".claudish", info.oauthFallback);
33105
33198
  if (existsSync8(credPath)) {
33106
33199
  return true;
33107
33200
  }
@@ -33475,10 +33568,10 @@ __export(exports_cli, {
33475
33568
  getMissingKeyResolutions: () => getMissingKeyResolutions,
33476
33569
  getMissingKeyError: () => getMissingKeyError
33477
33570
  });
33478
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, existsSync as existsSync9, mkdirSync as mkdirSync5, copyFileSync } from "node:fs";
33571
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync9, mkdirSync as mkdirSync6, copyFileSync } from "node:fs";
33479
33572
  import { fileURLToPath as fileURLToPath4 } from "node:url";
33480
33573
  import { dirname as dirname4, join as join9 } from "node:path";
33481
- import { homedir as homedir7 } from "node:os";
33574
+ import { homedir as homedir8 } from "node:os";
33482
33575
  function getVersion() {
33483
33576
  return VERSION;
33484
33577
  }
@@ -33755,8 +33848,8 @@ async function searchAndPrintModels(query, forceUpdate) {
33755
33848
  throw new Error(`API returned ${response.status}`);
33756
33849
  const data = await response.json();
33757
33850
  models = data.data;
33758
- mkdirSync5(CLAUDISH_CACHE_DIR3, { recursive: true });
33759
- writeFileSync5(ALL_MODELS_JSON_PATH2, JSON.stringify({
33851
+ mkdirSync6(CLAUDISH_CACHE_DIR3, { recursive: true });
33852
+ writeFileSync6(ALL_MODELS_JSON_PATH2, JSON.stringify({
33760
33853
  lastUpdated: new Date().toISOString(),
33761
33854
  models
33762
33855
  }), "utf-8");
@@ -33916,8 +34009,8 @@ async function printAllModels(jsonOutput, forceUpdate) {
33916
34009
  throw new Error(`API returned ${response.status}`);
33917
34010
  const data = await response.json();
33918
34011
  models = data.data;
33919
- mkdirSync5(CLAUDISH_CACHE_DIR3, { recursive: true });
33920
- writeFileSync5(ALL_MODELS_JSON_PATH2, JSON.stringify({
34012
+ mkdirSync6(CLAUDISH_CACHE_DIR3, { recursive: true });
34013
+ writeFileSync6(ALL_MODELS_JSON_PATH2, JSON.stringify({
33921
34014
  lastUpdated: new Date().toISOString(),
33922
34015
  models
33923
34016
  }), "utf-8");
@@ -34182,7 +34275,7 @@ async function updateModelsFromOpenRouter() {
34182
34275
  source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
34183
34276
  models: recommendations
34184
34277
  };
34185
- writeFileSync5(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
34278
+ writeFileSync6(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
34186
34279
  console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
34187
34280
  } catch (error46) {
34188
34281
  console.error(`❌ Failed to update models: ${error46 instanceof Error ? error46.message : String(error46)}`);
@@ -34543,15 +34636,15 @@ async function initializeClaudishSkill() {
34543
34636
  }
34544
34637
  try {
34545
34638
  if (!existsSync9(claudeDir)) {
34546
- mkdirSync5(claudeDir, { recursive: true });
34639
+ mkdirSync6(claudeDir, { recursive: true });
34547
34640
  console.log("\uD83D\uDCC1 Created .claude/ directory");
34548
34641
  }
34549
34642
  if (!existsSync9(skillsDir)) {
34550
- mkdirSync5(skillsDir, { recursive: true });
34643
+ mkdirSync6(skillsDir, { recursive: true });
34551
34644
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
34552
34645
  }
34553
34646
  if (!existsSync9(claudishSkillDir)) {
34554
- mkdirSync5(claudishSkillDir, { recursive: true });
34647
+ mkdirSync6(claudishSkillDir, { recursive: true });
34555
34648
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
34556
34649
  }
34557
34650
  copyFileSync(sourceSkillPath, skillFile);
@@ -34741,7 +34834,7 @@ async function fetchGLMCodingModels2() {
34741
34834
  return [];
34742
34835
  }
34743
34836
  }
34744
- var __filename5, __dirname5, VERSION = "4.6.0", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, CLAUDISH_CACHE_DIR3, ALL_MODELS_JSON_PATH2;
34837
+ var __filename5, __dirname5, VERSION = "4.6.2", CACHE_MAX_AGE_DAYS3 = 2, MODELS_JSON_PATH, CLAUDISH_CACHE_DIR3, ALL_MODELS_JSON_PATH2;
34745
34838
  var init_cli = __esm(() => {
34746
34839
  init_config();
34747
34840
  init_model_loader();
@@ -34754,7 +34847,7 @@ var init_cli = __esm(() => {
34754
34847
  VERSION = packageJson.version;
34755
34848
  } catch {}
34756
34849
  MODELS_JSON_PATH = join9(__dirname5, "../recommended-models.json");
34757
- CLAUDISH_CACHE_DIR3 = join9(homedir7(), ".claudish");
34850
+ CLAUDISH_CACHE_DIR3 = join9(homedir8(), ".claudish");
34758
34851
  ALL_MODELS_JSON_PATH2 = join9(CLAUDISH_CACHE_DIR3, "all-models.json");
34759
34852
  });
34760
34853
 
@@ -34765,8 +34858,8 @@ __export(exports_claude_runner, {
34765
34858
  checkClaudeInstalled: () => checkClaudeInstalled
34766
34859
  });
34767
34860
  import { spawn } from "node:child_process";
34768
- import { writeFileSync as writeFileSync6, unlinkSync as unlinkSync3, mkdirSync as mkdirSync6, existsSync as existsSync10 } from "node:fs";
34769
- import { tmpdir, homedir as homedir8 } from "node:os";
34861
+ import { writeFileSync as writeFileSync7, unlinkSync as unlinkSync3, mkdirSync as mkdirSync7, existsSync as existsSync10 } from "node:fs";
34862
+ import { tmpdir, homedir as homedir9 } from "node:os";
34770
34863
  import { join as join10 } from "node:path";
34771
34864
  function isWindows() {
34772
34865
  return process.platform === "win32";
@@ -34855,14 +34948,14 @@ process.stdin.on('end', () => {
34855
34948
  }
34856
34949
  });
34857
34950
  `;
34858
- writeFileSync6(scriptPath, script, "utf-8");
34951
+ writeFileSync7(scriptPath, script, "utf-8");
34859
34952
  return scriptPath;
34860
34953
  }
34861
34954
  function createTempSettingsFile(modelDisplay, port) {
34862
34955
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
34863
34956
  const claudishDir = join10(homeDir, ".claudish");
34864
34957
  try {
34865
- mkdirSync6(claudishDir, { recursive: true });
34958
+ mkdirSync7(claudishDir, { recursive: true });
34866
34959
  } catch {}
34867
34960
  const timestamp = Date.now();
34868
34961
  const tempPath = join10(claudishDir, `settings-${timestamp}.json`);
@@ -34889,7 +34982,7 @@ function createTempSettingsFile(modelDisplay, port) {
34889
34982
  padding: 0
34890
34983
  }
34891
34984
  };
34892
- writeFileSync6(tempPath, JSON.stringify(settings, null, 2), "utf-8");
34985
+ writeFileSync7(tempPath, JSON.stringify(settings, null, 2), "utf-8");
34893
34986
  return tempPath;
34894
34987
  }
34895
34988
  async function runClaudeWithProxy(config3, proxyUrl) {
@@ -34971,7 +35064,7 @@ async function runClaudeWithProxy(config3, proxyUrl) {
34971
35064
  console.error("Install it from: https://claude.com/claude-code");
34972
35065
  console.error(`
34973
35066
  Or set CLAUDE_PATH to your custom installation:`);
34974
- const home = homedir8();
35067
+ const home = homedir9();
34975
35068
  const localPath = isWindows() ? join10(home, ".claude", "local", "claude.exe") : join10(home, ".claude", "local", "claude");
34976
35069
  console.error(` export CLAUDE_PATH=${localPath}`);
34977
35070
  process.exit(1);
@@ -35015,7 +35108,7 @@ async function findClaudeBinary() {
35015
35108
  return process.env.CLAUDE_PATH;
35016
35109
  }
35017
35110
  }
35018
- const home = homedir8();
35111
+ const home = homedir9();
35019
35112
  const localPath = isWindows2 ? join10(home, ".claude", "local", "claude.exe") : join10(home, ".claude", "local", "claude");
35020
35113
  if (existsSync10(localPath)) {
35021
35114
  return localPath;
@@ -39525,8 +39618,8 @@ var init_remote_provider_types = __esm(() => {
39525
39618
  });
39526
39619
 
39527
39620
  // src/handlers/openrouter-handler.ts
39528
- import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "node:fs";
39529
- import { homedir as homedir9 } from "node:os";
39621
+ import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "node:fs";
39622
+ import { homedir as homedir10 } from "node:os";
39530
39623
  import { join as join11 } from "node:path";
39531
39624
 
39532
39625
  class OpenRouterHandler {
@@ -39579,9 +39672,9 @@ class OpenRouterHandler {
39579
39672
  updated_at: Date.now(),
39580
39673
  is_free: isFreeModel
39581
39674
  };
39582
- const claudishDir = join11(homedir9(), ".claudish");
39583
- mkdirSync7(claudishDir, { recursive: true });
39584
- writeFileSync7(join11(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
39675
+ const claudishDir = join11(homedir10(), ".claudish");
39676
+ mkdirSync8(claudishDir, { recursive: true });
39677
+ writeFileSync8(join11(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
39585
39678
  } catch (e) {}
39586
39679
  }
39587
39680
  async handle(c, payload) {
@@ -60588,8 +60681,8 @@ var init_local_queue = __esm(() => {
60588
60681
  });
60589
60682
 
60590
60683
  // src/handlers/local-provider-handler.ts
60591
- import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "node:fs";
60592
- import { homedir as homedir10 } from "node:os";
60684
+ import { writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
60685
+ import { homedir as homedir11 } from "node:os";
60593
60686
  import { join as join12 } from "node:path";
60594
60687
 
60595
60688
  class LocalProviderHandler {
@@ -60769,9 +60862,9 @@ class LocalProviderHandler {
60769
60862
  provider_name: providerNameMap[this.provider.name] || "Local",
60770
60863
  updated_at: Date.now()
60771
60864
  };
60772
- const claudishDir = join12(homedir10(), ".claudish");
60773
- mkdirSync8(claudishDir, { recursive: true });
60774
- writeFileSync8(join12(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
60865
+ const claudishDir = join12(homedir11(), ".claudish");
60866
+ mkdirSync9(claudishDir, { recursive: true });
60867
+ writeFileSync9(join12(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
60775
60868
  } catch (e) {}
60776
60869
  }
60777
60870
  async handle(c, payload) {
@@ -61361,8 +61454,8 @@ var init_gemini_retry = __esm(() => {
61361
61454
  });
61362
61455
 
61363
61456
  // src/handlers/base-gemini-handler.ts
61364
- import { writeFileSync as writeFileSync9, mkdirSync as mkdirSync9 } from "node:fs";
61365
- import { homedir as homedir11 } from "node:os";
61457
+ import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
61458
+ import { homedir as homedir12 } from "node:os";
61366
61459
  import { join as join13 } from "node:path";
61367
61460
 
61368
61461
  class BaseGeminiHandler {
@@ -61403,9 +61496,9 @@ class BaseGeminiHandler {
61403
61496
  provider_name: this.getProviderName(),
61404
61497
  updated_at: Date.now()
61405
61498
  };
61406
- const claudishDir = join13(homedir11(), ".claudish");
61407
- mkdirSync9(claudishDir, { recursive: true });
61408
- writeFileSync9(join13(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
61499
+ const claudishDir = join13(homedir12(), ".claudish");
61500
+ mkdirSync10(claudishDir, { recursive: true });
61501
+ writeFileSync10(join13(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
61409
61502
  } catch (e) {
61410
61503
  log(`[BaseGeminiHandler] Error writing token file: ${e}`);
61411
61504
  }
@@ -61946,8 +62039,8 @@ var init_gemini_handler = __esm(() => {
61946
62039
  });
61947
62040
 
61948
62041
  // src/handlers/gemini-codeassist-handler.ts
61949
- import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync10 } from "node:fs";
61950
- import { homedir as homedir12 } from "node:os";
62042
+ import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync11 } from "node:fs";
62043
+ import { homedir as homedir13 } from "node:os";
61951
62044
  import { join as join14 } from "node:path";
61952
62045
  import { randomUUID } from "node:crypto";
61953
62046
 
@@ -61996,9 +62089,9 @@ class GeminiCodeAssistHandler {
61996
62089
  provider_name: "Gemini Free",
61997
62090
  updated_at: Date.now()
61998
62091
  };
61999
- const claudishDir = join14(homedir12(), ".claudish");
62000
- mkdirSync10(claudishDir, { recursive: true });
62001
- writeFileSync10(join14(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
62092
+ const claudishDir = join14(homedir13(), ".claudish");
62093
+ mkdirSync11(claudishDir, { recursive: true });
62094
+ writeFileSync11(join14(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
62002
62095
  } catch (e) {
62003
62096
  log(`[GeminiCodeAssistHandler] Error writing token file: ${e}`);
62004
62097
  }
@@ -62413,8 +62506,8 @@ var init_gemini_codeassist_handler = __esm(() => {
62413
62506
  });
62414
62507
 
62415
62508
  // src/handlers/openai-handler.ts
62416
- import { writeFileSync as writeFileSync11, mkdirSync as mkdirSync11 } from "node:fs";
62417
- import { homedir as homedir13 } from "node:os";
62509
+ import { writeFileSync as writeFileSync12, mkdirSync as mkdirSync12 } from "node:fs";
62510
+ import { homedir as homedir14 } from "node:os";
62418
62511
  import { join as join15 } from "node:path";
62419
62512
 
62420
62513
  class OpenAIHandler {
@@ -62529,9 +62622,9 @@ class OpenAIHandler {
62529
62622
  is_free: isFreeModel,
62530
62623
  is_estimated: isEstimate || false
62531
62624
  };
62532
- const claudishDir = join15(homedir13(), ".claudish");
62533
- mkdirSync11(claudishDir, { recursive: true });
62534
- writeFileSync11(join15(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
62625
+ const claudishDir = join15(homedir14(), ".claudish");
62626
+ mkdirSync12(claudishDir, { recursive: true });
62627
+ writeFileSync12(join15(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
62535
62628
  } catch (e) {
62536
62629
  log(`[OpenAIHandler] Error writing token file: ${e}`);
62537
62630
  }
@@ -63139,8 +63232,8 @@ var init_openai_handler = __esm(() => {
63139
63232
  });
63140
63233
 
63141
63234
  // src/handlers/anthropic-compat-handler.ts
63142
- import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "node:fs";
63143
- import { homedir as homedir14 } from "node:os";
63235
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync13 } from "node:fs";
63236
+ import { homedir as homedir15 } from "node:os";
63144
63237
  import { join as join16 } from "node:path";
63145
63238
 
63146
63239
  class AnthropicCompatHandler {
@@ -63203,9 +63296,9 @@ class AnthropicCompatHandler {
63203
63296
  provider_name: providerDisplayName,
63204
63297
  updated_at: Date.now()
63205
63298
  };
63206
- const claudishDir = join16(homedir14(), ".claudish");
63207
- mkdirSync12(claudishDir, { recursive: true });
63208
- writeFileSync12(join16(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
63299
+ const claudishDir = join16(homedir15(), ".claudish");
63300
+ mkdirSync13(claudishDir, { recursive: true });
63301
+ writeFileSync13(join16(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
63209
63302
  } catch (e) {
63210
63303
  log(`[AnthropicCompatHandler] Error writing token file: ${e}`);
63211
63304
  }
@@ -63244,8 +63337,8 @@ class AnthropicCompatHandler {
63244
63337
  try {
63245
63338
  const { existsSync: existsSync11, readFileSync: readFileSync8 } = await import("node:fs");
63246
63339
  const { join: join17 } = await import("node:path");
63247
- const { homedir: homedir15 } = await import("node:os");
63248
- const credPath = join17(homedir15(), ".claudish", "kimi-oauth.json");
63340
+ const { homedir: homedir16 } = await import("node:os");
63341
+ const credPath = join17(homedir16(), ".claudish", "kimi-oauth.json");
63249
63342
  if (existsSync11(credPath)) {
63250
63343
  const data2 = JSON.parse(readFileSync8(credPath, "utf-8"));
63251
63344
  if (data2.access_token && data2.refresh_token) {
@@ -63354,7 +63447,7 @@ var init_anthropic_compat_handler = __esm(() => {
63354
63447
  import { exec as exec4 } from "node:child_process";
63355
63448
  import { promisify as promisify3 } from "node:util";
63356
63449
  import { existsSync as existsSync11 } from "node:fs";
63357
- import { homedir as homedir15 } from "node:os";
63450
+ import { homedir as homedir16 } from "node:os";
63358
63451
  import { join as join17 } from "node:path";
63359
63452
 
63360
63453
  class VertexAuthManager {
@@ -63409,7 +63502,7 @@ class VertexAuthManager {
63409
63502
  }
63410
63503
  async tryADC() {
63411
63504
  try {
63412
- const adcPath = join17(homedir15(), ".config/gcloud/application_default_credentials.json");
63505
+ const adcPath = join17(homedir16(), ".config/gcloud/application_default_credentials.json");
63413
63506
  if (!existsSync11(adcPath)) {
63414
63507
  log("[VertexAuth] ADC credentials file not found");
63415
63508
  return null;
@@ -63473,7 +63566,7 @@ function validateVertexOAuthConfig() {
63473
63566
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
63474
63567
  ` + " export VERTEX_LOCATION='us-central1' # optional";
63475
63568
  }
63476
- const adcPath = join17(homedir15(), ".config/gcloud/application_default_credentials.json");
63569
+ const adcPath = join17(homedir16(), ".config/gcloud/application_default_credentials.json");
63477
63570
  const hasADC = existsSync11(adcPath);
63478
63571
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
63479
63572
  if (!hasADC && !hasServiceAccount) {
@@ -63510,8 +63603,8 @@ var init_vertex_auth = __esm(() => {
63510
63603
  });
63511
63604
 
63512
63605
  // src/handlers/vertex-oauth-handler.ts
63513
- import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync13 } from "node:fs";
63514
- import { homedir as homedir16 } from "node:os";
63606
+ import { writeFileSync as writeFileSync14, mkdirSync as mkdirSync14 } from "node:fs";
63607
+ import { homedir as homedir17 } from "node:os";
63515
63608
  import { join as join18 } from "node:path";
63516
63609
  function parseVertexModel(modelId) {
63517
63610
  const parts = modelId.split("/");
@@ -63568,9 +63661,9 @@ class VertexOAuthHandler {
63568
63661
  provider_name: "Vertex AI",
63569
63662
  updated_at: Date.now()
63570
63663
  };
63571
- const claudishDir = join18(homedir16(), ".claudish");
63572
- mkdirSync13(claudishDir, { recursive: true });
63573
- writeFileSync13(join18(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
63664
+ const claudishDir = join18(homedir17(), ".claudish");
63665
+ mkdirSync14(claudishDir, { recursive: true });
63666
+ writeFileSync14(join18(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
63574
63667
  } catch (e) {
63575
63668
  log(`[VertexOAuth] Error writing token file: ${e}`);
63576
63669
  }
@@ -64275,7 +64368,7 @@ var init_vertex_oauth_handler = __esm(() => {
64275
64368
  });
64276
64369
 
64277
64370
  // src/handlers/poe-handler.ts
64278
- import { createHash as createHash2 } from "node:crypto";
64371
+ import { createHash as createHash3 } from "node:crypto";
64279
64372
 
64280
64373
  class SSEParser {
64281
64374
  buffer = "";
@@ -64509,7 +64602,7 @@ class PoeHandler {
64509
64602
  headers;
64510
64603
  constructor(apiKey) {
64511
64604
  this.apiKey = apiKey;
64512
- this.apiKeySha = createHash2("sha256").update(apiKey).digest("hex").substring(0, 16);
64605
+ this.apiKeySha = createHash3("sha256").update(apiKey).digest("hex").substring(0, 16);
64513
64606
  this.headers = {
64514
64607
  "Content-Type": "application/json",
64515
64608
  Authorization: `Bearer ${apiKey}`
@@ -64944,8 +65037,8 @@ var init_poe_handler = __esm(() => {
64944
65037
  });
64945
65038
 
64946
65039
  // src/handlers/ollamacloud-handler.ts
64947
- import { writeFileSync as writeFileSync14, mkdirSync as mkdirSync14 } from "node:fs";
64948
- import { homedir as homedir17 } from "node:os";
65040
+ import { writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "node:fs";
65041
+ import { homedir as homedir18 } from "node:os";
64949
65042
  import { join as join19 } from "node:path";
64950
65043
 
64951
65044
  class OllamaCloudHandler {
@@ -65031,9 +65124,9 @@ class OllamaCloudHandler {
65031
65124
  provider_name: "OllamaCloud",
65032
65125
  updated_at: Date.now()
65033
65126
  };
65034
- const claudishDir = join19(homedir17(), ".claudish");
65035
- mkdirSync14(claudishDir, { recursive: true });
65036
- writeFileSync14(join19(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
65127
+ const claudishDir = join19(homedir18(), ".claudish");
65128
+ mkdirSync15(claudishDir, { recursive: true });
65129
+ writeFileSync15(join19(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
65037
65130
  } catch (e) {}
65038
65131
  }
65039
65132
  async handle(c, payload) {
@@ -65246,8 +65339,8 @@ var init_ollamacloud_handler = __esm(() => {
65246
65339
  });
65247
65340
 
65248
65341
  // src/services/pricing-cache.ts
65249
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync15, existsSync as existsSync12, mkdirSync as mkdirSync15, statSync } from "node:fs";
65250
- import { homedir as homedir18 } from "node:os";
65342
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync16, existsSync as existsSync12, mkdirSync as mkdirSync16, statSync } from "node:fs";
65343
+ import { homedir as homedir19 } from "node:os";
65251
65344
  import { join as join20 } from "node:path";
65252
65345
  function getDynamicPricingSync(provider, modelName) {
65253
65346
  if (provider === "openrouter") {
@@ -65330,12 +65423,12 @@ function loadDiskCache() {
65330
65423
  }
65331
65424
  function saveDiskCache() {
65332
65425
  try {
65333
- mkdirSync15(CACHE_DIR, { recursive: true });
65426
+ mkdirSync16(CACHE_DIR, { recursive: true });
65334
65427
  const data = {};
65335
65428
  for (const [key, pricing] of pricingMap) {
65336
65429
  data[key] = pricing;
65337
65430
  }
65338
- writeFileSync15(CACHE_FILE, JSON.stringify(data), "utf-8");
65431
+ writeFileSync16(CACHE_FILE, JSON.stringify(data), "utf-8");
65339
65432
  } catch (error46) {
65340
65433
  log(`[PricingCache] Error saving disk cache: ${error46}`);
65341
65434
  }
@@ -65365,7 +65458,7 @@ var init_pricing_cache = __esm(() => {
65365
65458
  init_model_loader();
65366
65459
  init_remote_provider_types();
65367
65460
  pricingMap = new Map;
65368
- CACHE_DIR = join20(homedir18(), ".claudish");
65461
+ CACHE_DIR = join20(homedir19(), ".claudish");
65369
65462
  CACHE_FILE = join20(CACHE_DIR, "pricing-cache.json");
65370
65463
  CACHE_TTL_MS = 24 * 60 * 60 * 1000;
65371
65464
  PROVIDER_TO_OR_PREFIX = {
@@ -65397,7 +65490,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
65397
65490
  const poeHandlers = new Map;
65398
65491
  const getOpenRouterHandler = (targetModel) => {
65399
65492
  const parsed = parseModelSpec(targetModel);
65400
- const modelId = parsed.provider === "openrouter" ? parsed.model : targetModel;
65493
+ const modelId = parsed.provider !== "native-anthropic" ? parsed.model : targetModel;
65401
65494
  if (!openRouterHandlers.has(modelId)) {
65402
65495
  openRouterHandlers.set(modelId, new OpenRouterHandler(modelId, openrouterApiKey, port));
65403
65496
  }
@@ -65517,7 +65610,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
65517
65610
  const getHandlerForRequest = (requestedModel) => {
65518
65611
  if (monitorMode)
65519
65612
  return nativeHandler;
65520
- let target = requestedModel || model;
65613
+ let target = requestedModel;
65521
65614
  const req = requestedModel.toLowerCase();
65522
65615
  if (modelMap) {
65523
65616
  if (req.includes("opus") && modelMap.opus)
@@ -65526,6 +65619,10 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
65526
65619
  target = modelMap.sonnet;
65527
65620
  else if (req.includes("haiku") && modelMap.haiku)
65528
65621
  target = modelMap.haiku;
65622
+ else if (model)
65623
+ target = model;
65624
+ } else if (model) {
65625
+ target = model;
65529
65626
  }
65530
65627
  if (isPoeModel(target)) {
65531
65628
  const poeHandler = getPoeHandler(target);
@@ -65540,7 +65637,8 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
65540
65637
  const localHandler = getLocalProviderHandler(target);
65541
65638
  if (localHandler)
65542
65639
  return localHandler;
65543
- const isNative = !target.includes("/");
65640
+ const hasExplicitProvider = target.includes("@");
65641
+ const isNative = !target.includes("/") && !hasExplicitProvider;
65544
65642
  if (isNative) {
65545
65643
  return nativeHandler;
65546
65644
  }
@@ -65634,8 +65732,8 @@ __export(exports_update_checker, {
65634
65732
  checkForUpdates: () => checkForUpdates
65635
65733
  });
65636
65734
  import { execSync } from "node:child_process";
65637
- import { existsSync as existsSync13, mkdirSync as mkdirSync16, readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync16 } from "node:fs";
65638
- import { homedir as homedir19, platform as platform2, tmpdir as tmpdir2 } from "node:os";
65735
+ import { existsSync as existsSync13, mkdirSync as mkdirSync17, readFileSync as readFileSync10, unlinkSync as unlinkSync4, writeFileSync as writeFileSync17 } from "node:fs";
65736
+ import { homedir as homedir20, platform as platform2, tmpdir as tmpdir2 } from "node:os";
65639
65737
  import { join as join21 } from "node:path";
65640
65738
  import { createInterface as createInterface2 } from "node:readline";
65641
65739
  function getUpdateCommand() {
@@ -65648,14 +65746,14 @@ function getUpdateCommand() {
65648
65746
  function getCacheFilePath() {
65649
65747
  let cacheDir;
65650
65748
  if (isWindows2) {
65651
- const localAppData = process.env.LOCALAPPDATA || join21(homedir19(), "AppData", "Local");
65749
+ const localAppData = process.env.LOCALAPPDATA || join21(homedir20(), "AppData", "Local");
65652
65750
  cacheDir = join21(localAppData, "claudish");
65653
65751
  } else {
65654
- cacheDir = join21(homedir19(), ".cache", "claudish");
65752
+ cacheDir = join21(homedir20(), ".cache", "claudish");
65655
65753
  }
65656
65754
  try {
65657
65755
  if (!existsSync13(cacheDir)) {
65658
- mkdirSync16(cacheDir, { recursive: true });
65756
+ mkdirSync17(cacheDir, { recursive: true });
65659
65757
  }
65660
65758
  return join21(cacheDir, "update-check.json");
65661
65759
  } catch {
@@ -65681,7 +65779,7 @@ function writeCache(latestVersion) {
65681
65779
  lastCheck: Date.now(),
65682
65780
  latestVersion
65683
65781
  };
65684
- writeFileSync16(cachePath, JSON.stringify(data), "utf-8");
65782
+ writeFileSync17(cachePath, JSON.stringify(data), "utf-8");
65685
65783
  } catch {}
65686
65784
  }
65687
65785
  function isCacheValid(cache) {
@@ -65927,6 +66025,8 @@ function getUpdateCommand2(method) {
65927
66025
  }
65928
66026
  async function runSelfUpdate() {
65929
66027
  const { getVersion: getVersion2 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
66028
+ const { execSync: execSync2 } = await import("node:child_process");
66029
+ const { createInterface: createInterface3 } = await import("node:readline");
65930
66030
  const currentVersion = getVersion2();
65931
66031
  const installMethod = detectInstallMethod();
65932
66032
  console.log(`claudish v${currentVersion}`);
@@ -65948,12 +66048,39 @@ Checking for updates...
65948
66048
  console.log(`✓ claudish is up to date (v${currentVersion})`);
65949
66049
  process.exit(0);
65950
66050
  }
66051
+ const updateCmd = getUpdateCommand2(installMethod);
65951
66052
  console.log(`New version available: v${currentVersion} → v${latestVersion}
65952
66053
  `);
65953
- const updateCmd = getUpdateCommand2(installMethod);
65954
- console.log(`To update, run:
66054
+ const shouldUpdate = await new Promise((resolve) => {
66055
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
66056
+ rl.question("Update now? [Y/n] ", (answer) => {
66057
+ rl.close();
66058
+ const normalized = answer.toLowerCase().trim();
66059
+ resolve(normalized === "" || normalized === "y" || normalized === "yes");
66060
+ });
66061
+ });
66062
+ if (!shouldUpdate) {
66063
+ console.log(`
66064
+ Skipped. Update later with:
66065
+ ${updateCmd}
66066
+ `);
66067
+ process.exit(0);
66068
+ }
66069
+ console.log(`
66070
+ Updating...
66071
+ `);
66072
+ try {
66073
+ execSync2(updateCmd, { stdio: "inherit", shell: true });
66074
+ console.log(`
66075
+ ✓ Updated to v${latestVersion}! Please restart claudish.
66076
+ `);
66077
+ } catch {
66078
+ console.error(`
66079
+ Update failed. Try manually:
65955
66080
  ${updateCmd}
65956
66081
  `);
66082
+ process.exit(1);
66083
+ }
65957
66084
  process.exit(0);
65958
66085
  } catch (error46) {
65959
66086
  console.error("Failed to check for updates:", error46 instanceof Error ? error46.message : error46);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "4.6.0",
3
+ "version": "4.6.2",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1.2.0",
3
- "lastUpdated": "2026-02-12",
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": "$0.45/1M",
141
- "output": "$3.50/1M",
142
- "average": "$1.98/1M"
140
+ "input": "FREE",
141
+ "output": "FREE",
142
+ "average": "FREE"
143
143
  },
144
- "context": "262K",
145
- "maxOutputTokens": 262144,
144
+ "context": "131K",
145
+ "maxOutputTokens": 32768,
146
146
  "modality": "text+image->text",
147
147
  "supportsTools": true,
148
148
  "supportsReasoning": true,