claudish 4.4.0 → 4.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +667 -393
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28163,12 +28163,8 @@ var init_profile_config = __esm(() => {
|
|
|
28163
28163
|
profiles: {
|
|
28164
28164
|
default: {
|
|
28165
28165
|
name: "default",
|
|
28166
|
-
description: "Default profile -
|
|
28167
|
-
models: {
|
|
28168
|
-
opus: "xai@grok-4-0709",
|
|
28169
|
-
sonnet: "xai@grok-4-1-fast-reasoning",
|
|
28170
|
-
haiku: "xai@grok-code-fast-1"
|
|
28171
|
-
},
|
|
28166
|
+
description: "Default profile - shows model selector when no model specified",
|
|
28167
|
+
models: {},
|
|
28172
28168
|
createdAt: new Date().toISOString(),
|
|
28173
28169
|
updatedAt: new Date().toISOString()
|
|
28174
28170
|
}
|
|
@@ -30495,7 +30491,7 @@ function toModelInfo(model) {
|
|
|
30495
30491
|
async function fetchZenFreeModels() {
|
|
30496
30492
|
try {
|
|
30497
30493
|
const response = await fetch("https://models.dev/api.json", {
|
|
30498
|
-
signal: AbortSignal.timeout(
|
|
30494
|
+
signal: AbortSignal.timeout(5000)
|
|
30499
30495
|
});
|
|
30500
30496
|
if (!response.ok) {
|
|
30501
30497
|
return [];
|
|
@@ -30508,23 +30504,189 @@ async function fetchZenFreeModels() {
|
|
|
30508
30504
|
const isFree = m.cost?.input === 0 && m.cost?.output === 0;
|
|
30509
30505
|
const supportsTools = m.tool_call === true;
|
|
30510
30506
|
return isFree && supportsTools;
|
|
30511
|
-
}).map(([id, m]) =>
|
|
30512
|
-
|
|
30513
|
-
|
|
30514
|
-
|
|
30515
|
-
|
|
30507
|
+
}).map(([id, m]) => {
|
|
30508
|
+
const inputModalities = m.modalities?.input || [];
|
|
30509
|
+
const supportsVision = inputModalities.includes("image") || inputModalities.includes("video");
|
|
30510
|
+
return {
|
|
30511
|
+
id: `zen@${id}`,
|
|
30512
|
+
name: m.name || id,
|
|
30513
|
+
description: `OpenCode Zen free model`,
|
|
30514
|
+
provider: "Zen",
|
|
30515
|
+
pricing: {
|
|
30516
|
+
input: "FREE",
|
|
30517
|
+
output: "FREE",
|
|
30518
|
+
average: "FREE"
|
|
30519
|
+
},
|
|
30520
|
+
context: m.limit?.context ? `${Math.round(m.limit.context / 1000)}K` : "128K",
|
|
30521
|
+
contextLength: m.limit?.context || 128000,
|
|
30522
|
+
supportsTools: true,
|
|
30523
|
+
supportsReasoning: m.reasoning || false,
|
|
30524
|
+
supportsVision,
|
|
30525
|
+
isFree: true,
|
|
30526
|
+
source: "Zen"
|
|
30527
|
+
};
|
|
30528
|
+
});
|
|
30529
|
+
} catch {
|
|
30530
|
+
return [];
|
|
30531
|
+
}
|
|
30532
|
+
}
|
|
30533
|
+
function getXAIContextWindow(modelId) {
|
|
30534
|
+
const id = modelId.toLowerCase();
|
|
30535
|
+
if (id.includes("grok-4.1-fast") || id.includes("grok-4-1-fast")) {
|
|
30536
|
+
return { context: "2M", contextLength: 2000000 };
|
|
30537
|
+
}
|
|
30538
|
+
if (id.includes("grok-4-fast")) {
|
|
30539
|
+
return { context: "2M", contextLength: 2000000 };
|
|
30540
|
+
}
|
|
30541
|
+
if (id.includes("grok-code-fast")) {
|
|
30542
|
+
return { context: "256K", contextLength: 256000 };
|
|
30543
|
+
}
|
|
30544
|
+
if (id.includes("grok-4")) {
|
|
30545
|
+
return { context: "256K", contextLength: 256000 };
|
|
30546
|
+
}
|
|
30547
|
+
if (id.includes("grok-3")) {
|
|
30548
|
+
return { context: "131K", contextLength: 131072 };
|
|
30549
|
+
}
|
|
30550
|
+
if (id.includes("grok-2")) {
|
|
30551
|
+
return { context: "131K", contextLength: 131072 };
|
|
30552
|
+
}
|
|
30553
|
+
return { context: "131K", contextLength: 131072 };
|
|
30554
|
+
}
|
|
30555
|
+
async function fetchXAIModels() {
|
|
30556
|
+
const apiKey = process.env.XAI_API_KEY;
|
|
30557
|
+
if (!apiKey) {
|
|
30558
|
+
return [];
|
|
30559
|
+
}
|
|
30560
|
+
try {
|
|
30561
|
+
const response = await fetch("https://api.x.ai/v1/language-models", {
|
|
30562
|
+
headers: {
|
|
30563
|
+
Authorization: `Bearer ${apiKey}`,
|
|
30564
|
+
"Content-Type": "application/json"
|
|
30565
|
+
},
|
|
30566
|
+
signal: AbortSignal.timeout(5000)
|
|
30567
|
+
});
|
|
30568
|
+
if (!response.ok) {
|
|
30569
|
+
return [];
|
|
30570
|
+
}
|
|
30571
|
+
const data = await response.json();
|
|
30572
|
+
if (!data.models || !Array.isArray(data.models)) {
|
|
30573
|
+
return [];
|
|
30574
|
+
}
|
|
30575
|
+
return data.models.filter((model) => !model.id.includes("image") && !model.id.includes("imagine")).map((model) => {
|
|
30576
|
+
const inputPricePerM = (model.prompt_text_token_price || 0) / 1000;
|
|
30577
|
+
const outputPricePerM = (model.completion_text_token_price || 0) / 1000;
|
|
30578
|
+
const avgPrice = (inputPricePerM + outputPricePerM) / 2;
|
|
30579
|
+
const { context, contextLength } = getXAIContextWindow(model.id);
|
|
30580
|
+
const supportsVision = (model.input_modalities || []).includes("image");
|
|
30581
|
+
const supportsReasoning = model.id.includes("reasoning");
|
|
30582
|
+
return {
|
|
30583
|
+
id: `xai@${model.id}`,
|
|
30584
|
+
name: model.id,
|
|
30585
|
+
description: `xAI ${supportsReasoning ? "reasoning " : ""}model`,
|
|
30586
|
+
provider: "xAI",
|
|
30587
|
+
pricing: {
|
|
30588
|
+
input: `$${inputPricePerM.toFixed(2)}`,
|
|
30589
|
+
output: `$${outputPricePerM.toFixed(2)}`,
|
|
30590
|
+
average: `$${avgPrice.toFixed(2)}/1M`
|
|
30591
|
+
},
|
|
30592
|
+
context,
|
|
30593
|
+
contextLength,
|
|
30594
|
+
supportsTools: true,
|
|
30595
|
+
supportsReasoning,
|
|
30596
|
+
supportsVision,
|
|
30597
|
+
isFree: false,
|
|
30598
|
+
source: "xAI"
|
|
30599
|
+
};
|
|
30600
|
+
});
|
|
30601
|
+
} catch {
|
|
30602
|
+
return [];
|
|
30603
|
+
}
|
|
30604
|
+
}
|
|
30605
|
+
async function fetchGeminiModels() {
|
|
30606
|
+
const apiKey = process.env.GEMINI_API_KEY;
|
|
30607
|
+
if (!apiKey) {
|
|
30608
|
+
return [];
|
|
30609
|
+
}
|
|
30610
|
+
try {
|
|
30611
|
+
const response = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${apiKey}`, {
|
|
30612
|
+
signal: AbortSignal.timeout(5000)
|
|
30613
|
+
});
|
|
30614
|
+
if (!response.ok) {
|
|
30615
|
+
return [];
|
|
30616
|
+
}
|
|
30617
|
+
const data = await response.json();
|
|
30618
|
+
if (!data.models || !Array.isArray(data.models)) {
|
|
30619
|
+
return [];
|
|
30620
|
+
}
|
|
30621
|
+
return data.models.filter((model) => {
|
|
30622
|
+
const methods = model.supportedGenerationMethods || [];
|
|
30623
|
+
return methods.includes("generateContent");
|
|
30624
|
+
}).map((model) => {
|
|
30625
|
+
const modelName = model.name.replace("models/", "");
|
|
30626
|
+
return {
|
|
30627
|
+
id: `google@${modelName}`,
|
|
30628
|
+
name: model.displayName || modelName,
|
|
30629
|
+
description: model.description || `Google Gemini model`,
|
|
30630
|
+
provider: "Gemini",
|
|
30631
|
+
pricing: {
|
|
30632
|
+
input: "$0.50",
|
|
30633
|
+
output: "$2.00",
|
|
30634
|
+
average: "$1.25/1M"
|
|
30635
|
+
},
|
|
30636
|
+
context: "128K",
|
|
30637
|
+
contextLength: 128000,
|
|
30638
|
+
supportsTools: true,
|
|
30639
|
+
supportsReasoning: false,
|
|
30640
|
+
supportsVision: true,
|
|
30641
|
+
isFree: false,
|
|
30642
|
+
source: "Gemini"
|
|
30643
|
+
};
|
|
30644
|
+
});
|
|
30645
|
+
} catch {
|
|
30646
|
+
return [];
|
|
30647
|
+
}
|
|
30648
|
+
}
|
|
30649
|
+
async function fetchOpenAIModels() {
|
|
30650
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
30651
|
+
if (!apiKey) {
|
|
30652
|
+
return [];
|
|
30653
|
+
}
|
|
30654
|
+
try {
|
|
30655
|
+
const response = await fetch("https://api.openai.com/v1/models", {
|
|
30656
|
+
headers: {
|
|
30657
|
+
Authorization: `Bearer ${apiKey}`,
|
|
30658
|
+
"Content-Type": "application/json"
|
|
30659
|
+
},
|
|
30660
|
+
signal: AbortSignal.timeout(5000)
|
|
30661
|
+
});
|
|
30662
|
+
if (!response.ok) {
|
|
30663
|
+
return [];
|
|
30664
|
+
}
|
|
30665
|
+
const data = await response.json();
|
|
30666
|
+
if (!data.data || !Array.isArray(data.data)) {
|
|
30667
|
+
return [];
|
|
30668
|
+
}
|
|
30669
|
+
const chatModels = data.data.filter((model) => {
|
|
30670
|
+
const id = model.id.toLowerCase();
|
|
30671
|
+
return id.startsWith("gpt-") || id.startsWith("o1-") || id.startsWith("o3-") || id.startsWith("chatgpt-");
|
|
30672
|
+
});
|
|
30673
|
+
return chatModels.map((model) => ({
|
|
30674
|
+
id: `oai@${model.id}`,
|
|
30675
|
+
name: model.id,
|
|
30676
|
+
description: `OpenAI model`,
|
|
30677
|
+
provider: "OpenAI",
|
|
30516
30678
|
pricing: {
|
|
30517
|
-
input: "
|
|
30518
|
-
output: "
|
|
30519
|
-
average: "
|
|
30679
|
+
input: "$2.00",
|
|
30680
|
+
output: "$8.00",
|
|
30681
|
+
average: "$5.00/1M"
|
|
30520
30682
|
},
|
|
30521
|
-
context:
|
|
30522
|
-
contextLength:
|
|
30683
|
+
context: "128K",
|
|
30684
|
+
contextLength: 128000,
|
|
30523
30685
|
supportsTools: true,
|
|
30524
|
-
supportsReasoning:
|
|
30525
|
-
supportsVision:
|
|
30526
|
-
isFree:
|
|
30527
|
-
source: "
|
|
30686
|
+
supportsReasoning: model.id.startsWith("o1-") || model.id.startsWith("o3-"),
|
|
30687
|
+
supportsVision: model.id.includes("vision") || model.id.startsWith("gpt-4"),
|
|
30688
|
+
isFree: false,
|
|
30689
|
+
source: "OpenAI"
|
|
30528
30690
|
}));
|
|
30529
30691
|
} catch {
|
|
30530
30692
|
return [];
|
|
@@ -30575,8 +30737,16 @@ async function getFreeModels() {
|
|
|
30575
30737
|
return combined;
|
|
30576
30738
|
}
|
|
30577
30739
|
async function getAllModelsForSearch() {
|
|
30578
|
-
const
|
|
30579
|
-
|
|
30740
|
+
const [openRouterModels, xaiModels, geminiModels, openaiModels, zenModels] = await Promise.all([
|
|
30741
|
+
fetchAllModels().then((models) => models.map(toModelInfo)),
|
|
30742
|
+
fetchXAIModels(),
|
|
30743
|
+
fetchGeminiModels(),
|
|
30744
|
+
fetchOpenAIModels(),
|
|
30745
|
+
fetchZenFreeModels()
|
|
30746
|
+
]);
|
|
30747
|
+
const directApiModels = [...xaiModels, ...geminiModels, ...openaiModels];
|
|
30748
|
+
const allModels = [...zenModels, ...directApiModels, ...openRouterModels];
|
|
30749
|
+
return allModels;
|
|
30580
30750
|
}
|
|
30581
30751
|
function formatModelChoice(model, showSource = false) {
|
|
30582
30752
|
const caps = [
|
|
@@ -30588,7 +30758,14 @@ function formatModelChoice(model, showSource = false) {
|
|
|
30588
30758
|
const priceStr = model.pricing?.average || "N/A";
|
|
30589
30759
|
const ctxStr = model.context || "N/A";
|
|
30590
30760
|
if (showSource && model.source) {
|
|
30591
|
-
const
|
|
30761
|
+
const sourceTagMap = {
|
|
30762
|
+
Zen: "Zen",
|
|
30763
|
+
OpenRouter: "OR",
|
|
30764
|
+
xAI: "xAI",
|
|
30765
|
+
Gemini: "Gem",
|
|
30766
|
+
OpenAI: "OAI"
|
|
30767
|
+
};
|
|
30768
|
+
const sourceTag = sourceTagMap[model.source] || model.source;
|
|
30592
30769
|
return `${sourceTag} ${model.id} (${priceStr}, ${ctxStr}${capsStr})`;
|
|
30593
30770
|
}
|
|
30594
30771
|
return `${model.id} (${model.provider}, ${priceStr}, ${ctxStr}${capsStr})`;
|
|
@@ -30618,24 +30795,46 @@ async function selectModel(options = {}) {
|
|
|
30618
30795
|
if (models.length === 0) {
|
|
30619
30796
|
throw new Error("No free models available");
|
|
30620
30797
|
}
|
|
30621
|
-
} else if (recommended) {
|
|
30622
|
-
const recommendedModels = loadRecommendedModels2();
|
|
30623
|
-
if (recommendedModels.length > 0) {
|
|
30624
|
-
models = recommendedModels;
|
|
30625
|
-
} else {
|
|
30626
|
-
const allModels = await getAllModelsForSearch();
|
|
30627
|
-
models = allModels.slice(0, 20);
|
|
30628
|
-
}
|
|
30629
30798
|
} else {
|
|
30630
|
-
|
|
30799
|
+
const [allModels, recommendedModels] = await Promise.all([
|
|
30800
|
+
getAllModelsForSearch(),
|
|
30801
|
+
Promise.resolve(recommended ? loadRecommendedModels2() : [])
|
|
30802
|
+
]);
|
|
30803
|
+
const seenIds = new Set;
|
|
30804
|
+
models = [];
|
|
30805
|
+
for (const m of allModels.filter((m2) => m2.source === "Zen")) {
|
|
30806
|
+
if (!seenIds.has(m.id)) {
|
|
30807
|
+
seenIds.add(m.id);
|
|
30808
|
+
models.push(m);
|
|
30809
|
+
}
|
|
30810
|
+
}
|
|
30811
|
+
for (const m of recommendedModels) {
|
|
30812
|
+
if (!seenIds.has(m.id)) {
|
|
30813
|
+
seenIds.add(m.id);
|
|
30814
|
+
models.push(m);
|
|
30815
|
+
}
|
|
30816
|
+
}
|
|
30817
|
+
for (const m of allModels.filter((m2) => m2.source && m2.source !== "Zen" && m2.source !== "OpenRouter")) {
|
|
30818
|
+
if (!seenIds.has(m.id)) {
|
|
30819
|
+
seenIds.add(m.id);
|
|
30820
|
+
models.push(m);
|
|
30821
|
+
}
|
|
30822
|
+
}
|
|
30823
|
+
for (const m of allModels.filter((m2) => m2.source === "OpenRouter")) {
|
|
30824
|
+
if (!seenIds.has(m.id)) {
|
|
30825
|
+
seenIds.add(m.id);
|
|
30826
|
+
models.push(m);
|
|
30827
|
+
}
|
|
30828
|
+
}
|
|
30631
30829
|
}
|
|
30632
30830
|
const promptMessage = message || (freeOnly ? "Select a FREE model:" : "Select a model (type to search):");
|
|
30633
30831
|
const selected = await dist_default4({
|
|
30634
30832
|
message: promptMessage,
|
|
30833
|
+
pageSize: 20,
|
|
30635
30834
|
source: async (term) => {
|
|
30636
30835
|
if (!term) {
|
|
30637
|
-
return models.slice(0,
|
|
30638
|
-
name: formatModelChoice(m,
|
|
30836
|
+
return models.slice(0, 30).map((m) => ({
|
|
30837
|
+
name: formatModelChoice(m, true),
|
|
30639
30838
|
value: m.id,
|
|
30640
30839
|
description: m.description?.slice(0, 80)
|
|
30641
30840
|
}));
|
|
@@ -30643,9 +30842,9 @@ async function selectModel(options = {}) {
|
|
|
30643
30842
|
const results = models.map((m) => ({
|
|
30644
30843
|
model: m,
|
|
30645
30844
|
score: Math.max(fuzzyMatch(m.id, term), fuzzyMatch(m.name, term), fuzzyMatch(m.provider, term) * 0.5)
|
|
30646
|
-
})).filter((r) => r.score > 0.1).sort((a, b) => b.score - a.score).slice(0,
|
|
30845
|
+
})).filter((r) => r.score > 0.1).sort((a, b) => b.score - a.score).slice(0, 30);
|
|
30647
30846
|
return results.map((r) => ({
|
|
30648
|
-
name: formatModelChoice(r.model,
|
|
30847
|
+
name: formatModelChoice(r.model, true),
|
|
30649
30848
|
value: r.model.id,
|
|
30650
30849
|
description: r.model.description?.slice(0, 80)
|
|
30651
30850
|
}));
|
|
@@ -31113,332 +31312,19 @@ var init_config = __esm(() => {
|
|
|
31113
31312
|
};
|
|
31114
31313
|
});
|
|
31115
31314
|
|
|
31116
|
-
// src/claude-runner.ts
|
|
31117
|
-
var exports_claude_runner = {};
|
|
31118
|
-
__export(exports_claude_runner, {
|
|
31119
|
-
runClaudeWithProxy: () => runClaudeWithProxy,
|
|
31120
|
-
checkClaudeInstalled: () => checkClaudeInstalled
|
|
31121
|
-
});
|
|
31122
|
-
import { spawn } from "node:child_process";
|
|
31123
|
-
import { writeFileSync as writeFileSync5, unlinkSync as unlinkSync2, mkdirSync as mkdirSync5, existsSync as existsSync6 } from "node:fs";
|
|
31124
|
-
import { tmpdir, homedir as homedir5 } from "node:os";
|
|
31125
|
-
import { join as join6 } from "node:path";
|
|
31126
|
-
function isWindows() {
|
|
31127
|
-
return process.platform === "win32";
|
|
31128
|
-
}
|
|
31129
|
-
function createStatusLineScript(tokenFilePath) {
|
|
31130
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
|
|
31131
|
-
const claudishDir = join6(homeDir, ".claudish");
|
|
31132
|
-
const timestamp = Date.now();
|
|
31133
|
-
const scriptPath = join6(claudishDir, `status-${timestamp}.js`);
|
|
31134
|
-
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
31135
|
-
const script = `
|
|
31136
|
-
const fs = require('fs');
|
|
31137
|
-
const path = require('path');
|
|
31138
|
-
|
|
31139
|
-
const CYAN = "\\x1b[96m";
|
|
31140
|
-
const YELLOW = "\\x1b[93m";
|
|
31141
|
-
const GREEN = "\\x1b[92m";
|
|
31142
|
-
const MAGENTA = "\\x1b[95m";
|
|
31143
|
-
const DIM = "\\x1b[2m";
|
|
31144
|
-
const RESET = "\\x1b[0m";
|
|
31145
|
-
const BOLD = "\\x1b[1m";
|
|
31146
|
-
|
|
31147
|
-
// Format token count with k/M suffix
|
|
31148
|
-
function formatTokens(n) {
|
|
31149
|
-
if (n >= 1000000) return (n / 1000000).toFixed(n >= 10000000 ? 0 : 1).replace(/\\.0$/, '') + 'M';
|
|
31150
|
-
if (n >= 1000) return (n / 1000).toFixed(n >= 10000 ? 0 : 1).replace(/\\.0$/, '') + 'k';
|
|
31151
|
-
return String(n);
|
|
31152
|
-
}
|
|
31153
|
-
|
|
31154
|
-
let input = '';
|
|
31155
|
-
process.stdin.setEncoding('utf8');
|
|
31156
|
-
process.stdin.on('data', chunk => input += chunk);
|
|
31157
|
-
process.stdin.on('end', () => {
|
|
31158
|
-
try {
|
|
31159
|
-
let dir = path.basename(process.cwd());
|
|
31160
|
-
if (dir.length > 15) dir = dir.substring(0, 12) + '...';
|
|
31161
|
-
|
|
31162
|
-
let ctx = 100, cost = 0, inputTokens = 0, contextWindow = 0;
|
|
31163
|
-
const model = process.env.CLAUDISH_ACTIVE_MODEL_NAME || 'unknown';
|
|
31164
|
-
const isLocal = process.env.CLAUDISH_IS_LOCAL === 'true';
|
|
31165
|
-
|
|
31166
|
-
let isFree = false, isEstimated = false, providerName = '';
|
|
31167
|
-
try {
|
|
31168
|
-
const tokens = JSON.parse(fs.readFileSync('${escapedTokenPath}', 'utf-8'));
|
|
31169
|
-
cost = tokens.total_cost || 0;
|
|
31170
|
-
ctx = tokens.context_left_percent || 100;
|
|
31171
|
-
inputTokens = tokens.input_tokens || 0;
|
|
31172
|
-
contextWindow = tokens.context_window || 0;
|
|
31173
|
-
isFree = tokens.is_free || false;
|
|
31174
|
-
isEstimated = tokens.is_estimated || false;
|
|
31175
|
-
providerName = tokens.provider_name || '';
|
|
31176
|
-
} catch (e) {
|
|
31177
|
-
try {
|
|
31178
|
-
const json = JSON.parse(input);
|
|
31179
|
-
cost = json.total_cost_usd || 0;
|
|
31180
|
-
} catch {}
|
|
31181
|
-
}
|
|
31182
|
-
|
|
31183
|
-
let costDisplay;
|
|
31184
|
-
if (isLocal) {
|
|
31185
|
-
costDisplay = 'LOCAL';
|
|
31186
|
-
} else if (isFree) {
|
|
31187
|
-
costDisplay = 'FREE';
|
|
31188
|
-
} else if (isEstimated) {
|
|
31189
|
-
costDisplay = '~$' + cost.toFixed(3);
|
|
31190
|
-
} else {
|
|
31191
|
-
costDisplay = '$' + cost.toFixed(3);
|
|
31192
|
-
}
|
|
31193
|
-
const modelDisplay = providerName ? providerName + ' ' + model : model;
|
|
31194
|
-
// Format context display: "96% (37k/1M)" or just "96%" if no token data
|
|
31195
|
-
let ctxDisplay = ctx + '%';
|
|
31196
|
-
if (inputTokens > 0 && contextWindow > 0) {
|
|
31197
|
-
ctxDisplay = ctx + '% (' + formatTokens(inputTokens) + '/' + formatTokens(contextWindow) + ')';
|
|
31198
|
-
}
|
|
31199
|
-
console.log(\`\${CYAN}\${BOLD}\${dir}\${RESET} \${DIM}•\${RESET} \${YELLOW}\${modelDisplay}\${RESET} \${DIM}•\${RESET} \${GREEN}\${costDisplay}\${RESET} \${DIM}•\${RESET} \${MAGENTA}\${ctxDisplay}\${RESET}\`);
|
|
31200
|
-
} catch (e) {
|
|
31201
|
-
console.log('claudish');
|
|
31202
|
-
}
|
|
31203
|
-
});
|
|
31204
|
-
`;
|
|
31205
|
-
writeFileSync5(scriptPath, script, "utf-8");
|
|
31206
|
-
return scriptPath;
|
|
31207
|
-
}
|
|
31208
|
-
function createTempSettingsFile(modelDisplay, port) {
|
|
31209
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
|
|
31210
|
-
const claudishDir = join6(homeDir, ".claudish");
|
|
31211
|
-
try {
|
|
31212
|
-
mkdirSync5(claudishDir, { recursive: true });
|
|
31213
|
-
} catch {}
|
|
31214
|
-
const timestamp = Date.now();
|
|
31215
|
-
const tempPath = join6(claudishDir, `settings-${timestamp}.json`);
|
|
31216
|
-
const tokenFilePath = join6(claudishDir, `tokens-${port}.json`);
|
|
31217
|
-
let statusCommand;
|
|
31218
|
-
if (isWindows()) {
|
|
31219
|
-
const scriptPath = createStatusLineScript(tokenFilePath);
|
|
31220
|
-
statusCommand = `node "${scriptPath}"`;
|
|
31221
|
-
} else {
|
|
31222
|
-
const CYAN2 = "\\033[96m";
|
|
31223
|
-
const YELLOW2 = "\\033[93m";
|
|
31224
|
-
const GREEN2 = "\\033[92m";
|
|
31225
|
-
const MAGENTA = "\\033[95m";
|
|
31226
|
-
const DIM2 = "\\033[2m";
|
|
31227
|
-
const RESET2 = "\\033[0m";
|
|
31228
|
-
const BOLD2 = "\\033[1m";
|
|
31229
|
-
const formatTokensBash = `fmt_tok() { local n=\${1:-0}; if [ "$n" -ge 1000000 ]; then echo "$((n/1000000))M"; elif [ "$n" -ge 1000 ]; then echo "$((n/1000))k"; else echo "$n"; fi; }`;
|
|
31230
|
-
statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=100 && COST="0" && IS_FREE="false" && IS_EST="false" && PROVIDER="" && IN_TOK=0 && CTX_WIN=0 && ${formatTokensBash} && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d ' \\n') && REAL_CTX=$(echo "$TOKENS" | grep -o '"context_left_percent":[0-9]*' | grep -o '[0-9]*') && if [ ! -z "$REAL_CTX" ]; then CTX="$REAL_CTX"; fi && REAL_COST=$(echo "$TOKENS" | grep -o '"total_cost":[0-9.]*' | cut -d: -f2) && if [ ! -z "$REAL_COST" ]; then COST="$REAL_COST"; fi && IN_TOK=$(echo "$TOKENS" | grep -o '"input_tokens":[0-9]*' | grep -o '[0-9]*') && CTX_WIN=$(echo "$TOKENS" | grep -o '"context_window":[0-9]*' | grep -o '[0-9]*') && IS_FREE=$(echo "$TOKENS" | grep -o '"is_free":[a-z]*' | cut -d: -f2) && IS_EST=$(echo "$TOKENS" | grep -o '"is_estimated":[a-z]*' | cut -d: -f2) && PROVIDER=$(echo "$TOKENS" | grep -o '"provider_name":"[^"]*"' | cut -d'"' -f4); fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && MODEL_DISPLAY="$CLAUDISH_ACTIVE_MODEL_NAME" && if [ ! -z "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi && if [ "$IN_TOK" -gt 0 ] 2>/dev/null && [ "$CTX_WIN" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX%"; fi && printf "${CYAN2}${BOLD2}%s${RESET2} ${DIM2}•${RESET2} ${YELLOW2}%s${RESET2} ${DIM2}•${RESET2} ${GREEN2}%s${RESET2} ${DIM2}•${RESET2} ${MAGENTA}%s${RESET2}\\n" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"`;
|
|
31231
|
-
}
|
|
31232
|
-
const settings = {
|
|
31233
|
-
statusLine: {
|
|
31234
|
-
type: "command",
|
|
31235
|
-
command: statusCommand,
|
|
31236
|
-
padding: 0
|
|
31237
|
-
}
|
|
31238
|
-
};
|
|
31239
|
-
writeFileSync5(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
31240
|
-
return tempPath;
|
|
31241
|
-
}
|
|
31242
|
-
async function runClaudeWithProxy(config3, proxyUrl) {
|
|
31243
|
-
const modelId = config3.model || "unknown";
|
|
31244
|
-
const portMatch = proxyUrl.match(/:(\d+)/);
|
|
31245
|
-
const port = portMatch ? portMatch[1] : "unknown";
|
|
31246
|
-
const tempSettingsPath = createTempSettingsFile(modelId, port);
|
|
31247
|
-
const claudeArgs = [];
|
|
31248
|
-
claudeArgs.push("--settings", tempSettingsPath);
|
|
31249
|
-
if (config3.interactive) {
|
|
31250
|
-
if (config3.autoApprove) {
|
|
31251
|
-
claudeArgs.push("--dangerously-skip-permissions");
|
|
31252
|
-
}
|
|
31253
|
-
if (config3.dangerous) {
|
|
31254
|
-
claudeArgs.push("--dangerouslyDisableSandbox");
|
|
31255
|
-
}
|
|
31256
|
-
} else {
|
|
31257
|
-
claudeArgs.push("-p");
|
|
31258
|
-
if (config3.autoApprove) {
|
|
31259
|
-
claudeArgs.push("--dangerously-skip-permissions");
|
|
31260
|
-
}
|
|
31261
|
-
if (config3.dangerous) {
|
|
31262
|
-
claudeArgs.push("--dangerouslyDisableSandbox");
|
|
31263
|
-
}
|
|
31264
|
-
if (config3.jsonOutput) {
|
|
31265
|
-
claudeArgs.push("--output-format", "json");
|
|
31266
|
-
}
|
|
31267
|
-
if (config3.agent && config3.claudeArgs.length > 0) {
|
|
31268
|
-
const modifiedArgs = [...config3.claudeArgs];
|
|
31269
|
-
const agentId = config3.agent.startsWith("@agent-") ? config3.agent : `@agent-${config3.agent}`;
|
|
31270
|
-
modifiedArgs[0] = `Use the ${agentId} agent to: ${modifiedArgs[0]}`;
|
|
31271
|
-
claudeArgs.push(...modifiedArgs);
|
|
31272
|
-
} else {
|
|
31273
|
-
claudeArgs.push(...config3.claudeArgs);
|
|
31274
|
-
}
|
|
31275
|
-
}
|
|
31276
|
-
const isLocalModel = modelId.startsWith("ollama/") || modelId.startsWith("ollama:") || modelId.startsWith("lmstudio/") || modelId.startsWith("lmstudio:") || modelId.startsWith("vllm/") || modelId.startsWith("vllm:") || modelId.startsWith("mlx/") || modelId.startsWith("mlx:") || modelId.startsWith("http://") || modelId.startsWith("https://");
|
|
31277
|
-
const env = {
|
|
31278
|
-
...process.env,
|
|
31279
|
-
ANTHROPIC_BASE_URL: proxyUrl,
|
|
31280
|
-
[ENV.CLAUDISH_ACTIVE_MODEL_NAME]: modelId,
|
|
31281
|
-
CLAUDISH_IS_LOCAL: isLocalModel ? "true" : "false"
|
|
31282
|
-
};
|
|
31283
|
-
if (config3.monitor) {
|
|
31284
|
-
delete env.ANTHROPIC_API_KEY;
|
|
31285
|
-
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
31286
|
-
if (modelId && modelId !== "unknown") {
|
|
31287
|
-
env[ENV.ANTHROPIC_MODEL] = modelId;
|
|
31288
|
-
env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
|
|
31289
|
-
}
|
|
31290
|
-
} else {
|
|
31291
|
-
env[ENV.ANTHROPIC_MODEL] = modelId;
|
|
31292
|
-
env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
|
|
31293
|
-
env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
|
|
31294
|
-
env.ANTHROPIC_AUTH_TOKEN = process.env.ANTHROPIC_AUTH_TOKEN || "placeholder-token-not-used-proxy-handles-auth";
|
|
31295
|
-
}
|
|
31296
|
-
const log2 = (message) => {
|
|
31297
|
-
if (!config3.quiet) {
|
|
31298
|
-
console.log(message);
|
|
31299
|
-
}
|
|
31300
|
-
};
|
|
31301
|
-
if (config3.interactive) {
|
|
31302
|
-
log2(`
|
|
31303
|
-
[claudish] Model: ${modelId}
|
|
31304
|
-
`);
|
|
31305
|
-
} else {
|
|
31306
|
-
log2(`
|
|
31307
|
-
[claudish] Model: ${modelId}`);
|
|
31308
|
-
log2(`[claudish] Arguments: ${claudeArgs.join(" ")}
|
|
31309
|
-
`);
|
|
31310
|
-
}
|
|
31311
|
-
const claudeBinary = await findClaudeBinary();
|
|
31312
|
-
if (!claudeBinary) {
|
|
31313
|
-
console.error("Error: Claude Code CLI not found");
|
|
31314
|
-
console.error("Install it from: https://claude.com/claude-code");
|
|
31315
|
-
console.error(`
|
|
31316
|
-
Or set CLAUDE_PATH to your custom installation:`);
|
|
31317
|
-
const home = homedir5();
|
|
31318
|
-
const localPath = isWindows() ? join6(home, ".claude", "local", "claude.exe") : join6(home, ".claude", "local", "claude");
|
|
31319
|
-
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
31320
|
-
process.exit(1);
|
|
31321
|
-
}
|
|
31322
|
-
const proc = spawn(claudeBinary, claudeArgs, {
|
|
31323
|
-
env,
|
|
31324
|
-
stdio: "inherit",
|
|
31325
|
-
shell: false
|
|
31326
|
-
});
|
|
31327
|
-
setupSignalHandlers(proc, tempSettingsPath, config3.quiet);
|
|
31328
|
-
const exitCode = await new Promise((resolve) => {
|
|
31329
|
-
proc.on("exit", (code) => {
|
|
31330
|
-
resolve(code ?? 1);
|
|
31331
|
-
});
|
|
31332
|
-
});
|
|
31333
|
-
try {
|
|
31334
|
-
unlinkSync2(tempSettingsPath);
|
|
31335
|
-
} catch (error46) {}
|
|
31336
|
-
return exitCode;
|
|
31337
|
-
}
|
|
31338
|
-
function setupSignalHandlers(proc, tempSettingsPath, quiet) {
|
|
31339
|
-
const signals2 = isWindows() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
31340
|
-
for (const signal of signals2) {
|
|
31341
|
-
process.on(signal, () => {
|
|
31342
|
-
if (!quiet) {
|
|
31343
|
-
console.log(`
|
|
31344
|
-
[claudish] Received ${signal}, shutting down...`);
|
|
31345
|
-
}
|
|
31346
|
-
proc.kill();
|
|
31347
|
-
try {
|
|
31348
|
-
unlinkSync2(tempSettingsPath);
|
|
31349
|
-
} catch {}
|
|
31350
|
-
process.exit(0);
|
|
31351
|
-
});
|
|
31352
|
-
}
|
|
31353
|
-
}
|
|
31354
|
-
async function findClaudeBinary() {
|
|
31355
|
-
const isWindows2 = process.platform === "win32";
|
|
31356
|
-
if (process.env.CLAUDE_PATH) {
|
|
31357
|
-
if (existsSync6(process.env.CLAUDE_PATH)) {
|
|
31358
|
-
return process.env.CLAUDE_PATH;
|
|
31359
|
-
}
|
|
31360
|
-
}
|
|
31361
|
-
const home = homedir5();
|
|
31362
|
-
const localPath = isWindows2 ? join6(home, ".claude", "local", "claude.exe") : join6(home, ".claude", "local", "claude");
|
|
31363
|
-
if (existsSync6(localPath)) {
|
|
31364
|
-
return localPath;
|
|
31365
|
-
}
|
|
31366
|
-
if (isWindows2) {
|
|
31367
|
-
const windowsPaths = [
|
|
31368
|
-
join6(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
31369
|
-
join6(home, ".npm-global", "claude.cmd"),
|
|
31370
|
-
join6(home, "node_modules", ".bin", "claude.cmd")
|
|
31371
|
-
];
|
|
31372
|
-
for (const path of windowsPaths) {
|
|
31373
|
-
if (existsSync6(path)) {
|
|
31374
|
-
return path;
|
|
31375
|
-
}
|
|
31376
|
-
}
|
|
31377
|
-
} else {
|
|
31378
|
-
const commonPaths = [
|
|
31379
|
-
"/usr/local/bin/claude",
|
|
31380
|
-
"/opt/homebrew/bin/claude",
|
|
31381
|
-
join6(home, ".npm-global/bin/claude"),
|
|
31382
|
-
join6(home, ".local/bin/claude"),
|
|
31383
|
-
join6(home, "node_modules/.bin/claude"),
|
|
31384
|
-
"/data/data/com.termux/files/usr/bin/claude",
|
|
31385
|
-
join6(home, "../usr/bin/claude")
|
|
31386
|
-
];
|
|
31387
|
-
for (const path of commonPaths) {
|
|
31388
|
-
if (existsSync6(path)) {
|
|
31389
|
-
return path;
|
|
31390
|
-
}
|
|
31391
|
-
}
|
|
31392
|
-
}
|
|
31393
|
-
try {
|
|
31394
|
-
const shellCommand = isWindows2 ? "where claude" : "command -v claude";
|
|
31395
|
-
const proc = spawn(shellCommand, [], {
|
|
31396
|
-
stdio: "pipe",
|
|
31397
|
-
shell: true
|
|
31398
|
-
});
|
|
31399
|
-
let output = "";
|
|
31400
|
-
proc.stdout?.on("data", (data) => {
|
|
31401
|
-
output += data.toString();
|
|
31402
|
-
});
|
|
31403
|
-
const exitCode = await new Promise((resolve) => {
|
|
31404
|
-
proc.on("exit", (code) => {
|
|
31405
|
-
resolve(code ?? 1);
|
|
31406
|
-
});
|
|
31407
|
-
});
|
|
31408
|
-
if (exitCode === 0 && output.trim()) {
|
|
31409
|
-
const lines = output.trim().split(/\r?\n/);
|
|
31410
|
-
if (isWindows2) {
|
|
31411
|
-
const cmdPath = lines.find((line) => line.endsWith(".cmd"));
|
|
31412
|
-
if (cmdPath) {
|
|
31413
|
-
return cmdPath;
|
|
31414
|
-
}
|
|
31415
|
-
}
|
|
31416
|
-
return lines[0];
|
|
31417
|
-
}
|
|
31418
|
-
} catch {}
|
|
31419
|
-
return null;
|
|
31420
|
-
}
|
|
31421
|
-
async function checkClaudeInstalled() {
|
|
31422
|
-
const binary = await findClaudeBinary();
|
|
31423
|
-
return binary !== null;
|
|
31424
|
-
}
|
|
31425
|
-
var init_claude_runner = __esm(() => {
|
|
31426
|
-
init_config();
|
|
31427
|
-
});
|
|
31428
|
-
|
|
31429
31315
|
// src/model-loader.ts
|
|
31430
|
-
import { readFileSync as readFileSync5, existsSync as
|
|
31431
|
-
import { join as
|
|
31316
|
+
import { readFileSync as readFileSync5, existsSync as existsSync6 } from "node:fs";
|
|
31317
|
+
import { join as join6, dirname as dirname3 } from "node:path";
|
|
31432
31318
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
31433
31319
|
function getRecommendedModelsPath() {
|
|
31434
|
-
return
|
|
31320
|
+
return join6(__dirname4, "../recommended-models.json");
|
|
31435
31321
|
}
|
|
31436
31322
|
function loadRecommendedModelsJSON() {
|
|
31437
31323
|
if (_cachedRecommendedModels) {
|
|
31438
31324
|
return _cachedRecommendedModels;
|
|
31439
31325
|
}
|
|
31440
31326
|
const jsonPath = getRecommendedModelsPath();
|
|
31441
|
-
if (!
|
|
31327
|
+
if (!existsSync6(jsonPath)) {
|
|
31442
31328
|
throw new Error(`recommended-models.json not found at ${jsonPath}. ` + `Run 'claudish --update-models' to fetch the latest model list.`);
|
|
31443
31329
|
}
|
|
31444
31330
|
try {
|
|
@@ -32496,10 +32382,10 @@ __export(exports_cli, {
|
|
|
32496
32382
|
getMissingKeyResolutions: () => getMissingKeyResolutions,
|
|
32497
32383
|
getMissingKeyError: () => getMissingKeyError
|
|
32498
32384
|
});
|
|
32499
|
-
import { readFileSync as readFileSync6, writeFileSync as
|
|
32385
|
+
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, existsSync as existsSync7, mkdirSync as mkdirSync5, copyFileSync } from "node:fs";
|
|
32500
32386
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
32501
|
-
import { dirname as dirname4, join as
|
|
32502
|
-
import { homedir as
|
|
32387
|
+
import { dirname as dirname4, join as join7 } from "node:path";
|
|
32388
|
+
import { homedir as homedir5 } from "node:os";
|
|
32503
32389
|
function getVersion() {
|
|
32504
32390
|
return VERSION;
|
|
32505
32391
|
}
|
|
@@ -32757,7 +32643,7 @@ async function fetchOllamaModels() {
|
|
|
32757
32643
|
}
|
|
32758
32644
|
async function searchAndPrintModels(query, forceUpdate) {
|
|
32759
32645
|
let models = [];
|
|
32760
|
-
if (!forceUpdate &&
|
|
32646
|
+
if (!forceUpdate && existsSync7(ALL_MODELS_JSON_PATH2)) {
|
|
32761
32647
|
try {
|
|
32762
32648
|
const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH2, "utf-8"));
|
|
32763
32649
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
@@ -32776,8 +32662,8 @@ async function searchAndPrintModels(query, forceUpdate) {
|
|
|
32776
32662
|
throw new Error(`API returned ${response.status}`);
|
|
32777
32663
|
const data = await response.json();
|
|
32778
32664
|
models = data.data;
|
|
32779
|
-
|
|
32780
|
-
|
|
32665
|
+
mkdirSync5(CLAUDISH_CACHE_DIR3, { recursive: true });
|
|
32666
|
+
writeFileSync5(ALL_MODELS_JSON_PATH2, JSON.stringify({
|
|
32781
32667
|
lastUpdated: new Date().toISOString(),
|
|
32782
32668
|
models
|
|
32783
32669
|
}), "utf-8");
|
|
@@ -32865,7 +32751,7 @@ Found ${results.length} matching models:
|
|
|
32865
32751
|
async function printAllModels(jsonOutput, forceUpdate) {
|
|
32866
32752
|
let models = [];
|
|
32867
32753
|
const [ollamaModels, zenModels] = await Promise.all([fetchOllamaModels(), fetchZenModels()]);
|
|
32868
|
-
if (!forceUpdate &&
|
|
32754
|
+
if (!forceUpdate && existsSync7(ALL_MODELS_JSON_PATH2)) {
|
|
32869
32755
|
try {
|
|
32870
32756
|
const cacheData = JSON.parse(readFileSync6(ALL_MODELS_JSON_PATH2, "utf-8"));
|
|
32871
32757
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
@@ -32887,8 +32773,8 @@ async function printAllModels(jsonOutput, forceUpdate) {
|
|
|
32887
32773
|
throw new Error(`API returned ${response.status}`);
|
|
32888
32774
|
const data = await response.json();
|
|
32889
32775
|
models = data.data;
|
|
32890
|
-
|
|
32891
|
-
|
|
32776
|
+
mkdirSync5(CLAUDISH_CACHE_DIR3, { recursive: true });
|
|
32777
|
+
writeFileSync5(ALL_MODELS_JSON_PATH2, JSON.stringify({
|
|
32892
32778
|
lastUpdated: new Date().toISOString(),
|
|
32893
32779
|
models
|
|
32894
32780
|
}), "utf-8");
|
|
@@ -33042,7 +32928,7 @@ async function printAllModels(jsonOutput, forceUpdate) {
|
|
|
33042
32928
|
console.log("Top models: claudish --top-models");
|
|
33043
32929
|
}
|
|
33044
32930
|
function isCacheStale() {
|
|
33045
|
-
if (!
|
|
32931
|
+
if (!existsSync7(MODELS_JSON_PATH)) {
|
|
33046
32932
|
return true;
|
|
33047
32933
|
}
|
|
33048
32934
|
try {
|
|
@@ -33141,7 +33027,7 @@ async function updateModelsFromOpenRouter() {
|
|
|
33141
33027
|
providers.add(provider);
|
|
33142
33028
|
}
|
|
33143
33029
|
let version2 = "1.1.5";
|
|
33144
|
-
if (
|
|
33030
|
+
if (existsSync7(MODELS_JSON_PATH)) {
|
|
33145
33031
|
try {
|
|
33146
33032
|
const existing = JSON.parse(readFileSync6(MODELS_JSON_PATH, "utf-8"));
|
|
33147
33033
|
version2 = existing.version || version2;
|
|
@@ -33153,7 +33039,7 @@ async function updateModelsFromOpenRouter() {
|
|
|
33153
33039
|
source: "https://openrouter.ai/models?categories=programming&fmt=cards&order=top-weekly",
|
|
33154
33040
|
models: recommendations
|
|
33155
33041
|
};
|
|
33156
|
-
|
|
33042
|
+
writeFileSync5(MODELS_JSON_PATH, JSON.stringify(updatedData, null, 2), "utf-8");
|
|
33157
33043
|
console.error(`✅ Updated ${recommendations.length} models (last updated: ${updatedData.lastUpdated})`);
|
|
33158
33044
|
} catch (error46) {
|
|
33159
33045
|
console.error(`❌ Failed to update models: ${error46 instanceof Error ? error46.message : String(error46)}`);
|
|
@@ -33468,7 +33354,7 @@ MORE INFO:
|
|
|
33468
33354
|
}
|
|
33469
33355
|
function printAIAgentGuide() {
|
|
33470
33356
|
try {
|
|
33471
|
-
const guidePath =
|
|
33357
|
+
const guidePath = join7(__dirname5, "../AI_AGENT_GUIDE.md");
|
|
33472
33358
|
const guideContent = readFileSync6(guidePath, "utf-8");
|
|
33473
33359
|
console.log(guideContent);
|
|
33474
33360
|
} catch (error46) {
|
|
@@ -33485,19 +33371,19 @@ async function initializeClaudishSkill() {
|
|
|
33485
33371
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
33486
33372
|
`);
|
|
33487
33373
|
const cwd = process.cwd();
|
|
33488
|
-
const claudeDir =
|
|
33489
|
-
const skillsDir =
|
|
33490
|
-
const claudishSkillDir =
|
|
33491
|
-
const skillFile =
|
|
33492
|
-
if (
|
|
33374
|
+
const claudeDir = join7(cwd, ".claude");
|
|
33375
|
+
const skillsDir = join7(claudeDir, "skills");
|
|
33376
|
+
const claudishSkillDir = join7(skillsDir, "claudish-usage");
|
|
33377
|
+
const skillFile = join7(claudishSkillDir, "SKILL.md");
|
|
33378
|
+
if (existsSync7(skillFile)) {
|
|
33493
33379
|
console.log("✅ Claudish skill already installed at:");
|
|
33494
33380
|
console.log(` ${skillFile}
|
|
33495
33381
|
`);
|
|
33496
33382
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
33497
33383
|
return;
|
|
33498
33384
|
}
|
|
33499
|
-
const sourceSkillPath =
|
|
33500
|
-
if (!
|
|
33385
|
+
const sourceSkillPath = join7(__dirname5, "../skills/claudish-usage/SKILL.md");
|
|
33386
|
+
if (!existsSync7(sourceSkillPath)) {
|
|
33501
33387
|
console.error("❌ Error: Claudish skill file not found in installation.");
|
|
33502
33388
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
33503
33389
|
console.error(`
|
|
@@ -33506,16 +33392,16 @@ async function initializeClaudishSkill() {
|
|
|
33506
33392
|
process.exit(1);
|
|
33507
33393
|
}
|
|
33508
33394
|
try {
|
|
33509
|
-
if (!
|
|
33510
|
-
|
|
33395
|
+
if (!existsSync7(claudeDir)) {
|
|
33396
|
+
mkdirSync5(claudeDir, { recursive: true });
|
|
33511
33397
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
33512
33398
|
}
|
|
33513
|
-
if (!
|
|
33514
|
-
|
|
33399
|
+
if (!existsSync7(skillsDir)) {
|
|
33400
|
+
mkdirSync5(skillsDir, { recursive: true });
|
|
33515
33401
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
33516
33402
|
}
|
|
33517
|
-
if (!
|
|
33518
|
-
|
|
33403
|
+
if (!existsSync7(claudishSkillDir)) {
|
|
33404
|
+
mkdirSync5(claudishSkillDir, { recursive: true });
|
|
33519
33405
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
33520
33406
|
}
|
|
33521
33407
|
copyFileSync(sourceSkillPath, skillFile);
|
|
@@ -33557,7 +33443,7 @@ function printAvailableModels() {
|
|
|
33557
33443
|
let lastUpdated = "unknown";
|
|
33558
33444
|
let models = [];
|
|
33559
33445
|
try {
|
|
33560
|
-
if (
|
|
33446
|
+
if (existsSync7(MODELS_JSON_PATH)) {
|
|
33561
33447
|
const data = JSON.parse(readFileSync6(MODELS_JSON_PATH, "utf-8"));
|
|
33562
33448
|
lastUpdated = data.lastUpdated || "unknown";
|
|
33563
33449
|
models = data.models || [];
|
|
@@ -33611,7 +33497,7 @@ Force update: claudish --list-models --force-update
|
|
|
33611
33497
|
`);
|
|
33612
33498
|
}
|
|
33613
33499
|
function printAvailableModelsJSON() {
|
|
33614
|
-
const jsonPath =
|
|
33500
|
+
const jsonPath = join7(__dirname5, "../recommended-models.json");
|
|
33615
33501
|
try {
|
|
33616
33502
|
const jsonContent = readFileSync6(jsonPath, "utf-8");
|
|
33617
33503
|
const data = JSON.parse(jsonContent);
|
|
@@ -33683,12 +33569,325 @@ var init_cli = __esm(() => {
|
|
|
33683
33569
|
__filename5 = fileURLToPath4(import.meta.url);
|
|
33684
33570
|
__dirname5 = dirname4(__filename5);
|
|
33685
33571
|
try {
|
|
33686
|
-
const packageJson = JSON.parse(readFileSync6(
|
|
33572
|
+
const packageJson = JSON.parse(readFileSync6(join7(__dirname5, "../package.json"), "utf-8"));
|
|
33687
33573
|
VERSION = packageJson.version;
|
|
33688
33574
|
} catch {}
|
|
33689
|
-
MODELS_JSON_PATH =
|
|
33690
|
-
CLAUDISH_CACHE_DIR3 =
|
|
33691
|
-
ALL_MODELS_JSON_PATH2 =
|
|
33575
|
+
MODELS_JSON_PATH = join7(__dirname5, "../recommended-models.json");
|
|
33576
|
+
CLAUDISH_CACHE_DIR3 = join7(homedir5(), ".claudish");
|
|
33577
|
+
ALL_MODELS_JSON_PATH2 = join7(CLAUDISH_CACHE_DIR3, "all-models.json");
|
|
33578
|
+
});
|
|
33579
|
+
|
|
33580
|
+
// src/claude-runner.ts
|
|
33581
|
+
var exports_claude_runner = {};
|
|
33582
|
+
__export(exports_claude_runner, {
|
|
33583
|
+
runClaudeWithProxy: () => runClaudeWithProxy,
|
|
33584
|
+
checkClaudeInstalled: () => checkClaudeInstalled
|
|
33585
|
+
});
|
|
33586
|
+
import { spawn } from "node:child_process";
|
|
33587
|
+
import { writeFileSync as writeFileSync6, unlinkSync as unlinkSync2, mkdirSync as mkdirSync6, existsSync as existsSync8 } from "node:fs";
|
|
33588
|
+
import { tmpdir, homedir as homedir6 } from "node:os";
|
|
33589
|
+
import { join as join8 } from "node:path";
|
|
33590
|
+
function isWindows() {
|
|
33591
|
+
return process.platform === "win32";
|
|
33592
|
+
}
|
|
33593
|
+
function createStatusLineScript(tokenFilePath) {
|
|
33594
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
|
|
33595
|
+
const claudishDir = join8(homeDir, ".claudish");
|
|
33596
|
+
const timestamp = Date.now();
|
|
33597
|
+
const scriptPath = join8(claudishDir, `status-${timestamp}.js`);
|
|
33598
|
+
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
33599
|
+
const script = `
|
|
33600
|
+
const fs = require('fs');
|
|
33601
|
+
const path = require('path');
|
|
33602
|
+
|
|
33603
|
+
const CYAN = "\\x1b[96m";
|
|
33604
|
+
const YELLOW = "\\x1b[93m";
|
|
33605
|
+
const GREEN = "\\x1b[92m";
|
|
33606
|
+
const MAGENTA = "\\x1b[95m";
|
|
33607
|
+
const DIM = "\\x1b[2m";
|
|
33608
|
+
const RESET = "\\x1b[0m";
|
|
33609
|
+
const BOLD = "\\x1b[1m";
|
|
33610
|
+
|
|
33611
|
+
// Format token count with k/M suffix
|
|
33612
|
+
function formatTokens(n) {
|
|
33613
|
+
if (n >= 1000000) return (n / 1000000).toFixed(n >= 10000000 ? 0 : 1).replace(/\\.0$/, '') + 'M';
|
|
33614
|
+
if (n >= 1000) return (n / 1000).toFixed(n >= 10000 ? 0 : 1).replace(/\\.0$/, '') + 'k';
|
|
33615
|
+
return String(n);
|
|
33616
|
+
}
|
|
33617
|
+
|
|
33618
|
+
let input = '';
|
|
33619
|
+
process.stdin.setEncoding('utf8');
|
|
33620
|
+
process.stdin.on('data', chunk => input += chunk);
|
|
33621
|
+
process.stdin.on('end', () => {
|
|
33622
|
+
try {
|
|
33623
|
+
let dir = path.basename(process.cwd());
|
|
33624
|
+
if (dir.length > 15) dir = dir.substring(0, 12) + '...';
|
|
33625
|
+
|
|
33626
|
+
let ctx = 100, cost = 0, inputTokens = 0, contextWindow = 0;
|
|
33627
|
+
const model = process.env.CLAUDISH_ACTIVE_MODEL_NAME || 'unknown';
|
|
33628
|
+
const isLocal = process.env.CLAUDISH_IS_LOCAL === 'true';
|
|
33629
|
+
|
|
33630
|
+
let isFree = false, isEstimated = false, providerName = '';
|
|
33631
|
+
try {
|
|
33632
|
+
const tokens = JSON.parse(fs.readFileSync('${escapedTokenPath}', 'utf-8'));
|
|
33633
|
+
cost = tokens.total_cost || 0;
|
|
33634
|
+
ctx = tokens.context_left_percent || 100;
|
|
33635
|
+
inputTokens = tokens.input_tokens || 0;
|
|
33636
|
+
contextWindow = tokens.context_window || 0;
|
|
33637
|
+
isFree = tokens.is_free || false;
|
|
33638
|
+
isEstimated = tokens.is_estimated || false;
|
|
33639
|
+
providerName = tokens.provider_name || '';
|
|
33640
|
+
} catch (e) {
|
|
33641
|
+
try {
|
|
33642
|
+
const json = JSON.parse(input);
|
|
33643
|
+
cost = json.total_cost_usd || 0;
|
|
33644
|
+
} catch {}
|
|
33645
|
+
}
|
|
33646
|
+
|
|
33647
|
+
let costDisplay;
|
|
33648
|
+
if (isLocal) {
|
|
33649
|
+
costDisplay = 'LOCAL';
|
|
33650
|
+
} else if (isFree) {
|
|
33651
|
+
costDisplay = 'FREE';
|
|
33652
|
+
} else if (isEstimated) {
|
|
33653
|
+
costDisplay = '~$' + cost.toFixed(3);
|
|
33654
|
+
} else {
|
|
33655
|
+
costDisplay = '$' + cost.toFixed(3);
|
|
33656
|
+
}
|
|
33657
|
+
const modelDisplay = providerName ? providerName + ' ' + model : model;
|
|
33658
|
+
// Format context display: "96% (37k/1M)" or just "96%" if no token data
|
|
33659
|
+
let ctxDisplay = ctx + '%';
|
|
33660
|
+
if (inputTokens > 0 && contextWindow > 0) {
|
|
33661
|
+
ctxDisplay = ctx + '% (' + formatTokens(inputTokens) + '/' + formatTokens(contextWindow) + ')';
|
|
33662
|
+
}
|
|
33663
|
+
console.log(\`\${CYAN}\${BOLD}\${dir}\${RESET} \${DIM}•\${RESET} \${YELLOW}\${modelDisplay}\${RESET} \${DIM}•\${RESET} \${GREEN}\${costDisplay}\${RESET} \${DIM}•\${RESET} \${MAGENTA}\${ctxDisplay}\${RESET}\`);
|
|
33664
|
+
} catch (e) {
|
|
33665
|
+
console.log('claudish');
|
|
33666
|
+
}
|
|
33667
|
+
});
|
|
33668
|
+
`;
|
|
33669
|
+
writeFileSync6(scriptPath, script, "utf-8");
|
|
33670
|
+
return scriptPath;
|
|
33671
|
+
}
|
|
33672
|
+
function createTempSettingsFile(modelDisplay, port) {
|
|
33673
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir();
|
|
33674
|
+
const claudishDir = join8(homeDir, ".claudish");
|
|
33675
|
+
try {
|
|
33676
|
+
mkdirSync6(claudishDir, { recursive: true });
|
|
33677
|
+
} catch {}
|
|
33678
|
+
const timestamp = Date.now();
|
|
33679
|
+
const tempPath = join8(claudishDir, `settings-${timestamp}.json`);
|
|
33680
|
+
const tokenFilePath = join8(claudishDir, `tokens-${port}.json`);
|
|
33681
|
+
let statusCommand;
|
|
33682
|
+
if (isWindows()) {
|
|
33683
|
+
const scriptPath = createStatusLineScript(tokenFilePath);
|
|
33684
|
+
statusCommand = `node "${scriptPath}"`;
|
|
33685
|
+
} else {
|
|
33686
|
+
const CYAN2 = "\\033[96m";
|
|
33687
|
+
const YELLOW2 = "\\033[93m";
|
|
33688
|
+
const GREEN2 = "\\033[92m";
|
|
33689
|
+
const MAGENTA = "\\033[95m";
|
|
33690
|
+
const DIM2 = "\\033[2m";
|
|
33691
|
+
const RESET2 = "\\033[0m";
|
|
33692
|
+
const BOLD2 = "\\033[1m";
|
|
33693
|
+
const formatTokensBash = `fmt_tok() { local n=\${1:-0}; if [ "$n" -ge 1000000 ]; then echo "$((n/1000000))M"; elif [ "$n" -ge 1000 ]; then echo "$((n/1000))k"; else echo "$n"; fi; }`;
|
|
33694
|
+
statusCommand = `JSON=$(cat) && DIR=$(basename "$(pwd)") && [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true && CTX=100 && COST="0" && IS_FREE="false" && IS_EST="false" && PROVIDER="" && IN_TOK=0 && CTX_WIN=0 && ${formatTokensBash} && if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d ' \\n') && REAL_CTX=$(echo "$TOKENS" | grep -o '"context_left_percent":[0-9]*' | grep -o '[0-9]*') && if [ ! -z "$REAL_CTX" ]; then CTX="$REAL_CTX"; fi && REAL_COST=$(echo "$TOKENS" | grep -o '"total_cost":[0-9.]*' | cut -d: -f2) && if [ ! -z "$REAL_COST" ]; then COST="$REAL_COST"; fi && IN_TOK=$(echo "$TOKENS" | grep -o '"input_tokens":[0-9]*' | grep -o '[0-9]*') && CTX_WIN=$(echo "$TOKENS" | grep -o '"context_window":[0-9]*' | grep -o '[0-9]*') && IS_FREE=$(echo "$TOKENS" | grep -o '"is_free":[a-z]*' | cut -d: -f2) && IS_EST=$(echo "$TOKENS" | grep -o '"is_estimated":[a-z]*' | cut -d: -f2) && PROVIDER=$(echo "$TOKENS" | grep -o '"provider_name":"[^"]*"' | cut -d'"' -f4); fi && if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi && MODEL_DISPLAY="$CLAUDISH_ACTIVE_MODEL_NAME" && if [ ! -z "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi && if [ "$IN_TOK" -gt 0 ] 2>/dev/null && [ "$CTX_WIN" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX%"; fi && printf "${CYAN2}${BOLD2}%s${RESET2} ${DIM2}•${RESET2} ${YELLOW2}%s${RESET2} ${DIM2}•${RESET2} ${GREEN2}%s${RESET2} ${DIM2}•${RESET2} ${MAGENTA}%s${RESET2}\\n" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"`;
|
|
33695
|
+
}
|
|
33696
|
+
const settings = {
|
|
33697
|
+
statusLine: {
|
|
33698
|
+
type: "command",
|
|
33699
|
+
command: statusCommand,
|
|
33700
|
+
padding: 0
|
|
33701
|
+
}
|
|
33702
|
+
};
|
|
33703
|
+
writeFileSync6(tempPath, JSON.stringify(settings, null, 2), "utf-8");
|
|
33704
|
+
return tempPath;
|
|
33705
|
+
}
|
|
33706
|
+
async function runClaudeWithProxy(config3, proxyUrl) {
|
|
33707
|
+
const modelId = config3.model || "unknown";
|
|
33708
|
+
const portMatch = proxyUrl.match(/:(\d+)/);
|
|
33709
|
+
const port = portMatch ? portMatch[1] : "unknown";
|
|
33710
|
+
const tempSettingsPath = createTempSettingsFile(modelId, port);
|
|
33711
|
+
const claudeArgs = [];
|
|
33712
|
+
claudeArgs.push("--settings", tempSettingsPath);
|
|
33713
|
+
if (config3.interactive) {
|
|
33714
|
+
if (config3.autoApprove) {
|
|
33715
|
+
claudeArgs.push("--dangerously-skip-permissions");
|
|
33716
|
+
}
|
|
33717
|
+
if (config3.dangerous) {
|
|
33718
|
+
claudeArgs.push("--dangerouslyDisableSandbox");
|
|
33719
|
+
}
|
|
33720
|
+
} else {
|
|
33721
|
+
claudeArgs.push("-p");
|
|
33722
|
+
if (config3.autoApprove) {
|
|
33723
|
+
claudeArgs.push("--dangerously-skip-permissions");
|
|
33724
|
+
}
|
|
33725
|
+
if (config3.dangerous) {
|
|
33726
|
+
claudeArgs.push("--dangerouslyDisableSandbox");
|
|
33727
|
+
}
|
|
33728
|
+
if (config3.jsonOutput) {
|
|
33729
|
+
claudeArgs.push("--output-format", "json");
|
|
33730
|
+
}
|
|
33731
|
+
if (config3.agent && config3.claudeArgs.length > 0) {
|
|
33732
|
+
const modifiedArgs = [...config3.claudeArgs];
|
|
33733
|
+
const agentId = config3.agent.startsWith("@agent-") ? config3.agent : `@agent-${config3.agent}`;
|
|
33734
|
+
modifiedArgs[0] = `Use the ${agentId} agent to: ${modifiedArgs[0]}`;
|
|
33735
|
+
claudeArgs.push(...modifiedArgs);
|
|
33736
|
+
} else {
|
|
33737
|
+
claudeArgs.push(...config3.claudeArgs);
|
|
33738
|
+
}
|
|
33739
|
+
}
|
|
33740
|
+
const isLocalModel2 = modelId.startsWith("ollama/") || modelId.startsWith("ollama:") || modelId.startsWith("lmstudio/") || modelId.startsWith("lmstudio:") || modelId.startsWith("vllm/") || modelId.startsWith("vllm:") || modelId.startsWith("mlx/") || modelId.startsWith("mlx:") || modelId.startsWith("http://") || modelId.startsWith("https://");
|
|
33741
|
+
const env = {
|
|
33742
|
+
...process.env,
|
|
33743
|
+
ANTHROPIC_BASE_URL: proxyUrl,
|
|
33744
|
+
[ENV.CLAUDISH_ACTIVE_MODEL_NAME]: modelId,
|
|
33745
|
+
CLAUDISH_IS_LOCAL: isLocalModel2 ? "true" : "false"
|
|
33746
|
+
};
|
|
33747
|
+
if (config3.monitor) {
|
|
33748
|
+
delete env.ANTHROPIC_API_KEY;
|
|
33749
|
+
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
33750
|
+
if (modelId && modelId !== "unknown") {
|
|
33751
|
+
env[ENV.ANTHROPIC_MODEL] = modelId;
|
|
33752
|
+
env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
|
|
33753
|
+
}
|
|
33754
|
+
} else {
|
|
33755
|
+
env[ENV.ANTHROPIC_MODEL] = modelId;
|
|
33756
|
+
env[ENV.ANTHROPIC_SMALL_FAST_MODEL] = modelId;
|
|
33757
|
+
env.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY || "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx";
|
|
33758
|
+
env.ANTHROPIC_AUTH_TOKEN = process.env.ANTHROPIC_AUTH_TOKEN || "placeholder-token-not-used-proxy-handles-auth";
|
|
33759
|
+
}
|
|
33760
|
+
const log2 = (message) => {
|
|
33761
|
+
if (!config3.quiet) {
|
|
33762
|
+
console.log(message);
|
|
33763
|
+
}
|
|
33764
|
+
};
|
|
33765
|
+
if (config3.interactive) {
|
|
33766
|
+
log2(`
|
|
33767
|
+
[claudish] Model: ${modelId}
|
|
33768
|
+
`);
|
|
33769
|
+
} else {
|
|
33770
|
+
log2(`
|
|
33771
|
+
[claudish] Model: ${modelId}`);
|
|
33772
|
+
log2(`[claudish] Arguments: ${claudeArgs.join(" ")}
|
|
33773
|
+
`);
|
|
33774
|
+
}
|
|
33775
|
+
const claudeBinary = await findClaudeBinary();
|
|
33776
|
+
if (!claudeBinary) {
|
|
33777
|
+
console.error("Error: Claude Code CLI not found");
|
|
33778
|
+
console.error("Install it from: https://claude.com/claude-code");
|
|
33779
|
+
console.error(`
|
|
33780
|
+
Or set CLAUDE_PATH to your custom installation:`);
|
|
33781
|
+
const home = homedir6();
|
|
33782
|
+
const localPath = isWindows() ? join8(home, ".claude", "local", "claude.exe") : join8(home, ".claude", "local", "claude");
|
|
33783
|
+
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
33784
|
+
process.exit(1);
|
|
33785
|
+
}
|
|
33786
|
+
const proc = spawn(claudeBinary, claudeArgs, {
|
|
33787
|
+
env,
|
|
33788
|
+
stdio: "inherit",
|
|
33789
|
+
shell: false
|
|
33790
|
+
});
|
|
33791
|
+
setupSignalHandlers(proc, tempSettingsPath, config3.quiet);
|
|
33792
|
+
const exitCode = await new Promise((resolve) => {
|
|
33793
|
+
proc.on("exit", (code) => {
|
|
33794
|
+
resolve(code ?? 1);
|
|
33795
|
+
});
|
|
33796
|
+
});
|
|
33797
|
+
try {
|
|
33798
|
+
unlinkSync2(tempSettingsPath);
|
|
33799
|
+
} catch (error46) {}
|
|
33800
|
+
return exitCode;
|
|
33801
|
+
}
|
|
33802
|
+
function setupSignalHandlers(proc, tempSettingsPath, quiet) {
|
|
33803
|
+
const signals2 = isWindows() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
|
|
33804
|
+
for (const signal of signals2) {
|
|
33805
|
+
process.on(signal, () => {
|
|
33806
|
+
if (!quiet) {
|
|
33807
|
+
console.log(`
|
|
33808
|
+
[claudish] Received ${signal}, shutting down...`);
|
|
33809
|
+
}
|
|
33810
|
+
proc.kill();
|
|
33811
|
+
try {
|
|
33812
|
+
unlinkSync2(tempSettingsPath);
|
|
33813
|
+
} catch {}
|
|
33814
|
+
process.exit(0);
|
|
33815
|
+
});
|
|
33816
|
+
}
|
|
33817
|
+
}
|
|
33818
|
+
async function findClaudeBinary() {
|
|
33819
|
+
const isWindows2 = process.platform === "win32";
|
|
33820
|
+
if (process.env.CLAUDE_PATH) {
|
|
33821
|
+
if (existsSync8(process.env.CLAUDE_PATH)) {
|
|
33822
|
+
return process.env.CLAUDE_PATH;
|
|
33823
|
+
}
|
|
33824
|
+
}
|
|
33825
|
+
const home = homedir6();
|
|
33826
|
+
const localPath = isWindows2 ? join8(home, ".claude", "local", "claude.exe") : join8(home, ".claude", "local", "claude");
|
|
33827
|
+
if (existsSync8(localPath)) {
|
|
33828
|
+
return localPath;
|
|
33829
|
+
}
|
|
33830
|
+
if (isWindows2) {
|
|
33831
|
+
const windowsPaths = [
|
|
33832
|
+
join8(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
33833
|
+
join8(home, ".npm-global", "claude.cmd"),
|
|
33834
|
+
join8(home, "node_modules", ".bin", "claude.cmd")
|
|
33835
|
+
];
|
|
33836
|
+
for (const path of windowsPaths) {
|
|
33837
|
+
if (existsSync8(path)) {
|
|
33838
|
+
return path;
|
|
33839
|
+
}
|
|
33840
|
+
}
|
|
33841
|
+
} else {
|
|
33842
|
+
const commonPaths = [
|
|
33843
|
+
"/usr/local/bin/claude",
|
|
33844
|
+
"/opt/homebrew/bin/claude",
|
|
33845
|
+
join8(home, ".npm-global/bin/claude"),
|
|
33846
|
+
join8(home, ".local/bin/claude"),
|
|
33847
|
+
join8(home, "node_modules/.bin/claude"),
|
|
33848
|
+
"/data/data/com.termux/files/usr/bin/claude",
|
|
33849
|
+
join8(home, "../usr/bin/claude")
|
|
33850
|
+
];
|
|
33851
|
+
for (const path of commonPaths) {
|
|
33852
|
+
if (existsSync8(path)) {
|
|
33853
|
+
return path;
|
|
33854
|
+
}
|
|
33855
|
+
}
|
|
33856
|
+
}
|
|
33857
|
+
try {
|
|
33858
|
+
const shellCommand = isWindows2 ? "where claude" : "command -v claude";
|
|
33859
|
+
const proc = spawn(shellCommand, [], {
|
|
33860
|
+
stdio: "pipe",
|
|
33861
|
+
shell: true
|
|
33862
|
+
});
|
|
33863
|
+
let output = "";
|
|
33864
|
+
proc.stdout?.on("data", (data) => {
|
|
33865
|
+
output += data.toString();
|
|
33866
|
+
});
|
|
33867
|
+
const exitCode = await new Promise((resolve) => {
|
|
33868
|
+
proc.on("exit", (code) => {
|
|
33869
|
+
resolve(code ?? 1);
|
|
33870
|
+
});
|
|
33871
|
+
});
|
|
33872
|
+
if (exitCode === 0 && output.trim()) {
|
|
33873
|
+
const lines = output.trim().split(/\r?\n/);
|
|
33874
|
+
if (isWindows2) {
|
|
33875
|
+
const cmdPath = lines.find((line) => line.endsWith(".cmd"));
|
|
33876
|
+
if (cmdPath) {
|
|
33877
|
+
return cmdPath;
|
|
33878
|
+
}
|
|
33879
|
+
}
|
|
33880
|
+
return lines[0];
|
|
33881
|
+
}
|
|
33882
|
+
} catch {}
|
|
33883
|
+
return null;
|
|
33884
|
+
}
|
|
33885
|
+
async function checkClaudeInstalled() {
|
|
33886
|
+
const binary = await findClaudeBinary();
|
|
33887
|
+
return binary !== null;
|
|
33888
|
+
}
|
|
33889
|
+
var init_claude_runner = __esm(() => {
|
|
33890
|
+
init_config();
|
|
33692
33891
|
});
|
|
33693
33892
|
|
|
33694
33893
|
// src/port-manager.ts
|
|
@@ -60948,6 +61147,12 @@ class OpenAIHandler {
|
|
|
60948
61147
|
this.contextWindow = 131072;
|
|
60949
61148
|
} else if (model.includes("grok")) {
|
|
60950
61149
|
this.contextWindow = 131072;
|
|
61150
|
+
} else if (model.includes("kimi-k2.5") || model.includes("kimi-k2-5")) {
|
|
61151
|
+
this.contextWindow = 262144;
|
|
61152
|
+
} else if (model.includes("kimi-k2")) {
|
|
61153
|
+
this.contextWindow = 262144;
|
|
61154
|
+
} else if (model.includes("kimi")) {
|
|
61155
|
+
this.contextWindow = 131072;
|
|
60951
61156
|
} else if (model.includes("gpt-4o") || model.includes("gpt-4-turbo")) {
|
|
60952
61157
|
this.contextWindow = 128000;
|
|
60953
61158
|
} else if (model.includes("gpt-5")) {
|
|
@@ -60978,6 +61183,8 @@ class OpenAIHandler {
|
|
|
60978
61183
|
return "Zen";
|
|
60979
61184
|
if (name === "glm")
|
|
60980
61185
|
return "GLM";
|
|
61186
|
+
if (name === "openai")
|
|
61187
|
+
return "OpenAI";
|
|
60981
61188
|
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
60982
61189
|
};
|
|
60983
61190
|
const pricing = this.getPricing();
|
|
@@ -61187,7 +61394,7 @@ class OpenAIHandler {
|
|
|
61187
61394
|
}
|
|
61188
61395
|
return payload;
|
|
61189
61396
|
}
|
|
61190
|
-
async handleResponsesStreaming(c, response, _adapter, _claudeRequest) {
|
|
61397
|
+
async handleResponsesStreaming(c, response, _adapter, _claudeRequest, toolNameMap) {
|
|
61191
61398
|
const reader = response.body?.getReader();
|
|
61192
61399
|
if (!reader) {
|
|
61193
61400
|
return c.json({ error: "No response body" }, 500);
|
|
@@ -61283,7 +61490,8 @@ data: ${JSON.stringify(data)}
|
|
|
61283
61490
|
const itemId = event.item.id;
|
|
61284
61491
|
const openaiCallId = event.item.call_id || itemId;
|
|
61285
61492
|
const callId = openaiCallId.startsWith("toolu_") ? openaiCallId : `toolu_${openaiCallId.replace(/^fc_/, "")}`;
|
|
61286
|
-
const
|
|
61493
|
+
const rawFnName = event.item.name || "";
|
|
61494
|
+
const fnName = toolNameMap?.get(rawFnName) || rawFnName;
|
|
61287
61495
|
const fnIndex = blockIndex + functionCalls.size + (hasTextContent ? 1 : 0);
|
|
61288
61496
|
log(`[OpenAIHandler] Function call: itemId=${itemId}, openaiCallId=${openaiCallId}, claudeId=${callId}, name=${fnName}, index=${fnIndex}`);
|
|
61289
61497
|
const fnCallData = {
|
|
@@ -61524,6 +61732,7 @@ data: ${JSON.stringify(data)}
|
|
|
61524
61732
|
if (typeof adapter.reset === "function")
|
|
61525
61733
|
adapter.reset();
|
|
61526
61734
|
adapter.prepareRequest(apiPayload, claudeRequest);
|
|
61735
|
+
const toolNameMap = adapter.getToolNameMap();
|
|
61527
61736
|
await this.middlewareManager.beforeRequest({
|
|
61528
61737
|
modelId: `openai/${this.modelName}`,
|
|
61529
61738
|
messages,
|
|
@@ -61586,9 +61795,9 @@ data: ${JSON.stringify(data)}
|
|
|
61586
61795
|
}
|
|
61587
61796
|
if (isCodex) {
|
|
61588
61797
|
log(`[OpenAIHandler] Using Responses API streaming handler for Codex model`);
|
|
61589
|
-
return this.handleResponsesStreaming(c, response, adapter, claudeRequest);
|
|
61798
|
+
return this.handleResponsesStreaming(c, response, adapter, claudeRequest, toolNameMap);
|
|
61590
61799
|
}
|
|
61591
|
-
return createStreamingResponseHandler(c, response, adapter, `openai/${this.modelName}`, this.middlewareManager, (input, output) => this.updateTokenTracking(input, output), claudeRequest.tools);
|
|
61800
|
+
return createStreamingResponseHandler(c, response, adapter, `openai/${this.modelName}`, this.middlewareManager, (input, output) => this.updateTokenTracking(input, output), claudeRequest.tools, toolNameMap);
|
|
61592
61801
|
}
|
|
61593
61802
|
async shutdown() {}
|
|
61594
61803
|
}
|
|
@@ -64262,6 +64471,9 @@ var args = process.argv.slice(2);
|
|
|
64262
64471
|
var firstArg = args[0];
|
|
64263
64472
|
var isGeminiLogin = args.includes("--gemini-login");
|
|
64264
64473
|
var isGeminiLogout = args.includes("--gemini-logout");
|
|
64474
|
+
var isUpdateCommand = args.includes("update");
|
|
64475
|
+
var isInitCommand = args[0] === "init" || args.includes("init");
|
|
64476
|
+
var isProfileCommand = args[0] === "profile" || args.some((a, i) => a === "profile" && (i === 0 || !args[i - 1]?.startsWith("-")));
|
|
64265
64477
|
if (isMcpMode) {
|
|
64266
64478
|
Promise.resolve().then(() => (init_mcp_server(), exports_mcp_server)).then((mcp) => mcp.startMcpServer());
|
|
64267
64479
|
} else if (isGeminiLogin) {
|
|
@@ -64291,13 +64503,75 @@ if (isMcpMode) {
|
|
|
64291
64503
|
process.exit(1);
|
|
64292
64504
|
}
|
|
64293
64505
|
});
|
|
64294
|
-
} else if (
|
|
64506
|
+
} else if (isUpdateCommand) {
|
|
64507
|
+
runSelfUpdate();
|
|
64508
|
+
} else if (isInitCommand) {
|
|
64295
64509
|
Promise.resolve().then(() => (init_profile_commands(), exports_profile_commands)).then((pc) => pc.initCommand());
|
|
64296
|
-
} else if (
|
|
64297
|
-
|
|
64510
|
+
} else if (isProfileCommand) {
|
|
64511
|
+
const profileArgIndex = args.findIndex((a) => a === "profile");
|
|
64512
|
+
Promise.resolve().then(() => (init_profile_commands(), exports_profile_commands)).then((pc) => pc.profileCommand(args.slice(profileArgIndex + 1)));
|
|
64298
64513
|
} else {
|
|
64299
64514
|
runCli();
|
|
64300
64515
|
}
|
|
64516
|
+
function detectInstallMethod() {
|
|
64517
|
+
const scriptPath = process.argv[1] || "";
|
|
64518
|
+
if (scriptPath.includes("/.bun/")) {
|
|
64519
|
+
return "bun";
|
|
64520
|
+
}
|
|
64521
|
+
if (scriptPath.includes("/Cellar/") || scriptPath.includes("/homebrew/")) {
|
|
64522
|
+
return "brew";
|
|
64523
|
+
}
|
|
64524
|
+
if (scriptPath.includes("/node_modules/") || scriptPath.includes("/.nvm/") || scriptPath.includes("/npm/")) {
|
|
64525
|
+
return "npm";
|
|
64526
|
+
}
|
|
64527
|
+
return "unknown";
|
|
64528
|
+
}
|
|
64529
|
+
function getUpdateCommand2(method) {
|
|
64530
|
+
switch (method) {
|
|
64531
|
+
case "bun":
|
|
64532
|
+
return "bun install -g claudish@latest";
|
|
64533
|
+
case "brew":
|
|
64534
|
+
return "brew upgrade claudish";
|
|
64535
|
+
case "npm":
|
|
64536
|
+
default:
|
|
64537
|
+
return "npm install -g claudish@latest";
|
|
64538
|
+
}
|
|
64539
|
+
}
|
|
64540
|
+
async function runSelfUpdate() {
|
|
64541
|
+
const { getVersion: getVersion2 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
|
|
64542
|
+
const currentVersion = getVersion2();
|
|
64543
|
+
const installMethod = detectInstallMethod();
|
|
64544
|
+
console.log(`claudish v${currentVersion}`);
|
|
64545
|
+
console.log(`Installation: ${installMethod}`);
|
|
64546
|
+
console.log(`
|
|
64547
|
+
Checking for updates...
|
|
64548
|
+
`);
|
|
64549
|
+
try {
|
|
64550
|
+
const response = await fetch("https://registry.npmjs.org/claudish/latest", {
|
|
64551
|
+
signal: AbortSignal.timeout(5000)
|
|
64552
|
+
});
|
|
64553
|
+
if (!response.ok) {
|
|
64554
|
+
console.error("Failed to check for updates");
|
|
64555
|
+
process.exit(1);
|
|
64556
|
+
}
|
|
64557
|
+
const data = await response.json();
|
|
64558
|
+
const latestVersion = data.version;
|
|
64559
|
+
if (latestVersion === currentVersion) {
|
|
64560
|
+
console.log(`✓ claudish is up to date (v${currentVersion})`);
|
|
64561
|
+
process.exit(0);
|
|
64562
|
+
}
|
|
64563
|
+
console.log(`New version available: v${currentVersion} → v${latestVersion}
|
|
64564
|
+
`);
|
|
64565
|
+
const updateCmd = getUpdateCommand2(installMethod);
|
|
64566
|
+
console.log(`To update, run:
|
|
64567
|
+
${updateCmd}
|
|
64568
|
+
`);
|
|
64569
|
+
process.exit(0);
|
|
64570
|
+
} catch (error46) {
|
|
64571
|
+
console.error("Failed to check for updates:", error46 instanceof Error ? error46.message : error46);
|
|
64572
|
+
process.exit(1);
|
|
64573
|
+
}
|
|
64574
|
+
}
|
|
64301
64575
|
async function runCli() {
|
|
64302
64576
|
const { checkClaudeInstalled: checkClaudeInstalled2, runClaudeWithProxy: runClaudeWithProxy2 } = await Promise.resolve().then(() => (init_claude_runner(), exports_claude_runner));
|
|
64303
64577
|
const { parseArgs: parseArgs2, getVersion: getVersion2 } = await Promise.resolve().then(() => (init_cli(), exports_cli));
|