claudish 5.14.0 → 5.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -28416,19 +28416,379 @@ var init_stdio2 = __esm(() => {
28416
28416
  init_stdio();
28417
28417
  });
28418
28418
 
28419
+ // src/team-orchestrator.ts
28420
+ import { spawn } from "child_process";
28421
+ import {
28422
+ mkdirSync,
28423
+ writeFileSync,
28424
+ readFileSync,
28425
+ existsSync,
28426
+ readdirSync,
28427
+ statSync,
28428
+ createWriteStream
28429
+ } from "fs";
28430
+ import { join, resolve } from "path";
28431
+ function validateSessionPath(sessionPath) {
28432
+ const resolved = resolve(sessionPath);
28433
+ const cwd = process.cwd();
28434
+ if (!resolved.startsWith(cwd + "/") && resolved !== cwd) {
28435
+ throw new Error(`Session path must be within current directory: ${sessionPath}`);
28436
+ }
28437
+ return resolved;
28438
+ }
28439
+ function setupSession(sessionPath, models, input) {
28440
+ if (models.length === 0) {
28441
+ throw new Error("At least one model is required");
28442
+ }
28443
+ mkdirSync(join(sessionPath, "work"), { recursive: true });
28444
+ mkdirSync(join(sessionPath, "errors"), { recursive: true });
28445
+ if (input !== undefined) {
28446
+ writeFileSync(join(sessionPath, "input.md"), input, "utf-8");
28447
+ } else if (!existsSync(join(sessionPath, "input.md"))) {
28448
+ throw new Error(`No input.md found at ${sessionPath} and no input provided`);
28449
+ }
28450
+ const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
28451
+ const shuffled = fisherYatesShuffle([...ids]);
28452
+ const now = new Date().toISOString();
28453
+ const manifest = {
28454
+ created: now,
28455
+ models: {},
28456
+ shuffleOrder: shuffled
28457
+ };
28458
+ for (let i = 0;i < models.length; i++) {
28459
+ const anonId = shuffled[i];
28460
+ manifest.models[anonId] = {
28461
+ model: models[i],
28462
+ assignedAt: now
28463
+ };
28464
+ mkdirSync(join(sessionPath, "work", anonId), { recursive: true });
28465
+ }
28466
+ writeFileSync(join(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
28467
+ const status = {
28468
+ startedAt: now,
28469
+ models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
28470
+ id,
28471
+ {
28472
+ state: "PENDING",
28473
+ exitCode: null,
28474
+ startedAt: null,
28475
+ completedAt: null,
28476
+ outputSize: 0
28477
+ }
28478
+ ]))
28479
+ };
28480
+ writeFileSync(join(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
28481
+ return manifest;
28482
+ }
28483
+ async function runModels(sessionPath, opts = {}) {
28484
+ const timeoutMs = (opts.timeout ?? 300) * 1000;
28485
+ const manifest = JSON.parse(readFileSync(join(sessionPath, "manifest.json"), "utf-8"));
28486
+ const statusPath = join(sessionPath, "status.json");
28487
+ const inputPath = join(sessionPath, "input.md");
28488
+ const inputContent = readFileSync(inputPath, "utf-8");
28489
+ const statusCache = JSON.parse(readFileSync(statusPath, "utf-8"));
28490
+ function updateModelStatus(id, update) {
28491
+ statusCache.models[id] = { ...statusCache.models[id], ...update };
28492
+ writeFileSync(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
28493
+ }
28494
+ const processes = new Map;
28495
+ const sigintHandler = () => {
28496
+ for (const [, proc] of processes) {
28497
+ if (!proc.killed)
28498
+ proc.kill("SIGTERM");
28499
+ }
28500
+ process.exit(1);
28501
+ };
28502
+ process.on("SIGINT", sigintHandler);
28503
+ const completionPromises = [];
28504
+ for (const [anonId, entry] of Object.entries(manifest.models)) {
28505
+ const outputPath = join(sessionPath, `response-${anonId}.md`);
28506
+ const errorLogPath = join(sessionPath, "errors", `${anonId}.log`);
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
+ ];
28516
+ updateModelStatus(anonId, {
28517
+ state: "RUNNING",
28518
+ startedAt: new Date().toISOString()
28519
+ });
28520
+ const proc = spawn("claudish", args, {
28521
+ cwd: workDir,
28522
+ stdio: ["pipe", "pipe", "pipe"],
28523
+ shell: false
28524
+ });
28525
+ const outputStream = createWriteStream(outputPath);
28526
+ proc.stdout?.pipe(outputStream);
28527
+ let stderr = "";
28528
+ proc.stderr?.on("data", (chunk) => {
28529
+ stderr += chunk.toString();
28530
+ });
28531
+ proc.stdin?.write(inputContent);
28532
+ proc.stdin?.end();
28533
+ const completionPromise = new Promise((resolve2) => {
28534
+ let exitCode = null;
28535
+ let resolved = false;
28536
+ const finish = () => {
28537
+ if (resolved)
28538
+ return;
28539
+ resolved = true;
28540
+ let outputSize = 0;
28541
+ try {
28542
+ outputSize = statSync(outputPath).size;
28543
+ } catch {}
28544
+ updateModelStatus(anonId, {
28545
+ state: exitCode === 0 ? "COMPLETED" : "FAILED",
28546
+ exitCode: exitCode ?? 1,
28547
+ completedAt: new Date().toISOString(),
28548
+ outputSize
28549
+ });
28550
+ opts.onStatusChange?.(anonId, statusCache.models[anonId]);
28551
+ resolve2();
28552
+ };
28553
+ outputStream.on("close", finish);
28554
+ proc.on("exit", (code) => {
28555
+ const current = statusCache.models[anonId];
28556
+ if (current?.state === "TIMEOUT") {
28557
+ resolved = true;
28558
+ resolve2();
28559
+ return;
28560
+ }
28561
+ if (stderr) {
28562
+ writeFileSync(errorLogPath, stderr, "utf-8");
28563
+ }
28564
+ exitCode = code;
28565
+ if (outputStream.destroyed) {
28566
+ finish();
28567
+ }
28568
+ });
28569
+ });
28570
+ processes.set(anonId, proc);
28571
+ completionPromises.push(completionPromise);
28572
+ }
28573
+ let timeoutHandle = null;
28574
+ await Promise.race([
28575
+ Promise.all(completionPromises),
28576
+ new Promise((resolve2) => {
28577
+ timeoutHandle = setTimeout(() => {
28578
+ for (const [id, proc] of processes) {
28579
+ if (!proc.killed) {
28580
+ proc.kill("SIGTERM");
28581
+ updateModelStatus(id, {
28582
+ state: "TIMEOUT",
28583
+ completedAt: new Date().toISOString()
28584
+ });
28585
+ opts.onStatusChange?.(id, statusCache.models[id]);
28586
+ }
28587
+ }
28588
+ resolve2();
28589
+ }, timeoutMs);
28590
+ })
28591
+ ]);
28592
+ if (timeoutHandle !== null)
28593
+ clearTimeout(timeoutHandle);
28594
+ process.off("SIGINT", sigintHandler);
28595
+ return statusCache;
28596
+ }
28597
+ async function judgeResponses(sessionPath, opts = {}) {
28598
+ const responseFiles = readdirSync(sessionPath).filter((f) => f.startsWith("response-") && f.endsWith(".md")).sort();
28599
+ if (responseFiles.length < 2) {
28600
+ throw new Error(`Need at least 2 responses to judge, found ${responseFiles.length}`);
28601
+ }
28602
+ const responses = {};
28603
+ for (const file2 of responseFiles) {
28604
+ const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
28605
+ responses[id] = readFileSync(join(sessionPath, file2), "utf-8");
28606
+ }
28607
+ const input = readFileSync(join(sessionPath, "input.md"), "utf-8");
28608
+ const judgePrompt = buildJudgePrompt(input, responses);
28609
+ writeFileSync(join(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
28610
+ const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
28611
+ const judgePath = join(sessionPath, "judging");
28612
+ mkdirSync(judgePath, { recursive: true });
28613
+ setupSession(judgePath, judgeModels, judgePrompt);
28614
+ await runModels(judgePath, { claudeFlags: opts.claudeFlags });
28615
+ const votes = parseJudgeVotes(judgePath, Object.keys(responses));
28616
+ const verdict = aggregateVerdict(votes, Object.keys(responses));
28617
+ writeFileSync(join(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
28618
+ return verdict;
28619
+ }
28620
+ function getStatus(sessionPath) {
28621
+ return JSON.parse(readFileSync(join(sessionPath, "status.json"), "utf-8"));
28622
+ }
28623
+ function fisherYatesShuffle(arr) {
28624
+ for (let i = arr.length - 1;i > 0; i--) {
28625
+ const j = Math.floor(Math.random() * (i + 1));
28626
+ [arr[i], arr[j]] = [arr[j], arr[i]];
28627
+ }
28628
+ return arr;
28629
+ }
28630
+ function getDefaultJudgeModels(sessionPath) {
28631
+ const manifest = JSON.parse(readFileSync(join(sessionPath, "manifest.json"), "utf-8"));
28632
+ return Object.values(manifest.models).map((e) => e.model);
28633
+ }
28634
+ function buildJudgePrompt(input, responses) {
28635
+ const ids = Object.keys(responses).sort();
28636
+ let prompt = `## Blind Evaluation Task
28637
+
28638
+ `;
28639
+ prompt += `### Original Task
28640
+
28641
+ `;
28642
+ prompt += input + `
28643
+
28644
+ `;
28645
+ prompt += `---
28646
+
28647
+ `;
28648
+ prompt += `### Responses to Evaluate
28649
+
28650
+ `;
28651
+ prompt += `Evaluate each response independently. You do not know which model produced which response.
28652
+
28653
+ `;
28654
+ for (const id of ids) {
28655
+ prompt += `#### Response ${id}
28656
+
28657
+ `;
28658
+ prompt += responses[id] + `
28659
+
28660
+ `;
28661
+ prompt += `---
28662
+
28663
+ `;
28664
+ }
28665
+ prompt += `### Your Assignment
28666
+
28667
+ `;
28668
+ prompt += `For EACH of the ${ids.length} responses above, provide a vote block in this exact format:
28669
+
28670
+ `;
28671
+ prompt += "```vote\n";
28672
+ prompt += `RESPONSE: [ID]
28673
+ `;
28674
+ prompt += `VERDICT: [APPROVE|REJECT|ABSTAIN]
28675
+ `;
28676
+ prompt += `CONFIDENCE: [1-10]
28677
+ `;
28678
+ prompt += `SUMMARY: [One sentence]
28679
+ `;
28680
+ prompt += `KEY_ISSUES: [Comma-separated issues, or None]
28681
+ `;
28682
+ prompt += "```\n\n";
28683
+ prompt += `Provide exactly ${ids.length} vote blocks, one per response. Be decisive and analytical.
28684
+ `;
28685
+ return prompt;
28686
+ }
28687
+ function parseJudgeVotes(judgePath, responseIds) {
28688
+ const votes = [];
28689
+ const responseFiles = readdirSync(judgePath).filter((f) => f.startsWith("response-") && f.endsWith(".md")).sort();
28690
+ for (const file2 of responseFiles) {
28691
+ const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
28692
+ let content;
28693
+ try {
28694
+ content = readFileSync(join(judgePath, file2), "utf-8");
28695
+ } catch {
28696
+ continue;
28697
+ }
28698
+ const votePattern = /```vote\s*\n([\s\S]*?)\n\s*```/g;
28699
+ let match;
28700
+ while ((match = votePattern.exec(content)) !== null) {
28701
+ const block = match[1];
28702
+ const responseMatch = block.match(/RESPONSE:\s*(\S+)/);
28703
+ const verdictMatch = block.match(/VERDICT:\s*(APPROVE|REJECT|ABSTAIN)/);
28704
+ const confidenceMatch = block.match(/CONFIDENCE:\s*(\d+)/);
28705
+ const summaryMatch = block.match(/SUMMARY:\s*(.+)/);
28706
+ const keyIssuesMatch = block.match(/KEY_ISSUES:\s*(.+)/);
28707
+ const responseId = responseMatch?.[1];
28708
+ const verdict = verdictMatch?.[1];
28709
+ if (!responseId || !verdict)
28710
+ continue;
28711
+ if (!responseIds.includes(responseId))
28712
+ continue;
28713
+ votes.push({
28714
+ judgeId,
28715
+ responseId,
28716
+ verdict,
28717
+ confidence: parseInt(confidenceMatch?.[1] ?? "5", 10),
28718
+ summary: summaryMatch?.[1]?.trim() ?? "",
28719
+ keyIssues: keyIssuesMatch?.[1]?.split(",").map((s) => s.trim()).filter((s) => s.toLowerCase() !== "none" && s.length > 0) ?? []
28720
+ });
28721
+ }
28722
+ }
28723
+ return votes;
28724
+ }
28725
+ function aggregateVerdict(votes, responseIds) {
28726
+ const responses = {};
28727
+ for (const id of responseIds) {
28728
+ const votesForResponse = votes.filter((v) => v.responseId === id);
28729
+ const approvals = votesForResponse.filter((v) => v.verdict === "APPROVE").length;
28730
+ const rejections = votesForResponse.filter((v) => v.verdict === "REJECT").length;
28731
+ const abstentions = votesForResponse.filter((v) => v.verdict === "ABSTAIN").length;
28732
+ const total = approvals + rejections;
28733
+ responses[id] = {
28734
+ approvals,
28735
+ rejections,
28736
+ abstentions,
28737
+ score: total > 0 ? approvals / total : 0
28738
+ };
28739
+ }
28740
+ const ranking = Object.entries(responses).sort(([, a], [, b]) => b.score - a.score).map(([id]) => id);
28741
+ return { responses, ranking, votes };
28742
+ }
28743
+ function formatVerdict(verdict, sessionPath) {
28744
+ let manifest = null;
28745
+ try {
28746
+ manifest = JSON.parse(readFileSync(join(sessionPath, "manifest.json"), "utf-8"));
28747
+ } catch {}
28748
+ let output = `# Team Verdict
28749
+
28750
+ `;
28751
+ output += `## Ranking
28752
+
28753
+ `;
28754
+ output += `| Rank | Response | Model | Score | Approvals | Rejections | Abstentions |
28755
+ `;
28756
+ output += `|------|----------|-------|-------|-----------|------------|-------------|
28757
+ `;
28758
+ for (let i = 0;i < verdict.ranking.length; i++) {
28759
+ const id = verdict.ranking[i];
28760
+ const r = verdict.responses[id];
28761
+ const modelName = manifest?.models[id]?.model ?? "unknown";
28762
+ const scoreStr = `${(r.score * 100).toFixed(0)}%`;
28763
+ output += `| ${i + 1} | ${id} | ${modelName} | ${scoreStr} | ${r.approvals} | ${r.rejections} | ${r.abstentions} |
28764
+ `;
28765
+ }
28766
+ output += `
28767
+ ## Individual Votes
28768
+
28769
+ `;
28770
+ for (const vote of verdict.votes) {
28771
+ const issueStr = vote.keyIssues.length > 0 ? ` Issues: ${vote.keyIssues.join(", ")}.` : "";
28772
+ output += `- **Judge ${vote.judgeId}** -> Response ${vote.responseId}: **${vote.verdict}** (${vote.confidence}/10) \u2014 ${vote.summary}${issueStr}
28773
+ `;
28774
+ }
28775
+ return output;
28776
+ }
28777
+ var init_team_orchestrator = () => {};
28778
+
28419
28779
  // src/mcp-server.ts
28420
28780
  var exports_mcp_server = {};
28421
28781
  __export(exports_mcp_server, {
28422
28782
  startMcpServer: () => startMcpServer
28423
28783
  });
28424
- import { readFileSync, existsSync, writeFileSync, mkdirSync } from "fs";
28425
- import { join, dirname } from "path";
28784
+ import { readFileSync as readFileSync2, existsSync as existsSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
28785
+ import { join as join2, dirname } from "path";
28426
28786
  import { homedir } from "os";
28427
28787
  import { fileURLToPath } from "url";
28428
28788
  function loadRecommendedModels() {
28429
- if (existsSync(RECOMMENDED_MODELS_PATH)) {
28789
+ if (existsSync2(RECOMMENDED_MODELS_PATH)) {
28430
28790
  try {
28431
- const data = JSON.parse(readFileSync(RECOMMENDED_MODELS_PATH, "utf-8"));
28791
+ const data = JSON.parse(readFileSync2(RECOMMENDED_MODELS_PATH, "utf-8"));
28432
28792
  return data.models || [];
28433
28793
  } catch {
28434
28794
  return [];
@@ -28437,9 +28797,9 @@ function loadRecommendedModels() {
28437
28797
  return [];
28438
28798
  }
28439
28799
  async function loadAllModels(forceRefresh = false) {
28440
- if (!forceRefresh && existsSync(ALL_MODELS_CACHE_PATH)) {
28800
+ if (!forceRefresh && existsSync2(ALL_MODELS_CACHE_PATH)) {
28441
28801
  try {
28442
- const cacheData = JSON.parse(readFileSync(ALL_MODELS_CACHE_PATH, "utf-8"));
28802
+ const cacheData = JSON.parse(readFileSync2(ALL_MODELS_CACHE_PATH, "utf-8"));
28443
28803
  const lastUpdated = new Date(cacheData.lastUpdated);
28444
28804
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
28445
28805
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -28453,15 +28813,15 @@ async function loadAllModels(forceRefresh = false) {
28453
28813
  throw new Error(`API returned ${response.status}`);
28454
28814
  const data = await response.json();
28455
28815
  const models = data.data || [];
28456
- mkdirSync(CLAUDISH_CACHE_DIR, { recursive: true });
28457
- writeFileSync(ALL_MODELS_CACHE_PATH, JSON.stringify({
28816
+ mkdirSync2(CLAUDISH_CACHE_DIR, { recursive: true });
28817
+ writeFileSync2(ALL_MODELS_CACHE_PATH, JSON.stringify({
28458
28818
  lastUpdated: new Date().toISOString(),
28459
28819
  models
28460
28820
  }), "utf-8");
28461
28821
  return models;
28462
28822
  } catch (error46) {
28463
- if (existsSync(ALL_MODELS_CACHE_PATH)) {
28464
- const cacheData = JSON.parse(readFileSync(ALL_MODELS_CACHE_PATH, "utf-8"));
28823
+ if (existsSync2(ALL_MODELS_CACHE_PATH)) {
28824
+ const cacheData = JSON.parse(readFileSync2(ALL_MODELS_CACHE_PATH, "utf-8"));
28465
28825
  return cacheData.models || [];
28466
28826
  }
28467
28827
  return [];
@@ -28488,7 +28848,7 @@ async function runPrompt(model, prompt, systemPrompt, maxTokens) {
28488
28848
  body: JSON.stringify({
28489
28849
  model,
28490
28850
  messages,
28491
- max_tokens: maxTokens || 4096
28851
+ ...maxTokens ? { max_tokens: maxTokens } : {}
28492
28852
  })
28493
28853
  });
28494
28854
  if (!response.ok) {
@@ -28526,7 +28886,7 @@ async function main() {
28526
28886
  model: exports_external.string().describe("OpenRouter model ID (e.g., 'x-ai/grok-code-fast-1', 'openai/gpt-5.1-codex')"),
28527
28887
  prompt: exports_external.string().describe("The prompt to send to the model"),
28528
28888
  system_prompt: exports_external.string().optional().describe("Optional system prompt"),
28529
- max_tokens: exports_external.number().optional().describe("Maximum tokens in response (default: 4096)")
28889
+ max_tokens: exports_external.number().optional().describe("Maximum tokens in response (omit to let model decide)")
28530
28890
  }, async ({ model, prompt, system_prompt, max_tokens }) => {
28531
28891
  try {
28532
28892
  const result = await runPrompt(model, prompt, system_prompt, max_tokens);
@@ -28633,12 +28993,13 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
28633
28993
  server.tool("compare_models", "Run the same prompt through multiple models and compare responses", {
28634
28994
  models: exports_external.array(exports_external.string()).describe("List of model IDs to compare"),
28635
28995
  prompt: exports_external.string().describe("The prompt to send to all models"),
28636
- system_prompt: exports_external.string().optional().describe("Optional system prompt")
28637
- }, async ({ models, prompt, system_prompt }) => {
28996
+ system_prompt: exports_external.string().optional().describe("Optional system prompt"),
28997
+ max_tokens: exports_external.number().optional().describe("Maximum tokens in response (omit to let model decide)")
28998
+ }, async ({ models, prompt, system_prompt, max_tokens }) => {
28638
28999
  const results = [];
28639
29000
  for (const model of models) {
28640
29001
  try {
28641
- const result = await runPrompt(model, prompt, system_prompt, 2048);
29002
+ const result = await runPrompt(model, prompt, system_prompt, max_tokens);
28642
29003
  results.push({
28643
29004
  model,
28644
29005
  response: result.content,
@@ -28682,6 +29043,93 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
28682
29043
  }
28683
29044
  return { content: [{ type: "text", text: output }] };
28684
29045
  });
29046
+ server.tool("team_run", "Run multiple AI models on a task and produce anonymized outputs in a session directory", {
29047
+ path: exports_external.string().describe("Session directory path (must be within current working directory)"),
29048
+ models: exports_external.array(exports_external.string()).describe("Model IDs to run (e.g., ['minimax-m2.5', 'kimi-k2.5'])"),
29049
+ input: exports_external.string().optional().describe("Task prompt text (or place input.md in the session directory before calling)"),
29050
+ timeout: exports_external.number().optional().describe("Per-model timeout in seconds (default: 300)")
29051
+ }, async ({ path, models, input, timeout }) => {
29052
+ try {
29053
+ const resolved = validateSessionPath(path);
29054
+ setupSession(resolved, models, input);
29055
+ const status = await runModels(resolved, { timeout });
29056
+ return { content: [{ type: "text", text: JSON.stringify(status, null, 2) }] };
29057
+ } catch (error46) {
29058
+ return {
29059
+ content: [
29060
+ {
29061
+ type: "text",
29062
+ text: `Error: ${error46 instanceof Error ? error46.message : String(error46)}`
29063
+ }
29064
+ ],
29065
+ isError: true
29066
+ };
29067
+ }
29068
+ });
29069
+ server.tool("team_judge", "Blind-judge existing anonymized model outputs in a session directory", {
29070
+ path: exports_external.string().describe("Session directory containing response-*.md files (must be within current working directory)"),
29071
+ judges: exports_external.array(exports_external.string()).optional().describe("Model IDs to use as judges (default: same models that produced the responses)")
29072
+ }, async ({ path, judges }) => {
29073
+ try {
29074
+ const resolved = validateSessionPath(path);
29075
+ const verdict = await judgeResponses(resolved, { judges });
29076
+ return { content: [{ type: "text", text: JSON.stringify(verdict, null, 2) }] };
29077
+ } catch (error46) {
29078
+ return {
29079
+ content: [
29080
+ {
29081
+ type: "text",
29082
+ text: `Error: ${error46 instanceof Error ? error46.message : String(error46)}`
29083
+ }
29084
+ ],
29085
+ isError: true
29086
+ };
29087
+ }
29088
+ });
29089
+ server.tool("team_run_and_judge", "Run multiple AI models on a task, then blind-judge their outputs \u2014 full pipeline", {
29090
+ path: exports_external.string().describe("Session directory path (must be within current working directory)"),
29091
+ models: exports_external.array(exports_external.string()).describe("Model IDs to run"),
29092
+ judges: exports_external.array(exports_external.string()).optional().describe("Model IDs to use as judges (default: same as runners)"),
29093
+ input: exports_external.string().optional().describe("Task prompt text"),
29094
+ timeout: exports_external.number().optional().describe("Per-model timeout in seconds (default: 300)")
29095
+ }, async ({ path, models, judges, input, timeout }) => {
29096
+ try {
29097
+ const resolved = validateSessionPath(path);
29098
+ setupSession(resolved, models, input);
29099
+ await runModels(resolved, { timeout });
29100
+ const verdict = await judgeResponses(resolved, { judges });
29101
+ return { content: [{ type: "text", text: JSON.stringify(verdict, null, 2) }] };
29102
+ } catch (error46) {
29103
+ return {
29104
+ content: [
29105
+ {
29106
+ type: "text",
29107
+ text: `Error: ${error46 instanceof Error ? error46.message : String(error46)}`
29108
+ }
29109
+ ],
29110
+ isError: true
29111
+ };
29112
+ }
29113
+ });
29114
+ server.tool("team_status", "Check the execution status of a team orchestrator session", {
29115
+ path: exports_external.string().describe("Session directory path (must be within current working directory)")
29116
+ }, async ({ path }) => {
29117
+ try {
29118
+ const resolved = validateSessionPath(path);
29119
+ const status = getStatus(resolved);
29120
+ return { content: [{ type: "text", text: JSON.stringify(status, null, 2) }] };
29121
+ } catch (error46) {
29122
+ return {
29123
+ content: [
29124
+ {
29125
+ type: "text",
29126
+ text: `Error: ${error46 instanceof Error ? error46.message : String(error46)}`
29127
+ }
29128
+ ],
29129
+ isError: true
29130
+ };
29131
+ }
29132
+ });
28685
29133
  const transport = new StdioServerTransport;
28686
29134
  await server.connect(transport);
28687
29135
  console.error("[claudish] MCP server started");
@@ -28697,21 +29145,24 @@ var init_mcp_server = __esm(() => {
28697
29145
  init_mcp();
28698
29146
  init_stdio2();
28699
29147
  init_zod();
29148
+ init_team_orchestrator();
28700
29149
  import_dotenv = __toESM(require_main(), 1);
28701
29150
  import_dotenv.config();
28702
29151
  __filename2 = fileURLToPath(import.meta.url);
28703
29152
  __dirname2 = dirname(__filename2);
28704
- RECOMMENDED_MODELS_PATH = join(__dirname2, "../recommended-models.json");
28705
- CLAUDISH_CACHE_DIR = join(homedir(), ".claudish");
28706
- ALL_MODELS_CACHE_PATH = join(CLAUDISH_CACHE_DIR, "all-models.json");
29153
+ RECOMMENDED_MODELS_PATH = join2(__dirname2, "../recommended-models.json");
29154
+ CLAUDISH_CACHE_DIR = join2(homedir(), ".claudish");
29155
+ ALL_MODELS_CACHE_PATH = join2(CLAUDISH_CACHE_DIR, "all-models.json");
28707
29156
  });
28708
29157
 
28709
29158
  // src/logger.ts
28710
29159
  var exports_logger = {};
28711
29160
  __export(exports_logger, {
28712
29161
  truncateContent: () => truncateContent,
29162
+ structuralRedact: () => structuralRedact,
28713
29163
  setStderrQuiet: () => setStderrQuiet,
28714
29164
  setLogLevel: () => setLogLevel,
29165
+ setDiagOutput: () => setDiagOutput,
28715
29166
  maskCredential: () => maskCredential,
28716
29167
  logStructured: () => logStructured,
28717
29168
  logStderr: () => logStderr,
@@ -28719,10 +29170,12 @@ __export(exports_logger, {
28719
29170
  isLoggingEnabled: () => isLoggingEnabled,
28720
29171
  initLogger: () => initLogger,
28721
29172
  getLogLevel: () => getLogLevel,
28722
- getLogFilePath: () => getLogFilePath
29173
+ getLogFilePath: () => getLogFilePath,
29174
+ getAlwaysOnLogPath: () => getAlwaysOnLogPath
28723
29175
  });
28724
- import { writeFileSync as writeFileSync2, appendFile, existsSync as existsSync2, mkdirSync as mkdirSync2 } from "fs";
28725
- import { join as join2 } from "path";
29176
+ import { writeFileSync as writeFileSync3, appendFile, existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync2, unlinkSync } from "fs";
29177
+ import { join as join3 } from "path";
29178
+ import { homedir as homedir2 } from "os";
28726
29179
  function flushLogBuffer() {
28727
29180
  if (!logFilePath || logBuffer.length === 0)
28728
29181
  return;
@@ -28734,11 +29187,19 @@ function flushLogBuffer() {
28734
29187
  }
28735
29188
  });
28736
29189
  }
29190
+ function flushAlwaysOnBuffer() {
29191
+ if (!alwaysOnLogPath || alwaysOnBuffer.length === 0)
29192
+ return;
29193
+ const toWrite = alwaysOnBuffer.join("");
29194
+ alwaysOnBuffer = [];
29195
+ appendFile(alwaysOnLogPath, toWrite, () => {});
29196
+ }
28737
29197
  function scheduleFlush() {
28738
29198
  if (flushTimer)
28739
29199
  return;
28740
29200
  flushTimer = setInterval(() => {
28741
29201
  flushLogBuffer();
29202
+ flushAlwaysOnBuffer();
28742
29203
  }, FLUSH_INTERVAL_MS);
28743
29204
  process.on("exit", () => {
28744
29205
  if (flushTimer) {
@@ -28746,33 +29207,106 @@ function scheduleFlush() {
28746
29207
  flushTimer = null;
28747
29208
  }
28748
29209
  if (logFilePath && logBuffer.length > 0) {
28749
- writeFileSync2(logFilePath, logBuffer.join(""), { flag: "a" });
29210
+ writeFileSync3(logFilePath, logBuffer.join(""), { flag: "a" });
28750
29211
  logBuffer = [];
28751
29212
  }
29213
+ if (alwaysOnLogPath && alwaysOnBuffer.length > 0) {
29214
+ writeFileSync3(alwaysOnLogPath, alwaysOnBuffer.join(""), { flag: "a" });
29215
+ alwaysOnBuffer = [];
29216
+ }
28752
29217
  });
28753
29218
  }
28754
- function initLogger(debugMode, level = "info") {
28755
- if (!debugMode) {
28756
- logFilePath = null;
28757
- if (flushTimer) {
28758
- clearInterval(flushTimer);
28759
- flushTimer = null;
29219
+ function rotateOldLogs(dir, keep) {
29220
+ try {
29221
+ const files = readdirSync2(dir).filter((f) => f.startsWith("claudish_") && f.endsWith(".log")).sort().reverse();
29222
+ for (const file2 of files.slice(keep)) {
29223
+ try {
29224
+ unlinkSync(join3(dir, file2));
29225
+ } catch {}
28760
29226
  }
28761
- return;
29227
+ } catch {}
29228
+ }
29229
+ function structuralRedact(jsonStr) {
29230
+ try {
29231
+ const obj = JSON.parse(jsonStr);
29232
+ return JSON.stringify(redactDeep(obj));
29233
+ } catch {
29234
+ return jsonStr.replace(/"[^"]{20,}"/g, (m) => `"<${m.length - 2} chars>"`);
28762
29235
  }
28763
- logLevel = level;
28764
- const logsDir = join2(process.cwd(), "logs");
28765
- if (!existsSync2(logsDir)) {
28766
- mkdirSync2(logsDir, { recursive: true });
29236
+ }
29237
+ function redactDeep(val, key) {
29238
+ if (val === null || val === undefined)
29239
+ return val;
29240
+ if (typeof val === "boolean" || typeof val === "number")
29241
+ return val;
29242
+ if (typeof val === "string") {
29243
+ if (key && CONTENT_KEYS.has(key)) {
29244
+ return `<${val.length} chars>`;
29245
+ }
29246
+ return val.length <= 20 ? val : `<${val.length} chars>`;
29247
+ }
29248
+ if (Array.isArray(val))
29249
+ return val.map((v) => redactDeep(v));
29250
+ if (typeof val === "object") {
29251
+ const result = {};
29252
+ for (const [k, v] of Object.entries(val)) {
29253
+ result[k] = redactDeep(v, k);
29254
+ }
29255
+ return result;
29256
+ }
29257
+ return val;
29258
+ }
29259
+ function isStructuralLogWorthy(msg) {
29260
+ return msg.startsWith("[SSE:") || msg.startsWith("[Proxy]") || msg.startsWith("[Fallback]") || msg.startsWith("[Streaming] ===") || msg.startsWith("[Streaming] Chunk:") || msg.startsWith("[Streaming] Received") || msg.startsWith("[Streaming] Text-based tool calls") || msg.startsWith("[Streaming] Final usage") || msg.startsWith("[Streaming] Sending") || msg.startsWith("[AnthropicSSE] Stream complete") || msg.startsWith("[AnthropicSSE] Tool use:") || msg.includes("Response status:") || msg.includes("Error") || msg.includes("error") || msg.includes("[Auto-route]");
29261
+ }
29262
+ function redactLogLine(message, timestamp) {
29263
+ if (message.startsWith("[SSE:")) {
29264
+ const prefixEnd = message.indexOf("] ") + 2;
29265
+ const prefix = message.substring(0, prefixEnd);
29266
+ const payload = message.substring(prefixEnd);
29267
+ return `[${timestamp}] ${prefix}${structuralRedact(payload)}
29268
+ `;
28767
29269
  }
28768
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-").split("T").join("_").slice(0, -5);
28769
- logFilePath = join2(logsDir, `claudish_${timestamp}.log`);
28770
- writeFileSync2(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
29270
+ return `[${timestamp}] ${message}
29271
+ `;
29272
+ }
29273
+ function initLogger(debugMode, level = "info", noLogs = false) {
29274
+ if (!noLogs) {
29275
+ const logsDir = join3(homedir2(), ".claudish", "logs");
29276
+ if (!existsSync3(logsDir)) {
29277
+ mkdirSync3(logsDir, { recursive: true });
29278
+ }
29279
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").split("T").join("_").slice(0, -5);
29280
+ alwaysOnLogPath = join3(logsDir, `claudish_${timestamp}.log`);
29281
+ writeFileSync3(alwaysOnLogPath, `Claudish Session Log - ${new Date().toISOString()}
29282
+ Mode: structural (content redacted)
29283
+ ${"=".repeat(60)}
29284
+
29285
+ `);
29286
+ rotateOldLogs(logsDir, 20);
29287
+ scheduleFlush();
29288
+ }
29289
+ if (debugMode) {
29290
+ logLevel = level;
29291
+ const logsDir = join3(process.cwd(), "logs");
29292
+ if (!existsSync3(logsDir)) {
29293
+ mkdirSync3(logsDir, { recursive: true });
29294
+ }
29295
+ const timestamp = new Date().toISOString().replace(/[:.]/g, "-").split("T").join("_").slice(0, -5);
29296
+ logFilePath = join3(logsDir, `claudish_${timestamp}.log`);
29297
+ writeFileSync3(logFilePath, `Claudish Debug Log - ${new Date().toISOString()}
28771
29298
  Log Level: ${level}
28772
29299
  ${"=".repeat(80)}
28773
29300
 
28774
29301
  `);
28775
- scheduleFlush();
29302
+ scheduleFlush();
29303
+ } else {
29304
+ logFilePath = null;
29305
+ if (noLogs && flushTimer) {
29306
+ clearInterval(flushTimer);
29307
+ flushTimer = null;
29308
+ }
29309
+ }
28776
29310
  }
28777
29311
  function log(message, forceConsole = false) {
28778
29312
  const timestamp = new Date().toISOString();
@@ -28784,25 +29318,40 @@ function log(message, forceConsole = false) {
28784
29318
  flushLogBuffer();
28785
29319
  }
28786
29320
  }
29321
+ if (alwaysOnLogPath && isStructuralLogWorthy(message)) {
29322
+ const redactedLine = redactLogLine(message, timestamp);
29323
+ alwaysOnBuffer.push(redactedLine);
29324
+ if (alwaysOnBuffer.length >= MAX_BUFFER_SIZE) {
29325
+ flushAlwaysOnBuffer();
29326
+ }
29327
+ }
28787
29328
  if (forceConsole) {
28788
29329
  console.log(message);
28789
29330
  }
28790
29331
  }
28791
29332
  function logStderr(message) {
28792
- if (!stderrQuiet) {
29333
+ if (diagOutput) {
29334
+ diagOutput.write(message);
29335
+ } else if (!stderrQuiet) {
28793
29336
  process.stderr.write(`[claudish] ${message}
28794
29337
  `);
28795
29338
  }
28796
29339
  log(message);
28797
29340
  }
29341
+ function setDiagOutput(output) {
29342
+ diagOutput = output;
29343
+ }
28798
29344
  function setStderrQuiet(quiet) {
28799
29345
  stderrQuiet = quiet;
28800
29346
  }
28801
29347
  function getLogFilePath() {
28802
29348
  return logFilePath;
28803
29349
  }
29350
+ function getAlwaysOnLogPath() {
29351
+ return alwaysOnLogPath;
29352
+ }
28804
29353
  function isLoggingEnabled() {
28805
- return logFilePath !== null;
29354
+ return logFilePath !== null || alwaysOnLogPath !== null;
28806
29355
  }
28807
29356
  function maskCredential(credential) {
28808
29357
  if (!credential || credential.length <= 8) {
@@ -28849,9 +29398,19 @@ function logStructured(label, data) {
28849
29398
  }
28850
29399
  log(`[${label}] ${JSON.stringify(data, null, 2)}`);
28851
29400
  }
28852
- var logFilePath = null, logLevel = "info", stderrQuiet = false, logBuffer, flushTimer = null, FLUSH_INTERVAL_MS = 100, MAX_BUFFER_SIZE = 50;
29401
+ var logFilePath = null, logLevel = "info", stderrQuiet = false, diagOutput = null, logBuffer, flushTimer = null, FLUSH_INTERVAL_MS = 100, MAX_BUFFER_SIZE = 50, alwaysOnLogPath = null, alwaysOnBuffer, CONTENT_KEYS;
28853
29402
  var init_logger = __esm(() => {
28854
29403
  logBuffer = [];
29404
+ alwaysOnBuffer = [];
29405
+ CONTENT_KEYS = new Set([
29406
+ "content",
29407
+ "reasoning_content",
29408
+ "text",
29409
+ "thinking",
29410
+ "partial_json",
29411
+ "arguments",
29412
+ "input"
29413
+ ]);
28855
29414
  });
28856
29415
 
28857
29416
  // src/auth/gemini-oauth.ts
@@ -28864,9 +29423,9 @@ __export(exports_gemini_oauth, {
28864
29423
  });
28865
29424
  import { createServer } from "http";
28866
29425
  import { randomBytes, createHash } from "crypto";
28867
- import { readFileSync as readFileSync2, existsSync as existsSync3, unlinkSync, openSync, writeSync, closeSync } from "fs";
28868
- import { homedir as homedir2 } from "os";
28869
- import { join as join3 } from "path";
29426
+ import { readFileSync as readFileSync3, existsSync as existsSync4, unlinkSync as unlinkSync2, openSync, writeSync, closeSync } from "fs";
29427
+ import { homedir as homedir3 } from "os";
29428
+ import { join as join4 } from "path";
28870
29429
  import { exec } from "child_process";
28871
29430
  import { promisify } from "util";
28872
29431
 
@@ -28889,8 +29448,8 @@ class GeminiOAuth {
28889
29448
  return this.credentials !== null && !!this.credentials.refresh_token;
28890
29449
  }
28891
29450
  getCredentialsPath() {
28892
- const claudishDir = join3(homedir2(), ".claudish");
28893
- return join3(claudishDir, "gemini-oauth.json");
29451
+ const claudishDir = join4(homedir3(), ".claudish");
29452
+ return join4(claudishDir, "gemini-oauth.json");
28894
29453
  }
28895
29454
  async login() {
28896
29455
  log("[GeminiOAuth] Starting OAuth login flow");
@@ -28911,8 +29470,8 @@ class GeminiOAuth {
28911
29470
  }
28912
29471
  async logout() {
28913
29472
  const credPath = this.getCredentialsPath();
28914
- if (existsSync3(credPath)) {
28915
- unlinkSync(credPath);
29473
+ if (existsSync4(credPath)) {
29474
+ unlinkSync2(credPath);
28916
29475
  log("[GeminiOAuth] Credentials deleted");
28917
29476
  }
28918
29477
  this.credentials = null;
@@ -28988,11 +29547,11 @@ Details: ${e.message}`);
28988
29547
  }
28989
29548
  loadCredentials() {
28990
29549
  const credPath = this.getCredentialsPath();
28991
- if (!existsSync3(credPath)) {
29550
+ if (!existsSync4(credPath)) {
28992
29551
  return null;
28993
29552
  }
28994
29553
  try {
28995
- const data = readFileSync2(credPath, "utf-8");
29554
+ const data = readFileSync3(credPath, "utf-8");
28996
29555
  const credentials = JSON.parse(data);
28997
29556
  if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at) {
28998
29557
  log("[GeminiOAuth] Invalid credentials file structure");
@@ -29007,10 +29566,10 @@ Details: ${e.message}`);
29007
29566
  }
29008
29567
  saveCredentials(credentials) {
29009
29568
  const credPath = this.getCredentialsPath();
29010
- const claudishDir = join3(homedir2(), ".claudish");
29011
- if (!existsSync3(claudishDir)) {
29012
- const { mkdirSync: mkdirSync3 } = __require("fs");
29013
- mkdirSync3(claudishDir, { recursive: true });
29569
+ const claudishDir = join4(homedir3(), ".claudish");
29570
+ if (!existsSync4(claudishDir)) {
29571
+ const { mkdirSync: mkdirSync4 } = __require("fs");
29572
+ mkdirSync4(claudishDir, { recursive: true });
29014
29573
  }
29015
29574
  const fd = openSync(credPath, "w", 384);
29016
29575
  try {
@@ -29043,7 +29602,7 @@ Details: ${e.message}`);
29043
29602
  return `${OAUTH_CONFIG.authUrl}?${params.toString()}`;
29044
29603
  }
29045
29604
  async startCallbackServer(codeChallenge, state) {
29046
- return new Promise((resolve, reject) => {
29605
+ return new Promise((resolve2, reject) => {
29047
29606
  let redirectUri = "";
29048
29607
  const server = createServer((req, res) => {
29049
29608
  const url2 = new URL(req.url, redirectUri.replace("/callback", ""));
@@ -29106,7 +29665,7 @@ Details: ${e.message}`);
29106
29665
  </html>
29107
29666
  `);
29108
29667
  server.close();
29109
- resolve({ authCode: code, redirectUri });
29668
+ resolve2({ authCode: code, redirectUri });
29110
29669
  } else {
29111
29670
  res.writeHead(404, { "Content-Type": "text/plain" });
29112
29671
  res.end("Not found");
@@ -29322,9 +29881,9 @@ __export(exports_kimi_oauth, {
29322
29881
  KimiOAuth: () => KimiOAuth
29323
29882
  });
29324
29883
  import { randomBytes as randomBytes2 } from "crypto";
29325
- import { readFileSync as readFileSync3, existsSync as existsSync4, unlinkSync as unlinkSync2, openSync as openSync2, writeSync as writeSync2, closeSync as closeSync2 } from "fs";
29326
- import { homedir as homedir3, hostname as hostname3, platform, release } from "os";
29327
- import { join as join4 } from "path";
29884
+ import { readFileSync as readFileSync4, existsSync as existsSync5, unlinkSync as unlinkSync3, openSync as openSync2, writeSync as writeSync2, closeSync as closeSync2 } from "fs";
29885
+ import { homedir as homedir4, hostname as hostname3, platform, release } from "os";
29886
+ import { join as join5 } from "path";
29328
29887
  import { exec as exec2 } from "child_process";
29329
29888
  import { promisify as promisify2 } from "util";
29330
29889
 
@@ -29349,23 +29908,23 @@ class KimiOAuth {
29349
29908
  return this.credentials !== null && !!this.credentials.refresh_token;
29350
29909
  }
29351
29910
  getCredentialsPath() {
29352
- const claudishDir = join4(homedir3(), ".claudish");
29353
- return join4(claudishDir, "kimi-oauth.json");
29911
+ const claudishDir = join5(homedir4(), ".claudish");
29912
+ return join5(claudishDir, "kimi-oauth.json");
29354
29913
  }
29355
29914
  getDeviceIdPath() {
29356
- const claudishDir = join4(homedir3(), ".claudish");
29357
- return join4(claudishDir, "kimi-device-id");
29915
+ const claudishDir = join5(homedir4(), ".claudish");
29916
+ return join5(claudishDir, "kimi-device-id");
29358
29917
  }
29359
29918
  loadOrCreateDeviceId() {
29360
29919
  const deviceIdPath = this.getDeviceIdPath();
29361
- const claudishDir = join4(homedir3(), ".claudish");
29362
- if (!existsSync4(claudishDir)) {
29363
- const { mkdirSync: mkdirSync3 } = __require("fs");
29364
- mkdirSync3(claudishDir, { recursive: true });
29920
+ const claudishDir = join5(homedir4(), ".claudish");
29921
+ if (!existsSync5(claudishDir)) {
29922
+ const { mkdirSync: mkdirSync4 } = __require("fs");
29923
+ mkdirSync4(claudishDir, { recursive: true });
29365
29924
  }
29366
- if (existsSync4(deviceIdPath)) {
29925
+ if (existsSync5(deviceIdPath)) {
29367
29926
  try {
29368
- const deviceId2 = readFileSync3(deviceIdPath, "utf-8").trim();
29927
+ const deviceId2 = readFileSync4(deviceIdPath, "utf-8").trim();
29369
29928
  if (deviceId2) {
29370
29929
  return deviceId2;
29371
29930
  }
@@ -29389,7 +29948,7 @@ class KimiOAuth {
29389
29948
  }
29390
29949
  getVersion() {
29391
29950
  try {
29392
- const packageJson = JSON.parse(readFileSync3(join4(__dirname, "../../package.json"), "utf-8"));
29951
+ const packageJson = JSON.parse(readFileSync4(join5(__dirname, "../../package.json"), "utf-8"));
29393
29952
  return packageJson.version;
29394
29953
  } catch {
29395
29954
  return "4.0.6";
@@ -29467,7 +30026,7 @@ Waiting for authorization...`);
29467
30026
  const timeoutMs = expiresIn * 1000;
29468
30027
  let currentInterval = interval * 1000;
29469
30028
  while (Date.now() - startTime < timeoutMs) {
29470
- await new Promise((resolve) => setTimeout(resolve, currentInterval));
30029
+ await new Promise((resolve2) => setTimeout(resolve2, currentInterval));
29471
30030
  const result = await this.pollForTokenWithRetry(deviceCode);
29472
30031
  if (result.error) {
29473
30032
  if (result.error === "authorization_pending") {
@@ -29517,7 +30076,7 @@ Waiting for authorization...`);
29517
30076
  } catch (e) {
29518
30077
  if (retryCount < maxRetries) {
29519
30078
  log(`[KimiOAuth] Network error during polling (attempt ${retryCount + 1}/${maxRetries}), retrying in ${backoffMs}ms...`);
29520
- await new Promise((resolve) => setTimeout(resolve, backoffMs));
30079
+ await new Promise((resolve2) => setTimeout(resolve2, backoffMs));
29521
30080
  return this.pollForTokenWithRetry(deviceCode, retryCount + 1);
29522
30081
  }
29523
30082
  throw new Error(`Network error during token polling: ${e.message}`);
@@ -29539,8 +30098,8 @@ Waiting for authorization...`);
29539
30098
  }
29540
30099
  async logout() {
29541
30100
  const credPath = this.getCredentialsPath();
29542
- if (existsSync4(credPath)) {
29543
- unlinkSync2(credPath);
30101
+ if (existsSync5(credPath)) {
30102
+ unlinkSync3(credPath);
29544
30103
  log("[KimiOAuth] Credentials deleted");
29545
30104
  }
29546
30105
  this.credentials = null;
@@ -29606,8 +30165,8 @@ Waiting for authorization...`);
29606
30165
  } catch (e) {
29607
30166
  log(`[KimiOAuth] Refresh failed: ${e.message}`);
29608
30167
  const credPath = this.getCredentialsPath();
29609
- if (existsSync4(credPath)) {
29610
- unlinkSync2(credPath);
30168
+ if (existsSync5(credPath)) {
30169
+ unlinkSync3(credPath);
29611
30170
  }
29612
30171
  this.credentials = null;
29613
30172
  if (process.env.MOONSHOT_API_KEY || process.env.KIMI_API_KEY) {
@@ -29623,11 +30182,11 @@ Waiting for authorization...`);
29623
30182
  }
29624
30183
  loadCredentials() {
29625
30184
  const credPath = this.getCredentialsPath();
29626
- if (!existsSync4(credPath)) {
30185
+ if (!existsSync5(credPath)) {
29627
30186
  return null;
29628
30187
  }
29629
30188
  try {
29630
- const data = readFileSync3(credPath, "utf-8");
30189
+ const data = readFileSync4(credPath, "utf-8");
29631
30190
  const credentials = JSON.parse(data);
29632
30191
  if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at || !credentials.scope || !credentials.token_type) {
29633
30192
  log("[KimiOAuth] Invalid credentials file structure");
@@ -29642,10 +30201,10 @@ Waiting for authorization...`);
29642
30201
  }
29643
30202
  saveCredentials(credentials) {
29644
30203
  const credPath = this.getCredentialsPath();
29645
- const claudishDir = join4(homedir3(), ".claudish");
29646
- if (!existsSync4(claudishDir)) {
29647
- const { mkdirSync: mkdirSync3 } = __require("fs");
29648
- mkdirSync3(claudishDir, { recursive: true });
30204
+ const claudishDir = join5(homedir4(), ".claudish");
30205
+ if (!existsSync5(claudishDir)) {
30206
+ const { mkdirSync: mkdirSync4 } = __require("fs");
30207
+ mkdirSync4(claudishDir, { recursive: true });
29649
30208
  }
29650
30209
  const fd = openSync2(credPath, "w", 384);
29651
30210
  try {
@@ -29666,10 +30225,10 @@ async function getValidKimiAccessToken() {
29666
30225
  }
29667
30226
  function hasKimiOAuthCredentials() {
29668
30227
  try {
29669
- const credPath = join4(homedir3(), ".claudish", "kimi-oauth.json");
29670
- if (!existsSync4(credPath))
30228
+ const credPath = join5(homedir4(), ".claudish", "kimi-oauth.json");
30229
+ if (!existsSync5(credPath))
29671
30230
  return false;
29672
- const data = JSON.parse(readFileSync3(credPath, "utf-8"));
30231
+ const data = JSON.parse(readFileSync4(credPath, "utf-8"));
29673
30232
  const now = Date.now();
29674
30233
  const bufferMs = 5 * 60 * 1000;
29675
30234
  return !!(data.access_token && data.refresh_token && data.expires_at && data.expires_at > now + bufferMs);
@@ -29732,24 +30291,24 @@ var init_config = __esm(() => {
29732
30291
  });
29733
30292
 
29734
30293
  // src/model-loader.ts
29735
- import { readFileSync as readFileSync4, existsSync as existsSync5, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
29736
- import { join as join5, dirname as dirname2 } from "path";
30294
+ import { readFileSync as readFileSync5, existsSync as existsSync6, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
30295
+ import { join as join6, dirname as dirname2 } from "path";
29737
30296
  import { fileURLToPath as fileURLToPath2 } from "url";
29738
- import { homedir as homedir4 } from "os";
30297
+ import { homedir as homedir5 } from "os";
29739
30298
  import { createHash as createHash2 } from "crypto";
29740
30299
  function getRecommendedModelsPath() {
29741
- return join5(__dirname3, "../recommended-models.json");
30300
+ return join6(__dirname3, "../recommended-models.json");
29742
30301
  }
29743
30302
  function loadRecommendedModelsJSON() {
29744
30303
  if (_cachedRecommendedModels) {
29745
30304
  return _cachedRecommendedModels;
29746
30305
  }
29747
30306
  const jsonPath = getRecommendedModelsPath();
29748
- if (!existsSync5(jsonPath)) {
30307
+ if (!existsSync6(jsonPath)) {
29749
30308
  throw new Error(`recommended-models.json not found at ${jsonPath}. ` + `Run 'claudish --update-models' to fetch the latest model list.`);
29750
30309
  }
29751
30310
  try {
29752
- const jsonContent = readFileSync4(jsonPath, "utf-8");
30311
+ const jsonContent = readFileSync5(jsonPath, "utf-8");
29753
30312
  _cachedRecommendedModels = JSON.parse(jsonContent);
29754
30313
  return _cachedRecommendedModels;
29755
30314
  } catch (error46) {
@@ -29807,11 +30366,11 @@ async function ensureOpenRouterModelsLoaded() {
29807
30366
  }
29808
30367
  async function fetchLiteLLMModels(baseUrl, apiKey, forceUpdate = false) {
29809
30368
  const hash2 = createHash2("sha256").update(baseUrl).digest("hex").substring(0, 16);
29810
- const cacheDir = join5(homedir4(), ".claudish");
29811
- const cachePath = join5(cacheDir, `litellm-models-${hash2}.json`);
29812
- if (!forceUpdate && existsSync5(cachePath)) {
30369
+ const cacheDir = join6(homedir5(), ".claudish");
30370
+ const cachePath = join6(cacheDir, `litellm-models-${hash2}.json`);
30371
+ if (!forceUpdate && existsSync6(cachePath)) {
29813
30372
  try {
29814
- const cacheData = JSON.parse(readFileSync4(cachePath, "utf-8"));
30373
+ const cacheData = JSON.parse(readFileSync5(cachePath, "utf-8"));
29815
30374
  const timestamp = new Date(cacheData.timestamp);
29816
30375
  const now = new Date;
29817
30376
  const ageInHours = (now.getTime() - timestamp.getTime()) / (1000 * 60 * 60);
@@ -29830,9 +30389,9 @@ async function fetchLiteLLMModels(baseUrl, apiKey, forceUpdate = false) {
29830
30389
  });
29831
30390
  if (!response.ok) {
29832
30391
  console.error(`Failed to fetch LiteLLM models: ${response.status} ${response.statusText}`);
29833
- if (existsSync5(cachePath)) {
30392
+ if (existsSync6(cachePath)) {
29834
30393
  try {
29835
- const cacheData2 = JSON.parse(readFileSync4(cachePath, "utf-8"));
30394
+ const cacheData2 = JSON.parse(readFileSync5(cachePath, "utf-8"));
29836
30395
  return cacheData2.models;
29837
30396
  } catch {
29838
30397
  return [];
@@ -29868,18 +30427,18 @@ async function fetchLiteLLMModels(baseUrl, apiKey, forceUpdate = false) {
29868
30427
  source: "LiteLLM"
29869
30428
  };
29870
30429
  });
29871
- mkdirSync3(cacheDir, { recursive: true });
30430
+ mkdirSync4(cacheDir, { recursive: true });
29872
30431
  const cacheData = {
29873
30432
  timestamp: new Date().toISOString(),
29874
30433
  models: transformedModels
29875
30434
  };
29876
- writeFileSync3(cachePath, JSON.stringify(cacheData, null, 2), "utf-8");
30435
+ writeFileSync4(cachePath, JSON.stringify(cacheData, null, 2), "utf-8");
29877
30436
  return transformedModels;
29878
30437
  } catch (error46) {
29879
30438
  console.error(`Failed to fetch LiteLLM models: ${error46}`);
29880
- if (existsSync5(cachePath)) {
30439
+ if (existsSync6(cachePath)) {
29881
30440
  try {
29882
- const cacheData = JSON.parse(readFileSync4(cachePath, "utf-8"));
30441
+ const cacheData = JSON.parse(readFileSync5(cachePath, "utf-8"));
29883
30442
  return cacheData.models;
29884
30443
  } catch {
29885
30444
  return [];
@@ -29939,21 +30498,21 @@ function fuzzyScore2(text, query) {
29939
30498
  }
29940
30499
 
29941
30500
  // src/profile-config.ts
29942
- import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "fs";
29943
- import { homedir as homedir5 } from "os";
29944
- import { join as join6 } from "path";
30501
+ import { existsSync as existsSync7, mkdirSync as mkdirSync5, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
30502
+ import { homedir as homedir6 } from "os";
30503
+ import { join as join7 } from "path";
29945
30504
  function ensureConfigDir() {
29946
- if (!existsSync6(CONFIG_DIR)) {
29947
- mkdirSync4(CONFIG_DIR, { recursive: true });
30505
+ if (!existsSync7(CONFIG_DIR)) {
30506
+ mkdirSync5(CONFIG_DIR, { recursive: true });
29948
30507
  }
29949
30508
  }
29950
30509
  function loadConfig() {
29951
30510
  ensureConfigDir();
29952
- if (!existsSync6(CONFIG_FILE)) {
30511
+ if (!existsSync7(CONFIG_FILE)) {
29953
30512
  return { ...DEFAULT_CONFIG };
29954
30513
  }
29955
30514
  try {
29956
- const content = readFileSync5(CONFIG_FILE, "utf-8");
30515
+ const content = readFileSync6(CONFIG_FILE, "utf-8");
29957
30516
  const config3 = JSON.parse(content);
29958
30517
  const merged = {
29959
30518
  version: config3.version || DEFAULT_CONFIG.version,
@@ -29983,31 +30542,31 @@ function loadConfig() {
29983
30542
  }
29984
30543
  function saveConfig(config3) {
29985
30544
  ensureConfigDir();
29986
- writeFileSync4(CONFIG_FILE, JSON.stringify(config3, null, 2), "utf-8");
30545
+ writeFileSync5(CONFIG_FILE, JSON.stringify(config3, null, 2), "utf-8");
29987
30546
  }
29988
30547
  function configExists() {
29989
- return existsSync6(CONFIG_FILE);
30548
+ return existsSync7(CONFIG_FILE);
29990
30549
  }
29991
30550
  function getConfigPath() {
29992
30551
  return CONFIG_FILE;
29993
30552
  }
29994
30553
  function getLocalConfigPath() {
29995
- return join6(process.cwd(), LOCAL_CONFIG_FILENAME);
30554
+ return join7(process.cwd(), LOCAL_CONFIG_FILENAME);
29996
30555
  }
29997
30556
  function localConfigExists() {
29998
- return existsSync6(getLocalConfigPath());
30557
+ return existsSync7(getLocalConfigPath());
29999
30558
  }
30000
30559
  function isProjectDirectory() {
30001
30560
  const cwd = process.cwd();
30002
- return [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".claudish.json"].some((f) => existsSync6(join6(cwd, f)));
30561
+ return [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".claudish.json"].some((f) => existsSync7(join7(cwd, f)));
30003
30562
  }
30004
30563
  function loadLocalConfig() {
30005
30564
  const localPath = getLocalConfigPath();
30006
- if (!existsSync6(localPath)) {
30565
+ if (!existsSync7(localPath)) {
30007
30566
  return null;
30008
30567
  }
30009
30568
  try {
30010
- const content = readFileSync5(localPath, "utf-8");
30569
+ const content = readFileSync6(localPath, "utf-8");
30011
30570
  const config3 = JSON.parse(content);
30012
30571
  const local = {
30013
30572
  version: config3.version || DEFAULT_CONFIG.version,
@@ -30024,7 +30583,7 @@ function loadLocalConfig() {
30024
30583
  }
30025
30584
  }
30026
30585
  function saveLocalConfig(config3) {
30027
- writeFileSync4(getLocalConfigPath(), JSON.stringify(config3, null, 2), "utf-8");
30586
+ writeFileSync5(getLocalConfigPath(), JSON.stringify(config3, null, 2), "utf-8");
30028
30587
  }
30029
30588
  function loadConfigForScope(scope) {
30030
30589
  if (scope === "local") {
@@ -30229,8 +30788,8 @@ function removeEndpoint(name) {
30229
30788
  }
30230
30789
  var CONFIG_DIR, CONFIG_FILE, LOCAL_CONFIG_FILENAME = ".claudish.json", DEFAULT_CONFIG;
30231
30790
  var init_profile_config = __esm(() => {
30232
- CONFIG_DIR = join6(homedir5(), ".claudish");
30233
- CONFIG_FILE = join6(CONFIG_DIR, "config.json");
30791
+ CONFIG_DIR = join7(homedir6(), ".claudish");
30792
+ CONFIG_FILE = join7(CONFIG_DIR, "config.json");
30234
30793
  DEFAULT_CONFIG = {
30235
30794
  version: "1.0.0",
30236
30795
  defaultProfile: "default",
@@ -30246,6 +30805,554 @@ var init_profile_config = __esm(() => {
30246
30805
  };
30247
30806
  });
30248
30807
 
30808
+ // src/providers/provider-definitions.ts
30809
+ function ensureProviderByNameCache() {
30810
+ if (!_providerByNameCache) {
30811
+ _providerByNameCache = new Map;
30812
+ for (const def of BUILTIN_PROVIDERS) {
30813
+ _providerByNameCache.set(def.name, def);
30814
+ }
30815
+ }
30816
+ return _providerByNameCache;
30817
+ }
30818
+ function getShortcuts() {
30819
+ if (!_shortcutsCache) {
30820
+ _shortcutsCache = {};
30821
+ for (const def of BUILTIN_PROVIDERS) {
30822
+ for (const shortcut of def.shortcuts) {
30823
+ _shortcutsCache[shortcut] = def.name;
30824
+ }
30825
+ }
30826
+ }
30827
+ return _shortcutsCache;
30828
+ }
30829
+ function getLegacyPrefixPatterns() {
30830
+ if (!_legacyPrefixCache) {
30831
+ _legacyPrefixCache = [];
30832
+ for (const def of BUILTIN_PROVIDERS) {
30833
+ for (const lp of def.legacyPrefixes) {
30834
+ _legacyPrefixCache.push({
30835
+ prefix: lp.prefix,
30836
+ provider: def.name,
30837
+ stripPrefix: lp.stripPrefix
30838
+ });
30839
+ }
30840
+ }
30841
+ }
30842
+ return _legacyPrefixCache;
30843
+ }
30844
+ function getNativeModelPatterns() {
30845
+ if (!_nativeModelPatternsCache) {
30846
+ _nativeModelPatternsCache = [];
30847
+ for (const def of BUILTIN_PROVIDERS) {
30848
+ if (def.nativeModelPatterns) {
30849
+ for (const np of def.nativeModelPatterns) {
30850
+ _nativeModelPatternsCache.push({
30851
+ pattern: np.pattern,
30852
+ provider: def.name
30853
+ });
30854
+ }
30855
+ }
30856
+ }
30857
+ }
30858
+ return _nativeModelPatternsCache;
30859
+ }
30860
+ function getProviderByName(name) {
30861
+ return ensureProviderByNameCache().get(name);
30862
+ }
30863
+ function getApiKeyInfo(providerName) {
30864
+ const def = getProviderByName(providerName);
30865
+ if (!def)
30866
+ return null;
30867
+ return {
30868
+ envVar: def.apiKeyEnvVar,
30869
+ description: def.apiKeyDescription,
30870
+ url: def.apiKeyUrl,
30871
+ aliases: def.apiKeyAliases,
30872
+ oauthFallback: def.oauthFallback
30873
+ };
30874
+ }
30875
+ function getDisplayName(providerName) {
30876
+ const def = getProviderByName(providerName);
30877
+ return def?.displayName || providerName.charAt(0).toUpperCase() + providerName.slice(1);
30878
+ }
30879
+ function getEffectiveBaseUrl(def) {
30880
+ if (def.baseUrlEnvVars) {
30881
+ for (const envVar of def.baseUrlEnvVars) {
30882
+ const value = process.env[envVar];
30883
+ if (value)
30884
+ return value;
30885
+ }
30886
+ }
30887
+ return def.baseUrl;
30888
+ }
30889
+ function isLocalTransport(providerName) {
30890
+ if (!_localProvidersCache) {
30891
+ _localProvidersCache = new Set;
30892
+ for (const def of BUILTIN_PROVIDERS) {
30893
+ if (def.isLocal) {
30894
+ _localProvidersCache.add(def.name);
30895
+ }
30896
+ }
30897
+ }
30898
+ return _localProvidersCache.has(providerName.toLowerCase());
30899
+ }
30900
+ function toRemoteProvider(def) {
30901
+ const baseUrl = getEffectiveBaseUrl(def);
30902
+ let effectiveBaseUrl = baseUrl;
30903
+ if (def.name === "opencode-zen-go" && def.baseUrlEnvVars) {
30904
+ const envOverride = process.env[def.baseUrlEnvVars[0]];
30905
+ if (envOverride) {
30906
+ effectiveBaseUrl = envOverride.replace("/zen", "/zen/go");
30907
+ }
30908
+ }
30909
+ return {
30910
+ name: def.name === "google" ? "gemini" : def.name,
30911
+ baseUrl: effectiveBaseUrl,
30912
+ apiPath: def.apiPath,
30913
+ apiKeyEnvVar: def.apiKeyEnvVar,
30914
+ prefixes: def.legacyPrefixes.map((lp) => lp.prefix),
30915
+ headers: def.headers,
30916
+ authScheme: def.authScheme
30917
+ };
30918
+ }
30919
+ function getAllProviders() {
30920
+ return BUILTIN_PROVIDERS;
30921
+ }
30922
+ function getApiKeyEnvVars(providerName) {
30923
+ const def = getProviderByName(providerName);
30924
+ if (!def)
30925
+ return null;
30926
+ return {
30927
+ envVar: def.apiKeyEnvVar,
30928
+ aliases: def.apiKeyAliases
30929
+ };
30930
+ }
30931
+ var BUILTIN_PROVIDERS, _shortcutsCache = null, _legacyPrefixCache = null, _nativeModelPatternsCache = null, _providerByNameCache = null, _localProvidersCache = null;
30932
+ var init_provider_definitions = __esm(() => {
30933
+ BUILTIN_PROVIDERS = [
30934
+ {
30935
+ name: "google",
30936
+ displayName: "Gemini",
30937
+ transport: "gemini",
30938
+ baseUrl: "https://generativelanguage.googleapis.com",
30939
+ baseUrlEnvVars: ["GEMINI_BASE_URL"],
30940
+ apiPath: "/v1beta/models/{model}:streamGenerateContent?alt=sse",
30941
+ apiKeyEnvVar: "GEMINI_API_KEY",
30942
+ apiKeyDescription: "Google Gemini API Key",
30943
+ apiKeyUrl: "https://aistudio.google.com/app/apikey",
30944
+ shortcuts: ["g", "gemini"],
30945
+ shortestPrefix: "g",
30946
+ legacyPrefixes: [
30947
+ { prefix: "g/", stripPrefix: true },
30948
+ { prefix: "gemini/", stripPrefix: true }
30949
+ ],
30950
+ nativeModelPatterns: [{ pattern: /^google\//i }, { pattern: /^gemini-/i }],
30951
+ isDirectApi: true
30952
+ },
30953
+ {
30954
+ name: "gemini-codeassist",
30955
+ displayName: "Gemini Code Assist",
30956
+ transport: "gemini-oauth",
30957
+ baseUrl: "https://cloudcode-pa.googleapis.com",
30958
+ apiPath: "/v1internal:streamGenerateContent?alt=sse",
30959
+ apiKeyEnvVar: "",
30960
+ apiKeyDescription: "Gemini Code Assist (OAuth)",
30961
+ apiKeyUrl: "https://cloud.google.com/code-assist",
30962
+ shortcuts: ["go"],
30963
+ shortestPrefix: "go",
30964
+ legacyPrefixes: [{ prefix: "go/", stripPrefix: true }],
30965
+ isDirectApi: true
30966
+ },
30967
+ {
30968
+ name: "openai",
30969
+ displayName: "OpenAI",
30970
+ transport: "openai",
30971
+ tokenStrategy: "delta-aware",
30972
+ baseUrl: "https://api.openai.com",
30973
+ baseUrlEnvVars: ["OPENAI_BASE_URL"],
30974
+ apiPath: "/v1/chat/completions",
30975
+ apiKeyEnvVar: "OPENAI_API_KEY",
30976
+ apiKeyDescription: "OpenAI API Key",
30977
+ apiKeyUrl: "https://platform.openai.com/api-keys",
30978
+ shortcuts: ["oai"],
30979
+ shortestPrefix: "oai",
30980
+ legacyPrefixes: [{ prefix: "oai/", stripPrefix: true }],
30981
+ nativeModelPatterns: [
30982
+ { pattern: /^openai\//i },
30983
+ { pattern: /^gpt-/i },
30984
+ { pattern: /^o1(-|$)/i },
30985
+ { pattern: /^o3(-|$)/i },
30986
+ { pattern: /^chatgpt-/i }
30987
+ ],
30988
+ isDirectApi: true
30989
+ },
30990
+ {
30991
+ name: "openrouter",
30992
+ displayName: "OpenRouter",
30993
+ transport: "openrouter",
30994
+ baseUrl: "https://openrouter.ai",
30995
+ apiPath: "/api/v1/chat/completions",
30996
+ apiKeyEnvVar: "OPENROUTER_API_KEY",
30997
+ apiKeyDescription: "OpenRouter API Key",
30998
+ apiKeyUrl: "https://openrouter.ai/keys",
30999
+ shortcuts: ["or"],
31000
+ shortestPrefix: "or",
31001
+ legacyPrefixes: [{ prefix: "or/", stripPrefix: true }],
31002
+ nativeModelPatterns: [{ pattern: /^openrouter\//i }],
31003
+ headers: {
31004
+ "HTTP-Referer": "https://claudish.com",
31005
+ "X-Title": "Claudish - OpenRouter Proxy"
31006
+ },
31007
+ isDirectApi: true
31008
+ },
31009
+ {
31010
+ name: "minimax",
31011
+ displayName: "MiniMax",
31012
+ transport: "anthropic",
31013
+ baseUrl: "https://api.minimax.io",
31014
+ baseUrlEnvVars: ["MINIMAX_BASE_URL"],
31015
+ apiPath: "/anthropic/v1/messages",
31016
+ apiKeyEnvVar: "MINIMAX_API_KEY",
31017
+ apiKeyDescription: "MiniMax API Key",
31018
+ apiKeyUrl: "https://www.minimaxi.com/",
31019
+ authScheme: "bearer",
31020
+ shortcuts: ["mm", "mmax"],
31021
+ shortestPrefix: "mm",
31022
+ legacyPrefixes: [
31023
+ { prefix: "mmax/", stripPrefix: true },
31024
+ { prefix: "mm/", stripPrefix: true }
31025
+ ],
31026
+ nativeModelPatterns: [
31027
+ { pattern: /^minimax\//i },
31028
+ { pattern: /^minimax-/i },
31029
+ { pattern: /^abab-/i }
31030
+ ],
31031
+ isDirectApi: true
31032
+ },
31033
+ {
31034
+ name: "minimax-coding",
31035
+ displayName: "MiniMax Coding",
31036
+ transport: "anthropic",
31037
+ baseUrl: "https://api.minimax.io",
31038
+ baseUrlEnvVars: ["MINIMAX_CODING_BASE_URL"],
31039
+ apiPath: "/anthropic/v1/messages",
31040
+ apiKeyEnvVar: "MINIMAX_CODING_API_KEY",
31041
+ apiKeyDescription: "MiniMax Coding Plan API Key",
31042
+ apiKeyUrl: "https://platform.minimax.io/user-center/basic-information/interface-key",
31043
+ authScheme: "bearer",
31044
+ shortcuts: ["mmc"],
31045
+ shortestPrefix: "mmc",
31046
+ legacyPrefixes: [{ prefix: "mmc/", stripPrefix: true }],
31047
+ isDirectApi: true
31048
+ },
31049
+ {
31050
+ name: "kimi-coding",
31051
+ displayName: "Kimi Coding",
31052
+ transport: "kimi-coding",
31053
+ baseUrl: "https://api.kimi.com/coding/v1",
31054
+ apiPath: "/messages",
31055
+ apiKeyEnvVar: "KIMI_CODING_API_KEY",
31056
+ apiKeyDescription: "Kimi Coding API Key",
31057
+ apiKeyUrl: "https://kimi.com/code (get key from membership page, or run: claudish --kimi-login)",
31058
+ oauthFallback: "kimi-oauth.json",
31059
+ shortcuts: ["kc"],
31060
+ shortestPrefix: "kc",
31061
+ legacyPrefixes: [{ prefix: "kc/", stripPrefix: true }],
31062
+ nativeModelPatterns: [{ pattern: /^kimi-for-coding$/i }],
31063
+ isDirectApi: true
31064
+ },
31065
+ {
31066
+ name: "kimi",
31067
+ displayName: "Kimi",
31068
+ transport: "anthropic",
31069
+ baseUrl: "https://api.moonshot.ai",
31070
+ baseUrlEnvVars: ["MOONSHOT_BASE_URL", "KIMI_BASE_URL"],
31071
+ apiPath: "/anthropic/v1/messages",
31072
+ apiKeyEnvVar: "MOONSHOT_API_KEY",
31073
+ apiKeyAliases: ["KIMI_API_KEY"],
31074
+ apiKeyDescription: "Kimi/Moonshot API Key",
31075
+ apiKeyUrl: "https://platform.moonshot.cn/",
31076
+ shortcuts: ["kimi", "moon", "moonshot"],
31077
+ shortestPrefix: "kimi",
31078
+ legacyPrefixes: [
31079
+ { prefix: "kimi/", stripPrefix: true },
31080
+ { prefix: "moonshot/", stripPrefix: true }
31081
+ ],
31082
+ nativeModelPatterns: [
31083
+ { pattern: /^moonshot(ai)?\//i },
31084
+ { pattern: /^moonshot-/i },
31085
+ { pattern: /^kimi-/i }
31086
+ ],
31087
+ isDirectApi: true
31088
+ },
31089
+ {
31090
+ name: "glm",
31091
+ displayName: "GLM",
31092
+ transport: "openai",
31093
+ tokenStrategy: "delta-aware",
31094
+ baseUrl: "https://open.bigmodel.cn",
31095
+ baseUrlEnvVars: ["ZHIPU_BASE_URL", "GLM_BASE_URL"],
31096
+ apiPath: "/api/paas/v4/chat/completions",
31097
+ apiKeyEnvVar: "ZHIPU_API_KEY",
31098
+ apiKeyAliases: ["GLM_API_KEY"],
31099
+ apiKeyDescription: "GLM/Zhipu API Key",
31100
+ apiKeyUrl: "https://open.bigmodel.cn/",
31101
+ shortcuts: ["glm", "zhipu"],
31102
+ shortestPrefix: "glm",
31103
+ legacyPrefixes: [
31104
+ { prefix: "glm/", stripPrefix: true },
31105
+ { prefix: "zhipu/", stripPrefix: true }
31106
+ ],
31107
+ nativeModelPatterns: [
31108
+ { pattern: /^zhipu\//i },
31109
+ { pattern: /^glm-/i },
31110
+ { pattern: /^chatglm-/i }
31111
+ ],
31112
+ isDirectApi: true
31113
+ },
31114
+ {
31115
+ name: "glm-coding",
31116
+ displayName: "GLM Coding",
31117
+ transport: "openai",
31118
+ tokenStrategy: "delta-aware",
31119
+ baseUrl: "https://api.z.ai",
31120
+ apiPath: "/api/coding/paas/v4/chat/completions",
31121
+ apiKeyEnvVar: "GLM_CODING_API_KEY",
31122
+ apiKeyAliases: ["ZAI_CODING_API_KEY"],
31123
+ apiKeyDescription: "GLM Coding Plan API Key",
31124
+ apiKeyUrl: "https://z.ai/subscribe",
31125
+ shortcuts: ["gc"],
31126
+ shortestPrefix: "gc",
31127
+ legacyPrefixes: [{ prefix: "gc/", stripPrefix: true }],
31128
+ isDirectApi: true
31129
+ },
31130
+ {
31131
+ name: "zai",
31132
+ displayName: "Z.AI",
31133
+ transport: "anthropic",
31134
+ baseUrl: "https://api.z.ai",
31135
+ baseUrlEnvVars: ["ZAI_BASE_URL"],
31136
+ apiPath: "/api/anthropic/v1/messages",
31137
+ apiKeyEnvVar: "ZAI_API_KEY",
31138
+ apiKeyDescription: "Z.AI API Key",
31139
+ apiKeyUrl: "https://z.ai/",
31140
+ shortcuts: ["zai"],
31141
+ shortestPrefix: "zai",
31142
+ legacyPrefixes: [{ prefix: "zai/", stripPrefix: true }],
31143
+ nativeModelPatterns: [{ pattern: /^z-ai\//i }, { pattern: /^zai\//i }],
31144
+ isDirectApi: true
31145
+ },
31146
+ {
31147
+ name: "ollamacloud",
31148
+ displayName: "OllamaCloud",
31149
+ transport: "ollamacloud",
31150
+ tokenStrategy: "accumulate-both",
31151
+ baseUrl: "https://ollama.com",
31152
+ baseUrlEnvVars: ["OLLAMACLOUD_BASE_URL"],
31153
+ apiPath: "/api/chat",
31154
+ apiKeyEnvVar: "OLLAMA_API_KEY",
31155
+ apiKeyDescription: "OllamaCloud API Key",
31156
+ apiKeyUrl: "https://ollama.com/account",
31157
+ shortcuts: ["oc", "llama", "lc", "meta"],
31158
+ shortestPrefix: "oc",
31159
+ legacyPrefixes: [{ prefix: "oc/", stripPrefix: true }],
31160
+ nativeModelPatterns: [
31161
+ { pattern: /^ollamacloud\//i },
31162
+ { pattern: /^meta-llama\//i },
31163
+ { pattern: /^llama-/i },
31164
+ { pattern: /^llama3/i }
31165
+ ],
31166
+ isDirectApi: true
31167
+ },
31168
+ {
31169
+ name: "opencode-zen",
31170
+ displayName: "OpenCode Zen",
31171
+ transport: "openai",
31172
+ tokenStrategy: "delta-aware",
31173
+ baseUrl: "https://opencode.ai/zen",
31174
+ baseUrlEnvVars: ["OPENCODE_BASE_URL"],
31175
+ apiPath: "/v1/chat/completions",
31176
+ apiKeyEnvVar: "OPENCODE_API_KEY",
31177
+ apiKeyDescription: "OpenCode Zen (Free)",
31178
+ apiKeyUrl: "https://opencode.ai/",
31179
+ publicKeyFallback: "public",
31180
+ shortcuts: ["zen"],
31181
+ shortestPrefix: "zen",
31182
+ legacyPrefixes: [{ prefix: "zen/", stripPrefix: true }],
31183
+ isDirectApi: true
31184
+ },
31185
+ {
31186
+ name: "opencode-zen-go",
31187
+ displayName: "OpenCode Zen Go",
31188
+ transport: "openai",
31189
+ tokenStrategy: "delta-aware",
31190
+ baseUrl: "https://opencode.ai/zen/go",
31191
+ baseUrlEnvVars: ["OPENCODE_BASE_URL"],
31192
+ apiPath: "/v1/chat/completions",
31193
+ apiKeyEnvVar: "OPENCODE_API_KEY",
31194
+ apiKeyDescription: "OpenCode Zen Go (Lite Plan)",
31195
+ apiKeyUrl: "https://opencode.ai/",
31196
+ shortcuts: ["zengo", "zgo"],
31197
+ shortestPrefix: "zengo",
31198
+ legacyPrefixes: [
31199
+ { prefix: "zengo/", stripPrefix: true },
31200
+ { prefix: "zgo/", stripPrefix: true }
31201
+ ],
31202
+ isDirectApi: true
31203
+ },
31204
+ {
31205
+ name: "vertex",
31206
+ displayName: "Vertex AI",
31207
+ transport: "vertex",
31208
+ baseUrl: "",
31209
+ apiPath: "",
31210
+ apiKeyEnvVar: "VERTEX_PROJECT",
31211
+ apiKeyAliases: ["VERTEX_API_KEY"],
31212
+ apiKeyDescription: "Vertex AI API Key",
31213
+ apiKeyUrl: "https://console.cloud.google.com/vertex-ai",
31214
+ shortcuts: ["v", "vertex"],
31215
+ shortestPrefix: "v",
31216
+ legacyPrefixes: [
31217
+ { prefix: "v/", stripPrefix: true },
31218
+ { prefix: "vertex/", stripPrefix: true }
31219
+ ],
31220
+ isDirectApi: true
31221
+ },
31222
+ {
31223
+ name: "litellm",
31224
+ displayName: "LiteLLM",
31225
+ transport: "litellm",
31226
+ baseUrl: "",
31227
+ baseUrlEnvVars: ["LITELLM_BASE_URL"],
31228
+ apiPath: "/v1/chat/completions",
31229
+ apiKeyEnvVar: "LITELLM_API_KEY",
31230
+ apiKeyDescription: "LiteLLM API Key",
31231
+ apiKeyUrl: "https://docs.litellm.ai/",
31232
+ shortcuts: ["litellm", "ll"],
31233
+ shortestPrefix: "ll",
31234
+ legacyPrefixes: [
31235
+ { prefix: "litellm/", stripPrefix: true },
31236
+ { prefix: "ll/", stripPrefix: true }
31237
+ ],
31238
+ isDirectApi: true
31239
+ },
31240
+ {
31241
+ name: "poe",
31242
+ displayName: "Poe",
31243
+ transport: "poe",
31244
+ baseUrl: "https://api.poe.com",
31245
+ apiPath: "/v1/chat/completions",
31246
+ apiKeyEnvVar: "POE_API_KEY",
31247
+ apiKeyDescription: "Poe API Key",
31248
+ apiKeyUrl: "https://poe.com/api_key",
31249
+ shortcuts: ["poe"],
31250
+ shortestPrefix: "poe",
31251
+ legacyPrefixes: [],
31252
+ nativeModelPatterns: [{ pattern: /^poe:/i }],
31253
+ isDirectApi: true
31254
+ },
31255
+ {
31256
+ name: "ollama",
31257
+ displayName: "Ollama",
31258
+ transport: "local",
31259
+ baseUrl: "http://localhost:11434",
31260
+ apiPath: "/api/chat",
31261
+ apiKeyEnvVar: "",
31262
+ apiKeyDescription: "Ollama (Local)",
31263
+ apiKeyUrl: "",
31264
+ shortcuts: ["ollama"],
31265
+ shortestPrefix: "ollama",
31266
+ legacyPrefixes: [
31267
+ { prefix: "ollama/", stripPrefix: true },
31268
+ { prefix: "ollama:", stripPrefix: true }
31269
+ ],
31270
+ isLocal: true
31271
+ },
31272
+ {
31273
+ name: "lmstudio",
31274
+ displayName: "LM Studio",
31275
+ transport: "local",
31276
+ baseUrl: "http://localhost:1234",
31277
+ apiPath: "/v1/chat/completions",
31278
+ apiKeyEnvVar: "",
31279
+ apiKeyDescription: "LM Studio (Local)",
31280
+ apiKeyUrl: "",
31281
+ shortcuts: ["lms", "lmstudio", "mlstudio"],
31282
+ shortestPrefix: "lms",
31283
+ legacyPrefixes: [
31284
+ { prefix: "lmstudio/", stripPrefix: true },
31285
+ { prefix: "lmstudio:", stripPrefix: true },
31286
+ { prefix: "mlstudio/", stripPrefix: true },
31287
+ { prefix: "mlstudio:", stripPrefix: true }
31288
+ ],
31289
+ isLocal: true
31290
+ },
31291
+ {
31292
+ name: "vllm",
31293
+ displayName: "vLLM",
31294
+ transport: "local",
31295
+ baseUrl: "http://localhost:8000",
31296
+ apiPath: "/v1/chat/completions",
31297
+ apiKeyEnvVar: "",
31298
+ apiKeyDescription: "vLLM (Local)",
31299
+ apiKeyUrl: "",
31300
+ shortcuts: ["vllm"],
31301
+ shortestPrefix: "vllm",
31302
+ legacyPrefixes: [
31303
+ { prefix: "vllm/", stripPrefix: true },
31304
+ { prefix: "vllm:", stripPrefix: true }
31305
+ ],
31306
+ isLocal: true
31307
+ },
31308
+ {
31309
+ name: "mlx",
31310
+ displayName: "MLX",
31311
+ transport: "local",
31312
+ baseUrl: "http://localhost:8080",
31313
+ apiPath: "/v1/chat/completions",
31314
+ apiKeyEnvVar: "",
31315
+ apiKeyDescription: "MLX (Local)",
31316
+ apiKeyUrl: "",
31317
+ shortcuts: ["mlx"],
31318
+ shortestPrefix: "mlx",
31319
+ legacyPrefixes: [
31320
+ { prefix: "mlx/", stripPrefix: true },
31321
+ { prefix: "mlx:", stripPrefix: true }
31322
+ ],
31323
+ isLocal: true
31324
+ },
31325
+ {
31326
+ name: "qwen",
31327
+ displayName: "Qwen",
31328
+ transport: "openai",
31329
+ baseUrl: "",
31330
+ apiPath: "",
31331
+ apiKeyEnvVar: "",
31332
+ apiKeyDescription: "Qwen (auto-routed via OpenRouter)",
31333
+ apiKeyUrl: "",
31334
+ shortcuts: [],
31335
+ shortestPrefix: "qwen",
31336
+ legacyPrefixes: [],
31337
+ nativeModelPatterns: [{ pattern: /^qwen/i }]
31338
+ },
31339
+ {
31340
+ name: "native-anthropic",
31341
+ displayName: "Anthropic (Native)",
31342
+ transport: "anthropic",
31343
+ baseUrl: "",
31344
+ apiPath: "",
31345
+ apiKeyEnvVar: "",
31346
+ apiKeyDescription: "Anthropic (Native Claude Code auth)",
31347
+ apiKeyUrl: "",
31348
+ shortcuts: [],
31349
+ shortestPrefix: "",
31350
+ legacyPrefixes: [],
31351
+ nativeModelPatterns: [{ pattern: /^anthropic\//i }, { pattern: /^claude-/i }]
31352
+ }
31353
+ ];
31354
+ });
31355
+
30249
31356
  // src/providers/model-parser.ts
30250
31357
  function parseModelSpec(modelSpec) {
30251
31358
  const original = modelSpec;
@@ -30342,140 +31449,32 @@ function getLegacySyntaxWarning(parsed) {
30342
31449
  return `Deprecation warning: "${parsed.original}" uses legacy prefix syntax.
30343
31450
  ` + ` Consider using: ${newSyntax}`;
30344
31451
  }
30345
- var PROVIDER_SHORTCUTS, DIRECT_API_PROVIDERS, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
31452
+ var PROVIDER_SHORTCUTS, LOCAL_PROVIDERS, NATIVE_MODEL_PATTERNS, LEGACY_PREFIX_PATTERNS;
30346
31453
  var init_model_parser = __esm(() => {
30347
- PROVIDER_SHORTCUTS = {
30348
- g: "google",
30349
- gemini: "google",
30350
- oai: "openai",
30351
- or: "openrouter",
30352
- mm: "minimax",
30353
- mmax: "minimax",
30354
- mmc: "minimax-coding",
30355
- kimi: "kimi",
30356
- moon: "kimi",
30357
- moonshot: "kimi",
30358
- kc: "kimi-coding",
30359
- glm: "glm",
30360
- zhipu: "glm",
30361
- gc: "glm-coding",
30362
- zai: "zai",
30363
- oc: "ollamacloud",
30364
- zen: "opencode-zen",
30365
- zengo: "opencode-zen-go",
30366
- zgo: "opencode-zen-go",
30367
- v: "vertex",
30368
- vertex: "vertex",
30369
- go: "gemini-codeassist",
30370
- llama: "ollamacloud",
30371
- lc: "ollamacloud",
30372
- meta: "ollamacloud",
30373
- poe: "poe",
30374
- litellm: "litellm",
30375
- ll: "litellm",
30376
- ollama: "ollama",
30377
- lms: "lmstudio",
30378
- lmstudio: "lmstudio",
30379
- mlstudio: "lmstudio",
30380
- vllm: "vllm",
30381
- mlx: "mlx"
30382
- };
30383
- DIRECT_API_PROVIDERS = new Set([
30384
- "google",
30385
- "openai",
30386
- "minimax",
30387
- "kimi",
30388
- "minimax-coding",
30389
- "kimi-coding",
30390
- "glm",
30391
- "glm-coding",
30392
- "zai",
30393
- "ollamacloud",
30394
- "opencode-zen",
30395
- "vertex",
30396
- "gemini-codeassist",
30397
- "poe",
30398
- "litellm"
30399
- ]);
30400
- LOCAL_PROVIDERS = new Set(["ollama", "lmstudio", "vllm", "mlx"]);
30401
- NATIVE_MODEL_PATTERNS = [
30402
- { pattern: /^google\//i, provider: "google" },
30403
- { pattern: /^gemini-/i, provider: "google" },
30404
- { pattern: /^openai\//i, provider: "openai" },
30405
- { pattern: /^gpt-/i, provider: "openai" },
30406
- { pattern: /^o1(-|$)/i, provider: "openai" },
30407
- { pattern: /^o3(-|$)/i, provider: "openai" },
30408
- { pattern: /^chatgpt-/i, provider: "openai" },
30409
- { pattern: /^minimax\//i, provider: "minimax" },
30410
- { pattern: /^minimax-/i, provider: "minimax" },
30411
- { pattern: /^abab-/i, provider: "minimax" },
30412
- { pattern: /^kimi-for-coding$/i, provider: "kimi-coding" },
30413
- { pattern: /^moonshot(ai)?\//i, provider: "kimi" },
30414
- { pattern: /^moonshot-/i, provider: "kimi" },
30415
- { pattern: /^kimi-/i, provider: "kimi" },
30416
- { pattern: /^zhipu\//i, provider: "glm" },
30417
- { pattern: /^glm-/i, provider: "glm" },
30418
- { pattern: /^chatglm-/i, provider: "glm" },
30419
- { pattern: /^z-ai\//i, provider: "zai" },
30420
- { pattern: /^zai\//i, provider: "zai" },
30421
- { pattern: /^ollamacloud\//i, provider: "ollamacloud" },
30422
- { pattern: /^meta-llama\//i, provider: "ollamacloud" },
30423
- { pattern: /^llama-/i, provider: "ollamacloud" },
30424
- { pattern: /^llama3/i, provider: "ollamacloud" },
30425
- { pattern: /^openrouter\//i, provider: "openrouter" },
30426
- { pattern: /^qwen/i, provider: "qwen" },
30427
- { pattern: /^poe:/i, provider: "poe" },
30428
- { pattern: /^anthropic\//i, provider: "native-anthropic" },
30429
- { pattern: /^claude-/i, provider: "native-anthropic" }
30430
- ];
30431
- LEGACY_PREFIX_PATTERNS = [
30432
- { prefix: "g/", provider: "google", stripPrefix: true },
30433
- { prefix: "gemini/", provider: "google", stripPrefix: true },
30434
- { prefix: "oai/", provider: "openai", stripPrefix: true },
30435
- { prefix: "or/", provider: "openrouter", stripPrefix: true },
30436
- { prefix: "mmax/", provider: "minimax", stripPrefix: true },
30437
- { prefix: "mm/", provider: "minimax", stripPrefix: true },
30438
- { prefix: "mmc/", provider: "minimax-coding", stripPrefix: true },
30439
- { prefix: "kimi/", provider: "kimi", stripPrefix: true },
30440
- { prefix: "moonshot/", provider: "kimi", stripPrefix: true },
30441
- { prefix: "kc/", provider: "kimi-coding", stripPrefix: true },
30442
- { prefix: "glm/", provider: "glm", stripPrefix: true },
30443
- { prefix: "zhipu/", provider: "glm", stripPrefix: true },
30444
- { prefix: "gc/", provider: "glm-coding", stripPrefix: true },
30445
- { prefix: "zai/", provider: "zai", stripPrefix: true },
30446
- { prefix: "oc/", provider: "ollamacloud", stripPrefix: true },
30447
- { prefix: "zen/", provider: "opencode-zen", stripPrefix: true },
30448
- { prefix: "zengo/", provider: "opencode-zen-go", stripPrefix: true },
30449
- { prefix: "zgo/", provider: "opencode-zen-go", stripPrefix: true },
30450
- { prefix: "v/", provider: "vertex", stripPrefix: true },
30451
- { prefix: "vertex/", provider: "vertex", stripPrefix: true },
30452
- { prefix: "go/", provider: "gemini-codeassist", stripPrefix: true },
30453
- { prefix: "ollama/", provider: "ollama", stripPrefix: true },
30454
- { prefix: "ollama:", provider: "ollama", stripPrefix: true },
30455
- { prefix: "lmstudio/", provider: "lmstudio", stripPrefix: true },
30456
- { prefix: "lmstudio:", provider: "lmstudio", stripPrefix: true },
30457
- { prefix: "mlstudio/", provider: "lmstudio", stripPrefix: true },
30458
- { prefix: "mlstudio:", provider: "lmstudio", stripPrefix: true },
30459
- { prefix: "vllm/", provider: "vllm", stripPrefix: true },
30460
- { prefix: "vllm:", provider: "vllm", stripPrefix: true },
30461
- { prefix: "mlx/", provider: "mlx", stripPrefix: true },
30462
- { prefix: "mlx:", provider: "mlx", stripPrefix: true }
30463
- ];
31454
+ init_provider_definitions();
31455
+ PROVIDER_SHORTCUTS = getShortcuts();
31456
+ LOCAL_PROVIDERS = {
31457
+ has(name) {
31458
+ return isLocalTransport(name);
31459
+ }
31460
+ };
31461
+ NATIVE_MODEL_PATTERNS = getNativeModelPatterns();
31462
+ LEGACY_PREFIX_PATTERNS = getLegacyPrefixPatterns();
30464
31463
  });
30465
31464
 
30466
31465
  // src/auth/oauth-registry.ts
30467
- import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
30468
- import { join as join7 } from "path";
30469
- import { homedir as homedir6 } from "os";
31466
+ import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
31467
+ import { join as join8 } from "path";
31468
+ import { homedir as homedir7 } from "os";
30470
31469
  function hasValidOAuthCredentials(descriptor) {
30471
- const credPath = join7(homedir6(), ".claudish", descriptor.credentialFile);
30472
- if (!existsSync7(credPath))
31470
+ const credPath = join8(homedir7(), ".claudish", descriptor.credentialFile);
31471
+ if (!existsSync8(credPath))
30473
31472
  return false;
30474
31473
  if (descriptor.validationMode === "file-exists") {
30475
31474
  return true;
30476
31475
  }
30477
31476
  try {
30478
- const data = JSON.parse(readFileSync6(credPath, "utf-8"));
31477
+ const data = JSON.parse(readFileSync7(credPath, "utf-8"));
30479
31478
  if (!data.access_token)
30480
31479
  return false;
30481
31480
  if (data.refresh_token)
@@ -30555,9 +31554,9 @@ var init_static_fallback = __esm(() => {
30555
31554
  });
30556
31555
 
30557
31556
  // src/providers/catalog-resolvers/openrouter.ts
30558
- import { readFileSync as readFileSync7, existsSync as existsSync8 } from "fs";
30559
- import { join as join8 } from "path";
30560
- import { homedir as homedir7 } from "os";
31557
+ import { readFileSync as readFileSync8, existsSync as existsSync9 } from "fs";
31558
+ import { join as join9 } from "path";
31559
+ import { homedir as homedir8 } from "os";
30561
31560
 
30562
31561
  class OpenRouterCatalogResolver {
30563
31562
  provider = "openrouter";
@@ -30602,10 +31601,10 @@ class OpenRouterCatalogResolver {
30602
31601
  _getModels() {
30603
31602
  if (_memCache)
30604
31603
  return _memCache;
30605
- const diskPath = join8(homedir7(), ".claudish", "all-models.json");
30606
- if (existsSync8(diskPath)) {
31604
+ const diskPath = join9(homedir8(), ".claudish", "all-models.json");
31605
+ if (existsSync9(diskPath)) {
30607
31606
  try {
30608
- const data = JSON.parse(readFileSync7(diskPath, "utf-8"));
31607
+ const data = JSON.parse(readFileSync8(diskPath, "utf-8"));
30609
31608
  if (Array.isArray(data.models) && data.models.length > 0) {
30610
31609
  _memCache = data.models;
30611
31610
  return _memCache;
@@ -30622,16 +31621,16 @@ var init_openrouter = __esm(() => {
30622
31621
  });
30623
31622
 
30624
31623
  // src/providers/catalog-resolvers/litellm.ts
30625
- import { readFileSync as readFileSync8, existsSync as existsSync9 } from "fs";
30626
- import { join as join9 } from "path";
30627
- import { homedir as homedir8 } from "os";
31624
+ import { readFileSync as readFileSync9, existsSync as existsSync10 } from "fs";
31625
+ import { join as join10 } from "path";
31626
+ import { homedir as homedir9 } from "os";
30628
31627
  import { createHash as createHash3 } from "crypto";
30629
31628
  function getCachePath() {
30630
31629
  const baseUrl = process.env.LITELLM_BASE_URL;
30631
31630
  if (!baseUrl)
30632
31631
  return null;
30633
31632
  const hash2 = createHash3("sha256").update(baseUrl).digest("hex").substring(0, 16);
30634
- return join9(homedir8(), ".claudish", `litellm-models-${hash2}.json`);
31633
+ return join10(homedir9(), ".claudish", `litellm-models-${hash2}.json`);
30635
31634
  }
30636
31635
 
30637
31636
  class LiteLLMCatalogResolver {
@@ -30659,10 +31658,10 @@ class LiteLLMCatalogResolver {
30659
31658
  }
30660
31659
  async warmCache() {
30661
31660
  const path = getCachePath();
30662
- if (!path || !existsSync9(path))
31661
+ if (!path || !existsSync10(path))
30663
31662
  return;
30664
31663
  try {
30665
- const data = JSON.parse(readFileSync8(path, "utf-8"));
31664
+ const data = JSON.parse(readFileSync9(path, "utf-8"));
30666
31665
  if (Array.isArray(data.models)) {
30667
31666
  _memCache2 = data.models.map((m) => m.name ?? m.id?.replace("litellm@", "") ?? "");
30668
31667
  }
@@ -30675,10 +31674,10 @@ class LiteLLMCatalogResolver {
30675
31674
  if (_memCache2)
30676
31675
  return _memCache2;
30677
31676
  const path = getCachePath();
30678
- if (!path || !existsSync9(path))
31677
+ if (!path || !existsSync10(path))
30679
31678
  return null;
30680
31679
  try {
30681
- const data = JSON.parse(readFileSync8(path, "utf-8"));
31680
+ const data = JSON.parse(readFileSync9(path, "utf-8"));
30682
31681
  if (Array.isArray(data.models)) {
30683
31682
  _memCache2 = data.models.map((m) => m.name ?? m.id?.replace("litellm@", "") ?? "");
30684
31683
  return _memCache2;
@@ -30737,17 +31736,17 @@ var init_model_catalog_resolver = __esm(() => {
30737
31736
  });
30738
31737
 
30739
31738
  // src/providers/auto-route.ts
30740
- import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
30741
- import { join as join10 } from "path";
30742
- import { homedir as homedir9 } from "os";
31739
+ import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
31740
+ import { join as join11 } from "path";
31741
+ import { homedir as homedir10 } from "os";
30743
31742
  import { createHash as createHash4 } from "crypto";
30744
31743
  function readLiteLLMCacheSync(baseUrl) {
30745
31744
  const hash2 = createHash4("sha256").update(baseUrl).digest("hex").substring(0, 16);
30746
- const cachePath = join10(homedir9(), ".claudish", `litellm-models-${hash2}.json`);
30747
- if (!existsSync10(cachePath))
31745
+ const cachePath = join11(homedir10(), ".claudish", `litellm-models-${hash2}.json`);
31746
+ if (!existsSync11(cachePath))
30748
31747
  return null;
30749
31748
  try {
30750
- const data = JSON.parse(readFileSync9(cachePath, "utf-8"));
31749
+ const data = JSON.parse(readFileSync10(cachePath, "utf-8"));
30751
31750
  if (!Array.isArray(data.models))
30752
31751
  return null;
30753
31752
  return data.models;
@@ -30767,7 +31766,7 @@ function checkOAuthForProvider(nativeProvider, modelName) {
30767
31766
  };
30768
31767
  }
30769
31768
  function checkApiKeyForProvider(nativeProvider, modelName) {
30770
- const keyInfo = API_KEY_ENV_VARS[nativeProvider];
31769
+ const keyInfo = getApiKeyEnvVars(nativeProvider);
30771
31770
  if (!keyInfo)
30772
31771
  return null;
30773
31772
  if (keyInfo.envVar && process.env[keyInfo.envVar]) {
@@ -30858,11 +31857,11 @@ function autoRoute(modelName, nativeProvider) {
30858
31857
  return null;
30859
31858
  }
30860
31859
  function readZenModelCacheSync() {
30861
- const cachePath = join10(homedir9(), ".claudish", "zen-models.json");
30862
- if (!existsSync10(cachePath))
31860
+ const cachePath = join11(homedir10(), ".claudish", "zen-models.json");
31861
+ if (!existsSync11(cachePath))
30863
31862
  return null;
30864
31863
  try {
30865
- const data = JSON.parse(readFileSync9(cachePath, "utf-8"));
31864
+ const data = JSON.parse(readFileSync10(cachePath, "utf-8"));
30866
31865
  if (!Array.isArray(data.models))
30867
31866
  return null;
30868
31867
  return new Set(data.models.map((m) => m.id));
@@ -30889,13 +31888,13 @@ async function warmZenModelCache() {
30889
31888
  const models = (data.data ?? []).map((m) => ({ id: m.id }));
30890
31889
  if (models.length === 0)
30891
31890
  return;
30892
- const cacheDir = join10(homedir9(), ".claudish");
30893
- const { mkdirSync: mkdirSync5, writeFileSync: writeSync3 } = await import("fs");
30894
- mkdirSync5(cacheDir, { recursive: true });
30895
- writeSync3(join10(cacheDir, "zen-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
31891
+ const cacheDir = join11(homedir10(), ".claudish");
31892
+ const { mkdirSync: mkdirSync6, writeFileSync: writeSync3 } = await import("fs");
31893
+ mkdirSync6(cacheDir, { recursive: true });
31894
+ writeSync3(join11(cacheDir, "zen-models.json"), JSON.stringify({ models, fetchedAt: new Date().toISOString() }));
30896
31895
  }
30897
31896
  function hasProviderCredentials(provider) {
30898
- const keyInfo = API_KEY_ENV_VARS[provider];
31897
+ const keyInfo = getApiKeyEnvVars(provider);
30899
31898
  if (keyInfo?.envVar && process.env[keyInfo.envVar])
30900
31899
  return true;
30901
31900
  if (keyInfo?.aliases?.some((a) => process.env[a]))
@@ -30948,27 +31947,12 @@ function getFallbackChain(modelName, nativeProvider) {
30948
31947
  }
30949
31948
  return routes;
30950
31949
  }
30951
- var API_KEY_ENV_VARS, PROVIDER_HINT_MAP, PROVIDER_TO_PREFIX, DISPLAY_NAMES, SUBSCRIPTION_ALTERNATIVES;
31950
+ var PROVIDER_HINT_MAP, PROVIDER_TO_PREFIX, DISPLAY_NAMES, SUBSCRIPTION_ALTERNATIVES;
30952
31951
  var init_auto_route = __esm(() => {
30953
31952
  init_oauth_registry();
30954
31953
  init_model_catalog_resolver();
30955
- API_KEY_ENV_VARS = {
30956
- google: { envVar: "GEMINI_API_KEY" },
30957
- "gemini-codeassist": { envVar: "GEMINI_API_KEY" },
30958
- openai: { envVar: "OPENAI_API_KEY" },
30959
- minimax: { envVar: "MINIMAX_API_KEY" },
30960
- "minimax-coding": { envVar: "MINIMAX_CODING_API_KEY" },
30961
- kimi: { envVar: "MOONSHOT_API_KEY", aliases: ["KIMI_API_KEY"] },
30962
- "kimi-coding": { envVar: "KIMI_CODING_API_KEY" },
30963
- glm: { envVar: "ZHIPU_API_KEY", aliases: ["GLM_API_KEY"] },
30964
- "glm-coding": { envVar: "GLM_CODING_API_KEY", aliases: ["ZAI_CODING_API_KEY"] },
30965
- zai: { envVar: "ZAI_API_KEY" },
30966
- ollamacloud: { envVar: "OLLAMA_API_KEY" },
30967
- litellm: { envVar: "LITELLM_API_KEY" },
30968
- openrouter: { envVar: "OPENROUTER_API_KEY" },
30969
- vertex: { envVar: "VERTEX_API_KEY", aliases: ["VERTEX_PROJECT"] },
30970
- poe: { envVar: "POE_API_KEY" }
30971
- };
31954
+ init_provider_definitions();
31955
+ init_provider_definitions();
30972
31956
  PROVIDER_HINT_MAP = {
30973
31957
  "kimi-coding": {
30974
31958
  loginFlag: "--kimi-login",
@@ -31012,39 +31996,22 @@ var init_auto_route = __esm(() => {
31012
31996
  apiKeyEnvVar: "OLLAMA_API_KEY"
31013
31997
  }
31014
31998
  };
31015
- PROVIDER_TO_PREFIX = {
31016
- google: "g",
31017
- openai: "oai",
31018
- minimax: "mm",
31019
- "minimax-coding": "mmc",
31020
- kimi: "kimi",
31021
- "kimi-coding": "kc",
31022
- glm: "glm",
31023
- "glm-coding": "gc",
31024
- zai: "zai",
31025
- ollamacloud: "oc",
31026
- "opencode-zen": "zen",
31027
- "opencode-zen-go": "zengo",
31028
- litellm: "ll",
31029
- vertex: "v",
31030
- "gemini-codeassist": "go"
31031
- };
31032
- DISPLAY_NAMES = {
31033
- google: "Gemini",
31034
- openai: "OpenAI",
31035
- minimax: "MiniMax",
31036
- "minimax-coding": "MiniMax Coding",
31037
- kimi: "Kimi",
31038
- "kimi-coding": "Kimi Coding",
31039
- glm: "GLM",
31040
- "glm-coding": "GLM Coding",
31041
- zai: "Z.AI",
31042
- ollamacloud: "OllamaCloud",
31043
- "opencode-zen": "OpenCode Zen",
31044
- "opencode-zen-go": "OpenCode Zen Go",
31045
- litellm: "LiteLLM",
31046
- openrouter: "OpenRouter"
31047
- };
31999
+ PROVIDER_TO_PREFIX = (() => {
32000
+ const map3 = {};
32001
+ for (const def of getAllProviders()) {
32002
+ if (def.shortestPrefix) {
32003
+ map3[def.name] = def.shortestPrefix;
32004
+ }
32005
+ }
32006
+ return map3;
32007
+ })();
32008
+ DISPLAY_NAMES = (() => {
32009
+ const map3 = {};
32010
+ for (const def of getAllProviders()) {
32011
+ map3[def.name] = def.displayName;
32012
+ }
32013
+ return map3;
32014
+ })();
31048
32015
  SUBSCRIPTION_ALTERNATIVES = {
31049
32016
  kimi: {
31050
32017
  subscriptionProvider: "kimi-coding",
@@ -31275,40 +32242,20 @@ function resolveRemoteProvider(modelId) {
31275
32242
  if (parsed.provider === "custom-url") {
31276
32243
  return null;
31277
32244
  }
31278
- const providerNameMap = {
31279
- google: "gemini",
31280
- openai: "openai",
31281
- openrouter: "openrouter",
31282
- minimax: "minimax",
31283
- "minimax-coding": "minimax-coding",
31284
- kimi: "kimi",
31285
- "kimi-coding": "kimi-coding",
31286
- glm: "glm",
31287
- "glm-coding": "glm-coding",
31288
- zai: "zai",
31289
- ollamacloud: "ollamacloud",
31290
- "opencode-zen": "opencode-zen",
31291
- "opencode-zen-go": "opencode-zen-go",
31292
- vertex: "vertex",
31293
- "gemini-codeassist": "gemini-codeassist",
31294
- litellm: "litellm"
31295
- };
31296
- const mappedProviderName = providerNameMap[parsed.provider];
31297
- if (mappedProviderName) {
31298
- const provider = providers.find((p) => p.name === mappedProviderName);
31299
- if (provider) {
31300
- return {
31301
- provider,
31302
- modelName: parsed.model,
31303
- isLegacySyntax: parsed.isLegacySyntax
31304
- };
31305
- }
32245
+ const mappedName = parsed.provider === "google" ? "gemini" : parsed.provider;
32246
+ const provider = providers.find((p) => p.name === mappedName || p.name === parsed.provider);
32247
+ if (provider) {
32248
+ return {
32249
+ provider,
32250
+ modelName: parsed.model,
32251
+ isLegacySyntax: parsed.isLegacySyntax
32252
+ };
31306
32253
  }
31307
- for (const provider of providers) {
31308
- for (const prefix of provider.prefixes) {
32254
+ for (const provider2 of providers) {
32255
+ for (const prefix of provider2.prefixes) {
31309
32256
  if (modelId.startsWith(prefix)) {
31310
32257
  return {
31311
- provider,
32258
+ provider: provider2,
31312
32259
  modelName: modelId.slice(prefix.length),
31313
32260
  isLegacySyntax: true
31314
32261
  };
@@ -31354,128 +32301,12 @@ Set it with:
31354
32301
  function getRegisteredRemoteProviders() {
31355
32302
  return getRemoteProviders();
31356
32303
  }
31357
- var getRemoteProviders = () => [
31358
- {
31359
- name: "gemini",
31360
- baseUrl: process.env.GEMINI_BASE_URL || "https://generativelanguage.googleapis.com",
31361
- apiPath: "/v1beta/models/{model}:streamGenerateContent?alt=sse",
31362
- apiKeyEnvVar: "GEMINI_API_KEY",
31363
- prefixes: ["g/", "gemini/"]
31364
- },
31365
- {
31366
- name: "gemini-codeassist",
31367
- baseUrl: "https://cloudcode-pa.googleapis.com",
31368
- apiPath: "/v1internal:streamGenerateContent?alt=sse",
31369
- apiKeyEnvVar: "",
31370
- prefixes: ["go/"]
31371
- },
31372
- {
31373
- name: "openai",
31374
- baseUrl: process.env.OPENAI_BASE_URL || "https://api.openai.com",
31375
- apiPath: "/v1/chat/completions",
31376
- apiKeyEnvVar: "OPENAI_API_KEY",
31377
- prefixes: ["oai/"]
31378
- },
31379
- {
31380
- name: "openrouter",
31381
- baseUrl: "https://openrouter.ai",
31382
- apiPath: "/api/v1/chat/completions",
31383
- apiKeyEnvVar: "OPENROUTER_API_KEY",
31384
- prefixes: ["or/"],
31385
- headers: {
31386
- "HTTP-Referer": "https://claudish.com",
31387
- "X-Title": "Claudish - OpenRouter Proxy"
31388
- }
31389
- },
31390
- {
31391
- name: "minimax",
31392
- baseUrl: process.env.MINIMAX_BASE_URL || "https://api.minimax.io",
31393
- apiPath: "/anthropic/v1/messages",
31394
- apiKeyEnvVar: "MINIMAX_API_KEY",
31395
- prefixes: ["mmax/", "mm/"],
31396
- authScheme: "bearer"
31397
- },
31398
- {
31399
- name: "minimax-coding",
31400
- baseUrl: process.env.MINIMAX_CODING_BASE_URL || "https://api.minimax.io",
31401
- apiPath: "/anthropic/v1/messages",
31402
- apiKeyEnvVar: "MINIMAX_CODING_API_KEY",
31403
- prefixes: ["mmc/"],
31404
- authScheme: "bearer"
31405
- },
31406
- {
31407
- name: "kimi",
31408
- baseUrl: process.env.MOONSHOT_BASE_URL || process.env.KIMI_BASE_URL || "https://api.moonshot.ai",
31409
- apiPath: "/anthropic/v1/messages",
31410
- apiKeyEnvVar: "MOONSHOT_API_KEY",
31411
- prefixes: ["kimi/", "moonshot/"]
31412
- },
31413
- {
31414
- name: "kimi-coding",
31415
- baseUrl: "https://api.kimi.com/coding/v1",
31416
- apiPath: "/messages",
31417
- apiKeyEnvVar: "KIMI_CODING_API_KEY",
31418
- prefixes: ["kc/"]
31419
- },
31420
- {
31421
- name: "glm",
31422
- baseUrl: process.env.ZHIPU_BASE_URL || process.env.GLM_BASE_URL || "https://open.bigmodel.cn",
31423
- apiPath: "/api/paas/v4/chat/completions",
31424
- apiKeyEnvVar: "ZHIPU_API_KEY",
31425
- prefixes: ["glm/", "zhipu/"]
31426
- },
31427
- {
31428
- name: "glm-coding",
31429
- baseUrl: "https://api.z.ai",
31430
- apiPath: "/api/coding/paas/v4/chat/completions",
31431
- apiKeyEnvVar: "GLM_CODING_API_KEY",
31432
- prefixes: ["gc/"]
31433
- },
31434
- {
31435
- name: "zai",
31436
- baseUrl: process.env.ZAI_BASE_URL || "https://api.z.ai",
31437
- apiPath: "/api/anthropic/v1/messages",
31438
- apiKeyEnvVar: "ZAI_API_KEY",
31439
- prefixes: ["zai/"]
31440
- },
31441
- {
31442
- name: "ollamacloud",
31443
- baseUrl: process.env.OLLAMACLOUD_BASE_URL || "https://ollama.com",
31444
- apiPath: "/api/chat",
31445
- apiKeyEnvVar: "OLLAMA_API_KEY",
31446
- prefixes: ["oc/"]
31447
- },
31448
- {
31449
- name: "opencode-zen",
31450
- baseUrl: process.env.OPENCODE_BASE_URL || "https://opencode.ai/zen",
31451
- apiPath: "/v1/chat/completions",
31452
- apiKeyEnvVar: "OPENCODE_API_KEY",
31453
- prefixes: ["zen/"]
31454
- },
31455
- {
31456
- name: "opencode-zen-go",
31457
- baseUrl: process.env.OPENCODE_BASE_URL ? process.env.OPENCODE_BASE_URL.replace("/zen", "/zen/go") : "https://opencode.ai/zen/go",
31458
- apiPath: "/v1/chat/completions",
31459
- apiKeyEnvVar: "OPENCODE_API_KEY",
31460
- prefixes: ["zengo/", "zgo/"]
31461
- },
31462
- {
31463
- name: "vertex",
31464
- baseUrl: "",
31465
- apiPath: "",
31466
- apiKeyEnvVar: "VERTEX_PROJECT",
31467
- prefixes: ["v/", "vertex/"]
31468
- },
31469
- {
31470
- name: "litellm",
31471
- baseUrl: process.env.LITELLM_BASE_URL || "",
31472
- apiPath: "/v1/chat/completions",
31473
- apiKeyEnvVar: "LITELLM_API_KEY",
31474
- prefixes: ["litellm/", "ll/"]
31475
- }
31476
- ];
32304
+ var getRemoteProviders = () => {
32305
+ return getAllProviders().filter((def) => !def.isLocal && def.baseUrl !== "" && def.name !== "qwen" && def.name !== "native-anthropic").map(toRemoteProvider);
32306
+ };
31477
32307
  var init_remote_provider_registry = __esm(() => {
31478
32308
  init_model_parser();
32309
+ init_provider_definitions();
31479
32310
  });
31480
32311
 
31481
32312
  // src/providers/provider-resolver.ts
@@ -31489,9 +32320,27 @@ __export(exports_provider_resolver, {
31489
32320
  getMissingKeyResolutions: () => getMissingKeyResolutions,
31490
32321
  getMissingKeyError: () => getMissingKeyError
31491
32322
  });
31492
- import { existsSync as existsSync11 } from "fs";
31493
- import { join as join11 } from "path";
31494
- import { homedir as homedir10 } from "os";
32323
+ import { existsSync as existsSync12 } from "fs";
32324
+ import { join as join12 } from "path";
32325
+ import { homedir as homedir11 } from "os";
32326
+ function getApiKeyInfoForProvider(providerName) {
32327
+ const lookupName = providerName === "gemini" ? "google" : providerName;
32328
+ const info = getApiKeyInfo(lookupName);
32329
+ if (info) {
32330
+ return {
32331
+ envVar: info.envVar,
32332
+ description: info.description,
32333
+ url: info.url,
32334
+ aliases: info.aliases,
32335
+ oauthFallback: info.oauthFallback
32336
+ };
32337
+ }
32338
+ return {
32339
+ envVar: "",
32340
+ description: `${providerName} API Key`,
32341
+ url: ""
32342
+ };
32343
+ }
31495
32344
  function isApiKeyAvailable(info) {
31496
32345
  if (!info.envVar) {
31497
32346
  return true;
@@ -31508,8 +32357,8 @@ function isApiKeyAvailable(info) {
31508
32357
  }
31509
32358
  if (info.oauthFallback) {
31510
32359
  try {
31511
- const credPath = join11(homedir10(), ".claudish", info.oauthFallback);
31512
- if (existsSync11(credPath)) {
32360
+ const credPath = join12(homedir11(), ".claudish", info.oauthFallback);
32361
+ if (existsSync12(credPath)) {
31513
32362
  return true;
31514
32363
  }
31515
32364
  } catch {}
@@ -31792,105 +32641,21 @@ var init_provider_resolver = __esm(() => {
31792
32641
  init_remote_provider_registry();
31793
32642
  init_auto_route();
31794
32643
  init_model_parser();
31795
- API_KEY_INFO = {
31796
- openrouter: {
31797
- envVar: "OPENROUTER_API_KEY",
31798
- description: "OpenRouter API Key",
31799
- url: "https://openrouter.ai/keys"
31800
- },
31801
- gemini: {
31802
- envVar: "GEMINI_API_KEY",
31803
- description: "Google Gemini API Key",
31804
- url: "https://aistudio.google.com/app/apikey"
31805
- },
31806
- "gemini-codeassist": {
31807
- envVar: "",
31808
- description: "Gemini Code Assist (OAuth)",
31809
- url: "https://cloud.google.com/code-assist"
31810
- },
31811
- vertex: {
31812
- envVar: "VERTEX_API_KEY",
31813
- description: "Vertex AI API Key",
31814
- url: "https://console.cloud.google.com/vertex-ai",
31815
- aliases: ["VERTEX_PROJECT"]
31816
- },
31817
- openai: {
31818
- envVar: "OPENAI_API_KEY",
31819
- description: "OpenAI API Key",
31820
- url: "https://platform.openai.com/api-keys"
31821
- },
31822
- minimax: {
31823
- envVar: "MINIMAX_API_KEY",
31824
- description: "MiniMax API Key",
31825
- url: "https://www.minimaxi.com/"
31826
- },
31827
- "minimax-coding": {
31828
- envVar: "MINIMAX_CODING_API_KEY",
31829
- description: "MiniMax Coding Plan API Key",
31830
- url: "https://platform.minimax.io/user-center/basic-information/interface-key"
31831
- },
31832
- kimi: {
31833
- envVar: "MOONSHOT_API_KEY",
31834
- description: "Kimi/Moonshot API Key",
31835
- url: "https://platform.moonshot.cn/",
31836
- aliases: ["KIMI_API_KEY"]
31837
- },
31838
- "kimi-coding": {
31839
- envVar: "KIMI_CODING_API_KEY",
31840
- description: "Kimi Coding API Key",
31841
- url: "https://kimi.com/code (get key from membership page, or run: claudish --kimi-login)",
31842
- oauthFallback: "kimi-oauth.json"
32644
+ init_provider_definitions();
32645
+ API_KEY_INFO = new Proxy({}, {
32646
+ get(_target, prop) {
32647
+ return getApiKeyInfoForProvider(prop);
31843
32648
  },
31844
- glm: {
31845
- envVar: "ZHIPU_API_KEY",
31846
- description: "GLM/Zhipu API Key",
31847
- url: "https://open.bigmodel.cn/",
31848
- aliases: ["GLM_API_KEY"]
31849
- },
31850
- "glm-coding": {
31851
- envVar: "GLM_CODING_API_KEY",
31852
- description: "GLM Coding Plan API Key",
31853
- url: "https://z.ai/subscribe",
31854
- aliases: ["ZAI_CODING_API_KEY"]
31855
- },
31856
- ollamacloud: {
31857
- envVar: "OLLAMA_API_KEY",
31858
- description: "OllamaCloud API Key",
31859
- url: "https://ollama.com/account"
31860
- },
31861
- "opencode-zen": {
31862
- envVar: "",
31863
- description: "OpenCode Zen (Free)",
31864
- url: "https://opencode.ai/"
31865
- },
31866
- zai: {
31867
- envVar: "ZAI_API_KEY",
31868
- description: "Z.AI API Key",
31869
- url: "https://z.ai/"
31870
- },
31871
- litellm: {
31872
- envVar: "LITELLM_API_KEY",
31873
- description: "LiteLLM API Key",
31874
- url: "https://docs.litellm.ai/"
32649
+ has() {
32650
+ return true;
31875
32651
  }
31876
- };
31877
- PROVIDER_DISPLAY_NAMES = {
31878
- gemini: "Gemini",
31879
- "gemini-codeassist": "Gemini Code Assist",
31880
- vertex: "Vertex AI",
31881
- openai: "OpenAI",
31882
- openrouter: "OpenRouter",
31883
- minimax: "MiniMax",
31884
- "minimax-coding": "MiniMax Coding",
31885
- kimi: "Kimi",
31886
- "kimi-coding": "Kimi Coding",
31887
- glm: "GLM",
31888
- "glm-coding": "GLM Coding",
31889
- zai: "Z.AI",
31890
- ollamacloud: "OllamaCloud",
31891
- "opencode-zen": "OpenCode Zen",
31892
- litellm: "LiteLLM"
31893
- };
32652
+ });
32653
+ PROVIDER_DISPLAY_NAMES = new Proxy({}, {
32654
+ get(_target, prop) {
32655
+ const lookupName = prop === "gemini" ? "google" : prop;
32656
+ return getDisplayName(lookupName);
32657
+ }
32658
+ });
31894
32659
  });
31895
32660
 
31896
32661
  // src/adapters/tool-name-utils.ts
@@ -32219,6 +32984,12 @@ var init_openai_tools = __esm(() => {
32219
32984
  });
32220
32985
 
32221
32986
  // src/adapters/base-adapter.ts
32987
+ function matchesModelFamily(modelId, family) {
32988
+ const lower = modelId.toLowerCase();
32989
+ const fam = family.toLowerCase();
32990
+ return lower.startsWith(fam) || lower.includes(`/${fam}`);
32991
+ }
32992
+
32222
32993
  class BaseModelAdapter {
32223
32994
  modelId;
32224
32995
  toolNameMap = new Map;
@@ -32414,13 +33185,15 @@ var init_grok_adapter = __esm(() => {
32414
33185
  return params;
32415
33186
  }
32416
33187
  shouldHandle(modelId) {
32417
- return modelId.includes("grok") || modelId.includes("x-ai/");
33188
+ return matchesModelFamily(modelId, "grok") || modelId.toLowerCase().includes("x-ai/");
32418
33189
  }
32419
33190
  getName() {
32420
33191
  return "GrokAdapter";
32421
33192
  }
32422
33193
  getContextWindow() {
32423
33194
  const model = this.modelId.toLowerCase();
33195
+ if (model.includes("grok-4.20") || model.includes("grok-4-20"))
33196
+ return 2000000;
32424
33197
  if (model.includes("grok-4.1-fast") || model.includes("grok-4-1-fast"))
32425
33198
  return 2000000;
32426
33199
  if (model.includes("grok-4-fast"))
@@ -33666,10 +34439,10 @@ CRITICAL INSTRUCTION FOR OUTPUT FORMAT:
33666
34439
  this.reasoningBlockDepth = 0;
33667
34440
  }
33668
34441
  getContextWindow() {
33669
- return 1e6;
34442
+ return 1048576;
33670
34443
  }
33671
34444
  shouldHandle(modelId) {
33672
- return modelId.includes("gemini") || modelId.includes("google/");
34445
+ return matchesModelFamily(modelId, "gemini") || modelId.toLowerCase().includes("google/");
33673
34446
  }
33674
34447
  getName() {
33675
34448
  return "GeminiAdapter";
@@ -33722,7 +34495,7 @@ var init_codex_adapter = __esm(() => {
33722
34495
  };
33723
34496
  }
33724
34497
  shouldHandle(modelId) {
33725
- return modelId.toLowerCase().includes("codex");
34498
+ return matchesModelFamily(modelId, "codex");
33726
34499
  }
33727
34500
  getName() {
33728
34501
  return "CodexAdapter";
@@ -33886,9 +34659,11 @@ var init_openai_adapter = __esm(() => {
33886
34659
  }
33887
34660
  getContextWindow() {
33888
34661
  const model = this.modelId.toLowerCase();
34662
+ if (model.includes("gpt-5.4"))
34663
+ return 1050000;
33889
34664
  if (model.includes("gpt-5"))
33890
- return 256000;
33891
- if (model.includes("o1") || model.includes("o3"))
34665
+ return 400000;
34666
+ if (model.includes("o1") || model.includes("o3") || model.includes("o4"))
33892
34667
  return 200000;
33893
34668
  if (model.includes("gpt-4o") || model.includes("gpt-4-turbo"))
33894
34669
  return 128000;
@@ -33994,8 +34769,7 @@ var init_qwen_adapter = __esm(() => {
33994
34769
  return request;
33995
34770
  }
33996
34771
  shouldHandle(modelId) {
33997
- const lower = modelId.toLowerCase();
33998
- return lower.includes("qwen") || lower.includes("alibaba");
34772
+ return matchesModelFamily(modelId, "qwen") || matchesModelFamily(modelId, "alibaba");
33999
34773
  }
34000
34774
  getName() {
34001
34775
  return "QwenAdapter";
@@ -34025,7 +34799,7 @@ var init_minimax_adapter = __esm(() => {
34025
34799
  return request;
34026
34800
  }
34027
34801
  shouldHandle(modelId) {
34028
- return modelId.includes("minimax");
34802
+ return matchesModelFamily(modelId, "minimax");
34029
34803
  }
34030
34804
  getName() {
34031
34805
  return "MiniMaxAdapter";
@@ -34054,7 +34828,7 @@ var init_deepseek_adapter = __esm(() => {
34054
34828
  return request;
34055
34829
  }
34056
34830
  shouldHandle(modelId) {
34057
- return modelId.includes("deepseek");
34831
+ return matchesModelFamily(modelId, "deepseek");
34058
34832
  }
34059
34833
  getName() {
34060
34834
  return "DeepSeekAdapter";
@@ -34068,18 +34842,20 @@ var init_glm_adapter = __esm(() => {
34068
34842
  init_base_adapter();
34069
34843
  init_logger();
34070
34844
  GLM_CONTEXT_WINDOWS = [
34071
- ["glm-5", 204800],
34072
- ["glm-4.7-flash", 200000],
34073
- ["glm-4.7", 204800],
34074
- ["glm-4.6v", 128000],
34845
+ ["glm-5-turbo", 202752],
34846
+ ["glm-5", 80000],
34847
+ ["glm-4.7-flash", 202752],
34848
+ ["glm-4.7", 202752],
34849
+ ["glm-4.6v", 131072],
34075
34850
  ["glm-4.6", 204800],
34076
- ["glm-4.5v", 64000],
34851
+ ["glm-4.5v", 65536],
34077
34852
  ["glm-4.5-flash", 131072],
34078
34853
  ["glm-4.5-air", 131072],
34079
34854
  ["glm-4.5", 131072],
34080
34855
  ["glm-4-long", 1e6],
34081
34856
  ["glm-4-plus", 128000],
34082
34857
  ["glm-4-flash", 128000],
34858
+ ["glm-4-32b", 128000],
34083
34859
  ["glm-4", 128000],
34084
34860
  ["glm-3-turbo", 128000],
34085
34861
  ["glm-", 131072]
@@ -34101,7 +34877,7 @@ var init_glm_adapter = __esm(() => {
34101
34877
  return request;
34102
34878
  }
34103
34879
  shouldHandle(modelId) {
34104
- return modelId.includes("glm-") || modelId.includes("zhipu/");
34880
+ return matchesModelFamily(modelId, "glm-") || matchesModelFamily(modelId, "chatglm-") || modelId.toLowerCase().includes("zhipu/");
34105
34881
  }
34106
34882
  getName() {
34107
34883
  return "GLMAdapter";
@@ -34121,6 +34897,42 @@ var init_glm_adapter = __esm(() => {
34121
34897
  };
34122
34898
  });
34123
34899
 
34900
+ // src/adapters/xiaomi-adapter.ts
34901
+ var XiaomiAdapter;
34902
+ var init_xiaomi_adapter = __esm(() => {
34903
+ init_base_adapter();
34904
+ init_logger();
34905
+ XiaomiAdapter = class XiaomiAdapter extends BaseModelAdapter {
34906
+ processTextContent(textContent, accumulatedText) {
34907
+ return {
34908
+ cleanedText: textContent,
34909
+ extractedToolCalls: [],
34910
+ wasTransformed: false
34911
+ };
34912
+ }
34913
+ getToolNameLimit() {
34914
+ return 64;
34915
+ }
34916
+ prepareRequest(request, originalRequest) {
34917
+ if (originalRequest.thinking) {
34918
+ log(`[XiaomiAdapter] Stripping thinking object (not supported by Xiaomi API)`);
34919
+ delete request.thinking;
34920
+ }
34921
+ this.truncateToolNames(request);
34922
+ if (request.messages) {
34923
+ this.truncateToolNamesInMessages(request.messages);
34924
+ }
34925
+ return request;
34926
+ }
34927
+ shouldHandle(modelId) {
34928
+ return matchesModelFamily(modelId, "xiaomi") || matchesModelFamily(modelId, "mimo");
34929
+ }
34930
+ getName() {
34931
+ return "XiaomiAdapter";
34932
+ }
34933
+ };
34934
+ });
34935
+
34124
34936
  // src/adapters/adapter-manager.ts
34125
34937
  var exports_adapter_manager = {};
34126
34938
  __export(exports_adapter_manager, {
@@ -34139,7 +34951,8 @@ class AdapterManager {
34139
34951
  new QwenAdapter(modelId),
34140
34952
  new MiniMaxAdapter(modelId),
34141
34953
  new DeepSeekAdapter(modelId),
34142
- new GLMAdapter(modelId)
34954
+ new GLMAdapter(modelId),
34955
+ new XiaomiAdapter(modelId)
34143
34956
  ];
34144
34957
  this.defaultAdapter = new DefaultAdapter(modelId);
34145
34958
  }
@@ -34165,6 +34978,7 @@ var init_adapter_manager = __esm(() => {
34165
34978
  init_minimax_adapter();
34166
34979
  init_deepseek_adapter();
34167
34980
  init_glm_adapter();
34981
+ init_xiaomi_adapter();
34168
34982
  });
34169
34983
 
34170
34984
  // src/cli.ts
@@ -34181,31 +34995,31 @@ __export(exports_cli, {
34181
34995
  getMissingKeyError: () => getMissingKeyError
34182
34996
  });
34183
34997
  import {
34184
- readFileSync as readFileSync10,
34185
- writeFileSync as writeFileSync5,
34186
- existsSync as existsSync12,
34187
- mkdirSync as mkdirSync5,
34998
+ readFileSync as readFileSync11,
34999
+ writeFileSync as writeFileSync6,
35000
+ existsSync as existsSync13,
35001
+ mkdirSync as mkdirSync6,
34188
35002
  copyFileSync,
34189
- readdirSync,
34190
- unlinkSync as unlinkSync3
35003
+ readdirSync as readdirSync3,
35004
+ unlinkSync as unlinkSync4
34191
35005
  } from "fs";
34192
35006
  import { fileURLToPath as fileURLToPath3 } from "url";
34193
- import { dirname as dirname3, join as join12 } from "path";
34194
- import { homedir as homedir11 } from "os";
35007
+ import { dirname as dirname3, join as join13 } from "path";
35008
+ import { homedir as homedir12 } from "os";
34195
35009
  function getVersion() {
34196
35010
  return VERSION;
34197
35011
  }
34198
35012
  function clearAllModelCaches() {
34199
- const cacheDir = join12(homedir11(), ".claudish");
34200
- if (!existsSync12(cacheDir))
35013
+ const cacheDir = join13(homedir12(), ".claudish");
35014
+ if (!existsSync13(cacheDir))
34201
35015
  return;
34202
35016
  const cachePatterns = ["all-models.json", "pricing-cache.json"];
34203
35017
  let cleared = 0;
34204
35018
  try {
34205
- const files = readdirSync(cacheDir);
35019
+ const files = readdirSync3(cacheDir);
34206
35020
  for (const file2 of files) {
34207
35021
  if (cachePatterns.includes(file2) || file2.startsWith("litellm-models-")) {
34208
- unlinkSync3(join12(cacheDir, file2));
35022
+ unlinkSync4(join13(cacheDir, file2));
34209
35023
  cleared++;
34210
35024
  }
34211
35025
  }
@@ -34229,6 +35043,7 @@ async function parseArgs(args) {
34229
35043
  monitor: false,
34230
35044
  stdin: false,
34231
35045
  freeOnly: false,
35046
+ noLogs: false,
34232
35047
  claudeArgs: []
34233
35048
  };
34234
35049
  const claudishModel = process.env[ENV.CLAUDISH_MODEL];
@@ -34395,6 +35210,8 @@ async function parseArgs(args) {
34395
35210
  process.exit(0);
34396
35211
  } else if (arg === "--summarize-tools") {
34397
35212
  config3.summarizeTools = true;
35213
+ } else if (arg === "--no-logs") {
35214
+ config3.noLogs = true;
34398
35215
  } else if (arg === "--") {
34399
35216
  config3.claudeArgs.push(...args.slice(i + 1));
34400
35217
  break;
@@ -34496,9 +35313,9 @@ async function fetchOllamaModels() {
34496
35313
  }
34497
35314
  async function searchAndPrintModels(query, forceUpdate) {
34498
35315
  let models = [];
34499
- if (!forceUpdate && existsSync12(ALL_MODELS_JSON_PATH)) {
35316
+ if (!forceUpdate && existsSync13(ALL_MODELS_JSON_PATH)) {
34500
35317
  try {
34501
- const cacheData = JSON.parse(readFileSync10(ALL_MODELS_JSON_PATH, "utf-8"));
35318
+ const cacheData = JSON.parse(readFileSync11(ALL_MODELS_JSON_PATH, "utf-8"));
34502
35319
  const lastUpdated = new Date(cacheData.lastUpdated);
34503
35320
  const now = new Date;
34504
35321
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -34515,8 +35332,8 @@ async function searchAndPrintModels(query, forceUpdate) {
34515
35332
  throw new Error(`API returned ${response.status}`);
34516
35333
  const data = await response.json();
34517
35334
  models = data.data;
34518
- mkdirSync5(CLAUDISH_CACHE_DIR2, { recursive: true });
34519
- writeFileSync5(ALL_MODELS_JSON_PATH, JSON.stringify({
35335
+ mkdirSync6(CLAUDISH_CACHE_DIR2, { recursive: true });
35336
+ writeFileSync6(ALL_MODELS_JSON_PATH, JSON.stringify({
34520
35337
  lastUpdated: new Date().toISOString(),
34521
35338
  models
34522
35339
  }), "utf-8");
@@ -34666,9 +35483,9 @@ Found ${results.length} matching models:
34666
35483
  async function printAllModels(jsonOutput, forceUpdate) {
34667
35484
  let models = [];
34668
35485
  const [ollamaModels, zenModels] = await Promise.all([fetchOllamaModels(), fetchZenModels()]);
34669
- if (!forceUpdate && existsSync12(ALL_MODELS_JSON_PATH)) {
35486
+ if (!forceUpdate && existsSync13(ALL_MODELS_JSON_PATH)) {
34670
35487
  try {
34671
- const cacheData = JSON.parse(readFileSync10(ALL_MODELS_JSON_PATH, "utf-8"));
35488
+ const cacheData = JSON.parse(readFileSync11(ALL_MODELS_JSON_PATH, "utf-8"));
34672
35489
  const lastUpdated = new Date(cacheData.lastUpdated);
34673
35490
  const now = new Date;
34674
35491
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -34688,8 +35505,8 @@ async function printAllModels(jsonOutput, forceUpdate) {
34688
35505
  throw new Error(`API returned ${response.status}`);
34689
35506
  const data = await response.json();
34690
35507
  models = data.data;
34691
- mkdirSync5(CLAUDISH_CACHE_DIR2, { recursive: true });
34692
- writeFileSync5(ALL_MODELS_JSON_PATH, JSON.stringify({
35508
+ mkdirSync6(CLAUDISH_CACHE_DIR2, { recursive: true });
35509
+ writeFileSync6(ALL_MODELS_JSON_PATH, JSON.stringify({
34693
35510
  lastUpdated: new Date().toISOString(),
34694
35511
  models
34695
35512
  }), "utf-8");
@@ -34869,12 +35686,12 @@ async function printAllModels(jsonOutput, forceUpdate) {
34869
35686
  console.log("Top models: claudish --top-models");
34870
35687
  }
34871
35688
  function isCacheStale() {
34872
- const cachePath = existsSync12(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
34873
- if (!existsSync12(cachePath)) {
35689
+ const cachePath = existsSync13(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
35690
+ if (!existsSync13(cachePath)) {
34874
35691
  return true;
34875
35692
  }
34876
35693
  try {
34877
- const jsonContent = readFileSync10(cachePath, "utf-8");
35694
+ const jsonContent = readFileSync11(cachePath, "utf-8");
34878
35695
  const data = JSON.parse(jsonContent);
34879
35696
  if (!data.lastUpdated) {
34880
35697
  return true;
@@ -34953,10 +35770,10 @@ async function updateModelsFromOpenRouter() {
34953
35770
  providers.add(provider);
34954
35771
  }
34955
35772
  let version2 = "1.2.0";
34956
- const existingPath = existsSync12(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
34957
- if (existsSync12(existingPath)) {
35773
+ const existingPath = existsSync13(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
35774
+ if (existsSync13(existingPath)) {
34958
35775
  try {
34959
- const existing = JSON.parse(readFileSync10(existingPath, "utf-8"));
35776
+ const existing = JSON.parse(readFileSync11(existingPath, "utf-8"));
34960
35777
  version2 = existing.version || version2;
34961
35778
  } catch {}
34962
35779
  }
@@ -34966,8 +35783,8 @@ async function updateModelsFromOpenRouter() {
34966
35783
  source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
34967
35784
  models: recommendations
34968
35785
  };
34969
- mkdirSync5(CLAUDISH_CACHE_DIR2, { recursive: true });
34970
- writeFileSync5(CACHED_MODELS_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
35786
+ mkdirSync6(CLAUDISH_CACHE_DIR2, { recursive: true });
35787
+ writeFileSync6(CACHED_MODELS_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
34971
35788
  console.error(`\u2705 Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
34972
35789
  } catch (error46) {
34973
35790
  console.error(`\u274C Failed to update models: ${error46 instanceof Error ? error46.message : String(error46)}`);
@@ -34985,8 +35802,8 @@ async function checkAndUpdateModelsCache(forceUpdate = false) {
34985
35802
  await updateModelsFromOpenRouter();
34986
35803
  } else {
34987
35804
  try {
34988
- const cachePath = existsSync12(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
34989
- const data = JSON.parse(readFileSync10(cachePath, "utf-8"));
35805
+ const cachePath = existsSync13(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
35806
+ const data = JSON.parse(readFileSync11(cachePath, "utf-8"));
34990
35807
  console.error(`\u2713 Using cached models (last updated: ${data.lastUpdated})`);
34991
35808
  } catch {}
34992
35809
  }
@@ -35293,6 +36110,7 @@ OPTIONS:
35293
36110
  -p, --profile <name> Use named profile for model mapping (default: uses default profile)
35294
36111
  --port <port> Proxy server port (default: random)
35295
36112
  -d, --debug Enable debug logging to file (logs/claudish_*.log)
36113
+ --no-logs Disable always-on structural logging (~/.claudish/logs/)
35296
36114
  --log-level <level> Log verbosity: debug (full), info (truncated), minimal (labels only)
35297
36115
  -q, --quiet Suppress [claudish] log messages (default in single-shot mode)
35298
36116
  -v, --verbose Show [claudish] log messages (default in interactive mode)
@@ -35544,8 +36362,8 @@ MORE INFO:
35544
36362
  }
35545
36363
  function printAIAgentGuide() {
35546
36364
  try {
35547
- const guidePath = join12(__dirname4, "../AI_AGENT_GUIDE.md");
35548
- const guideContent = readFileSync10(guidePath, "utf-8");
36365
+ const guidePath = join13(__dirname4, "../AI_AGENT_GUIDE.md");
36366
+ const guideContent = readFileSync11(guidePath, "utf-8");
35549
36367
  console.log(guideContent);
35550
36368
  } catch (error46) {
35551
36369
  console.error("Error reading AI Agent Guide:");
@@ -35561,19 +36379,19 @@ async function initializeClaudishSkill() {
35561
36379
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
35562
36380
  `);
35563
36381
  const cwd = process.cwd();
35564
- const claudeDir = join12(cwd, ".claude");
35565
- const skillsDir = join12(claudeDir, "skills");
35566
- const claudishSkillDir = join12(skillsDir, "claudish-usage");
35567
- const skillFile = join12(claudishSkillDir, "SKILL.md");
35568
- if (existsSync12(skillFile)) {
36382
+ const claudeDir = join13(cwd, ".claude");
36383
+ const skillsDir = join13(claudeDir, "skills");
36384
+ const claudishSkillDir = join13(skillsDir, "claudish-usage");
36385
+ const skillFile = join13(claudishSkillDir, "SKILL.md");
36386
+ if (existsSync13(skillFile)) {
35569
36387
  console.log("\u2705 Claudish skill already installed at:");
35570
36388
  console.log(` ${skillFile}
35571
36389
  `);
35572
36390
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
35573
36391
  return;
35574
36392
  }
35575
- const sourceSkillPath = join12(__dirname4, "../skills/claudish-usage/SKILL.md");
35576
- if (!existsSync12(sourceSkillPath)) {
36393
+ const sourceSkillPath = join13(__dirname4, "../skills/claudish-usage/SKILL.md");
36394
+ if (!existsSync13(sourceSkillPath)) {
35577
36395
  console.error("\u274C Error: Claudish skill file not found in installation.");
35578
36396
  console.error(` Expected at: ${sourceSkillPath}`);
35579
36397
  console.error(`
@@ -35582,16 +36400,16 @@ async function initializeClaudishSkill() {
35582
36400
  process.exit(1);
35583
36401
  }
35584
36402
  try {
35585
- if (!existsSync12(claudeDir)) {
35586
- mkdirSync5(claudeDir, { recursive: true });
36403
+ if (!existsSync13(claudeDir)) {
36404
+ mkdirSync6(claudeDir, { recursive: true });
35587
36405
  console.log("\uD83D\uDCC1 Created .claude/ directory");
35588
36406
  }
35589
- if (!existsSync12(skillsDir)) {
35590
- mkdirSync5(skillsDir, { recursive: true });
36407
+ if (!existsSync13(skillsDir)) {
36408
+ mkdirSync6(skillsDir, { recursive: true });
35591
36409
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
35592
36410
  }
35593
- if (!existsSync12(claudishSkillDir)) {
35594
- mkdirSync5(claudishSkillDir, { recursive: true });
36411
+ if (!existsSync13(claudishSkillDir)) {
36412
+ mkdirSync6(claudishSkillDir, { recursive: true });
35595
36413
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
35596
36414
  }
35597
36415
  copyFileSync(sourceSkillPath, skillFile);
@@ -35633,9 +36451,9 @@ function printAvailableModels() {
35633
36451
  let lastUpdated = "unknown";
35634
36452
  let models = [];
35635
36453
  try {
35636
- const cachePath = existsSync12(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
35637
- if (existsSync12(cachePath)) {
35638
- const data = JSON.parse(readFileSync10(cachePath, "utf-8"));
36454
+ const cachePath = existsSync13(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36455
+ if (existsSync13(cachePath)) {
36456
+ const data = JSON.parse(readFileSync11(cachePath, "utf-8"));
35639
36457
  lastUpdated = data.lastUpdated || "unknown";
35640
36458
  models = data.models || [];
35641
36459
  }
@@ -35684,9 +36502,9 @@ Force update: claudish --list-models --force-update
35684
36502
  `);
35685
36503
  }
35686
36504
  function printAvailableModelsJSON() {
35687
- const jsonPath = existsSync12(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
36505
+ const jsonPath = existsSync13(CACHED_MODELS_PATH) ? CACHED_MODELS_PATH : BUNDLED_MODELS_PATH;
35688
36506
  try {
35689
- const jsonContent = readFileSync10(jsonPath, "utf-8");
36507
+ const jsonContent = readFileSync11(jsonPath, "utf-8");
35690
36508
  const data = JSON.parse(jsonContent);
35691
36509
  console.log(JSON.stringify(data, null, 2));
35692
36510
  } catch (error46) {
@@ -35771,7 +36589,7 @@ async function fetchGLMCodingModels() {
35771
36589
  return [];
35772
36590
  }
35773
36591
  }
35774
- var __filename4, __dirname4, VERSION = "5.14.0", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
36592
+ var __filename4, __dirname4, VERSION = "5.16.0", CACHE_MAX_AGE_DAYS2 = 2, CLAUDISH_CACHE_DIR2, BUNDLED_MODELS_PATH, CACHED_MODELS_PATH, ALL_MODELS_JSON_PATH;
35775
36593
  var init_cli = __esm(() => {
35776
36594
  init_config();
35777
36595
  init_model_loader();
@@ -35783,13 +36601,13 @@ var init_cli = __esm(() => {
35783
36601
  __filename4 = fileURLToPath3(import.meta.url);
35784
36602
  __dirname4 = dirname3(__filename4);
35785
36603
  try {
35786
- const packageJson = JSON.parse(readFileSync10(join12(__dirname4, "../package.json"), "utf-8"));
36604
+ const packageJson = JSON.parse(readFileSync11(join13(__dirname4, "../package.json"), "utf-8"));
35787
36605
  VERSION = packageJson.version;
35788
36606
  } catch {}
35789
- CLAUDISH_CACHE_DIR2 = join12(homedir11(), ".claudish");
35790
- BUNDLED_MODELS_PATH = join12(__dirname4, "../recommended-models.json");
35791
- CACHED_MODELS_PATH = join12(CLAUDISH_CACHE_DIR2, "recommended-models.json");
35792
- ALL_MODELS_JSON_PATH = join12(CLAUDISH_CACHE_DIR2, "all-models.json");
36607
+ CLAUDISH_CACHE_DIR2 = join13(homedir12(), ".claudish");
36608
+ BUNDLED_MODELS_PATH = join13(__dirname4, "../recommended-models.json");
36609
+ CACHED_MODELS_PATH = join13(CLAUDISH_CACHE_DIR2, "recommended-models.json");
36610
+ ALL_MODELS_JSON_PATH = join13(CLAUDISH_CACHE_DIR2, "all-models.json");
35793
36611
  });
35794
36612
 
35795
36613
  // src/update-checker.ts
@@ -35801,9 +36619,9 @@ __export(exports_update_checker, {
35801
36619
  checkForUpdates: () => checkForUpdates
35802
36620
  });
35803
36621
  import { execSync } from "child_process";
35804
- import { existsSync as existsSync13, mkdirSync as mkdirSync6, readFileSync as readFileSync11, unlinkSync as unlinkSync4, writeFileSync as writeFileSync6 } from "fs";
35805
- import { homedir as homedir12, platform as platform2, tmpdir } from "os";
35806
- import { join as join13 } from "path";
36622
+ import { existsSync as existsSync14, mkdirSync as mkdirSync7, readFileSync as readFileSync12, unlinkSync as unlinkSync5, writeFileSync as writeFileSync7 } from "fs";
36623
+ import { homedir as homedir13, platform as platform2, tmpdir } from "os";
36624
+ import { join as join14 } from "path";
35807
36625
  import { createInterface } from "readline";
35808
36626
  function getUpdateCommand() {
35809
36627
  const scriptPath = process.argv[1] || "";
@@ -35815,27 +36633,27 @@ function getUpdateCommand() {
35815
36633
  function getCacheFilePath() {
35816
36634
  let cacheDir;
35817
36635
  if (isWindows) {
35818
- const localAppData = process.env.LOCALAPPDATA || join13(homedir12(), "AppData", "Local");
35819
- cacheDir = join13(localAppData, "claudish");
36636
+ const localAppData = process.env.LOCALAPPDATA || join14(homedir13(), "AppData", "Local");
36637
+ cacheDir = join14(localAppData, "claudish");
35820
36638
  } else {
35821
- cacheDir = join13(homedir12(), ".cache", "claudish");
36639
+ cacheDir = join14(homedir13(), ".cache", "claudish");
35822
36640
  }
35823
36641
  try {
35824
- if (!existsSync13(cacheDir)) {
35825
- mkdirSync6(cacheDir, { recursive: true });
36642
+ if (!existsSync14(cacheDir)) {
36643
+ mkdirSync7(cacheDir, { recursive: true });
35826
36644
  }
35827
- return join13(cacheDir, "update-check.json");
36645
+ return join14(cacheDir, "update-check.json");
35828
36646
  } catch {
35829
- return join13(tmpdir(), "claudish-update-check.json");
36647
+ return join14(tmpdir(), "claudish-update-check.json");
35830
36648
  }
35831
36649
  }
35832
36650
  function readCache() {
35833
36651
  try {
35834
36652
  const cachePath = getCacheFilePath();
35835
- if (!existsSync13(cachePath)) {
36653
+ if (!existsSync14(cachePath)) {
35836
36654
  return null;
35837
36655
  }
35838
- const data = JSON.parse(readFileSync11(cachePath, "utf-8"));
36656
+ const data = JSON.parse(readFileSync12(cachePath, "utf-8"));
35839
36657
  return data;
35840
36658
  } catch {
35841
36659
  return null;
@@ -35848,7 +36666,7 @@ function writeCache(latestVersion) {
35848
36666
  lastCheck: Date.now(),
35849
36667
  latestVersion
35850
36668
  };
35851
- writeFileSync6(cachePath, JSON.stringify(data), "utf-8");
36669
+ writeFileSync7(cachePath, JSON.stringify(data), "utf-8");
35852
36670
  } catch {}
35853
36671
  }
35854
36672
  function isCacheValid(cache) {
@@ -35858,8 +36676,8 @@ function isCacheValid(cache) {
35858
36676
  function clearCache() {
35859
36677
  try {
35860
36678
  const cachePath = getCacheFilePath();
35861
- if (existsSync13(cachePath)) {
35862
- unlinkSync4(cachePath);
36679
+ if (existsSync14(cachePath)) {
36680
+ unlinkSync5(cachePath);
35863
36681
  }
35864
36682
  } catch {}
35865
36683
  }
@@ -35895,7 +36713,7 @@ async function fetchLatestVersion() {
35895
36713
  }
35896
36714
  }
35897
36715
  function promptUser(question) {
35898
- return new Promise((resolve) => {
36716
+ return new Promise((resolve2) => {
35899
36717
  const rl = createInterface({
35900
36718
  input: process.stdin,
35901
36719
  output: process.stderr
@@ -35903,7 +36721,7 @@ function promptUser(question) {
35903
36721
  rl.question(question, (answer) => {
35904
36722
  rl.close();
35905
36723
  const normalized = answer.toLowerCase().trim();
35906
- resolve(normalized === "y" || normalized === "yes");
36724
+ resolve2(normalized === "y" || normalized === "yes");
35907
36725
  });
35908
36726
  });
35909
36727
  }
@@ -36014,7 +36832,7 @@ function getUpdateCommand2(method) {
36014
36832
  }
36015
36833
  }
36016
36834
  function promptUser2(question) {
36017
- return new Promise((resolve) => {
36835
+ return new Promise((resolve2) => {
36018
36836
  const rl = createInterface2({
36019
36837
  input: process.stdin,
36020
36838
  output: process.stdout
@@ -36022,7 +36840,7 @@ function promptUser2(question) {
36022
36840
  rl.question(question, (answer) => {
36023
36841
  rl.close();
36024
36842
  const normalized = answer.toLowerCase().trim();
36025
- resolve(normalized === "y" || normalized === "yes" || normalized === "");
36843
+ resolve2(normalized === "y" || normalized === "yes" || normalized === "");
36026
36844
  });
36027
36845
  });
36028
36846
  }
@@ -37708,13 +38526,13 @@ var PromisePolyfill;
37708
38526
  var init_promise_polyfill = __esm(() => {
37709
38527
  PromisePolyfill = class PromisePolyfill extends Promise {
37710
38528
  static withResolver() {
37711
- let resolve;
38529
+ let resolve2;
37712
38530
  let reject;
37713
38531
  const promise3 = new Promise((res, rej) => {
37714
- resolve = res;
38532
+ resolve2 = res;
37715
38533
  reject = rej;
37716
38534
  });
37717
- return { promise: promise3, resolve, reject };
38535
+ return { promise: promise3, resolve: resolve2, reject };
37718
38536
  }
37719
38537
  };
37720
38538
  });
@@ -37751,7 +38569,7 @@ function createPrompt(view) {
37751
38569
  output
37752
38570
  });
37753
38571
  const screen = new ScreenManager(rl);
37754
- const { promise: promise3, resolve, reject } = PromisePolyfill.withResolver();
38572
+ const { promise: promise3, resolve: resolve2, reject } = PromisePolyfill.withResolver();
37755
38573
  const cancel = () => reject(new CancelPromptError);
37756
38574
  if (signal) {
37757
38575
  const abort = () => reject(new AbortPromptError({ cause: signal.reason }));
@@ -37778,7 +38596,7 @@ function createPrompt(view) {
37778
38596
  cycle(() => {
37779
38597
  try {
37780
38598
  const nextView = view(config3, (value) => {
37781
- setImmediate(() => resolve(value));
38599
+ setImmediate(() => resolve2(value));
37782
38600
  });
37783
38601
  if (nextView === undefined) {
37784
38602
  const callerFilename = callSites[1]?.getFileName();
@@ -38339,14 +39157,14 @@ __export(exports_model_selector, {
38339
39157
  promptForApiKey: () => promptForApiKey,
38340
39158
  confirmAction: () => confirmAction
38341
39159
  });
38342
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync7, existsSync as existsSync14, mkdirSync as mkdirSync7 } from "fs";
38343
- import { join as join14, dirname as dirname4 } from "path";
38344
- import { homedir as homedir13 } from "os";
39160
+ import { readFileSync as readFileSync13, writeFileSync as writeFileSync8, existsSync as existsSync15, mkdirSync as mkdirSync8 } from "fs";
39161
+ import { join as join15, dirname as dirname4 } from "path";
39162
+ import { homedir as homedir14 } from "os";
38345
39163
  import { fileURLToPath as fileURLToPath4 } from "url";
38346
39164
  function loadRecommendedModels2() {
38347
- if (existsSync14(RECOMMENDED_MODELS_JSON_PATH)) {
39165
+ if (existsSync15(RECOMMENDED_MODELS_JSON_PATH)) {
38348
39166
  try {
38349
- const content = readFileSync12(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
39167
+ const content = readFileSync13(RECOMMENDED_MODELS_JSON_PATH, "utf-8");
38350
39168
  const data = JSON.parse(content);
38351
39169
  return (data.models || []).map((model) => ({
38352
39170
  ...model,
@@ -38359,9 +39177,9 @@ function loadRecommendedModels2() {
38359
39177
  return [];
38360
39178
  }
38361
39179
  async function fetchAllModels(forceUpdate = false) {
38362
- if (!forceUpdate && existsSync14(ALL_MODELS_JSON_PATH2)) {
39180
+ if (!forceUpdate && existsSync15(ALL_MODELS_JSON_PATH2)) {
38363
39181
  try {
38364
- const cacheData = JSON.parse(readFileSync12(ALL_MODELS_JSON_PATH2, "utf-8"));
39182
+ const cacheData = JSON.parse(readFileSync13(ALL_MODELS_JSON_PATH2, "utf-8"));
38365
39183
  const lastUpdated = new Date(cacheData.lastUpdated);
38366
39184
  const now = new Date;
38367
39185
  const ageInDays = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
@@ -38377,8 +39195,8 @@ async function fetchAllModels(forceUpdate = false) {
38377
39195
  throw new Error(`API returned ${response.status}`);
38378
39196
  const data = await response.json();
38379
39197
  const models = data.data;
38380
- mkdirSync7(CLAUDISH_CACHE_DIR3, { recursive: true });
38381
- writeFileSync7(ALL_MODELS_JSON_PATH2, JSON.stringify({
39198
+ mkdirSync8(CLAUDISH_CACHE_DIR3, { recursive: true });
39199
+ writeFileSync8(ALL_MODELS_JSON_PATH2, JSON.stringify({
38382
39200
  lastUpdated: new Date().toISOString(),
38383
39201
  models
38384
39202
  }), "utf-8");
@@ -38863,11 +39681,11 @@ async function fetchOllamaCloudModels() {
38863
39681
  }
38864
39682
  }
38865
39683
  function shouldRefreshForFreeModels() {
38866
- if (!existsSync14(ALL_MODELS_JSON_PATH2)) {
39684
+ if (!existsSync15(ALL_MODELS_JSON_PATH2)) {
38867
39685
  return true;
38868
39686
  }
38869
39687
  try {
38870
- const cacheData = JSON.parse(readFileSync12(ALL_MODELS_JSON_PATH2, "utf-8"));
39688
+ const cacheData = JSON.parse(readFileSync13(ALL_MODELS_JSON_PATH2, "utf-8"));
38871
39689
  const lastUpdated = new Date(cacheData.lastUpdated);
38872
39690
  const now = new Date;
38873
39691
  const ageInHours = (now.getTime() - lastUpdated.getTime()) / (1000 * 60 * 60);
@@ -39468,9 +40286,9 @@ var init_model_selector = __esm(() => {
39468
40286
  init_model_loader();
39469
40287
  __filename5 = fileURLToPath4(import.meta.url);
39470
40288
  __dirname5 = dirname4(__filename5);
39471
- CLAUDISH_CACHE_DIR3 = join14(homedir13(), ".claudish");
39472
- ALL_MODELS_JSON_PATH2 = join14(CLAUDISH_CACHE_DIR3, "all-models.json");
39473
- RECOMMENDED_MODELS_JSON_PATH = join14(__dirname5, "../recommended-models.json");
40289
+ CLAUDISH_CACHE_DIR3 = join15(homedir14(), ".claudish");
40290
+ ALL_MODELS_JSON_PATH2 = join15(CLAUDISH_CACHE_DIR3, "all-models.json");
40291
+ RECOMMENDED_MODELS_JSON_PATH = join15(__dirname5, "../recommended-models.json");
39474
40292
  PROVIDER_FILTER_ALIASES = {
39475
40293
  zen: "Zen",
39476
40294
  openrouter: "OpenRouter",
@@ -40328,11 +41146,11 @@ async function runConsentPrompt(ctx) {
40328
41146
  Does NOT send: prompts, paths, API keys, or credentials.
40329
41147
  Disable anytime: claudish telemetry off
40330
41148
  `);
40331
- const answer = await new Promise((resolve) => {
41149
+ const answer = await new Promise((resolve2) => {
40332
41150
  const rl = createInterface4({ input: process.stdin, output: process.stderr });
40333
41151
  rl.question("Send anonymous error report? [y/N] ", (ans) => {
40334
41152
  rl.close();
40335
- resolve(ans.trim().toLowerCase());
41153
+ resolve2(ans.trim().toLowerCase());
40336
41154
  });
40337
41155
  });
40338
41156
  const accepted = answer === "y" || answer === "yes";
@@ -40516,25 +41334,25 @@ var init_telemetry = __esm(() => {
40516
41334
 
40517
41335
  // src/stats-buffer.ts
40518
41336
  import {
40519
- existsSync as existsSync15,
40520
- mkdirSync as mkdirSync8,
40521
- readFileSync as readFileSync13,
41337
+ existsSync as existsSync16,
41338
+ mkdirSync as mkdirSync9,
41339
+ readFileSync as readFileSync14,
40522
41340
  renameSync,
40523
- unlinkSync as unlinkSync5,
40524
- writeFileSync as writeFileSync8
41341
+ unlinkSync as unlinkSync6,
41342
+ writeFileSync as writeFileSync9
40525
41343
  } from "fs";
40526
- import { homedir as homedir14 } from "os";
40527
- import { join as join15 } from "path";
41344
+ import { homedir as homedir15 } from "os";
41345
+ import { join as join16 } from "path";
40528
41346
  function ensureDir() {
40529
- if (!existsSync15(CLAUDISH_DIR)) {
40530
- mkdirSync8(CLAUDISH_DIR, { recursive: true });
41347
+ if (!existsSync16(CLAUDISH_DIR)) {
41348
+ mkdirSync9(CLAUDISH_DIR, { recursive: true });
40531
41349
  }
40532
41350
  }
40533
41351
  function readFromDisk() {
40534
41352
  try {
40535
- if (!existsSync15(BUFFER_FILE))
41353
+ if (!existsSync16(BUFFER_FILE))
40536
41354
  return [];
40537
- const raw = readFileSync13(BUFFER_FILE, "utf-8");
41355
+ const raw = readFileSync14(BUFFER_FILE, "utf-8");
40538
41356
  const parsed = JSON.parse(raw);
40539
41357
  if (!Array.isArray(parsed.events))
40540
41358
  return [];
@@ -40558,8 +41376,8 @@ function writeToDisk(events) {
40558
41376
  ensureDir();
40559
41377
  const trimmed = enforceSizeCap([...events]);
40560
41378
  const payload = { version: 1, events: trimmed };
40561
- const tmpFile = join15(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
40562
- writeFileSync8(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
41379
+ const tmpFile = join16(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
41380
+ writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
40563
41381
  renameSync(tmpFile, BUFFER_FILE);
40564
41382
  memoryCache = trimmed;
40565
41383
  } catch {}
@@ -40603,8 +41421,8 @@ function clearBuffer() {
40603
41421
  try {
40604
41422
  memoryCache = [];
40605
41423
  eventsSinceLastFlush = 0;
40606
- if (existsSync15(BUFFER_FILE)) {
40607
- unlinkSync5(BUFFER_FILE);
41424
+ if (existsSync16(BUFFER_FILE)) {
41425
+ unlinkSync6(BUFFER_FILE);
40608
41426
  }
40609
41427
  } catch {}
40610
41428
  }
@@ -40632,8 +41450,8 @@ function syncFlushOnExit() {
40632
41450
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, lastFlushTime, flushScheduled = false;
40633
41451
  var init_stats_buffer = __esm(() => {
40634
41452
  BUFFER_MAX_BYTES = 64 * 1024;
40635
- CLAUDISH_DIR = join15(homedir14(), ".claudish");
40636
- BUFFER_FILE = join15(CLAUDISH_DIR, "stats-buffer.json");
41453
+ CLAUDISH_DIR = join16(homedir15(), ".claudish");
41454
+ BUFFER_FILE = join16(CLAUDISH_DIR, "stats-buffer.json");
40637
41455
  lastFlushTime = Date.now();
40638
41456
  process.on("exit", syncFlushOnExit);
40639
41457
  process.on("SIGTERM", () => {
@@ -41118,16 +41936,16 @@ import { EventEmitter } from "events";
41118
41936
  import { Buffer as Buffer2 } from "buffer";
41119
41937
  import { Buffer as Buffer3 } from "buffer";
41120
41938
  import { EventEmitter as EventEmitter2 } from "events";
41121
- import { resolve, dirname as dirname5 } from "path";
41939
+ import { resolve as resolve2, dirname as dirname5 } from "path";
41122
41940
  import { fileURLToPath as fileURLToPath5 } from "url";
41123
- import { resolve as resolve2, isAbsolute, parse as parse6 } from "path";
41124
- import { existsSync as existsSync16 } from "fs";
41125
- import { basename, join as join16 } from "path";
41941
+ import { resolve as resolve22, isAbsolute, parse as parse6 } from "path";
41942
+ import { existsSync as existsSync17 } from "fs";
41943
+ import { basename, join as join17 } from "path";
41126
41944
  import os from "os";
41127
41945
  import path from "path";
41128
41946
  import { EventEmitter as EventEmitter3 } from "events";
41129
41947
  import { dlopen, toArrayBuffer as toArrayBuffer4, JSCallback, ptr as ptr4 } from "bun:ffi";
41130
- import { existsSync as existsSync22, writeFileSync as writeFileSync9 } from "fs";
41948
+ import { existsSync as existsSync22, writeFileSync as writeFileSync10 } from "fs";
41131
41949
  import { EventEmitter as EventEmitter4 } from "events";
41132
41950
  import { toArrayBuffer, ptr } from "bun:ffi";
41133
41951
  import { ptr as ptr2, toArrayBuffer as toArrayBuffer2 } from "bun:ffi";
@@ -43463,24 +44281,24 @@ function getParsers() {
43463
44281
  {
43464
44282
  filetype: "javascript",
43465
44283
  queries: {
43466
- highlights: [resolve(dirname5(fileURLToPath5(import.meta.url)), highlights_default)]
44284
+ highlights: [resolve2(dirname5(fileURLToPath5(import.meta.url)), highlights_default)]
43467
44285
  },
43468
- wasm: resolve(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_javascript_default)
44286
+ wasm: resolve2(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_javascript_default)
43469
44287
  },
43470
44288
  {
43471
44289
  filetype: "typescript",
43472
44290
  queries: {
43473
- highlights: [resolve(dirname5(fileURLToPath5(import.meta.url)), highlights_default2)]
44291
+ highlights: [resolve2(dirname5(fileURLToPath5(import.meta.url)), highlights_default2)]
43474
44292
  },
43475
- wasm: resolve(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_typescript_default)
44293
+ wasm: resolve2(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_typescript_default)
43476
44294
  },
43477
44295
  {
43478
44296
  filetype: "markdown",
43479
44297
  queries: {
43480
- highlights: [resolve(dirname5(fileURLToPath5(import.meta.url)), highlights_default3)],
43481
- injections: [resolve(dirname5(fileURLToPath5(import.meta.url)), injections_default)]
44298
+ highlights: [resolve2(dirname5(fileURLToPath5(import.meta.url)), highlights_default3)],
44299
+ injections: [resolve2(dirname5(fileURLToPath5(import.meta.url)), injections_default)]
43482
44300
  },
43483
- wasm: resolve(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_markdown_default),
44301
+ wasm: resolve2(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_markdown_default),
43484
44302
  injectionMapping: {
43485
44303
  nodeTypes: {
43486
44304
  inline: "markdown_inline",
@@ -43499,16 +44317,16 @@ function getParsers() {
43499
44317
  {
43500
44318
  filetype: "markdown_inline",
43501
44319
  queries: {
43502
- highlights: [resolve(dirname5(fileURLToPath5(import.meta.url)), highlights_default4)]
44320
+ highlights: [resolve2(dirname5(fileURLToPath5(import.meta.url)), highlights_default4)]
43503
44321
  },
43504
- wasm: resolve(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_markdown_inline_default)
44322
+ wasm: resolve2(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_markdown_inline_default)
43505
44323
  },
43506
44324
  {
43507
44325
  filetype: "zig",
43508
44326
  queries: {
43509
- highlights: [resolve(dirname5(fileURLToPath5(import.meta.url)), highlights_default5)]
44327
+ highlights: [resolve2(dirname5(fileURLToPath5(import.meta.url)), highlights_default5)]
43510
44328
  },
43511
- wasm: resolve(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_zig_default)
44329
+ wasm: resolve2(dirname5(fileURLToPath5(import.meta.url)), tree_sitter_zig_default)
43512
44330
  }
43513
44331
  ];
43514
44332
  }
@@ -43521,7 +44339,7 @@ function getBunfsRootPath() {
43521
44339
  return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
43522
44340
  }
43523
44341
  function normalizeBunfsPath(fileName) {
43524
- return join16(getBunfsRootPath(), basename(fileName));
44342
+ return join17(getBunfsRootPath(), basename(fileName));
43525
44343
  }
43526
44344
  function isValidDirectoryName(name) {
43527
44345
  if (!name || typeof name !== "string") {
@@ -46473,7 +47291,7 @@ function convertToDebugSymbols(symbols) {
46473
47291
  if (env.OTUI_DEBUG_FFI && globalFFILogPath) {
46474
47292
  const logPath = globalFFILogPath;
46475
47293
  const writeSync3 = (msg) => {
46476
- writeFileSync9(logPath, msg + `
47294
+ writeFileSync10(logPath, msg + `
46477
47295
  `, { flag: "a" });
46478
47296
  };
46479
47297
  Object.entries(symbols).forEach(([key, value]) => {
@@ -53717,7 +54535,7 @@ var init_index_0wbvecnk = __esm(async () => {
53717
54535
  worker_path = this.options.workerPath;
53718
54536
  } else {
53719
54537
  worker_path = new URL("./parser.worker.js", import.meta.url).href;
53720
- if (!existsSync16(resolve2(import.meta.dirname, "parser.worker.js"))) {
54538
+ if (!existsSync17(resolve22(import.meta.dirname, "parser.worker.js"))) {
53721
54539
  worker_path = new URL("./parser.worker.ts", import.meta.url).href;
53722
54540
  }
53723
54541
  }
@@ -53783,7 +54601,7 @@ var init_index_0wbvecnk = __esm(async () => {
53783
54601
  return normalizeBunfsPath(parse6(path2).base);
53784
54602
  }
53785
54603
  if (!isAbsolute(path2)) {
53786
- return resolve2(path2);
54604
+ return resolve22(path2);
53787
54605
  }
53788
54606
  return path2;
53789
54607
  }
@@ -82869,9 +83687,9 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
82869
83687
  }
82870
83688
  function getWrappedDisplayName(outerType, innerType, wrapperName, fallbackName) {
82871
83689
  var displayName = outerType === null || outerType === undefined ? undefined : outerType.displayName;
82872
- return displayName || "".concat(wrapperName, "(").concat(getDisplayName(innerType, fallbackName), ")");
83690
+ return displayName || "".concat(wrapperName, "(").concat(getDisplayName2(innerType, fallbackName), ")");
82873
83691
  }
82874
- function getDisplayName(type) {
83692
+ function getDisplayName2(type) {
82875
83693
  var fallbackName = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "Anonymous";
82876
83694
  var nameFromCache = cachedDisplayNames.get(type);
82877
83695
  if (nameFromCache != null) {
@@ -83414,7 +84232,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
83414
84232
  if (typeof type === "string") {
83415
84233
  return type;
83416
84234
  } else if (typeof type === "function") {
83417
- return getDisplayName(type, "Anonymous");
84235
+ return getDisplayName2(type, "Anonymous");
83418
84236
  } else if (type != null) {
83419
84237
  return "NotImplementedInDevtools";
83420
84238
  } else {
@@ -89342,7 +90160,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
89342
90160
  case IncompleteFunctionComponent:
89343
90161
  case FunctionComponent:
89344
90162
  case IndeterminateComponent:
89345
- return getDisplayName(resolvedType);
90163
+ return getDisplayName2(resolvedType);
89346
90164
  case ForwardRef:
89347
90165
  return getWrappedDisplayName(elementType, resolvedType, "ForwardRef", "Anonymous");
89348
90166
  case HostRoot:
@@ -94297,7 +95115,7 @@ The error thrown in the component is:
94297
95115
  if (typeof elementType === "string") {
94298
95116
  displayName = elementType;
94299
95117
  } else if (typeof elementType === "function") {
94300
- displayName = getDisplayName(elementType);
95118
+ displayName = getDisplayName2(elementType);
94301
95119
  }
94302
95120
  }
94303
95121
  return {
@@ -98429,24 +99247,163 @@ var init_tui = __esm(async () => {
98429
99247
  }
98430
99248
  });
98431
99249
 
99250
+ // src/team-cli.ts
99251
+ var exports_team_cli = {};
99252
+ __export(exports_team_cli, {
99253
+ teamCommand: () => teamCommand
99254
+ });
99255
+ import { readFileSync as readFileSync15 } from "fs";
99256
+ import { join as join18 } from "path";
99257
+ function getFlag(args, flag) {
99258
+ const idx = args.indexOf(flag);
99259
+ if (idx === -1 || idx + 1 >= args.length)
99260
+ return;
99261
+ return args[idx + 1];
99262
+ }
99263
+ function hasFlag(args, flag) {
99264
+ return args.includes(flag);
99265
+ }
99266
+ function printStatus(status) {
99267
+ const modelIds = Object.keys(status.models).sort();
99268
+ console.log(`
99269
+ Team Status (started: ${status.startedAt})`);
99270
+ console.log("\u2500".repeat(60));
99271
+ for (const id of modelIds) {
99272
+ const m2 = status.models[id];
99273
+ const duration3 = m2.startedAt && m2.completedAt ? `${Math.round((new Date(m2.completedAt).getTime() - new Date(m2.startedAt).getTime()) / 1000)}s` : m2.startedAt ? "running" : "pending";
99274
+ const size = m2.outputSize > 0 ? ` (${m2.outputSize} bytes)` : "";
99275
+ console.log(` ${id} ${m2.state.padEnd(10)} ${duration3}${size}`);
99276
+ }
99277
+ console.log("");
99278
+ }
99279
+ function printHelp2() {
99280
+ console.log(`
99281
+ Usage: claudish team <subcommand> [options]
99282
+
99283
+ Subcommands:
99284
+ run Run multiple models on a task in parallel
99285
+ judge Blind-judge existing model outputs
99286
+ run-and-judge Run models then judge their outputs
99287
+ status Show current session status
99288
+
99289
+ Options (run / run-and-judge):
99290
+ --path <dir> Session directory (default: .)
99291
+ --models <a,b,...> Comma-separated model IDs to run
99292
+ --input <text> Task prompt (or create input.md in --path beforehand)
99293
+ --timeout <secs> Timeout per model in seconds (default: 300)
99294
+
99295
+ Options (judge / run-and-judge):
99296
+ --judges <a,b,...> Comma-separated judge model IDs (default: same as runners)
99297
+
99298
+ Options (status):
99299
+ --path <dir> Session directory (default: .)
99300
+
99301
+ Examples:
99302
+ claudish team run --path ./review --models minimax-m2.5,kimi-k2.5 --input "Review this code"
99303
+ claudish team judge --path ./review
99304
+ claudish team run-and-judge --path ./review --models gpt-5.4,gemini-3.1-pro-preview --input "Evaluate this design"
99305
+ claudish team status --path ./review
99306
+ `);
99307
+ }
99308
+ async function teamCommand(args) {
99309
+ const subcommand = args[0];
99310
+ if (!subcommand || hasFlag(args, "--help") || hasFlag(args, "-h")) {
99311
+ printHelp2();
99312
+ process.exit(0);
99313
+ }
99314
+ const rawSessionPath = getFlag(args, "--path") ?? ".";
99315
+ let sessionPath;
99316
+ try {
99317
+ sessionPath = validateSessionPath(rawSessionPath);
99318
+ } catch (err) {
99319
+ console.error(`Error: ${err instanceof Error ? err.message : String(err)}`);
99320
+ process.exit(1);
99321
+ }
99322
+ const modelsRaw = getFlag(args, "--models");
99323
+ const judgesRaw = getFlag(args, "--judges");
99324
+ const input = getFlag(args, "--input");
99325
+ const timeoutStr = getFlag(args, "--timeout");
99326
+ const timeout = timeoutStr ? parseInt(timeoutStr, 10) : 300;
99327
+ const models = modelsRaw ? modelsRaw.split(",").map((m2) => m2.trim()).filter(Boolean) : [];
99328
+ const judges = judgesRaw ? judgesRaw.split(",").map((m2) => m2.trim()).filter(Boolean) : undefined;
99329
+ switch (subcommand) {
99330
+ case "run": {
99331
+ if (models.length === 0) {
99332
+ console.error("Error: --models is required for 'run'");
99333
+ process.exit(1);
99334
+ }
99335
+ setupSession(sessionPath, models, input);
99336
+ const runStatus = await runModels(sessionPath, {
99337
+ timeout,
99338
+ onStatusChange: (id, s) => {
99339
+ process.stderr.write(`[team] ${id}: ${s.state}
99340
+ `);
99341
+ }
99342
+ });
99343
+ printStatus(runStatus);
99344
+ break;
99345
+ }
99346
+ case "judge": {
99347
+ const verdict = await judgeResponses(sessionPath, { judges });
99348
+ console.log(readFileSync15(join18(sessionPath, "verdict.md"), "utf-8"));
99349
+ break;
99350
+ }
99351
+ case "run-and-judge": {
99352
+ if (models.length === 0) {
99353
+ console.error("Error: --models is required for 'run-and-judge'");
99354
+ process.exit(1);
99355
+ }
99356
+ setupSession(sessionPath, models, input);
99357
+ const status = await runModels(sessionPath, {
99358
+ timeout,
99359
+ onStatusChange: (id, s) => {
99360
+ process.stderr.write(`[team] ${id}: ${s.state}
99361
+ `);
99362
+ }
99363
+ });
99364
+ printStatus(status);
99365
+ await judgeResponses(sessionPath, { judges });
99366
+ console.log(readFileSync15(join18(sessionPath, "verdict.md"), "utf-8"));
99367
+ break;
99368
+ }
99369
+ case "status": {
99370
+ const status = getStatus(sessionPath);
99371
+ printStatus(status);
99372
+ break;
99373
+ }
99374
+ default: {
99375
+ console.error(`Unknown team subcommand: ${subcommand}`);
99376
+ printHelp2();
99377
+ process.exit(1);
99378
+ }
99379
+ }
99380
+ }
99381
+ var init_team_cli = __esm(() => {
99382
+ init_team_orchestrator();
99383
+ });
99384
+
98432
99385
  // src/claude-runner.ts
98433
99386
  var exports_claude_runner = {};
98434
99387
  __export(exports_claude_runner, {
98435
99388
  runClaudeWithProxy: () => runClaudeWithProxy,
98436
99389
  checkClaudeInstalled: () => checkClaudeInstalled
98437
99390
  });
98438
- import { spawn } from "child_process";
98439
- import { writeFileSync as writeFileSync10, unlinkSync as unlinkSync6, mkdirSync as mkdirSync9, existsSync as existsSync17, readFileSync as readFileSync14 } from "fs";
98440
- import { tmpdir as tmpdir2, homedir as homedir15 } from "os";
98441
- import { join as join17 } from "path";
99391
+ import { spawn as spawn2 } from "child_process";
99392
+ import { writeFileSync as writeFileSync11, unlinkSync as unlinkSync7, mkdirSync as mkdirSync10, existsSync as existsSync18, readFileSync as readFileSync16 } from "fs";
99393
+ import { tmpdir as tmpdir2, homedir as homedir16 } from "os";
99394
+ import { join as join19 } from "path";
99395
+ function hasNativeAnthropicMapping(config3) {
99396
+ const models = [config3.model, config3.modelOpus, config3.modelSonnet, config3.modelHaiku, config3.modelSubagent];
99397
+ return models.some((m2) => m2 && parseModelSpec(m2).provider === "native-anthropic");
99398
+ }
98442
99399
  function isWindows2() {
98443
99400
  return process.platform === "win32";
98444
99401
  }
98445
99402
  function createStatusLineScript(tokenFilePath) {
98446
99403
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
98447
- const claudishDir = join17(homeDir, ".claudish");
99404
+ const claudishDir = join19(homeDir, ".claudish");
98448
99405
  const timestamp = Date.now();
98449
- const scriptPath = join17(claudishDir, `status-${timestamp}.js`);
99406
+ const scriptPath = join19(claudishDir, `status-${timestamp}.js`);
98450
99407
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
98451
99408
  const script = `
98452
99409
  const fs = require('fs');
@@ -98526,18 +99483,18 @@ process.stdin.on('end', () => {
98526
99483
  }
98527
99484
  });
98528
99485
  `;
98529
- writeFileSync10(scriptPath, script, "utf-8");
99486
+ writeFileSync11(scriptPath, script, "utf-8");
98530
99487
  return scriptPath;
98531
99488
  }
98532
99489
  function createTempSettingsFile(modelDisplay, port) {
98533
99490
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
98534
- const claudishDir = join17(homeDir, ".claudish");
99491
+ const claudishDir = join19(homeDir, ".claudish");
98535
99492
  try {
98536
- mkdirSync9(claudishDir, { recursive: true });
99493
+ mkdirSync10(claudishDir, { recursive: true });
98537
99494
  } catch {}
98538
99495
  const timestamp = Date.now();
98539
- const tempPath = join17(claudishDir, `settings-${timestamp}.json`);
98540
- const tokenFilePath = join17(claudishDir, `tokens-${port}.json`);
99496
+ const tempPath = join19(claudishDir, `settings-${timestamp}.json`);
99497
+ const tokenFilePath = join19(claudishDir, `tokens-${port}.json`);
98541
99498
  let statusCommand;
98542
99499
  if (isWindows2()) {
98543
99500
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -98559,7 +99516,7 @@ function createTempSettingsFile(modelDisplay, port) {
98559
99516
  padding: 0
98560
99517
  };
98561
99518
  const settings = { statusLine };
98562
- writeFileSync10(tempPath, JSON.stringify(settings, null, 2), "utf-8");
99519
+ writeFileSync11(tempPath, JSON.stringify(settings, null, 2), "utf-8");
98563
99520
  return { path: tempPath, statusLine };
98564
99521
  }
98565
99522
  function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
@@ -98573,11 +99530,11 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
98573
99530
  if (userSettingsValue.trimStart().startsWith("{")) {
98574
99531
  userSettings = JSON.parse(userSettingsValue);
98575
99532
  } else {
98576
- const rawUserSettings = readFileSync14(userSettingsValue, "utf-8");
99533
+ const rawUserSettings = readFileSync16(userSettingsValue, "utf-8");
98577
99534
  userSettings = JSON.parse(rawUserSettings);
98578
99535
  }
98579
99536
  userSettings.statusLine = statusLine;
98580
- writeFileSync10(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
99537
+ writeFileSync11(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
98581
99538
  } catch {
98582
99539
  if (!config3.quiet) {
98583
99540
  console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
@@ -98585,7 +99542,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine) {
98585
99542
  }
98586
99543
  config3.claudeArgs.splice(idx, 2);
98587
99544
  }
98588
- async function runClaudeWithProxy(config3, proxyUrl) {
99545
+ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
98589
99546
  const hasProfileMappings = config3.modelOpus || config3.modelSonnet || config3.modelHaiku || config3.modelSubagent;
98590
99547
  const modelId = config3.model || (hasProfileMappings || config3.monitor ? undefined : "unknown");
98591
99548
  const portMatch = proxyUrl.match(/:(\d+)/);
@@ -98636,14 +99593,19 @@ async function runClaudeWithProxy(config3, proxyUrl) {
98636
99593
  env2[ENV.ANTHROPIC_MODEL] = modelId;
98637
99594
  env2[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
98638
99595
  }
98639
- env2.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
98640
- env2.ANTHROPIC_AUTH_TOKEN = process.env.ANTHROPIC_AUTH_TOKEN || "placeholder-token-not-used-proxy-handles-auth";
99596
+ if (hasNativeAnthropicMapping(config3)) {} else {
99597
+ env2.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
99598
+ env2.ANTHROPIC_AUTH_TOKEN = process.env.ANTHROPIC_AUTH_TOKEN || "placeholder-token-not-used-proxy-handles-auth";
99599
+ }
98641
99600
  }
98642
99601
  const log2 = (message) => {
98643
99602
  if (!config3.quiet) {
98644
99603
  console.log(message);
98645
99604
  }
98646
99605
  };
99606
+ if (!config3.monitor && hasNativeAnthropicMapping(config3)) {
99607
+ log2("[claudish] Native Claude model detected \u2014 using Claude Code subscription credentials");
99608
+ }
98647
99609
  if (config3.interactive) {
98648
99610
  log2(`
98649
99611
  [claudish] Model: ${modelDisplayName}
@@ -98660,30 +99622,30 @@ async function runClaudeWithProxy(config3, proxyUrl) {
98660
99622
  console.error("Install it from: https://claude.com/claude-code");
98661
99623
  console.error(`
98662
99624
  Or set CLAUDE_PATH to your custom installation:`);
98663
- const home = homedir15();
98664
- const localPath = isWindows2() ? join17(home, ".claude", "local", "claude.exe") : join17(home, ".claude", "local", "claude");
99625
+ const home = homedir16();
99626
+ const localPath = isWindows2() ? join19(home, ".claude", "local", "claude.exe") : join19(home, ".claude", "local", "claude");
98665
99627
  console.error(` export CLAUDE_PATH=${localPath}`);
98666
99628
  process.exit(1);
98667
99629
  }
98668
99630
  const needsShell = isWindows2() && claudeBinary.endsWith(".cmd");
98669
99631
  const spawnCommand = needsShell ? `"${claudeBinary}"` : claudeBinary;
98670
- const proc = spawn(spawnCommand, claudeArgs, {
99632
+ const proc = spawn2(spawnCommand, claudeArgs, {
98671
99633
  env: env2,
98672
99634
  stdio: "inherit",
98673
99635
  shell: needsShell
98674
99636
  });
98675
- setupSignalHandlers(proc, tempSettingsPath, config3.quiet);
99637
+ setupSignalHandlers(proc, tempSettingsPath, config3.quiet, onCleanup);
98676
99638
  const exitCode = await new Promise((resolve3) => {
98677
99639
  proc.on("exit", (code) => {
98678
99640
  resolve3(code ?? 1);
98679
99641
  });
98680
99642
  });
98681
99643
  try {
98682
- unlinkSync6(tempSettingsPath);
99644
+ unlinkSync7(tempSettingsPath);
98683
99645
  } catch (error46) {}
98684
99646
  return exitCode;
98685
99647
  }
98686
- function setupSignalHandlers(proc, tempSettingsPath, quiet) {
99648
+ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
98687
99649
  const signals2 = isWindows2() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
98688
99650
  for (const signal of signals2) {
98689
99651
  process.on(signal, () => {
@@ -98692,8 +99654,13 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet) {
98692
99654
  [claudish] Received ${signal}, shutting down...`);
98693
99655
  }
98694
99656
  proc.kill();
99657
+ if (onCleanup) {
99658
+ try {
99659
+ onCleanup();
99660
+ } catch {}
99661
+ }
98695
99662
  try {
98696
- unlinkSync6(tempSettingsPath);
99663
+ unlinkSync7(tempSettingsPath);
98697
99664
  } catch {}
98698
99665
  process.exit(0);
98699
99666
  });
@@ -98702,23 +99669,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet) {
98702
99669
  async function findClaudeBinary() {
98703
99670
  const isWindows3 = process.platform === "win32";
98704
99671
  if (process.env.CLAUDE_PATH) {
98705
- if (existsSync17(process.env.CLAUDE_PATH)) {
99672
+ if (existsSync18(process.env.CLAUDE_PATH)) {
98706
99673
  return process.env.CLAUDE_PATH;
98707
99674
  }
98708
99675
  }
98709
- const home = homedir15();
98710
- const localPath = isWindows3 ? join17(home, ".claude", "local", "claude.exe") : join17(home, ".claude", "local", "claude");
98711
- if (existsSync17(localPath)) {
99676
+ const home = homedir16();
99677
+ const localPath = isWindows3 ? join19(home, ".claude", "local", "claude.exe") : join19(home, ".claude", "local", "claude");
99678
+ if (existsSync18(localPath)) {
98712
99679
  return localPath;
98713
99680
  }
98714
99681
  if (isWindows3) {
98715
99682
  const windowsPaths = [
98716
- join17(home, "AppData", "Roaming", "npm", "claude.cmd"),
98717
- join17(home, ".npm-global", "claude.cmd"),
98718
- join17(home, "node_modules", ".bin", "claude.cmd")
99683
+ join19(home, "AppData", "Roaming", "npm", "claude.cmd"),
99684
+ join19(home, ".npm-global", "claude.cmd"),
99685
+ join19(home, "node_modules", ".bin", "claude.cmd")
98719
99686
  ];
98720
99687
  for (const path2 of windowsPaths) {
98721
- if (existsSync17(path2)) {
99688
+ if (existsSync18(path2)) {
98722
99689
  return path2;
98723
99690
  }
98724
99691
  }
@@ -98726,21 +99693,21 @@ async function findClaudeBinary() {
98726
99693
  const commonPaths = [
98727
99694
  "/usr/local/bin/claude",
98728
99695
  "/opt/homebrew/bin/claude",
98729
- join17(home, ".npm-global/bin/claude"),
98730
- join17(home, ".local/bin/claude"),
98731
- join17(home, "node_modules/.bin/claude"),
99696
+ join19(home, ".npm-global/bin/claude"),
99697
+ join19(home, ".local/bin/claude"),
99698
+ join19(home, "node_modules/.bin/claude"),
98732
99699
  "/data/data/com.termux/files/usr/bin/claude",
98733
- join17(home, "../usr/bin/claude")
99700
+ join19(home, "../usr/bin/claude")
98734
99701
  ];
98735
99702
  for (const path2 of commonPaths) {
98736
- if (existsSync17(path2)) {
99703
+ if (existsSync18(path2)) {
98737
99704
  return path2;
98738
99705
  }
98739
99706
  }
98740
99707
  }
98741
99708
  try {
98742
99709
  const shellCommand = isWindows3 ? "where claude" : "command -v claude";
98743
- const proc = spawn(shellCommand, [], {
99710
+ const proc = spawn2(shellCommand, [], {
98744
99711
  stdio: "pipe",
98745
99712
  shell: true
98746
99713
  });
@@ -98772,6 +99739,106 @@ async function checkClaudeInstalled() {
98772
99739
  }
98773
99740
  var init_claude_runner = __esm(() => {
98774
99741
  init_config();
99742
+ init_model_parser();
99743
+ });
99744
+
99745
+ // src/diag-output.ts
99746
+ var exports_diag_output = {};
99747
+ __export(exports_diag_output, {
99748
+ createDiagOutput: () => createDiagOutput,
99749
+ TmuxDiagOutput: () => TmuxDiagOutput,
99750
+ NullDiagOutput: () => NullDiagOutput,
99751
+ LogFileDiagOutput: () => LogFileDiagOutput
99752
+ });
99753
+ import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync11, writeFileSync as writeFileSync12, unlinkSync as unlinkSync8 } from "fs";
99754
+ import { execFileSync } from "child_process";
99755
+ import { homedir as homedir17 } from "os";
99756
+ import { join as join20 } from "path";
99757
+ function getClaudishDir() {
99758
+ const dir = join20(homedir17(), ".claudish");
99759
+ try {
99760
+ mkdirSync11(dir, { recursive: true });
99761
+ } catch {}
99762
+ return dir;
99763
+ }
99764
+ function getDiagLogPath() {
99765
+ return join20(getClaudishDir(), `diag-${process.pid}.log`);
99766
+ }
99767
+
99768
+ class LogFileDiagOutput {
99769
+ logPath;
99770
+ stream;
99771
+ constructor() {
99772
+ this.logPath = getDiagLogPath();
99773
+ try {
99774
+ writeFileSync12(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
99775
+ `);
99776
+ } catch {}
99777
+ this.stream = createWriteStream2(this.logPath, { flags: "a" });
99778
+ this.stream.on("error", () => {});
99779
+ }
99780
+ write(msg) {
99781
+ const timestamp = new Date().toISOString();
99782
+ const line = `[${timestamp}] ${msg}
99783
+ `;
99784
+ try {
99785
+ this.stream.write(line);
99786
+ } catch {}
99787
+ }
99788
+ cleanup() {
99789
+ try {
99790
+ this.stream.end();
99791
+ } catch {}
99792
+ try {
99793
+ unlinkSync8(this.logPath);
99794
+ } catch {}
99795
+ }
99796
+ getLogPath() {
99797
+ return this.logPath;
99798
+ }
99799
+ }
99800
+
99801
+ class NullDiagOutput {
99802
+ write(_msg) {}
99803
+ cleanup() {}
99804
+ }
99805
+ function createDiagOutput(options) {
99806
+ if (!options.interactive) {
99807
+ return new NullDiagOutput;
99808
+ }
99809
+ if (process.env.TMUX) {
99810
+ return new TmuxDiagOutput;
99811
+ }
99812
+ return new LogFileDiagOutput;
99813
+ }
99814
+ var TmuxDiagOutput;
99815
+ var init_diag_output = __esm(() => {
99816
+ TmuxDiagOutput = class TmuxDiagOutput extends LogFileDiagOutput {
99817
+ paneId = null;
99818
+ constructor() {
99819
+ super();
99820
+ this.openTmuxPane();
99821
+ }
99822
+ openTmuxPane() {
99823
+ try {
99824
+ const output = execFileSync("tmux", ["split-window", "-v", "-l", "5", "-d", "-P", "-F", "#{pane_id}", "tail", "-f", this.logPath], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
99825
+ this.paneId = output.trim();
99826
+ } catch {
99827
+ this.paneId = null;
99828
+ }
99829
+ }
99830
+ cleanup() {
99831
+ if (this.paneId) {
99832
+ try {
99833
+ execFileSync("tmux", ["kill-pane", "-t", this.paneId], {
99834
+ stdio: ["pipe", "pipe", "pipe"]
99835
+ });
99836
+ } catch {}
99837
+ this.paneId = null;
99838
+ }
99839
+ super.cleanup();
99840
+ }
99841
+ };
98775
99842
  });
98776
99843
 
98777
99844
  // src/port-manager.ts
@@ -101360,8 +102427,10 @@ class OpenRouterProvider {
101360
102427
  streamFormat = "openai-sse";
101361
102428
  apiKey;
101362
102429
  queue;
101363
- constructor(apiKey) {
102430
+ modelId;
102431
+ constructor(apiKey, modelId) {
101364
102432
  this.apiKey = apiKey;
102433
+ this.modelId = modelId || "";
101365
102434
  this.queue = OpenRouterRequestQueue.getInstance();
101366
102435
  }
101367
102436
  overrideStreamFormat() {
@@ -101380,10 +102449,16 @@ class OpenRouterProvider {
101380
102449
  async enqueueRequest(fetchFn) {
101381
102450
  return this.queue.enqueue(fetchFn);
101382
102451
  }
102452
+ getContextWindow() {
102453
+ const models = this.modelId ? getCachedOpenRouterModels() : null;
102454
+ const model = models?.find((m2) => m2.id === this.modelId);
102455
+ return model?.context_length || model?.top_provider?.context_length || 200000;
102456
+ }
101383
102457
  }
101384
102458
  var OPENROUTER_API_URL2 = "https://openrouter.ai/api/v1/chat/completions";
101385
102459
  var init_openrouter2 = __esm(() => {
101386
102460
  init_openrouter_queue();
102461
+ init_model_loader();
101387
102462
  });
101388
102463
 
101389
102464
  // src/adapters/openrouter-adapter.ts
@@ -102349,9 +103424,9 @@ var init_middleware = __esm(() => {
102349
103424
  });
102350
103425
 
102351
103426
  // src/handlers/shared/token-tracker.ts
102352
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
102353
- import { homedir as homedir16 } from "os";
102354
- import { join as join18 } from "path";
103427
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync13 } from "fs";
103428
+ import { homedir as homedir18 } from "os";
103429
+ import { join as join21 } from "path";
102355
103430
 
102356
103431
  class TokenTracker {
102357
103432
  port;
@@ -102465,9 +103540,9 @@ class TokenTracker {
102465
103540
  is_free: isFreeModel,
102466
103541
  is_estimated: isEstimate || false
102467
103542
  };
102468
- const claudishDir = join18(homedir16(), ".claudish");
102469
- mkdirSync10(claudishDir, { recursive: true });
102470
- writeFileSync11(join18(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
103543
+ const claudishDir = join21(homedir18(), ".claudish");
103544
+ mkdirSync12(claudishDir, { recursive: true });
103545
+ writeFileSync13(join21(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
102471
103546
  } catch (e) {
102472
103547
  log(`[TokenTracker] Error writing token file: ${e}`);
102473
103548
  }
@@ -103519,9 +104594,9 @@ class ComposedHandler {
103519
104594
  });
103520
104595
  return c.json({ error: { type: "connection_error", message: err.message } }, 503);
103521
104596
  }
103522
- if (this.provider.getContextWindow) {
103523
- this.tokenTracker.setContextWindow(this.provider.getContextWindow());
103524
- }
104597
+ }
104598
+ if (this.provider.getContextWindow) {
104599
+ this.tokenTracker.setContextWindow(this.provider.getContextWindow());
103525
104600
  }
103526
104601
  if (this.provider.transformPayload) {
103527
104602
  requestPayload = this.provider.transformPayload(requestPayload);
@@ -103888,9 +104963,9 @@ var init_composed_handler = __esm(() => {
103888
104963
  });
103889
104964
 
103890
104965
  // src/services/pricing-cache.ts
103891
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, existsSync as existsSync18, mkdirSync as mkdirSync11, statSync } from "fs";
103892
- import { homedir as homedir17 } from "os";
103893
- import { join as join19 } from "path";
104966
+ import { readFileSync as readFileSync17, writeFileSync as writeFileSync14, existsSync as existsSync19, mkdirSync as mkdirSync13, statSync as statSync2 } from "fs";
104967
+ import { homedir as homedir19 } from "os";
104968
+ import { join as join22 } from "path";
103894
104969
  function getDynamicPricingSync(provider, modelName) {
103895
104970
  if (provider === "openrouter") {
103896
104971
  const direct = pricingMap.get(modelName);
@@ -103955,12 +105030,12 @@ async function warmPricingCache() {
103955
105030
  }
103956
105031
  function loadDiskCache() {
103957
105032
  try {
103958
- if (!existsSync18(CACHE_FILE))
105033
+ if (!existsSync19(CACHE_FILE))
103959
105034
  return false;
103960
- const stat = statSync(CACHE_FILE);
105035
+ const stat = statSync2(CACHE_FILE);
103961
105036
  const age = Date.now() - stat.mtimeMs;
103962
105037
  const isFresh = age < CACHE_TTL_MS;
103963
- const raw2 = readFileSync15(CACHE_FILE, "utf-8");
105038
+ const raw2 = readFileSync17(CACHE_FILE, "utf-8");
103964
105039
  const data = JSON.parse(raw2);
103965
105040
  for (const [key, pricing] of Object.entries(data)) {
103966
105041
  pricingMap.set(key, pricing);
@@ -103972,12 +105047,12 @@ function loadDiskCache() {
103972
105047
  }
103973
105048
  function saveDiskCache() {
103974
105049
  try {
103975
- mkdirSync11(CACHE_DIR, { recursive: true });
105050
+ mkdirSync13(CACHE_DIR, { recursive: true });
103976
105051
  const data = {};
103977
105052
  for (const [key, pricing] of pricingMap) {
103978
105053
  data[key] = pricing;
103979
105054
  }
103980
- writeFileSync12(CACHE_FILE, JSON.stringify(data), "utf-8");
105055
+ writeFileSync14(CACHE_FILE, JSON.stringify(data), "utf-8");
103981
105056
  } catch (error46) {
103982
105057
  log(`[PricingCache] Error saving disk cache: ${error46}`);
103983
105058
  }
@@ -104007,8 +105082,8 @@ var init_pricing_cache = __esm(() => {
104007
105082
  init_model_loader();
104008
105083
  init_remote_provider_types();
104009
105084
  pricingMap = new Map;
104010
- CACHE_DIR = join19(homedir17(), ".claudish");
104011
- CACHE_FILE = join19(CACHE_DIR, "pricing-cache.json");
105085
+ CACHE_DIR = join22(homedir19(), ".claudish");
105086
+ CACHE_FILE = join22(CACHE_DIR, "pricing-cache.json");
104012
105087
  CACHE_TTL_MS = 24 * 60 * 60 * 1000;
104013
105088
  PROVIDER_TO_OR_PREFIX = {
104014
105089
  openai: ["openai/"],
@@ -104467,12 +105542,12 @@ class AnthropicCompatProvider {
104467
105542
  }
104468
105543
  if (this.provider.name === "kimi-coding" && !this.apiKey) {
104469
105544
  try {
104470
- const { existsSync: existsSync19, readFileSync: readFileSync16 } = await import("fs");
104471
- const { join: join20 } = await import("path");
104472
- const { homedir: homedir18 } = await import("os");
104473
- const credPath = join20(homedir18(), ".claudish", "kimi-oauth.json");
104474
- if (existsSync19(credPath)) {
104475
- const data = JSON.parse(readFileSync16(credPath, "utf-8"));
105545
+ const { existsSync: existsSync20, readFileSync: readFileSync18 } = await import("fs");
105546
+ const { join: join23 } = await import("path");
105547
+ const { homedir: homedir20 } = await import("os");
105548
+ const credPath = join23(homedir20(), ".claudish", "kimi-oauth.json");
105549
+ if (existsSync20(credPath)) {
105550
+ const data = JSON.parse(readFileSync18(credPath, "utf-8"));
104476
105551
  if (data.access_token && data.refresh_token) {
104477
105552
  const { KimiOAuth: KimiOAuth2 } = await Promise.resolve().then(() => (init_kimi_oauth(), exports_kimi_oauth));
104478
105553
  const oauth = KimiOAuth2.getInstance();
@@ -104589,12 +105664,18 @@ var init_anthropic_passthrough_adapter = __esm(() => {
104589
105664
  if (model.includes("kimi-k2.5") || model.includes("kimi-k2-5"))
104590
105665
  return 262144;
104591
105666
  if (model.includes("kimi-k2"))
104592
- return 262144;
105667
+ return 131000;
104593
105668
  if (this.providerName === "kimi" || this.providerName === "kimi-coding" || model.includes("kimi")) {
104594
105669
  return 131072;
104595
105670
  }
105671
+ if (model.includes("minimax-01") || model.includes("minimax-m1"))
105672
+ return 1e6;
105673
+ if (model.includes("minimax-m2.7"))
105674
+ return 204800;
105675
+ if (model.includes("minimax-m2"))
105676
+ return 196608;
104596
105677
  if (this.providerName === "minimax" || this.providerName === "minimax-coding") {
104597
- return 1e5;
105678
+ return 196608;
104598
105679
  }
104599
105680
  return 128000;
104600
105681
  }
@@ -104775,10 +105856,10 @@ var init_litellm2 = __esm(() => {
104775
105856
  });
104776
105857
 
104777
105858
  // src/adapters/litellm-adapter.ts
104778
- import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
105859
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
104779
105860
  import { createHash as createHash5 } from "crypto";
104780
- import { homedir as homedir18 } from "os";
104781
- import { join as join20 } from "path";
105861
+ import { homedir as homedir20 } from "os";
105862
+ import { join as join23 } from "path";
104782
105863
  var INLINE_IMAGE_MODEL_PATTERNS, LiteLLMAdapter;
104783
105864
  var init_litellm_adapter = __esm(() => {
104784
105865
  init_base_adapter();
@@ -104874,10 +105955,10 @@ var init_litellm_adapter = __esm(() => {
104874
105955
  checkVisionSupport() {
104875
105956
  try {
104876
105957
  const hash2 = createHash5("sha256").update(this.baseUrl).digest("hex").substring(0, 16);
104877
- const cachePath = join20(homedir18(), ".claudish", `litellm-models-${hash2}.json`);
104878
- if (!existsSync19(cachePath))
105958
+ const cachePath = join23(homedir20(), ".claudish", `litellm-models-${hash2}.json`);
105959
+ if (!existsSync20(cachePath))
104879
105960
  return true;
104880
- const cacheData = JSON.parse(readFileSync16(cachePath, "utf-8"));
105961
+ const cacheData = JSON.parse(readFileSync18(cachePath, "utf-8"));
104881
105962
  const model = cacheData.models?.find((m2) => m2.name === this.modelId);
104882
105963
  if (model && model.supportsVision === false) {
104883
105964
  log(`[LiteLLMAdapter] Model ${this.modelId} does not support vision`);
@@ -104894,9 +105975,9 @@ var init_litellm_adapter = __esm(() => {
104894
105975
  // src/auth/vertex-auth.ts
104895
105976
  import { exec as exec4 } from "child_process";
104896
105977
  import { promisify as promisify3 } from "util";
104897
- import { existsSync as existsSync20 } from "fs";
104898
- import { homedir as homedir19 } from "os";
104899
- import { join as join21 } from "path";
105978
+ import { existsSync as existsSync21 } from "fs";
105979
+ import { homedir as homedir21 } from "os";
105980
+ import { join as join24 } from "path";
104900
105981
 
104901
105982
  class VertexAuthManager {
104902
105983
  cachedToken = null;
@@ -104950,8 +106031,8 @@ class VertexAuthManager {
104950
106031
  }
104951
106032
  async tryADC() {
104952
106033
  try {
104953
- const adcPath = join21(homedir19(), ".config/gcloud/application_default_credentials.json");
104954
- if (!existsSync20(adcPath)) {
106034
+ const adcPath = join24(homedir21(), ".config/gcloud/application_default_credentials.json");
106035
+ if (!existsSync21(adcPath)) {
104955
106036
  log("[VertexAuth] ADC credentials file not found");
104956
106037
  return null;
104957
106038
  }
@@ -104975,7 +106056,7 @@ class VertexAuthManager {
104975
106056
  if (!credPath) {
104976
106057
  return null;
104977
106058
  }
104978
- if (!existsSync20(credPath)) {
106059
+ if (!existsSync21(credPath)) {
104979
106060
  throw new Error(`Service account file not found: ${credPath}
104980
106061
 
104981
106062
  Check GOOGLE_APPLICATION_CREDENTIALS path.`);
@@ -105014,8 +106095,8 @@ function validateVertexOAuthConfig() {
105014
106095
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
105015
106096
  ` + " export VERTEX_LOCATION='us-central1' # optional";
105016
106097
  }
105017
- const adcPath = join21(homedir19(), ".config/gcloud/application_default_credentials.json");
105018
- const hasADC = existsSync20(adcPath);
106098
+ const adcPath = join24(homedir21(), ".config/gcloud/application_default_credentials.json");
106099
+ const hasADC = existsSync21(adcPath);
105019
106100
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
105020
106101
  if (!hasADC && !hasServiceAccount) {
105021
106102
  return `No Vertex AI credentials found.
@@ -105343,7 +106424,7 @@ async function createProxyServer(port, openrouterApiKey, model, monitorMode = fa
105343
106424
  const parsed = parseModelSpec(targetModel);
105344
106425
  const modelId = targetModel.includes("@") ? parsed.model : targetModel;
105345
106426
  if (!openRouterHandlers.has(modelId)) {
105346
- const orProvider = new OpenRouterProvider(openrouterApiKey || "");
106427
+ const orProvider = new OpenRouterProvider(openrouterApiKey || "", modelId);
105347
106428
  const orAdapter = new OpenRouterAdapter(modelId);
105348
106429
  openRouterHandlers.set(modelId, new ComposedHandler(orProvider, modelId, modelId, port, {
105349
106430
  adapter: orAdapter,
@@ -105651,16 +106732,16 @@ var init_proxy_server = __esm(() => {
105651
106732
 
105652
106733
  // src/index.ts
105653
106734
  var import_dotenv2 = __toESM(require_main(), 1);
105654
- import { existsSync as existsSync21, readFileSync as readFileSync18 } from "fs";
105655
- import { homedir as homedir20 } from "os";
105656
- import { join as join22 } from "path";
106735
+ import { existsSync as existsSync23, readFileSync as readFileSync20 } from "fs";
106736
+ import { homedir as homedir22 } from "os";
106737
+ import { join as join25 } from "path";
105657
106738
  import_dotenv2.config({ quiet: true });
105658
106739
  function loadStoredApiKeys() {
105659
106740
  try {
105660
- const configPath = join22(homedir20(), ".claudish", "config.json");
105661
- if (!existsSync21(configPath))
106741
+ const configPath = join25(homedir22(), ".claudish", "config.json");
106742
+ if (!existsSync23(configPath))
105662
106743
  return;
105663
- const raw2 = readFileSync18(configPath, "utf-8");
106744
+ const raw2 = readFileSync20(configPath, "utf-8");
105664
106745
  const cfg = JSON.parse(raw2);
105665
106746
  if (cfg.apiKeys) {
105666
106747
  for (const [envVar, value] of Object.entries(cfg.apiKeys)) {
@@ -105698,6 +106779,7 @@ var isProfileCommand = args[0] === "profile" || args.some((a, i) => a === "profi
105698
106779
  var isTelemetryCommand = args[0] === "telemetry";
105699
106780
  var isStatsCommand = args[0] === "stats";
105700
106781
  var isConfigCommand = args[0] === "config";
106782
+ var isTeamCommand = args[0] === "team";
105701
106783
  if (isMcpMode) {
105702
106784
  Promise.resolve().then(() => (init_mcp_server(), exports_mcp_server)).then((mcp) => mcp.startMcpServer());
105703
106785
  } else if (isGeminiLogin) {
@@ -105776,6 +106858,8 @@ if (isMcpMode) {
105776
106858
  });
105777
106859
  } else if (isConfigCommand) {
105778
106860
  init_tui().then(() => exports_tui).then((m2) => m2.startConfigTui().catch(handlePromptExit));
106861
+ } else if (isTeamCommand) {
106862
+ Promise.resolve().then(() => (init_team_cli(), exports_team_cli)).then((m2) => m2.teamCommand(args.slice(1)));
105779
106863
  } else {
105780
106864
  runCli();
105781
106865
  }
@@ -105790,7 +106874,8 @@ async function runCli() {
105790
106874
  getMissingKeyResolutions: getMissingKeyResolutions2,
105791
106875
  getMissingKeysError: getMissingKeysError2
105792
106876
  } = await Promise.resolve().then(() => (init_provider_resolver(), exports_provider_resolver));
105793
- const { initLogger: initLogger2, getLogFilePath: getLogFilePath2, setStderrQuiet: setStderrQuiet2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
106877
+ const { initLogger: initLogger2, getLogFilePath: getLogFilePath2, getAlwaysOnLogPath: getAlwaysOnLogPath2, setDiagOutput: setDiagOutput2 } = await Promise.resolve().then(() => (init_logger(), exports_logger));
106878
+ const { createDiagOutput: createDiagOutput2, LogFileDiagOutput: LogFileDiagOutput2 } = await Promise.resolve().then(() => (init_diag_output(), exports_diag_output));
105794
106879
  const { findAvailablePort: findAvailablePort2 } = await Promise.resolve().then(() => (init_port_manager(), exports_port_manager));
105795
106880
  const { createProxyServer: createProxyServer2 } = await Promise.resolve().then(() => (init_proxy_server(), exports_proxy_server));
105796
106881
  const { checkForUpdates: checkForUpdates2 } = await Promise.resolve().then(() => (init_update_checker(), exports_update_checker));
@@ -105803,7 +106888,7 @@ async function runCli() {
105803
106888
  }
105804
106889
  try {
105805
106890
  const cliConfig = await parseArgs2(process.argv.slice(2));
105806
- initLogger2(cliConfig.debug, cliConfig.logLevel);
106891
+ initLogger2(cliConfig.debug, cliConfig.logLevel, cliConfig.noLogs);
105807
106892
  const { initTelemetry: initTelemetry2 } = await Promise.resolve().then(() => (init_telemetry(), exports_telemetry));
105808
106893
  initTelemetry2(cliConfig);
105809
106894
  const { initStats: initStats2, showMonthlyBanner: showMonthlyBanner2 } = await Promise.resolve().then(() => (init_stats(), exports_stats));
@@ -105908,14 +106993,19 @@ async function runCli() {
105908
106993
  quiet: cliConfig.quiet,
105909
106994
  isInteractive: cliConfig.interactive
105910
106995
  });
106996
+ const diag = createDiagOutput2({ interactive: cliConfig.interactive });
105911
106997
  if (cliConfig.interactive) {
105912
- setStderrQuiet2(true);
106998
+ setDiagOutput2(diag);
106999
+ if (!process.env.TMUX && !cliConfig.quiet && diag instanceof LogFileDiagOutput2) {
107000
+ console.log(`[claudish] Diagnostic log: ${diag.getLogPath()}`);
107001
+ }
105913
107002
  }
105914
107003
  let exitCode = 0;
105915
107004
  try {
105916
- exitCode = await runClaudeWithProxy2(cliConfig, proxy.url);
107005
+ exitCode = await runClaudeWithProxy2(cliConfig, proxy.url, () => diag.cleanup());
105917
107006
  } finally {
105918
- setStderrQuiet2(false);
107007
+ setDiagOutput2(null);
107008
+ diag.cleanup();
105919
107009
  if (!cliConfig.quiet) {
105920
107010
  console.log(`
105921
107011
  [claudish] Shutting down proxy server...`);
@@ -105926,6 +107016,12 @@ async function runCli() {
105926
107016
  console.log(`[claudish] Done
105927
107017
  `);
105928
107018
  }
107019
+ const sessionLogPath = getAlwaysOnLogPath2();
107020
+ if (exitCode !== 0 && sessionLogPath && !cliConfig.quiet) {
107021
+ console.error(`
107022
+ [claudish] Session ended with errors. Log: ${sessionLogPath}`);
107023
+ console.error(`[claudish] To review: /debug-logs ${sessionLogPath}`);
107024
+ }
105929
107025
  process.exit(exitCode);
105930
107026
  } catch (error46) {
105931
107027
  console.error("[claudish] Fatal error:", error46);