claudish 6.0.1 → 6.1.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
@@ -28505,14 +28505,7 @@ async function runModels(sessionPath, opts = {}) {
28505
28505
  const outputPath = join(sessionPath, `response-${anonId}.md`);
28506
28506
  const errorLogPath = join(sessionPath, "errors", `${anonId}.log`);
28507
28507
  const workDir = join(sessionPath, "work", anonId);
28508
- const args = [
28509
- "--model",
28510
- entry.model,
28511
- "-y",
28512
- "--stdin",
28513
- "--quiet",
28514
- ...opts.claudeFlags ?? []
28515
- ];
28508
+ const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
28516
28509
  updateModelStatus(anonId, {
28517
28510
  state: "RUNNING",
28518
28511
  startedAt: new Date().toISOString()
@@ -29243,31 +29236,52 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
29243
29236
  signal: AbortSignal.timeout(5000)
29244
29237
  });
29245
29238
  if (response.ok) {
29246
- return { content: [{ type: "text", text: `Error report sent successfully.
29239
+ return {
29240
+ content: [
29241
+ {
29242
+ type: "text",
29243
+ text: `Error report sent successfully.
29247
29244
 
29248
29245
  **Sanitized data sent:**
29249
29246
  \`\`\`json
29250
29247
  ${reportSummary}
29251
- \`\`\`${autoSendHint}` }] };
29248
+ \`\`\`${autoSendHint}`
29249
+ }
29250
+ ]
29251
+ };
29252
29252
  } else {
29253
- return { content: [{ type: "text", text: `Error report endpoint returned ${response.status}. Report was NOT sent.
29253
+ return {
29254
+ content: [
29255
+ {
29256
+ type: "text",
29257
+ text: `Error report endpoint returned ${response.status}. Report was NOT sent.
29254
29258
 
29255
29259
  **Data that would have been sent (all sanitized):**
29256
29260
  \`\`\`json
29257
29261
  ${reportSummary}
29258
29262
  \`\`\`
29259
29263
 
29260
- You can manually report this at https://github.com/anthropics/claudish/issues${autoSendHint}` }] };
29264
+ You can manually report this at https://github.com/anthropics/claudish/issues${autoSendHint}`
29265
+ }
29266
+ ]
29267
+ };
29261
29268
  }
29262
29269
  } catch (err) {
29263
- return { content: [{ type: "text", text: `Could not reach error reporting endpoint (${err instanceof Error ? err.message : "network error"}).
29270
+ return {
29271
+ content: [
29272
+ {
29273
+ type: "text",
29274
+ text: `Could not reach error reporting endpoint (${err instanceof Error ? err.message : "network error"}).
29264
29275
 
29265
29276
  **Sanitized error data (for manual reporting):**
29266
29277
  \`\`\`json
29267
29278
  ${reportSummary}
29268
29279
  \`\`\`
29269
29280
 
29270
- Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}` }] };
29281
+ Report manually at https://github.com/anthropics/claudish/issues${autoSendHint}`
29282
+ }
29283
+ ]
29284
+ };
29271
29285
  }
29272
29286
  });
29273
29287
  }
@@ -30641,6 +30655,36 @@ function fuzzyScore2(text, query) {
30641
30655
  }
30642
30656
 
30643
30657
  // src/profile-config.ts
30658
+ var exports_profile_config = {};
30659
+ __export(exports_profile_config, {
30660
+ setProfile: () => setProfile,
30661
+ setEndpoint: () => setEndpoint,
30662
+ setDefaultProfile: () => setDefaultProfile,
30663
+ setApiKey: () => setApiKey,
30664
+ saveLocalConfig: () => saveLocalConfig,
30665
+ saveConfig: () => saveConfig,
30666
+ removeEndpoint: () => removeEndpoint,
30667
+ removeApiKey: () => removeApiKey,
30668
+ localConfigExists: () => localConfigExists,
30669
+ loadLocalConfig: () => loadLocalConfig,
30670
+ loadConfig: () => loadConfig,
30671
+ listProfiles: () => listProfiles,
30672
+ listAllProfiles: () => listAllProfiles,
30673
+ isProjectDirectory: () => isProjectDirectory,
30674
+ getProfileNames: () => getProfileNames,
30675
+ getProfile: () => getProfile,
30676
+ getModelMapping: () => getModelMapping,
30677
+ getLocalConfigPath: () => getLocalConfigPath,
30678
+ getEndpoint: () => getEndpoint,
30679
+ getDefaultProfile: () => getDefaultProfile,
30680
+ getConfigPathForScope: () => getConfigPathForScope,
30681
+ getConfigPath: () => getConfigPath,
30682
+ getApiKey: () => getApiKey,
30683
+ deleteProfile: () => deleteProfile,
30684
+ createProfile: () => createProfile,
30685
+ configExistsForScope: () => configExistsForScope,
30686
+ configExists: () => configExists
30687
+ });
30644
30688
  import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
30645
30689
  import { homedir as homedir6 } from "os";
30646
30690
  import { join as join7 } from "path";
@@ -30877,6 +30921,13 @@ function createProfile(name, models, description, scope = "global") {
30877
30921
  setProfile(profile, scope);
30878
30922
  return profile;
30879
30923
  }
30924
+ function listProfiles() {
30925
+ const config3 = loadConfig();
30926
+ return Object.values(config3.profiles).map((profile) => ({
30927
+ ...profile,
30928
+ isDefault: profile.name === config3.defaultProfile
30929
+ }));
30930
+ }
30880
30931
  function listAllProfiles() {
30881
30932
  const globalConfig2 = loadConfig();
30882
30933
  const localConfig = loadLocalConfig();
@@ -30901,6 +30952,10 @@ function listAllProfiles() {
30901
30952
  }
30902
30953
  return result;
30903
30954
  }
30955
+ function getApiKey(envVar) {
30956
+ const config3 = loadConfig();
30957
+ return config3.apiKeys?.[envVar];
30958
+ }
30904
30959
  function setApiKey(envVar, value) {
30905
30960
  const config3 = loadConfig();
30906
30961
  if (!config3.apiKeys)
@@ -30915,6 +30970,10 @@ function removeApiKey(envVar) {
30915
30970
  saveConfig(config3);
30916
30971
  }
30917
30972
  }
