claudish 6.11.0 → 6.11.1

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
@@ -17324,6 +17324,24 @@ function loadRecommendedModelsJSON() {
17324
17324
  if (_cachedRecommendedModels) {
17325
17325
  return _cachedRecommendedModels;
17326
17326
  }
17327
+ if (existsSync3(RECOMMENDED_CACHE_PATH)) {
17328
+ try {
17329
+ const cacheData = JSON.parse(readFileSync2(RECOMMENDED_CACHE_PATH, "utf-8"));
17330
+ if (cacheData.models && cacheData.models.length > 0) {
17331
+ const generatedAt = cacheData.generatedAt;
17332
+ if (generatedAt) {
17333
+ const ageHours = (Date.now() - new Date(generatedAt).getTime()) / (1000 * 60 * 60);
17334
+ if (ageHours <= RECOMMENDED_CACHE_MAX_AGE_HOURS) {
17335
+ _cachedRecommendedModels = cacheData;
17336
+ return cacheData;
17337
+ }
17338
+ } else {
17339
+ _cachedRecommendedModels = cacheData;
17340
+ return cacheData;
17341
+ }
17342
+ }
17343
+ } catch {}
17344
+ }
17327
17345
  const jsonPath = getRecommendedModelsPath();
17328
17346
  if (!existsSync3(jsonPath)) {
17329
17347
  throw new Error(`recommended-models.json not found at ${jsonPath}. ` + `Run 'claudish --update-models' to fetch the latest model list.`);
@@ -17468,10 +17486,11 @@ async function fetchLiteLLMModels(baseUrl, apiKey, forceUpdate = false) {
17468
17486
  return [];
17469
17487
  }
17470
17488
  }
17471
- var __filename2, __dirname2, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, _cachedOpenRouterModels = null, LITELLM_CACHE_MAX_AGE_HOURS = 24;
17489
+ var __filename2, __dirname2, _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels = null, RECOMMENDED_CACHE_PATH, RECOMMENDED_CACHE_MAX_AGE_HOURS = 12, _cachedOpenRouterModels = null, LITELLM_CACHE_MAX_AGE_HOURS = 24;
17472
17490
  var init_model_loader = __esm(() => {
17473
17491
  __filename2 = fileURLToPath(import.meta.url);
17474
17492
  __dirname2 = dirname(__filename2);
17493
+ RECOMMENDED_CACHE_PATH = join4(homedir3(), ".claudish", "recommended-models-cache.json");
17475
17494
  });
17476
17495
 
17477
17496
  // src/providers/transport/openrouter.ts
@@ -17506,7 +17525,7 @@ class OpenRouterProviderTransport {
17506
17525
  getContextWindow() {
17507
17526
  const models = this.modelId ? getCachedOpenRouterModels() : null;
17508
17527
  const model = models?.find((m) => m.id === this.modelId);
17509
- return model?.context_length || model?.top_provider?.context_length || 200000;
17528
+ return model?.context_length || model?.top_provider?.context_length || 0;
17510
17529
  }
17511
17530
  }
17512
17531
  var OPENROUTER_API_URL = "https://openrouter.ai/api/v1/chat/completions";
@@ -17589,6 +17608,83 @@ var init_remote_provider_types = __esm(() => {
17589
17608
  };
17590
17609
  });
17591
17610
 
17611
+ // src/adapters/model-catalog.ts
17612
+ function lookupModel(modelId) {
17613
+ const lower = modelId.toLowerCase();
17614
+ let unprefixed = lower;
17615
+ if (lower.includes("@"))
17616
+ unprefixed = lower.substring(lower.indexOf("@") + 1);
17617
+ else if (lower.includes("/"))
17618
+ unprefixed = lower.substring(lower.lastIndexOf("/") + 1);
17619
+ for (const entry of MODEL_CATALOG) {
17620
+ if (unprefixed.includes(entry.pattern) || lower.includes(entry.pattern)) {
17621
+ return entry;
17622
+ }
17623
+ }
17624
+ return;
17625
+ }
17626
+ var MODEL_CATALOG;
17627
+ var init_model_catalog = __esm(() => {
17628
+ MODEL_CATALOG = [
17629
+ { pattern: "grok-4.20", contextWindow: 2000000 },
17630
+ { pattern: "grok-4-20", contextWindow: 2000000 },
17631
+ { pattern: "grok-4.1-fast", contextWindow: 2000000 },
17632
+ { pattern: "grok-4-1-fast", contextWindow: 2000000 },
17633
+ { pattern: "grok-4-fast", contextWindow: 2000000 },
17634
+ { pattern: "grok-code-fast", contextWindow: 256000 },
17635
+ { pattern: "grok-4", contextWindow: 256000 },
17636
+ { pattern: "grok-3", contextWindow: 131072 },
17637
+ { pattern: "grok-2", contextWindow: 131072 },
17638
+ { pattern: "glm-5-turbo", contextWindow: 202752 },
17639
+ { pattern: "glm-5", contextWindow: 80000, supportsVision: true },
17640
+ { pattern: "glm-4.7-flash", contextWindow: 202752 },
17641
+ { pattern: "glm-4.7", contextWindow: 202752 },
17642
+ { pattern: "glm-4.6v", contextWindow: 131072, supportsVision: true },
17643
+ { pattern: "glm-4.6", contextWindow: 204800 },
17644
+ { pattern: "glm-4.5v", contextWindow: 65536, supportsVision: true },
17645
+ { pattern: "glm-4.5-flash", contextWindow: 131072 },
17646
+ { pattern: "glm-4.5-air", contextWindow: 131072 },
17647
+ { pattern: "glm-4.5", contextWindow: 131072 },
17648
+ { pattern: "glm-4v-plus", contextWindow: 128000, supportsVision: true },
17649
+ { pattern: "glm-4v", contextWindow: 128000, supportsVision: true },
17650
+ { pattern: "glm-4-long", contextWindow: 1e6 },
17651
+ { pattern: "glm-4-plus", contextWindow: 128000 },
17652
+ { pattern: "glm-4-flash", contextWindow: 128000 },
17653
+ { pattern: "glm-4-32b", contextWindow: 128000 },
17654
+ { pattern: "glm-4", contextWindow: 128000 },
17655
+ { pattern: "glm-3-turbo", contextWindow: 128000 },
17656
+ { pattern: "minimax-01", contextWindow: 1e6, supportsVision: false },
17657
+ { pattern: "minimax-m1", contextWindow: 1e6, supportsVision: false },
17658
+ {
17659
+ pattern: "minimax",
17660
+ contextWindow: 0,
17661
+ supportsVision: false,
17662
+ temperatureRange: { min: 0.01, max: 1 }
17663
+ },
17664
+ { pattern: "gpt-5.4", contextWindow: 1050000, maxToolCount: 128 },
17665
+ { pattern: "gpt-5", contextWindow: 400000, maxToolCount: 128 },
17666
+ { pattern: "o1", contextWindow: 200000, maxToolCount: 128 },
17667
+ { pattern: "o3", contextWindow: 200000, maxToolCount: 128 },
17668
+ { pattern: "o4", contextWindow: 200000, maxToolCount: 128 },
17669
+ { pattern: "gpt-4o", contextWindow: 128000, maxToolCount: 128 },
17670
+ { pattern: "gpt-4-turbo", contextWindow: 128000, maxToolCount: 128 },
17671
+ { pattern: "gpt-3.5", contextWindow: 16385, maxToolCount: 128 },
17672
+ { pattern: "kimi-k2.5", contextWindow: 262144 },
17673
+ { pattern: "kimi-k2-5", contextWindow: 262144 },
17674
+ { pattern: "kimi-k2", contextWindow: 131000 },
17675
+ { pattern: "qwen3.6", contextWindow: 1048576 },
17676
+ { pattern: "qwen3-6", contextWindow: 1048576 },
17677
+ { pattern: "qwen3.5", contextWindow: 262144 },
17678
+ { pattern: "qwen3-5", contextWindow: 262144 },
17679
+ { pattern: "qwen3-coder", contextWindow: 262144 },
17680
+ { pattern: "qwen3", contextWindow: 131072 },
17681
+ { pattern: "qwen2.5", contextWindow: 131072 },
17682
+ { pattern: "qwen2-5", contextWindow: 131072 },
17683
+ { pattern: "xiaomi", contextWindow: 0, toolNameLimit: 64 },
17684
+ { pattern: "mimo", contextWindow: 0, toolNameLimit: 64 }
17685
+ ];
17686
+ });
17687
+
17592
17688
  // src/handlers/shared/format/openai-messages.ts
