claudish 9.0.9 → 9.2.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 +383 -203
- 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.2.0";
|
|
719
719
|
|
|
720
720
|
// src/logger.ts
|
|
721
721
|
import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -40410,6 +40410,18 @@ function teamSlotActivity(teamSessionId) {
|
|
|
40410
40410
|
}
|
|
40411
40411
|
return out;
|
|
40412
40412
|
}
|
|
40413
|
+
function teamSlotLiveBytes(teamSessionId) {
|
|
40414
|
+
const run = liveTeamRuns.get(teamSessionId);
|
|
40415
|
+
if (!run)
|
|
40416
|
+
return null;
|
|
40417
|
+
const out = {};
|
|
40418
|
+
for (const slotId of run.processes.keys()) {
|
|
40419
|
+
const bytes = run.liveBytesFor(slotId);
|
|
40420
|
+
if (bytes !== null)
|
|
40421
|
+
out[slotId] = bytes;
|
|
40422
|
+
}
|
|
40423
|
+
return out;
|
|
40424
|
+
}
|
|
40413
40425
|
async function cancelTeamRun(teamSessionId, slotId) {
|
|
40414
40426
|
const run = liveTeamRuns.get(teamSessionId);
|
|
40415
40427
|
if (!run)
|
|
@@ -40862,6 +40874,7 @@ async function startModels(sessionPath, opts = {}) {
|
|
|
40862
40874
|
processes,
|
|
40863
40875
|
idleMsFor: (slotId) => runtimes.get(slotId)?.getIdleMs() ?? null,
|
|
40864
40876
|
activityFor: (slotId) => runtimes.get(slotId)?.getActivity() ?? null,
|
|
40877
|
+
liveBytesFor: (slotId) => runtimes.get(slotId)?.getByteCount() ?? null,
|
|
40865
40878
|
cancelledSlots
|
|
40866
40879
|
});
|
|
40867
40880
|
const done = (async () => {
|
|
@@ -47107,6 +47120,28 @@ function buildChildClaudeFlags(agent, claudeFlags) {
|
|
|
47107
47120
|
const flags = [...named ? ["--agent", named] : [], ...cleaned];
|
|
47108
47121
|
return flags.length > 0 ? flags : undefined;
|
|
47109
47122
|
}
|
|
47123
|
+
function teamStatusNote(opts) {
|
|
47124
|
+
if (!opts.anyRunning)
|
|
47125
|
+
return;
|
|
47126
|
+
const trap = "outputSize is the size of the FINAL answer and is written once, when a slot " + "finishes. Every RUNNING slot therefore reports 0 however much work it has done: " + "it is NOT a progress signal, and 0 there does not mean the slot produced nothing.";
|
|
47127
|
+
if (!opts.live) {
|
|
47128
|
+
return `${trap} This run is not live in this process \u2014 it was started elsewhere, or this ` + "server restarted \u2014 so there are no liveness fields for it and the states above are " + "whatever was last written to status.json.";
|
|
47129
|
+
}
|
|
47130
|
+
return `${trap} Judge a running slot on three fields read TOGETHER: ` + "live_output_bytes_by_slot (answer bytes so far, the number outputSize will become), " + "idle_seconds_by_slot (seconds of silence) and activity_by_slot (what it is doing). " + "Silence in tool_executing is a build or test suite running, and is not a failure " + 'signal. Nothing cancels on your behalf \u2014 use mode:"cancel" if you decide to.';
|
|
47131
|
+
}
|
|
47132
|
+
function buildTeamStatusPayload(opts) {
|
|
47133
|
+
const { status, sessionPath, idle, activity, liveBytes } = opts;
|
|
47134
|
+
const anyRunning = Object.values(status.models).some((m) => m.state === "RUNNING");
|
|
47135
|
+
const note = teamStatusNote({ anyRunning, live: idle !== null });
|
|
47136
|
+
return {
|
|
47137
|
+
...status,
|
|
47138
|
+
live_output_bytes_by_slot: liveBytes,
|
|
47139
|
+
idle_seconds_by_slot: idle,
|
|
47140
|
+
activity_by_slot: activity,
|
|
47141
|
+
...note ? { note } : {},
|
|
47142
|
+
...anyRunning ? {} : { summary: formatTeamResult(status, sessionPath) }
|
|
47143
|
+
};
|
|
47144
|
+
}
|
|
47110
47145
|
function formatTeamResult(status, sessionPath) {
|
|
47111
47146
|
const entries = Object.entries(status.models).sort(([a], [b]) => a.localeCompare(b));
|
|
47112
47147
|
const failed = entries.filter(([, m]) => m.state === "FAILED" || m.state === "TIMEOUT" || m.state === "EMPTY");
|
|
@@ -47592,14 +47627,14 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
47592
47627
|
});
|
|
47593
47628
|
tools.push({
|
|
47594
47629
|
name: "team",
|
|
47595
|
-
description: "Run AI models on a task with anonymized outputs and optional blind judging. " + "Modes: 'run' (START the models and return a slot map immediately \u2014 it does NOT " + "wait), 'status' (per-slot state, plus
|
|
47630
|
+
description: "Run AI models on a task with anonymized outputs and optional blind judging. " + "Modes: 'run' (START the models and return a slot map immediately \u2014 it does NOT " + "wait), 'status' (per-slot state, plus live answer bytes, seconds of silence and " + "current activity per slot), " + "'cancel' (stop one slot or the whole run), 'judge' (blind-vote on existing " + "outputs), 'run-and-judge' (the blocking pipeline). " + "NO SLOT IS EVER KILLED ON A TIMER. A team slot is a full Claude Code session and " + "may work for a long time; a slot inside a build or test suite emits nothing for " + "minutes and is working, not stuck. Poll 'status', judge the silence against the " + "task you set, and use 'cancel' if you decide a slot is wedged. " + "JUDGING A RUNNING SLOT: read live_output_bytes_by_slot, idle_seconds_by_slot and " + "activity_by_slot. Do NOT use 'outputSize' \u2014 it is the size of the final answer, " + "written only when a slot finishes, so it is 0 for every running slot no matter how " + "much that slot has produced.",
|
|
47596
47631
|
inputSchema: {
|
|
47597
47632
|
type: "object",
|
|
47598
47633
|
properties: {
|
|
47599
47634
|
mode: {
|
|
47600
47635
|
type: "string",
|
|
47601
47636
|
enum: ["run", "judge", "run-and-judge", "status", "cancel"],
|
|
47602
|
-
description: "Operation mode. 'run' STARTS the models and returns immediately with a " + "slot map \u2014 it does not wait. Poll 'status' for progress, then 'judge' once
|
|
47637
|
+
description: "Operation mode. 'run' STARTS the models and returns immediately with a " + "slot map \u2014 it does not wait. Poll 'status' for progress (read it from " + "live_output_bytes_by_slot and activity_by_slot, never from outputSize, " + "which stays 0 until a slot finishes), then 'judge' once the slots have " + "finished. 'run-and-judge' is the blocking pipeline and holds the call open " + "for the whole run. 'cancel' stops one slot or the whole run."
|
|
47603
47638
|
},
|
|
47604
47639
|
slot: {
|
|
47605
47640
|
type: "string",
|
|
@@ -47750,21 +47785,17 @@ Use with: run_prompt(model="${suggested}", prompt="your prompt")`;
|
|
|
47750
47785
|
case "status": {
|
|
47751
47786
|
const status = getStatus(resolved);
|
|
47752
47787
|
const teamSessionId = resolved.split("/").filter(Boolean).pop() ?? "team";
|
|
47753
|
-
const idle = teamSlotIdleSeconds(teamSessionId);
|
|
47754
|
-
const settled = !Object.values(status.models).some((m) => m.state === "RUNNING");
|
|
47755
47788
|
return {
|
|
47756
47789
|
content: [
|
|
47757
47790
|
{
|
|
47758
47791
|
type: "text",
|
|
47759
|
-
text: JSON.stringify({
|
|
47760
|
-
|
|
47761
|
-
|
|
47762
|
-
|
|
47763
|
-
|
|
47764
|
-
|
|
47765
|
-
|
|
47766
|
-
...settled ? { summary: formatTeamResult(status, resolved) } : {}
|
|
47767
|
-
}, null, 2)
|
|
47792
|
+
text: JSON.stringify(buildTeamStatusPayload({
|
|
47793
|
+
status,
|
|
47794
|
+
sessionPath: resolved,
|
|
47795
|
+
idle: teamSlotIdleSeconds(teamSessionId),
|
|
47796
|
+
activity: teamSlotActivity(teamSessionId),
|
|
47797
|
+
liveBytes: teamSlotLiveBytes(teamSessionId)
|
|
47798
|
+
}), null, 2)
|
|
47768
47799
|
}
|
|
47769
47800
|
]
|
|
47770
47801
|
};
|
|
@@ -56013,25 +56044,214 @@ var init_api_key_map = __esm(() => {
|
|
|
56013
56044
|
};
|
|
56014
56045
|
});
|
|
56015
56046
|
|
|
56047
|
+
// src/branding.ts
|
|
56048
|
+
function paint(line) {
|
|
56049
|
+
const { RESET, BOLD, CYAN, BLUE, DIM } = cliAnsi();
|
|
56050
|
+
if (!CYAN && !BLUE)
|
|
56051
|
+
return line;
|
|
56052
|
+
return line.replace(/\u2588+/g, (run) => `${BOLD}${CYAN}${run}${RESET}`).replace(/[\u2557\u255D\u2551\u2550\u2554\u255A]+/g, (run) => `${DIM}${BLUE}${run}${RESET}`);
|
|
56053
|
+
}
|
|
56054
|
+
function fitsWordmark(stream) {
|
|
56055
|
+
if (process.env.TERM === "dumb")
|
|
56056
|
+
return false;
|
|
56057
|
+
const columns = stream.columns ?? 0;
|
|
56058
|
+
return columns >= MIN_LOGO_WIDTH;
|
|
56059
|
+
}
|
|
56060
|
+
function wordmarkLines() {
|
|
56061
|
+
return WORDMARK.map((line) => ` ${paint(line)}`);
|
|
56062
|
+
}
|
|
56063
|
+
function compactLogo() {
|
|
56064
|
+
const { RESET, BOLD, CYAN, DIM } = cliAnsi();
|
|
56065
|
+
return ` ${BOLD}${CYAN}claudish${RESET} ${DIM}\xB7${RESET} ${TAGLINE}`;
|
|
56066
|
+
}
|
|
56067
|
+
function printLogo(stream, options = {}) {
|
|
56068
|
+
const { version, trailingBlankLine = true } = options;
|
|
56069
|
+
const { RESET, BOLD, DIM, GRAY } = cliAnsi();
|
|
56070
|
+
stream.write(`
|
|
56071
|
+
`);
|
|
56072
|
+
if (fitsWordmark(stream)) {
|
|
56073
|
+
for (const line of wordmarkLines())
|
|
56074
|
+
stream.write(`${line}
|
|
56075
|
+
`);
|
|
56076
|
+
stream.write(`
|
|
56077
|
+
${GRAY}${TAGLINE}${RESET}
|
|
56078
|
+
`);
|
|
56079
|
+
} else {
|
|
56080
|
+
stream.write(`${compactLogo()}
|
|
56081
|
+
`);
|
|
56082
|
+
}
|
|
56083
|
+
if (version) {
|
|
56084
|
+
stream.write(` ${DIM}claudish version${RESET} ${BOLD}${version}${RESET}
|
|
56085
|
+
`);
|
|
56086
|
+
}
|
|
56087
|
+
if (trailingBlankLine)
|
|
56088
|
+
stream.write(`
|
|
56089
|
+
`);
|
|
56090
|
+
}
|
|
56091
|
+
var MIN_LOGO_WIDTH = 64, TAGLINE = "Claude Code. Any Model.", WORDMARK;
|
|
56092
|
+
var init_branding = __esm(() => {
|
|
56093
|
+
init_ansi();
|
|
56094
|
+
WORDMARK = [
|
|
56095
|
+
" \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",
|
|
56096
|
+
"\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",
|
|
56097
|
+
"\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",
|
|
56098
|
+
"\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",
|
|
56099
|
+
"\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",
|
|
56100
|
+
" \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"
|
|
56101
|
+
];
|
|
56102
|
+
});
|
|
56103
|
+
|
|
56104
|
+
// src/update-checker.ts
|
|
56105
|
+
import { existsSync as existsSync28, mkdirSync as mkdirSync16, readFileSync as readFileSync28, unlinkSync as unlinkSync7, writeFileSync as writeFileSync17 } from "fs";
|
|
56106
|
+
import { homedir as homedir33, platform as platform2, tmpdir } from "os";
|
|
56107
|
+
import { join as join38 } from "path";
|
|
56108
|
+
function getCacheFilePath() {
|
|
56109
|
+
let cacheDir;
|
|
56110
|
+
if (isWindows) {
|
|
56111
|
+
const localAppData = process.env.LOCALAPPDATA || join38(homedir33(), "AppData", "Local");
|
|
56112
|
+
cacheDir = join38(localAppData, "claudish");
|
|
56113
|
+
} else {
|
|
56114
|
+
cacheDir = join38(homedir33(), ".cache", "claudish");
|
|
56115
|
+
}
|
|
56116
|
+
try {
|
|
56117
|
+
if (!existsSync28(cacheDir)) {
|
|
56118
|
+
mkdirSync16(cacheDir, { recursive: true });
|
|
56119
|
+
}
|
|
56120
|
+
return join38(cacheDir, "update-check.json");
|
|
56121
|
+
} catch {
|
|
56122
|
+
return join38(tmpdir(), "claudish-update-check.json");
|
|
56123
|
+
}
|
|
56124
|
+
}
|
|
56125
|
+
function readCache() {
|
|
56126
|
+
try {
|
|
56127
|
+
const cachePath = getCacheFilePath();
|
|
56128
|
+
if (!existsSync28(cachePath)) {
|
|
56129
|
+
return null;
|
|
56130
|
+
}
|
|
56131
|
+
const data = JSON.parse(readFileSync28(cachePath, "utf-8"));
|
|
56132
|
+
return data;
|
|
56133
|
+
} catch {
|
|
56134
|
+
return null;
|
|
56135
|
+
}
|
|
56136
|
+
}
|
|
56137
|
+
function writeCache(latestVersion) {
|
|
56138
|
+
try {
|
|
56139
|
+
const cachePath = getCacheFilePath();
|
|
56140
|
+
const data = {
|
|
56141
|
+
lastCheck: Date.now(),
|
|
56142
|
+
latestVersion
|
|
56143
|
+
};
|
|
56144
|
+
writeFileSync17(cachePath, JSON.stringify(data), "utf-8");
|
|
56145
|
+
} catch {}
|
|
56146
|
+
}
|
|
56147
|
+
function isCacheValid(cache) {
|
|
56148
|
+
const age = Date.now() - cache.lastCheck;
|
|
56149
|
+
return age < CACHE_MAX_AGE_MS;
|
|
56150
|
+
}
|
|
56151
|
+
function clearCache() {
|
|
56152
|
+
try {
|
|
56153
|
+
const cachePath = getCacheFilePath();
|
|
56154
|
+
if (existsSync28(cachePath)) {
|
|
56155
|
+
unlinkSync7(cachePath);
|
|
56156
|
+
}
|
|
56157
|
+
} catch {}
|
|
56158
|
+
}
|
|
56159
|
+
function compareVersions(v1, v2) {
|
|
56160
|
+
const parts1 = v1.replace(/^v/, "").split(".").map(Number);
|
|
56161
|
+
const parts2 = v2.replace(/^v/, "").split(".").map(Number);
|
|
56162
|
+
for (let i = 0;i < Math.max(parts1.length, parts2.length); i++) {
|
|
56163
|
+
const p1 = parts1[i] || 0;
|
|
56164
|
+
const p2 = parts2[i] || 0;
|
|
56165
|
+
if (p1 > p2)
|
|
56166
|
+
return 1;
|
|
56167
|
+
if (p1 < p2)
|
|
56168
|
+
return -1;
|
|
56169
|
+
}
|
|
56170
|
+
return 0;
|
|
56171
|
+
}
|
|
56172
|
+
async function fetchLatestVersionOrThrow(options = {}) {
|
|
56173
|
+
const { timeoutMs = 5000, retries = 0 } = options;
|
|
56174
|
+
let lastError = new Error("unknown error");
|
|
56175
|
+
for (let attempt = 0;attempt <= retries; attempt++) {
|
|
56176
|
+
const controller = new AbortController;
|
|
56177
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
56178
|
+
try {
|
|
56179
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
56180
|
+
signal: controller.signal,
|
|
56181
|
+
headers: { Accept: "application/json" }
|
|
56182
|
+
});
|
|
56183
|
+
if (!response.ok) {
|
|
56184
|
+
throw new Error(`npm registry returned HTTP ${response.status}`);
|
|
56185
|
+
}
|
|
56186
|
+
const data = await response.json();
|
|
56187
|
+
if (!data.version) {
|
|
56188
|
+
throw new Error("npm registry response contained no version field");
|
|
56189
|
+
}
|
|
56190
|
+
return data.version;
|
|
56191
|
+
} catch (error) {
|
|
56192
|
+
lastError = error instanceof Error && error.name === "AbortError" ? new Error(`request timed out after ${timeoutMs}ms`) : error instanceof Error ? error : new Error(String(error));
|
|
56193
|
+
if (attempt < retries) {
|
|
56194
|
+
await new Promise((resolve) => setTimeout(resolve, 300 * (attempt + 1)));
|
|
56195
|
+
}
|
|
56196
|
+
} finally {
|
|
56197
|
+
clearTimeout(timeout);
|
|
56198
|
+
}
|
|
56199
|
+
}
|
|
56200
|
+
throw lastError;
|
|
56201
|
+
}
|
|
56202
|
+
async function fetchLatestVersion(options = {}) {
|
|
56203
|
+
try {
|
|
56204
|
+
return await fetchLatestVersionOrThrow(options);
|
|
56205
|
+
} catch {
|
|
56206
|
+
return null;
|
|
56207
|
+
}
|
|
56208
|
+
}
|
|
56209
|
+
async function getLatestVersionCached(options = {}) {
|
|
56210
|
+
const cache = readCache();
|
|
56211
|
+
if (cache && isCacheValid(cache)) {
|
|
56212
|
+
return cache.latestVersion;
|
|
56213
|
+
}
|
|
56214
|
+
const latestVersion = await fetchLatestVersion(options);
|
|
56215
|
+
writeCache(latestVersion);
|
|
56216
|
+
return latestVersion;
|
|
56217
|
+
}
|
|
56218
|
+
function isUpgrade(latestVersion, currentVersion) {
|
|
56219
|
+
if (!latestVersion)
|
|
56220
|
+
return false;
|
|
56221
|
+
return compareVersions(latestVersion, currentVersion) > 0;
|
|
56222
|
+
}
|
|
56223
|
+
function formatUpdateNotice(currentVersion, latestVersion, options = {}) {
|
|
56224
|
+
const { hint = true } = options;
|
|
56225
|
+
const { RESET, BOLD, GREEN, CYAN, DIM } = cliAnsi();
|
|
56226
|
+
const runHint = hint ? ` ${DIM}Run:${RESET} ${BOLD}${CYAN}claudish update${RESET}` : "";
|
|
56227
|
+
return ` ${CYAN}\u250C${RESET} ${BOLD}Update available:${RESET} ${currentVersion} ${DIM}\u2192${RESET} ${GREEN}${latestVersion}${RESET}${runHint}`;
|
|
56228
|
+
}
|
|
56229
|
+
var isWindows, NPM_REGISTRY_URL = "https://registry.npmjs.org/claudish/latest", CACHE_MAX_AGE_MS;
|
|
56230
|
+
var init_update_checker = __esm(() => {
|
|
56231
|
+
init_ansi();
|
|
56232
|
+
isWindows = platform2() === "win32";
|
|
56233
|
+
CACHE_MAX_AGE_MS = 24 * 60 * 60 * 1000;
|
|
56234
|
+
});
|
|
56235
|
+
|
|
56016
56236
|
// src/cli.ts
|
|
56017
56237
|
import {
|
|
56018
56238
|
copyFileSync as copyFileSync2,
|
|
56019
|
-
existsSync as
|
|
56020
|
-
mkdirSync as
|
|
56021
|
-
readFileSync as
|
|
56239
|
+
existsSync as existsSync29,
|
|
56240
|
+
mkdirSync as mkdirSync17,
|
|
56241
|
+
readFileSync as readFileSync29,
|
|
56022
56242
|
readdirSync as readdirSync7,
|
|
56023
|
-
unlinkSync as
|
|
56024
|
-
writeFileSync as
|
|
56243
|
+
unlinkSync as unlinkSync8,
|
|
56244
|
+
writeFileSync as writeFileSync18
|
|
56025
56245
|
} from "fs";
|
|
56026
|
-
import { homedir as
|
|
56027
|
-
import { dirname as dirname11, join as
|
|
56246
|
+
import { homedir as homedir34 } from "os";
|
|
56247
|
+
import { dirname as dirname11, join as join39 } from "path";
|
|
56028
56248
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
56029
56249
|
function getVersion3() {
|
|
56030
56250
|
return VERSION;
|
|
56031
56251
|
}
|
|
56032
56252
|
function clearAllModelCaches() {
|
|
56033
|
-
const cacheDir =
|
|
56034
|
-
if (!
|
|
56253
|
+
const cacheDir = join39(homedir34(), ".claudish");
|
|
56254
|
+
if (!existsSync29(cacheDir))
|
|
56035
56255
|
return;
|
|
56036
56256
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
|
|
56037
56257
|
let cleared = 0;
|
|
@@ -56039,7 +56259,7 @@ function clearAllModelCaches() {
|
|
|
56039
56259
|
const files = readdirSync7(cacheDir);
|
|
56040
56260
|
for (const file of files) {
|
|
56041
56261
|
if (cachePatterns.includes(file)) {
|
|
56042
|
-
|
|
56262
|
+
unlinkSync8(join39(cacheDir, file));
|
|
56043
56263
|
cleared++;
|
|
56044
56264
|
}
|
|
56045
56265
|
}
|
|
@@ -56310,7 +56530,7 @@ async function parseArgs(args) {
|
|
|
56310
56530
|
} else if (arg === "--cost-reset") {
|
|
56311
56531
|
config.resetCosts = true;
|
|
56312
56532
|
} else if (arg === "--version") {
|
|
56313
|
-
printVersion();
|
|
56533
|
+
await printVersion();
|
|
56314
56534
|
process.exit(0);
|
|
56315
56535
|
} else if (arg === "--help" || arg === "-h") {
|
|
56316
56536
|
printHelp2();
|
|
@@ -56496,15 +56716,15 @@ Usage: claudish --models --provider <slug>`);
|
|
|
56496
56716
|
});
|
|
56497
56717
|
config.resolvedDefaultProvider = resolved;
|
|
56498
56718
|
if (resolved.legacyAutoPromoted && !config.quiet) {
|
|
56499
|
-
const markerFile =
|
|
56500
|
-
if (!
|
|
56719
|
+
const markerFile = join39(homedir34(), ".claudish", ".legacy-litellm-hint-shown");
|
|
56720
|
+
if (!existsSync29(markerFile)) {
|
|
56501
56721
|
const hint = buildLegacyHint(resolved);
|
|
56502
56722
|
if (hint) {
|
|
56503
56723
|
console.error(hint);
|
|
56504
56724
|
}
|
|
56505
56725
|
try {
|
|
56506
|
-
|
|
56507
|
-
|
|
56726
|
+
mkdirSync17(dirname11(markerFile), { recursive: true });
|
|
56727
|
+
writeFileSync18(markerFile, new Date().toISOString(), "utf-8");
|
|
56508
56728
|
} catch {}
|
|
56509
56729
|
}
|
|
56510
56730
|
}
|
|
@@ -56797,8 +57017,20 @@ Recommended Models (last updated: ${lastUpdated}):
|
|
|
56797
57017
|
console.log(" claudish --models-top --models-refresh (refresh from Firebase)");
|
|
56798
57018
|
console.log("");
|
|
56799
57019
|
}
|
|
56800
|
-
function printVersion() {
|
|
56801
|
-
|
|
57020
|
+
async function printVersion() {
|
|
57021
|
+
if (!process.stdout.isTTY) {
|
|
57022
|
+
console.log(`claudish version ${VERSION}`);
|
|
57023
|
+
return;
|
|
57024
|
+
}
|
|
57025
|
+
await Promise.resolve().then(() => init_branding());
|
|
57026
|
+
printLogo(process.stdout, { version: VERSION, trailingBlankLine: false });
|
|
57027
|
+
await Promise.resolve().then(() => init_update_checker());
|
|
57028
|
+
const latestVersion = await getLatestVersionCached({ timeoutMs: 1500 });
|
|
57029
|
+
if (latestVersion && isUpgrade(latestVersion, VERSION)) {
|
|
57030
|
+
console.log("");
|
|
57031
|
+
console.log(formatUpdateNotice(VERSION, latestVersion));
|
|
57032
|
+
}
|
|
57033
|
+
console.log("");
|
|
56802
57034
|
}
|
|
56803
57035
|
async function probeModelRouting(models, jsonOutput, options = { live: true, timeoutMs: 40000 }) {
|
|
56804
57036
|
const userRoutingKeys = new Set([
|
|
@@ -57629,8 +57861,8 @@ ${h("MORE INFO")}
|
|
|
57629
57861
|
}
|
|
57630
57862
|
function printAIAgentGuide() {
|
|
57631
57863
|
try {
|
|
57632
|
-
const guidePath =
|
|
57633
|
-
const guideContent =
|
|
57864
|
+
const guidePath = join39(__dirname3, "../AI_AGENT_GUIDE.md");
|
|
57865
|
+
const guideContent = readFileSync29(guidePath, "utf-8");
|
|
57634
57866
|
console.log(guideContent);
|
|
57635
57867
|
} catch (error) {
|
|
57636
57868
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -57646,19 +57878,19 @@ async function initializeClaudishSkill() {
|
|
|
57646
57878
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
57647
57879
|
`);
|
|
57648
57880
|
const cwd = process.cwd();
|
|
57649
|
-
const claudeDir =
|
|
57650
|
-
const skillsDir =
|
|
57651
|
-
const claudishSkillDir =
|
|
57652
|
-
const skillFile =
|
|
57653
|
-
if (
|
|
57881
|
+
const claudeDir = join39(cwd, ".claude");
|
|
57882
|
+
const skillsDir = join39(claudeDir, "skills");
|
|
57883
|
+
const claudishSkillDir = join39(skillsDir, "claudish-usage");
|
|
57884
|
+
const skillFile = join39(claudishSkillDir, "SKILL.md");
|
|
57885
|
+
if (existsSync29(skillFile)) {
|
|
57654
57886
|
console.log("\u2705 Claudish skill already installed at:");
|
|
57655
57887
|
console.log(` ${skillFile}
|
|
57656
57888
|
`);
|
|
57657
57889
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
57658
57890
|
return;
|
|
57659
57891
|
}
|
|
57660
|
-
const sourceSkillPath =
|
|
57661
|
-
if (!
|
|
57892
|
+
const sourceSkillPath = join39(__dirname3, "../skills/claudish-usage/SKILL.md");
|
|
57893
|
+
if (!existsSync29(sourceSkillPath)) {
|
|
57662
57894
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
57663
57895
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
57664
57896
|
console.error(`
|
|
@@ -57667,16 +57899,16 @@ async function initializeClaudishSkill() {
|
|
|
57667
57899
|
process.exit(1);
|
|
57668
57900
|
}
|
|
57669
57901
|
try {
|
|
57670
|
-
if (!
|
|
57671
|
-
|
|
57902
|
+
if (!existsSync29(claudeDir)) {
|
|
57903
|
+
mkdirSync17(claudeDir, { recursive: true });
|
|
57672
57904
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
57673
57905
|
}
|
|
57674
|
-
if (!
|
|
57675
|
-
|
|
57906
|
+
if (!existsSync29(skillsDir)) {
|
|
57907
|
+
mkdirSync17(skillsDir, { recursive: true });
|
|
57676
57908
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
57677
57909
|
}
|
|
57678
|
-
if (!
|
|
57679
|
-
|
|
57910
|
+
if (!existsSync29(claudishSkillDir)) {
|
|
57911
|
+
mkdirSync17(claudishSkillDir, { recursive: true });
|
|
57680
57912
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
57681
57913
|
}
|
|
57682
57914
|
copyFileSync2(sourceSkillPath, skillFile);
|
|
@@ -57756,141 +57988,6 @@ var init_cli = __esm(() => {
|
|
|
57756
57988
|
__dirname3 = dirname11(__filename3);
|
|
57757
57989
|
});
|
|
57758
57990
|
|
|
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
57991
|
// src/update-command.ts
|
|
57895
57992
|
import { execSync as execSync2 } from "child_process";
|
|
57896
57993
|
function refreshAnsi2() {
|
|
@@ -58083,6 +58180,24 @@ async function resolveLatestVersion() {
|
|
|
58083
58180
|
return { version: viaNpm };
|
|
58084
58181
|
return { error: fetchError };
|
|
58085
58182
|
}
|
|
58183
|
+
async function performUpdate() {
|
|
58184
|
+
refreshAnsi2();
|
|
58185
|
+
const installInfo = detectInstallationMethod();
|
|
58186
|
+
if (installInfo.method === "unknown") {
|
|
58187
|
+
printManualInstructions();
|
|
58188
|
+
return { status: "unsupported" };
|
|
58189
|
+
}
|
|
58190
|
+
const command = getUpdateCommand(installInfo.method);
|
|
58191
|
+
console.log(`
|
|
58192
|
+
${DIM}Updating...${RESET}
|
|
58193
|
+
`);
|
|
58194
|
+
const success = await executeUpdate(command);
|
|
58195
|
+
if (success) {
|
|
58196
|
+
clearCache();
|
|
58197
|
+
return { status: "updated", method: installInfo.method };
|
|
58198
|
+
}
|
|
58199
|
+
return { status: "failed", method: installInfo.method };
|
|
58200
|
+
}
|
|
58086
58201
|
async function updateCommand() {
|
|
58087
58202
|
refreshAnsi2();
|
|
58088
58203
|
const currentVersion = getVersion3();
|
|
@@ -58111,19 +58226,13 @@ async function updateCommand() {
|
|
|
58111
58226
|
process.exit(0);
|
|
58112
58227
|
}
|
|
58113
58228
|
console.log(` ${BOLD}claudish${RESET} ${YELLOW}v${currentVersion}${RESET} ${DIM}\u2192${RESET} ${GREEN}v${latestVersion}${RESET} ${DIM}(${installInfo.method})${RESET}`);
|
|
58114
|
-
|
|
58115
|
-
|
|
58229
|
+
const outcome = await performUpdate();
|
|
58230
|
+
if (outcome.status === "unsupported") {
|
|
58116
58231
|
process.exit(1);
|
|
58117
58232
|
}
|
|
58118
|
-
|
|
58119
|
-
console.log(`
|
|
58120
|
-
${DIM}Updating...${RESET}
|
|
58121
|
-
`);
|
|
58122
|
-
const success = await executeUpdate(command);
|
|
58123
|
-
if (success) {
|
|
58233
|
+
if (outcome.status === "updated") {
|
|
58124
58234
|
console.log(`
|
|
58125
58235
|
${GREEN}\u2713${RESET} ${BOLD}Updated successfully${RESET}`);
|
|
58126
|
-
clearCache();
|
|
58127
58236
|
const changelog = await fetchChangelog(currentVersion, latestVersion);
|
|
58128
58237
|
displayChangelog(changelog);
|
|
58129
58238
|
console.log("");
|
|
@@ -66293,6 +66402,67 @@ function createDiagOutput(options) {
|
|
|
66293
66402
|
}
|
|
66294
66403
|
var init_diag_output = () => {};
|
|
66295
66404
|
|
|
66405
|
+
// src/update-prompt.ts
|
|
66406
|
+
async function confirm(question) {
|
|
66407
|
+
const { createInterface } = await import("readline");
|
|
66408
|
+
return new Promise((resolve) => {
|
|
66409
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
66410
|
+
let answered = false;
|
|
66411
|
+
rl.question(question, (value) => {
|
|
66412
|
+
answered = true;
|
|
66413
|
+
rl.close();
|
|
66414
|
+
const normalized = value.trim().toLowerCase();
|
|
66415
|
+
resolve(!(normalized === "n" || normalized === "no"));
|
|
66416
|
+
});
|
|
66417
|
+
rl.on("close", () => {
|
|
66418
|
+
if (!answered)
|
|
66419
|
+
resolve(false);
|
|
66420
|
+
});
|
|
66421
|
+
});
|
|
66422
|
+
}
|
|
66423
|
+
async function checkForUpdatesInteractive(currentVersion, options = {}) {
|
|
66424
|
+
const { quiet = false, canPrompt = true } = options;
|
|
66425
|
+
const latestVersion = await getLatestVersionCached();
|
|
66426
|
+
if (!latestVersion || !isUpgrade(latestVersion, currentVersion)) {
|
|
66427
|
+
return "continue";
|
|
66428
|
+
}
|
|
66429
|
+
if (quiet) {
|
|
66430
|
+
return "continue";
|
|
66431
|
+
}
|
|
66432
|
+
const { RESET, BOLD, GREEN, CYAN, DIM, YELLOW } = cliAnsi();
|
|
66433
|
+
if (!canPrompt || !process.stdin.isTTY) {
|
|
66434
|
+
console.error("");
|
|
66435
|
+
console.error(formatUpdateNotice(currentVersion, latestVersion));
|
|
66436
|
+
console.error("");
|
|
66437
|
+
return "continue";
|
|
66438
|
+
}
|
|
66439
|
+
console.error("");
|
|
66440
|
+
console.error(formatUpdateNotice(currentVersion, latestVersion, { hint: false }));
|
|
66441
|
+
console.error("");
|
|
66442
|
+
const accepted = await confirm(` ${BOLD}Update now?${RESET} ${DIM}[Y/n]${RESET} `);
|
|
66443
|
+
if (!accepted) {
|
|
66444
|
+
console.error(` ${DIM}Skipped. Run${RESET} ${BOLD}${CYAN}claudish update${RESET} ${DIM}when you are ready.${RESET}
|
|
66445
|
+
`);
|
|
66446
|
+
return "continue";
|
|
66447
|
+
}
|
|
66448
|
+
const outcome = await performUpdate();
|
|
66449
|
+
if (outcome.status === "updated") {
|
|
66450
|
+
console.error("");
|
|
66451
|
+
console.error(` ${GREEN}\u2713${RESET} ${BOLD}Updated to ${latestVersion}.${RESET} ${DIM}This process is still running ${currentVersion}.${RESET}`);
|
|
66452
|
+
console.error(` ${DIM}Run${RESET} ${BOLD}${CYAN}claudish${RESET} ${DIM}again to start.${RESET}`);
|
|
66453
|
+
console.error("");
|
|
66454
|
+
return "restart-required";
|
|
66455
|
+
}
|
|
66456
|
+
console.error(` ${YELLOW}Continuing on ${currentVersion}.${RESET}
|
|
66457
|
+
`);
|
|
66458
|
+
return "continue";
|
|
66459
|
+
}
|
|
66460
|
+
var init_update_prompt = __esm(() => {
|
|
66461
|
+
init_ansi();
|
|
66462
|
+
init_update_checker();
|
|
66463
|
+
init_update_command();
|
|
66464
|
+
});
|
|
66465
|
+
|
|
66296
66466
|
// src/launcher/catalog-warm.ts
|
|
66297
66467
|
function shouldWarmCatalog(args) {
|
|
66298
66468
|
if (args.skipModelsUpdate)
|
|
@@ -68647,7 +68817,7 @@ function bg(hex) {
|
|
|
68647
68817
|
const [r, g, b] = rgb(hex);
|
|
68648
68818
|
return `\x1B[48;2;${r};${g};${b}m`;
|
|
68649
68819
|
}
|
|
68650
|
-
function
|
|
68820
|
+
function paint2(text, hex, bold = false) {
|
|
68651
68821
|
return `${bold ? BOLD4 : ""}${fg(hex)}${text}${RESET3}`;
|
|
68652
68822
|
}
|
|
68653
68823
|
function meter(pct, width, ramp = ramps.load) {
|
|
@@ -68655,7 +68825,7 @@ function meter(pct, width, ramp = ramps.load) {
|
|
|
68655
68825
|
if (!Number.isFinite(cells) || cells <= 0)
|
|
68656
68826
|
return "";
|
|
68657
68827
|
if (Number.isNaN(pct))
|
|
68658
|
-
return
|
|
68828
|
+
return paint2(NODATA2.repeat(cells), tokens.dead);
|
|
68659
68829
|
const cols = rampFor(cells, ramp);
|
|
68660
68830
|
const filled = fillCells(pct, cells);
|
|
68661
68831
|
let out = "";
|
|
@@ -68676,7 +68846,7 @@ function stackedBar(segments, width) {
|
|
|
68676
68846
|
return "";
|
|
68677
68847
|
const split = splitCells(segments.map((s) => s.value), cells);
|
|
68678
68848
|
if (split.reduce((a, b) => a + b, 0) === 0)
|
|
68679
|
-
return
|
|
68849
|
+
return paint2(TRACK2.repeat(cells), tokens.border);
|
|
68680
68850
|
let out = "";
|
|
68681
68851
|
for (let i = 0;i < split.length; i++) {
|
|
68682
68852
|
const n = split[i];
|
|
@@ -68801,14 +68971,14 @@ function renderSessionSummary(input) {
|
|
|
68801
68971
|
const W = cardWidth();
|
|
68802
68972
|
const inner = W - CHROME;
|
|
68803
68973
|
const out = [];
|
|
68804
|
-
const dim = (s) =>
|
|
68805
|
-
const body = (s) =>
|
|
68974
|
+
const dim = (s) => paint2(s, tokens.subtle);
|
|
68975
|
+
const body = (s) => paint2(s, tokens.text);
|
|
68806
68976
|
const titleText = exitCode === 0 ? " session " : " session \xB7 failed ";
|
|
68807
68977
|
const titleHex = exitCode === 0 ? tokens.accent : tokens.error;
|
|
68808
68978
|
const rule = "\u2500".repeat(Math.max(0, W - 2 - visibleWidth(titleText) - 1));
|
|
68809
|
-
out.push(
|
|
68979
|
+
out.push(paint2("\u256D\u2500", tokens.border) + paint2(titleText, titleHex) + paint2(rule + "\u256E", tokens.border));
|
|
68810
68980
|
const row = (s) => {
|
|
68811
|
-
out.push(`${
|
|
68981
|
+
out.push(`${paint2("\u2502", tokens.border)} ${padVisible2(s, inner)} ${paint2("\u2502", tokens.border)}`);
|
|
68812
68982
|
};
|
|
68813
68983
|
const blank = () => row("");
|
|
68814
68984
|
const chips = [badge(truncate3(modelSpec, 34), tokens.accent)];
|
|
@@ -68858,13 +69028,13 @@ function renderSessionSummary(input) {
|
|
|
68858
69028
|
if (rest > 0)
|
|
68859
69029
|
segs.push({ value: rest, color: area(other) });
|
|
68860
69030
|
dataRow("tools", stackedBar(segs, barW), body(padStartTo(String(stats.toolCallTotal), 4)) + dim(" calls"));
|
|
68861
|
-
const legend = shown.map((t, i) =>
|
|
69031
|
+
const legend = shown.map((t, i) => paint2(`${t.name} ${t.count}`, toolCols[i])).concat(rest > 0 ? [paint2(`other ${rest}`, other)] : []);
|
|
68862
69032
|
for (const line of wrapStyled(legend, dim(" \xB7 "), inner - LABEL_W)) {
|
|
68863
69033
|
row(" ".repeat(LABEL_W) + line);
|
|
68864
69034
|
}
|
|
68865
69035
|
}
|
|
68866
69036
|
blank();
|
|
68867
|
-
row(dim(padTo("cost", LABEL_W)) +
|
|
69037
|
+
row(dim(padTo("cost", LABEL_W)) + paint2(stats.isFree ? "free" : usd(stats.costUsd), tokens.text, true) + (stats.isEstimated && !stats.isFree ? dim(" estimated") : ""));
|
|
68868
69038
|
const dearest = Math.max(0, ...stats.savings.map((s) => s.baselineUsd));
|
|
68869
69039
|
for (const s of stats.savings) {
|
|
68870
69040
|
const label = padTo(`vs ${s.label}`, LABEL_W);
|
|
@@ -68873,10 +69043,10 @@ function renderSessionSummary(input) {
|
|
|
68873
69043
|
const share = dearest > 0 ? s.savedUsd / dearest * 100 : 0;
|
|
68874
69044
|
dataRow(label, meter(share, barW, areaRamp(ramps.volume)), dim(`${padStartTo(`${Math.round(pct)}%`, 4)} saved `) + body(usd(s.savedUsd)));
|
|
68875
69045
|
} else {
|
|
68876
|
-
dataRow(label, meter(0, barW, areaRamp(ramps.volume)), dim("over by ") +
|
|
69046
|
+
dataRow(label, meter(0, barW, areaRamp(ramps.volume)), dim("over by ") + paint2(usd(-s.savedUsd), tokens.error));
|
|
68877
69047
|
}
|
|
68878
69048
|
}
|
|
68879
|
-
out.push(
|
|
69049
|
+
out.push(paint2(`\u2570${"\u2500".repeat(W - 2)}\u256F`, tokens.border));
|
|
68880
69050
|
if (resumeId) {
|
|
68881
69051
|
out.push("");
|
|
68882
69052
|
out.push(dim("Resume this session with:"));
|
|
@@ -69170,7 +69340,8 @@ async function runCli() {
|
|
|
69170
69340
|
await Promise.resolve().then(() => init_diag_output());
|
|
69171
69341
|
await Promise.resolve().then(() => init_port_manager());
|
|
69172
69342
|
await Promise.resolve().then(() => init_proxy_server());
|
|
69173
|
-
await Promise.resolve().then(() =>
|
|
69343
|
+
await Promise.resolve().then(() => init_update_prompt());
|
|
69344
|
+
await Promise.resolve().then(() => init_branding());
|
|
69174
69345
|
await Promise.resolve().then(() => init_catalog_warm());
|
|
69175
69346
|
endImports();
|
|
69176
69347
|
async function readStdin() {
|
|
@@ -69241,6 +69412,9 @@ Team Status`);
|
|
|
69241
69412
|
}
|
|
69242
69413
|
process.exit(0);
|
|
69243
69414
|
}
|
|
69415
|
+
if (cliConfig.interactive && !cliConfig.quiet && process.stderr.isTTY) {
|
|
69416
|
+
printLogo(process.stderr, { version: getVersion3() });
|
|
69417
|
+
}
|
|
69244
69418
|
const rawArgs = process.argv.slice(2);
|
|
69245
69419
|
const explicitNoAutoApprove = rawArgs.includes("--no-auto-approve");
|
|
69246
69420
|
if (cliConfig.autoApprove && !explicitNoAutoApprove && !cliConfig.stdin && cliConfig.interactive) {
|
|
@@ -69295,7 +69469,13 @@ Team Status`);
|
|
|
69295
69469
|
}
|
|
69296
69470
|
}
|
|
69297
69471
|
if (cliConfig.interactive && !cliConfig.jsonOutput) {
|
|
69298
|
-
await traceSpan("startup:update-check", () =>
|
|
69472
|
+
const updateStep = await traceSpan("startup:update-check", () => checkForUpdatesInteractive(getVersion3(), {
|
|
69473
|
+
quiet: cliConfig.quiet,
|
|
69474
|
+
canPrompt: !cliConfig.stdin
|
|
69475
|
+
}), { mayIncludeUserPrompt: true });
|
|
69476
|
+
if (updateStep === "restart-required") {
|
|
69477
|
+
process.exit(0);
|
|
69478
|
+
}
|
|
69299
69479
|
}
|
|
69300
69480
|
if (!await traceSpan("startup:claude-detect", () => checkClaudeInstalled())) {
|
|
69301
69481
|
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.2.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.2.0",
|
|
64
|
+
"@claudish/magmux-darwin-x64": "9.2.0",
|
|
65
|
+
"@claudish/magmux-linux-arm64": "9.2.0",
|
|
66
|
+
"@claudish/magmux-linux-x64": "9.2.0"
|
|
67
67
|
},
|
|
68
68
|
"author": "Jack Rudenko <i@madappgang.com>",
|
|
69
69
|
"license": "MIT",
|