30973
+ function getEndpoint(name) {
30974
+ const config3 = loadConfig();
30975
+ return config3.endpoints?.[name];
30976
+ }
30918
30977
  function setEndpoint(name, value) {
30919
30978
  const config3 = loadConfig();
30920
30979
  if (!config3.endpoints)
@@ -30949,6 +31008,9 @@ var init_profile_config = __esm(() => {
30949
31008
  });
30950
31009
 
30951
31010
  // src/providers/provider-definitions.ts
31011
+ import { existsSync as existsSync8 } from "fs";
31012
+ import { join as join8 } from "path";
31013
+ import { homedir as homedir7 } from "os";
30952
31014
  function ensureProviderByNameCache() {
30953
31015
  if (!_providerByNameCache) {
30954
31016
  _providerByNameCache = new Map;
@@ -31071,6 +31133,29 @@ function getApiKeyEnvVars(providerName) {
31071
31133
  aliases: def.apiKeyAliases
31072
31134
  };
31073
31135
  }
31136
+ function isProviderAvailable(def) {
31137
+ if (def.isLocal)
31138
+ return true;
31139
+ if (def.publicKeyFallback)
31140
+ return true;
31141
+ if (!def.apiKeyEnvVar)
31142
+ return true;
31143
+ if (process.env[def.apiKeyEnvVar])
31144
+ return true;
31145
+ if (def.apiKeyAliases) {
31146
+ for (const alias of def.apiKeyAliases) {
31147
+ if (process.env[alias])
31148
+ return true;
31149
+ }
31150
+ }
31151
+ if (def.oauthFallback) {
31152
+ try {
31153
+ if (existsSync8(join8(homedir7(), ".claudish", def.oauthFallback)))
31154
+ return true;
31155
+ } catch {}
31156
+ }
31157
+ return false;
31158
+ }
31074
31159
  var BUILTIN_PROVIDERS, _shortcutsCache = null, _legacyPrefixCache = null, _nativeModelPatternsCache = null, _providerByNameCache = null, _localProvidersCache = null;
31075
31160
  var init_provider_definitions = __esm(() => {
31076
31161
  BUILTIN_PROVIDERS = [
@@ -31091,7 +31176,8 @@ var init_provider_definitions = __esm(() => {
31091
31176
  { prefix: "gemini/", stripPrefix: true }
31092
31177
  ],
31093
31178
  nativeModelPatterns: [{ pattern: /^google\//i }, { pattern: /^gemini-/i }],
31094
- isDirectApi: true
31179
+ isDirectApi: true,
31180
+ description: "Direct Gemini API (g@, google@)"
31095
31181
  },
31096
31182
  {
31097
31183
  name: "gemini-codeassist",
@@ -31105,7 +31191,8 @@ var init_provider_definitions = __esm(() => {
31105
31191
  shortcuts: ["go"],
31106
31192
  shortestPrefix: "go",
31107
31193
  legacyPrefixes: [{ prefix: "go/", stripPrefix: true }],
31108
- isDirectApi: true
31194
+ isDirectApi: true,
31195
+ description: "Gemini Code Assist OAuth (go@)"
31109
31196
  },
31110
31197
  {
31111
31198
  name: "openai",
@@ -31128,7 +31215,8 @@ var init_provider_definitions = __esm(() => {
31128
31215
  { pattern: /^o3(-|$)/i },
31129
31216
  { pattern: /^chatgpt-/i }
31130
31217
  ],
31131
- isDirectApi: true
31218
+ isDirectApi: true,
31219
+ description: "Direct OpenAI API (oai@)"
31132
31220
  },
31133
31221
  {
31134
31222
  name: "openrouter",
@@ -31147,6 +31235,26 @@ var init_provider_definitions = __esm(() => {
31147
31235
  "HTTP-Referer": "https://claudish.com",
31148
31236
  "X-Title": "Claudish - OpenRouter Proxy"
31149
31237
  },
31238
+ isDirectApi: true,
31239
+ description: "580+ models, default backend (or@)"
31240
+ },
31241
+ {
31242
+ name: "xai",
31243
+ displayName: "xAI",
31244
+ transport: "openai",
31245
+ tokenStrategy: "delta-aware",
31246
+ baseUrl: "https://api.x.ai",
31247
+ apiPath: "/v1/chat/completions",
31248
+ apiKeyEnvVar: "XAI_API_KEY",
31249
+ apiKeyDescription: "xAI API Key",
31250
+ apiKeyUrl: "https://console.x.ai/",
31251
+ shortcuts: ["xai", "grok"],
31252
+ shortestPrefix: "xai",
31253
+ legacyPrefixes: [{ prefix: "xai/", stripPrefix: true }],
31254
+ nativeModelPatterns: [
31255
+ { pattern: /^x-ai\//i },
31256
+ { pattern: /^grok-/i }
31257
+ ],
31150
31258
  isDirectApi: true
31151
31259
  },
31152
31260
  {
@@ -31171,7 +31279,8 @@ var init_provider_definitions = __esm(() => {
31171
31279
  { pattern: /^minimax-/i },
31172
31280
  { pattern: /^abab-/i }
31173
31281
  ],
31174
- isDirectApi: true
31282
+ isDirectApi: true,
31283
+ description: "MiniMax API (mm@, mmax@)"
31175
31284
  },
31176
31285
  {
31177
31286
  name: "minimax-coding",
@@ -31187,7 +31296,8 @@ var init_provider_definitions = __esm(() => {
31187
31296
  shortcuts: ["mmc"],
31188
31297
  shortestPrefix: "mmc",
31189
31298
  legacyPrefixes: [{ prefix: "mmc/", stripPrefix: true }],
31190
- isDirectApi: true
31299
+ isDirectApi: true,
31300
+ description: "MiniMax Coding Plan (mmc@)"
31191
31301
  },
31192
31302
  {
31193
31303
  name: "kimi-coding",
@@ -31203,7 +31313,8 @@ var init_provider_definitions = __esm(() => {
31203
31313
  shortestPrefix: "kc",
31204
31314
  legacyPrefixes: [{ prefix: "kc/", stripPrefix: true }],
31205
31315
  nativeModelPatterns: [{ pattern: /^kimi-for-coding$/i }],
31206
- isDirectApi: true
31316
+ isDirectApi: true,
31317
+ description: "Kimi Coding Plan (kc@)"
31207
31318
  },
31208
31319
  {
31209
31320
  name: "kimi",
@@ -31227,7 +31338,8 @@ var init_provider_definitions = __esm(() => {
31227
31338
  { pattern: /^moonshot-/i },
31228
31339
  { pattern: /^kimi-/i }
31229
31340
  ],
31230
- isDirectApi: true
31341
+ isDirectApi: true,
31342
+ description: "Kimi API (kimi@, moon@)"
31231
31343
  },
31232
31344
  {
31233
31345
  name: "glm",
@@ -31252,7 +31364,8 @@ var init_provider_definitions = __esm(() => {
31252
31364
  { pattern: /^glm-/i },
31253
31365
  { pattern: /^chatglm-/i }
31254
31366
  ],
31255
- isDirectApi: true
31367
+ isDirectApi: true,
31368
+ description: "GLM API (glm@, zhipu@)"
31256
31369
  },
31257
31370
  {
31258
31371
  name: "glm-coding",
@@ -31268,7 +31381,8 @@ var init_provider_definitions = __esm(() => {
31268
31381
  shortcuts: ["gc"],
31269
31382
  shortestPrefix: "gc",
31270
31383
  legacyPrefixes: [{ prefix: "gc/", stripPrefix: true }],
31271
- isDirectApi: true
31384
+ isDirectApi: true,
31385
+ description: "GLM Coding Plan (gc@)"
31272
31386
  },
31273
31387
  {
31274
31388
  name: "zai",
@@ -31284,7 +31398,8 @@ var init_provider_definitions = __esm(() => {
31284
31398
  shortestPrefix: "zai",
31285
31399
  legacyPrefixes: [{ prefix: "zai/", stripPrefix: true }],
31286
31400
  nativeModelPatterns: [{ pattern: /^z-ai\//i }, { pattern: /^zai\//i }],
31287
- isDirectApi: true
31401
+ isDirectApi: true,
31402
+ description: "Z.AI API (zai@)"
31288
31403
  },
31289
31404
  {
31290
31405
  name: "ollamacloud",
@@ -31306,7 +31421,8 @@ var init_provider_definitions = __esm(() => {
31306
31421
  { pattern: /^llama-/i },
31307
31422
  { pattern: /^llama3/i }
31308
31423
  ],
31309
- isDirectApi: true
31424
+ isDirectApi: true,
31425
+ description: "Cloud Ollama (oc@, llama@)"
31310
31426
  },
31311
31427
  {
31312
31428
  name: "opencode-zen",
@@ -31323,7 +31439,8 @@ var init_provider_definitions = __esm(() => {
31323
31439
  shortcuts: ["zen"],
31324
31440
  shortestPrefix: "zen",
31325
31441
  legacyPrefixes: [{ prefix: "zen/", stripPrefix: true }],
31326
- isDirectApi: true
31442
+ isDirectApi: true,
31443
+ description: "OpenCode Zen (zen@) - free models"
31327
31444
  },
31328
31445
  {
31329
31446
  name: "opencode-zen-go",
@@ -31342,7 +31459,8 @@ var init_provider_definitions = __esm(() => {
31342
31459
  { prefix: "zengo/", stripPrefix: true },
31343
31460
  { prefix: "zgo/", stripPrefix: true }
31344
31461
  ],
31345
- isDirectApi: true
31462
+ isDirectApi: true,
31463
+ description: "OpenCode Zen Go plan (zengo@)"
31346
31464
  },
31347
31465
  {
31348
31466
  name: "vertex",
@@ -31360,7 +31478,8 @@ var init_provider_definitions = __esm(() => {
31360
31478
  { prefix: "v/", stripPrefix: true },
31361
31479
  { prefix: "vertex/", stripPrefix: true }
31362
31480
  ],
31363
- isDirectApi: true
31481
+ isDirectApi: true,
31482
+ description: "Vertex AI Express (v@, vertex@)"
31364
31483
  },
31365
31484
  {
31366
31485
  name: "litellm",
@@ -31378,7 +31497,8 @@ var init_provider_definitions = __esm(() => {
31378
31497
  { prefix: "litellm/", stripPrefix: true },
31379
31498
  { prefix: "ll/", stripPrefix: true }
31380
31499
  ],
31381
- isDirectApi: true
31500
+ isDirectApi: true,
31501
+ description: "LiteLLM proxy (ll@, litellm@)"
31382
31502
  },
31383
31503
  {
31384
31504
  name: "poe",
@@ -31393,7 +31513,8 @@ var init_provider_definitions = __esm(() => {
31393
31513
  shortestPrefix: "poe",
31394
31514
  legacyPrefixes: [],
31395
31515
  nativeModelPatterns: [{ pattern: /^poe:/i }],
31396
- isDirectApi: true
31516
+ isDirectApi: true,
31517
+ description: "Poe API (poe@)"
31397
31518
  },
31398
31519
  {
31399
31520
  name: "ollama",
@@ -31410,7 +31531,8 @@ var init_provider_definitions = __esm(() => {
31410
31531
  { prefix: "ollama/", stripPrefix: true },
31411
31532
  { prefix: "ollama:", stripPrefix: true }
31412
31533
  ],
31413
- isLocal: true
31534
+ isLocal: true,
31535
+ description: "Local Ollama (ollama@)"
31414
31536
  },
31415
31537
  {
31416
31538
  name: "lmstudio",
@@ -31429,7 +31551,8 @@ var init_provider_definitions = __esm(() => {
31429
31551
  { prefix: "mlstudio/", stripPrefix: true },
31430
31552
  { prefix: "mlstudio:", stripPrefix: true }
31431
31553
  ],
31432
- isLocal: true
31554
+ isLocal: true,
31555
+ description: "Local LM Studio (lms@)"
31433
31556
  },
31434
31557
  {
31435
31558
  name: "vllm",
@@ -31446,7 +31569,8 @@ var init_provider_definitions = __esm(() => {
31446
31569
  { prefix: "vllm/", stripPrefix: true },
31447
31570
  { prefix: "vllm:", stripPrefix: true }
31448
31571
  ],
31449
- isLocal: true
31572
+ isLocal: true,
31573
+ description: "Local vLLM (vllm@)"
31450
31574
  },
31451
31575
  {
31452
31576
  name: "mlx",
@@ -31463,7 +31587,8 @@ var init_provider_definitions = __esm(() => {
31463
31587
  { prefix: "mlx/", stripPrefix: true },
31464
31588
  { prefix: "mlx:", stripPrefix: true }
31465
31589
  ],
31466
- isLocal: true
31590
+ isLocal: true,
31591
+ description: "Local MLX (mlx@)"
31467
31592
  },
31468
31593
  {
31469
31594
  name: "qwen",
@@ -31477,7 +31602,8 @@ var init_provider_definitions = __esm(() => {
31477
31602
  shortcuts: [],
31478
31603
  shortestPrefix: "qwen",
31479
31604
  legacyPrefixes: [],
31480
- nativeModelPatterns: [{ pattern: /^qwen/i }]
31605
+ nativeModelPatterns: [{ pattern: /^qwen/i }],
31606
+ description: "Qwen (auto-routed via OpenRouter)"
31481
31607
  },
31482
31608
  {
31483
31609
  name: "native-anthropic",
@@ -31491,7 +31617,8 @@ var init_provider_definitions = __esm(() => {
31491
31617
  shortcuts: [],
31492
31618
  shortestPrefix: "",
31493
31619
  legacyPrefixes: [],
31494
- nativeModelPatterns: [{ pattern: /^anthropic\//i }, { pattern: /^claude-/i }]
31620
+ nativeModelPatterns: [{ pattern: /^anthropic\//i }, { pattern: /^claude-/i }],
31621
+ description: "Native Claude Code auth"
31495
31622
  }
31496
31623
  ];
31497
31624
  });
@@ -31606,12 +31733,12 @@ var init_model_parser = __esm(() => {
31606
31733
  });
31607
31734
 
31608
31735
  // src/auth/oauth-registry.ts
31609
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
31610
- import { join as join8 } from "path";
31611
- import { homedir as homedir7 } from "os";
31736
+ import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
31737
+ import { join as join9 } from "path";
31738
+ import { homedir as homedir8 } from "os";
31612
31739
  function hasValidOAuthCredentials(descriptor) {
31613
- const credPath = join8(homedir7(), ".claudish", descriptor.credentialFile);
31614
- if (!existsSync8(credPath))
31740
+ const credPath = join9(homedir8(), ".claudish", descriptor.credentialFile);
31741
+ if (!existsSync9(credPath))
31615
31742
  return false;
31616
31743
  if (descriptor.validationMode === "file-exists") {
31617
31744
  return true;
@@ -31697,9 +31824,9 @@ var init_static_fallback = __esm(() => {
31697
31824
  });
31698
31825
 
31699
31826
  // src/providers/catalog-resolvers/openrouter.ts
31700
- import { readFileSync as readFileSync8, existsSync as existsSync9 } from "fs";
31701
- import { join as join9 } from "path";
31702
- import { homedir as homedir8 } from "os";
31827
+ import { readFileSync as readFileSync8, existsSync as existsSync10 } from "fs";
31828
+ import { join as join10 } from "path";
31829
+ import { homedir as homedir9 } from "os";
31703
31830
 
31704
31831
  class OpenRouterCatalogResolver {
31705
31832
  provider = "openrouter";
@@ -31744,8 +31871,8 @@ class OpenRouterCatalogResolver {
31744
31871
  _getModels() {
31745
31872
  if (_memCache)
31746
31873
  return _memCache;
31747
- const diskPath = join9(homedir8(), ".claudish", "all-models.json");
31748
- if (existsSync9(diskPath)) {
31874
+ const diskPath = join10(homedir9(), ".claudish", "all-models.json");
31875
+ if (existsSync10(diskPath)) {
31749
31876
  try {
31750
31877
  const data = JSON.parse(readFileSync8(diskPath, "utf-8"));
31751
31878
  if (Array.isArray(data.models) && data.models.length > 0) {
@@ -31764,16 +31891,16 @@ var init_openrouter = __esm(() => {
31764
31891
  });
31765
31892
 
31766
31893
  // src/providers/catalog-resolvers/litellm.ts
31767
- import { readFileSync as readFileSync9, existsSync as existsSync10 } from "fs";
31768
- import { join as join10 } from "path";
31769
- import { homedir as homedir9 } from "os";
31894
+ import { readFileSync as readFileSync9, existsSync as existsSync11 } from "fs";
31895
+ import { join as join11 } from "path";
31896
+ import { homedir as homedir10 } from "os";
31770
31897
  import { createHash as createHash3 } from "crypto";
31771
31898
  function getCachePath() {
31772
31899
  const baseUrl = process.env.LITELLM_BASE_URL;
31773
31900
  if (!baseUrl)
31774
31901
  return null;
31775
31902
  const hash2 = createHash3("sha256").update(baseUrl).digest("hex").substring(0, 16);
31776
- return join10(homedir9(), ".claudish", `litellm-models-${hash2}.json`);
31903
+ return join11(homedir10(), ".claudish", `litellm-models-${hash2}.json`);
31777
31904
  }
31778
31905
 
31779
31906
  class LiteLLMCatalogResolver {
@@ -31801,7 +31928,7 @@ class LiteLLMCatalogResolver {
31801
31928
  }
31802
31929
  async warmCache() {
31803
31930
  const path = getCachePath();
31804
- if (!path || !existsSync10(path))
31931
+ if (!path || !existsSync11(path))
31805
31932
  return;
31806
31933
  try {
31807
31934
  const data = JSON.parse(readFileSync9(path, "utf-8"));
@@ -31817,7 +31944,7 @@ class LiteLLMCatalogResolver {
31817
31944
  if (_memCache2)
31818
31945
  return _memCache2;
31819
31946
  const path = getCachePath();
31820
- if (!path || !existsSync10(path))
31947
+ if (!path || !existsSync11(path))
31821
31948
  return null;
31822
31949
  try {
31823
31950
  const data = JSON.parse(readFileSync9(path, "utf-8"));
@@ -31879,14 +32006,14 @@ var init_model_catalog_resolver = __esm(() => {
31879
32006
  });
31880
32007
 
31881
32008
  // src/providers/auto-route.ts
31882
- import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
31883
- import { join as join11 } from "path";
31884
- import { homedir as homedir10 } from "os";
32009
+ import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
32010
+ import { join as join12 } from "path";
32011
+ import { homedir as homedir11 } from "os";
31885
32012
  import { createHash as createHash4 } from "crypto";
31886
32013
  function readLiteLLMCacheSync(baseUrl) {
31887
32014
  const hash2 = createHash4("sha256").update(baseUrl).digest("hex").substring(0, 16);
31888
- const cachePath = join11(homedir10(), ".claudish", `litellm-models-${hash2}.json`);
31889
- if (!existsSync11(cachePath))
32015
+ const cachePath = join12(homedir11(), ".claudish", `litellm-models-${hash2}.json`);
32016
+ if (!existsSync12(cachePath))
31890
32017
  return null;
31891
32018
  try {
31892
32019
  const data = JSON.parse(readFileSync10(cachePath, "utf-8"));
@@ -31999,9 +32126,27 @@ function autoRoute(modelName, nativeProvider) {
31999
32126
  }
32000
32127
  return null;
32001
32128
  }
32002
- function readZenModelCacheSync() {
32003
- const cachePath = join11(homedir10(), ".claudish", "zen-models.json");
32004
- if (!existsSync11(cachePath))
32129
+ async function warmZenModelCache() {
32130
+ const apiKey = process.env.OPENCODE_API_KEY || "public";
32131
+ const baseUrl = process.env.OPENCODE_BASE_URL || "https://opencode.ai/zen";
32132
+ const resp = await fetch(`${baseUrl}/v1/models`, {
32133
+ headers: { Authorization: `Bearer ${apiKey}` },
32134
+ signal: AbortSignal.timeout(5000)
32135
+ });
32136
+ if (!resp.ok)
32137
+ return;
32138
+ const data = await resp.json();
32139
+ const models = (data.data ?? []).map((m) => ({ id: m.id }));
32140
+ if (models.length === 0)
32141
+ return;
32142
+ const cacheDir = join12(homedir11(), ".claudish");
32143
+ const { mkdirSync: mkdirSync6, writeFileSync: writeSync3 } = await import("fs");
32144
+ mkdirSync6(cacheDir, { recursive: true });
32145
+ writeSync3(join12(cacheDir, "zen-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
32146
+ }
32147
+ function readZenGoModelCacheSync() {
32148
+ const cachePath = join12(homedir11(), ".claudish", "zen-go-models.json");
32149
+ if (!existsSync12(cachePath))
32005
32150
  return null;
32006
32151
  try {
32007
32152
  const data = JSON.parse(readFileSync10(cachePath, "utf-8"));
@@ -32012,16 +32157,16 @@ function readZenModelCacheSync() {
32012
32157
  return null;
32013
32158
  }
32014
32159
  }
32015
- function isZenCompatibleModel(modelName) {
32016
- const zenModels = readZenModelCacheSync();
32017
- if (!zenModels)
32160
+ function isZenGoCompatibleModel(modelName) {
32161
+ const zenGoModels = readZenGoModelCacheSync();
32162
+ if (!zenGoModels)
32018
32163
  return false;
32019
- return zenModels.has(modelName);
32164
+ return zenGoModels.has(modelName);
32020
32165
  }
32021
- async function warmZenModelCache() {
32166
+ async function warmZenGoModelCache() {
32022
32167
  const apiKey = process.env.OPENCODE_API_KEY || "public";
32023
32168
  const baseUrl = process.env.OPENCODE_BASE_URL || "https://opencode.ai/zen";
32024
- const resp = await fetch(`${baseUrl}/v1/models`, {
32169
+ const resp = await fetch(`${baseUrl}/go/v1/models`, {
32025
32170
  headers: { Authorization: `Bearer ${apiKey}` },
32026
32171
  signal: AbortSignal.timeout(5000)
32027
32172
  });
@@ -32031,10 +32176,10 @@ async function warmZenModelCache() {
32031
32176
  const models = (data.data ?? []).map((m) => ({ id: m.id }));
32032
32177
  if (models.length === 0)
32033
32178
  return;
32034
- const cacheDir = join11(homedir10(), ".claudish");
32179
+ const cacheDir = join12(homedir11(), ".claudish");
32035
32180
  const { mkdirSync: mkdirSync6, writeFileSync: writeSync3 } = await import("fs");
32036
32181
  mkdirSync6(cacheDir, { recursive: true });
32037
- writeSync3(join11(cacheDir, "zen-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
32182
+ writeSync3(join12(cacheDir, "zen-go-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
32038
32183
  }
32039
32184
  function hasProviderCredentials(provider) {
32040
32185
  const keyInfo = getApiKeyEnvVars(provider);
@@ -32054,7 +32199,7 @@ function getFallbackChain(modelName, nativeProvider) {
32054
32199
  displayName: "LiteLLM"
32055
32200
  });
32056
32201
  }
32057
- if (process.env.OPENCODE_API_KEY && isZenCompatibleModel(modelName)) {
32202
+ if (process.env.OPENCODE_API_KEY && isZenGoCompatibleModel(modelName)) {
32058
32203
  routes.push({
32059
32204
  provider: "opencode-zen-go",
32060
32205
  modelSpec: `zengo@${modelName}`,
@@ -32263,9 +32408,9 @@ var init_routing_rules = __esm(() => {
32263
32408
  });
32264
32409
 
32265
32410
  // src/providers/api-key-provenance.ts
32266
- import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
32267
- import { join as join12, resolve as resolve2 } from "path";
32268
- import { homedir as homedir11 } from "os";
32411
+ import { existsSync as existsSync13, readFileSync as readFileSync11 } from "fs";
32412
+ import { join as join13, resolve as resolve2 } from "path";
32413
+ import { homedir as homedir12 } from "os";
32269
32414
  function maskKey(key) {
32270
32415
  if (!key)
32271
32416
  return null;
@@ -32350,7 +32495,7 @@ function formatProvenanceProbe(p, indent = " ") {
32350
32495
  function readDotenvKey(envVars) {
32351
32496
  try {
32352
32497
  const dotenvPath = resolve2(".env");
32353
- if (!existsSync12(dotenvPath))
32498
+ if (!existsSync13(dotenvPath))
32354
32499
  return null;
32355
32500
  const parsed = import_dotenv2.parse(readFileSync11(dotenvPath, "utf-8"));
32356
32501
  for (const v of envVars) {
@@ -32364,8 +32509,8 @@ function readDotenvKey(envVars) {
32364
32509
  }
32365
32510
  function readConfigKey(envVar) {
32366
32511
  try {
32367
- const configPath = join12(homedir11(), ".claudish", "config.json");
32368
- if (!existsSync12(configPath))
32512
+ const configPath = join13(homedir12(), ".claudish", "config.json");
32513
+ if (!existsSync13(configPath))
32369
32514
  return null;
32370
32515
  const cfg = JSON.parse(readFileSync11(configPath, "utf-8"));
32371
32516
  return cfg.apiKeys?.[envVar] || null;
@@ -32579,9 +32724,9 @@ __export(exports_provider_resolver, {
32579
32724
  getMissingKeyResolutions: () => getMissingKeyResolutions,
32580
32725
  getMissingKeyError: () => getMissingKeyError
32581
32726
  });
32582
- import { existsSync as existsSync13 } from "fs";
32583
- import { join as join13 } from "path";
32584
- import { homedir as homedir12 } from "os";
32727
+ import { existsSync as existsSync14 } from "fs";
32728
+ import { join as join14 } from "path";
32729
+ import { homedir as homedir13 } from "os";
32585
32730
  function getApiKeyInfoForProvider(providerName) {
32586
32731
  const lookupName = providerName === "gemini" ? "google" : providerName;
32587
32732
  const info = getApiKeyInfo(lookupName);
@@ -32616,8 +32761,8 @@ function isApiKeyAvailable(info) {
32616
32761
  }
32617
32762
  if (info.oauthFallback) {
32618
32763
  try {
32619
- const credPath = join13(homedir12(), ".claudish", info.oauthFallback);
32620
- if (existsSync13(credPath)) {
32764
+ const credPath = join14(homedir13(), ".claudish", info.oauthFallback);
32765
+ if (existsSync14(credPath)) {
32621
32766
  return true;
32622
32767
  }
32623
32768
  } catch {}
@@ -33079,12 +33224,14 @@ function processAssistantMessage(msg, messages, simpleFormat = false) {
33079
33224
  const toolCalls = [];
33080
33225
  const seen = new Set;
33081
33226
  let reasoningContent = "";
33227
+ let hasThinking = false;
33082
33228
  for (const block of msg.content) {
33083
33229
  if (block.type === "text") {
33084
33230
  strings.push(block.text);
33085
33231
  } else if (block.type === "thinking") {
33086
- if (!simpleFormat && block.thinking) {
33087
- reasoningContent += block.thinking;
33232
+ if (!simpleFormat) {
33233
+ hasThinking = true;
33234
+ reasoningContent += block.thinking || "";
33088
33235
  }
33089
33236
  } else if (block.type === "tool_use") {
33090
33237
  if (seen.has(block.id))
@@ -33114,7 +33261,7 @@ function processAssistantMessage(msg, messages, simpleFormat = false) {
33114
33261
  m.content = null;
33115
33262
  if (toolCalls.length)
33116
33263
  m.tool_calls = toolCalls;
33117
- if (reasoningContent)
33264
+ if (hasThinking)
33118
33265
  m.reasoning_content = reasoningContent;
33119
33266
  if (m.content !== undefined || m.tool_calls)
33120
33267
  messages.push(m);
@@ -33200,13 +33347,34 @@ function transformOpenAIToClaude(claudeRequestInput) {
33200
33347
  var init_transform = () => {};
33201
33348
 
33202
33349
  // src/handlers/shared/format/openai-tools.ts
33350
+ function sanitizeSchemaForOpenAI(schema) {
33351
+ if (!schema || typeof schema !== "object") {
33352
+ return removeUriFormat(schema);
33353
+ }
33354
+ let root = { ...schema };
33355
+ const combinerKey = ["oneOf", "anyOf", "allOf"].find((k) => Array.isArray(root[k]) && root[k].length > 0);
33356
+ if (combinerKey) {
33357
+ const branches = root[combinerKey];
33358
+ const objectBranch = branches.find((b) => b && typeof b === "object" && b.type === "object");
33359
+ if (objectBranch) {
33360
+ const { [combinerKey]: _dropped, ...rest } = root;
33361
+ root = { ...rest, ...objectBranch };
33362
+ } else {
33363
+ root = { type: "object", properties: {}, additionalProperties: true };
33364
+ }
33365
+ }
33366
+ const { enum: _enum3, not: _not, ...withoutForbidden } = root;
33367
+ root = withoutForbidden;
33368
+ root.type = "object";
33369
+ return removeUriFormat(root);
33370
+ }
33203
33371
  function convertToolsToOpenAI(req, summarize = false) {
33204
33372
  return req.tools?.map((tool) => ({
33205
33373
  type: "function",
33206
33374
  function: {
33207
33375
  name: tool.name,
33208
33376
  description: summarize ? summarizeToolDescription(tool.name, tool.description) : tool.description,
33209
- parameters: summarize ? summarizeToolParameters(tool.input_schema) : removeUriFormat(tool.input_schema)
33377
+ parameters: summarize ? summarizeToolParameters(tool.input_schema) : sanitizeSchemaForOpenAI(tool.input_schema)
33210
33378
  }
33211
33379
  })) || [];
33212
33380
  }
@@ -33223,7 +33391,7 @@ function summarizeToolDescription(name, description) {
33223
33391
  function summarizeToolParameters(schema) {
33224
33392
  if (!schema)
33225
33393
  return schema;
33226
- const summarized = removeUriFormat({ ...schema });
33394
+ const summarized = sanitizeSchemaForOpenAI({ ...schema });
33227
33395
  if (summarized.properties) {
33228
33396
  for (const [key, prop] of Object.entries(summarized.properties)) {
33229
33397
  const p = prop;
@@ -33364,11 +33532,80 @@ var init_base_api_format = __esm(() => {
33364
33532
  };
33365
33533
  });
33366
33534
 
33535
+ // src/adapters/model-catalog.ts
33536
+ function lookupModel(modelId) {
33537
+ const lower = modelId.toLowerCase();
33538
+ const unprefixed = lower.includes("/") ? lower.substring(lower.lastIndexOf("/") + 1) : lower;
33539
+ for (const entry of MODEL_CATALOG) {
33540
+ if (unprefixed.includes(entry.pattern) || lower.includes(entry.pattern)) {
33541
+ return entry;
33542
+ }
33543
+ }
33544
+ return;
33545
+ }
33546
+ var MODEL_CATALOG;
33547
+ var init_model_catalog = __esm(() => {
33548
+ MODEL_CATALOG = [
33549
+ { pattern: "grok-4.20", contextWindow: 2000000 },
33550
+ { pattern: "grok-4-20", contextWindow: 2000000 },
33551
+ { pattern: "grok-4.1-fast", contextWindow: 2000000 },
33552
+ { pattern: "grok-4-1-fast", contextWindow: 2000000 },
33553
+ { pattern: "grok-4-fast", contextWindow: 2000000 },
33554
+ { pattern: "grok-code-fast", contextWindow: 256000 },
33555
+ { pattern: "grok-4", contextWindow: 256000 },
33556
+ { pattern: "grok-3", contextWindow: 131072 },
33557
+ { pattern: "grok-2", contextWindow: 131072 },
33558
+ { pattern: "grok", contextWindow: 131072 },
33559
+ { pattern: "glm-5-turbo", contextWindow: 202752 },
33560
+ { pattern: "glm-5", contextWindow: 80000, supportsVision: true },
33561
+ { pattern: "glm-4.7-flash", contextWindow: 202752 },
33562
+ { pattern: "glm-4.7", contextWindow: 202752 },
33563
+ { pattern: "glm-4.6v", contextWindow: 131072, supportsVision: true },
33564
+ { pattern: "glm-4.6", contextWindow: 204800 },
33565
+ { pattern: "glm-4.5v", contextWindow: 65536, supportsVision: true },
33566
+ { pattern: "glm-4.5-flash", contextWindow: 131072 },
33567
+ { pattern: "glm-4.5-air", contextWindow: 131072 },
33568
+ { pattern: "glm-4.5", contextWindow: 131072 },
33569
+ { pattern: "glm-4v-plus", contextWindow: 128000, supportsVision: true },
33570
+ { pattern: "glm-4v", contextWindow: 128000, supportsVision: true },
33571
+ { pattern: "glm-4-long", contextWindow: 1e6 },
33572
+ { pattern: "glm-4-plus", contextWindow: 128000 },
33573
+ { pattern: "glm-4-flash", contextWindow: 128000 },
33574
+ { pattern: "glm-4-32b", contextWindow: 128000 },
33575
+ { pattern: "glm-4", contextWindow: 128000 },
33576
+ { pattern: "glm-3-turbo", contextWindow: 128000 },
33577
+ { pattern: "glm-", contextWindow: 131072, supportsVision: false },
33578
+ { pattern: "minimax-01", contextWindow: 1e6, supportsVision: false },
33579
+ { pattern: "minimax-m1", contextWindow: 1e6, supportsVision: false },
33580
+ {
33581
+ pattern: "minimax",
33582
+ contextWindow: 204800,
33583
+ supportsVision: false,
33584
+ temperatureRange: { min: 0.01, max: 1 }
33585
+ },
33586
+ { pattern: "gpt-5.4", contextWindow: 1050000 },
33587
+ { pattern: "gpt-5", contextWindow: 400000 },
33588
+ { pattern: "o1", contextWindow: 200000 },
33589
+ { pattern: "o3", contextWindow: 200000 },
33590
+ { pattern: "o4", contextWindow: 200000 },
33591
+ { pattern: "gpt-4o", contextWindow: 128000 },
33592
+ { pattern: "gpt-4-turbo", contextWindow: 128000 },
33593
+ { pattern: "gpt-3.5", contextWindow: 16385 },
33594
+ { pattern: "kimi-k2.5", contextWindow: 262144 },
33595
+ { pattern: "kimi-k2-5", contextWindow: 262144 },
33596
+ { pattern: "kimi-k2", contextWindow: 131000 },
33597
+ { pattern: "kimi", contextWindow: 131072 },
33598
+ { pattern: "xiaomi", contextWindow: 200000, toolNameLimit: 64 },
33599
+ { pattern: "mimo", contextWindow: 200000, toolNameLimit: 64 }
33600
+ ];
33601
+ });
33602
+
33367
33603
  // src/adapters/grok-model-dialect.ts
33368
33604
  var GrokModelDialect;
33369
33605
  var init_grok_model_dialect = __esm(() => {
33370
33606
  init_base_api_format();
33371
33607
  init_logger();
33608
+ init_model_catalog();
33372
33609
  GrokModelDialect = class GrokModelDialect extends BaseAPIFormat {
33373
33610
  xmlBuffer = "";
33374
33611
  processTextContent(textContent, accumulatedText) {
@@ -33450,22 +33687,7 @@ var init_grok_model_dialect = __esm(() => {
33450
33687
  return "GrokModelDialect";
33451
33688
  }
33452
33689
  getContextWindow() {
33453
- const model = this.modelId.toLowerCase();
33454
- if (model.includes("grok-4.20") || model.includes("grok-4-20"))
33455
- return 2000000;
33456
- if (model.includes("grok-4.1-fast") || model.includes("grok-4-1-fast"))
33457
- return 2000000;
33458
- if (model.includes("grok-4-fast"))
33459
- return 2000000;
33460
- if (model.includes("grok-code-fast"))
33461
- return 256000;
33462
- if (model.includes("grok-4"))
33463
- return 256000;
33464
- if (model.includes("grok-3"))
33465
- return 131072;
33466
- if (model.includes("grok-2"))
33467
- return 131072;
33468
- return 131072;
33690
+ return lookupModel(this.modelId)?.contextWindow ?? 131072;
33469
33691
  }
33470
33692
  reset() {
33471
33693
  this.xmlBuffer = "";
@@ -34876,6 +35098,7 @@ var OpenAIAPIFormat;
34876
35098
  var init_openai_api_format = __esm(() => {
34877
35099
  init_base_api_format();
34878
35100
  init_logger();
35101
+ init_model_catalog();
34879
35102
  OpenAIAPIFormat = class OpenAIAPIFormat extends BaseAPIFormat {
34880
35103
  constructor(modelId) {
34881
35104
  super(modelId);
@@ -34917,18 +35140,7 @@ var init_openai_api_format = __esm(() => {
34917
35140
  return "OpenAIAPIFormat";
34918
35141
  }
34919
35142
  getContextWindow() {
34920
- const model = this.modelId.toLowerCase();
34921
- if (model.includes("gpt-5.4"))
34922
- return 1050000;
34923
- if (model.includes("gpt-5"))
34924
- return 400000;
34925
- if (model.includes("o1") || model.includes("o3") || model.includes("o4"))
34926
- return 200000;
34927
- if (model.includes("gpt-4o") || model.includes("gpt-4-turbo"))
34928
- return 128000;
34929
- if (model.includes("gpt-3.5"))
34930
- return 16385;
34931
- return 128000;
35143
+ return lookupModel(this.modelId)?.contextWindow ?? 128000;
34932
35144
  }
34933
35145
  buildPayload(claudeRequest, messages, tools) {
34934
35146
  return this.buildChatCompletionsPayload(claudeRequest, messages, tools);
@@ -35041,6 +35253,7 @@ var MiniMaxModelDialect;
35041
35253
  var init_minimax_model_dialect = __esm(() => {
35042
35254
  init_base_api_format();
35043
35255
  init_logger();
35256
+ init_model_catalog();
35044
35257
  MiniMaxModelDialect = class MiniMaxModelDialect extends BaseAPIFormat {
35045
35258
  processTextContent(textContent, accumulatedText) {
35046
35259
  return {
@@ -35050,13 +35263,25 @@ var init_minimax_model_dialect = __esm(() => {
35050
35263
  };
35051
35264
  }
35052
35265
  prepareRequest(request, originalRequest) {
35053
- if (originalRequest.thinking) {
35054
- request.reasoning_split = true;
35055
- log(`[MiniMaxModelDialect] Enabled reasoning_split: true`);
35056
- delete request.thinking;
35266
+ const entry = lookupModel(this.modelId);
35267
+ const tempRange = entry?.temperatureRange;
35268
+ if (request.temperature !== undefined && tempRange) {
35269
+ if (request.temperature < tempRange.min) {
35270
+ log(`[MiniMaxModelDialect] Clamping temperature ${request.temperature} \u2192 ${tempRange.min} (MiniMax requires >= ${tempRange.min})`);
35271
+ request.temperature = tempRange.min;
35272
+ } else if (request.temperature > tempRange.max) {
35273
+ log(`[MiniMaxModelDialect] Clamping temperature ${request.temperature} \u2192 ${tempRange.max} (MiniMax requires <= ${tempRange.max})`);
35274
+ request.temperature = tempRange.max;
35275
+ }
35057
35276
  }
35058
35277
  return request;
35059
35278
  }
35279
+ getContextWindow() {
35280
+ return lookupModel(this.modelId)?.contextWindow ?? 204800;
35281
+ }
35282
+ supportsVision() {
35283
+ return lookupModel(this.modelId)?.supportsVision ?? false;
35284
+ }
35060
35285
  shouldHandle(modelId) {
35061
35286
  return matchesModelFamily(modelId, "minimax");
35062
35287
  }
@@ -35096,30 +35321,11 @@ var init_deepseek_model_dialect = __esm(() => {
35096
35321
  });
35097
35322
 
35098
35323
  // src/adapters/glm-model-dialect.ts
35099
- var GLM_CONTEXT_WINDOWS, GLM_VISION_MODELS, GLMModelDialect;
35324
+ var GLMModelDialect;
35100
35325
  var init_glm_model_dialect = __esm(() => {
35101
35326
  init_base_api_format();
35102
35327
  init_logger();
35103
- GLM_CONTEXT_WINDOWS = [
35104
- ["glm-5-turbo", 202752],
35105
- ["glm-5", 80000],
35106
- ["glm-4.7-flash", 202752],
35107
- ["glm-4.7", 202752],
35108
- ["glm-4.6v", 131072],
35109
- ["glm-4.6", 204800],
35110
- ["glm-4.5v", 65536],
35111
- ["glm-4.5-flash", 131072],
35112
- ["glm-4.5-air", 131072],
35113
- ["glm-4.5", 131072],
35114
- ["glm-4-long", 1e6],
35115
- ["glm-4-plus", 128000],
35116
- ["glm-4-flash", 128000],
35117
- ["glm-4-32b", 128000],
35118
- ["glm-4", 128000],
35119
- ["glm-3-turbo", 128000],
35120
- ["glm-", 131072]
35121
- ];
35122
- GLM_VISION_MODELS = ["glm-4v", "glm-4v-plus", "glm-4.5v", "glm-4.6v", "glm-5"];
35328
+ init_model_catalog();
35123
35329
  GLMModelDialect = class GLMModelDialect extends BaseAPIFormat {
35124
35330
  processTextContent(textContent, accumulatedText) {
35125
35331
  return {
@@ -35142,16 +35348,10 @@ var init_glm_model_dialect = __esm(() => {
35142
35348
  return "GLMModelDialect";
35143
35349
  }
35144
35350
  getContextWindow() {
35145
- const lower = this.modelId.toLowerCase();
35146
- for (const [pattern, size] of GLM_CONTEXT_WINDOWS) {
35147
- if (lower.includes(pattern))
35148
- return size;
35149
- }
35150
- return 128000;
35351
+ return lookupModel(this.modelId)?.contextWindow ?? 128000;
35151
35352
  }
35152
35353
  supportsVision() {
35153
- const lower = this.modelId.toLowerCase();
35154
- return GLM_VISION_MODELS.some((m) => lower.includes(m));
35354
+ return lookupModel(this.modelId)?.supportsVision ?? false;
35155
35355
  }
35156
35356
  };
35157
35357
  });
@@ -35161,6 +35361,7 @@ var XiaomiModelDialect;
35161
35361
  var init_xiaomi_model_dialect = __esm(() => {
35162
35362
  init_base_api_format();
35163
35363
  init_logger();
35364
+ init_model_catalog();
35164
35365
  XiaomiModelDialect = class XiaomiModelDialect extends BaseAPIFormat {
35165
35366
  processTextContent(textContent, accumulatedText) {
35166
35367
  return {
@@ -35170,7 +35371,7 @@ var init_xiaomi_model_dialect = __esm(() => {
35170
35371
  };
35171
35372
  }
35172
35373
  getToolNameLimit() {
35173
- return 64;
35374
+ return lookupModel(this.modelId)?.toolNameLimit ?? null;
35174
35375
  }
35175
35376
  prepareRequest(request, originalRequest) {
35176
35377
  if (originalRequest.thinking) {
@@ -35257,21 +35458,21 @@ __export(exports_cli, {
35257
35458
  import {
35258
35459
  readFileSync as readFileSync12,
35259
35460
  writeFileSync as writeFileSync6,
35260
- existsSync as existsSync14,
35461
+ existsSync as existsSync15,
35261
35462
  mkdirSync as mkdirSync6,
35262
35463
  copyFileSync,
35263
35464
  readdirSync as readdirSync4,
35264
35465
  unlinkSync as unlinkSync4
35265
35466
  } from "fs";
35266
35467
  import { fileURLToPath as fileURLToPath3 } from "url";
35267
- import { dirname as dirname3, join as join14 } from "path";
35268
- import { homedir as homedir13 } from "os";
35468
+ import { dirname as dirname3, join as join15 } from "path";
35469
+ import { homedir as homedir14 } from "os";
35269
35470
  function getVersion() {
35270
35471
  return VERSION;
35271
35472
  }
35272
35473
  function clearAllModelCaches() {
35273
- const cacheDir = join14(homedir13(), ".claudish");
35274
- if (!existsSync14(cacheDir))
35474
+ const cacheDir = join15(homedir14(), ".claudish");
35475
+ if (!existsSync15(cacheDir))
35275
35476
  return;
35276
35477
  const cachePatterns = ["all-models.json", "pricing-cache.json"];
35277
35478
  let cleared = 0;
@@ -35279,7 +35480,7 @@ function clearAllModelCaches() {
35279
35480
  const files = readdirSync4(cacheDir);
35280
35481
  for (const file2 of files) {
35281
35482
  if (cachePatterns.includes(file2) || file2.startsWith("litellm-models-")) {
35282
- unlinkSync4(join14(cacheDir, file2));
35483
+ unlinkSync4(join15(cacheDir, file2));
35283
35484
  cleared++;
35284
35485
  }
35285
35486
  }
@@ -35293,7 +35494,7 @@ function clearAllModelCaches() {
35293
35494
  async function parseArgs(args) {
35294
35495
  const config3 = {
35295
35496
  model: undefined,
35296
- autoApprove: false,
35497
+ autoApprove: true,
35297
35498
  dangerous: false,
35298
35499
  interactive: false,
35299
35500
  debug: false,
@@ -35583,7 +35784,7 @@ async function fetchOllamaModels() {
35583
35784
  }
35584
35785
  async function searchAndPrintModels(query, forceUpdate) {
35585
35786
  let models = [];
35586
- if (!forceUpdate && existsSync14(ALL_MODELS_JSON_PATH)) {
35787
+ if (!forceUpdate && existsSync15(ALL_MODELS_JSON_PATH)) {
35587
35788
  try {
35588
35789
  const cacheData = JSON.parse(readFileSync12(ALL_MODELS_JSON_PATH, "utf-8"));
35589
35790
  const lastUpdated = new Date(cacheData.lastUpdated);
@@ -35753,7 +35954,7 @@ Found ${results.length} matching models:
35753
35954
  async function printAllModels(jsonOutput, forceUpdate) {
35754
35955
  let models = [];
35755
35956
  const [ollamaModels, zenModels] = await Promise.all([fetchOllamaModels(), fetchZenModels()]);
35756
- if (!forceUpdate && existsSync14(ALL_MODELS_JSON_PATH)) {
35957
+ if (!forceUpdate && existsSync15(ALL_MODELS_JSON_PATH)) {
35757
35958
  try {
35758
35959
  const cacheData = JSON.parse(readFileSync12(ALL_MODELS_JSON_PATH, "utf-8"));
35759
35960
  const lastUpdated = new Date(cacheData.lastUpdated);
@@ -35956,8 +36157,8 @@ async function printAllModels(jsonOutput, forceUpdate) {
35956
36157
  console.log("Top models: claudish --top-models");
35957
36158
  }
35958
36159
  function isCacheStale() {
35959
- const cachePath = existsSync14(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
35960
- if (!existsSync14(cachePath)) {
36160
+ const cachePath = existsSync15(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36161
+ if (!existsSync15(cachePath)) {
35961
36162
  return true;
35962
36163
  }
35963
36164
  try {
@@ -36040,8 +36241,8 @@ async function updateModelsFromOpenRouter() {
36040
36241
  providers.add(provider);
36041
36242
  }
36042
36243
  let version2 = "1.2.0";
36043
- const existingPath = existsSync14(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36044
- if (existsSync14(existingPath)) {
36244
+ const existingPath = existsSync15(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36245
+ if (existsSync15(existingPath)) {
36045
36246
  try {
36046
36247
  const existing = JSON.parse(readFileSync12(existingPath, "utf-8"));
36047
36248
  version2 = existing.version || version2;
@@ -36072,7 +36273,7 @@ async function checkAndUpdateModelsCache(forceUpdate = false) {
36072
36273
  await updateModelsFromOpenRouter();
36073
36274
  } else {
36074
36275
  try {
36075
- const cachePath = existsSync14(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36276
+ const cachePath = existsSync15(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36076
36277
  const data = JSON.parse(readFileSync12(cachePath, "utf-8"));
36077
36278
  console.error(`\u2713 Using cached models (last updated: ${data.lastUpdated})`);
36078
36279
  } catch {}
@@ -36092,7 +36293,8 @@ async function probeModelRouting(models, jsonOutput) {
36092
36293
  const BG_DIM = "\x1B[48;5;236m";
36093
36294
  console.error(`${DIM}Warming provider caches...${RESET}`);
36094
36295
  await Promise.allSettled([
36095
- warmZenModelCache()
36296
+ warmZenModelCache(),
36297
+ warmZenGoModelCache()
36096
36298
  ]);
36097
36299
  const routingRules = loadRoutingRules();
36098
36300
  const results = [];
@@ -36664,7 +36866,7 @@ MORE INFO:
36664
36866
  }
36665
36867
  function printAIAgentGuide() {
36666
36868
  try {
36667
- const guidePath = join14(__dirname4, "../AI_AGENT_GUIDE.md");
36869
+ const guidePath = join15(__dirname4, "../AI_AGENT_GUIDE.md");
36668
36870
  const guideContent = readFileSync12(guidePath, "utf-8");
36669
36871
  console.log(guideContent);
36670
36872
  } catch (error46) {
@@ -36681,19 +36883,19 @@ async function initializeClaudishSkill() {
36681
36883
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
36682
36884
  `);
36683
36885
  const cwd = process.cwd();
36684
- const claudeDir = join14(cwd, ".claude");
36685
- const skillsDir = join14(claudeDir, "skills");
36686
- const claudishSkillDir = join14(skillsDir, "claudish-usage");
36687
- const skillFile = join14(claudishSkillDir, "SKILL.md");
36688
- if (existsSync14(skillFile)) {
36886
+ const claudeDir = join15(cwd, ".claude");
36887
+ const skillsDir = join15(claudeDir, "skills");
36888
+ const claudishSkillDir = join15(skillsDir, "claudish-usage");
36889
+ const skillFile = join15(claudishSkillDir, "SKILL.md");
36890
+ if (existsSync15(skillFile)) {
36689
36891
  console.log("\u2705 Claudish skill already installed at:");
36690
36892
  console.log(` ${skillFile}
36691
36893
  `);
36692
36894
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
36693
36895
  return;
36694
36896
  }
36695
- const sourceSkillPath = join14(__dirname4, "../skills/claudish-usage/SKILL.md");
36696
- if (!existsSync14(sourceSkillPath)) {
36897
+ const sourceSkillPath = join15(__dirname4, "../skills/claudish-usage/SKILL.md");
36898
+ if (!existsSync15(sourceSkillPath)) {
36697
36899
  console.error("\u274C Error: Claudish skill file not found in installation.");
36698
36900
  console.error(` Expected at: ${sourceSkillPath}`);
36699
36901
  console.error(`
@@ -36702,15 +36904,15 @@ async function initializeClaudishSkill() {
36702
36904
  process.exit(1);
36703
36905
  }
36704
36906
  try {
36705
- if (!existsSync14(claudeDir)) {
36907
+ if (!existsSync15(claudeDir)) {
36706
36908
  mkdirSync6(claudeDir, { recursive: true });
36707
36909
  console.log("\uD83D\uDCC1 Created .claude/ directory");
36708
36910
  }
36709
- if (!existsSync14(skillsDir)) {
36911
+ if (!existsSync15(skillsDir)) {
36710
36912
  mkdirSync6(skillsDir, { recursive: true });
36711
36913
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
36712
36914
  }
36713
- if (!existsSync14(claudishSkillDir)) {
36915
+ if (!existsSync15(claudishSkillDir)) {
36714
36916
  mkdirSync6(claudishSkillDir, { recursive: true });
36715
36917
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
36716
36918
  }
@@ -36753,8 +36955,8 @@ function printAvailableModels() {
36753
36955
  let lastUpdated = "unknown";
36754
36956
  let models = [];
36755
36957
  try {
36756
- const cachePath = existsSync14(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36757
- if (existsSync14(cachePath)) {
36958
+ const cachePath = existsSync15(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36959
+ if (existsSync15(cachePath)) {
36758
36960
  const data = JSON.parse(readFileSync12(cachePath, "utf-8"));
36759
36961
  lastUpdated = data.lastUpdated || "unknown";
36760
36962
  models = data.models || [];
@@ -36804,7 +37006,7 @@ Force update: claudish --list-models --force-update
36804
37006
  `);
36805
37007
  }
36806
37008
  function printAvailableModelsJSON() {
36807
- const jsonPath = existsSync14(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
37009
+ const jsonPath = existsSync15(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36808
37010
  try {
36809
37011
  const jsonContent = readFileSync12(jsonPath, "utf-8");
36810
37012
  const data = JSON.parse(jsonContent);
@@ -36891,7 +37093,7 @@ async function fetchGLMCodingModels() {
36891
37093
  return [];
36892
37094
  }
36893
37095
  }
36894
- var __filename4, __dirname4, VERSION = "6.0.1", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
37096
+ var __filename4, __dirname4, VERSION = "6.1.1", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
36895
37097
  var init_cli = __esm(() => {
36896
37098
  init_config();
36897
37099
  init_model_loader();
@@ -36904,13 +37106,13 @@ var init_cli = __esm(() => {
36904
37106
  __filename4 = fileURLToPath3(import.meta.url);
36905
37107
  __dirname4 = dirname3(__filename4);
36906
37108
  try {
36907
- const packageJson = JSON.parse(readFileSync12(join14(__dirname4, "../package.json"), "utf-8"));
37109
+ const packageJson = JSON.parse(readFileSync12(join15(__dirname4, "../package.json"), "utf-8"));
36908
37110
  VERSION = packageJson.version;
36909
37111
  } catch {}
36910
- CLAUDISH_CACHE_DIR2 = join14(homedir13(), ".claudish");
36911
- BUNDLED_MODELS_PATH = join14(__dirname4, "../recommended-models.json");
36912
- CACHED_MODELS_PATH = join14(CLAUDISH_CACHE_DIR2, "recommended-models.json");
36913
- ALL_MODELS_JSON_PATH = join14(CLAUDISH_CACHE_DIR2, "all-models.json");
37112
+ CLAUDISH_CACHE_DIR2 = join15(homedir14(), ".claudish");
37113
+ BUNDLED_MODELS_PATH = join15(__dirname4, "../recommended-models.json");
37114
+ CACHED_MODELS_PATH = join15(CLAUDISH_CACHE_DIR2, "recommended-models.json");
37115
+ ALL_MODELS_JSON_PATH = join15(CLAUDISH_CACHE_DIR2, "all-models.json");
36914
37116
  });
36915
37117
 
36916
37118
  // src/update-checker.ts
@@ -36922,9 +37124,9 @@ __export(exports_update_checker, {
36922
37124
  checkForUpdates: () => checkForUpdates
36923
37125
  });
36924
37126
  import { execSync } from "child_process";
36925
- import { existsSync as existsSync15, mkdirSync as mkdirSync7, readFileSync as readFileSync13, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "fs";
36926
- import { homedir as homedir14, platform as platform2, tmpdir } from "os";
36927
- import { join as join15 } from "path";
37127
+ import { existsSync as existsSync16, mkdirSync as mkdirSync7, readFileSync as readFileSync13, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "fs";
37128
+ import { homedir as homedir15, platform as platform2, tmpdir } from "os";
37129
+ import { join as join16 } from "path";
36928
37130
  import { createInterface } from "readline";
36929
37131
  function getUpdateCommand() {
36930
37132
  const scriptPath = process.argv[1] || "";
@@ -36936,24 +37138,24 @@ function getUpdateCommand() {
36936
37138
  function getCacheFilePath() {
36937
37139
  let cacheDir;
36938
37140
  if (isWindows) {
36939
- const localAppData = process.env.LOCALAPPDATA || join15(homedir14(), "AppData", "Local");
36940
- cacheDir = join15(localAppData, "claudish");
37141
+ const localAppData = process.env.LOCALAPPDATA || join16(homedir15(), "AppData", "Local");
37142
+ cacheDir = join16(localAppData, "claudish");
36941
37143
  } else {
36942
- cacheDir = join15(homedir14(), ".cache", "claudish");
37144
+ cacheDir = join16(homedir15(), ".cache", "claudish");
36943
37145
  }
36944
37146
  try {
36945
- if (!existsSync15(cacheDir)) {
37147
+ if (!existsSync16(cacheDir)) {
36946
37148
  mkdirSync7(cacheDir, { recursive: true });
36947
37149
  }
36948
- return join15(cacheDir, "update-check.json");
37150
+ return join16(cacheDir, "update-check.json");
36949
37151
  } catch {
36950
- return join15(tmpdir(), "claudish-update-check.json");
37152
+ return join16(tmpdir(), "claudish-update-check.json");
36951
37153
  }
36952
37154
  }
36953
37155
  function readCache() {
36954
37156
  try {
36955
37157
  const cachePath = getCacheFilePath();
36956
- if (!existsSync15(cachePath)) {
37158
+ if (!existsSync16(cachePath)) {
36957
37159
  return null;
36958
37160
  }
36959
37161
  const data = JSON.parse(readFileSync13(cachePath, "utf-8"));
@@ -36979,7 +37181,7 @@ function isCacheValid(cache) {
36979
37181
  function clearCache() {
36980
37182
  try {
36981
37183
  const cachePath = getCacheFilePath();
36982
- if (existsSync15(cachePath)) {
37184
+ if (existsSync16(cachePath)) {
36983
37185
  unlinkSync5(cachePath);
36984
37186
  }
36985
37187
  } catch {}
@@ -39460,12 +39662,12 @@ __export(exports_model_selector, {
39460
39662
  promptForApiKey: () => promptForApiKey,
39461
39663
  confirmAction: () => confirmAction
39462
39664
  });
39463
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync8, existsSync as existsSync16, mkdirSync as mkdirSync8 } from "fs";
39464
- import { join as join16, dirname as dirname4 } from "path";
39465
- import { homedir as homedir15 } from "os";
39665
+ import { readFileSync as readFileSync14, writeFileSync as writeFileSync8, existsSync as existsSync17, mkdirSync as mkdirSync8 } from "fs";
39666
+ import { join as join17, dirname as dirname4 } from "path";
39667
+ import { homedir as homedir16 } from "os";
39466
39668
  import { fileURLToPath as fileURLToPath4 } from "url";
39467
39669
  function loadRecommendedModels2() {
39468
- if (existsSync16(RECOMMENDED_MODELS_JSON_PATH)) {
39670
+ if (existsSync17(RECOMMENDED_MODELS_JSON_PATH)) {
39469
39671
  try {
39470
39672
  const content = readFileSync14(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
39471
39673
  const data = JSON.parse(content);
@@ -39480,7 +39682,7 @@ function loadRecommendedModels2() {
39480
39682
  return [];
39481
39683
  }
39482
39684
  async function fetchAllModels(forceUpdate = false) {
39483
- if (!forceUpdate && existsSync16(ALL_MODELS_JSON_PATH2)) {
39685
+ if (!forceUpdate && existsSync17(ALL_MODELS_JSON_PATH2)) {
39484
39686
  try {
39485
39687
  const cacheData = JSON.parse(readFileSync14(ALL_MODELS_JSON_PATH2, "utf-8"));
39486
39688
  const lastUpdated = new Date(cacheData.lastUpdated);
@@ -39984,7 +40186,7 @@ async function fetchOllamaCloudModels() {
39984
40186
  }
39985
40187
  }
39986
40188
  function shouldRefreshForFreeModels() {
39987
- if (!existsSync16(ALL_MODELS_JSON_PATH2)) {
40189
+ if (!existsSync17(ALL_MODELS_JSON_PATH2)) {
39988
40190
  return true;
39989
40191
  }
39990
40192
  try {
@@ -40030,45 +40232,61 @@ async function getFreeModels() {
40030
40232
  async function getAllModelsForSearch(forceUpdate = false) {
40031
40233
  const litellmBaseUrl = process.env.LITELLM_BASE_URL;
40032
40234
  const litellmApiKey = process.env.LITELLM_API_KEY;
40033
- const fetchEntries = [
40235
+ const allEntries = [
40034
40236
  {
40035
40237
  name: "OpenRouter",
40036
- promise: fetchAllModels(forceUpdate).then((models) => models.map(toModelInfo))
40238
+ promise: () => fetchAllModels(forceUpdate).then((models) => models.map(toModelInfo))
40037
40239
  },
40038
- { name: "xAI", promise: fetchXAIModels() },
40039
- { name: "Gemini", promise: fetchGeminiModels() },
40040
- { name: "OpenAI", promise: fetchOpenAIModels() },
40041
- { name: "GLM", promise: fetchGLMDirectModels() },
40042
- { name: "GLM Coding", promise: fetchGLMCodingModels2() },
40043
- { name: "OllamaCloud", promise: fetchOllamaCloudModels() },
40044
- { name: "Zen", promise: fetchZenFreeModels() },
40045
- { name: "Zen Go", promise: fetchZenGoModels() }
40240
+ { name: "xAI", provider: "xai", promise: () => fetchXAIModels() },
40241
+ { name: "Gemini", provider: "google", promise: () => fetchGeminiModels() },
40242
+ { name: "OpenAI", provider: "openai", promise: () => fetchOpenAIModels() },
40243
+ { name: "GLM", provider: "glm", promise: () => fetchGLMDirectModels() },
40244
+ { name: "GLM Coding", provider: "glm-coding", promise: () => fetchGLMCodingModels2() },
40245
+ { name: "OllamaCloud", provider: "ollamacloud", promise: () => fetchOllamaCloudModels() },
40246
+ { name: "Zen", provider: "opencode-zen", promise: () => fetchZenFreeModels() },
40247
+ { name: "Zen Go", provider: "opencode-zen-go", promise: () => fetchZenGoModels() },
40248
+ { name: "MiniMax", provider: "minimax", promise: () => Promise.resolve(getKnownModels("minimax")) },
40249
+ { name: "MiniMax Coding", provider: "minimax-coding", promise: () => Promise.resolve(getKnownModels("minimax-coding")) },
40250
+ { name: "Kimi", provider: "kimi", promise: () => Promise.resolve(getKnownModels("kimi")) },
40251
+ { name: "Kimi Coding", provider: "kimi-coding", promise: () => Promise.resolve(getKnownModels("kimi-coding")) },
40252
+ { name: "Z.AI", provider: "zai", promise: () => Promise.resolve(getKnownModels("zai")) }
40046
40253
  ];
40047
40254
  if (litellmBaseUrl && litellmApiKey) {
40048
- fetchEntries.push({
40255
+ allEntries.push({
40049
40256
  name: "LiteLLM",
40050
- promise: fetchLiteLLMModels(litellmBaseUrl, litellmApiKey, forceUpdate)
40257
+ provider: "litellm",
40258
+ promise: () => fetchLiteLLMModels(litellmBaseUrl, litellmApiKey, forceUpdate)
40051
40259
  });
40052
40260
  }
40261
+ const fetchEntries = allEntries.filter((e) => {
40262
+ if (!e.provider)
40263
+ return true;
40264
+ const def = getProviderByName(e.provider);
40265
+ return def ? isProviderAvailable(def) : true;
40266
+ }).map((e) => ({ name: e.name, promise: e.promise() }));
40053
40267
  const settled = await Promise.allSettled(fetchEntries.map((e) => e.promise));
40054
40268
  const fetchResults = {};
40055
40269
  for (let i = 0;i < settled.length; i++) {
40056
40270
  const result = settled[i];
40057
40271
  fetchResults[fetchEntries[i].name] = result.status === "fulfilled" ? result.value : [];
40058
40272
  }
40059
- const directApiModels = [
40060
- ...fetchResults["xAI"],
40061
- ...fetchResults["Gemini"],
40062
- ...fetchResults["OpenAI"],
40063
- ...fetchResults["GLM"],
40064
- ...fetchResults["GLM Coding"]
40065
- ];
40273
+ const r = (name) => fetchResults[name] || [];
40066
40274
  const allModels = [
40067
- ...fetchResults["Zen"],
40068
- ...fetchResults["OllamaCloud"],
40069
- ...directApiModels,
40070
- ...fetchResults["LiteLLM"] || [],
40071
- ...fetchResults["OpenRouter"]
40275
+ ...r("Zen"),
40276
+ ...r("Zen Go"),
40277
+ ...r("OllamaCloud"),
40278
+ ...r("xAI"),
40279
+ ...r("Gemini"),
40280
+ ...r("OpenAI"),
40281
+ ...r("GLM"),
40282
+ ...r("GLM Coding"),
40283
+ ...r("MiniMax"),
40284
+ ...r("MiniMax Coding"),
40285
+ ...r("Kimi"),
40286
+ ...r("Kimi Coding"),
40287
+ ...r("Z.AI"),
40288
+ ...r("LiteLLM"),
40289
+ ...r("OpenRouter")
40072
40290
  ];
40073
40291
  return allModels;
40074
40292
  }
@@ -40090,8 +40308,11 @@ function formatModelChoice(model, showSource = false) {
40090
40308
  OpenAI: "OAI",
40091
40309
  GLM: "GLM",
40092
40310
  "GLM Coding": "GC",
40311
+ MiniMax: "MM",
40093
40312
  "MiniMax Coding": "MMC",
40313
+ Kimi: "Kimi",
40094
40314
  "Kimi Coding": "KC",
40315
+ "Z.AI": "ZAI",
40095
40316
  OllamaCloud: "OC",
40096
40317
  LiteLLM: "LL"
40097
40318
  };
@@ -40250,7 +40471,12 @@ async function selectModel(options = {}) {
40250
40471
  return selected;
40251
40472
  }
40252
40473
  function getProviderChoices() {
40253
- return ALL_PROVIDER_CHOICES.filter((choice) => !choice.envVar || process.env[choice.envVar]);
40474
+ return ALL_PROVIDER_CHOICES.filter((choice) => {
40475
+ if (!choice.provider)
40476
+ return true;
40477
+ const def = getProviderByName(choice.provider);
40478
+ return def ? isProviderAvailable(def) : true;
40479
+ });
40254
40480
  }
40255
40481
  function getKnownModels(provider) {
40256
40482
  const known = {
@@ -40383,6 +40609,19 @@ function getKnownModels(provider) {
40383
40609
  }
40384
40610
  ]
40385
40611
  };
40612
+ const sourceMap = {
40613
+ minimax: "MiniMax",
40614
+ "minimax-coding": "MiniMax Coding",
40615
+ kimi: "Kimi",
40616
+ "kimi-coding": "Kimi Coding",
40617
+ zai: "Z.AI",
40618
+ glm: "GLM",
40619
+ "glm-coding": "GLM Coding",
40620
+ ollamacloud: "OllamaCloud",
40621
+ google: "Gemini",
40622
+ openai: "OpenAI",
40623
+ xai: "xAI"
40624
+ };
40386
40625
  const providerDisplay = provider.charAt(0).toUpperCase() + provider.slice(1);
40387
40626
  return (known[provider] || []).map((m) => ({
40388
40627
  id: m.id,
@@ -40390,7 +40629,8 @@ function getKnownModels(provider) {
40390
40629
  description: m.description || `${providerDisplay} model`,
40391
40630
  provider: providerDisplay,
40392
40631
  context: m.context,
40393
- supportsTools: true
40632
+ supportsTools: true,
40633
+ source: sourceMap[provider]
40394
40634
  }));
40395
40635
  }
40396
40636
  function filterModelsByProvider(allModels, provider) {
@@ -40587,11 +40827,12 @@ var __filename5, __dirname5, CLAUDISH_CACHE_DIR3, ALL_MODELS_JSON_PATH2, RECOMME
40587
40827
  var init_model_selector = __esm(() => {
40588
40828
  init_dist8();
40589
40829
  init_model_loader();
40830
+ init_provider_definitions();
40590
40831
  __filename5 = fileURLToPath4(import.meta.url);
40591
40832
  __dirname5 = dirname4(__filename5);
40592
- CLAUDISH_CACHE_DIR3 = join16(homedir15(), ".claudish");
40593
- ALL_MODELS_JSON_PATH2 = join16(CLAUDISH_CACHE_DIR3, "all-models.json");
40594
- RECOMMENDED_MODELS_JSON_PATH = join16(__dirname5, "../recommended-models.json");
40833
+ CLAUDISH_CACHE_DIR3 = join17(homedir16(), ".claudish");
40834
+ ALL_MODELS_JSON_PATH2 = join17(CLAUDISH_CACHE_DIR3, "all-models.json");
40835
+ RECOMMENDED_MODELS_JSON_PATH = join17(__dirname5, "../recommended-models.json");
40595
40836
  PROVIDER_FILTER_ALIASES = {
40596
40837
  zen: "Zen",
40597
40838
  openrouter: "OpenRouter",
@@ -40605,10 +40846,16 @@ var init_model_selector = __esm(() => {
40605
40846
  glm: "GLM",
40606
40847
  "glm-coding": "GLM Coding",
40607
40848
  gc: "GLM Coding",
40849
+ minimax: "MiniMax",
40850
+ mm: "MiniMax",
40608
40851
  mmc: "MiniMax Coding",
40609
40852
  "minimax-coding": "MiniMax Coding",
40853
+ kimi: "Kimi",
40854
+ moon: "Kimi",
40855
+ moonshot: "Kimi",
40610
40856
  kc: "Kimi Coding",
40611
40857
  "kimi-coding": "Kimi Coding",
40858
+ zai: "Z.AI",
40612
40859
  ollamacloud: "OllamaCloud",
40613
40860
  oc: "OllamaCloud",
40614
40861
  litellm: "LiteLLM",
@@ -40620,66 +40867,21 @@ var init_model_selector = __esm(() => {
40620
40867
  value: "skip",
40621
40868
  description: "Use native Claude model for this tier"
40622
40869
  },
40623
- { name: "OpenRouter", value: "openrouter", description: "580+ models via unified API" },
40624
- { name: "OpenCode Zen", value: "zen", description: "Free models, no API key needed" },
40625
- {
40626
- name: "Google Gemini",
40627
- value: "google",
40628
- description: "Direct API (GEMINI_API_KEY)",
40629
- envVar: "GEMINI_API_KEY"
40630
- },
40631
- {
40632
- name: "OpenAI",
40633
- value: "openai",
40634
- description: "Direct API (OPENAI_API_KEY)",
40635
- envVar: "OPENAI_API_KEY"
40636
- },
40637
- {
40638
- name: "xAI / Grok",
40639
- value: "xai",
40640
- description: "Direct API (XAI_API_KEY)",
40641
- envVar: "XAI_API_KEY"
40642
- },
40643
- {
40644
- name: "MiniMax",
40645
- value: "minimax",
40646
- description: "Direct API (MINIMAX_API_KEY)",
40647
- envVar: "MINIMAX_API_KEY"
40648
- },
40649
- {
40650
- name: "MiniMax Coding",
40651
- value: "minimax-coding",
40652
- description: "MiniMax Coding subscription (MINIMAX_CODING_API_KEY)",
40653
- envVar: "MINIMAX_CODING_API_KEY"
40654
- },
40655
- {
40656
- name: "Kimi / Moonshot",
40657
- value: "kimi",
40658
- description: "Direct API (MOONSHOT_API_KEY)",
40659
- envVar: "MOONSHOT_API_KEY"
40660
- },
40661
- {
40662
- name: "Kimi Coding",
40663
- value: "kimi-coding",
40664
- description: "Kimi Coding subscription (KIMI_CODING_API_KEY)",
40665
- envVar: "KIMI_CODING_API_KEY"
40666
- },
40667
- {
40668
- name: "GLM / Zhipu",
40669
- value: "glm",
40670
- description: "Direct API (ZHIPU_API_KEY)",
40671
- envVar: "ZHIPU_API_KEY"
40672
- },
40673
- {
40674
- name: "GLM Coding Plan",
40675
- value: "glm-coding",
40676
- description: "GLM Coding subscription (GLM_CODING_API_KEY)",
40677
- envVar: "GLM_CODING_API_KEY"
40678
- },
40679
- { name: "Z.AI", value: "zai", description: "Z.AI API (ZAI_API_KEY)", envVar: "ZAI_API_KEY" },
40680
- { name: "OllamaCloud", value: "ollamacloud", description: "Cloud models (OLLAMA_API_KEY)" },
40681
- { name: "Ollama (local)", value: "ollama", description: "Local Ollama instance" },
40682
- { name: "LM Studio (local)", value: "lmstudio", description: "Local LM Studio instance" },
40870
+ { name: "OpenRouter", value: "openrouter", description: "580+ models via unified API", provider: "openrouter" },
40871
+ { name: "OpenCode Zen", value: "zen", description: "Free models, no API key needed", provider: "opencode-zen" },
40872
+ { name: "Google Gemini", value: "google", description: "Direct API", provider: "google" },
40873
+ { name: "OpenAI", value: "openai", description: "Direct API", provider: "openai" },
40874
+ { name: "xAI / Grok", value: "xai", description: "Direct API", provider: "xai" },
40875
+ { name: "MiniMax", value: "minimax", description: "Direct API", provider: "minimax" },
40876
+ { name: "MiniMax Coding", value: "minimax-coding", description: "Coding subscription", provider: "minimax-coding" },
40877
+ { name: "Kimi / Moonshot", value: "kimi", description: "Direct API", provider: "kimi" },
40878
+ { name: "Kimi Coding", value: "kimi-coding", description: "Coding subscription", provider: "kimi-coding" },
40879
+ { name: "GLM / Zhipu", value: "glm", description: "Direct API", provider: "glm" },
40880
+ { name: "GLM Coding Plan", value: "glm-coding", description: "Coding subscription", provider: "glm-coding" },
40881
+ { name: "Z.AI", value: "zai", description: "Direct API", provider: "zai" },
40882
+ { name: "OllamaCloud", value: "ollamacloud", description: "Cloud models", provider: "ollamacloud" },
40883
+ { name: "Ollama (local)", value: "ollama", description: "Local Ollama instance", provider: "ollama" },
40884
+ { name: "LM Studio (local)", value: "lmstudio", description: "Local LM Studio instance", provider: "lmstudio" },
40683
40885
  {
40684
40886
  name: "Enter custom model",
40685
40887
  value: "custom",
@@ -40709,6 +40911,12 @@ var init_model_selector = __esm(() => {
40709
40911
  openai: "OpenAI",
40710
40912
  xai: "xAI",
40711
40913
  glm: "GLM",
40914
+ "glm-coding": "GLM Coding",
40915
+ minimax: "MiniMax",
40916
+ "minimax-coding": "MiniMax Coding",
40917
+ kimi: "Kimi",
40918
+ "kimi-coding": "Kimi Coding",
40919
+ zai: "Z.AI",
40712
40920
  ollamacloud: "OllamaCloud",
40713
40921
  zen: "Zen"
40714
40922
  };
@@ -41637,23 +41845,23 @@ var init_telemetry = __esm(() => {
41637
41845
 
41638
41846
  // src/stats-buffer.ts
41639
41847
  import {
41640
- existsSync as existsSync17,
41848
+ existsSync as existsSync18,
41641
41849
  mkdirSync as mkdirSync9,
41642
41850
  readFileSync as readFileSync15,
41643
41851
  renameSync,
41644
41852
  unlinkSync as unlinkSync6,
41645
41853
  writeFileSync as writeFileSync9
41646
41854
  } from "fs";
41647
- import { homedir as homedir16 } from "os";
41648
- import { join as join17 } from "path";
41855
+ import { homedir as homedir17 } from "os";
41856
+ import { join as join18 } from "path";
41649
41857
  function ensureDir() {
41650
- if (!existsSync17(CLAUDISH_DIR)) {
41858
+ if (!existsSync18(CLAUDISH_DIR)) {
41651
41859
  mkdirSync9(CLAUDISH_DIR, { recursive: true });
41652
41860
  }
41653
41861
  }
41654
41862
  function readFromDisk() {
41655
41863
  try {
41656
- if (!existsSync17(BUFFER_FILE))
41864
+ if (!existsSync18(BUFFER_FILE))
41657
41865
  return [];
41658
41866
  const raw = readFileSync15(BUFFER_FILE, "utf-8");
41659
41867
  const parsed = JSON.parse(raw);
@@ -41679,7 +41887,7 @@ function writeToDisk(events) {
41679
41887
  ensureDir();
41680
41888
  const trimmed = enforceSizeCap([...events]);
41681
41889
  const payload = { version: 1, events: trimmed };
41682
- const tmpFile = join17(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
41890
+ const tmpFile = join18(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
41683
41891
  writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
41684
41892
  renameSync(tmpFile, BUFFER_FILE);
41685
41893
  memoryCache = trimmed;
@@ -41724,7 +41932,7 @@ function clearBuffer() {
41724
41932
  try {
41725
41933
  memoryCache = [];
41726
41934
  eventsSinceLastFlush = 0;
41727
- if (existsSync17(BUFFER_FILE)) {
41935
+ if (existsSync18(BUFFER_FILE)) {
41728
41936
  unlinkSync6(BUFFER_FILE);
41729
41937
  }
41730
41938
  } catch {}
@@ -41753,8 +41961,8 @@ function syncFlushOnExit() {
41753
41961
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, lastFlushTime, flushScheduled = false;
41754
41962
  var init_stats_buffer = __esm(() => {
41755
41963
  BUFFER_MAX_BYTES = 64 * 1024;
41756
- CLAUDISH_DIR = join17(homedir16(), ".claudish");
41757
- BUFFER_FILE = join17(CLAUDISH_DIR, "stats-buffer.json");
41964
+ CLAUDISH_DIR = join18(homedir17(), ".claudish");
41965
+ BUFFER_FILE = join18(CLAUDISH_DIR, "stats-buffer.json");
41758
41966
  lastFlushTime = Date.now();
41759
41967
  process.on("exit", syncFlushOnExit);
41760
41968
  process.on("SIGTERM", () => {
@@ -42242,8 +42450,8 @@ import { EventEmitter as EventEmitter2 } from "events";
42242
42450
  import { resolve as resolve3, dirname as dirname5 } from "path";
42243
42451
  import { fileURLToPath as fileURLToPath5 } from "url";
42244
42452
  import { resolve as resolve22, isAbsolute, parse as parse6 } from "path";
42245
- import { existsSync as existsSync18 } from "fs";
42246
- import { basename, join as join18 } from "path";
42453
+ import { existsSync as existsSync19 } from "fs";
42454
+ import { basename, join as join19 } from "path";
42247
42455
  import os from "os";
42248
42456
  import path from "path";
42249
42457
  import { EventEmitter as EventEmitter3 } from "events";
@@ -44642,7 +44850,7 @@ function getBunfsRootPath() {
44642
44850
  return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
44643
44851
  }
44644
44852
  function normalizeBunfsPath(fileName) {
44645
- return join18(getBunfsRootPath(), basename(fileName));
44853
+ return join19(getBunfsRootPath(), basename(fileName));
44646
44854
  }
44647
44855
  function isValidDirectoryName(name) {
44648
44856
  if (!name || typeof name !== "string") {
@@ -54838,7 +55046,7 @@ var init_index_0wbvecnk = __esm(async () => {
54838
55046
  worker_path = this.options.workerPath;
54839
55047
  } else {
54840
55048
  worker_path = new URL("./parser.worker.js", import.meta.url).href;
54841
- if (!existsSync18(resolve22(import.meta.dirname, "parser.worker.js"))) {
55049
+ if (!existsSync19(resolve22(import.meta.dirname, "parser.worker.js"))) {
54842
55050
  worker_path = new URL("./parser.worker.ts", import.meta.url).href;
54843
55051
  }
54844
55052
  }
@@ -98101,6 +98309,18 @@ var init_react = __esm(async () => {
98101
98309
  });
98102
98310
 
98103
98311
  // src/tui/providers.ts
98312
+ function toProviderDef(def) {
98313
+ return {
98314
+ name: def.name === "google" ? "gemini" : def.name,
98315
+ displayName: def.displayName,
98316
+ apiKeyEnvVar: def.apiKeyEnvVar,
98317
+ description: def.description || def.apiKeyDescription,
98318
+ keyUrl: def.apiKeyUrl,
98319
+ endpointEnvVar: def.baseUrlEnvVars?.[0],
98320
+ defaultEndpoint: def.baseUrl || undefined,
98321
+ aliases: def.apiKeyAliases
98322
+ };
98323
+ }
98104
98324
  function maskKey2(key) {
98105
98325
  if (!key)
98106
98326
  return "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500";
@@ -98108,113 +98328,11 @@ function maskKey2(key) {
98108
98328
  return "**** ";
98109
98329
  return `${key.slice(0, 3)}\u2022\u2022${key.slice(-3)}`;
98110
98330
  }
98111
- var PROVIDERS;
98331
+ var SKIP, PROVIDERS;
98112
98332
  var init_providers = __esm(() => {
98113
- PROVIDERS = [
98114
- {
98115
- name: "openrouter",
98116
- displayName: "OpenRouter",
98117
- apiKeyEnvVar: "OPENROUTER_API_KEY",
98118
- description: "580+ models, default backend",
98119
- keyUrl: "https://openrouter.ai/keys"
98120
- },
98121
- {
98122
- name: "gemini",
98123
- displayName: "Google Gemini",
98124
- apiKeyEnvVar: "GEMINI_API_KEY",
98125
- description: "Direct Gemini API (g@, google@)",
98126
- keyUrl: "https://aistudio.google.com/app/apikey",
98127
- endpointEnvVar: "GEMINI_BASE_URL",
98128
- defaultEndpoint: "https://generativelanguage.googleapis.com"
98129
- },
98130
- {
98131
- name: "openai",
98132
- displayName: "OpenAI",
98133
- apiKeyEnvVar: "OPENAI_API_KEY",
98134
- description: "Direct OpenAI API (oai@)",
98135
- keyUrl: "https://platform.openai.com/api-keys",
98136
- endpointEnvVar: "OPENAI_BASE_URL",
98137
- defaultEndpoint: "https://api.openai.com"
98138
- },
98139
- {
98140
- name: "minimax",
98141
- displayName: "MiniMax",
98142
- apiKeyEnvVar: "MINIMAX_API_KEY",
98143
- description: "MiniMax API (mm@, mmax@)",
98144
- keyUrl: "https://www.minimaxi.com/",
98145
- endpointEnvVar: "MINIMAX_BASE_URL",
98146
- defaultEndpoint: "https://api.minimax.io"
98147
- },
98148
- {
98149
- name: "kimi",
98150
- displayName: "Kimi / Moonshot",
98151
- apiKeyEnvVar: "MOONSHOT_API_KEY",
98152
- description: "Kimi API (kimi@, moon@)",
98153
- keyUrl: "https://platform.moonshot.cn/",
98154
- aliases: ["KIMI_API_KEY"],
98155
- endpointEnvVar: "MOONSHOT_BASE_URL",
98156
- defaultEndpoint: "https://api.moonshot.ai"
98157
- },
98158
- {
98159
- name: "glm",
98160
- displayName: "GLM / Zhipu",
98161
- apiKeyEnvVar: "ZHIPU_API_KEY",
98162
- description: "GLM API (glm@, zhipu@)",
98163
- keyUrl: "https://open.bigmodel.cn/",
98164
- aliases: ["GLM_API_KEY"],
98165
- endpointEnvVar: "ZHIPU_BASE_URL",
98166
- defaultEndpoint: "https://open.bigmodel.cn"
98167
- },
98168
- {
98169
- name: "zai",
98170
- displayName: "Z.AI",
98171
- apiKeyEnvVar: "ZAI_API_KEY",
98172
- description: "Z.AI API (zai@)",
98173
- keyUrl: "https://z.ai/",
98174
- endpointEnvVar: "ZAI_BASE_URL",
98175
- defaultEndpoint: "https://api.z.ai"
98176
- },
98177
- {
98178
- name: "ollamacloud",
98179
- displayName: "OllamaCloud",
98180
- apiKeyEnvVar: "OLLAMA_API_KEY",
98181
- description: "Cloud Ollama (oc@, llama@)",
98182
- keyUrl: "https://ollama.com/account",
98183
- endpointEnvVar: "OLLAMACLOUD_BASE_URL",
98184
- defaultEndpoint: "https://ollama.com"
98185
- },
98186
- {
98187
- name: "opencode",
98188
- displayName: "OpenCode Zen",
98189
- apiKeyEnvVar: "OPENCODE_API_KEY",
98190
- description: "OpenCode Zen (zen@) \u2014 optional for free models",
98191
- keyUrl: "https://opencode.ai/",
98192
- endpointEnvVar: "OPENCODE_BASE_URL",
98193
- defaultEndpoint: "https://opencode.ai/zen"
98194
- },
98195
- {
98196
- name: "litellm",
98197
- displayName: "LiteLLM",
98198
- apiKeyEnvVar: "LITELLM_API_KEY",
98199
- description: "LiteLLM proxy (ll@, litellm@)",
98200
- keyUrl: "https://docs.litellm.ai/",
98201
- endpointEnvVar: "LITELLM_BASE_URL"
98202
- },
98203
- {
98204
- name: "vertex",
98205
- displayName: "Vertex AI",
98206
- apiKeyEnvVar: "VERTEX_API_KEY",
98207
- description: "Vertex AI Express (v@, vertex@)",
98208
- keyUrl: "https://console.cloud.google.com/vertex-ai"
98209
- },
98210
- {
98211
- name: "poe",
98212
- displayName: "Poe",
98213
- apiKeyEnvVar: "POE_API_KEY",
98214
- description: "Poe API (poe@)",
98215
- keyUrl: "https://poe.com/"
98216
- }
98217
- ];
98333
+ init_provider_definitions();
98334
+ SKIP = new Set(["qwen", "native-anthropic"]);
98335
+ PROVIDERS = getAllProviders().filter((d2) => !SKIP.has(d2.name)).map(toProviderDef);
98218
98336
  });
98219
98337
 
98220
98338
  // src/tui/theme.ts
@@ -98271,7 +98389,11 @@ function App() {
98271
98389
  const [inputValue, setInputValue] = import_react13.useState("");
98272
98390
  const [routingPattern, setRoutingPattern] = import_react13.useState("");
98273
98391
  const [routingChain, setRoutingChain] = import_react13.useState("");
98392
+ const [chainSelected, setChainSelected] = import_react13.useState(new Set);
98393
+ const [chainOrder, setChainOrder] = import_react13.useState([]);
98394
+ const [chainCursor, setChainCursor] = import_react13.useState(0);
98274
98395
  const [statusMsg, setStatusMsg] = import_react13.useState(null);
98396
+ const CHAIN_PROVIDERS = PROVIDERS;
98275
98397
  const quit = import_react13.useCallback(() => renderer.destroy(), [renderer]);
98276
98398
  const displayProviders = import_react13.useMemo(() => {
98277
98399
  return [...PROVIDERS].sort((a, b2) => {
@@ -98332,30 +98454,75 @@ function App() {
98332
98454
  }
98333
98455
  if (mode === "add_routing_pattern") {
98334
98456
  if (key.name === "return" || key.name === "enter") {
98335
- if (routingPattern.trim())
98457
+ if (routingPattern.trim()) {
98458
+ setChainSelected(new Set);
98459
+ setChainCursor(0);
98460
+ setChainOrder([]);
98336
98461
  setMode("add_routing_chain");
98462
+ }
98337
98463
  } else if (key.name === "escape") {
98464
+ setRoutingPattern("");
98338
98465
  setMode("browse");
98466
+ } else if (key.name === "backspace" || key.name === "delete") {
98467
+ setRoutingPattern((p) => p.slice(0, -1));
98468
+ } else if (key.raw && key.raw.length === 1 && !key.ctrl && !key.meta) {
98469
+ setRoutingPattern((p) => p + key.raw);
98339
98470
  }
98340
98471
  return;
98341
98472
  }
98342
98473
  if (mode === "add_routing_chain") {
98343
- if (key.name === "return" || key.name === "enter") {
98474
+ if (key.name === "up" || key.name === "k") {
98475
+ setChainCursor((i) => Math.max(0, i - 1));
98476
+ } else if (key.name === "down" || key.name === "j") {
98477
+ setChainCursor((i) => Math.min(CHAIN_PROVIDERS.length - 1, i + 1));
98478
+ } else if (key.name === "space" || key.raw === " ") {
98479
+ const provName = CHAIN_PROVIDERS[chainCursor].name;
98480
+ setChainSelected((prev) => {
98481
+ const next = new Set(prev);
98482
+ if (next.has(provName)) {
98483
+ next.delete(provName);
98484
+ setChainOrder((o) => o.filter((p) => p !== provName));
98485
+ } else {
98486
+ next.add(provName);
98487
+ setChainOrder((o) => [...o, provName]);
98488
+ }
98489
+ return next;
98490
+ });
98491
+ } else if (key.raw && key.raw >= "1" && key.raw <= "9") {
98492
+ const provName = CHAIN_PROVIDERS[chainCursor].name;
98493
+ const targetPos = parseInt(key.raw, 10) - 1;
98494
+ setChainSelected((prev) => {
98495
+ const next = new Set(prev);
98496
+ next.add(provName);
98497
+ return next;
98498
+ });
98499
+ setChainOrder((prev) => {
98500
+ const without = prev.filter((p) => p !== provName);
98501
+ const insertAt = Math.min(targetPos, without.length);
98502
+ without.splice(insertAt, 0, provName);
98503
+ return without;
98504
+ });
98505
+ } else if (key.name === "return" || key.name === "enter") {
98344
98506
  const pat = routingPattern.trim();
98345
- const ch = routingChain.trim().split(",").map((s) => s.trim()).filter(Boolean);
98346
- if (pat && ch.length) {
98507
+ if (pat && chainOrder.length) {
98347
98508
  const cfg = loadConfig();
98348
98509
  if (!cfg.routing)
98349
98510
  cfg.routing = {};
98350
- cfg.routing[pat] = ch;
98511
+ cfg.routing[pat] = chainOrder;
98351
98512
  saveConfig(cfg);
98352
98513
  refreshConfig();
98353
- setStatusMsg(`Rule added for '${pat}'.`);
98514
+ setStatusMsg(`Rule added: ${pat} \u2192 ${chainOrder.join(", ")}`);
98354
98515
  }
98355
98516
  setRoutingPattern("");
98356
98517
  setRoutingChain("");
98518
+ setChainSelected(new Set);
98519
+ setChainOrder([]);
98520
+ setChainCursor(0);
98357
98521
  setMode("browse");
98358
98522
  } else if (key.name === "escape") {
98523
+ setChainSelected(new Set);
98524
+ setChainOrder([]);
98525
+ setChainCursor(0);
98359
98526
  setMode("add_routing_pattern");
98360
98527
  }
98361
98528
  return;
@@ -98494,7 +98661,7 @@ function App() {
98494
98661
  const HEADER_H = 1;
98495
98662
  const TABS_H = 3;
98496
98663
  const FOOTER_H = 1;
98497
- const DETAIL_H = 5;
98664
+ const DETAIL_H = 7;
98498
98665
  const contentH = Math.max(4, height2 - HEADER_H - TABS_H - DETAIL_H - FOOTER_H - 1);
98499
98666
  function TabBar() {
98500
98667
  const tabs = [
@@ -98725,8 +98892,11 @@ function App() {
98725
98892
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98726
98893
  fg: C2.green,
98727
98894
  bold: true,
98728
- children: "Enter "
98729
- }, undefined, false, undefined, this),
98895
+ children: [
98896
+ "Enter",
98897
+ " "
98898
+ ]
98899
+ }, undefined, true, undefined, this),
98730
98900
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98731
98901
  fg: C2.fgMuted,
98732
98902
  children: "to save \xB7 "
@@ -98734,8 +98904,11 @@ function App() {
98734
98904
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98735
98905
  fg: C2.red,
98736
98906
  bold: true,
98737
- children: "Esc "
98738
- }, undefined, false, undefined, this),
98907
+ children: [
98908
+ "Esc",
98909
+ " "
98910
+ ]
98911
+ }, undefined, true, undefined, this),
98739
98912
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98740
98913
  fg: C2.fgMuted,
98741
98914
  children: "to cancel"
@@ -98749,8 +98922,11 @@ function App() {
98749
98922
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98750
98923
  fg: C2.green,
98751
98924
  bold: true,
98752
- children: "> "
98753
- }, undefined, false, undefined, this)
98925
+ children: [
98926
+ ">",
98927
+ " "
98928
+ ]
98929
+ }, undefined, true, undefined, this)
98754
98930
  }, undefined, false, undefined, this),
98755
98931
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("input", {
98756
98932
  value: inputValue,
@@ -98782,8 +98958,11 @@ function App() {
98782
98958
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98783
98959
  fg: C2.blue,
98784
98960
  bold: true,
98785
- children: "Status: "
98786
- }, undefined, false, undefined, this),
98961
+ children: [
98962
+ "Status:",
98963
+ " "
98964
+ ]
98965
+ }, undefined, true, undefined, this),
98787
98966
  hasKey ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98788
98967
  fg: C2.green,
98789
98968
  bold: true,
@@ -98799,8 +98978,11 @@ function App() {
98799
98978
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98800
98979
  fg: C2.blue,
98801
98980
  bold: true,
98802
- children: "Key: "
98803
- }, undefined, false, undefined, this),
98981
+ children: [
98982
+ "Key:",
98983
+ " "
98984
+ ]
98985
+ }, undefined, true, undefined, this),
98804
98986
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98805
98987
  fg: C2.green,
98806
98988
  children: displayKey
@@ -98821,8 +99003,11 @@ function App() {
98821
99003
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98822
99004
  fg: C2.blue,
98823
99005
  bold: true,
98824
- children: "URL: "
98825
- }, undefined, false, undefined, this),
99006
+ children: [
99007
+ "URL:",
99008
+ " "
99009
+ ]
99010
+ }, undefined, true, undefined, this),
98826
99011
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98827
99012
  fg: C2.cyan,
98828
99013
  children: activeEndpoint || selectedProvider.defaultEndpoint || "default"
@@ -98834,8 +99019,11 @@ function App() {
98834
99019
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98835
99020
  fg: C2.blue,
98836
99021
  bold: true,
98837
- children: "Desc: "
98838
- }, undefined, false, undefined, this),
99022
+ children: [
99023
+ "Desc:",
99024
+ " "
99025
+ ]
99026
+ }, undefined, true, undefined, this),
98839
99027
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98840
99028
  fg: C2.white,
98841
99029
  children: selectedProvider.description
@@ -98847,8 +99035,11 @@ function App() {
98847
99035
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98848
99036
  fg: C2.blue,
98849
99037
  bold: true,
98850
- children: "Get Key: "
98851
- }, undefined, false, undefined, this),
99038
+ children: [
99039
+ "Get Key:",
99040
+ " "
99041
+ ]
99042
+ }, undefined, true, undefined, this),
98852
99043
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98853
99044
  fg: C2.cyan,
98854
99045
  children: selectedProvider.keyUrl
@@ -98872,37 +99063,81 @@ function App() {
98872
99063
  flexDirection: "column",
98873
99064
  paddingX: 1,
98874
99065
  children: [
99066
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99067
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99068
+ fg: C2.blue,
99069
+ bold: true,
99070
+ children: " Default fallback chain:"
99071
+ }, undefined, false, undefined, this)
99072
+ }, undefined, false, undefined, this),
98875
99073
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
98876
99074
  children: [
98877
99075
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98878
99076
  fg: C2.dim,
98879
- children: " * "
99077
+ children: " "
98880
99078
  }, undefined, false, undefined, this),
98881
99079
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98882
- fg: C2.fgMuted,
98883
- children: "LiteLLM \u2192 Zen Go \u2192 Subscription \u2192 Provider Direct \u2192 OpenRouter"
99080
+ fg: C2.cyan,
99081
+ children: "LiteLLM"
99082
+ }, undefined, false, undefined, this),
99083
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99084
+ fg: C2.dim,
99085
+ children: " \u2192 "
99086
+ }, undefined, false, undefined, this),
99087
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99088
+ fg: C2.cyan,
99089
+ children: "Zen Go"
99090
+ }, undefined, false, undefined, this),
99091
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99092
+ fg: C2.dim,
99093
+ children: " \u2192 "
99094
+ }, undefined, false, undefined, this),
99095
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99096
+ fg: C2.cyan,
99097
+ children: "Subscription"
99098
+ }, undefined, false, undefined, this),
99099
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99100
+ fg: C2.dim,
99101
+ children: " \u2192 "
99102
+ }, undefined, false, undefined, this),
99103
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99104
+ fg: C2.cyan,
99105
+ children: "Provider Direct"
98884
99106
  }, undefined, false, undefined, this),
98885
99107
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98886
99108
  fg: C2.dim,
98887
- children: " (built-in)"
99109
+ children: " \u2192 "
99110
+ }, undefined, false, undefined, this),
99111
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99112
+ fg: C2.cyan,
99113
+ children: "OpenRouter"
98888
99114
  }, undefined, false, undefined, this)
98889
99115
  ]
98890
99116
  }, undefined, true, undefined, this),
98891
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
98892
- children: " "
98893
- }, undefined, false, undefined, this),
98894
99117
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
98895
99118
  children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98896
- fg: C2.blue,
98897
- bold: true,
98898
- children: " PATTERN CHAIN"
99119
+ fg: C2.dim,
99120
+ children: " \u2500".repeat(Math.max(1, Math.floor((width - 6) / 2)))
98899
99121
  }, undefined, false, undefined, this)
98900
99122
  }, undefined, false, undefined, this),
99123
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99124
+ children: [
99125
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99126
+ fg: C2.blue,
99127
+ bold: true,
99128
+ children: " Custom rules:"
99129
+ }, undefined, false, undefined, this),
99130
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99131
+ fg: C2.fgMuted,
99132
+ children: " (override default for matching models)"
99133
+ }, undefined, false, undefined, this)
99134
+ ]
99135
+ }, undefined, true, undefined, this),
98901
99136
  ruleEntries.length === 0 && !isRoutingInput && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
98902
99137
  children: [
98903
99138
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98904
99139
  fg: C2.fgMuted,
98905
- children: " No custom rules. Press "
99140
+ children: " None configured. Press "
98906
99141
  }, undefined, false, undefined, this),
98907
99142
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98908
99143
  fg: C2.green,
@@ -98911,7 +99146,7 @@ function App() {
98911
99146
  }, undefined, false, undefined, this),
98912
99147
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98913
99148
  fg: C2.fgMuted,
98914
- children: " to add one."
99149
+ children: " to add."
98915
99150
  }, undefined, false, undefined, this)
98916
99151
  ]
98917
99152
  }, undefined, true, undefined, this),
@@ -98974,23 +99209,20 @@ function App() {
98974
99209
  }, undefined, false, undefined, this)
98975
99210
  ]
98976
99211
  }, undefined, true, undefined, this),
98977
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
98978
- flexDirection: "row",
99212
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
98979
99213
  children: [
98980
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
98981
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
98982
- fg: C2.green,
98983
- bold: true,
98984
- children: "> "
98985
- }, undefined, false, undefined, this)
99214
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99215
+ fg: C2.green,
99216
+ bold: true,
99217
+ children: "> "
99218
+ }, undefined, false, undefined, this),
99219
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99220
+ fg: C2.white,
99221
+ children: routingPattern
98986
99222
  }, undefined, false, undefined, this),
98987
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("input", {
98988
- value: routingPattern,
98989
- onChange: setRoutingPattern,
98990
- focused: true,
98991
- width: width - 8,
98992
- backgroundColor: C2.bgHighlight,
98993
- textColor: C2.white
99223
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99224
+ fg: C2.cyan,
99225
+ children: "\u2588"
98994
99226
  }, undefined, false, undefined, this)
98995
99227
  ]
98996
99228
  }, undefined, true, undefined, this),
@@ -98999,8 +99231,11 @@ function App() {
98999
99231
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99000
99232
  fg: C2.green,
99001
99233
  bold: true,
99002
- children: "Enter "
99003
- }, undefined, false, undefined, this),
99234
+ children: [
99235
+ "Enter",
99236
+ " "
99237
+ ]
99238
+ }, undefined, true, undefined, this),
99004
99239
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99005
99240
  fg: C2.fgMuted,
99006
99241
  children: "to continue \xB7 "
@@ -99008,8 +99243,11 @@ function App() {
99008
99243
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99009
99244
  fg: C2.red,
99010
99245
  bold: true,
99011
- children: "Esc "
99012
- }, undefined, false, undefined, this),
99246
+ children: [
99247
+ "Esc",
99248
+ " "
99249
+ ]
99250
+ }, undefined, true, undefined, this),
99013
99251
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99014
99252
  fg: C2.fgMuted,
99015
99253
  children: "to cancel"
@@ -99026,7 +99264,7 @@ function App() {
99026
99264
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99027
99265
  fg: C2.blue,
99028
99266
  bold: true,
99029
- children: "Chain for "
99267
+ children: "Select providers for "
99030
99268
  }, undefined, false, undefined, this),
99031
99269
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99032
99270
  fg: C2.white,
@@ -99035,52 +99273,57 @@ function App() {
99035
99273
  }, undefined, false, undefined, this),
99036
99274
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99037
99275
  fg: C2.dim,
99038
- children: " (comma-separated providers):"
99039
- }, undefined, false, undefined, this)
99040
- ]
99041
- }, undefined, true, undefined, this),
99042
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
99043
- flexDirection: "row",
99044
- children: [
99045
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99046
- children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99047
- fg: C2.green,
99048
- bold: true,
99049
- children: "> "
99050
- }, undefined, false, undefined, this)
99051
- }, undefined, false, undefined, this),
99052
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("input", {
99053
- value: routingChain,
99054
- onChange: setRoutingChain,
99055
- focused: true,
99056
- width: width - 8,
99057
- backgroundColor: C2.bgHighlight,
99058
- textColor: C2.white
99276
+ children: " (Space=toggle, 1-9=set position, Enter=save)"
99059
99277
  }, undefined, false, undefined, this)
99060
99278
  ]
99061
99279
  }, undefined, true, undefined, this),
99062
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99280
+ chainOrder.length > 0 && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99063
99281
  children: [
99064
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99065
- fg: C2.green,
99066
- bold: true,
99067
- children: "Enter "
99068
- }, undefined, false, undefined, this),
99069
99282
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99070
99283
  fg: C2.fgMuted,
99071
- children: "to save \xB7 "
99284
+ children: " Chain: "
99072
99285
  }, undefined, false, undefined, this),
99073
99286
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99074
- fg: C2.red,
99075
- bold: true,
99076
- children: "Esc "
99077
- }, undefined, false, undefined, this),
99078
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99079
- fg: C2.fgMuted,
99080
- children: "to go back"
99287
+ fg: C2.cyan,
99288
+ children: chainOrder.join(" \u2192 ")
99081
99289
  }, undefined, false, undefined, this)
99082
99290
  ]
99083
- }, undefined, true, undefined, this)
99291
+ }, undefined, true, undefined, this),
99292
+ CHAIN_PROVIDERS.map((prov, idx) => {
99293
+ const isCursor = idx === chainCursor;
99294
+ const isOn = chainSelected.has(prov.name);
99295
+ const pos = isOn ? chainOrder.indexOf(prov.name) + 1 : 0;
99296
+ const hasKey2 = !!(config3.apiKeys?.[prov.apiKeyEnvVar] || process.env[prov.apiKeyEnvVar]);
99297
+ const label = prov.displayName.padEnd(18).substring(0, 18);
99298
+ return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
99299
+ height: 1,
99300
+ backgroundColor: isCursor ? C2.bgHighlight : C2.bg,
99301
+ children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99302
+ children: [
99303
+ isOn ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99304
+ fg: C2.green,
99305
+ bold: true,
99306
+ children: ` [${pos}] `
99307
+ }, undefined, false, undefined, this) : /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99308
+ fg: C2.dim,
99309
+ children: " [ ] "
99310
+ }, undefined, false, undefined, this),
99311
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99312
+ fg: isCursor ? C2.white : hasKey2 ? C2.fgMuted : C2.dim,
99313
+ bold: isCursor,
99314
+ children: label
99315
+ }, undefined, false, undefined, this),
99316
+ hasKey2 ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99317
+ fg: C2.green,
99318
+ children: " \u25CF"
99319
+ }, undefined, false, undefined, this) : /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99320
+ fg: C2.dim,
99321
+ children: " \u25CB no key"
99322
+ }, undefined, false, undefined, this)
99323
+ ]
99324
+ }, undefined, true, undefined, this)
99325
+ }, prov.name, false, undefined, this);
99326
+ })
99084
99327
  ]
99085
99328
  }, undefined, true, undefined, this)
99086
99329
  ]
@@ -99099,74 +99342,74 @@ function App() {
99099
99342
  children: [
99100
99343
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99101
99344
  children: [
99102
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99103
- fg: C2.dim,
99104
- children: "kimi-* "
99105
- }, undefined, false, undefined, this),
99106
99345
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99107
99346
  fg: C2.fgMuted,
99108
- children: "kimi \u2192 or"
99347
+ children: " kimi-* "
99109
99348
  }, undefined, false, undefined, this),
99110
99349
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99111
99350
  fg: C2.dim,
99112
- children: " "
99351
+ children: " \u2192 "
99113
99352
  }, undefined, false, undefined, this),
99114
99353
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99115
- fg: C2.dim,
99116
- children: "gpt-* "
99117
- }, undefined, false, undefined, this),
99354
+ fg: C2.cyan,
99355
+ children: "kimi, openrouter"
99356
+ }, undefined, false, undefined, this)
99357
+ ]
99358
+ }, undefined, true, undefined, this),
99359
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99360
+ children: [
99118
99361
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99119
99362
  fg: C2.fgMuted,
99120
- children: "oai \u2192 litellm"
99363
+ children: " gpt-* "
99121
99364
  }, undefined, false, undefined, this),
99122
99365
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99123
99366
  fg: C2.dim,
99124
- children: " "
99367
+ children: " \u2192 "
99125
99368
  }, undefined, false, undefined, this),
99126
99369
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99127
- fg: C2.dim,
99128
- children: "gemini-* "
99129
- }, undefined, false, undefined, this),
99130
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99131
- fg: C2.fgMuted,
99132
- children: "google \u2192 zen \u2192 or"
99370
+ fg: C2.cyan,
99371
+ children: "oai, litellm"
99133
99372
  }, undefined, false, undefined, this)
99134
99373
  ]
99135
99374
  }, undefined, true, undefined, this),
99136
99375
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99137
99376
  children: [
99138
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99139
- fg: C2.dim,
99140
- children: "glm-* "
99141
- }, undefined, false, undefined, this),
99142
99377
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99143
99378
  fg: C2.fgMuted,
99144
- children: "glm \u2192 zen \u2192 or"
99379
+ children: " gemini-* "
99145
99380
  }, undefined, false, undefined, this),
99146
99381
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99147
99382
  fg: C2.dim,
99148
- children: " "
99383
+ children: " \u2192 "
99149
99384
  }, undefined, false, undefined, this),
99150
99385
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99151
- fg: C2.dim,
99152
- children: "deepseek-* "
99153
- }, undefined, false, undefined, this),
99386
+ fg: C2.cyan,
99387
+ children: "google, zen, openrouter"
99388
+ }, undefined, false, undefined, this)
99389
+ ]
99390
+ }, undefined, true, undefined, this),
99391
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99392
+ children: [
99154
99393
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99155
99394
  fg: C2.fgMuted,
99156
- children: "zen \u2192 or"
99395
+ children: " deepseek-* "
99157
99396
  }, undefined, false, undefined, this),
99158
99397
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99159
99398
  fg: C2.dim,
99160
- children: " "
99399
+ children: " \u2192 "
99161
99400
  }, undefined, false, undefined, this),
99162
99401
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99163
- fg: C2.dim,
99164
- children: "Pattern: glob (* = any)"
99402
+ fg: C2.cyan,
99403
+ children: "zen, openrouter"
99165
99404
  }, undefined, false, undefined, this)
99166
99405
  ]
99167
99406
  }, undefined, true, undefined, this),
99168
99407
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
99169
99408
  children: [
99409
+ /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99410
+ fg: C2.dim,
99411
+ children: " Glob pattern (* = any). Chain tried left to right. "
99412
+ }, undefined, false, undefined, this),
99170
99413
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99171
99414
  fg: C2.cyan,
99172
99415
  bold: true,
@@ -99174,8 +99417,11 @@ function App() {
99174
99417
  }, undefined, false, undefined, this),
99175
99418
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99176
99419
  fg: C2.fgMuted,
99177
- children: ` custom rule${ruleEntries.length !== 1 ? "s" : ""}`
99178
- }, undefined, false, undefined, this)
99420
+ children: [
99421
+ " custom rule",
99422
+ ruleEntries.length !== 1 ? "s" : ""
99423
+ ]
99424
+ }, undefined, true, undefined, this)
99179
99425
  ]
99180
99426
  }, undefined, true, undefined, this)
99181
99427
  ]
@@ -99206,8 +99452,11 @@ function App() {
99206
99452
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99207
99453
  fg: C2.blue,
99208
99454
  bold: true,
99209
- children: "Status: "
99210
- }, undefined, false, undefined, this),
99455
+ children: [
99456
+ "Status:",
99457
+ " "
99458
+ ]
99459
+ }, undefined, true, undefined, this),
99211
99460
  telemetryEnabled ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99212
99461
  fg: C2.green,
99213
99462
  bold: true,
@@ -99281,8 +99530,11 @@ function App() {
99281
99530
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99282
99531
  fg: C2.blue,
99283
99532
  bold: true,
99284
- children: "Status: "
99285
- }, undefined, false, undefined, this),
99533
+ children: [
99534
+ "Status:",
99535
+ " "
99536
+ ]
99537
+ }, undefined, true, undefined, this),
99286
99538
  statsEnabled2 ? /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99287
99539
  fg: C2.green,
99288
99540
  bold: true,
@@ -99298,8 +99550,11 @@ function App() {
99298
99550
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99299
99551
  fg: C2.blue,
99300
99552
  bold: true,
99301
- children: "Buffer: "
99302
- }, undefined, false, undefined, this),
99553
+ children: [
99554
+ "Buffer:",
99555
+ " "
99556
+ ]
99557
+ }, undefined, true, undefined, this),
99303
99558
  /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("span", {
99304
99559
  fg: C2.white,
99305
99560
  bold: true,
@@ -99577,7 +99832,7 @@ __export(exports_team_cli, {
99577
99832
  teamCommand: () => teamCommand
99578
99833
  });
99579
99834
  import { readFileSync as readFileSync16 } from "fs";
99580
- import { join as join19 } from "path";
99835
+ import { join as join20 } from "path";
99581
99836
  function getFlag(args, flag) {
99582
99837
  const idx = args.indexOf(flag);
99583
99838
  if (idx === -1 || idx + 1 >= args.length)
@@ -99669,7 +99924,7 @@ async function teamCommand(args) {
99669
99924
  }
99670
99925
  case "judge": {
99671
99926
  const verdict = await judgeResponses(sessionPath, { judges });
99672
- console.log(readFileSync16(join19(sessionPath, "verdict.md"), "utf-8"));
99927
+ console.log(readFileSync16(join20(sessionPath, "verdict.md"), "utf-8"));
99673
99928
  break;
99674
99929
  }
99675
99930
  case "run-and-judge": {
@@ -99687,7 +99942,7 @@ async function teamCommand(args) {
99687
99942
  });
99688
99943
  printStatus(status);
99689
99944
  await judgeResponses(sessionPath, { judges });
99690
- console.log(readFileSync16(join19(sessionPath, "verdict.md"), "utf-8"));
99945
+ console.log(readFileSync16(join20(sessionPath, "verdict.md"), "utf-8"));
99691
99946
  break;
99692
99947
  }
99693
99948
  case "status": {
@@ -99713,11 +99968,17 @@ __export(exports_claude_runner, {
99713
99968
  checkClaudeInstalled: () => checkClaudeInstalled
99714
99969
  });
99715
99970
  import { spawn as spawn2 } from "child_process";
99716
- import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync7, mkdirSync as mkdirSync10, existsSync as existsSync19, readFileSync as readFileSync17 } from "fs";
99717
- import { tmpdir as tmpdir2, homedir as homedir17 } from "os";
99718
- import { join as join20 } from "path";
99971
+ import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync7, mkdirSync as mkdirSync10, existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
99972
+ import { tmpdir as tmpdir2, homedir as homedir18 } from "os";
99973
+ import { join as join21 } from "path";
99719
99974
  function hasNativeAnthropicMapping(config3) {
99720
- const models = [config3.model, config3.modelOpus, config3.modelSonnet, config3.modelHaiku, config3.modelSubagent];
99975
+ const models = [
99976
+ config3.model,
99977
+ config3.modelOpus,
99978
+ config3.modelSonnet,
99979
+ config3.modelHaiku,
99980
+ config3.modelSubagent
99981
+ ];
99721
99982
  return models.some((m2) => m2 && parseModelSpec(m2).provider === "native-anthropic");
99722
99983
  }
99723
99984
  function isWindows2() {
@@ -99725,9 +99986,9 @@ function isWindows2() {
99725
99986
  }
99726
99987
  function createStatusLineScript(tokenFilePath) {
99727
99988
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
99728
- const claudishDir = join20(homeDir, ".claudish");
99989
+ const claudishDir = join21(homeDir, ".claudish");
99729
99990
  const timestamp = Date.now();
99730
- const scriptPath = join20(claudishDir, `status-${timestamp}.js`);
99991
+ const scriptPath = join21(claudishDir, `status-${timestamp}.js`);
99731
99992
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
99732
99993
  const script = `
99733
99994
  const fs = require('fs');
@@ -99812,13 +100073,13 @@ process.stdin.on('end', () => {
99812
100073
  }
99813
100074
  function createTempSettingsFile(modelDisplay, port) {
99814
100075
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
99815
- const claudishDir = join20(homeDir, ".claudish");
100076
+ const claudishDir = join21(homeDir, ".claudish");
99816
100077
  try {
99817
100078
  mkdirSync10(claudishDir, { recursive: true });
99818
100079
  } catch {}
99819
100080
  const timestamp = Date.now();
99820
- const tempPath = join20(claudishDir, `settings-${timestamp}.json`);
99821
- const tokenFilePath = join20(claudishDir, `tokens-${port}.json`);
100081
+ const tempPath = join21(claudishDir, `settings-${timestamp}.json`);
100082
+ const tokenFilePath = join21(claudishDir, `tokens-${port}.json`);
99822
100083
  let statusCommand;
99823
100084
  if (isWindows2()) {
99824
100085
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -99946,8 +100207,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup, ptyDiagRunner) {
99946
100207
  console.error("Install it from: https://claude.com/claude-code");
99947
100208
  console.error(`
99948
100209
  Or set CLAUDE_PATH to your custom installation:`);
99949
- const home = homedir17();
99950
- const localPath = isWindows2() ? join20(home, ".claude", "local", "claude.exe") : join20(home, ".claude", "local", "claude");
100210
+ const home = homedir18();
100211
+ const localPath = isWindows2() ? join21(home, ".claude", "local", "claude.exe") : join21(home, ".claude", "local", "claude");
99951
100212
  console.error(` export CLAUDE_PATH=${localPath}`);
99952
100213
  process.exit(1);
99953
100214
  }
@@ -100001,23 +100262,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
100001
100262
  async function findClaudeBinary() {
100002
100263
  const isWindows3 = process.platform === "win32";
100003
100264
  if (process.env.CLAUDE_PATH) {
100004
- if (existsSync19(process.env.CLAUDE_PATH)) {
100265
+ if (existsSync20(process.env.CLAUDE_PATH)) {
100005
100266
  return process.env.CLAUDE_PATH;
100006
100267
  }
100007
100268
  }
100008
- const home = homedir17();
100009
- const localPath = isWindows3 ? join20(home, ".claude", "local", "claude.exe") : join20(home, ".claude", "local", "claude");
100010
- if (existsSync19(localPath)) {
100269
+ const home = homedir18();
100270
+ const localPath = isWindows3 ? join21(home, ".claude", "local", "claude.exe") : join21(home, ".claude", "local", "claude");
100271
+ if (existsSync20(localPath)) {
100011
100272
  return localPath;
100012
100273
  }
100013
100274
  if (isWindows3) {
100014
100275
  const windowsPaths = [
100015
- join20(home, "AppData", "Roaming", "npm", "claude.cmd"),
100016
- join20(home, ".npm-global", "claude.cmd"),
100017
- join20(home, "node_modules", ".bin", "claude.cmd")
100276
+ join21(home, "AppData", "Roaming", "npm", "claude.cmd"),
100277
+ join21(home, ".npm-global", "claude.cmd"),
100278
+ join21(home, "node_modules", ".bin", "claude.cmd")
100018
100279
  ];
100019
100280
  for (const path2 of windowsPaths) {
100020
- if (existsSync19(path2)) {
100281
+ if (existsSync20(path2)) {
100021
100282
  return path2;
100022
100283
  }
100023
100284
  }
@@ -100025,14 +100286,14 @@ async function findClaudeBinary() {
100025
100286
  const commonPaths = [
100026
100287
  "/usr/local/bin/claude",
100027
100288
  "/opt/homebrew/bin/claude",
100028
- join20(home, ".npm-global/bin/claude"),
100029
- join20(home, ".local/bin/claude"),
100030
- join20(home, "node_modules/.bin/claude"),
100289
+ join21(home, ".npm-global/bin/claude"),
100290
+ join21(home, ".local/bin/claude"),
100291
+ join21(home, "node_modules/.bin/claude"),
100031
100292
  "/data/data/com.termux/files/usr/bin/claude",
100032
- join20(home, "../usr/bin/claude")
100293
+ join21(home, "../usr/bin/claude")
100033
100294
  ];
100034
100295
  for (const path2 of commonPaths) {
100035
- if (existsSync19(path2)) {
100296
+ if (existsSync20(path2)) {
100036
100297
  return path2;
100037
100298
  }
100038
100299
  }
@@ -100081,21 +100342,22 @@ __export(exports_diag_output, {
100081
100342
  TmuxDiagOutput: () => TmuxDiagOutput,
100082
100343
  OpentUiDiagOutput: () => OpentUiDiagOutput,
100083
100344
  NullDiagOutput: () => NullDiagOutput,
100345
+ MtmDiagOutput: () => MtmDiagOutput,
100084
100346
  LogFileDiagOutput: () => LogFileDiagOutput
100085
100347
  });
100086
100348
  import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync11, writeFileSync as writeFileSync12, unlinkSync as unlinkSync8 } from "fs";
100087
100349
  import { execFileSync } from "child_process";
100088
- import { homedir as homedir18 } from "os";
100089
- import { join as join21 } from "path";
100350
+ import { homedir as homedir19 } from "os";
100351
+ import { join as join22 } from "path";
100090
100352
  function getClaudishDir() {
100091
- const dir = join21(homedir18(), ".claudish");
100353
+ const dir = join22(homedir19(), ".claudish");
100092
100354
  try {
100093
100355
  mkdirSync11(dir, { recursive: true });
100094
100356
  } catch {}
100095
100357
  return dir;
100096
100358
  }
100097
100359
  function getDiagLogPath() {
100098
- return join21(getClaudishDir(), `diag-${process.pid}.log`);
100360
+ return join22(getClaudishDir(), `diag-${process.pid}.log`);
100099
100361
  }
100100
100362
 
100101
100363
  class LogFileDiagOutput {
@@ -100131,22 +100393,27 @@ class LogFileDiagOutput {
100131
100393
  }
100132
100394
  }
100133
100395
 
100134
- class OpentUiDiagOutput {
100396
+ class MtmDiagOutput {
100135
100397
  runner;
100136
- messages = [];
100137
100398
  constructor(runner) {
100138
100399
  this.runner = runner;
100139
100400
  }
100140
100401
  write(msg) {
100141
- const level = msg.toLowerCase().includes("error") ? "error" : msg.toLowerCase().includes("warn") ? "warn" : "info";
100142
- this.messages.push({ text: msg, level });
100143
- if (this.messages.length > 4) {
100144
- this.messages = this.messages.slice(-4);
100145
- }
100146
- this.runner.showDiag(this.messages).catch(() => {});
100402
+ this.runner.write(msg);
100403
+ }
100404
+ cleanup() {}
100405
+ }
100406
+
100407
+ class OpentUiDiagOutput {
100408
+ inner;
100409
+ constructor(runner) {
100410
+ this.inner = new MtmDiagOutput(runner);
100411
+ }
100412
+ write(msg) {
100413
+ this.inner.write(msg);
100147
100414
  }
100148
100415
  cleanup() {
100149
- this.runner.hideDiag();
100416
+ this.inner.cleanup();
100150
100417
  }
100151
100418
  }
100152
100419
 
@@ -100162,9 +100429,10 @@ function createDiagOutput(options) {
100162
100429
  if (mode === "off") {
100163
100430
  return new NullDiagOutput;
100164
100431
  }
100432
+ const mtmRunner = options.mtmRunner ?? options.ptyRunner ?? null;
100165
100433
  if (mode === "pty" || mode === "auto") {
100166
- if (options.ptyRunner) {
100167
- return new OpentUiDiagOutput(options.ptyRunner);
100434
+ if (mtmRunner) {
100435
+ return new MtmDiagOutput(mtmRunner);
100168
100436
  }
100169
100437
  if (mode === "pty") {
100170
100438
  return new LogFileDiagOutput;
@@ -100196,7 +100464,10 @@ var init_diag_output = __esm(() => {
100196
100464
  args.push("-t", targetPane);
100197
100465
  }
100198
100466
  args.push("tail", "-f", this.logPath);
100199
- const output = execFileSync("tmux", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
100467
+ const output = execFileSync("tmux", args, {
100468
+ encoding: "utf-8",
100469
+ stdio: ["pipe", "pipe", "pipe"]
100470
+ });
100200
100471
  this.paneId = output.trim();
100201
100472
  } catch {
100202
100473
  this.paneId = null;
@@ -100216,213 +100487,199 @@ var init_diag_output = __esm(() => {
100216
100487
  };
100217
100488
  });
100218
100489
 
100219
- // src/tui/DiagPanel.tsx
100220
- function DiagPanel({ messages }) {
100221
- const { width } = useTerminalDimensions();
100222
- const panelWidth = Math.max(1, width);
100223
- const separator = "\u2500".repeat(panelWidth);
100224
- return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
100225
- x: 0,
100226
- y: 0,
100227
- width: panelWidth,
100228
- height: 5,
100229
- backgroundColor: "#1a1a2e",
100230
- children: [
100231
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
100232
- x: 0,
100233
- y: 0,
100234
- content: separator,
100235
- color: "#44475a"
100236
- }, undefined, false, undefined, this),
100237
- messages.slice(-3).map((msg, i) => {
100238
- const prefix = LEVEL_PREFIX[msg.level];
100239
- const color = LEVEL_COLORS[msg.level];
100240
- const maxTextLen = Math.max(1, panelWidth - prefix.length - 1);
100241
- const truncated = msg.text.length > maxTextLen ? `${msg.text.slice(0, maxTextLen - 1)}\u2026` : msg.text;
100242
- return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
100243
- x: 0,
100244
- y: i + 1,
100245
- content: `${prefix} ${truncated}`,
100246
- color
100247
- }, `msg-${i}`, false, undefined, this);
100248
- }),
100249
- messages.length < 3 && Array.from({ length: 3 - messages.length }).map((_2, i) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
100250
- x: 0,
100251
- y: messages.length + i + 1,
100252
- content: ""
100253
- }, `empty-${i}`, false, undefined, this)),
100254
- /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
100255
- x: 0,
100256
- y: 4,
100257
- content: "Press ESC to dismiss",
100258
- color: "#6272a4"
100259
- }, undefined, false, undefined, this)
100260
- ]
100261
- }, undefined, true, undefined, this);
100262
- }
100263
- var LEVEL_COLORS, LEVEL_PREFIX;
100264
- var init_DiagPanel = __esm(async () => {
100265
- init_jsx_dev_runtime();
100266
- await init_react();
100267
- LEVEL_COLORS = {
100268
- error: "#ff5555",
100269
- warn: "#ffb86c",
100270
- info: "#8be9fd"
100271
- };
100272
- LEVEL_PREFIX = {
100273
- error: "[ERROR]",
100274
- warn: "[WARN] ",
100275
- info: "[INFO] "
100276
- };
100277
- });
100278
-
100279
100490
  // src/pty-diag-runner.ts
100280
100491
  var exports_pty_diag_runner = {};
100281
100492
  __export(exports_pty_diag_runner, {
100282
100493
  tryCreatePtyRunner: () => tryCreatePtyRunner,
100283
- PtyDiagRunner: () => PtyDiagRunner
100494
+ tryCreateMtmRunner: () => tryCreateMtmRunner,
100495
+ PtyDiagRunner: () => MtmDiagRunner,
100496
+ MtmDiagRunner: () => MtmDiagRunner
100284
100497
  });
100285
- import { writeSync as writeSync3 } from "fs";
100498
+ import { spawn as spawn3 } from "child_process";
100499
+ import { appendFileSync, createWriteStream as createWriteStream3, existsSync as existsSync21, mkdirSync as mkdirSync12, unlinkSync as unlinkSync9, writeFileSync as writeFileSync13 } from "fs";
100500
+ import { homedir as homedir20 } from "os";
100501
+ import { dirname as dirname6, join as join23 } from "path";
100502
+ import { execSync as execSync3 } from "child_process";
100503
+ import { fileURLToPath as fileURLToPath6 } from "url";
100286
100504
 
100287
- class PtyDiagRunner {
100288
- renderer = null;
100289
- bunProc = null;
100290
- messages = [];
100291
- autoHideTimer = null;
100292
- reactRoot = null;
100293
- rawStdinHandler = null;
100294
- rendererInitializing = false;
100295
- async run(command, args, env2) {
100296
- const cols = process.stdout.columns || 80;
100297
- const rows = process.stdout.rows || 24;
100298
- this.bunProc = Bun.spawn([command, ...args], {
100299
- terminal: {
100300
- cols,
100301
- rows,
100302
- data: (_terminal, data) => {
100303
- const buf = typeof data === "string" ? Buffer.from(data, "binary") : data;
100304
- writeSync3(1, buf);
100305
- }
100306
- },
100307
- cwd: process.cwd(),
100308
- env: env2
100505
+ class MtmDiagRunner {
100506
+ mtmProc = null;
100507
+ logPath;
100508
+ statusPath;
100509
+ logStream = null;
100510
+ constructor() {
100511
+ const dir = join23(homedir20(), ".claudish");
100512
+ try {
100513
+ mkdirSync12(dir, { recursive: true });
100514
+ } catch {}
100515
+ this.logPath = join23(dir, `diag-${process.pid}.log`);
100516
+ this.statusPath = join23(dir, `status-${process.pid}.txt`);
100517
+ this.logStream = createWriteStream3(this.logPath, { flags: "w" });
100518
+ this.logStream.on("error", () => {});
100519
+ try {
100520
+ writeFileSync13(this.statusPath, renderStatusBar({ model: "", provider: "", errorCount: 0, lastError: "" }) + `
100521
+ `);
100522
+ } catch {}
100523
+ }
100524
+ async run(claudeCommand, claudeArgs, env2) {
100525
+ const mtmBin = this.findMtmBinary();
100526
+ const quotedArgs = claudeArgs.map((a) => shellQuote(a)).join(" ");
100527
+ const claudeCmd = `${shellQuote(claudeCommand)} ${quotedArgs}`;
100528
+ const mergedEnv = { ...process.env, ...env2 };
100529
+ this.mtmProc = spawn3(mtmBin, ["-e", claudeCmd, "-S", this.statusPath], {
100530
+ stdio: "inherit",
100531
+ env: mergedEnv
100532
+ });
100533
+ const exitCode = await new Promise((resolve4) => {
100534
+ this.mtmProc.on("exit", (code) => resolve4(code ?? 1));
100535
+ this.mtmProc.on("error", () => resolve4(1));
100309
100536
  });
100310
- const startTime = Date.now();
100311
- const GRACE_PERIOD_MS = 2000;
100312
- this.rawStdinHandler = (chunk) => {
100313
- if (!this.bunProc?.terminal)
100314
- return;
100315
- const str = typeof chunk === "string" ? chunk : chunk.toString("binary");
100316
- if (Date.now() - startTime < GRACE_PERIOD_MS) {
100317
- if (str.includes("\x1B"))
100318
- return;
100319
- }
100320
- this.bunProc.terminal.write(str);
100321
- };
100322
- process.stdin.on("data", this.rawStdinHandler);
100323
- const resizeHandler = () => {
100324
- if (this.bunProc?.terminal) {
100325
- try {
100326
- this.bunProc.terminal.resize(process.stdout.columns || 80, process.stdout.rows || 24);
100327
- } catch {}
100328
- }
100329
- };
100330
- process.on("SIGWINCH", resizeHandler);
100331
- await this.bunProc.exited;
100332
- const exitCode = this.bunProc.exitCode ?? 1;
100333
- process.removeListener("SIGWINCH", resizeHandler);
100334
100537
  this.cleanup();
100335
100538
  return exitCode;
100336
100539
  }
100337
- async showDiag(messages) {
100338
- this.messages = messages.slice(-4);
100339
- if (!this.renderer && !this.rendererInitializing) {
100340
- this.rendererInitializing = true;
100341
- try {
100342
- this.renderer = await createCliRenderer({
100343
- useAlternateScreen: false,
100344
- experimental_splitHeight: 5,
100345
- exitOnCtrlC: false,
100346
- useMouse: false,
100347
- useKittyKeyboard: null,
100348
- targetFps: 10
100349
- });
100350
- this.reactRoot = createRoot(this.renderer);
100351
- this.renderDiagPanel();
100352
- } catch {
100353
- this.rendererInitializing = false;
100354
- return;
100355
- }
100356
- this.rendererInitializing = false;
100357
- } else if (this.renderer) {
100358
- if (this.renderer.experimental_splitHeight === 0) {
100359
- this.renderer.experimental_splitHeight = 5;
100360
- }
100361
- this.renderDiagPanel();
100362
- }
100363
- if (this.autoHideTimer)
100364
- clearTimeout(this.autoHideTimer);
100365
- this.autoHideTimer = setTimeout(() => this.hideDiag(), 1e4);
100366
- }
100367
- hideDiag() {
100368
- if (!this.renderer)
100540
+ write(msg) {
100541
+ if (!this.logStream)
100369
100542
  return;
100370
- if (this.autoHideTimer) {
100371
- clearTimeout(this.autoHideTimer);
100372
- this.autoHideTimer = null;
100373
- }
100374
- this.renderer.experimental_splitHeight = 0;
100543
+ const timestamp = new Date().toISOString();
100544
+ try {
100545
+ this.logStream.write(`[${timestamp}] ${msg}
100546
+ `);
100547
+ } catch {}
100548
+ const parsed = parseLogMessage(msg);
100549
+ if (parsed.isError) {
100550
+ this.errorCount++;
100551
+ this.lastError = parsed.short;
100552
+ if (parsed.provider)
100553
+ this.provider = parsed.provider;
100554
+ }
100555
+ this.refreshStatusBar();
100556
+ }
100557
+ modelName = "";
100558
+ provider = "";
100559
+ lastError = "";
100560
+ errorCount = 0;
100561
+ setModel(name) {
100562
+ this.modelName = name.includes("/") ? name.split("/").pop() : name;
100563
+ if (name.includes("@")) {
100564
+ this.provider = name.split("@")[0];
100565
+ } else if (name.includes("/")) {
100566
+ this.provider = name.split("/")[0];
100567
+ }
100568
+ this.refreshStatusBar();
100569
+ }
100570
+ refreshStatusBar() {
100571
+ const bar = renderStatusBar({
100572
+ model: this.modelName,
100573
+ provider: this.provider,
100574
+ errorCount: this.errorCount,
100575
+ lastError: this.lastError
100576
+ });
100577
+ try {
100578
+ appendFileSync(this.statusPath, bar + `
100579
+ `);
100580
+ } catch {}
100375
100581
  }
100376
- renderDiagPanel() {
100377
- if (!this.reactRoot)
100378
- return;
100379
- this.reactRoot.render(import_react17.createElement(DiagPanel, { messages: this.messages }));
100582
+ getLogPath() {
100583
+ return this.logPath;
100380
100584
  }
100381
100585
  cleanup() {
100382
- if (this.autoHideTimer) {
100383
- clearTimeout(this.autoHideTimer);
100384
- this.autoHideTimer = null;
100385
- }
100386
- if (this.rawStdinHandler) {
100387
- process.stdin.removeListener("data", this.rawStdinHandler);
100388
- this.rawStdinHandler = null;
100389
- }
100390
- if (this.bunProc) {
100391
- try {
100392
- this.bunProc.kill();
100393
- } catch {}
100586
+ if (this.logStream) {
100394
100587
  try {
100395
- this.bunProc.terminal?.close();
100588
+ this.logStream.end();
100396
100589
  } catch {}
100397
- this.bunProc = null;
100590
+ this.logStream = null;
100398
100591
  }
100399
- if (this.renderer && !this.renderer.isDestroyed) {
100592
+ try {
100593
+ unlinkSync9(this.logPath);
100594
+ } catch {}
100595
+ try {
100596
+ unlinkSync9(this.statusPath);
100597
+ } catch {}
100598
+ if (this.mtmProc) {
100400
100599
  try {
100401
- this.renderer.destroy();
100600
+ this.mtmProc.kill();
100402
100601
  } catch {}
100403
- this.renderer = null;
100602
+ this.mtmProc = null;
100603
+ }
100604
+ }
100605
+ findMtmBinary() {
100606
+ const thisFile = fileURLToPath6(import.meta.url);
100607
+ const thisDir = dirname6(thisFile);
100608
+ const platform3 = process.platform;
100609
+ const arch = process.arch;
100610
+ const bundledPlatform = join23(thisDir, "..", "..", "native", "mtm", `mtm-${platform3}-${arch}`);
100611
+ if (existsSync21(bundledPlatform))
100612
+ return bundledPlatform;
100613
+ const builtDev = join23(thisDir, "..", "native", "mtm", "mtm");
100614
+ if (existsSync21(builtDev))
100615
+ return builtDev;
100616
+ try {
100617
+ const result = execSync3("which mtm", { encoding: "utf-8" }).trim();
100618
+ if (result)
100619
+ return result;
100620
+ } catch {}
100621
+ throw new Error("mtm binary not found. Build it with: cd packages/cli/native/mtm && make");
100622
+ }
100623
+ }
100624
+ function shellQuote(s) {
100625
+ return "'" + s.replace(/'/g, "'\\''") + "'";
100626
+ }
100627
+ function renderStatusBar(state) {
100628
+ const { model, provider, errorCount, lastError } = state;
100629
+ const parts = [];
100630
+ parts.push("M: claudish ");
100631
+ if (model)
100632
+ parts.push(`C: ${model} `);
100633
+ if (provider)
100634
+ parts.push(`D: ${provider} `);
100635
+ if (errorCount > 0) {
100636
+ const errLabel = errorCount === 1 ? " \u26A0 1 error " : ` \u26A0 ${errorCount} errors `;
100637
+ parts.push(`R:${errLabel}`);
100638
+ if (lastError)
100639
+ parts.push(`D: ${lastError} `);
100640
+ } else {
100641
+ parts.push("G: \u25CF ok ");
100642
+ }
100643
+ return parts.join("\t");
100644
+ }
100645
+ function parseLogMessage(msg) {
100646
+ const providerMatch = msg.match(/\[(\w+)\]/);
100647
+ const provider = providerMatch?.[1];
100648
+ const httpMatch = msg.match(/HTTP (\d{3})/);
100649
+ if (httpMatch) {
100650
+ const jsonMatch = msg.match(/"message"\s*:\s*"([^"]+)"/);
100651
+ if (jsonMatch?.[1]) {
100652
+ const detail = jsonMatch[1].replace(/is not a valid model ID/, "invalid model").replace(/Provider returned error/, "provider error");
100653
+ return { isError: true, short: detail, provider };
100654
+ }
100655
+ const hintMatch = msg.match(/HTTP \d{3}\.\s*(.+?)\.?\s*$/);
100656
+ if (hintMatch?.[1]) {
100657
+ return { isError: true, short: hintMatch[1], provider };
100404
100658
  }
100659
+ return { isError: true, short: `HTTP ${httpMatch[1]}`, provider };
100660
+ }
100661
+ if (msg.includes("[Fallback]")) {
100662
+ const countMatch = msg.match(/(\d+) provider/);
100663
+ return { isError: false, short: `fallback: ${countMatch?.[1] || "?"} providers`, provider };
100664
+ }
100665
+ if (msg.toLowerCase().includes("error")) {
100666
+ const short = msg.replace(/^Error\s*\[\w+\]:\s*/, "").replace(/\.\s*$/, "");
100667
+ return { isError: true, short: short.length > 40 ? short.slice(0, 39) + "\u2026" : short, provider };
100405
100668
  }
100669
+ return { isError: false, short: msg.length > 40 ? msg.slice(0, 39) + "\u2026" : msg };
100406
100670
  }
100407
- async function tryCreatePtyRunner() {
100671
+ async function tryCreateMtmRunner() {
100408
100672
  try {
100409
- if (typeof Bun === "undefined")
100410
- return null;
100411
- const test = Bun.spawn(["true"], { terminal: { cols: 1, rows: 1 } });
100412
- await test.exited;
100413
- return new PtyDiagRunner;
100673
+ const runner = new MtmDiagRunner;
100674
+ runner.findMtmBinary();
100675
+ return runner;
100414
100676
  } catch {
100415
100677
  return null;
100416
100678
  }
100417
100679
  }
100418
- var import_react17;
100419
- var init_pty_diag_runner = __esm(async () => {
100420
- await __promiseAll([
100421
- init_core3(),
100422
- init_react(),
100423
- init_DiagPanel()
100424
- ]);
100425
- import_react17 = __toESM(require_react(), 1);
100680
+ var tryCreatePtyRunner;
100681
+ var init_pty_diag_runner = __esm(() => {
100682
+ tryCreatePtyRunner = tryCreateMtmRunner;
100426
100683
  });
100427
100684
 
100428
100685
  // src/port-manager.ts
@@ -104008,9 +104265,9 @@ var init_middleware = __esm(() => {
104008
104265
  });
104009
104266
 
104010
104267
  // src/handlers/shared/token-tracker.ts
104011
- import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync13 } from "fs";
104012
- import { homedir as homedir19 } from "os";
104013
- import { join as join22 } from "path";
104268
+ import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync14 } from "fs";
104269
+ import { homedir as homedir21 } from "os";
104270
+ import { join as join24 } from "path";
104014
104271
 
104015
104272
  class TokenTracker {
104016
104273
  port;
@@ -104124,9 +104381,9 @@ class TokenTracker {
104124
104381
  is_free: isFreeModel,
104125
104382
  is_estimated: isEstimate || false
104126
104383
  };
104127
- const claudishDir = join22(homedir19(), ".claudish");
104128
- mkdirSync12(claudishDir, { recursive: true });
104129
- writeFileSync13(join22(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
104384
+ const claudishDir = join24(homedir21(), ".claudish");
104385
+ mkdirSync13(claudishDir, { recursive: true });
104386
+ writeFileSync14(join24(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
104130
104387
  } catch (e) {
104131
104388
  log(`[TokenTracker] Error writing token file: ${e}`);
104132
104389
  }
@@ -105095,7 +105352,7 @@ class ComposedHandler {
105095
105352
  if (Array.isArray(msg.content)) {
105096
105353
  for (let partIdx = 0;partIdx < msg.content.length; partIdx++) {
105097
105354
  const part = msg.content[partIdx];
105098
- if (part.type === "image_url") {
105355
+ if (part.type === "image_url" || part.type === "image" || part.type === "document") {
105099
105356
  imageBlocks.push({ msgIdx, partIdx, block: part });
105100
105357
  }
105101
105358
  }
@@ -105103,22 +105360,36 @@ class ComposedHandler {
105103
105360
  }
105104
105361
  if (imageBlocks.length > 0) {
105105
105362
  log(`[ComposedHandler] Non-vision model received ${imageBlocks.length} image(s), calling vision proxy`);
105106
- const auth = extractAuthHeaders(c);
105107
- const descriptions = await describeImages(imageBlocks.map((b2) => b2.block), auth);
105108
- if (descriptions !== null) {
105109
- for (let i = 0;i < imageBlocks.length; i++) {
105110
- const { msgIdx, partIdx } = imageBlocks[i];
105363
+ const openAIImageBlocks = imageBlocks.filter((b2) => b2.block.type === "image_url");
105364
+ let descriptions = null;
105365
+ if (openAIImageBlocks.length > 0) {
105366
+ const auth = extractAuthHeaders(c);
105367
+ descriptions = await describeImages(openAIImageBlocks.map((b2) => b2.block), auth);
105368
+ }
105369
+ if (descriptions !== null && openAIImageBlocks.length > 0) {
105370
+ for (let i = 0;i < openAIImageBlocks.length; i++) {
105371
+ const { msgIdx, partIdx } = openAIImageBlocks[i];
105111
105372
  messages[msgIdx].content[partIdx] = {
105112
105373
  type: "text",
105113
105374
  text: `[Image Description: ${descriptions[i]}]`
105114
105375
  };
105115
105376
  }
105116
105377
  log(`[ComposedHandler] Vision proxy described ${descriptions.length} image(s)`);
105378
+ for (const msg of messages) {
105379
+ if (Array.isArray(msg.content)) {
105380
+ msg.content = msg.content.filter((part) => part.type !== "image" && part.type !== "document");
105381
+ if (msg.content.length === 1 && msg.content[0].type === "text") {
105382
+ msg.content = msg.content[0].text;
105383
+ } else if (msg.content.length === 0) {
105384
+ msg.content = "";
105385
+ }
105386
+ }
105387
+ }
105117
105388
  } else {
105118
- log(`[ComposedHandler] Vision proxy failed, stripping images`);
105389
+ log(`[ComposedHandler] Stripping image/document blocks (vision not supported)`);
105119
105390
  for (const msg of messages) {
105120
105391
  if (Array.isArray(msg.content)) {
105121
- msg.content = msg.content.filter((part) => part.type !== "image_url");
105392
+ msg.content = msg.content.filter((part) => part.type !== "image_url" && part.type !== "image" && part.type !== "document");
105122
105393
  if (msg.content.length === 1 && msg.content[0].type === "text") {
105123
105394
  msg.content = msg.content[0].text;
105124
105395
  } else if (msg.content.length === 0) {
@@ -105548,9 +105819,9 @@ var init_composed_handler = __esm(() => {
105548
105819
  });
105549
105820
 
105550
105821
  // src/services/pricing-cache.ts
105551
- import { readFileSync as readFileSync18, writeFileSync as writeFileSync14, existsSync as existsSync20, mkdirSync as mkdirSync13, statSync as statSync2 } from "fs";
105552
- import { homedir as homedir20 } from "os";
105553
- import { join as join23 } from "path";
105822
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync15, existsSync as existsSync23, mkdirSync as mkdirSync14, statSync as statSync2 } from "fs";
105823
+ import { homedir as homedir22 } from "os";
105824
+ import { join as join25 } from "path";
105554
105825
  function getDynamicPricingSync(provider, modelName) {
105555
105826
  if (provider === "openrouter") {
105556
105827
  const direct = pricingMap.get(modelName);
@@ -105615,7 +105886,7 @@ async function warmPricingCache() {
105615
105886
  }
105616
105887
  function loadDiskCache() {
105617
105888
  try {
105618
- if (!existsSync20(CACHE_FILE))
105889
+ if (!existsSync23(CACHE_FILE))
105619
105890
  return false;
105620
105891
  const stat = statSync2(CACHE_FILE);
105621
105892
  const age = Date.now() - stat.mtimeMs;
@@ -105632,12 +105903,12 @@ function loadDiskCache() {
105632
105903
  }
105633
105904
  function saveDiskCache() {
105634
105905
  try {
105635
- mkdirSync13(CACHE_DIR, { recursive: true });
105906
+ mkdirSync14(CACHE_DIR, { recursive: true });
105636
105907
  const data = {};
105637
105908
  for (const [key, pricing] of pricingMap) {
105638
105909
  data[key] = pricing;
105639
105910
  }
105640
- writeFileSync14(CACHE_FILE, JSON.stringify(data), "utf-8");
105911
+ writeFileSync15(CACHE_FILE, JSON.stringify(data), "utf-8");
105641
105912
  } catch (error46) {
105642
105913
  log(`[PricingCache] Error saving disk cache: ${error46}`);
105643
105914
  }
@@ -105667,8 +105938,8 @@ var init_pricing_cache = __esm(() => {
105667
105938
  init_model_loader();
105668
105939
  init_remote_provider_types();
105669
105940
  pricingMap = new Map;
105670
- CACHE_DIR = join23(homedir20(), ".claudish");
105671
- CACHE_FILE = join23(CACHE_DIR, "pricing-cache.json");
105941
+ CACHE_DIR = join25(homedir22(), ".claudish");
105942
+ CACHE_FILE = join25(CACHE_DIR, "pricing-cache.json");
105672
105943
  CACHE_TTL_MS = 24 * 60 * 60 * 1000;
105673
105944
  PROVIDER_TO_OR_PREFIX = {
105674
105945
  openai: ["openai/"],
@@ -106127,11 +106398,11 @@ class AnthropicProviderTransport {
106127
106398
  }
106128
106399
  if (this.provider.name === "kimi-coding" && !this.apiKey) {
106129
106400
  try {
106130
- const { existsSync: existsSync21, readFileSync: readFileSync19 } = await import("fs");
106131
- const { join: join24 } = await import("path");
106132
- const { homedir: homedir21 } = await import("os");
106133
- const credPath = join24(homedir21(), ".claudish", "kimi-oauth.json");
106134
- if (existsSync21(credPath)) {
106401
+ const { existsSync: existsSync24, readFileSync: readFileSync19 } = await import("fs");
106402
+ const { join: join26 } = await import("path");
106403
+ const { homedir: homedir23 } = await import("os");
106404
+ const credPath = join26(homedir23(), ".claudish", "kimi-oauth.json");
106405
+ if (existsSync24(credPath)) {
106135
106406
  const data = JSON.parse(readFileSync19(credPath, "utf-8"));
106136
106407
  if (data.access_token && data.refresh_token) {
106137
106408
  const { KimiOAuth: KimiOAuth2 } = await Promise.resolve().then(() => (init_kimi_oauth(), exports_kimi_oauth));
@@ -106169,6 +106440,7 @@ var init_anthropic_compat = __esm(() => {
106169
106440
  var AnthropicAPIFormat;
106170
106441
  var init_anthropic_api_format = __esm(() => {
106171
106442
  init_base_api_format();
106443
+ init_model_catalog();
106172
106444
  AnthropicAPIFormat = class AnthropicAPIFormat extends BaseAPIFormat {
106173
106445
  providerName;
106174
106446
  constructor(modelId, providerName) {
@@ -106245,23 +106517,13 @@ var init_anthropic_api_format = __esm(() => {
106245
106517
  return "anthropic-sse";
106246
106518
  }
106247
106519
  getContextWindow() {
106248
- const model = this.modelId.toLowerCase();
106249
- if (model.includes("kimi-k2.5") || model.includes("kimi-k2-5"))
106250
- return 262144;
106251
- if (model.includes("kimi-k2"))
106252
- return 131000;
106253
- if (this.providerName === "kimi" || this.providerName === "kimi-coding" || model.includes("kimi")) {
106520
+ const catalogEntry = lookupModel(this.modelId);
106521
+ if (catalogEntry)
106522
+ return catalogEntry.contextWindow;
106523
+ if (this.providerName === "kimi" || this.providerName === "kimi-coding")
106254
106524
  return 131072;
106255
- }
106256
- if (model.includes("minimax-01") || model.includes("minimax-m1"))
106257
- return 1e6;
106258
- if (model.includes("minimax-m2.7"))
106525
+ if (this.providerName === "minimax" || this.providerName === "minimax-coding")
106259
106526
  return 204800;
106260
- if (model.includes("minimax-m2"))
106261
- return 196608;
106262
- if (this.providerName === "minimax" || this.providerName === "minimax-coding") {
106263
- return 196608;
106264
- }
106265
106527
  return 128000;
106266
106528
  }
106267
106529
  supportsVision() {
@@ -106442,10 +106704,10 @@ var init_litellm2 = __esm(() => {
106442
106704
  });
106443
106705
 
106444
106706
  // src/adapters/litellm-api-format.ts
106445
- import { existsSync as existsSync21, readFileSync as readFileSync19 } from "fs";
106707
+ import { existsSync as existsSync25, readFileSync as readFileSync19 } from "fs";
106446
106708
  import { createHash as createHash5 } from "crypto";
106447
- import { homedir as homedir21 } from "os";
106448
- import { join as join24 } from "path";
106709
+ import { homedir as homedir23 } from "os";
106710
+ import { join as join26 } from "path";
106449
106711
  var INLINE_IMAGE_MODEL_PATTERNS, LiteLLMAPIFormat;
106450
106712
  var init_litellm_api_format = __esm(() => {
106451
106713
  init_base_api_format();
@@ -106541,8 +106803,8 @@ var init_litellm_api_format = __esm(() => {
106541
106803
  checkVisionSupport() {
106542
106804
  try {
106543
106805
  const hash2 = createHash5("sha256").update(this.baseUrl).digest("hex").substring(0, 16);
106544
- const cachePath = join24(homedir21(), ".claudish", `litellm-models-${hash2}.json`);
106545
- if (!existsSync21(cachePath))
106806
+ const cachePath = join26(homedir23(), ".claudish", `litellm-models-${hash2}.json`);
106807
+ if (!existsSync25(cachePath))
106546
106808
  return true;
106547
106809
  const cacheData = JSON.parse(readFileSync19(cachePath, "utf-8"));
106548
106810
  const model = cacheData.models?.find((m2) => m2.name === this.modelId);
@@ -106561,9 +106823,9 @@ var init_litellm_api_format = __esm(() => {
106561
106823
  // src/auth/vertex-auth.ts
106562
106824
  import { exec as exec4 } from "child_process";
106563
106825
  import { promisify as promisify3 } from "util";
106564
- import { existsSync as existsSync23 } from "fs";
106565
- import { homedir as homedir22 } from "os";
106566
- import { join as join25 } from "path";
106826
+ import { existsSync as existsSync26 } from "fs";
106827
+ import { homedir as homedir24 } from "os";
106828
+ import { join as join27 } from "path";
106567
106829
 
106568
106830
  class VertexAuthManager {
106569
106831
  cachedToken = null;
@@ -106617,8 +106879,8 @@ class VertexAuthManager {
106617
106879
  }
106618
106880
  async tryADC() {
106619
106881
  try {
106620
- const adcPath = join25(homedir22(), ".config/gcloud/application_default_credentials.json");
106621
- if (!existsSync23(adcPath)) {
106882
+ const adcPath = join27(homedir24(), ".config/gcloud/application_default_credentials.json");
106883
+ if (!existsSync26(adcPath)) {
106622
106884
  log("[VertexAuth] ADC credentials file not found");
106623
106885
  return null;
106624
106886
  }
@@ -106642,7 +106904,7 @@ class VertexAuthManager {
106642
106904
  if (!credPath) {
106643
106905
  return null;
106644
106906
  }
106645
- if (!existsSync23(credPath)) {
106907
+ if (!existsSync26(credPath)) {
106646
106908
  throw new Error(`Service account file not found: ${credPath}
106647
106909
 
106648
106910
  Check GOOGLE_APPLICATION_CREDENTIALS path.`);
@@ -106681,8 +106943,8 @@ function validateVertexOAuthConfig() {
106681
106943
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
106682
106944
  ` + " export VERTEX_LOCATION='us-central1' # optional";
106683
106945
  }
106684
- const adcPath = join25(homedir22(), ".config/gcloud/application_default_credentials.json");
106685
- const hasADC = existsSync23(adcPath);
106946
+ const adcPath = join27(homedir24(), ".config/gcloud/application_default_credentials.json");
106947
+ const hasADC = existsSync26(adcPath);
106686
106948
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
106687
106949
  if (!hasADC && !hasServiceAccount) {
106688
106950
  return `No Vertex AI credentials found.
@@ -106814,6 +107076,7 @@ var init_provider_profiles = __esm(() => {
106814
107076
  init_ollama_api_format();
106815
107077
  init_litellm2();
106816
107078
  init_litellm_api_format();
107079
+ init_codex_api_format();
106817
107080
  init_vertex_oauth();
106818
107081
  init_base_api_format();
106819
107082
  init_remote_provider_registry();
@@ -106897,6 +107160,18 @@ var init_provider_profiles = __esm(() => {
106897
107160
  log(`[Proxy] Created OpenCode Zen${isGoProvider ? " Go" : ""} (Anthropic composed): ${ctx.modelName}`);
106898
107161
  return handler2;
106899
107162
  }
107163
+ if (ctx.modelName.toLowerCase().startsWith("gpt-")) {
107164
+ const responsesProvider = { ...ctx.provider, apiPath: "/v1/responses" };
107165
+ const transport2 = new OpenAIProviderTransport(responsesProvider, ctx.modelName, zenApiKey);
107166
+ const adapter2 = new CodexAPIFormat(ctx.modelName);
107167
+ const handler2 = new ComposedHandler(transport2, ctx.targetModel, ctx.modelName, ctx.port, {
107168
+ adapter: adapter2,
107169
+ tokenStrategy: "delta-aware",
107170
+ ...ctx.sharedOpts
107171
+ });
107172
+ log(`[Proxy] Created OpenCode Zen${isGoProvider ? " Go" : ""} (Responses API composed): ${ctx.modelName}`);
107173
+ return handler2;
107174
+ }
106900
107175
  const transport = new OpenAIProviderTransport(ctx.provider, ctx.modelName, zenApiKey);
106901
107176
  const adapter = new OpenAIAPIFormat(ctx.modelName);
106902
107177
  const handler = new ComposedHandler(transport, ctx.targetModel, ctx.modelName, ctx.port, {
@@ -107136,6 +107411,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
107136
107411
  }).catch(() => {});
107137
107412
  }
107138
107413
  warmZenModelCache().then(() => log("[Proxy] Zen model cache pre-warmed for fallback filtering")).catch(() => {});
107414
+ warmZenGoModelCache().then(() => log("[Proxy] Zen Go model cache pre-warmed for fallback filtering")).catch(() => {});
107139
107415
  const customRoutingRules = loadRoutingRules();
107140
107416
  const fallbackHandlerCache = new Map;
107141
107417
  const detectInvocationMode = (target, wasFromModelMap) => {
@@ -107325,14 +107601,14 @@ var init_proxy_server = __esm(() => {
107325
107601
 
107326
107602
  // src/index.ts
107327
107603
  var import_dotenv3 = __toESM(require_main(), 1);
107328
- import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
107329
- import { homedir as homedir23 } from "os";
107330
- import { join as join26 } from "path";
107604
+ import { existsSync as existsSync27, readFileSync as readFileSync21 } from "fs";
107605
+ import { homedir as homedir25 } from "os";
107606
+ import { join as join28 } from "path";
107331
107607
  import_dotenv3.config({ quiet: true });
107332
107608
  function loadStoredApiKeys() {
107333
107609
  try {
107334
- const configPath = join26(homedir23(), ".claudish", "config.json");
107335
- if (!existsSync25(configPath))
107610
+ const configPath = join28(homedir25(), ".claudish", "config.json");
107611
+ if (!existsSync27(configPath))
107336
107612
  return;
107337
107613
  const raw2 = readFileSync21(configPath, "utf-8");
107338
107614
  const cfg = JSON.parse(raw2);
@@ -107469,7 +107745,7 @@ async function runCli() {
107469
107745
  } = await Promise.resolve().then(() => (init_provider_resolver(), exports_provider_resolver));
107470
107746
  const { initLogger: initLogger2, getLogFilePath: getLogFilePath2, getAlwaysOnLogPath: getAlwaysOnLogPath2, setDiagOutput: setDiagOutput2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
107471
107747
  const { createDiagOutput: createDiagOutput2, LogFileDiagOutput: LogFileDiagOutput2 } = await Promise.resolve().then(() => (init_diag_output(), exports_diag_output));
107472
- const { tryCreatePtyRunner: tryCreatePtyRunner2 } = await init_pty_diag_runner().then(() => exports_pty_diag_runner);
107748
+ const { tryCreateMtmRunner: tryCreateMtmRunner2 } = await Promise.resolve().then(() => (init_pty_diag_runner(), exports_pty_diag_runner));
107473
107749
  const { findAvailablePort: findAvailablePort2 } = await Promise.resolve().then(() => (init_port_manager(), exports_port_manager));
107474
107750
  const { createProxyServer: createProxyServer2 } = await Promise.resolve().then(() => (init_proxy_server(), exports_proxy_server));
107475
107751
  const { checkForUpdates: checkForUpdates2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
@@ -107482,6 +107758,43 @@ async function runCli() {
107482
107758
  }
107483
107759
  try {
107484
107760
  const cliConfig = await parseArgs2(process.argv.slice(2));
107761
+ const rawArgs = process.argv.slice(2);
107762
+ const explicitNoAutoApprove = rawArgs.includes("--no-auto-approve");
107763
+ if (cliConfig.autoApprove && !explicitNoAutoApprove) {
107764
+ const { loadConfig: loadConfig2, saveConfig: saveConfig2 } = await Promise.resolve().then(() => (init_profile_config(), exports_profile_config));
107765
+ try {
107766
+ const cfg = loadConfig2();
107767
+ if (!cfg.autoApproveConfirmedAt) {
107768
+ const { createInterface: createInterface4 } = await import("readline");
107769
+ process.stderr.write(`
107770
+ [claudish] Auto-approve is enabled by default.
107771
+ This skips Claude Code permission prompts for tools like Bash, Read, Write.
107772
+ You can disable it anytime with: --no-auto-approve
107773
+
107774
+ `);
107775
+ const answer = await new Promise((resolve4) => {
107776
+ const rl = createInterface4({ input: process.stdin, output: process.stderr });
107777
+ rl.question("Enable auto-approve? [Y/n] ", (ans) => {
107778
+ rl.close();
107779
+ resolve4(ans.trim().toLowerCase());
107780
+ });
107781
+ });
107782
+ const declined = answer === "n" || answer === "no";
107783
+ if (declined) {
107784
+ cliConfig.autoApprove = false;
107785
+ process.stderr.write(`[claudish] Auto-approve disabled. Use -y to enable per-run.
107786
+
107787
+ `);
107788
+ } else {
107789
+ process.stderr.write(`[claudish] Auto-approve confirmed.
107790
+
107791
+ `);
107792
+ }
107793
+ cfg.autoApproveConfirmedAt = new Date().toISOString();
107794
+ saveConfig2(cfg);
107795
+ }
107796
+ } catch {}
107797
+ }
107485
107798
  initLogger2(cliConfig.debug, cliConfig.logLevel, cliConfig.noLogs);
107486
107799
  const { initTelemetry: initTelemetry2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
107487
107800
  initTelemetry2(cliConfig);
@@ -107587,22 +107900,25 @@ async function runCli() {
107587
107900
  quiet: cliConfig.quiet,
107588
107901
  isInteractive: cliConfig.interactive
107589
107902
  });
107590
- const needsPty = cliConfig.interactive && (cliConfig.diagMode === "auto" || cliConfig.diagMode === "pty");
107591
- const ptyRunner = needsPty ? await tryCreatePtyRunner2() : null;
107903
+ const needsMtm = cliConfig.interactive && (cliConfig.diagMode === "auto" || cliConfig.diagMode === "pty");
107904
+ const mtmRunner = needsMtm ? await tryCreateMtmRunner2() : null;
107905
+ if (mtmRunner && explicitModel) {
107906
+ mtmRunner.setModel(explicitModel);
107907
+ }
107592
107908
  const diag = createDiagOutput2({
107593
107909
  interactive: cliConfig.interactive,
107594
- ptyRunner,
107910
+ mtmRunner,
107595
107911
  diagMode: cliConfig.diagMode
107596
107912
  });
107597
107913
  if (cliConfig.interactive) {
107598
107914
  setDiagOutput2(diag);
107599
- if (!ptyRunner && !process.env.TMUX && !cliConfig.quiet && diag instanceof LogFileDiagOutput2) {
107915
+ if (!mtmRunner && !process.env.TMUX && !cliConfig.quiet && diag instanceof LogFileDiagOutput2) {
107600
107916
  console.log(`[claudish] Diagnostic log: ${diag.getLogPath()}`);
107601
107917
  }
107602
107918
  }
107603
107919
  let exitCode = 0;
107604
107920
  try {
107605
- exitCode = await runClaudeWithProxy2(cliConfig, proxy.url, () => diag.cleanup(), ptyRunner);
107921
+ exitCode = await runClaudeWithProxy2(cliConfig, proxy.url, () => diag.cleanup(), mtmRunner);
107606
107922
  } finally {
107607
107923
  setDiagOutput2(null);
107608
107924
  diag.cleanup();