claudish 9.0.9 → 9.1.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 +339 -190
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -715,7 +715,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
715
715
|
});
|
|
716
716
|
|
|
717
717
|
// src/version.ts
|
|
718
|
-
var VERSION = "9.0
|
|
718
|
+
var VERSION = "9.1.0";
|
|
719
719
|
|
|
720
720
|
// src/logger.ts
|
|
721
721
|
import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -56013,25 +56013,214 @@ var init_api_key_map = __esm(() => {
|
|
|
56013
56013
|
};
|
|
56014
56014
|
});
|
|
56015
56015
|
|
|
56016
|
+
// src/branding.ts
|
|
56017
|
+
function paint(line) {
|
|
56018
|
+
const { RESET, BOLD, CYAN, BLUE, DIM } = cliAnsi();
|
|
56019
|
+
if (!CYAN && !BLUE)
|
|
56020
|
+
return line;
|
|
56021
|
+
return line.replace(/\u2588+/g, (run) => `${BOLD}${CYAN}${run}${RESET}`).replace(/[\u2557\u255D\u2551\u2550\u2554\u255A]+/g, (run) => `${DIM}${BLUE}${run}${RESET}`);
|
|
56022
|
+
}
|
|
56023
|
+
function fitsWordmark(stream) {
|
|
56024
|
+
if (process.env.TERM === "dumb")
|
|
56025
|
+
return false;
|
|
56026
|
+
const columns = stream.columns ?? 0;
|
|
56027
|
+
return columns >= MIN_LOGO_WIDTH;
|
|
56028
|
+
}
|
|
56029
|
+
function wordmarkLines() {
|
|
56030
|
+
return WORDMARK.map((line) => ` ${paint(line)}`);
|
|
56031
|
+
}
|
|
56032
|
+
function compactLogo() {
|
|
56033
|
+
const { RESET, BOLD, CYAN, DIM } = cliAnsi();
|
|
56034
|
+
return ` ${BOLD}${CYAN}claudish${RESET} ${DIM}\xB7${RESET} ${TAGLINE}`;
|
|
56035
|
+
}
|
|
56036
|
+
function printLogo(stream, options = {}) {
|
|
56037
|
+
const { version, trailingBlankLine = true } = options;
|
|
56038
|
+
const { RESET, BOLD, DIM, GRAY } = cliAnsi();
|
|
56039
|
+
stream.write(`
|
|
56040
|
+
`);
|
|
56041
|
+
if (fitsWordmark(stream)) {
|
|
56042
|
+
for (const line of wordmarkLines())
|
|
56043
|
+
stream.write(`${line}
|
|
56044
|
+
`);
|
|
56045
|
+
stream.write(`
|
|
56046
|
+
${GRAY}${TAGLINE}${RESET}
|
|
56047
|
+
`);
|
|
56048
|
+
} else {
|
|
56049
|
+
stream.write(`${compactLogo()}
|
|
56050
|
+
`);
|
|
56051
|
+
}
|
|
56052
|
+
if (version) {
|
|
56053
|
+
stream.write(` ${DIM}claudish version${RESET} ${BOLD}${version}${RESET}
|
|
56054
|
+
`);
|
|
56055
|
+
}
|
|
56056
|
+
if (trailingBlankLine)
|
|
56057
|
+
stream.write(`
|
|
56058
|
+
`);
|
|
56059
|
+
}
|
|
56060
|
+
var MIN_LOGO_WIDTH = 64, TAGLINE = "Claude Code. Any Model.", WORDMARK;
|
|
56061
|
+
var init_branding = __esm(() => {
|
|
56062
|
+
init_ansi();
|
|
56063
|
+
WORDMARK = [
|
|
56064
|
+
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557",
|
|
56065
|
+
"\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
56066
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551",
|
|
56067
|
+
"\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u255A\u2550\u2550\u2550\u2550\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551",
|
|
56068
|
+
"\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551",
|
|
56069
|
+
" \u255A\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"
|
|
56070
|
+
];
|
|
56071
|
+
});
|
|
56072
|
+
|
|
56073
|
+
// src/update-checker.ts
|
|
56074
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync16, readFileSync as readFileSync28, unlinkSync as unlinkSync7, writeFileSync as writeFileSync17 } from "fs";
|
|
56075
|
+
import { homedir as homedir33, platform as platform2, tmpdir } from "os";
|
|
56076
|
+
import { join as join38 } from "path";
|
|
56077
|
+
function getCacheFilePath() {
|
|
56078
|
+
let cacheDir;
|
|
56079
|
+
if (isWindows) {
|
|
56080
|
+
const localAppData = process.env.LOCALAPPDATA || join38(homedir33(), "AppData", "Local");
|
|
56081
|
+
cacheDir = join38(localAppData, "claudish");
|
|
56082
|
+
} else {
|
|
56083
|
+
cacheDir = join38(homedir33(), ".cache", "claudish");
|
|
56084
|
+
}
|
|
56085
|
+
try {
|
|
56086
|
+
if (!existsSync28(cacheDir)) {
|
|
56087
|
+
mkdirSync16(cacheDir, { recursive: true });
|
|
56088
|
+
}
|
|
56089
|
+
return join38(cacheDir, "update-check.json");
|
|
56090
|
+
} catch {
|
|
56091
|
+
return join38(tmpdir(), "claudish-update-check.json");
|
|
56092
|
+
}
|
|
56093
|
+
}
|
|
56094
|
+
function readCache() {
|
|
56095
|
+
try {
|
|
56096
|
+
const cachePath = getCacheFilePath();
|
|
56097
|
+
if (!existsSync28(cachePath)) {
|
|
56098
|
+
return null;
|
|
56099
|
+
}
|
|
56100
|
+
const data = JSON.parse(readFileSync28(cachePath, "utf-8"));
|
|
56101
|
+
return data;
|
|
56102
|
+
} catch {
|
|
56103
|
+
return null;
|
|
56104
|
+
}
|
|
56105
|
+
}
|
|
56106
|
+
function writeCache(latestVersion) {
|
|
56107
|
+
try {
|
|
56108
|
+
const cachePath = getCacheFilePath();
|
|
56109
|
+
const data = {
|
|
56110
|
+
lastCheck: Date.now(),
|
|
56111
|
+
latestVersion
|
|
56112
|
+
};
|
|
56113
|
+
writeFileSync17(cachePath, JSON.stringify(data), "utf-8");
|
|
56114
|
+
} catch {}
|
|
56115
|
+
}
|
|
56116
|
+
function isCacheValid(cache) {
|
|
56117
|
+
const age = Date.now() - cache.lastCheck;
|
|
56118
|
+
return age < CACHE_MAX_AGE_MS;
|
|
56119
|
+
}
|
|
56120
|
+
function clearCache() {
|
|
56121
|
+
try {
|
|
56122
|
+
const cachePath = getCacheFilePath();
|
|
56123
|
+
if (existsSync28(cachePath)) {
|
|
56124
|
+
unlinkSync7(cachePath);
|
|
56125
|
+
}
|
|
56126
|
+
} catch {}
|
|
56127
|
+
}
|
|
56128
|
+
function compareVersions(v1, v2) {
|
|
56129
|
+
const parts1 = v1.replace(/^v/, "").split(".").map(Number);
|
|
56130
|
+
const parts2 = v2.replace(/^v/, "").split(".").map(Number);
|
|
56131
|
+
for (let i = 0;i < Math.max(parts1.length, parts2.length); i++) {
|
|
56132
|
+
const p1 = parts1[i] || 0;
|
|
56133
|
+
const p2 = parts2[i] || 0;
|
|
56134
|
+
if (p1 > p2)
|
|
56135
|
+
return 1;
|
|
56136
|
+
if (p1 < p2)
|
|
56137
|
+
return -1;
|
|
56138
|
+
}
|
|
56139
|
+
return 0;
|
|
56140
|
+
}
|
|
56141
|
+
async function fetchLatestVersionOrThrow(options = {}) {
|
|
56142
|
+
const { timeoutMs = 5000, retries = 0 } = options;
|
|
56143
|
+
let lastError = new Error("unknown error");
|
|
56144
|
+
for (let attempt = 0;attempt <= retries; attempt++) {
|
|
56145
|
+
const controller = new AbortController;
|
|
56146
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
56147
|
+
try {
|
|
56148
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
56149
|
+
signal: controller.signal,
|
|
56150
|
+
headers: { Accept: "application/json" }
|
|
56151
|
+
});
|
|
56152
|
+
if (!response.ok) {
|
|
56153
|
+
throw new Error(`npm registry returned HTTP ${response.status}`);
|
|
56154
|
+
}
|
|
56155
|
+
const data = await response.json();
|
|
56156
|
+
if (!data.version) {
|
|
56157
|
+
throw new Error("npm registry response contained no version field");
|
|
56158
|
+
}
|
|
56159
|
+
return data.version;
|
|
56160
|
+
} catch (error) {
|
|
56161
|
+
lastError = error instanceof Error && error.name === "AbortError" ? new Error(`request timed out after ${timeoutMs}ms`) : error instanceof Error ? error : new Error(String(error));
|
|
56162
|
+
if (attempt < retries) {
|
|
56163
|
+
await new Promise((resolve) => setTimeout(resolve, 300 * (attempt + 1)));
|
|
56164
|
+
}
|
|
56165
|
+
} finally {
|
|
56166
|
+
clearTimeout(timeout);
|
|
56167
|
+
}
|
|
56168
|
+
}
|
|
56169
|
+
throw lastError;
|
|
56170
|
+
}
|
|
56171
|
+
async function fetchLatestVersion(options = {}) {
|
|
56172
|
+
try {
|
|
56173
|
+
return await fetchLatestVersionOrThrow(options);
|
|
56174
|
+
} catch {
|
|
56175
|
+
return null;
|
|
56176
|
+
}
|
|
56177
|
+
}
|
|
56178
|
+
async function getLatestVersionCached(options = {}) {
|
|
56179
|
+
const cache = readCache();
|
|
56180
|
+
if (cache && isCacheValid(cache)) {
|
|
56181
|
+
return cache.latestVersion;
|
|
56182
|
+
}
|
|
56183
|
+
const latestVersion = await fetchLatestVersion(options);
|
|
56184
|
+
writeCache(latestVersion);
|
|
56185
|
+
return latestVersion;
|
|
56186
|
+
}
|
|
56187
|
+
function isUpgrade(latestVersion, currentVersion) {
|
|
56188
|
+
if (!latestVersion)
|
|
56189
|
+
return false;
|
|
56190
|
+
return compareVersions(latestVersion, currentVersion) > 0;
|
|
56191
|
+
}
|
|
56192
|
+
function formatUpdateNotice(currentVersion, latestVersion, options = {}) {
|
|
56193
|
+
const { hint = true } = options;
|
|
56194
|
+
const { RESET, BOLD, GREEN, CYAN, DIM } = cliAnsi();
|
|
56195
|
+
const runHint = hint ? ` ${DIM}Run:${RESET} ${BOLD}${CYAN}claudish update${RESET}` : "";
|
|
56196
|
+
return ` ${CYAN}\u250C${RESET} ${BOLD}Update available:${RESET} ${currentVersion} ${DIM}\u2192${RESET} ${GREEN}${latestVersion}${RESET}${runHint}`;
|
|
56197
|
+
}
|
|
56198
|
+
var isWindows, NPM_REGISTRY_URL = "https://registry.npmjs.org/claudish/latest", CACHE_MAX_AGE_MS;
|
|
56199
|
+
var init_update_checker = __esm(() => {
|
|
56200
|
+
init_ansi();
|
|
56201
|
+
isWindows = platform2() === "win32";
|
|
56202
|
+
CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
56203
|
+
});
|
|
56204
|
+
|
|
56016
56205
|
// src/cli.ts
|
|
56017
56206
|
import {
|
|
56018
56207
|
copyFileSync as copyFileSync2,
|
|
56019
|
-
existsSync as
|
|
56020
|
-
mkdirSync as
|
|
56021
|
-
readFileSync as
|
|
56208
|
+
existsSync as existsSync29,
|
|
56209
|
+
mkdirSync as mkdirSync17,
|
|
56210
|
+
readFileSync as readFileSync29,
|
|
56022
56211
|
readdirSync as readdirSync7,
|
|
56023
|
-
unlinkSync as
|
|
56024
|
-
writeFileSync as
|
|
56212
|
+
unlinkSync as unlinkSync8,
|
|
56213
|
+
writeFileSync as writeFileSync18
|
|
56025
56214
|
} from "fs";
|
|
56026
|
-
import { homedir as
|
|
56027
|
-
import { dirname as dirname11, join as
|
|
56215
|
+
import { homedir as homedir34 } from "os";
|
|
56216
|
+
import { dirname as dirname11, join as join39 } from "path";
|
|
56028
56217
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
56029
56218
|
function getVersion3() {
|
|
56030
56219
|
return VERSION;
|
|
56031
56220
|
}
|
|
56032
56221
|
function clearAllModelCaches() {
|
|
56033
|
-
const cacheDir =
|
|
56034
|
-
if (!
|
|
56222
|
+
const cacheDir = join39(homedir34(), ".claudish");
|
|
56223
|
+
if (!existsSync29(cacheDir))
|
|
56035
56224
|
return;
|
|
56036
56225
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
56037
56226
|
let cleared = 0;
|
|
@@ -56039,7 +56228,7 @@ function clearAllModelCaches() {
|
|
|
56039
56228
|
const files = readdirSync7(cacheDir);
|
|
56040
56229
|
for (const file of files) {
|
|
56041
56230
|
if (cachePatterns.includes(file)) {
|
|
56042
|
-
|
|
56231
|
+
unlinkSync8(join39(cacheDir, file));
|
|
56043
56232
|
cleared++;
|
|
56044
56233
|
}
|
|
56045
56234
|
}
|
|
@@ -56310,7 +56499,7 @@ async function parseArgs(args) {
|
|
|
56310
56499
|
} else if (arg === "--cost-reset") {
|
|
56311
56500
|
config.resetCosts = true;
|
|
56312
56501
|
} else if (arg === "--version") {
|
|
56313
|
-
printVersion();
|
|
56502
|
+
await printVersion();
|
|
56314
56503
|
process.exit(0);
|
|
56315
56504
|
} else if (arg === "--help" || arg === "-h") {
|
|
56316
56505
|
printHelp2();
|
|
@@ -56496,15 +56685,15 @@ Usage: claudish --models --provider <slug>`);
|
|
|
56496
56685
|
});
|
|
56497
56686
|
config.resolvedDefaultProvider = resolved;
|
|
56498
56687
|
if (resolved.legacyAutoPromoted && !config.quiet) {
|
|
56499
|
-
const markerFile =
|
|
56500
|
-
if (!
|
|
56688
|
+
const markerFile = join39(homedir34(), ".claudish", ".legacy-litellm-hint-shown");
|
|
56689
|
+
if (!existsSync29(markerFile)) {
|
|
56501
56690
|
const hint = buildLegacyHint(resolved);
|
|
56502
56691
|
if (hint) {
|
|
56503
56692
|
console.error(hint);
|
|
56504
56693
|
}
|
|
56505
56694
|
try {
|
|
56506
|
-
|
|
56507
|
-
|
|
56695
|
+
mkdirSync17(dirname11(markerFile), { recursive: true });
|
|
56696
|
+
writeFileSync18(markerFile, new Date().toISOString(), "utf-8");
|
|
56508
56697
|
} catch {}
|
|
56509
56698
|
}
|
|
56510
56699
|
}
|
|
@@ -56797,8 +56986,20 @@ Recommended Models (last updated: ${lastUpdated}):
|
|
|
56797
56986
|
console.log(" claudish --models-top --models-refresh (refresh from Firebase)");
|
|
56798
56987
|
console.log("");
|
|
56799
56988
|
}
|
|
56800
|
-
function printVersion() {
|
|
56801
|
-
|
|
56989
|
+
async function printVersion() {
|
|
56990
|
+
if (!process.stdout.isTTY) {
|
|
56991
|
+
console.log(`claudish version ${VERSION}`);
|
|
56992
|
+
return;
|
|
56993
|
+
}
|
|
56994
|
+
await Promise.resolve().then(() => init_branding());
|
|
56995
|
+
printLogo(process.stdout, { version: VERSION, trailingBlankLine: false });
|
|
56996
|
+
await Promise.resolve().then(() => init_update_checker());
|
|
56997
|
+
const latestVersion = await getLatestVersionCached({ timeoutMs: 1500 });
|
|
56998
|
+
if (latestVersion && isUpgrade(latestVersion, VERSION)) {
|
|
56999
|
+
console.log("");
|
|
57000
|
+
console.log(formatUpdateNotice(VERSION, latestVersion));
|
|
57001
|
+
}
|
|
57002
|
+
console.log("");
|
|
56802
57003
|
}
|
|
56803
57004
|
async function probeModelRouting(models, jsonOutput, options = { live: true, timeoutMs: 40000 }) {
|
|
56804
57005
|
const userRoutingKeys = new Set([
|
|
@@ -57629,8 +57830,8 @@ ${h("MORE INFO")}
|
|
|
57629
57830
|
}
|
|
57630
57831
|
function printAIAgentGuide() {
|
|
57631
57832
|
try {
|
|
57632
|
-
const guidePath =
|
|
57633
|
-
const guideContent =
|
|
57833
|
+
const guidePath = join39(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
57834
|
+
const guideContent = readFileSync29(guidePath, "utf-8");
|
|
57634
57835
|
console.log(guideContent);
|
|
57635
57836
|
} catch (error) {
|
|
57636
57837
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -57646,19 +57847,19 @@ async function initializeClaudishSkill() {
|
|
|
57646
57847
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
57647
57848
|
`);
|
|
57648
57849
|
const cwd = process.cwd();
|
|
57649
|
-
const claudeDir =
|
|
57650
|
-
const skillsDir =
|
|
57651
|
-
const claudishSkillDir =
|
|
57652
|
-
const skillFile =
|
|
57653
|
-
if (
|
|
57850
|
+
const claudeDir = join39(cwd, ".claude");
|
|
57851
|
+
const skillsDir = join39(claudeDir, "skills");
|
|
57852
|
+
const claudishSkillDir = join39(skillsDir, "claudish-usage");
|
|
57853
|
+
const skillFile = join39(claudishSkillDir, "SKILL.md");
|
|
57854
|
+
if (existsSync29(skillFile)) {
|
|
57654
57855
|
console.log("\u2705 Claudish skill already installed at:");
|
|
57655
57856
|
console.log(` ${skillFile}
|
|
57656
57857
|
`);
|
|
57657
57858
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
57658
57859
|
return;
|
|
57659
57860
|
}
|
|
57660
|
-
const sourceSkillPath =
|
|
57661
|
-
if (!
|
|
57861
|
+
const sourceSkillPath = join39(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
57862
|
+
if (!existsSync29(sourceSkillPath)) {
|
|
57662
57863
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
57663
57864
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
57664
57865
|
console.error(`
|
|
@@ -57667,16 +57868,16 @@ async function initializeClaudishSkill() {
|
|
|
57667
57868
|
process.exit(1);
|
|
57668
57869
|
}
|
|
57669
57870
|
try {
|
|
57670
|
-
if (!
|
|
57671
|
-
|
|
57871
|
+
if (!existsSync29(claudeDir)) {
|
|
57872
|
+
mkdirSync17(claudeDir, { recursive: true });
|
|
57672
57873
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
57673
57874
|
}
|
|
57674
|
-
if (!
|
|
57675
|
-
|
|
57875
|
+
if (!existsSync29(skillsDir)) {
|
|
57876
|
+
mkdirSync17(skillsDir, { recursive: true });
|
|
57676
57877
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
57677
57878
|
}
|
|
57678
|
-
if (!
|
|
57679
|
-
|
|
57879
|
+
if (!existsSync29(claudishSkillDir)) {
|
|
57880
|
+
mkdirSync17(claudishSkillDir, { recursive: true });
|
|
57680
57881
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
57681
57882
|
}
|
|
57682
57883
|
copyFileSync2(sourceSkillPath, skillFile);
|
|
@@ -57756,141 +57957,6 @@ var init_cli = __esm(() => {
|
|
|
57756
57957
|
__dirname3 = dirname11(__filename3);
|
|
57757
57958
|
});
|
|
57758
57959
|
|
|
57759
|
-
// src/update-checker.ts
|
|
57760
|
-
import { existsSync as existsSync29, mkdirSync as mkdirSync17, readFileSync as readFileSync29, unlinkSync as unlinkSync8, writeFileSync as writeFileSync18 } from "fs";
|
|
57761
|
-
import { homedir as homedir34, platform as platform2, tmpdir } from "os";
|
|
57762
|
-
import { join as join39 } from "path";
|
|
57763
|
-
function getCacheFilePath() {
|
|
57764
|
-
let cacheDir;
|
|
57765
|
-
if (isWindows) {
|
|
57766
|
-
const localAppData = process.env.LOCALAPPDATA || join39(homedir34(), "AppData", "Local");
|
|
57767
|
-
cacheDir = join39(localAppData, "claudish");
|
|
57768
|
-
} else {
|
|
57769
|
-
cacheDir = join39(homedir34(), ".cache", "claudish");
|
|
57770
|
-
}
|
|
57771
|
-
try {
|
|
57772
|
-
if (!existsSync29(cacheDir)) {
|
|
57773
|
-
mkdirSync17(cacheDir, { recursive: true });
|
|
57774
|
-
}
|
|
57775
|
-
return join39(cacheDir, "update-check.json");
|
|
57776
|
-
} catch {
|
|
57777
|
-
return join39(tmpdir(), "claudish-update-check.json");
|
|
57778
|
-
}
|
|
57779
|
-
}
|
|
57780
|
-
function readCache() {
|
|
57781
|
-
try {
|
|
57782
|
-
const cachePath = getCacheFilePath();
|
|
57783
|
-
if (!existsSync29(cachePath)) {
|
|
57784
|
-
return null;
|
|
57785
|
-
}
|
|
57786
|
-
const data = JSON.parse(readFileSync29(cachePath, "utf-8"));
|
|
57787
|
-
return data;
|
|
57788
|
-
} catch {
|
|
57789
|
-
return null;
|
|
57790
|
-
}
|
|
57791
|
-
}
|
|
57792
|
-
function writeCache(latestVersion) {
|
|
57793
|
-
try {
|
|
57794
|
-
const cachePath = getCacheFilePath();
|
|
57795
|
-
const data = {
|
|
57796
|
-
lastCheck: Date.now(),
|
|
57797
|
-
latestVersion
|
|
57798
|
-
};
|
|
57799
|
-
writeFileSync18(cachePath, JSON.stringify(data), "utf-8");
|
|
57800
|
-
} catch {}
|
|
57801
|
-
}
|
|
57802
|
-
function isCacheValid(cache) {
|
|
57803
|
-
const age = Date.now() - cache.lastCheck;
|
|
57804
|
-
return age < CACHE_MAX_AGE_MS;
|
|
57805
|
-
}
|
|
57806
|
-
function clearCache() {
|
|
57807
|
-
try {
|
|
57808
|
-
const cachePath = getCacheFilePath();
|
|
57809
|
-
if (existsSync29(cachePath)) {
|
|
57810
|
-
unlinkSync8(cachePath);
|
|
57811
|
-
}
|
|
57812
|
-
} catch {}
|
|
57813
|
-
}
|
|
57814
|
-
function compareVersions(v1, v2) {
|
|
57815
|
-
const parts1 = v1.replace(/^v/, "").split(".").map(Number);
|
|
57816
|
-
const parts2 = v2.replace(/^v/, "").split(".").map(Number);
|
|
57817
|
-
for (let i = 0;i < Math.max(parts1.length, parts2.length); i++) {
|
|
57818
|
-
const p1 = parts1[i] || 0;
|
|
57819
|
-
const p2 = parts2[i] || 0;
|
|
57820
|
-
if (p1 > p2)
|
|
57821
|
-
return 1;
|
|
57822
|
-
if (p1 < p2)
|
|
57823
|
-
return -1;
|
|
57824
|
-
}
|
|
57825
|
-
return 0;
|
|
57826
|
-
}
|
|
57827
|
-
async function fetchLatestVersionOrThrow(options = {}) {
|
|
57828
|
-
const { timeoutMs = 5000, retries = 0 } = options;
|
|
57829
|
-
let lastError = new Error("unknown error");
|
|
57830
|
-
for (let attempt = 0;attempt <= retries; attempt++) {
|
|
57831
|
-
const controller = new AbortController;
|
|
57832
|
-
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
57833
|
-
try {
|
|
57834
|
-
const response = await fetch(NPM_REGISTRY_URL, {
|
|
57835
|
-
signal: controller.signal,
|
|
57836
|
-
headers: { Accept: "application/json" }
|
|
57837
|
-
});
|
|
57838
|
-
if (!response.ok) {
|
|
57839
|
-
throw new Error(`npm registry returned HTTP ${response.status}`);
|
|
57840
|
-
}
|
|
57841
|
-
const data = await response.json();
|
|
57842
|
-
if (!data.version) {
|
|
57843
|
-
throw new Error("npm registry response contained no version field");
|
|
57844
|
-
}
|
|
57845
|
-
return data.version;
|
|
57846
|
-
} catch (error) {
|
|
57847
|
-
lastError = error instanceof Error && error.name === "AbortError" ? new Error(`request timed out after ${timeoutMs}ms`) : error instanceof Error ? error : new Error(String(error));
|
|
57848
|
-
if (attempt < retries) {
|
|
57849
|
-
await new Promise((resolve) => setTimeout(resolve, 300 * (attempt + 1)));
|
|
57850
|
-
}
|
|
57851
|
-
} finally {
|
|
57852
|
-
clearTimeout(timeout);
|
|
57853
|
-
}
|
|
57854
|
-
}
|
|
57855
|
-
throw lastError;
|
|
57856
|
-
}
|
|
57857
|
-
async function fetchLatestVersion(options = {}) {
|
|
57858
|
-
try {
|
|
57859
|
-
return await fetchLatestVersionOrThrow(options);
|
|
57860
|
-
} catch {
|
|
57861
|
-
return null;
|
|
57862
|
-
}
|
|
57863
|
-
}
|
|
57864
|
-
async function checkForUpdates(currentVersion, options = {}) {
|
|
57865
|
-
const { quiet = false } = options;
|
|
57866
|
-
let latestVersion = null;
|
|
57867
|
-
const cache = readCache();
|
|
57868
|
-
if (cache && isCacheValid(cache)) {
|
|
57869
|
-
latestVersion = cache.latestVersion;
|
|
57870
|
-
} else {
|
|
57871
|
-
latestVersion = await fetchLatestVersion();
|
|
57872
|
-
writeCache(latestVersion);
|
|
57873
|
-
}
|
|
57874
|
-
if (!latestVersion) {
|
|
57875
|
-
return;
|
|
57876
|
-
}
|
|
57877
|
-
if (compareVersions(latestVersion, currentVersion) <= 0) {
|
|
57878
|
-
return;
|
|
57879
|
-
}
|
|
57880
|
-
if (!quiet) {
|
|
57881
|
-
const { RESET, BOLD, GREEN, CYAN, DIM } = cliAnsi();
|
|
57882
|
-
console.error("");
|
|
57883
|
-
console.error(` ${CYAN}\u250C${RESET} ${BOLD}Update available:${RESET} ${currentVersion} ${DIM}\u2192${RESET} ${GREEN}${latestVersion}${RESET} ${DIM}Run:${RESET} ${BOLD}${CYAN}claudish update${RESET}`);
|
|
57884
|
-
console.error("");
|
|
57885
|
-
}
|
|
57886
|
-
}
|
|
57887
|
-
var isWindows, NPM_REGISTRY_URL = "https://registry.npmjs.org/claudish/latest", CACHE_MAX_AGE_MS;
|
|
57888
|
-
var init_update_checker = __esm(() => {
|
|
57889
|
-
init_ansi();
|
|
57890
|
-
isWindows = platform2() === "win32";
|
|
57891
|
-
CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
57892
|
-
});
|
|
57893
|
-
|
|
57894
57960
|
// src/update-command.ts
|
|
57895
57961
|
import { execSync as execSync2 } from "child_process";
|
|
57896
57962
|
function refreshAnsi2() {
|
|
@@ -58083,6 +58149,24 @@ async function resolveLatestVersion() {
|
|
|
58083
58149
|
return { version: viaNpm };
|
|
58084
58150
|
return { error: fetchError };
|
|
58085
58151
|
}
|
|
58152
|
+
async function performUpdate() {
|
|
58153
|
+
refreshAnsi2();
|
|
58154
|
+
const installInfo = detectInstallationMethod();
|
|
58155
|
+
if (installInfo.method === "unknown") {
|
|
58156
|
+
printManualInstructions();
|
|
58157
|
+
return { status: "unsupported" };
|
|
58158
|
+
}
|
|
58159
|
+
const command = getUpdateCommand(installInfo.method);
|
|
58160
|
+
console.log(`
|
|
58161
|
+
${DIM}Updating...${RESET}
|
|
58162
|
+
`);
|
|
58163
|
+
const success = await executeUpdate(command);
|
|
58164
|
+
if (success) {
|
|
58165
|
+
clearCache();
|
|
58166
|
+
return { status: "updated", method: installInfo.method };
|
|
58167
|
+
}
|
|
58168
|
+
return { status: "failed", method: installInfo.method };
|
|
58169
|
+
}
|
|
58086
58170
|
async function updateCommand() {
|
|
58087
58171
|
refreshAnsi2();
|
|
58088
58172
|
const currentVersion = getVersion3();
|
|
@@ -58111,19 +58195,13 @@ async function updateCommand() {
|
|
|
58111
58195
|
process.exit(0);
|
|
58112
58196
|
}
|
|
58113
58197
|
console.log(` ${BOLD}claudish${RESET} ${YELLOW}v${currentVersion}${RESET} ${DIM}\u2192${RESET} ${GREEN}v${latestVersion}${RESET} ${DIM}(${installInfo.method})${RESET}`);
|
|
58114
|
-
|
|
58115
|
-
|
|
58198
|
+
const outcome = await performUpdate();
|
|
58199
|
+
if (outcome.status === "unsupported") {
|
|
58116
58200
|
process.exit(1);
|
|
58117
58201
|
}
|
|
58118
|
-
|
|
58119
|
-
console.log(`
|
|
58120
|
-
${DIM}Updating...${RESET}
|
|
58121
|
-
`);
|
|
58122
|
-
const success = await executeUpdate(command);
|
|
58123
|
-
if (success) {
|
|
58202
|
+
if (outcome.status === "updated") {
|
|
58124
58203
|
console.log(`
|
|
58125
58204
|
${GREEN}\u2713${RESET} ${BOLD}Updated successfully${RESET}`);
|
|
58126
|
-
clearCache();
|
|
58127
58205
|
const changelog = await fetchChangelog(currentVersion, latestVersion);
|
|
58128
58206
|
displayChangelog(changelog);
|
|
58129
58207
|
console.log("");
|
|
@@ -66293,6 +66371,67 @@ function createDiagOutput(options) {
|
|
|
66293
66371
|
}
|
|
66294
66372
|
var init_diag_output = () => {};
|
|
66295
66373
|
|
|
66374
|
+
// src/update-prompt.ts
|
|
66375
|
+
async function confirm(question) {
|
|
66376
|
+
const { createInterface } = await import("readline");
|
|
66377
|
+
return new Promise((resolve) => {
|
|
66378
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
66379
|
+
let answered = false;
|
|
66380
|
+
rl.question(question, (value) => {
|
|
66381
|
+
answered = true;
|
|
66382
|
+
rl.close();
|
|
66383
|
+
const normalized = value.trim().toLowerCase();
|
|
66384
|
+
resolve(!(normalized === "n" || normalized === "no"));
|
|
66385
|
+
});
|
|
66386
|
+
rl.on("close", () => {
|
|
66387
|
+
if (!answered)
|
|
66388
|
+
resolve(false);
|
|
66389
|
+
});
|
|
66390
|
+
});
|
|
66391
|
+
}
|
|
66392
|
+
async function checkForUpdatesInteractive(currentVersion, options = {}) {
|
|
66393
|
+
const { quiet = false, canPrompt = true } = options;
|
|
66394
|
+
const latestVersion = await getLatestVersionCached();
|
|
66395
|
+
if (!latestVersion || !isUpgrade(latestVersion, currentVersion)) {
|
|
66396
|
+
return "continue";
|
|
66397
|
+
}
|
|
66398
|
+
if (quiet) {
|
|
66399
|
+
return "continue";
|
|
66400
|
+
}
|
|
66401
|
+
const { RESET, BOLD, GREEN, CYAN, DIM, YELLOW } = cliAnsi();
|
|
66402
|
+
if (!canPrompt || !process.stdin.isTTY) {
|
|
66403
|
+
console.error("");
|
|
66404
|
+
console.error(formatUpdateNotice(currentVersion, latestVersion));
|
|
66405
|
+
console.error("");
|
|
66406
|
+
return "continue";
|
|
66407
|
+
}
|
|
66408
|
+
console.error("");
|
|
66409
|
+
console.error(formatUpdateNotice(currentVersion, latestVersion, { hint: false }));
|
|
66410
|
+
console.error("");
|
|
66411
|
+
const accepted = await confirm(` ${BOLD}Update now?${RESET} ${DIM}[Y/n]${RESET} `);
|
|
66412
|
+
if (!accepted) {
|
|
66413
|
+
console.error(` ${DIM}Skipped. Run${RESET} ${BOLD}${CYAN}claudish update${RESET} ${DIM}when you are ready.${RESET}
|
|
66414
|
+
`);
|
|
66415
|
+
return "continue";
|
|
66416
|
+
}
|
|
66417
|
+
const outcome = await performUpdate();
|
|
66418
|
+
if (outcome.status === "updated") {
|
|
66419
|
+
console.error("");
|
|
66420
|
+
console.error(` ${GREEN}\u2713${RESET} ${BOLD}Updated to ${latestVersion}.${RESET} ${DIM}This process is still running ${currentVersion}.${RESET}`);
|
|
66421
|
+
console.error(` ${DIM}Run${RESET} ${BOLD}${CYAN}claudish${RESET} ${DIM}again to start.${RESET}`);
|
|
66422
|
+
console.error("");
|
|
66423
|
+
return "restart-required";
|
|
66424
|
+
}
|
|
66425
|
+
console.error(` ${YELLOW}Continuing on ${currentVersion}.${RESET}
|
|
66426
|
+
`);
|
|
66427
|
+
return "continue";
|
|
66428
|
+
}
|
|
66429
|
+
var init_update_prompt = __esm(() => {
|
|
66430
|
+
init_ansi();
|
|
66431
|
+
init_update_checker();
|
|
66432
|
+
init_update_command();
|
|
66433
|
+
});
|
|
66434
|
+
|
|
66296
66435
|
// src/launcher/catalog-warm.ts
|
|
66297
66436
|
function shouldWarmCatalog(args) {
|
|
66298
66437
|
if (args.skipModelsUpdate)
|
|
@@ -68647,7 +68786,7 @@ function bg(hex) {
|
|
|
68647
68786
|
const [r, g, b] = rgb(hex);
|
|
68648
68787
|
return `\x1B[48;2;${r};${g};${b}m`;
|
|
68649
68788
|
}
|
|
68650
|
-
function
|
|
68789
|
+
function paint2(text, hex, bold = false) {
|
|
68651
68790
|
return `${bold ? BOLD4 : ""}${fg(hex)}${text}${RESET3}`;
|
|
68652
68791
|
}
|
|
68653
68792
|
function meter(pct, width, ramp = ramps.load) {
|
|
@@ -68655,7 +68794,7 @@ function meter(pct, width, ramp = ramps.load) {
|
|
|
68655
68794
|
if (!Number.isFinite(cells) || cells <= 0)
|
|
68656
68795
|
return "";
|
|
68657
68796
|
if (Number.isNaN(pct))
|
|
68658
|
-
return
|
|
68797
|
+
return paint2(NODATA2.repeat(cells), tokens.dead);
|
|
68659
68798
|
const cols = rampFor(cells, ramp);
|
|
68660
68799
|
const filled = fillCells(pct, cells);
|
|
68661
68800
|
let out = "";
|
|
@@ -68676,7 +68815,7 @@ function stackedBar(segments, width) {
|
|
|
68676
68815
|
return "";
|
|
68677
68816
|
const split = splitCells(segments.map((s) => s.value), cells);
|
|
68678
68817
|
if (split.reduce((a, b) => a + b, 0) === 0)
|
|
68679
|
-
return
|
|
68818
|
+
return paint2(TRACK2.repeat(cells), tokens.border);
|
|
68680
68819
|
let out = "";
|
|
68681
68820
|
for (let i = 0;i < split.length; i++) {
|
|
68682
68821
|
const n = split[i];
|
|
@@ -68801,14 +68940,14 @@ function renderSessionSummary(input) {
|
|
|
68801
68940
|
const W = cardWidth();
|
|
68802
68941
|
const inner = W - CHROME;
|
|
68803
68942
|
const out = [];
|
|
68804
|
-
const dim = (s) =>
|
|
68805
|
-
const body = (s) =>
|
|
68943
|
+
const dim = (s) => paint2(s, tokens.subtle);
|
|
68944
|
+
const body = (s) => paint2(s, tokens.text);
|
|
68806
68945
|
const titleText = exitCode === 0 ? " session " : " session \xB7 failed ";
|
|
68807
68946
|
const titleHex = exitCode === 0 ? tokens.accent : tokens.error;
|
|
68808
68947
|
const rule = "\u2500".repeat(Math.max(0, W - 2 - visibleWidth(titleText) - 1));
|
|
68809
|
-
out.push(
|
|
68948
|
+
out.push(paint2("\u256D\u2500", tokens.border) + paint2(titleText, titleHex) + paint2(rule + "\u256E", tokens.border));
|
|
68810
68949
|
const row = (s) => {
|
|
68811
|
-
out.push(`${
|
|
68950
|
+
out.push(`${paint2("\u2502", tokens.border)} ${padVisible2(s, inner)} ${paint2("\u2502", tokens.border)}`);
|
|
68812
68951
|
};
|
|
68813
68952
|
const blank = () => row("");
|
|
68814
68953
|
const chips = [badge(truncate3(modelSpec, 34), tokens.accent)];
|
|
@@ -68858,13 +68997,13 @@ function renderSessionSummary(input) {
|
|
|
68858
68997
|
if (rest > 0)
|
|
68859
68998
|
segs.push({ value: rest, color: area(other) });
|
|
68860
68999
|
dataRow("tools", stackedBar(segs, barW), body(padStartTo(String(stats.toolCallTotal), 4)) + dim(" calls"));
|
|
68861
|
-
const legend = shown.map((t, i) =>
|
|
69000
|
+
const legend = shown.map((t, i) => paint2(`${t.name} ${t.count}`, toolCols[i])).concat(rest > 0 ? [paint2(`other ${rest}`, other)] : []);
|
|
68862
69001
|
for (const line of wrapStyled(legend, dim(" \xB7 "), inner - LABEL_W)) {
|
|
68863
69002
|
row(" ".repeat(LABEL_W) + line);
|
|
68864
69003
|
}
|
|
68865
69004
|
}
|
|
68866
69005
|
blank();
|
|
68867
|
-
row(dim(padTo("cost", LABEL_W)) +
|
|
69006
|
+
row(dim(padTo("cost", LABEL_W)) + paint2(stats.isFree ? "free" : usd(stats.costUsd), tokens.text, true) + (stats.isEstimated && !stats.isFree ? dim(" estimated") : ""));
|
|
68868
69007
|
const dearest = Math.max(0, ...stats.savings.map((s) => s.baselineUsd));
|
|
68869
69008
|
for (const s of stats.savings) {
|
|
68870
69009
|
const label = padTo(`vs ${s.label}`, LABEL_W);
|
|
@@ -68873,10 +69012,10 @@ function renderSessionSummary(input) {
|
|
|
68873
69012
|
const share = dearest > 0 ? s.savedUsd / dearest * 100 : 0;
|
|
68874
69013
|
dataRow(label, meter(share, barW, areaRamp(ramps.volume)), dim(`${padStartTo(`${Math.round(pct)}%`, 4)} saved `) + body(usd(s.savedUsd)));
|
|
68875
69014
|
} else {
|
|
68876
|
-
dataRow(label, meter(0, barW, areaRamp(ramps.volume)), dim("over by ") +
|
|
69015
|
+
dataRow(label, meter(0, barW, areaRamp(ramps.volume)), dim("over by ") + paint2(usd(-s.savedUsd), tokens.error));
|
|
68877
69016
|
}
|
|
68878
69017
|
}
|
|
68879
|
-
out.push(
|
|
69018
|
+
out.push(paint2(`\u2570${"\u2500".repeat(W - 2)}\u256F`, tokens.border));
|
|
68880
69019
|
if (resumeId) {
|
|
68881
69020
|
out.push("");
|
|
68882
69021
|
out.push(dim("Resume this session with:"));
|
|
@@ -69170,7 +69309,8 @@ async function runCli() {
|
|
|
69170
69309
|
await Promise.resolve().then(() => init_diag_output());
|
|
69171
69310
|
await Promise.resolve().then(() => init_port_manager());
|
|
69172
69311
|
await Promise.resolve().then(() => init_proxy_server());
|
|
69173
|
-
await Promise.resolve().then(() =>
|
|
69312
|
+
await Promise.resolve().then(() => init_update_prompt());
|
|
69313
|
+
await Promise.resolve().then(() => init_branding());
|
|
69174
69314
|
await Promise.resolve().then(() => init_catalog_warm());
|
|
69175
69315
|
endImports();
|
|
69176
69316
|
async function readStdin() {
|
|
@@ -69241,6 +69381,9 @@ Team Status`);
|
|
|
69241
69381
|
}
|
|
69242
69382
|
process.exit(0);
|
|
69243
69383
|
}
|
|
69384
|
+
if (cliConfig.interactive && !cliConfig.quiet && process.stderr.isTTY) {
|
|
69385
|
+
printLogo(process.stderr, { version: getVersion3() });
|
|
69386
|
+
}
|
|
69244
69387
|
const rawArgs = process.argv.slice(2);
|
|
69245
69388
|
const explicitNoAutoApprove = rawArgs.includes("--no-auto-approve");
|
|
69246
69389
|
if (cliConfig.autoApprove && !explicitNoAutoApprove && !cliConfig.stdin && cliConfig.interactive) {
|
|
@@ -69295,7 +69438,13 @@ Team Status`);
|
|
|
69295
69438
|
}
|
|
69296
69439
|
}
|
|
69297
69440
|
if (cliConfig.interactive && !cliConfig.jsonOutput) {
|
|
69298
|
-
await traceSpan("startup:update-check", () =>
|
|
69441
|
+
const updateStep = await traceSpan("startup:update-check", () => checkForUpdatesInteractive(getVersion3(), {
|
|
69442
|
+
quiet: cliConfig.quiet,
|
|
69443
|
+
canPrompt: !cliConfig.stdin
|
|
69444
|
+
}), { mayIncludeUserPrompt: true });
|
|
69445
|
+
if (updateStep === "restart-required") {
|
|
69446
|
+
process.exit(0);
|
|
69447
|
+
}
|
|
69299
69448
|
}
|
|
69300
69449
|
if (!await traceSpan("startup:claude-detect", () => checkClaudeInstalled())) {
|
|
69301
69450
|
console.error("Error: Claude Code CLI not found");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claudish",
|
|
3
|
-
"version": "9.0
|
|
3
|
+
"version": "9.1.0",
|
|
4
4
|
"description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
"ai"
|
|
61
61
|
],
|
|
62
62
|
"optionalDependencies": {
|
|
63
|
-
"@claudish/magmux-darwin-arm64": "9.0
|
|
64
|
-
"@claudish/magmux-darwin-x64": "9.0
|
|
65
|
-
"@claudish/magmux-linux-arm64": "9.0
|
|
66
|
-
"@claudish/magmux-linux-x64": "9.0
|
|
63
|
+
"@claudish/magmux-darwin-arm64": "9.1.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "9.1.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "9.1.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "9.1.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|