claudish 14.18.6 → 14.19.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 +1338 -553
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -5494,7 +5494,7 @@ var init_onepassword_config = __esm(() => {
|
|
|
5494
5494
|
});
|
|
5495
5495
|
|
|
5496
5496
|
// src/version.ts
|
|
5497
|
-
var VERSION = "14.
|
|
5497
|
+
var VERSION = "14.19.0";
|
|
5498
5498
|
|
|
5499
5499
|
// src/redact.ts
|
|
5500
5500
|
function isPlaceholder(value) {
|
|
@@ -11600,6 +11600,22 @@ var init_profile_config = __esm(() => {
|
|
|
11600
11600
|
};
|
|
11601
11601
|
});
|
|
11602
11602
|
|
|
11603
|
+
// src/providers/context-window-limit.ts
|
|
11604
|
+
function parseContextWindow(text) {
|
|
11605
|
+
const match = /^(\d+(?:\.\d+)?)([km]?)$/i.exec(text.trim());
|
|
11606
|
+
if (!match)
|
|
11607
|
+
return;
|
|
11608
|
+
const size = Math.round(Number(match[1]) * (UNIT_TOKENS[match[2].toLowerCase()] ?? 1));
|
|
11609
|
+
return size > 0 ? size : undefined;
|
|
11610
|
+
}
|
|
11611
|
+
function contextWindowLimit() {
|
|
11612
|
+
return parseContextWindow(process.env.CLAUDISH_CONTEXT_WINDOW ?? "");
|
|
11613
|
+
}
|
|
11614
|
+
var DEFAULT_LOCAL_CONTEXT_WINDOW = 128000, UNIT_TOKENS;
|
|
11615
|
+
var init_context_window_limit = __esm(() => {
|
|
11616
|
+
UNIT_TOKENS = { "": 1, k: 1000, m: 1e6 };
|
|
11617
|
+
});
|
|
11618
|
+
|
|
11603
11619
|
// src/providers/runtime-providers.ts
|
|
11604
11620
|
function registerRuntimeProvider(def) {
|
|
11605
11621
|
_runtimeProviders.set(def.name, def);
|
|
@@ -12294,6 +12310,9 @@ function findCacheEntry(modelId, cachePath) {
|
|
|
12294
12310
|
if (modelId.startsWith("@"))
|
|
12295
12311
|
return;
|
|
12296
12312
|
if (modelId.includes("@")) {
|
|
12313
|
+
const prefix = modelId.slice(0, modelId.indexOf("@")).toLowerCase();
|
|
12314
|
+
if (getShortcuts()[prefix] === undefined && !getProviderByName(prefix))
|
|
12315
|
+
return;
|
|
12297
12316
|
throw new Error(`model-catalog lookup received provider-routed ID "${modelId}" \u2014 callers must strip the "@" prefix before calling`);
|
|
12298
12317
|
}
|
|
12299
12318
|
const cache = readAllModelsCache(cachePath);
|
|
@@ -12387,6 +12406,7 @@ function searchCatalogModels(query, limit = 10, cachePath) {
|
|
|
12387
12406
|
var init_model_catalog = __esm(() => {
|
|
12388
12407
|
init_all_models_cache();
|
|
12389
12408
|
init_catalog_route_bindings();
|
|
12409
|
+
init_provider_definitions();
|
|
12390
12410
|
});
|
|
12391
12411
|
|
|
12392
12412
|
// src/adapters/optional-param-rejection.ts
|
|
@@ -50065,6 +50085,440 @@ var init_connection_resolver = __esm(() => {
|
|
|
50065
50085
|
init_connection_wire();
|
|
50066
50086
|
});
|
|
50067
50087
|
|
|
50088
|
+
// src/providers/lmstudio-devices.ts
|
|
50089
|
+
import { execFile as execFile2 } from "child_process";
|
|
50090
|
+
import {
|
|
50091
|
+
linkSync as linkSync3,
|
|
50092
|
+
mkdirSync as mkdirSync16,
|
|
50093
|
+
readFileSync as readFileSync29,
|
|
50094
|
+
readdirSync as readdirSync4,
|
|
50095
|
+
renameSync as renameSync8,
|
|
50096
|
+
rmSync as rmSync10,
|
|
50097
|
+
rmdirSync,
|
|
50098
|
+
statSync as statSync9,
|
|
50099
|
+
writeFileSync as writeFileSync11
|
|
50100
|
+
} from "fs";
|
|
50101
|
+
import { homedir as homedir28 } from "os";
|
|
50102
|
+
import { basename as basename2, dirname as dirname14, join as join29 } from "path";
|
|
50103
|
+
function execLms(binary, args, timeoutMs) {
|
|
50104
|
+
return new Promise((resolve) => {
|
|
50105
|
+
execFile2(binary, args, { timeout: timeoutMs, maxBuffer: 16 * 1024 * 1024 }, (error, stdout) => {
|
|
50106
|
+
resolve({
|
|
50107
|
+
stdout: error ? null : stdout,
|
|
50108
|
+
missing: error?.code === "ENOENT"
|
|
50109
|
+
});
|
|
50110
|
+
});
|
|
50111
|
+
});
|
|
50112
|
+
}
|
|
50113
|
+
function splitLMStudioDevice(modelId) {
|
|
50114
|
+
const at = modelId.lastIndexOf(LMSTUDIO_DEVICE_SEPARATOR);
|
|
50115
|
+
if (at <= 0 || at === modelId.length - 1)
|
|
50116
|
+
return { model: modelId };
|
|
50117
|
+
return { model: modelId.slice(0, at), device: modelId.slice(at + 1) };
|
|
50118
|
+
}
|
|
50119
|
+
function isLoopbackUrl(url) {
|
|
50120
|
+
try {
|
|
50121
|
+
const host = new URL(url).hostname;
|
|
50122
|
+
return host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host === "::1";
|
|
50123
|
+
} catch {
|
|
50124
|
+
return false;
|
|
50125
|
+
}
|
|
50126
|
+
}
|
|
50127
|
+
function parseJson(text) {
|
|
50128
|
+
if (text === null)
|
|
50129
|
+
return null;
|
|
50130
|
+
try {
|
|
50131
|
+
return JSON.parse(text);
|
|
50132
|
+
} catch {
|
|
50133
|
+
return null;
|
|
50134
|
+
}
|
|
50135
|
+
}
|
|
50136
|
+
async function readLink(run) {
|
|
50137
|
+
const raw = parseJson(await run(["link", "status", "--json"], LIST_TIMEOUT_MS));
|
|
50138
|
+
if (!raw?.deviceIdentifier)
|
|
50139
|
+
return null;
|
|
50140
|
+
const peers = [];
|
|
50141
|
+
for (const peer of raw.peers ?? []) {
|
|
50142
|
+
if (peer.status === "connected" && peer.deviceIdentifier && peer.deviceName) {
|
|
50143
|
+
peers.push({ id: peer.deviceIdentifier, name: peer.deviceName });
|
|
50144
|
+
}
|
|
50145
|
+
}
|
|
50146
|
+
return { self: raw.deviceIdentifier, preferred: raw.preferredDeviceIdentifier, peers };
|
|
50147
|
+
}
|
|
50148
|
+
async function readLoaded(run) {
|
|
50149
|
+
return parseJson(await run(["ps", "--json"], LIST_TIMEOUT_MS));
|
|
50150
|
+
}
|
|
50151
|
+
function machineLabel(peer) {
|
|
50152
|
+
return /^[\w. -]+$/.test(peer.name) ? peer.name : peer.id;
|
|
50153
|
+
}
|
|
50154
|
+
async function readLMStudioMachines(run = runLms) {
|
|
50155
|
+
const [link, stored, loaded] = await Promise.all([
|
|
50156
|
+
readLink(run),
|
|
50157
|
+
run(["ls", "--json"], LIST_TIMEOUT_MS).then((text) => parseJson(text)),
|
|
50158
|
+
readLoaded(run)
|
|
50159
|
+
]);
|
|
50160
|
+
if (!link || link.peers.length === 0 || !Array.isArray(stored))
|
|
50161
|
+
return null;
|
|
50162
|
+
const labelOf = (device) => {
|
|
50163
|
+
if (device === null || device === link.self)
|
|
50164
|
+
return LMSTUDIO_THIS_MACHINE;
|
|
50165
|
+
const peer = link.peers.find((p) => p.id === device);
|
|
50166
|
+
return peer ? machineLabel(peer) : undefined;
|
|
50167
|
+
};
|
|
50168
|
+
const labelsByModel = new Map;
|
|
50169
|
+
const maxWindows = new Map;
|
|
50170
|
+
for (const copy of stored) {
|
|
50171
|
+
const label = labelOf(copy.deviceIdentifier);
|
|
50172
|
+
if (!label)
|
|
50173
|
+
continue;
|
|
50174
|
+
if (copy.maxContextLength) {
|
|
50175
|
+
maxWindows.set(`${copy.modelKey}${LMSTUDIO_DEVICE_SEPARATOR}${label}`, copy.maxContextLength);
|
|
50176
|
+
}
|
|
50177
|
+
const labels = labelsByModel.get(copy.modelKey) ?? [];
|
|
50178
|
+
if (!labels.includes(label))
|
|
50179
|
+
labels.push(label);
|
|
50180
|
+
labelsByModel.set(copy.modelKey, labels);
|
|
50181
|
+
}
|
|
50182
|
+
for (const labels of labelsByModel.values()) {
|
|
50183
|
+
labels.sort((a, b) => Number(b === LMSTUDIO_THIS_MACHINE) - Number(a === LMSTUDIO_THIS_MACHINE));
|
|
50184
|
+
}
|
|
50185
|
+
const loadedWindows = new Map;
|
|
50186
|
+
for (const row of Array.isArray(loaded) ? loaded : []) {
|
|
50187
|
+
const label = labelOf(row.deviceIdentifier);
|
|
50188
|
+
if (label && row.modelKey && row.contextLength) {
|
|
50189
|
+
loadedWindows.set(`${row.modelKey}${LMSTUDIO_DEVICE_SEPARATOR}${label}`, row.contextLength);
|
|
50190
|
+
}
|
|
50191
|
+
}
|
|
50192
|
+
return { labelsByModel, loadedWindows, maxWindows };
|
|
50193
|
+
}
|
|
50194
|
+
function expandModelsToMachines(models, machines, defaultWindow) {
|
|
50195
|
+
return models.flatMap((model) => {
|
|
50196
|
+
const labels = machines.labelsByModel.get(model.id);
|
|
50197
|
+
if (!labels)
|
|
50198
|
+
return [model];
|
|
50199
|
+
return labels.map((label) => {
|
|
50200
|
+
const id = `${model.id}${LMSTUDIO_DEVICE_SEPARATOR}${label}`;
|
|
50201
|
+
const max = machines.maxWindows.get(id);
|
|
50202
|
+
const ceiling = defaultWindow && max && max < defaultWindow ? max : undefined;
|
|
50203
|
+
const loaded = machines.loadedWindows.get(id);
|
|
50204
|
+
const name = label === LMSTUDIO_THIS_MACHINE ? THIS_MACHINE_NAME : label;
|
|
50205
|
+
return {
|
|
50206
|
+
...model,
|
|
50207
|
+
id,
|
|
50208
|
+
displayName: `${model.displayName ?? model.id} (${name})`,
|
|
50209
|
+
machine: { name, modelId: model.id },
|
|
50210
|
+
contextWindow: loaded ?? ceiling,
|
|
50211
|
+
maxContextWindow: loaded ?? max,
|
|
50212
|
+
contextCeiling: loaded ?? max ?? model.contextCeiling
|
|
50213
|
+
};
|
|
50214
|
+
});
|
|
50215
|
+
});
|
|
50216
|
+
}
|
|
50217
|
+
function defaultLockPath2() {
|
|
50218
|
+
return join29(homedir28(), ".claudish", "lmstudio-machine.lock");
|
|
50219
|
+
}
|
|
50220
|
+
function lookAtLock(lockPath) {
|
|
50221
|
+
const identity = lockIdentity(lockPath);
|
|
50222
|
+
if (identity === undefined)
|
|
50223
|
+
return;
|
|
50224
|
+
let owner = "";
|
|
50225
|
+
try {
|
|
50226
|
+
owner = readFileSync29(join29(lockPath, "owner"), "utf-8");
|
|
50227
|
+
} catch {}
|
|
50228
|
+
const pid = Number.parseInt(owner, 10);
|
|
50229
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
50230
|
+
try {
|
|
50231
|
+
return { alive: Date.now() - statSync9(lockPath).mtimeMs < LOAD_TIMEOUT_MS2, identity };
|
|
50232
|
+
} catch {
|
|
50233
|
+
return;
|
|
50234
|
+
}
|
|
50235
|
+
}
|
|
50236
|
+
return { alive: pidAlive(pid), identity };
|
|
50237
|
+
}
|
|
50238
|
+
function pidAlive(pid) {
|
|
50239
|
+
try {
|
|
50240
|
+
process.kill(pid, 0);
|
|
50241
|
+
return true;
|
|
50242
|
+
} catch (error) {
|
|
50243
|
+
return error.code === "EPERM";
|
|
50244
|
+
}
|
|
50245
|
+
}
|
|
50246
|
+
function lockIdentity(path) {
|
|
50247
|
+
let stats;
|
|
50248
|
+
try {
|
|
50249
|
+
stats = statSync9(path);
|
|
50250
|
+
} catch {
|
|
50251
|
+
return;
|
|
50252
|
+
}
|
|
50253
|
+
let owner = "";
|
|
50254
|
+
try {
|
|
50255
|
+
owner = readFileSync29(join29(path, "owner"), "utf-8");
|
|
50256
|
+
} catch {}
|
|
50257
|
+
return `${stats.ino}:${stats.birthtimeMs}:${owner}`;
|
|
50258
|
+
}
|
|
50259
|
+
function takeOverStaleLock(lockPath, identity) {
|
|
50260
|
+
const entry = makeClaim(join29(lockPath, CLAIM));
|
|
50261
|
+
if (entry === undefined)
|
|
50262
|
+
return false;
|
|
50263
|
+
if (lockIdentity(lockPath) !== identity) {
|
|
50264
|
+
rmSync10(entry, { force: true });
|
|
50265
|
+
try {
|
|
50266
|
+
rmdirSync(dirname14(entry));
|
|
50267
|
+
} catch {}
|
|
50268
|
+
return false;
|
|
50269
|
+
}
|
|
50270
|
+
const aside = `${lockPath}.dead.${process.pid}.${Math.random().toString(36).slice(2)}`;
|
|
50271
|
+
try {
|
|
50272
|
+
renameSync8(lockPath, aside);
|
|
50273
|
+
} catch {
|
|
50274
|
+
return false;
|
|
50275
|
+
}
|
|
50276
|
+
rmSync10(aside, { recursive: true, force: true });
|
|
50277
|
+
return true;
|
|
50278
|
+
}
|
|
50279
|
+
function makeClaim(claim) {
|
|
50280
|
+
try {
|
|
50281
|
+
mkdirSync16(claim);
|
|
50282
|
+
} catch (error) {
|
|
50283
|
+
if (error.code !== "EEXIST")
|
|
50284
|
+
return;
|
|
50285
|
+
}
|
|
50286
|
+
const draft = `${claim}.${process.pid}.${Math.random().toString(36).slice(2)}`;
|
|
50287
|
+
try {
|
|
50288
|
+
writeFileSync11(draft, String(process.pid));
|
|
50289
|
+
let name = "pid";
|
|
50290
|
+
for (let step = 0;step < MAX_CLAIM_CHAIN; step++) {
|
|
50291
|
+
const entry = join29(claim, name);
|
|
50292
|
+
try {
|
|
50293
|
+
linkSync3(draft, entry);
|
|
50294
|
+
return entry;
|
|
50295
|
+
} catch (error) {
|
|
50296
|
+
if (error.code !== "EEXIST")
|
|
50297
|
+
return;
|
|
50298
|
+
}
|
|
50299
|
+
const holder = entryPid(entry);
|
|
50300
|
+
if (holder === undefined)
|
|
50301
|
+
return;
|
|
50302
|
+
if (holder === process.pid)
|
|
50303
|
+
return entry;
|
|
50304
|
+
if (pidAlive(holder))
|
|
50305
|
+
return;
|
|
50306
|
+
name = `after-${holder}`;
|
|
50307
|
+
}
|
|
50308
|
+
return;
|
|
50309
|
+
} catch {
|
|
50310
|
+
return;
|
|
50311
|
+
} finally {
|
|
50312
|
+
rmSync10(draft, { force: true });
|
|
50313
|
+
}
|
|
50314
|
+
}
|
|
50315
|
+
function entryPid(entry) {
|
|
50316
|
+
try {
|
|
50317
|
+
const pid = Number.parseInt(readFileSync29(entry, "utf-8"), 10);
|
|
50318
|
+
return Number.isInteger(pid) && pid > 0 ? pid : undefined;
|
|
50319
|
+
} catch {
|
|
50320
|
+
return;
|
|
50321
|
+
}
|
|
50322
|
+
}
|
|
50323
|
+
function removeAbandonedCopies(lockPath) {
|
|
50324
|
+
const prefix = `${basename2(lockPath)}.dead.`;
|
|
50325
|
+
let names;
|
|
50326
|
+
try {
|
|
50327
|
+
names = readdirSync4(dirname14(lockPath));
|
|
50328
|
+
} catch {
|
|
50329
|
+
return;
|
|
50330
|
+
}
|
|
50331
|
+
for (const name of names) {
|
|
50332
|
+
if (!name.startsWith(prefix))
|
|
50333
|
+
continue;
|
|
50334
|
+
const pid = Number.parseInt(name.slice(prefix.length), 10);
|
|
50335
|
+
if (!Number.isInteger(pid) || pid <= 0 || pidAlive(pid))
|
|
50336
|
+
continue;
|
|
50337
|
+
rmSync10(join29(dirname14(lockPath), name), { recursive: true, force: true });
|
|
50338
|
+
}
|
|
50339
|
+
}
|
|
50340
|
+
function signLock(lockPath) {
|
|
50341
|
+
const draft = join29(lockPath, `owner.${process.pid}`);
|
|
50342
|
+
writeFileSync11(draft, String(process.pid));
|
|
50343
|
+
renameSync8(draft, join29(lockPath, "owner"));
|
|
50344
|
+
}
|
|
50345
|
+
async function withMachineLock(lockPath, pollMs, work) {
|
|
50346
|
+
mkdirSync16(dirname14(lockPath), { recursive: true });
|
|
50347
|
+
removeAbandonedCopies(lockPath);
|
|
50348
|
+
const deadline = Date.now() + LOAD_TIMEOUT_MS2 + LIST_TIMEOUT_MS;
|
|
50349
|
+
for (;; ) {
|
|
50350
|
+
try {
|
|
50351
|
+
mkdirSync16(lockPath);
|
|
50352
|
+
break;
|
|
50353
|
+
} catch (error) {
|
|
50354
|
+
if (error.code !== "EEXIST")
|
|
50355
|
+
throw error;
|
|
50356
|
+
}
|
|
50357
|
+
const look = lookAtLock(lockPath);
|
|
50358
|
+
if (look === undefined)
|
|
50359
|
+
continue;
|
|
50360
|
+
if (!look.alive && takeOverStaleLock(lockPath, look.identity))
|
|
50361
|
+
continue;
|
|
50362
|
+
if (Date.now() > deadline) {
|
|
50363
|
+
throw new Error(`Another claudish process is placing an LM Studio model (lock ${lockPath}). Retry when it finishes.`);
|
|
50364
|
+
}
|
|
50365
|
+
await new Promise((resolve) => setTimeout(resolve, pollMs));
|
|
50366
|
+
}
|
|
50367
|
+
let own;
|
|
50368
|
+
try {
|
|
50369
|
+
signLock(lockPath);
|
|
50370
|
+
own = lockIdentity(lockPath);
|
|
50371
|
+
return await work();
|
|
50372
|
+
} finally {
|
|
50373
|
+
if (own === undefined || lockIdentity(lockPath) === own) {
|
|
50374
|
+
rmSync10(lockPath, { recursive: true, force: true });
|
|
50375
|
+
}
|
|
50376
|
+
}
|
|
50377
|
+
}
|
|
50378
|
+
function serialized(work) {
|
|
50379
|
+
const result = machineQueue.then(work, work);
|
|
50380
|
+
machineQueue = result.catch(() => {
|
|
50381
|
+
return;
|
|
50382
|
+
});
|
|
50383
|
+
return result;
|
|
50384
|
+
}
|
|
50385
|
+
function requireMachine(link, device) {
|
|
50386
|
+
const wanted = device.toLowerCase();
|
|
50387
|
+
if (wanted === LMSTUDIO_THIS_MACHINE)
|
|
50388
|
+
return link.self;
|
|
50389
|
+
const peer = link.peers.find((p) => p.id.toLowerCase() === wanted || machineLabel(p).toLowerCase() === wanted);
|
|
50390
|
+
if (peer)
|
|
50391
|
+
return peer.id;
|
|
50392
|
+
const known = [LMSTUDIO_THIS_MACHINE, ...link.peers.map(machineLabel)].join(", ");
|
|
50393
|
+
throw new Error(`LM Studio machine "${device}" is not connected through LM Link. Connected: ${known}.`);
|
|
50394
|
+
}
|
|
50395
|
+
function loadContextLength(stored, model, device, link, wanted) {
|
|
50396
|
+
if (wanted === undefined)
|
|
50397
|
+
return;
|
|
50398
|
+
const copy = stored?.find((row) => row.modelKey === model && (row.deviceIdentifier ?? link.self) === device);
|
|
50399
|
+
return copy?.maxContextLength ? Math.min(wanted, copy.maxContextLength) : wanted;
|
|
50400
|
+
}
|
|
50401
|
+
function assertContextLength(identifier, actual, wanted) {
|
|
50402
|
+
if (wanted === undefined || actual === undefined || actual >= wanted)
|
|
50403
|
+
return;
|
|
50404
|
+
throw new Error(`LM Studio runs ${identifier} with ${actual} tokens of context and claudish needs ${wanted}. Reload it with more context in LM Studio, or pass --context-window ${actual} to accept this size.`);
|
|
50405
|
+
}
|
|
50406
|
+
function ambiguityError(identifier) {
|
|
50407
|
+
return new Error(`LM Studio has instances named ${identifier} on more than one machine, so a request cannot select one. Unload one of them in LM Studio.`);
|
|
50408
|
+
}
|
|
50409
|
+
async function ensureLMStudioInstance(options) {
|
|
50410
|
+
const {
|
|
50411
|
+
baseUrl,
|
|
50412
|
+
model,
|
|
50413
|
+
device,
|
|
50414
|
+
headers,
|
|
50415
|
+
contextLength,
|
|
50416
|
+
run = runLms,
|
|
50417
|
+
log,
|
|
50418
|
+
lockPath = defaultLockPath2(),
|
|
50419
|
+
lockPollMs = LOCK_POLL_MS2
|
|
50420
|
+
} = options;
|
|
50421
|
+
if (!isLoopbackUrl(baseUrl)) {
|
|
50422
|
+
throw new Error(`LM Studio at ${baseUrl} is on another host, so claudish cannot choose the machine "${device}" there. Remove the ~${device} suffix.`);
|
|
50423
|
+
}
|
|
50424
|
+
return serialized(() => withMachineLock(lockPath, lockPollMs, async () => {
|
|
50425
|
+
const link = await readLink(run);
|
|
50426
|
+
if (!link)
|
|
50427
|
+
throw new Error("Could not read LM Link status: `lms link status --json` failed.");
|
|
50428
|
+
const target = requireMachine(link, device);
|
|
50429
|
+
const isOnTarget = (row) => (row.deviceIdentifier ?? link.self) === target;
|
|
50430
|
+
const isThisMachine = target === link.self;
|
|
50431
|
+
const identifier = isThisMachine ? `${model}${LMSTUDIO_DEVICE_SEPARATOR}${LMSTUDIO_THIS_MACHINE}` : model;
|
|
50432
|
+
const before = await readLoaded(run);
|
|
50433
|
+
if (!before)
|
|
50434
|
+
throw listError();
|
|
50435
|
+
const hasNamesake = (name) => before.some((row) => row.identifier === name && !isOnTarget(row));
|
|
50436
|
+
const stored = parseJson(await run(["ls", "--json"], LIST_TIMEOUT_MS));
|
|
50437
|
+
const length = loadContextLength(stored, model, target, link, contextLength);
|
|
50438
|
+
const running = before.find((row) => row.modelKey === model && isOnTarget(row));
|
|
50439
|
+
if (running) {
|
|
50440
|
+
if (hasNamesake(running.identifier))
|
|
50441
|
+
throw ambiguityError(running.identifier);
|
|
50442
|
+
assertContextLength(running.identifier, running.contextLength, length);
|
|
50443
|
+
return { instanceId: running.identifier, contextLength: running.contextLength };
|
|
50444
|
+
}
|
|
50445
|
+
if (hasNamesake(identifier))
|
|
50446
|
+
throw ambiguityError(identifier);
|
|
50447
|
+
let expected = identifier;
|
|
50448
|
+
if (isThisMachine) {
|
|
50449
|
+
const lengthArgs = length === undefined ? [] : ["-c", String(length)];
|
|
50450
|
+
const loaded = await run(["load", model, "--identifier", identifier, "-y", ...lengthArgs], LOAD_TIMEOUT_MS2);
|
|
50451
|
+
if (loaded === null)
|
|
50452
|
+
throw new Error(`LM Studio could not load ${model} on this machine.`);
|
|
50453
|
+
} else {
|
|
50454
|
+
const reported = await loadOnLinkedMachine({ baseUrl, model, device, headers, run, log }, link, target, length);
|
|
50455
|
+
expected = reported ?? identifier;
|
|
50456
|
+
}
|
|
50457
|
+
const after = await readLoaded(run);
|
|
50458
|
+
if (!after)
|
|
50459
|
+
throw listError();
|
|
50460
|
+
const placed = after.find((row) => row.identifier === expected && isOnTarget(row));
|
|
50461
|
+
if (!placed) {
|
|
50462
|
+
throw new Error(`LM Studio loaded ${model} on a different machine than ${device}. Another LM Link client may have changed the preferred device; retry.`);
|
|
50463
|
+
}
|
|
50464
|
+
if (after.some((row) => row.identifier === expected && !isOnTarget(row))) {
|
|
50465
|
+
throw ambiguityError(expected);
|
|
50466
|
+
}
|
|
50467
|
+
assertContextLength(placed.identifier, placed.contextLength, length);
|
|
50468
|
+
return { instanceId: placed.identifier, contextLength: placed.contextLength };
|
|
50469
|
+
}));
|
|
50470
|
+
}
|
|
50471
|
+
function listError() {
|
|
50472
|
+
return new Error("Could not list the running LM Studio instances: `lms ps --json` failed. Without that list claudish cannot tell which machine a model name reaches.");
|
|
50473
|
+
}
|
|
50474
|
+
async function loadOnLinkedMachine(options, link, target, contextLength) {
|
|
50475
|
+
const { baseUrl, model, device, headers, run, log } = options;
|
|
50476
|
+
const original = link.preferred;
|
|
50477
|
+
const mustSwitch = original !== target;
|
|
50478
|
+
if (mustSwitch) {
|
|
50479
|
+
const switched = await run(["link", "set-preferred-device", target], LIST_TIMEOUT_MS);
|
|
50480
|
+
if (switched === null)
|
|
50481
|
+
throw new Error(`Could not select LM Link device ${device}.`);
|
|
50482
|
+
}
|
|
50483
|
+
try {
|
|
50484
|
+
const response = await fetch(`${baseUrl}/api/v1/models/load`, {
|
|
50485
|
+
method: "POST",
|
|
50486
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
50487
|
+
body: JSON.stringify({
|
|
50488
|
+
model,
|
|
50489
|
+
...contextLength === undefined ? {} : { context_length: contextLength }
|
|
50490
|
+
}),
|
|
50491
|
+
signal: AbortSignal.timeout(LOAD_TIMEOUT_MS2)
|
|
50492
|
+
});
|
|
50493
|
+
if (!response.ok) {
|
|
50494
|
+
const body = redactExactValues(await response.text(), credentialValuesFromRequest(headers));
|
|
50495
|
+
throw new Error(`LM Studio could not load ${model} on ${device}: ${response.status} ${body}`);
|
|
50496
|
+
}
|
|
50497
|
+
const body = await response.json().catch(() => null);
|
|
50498
|
+
return typeof body?.instance_id === "string" && body.instance_id !== "" ? body.instance_id : undefined;
|
|
50499
|
+
} finally {
|
|
50500
|
+
if (mustSwitch && original) {
|
|
50501
|
+
const restored = await run(["link", "set-preferred-device", original], LIST_TIMEOUT_MS);
|
|
50502
|
+
if (restored === null)
|
|
50503
|
+
log?.(`Could not restore LM Link preferred device ${original}.`);
|
|
50504
|
+
}
|
|
50505
|
+
}
|
|
50506
|
+
}
|
|
50507
|
+
var LMSTUDIO_DEVICE_SEPARATOR = "~", LMSTUDIO_THIS_MACHINE = "local", LIST_TIMEOUT_MS = 5000, LOAD_TIMEOUT_MS2 = 600000, runLms = async (args, timeoutMs) => {
|
|
50508
|
+
const configured = process.env.CLAUDISH_LMS_BIN;
|
|
50509
|
+
if (configured)
|
|
50510
|
+
return (await execLms(configured, args, timeoutMs)).stdout;
|
|
50511
|
+
const onPath = await execLms("lms", args, timeoutMs);
|
|
50512
|
+
if (!onPath.missing)
|
|
50513
|
+
return onPath.stdout;
|
|
50514
|
+
return (await execLms(join29(homedir28(), ".lmstudio", "bin", "lms"), args, timeoutMs)).stdout;
|
|
50515
|
+
}, THIS_MACHINE_NAME = "this Mac", LOCK_POLL_MS2 = 250, CLAIM = "takeover", MAX_CLAIM_CHAIN = 64, machineQueue;
|
|
50516
|
+
var init_lmstudio_devices = __esm(() => {
|
|
50517
|
+
init_call_context();
|
|
50518
|
+
init_redact();
|
|
50519
|
+
machineQueue = Promise.resolve();
|
|
50520
|
+
});
|
|
50521
|
+
|
|
50068
50522
|
// src/providers/devin/proto-codec.ts
|
|
50069
50523
|
function cat(parts) {
|
|
50070
50524
|
let total = 0;
|
|
@@ -51076,7 +51530,31 @@ function readCreatedDate(row) {
|
|
|
51076
51530
|
const iso = new Date(seconds * 1000).toISOString();
|
|
51077
51531
|
return iso.slice(0, 10);
|
|
51078
51532
|
}
|
|
51079
|
-
function
|
|
51533
|
+
function readLMStudioContextWindow(row) {
|
|
51534
|
+
const loaded = positive(row.loaded_context_length);
|
|
51535
|
+
if (loaded !== undefined)
|
|
51536
|
+
return loaded;
|
|
51537
|
+
const max = positive(row.max_context_length);
|
|
51538
|
+
const wanted = getProviderByName("lmstudio")?.unknownContextWindow;
|
|
51539
|
+
return max !== undefined && wanted !== undefined && max < wanted ? max : undefined;
|
|
51540
|
+
}
|
|
51541
|
+
function ceilingOf(row) {
|
|
51542
|
+
const ceiling = positive(row.max_context_length);
|
|
51543
|
+
return ceiling === undefined ? {} : { contextCeiling: ceiling };
|
|
51544
|
+
}
|
|
51545
|
+
function positive(value) {
|
|
51546
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : undefined;
|
|
51547
|
+
}
|
|
51548
|
+
async function withLMStudioMachines(models, baseUrl) {
|
|
51549
|
+
if (!isLoopbackUrl(baseUrl))
|
|
51550
|
+
return models;
|
|
51551
|
+
const machines = await readLMStudioMachines();
|
|
51552
|
+
if (!machines)
|
|
51553
|
+
return models;
|
|
51554
|
+
return expandModelsToMachines(models, machines, getProviderByName("lmstudio")?.unknownContextWindow);
|
|
51555
|
+
}
|
|
51556
|
+
function parseOpenAIModelsList(body, format) {
|
|
51557
|
+
const isLMStudio = format === "lmstudio-models";
|
|
51080
51558
|
const data = body?.data;
|
|
51081
51559
|
if (!Array.isArray(data))
|
|
51082
51560
|
return { models: [], dropped: 0, total: null };
|
|
@@ -51097,8 +51575,10 @@ function parseOpenAIModelsList(body) {
|
|
|
51097
51575
|
models.push({
|
|
51098
51576
|
id,
|
|
51099
51577
|
displayName,
|
|
51100
|
-
contextWindow: readContextWindow(row),
|
|
51101
|
-
releaseDate: readCreatedDate(row)
|
|
51578
|
+
contextWindow: isLMStudio ? readLMStudioContextWindow(row) : readContextWindow(row),
|
|
51579
|
+
releaseDate: readCreatedDate(row),
|
|
51580
|
+
...isLMStudio ? { reported: lmStudioReported(row) } : {},
|
|
51581
|
+
...isLMStudio ? ceilingOf(row) : {}
|
|
51102
51582
|
});
|
|
51103
51583
|
}
|
|
51104
51584
|
return { models, dropped, total: data.length };
|
|
@@ -51223,9 +51703,10 @@ async function fetchServedModels(providerName) {
|
|
|
51223
51703
|
const descriptor = def?.modelDiscovery;
|
|
51224
51704
|
if (!def || !descriptor)
|
|
51225
51705
|
return { kind: "unsupported", reason: "no-descriptor" };
|
|
51226
|
-
if (descriptor.format !== "openai-models-list") {
|
|
51706
|
+
if (descriptor.format !== "openai-models-list" && descriptor.format !== "lmstudio-models") {
|
|
51227
51707
|
return await discoverViaFetcher(providerName, descriptor.format);
|
|
51228
51708
|
}
|
|
51709
|
+
const isLMStudio = descriptor.format === "lmstudio-models";
|
|
51229
51710
|
const baseUrl = resolveBaseUrl(providerName);
|
|
51230
51711
|
if (!baseUrl) {
|
|
51231
51712
|
const overrides = (def.baseUrlEnvVars ?? []).join(", ");
|
|
@@ -51236,7 +51717,8 @@ async function fetchServedModels(providerName) {
|
|
|
51236
51717
|
});
|
|
51237
51718
|
}
|
|
51238
51719
|
const definitionEndpoint = `${baseUrl}${descriptor.path}`;
|
|
51239
|
-
let endpoint = registryModelsEndpoint(providerName, def) ?? definitionEndpoint;
|
|
51720
|
+
let endpoint = isLMStudio ? definitionEndpoint : registryModelsEndpoint(providerName, def) ?? definitionEndpoint;
|
|
51721
|
+
let bodyFormat = descriptor.format;
|
|
51240
51722
|
let headers = {};
|
|
51241
51723
|
if (def.isLocal) {
|
|
51242
51724
|
const key = def.apiKeyEnvVar ? process.env[def.apiKeyEnvVar] : undefined;
|
|
@@ -51271,6 +51753,11 @@ async function fetchServedModels(providerName) {
|
|
|
51271
51753
|
endpoint = definitionEndpoint;
|
|
51272
51754
|
response = await fetchList(endpoint);
|
|
51273
51755
|
}
|
|
51756
|
+
if (response.status === 404 && isLMStudio) {
|
|
51757
|
+
endpoint = `${baseUrl}/v1/models`;
|
|
51758
|
+
bodyFormat = "openai-models-list";
|
|
51759
|
+
response = await fetchList(endpoint);
|
|
51760
|
+
}
|
|
51274
51761
|
} catch (e) {
|
|
51275
51762
|
return recordFailure({
|
|
51276
51763
|
kind: "unreachable",
|
|
@@ -51299,7 +51786,7 @@ async function fetchServedModels(providerName) {
|
|
|
51299
51786
|
} catch {
|
|
51300
51787
|
return recordFailure({ kind: "malformed", provider: providerName, endpoint });
|
|
51301
51788
|
}
|
|
51302
|
-
const parsed = parseOpenAIModelsList(body);
|
|
51789
|
+
const parsed = parseOpenAIModelsList(body, bodyFormat);
|
|
51303
51790
|
const incomplete = describeIncompleteness(body, parsed);
|
|
51304
51791
|
if (incomplete) {
|
|
51305
51792
|
return recordFailure({
|
|
@@ -51309,7 +51796,7 @@ async function fetchServedModels(providerName) {
|
|
|
51309
51796
|
detail: incomplete
|
|
51310
51797
|
});
|
|
51311
51798
|
}
|
|
51312
|
-
const models = parsed.models;
|
|
51799
|
+
const models = isLMStudio ? await withLMStudioMachines(parsed.models, baseUrl) : parsed.models;
|
|
51313
51800
|
_failures.delete(providerName);
|
|
51314
51801
|
log(`[model-discovery:${providerName}] discovered ${models.length} models from ${endpoint}: ` + models.map((m) => `${m.id}(${m.contextWindow ?? "?"})`).join(", "));
|
|
51315
51802
|
return { kind: "served", models };
|
|
@@ -51318,16 +51805,27 @@ async function discoverProviderModels(providerName) {
|
|
|
51318
51805
|
const outcome = await discoverProviderModelsCatalog(providerName);
|
|
51319
51806
|
return outcome.kind === "served" ? outcome.models : [];
|
|
51320
51807
|
}
|
|
51321
|
-
function windowOf(models, modelId) {
|
|
51808
|
+
function windowOf(models, modelId, upTo) {
|
|
51322
51809
|
const needle = modelId.toLowerCase();
|
|
51323
|
-
|
|
51810
|
+
const exact = models.find((m) => m.id.toLowerCase() === needle);
|
|
51811
|
+
if (exact)
|
|
51812
|
+
return rowWindow(exact, upTo);
|
|
51813
|
+
const windows = models.filter((m) => m.machine?.modelId.toLowerCase() === needle).map((m) => rowWindow(m, upTo)).filter((w) => w !== undefined);
|
|
51814
|
+
return windows.length > 0 ? Math.min(...windows) : undefined;
|
|
51815
|
+
}
|
|
51816
|
+
function rowWindow(model, upTo) {
|
|
51817
|
+
if (model.contextWindow !== undefined)
|
|
51818
|
+
return model.contextWindow;
|
|
51819
|
+
const ceiling = model.contextCeiling;
|
|
51820
|
+
return upTo !== undefined && ceiling !== undefined && ceiling < upTo ? ceiling : undefined;
|
|
51324
51821
|
}
|
|
51325
51822
|
async function discoverContextWindow(providerName, modelId, opts = {}) {
|
|
51823
|
+
const { upTo } = opts;
|
|
51326
51824
|
if (opts.network === "cached-first") {
|
|
51327
51825
|
await Promise.resolve().then(() => init_dynamic_models_catalog());
|
|
51328
51826
|
const stored = await readAccountModelsList(providerName);
|
|
51329
51827
|
if (stored)
|
|
51330
|
-
return windowOf(stored.models, modelId);
|
|
51828
|
+
return windowOf(stored.models, modelId, upTo);
|
|
51331
51829
|
coldRefresh(providerName);
|
|
51332
51830
|
return;
|
|
51333
51831
|
}
|
|
@@ -51337,13 +51835,13 @@ async function discoverContextWindow(providerName, modelId, opts = {}) {
|
|
|
51337
51835
|
timer = setTimeout(() => resolve([]), LIVE_DISCOVERY_BOUND_MS);
|
|
51338
51836
|
});
|
|
51339
51837
|
try {
|
|
51340
|
-
return windowOf(await Promise.race([coldRefresh(providerName), bound]), modelId);
|
|
51838
|
+
return windowOf(await Promise.race([coldRefresh(providerName), bound]), modelId, upTo);
|
|
51341
51839
|
} finally {
|
|
51342
51840
|
clearTimeout(timer);
|
|
51343
51841
|
}
|
|
51344
51842
|
}
|
|
51345
51843
|
const { served, optIn } = await discoverProviderServedIds(providerName);
|
|
51346
|
-
return windowOf([...served, ...optIn], modelId);
|
|
51844
|
+
return windowOf([...served, ...optIn], modelId, upTo);
|
|
51347
51845
|
}
|
|
51348
51846
|
function coldRefresh(providerName) {
|
|
51349
51847
|
const running = coldRefreshes.get(providerName);
|
|
@@ -51379,7 +51877,9 @@ var init_model_discovery = __esm(() => {
|
|
|
51379
51877
|
init_authority();
|
|
51380
51878
|
init_logger();
|
|
51381
51879
|
init_connection_resolver();
|
|
51880
|
+
init_lmstudio_devices();
|
|
51382
51881
|
init_provider_definitions();
|
|
51882
|
+
init_probe_discovery();
|
|
51383
51883
|
_fetchers = new Map;
|
|
51384
51884
|
CACHE_TTL_MS2 = 5 * 60 * 1000;
|
|
51385
51885
|
_cache2 = new Map;
|
|
@@ -51941,7 +52441,7 @@ var init_wire_markers = __esm(() => {
|
|
|
51941
52441
|
});
|
|
51942
52442
|
|
|
51943
52443
|
// src/providers/catalog-query.ts
|
|
51944
|
-
import { statSync as
|
|
52444
|
+
import { statSync as statSync10 } from "fs";
|
|
51945
52445
|
function project(entry) {
|
|
51946
52446
|
return {
|
|
51947
52447
|
modelId: entry.modelId,
|
|
@@ -51955,7 +52455,7 @@ function project(entry) {
|
|
|
51955
52455
|
function getCachedEntries() {
|
|
51956
52456
|
let mtimeMs;
|
|
51957
52457
|
try {
|
|
51958
|
-
mtimeMs =
|
|
52458
|
+
mtimeMs = statSync10(ALL_MODELS_CACHE_PATH).mtimeMs;
|
|
51959
52459
|
} catch {
|
|
51960
52460
|
return null;
|
|
51961
52461
|
}
|
|
@@ -52128,17 +52628,17 @@ var init_vision_proxy = __esm(() => {
|
|
|
52128
52628
|
});
|
|
52129
52629
|
|
|
52130
52630
|
// src/mcp-session/home-dir.ts
|
|
52131
|
-
import { homedir as
|
|
52132
|
-
import { join as
|
|
52133
|
-
function userHomeFrom(env, homedirFn =
|
|
52631
|
+
import { homedir as homedir29 } from "os";
|
|
52632
|
+
import { join as join30 } from "path";
|
|
52633
|
+
function userHomeFrom(env, homedirFn = homedir29) {
|
|
52134
52634
|
const home = env.HOME;
|
|
52135
52635
|
return home && home.length > 0 ? home : homedirFn();
|
|
52136
52636
|
}
|
|
52137
|
-
function sessionsDirFrom(env, homedirFn =
|
|
52637
|
+
function sessionsDirFrom(env, homedirFn = homedir29) {
|
|
52138
52638
|
const explicit = env.CLAUDISH_SESSIONS_DIR;
|
|
52139
52639
|
if (explicit && explicit.length > 0)
|
|
52140
52640
|
return explicit;
|
|
52141
|
-
return
|
|
52641
|
+
return join30(userHomeFrom(env, homedirFn), ".claudish", "sessions");
|
|
52142
52642
|
}
|
|
52143
52643
|
function claudeCodeStringHash(s) {
|
|
52144
52644
|
let h = 0;
|
|
@@ -52229,7 +52729,7 @@ function reduceEvent(state, event) {
|
|
|
52229
52729
|
}
|
|
52230
52730
|
|
|
52231
52731
|
// src/session-events/transcript-tailer.ts
|
|
52232
|
-
import { closeSync as closeSync9, openSync as openSync9, readSync as readSync2, statSync as
|
|
52732
|
+
import { closeSync as closeSync9, openSync as openSync9, readSync as readSync2, statSync as statSync11 } from "fs";
|
|
52233
52733
|
|
|
52234
52734
|
class TranscriptTailer {
|
|
52235
52735
|
filePath;
|
|
@@ -52274,7 +52774,7 @@ class TranscriptTailer {
|
|
|
52274
52774
|
if (this.disposed)
|
|
52275
52775
|
return;
|
|
52276
52776
|
try {
|
|
52277
|
-
const size =
|
|
52777
|
+
const size = statSync11(this.filePath).size;
|
|
52278
52778
|
if (size < this.offset) {
|
|
52279
52779
|
this.offset = 0;
|
|
52280
52780
|
this.buffer = "";
|
|
@@ -52311,9 +52811,9 @@ var DEFAULT_POLL_INTERVAL_MS = 250;
|
|
|
52311
52811
|
var init_transcript_tailer = () => {};
|
|
52312
52812
|
|
|
52313
52813
|
// src/session-events/index.ts
|
|
52314
|
-
import { existsSync as existsSync22, readFileSync as
|
|
52315
|
-
import { homedir as
|
|
52316
|
-
import { join as
|
|
52814
|
+
import { existsSync as existsSync22, readFileSync as readFileSync30, readdirSync as readdirSync5 } from "fs";
|
|
52815
|
+
import { homedir as homedir30 } from "os";
|
|
52816
|
+
import { join as join31 } from "path";
|
|
52317
52817
|
function extractSessionId2(metadata) {
|
|
52318
52818
|
const userId = metadata?.user_id;
|
|
52319
52819
|
if (typeof userId !== "string")
|
|
@@ -52338,7 +52838,7 @@ class SessionEventRegistry {
|
|
|
52338
52838
|
claudeHome;
|
|
52339
52839
|
pollIntervalMs;
|
|
52340
52840
|
constructor(opts = {}) {
|
|
52341
|
-
this.claudeHome = opts.claudeHome ??
|
|
52841
|
+
this.claudeHome = opts.claudeHome ?? join31(homedir30(), ".claude");
|
|
52342
52842
|
this.pollIntervalMs = opts.pollIntervalMs;
|
|
52343
52843
|
}
|
|
52344
52844
|
ensureSession(sessionId) {
|
|
@@ -52424,13 +52924,13 @@ class SessionEventRegistry {
|
|
|
52424
52924
|
}
|
|
52425
52925
|
}
|
|
52426
52926
|
locateTranscript(sessionId) {
|
|
52427
|
-
const projectsDir =
|
|
52428
|
-
const primary =
|
|
52927
|
+
const projectsDir = join31(this.claudeHome, "projects");
|
|
52928
|
+
const primary = join31(projectsDir, slugFromCwd(process.cwd()), `${sessionId}.jsonl`);
|
|
52429
52929
|
if (existsSync22(primary))
|
|
52430
52930
|
return primary;
|
|
52431
52931
|
try {
|
|
52432
|
-
for (const dir of
|
|
52433
|
-
const candidate =
|
|
52932
|
+
for (const dir of readdirSync5(projectsDir)) {
|
|
52933
|
+
const candidate = join31(projectsDir, dir, `${sessionId}.jsonl`);
|
|
52434
52934
|
if (existsSync22(candidate))
|
|
52435
52935
|
return candidate;
|
|
52436
52936
|
}
|
|
@@ -52439,7 +52939,7 @@ class SessionEventRegistry {
|
|
|
52439
52939
|
}
|
|
52440
52940
|
readSettingsEffortLevel() {
|
|
52441
52941
|
try {
|
|
52442
|
-
const settings = JSON.parse(
|
|
52942
|
+
const settings = JSON.parse(readFileSync30(join31(this.claudeHome, "settings.json"), "utf-8"));
|
|
52443
52943
|
return typeof settings.effortLevel === "string" ? settings.effortLevel : undefined;
|
|
52444
52944
|
} catch {
|
|
52445
52945
|
return;
|
|
@@ -52543,24 +53043,24 @@ var claimed = false;
|
|
|
52543
53043
|
// src/stats-buffer.ts
|
|
52544
53044
|
import {
|
|
52545
53045
|
existsSync as existsSync23,
|
|
52546
|
-
mkdirSync as
|
|
52547
|
-
readFileSync as
|
|
52548
|
-
renameSync as
|
|
53046
|
+
mkdirSync as mkdirSync17,
|
|
53047
|
+
readFileSync as readFileSync31,
|
|
53048
|
+
renameSync as renameSync9,
|
|
52549
53049
|
unlinkSync as unlinkSync8,
|
|
52550
|
-
writeFileSync as
|
|
53050
|
+
writeFileSync as writeFileSync12
|
|
52551
53051
|
} from "fs";
|
|
52552
|
-
import { homedir as
|
|
52553
|
-
import { join as
|
|
53052
|
+
import { homedir as homedir31 } from "os";
|
|
53053
|
+
import { join as join32 } from "path";
|
|
52554
53054
|
function ensureDir() {
|
|
52555
53055
|
if (!existsSync23(CLAUDISH_DIR)) {
|
|
52556
|
-
|
|
53056
|
+
mkdirSync17(CLAUDISH_DIR, { recursive: true });
|
|
52557
53057
|
}
|
|
52558
53058
|
}
|
|
52559
53059
|
function readFromDisk() {
|
|
52560
53060
|
try {
|
|
52561
53061
|
if (!existsSync23(BUFFER_FILE))
|
|
52562
53062
|
return [];
|
|
52563
|
-
const raw =
|
|
53063
|
+
const raw = readFileSync31(BUFFER_FILE, "utf-8");
|
|
52564
53064
|
const parsed = JSON.parse(raw);
|
|
52565
53065
|
if (!Array.isArray(parsed.events))
|
|
52566
53066
|
return [];
|
|
@@ -52585,9 +53085,9 @@ function writeToDisk(events) {
|
|
|
52585
53085
|
ensureDir();
|
|
52586
53086
|
const trimmed = enforceSizeCap([...events]);
|
|
52587
53087
|
const payload = { version: 1, events: trimmed };
|
|
52588
|
-
const tmpFile =
|
|
52589
|
-
|
|
52590
|
-
|
|
53088
|
+
const tmpFile = join32(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
|
|
53089
|
+
writeFileSync12(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
|
|
53090
|
+
renameSync9(tmpFile, BUFFER_FILE);
|
|
52591
53091
|
memoryCache = trimmed;
|
|
52592
53092
|
} catch {}
|
|
52593
53093
|
}
|
|
@@ -52658,8 +53158,8 @@ function syncFlushOnExit() {
|
|
|
52658
53158
|
var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false, SIGNAL_EXIT_CODE;
|
|
52659
53159
|
var init_stats_buffer = __esm(() => {
|
|
52660
53160
|
BUFFER_MAX_BYTES = 64 * 1024;
|
|
52661
|
-
CLAUDISH_DIR =
|
|
52662
|
-
BUFFER_FILE =
|
|
53161
|
+
CLAUDISH_DIR = join32(homedir31(), ".claudish");
|
|
53162
|
+
BUFFER_FILE = join32(CLAUDISH_DIR, "stats-buffer.json");
|
|
52663
53163
|
process.on("exit", syncFlushOnExit);
|
|
52664
53164
|
SIGNAL_EXIT_CODE = { SIGTERM: 143, SIGINT: 130 };
|
|
52665
53165
|
for (const signal of ["SIGTERM", "SIGINT"]) {
|
|
@@ -56741,7 +57241,7 @@ var init_openai_responses_sse = __esm(() => {
|
|
|
56741
57241
|
});
|
|
56742
57242
|
|
|
56743
57243
|
// src/session/token-file.ts
|
|
56744
|
-
import { join as
|
|
57244
|
+
import { join as join33 } from "path";
|
|
56745
57245
|
function assignedTokenFile(env) {
|
|
56746
57246
|
const f = env.CLAUDISH_TOKEN_FILE;
|
|
56747
57247
|
if (!f || f === env.CLAUDISH_PUBLISHED_TOKEN_FILE)
|
|
@@ -56749,15 +57249,15 @@ function assignedTokenFile(env) {
|
|
|
56749
57249
|
return f;
|
|
56750
57250
|
}
|
|
56751
57251
|
function resolveTokenFilePath(port, env = process.env) {
|
|
56752
|
-
return assignedTokenFile(env) ??
|
|
57252
|
+
return assignedTokenFile(env) ?? join33(userHomeFrom(env), ".claudish", `tokens-${port}.json`);
|
|
56753
57253
|
}
|
|
56754
57254
|
var init_token_file = __esm(() => {
|
|
56755
57255
|
init_home_dir();
|
|
56756
57256
|
});
|
|
56757
57257
|
|
|
56758
57258
|
// src/handlers/shared/token-tracker.ts
|
|
56759
|
-
import { mkdirSync as
|
|
56760
|
-
import { dirname as
|
|
57259
|
+
import { mkdirSync as mkdirSync18, writeFileSync as writeFileSync13 } from "fs";
|
|
57260
|
+
import { dirname as dirname15 } from "path";
|
|
56761
57261
|
function stripProviderPrefix(name) {
|
|
56762
57262
|
if (!hasProviderPrefix(name))
|
|
56763
57263
|
return name;
|
|
@@ -56998,8 +57498,8 @@ class TokenTracker {
|
|
|
56998
57498
|
};
|
|
56999
57499
|
}
|
|
57000
57500
|
const outPath = resolveTokenFilePath(this.port);
|
|
57001
|
-
|
|
57002
|
-
|
|
57501
|
+
mkdirSync18(dirname15(outPath), { recursive: true });
|
|
57502
|
+
writeFileSync13(outPath, JSON.stringify(data), "utf-8");
|
|
57003
57503
|
} catch (e) {
|
|
57004
57504
|
log(`[TokenTracker] Error writing token file: ${e}`);
|
|
57005
57505
|
}
|
|
@@ -59256,11 +59756,11 @@ var init_composed_handler = __esm(() => {
|
|
|
59256
59756
|
});
|
|
59257
59757
|
|
|
59258
59758
|
// src/providers/api-key-provenance.ts
|
|
59259
|
-
import { existsSync as existsSync24, readFileSync as
|
|
59260
|
-
import { homedir as
|
|
59261
|
-
import { join as
|
|
59759
|
+
import { existsSync as existsSync24, readFileSync as readFileSync32 } from "fs";
|
|
59760
|
+
import { homedir as homedir32 } from "os";
|
|
59761
|
+
import { join as join34, resolve as resolve3 } from "path";
|
|
59262
59762
|
function activeConfigPath() {
|
|
59263
|
-
return activeGlobalConfigFile(
|
|
59763
|
+
return activeGlobalConfigFile(join34(homedir32(), ".claudish", "config.json"));
|
|
59264
59764
|
}
|
|
59265
59765
|
function configLayerLabel() {
|
|
59266
59766
|
return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
|
|
@@ -59387,7 +59887,7 @@ function readDotenvKey(envVars) {
|
|
|
59387
59887
|
const dotenvPath = resolve3(".env");
|
|
59388
59888
|
if (!existsSync24(dotenvPath))
|
|
59389
59889
|
return null;
|
|
59390
|
-
const parsed = readAllowedDotenv(
|
|
59890
|
+
const parsed = readAllowedDotenv(readFileSync32(dotenvPath, "utf-8"));
|
|
59391
59891
|
for (const v of envVars) {
|
|
59392
59892
|
if (parsed[v])
|
|
59393
59893
|
return parsed[v];
|
|
@@ -59402,7 +59902,7 @@ function readConfigKey(envVar) {
|
|
|
59402
59902
|
const configPath = activeConfigPath();
|
|
59403
59903
|
if (!existsSync24(configPath))
|
|
59404
59904
|
return null;
|
|
59405
|
-
const cfg = JSON.parse(
|
|
59905
|
+
const cfg = JSON.parse(readFileSync32(configPath, "utf-8"));
|
|
59406
59906
|
return cfg.apiKeys?.[envVar] || null;
|
|
59407
59907
|
} catch {
|
|
59408
59908
|
return null;
|
|
@@ -61591,6 +62091,7 @@ var geminiHandler, antigravityHandler, devinHandler, grokSubscriptionHandler, mu
|
|
|
61591
62091
|
var init_provider_definitions = __esm(() => {
|
|
61592
62092
|
init_vertex_auth();
|
|
61593
62093
|
init_profile_config();
|
|
62094
|
+
init_context_window_limit();
|
|
61594
62095
|
init_runtime_providers();
|
|
61595
62096
|
geminiHandler = lazyHandler((m) => m.geminiProfile);
|
|
61596
62097
|
antigravityHandler = lazyHandler((m) => m.antigravityProfile);
|
|
@@ -62141,7 +62642,8 @@ var init_provider_definitions = __esm(() => {
|
|
|
62141
62642
|
{ prefix: "mlstudio:", stripPrefix: true }
|
|
62142
62643
|
],
|
|
62143
62644
|
isLocal: true,
|
|
62144
|
-
modelDiscovery: { path: "/
|
|
62645
|
+
modelDiscovery: { path: "/api/v0/models", format: "lmstudio-models" },
|
|
62646
|
+
unknownContextWindow: DEFAULT_LOCAL_CONTEXT_WINDOW,
|
|
62145
62647
|
description: "Local LM Studio (lms@)"
|
|
62146
62648
|
},
|
|
62147
62649
|
{
|
|
@@ -73156,9 +73658,9 @@ function compareByConnectionPrice(a, b) {
|
|
|
73156
73658
|
}
|
|
73157
73659
|
|
|
73158
73660
|
// src/providers/probe-catalog.ts
|
|
73159
|
-
import { existsSync as existsSync25, mkdirSync as
|
|
73160
|
-
import { homedir as
|
|
73161
|
-
import { dirname as
|
|
73661
|
+
import { existsSync as existsSync25, mkdirSync as mkdirSync19, readFileSync as readFileSync33, writeFileSync as writeFileSync14 } from "fs";
|
|
73662
|
+
import { homedir as homedir33 } from "os";
|
|
73663
|
+
import { dirname as dirname16, join as join35 } from "path";
|
|
73162
73664
|
function describeProbeCatalogFailure(outcome) {
|
|
73163
73665
|
switch (outcome.kind) {
|
|
73164
73666
|
case "incompatible":
|
|
@@ -73178,15 +73680,15 @@ function readProbeModelsCache(path = PROBE_MODELS_CACHE_PATH) {
|
|
|
73178
73680
|
return null;
|
|
73179
73681
|
let raw;
|
|
73180
73682
|
try {
|
|
73181
|
-
raw = JSON.parse(
|
|
73683
|
+
raw = JSON.parse(readFileSync33(path, "utf-8"));
|
|
73182
73684
|
} catch {
|
|
73183
73685
|
return null;
|
|
73184
73686
|
}
|
|
73185
73687
|
return isValidResponse(raw) ? raw : null;
|
|
73186
73688
|
}
|
|
73187
73689
|
function writeProbeModelsCache(data, path = PROBE_MODELS_CACHE_PATH) {
|
|
73188
|
-
|
|
73189
|
-
|
|
73690
|
+
mkdirSync19(dirname16(path), { recursive: true });
|
|
73691
|
+
writeFileSync14(path, JSON.stringify(data), "utf-8");
|
|
73190
73692
|
}
|
|
73191
73693
|
function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
|
|
73192
73694
|
if (!data)
|
|
@@ -73330,7 +73832,7 @@ var init_probe_catalog = __esm(() => {
|
|
|
73330
73832
|
init_catalog_endpoints();
|
|
73331
73833
|
init_catalog_route_bindings();
|
|
73332
73834
|
CACHE_TTL_MS4 = 60 * 60 * 1000;
|
|
73333
|
-
PROBE_MODELS_CACHE_PATH =
|
|
73835
|
+
PROBE_MODELS_CACHE_PATH = join35(homedir33(), ".claudish", "probe-models.json");
|
|
73334
73836
|
});
|
|
73335
73837
|
|
|
73336
73838
|
// src/providers/route-candidates.ts
|
|
@@ -74812,10 +75314,10 @@ var init_prehydrate = __esm(() => {
|
|
|
74812
75314
|
|
|
74813
75315
|
// src/auth/claude-code-facts.ts
|
|
74814
75316
|
import { createHash as createHash17 } from "crypto";
|
|
74815
|
-
import { homedir as
|
|
75317
|
+
import { homedir as homedir34 } from "os";
|
|
74816
75318
|
import { isAbsolute as isAbsolute2, resolve as resolve4 } from "path";
|
|
74817
75319
|
function defaultConfigDir(env) {
|
|
74818
|
-
return resolve4(env.HOME ||
|
|
75320
|
+
return resolve4(env.HOME || homedir34(), ".claude");
|
|
74819
75321
|
}
|
|
74820
75322
|
function configDirHash(configDir) {
|
|
74821
75323
|
return createHash17("sha256").update(configDir).digest("hex").slice(0, 8);
|
|
@@ -75683,7 +76185,7 @@ var init_magmux_client = __esm(() => {
|
|
|
75683
76185
|
});
|
|
75684
76186
|
|
|
75685
76187
|
// src/pane/own-pane.ts
|
|
75686
|
-
import { execFile as
|
|
76188
|
+
import { execFile as execFile3 } from "child_process";
|
|
75687
76189
|
import { promisify as promisify5 } from "util";
|
|
75688
76190
|
async function ancestorPids(maxDepth = ANCESTRY_DEPTH) {
|
|
75689
76191
|
const out = new Set([process.pid]);
|
|
@@ -75733,12 +76235,12 @@ async function findOwnPane(list, ancestors = () => ancestorPids()) {
|
|
|
75733
76235
|
}
|
|
75734
76236
|
var execFileAsync2, ANCESTRY_DEPTH = 6;
|
|
75735
76237
|
var init_own_pane = __esm(() => {
|
|
75736
|
-
execFileAsync2 = promisify5(
|
|
76238
|
+
execFileAsync2 = promisify5(execFile3);
|
|
75737
76239
|
});
|
|
75738
76240
|
|
|
75739
76241
|
// src/pane/prompt-delivery.ts
|
|
75740
|
-
import { writeFileSync as
|
|
75741
|
-
import { join as
|
|
76242
|
+
import { writeFileSync as writeFileSync15 } from "fs";
|
|
76243
|
+
import { join as join36 } from "path";
|
|
75742
76244
|
function stripControl(s) {
|
|
75743
76245
|
let out = "";
|
|
75744
76246
|
for (const ch of s) {
|
|
@@ -75805,7 +76307,7 @@ function renderTurnFile(text, limit = READ_LINE_LIMIT) {
|
|
|
75805
76307
|
`), lines: out.length, marker };
|
|
75806
76308
|
}
|
|
75807
76309
|
function turnFilePath(turnDir, turnIndex) {
|
|
75808
|
-
return
|
|
76310
|
+
return join36(turnDir, `turn-${turnIndex}.md`);
|
|
75809
76311
|
}
|
|
75810
76312
|
function fileTemplate(file, marker) {
|
|
75811
76313
|
const base = `Your task is in the file \`${file}\`. Read all of it with the Read tool (in parts if it is long), then do exactly what it says, treating its content as the user's message.`;
|
|
@@ -75876,7 +76378,7 @@ function deliveryRefusal(text, readAvailable) {
|
|
|
75876
76378
|
}
|
|
75877
76379
|
function writeTurnFile(d) {
|
|
75878
76380
|
if ((d.mode === "file" || d.mode === "command") && d.file && d.fileContent !== undefined) {
|
|
75879
|
-
|
|
76381
|
+
writeFileSync15(d.file, d.fileContent, { mode: 384, flag: "wx" });
|
|
75880
76382
|
}
|
|
75881
76383
|
}
|
|
75882
76384
|
var READ_LINE_LIMIT = 20000, MAX_TYPED_LINE = 512, SPLIT_MARKER = "\u21A9", ALT_SPLIT_MARKER = "\u2936", SLASH;
|
|
@@ -76485,11 +76987,11 @@ import {
|
|
|
76485
76987
|
fstatSync as fstatSync3,
|
|
76486
76988
|
openSync as openSync10,
|
|
76487
76989
|
readSync as readSync3,
|
|
76488
|
-
readdirSync as
|
|
76990
|
+
readdirSync as readdirSync6,
|
|
76489
76991
|
realpathSync as realpathSync4,
|
|
76490
|
-
statSync as
|
|
76992
|
+
statSync as statSync12
|
|
76491
76993
|
} from "fs";
|
|
76492
|
-
import { join as
|
|
76994
|
+
import { join as join37 } from "path";
|
|
76493
76995
|
function initialFollowerState(resolvePath = safeRealpath) {
|
|
76494
76996
|
return {
|
|
76495
76997
|
turns: [],
|
|
@@ -77053,7 +77555,7 @@ class TranscriptFollower {
|
|
|
77053
77555
|
if (!existsSync26(this.subagentsDir))
|
|
77054
77556
|
return [];
|
|
77055
77557
|
try {
|
|
77056
|
-
return
|
|
77558
|
+
return readdirSync6(this.subagentsDir).filter((f) => f.endsWith(".jsonl"));
|
|
77057
77559
|
} catch {
|
|
77058
77560
|
return [];
|
|
77059
77561
|
}
|
|
@@ -77063,7 +77565,7 @@ class TranscriptFollower {
|
|
|
77063
77565
|
for (const f of this.subagentFiles()) {
|
|
77064
77566
|
let tail = this.subs.get(f);
|
|
77065
77567
|
if (!tail) {
|
|
77066
|
-
tail = new Tail(
|
|
77568
|
+
tail = new Tail(join37(this.subagentsDir, f));
|
|
77067
77569
|
this.subs.set(f, tail);
|
|
77068
77570
|
}
|
|
77069
77571
|
for (const { line } of tail.read()) {
|
|
@@ -77138,7 +77640,7 @@ function lastHumanPromptOffset(path) {
|
|
|
77138
77640
|
}
|
|
77139
77641
|
function fileSize(p) {
|
|
77140
77642
|
try {
|
|
77141
|
-
return
|
|
77643
|
+
return statSync12(p).size;
|
|
77142
77644
|
} catch {
|
|
77143
77645
|
return 0;
|
|
77144
77646
|
}
|
|
@@ -77163,7 +77665,7 @@ var init_transcript_follower = __esm(() => {
|
|
|
77163
77665
|
|
|
77164
77666
|
// src/mcp-session/parent-session.ts
|
|
77165
77667
|
import { readFile as readFile7 } from "fs/promises";
|
|
77166
|
-
import { join as
|
|
77668
|
+
import { join as join38 } from "path";
|
|
77167
77669
|
function positiveInt(value) {
|
|
77168
77670
|
if (value === undefined || !/^[1-9][0-9]*$/.test(value))
|
|
77169
77671
|
return;
|
|
@@ -77187,11 +77689,11 @@ function parentSessionIdFrom(env) {
|
|
|
77187
77689
|
}
|
|
77188
77690
|
function claudeConfigDir(env) {
|
|
77189
77691
|
const fromEnv = env.CLAUDE_CONFIG_DIR;
|
|
77190
|
-
return fromEnv && fromEnv.length > 0 ? fromEnv :
|
|
77692
|
+
return fromEnv && fromEnv.length > 0 ? fromEnv : join38(userHomeFrom(env), ".claude");
|
|
77191
77693
|
}
|
|
77192
77694
|
async function readHostSessionRecord(opts) {
|
|
77193
77695
|
try {
|
|
77194
|
-
const raw = await readFile7(
|
|
77696
|
+
const raw = await readFile7(join38(opts.configDir, "sessions", `${opts.hostPid}.json`), "utf-8");
|
|
77195
77697
|
const parsed = JSON.parse(raw);
|
|
77196
77698
|
if (!parsed || typeof parsed !== "object")
|
|
77197
77699
|
return;
|
|
@@ -77235,11 +77737,11 @@ __export(exports_session_discovery, {
|
|
|
77235
77737
|
sessionLabel: () => sessionLabel,
|
|
77236
77738
|
transcriptPathFor: () => transcriptPathFor
|
|
77237
77739
|
});
|
|
77238
|
-
import { execFile as
|
|
77239
|
-
import { closeSync as closeSync11, openSync as openSync11, readSync as readSync4, readdirSync as
|
|
77240
|
-
import { basename as
|
|
77740
|
+
import { execFile as execFile4, execFileSync as execFileSync2 } from "child_process";
|
|
77741
|
+
import { closeSync as closeSync11, openSync as openSync11, readSync as readSync4, readdirSync as readdirSync7, realpathSync as realpathSync5, statSync as statSync13 } from "fs";
|
|
77742
|
+
import { basename as basename3, join as join39 } from "path";
|
|
77241
77743
|
function projectsDir(env = process.env) {
|
|
77242
|
-
return
|
|
77744
|
+
return join39(claudeConfigDir(env), "projects");
|
|
77243
77745
|
}
|
|
77244
77746
|
function slugForPath(absPath) {
|
|
77245
77747
|
return projectDirNameFor(absPath);
|
|
@@ -77249,7 +77751,7 @@ function transcriptPathFor(cwd, sessionUuid, projectsRoot = projectsDir()) {
|
|
|
77249
77751
|
try {
|
|
77250
77752
|
real = realpathSync5(cwd);
|
|
77251
77753
|
} catch {}
|
|
77252
|
-
return
|
|
77754
|
+
return join39(projectsRoot, slugForPath(real), `${sessionUuid}.jsonl`);
|
|
77253
77755
|
}
|
|
77254
77756
|
function isAgentSession(row) {
|
|
77255
77757
|
return row.entrypoint !== undefined && row.entrypoint !== "cli";
|
|
@@ -77290,28 +77792,28 @@ function getRepoContext(cwd = process.cwd()) {
|
|
|
77290
77792
|
}
|
|
77291
77793
|
function projectDirs() {
|
|
77292
77794
|
try {
|
|
77293
|
-
return
|
|
77795
|
+
return readdirSync7(projectsDir(), { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
77294
77796
|
} catch {
|
|
77295
77797
|
return [];
|
|
77296
77798
|
}
|
|
77297
77799
|
}
|
|
77298
77800
|
function sessionsIn2(dirName) {
|
|
77299
|
-
const dir =
|
|
77801
|
+
const dir = join39(projectsDir(), dirName);
|
|
77300
77802
|
let names;
|
|
77301
77803
|
try {
|
|
77302
|
-
names =
|
|
77804
|
+
names = readdirSync7(dir).filter((n) => n.endsWith(".jsonl"));
|
|
77303
77805
|
} catch {
|
|
77304
77806
|
return [];
|
|
77305
77807
|
}
|
|
77306
77808
|
const rows = [];
|
|
77307
77809
|
for (const n of names) {
|
|
77308
|
-
const file =
|
|
77810
|
+
const file = join39(dir, n);
|
|
77309
77811
|
try {
|
|
77310
|
-
const st =
|
|
77812
|
+
const st = statSync13(file);
|
|
77311
77813
|
if (st.size === 0)
|
|
77312
77814
|
continue;
|
|
77313
77815
|
const row = {
|
|
77314
|
-
id:
|
|
77816
|
+
id: basename3(n, ".jsonl"),
|
|
77315
77817
|
file,
|
|
77316
77818
|
mtimeMs: st.mtimeMs,
|
|
77317
77819
|
birthtimeMs: st.birthtimeMs,
|
|
@@ -77328,7 +77830,7 @@ function sessionsIn2(dirName) {
|
|
|
77328
77830
|
}
|
|
77329
77831
|
async function enrichWorktreeGit(groups, repoRoot) {
|
|
77330
77832
|
const run = (cwd, args) => new Promise((resolve) => {
|
|
77331
|
-
|
|
77833
|
+
execFile4("git", args, { cwd, encoding: "utf-8" }, (err, stdout) => resolve(err ? "" : stdout));
|
|
77332
77834
|
});
|
|
77333
77835
|
const trackByBranch = new Map;
|
|
77334
77836
|
const refs = await run(repoRoot, [
|
|
@@ -77413,7 +77915,7 @@ function discoverWorktreeGroups(repo) {
|
|
|
77413
77915
|
if (hit) {
|
|
77414
77916
|
path = hit.path;
|
|
77415
77917
|
live = true;
|
|
77416
|
-
name = hit.path === repo.root ? "(root)" :
|
|
77918
|
+
name = hit.path === repo.root ? "(root)" : basename3(hit.path);
|
|
77417
77919
|
} else if (at !== -1 && dir.startsWith(rootSlug)) {
|
|
77418
77920
|
path = null;
|
|
77419
77921
|
live = false;
|
|
@@ -77468,7 +77970,7 @@ function discoverWorktreeGroups(repo) {
|
|
|
77468
77970
|
g.activeNow = g.sessions.some((s) => isActive(s));
|
|
77469
77971
|
if (g.path) {
|
|
77470
77972
|
try {
|
|
77471
|
-
g.createdMs =
|
|
77973
|
+
g.createdMs = statSync13(g.path).birthtimeMs;
|
|
77472
77974
|
} catch {}
|
|
77473
77975
|
}
|
|
77474
77976
|
if (!g.createdMs && g.sessions.length > 0) {
|
|
@@ -77556,7 +78058,7 @@ function hydrateSession(row) {
|
|
|
77556
78058
|
row.hydrated = true;
|
|
77557
78059
|
if (isActive(row)) {
|
|
77558
78060
|
try {
|
|
77559
|
-
row.sizeBytes =
|
|
78061
|
+
row.sizeBytes = statSync13(row.file).size;
|
|
77560
78062
|
} catch {}
|
|
77561
78063
|
}
|
|
77562
78064
|
const head = parseRecords(readChunk(row.file, 0, Math.min(HEAD_BYTES, row.sizeBytes)), false);
|
|
@@ -77771,8 +78273,8 @@ var init_queue = __esm(() => {
|
|
|
77771
78273
|
});
|
|
77772
78274
|
|
|
77773
78275
|
// src/hooks/session/interactive-driver.ts
|
|
77774
|
-
import { existsSync as existsSync27, statSync as
|
|
77775
|
-
import { join as
|
|
78276
|
+
import { existsSync as existsSync27, statSync as statSync14 } from "fs";
|
|
78277
|
+
import { join as join40 } from "path";
|
|
77776
78278
|
function nextDriverPhase(phase, ev) {
|
|
77777
78279
|
const row = EDGES[phase];
|
|
77778
78280
|
return row[ev] ?? null;
|
|
@@ -77990,7 +78492,7 @@ class InteractiveDriver {
|
|
|
77990
78492
|
}
|
|
77991
78493
|
follow(sid, offset) {
|
|
77992
78494
|
const path = transcriptPathFor(this.o.cwd, sid, this.o.projectsRoot);
|
|
77993
|
-
this.follower = new TranscriptFollower(path,
|
|
78495
|
+
this.follower = new TranscriptFollower(path, join40(path.replace(/\.jsonl$/, ""), "subagents"));
|
|
77994
78496
|
this.sessionId = sid;
|
|
77995
78497
|
this.settledTurn = null;
|
|
77996
78498
|
this.lastPollAt = Date.now();
|
|
@@ -78535,7 +79037,7 @@ function assertNeverPhase(p) {
|
|
|
78535
79037
|
}
|
|
78536
79038
|
function fileSizeOf(path) {
|
|
78537
79039
|
try {
|
|
78538
|
-
return
|
|
79040
|
+
return statSync14(path).size;
|
|
78539
79041
|
} catch {
|
|
78540
79042
|
return 0;
|
|
78541
79043
|
}
|
|
@@ -78707,16 +79209,16 @@ var init_host_routing_env = __esm(() => {
|
|
|
78707
79209
|
// src/launcher/magmux-binary.ts
|
|
78708
79210
|
import { execSync } from "child_process";
|
|
78709
79211
|
import { existsSync as existsSync28 } from "fs";
|
|
78710
|
-
import { dirname as
|
|
79212
|
+
import { dirname as dirname17, join as join41 } from "path";
|
|
78711
79213
|
import { fileURLToPath } from "url";
|
|
78712
79214
|
function findMagmuxBinaryOrNull() {
|
|
78713
79215
|
const thisFile = fileURLToPath(import.meta.url);
|
|
78714
|
-
const thisDir =
|
|
78715
|
-
const pkgRoots = [
|
|
79216
|
+
const thisDir = dirname17(thisFile);
|
|
79217
|
+
const pkgRoots = [join41(thisDir, ".."), join41(thisDir, "..", "..")];
|
|
78716
79218
|
const platform = process.platform;
|
|
78717
79219
|
const arch = process.arch;
|
|
78718
79220
|
for (const pkgRoot of pkgRoots) {
|
|
78719
|
-
const bundled =
|
|
79221
|
+
const bundled = join41(pkgRoot, "native", `magmux-${platform}-${arch}`);
|
|
78720
79222
|
if (existsSync28(bundled))
|
|
78721
79223
|
return bundled;
|
|
78722
79224
|
}
|
|
@@ -78724,10 +79226,10 @@ function findMagmuxBinaryOrNull() {
|
|
|
78724
79226
|
const pkgName = `@claudish/magmux-${platform}-${arch}`;
|
|
78725
79227
|
let searchDir = pkgRoots[0];
|
|
78726
79228
|
for (let i = 0;i < 5; i++) {
|
|
78727
|
-
const candidate =
|
|
79229
|
+
const candidate = join41(searchDir, "node_modules", pkgName, "bin", "magmux");
|
|
78728
79230
|
if (existsSync28(candidate))
|
|
78729
79231
|
return candidate;
|
|
78730
|
-
const parent =
|
|
79232
|
+
const parent = dirname17(searchDir);
|
|
78731
79233
|
if (parent === searchDir)
|
|
78732
79234
|
break;
|
|
78733
79235
|
searchDir = parent;
|
|
@@ -78754,14 +79256,14 @@ import {
|
|
|
78754
79256
|
chmodSync as chmodSync3,
|
|
78755
79257
|
closeSync as closeSync12,
|
|
78756
79258
|
existsSync as existsSync29,
|
|
78757
|
-
mkdirSync as
|
|
79259
|
+
mkdirSync as mkdirSync20,
|
|
78758
79260
|
mkdtempSync,
|
|
78759
79261
|
openSync as openSync12,
|
|
78760
|
-
rmSync as
|
|
78761
|
-
writeFileSync as
|
|
79262
|
+
rmSync as rmSync11,
|
|
79263
|
+
writeFileSync as writeFileSync16
|
|
78762
79264
|
} from "fs";
|
|
78763
79265
|
import { connect as netConnect } from "net";
|
|
78764
|
-
import { join as
|
|
79266
|
+
import { join as join42 } from "path";
|
|
78765
79267
|
function envDeltas(parentEnv, childEnv) {
|
|
78766
79268
|
const set = [];
|
|
78767
79269
|
const unset = [];
|
|
@@ -78826,15 +79328,15 @@ function planMagmuxWrap(input) {
|
|
|
78826
79328
|
const id = `claudish-${pid}`;
|
|
78827
79329
|
const controlSocket = `/tmp/magmux-${id}.sock`;
|
|
78828
79330
|
const tmpRoot = input.tmpRoot ?? "/tmp";
|
|
78829
|
-
|
|
78830
|
-
const scriptDir = mkdtempSync(
|
|
79331
|
+
mkdirSync20(tmpRoot, { recursive: true });
|
|
79332
|
+
const scriptDir = mkdtempSync(join42(tmpRoot, "claudish-launch-"));
|
|
78831
79333
|
chmodSync3(scriptDir, 448);
|
|
78832
|
-
const scriptPath =
|
|
79334
|
+
const scriptPath = join42(scriptDir, "claude-launch.sh");
|
|
78833
79335
|
const parentEnv = input.parentEnv ?? process.env;
|
|
78834
79336
|
const deltas = envDeltas(parentEnv, input.childEnv);
|
|
78835
79337
|
const fd = openSync12(scriptPath, "wx", 384);
|
|
78836
79338
|
try {
|
|
78837
|
-
|
|
79339
|
+
writeFileSync16(fd, buildLauncherScript(input.claudeBinary, input.claudeArgs, deltas));
|
|
78838
79340
|
} finally {
|
|
78839
79341
|
closeSync12(fd);
|
|
78840
79342
|
}
|
|
@@ -78866,11 +79368,11 @@ function planMagmuxWrap(input) {
|
|
|
78866
79368
|
} catch {}
|
|
78867
79369
|
control = null;
|
|
78868
79370
|
try {
|
|
78869
|
-
|
|
79371
|
+
rmSync11(scriptDir, { recursive: true, force: true });
|
|
78870
79372
|
} catch {}
|
|
78871
79373
|
try {
|
|
78872
79374
|
if (existsSync29(controlSocket))
|
|
78873
|
-
|
|
79375
|
+
rmSync11(controlSocket, { force: true });
|
|
78874
79376
|
} catch {}
|
|
78875
79377
|
};
|
|
78876
79378
|
process.on("exit", cleanup);
|
|
@@ -78950,7 +79452,7 @@ var init_cache_ttl = __esm(() => {
|
|
|
78950
79452
|
});
|
|
78951
79453
|
|
|
78952
79454
|
// src/providers/effort-recommendations.ts
|
|
78953
|
-
import { readFileSync as
|
|
79455
|
+
import { readFileSync as readFileSync34, statSync as statSync15 } from "fs";
|
|
78954
79456
|
function effortRecommendationsPathFor(catalogPath) {
|
|
78955
79457
|
return catalogPath.endsWith(".json") ? `${catalogPath.slice(0, -5)}.efforts.json` : `${catalogPath}.efforts.json`;
|
|
78956
79458
|
}
|
|
@@ -79026,7 +79528,7 @@ function parseSidecar(raw) {
|
|
|
79026
79528
|
}
|
|
79027
79529
|
function statOrNull2(path) {
|
|
79028
79530
|
try {
|
|
79029
|
-
const { mtimeMs, size } =
|
|
79531
|
+
const { mtimeMs, size } = statSync15(path);
|
|
79030
79532
|
return { mtimeMs, size };
|
|
79031
79533
|
} catch {
|
|
79032
79534
|
return null;
|
|
@@ -79034,7 +79536,7 @@ function statOrNull2(path) {
|
|
|
79034
79536
|
}
|
|
79035
79537
|
function readSidecarFile(path) {
|
|
79036
79538
|
try {
|
|
79037
|
-
return parseSidecar(JSON.parse(
|
|
79539
|
+
return parseSidecar(JSON.parse(readFileSync34(path, "utf-8")));
|
|
79038
79540
|
} catch (err) {
|
|
79039
79541
|
if (err?.code !== "ENOENT") {
|
|
79040
79542
|
log(`[effort] unreadable ${path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -79044,7 +79546,7 @@ function readSidecarFile(path) {
|
|
|
79044
79546
|
}
|
|
79045
79547
|
function foreignSidecarFormat(path) {
|
|
79046
79548
|
try {
|
|
79047
|
-
const raw = JSON.parse(
|
|
79549
|
+
const raw = JSON.parse(readFileSync34(path, "utf-8"));
|
|
79048
79550
|
if (isRecord4(raw) && raw.format !== SIDECAR_FORMAT)
|
|
79049
79551
|
return raw.format ?? "none";
|
|
79050
79552
|
} catch {}
|
|
@@ -79103,9 +79605,9 @@ var init_effort_recommendations = __esm(() => {
|
|
|
79103
79605
|
});
|
|
79104
79606
|
|
|
79105
79607
|
// src/model-loader.ts
|
|
79106
|
-
import { existsSync as existsSync30, readFileSync as
|
|
79107
|
-
import { homedir as
|
|
79108
|
-
import { join as
|
|
79608
|
+
import { existsSync as existsSync30, readFileSync as readFileSync35 } from "fs";
|
|
79609
|
+
import { homedir as homedir35 } from "os";
|
|
79610
|
+
import { join as join43 } from "path";
|
|
79109
79611
|
function isRecommendationTier(value) {
|
|
79110
79612
|
return typeof value === "string" && RECOMMENDATION_TIER_INDEX.has(value);
|
|
79111
79613
|
}
|
|
@@ -79310,7 +79812,7 @@ function readRecommendedModelsCacheFile() {
|
|
|
79310
79812
|
return null;
|
|
79311
79813
|
let parsed;
|
|
79312
79814
|
try {
|
|
79313
|
-
parsed = JSON.parse(
|
|
79815
|
+
parsed = JSON.parse(readFileSync35(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
|
|
79314
79816
|
} catch (err) {
|
|
79315
79817
|
log(`[recommended] unreadable ${RECOMMENDED_MODELS_CACHE_PATH}: ${err instanceof Error ? err.message : String(err)}`);
|
|
79316
79818
|
return null;
|
|
@@ -79687,7 +80189,7 @@ var init_model_loader = __esm(() => {
|
|
|
79687
80189
|
{ recommendationTier: "subscription", title: "Subscription", quickPickEligible: true }
|
|
79688
80190
|
];
|
|
79689
80191
|
RECOMMENDATION_TIER_INDEX = new Map(RECOMMENDATION_SECTIONS.map((section, index) => [section.recommendationTier, index]));
|
|
79690
|
-
RECOMMENDED_MODELS_CACHE_PATH =
|
|
80192
|
+
RECOMMENDED_MODELS_CACHE_PATH = join43(homedir35(), ".claudish", "recommended-models-cache-v2.json");
|
|
79691
80193
|
RECOMMENDED_ROUTE_TIER_ORDER = {
|
|
79692
80194
|
native: 0,
|
|
79693
80195
|
general: 1,
|
|
@@ -80989,9 +81491,9 @@ var init_DiscoveryNotice = __esm(() => {
|
|
|
80989
81491
|
});
|
|
80990
81492
|
|
|
80991
81493
|
// src/providers/model-descriptions.ts
|
|
80992
|
-
import { existsSync as existsSync31, mkdirSync as
|
|
80993
|
-
import { homedir as
|
|
80994
|
-
import { dirname as
|
|
81494
|
+
import { existsSync as existsSync31, mkdirSync as mkdirSync21, readFileSync as readFileSync36, writeFileSync as writeFileSync17 } from "fs";
|
|
81495
|
+
import { homedir as homedir36 } from "os";
|
|
81496
|
+
import { dirname as dirname18, join as join44 } from "path";
|
|
80995
81497
|
function emptyDescriptionIndex() {
|
|
80996
81498
|
return EMPTY_INDEX;
|
|
80997
81499
|
}
|
|
@@ -81013,7 +81515,7 @@ function readCache(path) {
|
|
|
81013
81515
|
if (!existsSync31(path))
|
|
81014
81516
|
return null;
|
|
81015
81517
|
try {
|
|
81016
|
-
const raw = JSON.parse(
|
|
81518
|
+
const raw = JSON.parse(readFileSync36(path, "utf-8"));
|
|
81017
81519
|
if (!raw || typeof raw !== "object" || typeof raw.byId !== "object" || raw.byId === null) {
|
|
81018
81520
|
return null;
|
|
81019
81521
|
}
|
|
@@ -81029,8 +81531,8 @@ function readCache(path) {
|
|
|
81029
81531
|
}
|
|
81030
81532
|
function writeCache(path, cache) {
|
|
81031
81533
|
try {
|
|
81032
|
-
|
|
81033
|
-
|
|
81534
|
+
mkdirSync21(dirname18(path), { recursive: true });
|
|
81535
|
+
writeFileSync17(path, JSON.stringify(cache), "utf-8");
|
|
81034
81536
|
} catch (e) {
|
|
81035
81537
|
log(`[model-descriptions] cache write failed: ${e?.message ?? String(e)}`);
|
|
81036
81538
|
}
|
|
@@ -81084,7 +81586,7 @@ var init_model_descriptions = __esm(() => {
|
|
|
81084
81586
|
init_logger();
|
|
81085
81587
|
init_model_loader();
|
|
81086
81588
|
init_cache_ttl();
|
|
81087
|
-
MODEL_DESCRIPTIONS_CACHE_PATH =
|
|
81589
|
+
MODEL_DESCRIPTIONS_CACHE_PATH = join44(homedir36(), ".claudish", "model-descriptions.json");
|
|
81088
81590
|
EMPTY_INDEX = { get: () => {
|
|
81089
81591
|
return;
|
|
81090
81592
|
}, size: 0 };
|
|
@@ -81100,7 +81602,7 @@ function discoveryShapeOf(provider) {
|
|
|
81100
81602
|
const format = getProviderByName(provider)?.modelDiscovery?.format;
|
|
81101
81603
|
if (!format)
|
|
81102
81604
|
return "none";
|
|
81103
|
-
return format === "openai-models-list" ? "deadline" : "elapsed";
|
|
81605
|
+
return format === "openai-models-list" || format === "lmstudio-models" ? "deadline" : "elapsed";
|
|
81104
81606
|
}
|
|
81105
81607
|
async function* inCompletionOrder(promises) {
|
|
81106
81608
|
const live = new Map(promises.map((p, i) => [i, p.then((v) => ({ i, v }))]));
|
|
@@ -81527,6 +82029,20 @@ var init_chrome = __esm(() => {
|
|
|
81527
82029
|
init_tokens();
|
|
81528
82030
|
});
|
|
81529
82031
|
|
|
82032
|
+
// src/picker/context-window-choices.ts
|
|
82033
|
+
function contextWindowChoices(max, defaultSize) {
|
|
82034
|
+
const choices = COMMON_SIZES.filter((size) => size < max * NEAR_MAXIMUM).map((size) => ({ size, label: formatContextLength(size) }));
|
|
82035
|
+
choices.push({ size: max, label: `${formatContextLength(max)} (model maximum)` });
|
|
82036
|
+
const distance = (choice) => Math.abs(choice.size - defaultSize);
|
|
82037
|
+
const closest = choices.reduce((best, choice) => distance(choice) < distance(best) ? choice : best);
|
|
82038
|
+
return { choices, defaultIndex: choices.indexOf(closest) };
|
|
82039
|
+
}
|
|
82040
|
+
var COMMON_SIZES, NEAR_MAXIMUM = 0.9;
|
|
82041
|
+
var init_context_window_choices = __esm(() => {
|
|
82042
|
+
init_model_selector();
|
|
82043
|
+
COMMON_SIZES = [32000, 64000, 128000, 256000, 512000];
|
|
82044
|
+
});
|
|
82045
|
+
|
|
81530
82046
|
// src/picker/layout.ts
|
|
81531
82047
|
function deriveRowLayout(inner, opts = {}) {
|
|
81532
82048
|
const cells = Number.isFinite(inner) ? Math.max(0, Math.floor(inner)) : 0;
|
|
@@ -81683,7 +82199,7 @@ function detailText(spec, model) {
|
|
|
81683
82199
|
};
|
|
81684
82200
|
}
|
|
81685
82201
|
function providerFactsText(facts) {
|
|
81686
|
-
const billing = facts.billing === "sub" ? "flat-rate subscription \u2014 no per-token charge" : facts.billing === "local" ? "
|
|
82202
|
+
const billing = facts.billing === "sub" ? "flat-rate subscription \u2014 no per-token charge" : facts.billing === "local" ? "self-hosted \u2014 no per-token charge" : "metered \u2014 billed per token";
|
|
81687
82203
|
const billingShort = facts.billing === "sub" ? "flat-rate plan" : facts.billing === "local" ? "local" : "metered";
|
|
81688
82204
|
const auth = facts.envVar === "" ? "signs in \u2014 no API key variable" : facts.envVar;
|
|
81689
82205
|
return { billing, billingShort, auth };
|
|
@@ -81962,7 +82478,13 @@ function ChipCell({
|
|
|
81962
82478
|
]
|
|
81963
82479
|
}, undefined, true, undefined, this);
|
|
81964
82480
|
}
|
|
81965
|
-
function
|
|
82481
|
+
function lastColumnLabel(models) {
|
|
82482
|
+
return models.length > 0 && models.every((m) => m.machine) ? "machine" : "$/1M";
|
|
82483
|
+
}
|
|
82484
|
+
function ColumnHeader({
|
|
82485
|
+
layout,
|
|
82486
|
+
last = "$/1M"
|
|
82487
|
+
}) {
|
|
81966
82488
|
return /* @__PURE__ */ jsxDEV9("box", {
|
|
81967
82489
|
height: 1,
|
|
81968
82490
|
flexShrink: 0,
|
|
@@ -81999,7 +82521,7 @@ function ColumnHeader({ layout }) {
|
|
|
81999
82521
|
}, undefined, false, undefined, this),
|
|
82000
82522
|
/* @__PURE__ */ jsxDEV9("span", {
|
|
82001
82523
|
fg: tokens.trace,
|
|
82002
|
-
children: padStartTo(
|
|
82524
|
+
children: padStartTo(last, layout.price)
|
|
82003
82525
|
}, undefined, false, undefined, this),
|
|
82004
82526
|
layout.mark > 0 ? /* @__PURE__ */ jsxDEV9("span", {
|
|
82005
82527
|
fg: tokens.trace,
|
|
@@ -82044,7 +82566,7 @@ function ModelRow({
|
|
|
82044
82566
|
}, undefined, true, undefined, this) : null,
|
|
82045
82567
|
/* @__PURE__ */ jsxDEV9("span", {
|
|
82046
82568
|
fg: idFg,
|
|
82047
|
-
children: padTo(model.id, layout.id)
|
|
82569
|
+
children: padTo(model.machine?.modelId ?? model.id, layout.id)
|
|
82048
82570
|
}, undefined, false, undefined, this),
|
|
82049
82571
|
/* @__PURE__ */ jsxDEV9("span", {
|
|
82050
82572
|
children: gap(GAPS.afterId)
|
|
@@ -82056,7 +82578,10 @@ function ModelRow({
|
|
|
82056
82578
|
/* @__PURE__ */ jsxDEV9("span", {
|
|
82057
82579
|
children: gap(GAPS.afterCtx)
|
|
82058
82580
|
}, undefined, false, undefined, this),
|
|
82059
|
-
|
|
82581
|
+
model.machine ? /* @__PURE__ */ jsxDEV9("span", {
|
|
82582
|
+
fg: cursor ? C.strong : tokens.text,
|
|
82583
|
+
children: padStartTo(truncate(model.machine.name, layout.price), layout.price)
|
|
82584
|
+
}, undefined, false, undefined, this) : chipBg === null ? /* @__PURE__ */ jsxDEV9("span", {
|
|
82060
82585
|
fg: priceFg(price),
|
|
82061
82586
|
children: padStartTo(price, layout.price)
|
|
82062
82587
|
}, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV9(ChipCell, {
|
|
@@ -82379,13 +82904,32 @@ function buildLoadTasks(input) {
|
|
|
82379
82904
|
}
|
|
82380
82905
|
return tasks;
|
|
82381
82906
|
}
|
|
82382
|
-
function ModelPicker({
|
|
82907
|
+
function ModelPicker({
|
|
82908
|
+
source,
|
|
82909
|
+
onDone,
|
|
82910
|
+
askContextWindow = false,
|
|
82911
|
+
onDiscoveryFailure
|
|
82912
|
+
}) {
|
|
82383
82913
|
const { width, height } = useTerminalDimensions();
|
|
82384
82914
|
const providers = usePickerProviders(source);
|
|
82385
82915
|
const [view, setView] = useState7("providers");
|
|
82386
|
-
const [filter,
|
|
82387
|
-
const
|
|
82916
|
+
const [filter, setFilterState] = useState7("");
|
|
82917
|
+
const filterNow = useRef6(filter);
|
|
82918
|
+
filterNow.current = filter;
|
|
82919
|
+
const setFilter = (next) => {
|
|
82920
|
+
filterNow.current = typeof next === "function" ? next(filterNow.current) : next;
|
|
82921
|
+
setFilterState(filterNow.current);
|
|
82922
|
+
};
|
|
82923
|
+
const [typing, setTypingState] = useState7(false);
|
|
82924
|
+
const typingNow = useRef6(typing);
|
|
82925
|
+
typingNow.current = typing;
|
|
82926
|
+
const setTyping = (next) => {
|
|
82927
|
+
typingNow.current = next;
|
|
82928
|
+
setTypingState(next);
|
|
82929
|
+
};
|
|
82388
82930
|
const [custom, setCustom] = useState7("");
|
|
82931
|
+
const [sizing, setSizing] = useState7(null);
|
|
82932
|
+
const [sizeCursor, setSizeCursor] = useState7(0);
|
|
82389
82933
|
const [cursor, setCursor] = useState7(0);
|
|
82390
82934
|
const [providerCursor, setProviderCursor] = useState7(0);
|
|
82391
82935
|
const [revealKeyless, setRevealKeyless] = useState7(false);
|
|
@@ -82464,7 +83008,7 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82464
83008
|
const needle = filter.trim().toLowerCase();
|
|
82465
83009
|
if (!needle)
|
|
82466
83010
|
return list.rows;
|
|
82467
|
-
return list.rows.filter((r) => r.model.id.toLowerCase().includes(needle) || r.shortcut.toLowerCase().startsWith(needle) || (labels.get(r.provider) ?? "").toLowerCase().includes(needle));
|
|
83011
|
+
return list.rows.filter((r) => r.model.id.toLowerCase().includes(needle) || r.shortcut.toLowerCase().startsWith(needle) || (labels.get(r.provider) ?? "").toLowerCase().includes(needle) || (r.model.machine?.name ?? "").toLowerCase().includes(needle));
|
|
82468
83012
|
}, [list.rows, filter, labels]);
|
|
82469
83013
|
const busy = providers.probing || catalog.phase === "loading" || discovery.busy;
|
|
82470
83014
|
const frame = useAnimationFrame(busy);
|
|
@@ -82504,6 +83048,21 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82504
83048
|
onDone(null);
|
|
82505
83049
|
return;
|
|
82506
83050
|
}
|
|
83051
|
+
if (view === "context") {
|
|
83052
|
+
if (name === "escape") {
|
|
83053
|
+
setView("models");
|
|
83054
|
+
return;
|
|
83055
|
+
}
|
|
83056
|
+
if (name === "up" || name === "down") {
|
|
83057
|
+
const last = (sizing?.choices.length ?? 1) - 1;
|
|
83058
|
+
setSizeCursor((c) => Math.max(0, Math.min(last, c + (name === "up" ? -1 : 1))));
|
|
83059
|
+
return;
|
|
83060
|
+
}
|
|
83061
|
+
if ((name === "return" || name === "enter") && sizing) {
|
|
83062
|
+
onDone(sizing.spec, sizing.choices[sizeCursor]?.size);
|
|
83063
|
+
}
|
|
83064
|
+
return;
|
|
83065
|
+
}
|
|
82507
83066
|
if (view === "custom") {
|
|
82508
83067
|
if (name === "escape") {
|
|
82509
83068
|
setView("models");
|
|
@@ -82525,7 +83084,7 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82525
83084
|
}
|
|
82526
83085
|
if (view === "providers") {
|
|
82527
83086
|
if (name === "escape") {
|
|
82528
|
-
if (
|
|
83087
|
+
if (filterNow.current !== "" || typingNow.current) {
|
|
82529
83088
|
setFilter("");
|
|
82530
83089
|
setTyping(false);
|
|
82531
83090
|
setProviderCursor(0);
|
|
@@ -82568,7 +83127,7 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82568
83127
|
setProviderCursor(0);
|
|
82569
83128
|
return;
|
|
82570
83129
|
}
|
|
82571
|
-
const providerCommands =
|
|
83130
|
+
const providerCommands = filterNow.current === "" && !typingNow.current;
|
|
82572
83131
|
if (providerCommands && key.raw === "a") {
|
|
82573
83132
|
setScope(null);
|
|
82574
83133
|
setFilter("");
|
|
@@ -82596,7 +83155,7 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82596
83155
|
return;
|
|
82597
83156
|
}
|
|
82598
83157
|
if (name === "escape") {
|
|
82599
|
-
if (
|
|
83158
|
+
if (filterNow.current !== "" || typingNow.current) {
|
|
82600
83159
|
setFilter("");
|
|
82601
83160
|
setTyping(false);
|
|
82602
83161
|
setCursor(0);
|
|
@@ -82624,8 +83183,17 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82624
83183
|
return;
|
|
82625
83184
|
}
|
|
82626
83185
|
if (name === "return" || name === "enter") {
|
|
82627
|
-
if (selected)
|
|
83186
|
+
if (!selected)
|
|
83187
|
+
return;
|
|
83188
|
+
const max = askContextWindow ? selected.model.maxContextLength : undefined;
|
|
83189
|
+
if (max === undefined) {
|
|
82628
83190
|
onDone(selected.spec);
|
|
83191
|
+
return;
|
|
83192
|
+
}
|
|
83193
|
+
const { choices, defaultIndex } = contextWindowChoices(max, DEFAULT_LOCAL_CONTEXT_WINDOW);
|
|
83194
|
+
setSizing({ spec: selected.spec, choices });
|
|
83195
|
+
setSizeCursor(defaultIndex);
|
|
83196
|
+
setView("context");
|
|
82629
83197
|
return;
|
|
82630
83198
|
}
|
|
82631
83199
|
if (name === "backspace") {
|
|
@@ -82633,7 +83201,7 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82633
83201
|
setCursor(0);
|
|
82634
83202
|
return;
|
|
82635
83203
|
}
|
|
82636
|
-
const commandsLive =
|
|
83204
|
+
const commandsLive = filterNow.current === "" && !typingNow.current;
|
|
82637
83205
|
if (commandsLive && key.raw === "c") {
|
|
82638
83206
|
setView("custom");
|
|
82639
83207
|
return;
|
|
@@ -82655,6 +83223,44 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82655
83223
|
}
|
|
82656
83224
|
}
|
|
82657
83225
|
});
|
|
83226
|
+
if (view === "context" && sizing) {
|
|
83227
|
+
return /* @__PURE__ */ jsxDEV10(Centred, {
|
|
83228
|
+
width,
|
|
83229
|
+
height,
|
|
83230
|
+
children: /* @__PURE__ */ jsxDEV10(Dialog, {
|
|
83231
|
+
title: "context window",
|
|
83232
|
+
status: sizing.spec,
|
|
83233
|
+
width: layout.width,
|
|
83234
|
+
marginLeft: 0,
|
|
83235
|
+
children: [
|
|
83236
|
+
sizing.choices.map((choice, index) => /* @__PURE__ */ jsxDEV10("box", {
|
|
83237
|
+
height: 1,
|
|
83238
|
+
flexShrink: 0,
|
|
83239
|
+
children: /* @__PURE__ */ jsxDEV10("text", {
|
|
83240
|
+
children: [
|
|
83241
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
83242
|
+
fg: tokens.accent,
|
|
83243
|
+
children: index === sizeCursor ? "\u25B6 " : " "
|
|
83244
|
+
}, undefined, false, undefined, this),
|
|
83245
|
+
/* @__PURE__ */ jsxDEV10("span", {
|
|
83246
|
+
fg: tokens.text,
|
|
83247
|
+
children: choice.label
|
|
83248
|
+
}, undefined, false, undefined, this)
|
|
83249
|
+
]
|
|
83250
|
+
}, undefined, true, undefined, this)
|
|
83251
|
+
}, choice.size, false, undefined, this)),
|
|
83252
|
+
/* @__PURE__ */ jsxDEV10(Rule, {}, undefined, false, undefined, this),
|
|
83253
|
+
/* @__PURE__ */ jsxDEV10(Hints, {
|
|
83254
|
+
hints: [
|
|
83255
|
+
{ key: "\u2191\u2193", label: "move" },
|
|
83256
|
+
{ key: "\u23CE", label: "launch it" },
|
|
83257
|
+
{ key: "esc", label: "back" }
|
|
83258
|
+
]
|
|
83259
|
+
}, undefined, false, undefined, this)
|
|
83260
|
+
]
|
|
83261
|
+
}, "context", true, undefined, this)
|
|
83262
|
+
}, undefined, false, undefined, this);
|
|
83263
|
+
}
|
|
82658
83264
|
if (view === "custom") {
|
|
82659
83265
|
return /* @__PURE__ */ jsxDEV10(Centred, {
|
|
82660
83266
|
width,
|
|
@@ -82831,7 +83437,8 @@ function ModelPicker({ source, onDone, onDiscoveryFailure }) {
|
|
|
82831
83437
|
idle: orderedByProvider(storedShown ?? discovery.outcome) ? "" : undefined
|
|
82832
83438
|
}, undefined, false, undefined, this),
|
|
82833
83439
|
/* @__PURE__ */ jsxDEV10(ColumnHeader, {
|
|
82834
|
-
layout: rowLayout
|
|
83440
|
+
layout: rowLayout,
|
|
83441
|
+
last: lastColumnLabel(list.rows.map((r) => r.model))
|
|
82835
83442
|
}, undefined, false, undefined, this),
|
|
82836
83443
|
/* @__PURE__ */ jsxDEV10("box", {
|
|
82837
83444
|
flexDirection: "column",
|
|
@@ -82967,6 +83574,7 @@ function emptyLabel(loading, filter, total, scopedName, providers) {
|
|
|
82967
83574
|
}
|
|
82968
83575
|
var MAX_BANNER_ROWS = 5, HOUR_MS18;
|
|
82969
83576
|
var init_ModelPicker = __esm(() => {
|
|
83577
|
+
init_context_window_limit();
|
|
82970
83578
|
init_dynamic_models_catalog_store();
|
|
82971
83579
|
init_dynamic_models_catalog();
|
|
82972
83580
|
init_EmptyState();
|
|
@@ -82976,6 +83584,7 @@ var init_ModelPicker = __esm(() => {
|
|
|
82976
83584
|
init_DiscoveryNotice();
|
|
82977
83585
|
init_PickerDataSource();
|
|
82978
83586
|
init_chrome();
|
|
83587
|
+
init_context_window_choices();
|
|
82979
83588
|
init_detail();
|
|
82980
83589
|
init_useModelDescriptions();
|
|
82981
83590
|
init_usePickerModels();
|
|
@@ -83110,7 +83719,7 @@ async function resolveDataSource() {
|
|
|
83110
83719
|
await Promise.resolve().then(() => init_fixture_source());
|
|
83111
83720
|
return createFixtureDataSource(name);
|
|
83112
83721
|
}
|
|
83113
|
-
async function runModelPicker(
|
|
83722
|
+
async function runModelPicker(options = {}) {
|
|
83114
83723
|
ensureEndpointsRegistered();
|
|
83115
83724
|
const source = await resolveDataSource();
|
|
83116
83725
|
const deferred = [];
|
|
@@ -83123,18 +83732,21 @@ async function runModelPicker(_options = {}) {
|
|
|
83123
83732
|
await applyRendererThemeMode(renderer);
|
|
83124
83733
|
const root = createRoot(renderer);
|
|
83125
83734
|
let chosen = null;
|
|
83735
|
+
let chosenContextWindow;
|
|
83126
83736
|
try {
|
|
83127
83737
|
await new Promise((resolve) => {
|
|
83128
83738
|
let settled = false;
|
|
83129
|
-
const done = (spec) => {
|
|
83739
|
+
const done = (spec, contextWindow) => {
|
|
83130
83740
|
if (settled)
|
|
83131
83741
|
return;
|
|
83132
83742
|
settled = true;
|
|
83133
83743
|
chosen = spec;
|
|
83744
|
+
chosenContextWindow = contextWindow;
|
|
83134
83745
|
resolve();
|
|
83135
83746
|
};
|
|
83136
83747
|
root.render(/* @__PURE__ */ jsxDEV11(ModelPicker, {
|
|
83137
83748
|
source,
|
|
83749
|
+
askContextWindow: options.onContextWindow !== undefined,
|
|
83138
83750
|
onDone: done,
|
|
83139
83751
|
onDiscoveryFailure: (provider, lines) => deferred.push({ provider, lines })
|
|
83140
83752
|
}, undefined, false, undefined, this));
|
|
@@ -83152,7 +83764,7 @@ async function runModelPicker(_options = {}) {
|
|
|
83152
83764
|
process.stderr.write(line);
|
|
83153
83765
|
}
|
|
83154
83766
|
}
|
|
83155
|
-
return { model: chosen };
|
|
83767
|
+
return { model: chosen, contextWindow: chosenContextWindow };
|
|
83156
83768
|
}
|
|
83157
83769
|
var init_model_picker_run = __esm(() => {
|
|
83158
83770
|
init_logger();
|
|
@@ -83473,6 +84085,8 @@ async function selectModel(options = {}) {
|
|
|
83473
84085
|
const outcome = await selectModelInteractive(options);
|
|
83474
84086
|
if (outcome.model === null)
|
|
83475
84087
|
throw new PickerCancelled;
|
|
84088
|
+
if (outcome.contextWindow !== undefined)
|
|
84089
|
+
options.onContextWindow?.(outcome.contextWindow);
|
|
83476
84090
|
return outcome.model;
|
|
83477
84091
|
}
|
|
83478
84092
|
async function selectModelInteractive(options = {}) {
|
|
@@ -83839,7 +84453,7 @@ function buildRowsFromDiscovered(provider, displayName, discovered, catalogRows)
|
|
|
83839
84453
|
const discoveredById = new Map(discovered.map((m) => [m.id, m]));
|
|
83840
84454
|
const rows = choices.map((c) => {
|
|
83841
84455
|
const source = discoveredById.get(c.id);
|
|
83842
|
-
const contextLength = source ? resolveDiscoveredContextLength(source) : c.contextWindow ?? 0;
|
|
84456
|
+
const contextLength = (source ? resolveDiscoveredContextLength(source) : c.contextWindow ?? 0) || (source?.maxContextWindow ?? 0);
|
|
83843
84457
|
const parts = [c.displayName];
|
|
83844
84458
|
if (contextLength)
|
|
83845
84459
|
parts.push(`${formatContextLength(contextLength)} context`);
|
|
@@ -83857,6 +84471,8 @@ function buildRowsFromDiscovered(provider, displayName, discovered, catalogRows)
|
|
|
83857
84471
|
pricing: subscription ? SUBSCRIPTION_PRICING : pricingById.get(c.id.toLowerCase()),
|
|
83858
84472
|
context: formatContextLength(contextLength),
|
|
83859
84473
|
contextLength,
|
|
84474
|
+
maxContextLength: source?.maxContextWindow,
|
|
84475
|
+
machine: source?.machine,
|
|
83860
84476
|
supportsTools: lookupModelCapabilities(c.id)?.supportsTools ?? source?.supportsTools ?? true,
|
|
83861
84477
|
isFree: flatRate,
|
|
83862
84478
|
source: displayName
|
|
@@ -87577,24 +88193,24 @@ var init_branding = __esm(() => {
|
|
|
87577
88193
|
});
|
|
87578
88194
|
|
|
87579
88195
|
// src/update-checker.ts
|
|
87580
|
-
import { existsSync as existsSync32, mkdirSync as
|
|
87581
|
-
import { homedir as
|
|
87582
|
-
import { join as
|
|
88196
|
+
import { existsSync as existsSync32, mkdirSync as mkdirSync22, readFileSync as readFileSync37, unlinkSync as unlinkSync9, writeFileSync as writeFileSync18 } from "fs";
|
|
88197
|
+
import { homedir as homedir37, platform as platform2, tmpdir } from "os";
|
|
88198
|
+
import { join as join45 } from "path";
|
|
87583
88199
|
function getCacheFilePath() {
|
|
87584
88200
|
let cacheDir;
|
|
87585
88201
|
if (isWindows) {
|
|
87586
|
-
const localAppData = process.env.LOCALAPPDATA ||
|
|
87587
|
-
cacheDir =
|
|
88202
|
+
const localAppData = process.env.LOCALAPPDATA || join45(homedir37(), "AppData", "Local");
|
|
88203
|
+
cacheDir = join45(localAppData, "claudish");
|
|
87588
88204
|
} else {
|
|
87589
|
-
cacheDir =
|
|
88205
|
+
cacheDir = join45(homedir37(), ".cache", "claudish");
|
|
87590
88206
|
}
|
|
87591
88207
|
try {
|
|
87592
88208
|
if (!existsSync32(cacheDir)) {
|
|
87593
|
-
|
|
88209
|
+
mkdirSync22(cacheDir, { recursive: true });
|
|
87594
88210
|
}
|
|
87595
|
-
return
|
|
88211
|
+
return join45(cacheDir, "update-check.json");
|
|
87596
88212
|
} catch {
|
|
87597
|
-
return
|
|
88213
|
+
return join45(tmpdir(), "claudish-update-check.json");
|
|
87598
88214
|
}
|
|
87599
88215
|
}
|
|
87600
88216
|
function readCache2() {
|
|
@@ -87603,7 +88219,7 @@ function readCache2() {
|
|
|
87603
88219
|
if (!existsSync32(cachePath)) {
|
|
87604
88220
|
return null;
|
|
87605
88221
|
}
|
|
87606
|
-
const data = JSON.parse(
|
|
88222
|
+
const data = JSON.parse(readFileSync37(cachePath, "utf-8"));
|
|
87607
88223
|
return data;
|
|
87608
88224
|
} catch {
|
|
87609
88225
|
return null;
|
|
@@ -87616,7 +88232,7 @@ function writeCache2(latestVersion) {
|
|
|
87616
88232
|
lastCheck: Date.now(),
|
|
87617
88233
|
latestVersion
|
|
87618
88234
|
};
|
|
87619
|
-
|
|
88235
|
+
writeFileSync18(cachePath, JSON.stringify(data), "utf-8");
|
|
87620
88236
|
} catch {}
|
|
87621
88237
|
}
|
|
87622
88238
|
function isCacheValid(cache) {
|
|
@@ -92569,6 +93185,13 @@ class LocalTransport {
|
|
|
92569
93185
|
streamFormat = "openai-sse";
|
|
92570
93186
|
config;
|
|
92571
93187
|
modelName;
|
|
93188
|
+
lmStudioDevice;
|
|
93189
|
+
lmStudioInstance;
|
|
93190
|
+
lmStudioPlacedAt;
|
|
93191
|
+
lmStudioPlacementError;
|
|
93192
|
+
unplacedErrors = new Map;
|
|
93193
|
+
unplacedCount = 0;
|
|
93194
|
+
probeLeases = new Set;
|
|
92572
93195
|
concurrency;
|
|
92573
93196
|
healthChecked = false;
|
|
92574
93197
|
isHealthy = false;
|
|
@@ -92578,17 +93201,21 @@ class LocalTransport {
|
|
|
92578
93201
|
_isOllamaBackend;
|
|
92579
93202
|
constructor(config, modelName, options) {
|
|
92580
93203
|
this.config = config;
|
|
92581
|
-
|
|
93204
|
+
if (config.name === "lmstudio") {
|
|
93205
|
+
const { model, device } = splitLMStudioDevice(modelName);
|
|
93206
|
+
this.modelName = model;
|
|
93207
|
+
this.lmStudioDevice = device;
|
|
93208
|
+
} else {
|
|
93209
|
+
this.modelName = modelName;
|
|
93210
|
+
}
|
|
92582
93211
|
this.name = config.name;
|
|
92583
93212
|
this.displayName = DISPLAY_NAMES2[config.name] || "Local";
|
|
92584
93213
|
this.concurrency = options?.concurrency;
|
|
92585
|
-
|
|
92586
|
-
|
|
92587
|
-
|
|
92588
|
-
|
|
92589
|
-
|
|
92590
|
-
log(`[${this.displayName}] Context window from env: ${this._contextWindow}`);
|
|
92591
|
-
}
|
|
93214
|
+
this._contextWindow = getProviderByName(config.name)?.unknownContextWindow ?? 32768;
|
|
93215
|
+
const limit = contextWindowLimit();
|
|
93216
|
+
if (limit !== undefined) {
|
|
93217
|
+
this._contextWindow = limit;
|
|
93218
|
+
log(`[${this.displayName}] Context window limit: ${limit}`);
|
|
92592
93219
|
}
|
|
92593
93220
|
if (this.concurrency !== undefined) {
|
|
92594
93221
|
log(`[${this.displayName}] Concurrency: ${this.concurrency === 0 ? "unlimited" : this.concurrency}`);
|
|
@@ -92635,6 +93262,16 @@ class LocalTransport {
|
|
|
92635
93262
|
};
|
|
92636
93263
|
}
|
|
92637
93264
|
async getExtraPayloadFields() {
|
|
93265
|
+
if (this.lmStudioDevice) {
|
|
93266
|
+
this.lmStudioPlacementError = undefined;
|
|
93267
|
+
try {
|
|
93268
|
+
return { model: (await this.placeOnDevice()).instanceId };
|
|
93269
|
+
} catch (error) {
|
|
93270
|
+
this.lmStudioPlacementError = error;
|
|
93271
|
+
this.lmStudioInstance = undefined;
|
|
93272
|
+
return { model: this.markUnplaced(error) };
|
|
93273
|
+
}
|
|
93274
|
+
}
|
|
92638
93275
|
if (await this.isOllamaBackend()) {
|
|
92639
93276
|
const numCtx = Math.max(this._contextWindow, 32768);
|
|
92640
93277
|
log(`[${this.displayName}] Setting num_ctx: ${numCtx} (detected: ${this._contextWindow})`);
|
|
@@ -92648,15 +93285,96 @@ class LocalTransport {
|
|
|
92648
93285
|
return LocalModelQueue.getInstance().enqueue(fetchFn, this.name, this.concurrency, opts?.signal);
|
|
92649
93286
|
}
|
|
92650
93287
|
async refreshAuth() {
|
|
92651
|
-
|
|
93288
|
+
const lease = acquireSigningLease();
|
|
93289
|
+
this.probeLeases.add(lease);
|
|
93290
|
+
try {
|
|
93291
|
+
await this.refreshAuthUnderLease();
|
|
93292
|
+
} finally {
|
|
93293
|
+
this.probeLeases.delete(lease);
|
|
93294
|
+
lease.release();
|
|
93295
|
+
}
|
|
93296
|
+
}
|
|
93297
|
+
async refreshAuthUnderLease() {
|
|
93298
|
+
if (this.healthChecked) {
|
|
93299
|
+
await this.confirmPlacement();
|
|
92652
93300
|
return;
|
|
93301
|
+
}
|
|
92653
93302
|
const healthy = await this.checkHealth();
|
|
92654
93303
|
if (!healthy) {
|
|
93304
|
+
if (this.lmStudioPlacementError !== undefined) {
|
|
93305
|
+
this.lmStudioPlacementError = new Error(`LM Studio was not reachable when this request was built, so ${this.modelName} was not placed on ${this.lmStudioDevice}. Send the message again.`);
|
|
93306
|
+
}
|
|
92655
93307
|
throw Object.assign(new Error(this.getConnectionErrorMessage(), {
|
|
92656
93308
|
cause: this.lastProbeError
|
|
92657
93309
|
}), { claudishEndpoint: this.lastProbeUrl ?? this.config.baseUrl });
|
|
92658
93310
|
}
|
|
92659
93311
|
await this.fetchContextWindow();
|
|
93312
|
+
await this.confirmPlacement();
|
|
93313
|
+
}
|
|
93314
|
+
placeOnDevice() {
|
|
93315
|
+
const placedAt = this.lmStudioPlacedAt;
|
|
93316
|
+
if (this.lmStudioInstance && placedAt !== undefined && Date.now() - placedAt > PLACEMENT_RECHECK_MS) {
|
|
93317
|
+
this.lmStudioInstance = undefined;
|
|
93318
|
+
}
|
|
93319
|
+
if (this.lmStudioInstance)
|
|
93320
|
+
return this.lmStudioInstance;
|
|
93321
|
+
this.lmStudioPlacedAt = undefined;
|
|
93322
|
+
const pending = this.getHeaders().then((headers) => ensureLMStudioInstance({
|
|
93323
|
+
baseUrl: this.config.baseUrl,
|
|
93324
|
+
model: this.modelName,
|
|
93325
|
+
device: this.lmStudioDevice,
|
|
93326
|
+
contextLength: contextWindowLimit() ?? getProviderByName(this.config.name)?.unknownContextWindow,
|
|
93327
|
+
headers: Object.keys(headers).length > 0 ? headers : undefined,
|
|
93328
|
+
log
|
|
93329
|
+
})).then((instance) => {
|
|
93330
|
+
if (this.lmStudioInstance === pending)
|
|
93331
|
+
this.lmStudioPlacedAt = Date.now();
|
|
93332
|
+
return instance;
|
|
93333
|
+
});
|
|
93334
|
+
this.lmStudioInstance = pending;
|
|
93335
|
+
return pending;
|
|
93336
|
+
}
|
|
93337
|
+
async confirmPlacement() {
|
|
93338
|
+
if (!this.lmStudioDevice)
|
|
93339
|
+
return;
|
|
93340
|
+
if (this.lmStudioPlacementError !== undefined) {
|
|
93341
|
+
const error = this.lmStudioPlacementError;
|
|
93342
|
+
if (classifyConnectionError(error) === null)
|
|
93343
|
+
throw error;
|
|
93344
|
+
throw new Error(`LM Studio could not be reached while ${this.modelName} was placed on ${this.lmStudioDevice}. Send the message again.`);
|
|
93345
|
+
}
|
|
93346
|
+
let instance;
|
|
93347
|
+
try {
|
|
93348
|
+
instance = await this.placeOnDevice();
|
|
93349
|
+
} catch (error) {
|
|
93350
|
+
this.lmStudioInstance = undefined;
|
|
93351
|
+
throw error;
|
|
93352
|
+
}
|
|
93353
|
+
if (instance.contextLength) {
|
|
93354
|
+
this._contextWindow = Math.min(instance.contextLength, contextWindowLimit() ?? instance.contextLength);
|
|
93355
|
+
}
|
|
93356
|
+
}
|
|
93357
|
+
markUnplaced(error) {
|
|
93358
|
+
const marker = `${this.modelName}~${this.lmStudioDevice} (not placed #${++this.unplacedCount})`;
|
|
93359
|
+
this.unplacedErrors.set(marker, error);
|
|
93360
|
+
while (this.unplacedErrors.size > MAX_UNPLACED_ERRORS) {
|
|
93361
|
+
const oldest = this.unplacedErrors.keys().next().value;
|
|
93362
|
+
if (oldest === undefined)
|
|
93363
|
+
break;
|
|
93364
|
+
this.unplacedErrors.delete(oldest);
|
|
93365
|
+
}
|
|
93366
|
+
return marker;
|
|
93367
|
+
}
|
|
93368
|
+
transformPayload(payload) {
|
|
93369
|
+
const model = payload?.model;
|
|
93370
|
+
if (typeof model !== "string" || !model.endsWith(")") || !model.includes(" (not placed #")) {
|
|
93371
|
+
return payload;
|
|
93372
|
+
}
|
|
93373
|
+
const error = this.unplacedErrors.get(model);
|
|
93374
|
+
this.unplacedErrors.delete(model);
|
|
93375
|
+
if (error !== undefined && classifyConnectionError(error) === null)
|
|
93376
|
+
throw error;
|
|
93377
|
+
throw new Error(`LM Studio could not be reached while ${this.modelName} was placed on ${this.lmStudioDevice}. Send the message again.`);
|
|
92660
93378
|
}
|
|
92661
93379
|
getContextWindow() {
|
|
92662
93380
|
return this._contextWindow;
|
|
@@ -92674,6 +93392,7 @@ class LocalTransport {
|
|
|
92674
93392
|
try {
|
|
92675
93393
|
const response = await fetch(`${this.config.baseUrl}/api/tags`, {
|
|
92676
93394
|
method: "GET",
|
|
93395
|
+
headers: await this.probeHeaders(),
|
|
92677
93396
|
signal: AbortSignal.timeout(5000)
|
|
92678
93397
|
});
|
|
92679
93398
|
this._isOllamaBackend = await hasOllamaTagsShape(response);
|
|
@@ -92683,6 +93402,13 @@ class LocalTransport {
|
|
|
92683
93402
|
log(`[${this.displayName}] Ollama backend probe (${this.config.baseUrl}): ${this._isOllamaBackend}`);
|
|
92684
93403
|
return this._isOllamaBackend;
|
|
92685
93404
|
}
|
|
93405
|
+
async probeHeaders() {
|
|
93406
|
+
const headers = await this.getHeaders().catch(() => ({}));
|
|
93407
|
+
const values = credentialValuesFromRequest(headers);
|
|
93408
|
+
for (const lease of this.probeLeases)
|
|
93409
|
+
lease.add(values);
|
|
93410
|
+
return headers;
|
|
93411
|
+
}
|
|
92686
93412
|
async checkHealth() {
|
|
92687
93413
|
if (this.healthChecked)
|
|
92688
93414
|
return this.isHealthy;
|
|
@@ -92693,6 +93419,7 @@ class LocalTransport {
|
|
|
92693
93419
|
log(`[${this.displayName}] Trying health check: ${healthUrl}`);
|
|
92694
93420
|
const response = await fetch(healthUrl, {
|
|
92695
93421
|
method: "GET",
|
|
93422
|
+
headers: await this.probeHeaders(),
|
|
92696
93423
|
signal: AbortSignal.timeout(5000)
|
|
92697
93424
|
});
|
|
92698
93425
|
this._isOllamaBackend ??= await hasOllamaTagsShape(response);
|
|
@@ -92713,6 +93440,7 @@ class LocalTransport {
|
|
|
92713
93440
|
log(`[${this.displayName}] Trying health check: ${modelsUrl}`);
|
|
92714
93441
|
const response = await fetch(modelsUrl, {
|
|
92715
93442
|
method: "GET",
|
|
93443
|
+
headers: await this.probeHeaders(),
|
|
92716
93444
|
signal: AbortSignal.timeout(5000)
|
|
92717
93445
|
});
|
|
92718
93446
|
if (response.ok) {
|
|
@@ -92732,11 +93460,13 @@ class LocalTransport {
|
|
|
92732
93460
|
return false;
|
|
92733
93461
|
}
|
|
92734
93462
|
async fetchContextWindow() {
|
|
92735
|
-
if (
|
|
93463
|
+
if (contextWindowLimit() !== undefined)
|
|
92736
93464
|
return;
|
|
92737
93465
|
log(`[${this.displayName}] Fetching context window...`);
|
|
92738
93466
|
if (await this.isOllamaBackend()) {
|
|
92739
93467
|
await this.fetchOllamaContextWindow();
|
|
93468
|
+
} else if (this.lmStudioDevice) {
|
|
93469
|
+
log(`[${this.displayName}] Context window comes from the instance on ${this.lmStudioDevice}`);
|
|
92740
93470
|
} else if (this.config.name === "lmstudio") {
|
|
92741
93471
|
await this.fetchLMStudioContextWindow();
|
|
92742
93472
|
} else {
|
|
@@ -92747,7 +93477,7 @@ class LocalTransport {
|
|
|
92747
93477
|
try {
|
|
92748
93478
|
const response = await fetch(`${this.config.baseUrl}/api/show`, {
|
|
92749
93479
|
method: "POST",
|
|
92750
|
-
headers: { "Content-Type": "application/json" },
|
|
93480
|
+
headers: { "Content-Type": "application/json", ...await this.probeHeaders() },
|
|
92751
93481
|
body: JSON.stringify({ name: this.modelName }),
|
|
92752
93482
|
signal: AbortSignal.timeout(3000)
|
|
92753
93483
|
});
|
|
@@ -92778,8 +93508,9 @@ class LocalTransport {
|
|
|
92778
93508
|
}
|
|
92779
93509
|
async fetchLMStudioContextWindow() {
|
|
92780
93510
|
try {
|
|
92781
|
-
const response = await fetch(`${this.config.baseUrl}/
|
|
93511
|
+
const response = await fetch(`${this.config.baseUrl}/api/v0/models`, {
|
|
92782
93512
|
method: "GET",
|
|
93513
|
+
headers: await this.probeHeaders(),
|
|
92783
93514
|
signal: AbortSignal.timeout(3000)
|
|
92784
93515
|
});
|
|
92785
93516
|
if (response.ok) {
|
|
@@ -92787,19 +93518,21 @@ class LocalTransport {
|
|
|
92787
93518
|
log(`[${this.displayName}] Models response: ${JSON.stringify(data).slice(0, 500)}`);
|
|
92788
93519
|
const models = data.data || [];
|
|
92789
93520
|
const targetModel = models.find((m) => m.id === this.modelName) || models.find((m) => m.id?.endsWith(`/${this.modelName}`)) || models.find((m) => this.modelName.includes(m.id));
|
|
92790
|
-
|
|
92791
|
-
|
|
92792
|
-
|
|
92793
|
-
|
|
92794
|
-
|
|
92795
|
-
|
|
92796
|
-
|
|
93521
|
+
const ctxLength = targetModel?.loaded_context_length;
|
|
93522
|
+
if (typeof ctxLength === "number" && ctxLength > 0) {
|
|
93523
|
+
this._contextWindow = ctxLength;
|
|
93524
|
+
log(`[${this.displayName}] Context window from model: ${this._contextWindow}`);
|
|
93525
|
+
return;
|
|
93526
|
+
}
|
|
93527
|
+
const maxLength = targetModel?.max_context_length;
|
|
93528
|
+
if (typeof maxLength === "number" && maxLength > 0 && maxLength < this._contextWindow) {
|
|
93529
|
+
this._contextWindow = maxLength;
|
|
93530
|
+
log(`[${this.displayName}] Context window from model maximum: ${maxLength}`);
|
|
93531
|
+
return;
|
|
92797
93532
|
}
|
|
92798
|
-
this._contextWindow = 32768;
|
|
92799
93533
|
log(`[${this.displayName}] Using default context window: ${this._contextWindow}`);
|
|
92800
93534
|
}
|
|
92801
93535
|
} catch (e) {
|
|
92802
|
-
this._contextWindow = 32768;
|
|
92803
93536
|
log(`[${this.displayName}] Failed to fetch model info: ${e?.message || e}. Using default: ${this._contextWindow}`);
|
|
92804
93537
|
}
|
|
92805
93538
|
}
|
|
@@ -92816,12 +93549,17 @@ class LocalTransport {
|
|
|
92816
93549
|
}
|
|
92817
93550
|
}
|
|
92818
93551
|
}
|
|
92819
|
-
var localProviderAgent, DISPLAY_NAMES2;
|
|
93552
|
+
var MAX_UNPLACED_ERRORS = 64, localProviderAgent, DISPLAY_NAMES2, PLACEMENT_RECHECK_MS = 1e4;
|
|
92820
93553
|
var init_local = __esm(() => {
|
|
92821
93554
|
init_authority();
|
|
93555
|
+
init_call_context();
|
|
92822
93556
|
init_connection_error();
|
|
92823
93557
|
init_local_queue();
|
|
92824
93558
|
init_logger();
|
|
93559
|
+
init_lmstudio_devices();
|
|
93560
|
+
init_provider_definitions();
|
|
93561
|
+
init_redact();
|
|
93562
|
+
init_context_window_limit();
|
|
92825
93563
|
init_probe_discovery();
|
|
92826
93564
|
localProviderAgent = new Agent({
|
|
92827
93565
|
headersTimeout: 600000,
|
|
@@ -94064,9 +94802,9 @@ var init_response_seam = __esm(() => {
|
|
|
94064
94802
|
});
|
|
94065
94803
|
|
|
94066
94804
|
// src/services/pricing-cache.ts
|
|
94067
|
-
import { existsSync as existsSync33, readFileSync as
|
|
94068
|
-
import { homedir as
|
|
94069
|
-
import { join as
|
|
94805
|
+
import { existsSync as existsSync33, readFileSync as readFileSync38, statSync as statSync16 } from "fs";
|
|
94806
|
+
import { homedir as homedir38 } from "os";
|
|
94807
|
+
import { join as join46 } from "path";
|
|
94070
94808
|
function prefixMatch(modelName) {
|
|
94071
94809
|
for (const [key, pricing] of pricingMap) {
|
|
94072
94810
|
if (modelName.startsWith(key))
|
|
@@ -94106,10 +94844,10 @@ function loadDiskCache() {
|
|
|
94106
94844
|
try {
|
|
94107
94845
|
if (!existsSync33(CACHE_FILE))
|
|
94108
94846
|
return false;
|
|
94109
|
-
const stat =
|
|
94847
|
+
const stat = statSync16(CACHE_FILE);
|
|
94110
94848
|
const age = Date.now() - stat.mtimeMs;
|
|
94111
94849
|
const isFresh = age < CACHE_TTL_MS5;
|
|
94112
|
-
const raw =
|
|
94850
|
+
const raw = readFileSync38(CACHE_FILE, "utf-8");
|
|
94113
94851
|
const data = JSON.parse(raw);
|
|
94114
94852
|
for (const [key, pricing] of Object.entries(data)) {
|
|
94115
94853
|
pricingMap.set(key, pricing);
|
|
@@ -94126,14 +94864,14 @@ var init_pricing_cache = __esm(() => {
|
|
|
94126
94864
|
init_logger();
|
|
94127
94865
|
init_catalog_query();
|
|
94128
94866
|
pricingMap = new Map;
|
|
94129
|
-
CACHE_DIR =
|
|
94130
|
-
CACHE_FILE =
|
|
94867
|
+
CACHE_DIR = join46(homedir38(), ".claudish");
|
|
94868
|
+
CACHE_FILE = join46(CACHE_DIR, "pricing-cache.json");
|
|
94131
94869
|
CACHE_TTL_MS5 = 24 * 60 * 60 * 1000;
|
|
94132
94870
|
});
|
|
94133
94871
|
|
|
94134
94872
|
// src/proxy-server.ts
|
|
94135
|
-
import { appendFileSync as appendFileSync6, mkdirSync as
|
|
94136
|
-
import { join as
|
|
94873
|
+
import { appendFileSync as appendFileSync6, mkdirSync as mkdirSync23 } from "fs";
|
|
94874
|
+
import { join as join47 } from "path";
|
|
94137
94875
|
function isTerminalRoutingFailure(e) {
|
|
94138
94876
|
return e instanceof RoutingError;
|
|
94139
94877
|
}
|
|
@@ -94141,9 +94879,9 @@ function maybeCaptureClassifierRequest(c, body) {
|
|
|
94141
94879
|
if (!process.env.CLAUDISH_CLASSIFIER_DEBUG)
|
|
94142
94880
|
return;
|
|
94143
94881
|
try {
|
|
94144
|
-
const dir =
|
|
94882
|
+
const dir = join47(process.cwd(), "logs");
|
|
94145
94883
|
if (!classifierCaptureDirReady) {
|
|
94146
|
-
|
|
94884
|
+
mkdirSync23(dir, { recursive: true });
|
|
94147
94885
|
classifierCaptureDirReady = true;
|
|
94148
94886
|
}
|
|
94149
94887
|
const record = {
|
|
@@ -94166,7 +94904,7 @@ function maybeCaptureClassifierRequest(c, body) {
|
|
|
94166
94904
|
"x-api-key": c.req.header("x-api-key") ? "<present>" : null
|
|
94167
94905
|
}
|
|
94168
94906
|
};
|
|
94169
|
-
appendFileSync6(
|
|
94907
|
+
appendFileSync6(join47(dir, "classifier-capture.jsonl"), `${JSON.stringify(record)}
|
|
94170
94908
|
`);
|
|
94171
94909
|
} catch {}
|
|
94172
94910
|
}
|
|
@@ -94686,28 +95424,28 @@ var init_proxy_server = __esm(() => {
|
|
|
94686
95424
|
import {
|
|
94687
95425
|
copyFileSync as copyFileSync2,
|
|
94688
95426
|
existsSync as existsSync34,
|
|
94689
|
-
mkdirSync as
|
|
94690
|
-
readFileSync as
|
|
94691
|
-
readdirSync as
|
|
95427
|
+
mkdirSync as mkdirSync24,
|
|
95428
|
+
readFileSync as readFileSync39,
|
|
95429
|
+
readdirSync as readdirSync8,
|
|
94692
95430
|
unlinkSync as unlinkSync10
|
|
94693
95431
|
} from "fs";
|
|
94694
|
-
import { homedir as
|
|
94695
|
-
import { dirname as
|
|
95432
|
+
import { homedir as homedir39 } from "os";
|
|
95433
|
+
import { dirname as dirname19, join as join48 } from "path";
|
|
94696
95434
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
94697
95435
|
function getVersion3() {
|
|
94698
95436
|
return VERSION;
|
|
94699
95437
|
}
|
|
94700
95438
|
function clearAllModelCaches() {
|
|
94701
|
-
const cacheDir =
|
|
95439
|
+
const cacheDir = join48(homedir39(), ".claudish");
|
|
94702
95440
|
if (!existsSync34(cacheDir))
|
|
94703
95441
|
return;
|
|
94704
95442
|
const cachePatterns = ["pricing-cache.json", "recommended-models-cache-v2.json"];
|
|
94705
95443
|
let cleared = 0;
|
|
94706
95444
|
try {
|
|
94707
|
-
const files =
|
|
95445
|
+
const files = readdirSync8(cacheDir);
|
|
94708
95446
|
for (const file of files) {
|
|
94709
95447
|
if (cachePatterns.includes(file)) {
|
|
94710
|
-
unlinkSync10(
|
|
95448
|
+
unlinkSync10(join48(cacheDir, file));
|
|
94711
95449
|
cleared++;
|
|
94712
95450
|
}
|
|
94713
95451
|
}
|
|
@@ -95045,6 +95783,13 @@ async function parseArgs(args) {
|
|
|
95045
95783
|
process.exit(1);
|
|
95046
95784
|
}
|
|
95047
95785
|
config.effortOverride = effArg;
|
|
95786
|
+
} else if (arg === "--context-window") {
|
|
95787
|
+
const size = parseContextWindow(args[++i] ?? "");
|
|
95788
|
+
if (size === undefined) {
|
|
95789
|
+
console.error("--context-window requires a size in tokens (128000, 128k or 1m)");
|
|
95790
|
+
process.exit(1);
|
|
95791
|
+
}
|
|
95792
|
+
config.contextWindow = size;
|
|
95048
95793
|
} else if (arg === "--pro-on-ultracode") {
|
|
95049
95794
|
config.proOnUltracode = true;
|
|
95050
95795
|
} else if (arg === "--no-pro-on-ultracode") {
|
|
@@ -95989,6 +96734,7 @@ ${h("OPTIONS")}
|
|
|
95989
96734
|
${green("--advisor")} ${yellow('"m1,m2[:collector]"')} Multi-model advisor replacement (works with any --model)
|
|
95990
96735
|
${green("--model-params")} ${yellow('"k=v,..."')} Extra request params merged into the payload (e.g. reasoning.mode=pro)
|
|
95991
96736
|
${green("--effort-override")} ${yellow("<level>")} Pin reasoning effort verbatim, skipping the per-model clamp
|
|
96737
|
+
${green("--context-window")} ${yellow("<size>")} Largest context window (128000, 128k, 1m), for local models
|
|
95992
96738
|
${green("--pro-on-ultracode")} Apply the model's catalog preset while in ultracode (opt-in)
|
|
95993
96739
|
${green("--no-pro-on-ultracode")} Force that off for this run (when enabled in config/env)
|
|
95994
96740
|
${green("--code-mode")} ${yellow("<auto|on|off>")} cx@ tools as one exec script tool (default auto; env CLAUDISH_CODE_MODE)
|
|
@@ -96234,8 +96980,8 @@ ${h("MORE INFO")}
|
|
|
96234
96980
|
}
|
|
96235
96981
|
function printAIAgentGuide() {
|
|
96236
96982
|
try {
|
|
96237
|
-
const guidePath =
|
|
96238
|
-
const guideContent =
|
|
96983
|
+
const guidePath = join48(__dirname2, "../AI_AGENT_GUIDE.md");
|
|
96984
|
+
const guideContent = readFileSync39(guidePath, "utf-8");
|
|
96239
96985
|
console.log(guideContent);
|
|
96240
96986
|
} catch (error) {
|
|
96241
96987
|
console.error("Error reading AI Agent Guide:");
|
|
@@ -96251,10 +96997,10 @@ async function initializeClaudishSkill() {
|
|
|
96251
96997
|
console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
|
|
96252
96998
|
`);
|
|
96253
96999
|
const cwd = process.cwd();
|
|
96254
|
-
const claudeDir =
|
|
96255
|
-
const skillsDir =
|
|
96256
|
-
const claudishSkillDir =
|
|
96257
|
-
const skillFile =
|
|
97000
|
+
const claudeDir = join48(cwd, ".claude");
|
|
97001
|
+
const skillsDir = join48(claudeDir, "skills");
|
|
97002
|
+
const claudishSkillDir = join48(skillsDir, "claudish-usage");
|
|
97003
|
+
const skillFile = join48(claudishSkillDir, "SKILL.md");
|
|
96258
97004
|
if (existsSync34(skillFile)) {
|
|
96259
97005
|
console.log("\u2705 Claudish skill already installed at:");
|
|
96260
97006
|
console.log(` ${skillFile}
|
|
@@ -96262,7 +97008,7 @@ async function initializeClaudishSkill() {
|
|
|
96262
97008
|
console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
|
|
96263
97009
|
return;
|
|
96264
97010
|
}
|
|
96265
|
-
const sourceSkillPath =
|
|
97011
|
+
const sourceSkillPath = join48(__dirname2, "../skills/claudish-usage/SKILL.md");
|
|
96266
97012
|
if (!existsSync34(sourceSkillPath)) {
|
|
96267
97013
|
console.error("\u274C Error: Claudish skill file not found in installation.");
|
|
96268
97014
|
console.error(` Expected at: ${sourceSkillPath}`);
|
|
@@ -96273,15 +97019,15 @@ async function initializeClaudishSkill() {
|
|
|
96273
97019
|
}
|
|
96274
97020
|
try {
|
|
96275
97021
|
if (!existsSync34(claudeDir)) {
|
|
96276
|
-
|
|
97022
|
+
mkdirSync24(claudeDir, { recursive: true });
|
|
96277
97023
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
96278
97024
|
}
|
|
96279
97025
|
if (!existsSync34(skillsDir)) {
|
|
96280
|
-
|
|
97026
|
+
mkdirSync24(skillsDir, { recursive: true });
|
|
96281
97027
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
96282
97028
|
}
|
|
96283
97029
|
if (!existsSync34(claudishSkillDir)) {
|
|
96284
|
-
|
|
97030
|
+
mkdirSync24(claudishSkillDir, { recursive: true });
|
|
96285
97031
|
console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
|
|
96286
97032
|
}
|
|
96287
97033
|
copyFileSync2(sourceSkillPath, skillFile);
|
|
@@ -96353,6 +97099,7 @@ var init_cli = __esm(() => {
|
|
|
96353
97099
|
init_api_key_map();
|
|
96354
97100
|
init_api_key_provenance();
|
|
96355
97101
|
init_claude_code_aliases();
|
|
97102
|
+
init_context_window_limit();
|
|
96356
97103
|
init_endpoint_registration();
|
|
96357
97104
|
init_muse_credentials();
|
|
96358
97105
|
init_model_parser();
|
|
@@ -96367,7 +97114,7 @@ var init_cli = __esm(() => {
|
|
|
96367
97114
|
init_ansi();
|
|
96368
97115
|
init_provider_resolver();
|
|
96369
97116
|
__filename2 = fileURLToPath2(import.meta.url);
|
|
96370
|
-
__dirname2 =
|
|
97117
|
+
__dirname2 = dirname19(__filename2);
|
|
96371
97118
|
CLAUDISH_FLAG_ARITY = {
|
|
96372
97119
|
"--model": "value",
|
|
96373
97120
|
"-m": "value",
|
|
@@ -96409,6 +97156,7 @@ var init_cli = __esm(() => {
|
|
|
96409
97156
|
"--classifier-provider": "value",
|
|
96410
97157
|
"--model-params": "value",
|
|
96411
97158
|
"--effort-override": "value",
|
|
97159
|
+
"--context-window": "value",
|
|
96412
97160
|
"--pro-on-ultracode": "none",
|
|
96413
97161
|
"--no-pro-on-ultracode": "none",
|
|
96414
97162
|
"--code-mode": "value",
|
|
@@ -96485,9 +97233,9 @@ function samePaneSize(a, b) {
|
|
|
96485
97233
|
var DEFAULT_PANE_COLS = 160, DEFAULT_PANE_ROWS = 50, MIN_PANE_COLS = 40, MAX_PANE_COLS = 9999, MIN_PANE_ROWS = 24, MAX_PANE_ROWS = 9999, MAX_PANE_CELLS = 4000000, RESIZE_QUIET_MS = 2000;
|
|
96486
97234
|
|
|
96487
97235
|
// src/pane/process-identity.ts
|
|
96488
|
-
import { execFile as
|
|
97236
|
+
import { execFile as execFile5, execFileSync as execFileSync3 } from "child_process";
|
|
96489
97237
|
import { lstatSync as lstatSync6 } from "fs";
|
|
96490
|
-
import { basename as
|
|
97238
|
+
import { basename as basename4, dirname as dirname20, isAbsolute as isAbsolute3, join as join49, normalize } from "path";
|
|
96491
97239
|
function collapse(s) {
|
|
96492
97240
|
return s.trim().replace(/\s+/g, " ");
|
|
96493
97241
|
}
|
|
@@ -96698,7 +97446,7 @@ function parseGroupFile(text) {
|
|
|
96698
97446
|
return withEscaped(pgid, members, escaped);
|
|
96699
97447
|
}
|
|
96700
97448
|
function isLaunchDirPath(root, p) {
|
|
96701
|
-
if (
|
|
97449
|
+
if (dirname20(p) !== root || !LAUNCH_DIR_RE.test(basename4(p)))
|
|
96702
97450
|
return false;
|
|
96703
97451
|
try {
|
|
96704
97452
|
const st = lstatSync6(p);
|
|
@@ -96711,24 +97459,24 @@ function isValidPaneId(id) {
|
|
|
96711
97459
|
return PANE_ID_RE.test(id) && !/^\d+$/.test(id);
|
|
96712
97460
|
}
|
|
96713
97461
|
function sockPathOf(root, paneId) {
|
|
96714
|
-
return
|
|
97462
|
+
return join49(root, `magmux-${paneId}.sock`);
|
|
96715
97463
|
}
|
|
96716
97464
|
function recordPathOf(root, paneId) {
|
|
96717
|
-
return
|
|
97465
|
+
return join49(root, "panes", `${paneId}.json`);
|
|
96718
97466
|
}
|
|
96719
97467
|
function isPaneSockPath(root, p, paneId) {
|
|
96720
|
-
return isValidPaneId(paneId) &&
|
|
97468
|
+
return isValidPaneId(paneId) && dirname20(p) === root && basename4(p) === `magmux-${paneId}.sock`;
|
|
96721
97469
|
}
|
|
96722
97470
|
function isPaneRecordPath(root, p, paneId) {
|
|
96723
|
-
return isValidPaneId(paneId) &&
|
|
97471
|
+
return isValidPaneId(paneId) && dirname20(p) === join49(root, "panes") && basename4(p) === `${paneId}.json`;
|
|
96724
97472
|
}
|
|
96725
97473
|
function isForkRecordPath(projectsRoot, p, uuid) {
|
|
96726
97474
|
if (!isAbsolute3(projectsRoot) || normalize(projectsRoot) !== projectsRoot)
|
|
96727
97475
|
return false;
|
|
96728
|
-
if (
|
|
97476
|
+
if (basename4(projectsRoot) !== "projects" || !FORK_UUID_RE.test(uuid))
|
|
96729
97477
|
return false;
|
|
96730
|
-
const dir =
|
|
96731
|
-
return
|
|
97478
|
+
const dir = dirname20(p);
|
|
97479
|
+
return dirname20(dir) === projectsRoot && PROJECT_SLUG_RE.test(basename4(dir)) && basename4(p) === `${uuid}.jsonl`;
|
|
96732
97480
|
}
|
|
96733
97481
|
function watcherArgv(a) {
|
|
96734
97482
|
const fork = a.fork ? [a.fork.projectsRoot, a.fork.path, a.fork.removeProjectDir ? "1" : "0"] : [];
|
|
@@ -96843,7 +97591,7 @@ var init_process_identity = __esm(() => {
|
|
|
96843
97591
|
PS_ROW = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(?:((?:\d+-)?(?:\d+:)?\d+:\d+)\s+)?(\S+\s+\S+\s+\d+\s+\d\d:\d\d:\d\d\s+\d{4})\s?(.*)$/;
|
|
96844
97592
|
PS_ENV = { PATH: "/bin:/usr/bin:/usr/sbin:/sbin", LC_ALL: "C" };
|
|
96845
97593
|
PS_OPTIONS = { env: PS_ENV, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 };
|
|
96846
|
-
psSpawn = { execFile:
|
|
97594
|
+
psSpawn = { execFile: execFile5, execFileSync: execFileSync3 };
|
|
96847
97595
|
LAUNCH_DIR_RE = /^launch-[A-Za-z0-9]{6}$/;
|
|
96848
97596
|
PANE_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
96849
97597
|
FORK_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
@@ -96852,18 +97600,18 @@ var init_process_identity = __esm(() => {
|
|
|
96852
97600
|
});
|
|
96853
97601
|
|
|
96854
97602
|
// src/pane/pane-launch.ts
|
|
96855
|
-
import { execFile as
|
|
97603
|
+
import { execFile as execFile6, spawn } from "child_process";
|
|
96856
97604
|
import { randomBytes as randomBytes14 } from "crypto";
|
|
96857
97605
|
import {
|
|
96858
97606
|
chmodSync as chmodSync4,
|
|
96859
97607
|
lstatSync as lstatSync7,
|
|
96860
|
-
mkdirSync as
|
|
97608
|
+
mkdirSync as mkdirSync25,
|
|
96861
97609
|
mkdtempSync as mkdtempSync2,
|
|
96862
|
-
readFileSync as
|
|
96863
|
-
statSync as
|
|
96864
|
-
writeFileSync as
|
|
97610
|
+
readFileSync as readFileSync40,
|
|
97611
|
+
statSync as statSync17,
|
|
97612
|
+
writeFileSync as writeFileSync19
|
|
96865
97613
|
} from "fs";
|
|
96866
|
-
import { join as
|
|
97614
|
+
import { join as join50, resolve as resolve5 } from "path";
|
|
96867
97615
|
function uid() {
|
|
96868
97616
|
return typeof process.getuid === "function" ? process.getuid() : 0;
|
|
96869
97617
|
}
|
|
@@ -96883,17 +97631,17 @@ function assertPrivateDir(p) {
|
|
|
96883
97631
|
function ensureSockRoot(given = sockRootFor()) {
|
|
96884
97632
|
const root = resolve5(given);
|
|
96885
97633
|
try {
|
|
96886
|
-
|
|
97634
|
+
mkdirSync25(root, { mode: 448 });
|
|
96887
97635
|
} catch (e) {
|
|
96888
97636
|
if (e.code === "ENOENT")
|
|
96889
|
-
|
|
97637
|
+
mkdirSync25(root, { recursive: true, mode: 448 });
|
|
96890
97638
|
else if (e.code !== "EEXIST")
|
|
96891
97639
|
throw e;
|
|
96892
97640
|
}
|
|
96893
97641
|
assertPrivateDir(root);
|
|
96894
|
-
const panes =
|
|
97642
|
+
const panes = join50(root, "panes");
|
|
96895
97643
|
try {
|
|
96896
|
-
|
|
97644
|
+
mkdirSync25(panes, { mode: 448 });
|
|
96897
97645
|
} catch (e) {
|
|
96898
97646
|
if (e.code !== "EEXIST")
|
|
96899
97647
|
throw e;
|
|
@@ -96945,7 +97693,7 @@ function buildPaneEnv(input) {
|
|
|
96945
97693
|
if ((input.platform ?? process.platform) === "linux" && entryBytes > LINUX_ENV_STRING_LIMIT)
|
|
96946
97694
|
throw new PaneEnvTooLargeError(`pane environment snapshot is ${entryBytes} bytes, over Linux's 131072-byte limit per variable`);
|
|
96947
97695
|
env[ENV.CLAUDISH_PANE_ENV] = json;
|
|
96948
|
-
env.SHELL =
|
|
97696
|
+
env.SHELL = join50(input.ctlDir, "sh-shim");
|
|
96949
97697
|
return { magmuxEnv: env };
|
|
96950
97698
|
}
|
|
96951
97699
|
function buildReplayEnv(input) {
|
|
@@ -96957,7 +97705,7 @@ function buildReplayEnv(input) {
|
|
|
96957
97705
|
}
|
|
96958
97706
|
if (input.configDirOverride)
|
|
96959
97707
|
env.CLAUDE_CONFIG_DIR = input.configDirOverride;
|
|
96960
|
-
env.SHELL =
|
|
97708
|
+
env.SHELL = join50(input.ctlDir, "sh-shim");
|
|
96961
97709
|
env[ENV.CLAUDISH_PANE_CHILD] = "1";
|
|
96962
97710
|
env.CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC = "1";
|
|
96963
97711
|
env.CLAUDE_CODE_DISABLE_OFFICIAL_MARKETPLACE_AUTOINSTALL = "1";
|
|
@@ -96990,10 +97738,10 @@ function replaySettingsJson(statusLine) {
|
|
|
96990
97738
|
}
|
|
96991
97739
|
function readUserStatusLine(configDir) {
|
|
96992
97740
|
try {
|
|
96993
|
-
const path =
|
|
96994
|
-
if (
|
|
97741
|
+
const path = join50(configDir, "settings.json");
|
|
97742
|
+
if (statSync17(path).size > MAX_USER_SETTINGS_BYTES)
|
|
96995
97743
|
return null;
|
|
96996
|
-
const v = JSON.parse(
|
|
97744
|
+
const v = JSON.parse(readFileSync40(path, "utf8"))?.statusLine;
|
|
96997
97745
|
return v && typeof v === "object" && !Array.isArray(v) ? v : null;
|
|
96998
97746
|
} catch {
|
|
96999
97747
|
return null;
|
|
@@ -97175,7 +97923,7 @@ function runMagmuxVersion(found, timeoutMs) {
|
|
|
97175
97923
|
rejectRun(new MagmuxUnavailableError(`magmux_unavailable: ${found} --version failed: ${detail}`));
|
|
97176
97924
|
};
|
|
97177
97925
|
try {
|
|
97178
|
-
child =
|
|
97926
|
+
child = execFile6(found, ["--version"], { encoding: "utf8" }, (error, stdout, stderr) => {
|
|
97179
97927
|
if (error)
|
|
97180
97928
|
return fail(error.message);
|
|
97181
97929
|
if (settle())
|
|
@@ -97210,21 +97958,21 @@ function replayLauncherScript(realShell, cwd, launch, argv) {
|
|
|
97210
97958
|
${launcherScript(cwd, launch, argv)}`;
|
|
97211
97959
|
}
|
|
97212
97960
|
function paneCommand(ctlDir) {
|
|
97213
|
-
const cmd = `. ${shq2(
|
|
97961
|
+
const cmd = `. ${shq2(join50(ctlDir, "pane-launch.sh"))}`;
|
|
97214
97962
|
if (/claude /.test(cmd) || /claude$/.test(cmd) || /(^|\/)claude['"]?$/.test(cmd))
|
|
97215
97963
|
throw new Error(`pane command would attach magmux's Claude Code controller: ${cmd}`);
|
|
97216
97964
|
return cmd;
|
|
97217
97965
|
}
|
|
97218
97966
|
function createLaunchDirs(root) {
|
|
97219
|
-
const ctlDir = mkdtempSync2(
|
|
97967
|
+
const ctlDir = mkdtempSync2(join50(root, "launch-"));
|
|
97220
97968
|
chmodSync4(ctlDir, 448);
|
|
97221
|
-
const turnDir = mkdtempSync2(
|
|
97969
|
+
const turnDir = mkdtempSync2(join50(root, "launch-"));
|
|
97222
97970
|
chmodSync4(turnDir, 448);
|
|
97223
97971
|
return { ctlDir, turnDir };
|
|
97224
97972
|
}
|
|
97225
97973
|
function writeLauncherFiles(ctlDir, script) {
|
|
97226
|
-
|
|
97227
|
-
|
|
97974
|
+
writeFileSync19(join50(ctlDir, "pane-launch.sh"), script, { mode: 384, flag: "wx" });
|
|
97975
|
+
writeFileSync19(join50(ctlDir, "sh-shim"), SHELL_SHIM, { mode: 448, flag: "wx" });
|
|
97228
97976
|
}
|
|
97229
97977
|
function spawnPaneWatcher(args) {
|
|
97230
97978
|
const proc = spawn("/bin/sh", watcherArgv(args), {
|
|
@@ -97989,18 +98737,18 @@ import {
|
|
|
97989
98737
|
chmodSync as chmodSync5,
|
|
97990
98738
|
closeSync as closeSync13,
|
|
97991
98739
|
existsSync as existsSync36,
|
|
97992
|
-
mkdirSync as
|
|
98740
|
+
mkdirSync as mkdirSync26,
|
|
97993
98741
|
mkdtempSync as mkdtempSync3,
|
|
97994
98742
|
openSync as openSync13,
|
|
97995
|
-
readFileSync as
|
|
97996
|
-
readdirSync as
|
|
97997
|
-
rmSync as
|
|
97998
|
-
statSync as
|
|
98743
|
+
readFileSync as readFileSync41,
|
|
98744
|
+
readdirSync as readdirSync9,
|
|
98745
|
+
rmSync as rmSync12,
|
|
98746
|
+
statSync as statSync18,
|
|
97999
98747
|
unlinkSync as unlinkSync11,
|
|
98000
|
-
writeFileSync as
|
|
98748
|
+
writeFileSync as writeFileSync20
|
|
98001
98749
|
} from "fs";
|
|
98002
|
-
import { homedir as
|
|
98003
|
-
import { dirname as
|
|
98750
|
+
import { homedir as homedir40, tmpdir as tmpdir2 } from "os";
|
|
98751
|
+
import { dirname as dirname21, join as join51 } from "path";
|
|
98004
98752
|
import { isatty } from "tty";
|
|
98005
98753
|
function releaseTerminalIsolation() {
|
|
98006
98754
|
if (!restoreTerminal)
|
|
@@ -98078,7 +98826,7 @@ function hasResolvableAnthropicAuth(deps = {}) {
|
|
|
98078
98826
|
if (isRealAnthropicEnvCredential(env, "ANTHROPIC_API_KEY") || isRealAnthropicEnvCredential(env, "ANTHROPIC_AUTH_TOKEN")) {
|
|
98079
98827
|
return true;
|
|
98080
98828
|
}
|
|
98081
|
-
if (fileExists(
|
|
98829
|
+
if (fileExists(join51(homedir40(), ".claude", ".credentials.json")))
|
|
98082
98830
|
return true;
|
|
98083
98831
|
return keychainProbe();
|
|
98084
98832
|
}
|
|
@@ -98173,15 +98921,15 @@ function settingsAuthSource(settings) {
|
|
|
98173
98921
|
return null;
|
|
98174
98922
|
}
|
|
98175
98923
|
function readableClaudeSettingsLayers(config, env, deps) {
|
|
98176
|
-
const readFile = deps.readFile ?? ((path) =>
|
|
98177
|
-
const home = deps.home ??
|
|
98924
|
+
const readFile = deps.readFile ?? ((path) => readFileSync41(path, "utf-8"));
|
|
98925
|
+
const home = deps.home ?? homedir40();
|
|
98178
98926
|
const cwd = deps.cwd ?? process.cwd();
|
|
98179
98927
|
const files = [
|
|
98180
98928
|
managedSettingsPath(),
|
|
98181
|
-
|
|
98182
|
-
...env.CLAUDE_CONFIG_DIR ? [
|
|
98183
|
-
|
|
98184
|
-
|
|
98929
|
+
join51(home, ".claude", "settings.json"),
|
|
98930
|
+
...env.CLAUDE_CONFIG_DIR ? [join51(env.CLAUDE_CONFIG_DIR, "settings.json")] : [],
|
|
98931
|
+
join51(cwd, ".claude", "settings.json"),
|
|
98932
|
+
join51(cwd, ".claude", "settings.local.json")
|
|
98185
98933
|
];
|
|
98186
98934
|
const layers = [];
|
|
98187
98935
|
for (const file of files) {
|
|
@@ -98213,14 +98961,14 @@ function readSettingsSource(source, readFile) {
|
|
|
98213
98961
|
}
|
|
98214
98962
|
function managedSettingsPath() {
|
|
98215
98963
|
if (isWindows2()) {
|
|
98216
|
-
return
|
|
98964
|
+
return join51(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
|
|
98217
98965
|
}
|
|
98218
98966
|
if (process.platform === "darwin") {
|
|
98219
98967
|
return "/Library/Application Support/ClaudeCode/managed-settings.json";
|
|
98220
98968
|
}
|
|
98221
98969
|
return "/etc/claude-code/managed-settings.json";
|
|
98222
98970
|
}
|
|
98223
|
-
function managedSettingsForcesClaudeAi(readFile =
|
|
98971
|
+
function managedSettingsForcesClaudeAi(readFile = readFileSync41) {
|
|
98224
98972
|
try {
|
|
98225
98973
|
const raw = readFile(managedSettingsPath(), "utf-8");
|
|
98226
98974
|
const parsed = JSON.parse(raw);
|
|
@@ -98234,8 +98982,8 @@ function isWindows2() {
|
|
|
98234
98982
|
}
|
|
98235
98983
|
function createStatusLineScript(tokenFilePath) {
|
|
98236
98984
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
98237
|
-
const claudishDir =
|
|
98238
|
-
const scriptPath =
|
|
98985
|
+
const claudishDir = join51(homeDir, ".claudish");
|
|
98986
|
+
const scriptPath = join51(claudishDir, `status-${process.pid}-${Date.now()}.js`);
|
|
98239
98987
|
const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
|
|
98240
98988
|
const light = getThemeMode() === "light";
|
|
98241
98989
|
const cyanCode = light ? "38;2;14;116;144" : "96";
|
|
@@ -98347,6 +99095,8 @@ process.stdin.on('end', () => {
|
|
|
98347
99095
|
// gap is the whole reason this line exists.
|
|
98348
99096
|
const clamped = effWindow < contextWindow ? ' of ' + formatTokens(contextWindow) : '';
|
|
98349
99097
|
ctxDisplay = '[' + bar + '] ' + formatTokens(inputTokens) + '/' + formatTokens(effWindow) + clamped;
|
|
99098
|
+
} else if (effWindow > 0) {
|
|
99099
|
+
ctxDisplay = '[' + '\u2591'.repeat(15) + '] 0/' + formatTokens(effWindow);
|
|
98350
99100
|
} else {
|
|
98351
99101
|
ctxDisplay = ctx + '%';
|
|
98352
99102
|
}
|
|
@@ -98390,13 +99140,13 @@ process.stdin.on('end', () => {
|
|
|
98390
99140
|
}
|
|
98391
99141
|
});
|
|
98392
99142
|
`;
|
|
98393
|
-
|
|
99143
|
+
writeFileSync20(scriptPath, script, "utf-8");
|
|
98394
99144
|
return scriptPath;
|
|
98395
99145
|
}
|
|
98396
99146
|
function initializeTokenFile(tokenFilePath) {
|
|
98397
99147
|
try {
|
|
98398
|
-
|
|
98399
|
-
|
|
99148
|
+
mkdirSync26(dirname21(tokenFilePath), { recursive: true });
|
|
99149
|
+
writeFileSync20(tokenFilePath, JSON.stringify({
|
|
98400
99150
|
input_tokens: 0,
|
|
98401
99151
|
output_tokens: 0,
|
|
98402
99152
|
total_tokens: 0,
|
|
@@ -98411,11 +99161,23 @@ function initializeTokenFile(tokenFilePath) {
|
|
|
98411
99161
|
log(`[claude-runner] Could not initialize token file ${tokenFilePath}: ${e}`);
|
|
98412
99162
|
}
|
|
98413
99163
|
}
|
|
99164
|
+
function seedTokenFileWindow(tokenFilePath, window2) {
|
|
99165
|
+
if (!window2 || window2 <= 0)
|
|
99166
|
+
return;
|
|
99167
|
+
try {
|
|
99168
|
+
const record = JSON.parse(readFileSync41(tokenFilePath, "utf-8"));
|
|
99169
|
+
if (record.input_tokens !== 0 || record.context_window !== "unknown")
|
|
99170
|
+
return;
|
|
99171
|
+
writeFileSync20(tokenFilePath, JSON.stringify({ ...record, context_window: window2, context_left_percent: 100 }), "utf-8");
|
|
99172
|
+
} catch (e) {
|
|
99173
|
+
log(`[claude-runner] Could not seed token file ${tokenFilePath}: ${e}`);
|
|
99174
|
+
}
|
|
99175
|
+
}
|
|
98414
99176
|
function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FILE_MS) {
|
|
98415
99177
|
let removed = 0;
|
|
98416
99178
|
let entries;
|
|
98417
99179
|
try {
|
|
98418
|
-
entries =
|
|
99180
|
+
entries = readdirSync9(dir);
|
|
98419
99181
|
} catch {
|
|
98420
99182
|
return 0;
|
|
98421
99183
|
}
|
|
@@ -98427,9 +99189,9 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
|
|
|
98427
99189
|
if (!name.startsWith("tokens-") || !name.endsWith(".json"))
|
|
98428
99190
|
continue;
|
|
98429
99191
|
scanned++;
|
|
98430
|
-
const full =
|
|
99192
|
+
const full = join51(dir, name);
|
|
98431
99193
|
try {
|
|
98432
|
-
if (
|
|
99194
|
+
if (statSync18(full).mtimeMs >= cutoff)
|
|
98433
99195
|
continue;
|
|
98434
99196
|
unlinkSync11(full);
|
|
98435
99197
|
removed++;
|
|
@@ -98444,7 +99206,7 @@ function parseSettingsArg(value) {
|
|
|
98444
99206
|
if (value.trimStart().startsWith("{")) {
|
|
98445
99207
|
return JSON.parse(value);
|
|
98446
99208
|
}
|
|
98447
|
-
return JSON.parse(
|
|
99209
|
+
return JSON.parse(readFileSync41(value, "utf-8"));
|
|
98448
99210
|
}
|
|
98449
99211
|
function parseSettingsArgSafe(value) {
|
|
98450
99212
|
try {
|
|
@@ -98456,9 +99218,9 @@ function parseSettingsArgSafe(value) {
|
|
|
98456
99218
|
}
|
|
98457
99219
|
function userSettingsFileCandidates(cwd) {
|
|
98458
99220
|
return [
|
|
98459
|
-
|
|
98460
|
-
|
|
98461
|
-
|
|
99221
|
+
join51(homedir40(), ".claude", "settings.json"),
|
|
99222
|
+
join51(cwd, ".claude", "settings.json"),
|
|
99223
|
+
join51(cwd, ".claude", "settings.local.json")
|
|
98462
99224
|
];
|
|
98463
99225
|
}
|
|
98464
99226
|
function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
|
|
@@ -98499,11 +99261,11 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
|
|
|
98499
99261
|
}
|
|
98500
99262
|
function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
|
|
98501
99263
|
const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
|
|
98502
|
-
const claudishDir =
|
|
99264
|
+
const claudishDir = join51(homeDir, ".claudish");
|
|
98503
99265
|
try {
|
|
98504
|
-
|
|
99266
|
+
mkdirSync26(claudishDir, { recursive: true });
|
|
98505
99267
|
} catch {}
|
|
98506
|
-
const tempPath =
|
|
99268
|
+
const tempPath = join51(claudishDir, `settings-${process.pid}-${Date.now()}.json`);
|
|
98507
99269
|
const assignedFile = assignedTokenFile(process.env) !== null;
|
|
98508
99270
|
const tokenFilePath = resolveTokenFilePath(port);
|
|
98509
99271
|
cleanupStaleTokenFiles(claudishDir);
|
|
@@ -98529,7 +99291,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
98529
99291
|
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; }`;
|
|
98530
99292
|
const effWinBash = `eff_win() { local w=\${1:-0}; local m=\${CLAUDE_CODE_MAX_CONTEXT_TOKENS:-}; local a=\${CLAUDE_CODE_AUTO_COMPACT_WINDOW:-}; case "$m" in ''|*[!0-9]*) m=${CLAUDE_CODE_DEFAULT_MAX_CONTEXT};; esac; case "$a" in ''|*[!0-9]*) a=0;; esac; case "$w" in ''|*[!0-9]*) w=0;; esac; if [ "$w" -gt 0 ]; then if [ "$m" -gt 0 ] && [ "$m" -lt "$w" ]; then w=$m; fi; if [ "$a" -gt 0 ] && [ "$a" -lt "$w" ]; then w=$a; fi; fi; echo "$w"; }`;
|
|
98531
99293
|
const dirPrelude = `DIR=$(basename "$(pwd)"); [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true; `;
|
|
98532
|
-
const readState = `CTX=-1; COST="0"; IS_FREE="false"; IS_EST="false"; PROVIDER=""; TOKEN_MODEL=""; IN_TOK=0; CTX_WIN=0; PLAN_DISPLAY=""; ALLOW_DISPLAY=""; ALLOW_COLOR=""; ${formatTokensBash}; ${effWinBash}; ${fmtAtBash}; if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d '\\n\\r'); V=$(echo "$TOKENS" | grep -o '"context_left_percent": *-\\?[0-9]*' | grep -o '\\-\\?[0-9]*'); [ -n "$V" ] && CTX="$V"; V=$(echo "$TOKENS" | grep -o '"total_cost": *[0-9.]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && COST="$V"; V=$(echo "$TOKENS" | grep -o '"input_tokens": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && IN_TOK="$V"; V=$(echo "$TOKENS" | grep -o '"context_window": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && CTX_WIN="$V"; V=$(echo "$TOKENS" | grep -o '"is_free": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_FREE="$V"; V=$(echo "$TOKENS" | grep -o '"is_estimated": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_EST="$V"; V=$(echo "$TOKENS" | grep -o '"provider_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && PROVIDER="$V"; V=$(echo "$TOKENS" | grep -o '"model_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && TOKEN_MODEL="$V"; ${readPlanBash} ${readAllowanceBash} 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="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}"; if [ -n "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi; EFF_WIN=$(eff_win $CTX_WIN); if [ "$EFF_WIN" -gt 0 ] 2>/dev/null && [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX=$(( ((EFF_WIN - IN_TOK) * 200 / EFF_WIN + 1) / 2 )); if [ "$CTX" -lt 0 ]; then CTX=0; fi; fi; if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$EFF_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null; then if [ "$EFF_WIN" -lt "$CTX_WIN" ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN) of $(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN))"; fi; else CTX_DISPLAY="$CTX%"; fi`;
|
|
99294
|
+
const readState = `CTX=-1; COST="0"; IS_FREE="false"; IS_EST="false"; PROVIDER=""; TOKEN_MODEL=""; IN_TOK=0; CTX_WIN=0; PLAN_DISPLAY=""; ALLOW_DISPLAY=""; ALLOW_COLOR=""; ${formatTokensBash}; ${effWinBash}; ${fmtAtBash}; if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d '\\n\\r'); V=$(echo "$TOKENS" | grep -o '"context_left_percent": *-\\?[0-9]*' | grep -o '\\-\\?[0-9]*'); [ -n "$V" ] && CTX="$V"; V=$(echo "$TOKENS" | grep -o '"total_cost": *[0-9.]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && COST="$V"; V=$(echo "$TOKENS" | grep -o '"input_tokens": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && IN_TOK="$V"; V=$(echo "$TOKENS" | grep -o '"context_window": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && CTX_WIN="$V"; V=$(echo "$TOKENS" | grep -o '"is_free": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_FREE="$V"; V=$(echo "$TOKENS" | grep -o '"is_estimated": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_EST="$V"; V=$(echo "$TOKENS" | grep -o '"provider_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && PROVIDER="$V"; V=$(echo "$TOKENS" | grep -o '"model_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && TOKEN_MODEL="$V"; ${readPlanBash} ${readAllowanceBash} 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="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}"; if [ -n "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi; EFF_WIN=$(eff_win $CTX_WIN); if [ "$EFF_WIN" -gt 0 ] 2>/dev/null && [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX=$(( ((EFF_WIN - IN_TOK) * 200 / EFF_WIN + 1) / 2 )); if [ "$CTX" -lt 0 ]; then CTX=0; fi; fi; if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$EFF_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null; then if [ "$EFF_WIN" -lt "$CTX_WIN" ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN) of $(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN))"; fi; elif [ "$EFF_WIN" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$CTX% (0/$(fmt_tok $EFF_WIN))"; else CTX_DISPLAY="$CTX%"; fi`;
|
|
98533
99295
|
const planSuffix = `if [ -n "$PLAN_DISPLAY" ]; then printf " ${DIM}\u2022${RESET} ${GREEN}%s${RESET}" "$PLAN_DISPLAY"; fi; if [ -n "$ALLOW_DISPLAY" ]; then printf " ${DIM}\u2022${RESET} $ALLOW_COLOR%s${RESET}" "$ALLOW_DISPLAY"; fi`;
|
|
98534
99296
|
const segmentWithDir = `printf "${CYAN}${BOLD}%s${RESET} ${DIM}\u2022${RESET} ${YELLOW}%s${RESET} ${DIM}\u2022${RESET} ${GREEN}%s${RESET} ${DIM}\u2022${RESET} ${MAGENTA}%s${RESET}" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
|
|
98535
99297
|
const segmentNoDirWithProvider = `printf "${YELLOW}%s${RESET} ${DIM}\u2022${RESET} ${GREEN}%s${RESET} ${DIM}\u2022${RESET} ${MAGENTA}%s${RESET}" "$PROVIDER" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
|
|
@@ -98543,7 +99305,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
|
|
|
98543
99305
|
padding: 0
|
|
98544
99306
|
};
|
|
98545
99307
|
const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
|
|
98546
|
-
|
|
99308
|
+
writeFileSync20(tempPath, JSON.stringify(settings, null, 2), { encoding: "utf-8", mode: 384 });
|
|
98547
99309
|
return { path: tempPath, statusLine, tokenFilePath };
|
|
98548
99310
|
}
|
|
98549
99311
|
function scrubChildEnv(env, opts) {
|
|
@@ -98595,7 +99357,7 @@ function mergeUserSettingsIfPresent(config, tempSettingsPath, statusLine, proxyA
|
|
|
98595
99357
|
userSettings.tui = "fullscreen";
|
|
98596
99358
|
}
|
|
98597
99359
|
chmodSync5(tempSettingsPath, 384);
|
|
98598
|
-
|
|
99360
|
+
writeFileSync20(tempSettingsPath, JSON.stringify(userSettings, null, 2), {
|
|
98599
99361
|
encoding: "utf-8",
|
|
98600
99362
|
mode: 384
|
|
98601
99363
|
});
|
|
@@ -98617,10 +99379,24 @@ async function resolveLocalContextWindow(spec, cachePath) {
|
|
|
98617
99379
|
provider = plan.primary.provider;
|
|
98618
99380
|
wireId = parseModelSpec(plan.primary.modelSpec).model;
|
|
98619
99381
|
}
|
|
99382
|
+
const definition = getProviderByName(provider);
|
|
99383
|
+
const limit = definition?.isLocal ? contextWindowLimit() : undefined;
|
|
99384
|
+
const capped = (window2) => Math.min(window2, limit ?? window2);
|
|
99385
|
+
if (definition?.unknownContextWindow !== undefined) {
|
|
99386
|
+
const served = await discoverContextWindow(provider, wireId, {
|
|
99387
|
+
network: "bounded",
|
|
99388
|
+
upTo: limit ?? definition.unknownContextWindow
|
|
99389
|
+
});
|
|
99390
|
+
return {
|
|
99391
|
+
modelId: parsed.model,
|
|
99392
|
+
window: capped(served ?? limit ?? definition.unknownContextWindow)
|
|
99393
|
+
};
|
|
99394
|
+
}
|
|
98620
99395
|
const win = await discoverContextWindow(provider, wireId, { network: "cached-first" }) ?? lookupModelForProvider(parsed.model, provider, cachePath) ?? (wireId !== parsed.model ? lookupModelForProvider(wireId, provider, cachePath) : undefined) ?? await discoverContextWindow(provider, wireId, { network: "bounded" });
|
|
99396
|
+
const known = typeof win === "number" && win > 0 ? win : undefined;
|
|
98621
99397
|
return {
|
|
98622
99398
|
modelId: parsed.model,
|
|
98623
|
-
window:
|
|
99399
|
+
window: known !== undefined ? capped(known) : limit ?? null
|
|
98624
99400
|
};
|
|
98625
99401
|
}
|
|
98626
99402
|
async function computeMainThreadContextWindow(config, cachePath) {
|
|
@@ -98865,6 +99641,7 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
|
|
|
98865
99641
|
applyHostRouting(env);
|
|
98866
99642
|
const realWindow = await computeMainThreadContextWindow(config);
|
|
98867
99643
|
const contextEnv = resolveContextWindowEnv(realWindow, process.env);
|
|
99644
|
+
seedTokenFileWindow(resolveTokenFilePath(port), realWindow);
|
|
98868
99645
|
Object.assign(env, contextEnv.vars);
|
|
98869
99646
|
try {
|
|
98870
99647
|
await Promise.resolve().then(() => init_aggregate());
|
|
@@ -98914,8 +99691,8 @@ async function runClaudeWithProxy(config, proxyUrl, onCleanup) {
|
|
|
98914
99691
|
console.error("Install it from: https://claude.com/claude-code");
|
|
98915
99692
|
console.error(`
|
|
98916
99693
|
Or set CLAUDE_PATH to your custom installation:`);
|
|
98917
|
-
const home =
|
|
98918
|
-
const localPath = isWindows2() ?
|
|
99694
|
+
const home = homedir40();
|
|
99695
|
+
const localPath = isWindows2() ? join51(home, ".claude", "local", "claude.exe") : join51(home, ".claude", "local", "claude");
|
|
98919
99696
|
console.error(` export CLAUDE_PATH=${localPath}`);
|
|
98920
99697
|
process.exit(1);
|
|
98921
99698
|
}
|
|
@@ -98950,7 +99727,7 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
98950
99727
|
let driverLaunch = null;
|
|
98951
99728
|
if (surfaces.driver) {
|
|
98952
99729
|
const minted = sessionFlags.sessionId || sessionFlags.resumes ? null : randomUUID8();
|
|
98953
|
-
const turnDir = mkdtempSync3(
|
|
99730
|
+
const turnDir = mkdtempSync3(join51(tmpdir2(), "claudish-turns-"));
|
|
98954
99731
|
chmodSync5(turnDir, 448);
|
|
98955
99732
|
claudeArgs.unshift(...driverLeadingArgs({ mintedSessionId: minted, turnDir }));
|
|
98956
99733
|
const sink = new InProcessSink;
|
|
@@ -99056,7 +99833,7 @@ Or set CLAUDE_PATH to your custom installation:`);
|
|
|
99056
99833
|
if (driverLaunch) {
|
|
99057
99834
|
setProcessSink(null);
|
|
99058
99835
|
try {
|
|
99059
|
-
|
|
99836
|
+
rmSync12(driverLaunch.turnDir, { recursive: true, force: true });
|
|
99060
99837
|
} catch {}
|
|
99061
99838
|
}
|
|
99062
99839
|
log(exitSignal ? `[Claude Code] Exited from ${exitSignal} (exit code ${exitCode})` : `[Claude Code] Exited with code ${exitCode}`);
|
|
@@ -99154,16 +99931,16 @@ async function findClaudeBinary(env = process.env) {
|
|
|
99154
99931
|
return env.CLAUDE_PATH;
|
|
99155
99932
|
}
|
|
99156
99933
|
}
|
|
99157
|
-
const home =
|
|
99158
|
-
const localPath = isWindows ?
|
|
99934
|
+
const home = homedir40();
|
|
99935
|
+
const localPath = isWindows ? join51(home, ".claude", "local", "claude.exe") : join51(home, ".claude", "local", "claude");
|
|
99159
99936
|
if (existsSync36(localPath)) {
|
|
99160
99937
|
return localPath;
|
|
99161
99938
|
}
|
|
99162
99939
|
if (isWindows) {
|
|
99163
99940
|
const windowsPaths = [
|
|
99164
|
-
|
|
99165
|
-
|
|
99166
|
-
|
|
99941
|
+
join51(home, "AppData", "Roaming", "npm", "claude.cmd"),
|
|
99942
|
+
join51(home, ".npm-global", "claude.cmd"),
|
|
99943
|
+
join51(home, "node_modules", ".bin", "claude.cmd")
|
|
99167
99944
|
];
|
|
99168
99945
|
for (const path of windowsPaths) {
|
|
99169
99946
|
if (existsSync36(path)) {
|
|
@@ -99174,11 +99951,11 @@ async function findClaudeBinary(env = process.env) {
|
|
|
99174
99951
|
const commonPaths = [
|
|
99175
99952
|
"/usr/local/bin/claude",
|
|
99176
99953
|
"/opt/homebrew/bin/claude",
|
|
99177
|
-
|
|
99178
|
-
|
|
99179
|
-
|
|
99954
|
+
join51(home, ".npm-global/bin/claude"),
|
|
99955
|
+
join51(home, ".local/bin/claude"),
|
|
99956
|
+
join51(home, "node_modules/.bin/claude"),
|
|
99180
99957
|
"/data/data/com.termux/files/usr/bin/claude",
|
|
99181
|
-
|
|
99958
|
+
join51(home, "../usr/bin/claude")
|
|
99182
99959
|
];
|
|
99183
99960
|
for (const path of commonPaths) {
|
|
99184
99961
|
if (existsSync36(path)) {
|
|
@@ -99264,6 +100041,7 @@ var init_claude_runner = __esm(() => {
|
|
|
99264
100041
|
init_pane_launch();
|
|
99265
100042
|
init_process_tree();
|
|
99266
100043
|
init_profile_config();
|
|
100044
|
+
init_context_window_limit();
|
|
99267
100045
|
init_model_discovery();
|
|
99268
100046
|
init_model_parser();
|
|
99269
100047
|
init_provider_definitions();
|
|
@@ -99506,19 +100284,19 @@ var init_slot_row = __esm(() => {
|
|
|
99506
100284
|
});
|
|
99507
100285
|
|
|
99508
100286
|
// src/team-stats.ts
|
|
99509
|
-
import { existsSync as existsSync37, readFileSync as
|
|
99510
|
-
import { join as
|
|
100287
|
+
import { existsSync as existsSync37, readFileSync as readFileSync42, writeFileSync as writeFileSync21 } from "fs";
|
|
100288
|
+
import { join as join52 } from "path";
|
|
99511
100289
|
function statsDir(sessionPath) {
|
|
99512
|
-
return
|
|
100290
|
+
return join52(sessionPath, "stats");
|
|
99513
100291
|
}
|
|
99514
100292
|
function tokenFileFor(sessionPath, anonId) {
|
|
99515
|
-
return
|
|
100293
|
+
return join52(statsDir(sessionPath), `${anonId}.json`);
|
|
99516
100294
|
}
|
|
99517
100295
|
function readTokenStatsAt(path) {
|
|
99518
100296
|
if (!existsSync37(path))
|
|
99519
100297
|
return null;
|
|
99520
100298
|
try {
|
|
99521
|
-
return JSON.parse(
|
|
100299
|
+
return JSON.parse(readFileSync42(path, "utf-8"));
|
|
99522
100300
|
} catch {
|
|
99523
100301
|
return null;
|
|
99524
100302
|
}
|
|
@@ -99675,7 +100453,7 @@ ${segs.join(" \xB7 ")}`;
|
|
|
99675
100453
|
}
|
|
99676
100454
|
function writeStatusFile(sessionPath, manifest, status, opts) {
|
|
99677
100455
|
try {
|
|
99678
|
-
|
|
100456
|
+
writeFileSync21(join52(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
|
|
99679
100457
|
`, "utf-8");
|
|
99680
100458
|
} catch {}
|
|
99681
100459
|
}
|
|
@@ -99685,11 +100463,11 @@ var init_team_stats = __esm(() => {
|
|
|
99685
100463
|
});
|
|
99686
100464
|
|
|
99687
100465
|
// src/pane/accounting.ts
|
|
99688
|
-
import { statSync as
|
|
100466
|
+
import { statSync as statSync19 } from "fs";
|
|
99689
100467
|
function readTokenFileCached(path) {
|
|
99690
100468
|
let st;
|
|
99691
100469
|
try {
|
|
99692
|
-
const s =
|
|
100470
|
+
const s = statSync19(path);
|
|
99693
100471
|
st = { mtimeMs: s.mtimeMs, size: s.size };
|
|
99694
100472
|
} catch {
|
|
99695
100473
|
cache2.delete(path);
|
|
@@ -99762,15 +100540,15 @@ import {
|
|
|
99762
100540
|
accessSync as accessSync2,
|
|
99763
100541
|
existsSync as existsSync38,
|
|
99764
100542
|
lstatSync as lstatSync8,
|
|
99765
|
-
readFileSync as
|
|
99766
|
-
readdirSync as
|
|
99767
|
-
renameSync as
|
|
99768
|
-
rmSync as
|
|
99769
|
-
rmdirSync,
|
|
100543
|
+
readFileSync as readFileSync43,
|
|
100544
|
+
readdirSync as readdirSync10,
|
|
100545
|
+
renameSync as renameSync10,
|
|
100546
|
+
rmSync as rmSync13,
|
|
100547
|
+
rmdirSync as rmdirSync2,
|
|
99770
100548
|
unlinkSync as unlinkSync12,
|
|
99771
|
-
writeFileSync as
|
|
100549
|
+
writeFileSync as writeFileSync22
|
|
99772
100550
|
} from "fs";
|
|
99773
|
-
import { dirname as
|
|
100551
|
+
import { dirname as dirname22, join as join53 } from "path";
|
|
99774
100552
|
function ownerStartOfSelf() {
|
|
99775
100553
|
if (ownStart)
|
|
99776
100554
|
return ownStart;
|
|
@@ -99791,20 +100569,20 @@ function ownerAlive(owner, table) {
|
|
|
99791
100569
|
return !minted || startedAt(row, minted.startMs);
|
|
99792
100570
|
}
|
|
99793
100571
|
function recordsDir(root) {
|
|
99794
|
-
return
|
|
100572
|
+
return join53(root, "panes");
|
|
99795
100573
|
}
|
|
99796
100574
|
function writeRecord(root, rec) {
|
|
99797
100575
|
const p = recordPathOf(root, rec.paneId);
|
|
99798
100576
|
const tmp = `${p}.tmp-${process.pid}`;
|
|
99799
|
-
|
|
100577
|
+
writeFileSync22(tmp, `${JSON.stringify(rec)}
|
|
99800
100578
|
`, { mode: 384 });
|
|
99801
|
-
|
|
100579
|
+
renameSync10(tmp, p);
|
|
99802
100580
|
}
|
|
99803
100581
|
function readRecord(root, paneId) {
|
|
99804
100582
|
if (!isValidPaneId(paneId))
|
|
99805
100583
|
return null;
|
|
99806
100584
|
try {
|
|
99807
|
-
return validRecord(JSON.parse(
|
|
100585
|
+
return validRecord(JSON.parse(readFileSync43(recordPathOf(root, paneId), "utf8")), paneId);
|
|
99808
100586
|
} catch {
|
|
99809
100587
|
return null;
|
|
99810
100588
|
}
|
|
@@ -99861,7 +100639,7 @@ function validForkRef(v) {
|
|
|
99861
100639
|
function readRecords(root) {
|
|
99862
100640
|
let names;
|
|
99863
100641
|
try {
|
|
99864
|
-
names =
|
|
100642
|
+
names = readdirSync10(recordsDir(root)).filter((n) => n.endsWith(".json"));
|
|
99865
100643
|
} catch {
|
|
99866
100644
|
return [];
|
|
99867
100645
|
}
|
|
@@ -99875,36 +100653,36 @@ function readRecords(root) {
|
|
|
99875
100653
|
}
|
|
99876
100654
|
function readGroupFile(ctlDir) {
|
|
99877
100655
|
try {
|
|
99878
|
-
return parseGroupFile(
|
|
100656
|
+
return parseGroupFile(readFileSync43(join53(ctlDir, "group"), "utf8"));
|
|
99879
100657
|
} catch {
|
|
99880
100658
|
return null;
|
|
99881
100659
|
}
|
|
99882
100660
|
}
|
|
99883
100661
|
function writeGroupFile(ctlDir, snap) {
|
|
99884
|
-
const p =
|
|
100662
|
+
const p = join53(ctlDir, "group");
|
|
99885
100663
|
const tmp = `${p}.tmp`;
|
|
99886
100664
|
try {
|
|
99887
|
-
|
|
99888
|
-
|
|
100665
|
+
writeFileSync22(tmp, formatGroupFile(snap), { mode: 384 });
|
|
100666
|
+
renameSync10(tmp, p);
|
|
99889
100667
|
} catch {}
|
|
99890
100668
|
}
|
|
99891
100669
|
function removeForkRecord(fork, forkUuid) {
|
|
99892
100670
|
if (!isForkRecordPath(fork.projectsRoot, fork.path, forkUuid))
|
|
99893
100671
|
return;
|
|
99894
100672
|
try {
|
|
99895
|
-
|
|
100673
|
+
rmSync13(fork.path, { force: true });
|
|
99896
100674
|
if (fork.removeProjectDir)
|
|
99897
|
-
|
|
100675
|
+
rmdirSync2(dirname22(fork.path));
|
|
99898
100676
|
} catch {}
|
|
99899
100677
|
}
|
|
99900
100678
|
function removePaneFiles(root, f) {
|
|
99901
100679
|
if (f.fork && f.sessionUuid)
|
|
99902
100680
|
removeForkRecord(f.fork, f.sessionUuid);
|
|
99903
100681
|
if (isPaneSockPath(root, f.sockPath, f.paneId))
|
|
99904
|
-
|
|
100682
|
+
rmSync13(f.sockPath, { force: true });
|
|
99905
100683
|
for (const d of [f.launcherDir, f.turnDir])
|
|
99906
100684
|
if (d && isLaunchDirPath(root, d))
|
|
99907
|
-
|
|
100685
|
+
rmSync13(d, { recursive: true, force: true });
|
|
99908
100686
|
const rec = recordPathOf(root, f.paneId);
|
|
99909
100687
|
if (isPaneRecordPath(root, rec, f.paneId))
|
|
99910
100688
|
deleteRecord(root, f.paneId);
|
|
@@ -100169,11 +100947,11 @@ async function sweepRecordlessSocket(root, name, out) {
|
|
|
100169
100947
|
const owner = ownerOfSocketId(id);
|
|
100170
100948
|
if (!owner || ownerAlive(owner, table))
|
|
100171
100949
|
return;
|
|
100172
|
-
const sockPath =
|
|
100950
|
+
const sockPath = join53(root, name);
|
|
100173
100951
|
const magmuxMayLive = !table || table.some((r) => isPaneMagmuxCommand(r.command, id));
|
|
100174
100952
|
const probe = await probeSocket(sockPath, magmuxMayLive);
|
|
100175
100953
|
if (probe.state === "stale") {
|
|
100176
|
-
|
|
100954
|
+
rmSync13(sockPath, { force: true });
|
|
100177
100955
|
out.cleaned.push(id);
|
|
100178
100956
|
return;
|
|
100179
100957
|
}
|
|
@@ -100199,7 +100977,7 @@ async function sweepRecordlessSocket(root, name, out) {
|
|
|
100199
100977
|
if (mag)
|
|
100200
100978
|
signal(mag.pid, "SIGKILL");
|
|
100201
100979
|
await Bun.sleep(300);
|
|
100202
|
-
|
|
100980
|
+
rmSync13(sockPath, { force: true });
|
|
100203
100981
|
(mag ? out.reaped : out.kept).push(id);
|
|
100204
100982
|
}
|
|
100205
100983
|
async function ensureSwept(root) {
|
|
@@ -100218,7 +100996,7 @@ async function sweepOrphanPanes(root = sockRootFor()) {
|
|
|
100218
100996
|
const known = new Set(readRecords(root).map((r) => r.paneId));
|
|
100219
100997
|
let names = [];
|
|
100220
100998
|
try {
|
|
100221
|
-
names =
|
|
100999
|
+
names = readdirSync10(root).filter((n) => /^magmux-c\d+-[A-Za-z0-9_-]+\.sock$/.test(n));
|
|
100222
101000
|
} catch {
|
|
100223
101001
|
names = [];
|
|
100224
101002
|
}
|
|
@@ -100249,19 +101027,19 @@ var init_pane_registry = __esm(() => {
|
|
|
100249
101027
|
|
|
100250
101028
|
// src/pane/gate-binding.ts
|
|
100251
101029
|
import { realpathSync as realpathSync6 } from "fs";
|
|
100252
|
-
import { basename as
|
|
101030
|
+
import { basename as basename5, dirname as dirname23, join as join54, resolve as resolve6 } from "path";
|
|
100253
101031
|
function normaliseTranscriptPath(p) {
|
|
100254
101032
|
const abs = resolve6(p);
|
|
100255
101033
|
const tail = [];
|
|
100256
101034
|
let cur = abs;
|
|
100257
101035
|
for (;; ) {
|
|
100258
101036
|
try {
|
|
100259
|
-
return tail.length ?
|
|
101037
|
+
return tail.length ? join54(realpathSync6(cur), ...tail.reverse()) : realpathSync6(cur);
|
|
100260
101038
|
} catch {
|
|
100261
|
-
const parent =
|
|
101039
|
+
const parent = dirname23(cur);
|
|
100262
101040
|
if (parent === cur)
|
|
100263
101041
|
return abs;
|
|
100264
|
-
tail.push(
|
|
101042
|
+
tail.push(basename5(cur));
|
|
100265
101043
|
cur = parent;
|
|
100266
101044
|
}
|
|
100267
101045
|
}
|
|
@@ -100456,8 +101234,8 @@ var init_scroll_input = __esm(() => {
|
|
|
100456
101234
|
});
|
|
100457
101235
|
|
|
100458
101236
|
// src/pane/session-registry.ts
|
|
100459
|
-
import { readFileSync as
|
|
100460
|
-
import { join as
|
|
101237
|
+
import { readFileSync as readFileSync44, readdirSync as readdirSync11 } from "fs";
|
|
101238
|
+
import { join as join55 } from "path";
|
|
100461
101239
|
function parseRegistryRecord(raw) {
|
|
100462
101240
|
let parsed;
|
|
100463
101241
|
try {
|
|
@@ -100484,7 +101262,7 @@ function parseRegistryRecord(raw) {
|
|
|
100484
101262
|
version: typeof r.version === "string" ? r.version : null
|
|
100485
101263
|
};
|
|
100486
101264
|
}
|
|
100487
|
-
function
|
|
101265
|
+
function pidAlive2(pid) {
|
|
100488
101266
|
try {
|
|
100489
101267
|
process.kill(pid, 0);
|
|
100490
101268
|
return true;
|
|
@@ -100502,9 +101280,9 @@ class SessionRegistry {
|
|
|
100502
101280
|
isAlive;
|
|
100503
101281
|
constructor(o) {
|
|
100504
101282
|
this.o = o;
|
|
100505
|
-
this.dir =
|
|
101283
|
+
this.dir = join55(o.configDir, "sessions");
|
|
100506
101284
|
this.now = o.now ?? Date.now;
|
|
100507
|
-
this.isAlive = o.isAlive ??
|
|
101285
|
+
this.isAlive = o.isAlive ?? pidAlive2;
|
|
100508
101286
|
}
|
|
100509
101287
|
read() {
|
|
100510
101288
|
if (this.pid !== null) {
|
|
@@ -100519,7 +101297,7 @@ class SessionRegistry {
|
|
|
100519
101297
|
this.lastScanAt = now;
|
|
100520
101298
|
let names;
|
|
100521
101299
|
try {
|
|
100522
|
-
names =
|
|
101300
|
+
names = readdirSync11(this.dir);
|
|
100523
101301
|
} catch {
|
|
100524
101302
|
return null;
|
|
100525
101303
|
}
|
|
@@ -100538,7 +101316,7 @@ class SessionRegistry {
|
|
|
100538
101316
|
readPid(pid) {
|
|
100539
101317
|
let raw;
|
|
100540
101318
|
try {
|
|
100541
|
-
raw =
|
|
101319
|
+
raw = readFileSync44(join55(this.dir, `${pid}.json`), "utf8");
|
|
100542
101320
|
} catch {
|
|
100543
101321
|
return null;
|
|
100544
101322
|
}
|
|
@@ -100651,8 +101429,8 @@ var init_slot_state = __esm(() => {
|
|
|
100651
101429
|
});
|
|
100652
101430
|
|
|
100653
101431
|
// src/pane/pane-session.ts
|
|
100654
|
-
import { readFileSync as
|
|
100655
|
-
import { join as
|
|
101432
|
+
import { readFileSync as readFileSync45, realpathSync as realpathSync7, rmSync as rmSync14, statSync as statSync20, writeFileSync as writeFileSync23 } from "fs";
|
|
101433
|
+
import { join as join56 } from "path";
|
|
100656
101434
|
function iso3(ms) {
|
|
100657
101435
|
return new Date(ms).toISOString();
|
|
100658
101436
|
}
|
|
@@ -100801,7 +101579,7 @@ class PaneSessionImpl {
|
|
|
100801
101579
|
});
|
|
100802
101580
|
this.secondaryQuietMs = o.timings?.secondaryQuietMs ?? SECONDARY_QUIET_MS;
|
|
100803
101581
|
this.corroborationMs = o.timings?.corroborationMs ?? CORROBORATION_MS;
|
|
100804
|
-
this.follower = new TranscriptFollower(o.transcriptPath,
|
|
101582
|
+
this.follower = new TranscriptFollower(o.transcriptPath, join56(o.transcriptPath.replace(/\.jsonl$/, ""), "subagents"));
|
|
100805
101583
|
this.registry = new SessionRegistry({
|
|
100806
101584
|
configDir: claudeConfigDir(o.parentEnv ?? process.env),
|
|
100807
101585
|
sessionUuid: o.sessionUuid
|
|
@@ -100848,7 +101626,7 @@ class PaneSessionImpl {
|
|
|
100848
101626
|
return this.spawnFailed(new Error("magmux did not start"));
|
|
100849
101627
|
this.magmux = proc;
|
|
100850
101628
|
try {
|
|
100851
|
-
|
|
101629
|
+
writeFileSync23(join56(this.ctlDir, "magmux.pid"), `${proc.pid}
|
|
100852
101630
|
`, { mode: 384 });
|
|
100853
101631
|
} catch {}
|
|
100854
101632
|
updateRecord(this.root, this.paneId, { magmuxPid: proc.pid });
|
|
@@ -102596,7 +103374,7 @@ ${screenTailOf(this.screen)}`
|
|
|
102596
103374
|
if (!p)
|
|
102597
103375
|
return 0;
|
|
102598
103376
|
try {
|
|
102599
|
-
return
|
|
103377
|
+
return statSync20(p).size;
|
|
102600
103378
|
} catch {
|
|
102601
103379
|
return 0;
|
|
102602
103380
|
}
|
|
@@ -102605,7 +103383,7 @@ ${screenTailOf(this.screen)}`
|
|
|
102605
103383
|
const p = this.errorLogPath();
|
|
102606
103384
|
if (p && this.errorLogSize() > st.errorLogSize) {
|
|
102607
103385
|
try {
|
|
102608
|
-
const text =
|
|
103386
|
+
const text = readFileSync45(p, "utf8").slice(st.errorLogSize).trim();
|
|
102609
103387
|
return { status: null, category: "upstream_error_log", text };
|
|
102610
103388
|
} catch {}
|
|
102611
103389
|
}
|
|
@@ -103240,7 +104018,7 @@ function preparePane(o, root, parentEnv) {
|
|
|
103240
104018
|
} catch (e) {
|
|
103241
104019
|
for (const d of dirs ? [dirs.ctlDir, dirs.turnDir] : [])
|
|
103242
104020
|
if (isLaunchDirPath(root, d))
|
|
103243
|
-
|
|
104021
|
+
rmSync14(d, { recursive: true, force: true });
|
|
103244
104022
|
if (e.code)
|
|
103245
104023
|
throw e;
|
|
103246
104024
|
throw new PaneStartError("pane_lost", e instanceof Error ? e.message : String(e));
|
|
@@ -103361,8 +104139,8 @@ var init_pane_session = __esm(() => {
|
|
|
103361
104139
|
});
|
|
103362
104140
|
|
|
103363
104141
|
// src/pane/replay-pane.ts
|
|
103364
|
-
import { rmSync as
|
|
103365
|
-
import { join as
|
|
104142
|
+
import { rmSync as rmSync15, writeFileSync as writeFileSync24 } from "fs";
|
|
104143
|
+
import { join as join57 } from "path";
|
|
103366
104144
|
async function waitUntil(pred, ms) {
|
|
103367
104145
|
const end = Date.now() + ms;
|
|
103368
104146
|
while (!pred() && Date.now() < end)
|
|
@@ -103471,7 +104249,7 @@ class ReplayPane {
|
|
|
103471
104249
|
return failed(new Error("magmux did not start"));
|
|
103472
104250
|
this.magmuxProc = proc;
|
|
103473
104251
|
try {
|
|
103474
|
-
|
|
104252
|
+
writeFileSync24(join57(this.ctlDir, "magmux.pid"), `${proc.pid}
|
|
103475
104253
|
`, { mode: 384 });
|
|
103476
104254
|
} catch {}
|
|
103477
104255
|
updateRecord(this.root, this.paneId, { magmuxPid: proc.pid });
|
|
@@ -103921,7 +104699,7 @@ async function startReplayPane(o) {
|
|
|
103921
104699
|
} catch (e) {
|
|
103922
104700
|
for (const d of dirs ? [dirs.ctlDir, dirs.turnDir] : [])
|
|
103923
104701
|
if (isLaunchDirPath(root, d))
|
|
103924
|
-
|
|
104702
|
+
rmSync15(d, { recursive: true, force: true });
|
|
103925
104703
|
throw e;
|
|
103926
104704
|
}
|
|
103927
104705
|
const pane = new ReplayPane(o, {
|
|
@@ -104370,12 +105148,12 @@ import {
|
|
|
104370
105148
|
lstatSync as lstatSync9,
|
|
104371
105149
|
openSync as openSync15,
|
|
104372
105150
|
readSync as readSync6,
|
|
104373
|
-
readdirSync as
|
|
105151
|
+
readdirSync as readdirSync12,
|
|
104374
105152
|
readlinkSync,
|
|
104375
105153
|
realpathSync as realpathSync8,
|
|
104376
|
-
statSync as
|
|
105154
|
+
statSync as statSync21
|
|
104377
105155
|
} from "fs";
|
|
104378
|
-
import { basename as
|
|
105156
|
+
import { basename as basename6, dirname as dirname24, join as join58, sep } from "path";
|
|
104379
105157
|
function isUuid(v) {
|
|
104380
105158
|
return typeof v === "string" && UUID_RE.test(v);
|
|
104381
105159
|
}
|
|
@@ -104519,15 +105297,15 @@ function locateTranscriptByUuid(projectsRoot, uuid) {
|
|
|
104519
105297
|
return null;
|
|
104520
105298
|
let dirs;
|
|
104521
105299
|
try {
|
|
104522
|
-
dirs =
|
|
105300
|
+
dirs = readdirSync12(projectsRoot);
|
|
104523
105301
|
} catch {
|
|
104524
105302
|
return null;
|
|
104525
105303
|
}
|
|
104526
105304
|
let hit = null;
|
|
104527
105305
|
for (const d of dirs) {
|
|
104528
|
-
const p =
|
|
105306
|
+
const p = join58(projectsRoot, d, `${uuid}.jsonl`);
|
|
104529
105307
|
try {
|
|
104530
|
-
if (!
|
|
105308
|
+
if (!statSync21(p).isFile())
|
|
104531
105309
|
continue;
|
|
104532
105310
|
} catch {
|
|
104533
105311
|
continue;
|
|
@@ -104555,7 +105333,7 @@ function writerLiveness(pid) {
|
|
|
104555
105333
|
}
|
|
104556
105334
|
function fileAgeMs(path, now = Date.now()) {
|
|
104557
105335
|
try {
|
|
104558
|
-
return now -
|
|
105336
|
+
return now - statSync21(path).mtimeMs;
|
|
104559
105337
|
} catch {
|
|
104560
105338
|
return null;
|
|
104561
105339
|
}
|
|
@@ -104580,7 +105358,7 @@ function errText(e) {
|
|
|
104580
105358
|
return e instanceof Error ? e.message : String(e);
|
|
104581
105359
|
}
|
|
104582
105360
|
function openContainedTranscript(path, uuid, projectsRoot) {
|
|
104583
|
-
if (
|
|
105361
|
+
if (basename6(path) !== `${uuid}.jsonl`) {
|
|
104584
105362
|
logRejection(path, "basename is not the session uuid");
|
|
104585
105363
|
return null;
|
|
104586
105364
|
}
|
|
@@ -104615,7 +105393,7 @@ function openContainedTranscript(path, uuid, projectsRoot) {
|
|
|
104615
105393
|
closeQuietly(fd);
|
|
104616
105394
|
return null;
|
|
104617
105395
|
}
|
|
104618
|
-
const parent =
|
|
105396
|
+
const parent = dirname24(real);
|
|
104619
105397
|
const named = lstatSync9(real);
|
|
104620
105398
|
if (realpathSync8(parent) !== parent || !named.isFile() || named.dev !== st.dev || named.ino !== st.ino || !kernelPathMatches(fd, real)) {
|
|
104621
105399
|
logRejection(path, "the opened file is not the one under the projects directory");
|
|
@@ -104761,8 +105539,8 @@ var init_pane = __esm(() => {
|
|
|
104761
105539
|
|
|
104762
105540
|
// src/mcp-session/replay-manager.ts
|
|
104763
105541
|
import { randomBytes as randomBytes15, randomUUID as randomUUID9 } from "crypto";
|
|
104764
|
-
import { constants as constants6, accessSync as accessSync3, closeSync as closeSync16, existsSync as existsSync39, realpathSync as realpathSync9, statSync as
|
|
104765
|
-
import { dirname as
|
|
105542
|
+
import { constants as constants6, accessSync as accessSync3, closeSync as closeSync16, existsSync as existsSync39, realpathSync as realpathSync9, statSync as statSync22 } from "fs";
|
|
105543
|
+
import { dirname as dirname25, resolve as resolve7 } from "path";
|
|
104766
105544
|
function unavailable2(reason, message) {
|
|
104767
105545
|
return new ContractErrorException("replay_unavailable", message, reason);
|
|
104768
105546
|
}
|
|
@@ -104772,7 +105550,7 @@ function unknownReplay(id) {
|
|
|
104772
105550
|
function replayCwd(own) {
|
|
104773
105551
|
if (own) {
|
|
104774
105552
|
try {
|
|
104775
|
-
if (
|
|
105553
|
+
if (statSync22(own).isDirectory())
|
|
104776
105554
|
return realpathSync9(own);
|
|
104777
105555
|
} catch {}
|
|
104778
105556
|
}
|
|
@@ -104782,7 +105560,7 @@ async function replayClaudeBinary(env) {
|
|
|
104782
105560
|
const named = env.CLAUDE_PATH ? resolve7(env.CLAUDE_PATH) : "";
|
|
104783
105561
|
if (named) {
|
|
104784
105562
|
try {
|
|
104785
|
-
if (!
|
|
105563
|
+
if (!statSync22(named).isFile())
|
|
104786
105564
|
throw new Error("not a file");
|
|
104787
105565
|
accessSync3(named, constants6.X_OK);
|
|
104788
105566
|
} catch {
|
|
@@ -104837,8 +105615,8 @@ class ReplayManager {
|
|
|
104837
105615
|
cwd,
|
|
104838
105616
|
projectsRoot,
|
|
104839
105617
|
forkPath,
|
|
104840
|
-
removeProjectDir: !existsSync39(
|
|
104841
|
-
configDir:
|
|
105618
|
+
removeProjectDir: !existsSync39(dirname25(forkPath)),
|
|
105619
|
+
configDir: dirname25(projectsRoot),
|
|
104842
105620
|
cols: size.cols ?? DEFAULT_PANE_COLS,
|
|
104843
105621
|
rows: size.rows ?? DEFAULT_PANE_ROWS
|
|
104844
105622
|
});
|
|
@@ -105005,15 +105783,15 @@ import { randomBytes as randomBytes16, randomUUID as randomUUID10 } from "crypto
|
|
|
105005
105783
|
import {
|
|
105006
105784
|
existsSync as existsSync40,
|
|
105007
105785
|
lstatSync as lstatSync10,
|
|
105008
|
-
mkdirSync as
|
|
105009
|
-
readFileSync as
|
|
105010
|
-
readdirSync as
|
|
105786
|
+
mkdirSync as mkdirSync27,
|
|
105787
|
+
readFileSync as readFileSync46,
|
|
105788
|
+
readdirSync as readdirSync13,
|
|
105011
105789
|
realpathSync as realpathSync10,
|
|
105012
|
-
rmSync as
|
|
105013
|
-
statSync as
|
|
105014
|
-
writeFileSync as
|
|
105790
|
+
rmSync as rmSync16,
|
|
105791
|
+
statSync as statSync23,
|
|
105792
|
+
writeFileSync as writeFileSync25
|
|
105015
105793
|
} from "fs";
|
|
105016
|
-
import { basename as
|
|
105794
|
+
import { basename as basename7, dirname as dirname26, join as join59, resolve as resolve8, sep as sep2 } from "path";
|
|
105017
105795
|
function slotTerminal(e) {
|
|
105018
105796
|
if (!e.session)
|
|
105019
105797
|
return true;
|
|
@@ -105082,7 +105860,7 @@ function notableAnomalies(snap) {
|
|
|
105082
105860
|
return snap.anomalies.filter((a) => a.startsWith("background_shell_open") || a.startsWith("turn_end_record_missing") || a.startsWith("agent_count_mismatch") || a.startsWith("prompt_not_read"));
|
|
105083
105861
|
}
|
|
105084
105862
|
function upstreamLogPath(path, id) {
|
|
105085
|
-
return
|
|
105863
|
+
return join59(path, "errors", `${id}-upstream.jsonl`);
|
|
105086
105864
|
}
|
|
105087
105865
|
function neverSpawnedRow(e, m) {
|
|
105088
105866
|
return {
|
|
@@ -105179,9 +105957,9 @@ function teamRunRowFromDisk(path, status) {
|
|
|
105179
105957
|
const settled = slots.length > 0 && slots.every((s) => isTerminalState(s.state));
|
|
105180
105958
|
const completions = Object.values(status.models ?? {}).map((m) => m?.completedAt ? Date.parse(m.completedAt) : Number.NaN).filter(Number.isFinite);
|
|
105181
105959
|
return {
|
|
105182
|
-
run_id: status.runId ??
|
|
105960
|
+
run_id: status.runId ?? basename7(path),
|
|
105183
105961
|
path,
|
|
105184
|
-
kind: status.kind ?? (
|
|
105962
|
+
kind: status.kind ?? (basename7(path) === "judging" ? "judge" : "run"),
|
|
105185
105963
|
started_at: status.startedAt,
|
|
105186
105964
|
finished_at: settled ? new Date(completions.length ? Math.max(...completions) : statusMtimeMs(path) ?? Date.parse(status.startedAt)).toISOString() : null,
|
|
105187
105965
|
state: settled ? "SETTLED" : "ACTIVE",
|
|
@@ -105191,14 +105969,14 @@ function teamRunRowFromDisk(path, status) {
|
|
|
105191
105969
|
}
|
|
105192
105970
|
function statusMtimeMs(path) {
|
|
105193
105971
|
try {
|
|
105194
|
-
return
|
|
105972
|
+
return statSync23(join59(path, "status.json")).mtimeMs;
|
|
105195
105973
|
} catch {
|
|
105196
105974
|
return null;
|
|
105197
105975
|
}
|
|
105198
105976
|
}
|
|
105199
105977
|
function readManifestOrNull(path) {
|
|
105200
105978
|
try {
|
|
105201
|
-
return JSON.parse(
|
|
105979
|
+
return JSON.parse(readFileSync46(join59(path, "manifest.json"), "utf-8"));
|
|
105202
105980
|
} catch {
|
|
105203
105981
|
return null;
|
|
105204
105982
|
}
|
|
@@ -105321,7 +106099,7 @@ function teamSlotTranscriptSource(path, slot, runId, opts) {
|
|
|
105321
106099
|
}
|
|
105322
106100
|
if (!status || typeof status !== "object" || !status.models || typeof status.models !== "object")
|
|
105323
106101
|
throw unknownRun(path, runId);
|
|
105324
|
-
const fileRunId = typeof status.runId === "string" && status.runId ? status.runId :
|
|
106102
|
+
const fileRunId = typeof status.runId === "string" && status.runId ? status.runId : basename7(resolved);
|
|
105325
106103
|
if (runId !== undefined && runId !== fileRunId)
|
|
105326
106104
|
throw unknownRun(path, runId);
|
|
105327
106105
|
const m = Object.hasOwn(status.models, slot) ? status.models[slot] : undefined;
|
|
@@ -105486,12 +106264,12 @@ function readWrittenFile(path, root) {
|
|
|
105486
106264
|
if (real !== realRoot && !real.startsWith(realRoot + sep2))
|
|
105487
106265
|
return { skip: "outside the working directory" };
|
|
105488
106266
|
try {
|
|
105489
|
-
const st =
|
|
106267
|
+
const st = statSync23(real);
|
|
105490
106268
|
if (!st.isFile())
|
|
105491
106269
|
return { skip: "not a regular file" };
|
|
105492
106270
|
if (st.size > MAX_FILE_ANSWER_BYTES)
|
|
105493
106271
|
return { skip: "larger than 1 MiB" };
|
|
105494
|
-
const buf =
|
|
106272
|
+
const buf = readFileSync46(real);
|
|
105495
106273
|
if (buf.includes(0))
|
|
105496
106274
|
return { skip: "binary" };
|
|
105497
106275
|
return { text: buf.toString("utf8") };
|
|
@@ -105528,7 +106306,7 @@ function persistErrorLog(errorLogPath, header, sections) {
|
|
|
105528
106306
|
parts.push(`--- ${title} ---`, body.trim() ? redactSecrets(body) : "(empty)", "");
|
|
105529
106307
|
}
|
|
105530
106308
|
try {
|
|
105531
|
-
|
|
106309
|
+
writeFileSync25(errorLogPath, parts.join(`
|
|
105532
106310
|
`), "utf-8");
|
|
105533
106311
|
} catch {}
|
|
105534
106312
|
}
|
|
@@ -105542,16 +106320,16 @@ function validateSessionPath(sessionPath) {
|
|
|
105542
106320
|
lstatSync10(existing);
|
|
105543
106321
|
break;
|
|
105544
106322
|
} catch {
|
|
105545
|
-
const parent =
|
|
106323
|
+
const parent = dirname26(existing);
|
|
105546
106324
|
if (parent === existing)
|
|
105547
106325
|
break;
|
|
105548
|
-
tail.unshift(
|
|
106326
|
+
tail.unshift(basename7(existing));
|
|
105549
106327
|
existing = parent;
|
|
105550
106328
|
}
|
|
105551
106329
|
}
|
|
105552
106330
|
let real;
|
|
105553
106331
|
try {
|
|
105554
|
-
real =
|
|
106332
|
+
real = join59(realpathSync10(existing), ...tail);
|
|
105555
106333
|
} catch {
|
|
105556
106334
|
throw outside();
|
|
105557
106335
|
}
|
|
@@ -105570,7 +106348,7 @@ function readTeamInputFile(inputPath) {
|
|
|
105570
106348
|
if (!existsSync40(resolved)) {
|
|
105571
106349
|
throw new Error(`Input file not found: ${resolved}`);
|
|
105572
106350
|
}
|
|
105573
|
-
const text =
|
|
106351
|
+
const text = readFileSync46(resolved, "utf-8");
|
|
105574
106352
|
if (text.trim().length === 0) {
|
|
105575
106353
|
throw new Error(`Input file is empty: ${resolved}`);
|
|
105576
106354
|
}
|
|
@@ -105580,14 +106358,14 @@ function setupSession(sessionPath, models, input) {
|
|
|
105580
106358
|
if (models.length === 0) {
|
|
105581
106359
|
throw new Error("At least one model is required");
|
|
105582
106360
|
}
|
|
105583
|
-
if (existsSync40(
|
|
106361
|
+
if (existsSync40(join59(sessionPath, "manifest.json"))) {
|
|
105584
106362
|
throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
|
|
105585
106363
|
}
|
|
105586
|
-
|
|
105587
|
-
|
|
106364
|
+
mkdirSync27(join59(sessionPath, "work"), { recursive: true });
|
|
106365
|
+
mkdirSync27(join59(sessionPath, "errors"), { recursive: true });
|
|
105588
106366
|
if (input !== undefined) {
|
|
105589
|
-
|
|
105590
|
-
} else if (!existsSync40(
|
|
106367
|
+
writeFileSync25(join59(sessionPath, "input.md"), input, "utf-8");
|
|
106368
|
+
} else if (!existsSync40(join59(sessionPath, "input.md"))) {
|
|
105591
106369
|
throw new Error(`No input.md found at ${sessionPath} and no input provided`);
|
|
105592
106370
|
}
|
|
105593
106371
|
const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
|
|
@@ -105604,9 +106382,9 @@ function setupSession(sessionPath, models, input) {
|
|
|
105604
106382
|
model: models[i],
|
|
105605
106383
|
assignedAt: now
|
|
105606
106384
|
};
|
|
105607
|
-
|
|
106385
|
+
mkdirSync27(join59(sessionPath, "work", anonId), { recursive: true });
|
|
105608
106386
|
}
|
|
105609
|
-
|
|
106387
|
+
writeFileSync25(join59(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
|
|
105610
106388
|
const status = {
|
|
105611
106389
|
startedAt: now,
|
|
105612
106390
|
models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
|
|
@@ -105621,7 +106399,7 @@ function setupSession(sessionPath, models, input) {
|
|
|
105621
106399
|
}
|
|
105622
106400
|
]))
|
|
105623
106401
|
};
|
|
105624
|
-
writeFileAtomic(
|
|
106402
|
+
writeFileAtomic(join59(sessionPath, "status.json"), JSON.stringify(status, null, 2));
|
|
105625
106403
|
return manifest;
|
|
105626
106404
|
}
|
|
105627
106405
|
function assertValidRequirePattern(pattern) {
|
|
@@ -105656,7 +106434,7 @@ async function preflightTeamRun(opts) {
|
|
|
105656
106434
|
throw new Error(`pane_limit: ${live} live panes for this user, ${opts.slots} more would exceed ${MAX_LIVE_PANES}`);
|
|
105657
106435
|
}
|
|
105658
106436
|
function mintRunId(path, startMs) {
|
|
105659
|
-
return `${
|
|
106437
|
+
return `${basename7(path)}-${startMs.toString(36)}-${randomBytes16(3).toString("hex")}`;
|
|
105660
106438
|
}
|
|
105661
106439
|
function startModels(sessionPath, opts = {}) {
|
|
105662
106440
|
const flight = { aborted: false };
|
|
@@ -105682,9 +106460,9 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105682
106460
|
throw new Error(`invalid_args: ${flagCheck.message}`);
|
|
105683
106461
|
const agentRequested = requestedAgentOf(claudeFlags);
|
|
105684
106462
|
const path = resolve8(sessionPath);
|
|
105685
|
-
const manifest = JSON.parse(
|
|
105686
|
-
const statusPath =
|
|
105687
|
-
const inputContent =
|
|
106463
|
+
const manifest = JSON.parse(readFileSync46(join59(path, "manifest.json"), "utf-8"));
|
|
106464
|
+
const statusPath = join59(path, "status.json");
|
|
106465
|
+
const inputContent = readFileSync46(join59(path, "input.md"), "utf-8");
|
|
105688
106466
|
const readAvailable = !flagsRemoveRead(claudeFlags);
|
|
105689
106467
|
const refusal = deliveryRefusal(inputContent, readAvailable);
|
|
105690
106468
|
if (refusal)
|
|
@@ -105695,7 +106473,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105695
106473
|
const hookEngine = await (opts.hookEngine ?? (() => loadHooksOnce()))().catch(() => null);
|
|
105696
106474
|
const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
|
|
105697
106475
|
await assertMagmuxAvailable();
|
|
105698
|
-
const statusCache = JSON.parse(
|
|
106476
|
+
const statusCache = JSON.parse(readFileSync46(statusPath, "utf-8"));
|
|
105699
106477
|
const startMs = Date.now();
|
|
105700
106478
|
const runId = mintRunId(path, startMs);
|
|
105701
106479
|
statusCache.runId = runId;
|
|
@@ -105721,10 +106499,10 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105721
106499
|
const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
|
|
105722
106500
|
const requirePattern = opts.requirePattern;
|
|
105723
106501
|
const cwd = opts.cwd ?? process.cwd();
|
|
105724
|
-
|
|
106502
|
+
mkdirSync27(statsDir(path), { recursive: true });
|
|
105725
106503
|
const entries = new Map;
|
|
105726
106504
|
let run = null;
|
|
105727
|
-
const errorLogPathOf = (id) =>
|
|
106505
|
+
const errorLogPathOf = (id) => join59(path, "errors", `${id}.log`);
|
|
105728
106506
|
const upstreamLogOf = (id) => upstreamLogPath(path, id);
|
|
105729
106507
|
const flagsOf = (e) => {
|
|
105730
106508
|
const effort = opts.efforts?.[e.model];
|
|
@@ -105734,7 +106512,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105734
106512
|
function writeResponse(e, text) {
|
|
105735
106513
|
e.answer = text;
|
|
105736
106514
|
try {
|
|
105737
|
-
|
|
106515
|
+
writeFileSync25(join59(path, `response-${e.id}.md`), text, "utf-8");
|
|
105738
106516
|
} catch (err) {
|
|
105739
106517
|
persistErrorLog(errorLogPathOf(e.id), `response file not written: ${String(err)}`, []);
|
|
105740
106518
|
}
|
|
@@ -105744,7 +106522,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105744
106522
|
if (e.answer !== null || !e.session)
|
|
105745
106523
|
return;
|
|
105746
106524
|
try {
|
|
105747
|
-
|
|
106525
|
+
writeFileSync25(join59(path, `response-${e.id}.md`), e.session.chainText(), "utf-8");
|
|
105748
106526
|
} catch (err) {
|
|
105749
106527
|
persistErrorLog(errorLogPathOf(e.id), `response file not written: ${String(err)}`, []);
|
|
105750
106528
|
}
|
|
@@ -105941,7 +106719,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105941
106719
|
}
|
|
105942
106720
|
async function startSlot(e, uuid, transcriptPath) {
|
|
105943
106721
|
let session;
|
|
105944
|
-
e.inboxPath = createHookInbox(
|
|
106722
|
+
e.inboxPath = createHookInbox(join59(path, "work"), `${e.id}.hook-inbox.jsonl`);
|
|
105945
106723
|
const binding = bindingFor(e, uuid);
|
|
105946
106724
|
e.binding = binding;
|
|
105947
106725
|
try {
|
|
@@ -105996,7 +106774,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
105996
106774
|
if (!e.inboxPath)
|
|
105997
106775
|
return;
|
|
105998
106776
|
try {
|
|
105999
|
-
|
|
106777
|
+
rmSync16(e.inboxPath, { force: true });
|
|
106000
106778
|
} catch {}
|
|
106001
106779
|
}
|
|
106002
106780
|
const slotIds = Object.keys(manifest.models);
|
|
@@ -106161,7 +106939,7 @@ async function startModelsIn(flight, sessionPath, opts) {
|
|
|
106161
106939
|
done.catch((err) => log(`[team] run failed at ${path}: ${err instanceof Error ? err.message : String(err)}`));
|
|
106162
106940
|
return {
|
|
106163
106941
|
runId,
|
|
106164
|
-
teamSessionId:
|
|
106942
|
+
teamSessionId: basename7(path),
|
|
106165
106943
|
sessionPath: path,
|
|
106166
106944
|
slots: Object.fromEntries(Object.entries(manifest.models).map(([anonId, entry]) => [entry.model, anonId])),
|
|
106167
106945
|
done
|
|
@@ -106175,21 +106953,21 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
106175
106953
|
const active = activeRunAt(resolve8(sessionPath));
|
|
106176
106954
|
if (active)
|
|
106177
106955
|
throw new Error(`invalid_args: the team run at ${resolve8(sessionPath)} is still ACTIVE (run_id ${active.runId}); judge it once it has settled`);
|
|
106178
|
-
const responseFiles =
|
|
106956
|
+
const responseFiles = readdirSync13(sessionPath).filter((f) => f.startsWith("response-") && f.endsWith(".md")).sort();
|
|
106179
106957
|
if (responseFiles.length < 2) {
|
|
106180
106958
|
throw new Error(`Need at least 2 responses to judge, found ${responseFiles.length}`);
|
|
106181
106959
|
}
|
|
106182
106960
|
const responses = {};
|
|
106183
106961
|
for (const file of responseFiles) {
|
|
106184
106962
|
const id = file.replace(/^response-/, "").replace(/\.md$/, "");
|
|
106185
|
-
responses[id] =
|
|
106963
|
+
responses[id] = readFileSync46(join59(sessionPath, file), "utf-8");
|
|
106186
106964
|
}
|
|
106187
|
-
const input =
|
|
106965
|
+
const input = readFileSync46(join59(sessionPath, "input.md"), "utf-8");
|
|
106188
106966
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
106189
|
-
|
|
106967
|
+
writeFileSync25(join59(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
106190
106968
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
106191
|
-
const judgePath =
|
|
106192
|
-
|
|
106969
|
+
const judgePath = join59(sessionPath, "judging");
|
|
106970
|
+
mkdirSync27(judgePath, { recursive: true });
|
|
106193
106971
|
setupSession(judgePath, judgeModels, judgePrompt);
|
|
106194
106972
|
await runModels(judgePath, {
|
|
106195
106973
|
claudeFlags: opts.claudeFlags,
|
|
@@ -106200,11 +106978,11 @@ async function judgeResponses(sessionPath, opts = {}) {
|
|
|
106200
106978
|
});
|
|
106201
106979
|
const votes = parseJudgeVotes(judgePath, Object.keys(responses));
|
|
106202
106980
|
const verdict = aggregateVerdict(votes, Object.keys(responses));
|
|
106203
|
-
|
|
106981
|
+
writeFileSync25(join59(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
|
|
106204
106982
|
return verdict;
|
|
106205
106983
|
}
|
|
106206
106984
|
function getStatus(sessionPath) {
|
|
106207
|
-
return JSON.parse(
|
|
106985
|
+
return JSON.parse(readFileSync46(join59(sessionPath, "status.json"), "utf-8"));
|
|
106208
106986
|
}
|
|
106209
106987
|
function readTeamStatus(sessionPath) {
|
|
106210
106988
|
try {
|
|
@@ -106244,7 +107022,7 @@ function fisherYatesShuffle(arr) {
|
|
|
106244
107022
|
return arr;
|
|
106245
107023
|
}
|
|
106246
107024
|
function getDefaultJudgeModels(sessionPath) {
|
|
106247
|
-
const manifest = JSON.parse(
|
|
107025
|
+
const manifest = JSON.parse(readFileSync46(join59(sessionPath, "manifest.json"), "utf-8"));
|
|
106248
107026
|
return Object.values(manifest.models).map((e) => e.model);
|
|
106249
107027
|
}
|
|
106250
107028
|
function buildJudgePrompt(input, responses) {
|
|
@@ -106302,12 +107080,12 @@ function buildJudgePrompt(input, responses) {
|
|
|
106302
107080
|
}
|
|
106303
107081
|
function parseJudgeVotes(judgePath, responseIds) {
|
|
106304
107082
|
const votes = [];
|
|
106305
|
-
const responseFiles =
|
|
107083
|
+
const responseFiles = readdirSync13(judgePath).filter((f) => f.startsWith("response-") && f.endsWith(".md")).sort();
|
|
106306
107084
|
for (const file of responseFiles) {
|
|
106307
107085
|
const judgeId = file.replace(/^response-/, "").replace(/\.md$/, "");
|
|
106308
107086
|
let content;
|
|
106309
107087
|
try {
|
|
106310
|
-
content =
|
|
107088
|
+
content = readFileSync46(join59(judgePath, file), "utf-8");
|
|
106311
107089
|
} catch (err) {
|
|
106312
107090
|
log(`[team] judge answer ${file} unreadable: ${err instanceof Error ? err.message : String(err)}`);
|
|
106313
107091
|
continue;
|
|
@@ -106360,7 +107138,7 @@ function aggregateVerdict(votes, responseIds) {
|
|
|
106360
107138
|
function formatVerdict(verdict, sessionPath) {
|
|
106361
107139
|
let manifest = null;
|
|
106362
107140
|
try {
|
|
106363
|
-
manifest = JSON.parse(
|
|
107141
|
+
manifest = JSON.parse(readFileSync46(join59(sessionPath, "manifest.json"), "utf-8"));
|
|
106364
107142
|
} catch {}
|
|
106365
107143
|
let output = `# Team Verdict
|
|
106366
107144
|
|
|
@@ -106416,8 +107194,8 @@ var init_team_orchestrator = __esm(() => {
|
|
|
106416
107194
|
});
|
|
106417
107195
|
|
|
106418
107196
|
// src/mcp-session/inherited-settings.ts
|
|
106419
|
-
import { existsSync as existsSync41, readFileSync as
|
|
106420
|
-
import { join as
|
|
107197
|
+
import { existsSync as existsSync41, readFileSync as readFileSync47, statSync as statSync24 } from "fs";
|
|
107198
|
+
import { join as join60, resolve as resolve9 } from "path";
|
|
106421
107199
|
function isPlainObject7(value) {
|
|
106422
107200
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
106423
107201
|
}
|
|
@@ -106462,7 +107240,7 @@ function readSettingsValue(value) {
|
|
|
106462
107240
|
return parseLayer(value, value);
|
|
106463
107241
|
let text;
|
|
106464
107242
|
try {
|
|
106465
|
-
text =
|
|
107243
|
+
text = readFileSync47(value, "utf-8");
|
|
106466
107244
|
} catch (err) {
|
|
106467
107245
|
throw new Error(`invalid_args: settings ${value} cannot be read (${err.message})`);
|
|
106468
107246
|
}
|
|
@@ -106471,10 +107249,10 @@ function readSettingsValue(value) {
|
|
|
106471
107249
|
function buildInheritedSettingsLayer(setupFrom, callerFlags) {
|
|
106472
107250
|
const layers = [];
|
|
106473
107251
|
for (const name of ["settings.json", "settings.local.json"]) {
|
|
106474
|
-
const file =
|
|
107252
|
+
const file = join60(setupFrom, ".claude", name);
|
|
106475
107253
|
if (!existsSync41(file))
|
|
106476
107254
|
continue;
|
|
106477
|
-
layers.push(parseLayer(
|
|
107255
|
+
layers.push(parseLayer(readFileSync47(file, "utf-8"), file));
|
|
106478
107256
|
}
|
|
106479
107257
|
const restFlags = [];
|
|
106480
107258
|
for (let i = 0;i < callerFlags.length; i++) {
|
|
@@ -106504,7 +107282,7 @@ function resolveSetupFrom(arg, workDir, serverCwd) {
|
|
|
106504
107282
|
let setupFrom = serverCwd;
|
|
106505
107283
|
if (typeof arg === "string") {
|
|
106506
107284
|
setupFrom = resolve9(arg);
|
|
106507
|
-
if (!
|
|
107285
|
+
if (!statSync24(setupFrom, { throwIfNoEntry: false })?.isDirectory()) {
|
|
106508
107286
|
throw new Error(`invalid_args: setup_from ${setupFrom} is not an existing directory`);
|
|
106509
107287
|
}
|
|
106510
107288
|
} else if (arg !== undefined) {
|
|
@@ -106521,16 +107299,16 @@ import {
|
|
|
106521
107299
|
closeSync as closeSync17,
|
|
106522
107300
|
createWriteStream,
|
|
106523
107301
|
existsSync as existsSync42,
|
|
106524
|
-
mkdirSync as
|
|
107302
|
+
mkdirSync as mkdirSync28,
|
|
106525
107303
|
openSync as openSync16,
|
|
106526
|
-
readFileSync as
|
|
107304
|
+
readFileSync as readFileSync48,
|
|
106527
107305
|
readSync as readSync7,
|
|
106528
|
-
renameSync as
|
|
106529
|
-
rmSync as
|
|
106530
|
-
statSync as
|
|
106531
|
-
writeFileSync as
|
|
107306
|
+
renameSync as renameSync11,
|
|
107307
|
+
rmSync as rmSync17,
|
|
107308
|
+
statSync as statSync25,
|
|
107309
|
+
writeFileSync as writeFileSync26
|
|
106532
107310
|
} from "fs";
|
|
106533
|
-
import { join as
|
|
107311
|
+
import { join as join61, resolve as resolve10, sep as sep3 } from "path";
|
|
106534
107312
|
function normaliseTimeoutSeconds(raw) {
|
|
106535
107313
|
const n = typeof raw === "string" && raw.trim() !== "" ? Number(raw) : raw;
|
|
106536
107314
|
if (typeof n !== "number" || !Number.isFinite(n))
|
|
@@ -106624,8 +107402,8 @@ function toMetaRecord(info, cwd) {
|
|
|
106624
107402
|
}
|
|
106625
107403
|
function writeJsonAtomic(path, value) {
|
|
106626
107404
|
const tmp = `${path}.tmp`;
|
|
106627
|
-
|
|
106628
|
-
|
|
107405
|
+
writeFileSync26(tmp, JSON.stringify(value, null, 2), "utf-8");
|
|
107406
|
+
renameSync11(tmp, path);
|
|
106629
107407
|
}
|
|
106630
107408
|
function anomalyKey(a) {
|
|
106631
107409
|
const at = a.lastIndexOf(" \xD7");
|
|
@@ -106634,7 +107412,7 @@ function anomalyKey(a) {
|
|
|
106634
107412
|
function readTailText(path, maxBytes) {
|
|
106635
107413
|
let fd = null;
|
|
106636
107414
|
try {
|
|
106637
|
-
const size =
|
|
107415
|
+
const size = statSync25(path).size;
|
|
106638
107416
|
if (size === 0)
|
|
106639
107417
|
return { text: "", truncated: false };
|
|
106640
107418
|
const start = Math.max(0, size - maxBytes);
|
|
@@ -106665,7 +107443,7 @@ function readTailLines2(path, maxBytes) {
|
|
|
106665
107443
|
}
|
|
106666
107444
|
function fileSize2(path) {
|
|
106667
107445
|
try {
|
|
106668
|
-
return
|
|
107446
|
+
return statSync25(path).size;
|
|
106669
107447
|
} catch {
|
|
106670
107448
|
return 0;
|
|
106671
107449
|
}
|
|
@@ -106674,7 +107452,7 @@ function readJsonObject(path, maxBytes) {
|
|
|
106674
107452
|
try {
|
|
106675
107453
|
if (fileSize2(path) > maxBytes)
|
|
106676
107454
|
return null;
|
|
106677
|
-
const parsed = JSON.parse(
|
|
107455
|
+
const parsed = JSON.parse(readFileSync48(path, "utf-8"));
|
|
106678
107456
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
106679
107457
|
return null;
|
|
106680
107458
|
return parsed;
|
|
@@ -106700,7 +107478,7 @@ function dropLeadingFragment(tail) {
|
|
|
106700
107478
|
return firstBreak === -1 ? tail.text : tail.text.slice(firstBreak + 1);
|
|
106701
107479
|
}
|
|
106702
107480
|
function diskAccounting(sessionDir) {
|
|
106703
|
-
const stats = readTokenStatsAt(
|
|
107481
|
+
const stats = readTokenStatsAt(join61(sessionDir, "tokens.json"));
|
|
106704
107482
|
return {
|
|
106705
107483
|
tokensIn: stats?.billed_input_tokens ?? null,
|
|
106706
107484
|
tokensOut: stats?.output_tokens ?? null,
|
|
@@ -106780,14 +107558,14 @@ class SessionManager {
|
|
|
106780
107558
|
return this._launcherPid;
|
|
106781
107559
|
}
|
|
106782
107560
|
recordTeamRun(opts) {
|
|
106783
|
-
|
|
107561
|
+
mkdirSync28(this.sessionsDir, { recursive: true });
|
|
106784
107562
|
let id = "";
|
|
106785
107563
|
let dir = "";
|
|
106786
107564
|
for (let attempt = 0;; attempt++) {
|
|
106787
107565
|
id = `team-${randomUUID11().replace(/-/g, "").slice(0, 8)}`;
|
|
106788
|
-
dir =
|
|
107566
|
+
dir = join61(this.sessionsDir, id);
|
|
106789
107567
|
try {
|
|
106790
|
-
|
|
107568
|
+
mkdirSync28(dir);
|
|
106791
107569
|
break;
|
|
106792
107570
|
} catch (err) {
|
|
106793
107571
|
if (err?.code !== "EEXIST" || attempt >= 4)
|
|
@@ -106817,9 +107595,9 @@ class SessionManager {
|
|
|
106817
107595
|
if (dir === null)
|
|
106818
107596
|
throw new Error("not a record id");
|
|
106819
107597
|
const completedAt = new Date().toISOString();
|
|
106820
|
-
const startedAt = this.teamRunStarts.get(record) ?? metaString(readJsonObject(
|
|
107598
|
+
const startedAt = this.teamRunStarts.get(record) ?? metaString(readJsonObject(join61(dir, "spawn.json"), META_READ_LIMIT)?.startedAt) ?? completedAt;
|
|
106821
107599
|
const elapsedMs = Date.parse(completedAt) - Date.parse(startedAt);
|
|
106822
|
-
writeJsonAtomic(
|
|
107600
|
+
writeJsonAtomic(join61(dir, "meta.json"), {
|
|
106823
107601
|
kind: "team",
|
|
106824
107602
|
status: outcome.status,
|
|
106825
107603
|
startedAt,
|
|
@@ -106851,7 +107629,7 @@ class SessionManager {
|
|
|
106851
107629
|
startedAt,
|
|
106852
107630
|
...rest
|
|
106853
107631
|
};
|
|
106854
|
-
writeJsonAtomic(
|
|
107632
|
+
writeJsonAtomic(join61(dir, "spawn.json"), body);
|
|
106855
107633
|
}
|
|
106856
107634
|
async createSession(opts) {
|
|
106857
107635
|
if (this.activeSessions + this.starting >= this.maxSessions) {
|
|
@@ -106891,7 +107669,7 @@ class SessionManager {
|
|
|
106891
107669
|
throw err;
|
|
106892
107670
|
}
|
|
106893
107671
|
if (inherited.layer) {
|
|
106894
|
-
flags = [...inherited.restFlags, "--settings",
|
|
107672
|
+
flags = [...inherited.restFlags, "--settings", join61(entry.sessionDir, INHERITED_SETTINGS)];
|
|
106895
107673
|
}
|
|
106896
107674
|
this.sessions.set(entry.info.sessionId, entry);
|
|
106897
107675
|
uncount();
|
|
@@ -106916,10 +107694,10 @@ class SessionManager {
|
|
|
106916
107694
|
const timeout = normaliseTimeoutSeconds(opts.timeoutSeconds);
|
|
106917
107695
|
const agentRequested = requestedAgentOf(opts.claudishFlags ?? []);
|
|
106918
107696
|
const startedAt = new Date().toISOString();
|
|
106919
|
-
const sessionDir = opts.sessionDir ??
|
|
106920
|
-
|
|
107697
|
+
const sessionDir = opts.sessionDir ?? join61(this.sessionsDir, sessionId);
|
|
107698
|
+
mkdirSync28(sessionDir, { recursive: true });
|
|
106921
107699
|
if (opts.prompt)
|
|
106922
|
-
|
|
107700
|
+
writeFileSync26(join61(sessionDir, "prompt.md"), opts.prompt, "utf-8");
|
|
106923
107701
|
this.writeSpawnRecord(sessionDir, {
|
|
106924
107702
|
kind: "session",
|
|
106925
107703
|
sessionId,
|
|
@@ -106932,13 +107710,13 @@ class SessionManager {
|
|
|
106932
107710
|
...agentRequested ? { agentRequested } : {}
|
|
106933
107711
|
});
|
|
106934
107712
|
if (inheritedLayer) {
|
|
106935
|
-
|
|
107713
|
+
writeFileSync26(join61(sessionDir, INHERITED_SETTINGS), `${JSON.stringify(inheritedLayer, null, 2)}
|
|
106936
107714
|
`, { encoding: "utf-8", mode: 384 });
|
|
106937
107715
|
}
|
|
106938
107716
|
const cwd = opts.cwd ?? process.cwd();
|
|
106939
107717
|
const parentEnv = opts.parentEnv ?? this.parentEnv;
|
|
106940
107718
|
const spawnModel = opts.spawnModel ?? null;
|
|
106941
|
-
const tokenFile = opts.tokenFile ??
|
|
107719
|
+
const tokenFile = opts.tokenFile ?? join61(sessionDir, "tokens.json");
|
|
106942
107720
|
return {
|
|
106943
107721
|
info: {
|
|
106944
107722
|
sessionId,
|
|
@@ -106976,18 +107754,18 @@ class SessionManager {
|
|
|
106976
107754
|
},
|
|
106977
107755
|
session: null,
|
|
106978
107756
|
scrollback: new ScrollbackBuffer(this.scrollbackCapacity),
|
|
106979
|
-
outputLogStream: createWriteStream(
|
|
107757
|
+
outputLogStream: createWriteStream(join61(sessionDir, "output.log")),
|
|
106980
107758
|
sessionDir,
|
|
106981
107759
|
cwd,
|
|
106982
107760
|
tokenFile,
|
|
106983
|
-
eventLogPath:
|
|
107761
|
+
eventLogPath: join61(sessionDir, "events.jsonl"),
|
|
106984
107762
|
eventLogBytes: 0,
|
|
106985
|
-
upstreamErrorLogPath:
|
|
107763
|
+
upstreamErrorLogPath: join61(sessionDir, "upstream-errors.jsonl"),
|
|
106986
107764
|
eventRing: [],
|
|
106987
107765
|
proseBytes: 0,
|
|
106988
107766
|
answeredTurns: new Map,
|
|
106989
107767
|
inboxPath: null,
|
|
106990
|
-
waitLogPath:
|
|
107768
|
+
waitLogPath: join61(sessionDir, "waits.jsonl"),
|
|
106991
107769
|
waitLogBytes: 0,
|
|
106992
107770
|
waitSince: null,
|
|
106993
107771
|
ended: false,
|
|
@@ -107089,7 +107867,7 @@ class SessionManager {
|
|
|
107089
107867
|
if (!entry.inboxPath)
|
|
107090
107868
|
return;
|
|
107091
107869
|
try {
|
|
107092
|
-
|
|
107870
|
+
rmSync17(entry.inboxPath, { force: true });
|
|
107093
107871
|
} catch {}
|
|
107094
107872
|
}
|
|
107095
107873
|
failNeverSpawned(entry, err) {
|
|
@@ -107182,7 +107960,7 @@ class SessionManager {
|
|
|
107182
107960
|
try {
|
|
107183
107961
|
const text = screenLines.join(`
|
|
107184
107962
|
`).replace(/\s+$/, "");
|
|
107185
|
-
|
|
107963
|
+
writeFileSync26(join61(entry.sessionDir, "screen.txt"), `${redactSecrets(text)}
|
|
107186
107964
|
`, "utf-8");
|
|
107187
107965
|
} catch {}
|
|
107188
107966
|
}
|
|
@@ -107196,7 +107974,7 @@ class SessionManager {
|
|
|
107196
107974
|
entry.waitSince = null;
|
|
107197
107975
|
}
|
|
107198
107976
|
try {
|
|
107199
|
-
writeJsonAtomic(
|
|
107977
|
+
writeJsonAtomic(join61(entry.sessionDir, "meta.json"), toMetaRecord(entry.info, entry.cwd));
|
|
107200
107978
|
} catch (err) {
|
|
107201
107979
|
process.stderr.write(`[claudish] session ${entry.info.sessionId}: could not write meta.json: ` + `${err instanceof Error ? err.message : String(err)}
|
|
107202
107980
|
`);
|
|
@@ -107448,13 +108226,13 @@ class SessionManager {
|
|
|
107448
108226
|
if (sessionDir === null)
|
|
107449
108227
|
return null;
|
|
107450
108228
|
try {
|
|
107451
|
-
if (!
|
|
108229
|
+
if (!statSync25(sessionDir).isDirectory())
|
|
107452
108230
|
return null;
|
|
107453
108231
|
} catch {
|
|
107454
108232
|
return null;
|
|
107455
108233
|
}
|
|
107456
|
-
const spawnPath =
|
|
107457
|
-
const metaPath =
|
|
108234
|
+
const spawnPath = join61(sessionDir, "spawn.json");
|
|
108235
|
+
const metaPath = join61(sessionDir, "meta.json");
|
|
107458
108236
|
const spawnRecord = readJsonObject(spawnPath, META_READ_LIMIT);
|
|
107459
108237
|
if (spawnRecord?.kind === "team")
|
|
107460
108238
|
return null;
|
|
@@ -107548,7 +108326,7 @@ class SessionManager {
|
|
|
107548
108326
|
return null;
|
|
107549
108327
|
const root = resolve10(this.sessionsDir);
|
|
107550
108328
|
const dir = resolve10(root, sessionId);
|
|
107551
|
-
if (dir !==
|
|
108329
|
+
if (dir !== join61(root, sessionId))
|
|
107552
108330
|
return null;
|
|
107553
108331
|
if (!dir.startsWith(root + sep3))
|
|
107554
108332
|
return null;
|
|
@@ -107560,17 +108338,17 @@ class SessionManager {
|
|
|
107560
108338
|
return null;
|
|
107561
108339
|
let dirMtimeMs;
|
|
107562
108340
|
try {
|
|
107563
|
-
const stat =
|
|
108341
|
+
const stat = statSync25(sessionDir);
|
|
107564
108342
|
if (!stat.isDirectory())
|
|
107565
108343
|
return null;
|
|
107566
108344
|
dirMtimeMs = stat.mtimeMs;
|
|
107567
108345
|
} catch {
|
|
107568
108346
|
return null;
|
|
107569
108347
|
}
|
|
107570
|
-
const spawnRecord = readJsonObject(
|
|
108348
|
+
const spawnRecord = readJsonObject(join61(sessionDir, "spawn.json"), META_READ_LIMIT);
|
|
107571
108349
|
if (spawnRecord?.kind === "team")
|
|
107572
108350
|
return null;
|
|
107573
|
-
const meta = readJsonObject(
|
|
108351
|
+
const meta = readJsonObject(join61(sessionDir, "meta.json"), META_READ_LIMIT);
|
|
107574
108352
|
if (meta?.kind === "team")
|
|
107575
108353
|
return null;
|
|
107576
108354
|
const partial = meta === null;
|
|
@@ -107592,7 +108370,7 @@ class SessionManager {
|
|
|
107592
108370
|
return stored;
|
|
107593
108371
|
}
|
|
107594
108372
|
diskOutput(record, tailLines) {
|
|
107595
|
-
const tail = readTailText(
|
|
108373
|
+
const tail = readTailText(join61(record.sessionDir, "output.log"), OUTPUT_TAIL_BYTES);
|
|
107596
108374
|
const buffer = new ScrollbackBuffer(this.scrollbackCapacity);
|
|
107597
108375
|
if (tail?.text)
|
|
107598
108376
|
buffer.append(dropLeadingFragment(tail));
|
|
@@ -107612,12 +108390,12 @@ class SessionManager {
|
|
|
107612
108390
|
}
|
|
107613
108391
|
diskDiagnostics(record, limit) {
|
|
107614
108392
|
const { sessionDir, info } = record;
|
|
107615
|
-
const eventLogPath =
|
|
107616
|
-
const upstreamErrorLogPath =
|
|
107617
|
-
const outputLogPath =
|
|
108393
|
+
const eventLogPath = join61(sessionDir, "events.jsonl");
|
|
108394
|
+
const upstreamErrorLogPath = join61(sessionDir, "upstream-errors.jsonl");
|
|
108395
|
+
const outputLogPath = join61(sessionDir, "output.log");
|
|
107618
108396
|
const events = readTailLines2(eventLogPath, EVENT_TAIL_BYTES);
|
|
107619
108397
|
const outputTail = readTailText(outputLogPath, OUTPUT_TAIL_BYTES);
|
|
107620
|
-
const screen = readTailText(
|
|
108398
|
+
const screen = readTailText(join61(sessionDir, "screen.txt"), SCREEN_READ_BYTES);
|
|
107621
108399
|
return {
|
|
107622
108400
|
sessionId: info.sessionId,
|
|
107623
108401
|
state: info.state,
|
|
@@ -108022,9 +108800,9 @@ var init_progress_heartbeat = __esm(() => {
|
|
|
108022
108800
|
|
|
108023
108801
|
// src/mcp/run-prompt-claude-code.ts
|
|
108024
108802
|
import { spawn as spawn3 } from "child_process";
|
|
108025
|
-
import { mkdirSync as
|
|
108803
|
+
import { mkdirSync as mkdirSync29, mkdtempSync as mkdtempSync4, rmSync as rmSync18, writeFileSync as writeFileSync27 } from "fs";
|
|
108026
108804
|
import { tmpdir as tmpdir3 } from "os";
|
|
108027
|
-
import { join as
|
|
108805
|
+
import { join as join62 } from "path";
|
|
108028
108806
|
function claudeCodePrintArgv(model, systemPromptFile) {
|
|
108029
108807
|
const head = [PRINT_FLAGS[0], "--model", model, ...PRINT_FLAGS.slice(1)];
|
|
108030
108808
|
return systemPromptFile !== undefined ? [...head, "--system-prompt-file", systemPromptFile] : [...head, "--system-prompt", ""];
|
|
@@ -108144,14 +108922,14 @@ async function runPromptViaClaudeCode(model, prompt, systemPrompt, opts = {}) {
|
|
|
108144
108922
|
} catch (e) {
|
|
108145
108923
|
throw new Error(`cannot start claudish (${parentEnv.CLAUDISH_BIN?.trim() || "claudish"}): ${e instanceof Error ? e.message : String(e)}`);
|
|
108146
108924
|
}
|
|
108147
|
-
const root = mkdtempSync4(
|
|
108925
|
+
const root = mkdtempSync4(join62(tmpdir3(), "claudish-run-prompt-"));
|
|
108148
108926
|
try {
|
|
108149
|
-
const cwd =
|
|
108150
|
-
|
|
108927
|
+
const cwd = join62(root, "cwd");
|
|
108928
|
+
mkdirSync29(cwd, { mode: 448 });
|
|
108151
108929
|
let systemPromptFile;
|
|
108152
108930
|
if (typeof systemPrompt === "string" && systemPrompt.length > 0) {
|
|
108153
|
-
systemPromptFile =
|
|
108154
|
-
|
|
108931
|
+
systemPromptFile = join62(root, "system-prompt.txt");
|
|
108932
|
+
writeFileSync27(systemPromptFile, systemPrompt, { mode: 384 });
|
|
108155
108933
|
}
|
|
108156
108934
|
const argv = claudeCodePrintArgv(model, systemPromptFile);
|
|
108157
108935
|
const outcome = await runChild(launch, argv, cwd, claudeCodePrintEnv(parentEnv), prompt, signal);
|
|
@@ -108178,7 +108956,7 @@ async function runPromptViaClaudeCode(model, prompt, systemPrompt, opts = {}) {
|
|
|
108178
108956
|
answer.auth = auth;
|
|
108179
108957
|
return answer;
|
|
108180
108958
|
} finally {
|
|
108181
|
-
|
|
108959
|
+
rmSync18(root, { recursive: true, force: true });
|
|
108182
108960
|
}
|
|
108183
108961
|
}
|
|
108184
108962
|
function runChild(launch, argv, cwd, env, prompt, signal) {
|
|
@@ -108451,14 +109229,14 @@ var init_preflight_chain = __esm(() => {
|
|
|
108451
109229
|
});
|
|
108452
109230
|
|
|
108453
109231
|
// src/mcp-server.ts
|
|
108454
|
-
import { existsSync as existsSync43, readFileSync as
|
|
108455
|
-
import { homedir as
|
|
108456
|
-
import { dirname as
|
|
109232
|
+
import { existsSync as existsSync43, readFileSync as readFileSync49, readdirSync as readdirSync14 } from "fs";
|
|
109233
|
+
import { homedir as homedir41 } from "os";
|
|
109234
|
+
import { dirname as dirname27, join as join63, resolve as resolve11 } from "path";
|
|
108457
109235
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
108458
109236
|
async function loadAllModels(forceRefresh = false) {
|
|
108459
109237
|
if (!forceRefresh && existsSync43(OPENROUTER_MODELS_CACHE_PATH)) {
|
|
108460
109238
|
try {
|
|
108461
|
-
const cacheData = JSON.parse(
|
|
109239
|
+
const cacheData = JSON.parse(readFileSync49(OPENROUTER_MODELS_CACHE_PATH, "utf-8"));
|
|
108462
109240
|
const lastUpdated = new Date(cacheData.lastUpdated);
|
|
108463
109241
|
const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
|
|
108464
109242
|
if (ageInDays <= CACHE_MAX_AGE_DAYS) {
|
|
@@ -108482,7 +109260,7 @@ async function loadAllModels(forceRefresh = false) {
|
|
|
108482
109260
|
log(`[mcp] OpenRouter models fetch failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
108483
109261
|
try {
|
|
108484
109262
|
if (existsSync43(OPENROUTER_MODELS_CACHE_PATH)) {
|
|
108485
|
-
const cacheData = JSON.parse(
|
|
109263
|
+
const cacheData = JSON.parse(readFileSync49(OPENROUTER_MODELS_CACHE_PATH, "utf-8"));
|
|
108486
109264
|
return cacheData.models || [];
|
|
108487
109265
|
}
|
|
108488
109266
|
} catch (cacheErr) {
|
|
@@ -109661,8 +110439,8 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
|
|
|
109661
110439
|
const promptText = () => {
|
|
109662
110440
|
if (input !== undefined)
|
|
109663
110441
|
return input;
|
|
109664
|
-
const existing =
|
|
109665
|
-
return existsSync43(existing) ?
|
|
110442
|
+
const existing = join63(resolved, "input.md");
|
|
110443
|
+
return existsSync43(existing) ? readFileSync49(existing, "utf-8") : undefined;
|
|
109666
110444
|
};
|
|
109667
110445
|
const choice = await modelChoiceStop([
|
|
109668
110446
|
...runsModels && givenModels && models ? givenModels.map((given, i) => ({ given, spec: models[i] })) : [],
|
|
@@ -109836,7 +110614,7 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
|
|
|
109836
110614
|
let stderrFull = stderr_snippet || "";
|
|
109837
110615
|
if (error_log_path) {
|
|
109838
110616
|
try {
|
|
109839
|
-
stderrFull =
|
|
110617
|
+
stderrFull = readFileSync49(error_log_path, "utf-8");
|
|
109840
110618
|
} catch {}
|
|
109841
110619
|
}
|
|
109842
110620
|
const sessionData = {};
|
|
@@ -109844,26 +110622,26 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
|
|
|
109844
110622
|
const sp = session_path;
|
|
109845
110623
|
for (const file of ["status.json", "manifest.json", "input.md"]) {
|
|
109846
110624
|
try {
|
|
109847
|
-
sessionData[file] =
|
|
110625
|
+
sessionData[file] = readFileSync49(join63(sp, file), "utf-8");
|
|
109848
110626
|
} catch {}
|
|
109849
110627
|
}
|
|
109850
110628
|
try {
|
|
109851
|
-
const errorDir =
|
|
110629
|
+
const errorDir = join63(sp, "errors");
|
|
109852
110630
|
if (existsSync43(errorDir)) {
|
|
109853
|
-
for (const f of
|
|
110631
|
+
for (const f of readdirSync14(errorDir)) {
|
|
109854
110632
|
if (f.endsWith(".log")) {
|
|
109855
110633
|
try {
|
|
109856
|
-
sessionData[`errors/${f}`] =
|
|
110634
|
+
sessionData[`errors/${f}`] = readFileSync49(join63(errorDir, f), "utf-8");
|
|
109857
110635
|
} catch {}
|
|
109858
110636
|
}
|
|
109859
110637
|
}
|
|
109860
110638
|
}
|
|
109861
110639
|
} catch {}
|
|
109862
110640
|
try {
|
|
109863
|
-
for (const f of
|
|
110641
|
+
for (const f of readdirSync14(sp)) {
|
|
109864
110642
|
if (f.startsWith("response-") && f.endsWith(".md")) {
|
|
109865
110643
|
try {
|
|
109866
|
-
const content =
|
|
110644
|
+
const content = readFileSync49(join63(sp, f), "utf-8");
|
|
109867
110645
|
sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
|
|
109868
110646
|
} catch {}
|
|
109869
110647
|
}
|
|
@@ -109872,9 +110650,9 @@ This searched OpenRouter's listing only. Subscription wire ids and catalog alias
|
|
|
109872
110650
|
}
|
|
109873
110651
|
let version = "unknown";
|
|
109874
110652
|
try {
|
|
109875
|
-
const pkgPath =
|
|
110653
|
+
const pkgPath = join63(__dirname3, "../package.json");
|
|
109876
110654
|
if (existsSync43(pkgPath)) {
|
|
109877
|
-
version = JSON.parse(
|
|
110655
|
+
version = JSON.parse(readFileSync49(pkgPath, "utf-8")).version;
|
|
109878
110656
|
}
|
|
109879
110657
|
} catch {}
|
|
109880
110658
|
const report = {
|
|
@@ -110609,9 +111387,9 @@ var init_mcp_server = __esm(() => {
|
|
|
110609
111387
|
init_team_orchestrator();
|
|
110610
111388
|
init_preflight_chain();
|
|
110611
111389
|
__filename3 = fileURLToPath3(import.meta.url);
|
|
110612
|
-
__dirname3 =
|
|
110613
|
-
CLAUDISH_CACHE_DIR =
|
|
110614
|
-
OPENROUTER_MODELS_CACHE_PATH =
|
|
111390
|
+
__dirname3 = dirname27(__filename3);
|
|
111391
|
+
CLAUDISH_CACHE_DIR = join63(homedir41(), ".claudish");
|
|
111392
|
+
OPENROUTER_MODELS_CACHE_PATH = join63(CLAUDISH_CACHE_DIR, "openrouter-models.json");
|
|
110615
111393
|
NEXT_STEP = {
|
|
110616
111394
|
cancelled: "you stopped this slot; nothing is wrong with it. Re-run it if you still want its vote",
|
|
110617
111395
|
timeout: "grid mode only \u2014 magmux ended the pane. The orchestrator has no deadline",
|
|
@@ -110636,7 +111414,7 @@ var init_mcp_server = __esm(() => {
|
|
|
110636
111414
|
});
|
|
110637
111415
|
|
|
110638
111416
|
// src/serve-command.ts
|
|
110639
|
-
import { existsSync as existsSync44, readFileSync as
|
|
111417
|
+
import { existsSync as existsSync44, readFileSync as readFileSync50 } from "fs";
|
|
110640
111418
|
function parseServeArgs(args) {
|
|
110641
111419
|
const out = {};
|
|
110642
111420
|
for (let i = 0;i < args.length; i++) {
|
|
@@ -110660,7 +111438,7 @@ function loadModelMap(path) {
|
|
|
110660
111438
|
}
|
|
110661
111439
|
let raw;
|
|
110662
111440
|
try {
|
|
110663
|
-
raw =
|
|
111441
|
+
raw = readFileSync50(path, "utf-8");
|
|
110664
111442
|
} catch (e) {
|
|
110665
111443
|
throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
|
|
110666
111444
|
}
|
|
@@ -110741,9 +111519,9 @@ var init_serve_command = __esm(() => {
|
|
|
110741
111519
|
var HOOKS_AMBIENT_DTS = '// claudish hook types \u2014 written by `claudish hooks init`. Do not edit: run\n// `claudish hooks init` from a newer claudish to refresh it.\n// With this file beside your hook, `import type { HookDefinition } from\n// "claudish/hooks"` type-checks with nothing installed.\ndeclare module "claudish/hooks" {\n /**\n * claudish/hooks \u2014 the public hook contract.\n *\n * Everything a hook author can import lives here, and nothing else does. This\n * file imports nothing from the rest of claudish and has no side effects, so it\n * can be built on its own into `dist/hooks.js` + `dist/hooks.d.ts` and served to\n * user modules as the `claudish/hooks` virtual module (see `loader.ts`).\n *\n * Every internal hooks module takes its types from here, so the contract has a\n * single source.\n *\n * ## Process isolation\n *\n * A hook module\'s top-level state is PER PROCESS. In the interactive launcher,\n * proxy events (`request` \u2026 `responseEnd`, raw) and session events\n * (`sessionStart` \u2026 `sessionEnd`) run in one process. In `create_session` and\n * team children they do not: proxy events run in the pane child, and session\n * events run in the MCP server or the CLI process that drives the pane. Pass\n * per-turn data from a proxy event to `sessionIdle` with `annotateTurn`, never\n * with module variables.\n *\n * ## Execution: a hook chain\n *\n * The hooks of one event run one after another, in effective order. Each hook\'s\n * actions are applied before the next hook is called, so `ctx.request`,\n * `ctx.tool.args` and `ctx.response` show what the earlier hooks did, and\n * `ctx.prior` lists it. A warn-severity or failing hook changes nothing for the\n * next one. Each event has a budget for all its hooks together; a hook\'s timeout\n * is cut to what is left of it.\n *\n * ## Output\n *\n * Log with `ctx.log`. `console.*` and `process.stdout`/`stderr` writes made by a\n * hook are routed to claudish\'s debug log, never to the terminal or the MCP\n * protocol stream.\n */\n export const HOOK_API_VERSION = 1;\n export type Severity = "off" | "warn" | "fix";\n export type HookOrder = "pre" | "normal" | "post";\n /** native = RouteInfo.native true; foreign = RouteInfo.native false; all = both */\n export type RouteScope = "foreign" | "native" | "all";\n export type HostMode = "interactive" | "pane-child" | "serve" | "mcp" | "other";\n export type JsonValue = string | number | boolean | null | ReadonlyArray<JsonValue> | {\n readonly [k: string]: JsonValue;\n };\n export interface HarnessFacts {\n readonly planModeActive: boolean;\n readonly planFilePath?: string;\n readonly planDir?: string;\n /** Claude Code session id from request metadata */\n readonly sessionId?: string;\n /** empty = no listing found, not "no skills" */\n readonly skills?: ReadonlyArray<{\n name: string;\n description: string;\n }>;\n }\n export interface RouteInfo {\n /** bare model name the handler serves, e.g. "glm-5" */\n readonly modelId: string;\n /** claudish provider name, e.g. "openrouter"; "anthropic" for native */\n readonly provider: string;\n /**\n * true when the request is served by the native Anthropic handler, OR when\n * !forceForeignModel && (/^claude[-.]/i.test(modelId) || provider === "anthropic")\n * where forceForeignModel is the provider profile\'s opt-in override. This is the exact\n * rule the plan-mode built-in has always used (a claude-* uid on an aggregator that sets\n * forceForeignModel is foreign).\n */\n readonly native: boolean;\n }\n export interface ClaudeTool {\n name: string;\n description?: string;\n input_schema?: unknown;\n }\n /** A Claude-format content block. Only `text` blocks are editable by closed actions. */\n export type ClaudeContentBlock = {\n type: "text";\n text: string;\n } | {\n type: "tool_use";\n id: string;\n name: string;\n input: unknown;\n } | {\n type: "tool_result";\n tool_use_id: string;\n content?: unknown;\n is_error?: boolean;\n } | {\n type: "thinking";\n thinking: string;\n signature?: string;\n } | {\n type: string;\n [k: string]: unknown;\n };\n export interface ClaudeMessage {\n role: "user" | "assistant";\n content: string | ReadonlyArray<ClaudeContentBlock>;\n }\n /**\n * In `request`, the request as the earlier steps of the hook chain left it. On\n * the response side and in `claims()`, the request chain\'s final view.\n */\n export interface RequestFacts {\n /** as Claude Code asked for it; frozen */\n readonly model: string;\n /** frozen */\n readonly stream: boolean;\n /** system prompt flattened to text, after earlier steps */\n readonly systemText: string;\n /** read-only view after earlier steps; change it through actions */\n readonly messages: ReadonlyArray<ClaudeMessage>;\n /**\n * read-only view after earlier steps; `description` includes earlier description actions as\n * stage B will apply them to the Claude-format tool (the provider copy may be summarised)\n */\n readonly tools: ReadonlyArray<ClaudeTool>;\n }\n /** Which session a proxy event belongs to, when claudish knows. */\n export interface ProxySessionRef {\n readonly kind: SessionKind;\n readonly id: string;\n readonly role: "slot" | "judge" | null;\n }\n /** One action an earlier step of this hook chain applied or handed on. */\n export interface PriorAction {\n readonly hookId: string;\n readonly action: HookAction;\n }\n interface BaseContext {\n readonly hookId: string;\n /** "warn" or "fix" (an "off" hook is never called) */\n readonly severity: Severity;\n /** writes to claudish\'s debug log; never to the terminal */\n log(message: string): void;\n /**\n * this step\'s own signal: aborted when its step timeout elapses (its own timeout, or the\n * event budget left, whichever is shorter) or when the dispatch is aborted. Never shared\n * with another hook\'s step.\n */\n readonly signal: AbortSignal;\n /**\n * actions earlier steps of this hook chain applied (or, for responseEnd/sessionStart/\n * sessionIdle, handed on), in order. Empty for the first step and in claims()/the toolCall\n * predicate. Never lists warn actions or anything a warn-severity hook returned.\n */\n readonly prior: ReadonlyArray<PriorAction>;\n }\n export interface ProxyContext extends BaseContext {\n readonly host: {\n mode: HostMode;\n };\n readonly route: RouteInfo;\n readonly request: RequestFacts;\n readonly harness: HarnessFacts;\n readonly session: ProxySessionRef | null;\n }\n export interface RequestContext extends ProxyContext {\n readonly event: "request";\n }\n export interface ToolCallContext extends ProxyContext {\n readonly event: "toolCall";\n readonly tool: {\n id: string;\n name: string;\n /** the arguments after every repair earlier hooks in the chain applied */\n args: Readonly<Record<string, unknown>>;\n /** the argument JSON exactly as the model produced it; never rewritten */\n rawArgs: string;\n };\n }\n export type ResponseBlock = {\n type: "text";\n text: string;\n } | {\n type: "thinking";\n thinking: string;\n } | {\n type: "tool_use";\n id: string;\n name: string;\n input: unknown;\n } | {\n type: "other";\n blockType: string;\n };\n export interface ResponseView {\n blocks: ReadonlyArray<ResponseBlock>;\n /** every text block, joined with "\\n\\n" */\n text: string;\n /** every thinking block, joined with "\\n\\n" */\n reasoning: string;\n toolNames: ReadonlyArray<string>;\n /** "tool_use" = an intermediate step of a tool loop; the turn continues after the tool runs */\n stopReason: string | null;\n }\n /** response = the held response after every text action earlier hooks in the chain applied */\n export interface ResponseRewriteContext extends ProxyContext {\n readonly event: "responseRewrite";\n readonly response: ResponseView;\n }\n /** response = the final bytes the client received: after any rewrite AND any raw `response` replacement */\n export interface ResponseEndContext extends ProxyContext {\n readonly event: "responseEnd";\n readonly response: ResponseView;\n }\n export type SessionKind = "interactive" | "channel" | "team";\n export interface SessionInfo {\n kind: SessionKind;\n /** team only; null otherwise */\n role: "slot" | "judge" | null;\n /** channel: the 8-hex session_id \xB7 team: "<run_id>:<slot id>" \xB7 interactive: the Claude Code session id */\n id: string;\n claudeSessionId: string | null;\n /** as the caller asked for it */\n model: string;\n cwd: string;\n /** a one-shot session stays "one-shot" through a hook-extended turn chain */\n shape: "interactive" | "one-shot";\n injection: "available" | "unavailable";\n }\n export interface SessionStartContext extends BaseContext {\n readonly event: "sessionStart";\n readonly session: SessionInfo;\n }\n export interface TurnAnnotation {\n hookId: string;\n key: string;\n value: JsonValue;\n }\n export interface SessionIdleContext extends BaseContext {\n readonly event: "sessionIdle";\n readonly session: SessionInfo;\n readonly turn: {\n /** 1-based within the session; a re-woken turn keeps its index */\n index: number;\n /** this turn\'s assistant text */\n answer: string;\n stopReason: string | null;\n apiError: boolean;\n /** this turn was started by an injection */\n hookCaused: boolean;\n /** annotateTurn actions from this turn\'s responses, in arrival order */\n annotations: ReadonlyArray<TurnAnnotation>;\n };\n readonly consecutiveHookTurns: number;\n /** caller/human input is queued; an injection returned now will be dropped as stale */\n readonly callerInputPending: boolean;\n }\n export interface SessionBlockedContext extends BaseContext {\n readonly event: "sessionBlocked";\n readonly session: SessionInfo;\n readonly block: {\n kind: "question" | "permission";\n text: string;\n };\n }\n export interface SessionEndContext extends BaseContext {\n readonly event: "sessionEnd";\n readonly session: SessionInfo;\n readonly outcome: {\n state: string;\n reason: string | null;\n exitCode: number | null;\n };\n }\n type TextMatch = {\n find: string;\n regex?: boolean;\n flags?: string;\n };\n /** default ["user"] */\n type MessageRoles = {\n roles?: ReadonlyArray<"user" | "assistant">;\n };\n export type InjectSystemNote = {\n type: "injectSystemNote";\n text: string;\n };\n export type AppendUserText = {\n type: "appendUserText";\n text: string;\n };\n export type ReplaceMessageText = {\n type: "replaceMessageText";\n replace: string;\n } & TextMatch & MessageRoles;\n export type RemoveMessageText = {\n type: "removeMessageText";\n } & TextMatch & MessageRoles;\n export type RewriteToolDescription = {\n type: "rewriteToolDescription";\n tool: string;\n append: string;\n };\n export type ReplaceToolDescription = {\n type: "replaceToolDescription";\n tool: string;\n description: string;\n };\n export type ReplaceToolSchema = {\n type: "replaceToolSchema";\n tool: string;\n inputSchema: {\n type: "object";\n [k: string]: unknown;\n };\n };\n export type RemoveTool = {\n type: "removeTool";\n tool: string;\n };\n export type RepairToolArgs = {\n type: "repairToolArgs";\n args: Record<string, unknown>;\n reason: string;\n };\n export type AppendText = {\n type: "appendText";\n text: string;\n };\n export type PrependText = {\n type: "prependText";\n text: string;\n };\n export type ReplaceText = {\n type: "replaceText";\n replace: string;\n } & TextMatch;\n export type RemoveText = {\n type: "removeText";\n } & TextMatch;\n export type InjectUserTurn = {\n type: "injectUserTurn";\n text: string;\n };\n export type AnnotateTurn = {\n type: "annotateTurn";\n key: string;\n value: JsonValue;\n };\n export type Warn = {\n type: "warn";\n message: string;\n };\n export type RequestAction = InjectSystemNote | AppendUserText | ReplaceMessageText | RemoveMessageText | RewriteToolDescription | ReplaceToolDescription | ReplaceToolSchema | RemoveTool | Warn;\n export type ToolCallAction = RepairToolArgs | Warn;\n export type RewriteAction = AppendText | PrependText | ReplaceText | RemoveText | Warn;\n export type ResponseEndAction = InjectSystemNote | InjectUserTurn | AnnotateTurn | Warn;\n export type SessionAction = InjectUserTurn | Warn;\n export type ObserveAction = Warn;\n export type HookAction = RequestAction | ToolCallAction | RewriteAction | ResponseEndAction | SessionAction;\n export type HookResult<A> = A[] | void | Promise<A[] | void>;\n export interface HookHandlers {\n request?(ctx: RequestContext): HookResult<RequestAction>;\n toolCall?: {\n /** tool names whose completed arguments this hook sees; "*" = every tool (costs streaming of all tool input) */\n tools: ReadonlyArray<string>;\n /** synchronous, per request; default true. false = not armed for this request */\n armed?(ctx: RequestContext): boolean;\n /** true = see the call after it was forwarded; can only warn; never holds the stream */\n observe?: boolean;\n handle(ctx: ToolCallContext): HookResult<ToolCallAction>;\n };\n responseRewrite?: {\n /** synchronous, per request, evaluated before the response starts; default true */\n claims?(ctx: RequestContext): boolean;\n handle(ctx: ResponseRewriteContext): HookResult<RewriteAction>;\n };\n responseEnd?(ctx: ResponseEndContext): HookResult<ResponseEndAction>;\n sessionStart?(ctx: SessionStartContext): HookResult<SessionAction>;\n sessionIdle?(ctx: SessionIdleContext): HookResult<SessionAction>;\n sessionBlocked?(ctx: SessionBlockedContext): HookResult<ObserveAction>;\n sessionEnd?(ctx: SessionEndContext): HookResult<ObserveAction>;\n }\n export interface RawProviderRequestContext {\n readonly hookId: string;\n readonly route: RouteInfo;\n claudeRequest: any;\n messages: any[];\n tools: any[];\n }\n export interface RawProviderChunkContext {\n readonly hookId: string;\n readonly route: RouteInfo;\n /** A clone of the parsed provider event. Whatever this field holds when the call returns is\n * what the parser reads from then on, so it may be edited in place or replaced. */\n chunk: any;\n /** The delta object inside `chunk` at call time (Responses wire: `chunk` itself). Edit it in\n * place; assigning a new object to this field has no effect. */\n delta: any;\n /** per-stream, shared across this hook\'s chunk calls; never cloned */\n metadata: Map<string, unknown>;\n }\n export interface RawProviderStreamEndContext {\n readonly hookId: string;\n readonly route: RouteInfo;\n metadata: Map<string, unknown>;\n }\n export interface RawResponseContext {\n readonly hookId: string;\n readonly route: RouteInfo;\n readonly request: RequestFacts;\n /** A replay of the current Claude-format response (SSE, or JSON for stream:false), read at the\n * hook\'s own pace. claudish drains the original itself, so leaving this unread delays nothing. */\n response: Response;\n }\n export interface RawMiddleware {\n /**\n * Receives clones. They replace the live request only when this call returns (or its promise\n * resolves) within its timeout. A throw, a rejection or a timeout discards every change.\n */\n providerRequest?(ctx: RawProviderRequestContext): void | Promise<void>;\n /**\n * MUST be synchronous. Called on the parser\'s loop, on a clone of the chunk. On a normal return\n * of anything but a thenable, the clone (whatever `ctx.chunk` holds then) is committed: it\n * becomes the object the parser reads, deletions included. On a throw nothing is committed.\n * A declared `async` function is rejected at load. Any other thenable return is an invalid\n * invocation: the clone is discarded even if the hook mutated it before returning, the call is\n * journaled `invalid` (`async_return`) and counts toward the circuit breaker, and a rejection\n * handler is attached, so a rejection is journaled `error` and never becomes an\n * unhandledRejection.\n */\n providerChunk?(ctx: RawProviderChunkContext): void;\n providerStreamEnd?(ctx: RawProviderStreamEndContext): void | Promise<void>;\n /**\n * Return a replacement Response, or nothing to keep the current one. A replacement is read\n * whole and forwarded only when it completes cleanly; on any failure the original is forwarded.\n * The client never sees a partial replacement. A replacement must close within this hook\'s\n * timeout after the later of this call\'s return and the end of the original; the original\'s end\n * never depends on whether `ctx.response` is read.\n */\n response?(ctx: RawResponseContext): Response | void | Promise<Response | void>;\n }\n interface HookBase {\n apiVersion: 1;\n id: string;\n description?: string;\n /** default "fix" for user hooks */\n defaultSeverity?: Severity;\n /** default "normal" */\n order?: HookOrder;\n /** globs on RouteInfo.modelId; default "*"; proxy events only */\n models?: string | ReadonlyArray<string>;\n /** default "all"; proxy events only */\n routes?: RouteScope;\n /** per call; clamped to the event\'s maximum and to the event budget left when the hook\'s turn comes */\n timeoutMs?: number;\n on?: HookHandlers;\n }\n export interface SafeHook extends HookBase {\n unsafe?: never;\n raw?: never;\n }\n export interface UnsafeHook extends HookBase {\n unsafe: true;\n raw: RawMiddleware;\n }\n /**\n * One hook. Module-level state is per process: in `create_session` and team\n * children, proxy events run in the pane child and session events in the MCP\n * server or CLI process. Pass per-turn data from proxy events to `sessionIdle`\n * with `annotateTurn`, never with module variables.\n */\n export type HookDefinition = SafeHook | UnsafeHook;\n /** Identity function: gives editor type-checking and inference. */\n export function defineHook<const H extends HookDefinition>(hook: H): H;\n /** Action constructors (plain data; equivalent to writing the object literal). */\n export const act: {\n injectSystemNote(text: string): InjectSystemNote;\n appendUserText(text: string): AppendUserText;\n replaceMessageText(find: string, replace: string, opts?: {\n regex?: boolean;\n flags?: string;\n roles?: ReadonlyArray<"user" | "assistant">;\n }): ReplaceMessageText;\n removeMessageText(find: string, opts?: {\n regex?: boolean;\n flags?: string;\n roles?: ReadonlyArray<"user" | "assistant">;\n }): RemoveMessageText;\n rewriteToolDescription(tool: string, append: string): RewriteToolDescription;\n replaceToolDescription(tool: string, description: string): ReplaceToolDescription;\n replaceToolSchema(tool: string, inputSchema: {\n type: "object";\n [k: string]: unknown;\n }): ReplaceToolSchema;\n removeTool(tool: string): RemoveTool;\n repairToolArgs(args: Record<string, unknown>, reason: string): RepairToolArgs;\n appendText(text: string): AppendText;\n prependText(text: string): PrependText;\n replaceText(find: string, replace: string, opts?: {\n regex?: boolean;\n flags?: string;\n }): ReplaceText;\n removeText(find: string, opts?: {\n regex?: boolean;\n flags?: string;\n }): RemoveText;\n injectUserTurn(text: string): InjectUserTurn;\n annotateTurn(key: string, value: JsonValue): AnnotateTurn;\n warn(message: string): Warn;\n };\n}\n';
|
|
110742
111520
|
|
|
110743
111521
|
// src/hooks/observer/corpus.ts
|
|
110744
|
-
import { appendFileSync as appendFileSync8, readFileSync as
|
|
110745
|
-
import { homedir as
|
|
110746
|
-
import { join as
|
|
111522
|
+
import { appendFileSync as appendFileSync8, readFileSync as readFileSync51, readdirSync as readdirSync15, statSync as statSync26 } from "fs";
|
|
111523
|
+
import { homedir as homedir42 } from "os";
|
|
111524
|
+
import { join as join64 } from "path";
|
|
110747
111525
|
function directoryOf2(filePath) {
|
|
110748
111526
|
const slash = filePath.lastIndexOf("/");
|
|
110749
111527
|
return slash > 0 ? filePath.slice(0, slash) : undefined;
|
|
@@ -110765,7 +111543,7 @@ function writeTargetsOf(row) {
|
|
|
110765
111543
|
function replayTranscript(file) {
|
|
110766
111544
|
let text;
|
|
110767
111545
|
try {
|
|
110768
|
-
text =
|
|
111546
|
+
text = readFileSync51(file, "utf8");
|
|
110769
111547
|
} catch {
|
|
110770
111548
|
return [];
|
|
110771
111549
|
}
|
|
@@ -110817,31 +111595,31 @@ function listTranscripts(root) {
|
|
|
110817
111595
|
const files = [];
|
|
110818
111596
|
let projects;
|
|
110819
111597
|
try {
|
|
110820
|
-
projects =
|
|
111598
|
+
projects = readdirSync15(root);
|
|
110821
111599
|
} catch {
|
|
110822
111600
|
return files;
|
|
110823
111601
|
}
|
|
110824
111602
|
for (const project of projects) {
|
|
110825
|
-
const dir =
|
|
111603
|
+
const dir = join64(root, project);
|
|
110826
111604
|
try {
|
|
110827
|
-
if (!
|
|
111605
|
+
if (!statSync26(dir).isDirectory())
|
|
110828
111606
|
continue;
|
|
110829
|
-
for (const f of
|
|
111607
|
+
for (const f of readdirSync15(dir)) {
|
|
110830
111608
|
if (f.endsWith(".jsonl"))
|
|
110831
|
-
files.push(
|
|
111609
|
+
files.push(join64(dir, f));
|
|
110832
111610
|
}
|
|
110833
111611
|
} catch {}
|
|
110834
111612
|
}
|
|
110835
111613
|
return files;
|
|
110836
111614
|
}
|
|
110837
111615
|
function buildCorpus(options = {}) {
|
|
110838
|
-
const root = options.projectsRoot ??
|
|
111616
|
+
const root = options.projectsRoot ?? join64(homedir42(), ".claude", "projects");
|
|
110839
111617
|
const files = listTranscripts(root);
|
|
110840
111618
|
const records = [];
|
|
110841
111619
|
for (const f of files)
|
|
110842
111620
|
records.push(...replayTranscript(f));
|
|
110843
111621
|
if (options.write && records.length > 0) {
|
|
110844
|
-
const outputPath = options.outputPath ??
|
|
111622
|
+
const outputPath = options.outputPath ?? join64(homedir42(), ".claudish", "behavior-divergences.jsonl");
|
|
110845
111623
|
try {
|
|
110846
111624
|
appendFileSync8(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
|
|
110847
111625
|
`)}
|
|
@@ -110857,9 +111635,9 @@ var init_corpus = __esm(() => {
|
|
|
110857
111635
|
});
|
|
110858
111636
|
|
|
110859
111637
|
// src/hooks-command.ts
|
|
110860
|
-
import { existsSync as existsSync45, mkdirSync as
|
|
110861
|
-
import { homedir as
|
|
110862
|
-
import { join as
|
|
111638
|
+
import { existsSync as existsSync45, mkdirSync as mkdirSync30, readFileSync as readFileSync52, writeFileSync as writeFileSync28 } from "fs";
|
|
111639
|
+
import { homedir as homedir43 } from "os";
|
|
111640
|
+
import { join as join65, resolve as resolve12 } from "path";
|
|
110863
111641
|
function severityColor(sev) {
|
|
110864
111642
|
if (sev === "fix")
|
|
110865
111643
|
return green(sev);
|
|
@@ -110982,10 +111760,10 @@ async function check(file, json) {
|
|
|
110982
111760
|
return valid ? 0 : 1;
|
|
110983
111761
|
}
|
|
110984
111762
|
function init(dirArg) {
|
|
110985
|
-
const dir = dirArg ? resolve12(process.cwd(), dirArg) :
|
|
111763
|
+
const dir = dirArg ? resolve12(process.cwd(), dirArg) : join65(homedir43(), ".claudish", "hooks");
|
|
110986
111764
|
const files = [
|
|
110987
|
-
[
|
|
110988
|
-
[
|
|
111765
|
+
[join65(dir, "example-hook.ts"), EXAMPLE_HOOK],
|
|
111766
|
+
[join65(dir, "claudish-hooks.d.ts"), HOOKS_AMBIENT_DTS]
|
|
110989
111767
|
];
|
|
110990
111768
|
const existing = files.filter(([path]) => existsSync45(path)).map(([path]) => path);
|
|
110991
111769
|
if (existing.length > 0) {
|
|
@@ -110993,9 +111771,9 @@ function init(dirArg) {
|
|
|
110993
111771
|
console.error(`${path} already exists; not overwriting it.`);
|
|
110994
111772
|
return 1;
|
|
110995
111773
|
}
|
|
110996
|
-
|
|
111774
|
+
mkdirSync30(dir, { recursive: true });
|
|
110997
111775
|
for (const [path, text] of files)
|
|
110998
|
-
|
|
111776
|
+
writeFileSync28(path, text, { flag: "wx" });
|
|
110999
111777
|
console.log(`
|
|
111000
111778
|
wrote ${files.map(([p]) => p).join(`
|
|
111001
111779
|
wrote `)}
|
|
@@ -111078,7 +111856,7 @@ function telemetry(action, json) {
|
|
|
111078
111856
|
try {
|
|
111079
111857
|
const path = outboxPath();
|
|
111080
111858
|
if (existsSync45(path))
|
|
111081
|
-
pending =
|
|
111859
|
+
pending = readFileSync52(path, "utf8").split(`
|
|
111082
111860
|
`).filter(Boolean).length;
|
|
111083
111861
|
} catch {}
|
|
111084
111862
|
if (json) {
|
|
@@ -111186,9 +111964,9 @@ var init_hooks_command = __esm(() => {
|
|
|
111186
111964
|
|
|
111187
111965
|
// src/team-grid.ts
|
|
111188
111966
|
import { spawn as spawn4 } from "child_process";
|
|
111189
|
-
import { existsSync as existsSync46, readFileSync as
|
|
111967
|
+
import { existsSync as existsSync46, readFileSync as readFileSync53, writeFileSync as writeFileSync29 } from "fs";
|
|
111190
111968
|
import { connect as netConnect3 } from "net";
|
|
111191
|
-
import { join as
|
|
111969
|
+
import { join as join66 } from "path";
|
|
111192
111970
|
import { setTimeout as wait } from "timers/promises";
|
|
111193
111971
|
function paneRouteLine(explanation) {
|
|
111194
111972
|
const origin = describeRouteExplanation(explanation);
|
|
@@ -111338,9 +112116,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
111338
112116
|
const keep = opts?.keep ?? false;
|
|
111339
112117
|
const manifest = setupSession(sessionPath, models, input);
|
|
111340
112118
|
const startedAt = new Date().toISOString();
|
|
111341
|
-
const gridfilePath =
|
|
111342
|
-
const prompt =
|
|
111343
|
-
const rawPrompt =
|
|
112119
|
+
const gridfilePath = join66(sessionPath, "gridfile.txt");
|
|
112120
|
+
const prompt = readFileSync53(join66(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
|
|
112121
|
+
const rawPrompt = readFileSync53(join66(sessionPath, "input.md"), "utf-8");
|
|
111344
112122
|
const usedBannerColors = new Set;
|
|
111345
112123
|
const routeLines = mode === "interactive" ? new Map : await resolvePaneRouteLines(Object.values(manifest.models).map((entry) => entry.model));
|
|
111346
112124
|
const gridLines = Object.entries(manifest.models).map(([anonId]) => {
|
|
@@ -111352,7 +112130,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
111352
112130
|
const header = buildPaneHeader(model, routeLines.get(model) ?? "", rawPrompt, bg);
|
|
111353
112131
|
return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
|
|
111354
112132
|
});
|
|
111355
|
-
|
|
112133
|
+
writeFileSync29(gridfilePath, `${gridLines.join(`
|
|
111356
112134
|
`)}
|
|
111357
112135
|
`, "utf-8");
|
|
111358
112136
|
const magmuxPath = findMagmuxBinary();
|
|
@@ -111372,8 +112150,8 @@ async function runWithGrid(sessionPath, models, input, opts) {
|
|
|
111372
112150
|
});
|
|
111373
112151
|
const [{ results }] = await Promise.all([subscription, procExit]);
|
|
111374
112152
|
const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
|
|
111375
|
-
const statusPath =
|
|
111376
|
-
|
|
112153
|
+
const statusPath = join66(sessionPath, "status.json");
|
|
112154
|
+
writeFileSync29(statusPath, JSON.stringify(status, null, 2), "utf-8");
|
|
111377
112155
|
return status;
|
|
111378
112156
|
}
|
|
111379
112157
|
var BANNER_BG_COLORS;
|
|
@@ -111392,8 +112170,8 @@ var init_team_grid = __esm(() => {
|
|
|
111392
112170
|
});
|
|
111393
112171
|
|
|
111394
112172
|
// src/team-cli.ts
|
|
111395
|
-
import { readFileSync as
|
|
111396
|
-
import { join as
|
|
112173
|
+
import { readFileSync as readFileSync54 } from "fs";
|
|
112174
|
+
import { join as join67 } from "path";
|
|
111397
112175
|
async function runPaneTeam(sessionPath, models, input, opts) {
|
|
111398
112176
|
installPaneShutdownHooks({ exitAfter: true });
|
|
111399
112177
|
try {
|
|
@@ -111538,7 +112316,7 @@ async function teamCommand(args) {
|
|
|
111538
112316
|
}
|
|
111539
112317
|
case "judge": {
|
|
111540
112318
|
await judgeResponses(sessionPath, { judges });
|
|
111541
|
-
console.log(
|
|
112319
|
+
console.log(readFileSync54(join67(sessionPath, "verdict.md"), "utf-8"));
|
|
111542
112320
|
break;
|
|
111543
112321
|
}
|
|
111544
112322
|
case "run-and-judge": {
|
|
@@ -111554,7 +112332,7 @@ async function teamCommand(args) {
|
|
|
111554
112332
|
});
|
|
111555
112333
|
printStatus(status);
|
|
111556
112334
|
await judgeResponses(sessionPath, { judges });
|
|
111557
|
-
console.log(
|
|
112335
|
+
console.log(readFileSync54(join67(sessionPath, "verdict.md"), "utf-8"));
|
|
111558
112336
|
break;
|
|
111559
112337
|
}
|
|
111560
112338
|
case "status": {
|
|
@@ -113776,8 +114554,8 @@ var init_account_command = __esm(() => {
|
|
|
113776
114554
|
// src/auth/antigravity-oauth.ts
|
|
113777
114555
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
113778
114556
|
import { existsSync as existsSync47, unlinkSync as unlinkSync13 } from "fs";
|
|
113779
|
-
import { homedir as
|
|
113780
|
-
import { join as
|
|
114557
|
+
import { homedir as homedir44 } from "os";
|
|
114558
|
+
import { join as join68 } from "path";
|
|
113781
114559
|
async function defaultSuggestModel() {
|
|
113782
114560
|
try {
|
|
113783
114561
|
const token = await getValidAntigravityAccessToken();
|
|
@@ -113896,7 +114674,7 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
|
|
|
113896
114674
|
async logout(deps) {
|
|
113897
114675
|
deleteSharedAntigravityToken(deps);
|
|
113898
114676
|
try {
|
|
113899
|
-
const tokenFile =
|
|
114677
|
+
const tokenFile = join68(homedir44(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
|
|
113900
114678
|
if (existsSync47(tokenFile))
|
|
113901
114679
|
unlinkSync13(tokenFile);
|
|
113902
114680
|
} catch {}
|
|
@@ -113929,13 +114707,13 @@ var init_antigravity_oauth = __esm(() => {
|
|
|
113929
114707
|
});
|
|
113930
114708
|
|
|
113931
114709
|
// src/auth/meta-muse-oauth.ts
|
|
113932
|
-
import { execFile as
|
|
114710
|
+
import { execFile as execFile7 } from "child_process";
|
|
113933
114711
|
function openInBrowser(url) {
|
|
113934
114712
|
if (!/^https:\/\//i.test(url))
|
|
113935
114713
|
return Promise.resolve();
|
|
113936
114714
|
const command = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer" : "xdg-open";
|
|
113937
114715
|
return new Promise((resolve) => {
|
|
113938
|
-
|
|
114716
|
+
execFile7(command, [url], () => resolve());
|
|
113939
114717
|
});
|
|
113940
114718
|
}
|
|
113941
114719
|
function describe2(answer, status) {
|
|
@@ -122095,18 +122873,18 @@ var init_tui = __esm(() => {
|
|
|
122095
122873
|
});
|
|
122096
122874
|
|
|
122097
122875
|
// src/diag-output.ts
|
|
122098
|
-
import { createWriteStream as createWriteStream2, mkdirSync as
|
|
122099
|
-
import { homedir as
|
|
122100
|
-
import { join as
|
|
122876
|
+
import { createWriteStream as createWriteStream2, mkdirSync as mkdirSync31, unlinkSync as unlinkSync14, writeFileSync as writeFileSync30 } from "fs";
|
|
122877
|
+
import { homedir as homedir45 } from "os";
|
|
122878
|
+
import { join as join69 } from "path";
|
|
122101
122879
|
function getClaudishDir() {
|
|
122102
|
-
const dir =
|
|
122880
|
+
const dir = join69(homedir45(), ".claudish");
|
|
122103
122881
|
try {
|
|
122104
|
-
|
|
122882
|
+
mkdirSync31(dir, { recursive: true });
|
|
122105
122883
|
} catch {}
|
|
122106
122884
|
return dir;
|
|
122107
122885
|
}
|
|
122108
122886
|
function getDiagLogPath() {
|
|
122109
|
-
return
|
|
122887
|
+
return join69(getClaudishDir(), `diag-${process.pid}.log`);
|
|
122110
122888
|
}
|
|
122111
122889
|
|
|
122112
122890
|
class LogFileDiagOutput {
|
|
@@ -122115,7 +122893,7 @@ class LogFileDiagOutput {
|
|
|
122115
122893
|
constructor() {
|
|
122116
122894
|
this.logPath = getDiagLogPath();
|
|
122117
122895
|
try {
|
|
122118
|
-
|
|
122896
|
+
writeFileSync30(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
|
|
122119
122897
|
`);
|
|
122120
122898
|
} catch {}
|
|
122121
122899
|
this.stream = createWriteStream2(this.logPath, { flags: "a" });
|
|
@@ -122628,7 +123406,7 @@ var init_advisor_startup = __esm(() => {
|
|
|
122628
123406
|
});
|
|
122629
123407
|
|
|
122630
123408
|
// src/session/conversation.ts
|
|
122631
|
-
import { closeSync as closeSync18, openSync as openSync17, readSync as readSync8, statSync as
|
|
123409
|
+
import { closeSync as closeSync18, openSync as openSync17, readSync as readSync8, statSync as statSync27 } from "fs";
|
|
122632
123410
|
import { StringDecoder } from "string_decoder";
|
|
122633
123411
|
function looksLikeTurn(line) {
|
|
122634
123412
|
const assistant = line.includes('"type":"assistant"');
|
|
@@ -122683,7 +123461,7 @@ function readConversation(file, opts = {}) {
|
|
|
122683
123461
|
};
|
|
122684
123462
|
let fd = null;
|
|
122685
123463
|
try {
|
|
122686
|
-
const size =
|
|
123464
|
+
const size = statSync27(file).size;
|
|
122687
123465
|
fd = openSync17(file, "r");
|
|
122688
123466
|
const buf = Buffer.allocUnsafe(chunkBytes);
|
|
122689
123467
|
const decoder = new StringDecoder("utf-8");
|
|
@@ -124342,11 +125120,11 @@ var exports_session_stats = {};
|
|
|
124342
125120
|
__export(exports_session_stats, {
|
|
124343
125121
|
readSessionStats: () => readSessionStats
|
|
124344
125122
|
});
|
|
124345
|
-
import { readFileSync as
|
|
125123
|
+
import { readFileSync as readFileSync55 } from "fs";
|
|
124346
125124
|
function readSessionStats(port, opts) {
|
|
124347
125125
|
let raw;
|
|
124348
125126
|
try {
|
|
124349
|
-
raw = JSON.parse(
|
|
125127
|
+
raw = JSON.parse(readFileSync55(resolveTokenFilePath(port), "utf-8"));
|
|
124350
125128
|
} catch {
|
|
124351
125129
|
return null;
|
|
124352
125130
|
}
|
|
@@ -124724,8 +125502,8 @@ init_launch_env();
|
|
|
124724
125502
|
init_op_source();
|
|
124725
125503
|
init_startup_trace();
|
|
124726
125504
|
init_picker_cancelled();
|
|
124727
|
-
import { existsSync as existsSync48, readFileSync as
|
|
124728
|
-
import { join as
|
|
125505
|
+
import { existsSync as existsSync48, readFileSync as readFileSync56 } from "fs";
|
|
125506
|
+
import { join as join70, resolve as resolve13 } from "path";
|
|
124729
125507
|
|
|
124730
125508
|
// src/tui/runtime/should-open-picker.ts
|
|
124731
125509
|
function noModelConfigured(gate) {
|
|
@@ -124742,7 +125520,7 @@ function requiresExplicitModel(gate, tty) {
|
|
|
124742
125520
|
var autoloadDropped = [...droppedAtLaunch, ...takeLauncherDropped(process.env)];
|
|
124743
125521
|
var dotenvText;
|
|
124744
125522
|
try {
|
|
124745
|
-
dotenvText =
|
|
125523
|
+
dotenvText = readFileSync56(join70(process.cwd(), ".env"));
|
|
124746
125524
|
} catch {}
|
|
124747
125525
|
if (dotenvText !== undefined) {
|
|
124748
125526
|
await Promise.resolve().then(() => init_dotenv_allowlist());
|
|
@@ -125083,14 +125861,14 @@ async function runCli() {
|
|
|
125083
125861
|
if (cliConfig.team && cliConfig.team.length > 0) {
|
|
125084
125862
|
let prompt = cliConfig.claudeArgs.join(" ");
|
|
125085
125863
|
if (cliConfig.inputFile) {
|
|
125086
|
-
prompt =
|
|
125864
|
+
prompt = readFileSync56(cliConfig.inputFile, "utf-8");
|
|
125087
125865
|
}
|
|
125088
125866
|
if (!prompt.trim()) {
|
|
125089
125867
|
console.error("Error: --team requires a prompt (positional args or -f <file>)");
|
|
125090
125868
|
process.exit(1);
|
|
125091
125869
|
}
|
|
125092
125870
|
const mode = cliConfig.teamMode ?? "default";
|
|
125093
|
-
const sessionPath =
|
|
125871
|
+
const sessionPath = join70(process.cwd(), `.claudish-team-${Date.now()}`);
|
|
125094
125872
|
if (mode === "json") {
|
|
125095
125873
|
await Promise.resolve().then(() => init_pane());
|
|
125096
125874
|
await Promise.resolve().then(() => init_team_orchestrator());
|
|
@@ -125110,9 +125888,9 @@ async function runCli() {
|
|
|
125110
125888
|
const status = await runModels(sessionPath);
|
|
125111
125889
|
const result = { ...status, responses: {} };
|
|
125112
125890
|
for (const anonId of Object.keys(status.models)) {
|
|
125113
|
-
const responsePath =
|
|
125891
|
+
const responsePath = join70(sessionPath, `response-${anonId}.md`);
|
|
125114
125892
|
try {
|
|
125115
|
-
const raw =
|
|
125893
|
+
const raw = readFileSync56(responsePath, "utf-8").trim();
|
|
125116
125894
|
try {
|
|
125117
125895
|
result.responses[anonId] = JSON.parse(raw);
|
|
125118
125896
|
} catch {
|
|
@@ -125229,7 +126007,11 @@ Team Status`);
|
|
|
125229
126007
|
hasProfileTiers
|
|
125230
126008
|
});
|
|
125231
126009
|
if (shouldOpenPicker(pickerGate(), pickerCanDraw)) {
|
|
125232
|
-
|
|
126010
|
+
const sizeIsGiven = cliConfig.contextWindow !== undefined || process.env.CLAUDISH_CONTEXT_WINDOW !== undefined;
|
|
126011
|
+
const onContextWindow = sizeIsGiven ? undefined : (size) => {
|
|
126012
|
+
cliConfig.contextWindow = size;
|
|
126013
|
+
};
|
|
126014
|
+
cliConfig.model = await traceSpan("startup:model-select", () => selectModel({ freeOnly: cliConfig.freeOnly, onContextWindow }).catch(handlePromptExit), { mayIncludeUserPrompt: true });
|
|
125233
126015
|
console.log("");
|
|
125234
126016
|
}
|
|
125235
126017
|
if (requiresExplicitModel(pickerGate(), pickerCanDraw)) {
|
|
@@ -125374,6 +126156,9 @@ Team Status`);
|
|
|
125374
126156
|
}
|
|
125375
126157
|
}
|
|
125376
126158
|
}
|
|
126159
|
+
if (cliConfig.contextWindow !== undefined) {
|
|
126160
|
+
process.env.CLAUDISH_CONTEXT_WINDOW = String(cliConfig.contextWindow);
|
|
126161
|
+
}
|
|
125377
126162
|
const proxy = await traceSpan("startup:proxy-start", () => createProxyServer(port, cliConfig.monitor ? undefined : cliConfig.openrouterApiKey, cliConfig.monitor ? undefined : explicitModel, cliConfig.monitor, cliConfig.anthropicApiKey, modelMap, {
|
|
125378
126163
|
summarizeTools: cliConfig.summarizeTools,
|
|
125379
126164
|
quiet: cliConfig.quiet,
|