17593
17689
  function convertMessagesToOpenAI(req, modelId, filterIdentityFn, simpleFormat = false) {
17594
17690
  const messages = [];
@@ -17869,7 +17965,7 @@ var init_openai_tools = __esm(() => {
17869
17965
  function matchesModelFamily(modelId, family) {
17870
17966
  const lower = modelId.toLowerCase();
17871
17967
  const fam = family.toLowerCase();
17872
- return lower.startsWith(fam) || lower.includes(`/${fam}`);
17968
+ return lower.startsWith(fam) || lower.includes(`/${fam}`) || lower.includes(`@${fam}`);
17873
17969
  }
17874
17970
 
17875
17971
  class BaseAPIFormat {
@@ -17920,7 +18016,7 @@ class BaseAPIFormat {
17920
18016
  return "openai-sse";
17921
18017
  }
17922
18018
  getContextWindow() {
17923
- return 200000;
18019
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
17924
18020
  }
17925
18021
  getPricing(providerName) {
17926
18022
  return getModelPricing(providerName, this.modelId);
@@ -17969,6 +18065,7 @@ var DefaultAPIFormat;
17969
18065
  var init_base_api_format = __esm(() => {
17970
18066
  init_tool_name_utils();
17971
18067
  init_remote_provider_types();
18068
+ init_model_catalog();
17972
18069
  init_openai_tools();
17973
18070
  DefaultAPIFormat = class DefaultAPIFormat extends BaseAPIFormat {
17974
18071
  processTextContent(textContent, accumulatedText) {
@@ -17987,74 +18084,6 @@ var init_base_api_format = __esm(() => {
17987
18084
  };
17988
18085
  });
17989
18086
 
17990
- // src/adapters/model-catalog.ts
17991
- function lookupModel(modelId) {
17992
- const lower = modelId.toLowerCase();
17993
- const unprefixed = lower.includes("/") ? lower.substring(lower.lastIndexOf("/") + 1) : lower;
17994
- for (const entry of MODEL_CATALOG) {
17995
- if (unprefixed.includes(entry.pattern) || lower.includes(entry.pattern)) {
17996
- return entry;
17997
- }
17998
- }
17999
- return;
18000
- }
18001
- var MODEL_CATALOG;
18002
- var init_model_catalog = __esm(() => {
18003
- MODEL_CATALOG = [
18004
- { pattern: "grok-4.20", contextWindow: 2000000 },
18005
- { pattern: "grok-4-20", contextWindow: 2000000 },
18006
- { pattern: "grok-4.1-fast", contextWindow: 2000000 },
18007
- { pattern: "grok-4-1-fast", contextWindow: 2000000 },
18008
- { pattern: "grok-4-fast", contextWindow: 2000000 },
18009
- { pattern: "grok-code-fast", contextWindow: 256000 },
18010
- { pattern: "grok-4", contextWindow: 256000 },
18011
- { pattern: "grok-3", contextWindow: 131072 },
18012
- { pattern: "grok-2", contextWindow: 131072 },
18013
- { pattern: "grok", contextWindow: 131072 },
18014
- { pattern: "glm-5-turbo", contextWindow: 202752 },
18015
- { pattern: "glm-5", contextWindow: 80000, supportsVision: true },
18016
- { pattern: "glm-4.7-flash", contextWindow: 202752 },
18017
- { pattern: "glm-4.7", contextWindow: 202752 },
18018
- { pattern: "glm-4.6v", contextWindow: 131072, supportsVision: true },
18019
- { pattern: "glm-4.6", contextWindow: 204800 },
18020
- { pattern: "glm-4.5v", contextWindow: 65536, supportsVision: true },
18021
- { pattern: "glm-4.5-flash", contextWindow: 131072 },
18022
- { pattern: "glm-4.5-air", contextWindow: 131072 },
18023
- { pattern: "glm-4.5", contextWindow: 131072 },
18024
- { pattern: "glm-4v-plus", contextWindow: 128000, supportsVision: true },
18025
- { pattern: "glm-4v", contextWindow: 128000, supportsVision: true },
18026
- { pattern: "glm-4-long", contextWindow: 1e6 },
18027
- { pattern: "glm-4-plus", contextWindow: 128000 },
18028
- { pattern: "glm-4-flash", contextWindow: 128000 },
18029
- { pattern: "glm-4-32b", contextWindow: 128000 },
18030
- { pattern: "glm-4", contextWindow: 128000 },
18031
- { pattern: "glm-3-turbo", contextWindow: 128000 },
18032
- { pattern: "glm-", contextWindow: 131072, supportsVision: false },
18033
- { pattern: "minimax-01", contextWindow: 1e6, supportsVision: false },
18034
- { pattern: "minimax-m1", contextWindow: 1e6, supportsVision: false },
18035
- {
18036
- pattern: "minimax",
18037
- contextWindow: 204800,
18038
- supportsVision: false,
18039
- temperatureRange: { min: 0.01, max: 1 }
18040
- },
18041
- { pattern: "gpt-5.4", contextWindow: 1050000, maxToolCount: 128 },
18042
- { pattern: "gpt-5", contextWindow: 400000, maxToolCount: 128 },
18043
- { pattern: "o1", contextWindow: 200000, maxToolCount: 128 },
18044
- { pattern: "o3", contextWindow: 200000, maxToolCount: 128 },
18045
- { pattern: "o4", contextWindow: 200000, maxToolCount: 128 },
18046
- { pattern: "gpt-4o", contextWindow: 128000, maxToolCount: 128 },
18047
- { pattern: "gpt-4-turbo", contextWindow: 128000, maxToolCount: 128 },
18048
- { pattern: "gpt-3.5", contextWindow: 16385, maxToolCount: 128 },
18049
- { pattern: "kimi-k2.5", contextWindow: 262144 },
18050
- { pattern: "kimi-k2-5", contextWindow: 262144 },
18051
- { pattern: "kimi-k2", contextWindow: 131000 },
18052
- { pattern: "kimi", contextWindow: 131072 },
18053
- { pattern: "xiaomi", contextWindow: 200000, toolNameLimit: 64 },
18054
- { pattern: "mimo", contextWindow: 200000, toolNameLimit: 64 }
18055
- ];
18056
- });
18057
-
18058
18087
  // src/adapters/grok-model-dialect.ts
18059
18088
  var GrokModelDialect;
18060
18089
  var init_grok_model_dialect = __esm(() => {
@@ -18142,7 +18171,7 @@ var init_grok_model_dialect = __esm(() => {
18142
18171
  return "GrokModelDialect";
18143
18172
  }
18144
18173
  getContextWindow() {
18145
- return lookupModel(this.modelId)?.contextWindow ?? 131072;
18174
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
18146
18175
  }
18147
18176
  reset() {
18148
18177
  this.xmlBuffer = "";
@@ -19468,6 +19497,7 @@ CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
19468
19497
  var CodexAPIFormat;
19469
19498
  var init_codex_api_format = __esm(() => {
19470
19499
  init_base_api_format();
19500
+ init_model_catalog();
19471
19501
  CodexAPIFormat = class CodexAPIFormat extends BaseAPIFormat {
19472
19502
  constructor(modelId) {
19473
19503
  super(modelId);
@@ -19489,7 +19519,7 @@ var init_codex_api_format = __esm(() => {
19489
19519
  return "openai-responses-sse";
19490
19520
  }
19491
19521
  getContextWindow() {
19492
- return 200000;
19522
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
19493
19523
  }
19494
19524
  buildPayload(claudeRequest, messages, tools) {
19495
19525
  const convertedMessages = this.convertMessagesToResponsesAPI(messages);
@@ -19644,7 +19674,7 @@ var init_openai_api_format = __esm(() => {
19644
19674
  return "OpenAIAPIFormat";
19645
19675
  }
19646
19676
  getContextWindow() {
19647
- return lookupModel(this.modelId)?.contextWindow ?? 128000;
19677
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
19648
19678
  }
19649
19679
  buildPayload(claudeRequest, messages, tools) {
19650
19680
  return this.buildChatCompletionsPayload(claudeRequest, messages, tools);
@@ -19781,7 +19811,7 @@ var init_minimax_model_dialect = __esm(() => {
19781
19811
  return request;
19782
19812
  }
19783
19813
  getContextWindow() {
19784
- return lookupModel(this.modelId)?.contextWindow ?? 204800;
19814
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
19785
19815
  }
19786
19816
  supportsVision() {
19787
19817
  return lookupModel(this.modelId)?.supportsVision ?? false;
@@ -19852,7 +19882,7 @@ var init_glm_model_dialect = __esm(() => {
19852
19882
  return "GLMModelDialect";
19853
19883
  }
19854
19884
  getContextWindow() {
19855
- return lookupModel(this.modelId)?.contextWindow ?? 128000;
19885
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
19856
19886
  }
19857
19887
  supportsVision() {
19858
19888
  return lookupModel(this.modelId)?.supportsVision ?? false;
@@ -21024,7 +21054,7 @@ class TokenTracker {
21024
21054
  try {
21025
21055
  const total = inputTokens + outputTokens;
21026
21056
  const cw = this.config.contextWindow;
21027
- const leftPct = cw > 0 ? Math.max(0, Math.min(100, Math.round((cw - total) / cw * 100))) : 100;
21057
+ const leftPct = cw > 0 ? Math.max(0, Math.min(100, Math.round((cw - total) / cw * 100))) : -1;
21028
21058
  const pricing = this.getPricing();
21029
21059
  const isFreeModel = pricing.isFree || pricing.inputCostPer1M === 0 && pricing.outputCostPer1M === 0;
21030
21060
  const data = {
@@ -21032,7 +21062,7 @@ class TokenTracker {
21032
21062
  output_tokens: outputTokens,
21033
21063
  total_tokens: total,
21034
21064
  total_cost: this.sessionTotalCost,
21035
- context_window: cw,
21065
+ context_window: cw > 0 ? cw : "unknown",
21036
21066
  context_left_percent: leftPct,
21037
21067
  provider_name: this.getDisplayName(),
21038
21068
  updated_at: Date.now(),
@@ -22327,7 +22357,7 @@ var init_profile_config = __esm(() => {
22327
22357
  });
22328
22358
 
22329
22359
  // src/version.ts
22330
- var VERSION = "6.11.0";
22360
+ var VERSION = "6.11.1";
22331
22361
 
22332
22362
  // src/telemetry.ts
22333
22363
  var exports_telemetry = {};
@@ -26349,16 +26379,6 @@ var init_gemini_apikey = __esm(() => {
26349
26379
  });
26350
26380
 
26351
26381
  // src/auth/gemini-oauth.ts
26352
- var exports_gemini_oauth = {};
26353
- __export(exports_gemini_oauth, {
26354
- setupGeminiUser: () => setupGeminiUser,
26355
- retrieveUserQuota: () => retrieveUserQuota,
26356
- getValidAccessToken: () => getValidAccessToken,
26357
- getGeminiTierFullName: () => getGeminiTierFullName,
26358
- getGeminiTierDisplayName: () => getGeminiTierDisplayName,
26359
- getGeminiOAuth: () => getGeminiOAuth,
26360
- GeminiOAuth: () => GeminiOAuth
26361
- });
26362
26382
  import { createServer } from "http";
26363
26383
  import { randomBytes as randomBytes2, createHash as createHash4 } from "crypto";
26364
26384
  import { readFileSync as readFileSync10, existsSync as existsSync13, unlinkSync as unlinkSync3, openSync, writeSync, closeSync } from "fs";
@@ -26683,9 +26703,6 @@ Please open this URL in your browser to authenticate:`);
26683
26703
  }
26684
26704
  }
26685
26705
  }
26686
- function getGeminiOAuth() {
26687
- return GeminiOAuth.getInstance();
26688
- }
26689
26706
  async function getValidAccessToken() {
26690
26707
  const oauth = GeminiOAuth.getInstance();
26691
26708
  return oauth.getAccessToken();
@@ -26757,7 +26774,7 @@ async function setupGeminiUser(accessToken) {
26757
26774
  async function callLoadCodeAssist(accessToken, projectId) {
26758
26775
  const metadata = {
26759
26776
  pluginType: "GEMINI",
26760
- ideType: "IDE_UNSPECIFIED",
26777
+ ideType: "GEMINI_CLI",
26761
26778
  platform: "PLATFORM_UNSPECIFIED",
26762
26779
  duetProject: projectId
26763
26780
  };
@@ -26777,7 +26794,7 @@ async function callLoadCodeAssist(accessToken, projectId) {
26777
26794
  async function callOnboardUser(accessToken, tierId, projectId) {
26778
26795
  const metadata = {
26779
26796
  pluginType: "GEMINI",
26780
- ideType: "IDE_UNSPECIFIED",
26797
+ ideType: "GEMINI_CLI",
26781
26798
  platform: "PLATFORM_UNSPECIFIED",
26782
26799
  duetProject: projectId
26783
26800
  };
@@ -26953,12 +26970,11 @@ class GeminiCodeAssistProviderTransport {
26953
26970
  };
26954
26971
  }
26955
26972
  async refreshAuth() {
26956
- const { getValidAccessToken: getValidAccessToken2, setupGeminiUser: setupGeminiUser2, getGeminiTierDisplayName: getGeminiTierDisplayName2 } = await Promise.resolve().then(() => (init_gemini_oauth(), exports_gemini_oauth));
26957
- this.accessToken = await getValidAccessToken2();
26958
- const { projectId, tierId } = await setupGeminiUser2(this.accessToken);
26973
+ this.accessToken = await getValidAccessToken();
26974
+ const { projectId, tierId } = await setupGeminiUser(this.accessToken);
26959
26975
  this.projectId = projectId;
26960
26976
  this.tierId = tierId;
26961
- this._displayName = getGeminiTierDisplayName2();
26977
+ this._displayName = getGeminiTierDisplayName();
26962
26978
  log(`[GeminiCodeAssist] Auth refreshed, project: ${this.projectId}, tier: ${this._displayName}`);
26963
26979
  }
26964
26980
  transformPayload(payload) {
@@ -27059,8 +27075,7 @@ class GeminiCodeAssistProviderTransport {
27059
27075
  if (!this.accessToken || !this.projectId)
27060
27076
  return;
27061
27077
  try {
27062
- const { retrieveUserQuota: retrieveUserQuota2 } = await Promise.resolve().then(() => (init_gemini_oauth(), exports_gemini_oauth));
27063
- const data = await retrieveUserQuota2(this.accessToken, this.projectId);
27078
+ const data = await retrieveUserQuota(this.accessToken, this.projectId);
27064
27079
  if (!data?.buckets?.length)
27065
27080
  return;
27066
27081
  const lines = [];
@@ -27085,8 +27100,7 @@ ${lines.join(`
27085
27100
  if (!this.accessToken || !this.projectId)
27086
27101
  return;
27087
27102
  try {
27088
- const { retrieveUserQuota: retrieveUserQuota2 } = await Promise.resolve().then(() => (init_gemini_oauth(), exports_gemini_oauth));
27089
- const data = await retrieveUserQuota2(this.accessToken, this.projectId);
27103
+ const data = await retrieveUserQuota(this.accessToken, this.projectId);
27090
27104
  if (!data?.buckets?.length)
27091
27105
  return;
27092
27106
  const bucket = data.buckets.find((b) => b.modelId === modelName);
@@ -27100,6 +27114,7 @@ var CODE_ASSIST_BASE = "https://cloudcode-pa.googleapis.com", CODE_ASSIST_ENDPOI
27100
27114
  var init_gemini_codeassist = __esm(() => {
27101
27115
  init_gemini_queue();
27102
27116
  init_logger();
27117
+ init_gemini_oauth();
27103
27118
  CODE_ASSIST_ENDPOINT = `${CODE_ASSIST_BASE}/v1internal:streamGenerateContent?alt=sse`;
27104
27119
  CODE_ASSIST_FALLBACK_CHAIN = [
27105
27120
  "gemini-3.1-pro-preview",
@@ -27205,12 +27220,6 @@ var init_openai = __esm(() => {
27205
27220
  });
27206
27221
 
27207
27222
  // src/auth/codex-oauth.ts
27208
- var exports_codex_oauth = {};
27209
- __export(exports_codex_oauth, {
27210
- getValidCodexAccessToken: () => getValidCodexAccessToken,
27211
- getCodexOAuth: () => getCodexOAuth,
27212
- CodexOAuth: () => CodexOAuth
27213
- });
27214
27223
  import { exec as exec2 } from "child_process";
27215
27224
  import { createHash as createHash5, randomBytes as randomBytes3 } from "crypto";
27216
27225
  import { closeSync as closeSync2, existsSync as existsSync14, openSync as openSync2, readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeSync as writeSync2 } from "fs";
@@ -27560,13 +27569,6 @@ Please open this URL in your browser to authenticate:`);
27560
27569
  }
27561
27570
  }
27562
27571
  }
27563
- function getCodexOAuth() {
27564
- return CodexOAuth.getInstance();
27565
- }
27566
- async function getValidCodexAccessToken() {
27567
- const oauth = CodexOAuth.getInstance();
27568
- return oauth.getAccessToken();
27569
- }
27570
27572
  var execAsync2, OAUTH_CONFIG2;
27571
27573
  var init_codex_oauth = __esm(() => {
27572
27574
  init_logger();
@@ -27601,6 +27603,7 @@ var OpenAICodexTransport;
27601
27603
  var init_openai_codex = __esm(() => {
27602
27604
  init_logger();
27603
27605
  init_openai();
27606
+ init_codex_oauth();
27604
27607
  OpenAICodexTransport = class OpenAICodexTransport extends OpenAIProviderTransport {
27605
27608
  async getHeaders() {
27606
27609
  const oauthHeaders = await this.tryOAuthHeaders();
@@ -27618,8 +27621,7 @@ var init_openai_codex = __esm(() => {
27618
27621
  return null;
27619
27622
  const buffer = 5 * 60 * 1000;
27620
27623
  if (creds.expires_at && Date.now() > creds.expires_at - buffer) {
27621
- const { CodexOAuth: CodexOAuth2 } = await Promise.resolve().then(() => (init_codex_oauth(), exports_codex_oauth));
27622
- const oauth = CodexOAuth2.getInstance();
27624
+ const oauth = CodexOAuth.getInstance();
27623
27625
  const token = await oauth.getAccessToken();
27624
27626
  log("[OpenAI Codex] Using refreshed OAuth token");
27625
27627
  return buildOAuthHeaders(token, oauth.getAccountId());
@@ -27635,13 +27637,6 @@ var init_openai_codex = __esm(() => {
27635
27637
  });
27636
27638
 
27637
27639
  // src/auth/kimi-oauth.ts
27638
- var exports_kimi_oauth = {};
27639
- __export(exports_kimi_oauth, {
27640
- hasKimiOAuthCredentials: () => hasKimiOAuthCredentials,
27641
- getValidKimiAccessToken: () => getValidKimiAccessToken,
27642
- getKimiOAuth: () => getKimiOAuth,
27643
- KimiOAuth: () => KimiOAuth
27644
- });
27645
27640
  import { randomBytes as randomBytes4 } from "crypto";
27646
27641
  import { readFileSync as readFileSync13, existsSync as existsSync16, unlinkSync as unlinkSync5, openSync as openSync3, writeSync as writeSync3, closeSync as closeSync3 } from "fs";
27647
27642
  import { homedir as homedir17, hostname, platform, release } from "os";
@@ -27973,26 +27968,6 @@ Waiting for authorization...`);
27973
27968
  log(`[KimiOAuth] Credentials saved to ${credPath}`);
27974
27969
  }
27975
27970
  }
27976
- function getKimiOAuth() {
27977
- return KimiOAuth.getInstance();
27978
- }
27979
- async function getValidKimiAccessToken() {
27980
- const oauth = KimiOAuth.getInstance();
27981
- return oauth.getAccessToken();
27982
- }
27983
- function hasKimiOAuthCredentials() {
27984
- try {
27985
- const credPath = join18(homedir17(), ".claudish", "kimi-oauth.json");
27986
- if (!existsSync16(credPath))
27987
- return false;
27988
- const data = JSON.parse(readFileSync13(credPath, "utf-8"));
27989
- const now = Date.now();
27990
- const bufferMs = 5 * 60 * 1000;
27991
- return !!(data.access_token && data.refresh_token && data.expires_at && data.expires_at > now + bufferMs);
27992
- } catch {
27993
- return false;
27994
- }
27995
- }
27996
27971
  var execAsync3, OAUTH_CONFIG3;
27997
27972
  var init_kimi_oauth = __esm(() => {
27998
27973
  init_logger();
@@ -28006,6 +27981,10 @@ var init_kimi_oauth = __esm(() => {
28006
27981
  });
28007
27982
 
28008
27983
  // src/providers/transport/anthropic-compat.ts
27984
+ import { existsSync as existsSync17, readFileSync as readFileSync14 } from "fs";
27985
+ import { join as join19 } from "path";
27986
+ import { homedir as homedir18 } from "os";
27987
+
28009
27988
  class AnthropicProviderTransport {
28010
27989
  name;
28011
27990
  displayName;
@@ -28035,15 +28014,11 @@ class AnthropicProviderTransport {
28035
28014
  }
28036
28015
  if (this.provider.name === "kimi-coding" && !this.apiKey) {
28037
28016
  try {
28038
- const { existsSync: existsSync17, readFileSync: readFileSync14 } = await import("fs");
28039
- const { join: join19 } = await import("path");
28040
- const { homedir: homedir18 } = await import("os");
28041
28017
  const credPath = join19(homedir18(), ".claudish", "kimi-oauth.json");
28042
28018
  if (existsSync17(credPath)) {
28043
28019
  const data = JSON.parse(readFileSync14(credPath, "utf-8"));
28044
28020
  if (data.access_token && data.refresh_token) {
28045
- const { KimiOAuth: KimiOAuth2 } = await Promise.resolve().then(() => (init_kimi_oauth(), exports_kimi_oauth));
28046
- const oauth = KimiOAuth2.getInstance();
28021
+ const oauth = KimiOAuth.getInstance();
28047
28022
  const accessToken = await oauth.getAccessToken();
28048
28023
  delete headers["x-api-key"];
28049
28024
  headers["Authorization"] = `Bearer ${accessToken}`;
@@ -28071,6 +28046,7 @@ class AnthropicProviderTransport {
28071
28046
  }
28072
28047
  var init_anthropic_compat = __esm(() => {
28073
28048
  init_logger();
28049
+ init_kimi_oauth();
28074
28050
  });
28075
28051
 
28076
28052
  // src/adapters/anthropic-api-format.ts
@@ -28161,7 +28137,7 @@ var init_anthropic_api_format = __esm(() => {
28161
28137
  return 131072;
28162
28138
  if (this.providerName === "minimax" || this.providerName === "minimax-coding")
28163
28139
  return 204800;
28164
- return 128000;
28140
+ return 0;
28165
28141
  }
28166
28142
  supportsVision() {
28167
28143
  return true;
@@ -28341,13 +28317,14 @@ var init_litellm2 = __esm(() => {
28341
28317
  });
28342
28318
 
28343
28319
  // src/adapters/litellm-api-format.ts
28344
- import { existsSync as existsSync17, readFileSync as readFileSync14 } from "fs";
28320
+ import { existsSync as existsSync18, readFileSync as readFileSync15 } from "fs";
28345
28321
  import { createHash as createHash6 } from "crypto";
28346
- import { homedir as homedir18 } from "os";
28347
- import { join as join19 } from "path";
28322
+ import { homedir as homedir19 } from "os";
28323
+ import { join as join20 } from "path";
28348
28324
  var INLINE_IMAGE_MODEL_PATTERNS, LiteLLMAPIFormat;
28349
28325
  var init_litellm_api_format = __esm(() => {
28350
28326
  init_base_api_format();
28327
+ init_model_catalog();
28351
28328
  init_logger();
28352
28329
  INLINE_IMAGE_MODEL_PATTERNS = ["minimax"];
28353
28330
  LiteLLMAPIFormat = class LiteLLMAPIFormat extends DefaultAPIFormat {
@@ -28435,15 +28412,15 @@ var init_litellm_api_format = __esm(() => {
28435
28412
  return payload;
28436
28413
  }
28437
28414
  getContextWindow() {
28438
- return 200000;
28415
+ return lookupModel(this.modelId)?.contextWindow ?? 0;
28439
28416
  }
28440
28417
  checkVisionSupport() {
28441
28418
  try {
28442
28419
  const hash = createHash6("sha256").update(this.baseUrl).digest("hex").substring(0, 16);
28443
- const cachePath = join19(homedir18(), ".claudish", `litellm-models-${hash}.json`);
28444
- if (!existsSync17(cachePath))
28420
+ const cachePath = join20(homedir19(), ".claudish", `litellm-models-${hash}.json`);
28421
+ if (!existsSync18(cachePath))
28445
28422
  return true;
28446
- const cacheData = JSON.parse(readFileSync14(cachePath, "utf-8"));
28423
+ const cacheData = JSON.parse(readFileSync15(cachePath, "utf-8"));
28447
28424
  const model = cacheData.models?.find((m) => m.name === this.modelId);
28448
28425
  if (model && model.supportsVision === false) {
28449
28426
  log(`[LiteLLMAPIFormat] Model ${this.modelId} does not support vision`);
@@ -28460,9 +28437,9 @@ var init_litellm_api_format = __esm(() => {
28460
28437
  // src/auth/vertex-auth.ts
28461
28438
  import { exec as exec4 } from "child_process";
28462
28439
  import { promisify as promisify4 } from "util";
28463
- import { existsSync as existsSync18 } from "fs";
28464
- import { homedir as homedir19 } from "os";
28465
- import { join as join20 } from "path";
28440
+ import { existsSync as existsSync19 } from "fs";
28441
+ import { homedir as homedir20 } from "os";
28442
+ import { join as join21 } from "path";
28466
28443
 
28467
28444
  class VertexAuthManager {
28468
28445
  cachedToken = null;
@@ -28516,8 +28493,8 @@ class VertexAuthManager {
28516
28493
  }
28517
28494
  async tryADC() {
28518
28495
  try {
28519
- const adcPath = join20(homedir19(), ".config/gcloud/application_default_credentials.json");
28520
- if (!existsSync18(adcPath)) {
28496
+ const adcPath = join21(homedir20(), ".config/gcloud/application_default_credentials.json");
28497
+ if (!existsSync19(adcPath)) {
28521
28498
  log("[VertexAuth] ADC credentials file not found");
28522
28499
  return null;
28523
28500
  }
@@ -28541,7 +28518,7 @@ class VertexAuthManager {
28541
28518
  if (!credPath) {
28542
28519
  return null;
28543
28520
  }
28544
- if (!existsSync18(credPath)) {
28521
+ if (!existsSync19(credPath)) {
28545
28522
  throw new Error(`Service account file not found: ${credPath}
28546
28523
 
28547
28524
  Check GOOGLE_APPLICATION_CREDENTIALS path.`);
@@ -28580,8 +28557,8 @@ function validateVertexOAuthConfig() {
28580
28557
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
28581
28558
  ` + " export VERTEX_LOCATION='us-central1' # optional";
28582
28559
  }
28583
- const adcPath = join20(homedir19(), ".config/gcloud/application_default_credentials.json");
28584
- const hasADC = existsSync18(adcPath);
28560
+ const adcPath = join21(homedir20(), ".config/gcloud/application_default_credentials.json");
28561
+ const hasADC = existsSync19(adcPath);
28585
28562
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
28586
28563
  if (!hasADC && !hasServiceAccount) {
28587
28564
  return `No Vertex AI credentials found.
@@ -28687,9 +28664,9 @@ var init_vertex_oauth = __esm(() => {
28687
28664
  });
28688
28665
 
28689
28666
  // src/providers/api-key-provenance.ts
28690
- import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
28691
- import { join as join21, resolve as resolve2 } from "path";
28692
- import { homedir as homedir20 } from "os";
28667
+ import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
28668
+ import { join as join22, resolve as resolve2 } from "path";
28669
+ import { homedir as homedir21 } from "os";
28693
28670
  function maskKey(key) {
28694
28671
  if (!key)
28695
28672
  return null;
@@ -28774,9 +28751,9 @@ function formatProvenanceProbe(p, indent = " ") {
28774
28751
  function readDotenvKey(envVars) {
28775
28752
  try {
28776
28753
  const dotenvPath = resolve2(".env");
28777
- if (!existsSync19(dotenvPath))
28754
+ if (!existsSync20(dotenvPath))
28778
28755
  return null;
28779
- const parsed = import_dotenv.parse(readFileSync16(dotenvPath, "utf-8"));
28756
+ const parsed = import_dotenv.parse(readFileSync17(dotenvPath, "utf-8"));
28780
28757
  for (const v of envVars) {
28781
28758
  if (parsed[v])
28782
28759
  return parsed[v];
@@ -28788,10 +28765,10 @@ function readDotenvKey(envVars) {
28788
28765
  }
28789
28766
  function readConfigKey(envVar) {
28790
28767
  try {
28791
- const configPath = join21(homedir20(), ".claudish", "config.json");
28792
- if (!existsSync19(configPath))
28768
+ const configPath = join22(homedir21(), ".claudish", "config.json");
28769
+ if (!existsSync20(configPath))
28793
28770
  return null;
28794
- const cfg = JSON.parse(readFileSync16(configPath, "utf-8"));
28771
+ const cfg = JSON.parse(readFileSync17(configPath, "utf-8"));
28795
28772
  return cfg.apiKeys?.[envVar] || null;
28796
28773
  } catch {
28797
28774
  return null;
@@ -29409,14 +29386,22 @@ var exports_mcp_server = {};
29409
29386
  __export(exports_mcp_server, {
29410
29387
  startMcpServer: () => startMcpServer
29411
29388
  });
29412
- import { readFileSync as readFileSync17, existsSync as existsSync20, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync3 } from "fs";
29413
- import { join as join22, dirname as dirname2 } from "path";
29414
- import { homedir as homedir21 } from "os";
29389
+ import { readFileSync as readFileSync18, existsSync as existsSync21, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, readdirSync as readdirSync3 } from "fs";
29390
+ import { join as join23, dirname as dirname2 } from "path";
29391
+ import { homedir as homedir22 } from "os";
29415
29392
  import { fileURLToPath as fileURLToPath2 } from "url";
29416
29393
  function loadRecommendedModels() {
29417
- if (existsSync20(RECOMMENDED_MODELS_PATH)) {
29394
+ const cachedPath = join23(CLAUDISH_CACHE_DIR, "recommended-models-cache.json");
29395
+ if (existsSync21(cachedPath)) {
29396
+ try {
29397
+ const data = JSON.parse(readFileSync18(cachedPath, "utf-8"));
29398
+ if (data.models && data.models.length > 0)
29399
+ return data.models;
29400
+ } catch {}
29401
+ }
29402
+ if (existsSync21(RECOMMENDED_MODELS_PATH)) {
29418
29403
  try {
29419
- const data = JSON.parse(readFileSync17(RECOMMENDED_MODELS_PATH, "utf-8"));
29404
+ const data = JSON.parse(readFileSync18(RECOMMENDED_MODELS_PATH, "utf-8"));
29420
29405
  return data.models || [];
29421
29406
  } catch {
29422
29407
  return [];
@@ -29424,10 +29409,28 @@ function loadRecommendedModels() {
29424
29409
  }
29425
29410
  return [];
29426
29411
  }
29412
+ function parsePriceAvg(s) {
29413
+ if (!s || s === "N/A")
29414
+ return Infinity;
29415
+ if (s === "FREE")
29416
+ return 0;
29417
+ const m = s.match(/\$([\d.]+)/);
29418
+ return m ? parseFloat(m[1]) : Infinity;
29419
+ }
29420
+ function parseCtx(s) {
29421
+ if (!s || s === "N/A")
29422
+ return 0;
29423
+ const upper = s.toUpperCase();
29424
+ if (upper.includes("M"))
29425
+ return parseFloat(upper) * 1e6;
29426
+ if (upper.includes("K"))
29427
+ return parseFloat(upper) * 1000;
29428
+ return parseInt(s) || 0;
29429
+ }
29427
29430
  async function loadAllModels(forceRefresh = false) {
29428
- if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH)) {
29431
+ if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH)) {
29429
29432
  try {
29430
- const cacheData = JSON.parse(readFileSync17(ALL_MODELS_CACHE_PATH, "utf-8"));
29433
+ const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH, "utf-8"));
29431
29434
  const lastUpdated = new Date(cacheData.lastUpdated);
29432
29435
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
29433
29436
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -29445,8 +29448,8 @@ async function loadAllModels(forceRefresh = false) {
29445
29448
  writeFileSync10(ALL_MODELS_CACHE_PATH, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
29446
29449
  return models;
29447
29450
  } catch {
29448
- if (existsSync20(ALL_MODELS_CACHE_PATH)) {
29449
- const cacheData = JSON.parse(readFileSync17(ALL_MODELS_CACHE_PATH, "utf-8"));
29451
+ if (existsSync21(ALL_MODELS_CACHE_PATH)) {
29452
+ const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH, "utf-8"));
29450
29453
  return cacheData.models || [];
29451
29454
  }
29452
29455
  return [];
@@ -29679,12 +29682,26 @@ Tokens: ${result.usage.input} input, ${result.usage.output} output`;
29679
29682
  output += `
29680
29683
  ## Quick Picks
29681
29684
  `;
29682
- output += "- **Budget**: `minimax-m2.5` ($0.75/1M)\n";
29683
- output += "- **Large context**: `gemini-3.1-pro-preview` (1M tokens)\n";
29684
- output += "- **Most advanced**: `gpt-5.4` ($8.75/1M)\n";
29685
- output += "- **Vision + coding**: `kimi-k2.5` ($1.32/1M)\n";
29686
- output += "- **Agentic**: `glm-5` ($1.68/1M)\n";
29687
- output += "- **Multimodal**: `qwen3.5-plus-02-15` ($1.40/1M)\n";
29685
+ const cheapest = [...models].sort((a, b) => parsePriceAvg(a.pricing?.average) - parsePriceAvg(b.pricing?.average))[0];
29686
+ const bigCtx = [...models].sort((a, b) => parseCtx(b.context) - parseCtx(a.context))[0];
29687
+ const priciest = [...models].sort((a, b) => parsePriceAvg(b.pricing?.average) - parsePriceAvg(a.pricing?.average))[0];
29688
+ const vision = models.find((m) => m.supportsVision);
29689
+ const reasoning = models.find((m) => m.supportsReasoning && m.id !== priciest?.id);
29690
+ if (cheapest)
29691
+ output += `- **Budget**: \`${cheapest.id}\` (${cheapest.pricing?.average || "N/A"})
29692
+ `;
29693
+ if (bigCtx && bigCtx.id !== cheapest?.id)
29694
+ output += `- **Large context**: \`${bigCtx.id}\` (${bigCtx.context || "N/A"} tokens)
29695
+ `;
29696
+ if (priciest && priciest.id !== cheapest?.id)
29697
+ output += `- **Most advanced**: \`${priciest.id}\` (${priciest.pricing?.average || "N/A"})
29698
+ `;
29699
+ if (vision && vision.id !== cheapest?.id && vision.id !== priciest?.id)
29700
+ output += `- **Vision + coding**: \`${vision.id}\` (${vision.pricing?.average || "N/A"})
29701
+ `;
29702
+ if (reasoning && reasoning.id !== cheapest?.id)
29703
+ output += `- **Agentic**: \`${reasoning.id}\` (${reasoning.pricing?.average || "N/A"})
29704
+ `;
29688
29705
  return { content: [{ type: "text", text: output }] };
29689
29706
  }
29690
29707
  });
@@ -29946,7 +29963,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
29946
29963
  let stderrFull = stderr_snippet || "";
29947
29964
  if (error_log_path) {
29948
29965
  try {
29949
- stderrFull = readFileSync17(error_log_path, "utf-8");
29966
+ stderrFull = readFileSync18(error_log_path, "utf-8");
29950
29967
  } catch {}
29951
29968
  }
29952
29969
  let sessionData = {};
@@ -29954,16 +29971,16 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
29954
29971
  const sp = session_path;
29955
29972
  for (const file of ["status.json", "manifest.json", "input.md"]) {
29956
29973
  try {
29957
- sessionData[file] = readFileSync17(join22(sp, file), "utf-8");
29974
+ sessionData[file] = readFileSync18(join23(sp, file), "utf-8");
29958
29975
  } catch {}
29959
29976
  }
29960
29977
  try {
29961
- const errorDir = join22(sp, "errors");
29962
- if (existsSync20(errorDir)) {
29978
+ const errorDir = join23(sp, "errors");
29979
+ if (existsSync21(errorDir)) {
29963
29980
  for (const f of readdirSync3(errorDir)) {
29964
29981
  if (f.endsWith(".log")) {
29965
29982
  try {
29966
- sessionData[`errors/${f}`] = readFileSync17(join22(errorDir, f), "utf-8");
29983
+ sessionData[`errors/${f}`] = readFileSync18(join23(errorDir, f), "utf-8");
29967
29984
  } catch {}
29968
29985
  }
29969
29986
  }
@@ -29973,7 +29990,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
29973
29990
  for (const f of readdirSync3(sp)) {
29974
29991
  if (f.startsWith("response-") && f.endsWith(".md")) {
29975
29992
  try {
29976
- const content = readFileSync17(join22(sp, f), "utf-8");
29993
+ const content = readFileSync18(join23(sp, f), "utf-8");
29977
29994
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
29978
29995
  } catch {}
29979
29996
  }
@@ -29982,9 +29999,9 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
29982
29999
  }
29983
30000
  let version2 = "unknown";
29984
30001
  try {
29985
- const pkgPath = join22(__dirname3, "../package.json");
29986
- if (existsSync20(pkgPath)) {
29987
- version2 = JSON.parse(readFileSync17(pkgPath, "utf-8")).version;
30002
+ const pkgPath = join23(__dirname3, "../package.json");
30003
+ if (existsSync21(pkgPath)) {
30004
+ version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
29988
30005
  }
29989
30006
  } catch {}
29990
30007
  const report = {
@@ -30345,9 +30362,9 @@ var init_mcp_server = __esm(() => {
30345
30362
  import_dotenv2.config();
30346
30363
  __filename3 = fileURLToPath2(import.meta.url);
30347
30364
  __dirname3 = dirname2(__filename3);
30348
- RECOMMENDED_MODELS_PATH = join22(__dirname3, "../recommended-models.json");
30349
- CLAUDISH_CACHE_DIR = join22(homedir21(), ".claudish");
30350
- ALL_MODELS_CACHE_PATH = join22(CLAUDISH_CACHE_DIR, "all-models.json");
30365
+ RECOMMENDED_MODELS_PATH = join23(__dirname3, "../recommended-models.json");
30366
+ CLAUDISH_CACHE_DIR = join23(homedir22(), ".claudish");
30367
+ ALL_MODELS_CACHE_PATH = join23(CLAUDISH_CACHE_DIR, "all-models.json");
30351
30368
  });
30352
30369
 
30353
30370
  // ../../node_modules/.bun/@inquirer+core@11.0.1+04f2146be16c61ef/node_modules/@inquirer/core/dist/lib/key.js
@@ -41621,7 +41638,7 @@ var init_RemoveFileError = __esm(() => {
41621
41638
 
41622
41639
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
41623
41640
  import { spawn as spawn3, spawnSync } from "child_process";
41624
- import { readFileSync as readFileSync18, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
41641
+ import { readFileSync as readFileSync19, unlinkSync as unlinkSync6, writeFileSync as writeFileSync11 } from "fs";
41625
41642
  import path from "path";
41626
41643
  import os from "os";
41627
41644
  import { randomUUID as randomUUID3 } from "crypto";
@@ -41737,7 +41754,7 @@ class ExternalEditor {
41737
41754
  }
41738
41755
  readTemporaryFile() {
41739
41756
  try {
41740
- const tempFileBuffer = readFileSync18(this.tempFile);
41757
+ const tempFileBuffer = readFileSync19(this.tempFile);
41741
41758
  if (tempFileBuffer.length === 0) {
41742
41759
  this.text = "";
41743
41760
  } else {
@@ -42748,8 +42765,7 @@ async function loginCommand(providerArg) {
42748
42765
  process.exit(1);
42749
42766
  }
42750
42767
  try {
42751
- const mod = await import(provider.module);
42752
- const oauth = mod[provider.className].getInstance();
42768
+ const oauth = provider.getInstance();
42753
42769
  await oauth.login();
42754
42770
  console.log(`
42755
42771
  \u2705 ${provider.displayName} OAuth login successful!`);
@@ -42769,8 +42785,7 @@ async function logoutCommand(providerArg) {
42769
42785
  process.exit(1);
42770
42786
  }
42771
42787
  try {
42772
- const mod = await import(provider.module);
42773
- const oauth = mod[provider.className].getInstance();
42788
+ const oauth = provider.getInstance();
42774
42789
  await oauth.logout();
42775
42790
  console.log(`\u2705 ${provider.displayName} OAuth credentials cleared.`);
42776
42791
  process.exit(0);
@@ -42783,29 +42798,29 @@ var AUTH_PROVIDERS;
42783
42798
  var init_auth_commands = __esm(() => {
42784
42799
  init_dist17();
42785
42800
  init_oauth_registry();
42801
+ init_gemini_oauth();
42802
+ init_kimi_oauth();
42803
+ init_codex_oauth();
42786
42804
  AUTH_PROVIDERS = [
42787
42805
  {
42788
42806
  name: "gemini",
42789
42807
  displayName: "Gemini Code Assist",
42790
42808
  prefix: "go@",
42791
- module: "./gemini-oauth.js",
42792
- className: "GeminiOAuth",
42809
+ getInstance: () => GeminiOAuth.getInstance(),
42793
42810
  registryKeys: ["google", "gemini-codeassist"]
42794
42811
  },
42795
42812
  {
42796
42813
  name: "kimi",
42797
42814
  displayName: "Kimi / Moonshot AI",
42798
42815
  prefix: "kc@, kimi@",
42799
- module: "./kimi-oauth.js",
42800
- className: "KimiOAuth",
42816
+ getInstance: () => KimiOAuth.getInstance(),
42801
42817
  registryKeys: ["kimi", "kimi-coding"]
42802
42818
  },
42803
42819
  {
42804
42820
  name: "codex",
42805
42821
  displayName: "OpenAI Codex (ChatGPT Plus/Pro)",
42806
42822
  prefix: "cx@",
42807
- module: "./codex-oauth.js",
42808
- className: "CodexOAuth",
42823
+ getInstance: () => CodexOAuth.getInstance(),
42809
42824
  registryKeys: ["openai-codex"]
42810
42825
  }
42811
42826
  ];
@@ -42846,11 +42861,10 @@ async function geminiQuotaHandler() {
42846
42861
  process.exit(1);
42847
42862
  }
42848
42863
  try {
42849
- const { getValidAccessToken: getValidAccessToken2, setupGeminiUser: setupGeminiUser2, retrieveUserQuota: retrieveUserQuota2, getGeminiTierFullName: getGeminiTierFullName2 } = await Promise.resolve().then(() => (init_gemini_oauth(), exports_gemini_oauth));
42850
- const accessToken = await getValidAccessToken2();
42851
- const { projectId } = await setupGeminiUser2(accessToken);
42852
- const tierName = getGeminiTierFullName2();
42853
- const quota = await retrieveUserQuota2(accessToken, projectId);
42864
+ const accessToken = await getValidAccessToken();
42865
+ const { projectId } = await setupGeminiUser(accessToken);
42866
+ const tierName = getGeminiTierFullName();
42867
+ const quota = await retrieveUserQuota(accessToken, projectId);
42854
42868
  if (!quota?.buckets?.length) {
42855
42869
  console.log(`
42856
42870
  ${D}No quota data available.${R}
@@ -42918,15 +42932,15 @@ async function geminiQuotaHandler() {
42918
42932
  }
42919
42933
  }
42920
42934
  async function codexQuotaHandler() {
42921
- const { readFileSync: readFileSync19, existsSync: existsSync21 } = await import("fs");
42922
- const { join: join23 } = await import("path");
42923
- const { homedir: homedir22 } = await import("os");
42924
- const credPath = join23(homedir22(), ".claudish", "codex-oauth.json");
42925
- if (!existsSync21(credPath)) {
42935
+ const { readFileSync: readFileSync20, existsSync: existsSync22 } = await import("fs");
42936
+ const { join: join24 } = await import("path");
42937
+ const { homedir: homedir23 } = await import("os");
42938
+ const credPath = join24(homedir23(), ".claudish", "codex-oauth.json");
42939
+ if (!existsSync22(credPath)) {
42926
42940
  console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
42927
42941
  process.exit(1);
42928
42942
  }
42929
- const creds = JSON.parse(readFileSync19(credPath, "utf-8"));
42943
+ const creds = JSON.parse(readFileSync20(credPath, "utf-8"));
42930
42944
  let email2 = "";
42931
42945
  try {
42932
42946
  const parts = creds.access_token.split(".");
@@ -42972,9 +42986,9 @@ async function codexQuotaHandler() {
42972
42986
  }
42973
42987
  let modelSlugs = [];
42974
42988
  try {
42975
- const modelsPath = join23(homedir22(), ".codex", "models_cache.json");
42976
- if (existsSync21(modelsPath)) {
42977
- const cache = JSON.parse(readFileSync19(modelsPath, "utf-8"));
42989
+ const modelsPath = join24(homedir23(), ".codex", "models_cache.json");
42990
+ if (existsSync22(modelsPath)) {
42991
+ const cache = JSON.parse(readFileSync20(modelsPath, "utf-8"));
42978
42992
  modelSlugs = (cache.models || []).map((m) => m.slug || m.id).filter(Boolean);
42979
42993
  }
42980
42994
  } catch {}
@@ -43080,6 +43094,7 @@ function formatRelativeReset(resetTime) {
43080
43094
  var R = "\x1B[0m", B = "\x1B[1m", D = "\x1B[2m", I = "\x1B[3m", RED = "\x1B[31m", GRN = "\x1B[32m", YEL = "\x1B[33m", MAG = "\x1B[35m", CYN = "\x1B[36m", WHT = "\x1B[37m", GRY = "\x1B[90m", FALLBACK_CHAIN, QUOTA_ADAPTERS;
43081
43095
  var init_quota_command = __esm(() => {
43082
43096
  init_oauth_registry();
43097
+ init_gemini_oauth();
43083
43098
  FALLBACK_CHAIN = [
43084
43099
  "gemini-3.1-pro-preview",
43085
43100
  "gemini-3-pro-preview",
@@ -43204,23 +43219,23 @@ __export(exports_cli, {
43204
43219
  getMissingKeyError: () => getMissingKeyError
43205
43220
  });
43206
43221
  import {
43207
- readFileSync as readFileSync19,
43222
+ readFileSync as readFileSync20,
43208
43223
  writeFileSync as writeFileSync12,
43209
- existsSync as existsSync21,
43224
+ existsSync as existsSync22,
43210
43225
  mkdirSync as mkdirSync11,
43211
43226
  copyFileSync,
43212
43227
  readdirSync as readdirSync4,
43213
43228
  unlinkSync as unlinkSync7
43214
43229
  } from "fs";
43215
43230
  import { fileURLToPath as fileURLToPath3 } from "url";
43216
- import { dirname as dirname3, join as join23 } from "path";
43217
- import { homedir as homedir22 } from "os";
43231
+ import { dirname as dirname3, join as join24 } from "path";
43232
+ import { homedir as homedir23 } from "os";
43218
43233
  function getVersion3() {
43219
43234
  return VERSION;
43220
43235
  }
43221
43236
  function clearAllModelCaches() {
43222
- const cacheDir = join23(homedir22(), ".claudish");
43223
- if (!existsSync21(cacheDir))
43237
+ const cacheDir = join24(homedir23(), ".claudish");
43238
+ if (!existsSync22(cacheDir))
43224
43239
  return;
43225
43240
  const cachePatterns = ["all-models.json", "pricing-cache.json"];
43226
43241
  let cleared = 0;
@@ -43228,7 +43243,7 @@ function clearAllModelCaches() {
43228
43243
  const files = readdirSync4(cacheDir);
43229
43244
  for (const file of files) {
43230
43245
  if (cachePatterns.includes(file) || file.startsWith("litellm-models-")) {
43231
- unlinkSync7(join23(cacheDir, file));
43246
+ unlinkSync7(join24(cacheDir, file));
43232
43247
  cleared++;
43233
43248
  }
43234
43249
  }
@@ -43550,9 +43565,9 @@ async function fetchOllamaModels() {
43550
43565
  }
43551
43566
  async function searchAndPrintModels(query, forceUpdate) {
43552
43567
  let models = [];
43553
- if (!forceUpdate && existsSync21(ALL_MODELS_JSON_PATH)) {
43568
+ if (!forceUpdate && existsSync22(ALL_MODELS_JSON_PATH)) {
43554
43569
  try {
43555
- const cacheData = JSON.parse(readFileSync19(ALL_MODELS_JSON_PATH, "utf-8"));
43570
+ const cacheData = JSON.parse(readFileSync20(ALL_MODELS_JSON_PATH, "utf-8"));
43556
43571
  const lastUpdated = new Date(cacheData.lastUpdated);
43557
43572
  const now = new Date;
43558
43573
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -43720,9 +43735,9 @@ Found ${results.length} matching models:
43720
43735
  async function printAllModels(jsonOutput, forceUpdate) {
43721
43736
  let models = [];
43722
43737
  const [ollamaModels, zenModels] = await Promise.all([fetchOllamaModels(), fetchZenModels()]);
43723
- if (!forceUpdate && existsSync21(ALL_MODELS_JSON_PATH)) {
43738
+ if (!forceUpdate && existsSync22(ALL_MODELS_JSON_PATH)) {
43724
43739
  try {
43725
- const cacheData = JSON.parse(readFileSync19(ALL_MODELS_JSON_PATH, "utf-8"));
43740
+ const cacheData = JSON.parse(readFileSync20(ALL_MODELS_JSON_PATH, "utf-8"));
43726
43741
  const lastUpdated = new Date(cacheData.lastUpdated);
43727
43742
  const now = new Date;
43728
43743
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -43923,12 +43938,12 @@ async function printAllModels(jsonOutput, forceUpdate) {
43923
43938
  console.log("Top models: claudish --top-models");
43924
43939
  }
43925
43940
  function isCacheStale() {
43926
- const cachePath = existsSync21(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
43927
- if (!existsSync21(cachePath)) {
43941
+ const cachePath = existsSync22(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
43942
+ if (!existsSync22(cachePath)) {
43928
43943
  return true;
43929
43944
  }
43930
43945
  try {
43931
- const jsonContent = readFileSync19(cachePath, "utf-8");
43946
+ const jsonContent = readFileSync20(cachePath, "utf-8");
43932
43947
  const data = JSON.parse(jsonContent);
43933
43948
  if (!data.lastUpdated) {
43934
43949
  return true;
@@ -44007,10 +44022,10 @@ async function updateModelsFromOpenRouter() {
44007
44022
  providers.add(provider);
44008
44023
  }
44009
44024
  let version2 = "1.2.0";
44010
- const existingPath = existsSync21(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44011
- if (existsSync21(existingPath)) {
44025
+ const existingPath = existsSync22(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44026
+ if (existsSync22(existingPath)) {
44012
44027
  try {
44013
- const existing = JSON.parse(readFileSync19(existingPath, "utf-8"));
44028
+ const existing = JSON.parse(readFileSync20(existingPath, "utf-8"));
44014
44029
  version2 = existing.version || version2;
44015
44030
  } catch {}
44016
44031
  }
@@ -44039,8 +44054,8 @@ async function checkAndUpdateModelsCache(forceUpdate = false) {
44039
44054
  await updateModelsFromOpenRouter();
44040
44055
  } else {
44041
44056
  try {
44042
- const cachePath = existsSync21(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44043
- const data = JSON.parse(readFileSync19(cachePath, "utf-8"));
44057
+ const cachePath = existsSync22(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44058
+ const data = JSON.parse(readFileSync20(cachePath, "utf-8"));
44044
44059
  console.error(`\u2713 Using cached models (last updated: ${data.lastUpdated})`);
44045
44060
  } catch {}
44046
44061
  }
@@ -44638,8 +44653,8 @@ MORE INFO:
44638
44653
  }
44639
44654
  function printAIAgentGuide() {
44640
44655
  try {
44641
- const guidePath = join23(__dirname4, "../AI_AGENT_GUIDE.md");
44642
- const guideContent = readFileSync19(guidePath, "utf-8");
44656
+ const guidePath = join24(__dirname4, "../AI_AGENT_GUIDE.md");
44657
+ const guideContent = readFileSync20(guidePath, "utf-8");
44643
44658
  console.log(guideContent);
44644
44659
  } catch (error2) {
44645
44660
  console.error("Error reading AI Agent Guide:");
@@ -44655,19 +44670,19 @@ async function initializeClaudishSkill() {
44655
44670
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
44656
44671
  `);
44657
44672
  const cwd = process.cwd();
44658
- const claudeDir = join23(cwd, ".claude");
44659
- const skillsDir = join23(claudeDir, "skills");
44660
- const claudishSkillDir = join23(skillsDir, "claudish-usage");
44661
- const skillFile = join23(claudishSkillDir, "SKILL.md");
44662
- if (existsSync21(skillFile)) {
44673
+ const claudeDir = join24(cwd, ".claude");
44674
+ const skillsDir = join24(claudeDir, "skills");
44675
+ const claudishSkillDir = join24(skillsDir, "claudish-usage");
44676
+ const skillFile = join24(claudishSkillDir, "SKILL.md");
44677
+ if (existsSync22(skillFile)) {
44663
44678
  console.log("\u2705 Claudish skill already installed at:");
44664
44679
  console.log(` ${skillFile}
44665
44680
  `);
44666
44681
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
44667
44682
  return;
44668
44683
  }
44669
- const sourceSkillPath = join23(__dirname4, "../skills/claudish-usage/SKILL.md");
44670
- if (!existsSync21(sourceSkillPath)) {
44684
+ const sourceSkillPath = join24(__dirname4, "../skills/claudish-usage/SKILL.md");
44685
+ if (!existsSync22(sourceSkillPath)) {
44671
44686
  console.error("\u274C Error: Claudish skill file not found in installation.");
44672
44687
  console.error(` Expected at: ${sourceSkillPath}`);
44673
44688
  console.error(`
@@ -44676,15 +44691,15 @@ async function initializeClaudishSkill() {
44676
44691
  process.exit(1);
44677
44692
  }
44678
44693
  try {
44679
- if (!existsSync21(claudeDir)) {
44694
+ if (!existsSync22(claudeDir)) {
44680
44695
  mkdirSync11(claudeDir, { recursive: true });
44681
44696
  console.log("\uD83D\uDCC1 Created .claude/ directory");
44682
44697
  }
44683
- if (!existsSync21(skillsDir)) {
44698
+ if (!existsSync22(skillsDir)) {
44684
44699
  mkdirSync11(skillsDir, { recursive: true });
44685
44700
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
44686
44701
  }
44687
- if (!existsSync21(claudishSkillDir)) {
44702
+ if (!existsSync22(claudishSkillDir)) {
44688
44703
  mkdirSync11(claudishSkillDir, { recursive: true });
44689
44704
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
44690
44705
  }
@@ -44727,9 +44742,9 @@ function printAvailableModels() {
44727
44742
  let lastUpdated = "unknown";
44728
44743
  let models = [];
44729
44744
  try {
44730
- const cachePath = existsSync21(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44731
- if (existsSync21(cachePath)) {
44732
- const data = JSON.parse(readFileSync19(cachePath, "utf-8"));
44745
+ const cachePath = existsSync22(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44746
+ if (existsSync22(cachePath)) {
44747
+ const data = JSON.parse(readFileSync20(cachePath, "utf-8"));
44733
44748
  lastUpdated = data.lastUpdated || "unknown";
44734
44749
  models = data.models || [];
44735
44750
  }
@@ -44778,9 +44793,9 @@ Force update: claudish --list-models --force-update
44778
44793
  `);
44779
44794
  }
44780
44795
  function printAvailableModelsJSON() {
44781
- const jsonPath = existsSync21(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44796
+ const jsonPath = existsSync22(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
44782
44797
  try {
44783
- const jsonContent = readFileSync19(jsonPath, "utf-8");
44798
+ const jsonContent = readFileSync20(jsonPath, "utf-8");
44784
44799
  const data = JSON.parse(jsonContent);
44785
44800
  console.log(JSON.stringify(data, null, 2));
44786
44801
  } catch (error2) {
@@ -44877,10 +44892,10 @@ var init_cli = __esm(() => {
44877
44892
  init_provider_resolver();
44878
44893
  __filename4 = fileURLToPath3(import.meta.url);
44879
44894
  __dirname4 = dirname3(__filename4);
44880
- CLAUDISH_CACHE_DIR2 = join23(homedir22(), ".claudish");
44881
- BUNDLED_MODELS_PATH = join23(__dirname4, "../recommended-models.json");
44882
- CACHED_MODELS_PATH = join23(CLAUDISH_CACHE_DIR2, "recommended-models.json");
44883
- ALL_MODELS_JSON_PATH = join23(CLAUDISH_CACHE_DIR2, "all-models.json");
44895
+ CLAUDISH_CACHE_DIR2 = join24(homedir23(), ".claudish");
44896
+ BUNDLED_MODELS_PATH = join24(__dirname4, "../recommended-models.json");
44897
+ CACHED_MODELS_PATH = join24(CLAUDISH_CACHE_DIR2, "recommended-models.json");
44898
+ ALL_MODELS_JSON_PATH = join24(CLAUDISH_CACHE_DIR2, "all-models.json");
44884
44899
  });
44885
44900
 
44886
44901
  // src/update-checker.ts
@@ -44891,33 +44906,33 @@ __export(exports_update_checker, {
44891
44906
  clearCache: () => clearCache,
44892
44907
  checkForUpdates: () => checkForUpdates
44893
44908
  });
44894
- import { existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync20, unlinkSync as unlinkSync8, writeFileSync as writeFileSync13 } from "fs";
44895
- import { homedir as homedir23, platform as platform2, tmpdir } from "os";
44896
- import { join as join24 } from "path";
44909
+ import { existsSync as existsSync23, mkdirSync as mkdirSync12, readFileSync as readFileSync21, unlinkSync as unlinkSync8, writeFileSync as writeFileSync13 } from "fs";
44910
+ import { homedir as homedir24, platform as platform2, tmpdir } from "os";
44911
+ import { join as join25 } from "path";
44897
44912
  function getCacheFilePath() {
44898
44913
  let cacheDir;
44899
44914
  if (isWindows) {
44900
- const localAppData = process.env.LOCALAPPDATA || join24(homedir23(), "AppData", "Local");
44901
- cacheDir = join24(localAppData, "claudish");
44915
+ const localAppData = process.env.LOCALAPPDATA || join25(homedir24(), "AppData", "Local");
44916
+ cacheDir = join25(localAppData, "claudish");
44902
44917
  } else {
44903
- cacheDir = join24(homedir23(), ".cache", "claudish");
44918
+ cacheDir = join25(homedir24(), ".cache", "claudish");
44904
44919
  }
44905
44920
  try {
44906
- if (!existsSync22(cacheDir)) {
44921
+ if (!existsSync23(cacheDir)) {
44907
44922
  mkdirSync12(cacheDir, { recursive: true });
44908
44923
  }
44909
- return join24(cacheDir, "update-check.json");
44924
+ return join25(cacheDir, "update-check.json");
44910
44925
  } catch {
44911
- return join24(tmpdir(), "claudish-update-check.json");
44926
+ return join25(tmpdir(), "claudish-update-check.json");
44912
44927
  }
44913
44928
  }
44914
44929
  function readCache() {
44915
44930
  try {
44916
44931
  const cachePath = getCacheFilePath();
44917
- if (!existsSync22(cachePath)) {
44932
+ if (!existsSync23(cachePath)) {
44918
44933
  return null;
44919
44934
  }
44920
- const data = JSON.parse(readFileSync20(cachePath, "utf-8"));
44935
+ const data = JSON.parse(readFileSync21(cachePath, "utf-8"));
44921
44936
  return data;
44922
44937
  } catch {
44923
44938
  return null;
@@ -44940,7 +44955,7 @@ function isCacheValid(cache) {
44940
44955
  function clearCache() {
44941
44956
  try {
44942
44957
  const cachePath = getCacheFilePath();
44943
- if (existsSync22(cachePath)) {
44958
+ if (existsSync23(cachePath)) {
44944
44959
  unlinkSync8(cachePath);
44945
44960
  }
44946
44961
  } catch {}
@@ -45241,15 +45256,15 @@ __export(exports_model_selector, {
45241
45256
  promptForApiKey: () => promptForApiKey,
45242
45257
  confirmAction: () => confirmAction
45243
45258
  });
45244
- import { readFileSync as readFileSync21, writeFileSync as writeFileSync14, existsSync as existsSync23, mkdirSync as mkdirSync13 } from "fs";
45245
- import { join as join25, dirname as dirname4 } from "path";
45246
- import { homedir as homedir24 } from "os";
45259
+ import { readFileSync as readFileSync22, writeFileSync as writeFileSync14, existsSync as existsSync24, mkdirSync as mkdirSync13 } from "fs";
45260
+ import { join as join26, dirname as dirname4 } from "path";
45261
+ import { homedir as homedir25 } from "os";
45247
45262
  import { fileURLToPath as fileURLToPath4 } from "url";
45248
45263
  function loadRecommendedModels2() {
45249
- const cachedPath = join25(CLAUDISH_CACHE_DIR3, "recommended-models-cache.json");
45250
- if (existsSync23(cachedPath)) {
45264
+ const cachedPath = join26(CLAUDISH_CACHE_DIR3, "recommended-models-cache.json");
45265
+ if (existsSync24(cachedPath)) {
45251
45266
  try {
45252
- const data = JSON.parse(readFileSync21(cachedPath, "utf-8"));
45267
+ const data = JSON.parse(readFileSync22(cachedPath, "utf-8"));
45253
45268
  if (data.models && data.models.length > 0) {
45254
45269
  return data.models.map((model) => ({
45255
45270
  ...model,
@@ -45258,9 +45273,9 @@ function loadRecommendedModels2() {
45258
45273
  }
45259
45274
  } catch {}
45260
45275
  }
45261
- if (existsSync23(RECOMMENDED_MODELS_JSON_PATH)) {
45276
+ if (existsSync24(RECOMMENDED_MODELS_JSON_PATH)) {
45262
45277
  try {
45263
- const content = readFileSync21(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
45278
+ const content = readFileSync22(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
45264
45279
  const data = JSON.parse(content);
45265
45280
  return (data.models || []).map((model) => ({
45266
45281
  ...model,
@@ -45273,9 +45288,9 @@ function loadRecommendedModels2() {
45273
45288
  return [];
45274
45289
  }
45275
45290
  async function fetchAllModels(forceUpdate = false) {
45276
- if (!forceUpdate && existsSync23(ALL_MODELS_JSON_PATH2)) {
45291
+ if (!forceUpdate && existsSync24(ALL_MODELS_JSON_PATH2)) {
45277
45292
  try {
45278
- const cacheData = JSON.parse(readFileSync21(ALL_MODELS_JSON_PATH2, "utf-8"));
45293
+ const cacheData = JSON.parse(readFileSync22(ALL_MODELS_JSON_PATH2, "utf-8"));
45279
45294
  const lastUpdated = new Date(cacheData.lastUpdated);
45280
45295
  const now = new Date;
45281
45296
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -45777,11 +45792,11 @@ async function fetchOllamaCloudModels() {
45777
45792
  }
45778
45793
  }
45779
45794
  function shouldRefreshForFreeModels() {
45780
- if (!existsSync23(ALL_MODELS_JSON_PATH2)) {
45795
+ if (!existsSync24(ALL_MODELS_JSON_PATH2)) {
45781
45796
  return true;
45782
45797
  }
45783
45798
  try {
45784
- const cacheData = JSON.parse(readFileSync21(ALL_MODELS_JSON_PATH2, "utf-8"));
45799
+ const cacheData = JSON.parse(readFileSync22(ALL_MODELS_JSON_PATH2, "utf-8"));
45785
45800
  const lastUpdated = new Date(cacheData.lastUpdated);
45786
45801
  const now = new Date;
45787
45802
  const ageInHours = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60);
@@ -46478,9 +46493,9 @@ var init_model_selector = __esm(() => {
46478
46493
  init_provider_definitions();
46479
46494
  __filename5 = fileURLToPath4(import.meta.url);
46480
46495
  __dirname5 = dirname4(__filename5);
46481
- CLAUDISH_CACHE_DIR3 = join25(homedir24(), ".claudish");
46482
- ALL_MODELS_JSON_PATH2 = join25(CLAUDISH_CACHE_DIR3, "all-models.json");
46483
- RECOMMENDED_MODELS_JSON_PATH = join25(__dirname5, "../recommended-models.json");
46496
+ CLAUDISH_CACHE_DIR3 = join26(homedir25(), ".claudish");
46497
+ ALL_MODELS_JSON_PATH2 = join26(CLAUDISH_CACHE_DIR3, "all-models.json");
46498
+ RECOMMENDED_MODELS_JSON_PATH = join26(__dirname5, "../recommended-models.json");
46484
46499
  PROVIDER_FILTER_ALIASES = {
46485
46500
  zen: "Zen",
46486
46501
  openrouter: "OpenRouter",
@@ -47166,13 +47181,13 @@ import { EventEmitter as EventEmitter2 } from "events";
47166
47181
  import { resolve as resolve3, dirname as dirname5 } from "path";
47167
47182
  import { fileURLToPath as fileURLToPath5 } from "url";
47168
47183
  import { resolve as resolve22, isAbsolute, parse as parse6 } from "path";
47169
- import { existsSync as existsSync24 } from "fs";
47170
- import { basename, join as join26 } from "path";
47184
+ import { existsSync as existsSync25 } from "fs";
47185
+ import { basename, join as join27 } from "path";
47171
47186
  import os2 from "os";
47172
47187
  import path2 from "path";
47173
47188
  import { EventEmitter as EventEmitter3 } from "events";
47174
47189
  import { dlopen, toArrayBuffer as toArrayBuffer4, JSCallback, ptr as ptr4 } from "bun:ffi";
47175
- import { existsSync as existsSync25, writeFileSync as writeFileSync15 } from "fs";
47190
+ import { existsSync as existsSync26, writeFileSync as writeFileSync15 } from "fs";
47176
47191
  import { EventEmitter as EventEmitter4 } from "events";
47177
47192
  import { toArrayBuffer, ptr } from "bun:ffi";
47178
47193
  import { ptr as ptr2, toArrayBuffer as toArrayBuffer2 } from "bun:ffi";
@@ -49566,7 +49581,7 @@ function getBunfsRootPath() {
49566
49581
  return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
49567
49582
  }
49568
49583
  function normalizeBunfsPath(fileName) {
49569
- return join26(getBunfsRootPath(), basename(fileName));
49584
+ return join27(getBunfsRootPath(), basename(fileName));
49570
49585
  }
49571
49586
  function isValidDirectoryName(name) {
49572
49587
  if (!name || typeof name !== "string") {
@@ -59762,7 +59777,7 @@ var init_index_0wbvecnk = __esm(async () => {
59762
59777
  worker_path = this.options.workerPath;
59763
59778
  } else {
59764
59779
  worker_path = new URL("./parser.worker.js", import.meta.url).href;
59765
- if (!existsSync24(resolve22(import.meta.dirname, "parser.worker.js"))) {
59780
+ if (!existsSync25(resolve22(import.meta.dirname, "parser.worker.js"))) {
59766
59781
  worker_path = new URL("./parser.worker.ts", import.meta.url).href;
59767
59782
  }
59768
59783
  }
@@ -60463,7 +60478,7 @@ var init_index_0wbvecnk = __esm(async () => {
60463
60478
  if (isBunfsPath(targetLibPath)) {
60464
60479
  targetLibPath = targetLibPath.replace("../", "");
60465
60480
  }
60466
- if (!existsSync25(targetLibPath)) {
60481
+ if (!existsSync26(targetLibPath)) {
60467
60482
  throw new Error(`opentui is not supported on the current platform: ${process.platform}-${process.arch}`);
60468
60483
  }
60469
60484
  registerEnvVar({
@@ -106082,9 +106097,9 @@ __export(exports_claude_runner, {
106082
106097
  checkClaudeInstalled: () => checkClaudeInstalled
106083
106098
  });
106084
106099
  import { spawn as spawn4 } from "child_process";
106085
- import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync9, mkdirSync as mkdirSync14, existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
106086
- import { tmpdir as tmpdir2, homedir as homedir25 } from "os";
106087
- import { join as join27 } from "path";
106100
+ import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync9, mkdirSync as mkdirSync14, existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
106101
+ import { tmpdir as tmpdir2, homedir as homedir26 } from "os";
106102
+ import { join as join28 } from "path";
106088
106103
  function hasNativeAnthropicMapping(config3) {
106089
106104
  const models = [
106090
106105
  config3.model,
@@ -106100,9 +106115,9 @@ function isWindows2() {
106100
106115
  }
106101
106116
  function createStatusLineScript(tokenFilePath) {
106102
106117
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
106103
- const claudishDir = join27(homeDir, ".claudish");
106118
+ const claudishDir = join28(homeDir, ".claudish");
106104
106119
  const timestamp = Date.now();
106105
- const scriptPath = join27(claudishDir, `status-${timestamp}.js`);
106120
+ const scriptPath = join28(claudishDir, `status-${timestamp}.js`);
106106
106121
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
106107
106122
  const script = `
106108
106123
  const fs = require('fs');
@@ -106140,9 +106155,9 @@ process.stdin.on('end', () => {
106140
106155
  try {
106141
106156
  const tokens = JSON.parse(fs.readFileSync('${escapedTokenPath}', 'utf-8'));
106142
106157
  cost = tokens.total_cost || 0;
106143
- ctx = tokens.context_left_percent || 100;
106158
+ ctx = tokens.context_left_percent ?? -1;
106144
106159
  inputTokens = tokens.input_tokens || 0;
106145
- contextWindow = tokens.context_window || 0;
106160
+ contextWindow = typeof tokens.context_window === 'number' ? tokens.context_window : 0;
106146
106161
  isFree = tokens.is_free || false;
106147
106162
  isEstimated = tokens.is_estimated || false;
106148
106163
  providerName = tokens.provider_name || '';
@@ -106168,7 +106183,10 @@ process.stdin.on('end', () => {
106168
106183
  const modelDisplay = providerName ? providerName + ' ' + model : model;
106169
106184
  // Format context display as progress bar: [\u2588\u2588\u2588\u2588\u2591\u2591\u2591\u2591\u2591\u2591] 116k/1M
106170
106185
  let ctxDisplay = '';
106171
- if (inputTokens > 0 && contextWindow > 0) {
106186
+ if (ctx < 0 || contextWindow <= 0) {
106187
+ // Unknown context window \u2014 show token count only
106188
+ ctxDisplay = inputTokens > 0 ? formatTokens(inputTokens) + ' tokens' : 'N/A';
106189
+ } else if (inputTokens > 0 && contextWindow > 0) {
106172
106190
  const usedPct = 100 - ctx; // ctx is "left", so used = 100 - left
106173
106191
  const barWidth = 15;
106174
106192
  const filled = Math.round((usedPct / 100) * barWidth);
@@ -106196,13 +106214,13 @@ process.stdin.on('end', () => {
106196
106214
  }
106197
106215
  function createTempSettingsFile(modelDisplay, port) {
106198
106216
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
106199
- const claudishDir = join27(homeDir, ".claudish");
106217
+ const claudishDir = join28(homeDir, ".claudish");
106200
106218
  try {
106201
106219
  mkdirSync14(claudishDir, { recursive: true });
106202
106220
  } catch {}
106203
106221
  const timestamp = Date.now();
106204
- const tempPath = join27(claudishDir, `settings-${timestamp}.json`);
106205
- const tokenFilePath = join27(claudishDir, `tokens-${port}.json`);
106222
+ const tempPath = join28(claudishDir, `settings-${timestamp}.json`);
106223
+ const tokenFilePath = join28(claudishDir, `tokens-${port}.json`);
106206
106224
  let statusCommand;
106207
106225
  if (isWindows2()) {
106208
106226
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -106216,7 +106234,7 @@ function createTempSettingsFile(modelDisplay, port) {
106216
106234
  const RESET4 = "\\033[0m";
106217
106235
  const BOLD4 = "\\033[1m";
106218
106236
  const formatTokensBash = `fmt_tok() { local n=\${1:-0}; if [ "$n" -ge 1000000 ]; then echo "$((n/1000000))M"; elif [ "$n" -ge 1000 ]; then echo "$((n/1000))k"; else echo "$n"; fi; }`;
106219
- statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=100 && COST="0" && IS_FREE="false" && IS_EST="false" && PROVIDER="" && TOKEN_MODEL="" && IN_TOK=0 && CTX_WIN=0 && ${formatTokensBash} && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d ' \\n') && REAL_CTX=$(echo "$TOKENS" | grep -o '"context_left_percent":[0-9]*' | grep -o '[0-9]*') && if [ ! -z "$REAL_CTX" ]; then CTX="$REAL_CTX"; fi && REAL_COST=$(echo "$TOKENS" | grep -o '"total_cost":[0-9.]*' | cut -d: -f2) && if [ ! -z "$REAL_COST" ]; then COST="$REAL_COST"; fi && IN_TOK=$(echo "$TOKENS" | grep -o '"input_tokens":[0-9]*' | grep -o '[0-9]*') && CTX_WIN=$(echo "$TOKENS" | grep -o '"context_window":[0-9]*' | grep -o '[0-9]*') && IS_FREE=$(echo "$TOKENS" | grep -o '"is_free":[a-z]*' | cut -d: -f2) && IS_EST=$(echo "$TOKENS" | grep -o '"is_estimated":[a-z]*' | cut -d: -f2) && PROVIDER=$(echo "$TOKENS" | grep -o '"provider_name":"[^"]*"' | cut -d'"' -f4) && TOKEN_MODEL=$(echo "$TOKENS" | grep -o '"model_name":"[^"]*"' | cut -d'"' -f4); fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}" && if [ ! -z "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi && if [ "$IN_TOK" -gt 0 ] 2>/dev/null && [ "$CTX_WIN" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX%"; fi && printf "${CYAN4}${BOLD4}%s${RESET4} ${DIM4}\u2022${RESET4} ${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}\\n" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"`;
106237
+ statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=-1 && COST="0" && IS_FREE="false" && IS_EST="false" && PROVIDER="" && TOKEN_MODEL="" && IN_TOK=0 && CTX_WIN=0 && ${formatTokensBash} && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d ' \\n') && REAL_CTX=$(echo "$TOKENS" | grep -o '"context_left_percent":-\\?[0-9]*' | grep -o '\\-\\?[0-9]*') && if [ ! -z "$REAL_CTX" ]; then CTX="$REAL_CTX"; fi && REAL_COST=$(echo "$TOKENS" | grep -o '"total_cost":[0-9.]*' | cut -d: -f2) && if [ ! -z "$REAL_COST" ]; then COST="$REAL_COST"; fi && IN_TOK=$(echo "$TOKENS" | grep -o '"input_tokens":[0-9]*' | grep -o '[0-9]*') && CTX_WIN=$(echo "$TOKENS" | grep -o '"context_window":[0-9]*' | grep -o '[0-9]*') && IS_FREE=$(echo "$TOKENS" | grep -o '"is_free":[a-z]*' | cut -d: -f2) && IS_EST=$(echo "$TOKENS" | grep -o '"is_estimated":[a-z]*' | cut -d: -f2) && PROVIDER=$(echo "$TOKENS" | grep -o '"provider_name":"[^"]*"' | cut -d'"' -f4) && TOKEN_MODEL=$(echo "$TOKENS" | grep -o '"model_name":"[^"]*"' | cut -d'"' -f4); fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}" && if [ ! -z "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi && if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$CTX_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null && [ "$CTX_WIN" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX%"; fi && printf "${CYAN4}${BOLD4}%s${RESET4} ${DIM4}\u2022${RESET4} ${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}\\n" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"`;
106220
106238
  }
106221
106239
  const statusLine = {
106222
106240
  type: "command",
@@ -106238,7 +106256,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
106238
106256
  if (userSettingsValue.trimStart().startsWith("{")) {
106239
106257
  userSettings = JSON.parse(userSettingsValue);
106240
106258
  } else {
106241
- const rawUserSettings = readFileSync22(userSettingsValue, "utf-8");
106259
+ const rawUserSettings = readFileSync23(userSettingsValue, "utf-8");
106242
106260
  userSettings = JSON.parse(rawUserSettings);
106243
106261
  }
106244
106262
  userSettings.statusLine = statusLine;
@@ -106330,8 +106348,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
106330
106348
  console.error("Install it from: https://claude.com/claude-code");
106331
106349
  console.error(`
106332
106350
  Or set CLAUDE_PATH to your custom installation:`);
106333
- const home = homedir25();
106334
- const localPath = isWindows2() ? join27(home, ".claude", "local", "claude.exe") : join27(home, ".claude", "local", "claude");
106351
+ const home = homedir26();
106352
+ const localPath = isWindows2() ? join28(home, ".claude", "local", "claude.exe") : join28(home, ".claude", "local", "claude");
106335
106353
  console.error(` export CLAUDE_PATH=${localPath}`);
106336
106354
  process.exit(1);
106337
106355
  }
@@ -106377,23 +106395,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
106377
106395
  async function findClaudeBinary() {
106378
106396
  const isWindows3 = process.platform === "win32";
106379
106397
  if (process.env.CLAUDE_PATH) {
106380
- if (existsSync26(process.env.CLAUDE_PATH)) {
106398
+ if (existsSync27(process.env.CLAUDE_PATH)) {
106381
106399
  return process.env.CLAUDE_PATH;
106382
106400
  }
106383
106401
  }
106384
- const home = homedir25();
106385
- const localPath = isWindows3 ? join27(home, ".claude", "local", "claude.exe") : join27(home, ".claude", "local", "claude");
106386
- if (existsSync26(localPath)) {
106402
+ const home = homedir26();
106403
+ const localPath = isWindows3 ? join28(home, ".claude", "local", "claude.exe") : join28(home, ".claude", "local", "claude");
106404
+ if (existsSync27(localPath)) {
106387
106405
  return localPath;
106388
106406
  }
106389
106407
  if (isWindows3) {
106390
106408
  const windowsPaths = [
106391
- join27(home, "AppData", "Roaming", "npm", "claude.cmd"),
106392
- join27(home, ".npm-global", "claude.cmd"),
106393
- join27(home, "node_modules", ".bin", "claude.cmd")
106409
+ join28(home, "AppData", "Roaming", "npm", "claude.cmd"),
106410
+ join28(home, ".npm-global", "claude.cmd"),
106411
+ join28(home, "node_modules", ".bin", "claude.cmd")
106394
106412
  ];
106395
106413
  for (const path3 of windowsPaths) {
106396
- if (existsSync26(path3)) {
106414
+ if (existsSync27(path3)) {
106397
106415
  return path3;
106398
106416
  }
106399
106417
  }
@@ -106401,14 +106419,14 @@ async function findClaudeBinary() {
106401
106419
  const commonPaths = [
106402
106420
  "/usr/local/bin/claude",
106403
106421
  "/opt/homebrew/bin/claude",
106404
- join27(home, ".npm-global/bin/claude"),
106405
- join27(home, ".local/bin/claude"),
106406
- join27(home, "node_modules/.bin/claude"),
106422
+ join28(home, ".npm-global/bin/claude"),
106423
+ join28(home, ".local/bin/claude"),
106424
+ join28(home, "node_modules/.bin/claude"),
106407
106425
  "/data/data/com.termux/files/usr/bin/claude",
106408
- join27(home, "../usr/bin/claude")
106426
+ join28(home, "../usr/bin/claude")
106409
106427
  ];
106410
106428
  for (const path3 of commonPaths) {
106411
- if (existsSync26(path3)) {
106429
+ if (existsSync27(path3)) {
106412
106430
  return path3;
106413
106431
  }
106414
106432
  }
@@ -106458,17 +106476,17 @@ __export(exports_diag_output, {
106458
106476
  LogFileDiagOutput: () => LogFileDiagOutput
106459
106477
  });
106460
106478
  import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync15, writeFileSync as writeFileSync17, unlinkSync as unlinkSync10 } from "fs";
106461
- import { homedir as homedir26 } from "os";
106462
- import { join as join28 } from "path";
106479
+ import { homedir as homedir27 } from "os";
106480
+ import { join as join29 } from "path";
106463
106481
  function getClaudishDir() {
106464
- const dir = join28(homedir26(), ".claudish");
106482
+ const dir = join29(homedir27(), ".claudish");
106465
106483
  try {
106466
106484
  mkdirSync15(dir, { recursive: true });
106467
106485
  } catch {}
106468
106486
  return dir;
106469
106487
  }
106470
106488
  function getDiagLogPath() {
106471
- return join28(getClaudishDir(), `diag-${process.pid}.log`);
106489
+ return join29(getClaudishDir(), `diag-${process.pid}.log`);
106472
106490
  }
106473
106491
 
106474
106492
  class LogFileDiagOutput {
@@ -106527,42 +106545,112 @@ __export(exports_team_grid, {
106527
106545
  });
106528
106546
  import { spawn as spawn5 } from "child_process";
106529
106547
  import {
106530
- appendFileSync,
106531
- existsSync as existsSync28,
106548
+ existsSync as existsSync29,
106532
106549
  mkdirSync as mkdirSync16,
106533
- readFileSync as readFileSync23,
106550
+ readFileSync as readFileSync24,
106534
106551
  unlinkSync as unlinkSync11,
106535
106552
  writeFileSync as writeFileSync18
106536
106553
  } from "fs";
106537
- import { dirname as dirname6, join as join29 } from "path";
106554
+ import { dirname as dirname6, join as join30 } from "path";
106538
106555
  import { fileURLToPath as fileURLToPath6 } from "url";
106539
106556
  import { execSync as execSync2 } from "child_process";
106540
- function formatElapsed(ms) {
106541
- const s = Math.floor(ms / 1000);
106542
- if (s < 60)
106543
- return `${s}s`;
106544
- const m2 = Math.floor(s / 60);
106545
- const rem = s % 60;
106546
- return `${m2}m ${rem}s`;
106557
+ function resolveRouteInfo(modelId) {
106558
+ const parsed = parseModelSpec(modelId);
106559
+ if (parsed.isExplicitProvider) {
106560
+ return { chain: [parsed.provider], source: "direct" };
106561
+ }
106562
+ const local = loadLocalConfig();
106563
+ if (local?.routing && Object.keys(local.routing).length > 0) {
106564
+ const matched = matchRoutingRule(parsed.model, local.routing);
106565
+ if (matched) {
106566
+ const routes2 = buildRoutingChain(matched, parsed.model);
106567
+ const pattern = Object.keys(local.routing).find((k2) => {
106568
+ if (k2 === parsed.model)
106569
+ return true;
106570
+ if (k2.includes("*")) {
106571
+ const star = k2.indexOf("*");
106572
+ return parsed.model.startsWith(k2.slice(0, star)) && parsed.model.endsWith(k2.slice(star + 1));
106573
+ }
106574
+ return false;
106575
+ });
106576
+ return {
106577
+ chain: routes2.map((r) => r.displayName),
106578
+ source: "project routing",
106579
+ sourceDetail: pattern
106580
+ };
106581
+ }
106582
+ }
106583
+ const global_ = loadConfig();
106584
+ if (global_.routing && Object.keys(global_.routing).length > 0) {
106585
+ const matched = matchRoutingRule(parsed.model, global_.routing);
106586
+ if (matched) {
106587
+ const routes2 = buildRoutingChain(matched, parsed.model);
106588
+ const pattern = Object.keys(global_.routing).find((k2) => {
106589
+ if (k2 === parsed.model)
106590
+ return true;
106591
+ if (k2.includes("*")) {
106592
+ const star = k2.indexOf("*");
106593
+ return parsed.model.startsWith(k2.slice(0, star)) && parsed.model.endsWith(k2.slice(star + 1));
106594
+ }
106595
+ return false;
106596
+ });
106597
+ return {
106598
+ chain: routes2.map((r) => r.displayName),
106599
+ source: "user routing",
106600
+ sourceDetail: pattern
106601
+ };
106602
+ }
106603
+ }
106604
+ const routes = getFallbackChain(parsed.model, parsed.provider);
106605
+ return {
106606
+ chain: routes.map((r) => r.displayName),
106607
+ source: "auto"
106608
+ };
106609
+ }
106610
+ function buildPaneHeader(model, prompt) {
106611
+ const route = resolveRouteInfo(model);
106612
+ const esc2 = (s) => s.replace(/'/g, "'\\''");
106613
+ const bgColors = [
106614
+ "48;2;40;90;180",
106615
+ "48;2;140;60;160",
106616
+ "48;2;30;130;100",
106617
+ "48;2;160;80;40",
106618
+ "48;2;60;120;60",
106619
+ "48;2;160;50;70"
106620
+ ];
106621
+ let hash = 0;
106622
+ for (let i = 0;i < model.length; i++)
106623
+ hash = (hash << 5) - hash + model.charCodeAt(i) | 0;
106624
+ const bg2 = bgColors[Math.abs(hash) % bgColors.length];
106625
+ const chainStr = route.chain.join(" \u2192 ");
106626
+ const sourceLabel = route.sourceDetail ? `${route.source}: ${route.sourceDetail}` : route.source;
106627
+ const lines = [];
106628
+ lines.push(`printf '\\033[1;97;${bg2}m %s \\033[0m\\n' '${esc2(model)}';`);
106629
+ lines.push(`printf '\\033[2m route: ${esc2(chainStr)} (${esc2(sourceLabel)})\\033[0m\\n' ;`);
106630
+ lines.push(`printf '\\033[2m %s\\033[0m\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
106631
+ const promptForShell = esc2(prompt).replace(/\n/g, "\\n");
106632
+ lines.push(`printf '%b\\n' '${promptForShell}' | fold -s -w 78 | sed 's/^/ /';`);
106633
+ lines.push(`printf '\\033[2m %s\\033[0m\\n\\n' '\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500';`);
106634
+ return lines.join(" ");
106547
106635
  }
106548
106636
  function findMagmuxBinary() {
106549
106637
  const thisFile = fileURLToPath6(import.meta.url);
106550
106638
  const thisDir = dirname6(thisFile);
106551
- const pkgRoot = join29(thisDir, "..");
106639
+ const pkgRoot = join30(thisDir, "..");
106552
106640
  const platform3 = process.platform;
106553
106641
  const arch = process.arch;
106554
- const builtMagmux = join29(pkgRoot, "native", "magmux", "magmux");
106555
- if (existsSync28(builtMagmux))
106642
+ const builtMagmux = join30(pkgRoot, "native", "magmux", "magmux");
106643
+ if (existsSync29(builtMagmux))
106556
106644
  return builtMagmux;
106557
- const bundledMagmux = join29(pkgRoot, "native", "magmux", `magmux-${platform3}-${arch}`);
106558
- if (existsSync28(bundledMagmux))
106645
+ const bundledMagmux = join30(pkgRoot, "native", "magmux", `magmux-${platform3}-${arch}`);
106646
+ if (existsSync29(bundledMagmux))
106559
106647
  return bundledMagmux;
106560
106648
  try {
106561
106649
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
106562
106650
  let searchDir = pkgRoot;
106563
106651
  for (let i = 0;i < 5; i++) {
106564
- const candidate = join29(searchDir, "node_modules", pkgName, "bin", "magmux");
106565
- if (existsSync28(candidate))
106652
+ const candidate = join30(searchDir, "node_modules", pkgName, "bin", "magmux");
106653
+ if (existsSync29(candidate))
106566
106654
  return candidate;
106567
106655
  const parent = dirname6(searchDir);
106568
106656
  if (parent === searchDir)
@@ -106578,141 +106666,97 @@ function findMagmuxBinary() {
106578
106666
  throw new Error(`magmux not found. Install it:
106579
106667
  brew install MadAppGang/tap/magmux`);
106580
106668
  }
106581
- function renderGridStatusBar(counts) {
106582
- const elapsed = formatElapsed(counts.elapsedMs);
106583
- const { done, running, failed, total, allDone } = counts;
106584
- if (allDone) {
106585
- if (failed > 0) {
106586
- return [
106587
- "C: claudish team",
106588
- `G: ${done} done`,
106589
- `R: ${failed} failed`,
106590
- `D: ${elapsed}`,
106591
- "R: \u2717 issues",
106592
- "D: ctrl-g q to quit"
106593
- ].join("\t");
106594
- }
106595
- return [
106596
- "C: claudish team",
106597
- `G: ${total} done`,
106598
- `D: ${elapsed}`,
106599
- "G: \u2713 complete",
106600
- "D: ctrl-g q to quit"
106601
- ].join("\t");
106602
- }
106603
- return [
106604
- "C: claudish team",
106605
- `G: ${done} done`,
106606
- `C: ${running} running`,
106607
- `R: ${failed} failed`,
106608
- `D: ${elapsed}`
106609
- ].join("\t");
106610
- }
106611
- function pollStatus(state) {
106612
- const { statusCache, statusPath, sessionPath, anonIds, startTime, timeoutMs, statusbarPath } = state;
106613
- const elapsedMs = Date.now() - startTime;
106614
- let changed = false;
106615
- let done = 0;
106616
- let running = 0;
106617
- let failed = 0;
106669
+ function finalizeStatus(statusPath, sessionPath, anonIds) {
106670
+ const statusCache = JSON.parse(readFileSync24(statusPath, "utf-8"));
106618
106671
  for (const anonId of anonIds) {
106619
106672
  const current = statusCache.models[anonId];
106620
- if (current.state === "COMPLETED" || current.state === "FAILED" || current.state === "TIMEOUT") {
106621
- if (current.state === "COMPLETED")
106622
- done++;
106623
- else
106624
- failed++;
106673
+ if (current.state === "COMPLETED" || current.state === "FAILED")
106625
106674
  continue;
106626
- }
106627
- const exitCodePath = join29(sessionPath, "work", anonId, ".exit-code");
106628
- if (existsSync28(exitCodePath)) {
106629
- const codeStr = readFileSync23(exitCodePath, "utf-8").trim();
106630
- const code = parseInt(codeStr, 10);
106631
- const isSuccess = code === 0;
106632
- const newState = {
106675
+ const exitCodePath = join30(sessionPath, "work", anonId, ".exit-code");
106676
+ if (existsSync29(exitCodePath)) {
106677
+ const code = parseInt(readFileSync24(exitCodePath, "utf-8").trim(), 10);
106678
+ statusCache.models[anonId] = {
106633
106679
  ...current,
106634
- state: isSuccess ? "COMPLETED" : "FAILED",
106680
+ state: code === 0 ? "COMPLETED" : "FAILED",
106635
106681
  exitCode: code,
106636
- startedAt: current.startedAt ?? new Date().toISOString(),
106637
- completedAt: new Date().toISOString(),
106638
- outputSize: 0
106682
+ startedAt: current.startedAt ?? statusCache.startedAt,
106683
+ completedAt: new Date().toISOString()
106639
106684
  };
106640
- statusCache.models[anonId] = newState;
106641
- changed = true;
106642
- if (isSuccess)
106643
- done++;
106644
- else
106645
- failed++;
106646
106685
  } else {
106647
- if (!state.interactive && elapsedMs > timeoutMs) {
106648
- const newState = {
106649
- ...current,
106650
- state: "TIMEOUT",
106651
- startedAt: current.startedAt ?? new Date().toISOString(),
106652
- completedAt: new Date().toISOString(),
106653
- outputSize: 0
106654
- };
106655
- statusCache.models[anonId] = newState;
106656
- changed = true;
106657
- failed++;
106658
- } else {
106659
- if (current.state === "PENDING" && elapsedMs > 1000) {
106660
- statusCache.models[anonId] = {
106661
- ...current,
106662
- state: "RUNNING",
106663
- startedAt: current.startedAt ?? new Date().toISOString()
106664
- };
106665
- changed = true;
106666
- }
106667
- running++;
106668
- }
106686
+ statusCache.models[anonId] = { ...current, state: "TIMEOUT" };
106669
106687
  }
106670
106688
  }
106671
- if (changed) {
106672
- writeFileSync18(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
106673
- }
106674
- const total = anonIds.length;
106675
- const allDone = done + failed >= total;
106676
- if (allDone && !state.completedAtMs) {
106677
- state.completedAtMs = elapsedMs;
106678
- }
106679
- const counts = {
106680
- done,
106681
- running,
106682
- failed,
106683
- total,
106684
- elapsedMs: state.completedAtMs ?? elapsedMs,
106685
- allDone
106686
- };
106687
- appendFileSync(statusbarPath, renderGridStatusBar(counts) + `
106688
- `);
106689
- return allDone;
106689
+ writeFileSync18(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
106690
106690
  }
106691
106691
  async function runWithGrid(sessionPath, models, input, opts) {
106692
- const timeoutMs = (opts?.timeout ?? 300) * 1000;
106693
- const interactive = opts?.interactive ?? false;
106692
+ const mode = opts?.mode ?? "default";
106693
+ const keep = opts?.keep ?? false;
106694
106694
  const manifest = setupSession(sessionPath, models, input);
106695
- mkdirSync16(join29(sessionPath, "errors"), { recursive: true });
106695
+ mkdirSync16(join30(sessionPath, "errors"), { recursive: true });
106696
106696
  for (const anonId of Object.keys(manifest.models)) {
106697
- const stale = join29(sessionPath, "work", anonId, ".exit-code");
106697
+ const stale = join30(sessionPath, "work", anonId, ".exit-code");
106698
106698
  try {
106699
106699
  unlinkSync11(stale);
106700
106700
  } catch {}
106701
106701
  }
106702
- const gridfilePath = join29(sessionPath, "gridfile.txt");
106703
- const prompt = readFileSync23(join29(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
106702
+ const gridfilePath = join30(sessionPath, "gridfile.txt");
106703
+ const prompt = readFileSync24(join30(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
106704
+ const totalPanes = Object.keys(manifest.models).length;
106705
+ const workDir = join30(sessionPath, "work");
106706
+ const statusFunc = [
106707
+ `_update_bar() {`,
106708
+ `_d=0; _f=0;`,
106709
+ `for _ecf in $(find ${workDir} -name .exit-code 2>/dev/null); do`,
106710
+ `_c=$(cat "$_ecf" 2>/dev/null);`,
106711
+ `if [ "$_c" = "0" ]; then _d=$((_d+1)); else _f=$((_f+1)); fi;`,
106712
+ `done;`,
106713
+ `_r=$((${totalPanes}-_d-_f));`,
106714
+ `_e=$SECONDS;`,
106715
+ `if [ $_e -ge 60 ]; then _ts="$((_e/60))m $((_e%60))s"; else _ts="\${_e}s"; fi;`,
106716
+ `if [ $_r -eq 0 ] && [ $_f -eq 0 ]; then`,
106717
+ `_t="C: claudish team G: ${totalPanes} done G: complete D: \${_ts} D: ctrl-g q to quit";`,
106718
+ `elif [ $_r -eq 0 ] && [ $_f -gt 0 ]; then`,
106719
+ `_t="C: claudish team G: \${_d} done R: \${_f} failed D: \${_ts} D: ctrl-g q to quit";`,
106720
+ `else`,
106721
+ `_t="C: claudish team G: \${_d} done C: \${_r} running R: \${_f} failed D: \${_ts}";`,
106722
+ `fi;`,
106723
+ `_j=$(printf '%s' "$_t" | sed 's/ /\\\\t/g');`,
106724
+ `printf '{"cmd":"status","text":"%s"}' "$_j" | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
106725
+ `};`
106726
+ ].join(" ");
106727
+ const rawPrompt = readFileSync24(join30(sessionPath, "input.md"), "utf-8");
106704
106728
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
106705
- const errorLog = join29(sessionPath, "errors", `${anonId}.log`);
106706
- const exitCodeFile = join29(sessionPath, "work", anonId, ".exit-code");
106729
+ const errorLog = join30(sessionPath, "errors", `${anonId}.log`);
106730
+ const exitCodeFile = join30(sessionPath, "work", anonId, ".exit-code");
106707
106731
  const model = manifest.models[anonId].model;
106708
106732
  const paneIndex = Object.keys(manifest.models).indexOf(anonId);
106709
- if (interactive) {
106710
- return `claudish --model ${model} --dangerously-skip-permissions '${prompt}'`;
106711
- }
106733
+ if (mode === "interactive") {
106734
+ return [
106735
+ `${statusFunc}`,
106736
+ `if [ -n "$MAGMUX_SOCK" ]; then _update_bar; fi;`,
106737
+ `claudish --model ${model} -i --dangerously-skip-permissions '${prompt}' 2>${errorLog};`,
106738
+ `_ec=$?; echo $_ec > ${exitCodeFile};`,
106739
+ `if [ -n "$MAGMUX_SOCK" ]; then`,
106740
+ ` _update_bar;`,
106741
+ ` if [ $_ec -eq 0 ]; then`,
106742
+ ` echo '{"cmd":"tint","pane":${paneIndex},"color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
106743
+ ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"DONE","color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
106744
+ ` else`,
106745
+ ` echo '{"cmd":"tint","pane":${paneIndex},"color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
106746
+ ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"FAIL","color":"red"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
106747
+ ` fi;`,
106748
+ `fi`
106749
+ ].join(" ");
106750
+ }
106751
+ const header = buildPaneHeader(model, rawPrompt);
106712
106752
  return [
106713
- `claudish --model ${model} -y -v '${prompt}' 2>${errorLog};`,
106753
+ `${statusFunc}`,
106754
+ `if [ -n "$MAGMUX_SOCK" ]; then _update_bar; fi;`,
106755
+ `${header}`,
106756
+ `claudish --model ${model} -y --quiet '${prompt}' 2>${errorLog};`,
106714
106757
  `_ec=$?; echo $_ec > ${exitCodeFile};`,
106715
106758
  `if [ -n "$MAGMUX_SOCK" ]; then`,
106759
+ ` _update_bar;`,
106716
106760
  ` if [ $_ec -eq 0 ]; then`,
106717
106761
  ` echo '{"cmd":"tint","pane":${paneIndex},"color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
106718
106762
  ` echo '{"cmd":"overlay","pane":${paneIndex},"text":"DONE","color":"green"}' | nc -U "$MAGMUX_SOCK" -w 1 2>/dev/null;`,
@@ -106728,36 +106772,10 @@ async function runWithGrid(sessionPath, models, input, opts) {
106728
106772
  `) + `
106729
106773
  `, "utf-8");
106730
106774
  const magmuxPath = findMagmuxBinary();
106731
- const statusbarPath = join29(sessionPath, "statusbar.txt");
106732
- const statusPath = join29(sessionPath, "status.json");
106733
- const statusCache = JSON.parse(readFileSync23(statusPath, "utf-8"));
106775
+ const statusPath = join30(sessionPath, "status.json");
106734
106776
  const anonIds = Object.keys(manifest.models);
106735
- const startTime = Date.now();
106736
- appendFileSync(statusbarPath, renderGridStatusBar({
106737
- done: 0,
106738
- running: 0,
106739
- failed: 0,
106740
- total: anonIds.length,
106741
- elapsedMs: 0,
106742
- allDone: false
106743
- }) + `
106744
- `);
106745
- const pollState = {
106746
- statusCache,
106747
- statusPath,
106748
- sessionPath,
106749
- anonIds,
106750
- startTime,
106751
- timeoutMs,
106752
- statusbarPath,
106753
- completedAtMs: null,
106754
- interactive
106755
- };
106756
- const pollInterval = setInterval(() => {
106757
- pollStatus(pollState);
106758
- }, 500);
106759
- const spawnArgs = ["-g", gridfilePath, "-S", statusbarPath];
106760
- if (!interactive) {
106777
+ const spawnArgs = ["-g", gridfilePath];
106778
+ if (!keep && mode === "default") {
106761
106779
  spawnArgs.push("-w");
106762
106780
  }
106763
106781
  const proc = spawn5(magmuxPath, spawnArgs, {
@@ -106768,26 +106786,29 @@ async function runWithGrid(sessionPath, models, input, opts) {
106768
106786
  proc.on("exit", () => resolve4());
106769
106787
  proc.on("error", () => resolve4());
106770
106788
  });
106771
- clearInterval(pollInterval);
106772
- pollStatus(pollState);
106773
- return JSON.parse(readFileSync23(statusPath, "utf-8"));
106789
+ finalizeStatus(statusPath, sessionPath, anonIds);
106790
+ return JSON.parse(readFileSync24(statusPath, "utf-8"));
106774
106791
  }
106775
106792
  var init_team_grid = __esm(() => {
106776
106793
  init_team_orchestrator();
106794
+ init_model_parser();
106795
+ init_routing_rules();
106796
+ init_auto_route();
106797
+ init_profile_config();
106777
106798
  });
106778
106799
 
106779
106800
  // src/index.ts
106780
106801
  var import_dotenv3 = __toESM(require_main(), 1);
106781
- import { existsSync as existsSync29, readFileSync as readFileSync24 } from "fs";
106782
- import { homedir as homedir27 } from "os";
106783
- import { join as join30 } from "path";
106802
+ import { existsSync as existsSync30, readFileSync as readFileSync25 } from "fs";
106803
+ import { homedir as homedir28 } from "os";
106804
+ import { join as join31 } from "path";
106784
106805
  import_dotenv3.config({ quiet: true });
106785
106806
  function loadStoredApiKeys() {
106786
106807
  try {
106787
- const configPath = join30(homedir27(), ".claudish", "config.json");
106788
- if (!existsSync29(configPath))
106808
+ const configPath = join31(homedir28(), ".claudish", "config.json");
106809
+ if (!existsSync30(configPath))
106789
106810
  return;
106790
- const raw2 = readFileSync24(configPath, "utf-8");
106811
+ const raw2 = readFileSync25(configPath, "utf-8");
106791
106812
  const cfg = JSON.parse(raw2);
106792
106813
  if (cfg.apiKeys) {
106793
106814
  for (const [envVar, value] of Object.entries(cfg.apiKeys)) {
@@ -106901,14 +106922,14 @@ async function runCli() {
106901
106922
  if (cliConfig.team && cliConfig.team.length > 0) {
106902
106923
  let prompt = cliConfig.claudeArgs.join(" ");
106903
106924
  if (cliConfig.inputFile) {
106904
- prompt = readFileSync24(cliConfig.inputFile, "utf-8");
106925
+ prompt = readFileSync25(cliConfig.inputFile, "utf-8");
106905
106926
  }
106906
106927
  if (!prompt.trim()) {
106907
106928
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
106908
106929
  process.exit(1);
106909
106930
  }
106910
106931
  const mode = cliConfig.teamMode ?? "default";
106911
- const sessionPath = join30(process.cwd(), `.claudish-team-${Date.now()}`);
106932
+ const sessionPath = join31(process.cwd(), `.claudish-team-${Date.now()}`);
106912
106933
  if (mode === "json") {
106913
106934
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
106914
106935
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -106918,9 +106939,9 @@ async function runCli() {
106918
106939
  });
106919
106940
  const result = { ...status2, responses: {} };
106920
106941
  for (const anonId of Object.keys(status2.models)) {
106921
- const responsePath = join30(sessionPath, `response-${anonId}.md`);
106942
+ const responsePath = join31(sessionPath, `response-${anonId}.md`);
106922
106943
  try {
106923
- const raw2 = readFileSync24(responsePath, "utf-8").trim();
106944
+ const raw2 = readFileSync25(responsePath, "utf-8").trim();
106924
106945
  try {
106925
106946
  result.responses[anonId] = JSON.parse(raw2);
106926
106947
  } catch {