claudish 7.25.0 → 7.27.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.
Files changed (2) hide show
  1. package/dist/index.js +1140 -458
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -651,7 +651,7 @@ var init_onepassword_config = __esm(() => {
651
651
  });
652
652
 
653
653
  // src/version.ts
654
- var VERSION = "7.25.0";
654
+ var VERSION = "7.27.0";
655
655
 
656
656
  // src/logger.ts
657
657
  var exports_logger = {};
@@ -1173,6 +1173,122 @@ var init_startup_trace = __esm(() => {
1173
1173
  spans = [];
1174
1174
  });
1175
1175
 
1176
+ // src/providers/onepassword-handshake-lock.ts
1177
+ import { closeSync, mkdirSync as mkdirSync3, openSync, readFileSync as readFileSync3, rmSync, statSync, writeSync } from "fs";
1178
+ import { homedir as homedir4 } from "os";
1179
+ import { dirname as dirname2, join as join4 } from "path";
1180
+ function defaultLockPath() {
1181
+ return join4(homedir4(), ".claudish", "op-handshake.lock");
1182
+ }
1183
+ function currentLockPath() {
1184
+ return lockPath ?? defaultLockPath();
1185
+ }
1186
+ function trace(message) {
1187
+ if (process.env.CLAUDISH_OP_LOCK_TRACE !== "1")
1188
+ return;
1189
+ console.error(`[op-lock] pid=${process.pid} ${message}`);
1190
+ }
1191
+ function readHolder(path) {
1192
+ try {
1193
+ const [pidRaw, atRaw] = readFileSync3(path, "utf-8").trim().split(/\s+/);
1194
+ const pid = Number(pidRaw);
1195
+ const at = Number(atRaw);
1196
+ if (!Number.isInteger(pid) || pid <= 0)
1197
+ return null;
1198
+ return { pid, at: Number.isFinite(at) ? at : 0 };
1199
+ } catch {
1200
+ return null;
1201
+ }
1202
+ }
1203
+ function holderAlive(pid) {
1204
+ try {
1205
+ process.kill(pid, 0);
1206
+ return true;
1207
+ } catch (err) {
1208
+ return err?.code === "EPERM";
1209
+ }
1210
+ }
1211
+ function isAbandoned(path) {
1212
+ const holder = readHolder(path);
1213
+ if (!holder) {
1214
+ try {
1215
+ return Date.now() - statSync(path).mtimeMs > timing.staleMs;
1216
+ } catch {
1217
+ return false;
1218
+ }
1219
+ }
1220
+ if (holder.pid !== process.pid && !holderAlive(holder.pid))
1221
+ return true;
1222
+ return Date.now() - holder.at > timing.staleMs;
1223
+ }
1224
+ async function acquire(path) {
1225
+ const deadline = Date.now() + timing.timeoutMs;
1226
+ let madeDir = false;
1227
+ for (;; ) {
1228
+ try {
1229
+ if (!madeDir) {
1230
+ mkdirSync3(dirname2(path), { recursive: true });
1231
+ madeDir = true;
1232
+ }
1233
+ const fd = openSync(path, "wx");
1234
+ try {
1235
+ writeSync(fd, `${process.pid} ${Date.now()}`);
1236
+ } finally {
1237
+ closeSync(fd);
1238
+ }
1239
+ return true;
1240
+ } catch (err) {
1241
+ if (err?.code !== "EEXIST")
1242
+ return false;
1243
+ if (isAbandoned(path)) {
1244
+ try {
1245
+ rmSync(path, { force: true });
1246
+ } catch {}
1247
+ continue;
1248
+ }
1249
+ if (Date.now() >= deadline)
1250
+ return false;
1251
+ await sleep(timing.pollMs + Math.floor(Math.random() * timing.pollMs));
1252
+ }
1253
+ }
1254
+ }
1255
+ function release(path) {
1256
+ try {
1257
+ if (readHolder(path)?.pid === process.pid)
1258
+ rmSync(path, { force: true });
1259
+ } catch {}
1260
+ }
1261
+ async function withHandshakeLock(handshake) {
1262
+ if (process.env.CLAUDISH_NO_OP_HANDSHAKE_LOCK === "1") {
1263
+ trace("bypassed (CLAUDISH_NO_OP_HANDSHAKE_LOCK=1)");
1264
+ return handshake();
1265
+ }
1266
+ const path = currentLockPath();
1267
+ const t0 = Date.now();
1268
+ let held = false;
1269
+ try {
1270
+ held = await acquire(path);
1271
+ } catch {
1272
+ held = false;
1273
+ }
1274
+ trace(`${held ? "acquired" : "NOT held (timeout or unwritable)"} after ${Date.now() - t0}ms`);
1275
+ try {
1276
+ return await handshake();
1277
+ } finally {
1278
+ if (held)
1279
+ release(path);
1280
+ trace(`handshake done after ${Date.now() - t0}ms${held ? ", released" : ""}`);
1281
+ }
1282
+ }
1283
+ var DEFAULT_STALE_MS = 120000, DEFAULT_TIMEOUT_MS = 45000, DEFAULT_POLL_MS = 60, timing, lockPath, sleep = (ms) => new Promise((r) => setTimeout(r, ms));
1284
+ var init_onepassword_handshake_lock = __esm(() => {
1285
+ timing = {
1286
+ staleMs: DEFAULT_STALE_MS,
1287
+ timeoutMs: DEFAULT_TIMEOUT_MS,
1288
+ pollMs: DEFAULT_POLL_MS
1289
+ };
1290
+ });
1291
+
1176
1292
  // src/providers/onepassword-wasm.ts
1177
1293
  var exports_onepassword_wasm = {};
