claudish 13.0.1 → 13.0.3

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 +198 -81
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -575,7 +575,7 @@ var init_onepassword_config = __esm(() => {
575
575
  });
576
576
 
577
577
  // src/version.ts
578
- var VERSION = "13.0.1";
578
+ var VERSION = "13.0.3";
579
579
 
580
580
  // src/logger.ts
581
581
  import { appendFile, existsSync as existsSync2, mkdirSync, readdirSync, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
@@ -27780,7 +27780,8 @@ async function discoverEveryServedModel(providerName) {
27780
27780
  detail: `no base URL resolved \u2014 check ${overrides || "the provider's baseUrl"}`
27781
27781
  });
27782
27782
  }
27783
- const endpoint = registryModelsEndpoint(providerName, def) ?? `${baseUrl}${descriptor.path}`;
27783
+ const definitionEndpoint = `${baseUrl}${descriptor.path}`;
27784
+ let endpoint = registryModelsEndpoint(providerName, def) ?? definitionEndpoint;
27784
27785
  let headers = {};
27785
27786
  if (def.isLocal) {
27786
27787
  const key = def.apiKeyEnvVar ? process.env[def.apiKeyEnvVar] : undefined;
@@ -27807,13 +27808,14 @@ async function discoverEveryServedModel(providerName) {
27807
27808
  ...def.headers ?? {},
27808
27809
  ...headers
27809
27810
  };
27811
+ const fetchList = (url) => fetch(url, { method: "GET", headers, signal: AbortSignal.timeout(FETCH_TIMEOUT_MS3) });
27810
27812
  let response;
27811
27813
  try {
27812
- response = await fetch(endpoint, {
27813
- method: "GET",
27814
- headers,
27815
- signal: AbortSignal.timeout(FETCH_TIMEOUT_MS3)
27816
- });
27814
+ response = await fetchList(endpoint);
27815
+ if (response.status === 404 && endpoint !== definitionEndpoint) {
27816
+ endpoint = definitionEndpoint;
27817
+ response = await fetchList(endpoint);
27818
+ }
27817
27819
  } catch (e) {
27818
27820
  return recordFailure({
27819
27821
  kind: "unreachable",
@@ -27854,7 +27856,7 @@ async function discoverEveryServedModel(providerName) {
27854
27856
  }
27855
27857
  const models = parsed.models;
27856
27858
  _failures.delete(providerName);
27857
- log(`[model-discovery:${providerName}] discovered ${models.length} models: ` + models.map((m) => `${m.id}(${m.contextWindow ?? "?"})`).join(", "));
27859
+ log(`[model-discovery:${providerName}] discovered ${models.length} models from ${endpoint}: ` + models.map((m) => `${m.id}(${m.contextWindow ?? "?"})`).join(", "));
27858
27860
  _cache2.set(providerName, { models, expiresAt: Date.now() + CACHE_TTL_MS2 });
27859
27861
  return { kind: "served", models };
27860
27862
  }
@@ -29842,9 +29844,9 @@ async function flushStats() {
29842
29844
  }
29843
29845
  } catch {}
29844
29846
  }
29845
- function showMonthlyBanner() {
29847
+ function showMonthlyBanner(env = process.env) {
29846
29848
  try {
29847
- if (isStatsDisabledByEnv())
29849
+ if (isStatsDisabledByEnv() || isPaneChild(env))
29848
29850
  return;
29849
29851
  const profileConfig = loadConfig();
29850
29852
  const consent = profileConfig.stats;
@@ -29976,6 +29978,7 @@ Usage: claudish stats on|off|status|reset
29976
29978
  }
29977
29979
  var STATS_ENDPOINT = "https://claudish.com/v1/stats", FLUSH_INTERVAL_MS2, MONTHLY_INTERVAL_MS, SEND_TIMEOUT_MS = 5000, statsEnabled = false, initialized2 = false, claudishVersion2 = "", installMethod2 = "unknown", envAttributes;
29978
29980
  var init_stats = __esm(() => {
29981
+ init_child_env();
29979
29982
  init_profile_config();
29980
29983
  init_model_parser();
29981
29984
  init_stats_buffer();
@@ -36447,8 +36450,8 @@ var init_provider_definitions = __esm(() => {
36447
36450
  baseUrl: "https://api.kimi.com/coding/v1",
36448
36451
  apiPath: "/messages",
36449
36452
  apiKeyEnvVar: "KIMI_CODING_API_KEY",
36450
- apiKeyDescription: "Kimi Coding API Key",
36451
- apiKeyUrl: "https://kimi.com/code (get key from membership page, or run: claudish login kimi)",
36453
+ apiKeyDescription: "Kimi Coding API Key (membership page, or run: claudish login kimi)",
36454
+ apiKeyUrl: "https://www.kimi.com/code",
36452
36455
  oauthFallback: "kimi-oauth.json",
36453
36456
  oauthLoginSlug: "kimi",
36454
36457
  shortcuts: ["kc"],
@@ -36501,7 +36504,7 @@ var init_provider_definitions = __esm(() => {
36501
36504
  apiKeyEnvVar: "ZHIPU_API_KEY",
36502
36505
  apiKeyAliases: ["GLM_API_KEY"],
36503
36506
  apiKeyDescription: "GLM/Zhipu API Key",
36504
- apiKeyUrl: "https://z.ai/",
36507
+ apiKeyUrl: "https://z.ai/manage-apikey/apikey-list",
36505
36508
  shortcuts: ["glm", "zhipu"],
36506
36509
  shortestPrefix: "glm",
36507
36510
  legacyPrefixes: [
@@ -36547,7 +36550,7 @@ var init_provider_definitions = __esm(() => {
36547
36550
  apiPath: "/api/anthropic/v1/messages",
36548
36551
  apiKeyEnvVar: "ZAI_API_KEY",
36549
36552
  apiKeyDescription: "Z.AI API Key",
36550
- apiKeyUrl: "https://z.ai/",
36553
+ apiKeyUrl: "https://z.ai/manage-apikey/apikey-list",
36551
36554
  shortcuts: ["z-ai", "zai"],
36552
36555
  shortestPrefix: "z-ai",
36553
36556
  legacyPrefixes: [{ prefix: "zai/", stripPrefix: true }],
@@ -36567,7 +36570,7 @@ var init_provider_definitions = __esm(() => {
36567
36570
  apiPath: "/api/chat",
36568
36571
  apiKeyEnvVar: "OLLAMA_API_KEY",
36569
36572
  apiKeyDescription: "OllamaCloud API Key",
36570
- apiKeyUrl: "https://ollama.com/account",
36573
+ apiKeyUrl: "https://ollama.com/settings/keys",
36571
36574
  shortcuts: ["oc", "llama", "lc"],
36572
36575
  shortestPrefix: "oc",
36573
36576
  legacyPrefixes: [{ prefix: "oc/", stripPrefix: true }],
@@ -36591,8 +36594,8 @@ var init_provider_definitions = __esm(() => {
36591
36594
  baseUrlEnvVars: ["OPENCODE_BASE_URL"],
36592
36595
  apiPath: "/v1/chat/completions",
36593
36596
  apiKeyEnvVar: "OPENCODE_API_KEY",
36594
- apiKeyDescription: "OpenCode Zen API Key",
36595
- apiKeyUrl: "https://opencode.ai/",
36597
+ apiKeyDescription: "OpenCode Zen API Key (Console > Settings > Service accounts)",
36598
+ apiKeyUrl: "https://opencode.ai/console",
36596
36599
  shortcuts: ["zen"],
36597
36600
  shortestPrefix: "zen",
36598
36601
  legacyPrefixes: [{ prefix: "zen/", stripPrefix: true }],
@@ -36612,8 +36615,8 @@ var init_provider_definitions = __esm(() => {
36612
36615
  modelDiscovery: { path: "/v1/models", format: "openai-models-list" },
36613
36616
  apiKeyEnvVar: "OPENCODE_GO_API_KEY",
36614
36617
  siblingKeyEnvVars: ["OPENCODE_API_KEY"],
36615
- apiKeyDescription: "OpenCode Zen Go (Lite Plan) API Key",
36616
- apiKeyUrl: "https://opencode.ai/",
36618
+ apiKeyDescription: "OpenCode Zen Go (Lite Plan) API Key (Console > Settings > Service accounts)",
36619
+ apiKeyUrl: "https://opencode.ai/console",
36617
36620
  shortcuts: ["zengo", "zgo"],
36618
36621
  shortestPrefix: "zengo",
36619
36622
  legacyPrefixes: [
@@ -36717,7 +36720,7 @@ var init_provider_definitions = __esm(() => {
36717
36720
  apiPath: "/v1/chat/completions",
36718
36721
  apiKeyEnvVar: "LMSTUDIO_API_KEY",
36719
36722
  apiKeyDescription: "LM Studio API Key (optional \u2014 leave blank for localhost)",
36720
- apiKeyUrl: "https://lmstudio.ai/docs/local-server",
36723
+ apiKeyUrl: "https://lmstudio.ai/docs/developer/core/server",
36721
36724
  shortcuts: ["lms", "lmstudio", "mlstudio"],
36722
36725
  shortestPrefix: "lms",
36723
36726
  legacyPrefixes: [
@@ -68612,44 +68615,76 @@ import { basename as basename2, dirname as dirname14, join as join41 } from "pat
68612
68615
  function collapse(s) {
68613
68616
  return s.trim().replace(/\s+/g, " ");
68614
68617
  }
68615
- function parsePsTable(text) {
68618
+ function etimeSeconds(etime) {
68619
+ const [days, clock] = etime.includes("-") ? etime.split("-") : ["0", etime];
68620
+ const parts = (clock ?? "").split(":").map(Number);
68621
+ while (parts.length < 3)
68622
+ parts.unshift(0);
68623
+ const [h = 0, m = 0, s = 0] = parts;
68624
+ return Number(days) * 86400 + h * 3600 + m * 60 + s;
68625
+ }
68626
+ function parsePsTable(text, spawnedAtMs) {
68616
68627
  const rows = [];
68617
68628
  for (const line of text.split(`
68618
68629
  `)) {
68619
68630
  const m = line.match(PS_ROW);
68620
68631
  if (!m)
68621
68632
  continue;
68622
- rows.push({
68633
+ const row = {
68623
68634
  pid: Number(m[1]),
68624
68635
  ppid: Number(m[2]),
68625
68636
  pgid: Number(m[3]),
68626
- lstart: collapse(m[4] ?? ""),
68627
- command: (m[5] ?? "").trim()
68628
- });
68637
+ lstart: collapse(m[5] ?? ""),
68638
+ command: (m[6] ?? "").trim()
68639
+ };
68640
+ if (m[4] && spawnedAtMs !== undefined)
68641
+ row.startMs = spawnedAtMs - etimeSeconds(m[4]) * 1000;
68642
+ rows.push(row);
68629
68643
  }
68630
68644
  return rows;
68631
68645
  }
68646
+ function startedAt(row, startMs) {
68647
+ return row.startMs === undefined || Math.abs(row.startMs - startMs) < START_TOLERANCE_MS;
68648
+ }
68649
+ function pidMayBeAlive(pid) {
68650
+ if (!Number.isInteger(pid) || pid <= 0)
68651
+ return true;
68652
+ try {
68653
+ process.kill(pid, 0);
68654
+ return true;
68655
+ } catch (e) {
68656
+ return e.code !== "ESRCH";
68657
+ }
68658
+ }
68659
+ function processTableTrusted(rows) {
68660
+ return rows.some((r) => r.pid === process.pid);
68661
+ }
68662
+ function tableOf(stdout, spawnedAtMs) {
68663
+ if (stdout === null)
68664
+ return null;
68665
+ const rows = parsePsTable(stdout, spawnedAtMs);
68666
+ return processTableTrusted(rows) ? rows : null;
68667
+ }
68632
68668
  function readProcessTable() {
68669
+ const spawnedAt = Date.now();
68670
+ let stdout;
68633
68671
  try {
68634
- return parsePsTable(execFileSync2("ps", PS_ARGS, {
68635
- env: PS_ENV,
68636
- encoding: "utf8",
68637
- maxBuffer: 64 * 1024 * 1024,
68672
+ stdout = psSpawn.execFileSync("ps", PS_ARGS, {
68673
+ ...PS_OPTIONS,
68638
68674
  stdio: ["ignore", "pipe", "ignore"]
68639
- }));
68675
+ });
68640
68676
  } catch {
68641
- return [];
68677
+ stdout = null;
68642
68678
  }
68643
- }
68644
- function processTableTrusted(table) {
68645
- return table.some((r) => r.pid === process.pid);
68679
+ return tableOf(stdout, spawnedAt);
68646
68680
  }
68647
68681
  function readProcessTableAsync() {
68648
68682
  return new Promise((resolve) => {
68683
+ const spawnedAt = Date.now();
68649
68684
  try {
68650
- execFile2("ps", PS_ARGS, { env: PS_ENV, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 }, (err, stdout) => resolve(err ? [] : parsePsTable(String(stdout))));
68685
+ psSpawn.execFile("ps", PS_ARGS, PS_OPTIONS, (err, stdout) => resolve(tableOf(err ? null : String(stdout), spawnedAt)));
68651
68686
  } catch {
68652
- resolve([]);
68687
+ resolve(tableOf(null, spawnedAt));
68653
68688
  }
68654
68689
  });
68655
68690
  }
@@ -68666,12 +68701,12 @@ function isPaneMagmuxCommand(command, paneId) {
68666
68701
  return command.includes(magmuxNeedle(paneId));
68667
68702
  }
68668
68703
  function isPaneMagmux(pid, paneId, table) {
68669
- const rows = table ?? readProcessTable();
68704
+ const rows = table ?? readProcessTable() ?? [];
68670
68705
  const row = rows.find((r) => r.pid === pid);
68671
68706
  return !!row && isPaneMagmuxCommand(row.command, paneId);
68672
68707
  }
68673
68708
  function findPaneMagmux(paneId, table) {
68674
- return (table ?? readProcessTable()).filter((r) => isPaneMagmuxCommand(r.command, paneId));
68709
+ return (table ?? readProcessTable() ?? []).filter((r) => isPaneMagmuxCommand(r.command, paneId));
68675
68710
  }
68676
68711
  function paneIdentityMatches(command, pane) {
68677
68712
  return command.includes(sessionNeedle(pane.sessionUuid)) || command.includes(launcherNeedle(pane.ctlDir));
@@ -68824,11 +68859,12 @@ function watcherArgv(a) {
68824
68859
  function isPaneWatcherCommand(command, paneId) {
68825
68860
  return command.includes(` ${WATCHER_ARGV0} ${paneId} `);
68826
68861
  }
68827
- var PS_ARGS, PS_ROW, PS_ENV, LAUNCH_DIR_RE, PANE_ID_RE, WATCHER_FUNCTIONS = `
68862
+ var PS_ARGS, PS_ROW, START_TOLERANCE_MS = 2000, PS_ENV, PS_OPTIONS, psSpawn, LAUNCH_DIR_RE, PANE_ID_RE, WATCHER_FUNCTIONS = `
68828
68863
  set -f
68829
68864
  export LC_ALL=C
68830
68865
  PANE=$1 UUID=$2 CTL=$3 SOCKP=$4 REC=$5 TURN=$6 ROOT=$7
68831
68866
  pstable() { ps -ax -ww -o pid=,pgid=,lstart=,command=; }
68867
+ ps_ok() { ps -o pid= -p $$ >/dev/null 2>&1; }
68832
68868
  mag=""
68833
68869
  mag_ok() {
68834
68870
  case "$mag" in (''|*[!0-9]*) return 1;; esac
@@ -68877,6 +68913,9 @@ launch_dir_ok() {
68877
68913
  `, WATCHER_MAIN = `
68878
68914
  while IFS= read -r l; do [ "$l" = done ] && exit 0; done
68879
68915
  # EOF without "done": the owner is gone (SIGKILL included: the kernel closed its end).
68916
+ # No readable table (a sandbox refuses the setuid ps): nothing can be verified, so nothing
68917
+ # is signalled or removed; the files stay for a sweep that can read the table.
68918
+ ps_ok || exit 1
68880
68919
  find_mag
68881
68920
  find_pg
68882
68921
  for s in TERM KILL; do
@@ -68894,9 +68933,11 @@ launch_dir_ok "$TURN" && rm -rf -- "$TURN"
68894
68933
  exit 0
68895
68934
  `, WATCHER_SCRIPT, WATCHER_ARGV0 = "claudish-pane-watcher";
68896
68935
  var init_process_identity = __esm(() => {
68897
- PS_ARGS = ["-ax", "-ww", "-o", "pid=,ppid=,pgid=,lstart=,command="];
68898
- PS_ROW = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\S+\s+\S+\s+\d+\s+\d\d:\d\d:\d\d\s+\d{4})\s?(.*)$/;
68936
+ PS_ARGS = ["-ax", "-ww", "-o", "pid=,ppid=,pgid=,etime=,lstart=,command="];
68937
+ PS_ROW = /^\s*(\d+)\s+(\d+)\s+(\d+)\s+(?:((?:\d+-)?(?:\d+:)?\d+:\d+)\s+)?(\S+\s+\S+\s+\d+\s+\d\d:\d\d:\d\d\s+\d{4})\s?(.*)$/;
68899
68938
  PS_ENV = { PATH: "/bin:/usr/bin:/usr/sbin:/sbin", LC_ALL: "C" };
68939
+ PS_OPTIONS = { env: PS_ENV, encoding: "utf8", maxBuffer: 64 * 1024 * 1024 };
68940
+ psSpawn = { execFile: execFile2, execFileSync: execFileSync2 };
68900
68941
  LAUNCH_DIR_RE = /^launch-[A-Za-z0-9]{6}$/;
68901
68942
  PANE_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
68902
68943
  WATCHER_SCRIPT = `${WATCHER_FUNCTIONS}${WATCHER_MAIN}`;
@@ -69570,7 +69611,10 @@ var init_magmux_client = __esm(() => {
69570
69611
 
69571
69612
  // src/pane/pane-registry.ts
69572
69613
  import {
69614
+ constants,
69615
+ accessSync,
69573
69616
  existsSync as existsSync31,
69617
+ lstatSync as lstatSync3,
69574
69618
  readFileSync as readFileSync29,
69575
69619
  readdirSync as readdirSync4,
69576
69620
  renameSync as renameSync4,
@@ -69582,14 +69626,21 @@ import { join as join43 } from "path";
69582
69626
  function ownerStartOfSelf() {
69583
69627
  if (ownStart)
69584
69628
  return ownStart;
69585
- const row = readProcessTable().find((r) => r.pid === process.pid);
69629
+ const row = readProcessTable()?.find((r) => r.pid === process.pid);
69586
69630
  if (row)
69587
69631
  ownStart = row.lstart;
69588
69632
  return row?.lstart ?? "";
69589
69633
  }
69590
- function ownerAlive(rec, table) {
69591
- const row = table.find((r) => r.pid === rec.ownerPid);
69592
- return !!row && row.lstart === rec.ownerStart;
69634
+ function ownerAlive(owner, table) {
69635
+ if (!table)
69636
+ return pidMayBeAlive(owner.ownerPid);
69637
+ const row = table.find((r) => r.pid === owner.ownerPid);
69638
+ if (!row)
69639
+ return false;
69640
+ if (owner.ownerStart)
69641
+ return row.lstart === owner.ownerStart;
69642
+ const minted = ownerOfPaneId(owner.paneId);
69643
+ return !minted || startedAt(row, minted.startMs);
69593
69644
  }
69594
69645
  function recordsDir(root) {
69595
69646
  return join43(root, "panes");
@@ -69722,7 +69773,9 @@ async function tick() {
69722
69773
  return;
69723
69774
  ticking = true;
69724
69775
  try {
69725
- refreshGroups(await readProcessTableAsync());
69776
+ const table = await readProcessTableAsync();
69777
+ if (table)
69778
+ refreshGroups(table);
69726
69779
  for (const p of live.values())
69727
69780
  if (p.reapFailed)
69728
69781
  await p.retryReap();
@@ -69824,9 +69877,9 @@ function sweepTargets(rec, root, table) {
69824
69877
  return { mag: m.mag, group, unverified: m.unverified || groupImpostor };
69825
69878
  }
69826
69879
  async function killVerified(rec, root) {
69827
- const t = sweepTargets(rec, root, readProcessTable());
69880
+ const t = sweepTargets(rec, root, readProcessTable() ?? []);
69828
69881
  for (const sig of ["SIGTERM", "SIGKILL"]) {
69829
- const table = readProcessTable();
69882
+ const table = readProcessTable() ?? [];
69830
69883
  if (t.group && groupCheck(table, t.group))
69831
69884
  signal(-t.group.pgid, sig);
69832
69885
  for (const pid of liveEscaped(table, t.group))
@@ -69839,12 +69892,15 @@ async function killVerified(rec, root) {
69839
69892
  }
69840
69893
  async function sweepRecord(rec, root, out) {
69841
69894
  const table = readProcessTable();
69842
- if (!processTableTrusted(table)) {
69843
- out.kept.push(rec.paneId);
69895
+ if (ownerAlive(rec, table)) {
69896
+ if (!table)
69897
+ out.kept.push(rec.paneId);
69844
69898
  return;
69845
69899
  }
69846
- if (ownerAlive(rec, table))
69900
+ if (!table) {
69901
+ await sweepUnidentifiable(rec, root, out);
69847
69902
  return;
69903
+ }
69848
69904
  const watcher = rec.watcherPid ? table.find((r) => r.pid === rec.watcherPid) : undefined;
69849
69905
  if (watcher && isPaneWatcherCommand(watcher.command, rec.paneId)) {
69850
69906
  out.kept.push(rec.paneId);
@@ -69855,11 +69911,7 @@ async function sweepRecord(rec, root, out) {
69855
69911
  if (anyVerified)
69856
69912
  await killVerified(rec, root);
69857
69913
  const after = readProcessTable();
69858
- if (!processTableTrusted(after)) {
69859
- out.kept.push(rec.paneId);
69860
- return;
69861
- }
69862
- const stillAlive = t0.group && groupCheck(after, t0.group) || liveEscaped(after, t0.group).length > 0 || t0.mag !== null && isPaneMagmux(t0.mag, rec.paneId, after);
69914
+ const stillAlive = !after || t0.group && groupCheck(after, t0.group) || liveEscaped(after, t0.group).length > 0 || t0.mag !== null && isPaneMagmux(t0.mag, rec.paneId, after);
69863
69915
  if (stillAlive) {
69864
69916
  out.kept.push(rec.paneId);
69865
69917
  return;
@@ -69872,40 +69924,96 @@ async function sweepRecord(rec, root, out) {
69872
69924
  else
69873
69925
  out.cleaned.push(rec.paneId);
69874
69926
  }
69927
+ async function probeSocket(sockPath, magmuxMayLive) {
69928
+ const dial = dialSocket(sockPath);
69929
+ let timer;
69930
+ const timeout = new Promise((resolve) => {
69931
+ timer = setTimeout(() => resolve("timeout"), SOCKET_PROBE_TIMEOUT_MS);
69932
+ });
69933
+ try {
69934
+ const won = await Promise.race([dial, timeout]);
69935
+ if (won !== "timeout")
69936
+ return { state: "answers", client: won };
69937
+ dial.then((c) => c.close(), () => {
69938
+ return;
69939
+ });
69940
+ return { state: "inconclusive", code: "ETIMEDOUT" };
69941
+ } catch (e) {
69942
+ const code = dialErrno(e.errno ?? "unknown", sockPath);
69943
+ const stale = code === "ENOENT" || code === "ECONNREFUSED" && !magmuxMayLive;
69944
+ return stale ? { state: "stale", code } : { state: "inconclusive", code };
69945
+ } finally {
69946
+ clearTimeout(timer);
69947
+ }
69948
+ }
69949
+ function dialErrno(reported, sockPath) {
69950
+ if (reported !== "ENOENT")
69951
+ return reported;
69952
+ let isSocket;
69953
+ try {
69954
+ isSocket = lstatSync3(sockPath).isSocket();
69955
+ } catch (e) {
69956
+ return e.code ?? "unknown";
69957
+ }
69958
+ if (!isSocket)
69959
+ return "ENOTSOCK";
69960
+ try {
69961
+ accessSync(sockPath, constants.W_OK);
69962
+ } catch {
69963
+ return "EACCES";
69964
+ }
69965
+ return "ECONNREFUSED";
69966
+ }
69967
+ async function sweepUnidentifiable(rec, root, out) {
69968
+ if (rec.watcherPid && pidMayBeAlive(rec.watcherPid)) {
69969
+ out.kept.push(rec.paneId);
69970
+ return;
69971
+ }
69972
+ const magmuxMayLive = rec.magmuxPid === null || pidMayBeAlive(rec.magmuxPid);
69973
+ const probe = await probeSocket(sockPathOf(root, rec.paneId), magmuxMayLive);
69974
+ if (probe.state !== "stale") {
69975
+ if (probe.state === "answers")
69976
+ probe.client.close();
69977
+ out.kept.push(rec.paneId);
69978
+ return;
69979
+ }
69980
+ removePaneFiles(root, rec);
69981
+ out.cleaned.push(rec.paneId);
69982
+ }
69875
69983
  function ownerOfPaneId(id) {
69876
69984
  const m = id.match(/^c(\d+)-([0-9a-z]+)-/);
69877
69985
  if (!m)
69878
69986
  return null;
69879
69987
  return { pid: Number(m[1]), startMs: Number.parseInt(m[2] ?? "", 36) };
69880
69988
  }
69881
- function ownerOfIdAlive(id, table) {
69989
+ function ownerOfSocketId(id) {
69882
69990
  const o = ownerOfPaneId(id);
69883
- if (!o)
69884
- return true;
69885
- const row = table.find((r) => r.pid === o.pid);
69886
- if (!row)
69887
- return false;
69888
- const started = Date.parse(row.lstart);
69889
- return !Number.isFinite(started) || Math.abs(started - o.startMs) < 2000;
69991
+ return o ? { paneId: id, ownerPid: o.pid, ownerStart: "" } : null;
69890
69992
  }
69891
69993
  async function sweepRecordlessSocket(root, name, out) {
69892
69994
  const id = name.slice("magmux-".length, -".sock".length);
69893
69995
  const table = readProcessTable();
69894
- if (!processTableTrusted(table)) {
69895
- out.kept.push(id);
69896
- return;
69897
- }
69898
- if (ownerOfIdAlive(id, table))
69996
+ const owner = ownerOfSocketId(id);
69997
+ if (!owner || ownerAlive(owner, table))
69899
69998
  return;
69900
69999
  const sockPath = join43(root, name);
69901
- let client = null;
69902
- try {
69903
- client = await MagmuxClient.dial(sockPath);
69904
- } catch {
70000
+ const magmuxMayLive = !table || table.some((r) => isPaneMagmuxCommand(r.command, id));
70001
+ const probe = await probeSocket(sockPath, magmuxMayLive);
70002
+ if (probe.state === "stale") {
69905
70003
  rmSync6(sockPath, { force: true });
69906
70004
  out.cleaned.push(id);
69907
70005
  return;
69908
70006
  }
70007
+ if (probe.state === "inconclusive") {
70008
+ out.kept.push(id);
70009
+ return;
70010
+ }
70011
+ const client = probe.client;
70012
+ if (!table) {
70013
+ client.close();
70014
+ out.kept.push(id);
70015
+ return;
70016
+ }
69909
70017
  const list = await client.request({
69910
70018
  type: "list"
69911
70019
  });
@@ -69948,7 +70056,7 @@ async function sweepOrphanPanes(root = sockRootFor()) {
69948
70056
  }
69949
70057
  return out;
69950
70058
  }
69951
- var MAX_LIVE_PANES = 48, PaneLimitError, ownStart = null, live, reserved = 0, ticker = null, ticking = false, hookOpts, hooksInstalled = false, stdinHooked = false, shuttingDown = false, SIGNALS, sweptRoots;
70059
+ var MAX_LIVE_PANES = 48, PaneLimitError, ownStart = null, live, reserved = 0, ticker = null, ticking = false, hookOpts, hooksInstalled = false, stdinHooked = false, shuttingDown = false, SIGNALS, SOCKET_PROBE_TIMEOUT_MS = 2000, dialSocket = (p) => MagmuxClient.dial(p), sweptRoots;
69952
70060
  var init_pane_registry = __esm(() => {
69953
70061
  init_magmux_client();
69954
70062
  init_pane_launch();
@@ -72225,7 +72333,10 @@ class PaneSessionImpl {
72225
72333
  setPanePid(pid) {
72226
72334
  this.panePidValue = pid;
72227
72335
  updateRecord(this.root, this.paneId, { panePid: pid });
72228
- readProcessTableAsync().then((t) => refreshGroupOf(this, t));
72336
+ readProcessTableAsync().then((t) => {
72337
+ if (t)
72338
+ refreshGroupOf(this, t);
72339
+ });
72229
72340
  }
72230
72341
  onFrame(f) {
72231
72342
  if (f.pane !== undefined && f.pane !== 0)
@@ -74161,6 +74272,8 @@ ${screenTailOf(this.screen)}`
74161
74272
  }
74162
74273
  async captureGroupBeforeReap() {
74163
74274
  const table = await readProcessTableAsync();
74275
+ if (!table)
74276
+ return;
74164
74277
  if (!this.panePidValue && this.magmux?.pid) {
74165
74278
  const lead = table.find((r) => r.ppid === this.magmux?.pid && r.pgid === r.pid);
74166
74279
  if (lead) {
@@ -74175,12 +74288,16 @@ ${screenTailOf(this.screen)}`
74175
74288
  if (!this.group)
74176
74289
  return false;
74177
74290
  const table = await readProcessTableAsync();
74291
+ if (!table)
74292
+ return true;
74178
74293
  return groupCheck(table, this.group) || liveEscaped(table, this.group).length > 0;
74179
74294
  }
74180
74295
  async backstopTargets() {
74181
74296
  if (!this.group)
74182
74297
  return [];
74183
74298
  const table = await readProcessTableAsync();
74299
+ if (!table)
74300
+ return [];
74184
74301
  return [
74185
74302
  ...groupCheck(table, this.group) ? [-this.group.pgid] : [],
74186
74303
  ...liveEscaped(table, this.group)
@@ -74980,7 +75097,7 @@ var init_session_discovery = __esm(() => {
74980
75097
  import { randomBytes as randomBytes8, randomUUID as randomUUID6 } from "crypto";
74981
75098
  import {
74982
75099
  existsSync as existsSync33,
74983
- lstatSync as lstatSync3,
75100
+ lstatSync as lstatSync4,
74984
75101
  mkdirSync as mkdirSync21,
74985
75102
  readFileSync as readFileSync32,
74986
75103
  readdirSync as readdirSync8,
@@ -75383,7 +75500,7 @@ function validateSessionPath(sessionPath) {
75383
75500
  const tail = [];
75384
75501
  for (;; ) {
75385
75502
  try {
75386
- lstatSync3(existing);
75503
+ lstatSync4(existing);
75387
75504
  break;
75388
75505
  } catch {
75389
75506
  const parent = dirname16(existing);
@@ -84883,13 +85000,13 @@ function ProviderDetail({
84883
85000
  fg: C.blue,
84884
85001
  attributes: A.bold,
84885
85002
  children: [
84886
- "URL:",
85003
+ "API:",
84887
85004
  " "
84888
85005
  ]
84889
85006
  }),
84890
85007
  /* @__PURE__ */ jsx22("span", {
84891
85008
  fg: C.cyan,
84892
- children: activeEndpoint || selectedProvider.defaultEndpoint || "default"
85009
+ children: (activeEndpoint || selectedProvider.defaultEndpoint || "default").replace(/^https?:\/\//, "")
84893
85010
  })
84894
85011
  ]
84895
85012
  }),
@@ -90994,7 +91111,7 @@ function resolveContextWindowEnv(realWindow, processEnv = process.env) {
90994
91111
  if (processEnv[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW])
90995
91112
  return { vars };
90996
91113
  if (realWindow >= MIN_AUTO_COMPACT_WINDOW) {
90997
- vars[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW] = String(realWindow);
91114
+ vars[ENV.CLAUDE_CODE_AUTO_COMPACT_WINDOW] = String(Math.min(realWindow, MAX_AUTO_COMPACT_WINDOW));
90998
91115
  return {
90999
91116
  vars,
91000
91117
  notice: `[claudish] Auto-compact window: ${realWindow.toLocaleString()} tokens ` + "(Claude Code compacts before the backend's real limit)"
@@ -91501,7 +91618,7 @@ var restoreTerminal = null, macosKeychainAnthropicResult, defaultKeychainAnthrop
91501
91618
  macosKeychainAnthropicResult = false;
91502
91619
  }
91503
91620
  return macosKeychainAnthropicResult;
91504
- }, CLAUDISH_PLACEHOLDER_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx", CLAUDISH_PLACEHOLDER_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth", STALE_TOKEN_FILE_MS, MAX_TOKEN_FILES_SCANNED = 4000, CLAUDE_CODE_DEFAULT_MAX_CONTEXT = 200000, USER_STATUS_LINE_TIMEOUT_SECONDS = 3, MIN_AUTO_COMPACT_WINDOW = 200000, ADVISOR_TOOL_ENV_VAR = "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL", CLAUDISH_CHILD_ADVISOR_MODEL = "sonnet", CHILD_STDERR_NOISE, SIGNAL_EXIT_NUMBERS;
91621
+ }, CLAUDISH_PLACEHOLDER_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx", CLAUDISH_PLACEHOLDER_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth", STALE_TOKEN_FILE_MS, MAX_TOKEN_FILES_SCANNED = 4000, CLAUDE_CODE_DEFAULT_MAX_CONTEXT = 200000, USER_STATUS_LINE_TIMEOUT_SECONDS = 3, MIN_AUTO_COMPACT_WINDOW = 200000, MAX_AUTO_COMPACT_WINDOW = 1e6, ADVISOR_TOOL_ENV_VAR = "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL", CLAUDISH_CHILD_ADVISOR_MODEL = "sonnet", CHILD_STDERR_NOISE, SIGNAL_EXIT_NUMBERS;
91505
91622
  var init_claude_runner = __esm(() => {
91506
91623
  init_model_catalog();
91507
91624
  init_config();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "13.0.1",
3
+ "version": "13.0.3",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -69,10 +69,10 @@
69
69
  "ai"
70
70
  ],
71
71
  "optionalDependencies": {
72
- "@claudish/magmux-darwin-arm64": "13.0.1",
73
- "@claudish/magmux-darwin-x64": "13.0.1",
74
- "@claudish/magmux-linux-arm64": "13.0.1",
75
- "@claudish/magmux-linux-x64": "13.0.1"
72
+ "@claudish/magmux-darwin-arm64": "13.0.3",
73
+ "@claudish/magmux-darwin-x64": "13.0.3",
74
+ "@claudish/magmux-linux-arm64": "13.0.3",
75
+ "@claudish/magmux-linux-x64": "13.0.3"
76
76
  },
77
77
  "author": "Jack Rudenko <i@madappgang.com>",
78
78
  "license": "MIT",