1178
1294
  __export(exports_onepassword_wasm, {
@@ -1185,17 +1301,17 @@ __export(exports_onepassword_wasm, {
1185
1301
  SDK_CORE_INTEGRITY: () => SDK_CORE_INTEGRITY
1186
1302
  });
1187
1303
  import { createHash } from "crypto";
1188
- import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "fs";
1304
+ import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "fs";
1189
1305
  import { createRequire } from "module";
1190
- import { homedir as homedir4 } from "os";
1191
- import { dirname as dirname2, join as join4 } from "path";
1306
+ import { homedir as homedir5 } from "os";
1307
+ import { dirname as dirname3, join as join5 } from "path";
1192
1308
  import { gunzipSync } from "zlib";
1193
1309
  function tarballUrl() {
1194
1310
  return `https://registry.npmjs.org/@1password/sdk-core/-/sdk-core-${SDK_CORE_VERSION}.tgz`;
1195
1311
  }
1196
1312
  function cacheWasmPath() {
1197
- const root = cacheRootOverride ?? join4(homedir4(), ".claudish");
1198
- return join4(root, "cache", "1password", WASM_FILENAME);
1313
+ const root = cacheRootOverride ?? join5(homedir5(), ".claudish");
1314
+ return join5(root, "cache", "1password", WASM_FILENAME);
1199
1315
  }
1200
1316
  function verifyIntegrity(bytes) {
1201
1317
  const [algo, expected] = SDK_CORE_INTEGRITY.split("-", 2);
@@ -1236,7 +1352,7 @@ function installReadFileSyncIntercept() {
1236
1352
  }
1237
1353
  if (existsSync3(path)) {
1238
1354
  try {
1239
- mkdirSync3(dirname2(cached), { recursive: true });
1355
+ mkdirSync4(dirname3(cached), { recursive: true });
1240
1356
  copyFileSync(path, cached);
1241
1357
  } catch {}
1242
1358
  }
@@ -1259,7 +1375,7 @@ async function downloadAndCacheWasm() {
1259
1375
  if (!wasm) {
1260
1376
  throw new Error(`1Password runtime archive did not contain ${WASM_TARBALL_ENTRY}`);
1261
1377
  }
1262
- mkdirSync3(dirname2(cached), { recursive: true });
1378
+ mkdirSync4(dirname3(cached), { recursive: true });
1263
1379
  const tmp = `${cached}.tmp`;
1264
1380
  writeFileSync4(tmp, wasm);
1265
1381
  createRequire(import.meta.url)("node:fs").renameSync(tmp, cached);
@@ -1292,7 +1408,7 @@ function resolveNearbyWasmPath() {
1292
1408
  try {
1293
1409
  const require2 = createRequire(import.meta.url);
1294
1410
  const coreJs = require2.resolve("@1password/sdk-core/nodejs/core.js");
1295
- const wasm = join4(dirname2(coreJs), WASM_FILENAME);
1411
+ const wasm = join5(dirname3(coreJs), WASM_FILENAME);
1296
1412
  return existsSync3(wasm) ? wasm : null;
1297
1413
  } catch {
1298
1414
  return null;
@@ -1304,7 +1420,7 @@ function seedCacheFromNearbyWasm() {
1304
1420
  return false;
1305
1421
  try {
1306
1422
  const cached = cacheWasmPath();
1307
- mkdirSync3(dirname2(cached), { recursive: true });
1423
+ mkdirSync4(dirname3(cached), { recursive: true });
1308
1424
  copyFileSync(real, cached);
1309
1425
  return true;
1310
1426
  } catch {
@@ -3658,6 +3774,7 @@ __export(exports_onepassword, {
3658
3774
  valueTail: () => valueTail,
3659
3775
  setScreenLockProbe: () => setScreenLockProbe,
3660
3776
  setLockRetryTiming: () => setLockRetryTiming,
3777
+ setAppLockProbe: () => setAppLockProbe,
3661
3778
  resolveSecretsPartial: () => resolveSecretsPartial,
3662
3779
  resolveSecrets: () => resolveSecrets,
3663
3780
  resolveSdkAuth: () => resolveSdkAuth,
@@ -3682,6 +3799,7 @@ __export(exports_onepassword, {
3682
3799
  isOpHydratedVar: () => isOpHydratedVar,
3683
3800
  isLockedDenial: () => isLockedDenial,
3684
3801
  isGlobImport: () => isGlobImport,
3802
+ isAppLocked: () => isAppLocked,
3685
3803
  globToRegExp: () => globToRegExp,
3686
3804
  getOpFailures: () => getOpFailures,
3687
3805
  filterGlobFields: () => filterGlobFields,
@@ -3692,8 +3810,12 @@ __export(exports_onepassword, {
3692
3810
  defaultSdkClientFactory: () => defaultSdkClientFactory,
3693
3811
  defaultScreenLockProbe: () => defaultScreenLockProbe,
3694
3812
  defaultOpAccountLister: () => defaultOpAccountLister,
3813
+ defaultAppLockProbe: () => defaultAppLockProbe,
3814
+ currentLockCause: () => currentLockCause,
3695
3815
  collectConfigImports: () => collectConfigImports,
3816
+ classifyLockedDenial: () => classifyLockedDenial,
3696
3817
  buildAuthError: () => buildAuthError,
3818
+ appLockedFromSettings: () => appLockedFromSettings,
3697
3819
  acquireSdkClient: () => acquireSdkClient,
3698
3820
  OP_REF_RE: () => OP_REF_RE
3699
3821
  });
@@ -3735,11 +3857,24 @@ function renderOpFailureNotice(envVar) {
3735
3857
  }
3736
3858
  lines.push("");
3737
3859
  if (wasOpAuthorizationDenied()) {
3738
- lines.push(" The 1Password desktop app declined to release secrets. This happens when");
3739
- lines.push(" the approval prompt was dismissed, or when your Mac is locked and the");
3740
- lines.push(" prompt cannot be shown at all.");
3741
- lines.push("");
3742
- lines.push(" Fix: unlock the Mac, approve the 1Password prompt, and re-run.");
3860
+ const cause = currentLockCause();
3861
+ if (cause === "screen") {
3862
+ lines.push(" Your Mac is locked, so the 1Password approval prompt cannot be shown.");
3863
+ lines.push("");
3864
+ lines.push(" Fix: unlock the Mac, approve the prompt, and re-run.");
3865
+ } else if (cause === "app") {
3866
+ lines.push(" The 1Password app is LOCKED. With shared lock state (the default) a locked");
3867
+ lines.push(" app refuses the SDK outright \u2014 no approval prompt is ever shown, which is");
3868
+ lines.push(" why nothing appeared on screen.");
3869
+ lines.push("");
3870
+ lines.push(" Fix: unlock 1Password (Touch ID is enough) and re-run.");
3871
+ lines.push(" To stop it re-locking mid-session, raise Settings \u2192 Security \u2192 auto-lock.");
3872
+ } else {
3873
+ lines.push(" The 1Password desktop app declined to release secrets. The approval prompt");
3874
+ lines.push(" was most likely dismissed.");
3875
+ lines.push("");
3876
+ lines.push(" Fix: re-run and approve the 1Password prompt.");
3877
+ }
3743
3878
  lines.push(" Headless (no desktop app): export OP_SERVICE_ACCOUNT_TOKEN='ops_...'");
3744
3879
  } else {
3745
3880
  lines.push(" Fix: check the reference resolves \u2014 claudish config \u2192 1Password tab.");
@@ -4092,25 +4227,57 @@ function setScreenLockProbe(probe) {
4092
4227
  function isScreenLocked() {
4093
4228
  return screenLockProbe();
4094
4229
  }
4095
- function isLockedDenial(err, env = process.env) {
4230
+ function appLockedFromSettings(settings, nowSeconds) {
4231
+ if (typeof settings !== "object" || settings === null)
4232
+ return false;
4233
+ const s = settings;
4234
+ if (s["developers.sdkSharedLockState.enabled"] !== true)
4235
+ return false;
4236
+ const last = s["security.authenticatedUnlock.deviceBasedUnlock.lastUnlock"];
4237
+ const after = s["security.authenticatedUnlock.deviceBasedUnlock.askUnlockAfter"];
4238
+ if (typeof last !== "number" || typeof after !== "number")
4239
+ return false;
4240
+ return nowSeconds - last > after;
4241
+ }
4242
+ function setAppLockProbe(probe) {
4243
+ appLockProbe = probe ?? defaultAppLockProbe;
4244
+ }
4245
+ function isAppLocked() {
4246
+ return appLockProbe();
4247
+ }
4248
+ function currentLockCause() {
4249
+ if (isScreenLocked())
4250
+ return "screen";
4251
+ if (isAppLocked())
4252
+ return "app";
4253
+ return null;
4254
+ }
4255
+ function classifyLockedDenial(err, env = process.env) {
4096
4256
  const msg = (err instanceof Error ? err.message : String(err)).toLowerCase();
4097
4257
  if (!msg.includes("denied authorization"))
4098
- return false;
4258
+ return null;
4099
4259
  if (env.OP_SERVICE_ACCOUNT_TOKEN)
4100
- return false;
4101
- return isScreenLocked();
4260
+ return null;
4261
+ return currentLockCause();
4102
4262
  }
4103
- async function countdownForUnlock(round, rounds) {
4263
+ function isLockedDenial(err, env = process.env) {
4264
+ return classifyLockedDenial(err, env) !== null;
4265
+ }
4266
+ async function countdownForUnlock(round, rounds, cause) {
4104
4267
  const ttyOut = process.stderr.isTTY === true;
4105
4268
  const ttyIn = process.stdin.isTTY === true;
4106
4269
  let cancelled = false;
4107
4270
  if (round === 1) {
4271
+ const explain = cause === "screen" ? `${bold("\uD83D\uDD10 1Password needs your OK \u2014 but your Mac is locked, so it can't ask.")}
4272
+ Unlock your Mac and approve the popup. Claudish picks it up from there.` : `${bold("\uD83D\uDD10 1Password is locked, so it turned claudish away without asking you.")}
4273
+ Unlock 1Password (Touch ID is enough). Claudish retries on its own \u2014
4274
+ no popup will appear until it's unlocked.`;
4108
4275
  process.stderr.write(`
4109
- ${bold("\uD83D\uDD10 1Password needs your OK \u2014 but your Mac is locked, so it can't ask.")}
4110
- Unlock your Mac and approve the popup. Claudish picks it up from there.
4276
+ ${explain}
4111
4277
 
4112
4278
  `);
4113
4279
  }
4280
+ const stillLocked = () => cause === "screen" ? isScreenLocked() : isAppLocked();
4114
4281
  let restoreInput = () => {};
4115
4282
  if (ttyIn) {
4116
4283
  const onKey = (buf) => {
@@ -4141,7 +4308,7 @@ ${bold("\uD83D\uDD10 1Password needs your OK \u2014 but your Mac is locked, so i
4141
4308
  for (let remaining = lockRetrySeconds;remaining > 0; remaining--) {
4142
4309
  if (cancelled)
4143
4310
  break;
4144
- if (!isScreenLocked())
4311
+ if (!stillLocked())
4145
4312
  break;
4146
4313
  if (ttyOut)
4147
4314
  process.stderr.write(`\r\x1B[2K${line(remaining)}`);
@@ -4164,9 +4331,10 @@ async function withSdkRetry(op, label = "op:sdk-op") {
4164
4331
  try {
4165
4332
  return await withSdkTransientRetry(op, label);
4166
4333
  } catch (err) {
4167
- if (round > LOCK_RETRY_ROUNDS || !isLockedDenial(err))
4334
+ const cause = classifyLockedDenial(err);
4335
+ if (round > LOCK_RETRY_ROUNDS || cause === null)
4168
4336
  throw err;
4169
- if (await countdownForUnlock(round, LOCK_RETRY_ROUNDS) === "cancel")
4337
+ if (await countdownForUnlock(round, LOCK_RETRY_ROUNDS, cause) === "cancel")
4170
4338
  throw err;
4171
4339
  resetSdkClientCache();
4172
4340
  }
@@ -4359,11 +4527,12 @@ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache
4359
4527
  await ensureOpWasmAvailable2();
4360
4528
  return Promise.resolve().then(() => __toESM(require_sdk(), 1));
4361
4529
  });
4362
- const client = await traceSpan("op:client-handshake", () => createClient({
4530
+ const build2 = () => createClient({
4363
4531
  auth: auth.kind === "token" ? auth.token : new DesktopAuth(auth.accountName),
4364
4532
  integrationName: "claudish",
4365
4533
  integrationVersion: VERSION || "1.0.0"
4366
- }), { mayIncludeUserPrompt: true, authKind: auth.kind });
4534
+ });
4535
+ const client = await traceSpan("op:client-handshake", () => auth.kind === "token" ? build2() : withHandshakeLock(build2), { mayIncludeUserPrompt: true, authKind: auth.kind });
4367
4536
  return client;
4368
4537
  })();
4369
4538
  sdkClientCache.set(key, build);
@@ -4383,7 +4552,7 @@ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache
4383
4552
  } catch {
4384
4553
  return false;
4385
4554
  }
4386
- }, screenLockProbe, defaultOpAccountLister = () => {
4555
+ }, screenLockProbe, defaultAppLockProbe = () => false, appLockProbe, defaultOpAccountLister = () => {
4387
4556
  try {
4388
4557
  const res = spawnSync("op", ["account", "list", "--format=json"], { encoding: "utf-8" });
4389
4558
  if (res.error || res.status !== 0)
@@ -4412,6 +4581,7 @@ var OP_REF_RE, opHydratedVars, opSourceFailures, ENV_VAR_NAME_RE, sdkClientCache
4412
4581
  };
4413
4582
  var init_onepassword = __esm(() => {
4414
4583
  init_startup_trace();
4584
+ init_onepassword_handshake_lock();
4415
4585
  OP_REF_RE = /^op:\/\/[^\s]+$/;
4416
4586
  opHydratedVars = new Set;
4417
4587
  opSourceFailures = [];
@@ -4420,18 +4590,34 @@ var init_onepassword = __esm(() => {
4420
4590
  sdkQueue = Promise.resolve();
4421
4591
  lockRetrySeconds = LOCK_RETRY_SECONDS;
4422
4592
  screenLockProbe = defaultScreenLockProbe;
4593
+ appLockProbe = defaultAppLockProbe;
4423
4594
  });
4424
4595
 
4425
4596
  // src/auth/credentials/op-source.ts
4426
- import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
4427
- import { homedir as homedir5 } from "os";
4428
- import { join as join5 } from "path";
4597
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
4598
+ import { homedir as homedir6 } from "os";
4599
+ import { join as join6 } from "path";
4429
4600
  function warnOnce(message) {
4430
4601
  if (warnedMessages.has(message))
4431
4602
  return;
4432
4603
  warnedMessages.add(message);
4433
4604
  console.error(message);
4434
4605
  }
4606
+ function recordOpUnavailableVars(names) {
4607
+ for (const n of names) {
4608
+ if (typeof n === "string" && n.length > 0)
4609
+ opUnavailableVars.add(n);
4610
+ }
4611
+ }
4612
+ function getOpUnavailableVars() {
4613
+ return [...opUnavailableVars].sort();
4614
+ }
4615
+ function inheritedUnavailable() {
4616
+ const raw = process.env[OP_UNAVAILABLE_ENV];
4617
+ if (!raw)
4618
+ return new Set;
4619
+ return new Set(raw.split(",").map((s) => s.trim()).filter((s) => s.length > 0));
4620
+ }
4435
4621
  function saveAccount(accountUrl, scope) {
4436
4622
  try {
4437
4623
  saveOnepasswordAccount(accountUrl, scope);
@@ -4517,10 +4703,10 @@ function readConfigRaw() {
4517
4703
  if (testSeams?.config)
4518
4704
  return testSeams.config;
4519
4705
  try {
4520
- const configPath = activeGlobalConfigFile(join5(homedir5(), ".claudish", "config.json"));
4706
+ const configPath = activeGlobalConfigFile(join6(homedir6(), ".claudish", "config.json"));
4521
4707
  if (!existsSync4(configPath))
4522
4708
  return {};
4523
- return JSON.parse(readFileSync3(configPath, "utf-8"));
4709
+ return JSON.parse(readFileSync4(configPath, "utf-8"));
4524
4710
  } catch {
4525
4711
  return {};
4526
4712
  }
@@ -4623,12 +4809,12 @@ async function resolveGlobShared(globPath, auth) {
4623
4809
  return { resolved: await existing, cacheHit: true };
4624
4810
  const spanName = `op:glob-resolve(${maskGlobForTrace(globPath)})`;
4625
4811
  const promise = (async () => {
4626
- const { resolveGlobImportAll: resolveGlobImportAll2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4627
- const resolved = await traceSpan(spanName, () => resolveGlobImportAll2(globPath, {
4812
+ const { resolveGlobImportAll: resolveGlobImportAll2, recordOpHydratedVars: recordOpHydratedVars2, withSdkRetry: withSdkRetry2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4813
+ const resolved = await traceSpan(spanName, () => withSdkRetry2(() => resolveGlobImportAll2(globPath, {
4628
4814
  auth,
4629
4815
  sdkFactory: testSeams?.sdkFactory,
4630
4816
  warn: (m) => console.error(m)
4631
- }));
4817
+ }), spanName));
4632
4818
  addSpanMeta(spanName, { vars: Object.keys(resolved).length });
4633
4819
  for (const [k, v] of Object.entries(resolved)) {
4634
4820
  resolvedCache.set(k, v);
@@ -4650,8 +4836,8 @@ async function resolveEnvironmentShared(envId, auth) {
4650
4836
  return { resolved: await existing, cacheHit: true };
4651
4837
  const spanName = `op:env-resolve(${envId})`;
4652
4838
  const promise = (async () => {
4653
- const { readEnvironment: readEnvironment2, recordOpHydratedVars: recordOpHydratedVars2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4654
- const resolved = await traceSpan(spanName, () => readEnvironment2(envId, { auth, sdkFactory: testSeams?.sdkFactory }));
4839
+ const { readEnvironment: readEnvironment2, recordOpHydratedVars: recordOpHydratedVars2, withSdkRetry: withSdkRetry2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4840
+ const resolved = await traceSpan(spanName, () => withSdkRetry2(() => readEnvironment2(envId, { auth, sdkFactory: testSeams?.sdkFactory }), spanName));
4655
4841
  addSpanMeta(spanName, { vars: Object.keys(resolved).length });
4656
4842
  for (const [k, v] of Object.entries(resolved)) {
4657
4843
  resolvedCache.set(k, v);
@@ -4686,6 +4872,8 @@ async function resolveOpKeyForEnvVars(wanted, opts = {}) {
4686
4872
  else
4687
4873
  stillWanted.add(w);
4688
4874
  }
4875
+ for (const skip of inheritedUnavailable())
4876
+ stillWanted.delete(skip);
4689
4877
  if (stillWanted.size === 0)
4690
4878
  return cached;
4691
4879
  const label = `op:resolve(${[...stillWanted].sort().join(",")})`;
@@ -4712,6 +4900,7 @@ async function resolveOpKeyForEnvVars(wanted, opts = {}) {
4712
4900
  resolvedCache.set(k, v);
4713
4901
  out[k] = v;
4714
4902
  }
4903
+ recordOpUnavailableVars([...wantNow].filter((w) => !(w in resolved)));
4715
4904
  return out;
4716
4905
  }, label);
4717
4906
  }
@@ -4738,7 +4927,13 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4738
4927
  throw err;
4739
4928
  }
4740
4929
  }
4741
- const { collectConfigImports: collectConfigImports2, resolveSecrets: resolveSecrets2, recordOpHydratedVars: recordOpHydratedVars2, recordOpFailure: recordOpFailure2 } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4930
+ const {
4931
+ collectConfigImports: collectConfigImports2,
4932
+ resolveSecrets: resolveSecrets2,
4933
+ recordOpHydratedVars: recordOpHydratedVars2,
4934
+ recordOpFailure: recordOpFailure2,
4935
+ withSdkRetry: withSdkRetry2
4936
+ } = await Promise.resolve().then(() => (init_onepassword(), exports_onepassword));
4742
4937
  const cfg = readConfigRaw();
4743
4938
  const out = {};
4744
4939
  try {
@@ -4751,10 +4946,7 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4751
4946
  wantedRefs[envVar] = ref;
4752
4947
  }
4753
4948
  if (Object.keys(wantedRefs).length > 0) {
4754
- const resolved = await resolveSecrets2(wantedRefs, {
4755
- auth,
4756
- sdkFactory: testSeams?.sdkFactory
4757
- });
4949
+ const resolved = await withSdkRetry2(() => resolveSecrets2(wantedRefs, { auth, sdkFactory: testSeams?.sdkFactory }), "op:resolve-refs");
4758
4950
  Object.assign(out, resolved);
4759
4951
  }
4760
4952
  const stillWanted = new Set([...wanted].filter((w) => !(w in out)));
@@ -4791,10 +4983,7 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4791
4983
  customRefs[envVar] = apiKey;
4792
4984
  }
4793
4985
  if (Object.keys(customRefs).length > 0) {
4794
- const resolved = await resolveSecrets2(customRefs, {
4795
- auth,
4796
- sdkFactory: testSeams?.sdkFactory
4797
- });
4986
+ const resolved = await withSdkRetry2(() => resolveSecrets2(customRefs, { auth, sdkFactory: testSeams?.sdkFactory }), "op:resolve-custom-endpoint-refs");
4798
4987
  Object.assign(out, resolved);
4799
4988
  }
4800
4989
  }
@@ -4837,11 +5026,12 @@ async function resolveOpKeyForEnvVarsInner(wanted, opts = {}, span) {
4837
5026
  recordOpHydratedVars2(Object.keys(out));
4838
5027
  return out;
4839
5028
  }
4840
- var warnedMessages, OpAuthError, cachedSdkAuth, sdkAuthResolved = false, authInFlight, testSeams, sniffed, opQueue, resolvedCache, globResolutions, globResolvedVars, environmentResolutions;
5029
+ var warnedMessages, opUnavailableVars, OP_UNAVAILABLE_ENV = "CLAUDISH_OP_UNAVAILABLE", OpAuthError, cachedSdkAuth, sdkAuthResolved = false, authInFlight, testSeams, sniffed, opQueue, resolvedCache, globResolutions, globResolvedVars, environmentResolutions;
4841
5030
  var init_op_source = __esm(() => {
4842
5031
  init_onepassword_config();
4843
5032
  init_startup_trace();
4844
5033
  warnedMessages = new Set;
5034
+ opUnavailableVars = new Set;
4845
5035
  OpAuthError = class OpAuthError extends Error {
4846
5036
  constructor(message) {
4847
5037
  super(message);
@@ -26938,15 +27128,15 @@ __export(exports_profile_config, {
26938
27128
  configExists: () => configExists,
26939
27129
  activeConfigFile: () => activeConfigFile
26940
27130
  });
26941
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
26942
- import { homedir as homedir6 } from "os";
26943
- import { dirname as dirname3, join as join6, parse as parse6 } from "path";
27131
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
27132
+ import { homedir as homedir7 } from "os";
27133
+ import { dirname as dirname4, join as join7, parse as parse6 } from "path";
26944
27134
  function activeConfigFile() {
26945
27135
  return activeGlobalConfigFile(CONFIG_FILE);
26946
27136
  }
26947
27137
  function ensureConfigDir() {
26948
27138
  if (!existsSync5(CONFIG_DIR)) {
26949
- mkdirSync4(CONFIG_DIR, { recursive: true });
27139
+ mkdirSync5(CONFIG_DIR, { recursive: true });
26950
27140
  }
26951
27141
  }
26952
27142
  function loadConfig() {
@@ -26957,7 +27147,7 @@ function loadConfig() {
26957
27147
  return { ...DEFAULT_CONFIG };
26958
27148
  }
26959
27149
  try {
26960
- const content = readFileSync4(activeFile, "utf-8");
27150
+ const content = readFileSync5(activeFile, "utf-8");
26961
27151
  const config2 = JSON.parse(content);
26962
27152
  const merged = {
26963
27153
  version: config2.version || DEFAULT_CONFIG.version,
@@ -27027,26 +27217,26 @@ function getConfigPath() {
27027
27217
  return CONFIG_FILE;
27028
27218
  }
27029
27219
  function getLocalConfigPath() {
27030
- const home = homedir6();
27220
+ const home = homedir7();
27031
27221
  let dir = process.cwd();
27032
27222
  const root = parse6(dir).root;
27033
27223
  while (dir !== root && dir !== home) {
27034
- const candidate = join6(dir, LOCAL_CONFIG_FILENAME);
27224
+ const candidate = join7(dir, LOCAL_CONFIG_FILENAME);
27035
27225
  if (existsSync5(candidate))
27036
27226
  return candidate;
27037
- if (existsSync5(join6(dir, ".git"))) {
27227
+ if (existsSync5(join7(dir, ".git"))) {
27038
27228
  return candidate;
27039
27229
  }
27040
- dir = dirname3(dir);
27230
+ dir = dirname4(dir);
27041
27231
  }
27042
- return join6(process.cwd(), LOCAL_CONFIG_FILENAME);
27232
+ return join7(process.cwd(), LOCAL_CONFIG_FILENAME);
27043
27233
  }
27044
27234
  function localConfigExists() {
27045
27235
  return existsSync5(getLocalConfigPath());
27046
27236
  }
27047
27237
  function isProjectDirectory() {
27048
27238
  const cwd = process.cwd();
27049
- return [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".claudish.json"].some((f) => existsSync5(join6(cwd, f)));
27239
+ return [".git", "package.json", "Cargo.toml", "go.mod", "pyproject.toml", ".claudish.json"].some((f) => existsSync5(join7(cwd, f)));
27050
27240
  }
27051
27241
  function loadLocalConfig() {
27052
27242
  if (getConfigFileOverride())
@@ -27056,7 +27246,7 @@ function loadLocalConfig() {
27056
27246
  return null;
27057
27247
  }
27058
27248
  try {
27059
- const content = readFileSync4(localPath, "utf-8");
27249
+ const content = readFileSync5(localPath, "utf-8");
27060
27250
  const config2 = JSON.parse(content);
27061
27251
  return {
27062
27252
  ...config2,
@@ -27315,8 +27505,8 @@ function disableLocalProvider(providerName) {
27315
27505
  }
27316
27506
  var CONFIG_DIR, CONFIG_FILE, LOCAL_CONFIG_FILENAME = ".claudish.json", DEFAULT_CONFIG;
27317
27507
  var init_profile_config = __esm(() => {
27318
- CONFIG_DIR = join6(homedir6(), ".claudish");
27319
- CONFIG_FILE = join6(CONFIG_DIR, "config.json");
27508
+ CONFIG_DIR = join7(homedir7(), ".claudish");
27509
+ CONFIG_FILE = join7(CONFIG_DIR, "config.json");
27320
27510
  DEFAULT_CONFIG = {
27321
27511
  version: "1.0.0",
27322
27512
  defaultProfile: "default",
@@ -28043,8 +28233,8 @@ var init_provider_definitions = __esm(() => {
28043
28233
 
28044
28234
  // src/auth/credentials/api-key-credential.ts
28045
28235
  import { existsSync as existsSync6 } from "fs";
28046
- import { homedir as homedir7 } from "os";
28047
- import { join as join7 } from "path";
28236
+ import { homedir as homedir8 } from "os";
28237
+ import { join as join8 } from "path";
28048
28238
  function realValue(v) {
28049
28239
  if (!v)
28050
28240
  return;
@@ -28086,7 +28276,7 @@ class ApiKeyCredentialProvider {
28086
28276
  if (!this.oauthFallback)
28087
28277
  return false;
28088
28278
  try {
28089
- return existsSync6(join7(homedir7(), ".claudish", this.oauthFallback));
28279
+ return existsSync6(join8(homedir8(), ".claudish", this.oauthFallback));
28090
28280
  } catch {
28091
28281
  return false;
28092
28282
  }
@@ -28162,10 +28352,10 @@ var init_api_key_credential = __esm(() => {
28162
28352
  // src/auth/codex-oauth.ts
28163
28353
  import { exec } from "child_process";
28164
28354
  import { createHash as createHash2, randomBytes } from "crypto";
28165
- import { closeSync, existsSync as existsSync7, openSync, readFileSync as readFileSync5, unlinkSync as unlinkSync2, writeSync } from "fs";
28355
+ import { closeSync as closeSync2, existsSync as existsSync7, openSync as openSync2, readFileSync as readFileSync6, unlinkSync as unlinkSync2, writeSync as writeSync2 } from "fs";
28166
28356
  import { createServer } from "http";
28167
- import { homedir as homedir8 } from "os";
28168
- import { join as join8 } from "path";
28357
+ import { homedir as homedir9 } from "os";
28358
+ import { join as join9 } from "path";
28169
28359
  import { promisify } from "util";
28170
28360
 
28171
28361
  class CodexOAuth {
@@ -28191,8 +28381,8 @@ class CodexOAuth {
28191
28381
  return this.credentials !== null && !!this.credentials.refresh_token;
28192
28382
  }
28193
28383
  getCredentialsPath() {
28194
- const claudishDir = join8(homedir8(), ".claudish");
28195
- return join8(claudishDir, "codex-oauth.json");
28384
+ const claudishDir = join9(homedir9(), ".claudish");
28385
+ return join9(claudishDir, "codex-oauth.json");
28196
28386
  }
28197
28387
  async login() {
28198
28388
  log("[CodexOAuth] Starting OAuth login flow");
@@ -28300,7 +28490,7 @@ Details: ${e.message}`);
28300
28490
  return null;
28301
28491
  }
28302
28492
  try {
28303
- const data = readFileSync5(credPath, "utf-8");
28493
+ const data = readFileSync6(credPath, "utf-8");
28304
28494
  const credentials = JSON.parse(data);
28305
28495
  if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at) {
28306
28496
  log("[CodexOAuth] Invalid credentials file structure");
@@ -28315,17 +28505,17 @@ Details: ${e.message}`);
28315
28505
  }
28316
28506
  saveCredentials(credentials) {
28317
28507
  const credPath = this.getCredentialsPath();
28318
- const claudishDir = join8(homedir8(), ".claudish");
28508
+ const claudishDir = join9(homedir9(), ".claudish");
28319
28509
  if (!existsSync7(claudishDir)) {
28320
- const { mkdirSync: mkdirSync5 } = __require("fs");
28321
- mkdirSync5(claudishDir, { recursive: true });
28510
+ const { mkdirSync: mkdirSync6 } = __require("fs");
28511
+ mkdirSync6(claudishDir, { recursive: true });
28322
28512
  }
28323
- const fd = openSync(credPath, "w", 384);
28513
+ const fd = openSync2(credPath, "w", 384);
28324
28514
  try {
28325
28515
  const data = JSON.stringify(credentials, null, 2);
28326
- writeSync(fd, data, 0, "utf-8");
28516
+ writeSync2(fd, data, 0, "utf-8");
28327
28517
  } finally {
28328
- closeSync(fd);
28518
+ closeSync2(fd);
28329
28519
  }
28330
28520
  log(`[CodexOAuth] Credentials saved to ${credPath}`);
28331
28521
  }
@@ -28626,10 +28816,10 @@ var init_codex_credential = __esm(() => {
28626
28816
  // src/auth/gemini-oauth.ts
28627
28817
  import { exec as exec2 } from "child_process";
28628
28818
  import { createHash as createHash3, randomBytes as randomBytes2 } from "crypto";
28629
- import { closeSync as closeSync2, existsSync as existsSync8, openSync as openSync2, readFileSync as readFileSync6, unlinkSync as unlinkSync3, writeSync as writeSync2 } from "fs";
28819
+ import { closeSync as closeSync3, existsSync as existsSync8, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "fs";
28630
28820
  import { createServer as createServer2 } from "http";
28631
- import { homedir as homedir9 } from "os";
28632
- import { join as join9 } from "path";
28821
+ import { homedir as homedir10 } from "os";
28822
+ import { join as join10 } from "path";
28633
28823
  import { promisify as promisify2 } from "util";
28634
28824
 
28635
28825
  class GeminiOAuth {
@@ -28655,8 +28845,8 @@ class GeminiOAuth {
28655
28845
  return this.credentials !== null && !!this.credentials.refresh_token;
28656
28846
  }
28657
28847
  getCredentialsPath() {
28658
- const claudishDir = join9(homedir9(), ".claudish");
28659
- return join9(claudishDir, "gemini-oauth.json");
28848
+ const claudishDir = join10(homedir10(), ".claudish");
28849
+ return join10(claudishDir, "gemini-oauth.json");
28660
28850
  }
28661
28851
  async login() {
28662
28852
  log("[GeminiOAuth] Starting OAuth login flow");
@@ -28758,7 +28948,7 @@ Details: ${e.message}`);
28758
28948
  return null;
28759
28949
  }
28760
28950
  try {
28761
- const data = readFileSync6(credPath, "utf-8");
28951
+ const data = readFileSync7(credPath, "utf-8");
28762
28952
  const credentials = JSON.parse(data);
28763
28953
  if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at) {
28764
28954
  log("[GeminiOAuth] Invalid credentials file structure");
@@ -28773,17 +28963,17 @@ Details: ${e.message}`);
28773
28963
  }
28774
28964
  saveCredentials(credentials) {
28775
28965
  const credPath = this.getCredentialsPath();
28776
- const claudishDir = join9(homedir9(), ".claudish");
28966
+ const claudishDir = join10(homedir10(), ".claudish");
28777
28967
  if (!existsSync8(claudishDir)) {
28778
- const { mkdirSync: mkdirSync5 } = __require("fs");
28779
- mkdirSync5(claudishDir, { recursive: true });
28968
+ const { mkdirSync: mkdirSync6 } = __require("fs");
28969
+ mkdirSync6(claudishDir, { recursive: true });
28780
28970
  }
28781
- const fd = openSync2(credPath, "w", 384);
28971
+ const fd = openSync3(credPath, "w", 384);
28782
28972
  try {
28783
28973
  const data = JSON.stringify(credentials, null, 2);
28784
- writeSync2(fd, data, 0, "utf-8");
28974
+ writeSync3(fd, data, 0, "utf-8");
28785
28975
  } finally {
28786
- closeSync2(fd);
28976
+ closeSync3(fd);
28787
28977
  }
28788
28978
  log(`[GeminiOAuth] Credentials saved to ${credPath}`);
28789
28979
  }
@@ -29137,18 +29327,18 @@ var init_gemini_oauth = __esm(() => {
29137
29327
  });
29138
29328
 
29139
29329
  // src/auth/oauth-registry.ts
29140
- import { existsSync as existsSync9, readFileSync as readFileSync7 } from "fs";
29141
- import { homedir as homedir10 } from "os";
29142
- import { join as join10 } from "path";
29330
+ import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
29331
+ import { homedir as homedir11 } from "os";
29332
+ import { join as join11 } from "path";
29143
29333
  function hasValidOAuthCredentials(descriptor) {
29144
- const credPath = join10(homedir10(), ".claudish", descriptor.credentialFile);
29334
+ const credPath = join11(homedir11(), ".claudish", descriptor.credentialFile);
29145
29335
  if (!existsSync9(credPath))
29146
29336
  return false;
29147
29337
  if (descriptor.validationMode === "file-exists") {
29148
29338
  return true;
29149
29339
  }
29150
29340
  try {
29151
- const data = JSON.parse(readFileSync7(credPath, "utf-8"));
29341
+ const data = JSON.parse(readFileSync8(credPath, "utf-8"));
29152
29342
  if (!data.access_token)
29153
29343
  return false;
29154
29344
  if (data.refresh_token)
@@ -29258,9 +29448,9 @@ var init_gemini_credential = __esm(() => {
29258
29448
  // src/auth/kimi-oauth.ts
29259
29449
  import { exec as exec3 } from "child_process";
29260
29450
  import { randomBytes as randomBytes3 } from "crypto";
29261
- import { closeSync as closeSync3, existsSync as existsSync10, openSync as openSync3, readFileSync as readFileSync8, unlinkSync as unlinkSync4, writeSync as writeSync3 } from "fs";
29262
- import { homedir as homedir11, hostname as hostname3, platform, release } from "os";
29263
- import { join as join11 } from "path";
29451
+ import { closeSync as closeSync4, existsSync as existsSync10, openSync as openSync4, readFileSync as readFileSync9, unlinkSync as unlinkSync4, writeSync as writeSync4 } from "fs";
29452
+ import { homedir as homedir12, hostname as hostname3, platform, release as release2 } from "os";
29453
+ import { join as join12 } from "path";
29264
29454
  import { promisify as promisify3 } from "util";
29265
29455
 
29266
29456
  class KimiOAuth {
@@ -29288,23 +29478,23 @@ class KimiOAuth {
29288
29478
  return this.credentials !== null && !!this.credentials.refresh_token;
29289
29479
  }
29290
29480
  getCredentialsPath() {
29291
- const claudishDir = join11(homedir11(), ".claudish");
29292
- return join11(claudishDir, "kimi-oauth.json");
29481
+ const claudishDir = join12(homedir12(), ".claudish");
29482
+ return join12(claudishDir, "kimi-oauth.json");
29293
29483
  }
29294
29484
  getDeviceIdPath() {
29295
- const claudishDir = join11(homedir11(), ".claudish");
29296
- return join11(claudishDir, "kimi-device-id");
29485
+ const claudishDir = join12(homedir12(), ".claudish");
29486
+ return join12(claudishDir, "kimi-device-id");
29297
29487
  }
29298
29488
  loadOrCreateDeviceId() {
29299
29489
  const deviceIdPath = this.getDeviceIdPath();
29300
- const claudishDir = join11(homedir11(), ".claudish");
29490
+ const claudishDir = join12(homedir12(), ".claudish");
29301
29491
  if (!existsSync10(claudishDir)) {
29302
- const { mkdirSync: mkdirSync5 } = __require("fs");
29303
- mkdirSync5(claudishDir, { recursive: true });
29492
+ const { mkdirSync: mkdirSync6 } = __require("fs");
29493
+ mkdirSync6(claudishDir, { recursive: true });
29304
29494
  }
29305
29495
  if (existsSync10(deviceIdPath)) {
29306
29496
  try {
29307
- const deviceId2 = readFileSync8(deviceIdPath, "utf-8").trim();
29497
+ const deviceId2 = readFileSync9(deviceIdPath, "utf-8").trim();
29308
29498
  if (deviceId2) {
29309
29499
  return deviceId2;
29310
29500
  }
@@ -29314,11 +29504,11 @@ class KimiOAuth {
29314
29504
  }
29315
29505
  const deviceId = randomBytes3(16).toString("hex").replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, "$1-$2-$3-$4-$5");
29316
29506
  try {
29317
- const fd = openSync3(deviceIdPath, "w", 384);
29507
+ const fd = openSync4(deviceIdPath, "w", 384);
29318
29508
  try {
29319
- writeSync3(fd, deviceId, 0, "utf-8");
29509
+ writeSync4(fd, deviceId, 0, "utf-8");
29320
29510
  } finally {
29321
- closeSync3(fd);
29511
+ closeSync4(fd);
29322
29512
  }
29323
29513
  log(`[KimiOAuth] New device ID created: ${deviceId}`);
29324
29514
  } catch (e) {
@@ -29335,7 +29525,7 @@ class KimiOAuth {
29335
29525
  "X-Msh-Version": this.getVersion(),
29336
29526
  "X-Msh-Device-Name": hostname3(),
29337
29527
  "X-Msh-Device-Model": `${platform()}-${process.arch}`,
29338
- "X-Msh-Os-Version": release(),
29528
+ "X-Msh-Os-Version": release2(),
29339
29529
  "X-Msh-Device-Id": this.deviceId
29340
29530
  };
29341
29531
  }
@@ -29563,7 +29753,7 @@ Details: ${e.message}`);
29563
29753
  return null;
29564
29754
  }
29565
29755
  try {
29566
- const data = readFileSync8(credPath, "utf-8");
29756
+ const data = readFileSync9(credPath, "utf-8");
29567
29757
  const credentials = JSON.parse(data);
29568
29758
  if (!credentials.access_token || !credentials.refresh_token || !credentials.expires_at || !credentials.scope || !credentials.token_type) {
29569
29759
  log("[KimiOAuth] Invalid credentials file structure");
@@ -29578,17 +29768,17 @@ Details: ${e.message}`);
29578
29768
  }
29579
29769
  saveCredentials(credentials) {
29580
29770
  const credPath = this.getCredentialsPath();
29581
- const claudishDir = join11(homedir11(), ".claudish");
29771
+ const claudishDir = join12(homedir12(), ".claudish");
29582
29772
  if (!existsSync10(claudishDir)) {
29583
- const { mkdirSync: mkdirSync5 } = __require("fs");
29584
- mkdirSync5(claudishDir, { recursive: true });
29773
+ const { mkdirSync: mkdirSync6 } = __require("fs");
29774
+ mkdirSync6(claudishDir, { recursive: true });
29585
29775
  }
29586
- const fd = openSync3(credPath, "w", 384);
29776
+ const fd = openSync4(credPath, "w", 384);
29587
29777
  try {
29588
29778
  const data = JSON.stringify(credentials, null, 2);
29589
- writeSync3(fd, data, 0, "utf-8");
29779
+ writeSync4(fd, data, 0, "utf-8");
29590
29780
  } finally {
29591
- closeSync3(fd);
29781
+ closeSync4(fd);
29592
29782
  }
29593
29783
  log(`[KimiOAuth] Credentials saved to ${credPath}`);
29594
29784
  }
@@ -29754,8 +29944,8 @@ var init_native_anthropic_credential = __esm(() => {
29754
29944
  // src/auth/vertex-auth.ts
29755
29945
  import { exec as exec4 } from "child_process";
29756
29946
  import { existsSync as existsSync11 } from "fs";
29757
- import { homedir as homedir12 } from "os";
29758
- import { join as join12 } from "path";
29947
+ import { homedir as homedir13 } from "os";
29948
+ import { join as join13 } from "path";
29759
29949
  import { promisify as promisify4 } from "util";
29760
29950
 
29761
29951
  class VertexAuthManager {
@@ -29810,7 +30000,7 @@ class VertexAuthManager {
29810
30000
  }
29811
30001
  async tryADC() {
29812
30002
  try {
29813
- const adcPath = join12(homedir12(), ".config/gcloud/application_default_credentials.json");
30003
+ const adcPath = join13(homedir13(), ".config/gcloud/application_default_credentials.json");
29814
30004
  if (!existsSync11(adcPath)) {
29815
30005
  log("[VertexAuth] ADC credentials file not found");
29816
30006
  return null;
@@ -29874,7 +30064,7 @@ function validateVertexOAuthConfig() {
29874
30064
  ` + ` export VERTEX_PROJECT='your-gcp-project-id'
29875
30065
  ` + " export VERTEX_LOCATION='us-central1' # optional";
29876
30066
  }
29877
- const adcPath = join12(homedir12(), ".config/gcloud/application_default_credentials.json");
30067
+ const adcPath = join13(homedir13(), ".config/gcloud/application_default_credentials.json");
29878
30068
  const hasADC = existsSync11(adcPath);
29879
30069
  const hasServiceAccount = !!process.env.GOOGLE_APPLICATION_CREDENTIALS;
29880
30070
  if (!hasADC && !hasServiceAccount) {
@@ -30422,15 +30612,15 @@ var init_routing_hints = __esm(() => {
30422
30612
  });
30423
30613
 
30424
30614
  // src/providers/all-models-cache.ts
30425
- import { existsSync as existsSync12, mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync6 } from "fs";
30426
- import { homedir as homedir13 } from "os";
30427
- import { dirname as dirname4, join as join13 } from "path";
30615
+ import { existsSync as existsSync12, mkdirSync as mkdirSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
30616
+ import { homedir as homedir14 } from "os";
30617
+ import { dirname as dirname5, join as join14 } from "path";
30428
30618
  function readAllModelsCache(path = ALL_MODELS_CACHE_PATH) {
30429
30619
  if (!existsSync12(path))
30430
30620
  return null;
30431
30621
  let raw;
30432
30622
  try {
30433
- raw = JSON.parse(readFileSync9(path, "utf-8"));
30623
+ raw = JSON.parse(readFileSync10(path, "utf-8"));
30434
30624
  } catch {
30435
30625
  return null;
30436
30626
  }
@@ -30455,12 +30645,12 @@ function writeAllModelsCache(data, path = ALL_MODELS_CACHE_PATH) {
30455
30645
  entries: data.entries ?? existing?.entries ?? [],
30456
30646
  models: data.models ?? existing?.models ?? []
30457
30647
  };
30458
- mkdirSync5(dirname4(path), { recursive: true });
30648
+ mkdirSync6(dirname5(path), { recursive: true });
30459
30649
  writeFileSync6(path, JSON.stringify(merged), "utf-8");
30460
30650
  }
30461
30651
  var ALL_MODELS_CACHE_PATH;
30462
30652
  var init_all_models_cache = __esm(() => {
30463
- ALL_MODELS_CACHE_PATH = join13(homedir13(), ".claudish", "all-models.json");
30653
+ ALL_MODELS_CACHE_PATH = join14(homedir14(), ".claudish", "all-models.json");
30464
30654
  });
30465
30655
 
30466
30656
  // src/adapters/model-catalog.ts
@@ -31287,10 +31477,21 @@ async function prehydrateCredentialsForSpawn(models) {
31287
31477
  return;
31288
31478
  try {
31289
31479
  await validateApiKeysForModels(wanted);
31480
+ publishOpSkipList();
31290
31481
  } catch {}
31291
31482
  }
31483
+ function publishOpSkipList() {
31484
+ if (getOpFailures().length > 0)
31485
+ return;
31486
+ const unavailable = getOpUnavailableVars();
31487
+ if (unavailable.length === 0)
31488
+ return;
31489
+ process.env[OP_UNAVAILABLE_ENV] = unavailable.join(",");
31490
+ }
31292
31491
  var init_prehydrate = __esm(() => {
31492
+ init_onepassword();
31293
31493
  init_provider_resolver();
31494
+ init_op_source();
31294
31495
  });
31295
31496
 
31296
31497
  // src/channel/diagnostics.ts
@@ -31545,9 +31746,9 @@ var init_signal_watcher = __esm(() => {
31545
31746
  // src/channel/session-manager.ts
31546
31747
  import { spawn } from "child_process";
31547
31748
  import { randomUUID as randomUUID2 } from "crypto";
31548
- import { createWriteStream, mkdirSync as mkdirSync6, writeFileSync as writeFileSync7 } from "fs";
31549
- import { homedir as homedir14 } from "os";
31550
- import { join as join14 } from "path";
31749
+ import { createWriteStream, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7 } from "fs";
31750
+ import { homedir as homedir15 } from "os";
31751
+ import { join as join15 } from "path";
31551
31752
 
31552
31753
  class SessionManager {
31553
31754
  sessions = new Map;
@@ -31567,10 +31768,10 @@ class SessionManager {
31567
31768
  const sessionId = randomUUID2().slice(0, 8);
31568
31769
  const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
31569
31770
  const startedAt = new Date().toISOString();
31570
- const sessionDir = join14(homedir14(), ".claudish", "sessions", sessionId);
31571
- mkdirSync6(sessionDir, { recursive: true });
31771
+ const sessionDir = join15(homedir15(), ".claudish", "sessions", sessionId);
31772
+ mkdirSync7(sessionDir, { recursive: true });
31572
31773
  if (opts.prompt) {
31573
- writeFileSync7(join14(sessionDir, "prompt.md"), opts.prompt, "utf-8");
31774
+ writeFileSync7(join15(sessionDir, "prompt.md"), opts.prompt, "utf-8");
31574
31775
  }
31575
31776
  const args = ["--model", opts.model, "-y", "--stdin", "--quiet", ...opts.claudishFlags ?? []];
31576
31777
  const proc = spawn("claudish", args, {
@@ -31597,7 +31798,7 @@ class SessionManager {
31597
31798
  });
31598
31799
  }
31599
31800
  });
31600
- const outputLogStream = createWriteStream(join14(sessionDir, "output.log"));
31801
+ const outputLogStream = createWriteStream(join15(sessionDir, "output.log"));
31601
31802
  const entry = {
31602
31803
  info: {
31603
31804
  sessionId,
@@ -31644,9 +31845,9 @@ class SessionManager {
31644
31845
  watcher.processExited(code);
31645
31846
  outputLogStream.end();
31646
31847
  if (entry.stderr) {
31647
- writeFileSync7(join14(sessionDir, "stderr.log"), entry.stderr, "utf-8");
31848
+ writeFileSync7(join15(sessionDir, "stderr.log"), entry.stderr, "utf-8");
31648
31849
  }
31649
- writeFileSync7(join14(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
31850
+ writeFileSync7(join15(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
31650
31851
  this.cleanupSigint();
31651
31852
  });
31652
31853
  proc.on("error", (err) => {
@@ -31819,9 +32020,9 @@ var init_cache_ttl = __esm(() => {
31819
32020
  });
31820
32021
 
31821
32022
  // src/model-loader.ts
31822
- import { existsSync as existsSync13, mkdirSync as mkdirSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync8 } from "fs";
31823
- import { homedir as homedir15 } from "os";
31824
- import { join as join15 } from "path";
32023
+ import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
32024
+ import { homedir as homedir16 } from "os";
32025
+ import { join as join16 } from "path";
31825
32026
  function groupRecommendedModels(entries) {
31826
32027
  const byId = new Map;
31827
32028
  for (const entry of entries) {
@@ -31919,7 +32120,7 @@ async function getRecommendedModels(opts = {}) {
31919
32120
  }
31920
32121
  if (!forceRefresh && existsSync13(RECOMMENDED_MODELS_CACHE_PATH)) {
31921
32122
  try {
31922
- const cacheData = JSON.parse(readFileSync10(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
32123
+ const cacheData = JSON.parse(readFileSync11(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
31923
32124
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
31924
32125
  _cachedRecommendedModels = cacheData;
31925
32126
  return cacheData;
@@ -31935,8 +32136,8 @@ async function getRecommendedModels(opts = {}) {
31935
32136
  if (data.models && data.models.length > 0) {
31936
32137
  _cachedRecommendedModels = data;
31937
32138
  try {
31938
- const cacheDir = join15(homedir15(), ".claudish");
31939
- mkdirSync7(cacheDir, { recursive: true });
32139
+ const cacheDir = join16(homedir16(), ".claudish");
32140
+ mkdirSync8(cacheDir, { recursive: true });
31940
32141
  writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
31941
32142
  } catch {}
31942
32143
  return data;
@@ -31950,7 +32151,7 @@ function getRecommendedModelsSync() {
31950
32151
  return _cachedRecommendedModels;
31951
32152
  if (existsSync13(RECOMMENDED_MODELS_CACHE_PATH)) {
31952
32153
  try {
31953
- const cacheData = JSON.parse(readFileSync10(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
32154
+ const cacheData = JSON.parse(readFileSync11(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
31954
32155
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
31955
32156
  _cachedRecommendedModels = cacheData;
31956
32157
  return cacheData;
@@ -32074,7 +32275,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
32074
32275
  var init_model_loader = __esm(() => {
32075
32276
  init_cache_ttl();
32076
32277
  FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
32077
- RECOMMENDED_MODELS_CACHE_PATH = join15(homedir15(), ".claudish", "recommended-models-cache.json");
32278
+ RECOMMENDED_MODELS_CACHE_PATH = join16(homedir16(), ".claudish", "recommended-models-cache.json");
32078
32279
  FIREBASE_SLUG_TO_PROVIDER_NAME = {
32079
32280
  openai: "openai",
32080
32281
  google: "google",
@@ -32122,6 +32323,44 @@ async function isPortAvailable(port) {
32122
32323
  }
32123
32324
  var init_port_manager = () => {};
32124
32325
 
32326
+ // src/redact.ts
32327
+ function isPlaceholder(value) {
32328
+ return PLACEHOLDER.test(value.trim());
32329
+ }
32330
+ function redactSecrets(text) {
32331
+ if (!text)
32332
+ return "";
32333
+ let out = text;
32334
+ out = out.replace(ASSIGNMENT_RE, (match, lhs, value) => isPlaceholder(value) ? match : `${lhs}${MASK}`);
32335
+ for (const { re } of TOKEN_PATTERNS) {
32336
+ out = out.replace(re, (match) => {
32337
+ const scheme = /^(Bearer|Basic|Token)\s/.exec(match);
32338
+ return scheme ? `${scheme[1]} ${MASK}` : MASK;
32339
+ });
32340
+ }
32341
+ return out;
32342
+ }
32343
+ function sanitizeForReport(text) {
32344
+ if (!text)
32345
+ return "";
32346
+ return redactSecrets(text).replace(/\/Users\/[^/\s]+/g, "/Users/***").replace(/\/home\/[^/\s]+/g, "/home/***").replace(/[A-Z]:\\Users\\[^\\\s]+/gi, "C:\\Users\\***").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, "***@***.***");
32347
+ }
32348
+ var MASK = "***REDACTED***", PLACEHOLDER, ASSIGNMENT_RE, TOKEN_PATTERNS;
32349
+ var init_redact = __esm(() => {
32350
+ PLACEHOLDER = /^(['"`]?)(your[-_a-z0-9]*|<[^>]*>|\.\.\.|x{3,}|\*{3,}|REDACTED|CHANGEME|TODO|\$\{[^}]*\}|)(['"`]?)$/i;
32351
+ ASSIGNMENT_RE = /(["']?\b[A-Z][A-Z0-9_]*(?:_API_KEY|_KEY|_TOKEN|_SECRET|_PASSWORD)\b["']?\s*[:=]\s*)(["'`]?\$\{[^}]*\}["'`]?|["'`]?[^\s"'`,}]+["'`]?)/g;
32352
+ TOKEN_PATTERNS = [
32353
+ { name: "sk", re: /\bsk-[A-Za-z0-9_-]{16,}/g },
32354
+ { name: "google", re: /\bAIza[A-Za-z0-9_-]{20,}/g },
32355
+ { name: "xai", re: /\bxai-[A-Za-z0-9_-]{16,}/g },
32356
+ { name: "github", re: /\bgh[posur]_[A-Za-z0-9]{20,}/g },
32357
+ { name: "aws", re: /\bAKIA[0-9A-Z]{12,}/g },
32358
+ { name: "jwt", re: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g },
32359
+ { name: "zhipu", re: /\b[0-9a-f]{32}\.[A-Za-z0-9]{16}\b/g },
32360
+ { name: "bearer", re: /\b(?:Bearer|Basic|Token)\s+[A-Za-z0-9_.\-+/=]{12,}/g }
32361
+ ];
32362
+ });
32363
+
32125
32364
  // ../../node_modules/.bun/hono@4.10.6/node_modules/hono/dist/compose.js
32126
32365
  var compose = (middleware, onError, onNotFound) => {
32127
32366
  return (context, next) => {
@@ -34115,9 +34354,12 @@ function transformOpenAIToClaude(claudeRequestInput) {
34115
34354
  var init_transform = () => {};
34116
34355
 
34117
34356
  // src/handlers/shared/format/openai-tools.ts
34357
+ function emptyParamsSchema() {
34358
+ return { type: "object", properties: {} };
34359
+ }
34118
34360
  function sanitizeSchemaForOpenAI(schema) {
34119
34361
  if (!schema || typeof schema !== "object") {
34120
- return removeUriFormat(schema);
34362
+ return emptyParamsSchema();
34121
34363
  }
34122
34364
  let root = { ...schema };
34123
34365
  const combinerKey = ["oneOf", "anyOf", "allOf"].find((k) => Array.isArray(root[k]) && root[k].length > 0);
@@ -34159,8 +34401,8 @@ function summarizeToolDescription(name, description) {
34159
34401
  return firstSentence;
34160
34402
  }
34161
34403
  function summarizeToolParameters(schema) {
34162
- if (!schema)
34163
- return schema;
34404
+ if (!schema || typeof schema !== "object")
34405
+ return emptyParamsSchema();
34164
34406
  const summarized = sanitizeSchemaForOpenAI({ ...schema });
34165
34407
  if (summarized.properties) {
34166
34408
  for (const prop of Object.values(summarized.properties)) {
@@ -35122,7 +35364,21 @@ function createStreamingState() {
35122
35364
  accumulatedText: ""
35123
35365
  };
35124
35366
  }
35125
- function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens) {
35367
+ function createStreamingResponseHandler(c, response, adapter, target, middlewareManager, onTokenUpdate, toolSchemas, toolNameMap, priorInputTokens, behavior) {
35368
+ const repairArgs = (toolName, argsJson) => {
35369
+ if (!behavior?.onToolCall)
35370
+ return argsJson;
35371
+ try {
35372
+ const repaired = behavior.onToolCall(toolName, argsJson);
35373
+ if (typeof repaired === "string" && repaired !== argsJson) {
35374
+ log(`[Streaming] tool call repaired by behavior layer: ${toolName}`);
35375
+ return repaired;
35376
+ }
35377
+ } catch (err) {
35378
+ log(`[Streaming] behavior onToolCall threw for ${toolName}: ${err}`);
35379
+ }
35380
+ return argsJson;
35381
+ };
35126
35382
  log(`[Streaming] ===== HANDLER STARTED for ${target} =====`);
35127
35383
  let isClosed = false;
35128
35384
  let ping = null;
@@ -35187,7 +35443,10 @@ data: ${JSON.stringify(d)}
35187
35443
  send("content_block_delta", {
35188
35444
  type: "content_block_delta",
35189
35445
  index: toolIdx,
35190
- delta: { type: "input_json_delta", partial_json: JSON.stringify(tc.arguments) }
35446
+ delta: {
35447
+ type: "input_json_delta",
35448
+ partial_json: repairArgs(tc.name, JSON.stringify(tc.arguments))
35449
+ }
35191
35450
  });
35192
35451
  send("content_block_stop", { type: "content_block_stop", index: toolIdx });
35193
35452
  }
@@ -35203,7 +35462,7 @@ data: ${JSON.stringify(d)}
35203
35462
  if (toolSchemas && toolSchemas.length > 0) {
35204
35463
  const validation = validateToolArguments(t.name, t.arguments, toolSchemas, state.accumulatedText);
35205
35464
  if (validation.valid || validation.repaired && validation.repairedArgs) {
35206
- const argsJson = JSON.stringify(validation.repaired ? validation.repairedArgs : validation.parsedArgs);
35465
+ const argsJson = repairArgs(t.name, JSON.stringify(validation.repaired ? validation.repairedArgs : validation.parsedArgs));
35207
35466
  log(`[Streaming] Sending buffered tool call (finish_reason!=tool_calls): ${t.name} with args: ${argsJson}`);
35208
35467
  send("content_block_start", {
35209
35468
  type: "content_block_start",
@@ -35226,7 +35485,7 @@ data: ${JSON.stringify(d)}
35226
35485
  t.closed = true;
35227
35486
  }
35228
35487
  } else {
35229
- const argsJson = t.arguments || "{}";
35488
+ const argsJson = repairArgs(t.name, t.arguments || "{}");
35230
35489
  log(`[Streaming] Sending buffered tool call (no validation): ${t.name} with args: ${argsJson}`);
35231
35490
  send("content_block_start", {
35232
35491
  type: "content_block_start",
@@ -35423,7 +35682,7 @@ data: ${JSON.stringify(d)}
35423
35682
  started: false,
35424
35683
  closed: false,
35425
35684
  arguments: "",
35426
- buffered: !!toolSchemas && toolSchemas.length > 0
35685
+ buffered: !!toolSchemas && toolSchemas.length > 0 || behavior?.shouldBufferTool?.(restoredName) === true
35427
35686
  };
35428
35687
  state.tools.set(idx, t);
35429
35688
  if (isWebSearchToolCall(restoredName)) {
@@ -35462,7 +35721,7 @@ data: ${JSON.stringify(d)}
35462
35721
  const validation = validateToolArguments(t.name, t.arguments, toolSchemas, state.accumulatedText);
35463
35722
  if (validation.repaired && validation.repairedArgs) {
35464
35723
  log(`[Streaming] Tool call ${t.name} was repaired with inferred parameters`);
35465
- const repairedJson = JSON.stringify(validation.repairedArgs);
35724
+ const repairedJson = repairArgs(t.name, JSON.stringify(validation.repairedArgs));
35466
35725
  log(`[Streaming] Sending repaired tool call: ${t.name} with args: ${repairedJson}`);
35467
35726
  if (t.buffered && !t.started) {
35468
35727
  send("content_block_start", {
@@ -35538,7 +35797,7 @@ data: ${JSON.stringify(d)}
35538
35797
  continue;
35539
35798
  }
35540
35799
  if (t.buffered && !t.started) {
35541
- const argsJson = JSON.stringify(validation.parsedArgs);
35800
+ const argsJson = repairArgs(t.name, JSON.stringify(validation.parsedArgs));
35542
35801
  send("content_block_start", {
35543
35802
  type: "content_block_start",
35544
35803
  index: t.blockIndex,
@@ -37720,7 +37979,7 @@ var init_openai = __esm(() => {
37720
37979
  });
37721
37980
 
37722
37981
  // src/providers/catalog-query.ts
37723
- import { statSync } from "fs";
37982
+ import { statSync as statSync2 } from "fs";
37724
37983
  function project(entry) {
37725
37984
  return {
37726
37985
  modelId: entry.modelId,
@@ -37733,7 +37992,7 @@ function project(entry) {
37733
37992
  function getCachedEntries() {
37734
37993
  let mtimeMs;
37735
37994
  try {
37736
- mtimeMs = statSync(ALL_MODELS_CACHE_PATH).mtimeMs;
37995
+ mtimeMs = statSync2(ALL_MODELS_CACHE_PATH).mtimeMs;
37737
37996
  } catch {
37738
37997
  return null;
37739
37998
  }
@@ -37908,24 +38167,24 @@ var init_vision_proxy = __esm(() => {
37908
38167
  // src/stats-buffer.ts
37909
38168
  import {
37910
38169
  existsSync as existsSync14,
37911
- mkdirSync as mkdirSync8,
37912
- readFileSync as readFileSync11,
38170
+ mkdirSync as mkdirSync9,
38171
+ readFileSync as readFileSync12,
37913
38172
  renameSync,
37914
38173
  unlinkSync as unlinkSync5,
37915
38174
  writeFileSync as writeFileSync9
37916
38175
  } from "fs";
37917
- import { homedir as homedir16 } from "os";
37918
- import { join as join16 } from "path";
38176
+ import { homedir as homedir17 } from "os";
38177
+ import { join as join17 } from "path";
37919
38178
  function ensureDir() {
37920
38179
  if (!existsSync14(CLAUDISH_DIR)) {
37921
- mkdirSync8(CLAUDISH_DIR, { recursive: true });
38180
+ mkdirSync9(CLAUDISH_DIR, { recursive: true });
37922
38181
  }
37923
38182
  }
37924
38183
  function readFromDisk() {
37925
38184
  try {
37926
38185
  if (!existsSync14(BUFFER_FILE))
37927
38186
  return [];
37928
- const raw2 = readFileSync11(BUFFER_FILE, "utf-8");
38187
+ const raw2 = readFileSync12(BUFFER_FILE, "utf-8");
37929
38188
  const parsed = JSON.parse(raw2);
37930
38189
  if (!Array.isArray(parsed.events))
37931
38190
  return [];
@@ -37950,7 +38209,7 @@ function writeToDisk(events) {
37950
38209
  ensureDir();
37951
38210
  const trimmed = enforceSizeCap([...events]);
37952
38211
  const payload = { version: 1, events: trimmed };
37953
- const tmpFile = join16(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
38212
+ const tmpFile = join17(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
37954
38213
  writeFileSync9(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
37955
38214
  renameSync(tmpFile, BUFFER_FILE);
37956
38215
  memoryCache = trimmed;
@@ -38023,8 +38282,8 @@ function syncFlushOnExit() {
38023
38282
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
38024
38283
  var init_stats_buffer = __esm(() => {
38025
38284
  BUFFER_MAX_BYTES = 64 * 1024;
38026
- CLAUDISH_DIR = join16(homedir16(), ".claudish");
38027
- BUFFER_FILE = join16(CLAUDISH_DIR, "stats-buffer.json");
38285
+ CLAUDISH_DIR = join17(homedir17(), ".claudish");
38286
+ BUFFER_FILE = join17(CLAUDISH_DIR, "stats-buffer.json");
38028
38287
  process.on("exit", syncFlushOnExit);
38029
38288
  process.on("SIGTERM", () => {
38030
38289
  try {
@@ -39206,6 +39465,70 @@ var init_stream_head_sniffer = __esm(() => {
39206
39465
  });
39207
39466
 
39208
39467
  // src/handlers/shared/stream-parsers/anthropic-sse.ts
39468
+ function createToolRepairInterceptor(opts) {
39469
+ const heldTools = new Map;
39470
+ const flush = (index, stopFrame) => {
39471
+ const held = heldTools.get(index);
39472
+ if (!held)
39473
+ return stopFrame;
39474
+ heldTools.delete(index);
39475
+ let finalArgs = held.args;
39476
+ try {
39477
+ const repaired = opts.repairToolArgs?.(held.name, finalArgs);
39478
+ if (typeof repaired === "string" && repaired !== finalArgs) {
39479
+ log(`[AnthropicSSE] tool call repaired: ${held.name}`);
39480
+ finalArgs = repaired;
39481
+ }
39482
+ } catch (err) {
39483
+ log(`[AnthropicSSE] repairToolArgs threw for ${held.name}: ${err}`);
39484
+ }
39485
+ const deltaFrame = `event: content_block_delta
39486
+ data: ${JSON.stringify({
39487
+ type: "content_block_delta",
39488
+ index,
39489
+ delta: { type: "input_json_delta", partial_json: finalArgs }
39490
+ })}
39491
+
39492
+ `;
39493
+ return `${deltaFrame}${stopFrame}`;
39494
+ };
39495
+ const noteToolStart = (data) => {
39496
+ if (data.content_block?.type !== "tool_use")
39497
+ return;
39498
+ const name = data.content_block.name;
39499
+ if (typeof name !== "string")
39500
+ return;
39501
+ if (!opts.shouldBufferTool?.(name))
39502
+ return;
39503
+ heldTools.set(data.index, { name, args: "" });
39504
+ };
39505
+ const absorbFragment = (data) => {
39506
+ if (data.delta?.type !== "input_json_delta")
39507
+ return false;
39508
+ const held = heldTools.get(data.index);
39509
+ if (!held)
39510
+ return false;
39511
+ held.args += data.delta.partial_json ?? "";
39512
+ return true;
39513
+ };
39514
+ return (data, line) => {
39515
+ const asIs = `${line}
39516
+ `;
39517
+ if (!opts.repairToolArgs || !opts.shouldBufferTool)
39518
+ return asIs;
39519
+ switch (data?.type) {
39520
+ case "content_block_start":
39521
+ noteToolStart(data);
39522
+ return asIs;
39523
+ case "content_block_delta":
39524
+ return absorbFragment(data) ? null : asIs;
39525
+ case "content_block_stop":
39526
+ return heldTools.has(data.index) ? flush(data.index, asIs) : asIs;
39527
+ default:
39528
+ return asIs;
39529
+ }
39530
+ };
39531
+ }
39209
39532
  function createAnthropicPassthroughStream(c, response, opts) {
39210
39533
  const encoder = new TextEncoder;
39211
39534
  const decoder = new TextDecoder;
@@ -39213,6 +39536,14 @@ function createAnthropicPassthroughStream(c, response, opts) {
39213
39536
  let lastActivity = Date.now();
39214
39537
  let pingInterval = null;
39215
39538
  const filterThinking = opts.adapter?.shouldFilterThinking() ?? false;
39539
+ const interceptToolFrame = createToolRepairInterceptor(opts);
39540
+ const enqueueData = (controller, data, line) => {
39541
+ if (isClosed)
39542
+ return;
39543
+ const out = interceptToolFrame(data, line);
39544
+ if (out !== null)
39545
+ controller.enqueue(encoder.encode(out));
39546
+ };
39216
39547
  return c.body(new ReadableStream({
39217
39548
  async start(controller) {
39218
39549
  const sendPing = () => {
@@ -39295,10 +39626,7 @@ data: ${JSON.stringify({
39295
39626
  `));
39296
39627
  }
39297
39628
  } else {
39298
- if (!isClosed) {
39299
- controller.enqueue(encoder.encode(`${line}
39300
- `));
39301
- }
39629
+ enqueueData(controller, data, line);
39302
39630
  }
39303
39631
  } catch {
39304
39632
  if (!isClosed) {
@@ -39330,10 +39658,7 @@ data: ${JSON.stringify({
39330
39658
  }
39331
39659
  return;
39332
39660
  }
39333
- if (!isClosed) {
39334
- controller.enqueue(encoder.encode(`${line}
39335
- `));
39336
- }
39661
+ enqueueData(controller, data, line);
39337
39662
  if (data.message?.usage) {
39338
39663
  inputTokens = data.message.usage.input_tokens || inputTokens;
39339
39664
  outputTokens = data.message.usage.output_tokens || outputTokens;
@@ -39628,7 +39953,18 @@ data: ${JSON.stringify(data)}
39628
39953
  const toolIdx = toolCalls.size;
39629
39954
  const toolId = `toolu_${Date.now()}_${toolIdx}`;
39630
39955
  const blockIndex = curIdx++;
39631
- const args = JSON.stringify(part.functionCall.args || {});
39956
+ let args = JSON.stringify(part.functionCall.args || {});
39957
+ if (opts.repairToolArgs) {
39958
+ try {
39959
+ const repaired = opts.repairToolArgs(part.functionCall.name, args);
39960
+ if (typeof repaired === "string" && repaired !== args) {
39961
+ log(`[GeminiSSE] tool call repaired: ${part.functionCall.name}`);
39962
+ args = repaired;
39963
+ }
39964
+ } catch (err) {
39965
+ log(`[GeminiSSE] repairToolArgs threw for ${part.functionCall.name}: ${err}`);
39966
+ }
39967
+ }
39632
39968
  const t = {
39633
39969
  id: toolId,
39634
39970
  name: part.functionCall.name,
@@ -40227,9 +40563,9 @@ var init_openai_responses_sse = __esm(() => {
40227
40563
  });
40228
40564
 
40229
40565
  // src/handlers/shared/token-tracker.ts
40230
- import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync10 } from "fs";
40231
- import { homedir as homedir17 } from "os";
40232
- import { join as join17 } from "path";
40566
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
40567
+ import { homedir as homedir18 } from "os";
40568
+ import { dirname as dirname6, join as join18 } from "path";
40233
40569
 
40234
40570
  class TokenTracker {
40235
40571
  port;
@@ -40372,9 +40708,10 @@ class TokenTracker {
40372
40708
  if (this.quotaRemaining !== undefined) {
40373
40709
  data.quota_remaining = this.quotaRemaining;
40374
40710
  }
40375
- const claudishDir = join17(homedir17(), ".claudish");
40376
- mkdirSync9(claudishDir, { recursive: true });
40377
- writeFileSync10(join17(claudishDir, `tokens-${this.port}.json`), JSON.stringify(data), "utf-8");
40711
+ const override = process.env.CLAUDISH_TOKEN_FILE;
40712
+ const outPath = override || join18(homedir18(), ".claudish", `tokens-${this.port}.json`);
40713
+ mkdirSync10(dirname6(outPath), { recursive: true });
40714
+ writeFileSync10(outPath, JSON.stringify(data), "utf-8");
40378
40715
  } catch (e) {
40379
40716
  log(`[TokenTracker] Error writing token file: ${e}`);
40380
40717
  }
@@ -40960,7 +41297,10 @@ class ComposedHandler {
40960
41297
  const priorInputTokens = this.tokenTracker.getLastInputTokens();
40961
41298
  switch (streamFormat) {
40962
41299
  case "openai-sse":
40963
- return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens);
41300
+ return createStreamingResponseHandler(c, response, adapter, this.bareModelName, this.middlewareManager, onTokenUpdate, claudeRequest.tools, toolNameMap, priorInputTokens, behaviorSession && {
41301
+ shouldBufferTool: (name) => behaviorSession.interceptsTool(name),
41302
+ onToolCall: (name, argsJson) => behaviorSession.repairToolCall(name, argsJson)
41303
+ });
40964
41304
  case "openai-responses-sse":
40965
41305
  return createResponsesStreamHandler(c, response, {
40966
41306
  modelName: this.bareModelName,
@@ -40977,7 +41317,9 @@ class ComposedHandler {
40977
41317
  return createAnthropicPassthroughStream(c, response, {
40978
41318
  modelName: this.bareModelName,
40979
41319
  onTokenUpdate,
40980
- adapter
41320
+ adapter,
41321
+ shouldBufferTool: (name) => behaviorSession?.interceptsTool(name) ?? false,
41322
+ repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null
40981
41323
  });
40982
41324
  case "gemini-sse": {
40983
41325
  const onToolCall = (toolId, name, thoughtSignature) => {
@@ -40991,6 +41333,7 @@ class ComposedHandler {
40991
41333
  middlewareManager: this.middlewareManager,
40992
41334
  onTokenUpdate,
40993
41335
  onToolCall,
41336
+ repairToolArgs: (name, argsJson) => behaviorSession?.repairToolCall(name, argsJson) ?? null,
40994
41337
  unwrapResponse: this.options.unwrapGeminiResponse,
40995
41338
  priorInputTokens
40996
41339
  });
@@ -42871,11 +43214,11 @@ var init_ollama_api_format = __esm(() => {
42871
43214
  });
42872
43215
 
42873
43216
  // src/providers/api-key-provenance.ts
42874
- import { existsSync as existsSync15, readFileSync as readFileSync12 } from "fs";
42875
- import { homedir as homedir18 } from "os";
42876
- import { join as join18, resolve as resolve2 } from "path";
43217
+ import { existsSync as existsSync15, readFileSync as readFileSync13 } from "fs";
43218
+ import { homedir as homedir19 } from "os";
43219
+ import { join as join19, resolve as resolve2 } from "path";
42877
43220
  function activeConfigPath() {
42878
- return activeGlobalConfigFile(join18(homedir18(), ".claudish", "config.json"));
43221
+ return activeGlobalConfigFile(join19(homedir19(), ".claudish", "config.json"));
42879
43222
  }
42880
43223
  function configLayerLabel() {
42881
43224
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -42954,7 +43297,7 @@ function readDotenvKey(envVars) {
42954
43297
  const dotenvPath = resolve2(".env");
42955
43298
  if (!existsSync15(dotenvPath))
42956
43299
  return null;
42957
- const parsed = import_dotenv.parse(readFileSync12(dotenvPath, "utf-8"));
43300
+ const parsed = import_dotenv.parse(readFileSync13(dotenvPath, "utf-8"));
42958
43301
  for (const v of envVars) {
42959
43302
  if (parsed[v])
42960
43303
  return parsed[v];
@@ -42969,7 +43312,7 @@ function readConfigKey(envVar) {
42969
43312
  const configPath = activeConfigPath();
42970
43313
  if (!existsSync15(configPath))
42971
43314
  return null;
42972
- const cfg = JSON.parse(readFileSync12(configPath, "utf-8"));
43315
+ const cfg = JSON.parse(readFileSync13(configPath, "utf-8"));
42973
43316
  return cfg.apiKeys?.[envVar] || null;
42974
43317
  } catch {
42975
43318
  return null;
@@ -44527,9 +44870,9 @@ var init_poe = __esm(() => {
44527
44870
  });
44528
44871
 
44529
44872
  // src/services/pricing-cache.ts
44530
- import { existsSync as existsSync16, readFileSync as readFileSync13, statSync as statSync2 } from "fs";
44531
- import { homedir as homedir19 } from "os";
44532
- import { join as join19 } from "path";
44873
+ import { existsSync as existsSync16, readFileSync as readFileSync14, statSync as statSync3 } from "fs";
44874
+ import { homedir as homedir20 } from "os";
44875
+ import { join as join20 } from "path";
44533
44876
  function prefixMatch(modelName) {
44534
44877
  for (const [key, pricing] of pricingMap) {
44535
44878
  if (modelName.startsWith(key))
@@ -44569,10 +44912,10 @@ function loadDiskCache() {
44569
44912
  try {
44570
44913
  if (!existsSync16(CACHE_FILE))
44571
44914
  return false;
44572
- const stat = statSync2(CACHE_FILE);
44915
+ const stat = statSync3(CACHE_FILE);
44573
44916
  const age = Date.now() - stat.mtimeMs;
44574
44917
  const isFresh = age < CACHE_TTL_MS2;
44575
- const raw2 = readFileSync13(CACHE_FILE, "utf-8");
44918
+ const raw2 = readFileSync14(CACHE_FILE, "utf-8");
44576
44919
  const data = JSON.parse(raw2);
44577
44920
  for (const [key, pricing] of Object.entries(data)) {
44578
44921
  pricingMap.set(key, pricing);
@@ -44588,8 +44931,8 @@ var init_pricing_cache = __esm(() => {
44588
44931
  init_logger();
44589
44932
  init_catalog_query();
44590
44933
  pricingMap = new Map;
44591
- CACHE_DIR = join19(homedir19(), ".claudish");
44592
- CACHE_FILE = join19(CACHE_DIR, "pricing-cache.json");
44934
+ CACHE_DIR = join20(homedir20(), ".claudish");
44935
+ CACHE_FILE = join20(CACHE_DIR, "pricing-cache.json");
44593
44936
  CACHE_TTL_MS2 = 24 * 60 * 60 * 1000;
44594
44937
  });
44595
44938
 
@@ -45045,6 +45388,175 @@ var init_proxy_server = __esm(() => {
45045
45388
  };
45046
45389
  });
45047
45390
 
45391
+ // src/team-stats.ts
45392
+ import { existsSync as existsSync17, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "fs";
45393
+ import { join as join21 } from "path";
45394
+ function statsDir(sessionPath) {
45395
+ return join21(sessionPath, "stats");
45396
+ }
45397
+ function tokenFileFor(sessionPath, anonId) {
45398
+ return join21(statsDir(sessionPath), `${anonId}.json`);
45399
+ }
45400
+ function readTokenStats(sessionPath, anonId) {
45401
+ const path = tokenFileFor(sessionPath, anonId);
45402
+ if (!existsSync17(path))
45403
+ return null;
45404
+ try {
45405
+ return JSON.parse(readFileSync15(path, "utf-8"));
45406
+ } catch {
45407
+ return null;
45408
+ }
45409
+ }
45410
+ function fmtTokens(n) {
45411
+ if (!n || n <= 0)
45412
+ return "0";
45413
+ if (n < 1000)
45414
+ return String(n);
45415
+ if (n < 1e6)
45416
+ return `${(n / 1000).toFixed(1)}k`;
45417
+ return `${(n / 1e6).toFixed(1)}M`;
45418
+ }
45419
+ function fmtCost(cost, isFree) {
45420
+ if (isFree)
45421
+ return "free";
45422
+ if (cost === undefined || cost <= 0)
45423
+ return "$0";
45424
+ return `$${cost.toFixed(3)}`;
45425
+ }
45426
+ function fmtBytes(n) {
45427
+ if (n <= 0)
45428
+ return "0B";
45429
+ if (n < 1024)
45430
+ return `${n}B`;
45431
+ if (n < 1024 * 1024)
45432
+ return `${(n / 1024).toFixed(1)}KB`;
45433
+ return `${(n / (1024 * 1024)).toFixed(1)}MB`;
45434
+ }
45435
+ function fmtState(state) {
45436
+ switch (state) {
45437
+ case "COMPLETED":
45438
+ return "done";
45439
+ case "RUNNING":
45440
+ return "run ";
45441
+ case "FAILED":
45442
+ return "FAIL";
45443
+ case "TIMEOUT":
45444
+ return "TIME";
45445
+ case "EMPTY":
45446
+ return "EMPT";
45447
+ case "PENDING":
45448
+ return "wait";
45449
+ default:
45450
+ return "? ";
45451
+ }
45452
+ }
45453
+ function renderTeamStats(sessionPath, manifest, status, opts) {
45454
+ const nameWidth = opts.modelNameWidth ?? 18;
45455
+ const ids = Object.keys(manifest.models).sort();
45456
+ let done = 0;
45457
+ let running = 0;
45458
+ let failed = 0;
45459
+ let totalTokens = 0;
45460
+ let totalCost = 0;
45461
+ let anyFree = false;
45462
+ const rows = [];
45463
+ for (const id of ids) {
45464
+ const m = status.models[id];
45465
+ if (!m)
45466
+ continue;
45467
+ const model = manifest.models[id]?.model ?? "unknown";
45468
+ const stats = readTokenStats(sessionPath, id);
45469
+ if (m.state === "COMPLETED")
45470
+ done++;
45471
+ else if (m.state === "RUNNING" || m.state === "PENDING")
45472
+ running++;
45473
+ else
45474
+ failed++;
45475
+ const inTok = stats?.input_tokens ?? 0;
45476
+ const outTok = stats?.output_tokens ?? 0;
45477
+ totalTokens += stats?.total_tokens ?? inTok + outTok;
45478
+ totalCost += stats?.total_cost ?? 0;
45479
+ if (stats?.is_free)
45480
+ anyFree = true;
45481
+ const name = model.length > nameWidth ? `${model.slice(0, nameWidth - 1)}\u2026` : model;
45482
+ const bytes = m.outputSize > 0 ? fmtBytes(m.outputSize) : "";
45483
+ const tokens = stats ? `${fmtTokens(inTok)}/${outTok > 0 ? fmtTokens(outTok) : "-"}` : "";
45484
+ const cost = stats ? fmtCost(stats.total_cost, stats.is_free) : "";
45485
+ rows.push(` ${id} ${name.padEnd(nameWidth)} ${fmtState(m.state)} ` + `${bytes.padStart(7)} ${tokens.padStart(12)} ${cost.padStart(7)}`.trimEnd());
45486
+ }
45487
+ const parts = [`${ids.length} models`];
45488
+ if (done)
45489
+ parts.push(`${done} done`);
45490
+ if (running)
45491
+ parts.push(`${running} running`);
45492
+ if (failed)
45493
+ parts.push(`${failed} failed`);
45494
+ parts.push(`${Math.round(opts.elapsedSeconds)}s`);
45495
+ if (totalTokens > 0)
45496
+ parts.push(`${fmtTokens(totalTokens)} tok`);
45497
+ if (totalCost > 0 || anyFree)
45498
+ parts.push(fmtCost(totalCost, anyFree && totalCost === 0));
45499
+ return [`team: ${parts.join(", ")}`, ...rows].join(`
45500
+ `);
45501
+ }
45502
+ function renderTeamStatsCompact(sessionPath, manifest, status, opts) {
45503
+ const ids = Object.keys(manifest.models).sort();
45504
+ let done = 0;
45505
+ let running = 0;
45506
+ let failed = 0;
45507
+ let totalTokens = 0;
45508
+ let totalCost = 0;
45509
+ const segs = [];
45510
+ for (const id of ids) {
45511
+ const m = status.models[id];
45512
+ if (!m)
45513
+ continue;
45514
+ const model = manifest.models[id]?.model ?? "unknown";
45515
+ const stats = readTokenStats(sessionPath, id);
45516
+ if (m.state === "COMPLETED")
45517
+ done++;
45518
+ else if (m.state === "RUNNING" || m.state === "PENDING")
45519
+ running++;
45520
+ else
45521
+ failed++;
45522
+ totalTokens += stats?.total_tokens ?? 0;
45523
+ totalCost += stats?.total_cost ?? 0;
45524
+ const bits = [id, model, fmtState(m.state).trim()];
45525
+ if (m.outputSize > 0)
45526
+ bits.push(fmtBytes(m.outputSize));
45527
+ else if (stats?.total_tokens)
45528
+ bits.push(`${fmtTokens(stats.total_tokens)} tok`);
45529
+ segs.push(bits.join(" "));
45530
+ }
45531
+ const counts = [];
45532
+ if (done)
45533
+ counts.push(`${done} done`);
45534
+ if (running)
45535
+ counts.push(`${running} run`);
45536
+ if (failed)
45537
+ counts.push(`${failed} fail`);
45538
+ const head = [`team ${ids.length}: ${counts.join(" ") || "starting"}`];
45539
+ head.push(`${Math.round(opts.elapsedSeconds)}s`);
45540
+ if (totalTokens > 0)
45541
+ head.push(`${fmtTokens(totalTokens)} tok`);
45542
+ if (totalCost > 0)
45543
+ head.push(fmtCost(totalCost));
45544
+ let line1 = head.join(" \xB7 ");
45545
+ if (line1.length > CHANNEL_LINE_BUDGET) {
45546
+ line1 = line1.replace(/^team \d+: /, `t${ids.length}: `);
45547
+ }
45548
+ return `${line1}
45549
+ ${segs.join(" \xB7 ")}`;
45550
+ }
45551
+ function writeStatusFile(sessionPath, manifest, status, opts) {
45552
+ try {
45553
+ writeFileSync11(join21(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
45554
+ `, "utf-8");
45555
+ } catch {}
45556
+ }
45557
+ var CHANNEL_LINE_BUDGET = 58;
45558
+ var init_team_stats = () => {};
45559
+
45048
45560
  // src/team-orchestrator.ts
45049
45561
  var exports_team_orchestrator = {};
45050
45562
  __export(exports_team_orchestrator, {
@@ -45055,19 +45567,62 @@ __export(exports_team_orchestrator, {
45055
45567
  judgeResponses: () => judgeResponses,
45056
45568
  getStatus: () => getStatus,
45057
45569
  fisherYatesShuffle: () => fisherYatesShuffle,
45570
+ classifyRunOutput: () => classifyRunOutput,
45058
45571
  buildJudgePrompt: () => buildJudgePrompt,
45059
- aggregateVerdict: () => aggregateVerdict
45572
+ aggregateVerdict: () => aggregateVerdict,
45573
+ STDOUT_TAIL_LIMIT: () => STDOUT_TAIL_LIMIT,
45574
+ DEFAULT_MIN_OUTPUT_BYTES: () => DEFAULT_MIN_OUTPUT_BYTES
45060
45575
  });
45061
45576
  import { spawn as spawn2 } from "child_process";
45062
45577
  import {
45063
45578
  createWriteStream as createWriteStream2,
45064
- existsSync as existsSync17,
45065
- mkdirSync as mkdirSync10,
45066
- readFileSync as readFileSync14,
45579
+ existsSync as existsSync18,
45580
+ mkdirSync as mkdirSync11,
45581
+ readFileSync as readFileSync16,
45067
45582
  readdirSync as readdirSync2,
45068
- writeFileSync as writeFileSync11
45583
+ writeFileSync as writeFileSync12
45069
45584
  } from "fs";
45070
- import { join as join20, resolve as resolve3 } from "path";
45585
+ import { join as join22, resolve as resolve3 } from "path";
45586
+ function classifyRunOutput(opts) {
45587
+ const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
45588
+ const apiError = API_ERROR_RE.exec(stdoutTail);
45589
+ if (apiError) {
45590
+ return {
45591
+ reason: "api_error",
45592
+ detail: `Child exited 0 but stdout carries an API error: ${apiError[1]?.trim() || "unknown"}`
45593
+ };
45594
+ }
45595
+ const bgCeiling = BG_CEILING_RE.exec(stderr);
45596
+ if (bgCeiling) {
45597
+ return {
45598
+ reason: "background_task_ceiling",
45599
+ detail: `Claude Code terminated the turn after ${bgCeiling[1]}s waiting on background tasks, ` + `flushing only partial output. Set CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0 in the child ` + `environment to wait indefinitely, or tell the model not to spawn background work.`
45600
+ };
45601
+ }
45602
+ const tailIsWholeOutput = outputSize <= STDOUT_TAIL_LIMIT;
45603
+ if (outputSize === 0 || tailIsWholeOutput && stdoutTail.trim().length === 0) {
45604
+ return {
45605
+ reason: "empty_output",
45606
+ detail: `Child exited 0 but produced no non-whitespace output (${outputSize} B).`
45607
+ };
45608
+ }
45609
+ if (minOutputBytes > 0 && outputSize < minOutputBytes) {
45610
+ return {
45611
+ reason: "empty_output",
45612
+ detail: `Child exited 0 but produced only ${outputSize} B of stdout ` + `(caller required at least ${minOutputBytes} B).`
45613
+ };
45614
+ }
45615
+ return null;
45616
+ }
45617
+ function persistErrorLog(errorLogPath, header, stderr, stdoutTail) {
45618
+ const parts = [`=== ${redactSecrets(header)} ===`, ""];
45619
+ parts.push("--- stderr ---", stderr.trim() ? redactSecrets(stderr) : "(empty)", "");
45620
+ parts.push("--- stdout (tail) ---", stdoutTail.trim() ? redactSecrets(stdoutTail) : "(empty)", "");
45621
+ try {
45622
+ writeFileSync12(errorLogPath, parts.join(`
45623
+ `), "utf-8");
45624
+ } catch {}
45625
+ }
45071
45626
  function validateSessionPath(sessionPath) {
45072
45627
  const resolved = resolve3(sessionPath);
45073
45628
  const cwd = process.cwd();
@@ -45088,18 +45643,18 @@ function setupSession(sessionPath, models, input) {
45088
45643
  if (models.length === 0) {
45089
45644
  throw new Error("At least one model is required");
45090
45645
  }
45091
- if (existsSync17(join20(sessionPath, "manifest.json"))) {
45646
+ if (existsSync18(join22(sessionPath, "manifest.json"))) {
45092
45647
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
45093
45648
  }
45094
45649
  const sentinels = models.filter(isSentinelModel);
45095
45650
  if (sentinels.length > 0) {
45096
45651
  throw new Error(`Invalid model(s) for team run: ${sentinels.join(", ")}. These are Claude Code agent selectors, not external model IDs. Use real external models (e.g., "gemini-2.0-flash", "gpt-4o", "or@deepseek/deepseek-r1"). For Claude models, use a Task agent instead of the team tool.`);
45097
45652
  }
45098
- mkdirSync10(join20(sessionPath, "work"), { recursive: true });
45099
- mkdirSync10(join20(sessionPath, "errors"), { recursive: true });
45653
+ mkdirSync11(join22(sessionPath, "work"), { recursive: true });
45654
+ mkdirSync11(join22(sessionPath, "errors"), { recursive: true });
45100
45655
  if (input !== undefined) {
45101
- writeFileSync11(join20(sessionPath, "input.md"), input, "utf-8");
45102
- } else if (!existsSync17(join20(sessionPath, "input.md"))) {
45656
+ writeFileSync12(join22(sessionPath, "input.md"), input, "utf-8");
45657
+ } else if (!existsSync18(join22(sessionPath, "input.md"))) {
45103
45658
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
45104
45659
  }
45105
45660
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -45116,9 +45671,9 @@ function setupSession(sessionPath, models, input) {
45116
45671
  model: models[i],
45117
45672
  assignedAt: now
45118
45673
  };
45119
- mkdirSync10(join20(sessionPath, "work", anonId), { recursive: true });
45674
+ mkdirSync11(join22(sessionPath, "work", anonId), { recursive: true });
45120
45675
  }
45121
- writeFileSync11(join20(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
45676
+ writeFileSync12(join22(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
45122
45677
  const status = {
45123
45678
  startedAt: now,
45124
45679
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -45132,22 +45687,25 @@ function setupSession(sessionPath, models, input) {
45132
45687
  }
45133
45688
  ]))
45134
45689
  };
45135
- writeFileSync11(join20(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
45690
+ writeFileSync12(join22(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
45136
45691
  return manifest;
45137
45692
  }
45138
45693
  async function runModels(sessionPath, opts = {}) {
45139
45694
  const timeoutMs = (opts.timeout ?? 300) * 1000;
45140
- const manifest = JSON.parse(readFileSync14(join20(sessionPath, "manifest.json"), "utf-8"));
45141
- const statusPath = join20(sessionPath, "status.json");
45142
- const inputPath = join20(sessionPath, "input.md");
45143
- const inputContent = readFileSync14(inputPath, "utf-8");
45695
+ const manifest = JSON.parse(readFileSync16(join22(sessionPath, "manifest.json"), "utf-8"));
45696
+ const statusPath = join22(sessionPath, "status.json");
45697
+ const inputPath = join22(sessionPath, "input.md");
45698
+ const inputContent = readFileSync16(inputPath, "utf-8");
45144
45699
  await prehydrateCredentialsForSpawn(Object.values(manifest.models).map((m) => m.model));
45145
- const statusCache = JSON.parse(readFileSync14(statusPath, "utf-8"));
45700
+ const statusCache = JSON.parse(readFileSync16(statusPath, "utf-8"));
45146
45701
  function updateModelStatus(id, update) {
45147
45702
  statusCache.models[id] = { ...statusCache.models[id], ...update };
45148
- writeFileSync11(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
45703
+ writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
45149
45704
  }
45705
+ const minOutputBytes = opts.minOutputBytes ?? DEFAULT_MIN_OUTPUT_BYTES;
45706
+ mkdirSync11(statsDir(sessionPath), { recursive: true });
45150
45707
  const processes = new Map;
45708
+ const runtimes = new Map;
45151
45709
  const sigintHandler = () => {
45152
45710
  for (const [, proc] of processes) {
45153
45711
  if (!proc.killed)
@@ -45158,8 +45716,8 @@ async function runModels(sessionPath, opts = {}) {
45158
45716
  process.on("SIGINT", sigintHandler);
45159
45717
  const completionPromises = [];
45160
45718
  for (const [anonId, entry] of Object.entries(manifest.models)) {
45161
- const outputPath = join20(sessionPath, `response-${anonId}.md`);
45162
- const errorLogPath = join20(sessionPath, "errors", `${anonId}.log`);
45719
+ const outputPath = join22(sessionPath, `response-${anonId}.md`);
45720
+ const errorLogPath = join22(sessionPath, "errors", `${anonId}.log`);
45163
45721
  const args = ["--model", entry.model, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
45164
45722
  updateModelStatus(anonId, {
45165
45723
  state: "RUNNING",
@@ -45167,11 +45725,17 @@ async function runModels(sessionPath, opts = {}) {
45167
45725
  });
45168
45726
  const proc = spawn2("claudish", args, {
45169
45727
  stdio: ["pipe", "pipe", "pipe"],
45170
- shell: false
45728
+ shell: false,
45729
+ env: {
45730
+ ...process.env,
45731
+ CLAUDISH_TOKEN_FILE: tokenFileFor(sessionPath, anonId)
45732
+ }
45171
45733
  });
45172
45734
  let byteCount = 0;
45735
+ let stdoutTail = "";
45173
45736
  proc.stdout?.on("data", (chunk) => {
45174
45737
  byteCount += chunk.length;
45738
+ stdoutTail = (stdoutTail + chunk.toString()).slice(-STDOUT_TAIL_LIMIT);
45175
45739
  });
45176
45740
  const outputStream = createWriteStream2(outputPath);
45177
45741
  proc.stdout?.pipe(outputStream);
@@ -45179,6 +45743,14 @@ async function runModels(sessionPath, opts = {}) {
45179
45743
  proc.stderr?.on("data", (chunk) => {
45180
45744
  stderr += chunk.toString();
45181
45745
  });
45746
+ const command = `claudish ${args.join(" ")}`;
45747
+ runtimes.set(anonId, {
45748
+ command,
45749
+ errorLogPath,
45750
+ getStderr: () => stderr,
45751
+ getStdoutTail: () => stdoutTail,
45752
+ getByteCount: () => byteCount
45753
+ });
45182
45754
  proc.stdin?.write(inputContent);
45183
45755
  proc.stdin?.end();
45184
45756
  const completionPromise = new Promise((resolve4) => {
@@ -45194,20 +45766,39 @@ async function runModels(sessionPath, opts = {}) {
45194
45766
  }
45195
45767
  resolved = true;
45196
45768
  const outputSize = byteCount;
45197
- const failed = exitCode !== 0;
45198
- updateModelStatus(anonId, {
45199
- state: failed ? "FAILED" : "COMPLETED",
45200
- exitCode: exitCode ?? 1,
45201
- completedAt: new Date().toISOString(),
45202
- outputSize,
45203
- error: failed ? {
45204
- model: anonId,
45205
- command: `claudish ${args.join(" ")}`,
45206
- stderrSnippet: stderr ? stderr.slice(-2000) : undefined,
45207
- errorLogPath,
45208
- workDir: sessionPath
45209
- } : undefined
45210
- });
45769
+ const crashed = exitCode !== 0;
45770
+ const degraded = crashed ? null : classifyRunOutput({ outputSize, stdoutTail, stderr, minOutputBytes });
45771
+ const failed = crashed || degraded !== null;
45772
+ const state = crashed ? "FAILED" : degraded ? "EMPTY" : "COMPLETED";
45773
+ if (failed) {
45774
+ const reason = crashed ? "nonzero_exit" : degraded.reason;
45775
+ const detail = crashed ? `Child exited with code ${exitCode}.` : degraded.detail;
45776
+ persistErrorLog(errorLogPath, `${state}: ${detail}`, stderr, stdoutTail);
45777
+ updateModelStatus(anonId, {
45778
+ state,
45779
+ exitCode: exitCode ?? 1,
45780
+ completedAt: new Date().toISOString(),
45781
+ outputSize,
45782
+ error: {
45783
+ model: anonId,
45784
+ command,
45785
+ reason,
45786
+ detail,
45787
+ stderrSnippet: stderr ? redactSecrets(stderr).slice(-2000) : undefined,
45788
+ stdoutSnippet: stdoutTail ? redactSecrets(stdoutTail).slice(-2000) : undefined,
45789
+ errorLogPath,
45790
+ workDir: sessionPath
45791
+ }
45792
+ });
45793
+ } else {
45794
+ updateModelStatus(anonId, {
45795
+ state,
45796
+ exitCode: exitCode ?? 0,
45797
+ completedAt: new Date().toISOString(),
45798
+ outputSize,
45799
+ error: undefined
45800
+ });
45801
+ }
45211
45802
  opts.onStatusChange?.(anonId, statusCache.models[anonId]);
45212
45803
  resolve4();
45213
45804
  };
@@ -45220,7 +45811,7 @@ async function runModels(sessionPath, opts = {}) {
45220
45811
  return;
45221
45812
  }
45222
45813
  if (stderr) {
45223
- writeFileSync11(errorLogPath, stderr, "utf-8");
45814
+ writeFileSync12(errorLogPath, redactSecrets(stderr), "utf-8");
45224
45815
  }
45225
45816
  exitCode = code;
45226
45817
  if (outputStream.destroyed) {
@@ -45231,6 +45822,36 @@ async function runModels(sessionPath, opts = {}) {
45231
45822
  processes.set(anonId, proc);
45232
45823
  completionPromises.push(completionPromise);
45233
45824
  }
45825
+ const runStartedMs = Date.now();
45826
+ const POLL_MS = 2000;
45827
+ const heartbeatMs = (opts.heartbeatSeconds ?? 60) * 1000;
45828
+ let lastSignature = "";
45829
+ let lastEmitMs = 0;
45830
+ const stateSignature = () => Object.entries(statusCache.models).sort(([a], [b]) => a.localeCompare(b)).map(([id, m]) => `${id}:${m.state}:${m.outputSize}`).join("|");
45831
+ const emitProgress = (phase = "running") => {
45832
+ const elapsedSeconds = (Date.now() - runStartedMs) / 1000;
45833
+ writeStatusFile(sessionPath, manifest, statusCache, { elapsedSeconds });
45834
+ if (!opts.onProgress)
45835
+ return;
45836
+ const signature = stateSignature();
45837
+ const changed = signature !== lastSignature;
45838
+ const heartbeatDue = Date.now() - lastEmitMs >= heartbeatMs;
45839
+ if (phase !== "settled" && !changed && !heartbeatDue)
45840
+ return;
45841
+ lastSignature = signature;
45842
+ lastEmitMs = Date.now();
45843
+ try {
45844
+ const models = Object.values(statusCache.models);
45845
+ opts.onProgress({
45846
+ rendered: renderTeamStatsCompact(sessionPath, manifest, statusCache, { elapsedSeconds }),
45847
+ phase,
45848
+ allFailed: models.length > 0 && models.every((m) => m.state !== "COMPLETED")
45849
+ });
45850
+ } catch {}
45851
+ };
45852
+ emitProgress();
45853
+ const progressHandle = setInterval(() => emitProgress("running"), POLL_MS);
45854
+ progressHandle.unref?.();
45234
45855
  let timeoutHandle = null;
45235
45856
  await Promise.race([
45236
45857
  Promise.all(completionPromises),
@@ -45241,9 +45862,27 @@ async function runModels(sessionPath, opts = {}) {
45241
45862
  if (current.state === "RUNNING") {
45242
45863
  if (!proc.killed)
45243
45864
  proc.kill("SIGTERM");
45865
+ const rt = runtimes.get(id);
45866
+ const stderr = rt?.getStderr() ?? "";
45867
+ const stdoutTail = rt?.getStdoutTail() ?? "";
45868
+ const bytes = rt?.getByteCount() ?? 0;
45869
+ const detail = `Killed by the orchestrator after ${timeoutMs / 1000}s with ${bytes} B of stdout. ` + `In --quiet print mode the child emits its answer only at the end, so 0 B means ` + `"did not finish", not "produced nothing".`;
45870
+ if (rt)
45871
+ persistErrorLog(rt.errorLogPath, `TIMEOUT: ${detail}`, stderr, stdoutTail);
45244
45872
  updateModelStatus(id, {
45245
45873
  state: "TIMEOUT",
45246
- completedAt: new Date().toISOString()
45874
+ completedAt: new Date().toISOString(),
45875
+ outputSize: bytes,
45876
+ error: rt ? {
45877
+ model: id,
45878
+ command: rt.command,
45879
+ reason: "timeout",
45880
+ detail,
45881
+ stderrSnippet: stderr ? redactSecrets(stderr).slice(-2000) : undefined,
45882
+ stdoutSnippet: stdoutTail ? redactSecrets(stdoutTail).slice(-2000) : undefined,
45883
+ errorLogPath: rt.errorLogPath,
45884
+ workDir: sessionPath
45885
+ } : undefined
45247
45886
  });
45248
45887
  opts.onStatusChange?.(id, statusCache.models[id]);
45249
45888
  }
@@ -45254,6 +45893,8 @@ async function runModels(sessionPath, opts = {}) {
45254
45893
  ]);
45255
45894
  if (timeoutHandle !== null)
45256
45895
  clearTimeout(timeoutHandle);
45896
+ clearInterval(progressHandle);
45897
+ emitProgress("settled");
45257
45898
  process.off("SIGINT", sigintHandler);
45258
45899
  return statusCache;
45259
45900
  }
@@ -45265,23 +45906,23 @@ async function judgeResponses(sessionPath, opts = {}) {
45265
45906
  const responses = {};
45266
45907
  for (const file2 of responseFiles) {
45267
45908
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
45268
- responses[id] = readFileSync14(join20(sessionPath, file2), "utf-8");
45909
+ responses[id] = readFileSync16(join22(sessionPath, file2), "utf-8");
45269
45910
  }
45270
- const input = readFileSync14(join20(sessionPath, "input.md"), "utf-8");
45911
+ const input = readFileSync16(join22(sessionPath, "input.md"), "utf-8");
45271
45912
  const judgePrompt = buildJudgePrompt(input, responses);
45272
- writeFileSync11(join20(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
45913
+ writeFileSync12(join22(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
45273
45914
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
45274
- const judgePath = join20(sessionPath, "judging");
45275
- mkdirSync10(judgePath, { recursive: true });
45915
+ const judgePath = join22(sessionPath, "judging");
45916
+ mkdirSync11(judgePath, { recursive: true });
45276
45917
  setupSession(judgePath, judgeModels, judgePrompt);
45277
45918
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
45278
45919
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
45279
45920
  const verdict = aggregateVerdict(votes, Object.keys(responses));
45280
- writeFileSync11(join20(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
45921
+ writeFileSync12(join22(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
45281
45922
  return verdict;
45282
45923
  }
45283
45924
  function getStatus(sessionPath) {
45284
- return JSON.parse(readFileSync14(join20(sessionPath, "status.json"), "utf-8"));
45925
+ return JSON.parse(readFileSync16(join22(sessionPath, "status.json"), "utf-8"));
45285
45926
  }
45286
45927
  function fisherYatesShuffle(arr) {
45287
45928
  for (let i = arr.length - 1;i > 0; i--) {
@@ -45291,7 +45932,7 @@ function fisherYatesShuffle(arr) {
45291
45932
  return arr;
45292
45933
  }
45293
45934
  function getDefaultJudgeModels(sessionPath) {
45294
- const manifest = JSON.parse(readFileSync14(join20(sessionPath, "manifest.json"), "utf-8"));
45935
+ const manifest = JSON.parse(readFileSync16(join22(sessionPath, "manifest.json"), "utf-8"));
45295
45936
  return Object.values(manifest.models).map((e) => e.model);
45296
45937
  }
45297
45938
  function buildJudgePrompt(input, responses) {
@@ -45354,7 +45995,7 @@ function parseJudgeVotes(judgePath, responseIds) {
45354
45995
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
45355
45996
  let content;
45356
45997
  try {
45357
- content = readFileSync14(join20(judgePath, file2), "utf-8");
45998
+ content = readFileSync16(join22(judgePath, file2), "utf-8");
45358
45999
  } catch {
45359
46000
  continue;
45360
46001
  }
@@ -45406,7 +46047,7 @@ function aggregateVerdict(votes, responseIds) {
45406
46047
  function formatVerdict(verdict, sessionPath) {
45407
46048
  let manifest = null;
45408
46049
  try {
45409
- manifest = JSON.parse(readFileSync14(join20(sessionPath, "manifest.json"), "utf-8"));
46050
+ manifest = JSON.parse(readFileSync16(join22(sessionPath, "manifest.json"), "utf-8"));
45410
46051
  } catch {}
45411
46052
  let output = `# Team Verdict
45412
46053
 
@@ -45437,9 +46078,13 @@ function formatVerdict(verdict, sessionPath) {
45437
46078
  }
45438
46079
  return output;
45439
46080
  }
45440
- var SENTINEL_MODELS;
46081
+ var STDOUT_TAIL_LIMIT = 4000, API_ERROR_RE, BG_CEILING_RE, DEFAULT_MIN_OUTPUT_BYTES = 0, SENTINEL_MODELS;
45441
46082
  var init_team_orchestrator = __esm(() => {
45442
46083
  init_prehydrate();
46084
+ init_redact();
46085
+ init_team_stats();
46086
+ API_ERROR_RE = /\[API Error:\s*([^\]]{0,300})\]/i;
46087
+ BG_CEILING_RE = /Background tasks still running after (\d+)s; terminating/i;
45443
46088
  SENTINEL_MODELS = new Set([
45444
46089
  "internal",
45445
46090
  "default",
@@ -45454,16 +46099,17 @@ var exports_mcp_server = {};
45454
46099
  __export(exports_mcp_server, {
45455
46100
  startMcpServer: () => startMcpServer,
45456
46101
  runPromptViaProxy: () => runPromptViaProxy,
45457
- parseAnthropicSse: () => parseAnthropicSse
46102
+ parseAnthropicSse: () => parseAnthropicSse,
46103
+ formatTeamResult: () => formatTeamResult
45458
46104
  });
45459
- import { existsSync as existsSync18, mkdirSync as mkdirSync11, readFileSync as readFileSync15, readdirSync as readdirSync3, writeFileSync as writeFileSync12 } from "fs";
45460
- import { homedir as homedir20 } from "os";
45461
- import { dirname as dirname5, join as join21 } from "path";
46105
+ import { existsSync as existsSync19, mkdirSync as mkdirSync12, readFileSync as readFileSync17, readdirSync as readdirSync3, writeFileSync as writeFileSync13 } from "fs";
46106
+ import { homedir as homedir21 } from "os";
46107
+ import { dirname as dirname7, join as join23 } from "path";
45462
46108
  import { fileURLToPath } from "url";
45463
46109
  async function loadAllModels(forceRefresh = false) {
45464
- if (!forceRefresh && existsSync18(ALL_MODELS_CACHE_PATH2)) {
46110
+ if (!forceRefresh && existsSync19(ALL_MODELS_CACHE_PATH2)) {
45465
46111
  try {
45466
- const cacheData = JSON.parse(readFileSync15(ALL_MODELS_CACHE_PATH2, "utf-8"));
46112
+ const cacheData = JSON.parse(readFileSync17(ALL_MODELS_CACHE_PATH2, "utf-8"));
45467
46113
  const lastUpdated = new Date(cacheData.lastUpdated);
45468
46114
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
45469
46115
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -45477,12 +46123,12 @@ async function loadAllModels(forceRefresh = false) {
45477
46123
  throw new Error(`API returned ${response.status}`);
45478
46124
  const data = await response.json();
45479
46125
  const models = data.data || [];
45480
- mkdirSync11(CLAUDISH_CACHE_DIR, { recursive: true });
45481
- writeFileSync12(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
46126
+ mkdirSync12(CLAUDISH_CACHE_DIR, { recursive: true });
46127
+ writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
45482
46128
  return models;
45483
46129
  } catch {
45484
- if (existsSync18(ALL_MODELS_CACHE_PATH2)) {
45485
- const cacheData = JSON.parse(readFileSync15(ALL_MODELS_CACHE_PATH2, "utf-8"));
46130
+ if (existsSync19(ALL_MODELS_CACHE_PATH2)) {
46131
+ const cacheData = JSON.parse(readFileSync17(ALL_MODELS_CACHE_PATH2, "utf-8"));
45486
46132
  return cacheData.models || [];
45487
46133
  }
45488
46134
  return [];
@@ -45578,63 +46224,53 @@ function fuzzyScore(text, query) {
45578
46224
  }
45579
46225
  return queryIndex === lowerQuery.length ? score / lowerText.length : 0;
45580
46226
  }
46227
+ function fmtSize(n) {
46228
+ if (n <= 0)
46229
+ return "0B";
46230
+ if (n < 1024)
46231
+ return `${n}B`;
46232
+ if (n < 1024 * 1024)
46233
+ return `${(n / 1024).toFixed(1)}KB`;
46234
+ return `${(n / (1024 * 1024)).toFixed(1)}MB`;
46235
+ }
45581
46236
  function formatTeamResult(status, sessionPath) {
45582
- const entries = Object.entries(status.models);
45583
- const failed = entries.filter(([, m]) => m.state === "FAILED" || m.state === "TIMEOUT");
46237
+ const entries = Object.entries(status.models).sort(([a], [b]) => a.localeCompare(b));
46238
+ const failed = entries.filter(([, m]) => m.state === "FAILED" || m.state === "TIMEOUT" || m.state === "EMPTY");
45584
46239
  const succeeded = entries.filter(([, m]) => m.state === "COMPLETED");
45585
- let result = JSON.stringify(status, null, 2);
46240
+ const lines = [];
46241
+ lines.push(`<<<TEAM_RESULT path="${sessionPath}">>>`);
46242
+ lines.push(`status: ${failed.length === 0 ? "ok" : succeeded.length === 0 ? "all-failed" : "partial"}` + ` \u2014 ${succeeded.length}/${entries.length} succeeded`);
46243
+ if (succeeded.length > 0) {
46244
+ lines.push("succeeded:");
46245
+ for (const [id, m] of succeeded) {
46246
+ lines.push(` ${id} ${fmtSize(m.outputSize)} response-${id}.md`);
46247
+ }
46248
+ }
45586
46249
  if (failed.length > 0) {
45587
- result += `
45588
-
45589
- ---
45590
- ## Failures Detected
45591
-
45592
- `;
45593
- result += `${succeeded.length}/${entries.length} models succeeded, ${failed.length} failed.
45594
-
45595
- `;
46250
+ lines.push("failures:");
45596
46251
  for (const [id, m] of failed) {
45597
- result += `### Model ${id}: ${m.state}
45598
- `;
45599
- if (m.error) {
45600
- result += `- **Model:** ${m.error.model}
45601
- `;
45602
- result += `- **Command:** \`${m.error.command}\`
45603
- `;
45604
- result += `- **Exit code:** ${m.exitCode}
45605
- `;
45606
- if (m.error.stderrSnippet) {
45607
- result += `- **Error output:**
45608
- \`\`\`
45609
- ${m.error.stderrSnippet}
45610
- \`\`\`
45611
- `;
45612
- }
45613
- result += `- **Full error log:** ${m.error.errorLogPath}
45614
- `;
45615
- result += `- **Working directory:** ${m.error.workDir}
45616
- `;
46252
+ const reason = m.error?.reason ?? "unknown";
46253
+ const next = NEXT_STEP[reason] ?? "read the evidence log";
46254
+ lines.push(` ${id} ${m.state} reason=${reason}`);
46255
+ if (m.error?.detail)
46256
+ lines.push(` what: ${m.error.detail}`);
46257
+ lines.push(` next: ${next}`);
46258
+ if (m.error?.errorLogPath) {
46259
+ lines.push(` evidence: ${m.error.errorLogPath}`);
46260
+ } else {
46261
+ lines.push(" evidence: NONE CAPTURED \u2014 orchestrator bug, report via report_error");
45617
46262
  }
45618
- result += `
45619
- `;
45620
46263
  }
45621
- result += `---
45622
- `;
45623
- result += "**To help claudish devs fix this**, use the `report_error` tool with:\n";
45624
- result += '- `error_type`: "provider_failure" or "team_failure"\n';
45625
- result += `- \`session_path\`: "${sessionPath}"
45626
- `;
45627
- result += "- Copy the stderr snippet above into `stderr_snippet`\n";
45628
- result += "- Set `auto_send: true` to suggest enabling automatic reporting\n";
46264
+ lines.push("actions:");
46265
+ lines.push(` full stderr/stdout for one failure \u2192 Read the evidence path above`);
46266
+ lines.push(` machine-readable status \u2192 team(mode="status", path="${sessionPath}")`);
46267
+ lines.push(` report a provider bug \u2192 report_error(session_path="${sessionPath}")`);
45629
46268
  }
45630
- return result;
45631
- }
45632
- function sanitize(text) {
45633
- if (!text)
45634
- return "";
45635
- return text.replace(/sk-[a-zA-Z0-9_-]{10,}/g, "sk-***REDACTED***").replace(/Bearer [a-zA-Z0-9_.-]+/g, "Bearer ***REDACTED***").replace(/\/Users\/[^/\s]+/g, "/Users/***").replace(/\/home\/[^/\s]+/g, "/home/***").replace(/[A-Z_]+_API_KEY=[^\s]+/g, "***_API_KEY=REDACTED").replace(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g, "***@***.***");
46269
+ lines.push("<<<END_TEAM_RESULT>>>");
46270
+ return lines.join(`
46271
+ `);
45636
46272
  }
45637
- function defineTools(sessionManager) {
46273
+ function defineTools(sessionManager, notifyChannel) {
45638
46274
  const tools = [];
45639
46275
  tools.push({
45640
46276
  name: "run_prompt",
@@ -45965,12 +46601,25 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
45965
46601
  const input = args.input;
45966
46602
  const timeout = args.timeout;
45967
46603
  const resolved = validateSessionPath(path);
46604
+ const teamSessionId = resolved.split("/").filter(Boolean).pop() ?? "team";
46605
+ const teamCreatedAt = new Date().toISOString();
46606
+ const runOpts = {
46607
+ timeout,
46608
+ onProgress: (u) => notifyChannel({
46609
+ content: u.rendered,
46610
+ sessionId: teamSessionId,
46611
+ event: u.phase === "settled" ? u.allFailed ? "failed" : "completed" : "running",
46612
+ model: "team",
46613
+ elapsedSeconds: (Date.now() - Date.parse(teamCreatedAt)) / 1000,
46614
+ createdAt: teamCreatedAt
46615
+ })
46616
+ };
45968
46617
  switch (mode) {
45969
46618
  case "run": {
45970
46619
  if (!models?.length)
45971
46620
  throw new Error("'models' is required for 'run' mode");
45972
46621
  setupSession(resolved, models, input);
45973
- const status = await runModels(resolved, { timeout });
46622
+ const status = await runModels(resolved, runOpts);
45974
46623
  return {
45975
46624
  content: [{ type: "text", text: formatTeamResult(status, resolved) }]
45976
46625
  };
@@ -45983,7 +46632,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
45983
46632
  if (!models?.length)
45984
46633
  throw new Error("'models' is required for 'run-and-judge' mode");
45985
46634
  setupSession(resolved, models, input);
45986
- await runModels(resolved, { timeout });
46635
+ await runModels(resolved, runOpts);
45987
46636
  const verdict = await judgeResponses(resolved, { judges });
45988
46637
  return { content: [{ type: "text", text: JSON.stringify(verdict, null, 2) }] };
45989
46638
  }
@@ -46046,7 +46695,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
46046
46695
  let stderrFull = stderr_snippet || "";
46047
46696
  if (error_log_path) {
46048
46697
  try {
46049
- stderrFull = readFileSync15(error_log_path, "utf-8");
46698
+ stderrFull = readFileSync17(error_log_path, "utf-8");
46050
46699
  } catch {}
46051
46700
  }
46052
46701
  const sessionData = {};
@@ -46054,16 +46703,16 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
46054
46703
  const sp = session_path;
46055
46704
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
46056
46705
  try {
46057
- sessionData[file2] = readFileSync15(join21(sp, file2), "utf-8");
46706
+ sessionData[file2] = readFileSync17(join23(sp, file2), "utf-8");
46058
46707
  } catch {}
46059
46708
  }
46060
46709
  try {
46061
- const errorDir = join21(sp, "errors");
46062
- if (existsSync18(errorDir)) {
46710
+ const errorDir = join23(sp, "errors");
46711
+ if (existsSync19(errorDir)) {
46063
46712
  for (const f of readdirSync3(errorDir)) {
46064
46713
  if (f.endsWith(".log")) {
46065
46714
  try {
46066
- sessionData[`errors/${f}`] = readFileSync15(join21(errorDir, f), "utf-8");
46715
+ sessionData[`errors/${f}`] = readFileSync17(join23(errorDir, f), "utf-8");
46067
46716
  } catch {}
46068
46717
  }
46069
46718
  }
@@ -46073,7 +46722,7 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
46073
46722
  for (const f of readdirSync3(sp)) {
46074
46723
  if (f.startsWith("response-") && f.endsWith(".md")) {
46075
46724
  try {
46076
- const content = readFileSync15(join21(sp, f), "utf-8");
46725
+ const content = readFileSync17(join23(sp, f), "utf-8");
46077
46726
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
46078
46727
  } catch {}
46079
46728
  }
@@ -46082,9 +46731,9 @@ Use with: run_prompt(model="${results[0].model.id}", prompt="your prompt")`;
46082
46731
  }
46083
46732
  let version2 = "unknown";
46084
46733
  try {
46085
- const pkgPath = join21(__dirname2, "../package.json");
46086
- if (existsSync18(pkgPath)) {
46087
- version2 = JSON.parse(readFileSync15(pkgPath, "utf-8")).version;
46734
+ const pkgPath = join23(__dirname2, "../package.json");
46735
+ if (existsSync19(pkgPath)) {
46736
+ version2 = JSON.parse(readFileSync17(pkgPath, "utf-8")).version;
46088
46737
  }
46089
46738
  } catch {}
46090
46739
  const report = {
@@ -46369,7 +47018,31 @@ To report this error, use the report_error tool with error_type: "provider_failu
46369
47018
  watchNotificationResult(result, { sessionId: sessionId2, eventType: event.type });
46370
47019
  })
46371
47020
  });
46372
- const allTools = defineTools(sessionManager);
47021
+ const channelEnabled = enabledGroups.has("channel");
47022
+ const notifyChannel = (p) => {
47023
+ if (!channelEnabled)
47024
+ return;
47025
+ try {
47026
+ const result = server.notification({
47027
+ method: "notifications/claude/channel",
47028
+ params: {
47029
+ content: p.content,
47030
+ meta: {
47031
+ session_id: p.sessionId,
47032
+ event: p.event,
47033
+ model: p.model,
47034
+ elapsed_seconds: String(Math.round(p.elapsedSeconds)),
47035
+ task_id: p.sessionId,
47036
+ status: mapEventToTaskStatus(p.event),
47037
+ created_at: p.createdAt,
47038
+ last_updated_at: new Date().toISOString()
47039
+ }
47040
+ }
47041
+ });
47042
+ watchNotificationResult(result, { sessionId: p.sessionId, eventType: p.event });
47043
+ } catch {}
47044
+ };
47045
+ const allTools = defineTools(sessionManager, notifyChannel);
46373
47046
  const enabledTools = allTools.filter((t) => enabledGroups.has(t.group));
46374
47047
  const toolMap = new Map(enabledTools.map((t) => [t.name, t]));
46375
47048
  console.error(`[claudish] MCP server started (tools: ${toolMode}, ${enabledTools.length} tools)`);
@@ -46440,7 +47113,7 @@ When channel mode is active, you receive <channel source="claudish" ...> notific
46440
47113
  5. Use list_sessions to see all active/completed sessions.
46441
47114
  6. Use cancel_session to stop a running session.
46442
47115
 
46443
- The session_id in the channel tag's meta attributes is the key for all tool calls.`, proxyInstance = null, proxyStarting = null, EVENT_TO_TASK_STATUS;
47116
+ The session_id in the channel tag's meta attributes is the key for all tool calls.`, proxyInstance = null, proxyStarting = null, NEXT_STEP, sanitize, EVENT_TO_TASK_STATUS;
46444
47117
  var init_mcp_server = __esm(() => {
46445
47118
  init_server2();
46446
47119
  init_stdio2();
@@ -46450,15 +47123,24 @@ var init_mcp_server = __esm(() => {
46450
47123
  init_channel();
46451
47124
  init_model_loader();
46452
47125
  init_port_manager();
47126
+ init_redact();
46453
47127
  init_provider_definitions();
46454
47128
  init_proxy_server();
46455
47129
  init_team_orchestrator();
46456
47130
  import_dotenv2 = __toESM(require_main(), 1);
46457
47131
  import_dotenv2.config({ quiet: true });
46458
47132
  __filename2 = fileURLToPath(import.meta.url);
46459
- __dirname2 = dirname5(__filename2);
46460
- CLAUDISH_CACHE_DIR = join21(homedir20(), ".claudish");
46461
- ALL_MODELS_CACHE_PATH2 = join21(CLAUDISH_CACHE_DIR, "all-models.json");
47133
+ __dirname2 = dirname7(__filename2);
47134
+ CLAUDISH_CACHE_DIR = join23(homedir21(), ".claudish");
47135
+ ALL_MODELS_CACHE_PATH2 = join23(CLAUDISH_CACHE_DIR, "all-models.json");
47136
+ NEXT_STEP = {
47137
+ nonzero_exit: "read the evidence log, then retry or drop the model",
47138
+ timeout: "raise `timeout`, or pick a faster model",
47139
+ api_error: "retry once, or route via a different provider (or@<model>)",
47140
+ background_task_ceiling: "set CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0 for children, or forbid background work in the prompt",
47141
+ empty_output: "retry once; if it repeats, drop the model"
47142
+ };
47143
+ sanitize = sanitizeForReport;
46462
47144
  EVENT_TO_TASK_STATUS = new Map([
46463
47145
  ["starting", "working"],
46464
47146
  ["running", "working"],
@@ -46475,7 +47157,7 @@ var exports_serve_command = {};
46475
47157
  __export(exports_serve_command, {
46476
47158
  serveCommand: () => serveCommand
46477
47159
  });
46478
- import { existsSync as existsSync19, readFileSync as readFileSync16 } from "fs";
47160
+ import { existsSync as existsSync20, readFileSync as readFileSync18 } from "fs";
46479
47161
  function parseServeArgs(args) {
46480
47162
  const out = {};
46481
47163
  for (let i = 0;i < args.length; i++) {
@@ -46494,12 +47176,12 @@ function parseServeArgs(args) {
46494
47176
  return out;
46495
47177
  }
46496
47178
  function loadModelMap(path) {
46497
- if (!existsSync19(path)) {
47179
+ if (!existsSync20(path)) {
46498
47180
  throw new Error(`--models file not found: ${path}`);
46499
47181
  }
46500
47182
  let raw2;
46501
47183
  try {
46502
- raw2 = readFileSync16(path, "utf-8");
47184
+ raw2 = readFileSync18(path, "utf-8");
46503
47185
  } catch (e) {
46504
47186
  throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
46505
47187
  }
@@ -57971,7 +58653,7 @@ var init_RemoveFileError = __esm(() => {
57971
58653
 
57972
58654
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
57973
58655
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
57974
- import { readFileSync as readFileSync17, unlinkSync as unlinkSync6, writeFileSync as writeFileSync13 } from "fs";
58656
+ import { readFileSync as readFileSync19, unlinkSync as unlinkSync6, writeFileSync as writeFileSync14 } from "fs";
57975
58657
  import path from "path";
57976
58658
  import os from "os";
57977
58659
  import { randomUUID as randomUUID4 } from "crypto";
@@ -58080,14 +58762,14 @@ class ExternalEditor {
58080
58762
  if (Object.prototype.hasOwnProperty.call(this.fileOptions, "mode")) {
58081
58763
  opt.mode = this.fileOptions.mode;
58082
58764
  }
58083
- writeFileSync13(this.tempFile, this.text, opt);
58765
+ writeFileSync14(this.tempFile, this.text, opt);
58084
58766
  } catch (createFileError) {
58085
58767
  throw new CreateFileError(createFileError);
58086
58768
  }
58087
58769
  }
58088
58770
  readTemporaryFile() {
58089
58771
  try {
58090
- const tempFileBuffer = readFileSync17(this.tempFile);
58772
+ const tempFileBuffer = readFileSync19(this.tempFile);
58091
58773
  if (tempFileBuffer.length === 0) {
58092
58774
  this.text = "";
58093
58775
  } else {
@@ -59282,15 +59964,15 @@ async function geminiQuotaHandler() {
59282
59964
  }
59283
59965
  }
59284
59966
  async function codexQuotaHandler() {
59285
- const { readFileSync: readFileSync18, existsSync: existsSync20 } = await import("fs");
59286
- const { join: join22 } = await import("path");
59287
- const { homedir: homedir21 } = await import("os");
59288
- const credPath = join22(homedir21(), ".claudish", "codex-oauth.json");
59289
- if (!existsSync20(credPath)) {
59967
+ const { readFileSync: readFileSync20, existsSync: existsSync21 } = await import("fs");
59968
+ const { join: join24 } = await import("path");
59969
+ const { homedir: homedir22 } = await import("os");
59970
+ const credPath = join24(homedir22(), ".claudish", "codex-oauth.json");
59971
+ if (!existsSync21(credPath)) {
59290
59972
  console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
59291
59973
  process.exit(1);
59292
59974
  }
59293
- const creds = JSON.parse(readFileSync18(credPath, "utf-8"));
59975
+ const creds = JSON.parse(readFileSync20(credPath, "utf-8"));
59294
59976
  let email3 = "";
59295
59977
  try {
59296
59978
  const parts = creds.access_token.split(".");
@@ -59342,9 +60024,9 @@ async function codexQuotaHandler() {
59342
60024
  }
59343
60025
  let modelSlugs = [];
59344
60026
  try {
59345
- const modelsPath = join22(homedir21(), ".codex", "models_cache.json");
59346
- if (existsSync20(modelsPath)) {
59347
- const cache2 = JSON.parse(readFileSync18(modelsPath, "utf-8"));
60027
+ const modelsPath = join24(homedir22(), ".codex", "models_cache.json");
60028
+ if (existsSync21(modelsPath)) {
60029
+ const cache2 = JSON.parse(readFileSync20(modelsPath, "utf-8"));
59348
60030
  modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
59349
60031
  }
59350
60032
  } catch {}
@@ -60692,19 +61374,19 @@ async function probeLink(proxyUrl, link, timeoutMs) {
60692
61374
  }
60693
61375
  const streamResult = await consumeProbeStream(response, timeoutMs, startedAt);
60694
61376
  const totalMs = Date.now() - startedAt;
60695
- let timing;
61377
+ let timing2;
60696
61378
  if (streamResult.state === "live" && streamResult.ttftMs !== undefined && !streamResult.truncated) {
60697
61379
  const ttftMs = streamResult.ttftMs;
60698
61380
  const tokens = streamResult.tokens ?? 0;
60699
61381
  const streamMs = Math.max(STREAM_MS_FLOOR, totalMs - ttftMs);
60700
61382
  const tokensPerSec = tokens > 0 ? tokens / streamMs * 1000 : 0;
60701
- timing = { ttfbMs, ttftMs, totalMs, tokens, tokensPerSec };
61383
+ timing2 = { ttfbMs, ttftMs, totalMs, tokens, tokensPerSec };
60702
61384
  }
60703
61385
  const { ttftMs: _ttft, tokens: _tok, truncated: _trunc, ...rest } = streamResult;
60704
61386
  return annotateOAuthHint({
60705
61387
  ...rest,
60706
61388
  latencyMs: totalMs,
60707
- timing
61389
+ timing: timing2
60708
61390
  }, link.provider, isOAuth);
60709
61391
  }
60710
61392
  function annotateOAuthHint(result, provider, isOAuth) {
@@ -61301,8 +61983,8 @@ function breakdownNum(ms) {
61301
61983
  return formatLatency(ms);
61302
61984
  return `${Math.round(Math.max(0, ms))}`;
61303
61985
  }
61304
- function buildBarsLine(timing, scales, isFastest, usable) {
61305
- const t = timing;
61986
+ function buildBarsLine(timing2, scales, isFastest, usable) {
61987
+ const t = timing2;
61306
61988
  const showTokBar = usable >= PRINTER_BARS_FULL_WIDTH;
61307
61989
  const showBreakdown = usable >= PRINTER_BARS_FULL_WIDTH || usable >= PRINTER_BARS_NOTOK_WIDTH;
61308
61990
  const barCells = timelineBarCells(t.totalMs, scales.maxTotalMs, PRINTER_BAR_WIDTH);
@@ -63307,22 +63989,22 @@ __export(exports_cli, {
63307
63989
  });
63308
63990
  import {
63309
63991
  copyFileSync as copyFileSync2,
63310
- existsSync as existsSync20,
63311
- mkdirSync as mkdirSync12,
63312
- readFileSync as readFileSync18,
63992
+ existsSync as existsSync21,
63993
+ mkdirSync as mkdirSync13,
63994
+ readFileSync as readFileSync20,
63313
63995
  readdirSync as readdirSync4,
63314
63996
  unlinkSync as unlinkSync7,
63315
- writeFileSync as writeFileSync14
63997
+ writeFileSync as writeFileSync15
63316
63998
  } from "fs";
63317
- import { homedir as homedir21 } from "os";
63318
- import { dirname as dirname6, join as join22 } from "path";
63999
+ import { homedir as homedir22 } from "os";
64000
+ import { dirname as dirname8, join as join24 } from "path";
63319
64001
  import { fileURLToPath as fileURLToPath2 } from "url";
63320
64002
  function getVersion3() {
63321
64003
  return VERSION;
63322
64004
  }
63323
64005
  function clearAllModelCaches() {
63324
- const cacheDir = join22(homedir21(), ".claudish");
63325
- if (!existsSync20(cacheDir))
64006
+ const cacheDir = join24(homedir22(), ".claudish");
64007
+ if (!existsSync21(cacheDir))
63326
64008
  return;
63327
64009
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
63328
64010
  let cleared = 0;
@@ -63330,7 +64012,7 @@ function clearAllModelCaches() {
63330
64012
  const files = readdirSync4(cacheDir);
63331
64013
  for (const file2 of files) {
63332
64014
  if (cachePatterns.includes(file2)) {
63333
- unlinkSync7(join22(cacheDir, file2));
64015
+ unlinkSync7(join24(cacheDir, file2));
63334
64016
  cleared++;
63335
64017
  }
63336
64018
  }
@@ -63740,15 +64422,15 @@ Usage: claudish --models --provider <slug>`);
63740
64422
  });
63741
64423
  config3.resolvedDefaultProvider = resolved;
63742
64424
  if (resolved.legacyAutoPromoted && !config3.quiet) {
63743
- const markerFile = join22(homedir21(), ".claudish", ".legacy-litellm-hint-shown");
63744
- if (!existsSync20(markerFile)) {
64425
+ const markerFile = join24(homedir22(), ".claudish", ".legacy-litellm-hint-shown");
64426
+ if (!existsSync21(markerFile)) {
63745
64427
  const hint = buildLegacyHint(resolved);
63746
64428
  if (hint) {
63747
64429
  console.error(hint);
63748
64430
  }
63749
64431
  try {
63750
- mkdirSync12(dirname6(markerFile), { recursive: true });
63751
- writeFileSync14(markerFile, new Date().toISOString(), "utf-8");
64432
+ mkdirSync13(dirname8(markerFile), { recursive: true });
64433
+ writeFileSync15(markerFile, new Date().toISOString(), "utf-8");
63752
64434
  } catch {}
63753
64435
  }
63754
64436
  }
@@ -64808,8 +65490,8 @@ ${h("MORE INFO")}
64808
65490
  }
64809
65491
  function printAIAgentGuide() {
64810
65492
  try {
64811
- const guidePath = join22(__dirname3, "../AI_AGENT_GUIDE.md");
64812
- const guideContent = readFileSync18(guidePath, "utf-8");
65493
+ const guidePath = join24(__dirname3, "../AI_AGENT_GUIDE.md");
65494
+ const guideContent = readFileSync20(guidePath, "utf-8");
64813
65495
  console.log(guideContent);
64814
65496
  } catch (error46) {
64815
65497
  console.error("Error reading AI Agent Guide:");
@@ -64825,19 +65507,19 @@ async function initializeClaudishSkill() {
64825
65507
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
64826
65508
  `);
64827
65509
  const cwd = process.cwd();
64828
- const claudeDir = join22(cwd, ".claude");
64829
- const skillsDir = join22(claudeDir, "skills");
64830
- const claudishSkillDir = join22(skillsDir, "claudish-usage");
64831
- const skillFile = join22(claudishSkillDir, "SKILL.md");
64832
- if (existsSync20(skillFile)) {
65510
+ const claudeDir = join24(cwd, ".claude");
65511
+ const skillsDir = join24(claudeDir, "skills");
65512
+ const claudishSkillDir = join24(skillsDir, "claudish-usage");
65513
+ const skillFile = join24(claudishSkillDir, "SKILL.md");
65514
+ if (existsSync21(skillFile)) {
64833
65515
  console.log("\u2705 Claudish skill already installed at:");
64834
65516
  console.log(` ${skillFile}
64835
65517
  `);
64836
65518
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
64837
65519
  return;
64838
65520
  }
64839
- const sourceSkillPath = join22(__dirname3, "../skills/claudish-usage/SKILL.md");
64840
- if (!existsSync20(sourceSkillPath)) {
65521
+ const sourceSkillPath = join24(__dirname3, "../skills/claudish-usage/SKILL.md");
65522
+ if (!existsSync21(sourceSkillPath)) {
64841
65523
  console.error("\u274C Error: Claudish skill file not found in installation.");
64842
65524
  console.error(` Expected at: ${sourceSkillPath}`);
64843
65525
  console.error(`
@@ -64846,16 +65528,16 @@ async function initializeClaudishSkill() {
64846
65528
  process.exit(1);
64847
65529
  }
64848
65530
  try {
64849
- if (!existsSync20(claudeDir)) {
64850
- mkdirSync12(claudeDir, { recursive: true });
65531
+ if (!existsSync21(claudeDir)) {
65532
+ mkdirSync13(claudeDir, { recursive: true });
64851
65533
  console.log("\uD83D\uDCC1 Created .claude/ directory");
64852
65534
  }
64853
- if (!existsSync20(skillsDir)) {
64854
- mkdirSync12(skillsDir, { recursive: true });
65535
+ if (!existsSync21(skillsDir)) {
65536
+ mkdirSync13(skillsDir, { recursive: true });
64855
65537
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
64856
65538
  }
64857
- if (!existsSync20(claudishSkillDir)) {
64858
- mkdirSync12(claudishSkillDir, { recursive: true });
65539
+ if (!existsSync21(claudishSkillDir)) {
65540
+ mkdirSync13(claudishSkillDir, { recursive: true });
64859
65541
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
64860
65542
  }
64861
65543
  copyFileSync2(sourceSkillPath, skillFile);
@@ -64927,7 +65609,7 @@ var init_cli = __esm(() => {
64927
65609
  init_routing_rules();
64928
65610
  init_provider_resolver();
64929
65611
  __filename3 = fileURLToPath2(import.meta.url);
64930
- __dirname3 = dirname6(__filename3);
65612
+ __dirname3 = dirname8(__filename3);
64931
65613
  });
64932
65614
 
64933
65615
  // src/update-checker.ts
@@ -64939,33 +65621,33 @@ __export(exports_update_checker, {
64939
65621
  clearCache: () => clearCache,
64940
65622
  checkForUpdates: () => checkForUpdates
64941
65623
  });
64942
- import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync19, unlinkSync as unlinkSync8, writeFileSync as writeFileSync15 } from "fs";
64943
- import { homedir as homedir22, platform as platform2, tmpdir } from "os";
64944
- import { join as join23 } from "path";
65624
+ import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync21, unlinkSync as unlinkSync8, writeFileSync as writeFileSync16 } from "fs";
65625
+ import { homedir as homedir23, platform as platform2, tmpdir } from "os";
65626
+ import { join as join25 } from "path";
64945
65627
  function getCacheFilePath() {
64946
65628
  let cacheDir;
64947
65629
  if (isWindows) {
64948
- const localAppData = process.env.LOCALAPPDATA || join23(homedir22(), "AppData", "Local");
64949
- cacheDir = join23(localAppData, "claudish");
65630
+ const localAppData = process.env.LOCALAPPDATA || join25(homedir23(), "AppData", "Local");
65631
+ cacheDir = join25(localAppData, "claudish");
64950
65632
  } else {
64951
- cacheDir = join23(homedir22(), ".cache", "claudish");
65633
+ cacheDir = join25(homedir23(), ".cache", "claudish");
64952
65634
  }
64953
65635
  try {
64954
- if (!existsSync21(cacheDir)) {
64955
- mkdirSync13(cacheDir, { recursive: true });
65636
+ if (!existsSync22(cacheDir)) {
65637
+ mkdirSync14(cacheDir, { recursive: true });
64956
65638
  }
64957
- return join23(cacheDir, "update-check.json");
65639
+ return join25(cacheDir, "update-check.json");
64958
65640
  } catch {
64959
- return join23(tmpdir(), "claudish-update-check.json");
65641
+ return join25(tmpdir(), "claudish-update-check.json");
64960
65642
  }
64961
65643
  }
64962
65644
  function readCache() {
64963
65645
  try {
64964
65646
  const cachePath = getCacheFilePath();
64965
- if (!existsSync21(cachePath)) {
65647
+ if (!existsSync22(cachePath)) {
64966
65648
  return null;
64967
65649
  }
64968
- const data = JSON.parse(readFileSync19(cachePath, "utf-8"));
65650
+ const data = JSON.parse(readFileSync21(cachePath, "utf-8"));
64969
65651
  return data;
64970
65652
  } catch {
64971
65653
  return null;
@@ -64978,7 +65660,7 @@ function writeCache(latestVersion) {
64978
65660
  lastCheck: Date.now(),
64979
65661
  latestVersion
64980
65662
  };
64981
- writeFileSync15(cachePath, JSON.stringify(data), "utf-8");
65663
+ writeFileSync16(cachePath, JSON.stringify(data), "utf-8");
64982
65664
  } catch {}
64983
65665
  }
64984
65666
  function isCacheValid(cache2) {
@@ -64988,7 +65670,7 @@ function isCacheValid(cache2) {
64988
65670
  function clearCache() {
64989
65671
  try {
64990
65672
  const cachePath = getCacheFilePath();
64991
- if (existsSync21(cachePath)) {
65673
+ if (existsSync22(cachePath)) {
64992
65674
  unlinkSync8(cachePath);
64993
65675
  }
64994
65676
  } catch {}
@@ -65867,15 +66549,15 @@ var init_local_liveness = __esm(() => {
65867
66549
  });
65868
66550
 
65869
66551
  // src/providers/probe-catalog.ts
65870
- import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync20, writeFileSync as writeFileSync16 } from "fs";
65871
- import { homedir as homedir23 } from "os";
65872
- import { dirname as dirname7, join as join24 } from "path";
66552
+ import { existsSync as existsSync23, mkdirSync as mkdirSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync17 } from "fs";
66553
+ import { homedir as homedir24 } from "os";
66554
+ import { dirname as dirname9, join as join26 } from "path";
65873
66555
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
65874
- if (!existsSync22(path2))
66556
+ if (!existsSync23(path2))
65875
66557
  return null;
65876
66558
  let raw2;
65877
66559
  try {
65878
- raw2 = JSON.parse(readFileSync20(path2, "utf-8"));
66560
+ raw2 = JSON.parse(readFileSync22(path2, "utf-8"));
65879
66561
  } catch {
65880
66562
  return null;
65881
66563
  }
@@ -65884,8 +66566,8 @@ function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
65884
66566
  return raw2;
65885
66567
  }
65886
66568
  function writeProbeModelsCache(data, path2 = PROBE_MODELS_CACHE_PATH) {
65887
- mkdirSync14(dirname7(path2), { recursive: true });
65888
- writeFileSync16(path2, JSON.stringify(data), "utf-8");
66569
+ mkdirSync15(dirname9(path2), { recursive: true });
66570
+ writeFileSync17(path2, JSON.stringify(data), "utf-8");
65889
66571
  }
65890
66572
  function isCacheFresh(data, ttlMs = CACHE_TTL_MS4) {
65891
66573
  if (!data?.generatedAt)
@@ -66004,7 +66686,7 @@ function isValidResponse(raw2) {
66004
66686
  var PROBE_MODELS_URL = "https://us-central1-claudish-6da10.cloudfunctions.net/probeModels", CACHE_TTL_MS4, FETCH_TIMEOUT_MS3 = 15000, PROBE_MODELS_CACHE_PATH, _inFlight = null;
66005
66687
  var init_probe_catalog = __esm(() => {
66006
66688
  CACHE_TTL_MS4 = 60 * 60 * 1000;
66007
- PROBE_MODELS_CACHE_PATH = join24(homedir23(), ".claudish", "probe-models.json");
66689
+ PROBE_MODELS_CACHE_PATH = join26(homedir24(), ".claudish", "probe-models.json");
66008
66690
  });
66009
66691
 
66010
66692
  // src/tui/constants.ts
@@ -72337,16 +73019,16 @@ __export(exports_claude_runner, {
72337
73019
  });
72338
73020
  import { spawn as spawn4 } from "child_process";
72339
73021
  import {
72340
- closeSync as closeSync4,
72341
- existsSync as existsSync23,
72342
- mkdirSync as mkdirSync15,
72343
- openSync as openSync4,
72344
- readFileSync as readFileSync21,
73022
+ closeSync as closeSync5,
73023
+ existsSync as existsSync24,
73024
+ mkdirSync as mkdirSync16,
73025
+ openSync as openSync5,
73026
+ readFileSync as readFileSync23,
72345
73027
  unlinkSync as unlinkSync9,
72346
- writeFileSync as writeFileSync17
73028
+ writeFileSync as writeFileSync18
72347
73029
  } from "fs";
72348
- import { homedir as homedir24, tmpdir as tmpdir2 } from "os";
72349
- import { join as join25 } from "path";
73030
+ import { homedir as homedir25, tmpdir as tmpdir2 } from "os";
73031
+ import { join as join27 } from "path";
72350
73032
  import { isatty } from "tty";
72351
73033
  function releaseTerminalIsolation() {
72352
73034
  if (!restoreTerminal)
@@ -72381,14 +73063,14 @@ function isProxyAuthMode(config3) {
72381
73063
  }
72382
73064
  function managedSettingsPath() {
72383
73065
  if (isWindows2()) {
72384
- return join25(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
73066
+ return join27(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
72385
73067
  }
72386
73068
  if (process.platform === "darwin") {
72387
73069
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
72388
73070
  }
72389
73071
  return "/etc/claude-code/managed-settings.json";
72390
73072
  }
72391
- function managedSettingsForcesClaudeAi(readFile = readFileSync21) {
73073
+ function managedSettingsForcesClaudeAi(readFile = readFileSync23) {
72392
73074
  try {
72393
73075
  const raw2 = readFile(managedSettingsPath(), "utf-8");
72394
73076
  const parsed = JSON.parse(raw2);
@@ -72402,9 +73084,9 @@ function isWindows2() {
72402
73084
  }
72403
73085
  function createStatusLineScript(tokenFilePath) {
72404
73086
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
72405
- const claudishDir = join25(homeDir, ".claudish");
73087
+ const claudishDir = join27(homeDir, ".claudish");
72406
73088
  const timestamp = Date.now();
72407
- const scriptPath = join25(claudishDir, `status-${timestamp}.js`);
73089
+ const scriptPath = join27(claudishDir, `status-${timestamp}.js`);
72408
73090
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
72409
73091
  const script = `
72410
73092
  const fs = require('fs');
@@ -72496,18 +73178,18 @@ process.stdin.on('end', () => {
72496
73178
  }
72497
73179
  });
72498
73180
  `;
72499
- writeFileSync17(scriptPath, script, "utf-8");
73181
+ writeFileSync18(scriptPath, script, "utf-8");
72500
73182
  return scriptPath;
72501
73183
  }
72502
73184
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode) {
72503
73185
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
72504
- const claudishDir = join25(homeDir, ".claudish");
73186
+ const claudishDir = join27(homeDir, ".claudish");
72505
73187
  try {
72506
- mkdirSync15(claudishDir, { recursive: true });
73188
+ mkdirSync16(claudishDir, { recursive: true });
72507
73189
  } catch {}
72508
73190
  const timestamp = Date.now();
72509
- const tempPath = join25(claudishDir, `settings-${timestamp}.json`);
72510
- const tokenFilePath = join25(claudishDir, `tokens-${port}.json`);
73191
+ const tempPath = join27(claudishDir, `settings-${timestamp}.json`);
73192
+ const tokenFilePath = join27(claudishDir, `tokens-${port}.json`);
72511
73193
  let statusCommand;
72512
73194
  if (isWindows2()) {
72513
73195
  const scriptPath = createStatusLineScript(tokenFilePath);
@@ -72529,7 +73211,7 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode) {
72529
73211
  padding: 0
72530
73212
  };
72531
73213
  const settings = buildClaudishSettingsOverlay(statusLine, proxyAuthMode);
72532
- writeFileSync17(tempPath, JSON.stringify(settings, null, 2), "utf-8");
73214
+ writeFileSync18(tempPath, JSON.stringify(settings, null, 2), "utf-8");
72533
73215
  return { path: tempPath, statusLine };
72534
73216
  }
72535
73217
  function buildClaudishSettingsOverlay(statusLine, proxyAuthMode) {
@@ -72550,7 +73232,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
72550
73232
  if (userSettingsValue.trimStart().startsWith("{")) {
72551
73233
  userSettings = JSON.parse(userSettingsValue);
72552
73234
  } else {
72553
- const rawUserSettings = readFileSync21(userSettingsValue, "utf-8");
73235
+ const rawUserSettings = readFileSync23(userSettingsValue, "utf-8");
72554
73236
  userSettings = JSON.parse(rawUserSettings);
72555
73237
  }
72556
73238
  userSettings.statusLine = statusLine;
@@ -72560,7 +73242,7 @@ function mergeUserSettingsIfPresent(config3, tempSettingsPath, statusLine, proxy
72560
73242
  if (proxyAuthMode && !("forceLoginMethod" in userSettings)) {
72561
73243
  userSettings.forceLoginMethod = "console";
72562
73244
  }
72563
- writeFileSync17(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
73245
+ writeFileSync18(tempSettingsPath, JSON.stringify(userSettings, null, 2), "utf-8");
72564
73246
  } catch {
72565
73247
  if (!config3.quiet) {
72566
73248
  console.warn(`[claudish] Warning: could not merge user settings: ${userSettingsValue}`);
@@ -72721,8 +73403,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
72721
73403
  console.error("Install it from: https://claude.com/claude-code");
72722
73404
  console.error(`
72723
73405
  Or set CLAUDE_PATH to your custom installation:`);
72724
- const home = homedir24();
72725
- const localPath = isWindows2() ? join25(home, ".claude", "local", "claude.exe") : join25(home, ".claude", "local", "claude");
73406
+ const home = homedir25();
73407
+ const localPath = isWindows2() ? join27(home, ".claude", "local", "claude.exe") : join27(home, ".claude", "local", "claude");
72726
73408
  console.error(` export CLAUDE_PATH=${localPath}`);
72727
73409
  process.exit(1);
72728
73410
  }
@@ -72733,11 +73415,11 @@ Or set CLAUDE_PATH to your custom installation:`);
72733
73415
  const childWantsTty = config3.interactive && !process.stdout.isTTY && Boolean(process.stdin.isTTY);
72734
73416
  if (childWantsTty) {
72735
73417
  try {
72736
- const fd = openSync4("/dev/fd/0", "r+");
73418
+ const fd = openSync5("/dev/fd/0", "r+");
72737
73419
  if (isatty(fd)) {
72738
73420
  ttyFd = fd;
72739
73421
  } else {
72740
- closeSync4(fd);
73422
+ closeSync5(fd);
72741
73423
  }
72742
73424
  } catch {
72743
73425
  ttyFd = undefined;
@@ -72760,7 +73442,7 @@ Or set CLAUDE_PATH to your custom installation:`);
72760
73442
  const fdToClose = ttyFd;
72761
73443
  proc.on("spawn", () => {
72762
73444
  try {
72763
- closeSync4(fdToClose);
73445
+ closeSync5(fdToClose);
72764
73446
  } catch {}
72765
73447
  });
72766
73448
  }
@@ -72802,23 +73484,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
72802
73484
  async function findClaudeBinary() {
72803
73485
  const isWindows3 = process.platform === "win32";
72804
73486
  if (process.env.CLAUDE_PATH) {
72805
- if (existsSync23(process.env.CLAUDE_PATH)) {
73487
+ if (existsSync24(process.env.CLAUDE_PATH)) {
72806
73488
  return process.env.CLAUDE_PATH;
72807
73489
  }
72808
73490
  }
72809
- const home = homedir24();
72810
- const localPath = isWindows3 ? join25(home, ".claude", "local", "claude.exe") : join25(home, ".claude", "local", "claude");
72811
- if (existsSync23(localPath)) {
73491
+ const home = homedir25();
73492
+ const localPath = isWindows3 ? join27(home, ".claude", "local", "claude.exe") : join27(home, ".claude", "local", "claude");
73493
+ if (existsSync24(localPath)) {
72812
73494
  return localPath;
72813
73495
  }
72814
73496
  if (isWindows3) {
72815
73497
  const windowsPaths = [
72816
- join25(home, "AppData", "Roaming", "npm", "claude.cmd"),
72817
- join25(home, ".npm-global", "claude.cmd"),
72818
- join25(home, "node_modules", ".bin", "claude.cmd")
73498
+ join27(home, "AppData", "Roaming", "npm", "claude.cmd"),
73499
+ join27(home, ".npm-global", "claude.cmd"),
73500
+ join27(home, "node_modules", ".bin", "claude.cmd")
72819
73501
  ];
72820
73502
  for (const path2 of windowsPaths) {
72821
- if (existsSync23(path2)) {
73503
+ if (existsSync24(path2)) {
72822
73504
  return path2;
72823
73505
  }
72824
73506
  }
@@ -72826,14 +73508,14 @@ async function findClaudeBinary() {
72826
73508
  const commonPaths = [
72827
73509
  "/usr/local/bin/claude",
72828
73510
  "/opt/homebrew/bin/claude",
72829
- join25(home, ".npm-global/bin/claude"),
72830
- join25(home, ".local/bin/claude"),
72831
- join25(home, "node_modules/.bin/claude"),
73511
+ join27(home, ".npm-global/bin/claude"),
73512
+ join27(home, ".local/bin/claude"),
73513
+ join27(home, "node_modules/.bin/claude"),
72832
73514
  "/data/data/com.termux/files/usr/bin/claude",
72833
- join25(home, "../usr/bin/claude")
73515
+ join27(home, "../usr/bin/claude")
72834
73516
  ];
72835
73517
  for (const path2 of commonPaths) {
72836
- if (existsSync23(path2)) {
73518
+ if (existsSync24(path2)) {
72837
73519
  return path2;
72838
73520
  }
72839
73521
  }
@@ -72890,18 +73572,18 @@ __export(exports_diag_output, {
72890
73572
  NullDiagOutput: () => NullDiagOutput,
72891
73573
  LogFileDiagOutput: () => LogFileDiagOutput
72892
73574
  });
72893
- import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync16, unlinkSync as unlinkSync10, writeFileSync as writeFileSync18 } from "fs";
72894
- import { homedir as homedir25 } from "os";
72895
- import { join as join26 } from "path";
73575
+ import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync17, unlinkSync as unlinkSync10, writeFileSync as writeFileSync19 } from "fs";
73576
+ import { homedir as homedir26 } from "os";
73577
+ import { join as join28 } from "path";
72896
73578
  function getClaudishDir() {
72897
- const dir = join26(homedir25(), ".claudish");
73579
+ const dir = join28(homedir26(), ".claudish");
72898
73580
  try {
72899
- mkdirSync16(dir, { recursive: true });
73581
+ mkdirSync17(dir, { recursive: true });
72900
73582
  } catch {}
72901
73583
  return dir;
72902
73584
  }
72903
73585
  function getDiagLogPath() {
72904
- return join26(getClaudishDir(), `diag-${process.pid}.log`);
73586
+ return join28(getClaudishDir(), `diag-${process.pid}.log`);
72905
73587
  }
72906
73588
 
72907
73589
  class LogFileDiagOutput {
@@ -72910,7 +73592,7 @@ class LogFileDiagOutput {
72910
73592
  constructor() {
72911
73593
  this.logPath = getDiagLogPath();
72912
73594
  try {
72913
- writeFileSync18(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
73595
+ writeFileSync19(this.logPath, `--- claudish diag session ${new Date().toISOString()} ---
72914
73596
  `);
72915
73597
  } catch {}
72916
73598
  this.stream = createWriteStream3(this.logPath, { flags: "a" });
@@ -73112,9 +73794,9 @@ __export(exports_team_grid, {
73112
73794
  });
73113
73795
  import { spawn as spawn5 } from "child_process";
73114
73796
  import { execSync as execSync2 } from "child_process";
73115
- import { existsSync as existsSync24, readFileSync as readFileSync22, writeFileSync as writeFileSync19 } from "fs";
73797
+ import { existsSync as existsSync25, readFileSync as readFileSync24, writeFileSync as writeFileSync20 } from "fs";
73116
73798
  import { connect as netConnect } from "net";
73117
- import { dirname as dirname8, join as join27 } from "path";
73799
+ import { dirname as dirname10, join as join29 } from "path";
73118
73800
  import { setTimeout as wait } from "timers/promises";
73119
73801
  import { fileURLToPath as fileURLToPath3 } from "url";
73120
73802
  function resolveRouteInfo(modelId) {
@@ -73207,21 +73889,21 @@ function buildPaneHeader(model, prompt, bg) {
73207
73889
  }
73208
73890
  function findMagmuxBinary() {
73209
73891
  const thisFile = fileURLToPath3(import.meta.url);
73210
- const thisDir = dirname8(thisFile);
73211
- const pkgRoot = join27(thisDir, "..");
73892
+ const thisDir = dirname10(thisFile);
73893
+ const pkgRoot = join29(thisDir, "..");
73212
73894
  const platform3 = process.platform;
73213
73895
  const arch = process.arch;
73214
- const bundledMagmux = join27(pkgRoot, "native", `magmux-${platform3}-${arch}`);
73215
- if (existsSync24(bundledMagmux))
73896
+ const bundledMagmux = join29(pkgRoot, "native", `magmux-${platform3}-${arch}`);
73897
+ if (existsSync25(bundledMagmux))
73216
73898
  return bundledMagmux;
73217
73899
  try {
73218
73900
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
73219
73901
  let searchDir = pkgRoot;
73220
73902
  for (let i = 0;i < 5; i++) {
73221
- const candidate = join27(searchDir, "node_modules", pkgName, "bin", "magmux");
73222
- if (existsSync24(candidate))
73903
+ const candidate = join29(searchDir, "node_modules", pkgName, "bin", "magmux");
73904
+ if (existsSync25(candidate))
73223
73905
  return candidate;
73224
- const parent = dirname8(searchDir);
73906
+ const parent = dirname10(searchDir);
73225
73907
  if (parent === searchDir)
73226
73908
  break;
73227
73909
  searchDir = parent;
@@ -73238,7 +73920,7 @@ function findMagmuxBinary() {
73238
73920
  async function subscribeToMagmux(sockPath, onEvent) {
73239
73921
  let client = null;
73240
73922
  for (let attempt = 0;attempt < 40; attempt++) {
73241
- if (existsSync24(sockPath)) {
73923
+ if (existsSync25(sockPath)) {
73242
73924
  try {
73243
73925
  client = await new Promise((resolve4, reject) => {
73244
73926
  const s = netConnect(sockPath);
@@ -73325,9 +74007,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
73325
74007
  const keep = opts?.keep ?? false;
73326
74008
  const manifest = setupSession(sessionPath, models, input);
73327
74009
  const startedAt = new Date().toISOString();
73328
- const gridfilePath = join27(sessionPath, "gridfile.txt");
73329
- const prompt = readFileSync22(join27(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
73330
- const rawPrompt = readFileSync22(join27(sessionPath, "input.md"), "utf-8");
74010
+ const gridfilePath = join29(sessionPath, "gridfile.txt");
74011
+ const prompt = readFileSync24(join29(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
74012
+ const rawPrompt = readFileSync24(join29(sessionPath, "input.md"), "utf-8");
73331
74013
  const usedBannerColors = new Set;
73332
74014
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
73333
74015
  const model = manifest.models[anonId].model;
@@ -73338,7 +74020,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
73338
74020
  const header = buildPaneHeader(model, rawPrompt, bg);
73339
74021
  return `${header} claudish --model ${model} -y --quiet '${prompt}'`;
73340
74022
  });
73341
- writeFileSync19(gridfilePath, `${gridLines.join(`
74023
+ writeFileSync20(gridfilePath, `${gridLines.join(`
73342
74024
  `)}
73343
74025
  `, "utf-8");
73344
74026
  const magmuxPath = findMagmuxBinary();
@@ -73358,8 +74040,8 @@ async function runWithGrid(sessionPath, models, input, opts) {
73358
74040
  });
73359
74041
  const [{ results }] = await Promise.all([subscription, procExit]);
73360
74042
  const status = buildTeamStatus(manifest, startedAt, results?.panes ?? null);
73361
- const statusPath = join27(sessionPath, "status.json");
73362
- writeFileSync19(statusPath, JSON.stringify(status, null, 2), "utf-8");
74043
+ const statusPath = join29(sessionPath, "status.json");
74044
+ writeFileSync20(statusPath, JSON.stringify(status, null, 2), "utf-8");
73363
74045
  return status;
73364
74046
  }
73365
74047
  var BANNER_BG_COLORS;
@@ -73382,8 +74064,8 @@ var init_team_grid = __esm(() => {
73382
74064
  init_op_source();
73383
74065
  init_startup_trace();
73384
74066
  var import_dotenv3 = __toESM(require_main(), 1);
73385
- import { existsSync as existsSync25, readFileSync as readFileSync23 } from "fs";
73386
- import { join as join28, resolve as resolve4 } from "path";
74067
+ import { existsSync as existsSync26, readFileSync as readFileSync25 } from "fs";
74068
+ import { join as join30, resolve as resolve4 } from "path";
73387
74069
  import_dotenv3.config({ quiet: true });
73388
74070
  function classifyStartupKind() {
73389
74071
  const argv = process.argv.slice(2);
@@ -73482,7 +74164,7 @@ async function applyConfigOverride() {
73482
74164
  const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
73483
74165
  const plan = planConfigOverride2(process.argv.slice(2), process.env, {
73484
74166
  resolve: resolve4,
73485
- exists: existsSync25
74167
+ exists: existsSync26
73486
74168
  });
73487
74169
  if (plan.kind === "none")
73488
74170
  return;
@@ -73617,14 +74299,14 @@ async function runCli() {
73617
74299
  if (cliConfig.team && cliConfig.team.length > 0) {
73618
74300
  let prompt = cliConfig.claudeArgs.join(" ");
73619
74301
  if (cliConfig.inputFile) {
73620
- prompt = readFileSync23(cliConfig.inputFile, "utf-8");
74302
+ prompt = readFileSync25(cliConfig.inputFile, "utf-8");
73621
74303
  }
73622
74304
  if (!prompt.trim()) {
73623
74305
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
73624
74306
  process.exit(1);
73625
74307
  }
73626
74308
  const mode = cliConfig.teamMode ?? "default";
73627
- const sessionPath = join28(process.cwd(), `.claudish-team-${Date.now()}`);
74309
+ const sessionPath = join30(process.cwd(), `.claudish-team-${Date.now()}`);
73628
74310
  if (mode === "json") {
73629
74311
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
73630
74312
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -73634,9 +74316,9 @@ async function runCli() {
73634
74316
  });
73635
74317
  const result = { ...status2, responses: {} };
73636
74318
  for (const anonId of Object.keys(status2.models)) {
73637
- const responsePath = join28(sessionPath, `response-${anonId}.md`);
74319
+ const responsePath = join30(sessionPath, `response-${anonId}.md`);
73638
74320
  try {
73639
- const raw2 = readFileSync23(responsePath, "utf-8").trim();
74321
+ const raw2 = readFileSync25(responsePath, "utf-8").trim();
73640
74322
  try {
73641
74323
  result.responses[anonId] = JSON.parse(raw2);
73642
74324
  } catch {