claudish 7.38.0 → 7.39.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 +899 -509
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -729,7 +729,7 @@ var init_onepassword_config = __esm(() => {
729
729
  });
730
730
 
731
731
  // src/version.ts
732
- var VERSION = "7.38.0";
732
+ var VERSION = "7.39.0";
733
733
 
734
734
  // src/logger.ts
735
735
  var exports_logger = {};
@@ -30173,11 +30173,6 @@ function getGeminiTierDisplayName() {
30173
30173
  return "GeminiCA";
30174
30174
  return TIER_SHORT_NAMES[cachedTierId] || cachedTierId.replace(/-tier$/, "");
30175
30175
  }
30176
- function getGeminiTierFullName() {
30177
- if (cachedTierName)
30178
- return cachedTierName;
30179
- return getGeminiTierDisplayName();
30180
- }
30181
30176
  function makeTerminalSetupError(message) {
30182
30177
  const err = new Error(message);
30183
30178
  err.terminal = true;
@@ -34562,6 +34557,461 @@ var init_dialect_manager = __esm(() => {
34562
34557
  init_xiaomi_model_dialect();
34563
34558
  });
34564
34559
 
34560
+ // src/auth/quota/types.ts
34561
+ function isPlanStale(plan, now = Date.now()) {
34562
+ const observed = Date.parse(plan.observed_at);
34563
+ if (Number.isNaN(observed))
34564
+ return true;
34565
+ return now - observed > PLAN_TTL_MS;
34566
+ }
34567
+ function toUsedPct(value) {
34568
+ if (!Number.isFinite(value))
34569
+ return;
34570
+ return Math.max(0, Math.min(100, Math.round(value)));
34571
+ }
34572
+ function epochSecondsToIso(seconds) {
34573
+ if (!Number.isFinite(seconds) || seconds <= 0)
34574
+ return;
34575
+ const ms = seconds * 1000;
34576
+ const d = new Date(ms);
34577
+ return Number.isNaN(d.getTime()) ? undefined : d.toISOString();
34578
+ }
34579
+ var PLAN_TTL_MS, PLAN_POLL_INTERVAL_MS;
34580
+ var init_types2 = __esm(() => {
34581
+ PLAN_TTL_MS = 15 * 60 * 1000;
34582
+ PLAN_POLL_INTERVAL_MS = 5 * 60 * 1000;
34583
+ });
34584
+
34585
+ // src/auth/quota/sources/antigravity.ts
34586
+ function shortenModelId(modelId) {
34587
+ return modelId.replace(/^gemini-/, "").replace(/-preview/, "").replace(/-latest$/, "");
34588
+ }
34589
+ function usedPctOf(bucket) {
34590
+ if (typeof bucket.remainingFraction !== "number")
34591
+ return;
34592
+ return toUsedPct((1 - bucket.remainingFraction) * 100);
34593
+ }
34594
+ function selectBucket(buckets, activeModelId) {
34595
+ const usable = buckets.filter((b) => b.modelId && usedPctOf(b) !== undefined);
34596
+ if (usable.length === 0)
34597
+ return;
34598
+ const exact = usable.find((b) => b.modelId === activeModelId);
34599
+ if (exact)
34600
+ return exact;
34601
+ for (const tier of REASONING_TIERS) {
34602
+ const suffix = `-${tier}`;
34603
+ if (!activeModelId.endsWith(suffix))
34604
+ continue;
34605
+ const base = activeModelId.slice(0, -suffix.length);
34606
+ const match = usable.find((b) => b.modelId === base);
34607
+ if (match)
34608
+ return match;
34609
+ }
34610
+ return;
34611
+ }
34612
+ function windowFromBucket(bucket) {
34613
+ const used = usedPctOf(bucket);
34614
+ if (used === undefined)
34615
+ return;
34616
+ const window2 = {
34617
+ id: shortenModelId(bucket.modelId ?? "quota"),
34618
+ used_pct: used
34619
+ };
34620
+ if (bucket.resetTime && !Number.isNaN(Date.parse(bucket.resetTime))) {
34621
+ window2.resets_at = new Date(bucket.resetTime).toISOString();
34622
+ }
34623
+ return window2;
34624
+ }
34625
+ function planFromBuckets(buckets, activeModelId) {
34626
+ const windows = [];
34627
+ if (activeModelId) {
34628
+ const bucket = selectBucket(buckets, activeModelId);
34629
+ if (!bucket)
34630
+ return;
34631
+ const w = windowFromBucket(bucket);
34632
+ if (w)
34633
+ windows.push(w);
34634
+ } else {
34635
+ for (const b of buckets) {
34636
+ const w = windowFromBucket(b);
34637
+ if (w)
34638
+ windows.push(w);
34639
+ }
34640
+ }
34641
+ if (windows.length === 0)
34642
+ return;
34643
+ return {
34644
+ label: getAntigravityTierDisplayName(),
34645
+ windows,
34646
+ source: "provider",
34647
+ observed_at: new Date().toISOString()
34648
+ };
34649
+ }
34650
+ async function fetchPlan(ctx) {
34651
+ try {
34652
+ const accessToken = await getValidAntigravityAccessToken();
34653
+ const { projectId } = await setupAntigravityUser(accessToken);
34654
+ const quota = await retrieveUserQuota(accessToken, projectId);
34655
+ if (!quota?.buckets?.length)
34656
+ return;
34657
+ return planFromBuckets(quota.buckets, ctx?.modelId);
34658
+ } catch (err) {
34659
+ log(`[quota:antigravity] fetch failed: ${err}`);
34660
+ return;
34661
+ }
34662
+ }
34663
+ var REASONING_TIERS, antigravityQuotaAdapter;
34664
+ var init_antigravity2 = __esm(() => {
34665
+ init_logger();
34666
+ init_antigravity_token();
34667
+ init_gemini_oauth();
34668
+ init_types2();
34669
+ REASONING_TIERS = ["extra-low", "medium", "tiered", "high", "low"];
34670
+ antigravityQuotaAdapter = {
34671
+ providerId: "antigravity",
34672
+ label: "Antigravity",
34673
+ capability() {
34674
+ return { kind: "endpoint" };
34675
+ },
34676
+ isAvailable() {
34677
+ try {
34678
+ return hasSharedAntigravityToken();
34679
+ } catch {
34680
+ return false;
34681
+ }
34682
+ },
34683
+ poll(ctx) {
34684
+ return fetchPlan(ctx);
34685
+ },
34686
+ fetchExplicit(ctx) {
34687
+ return fetchPlan(ctx);
34688
+ }
34689
+ };
34690
+ });
34691
+
34692
+ // src/auth/quota/sources/codex.ts
34693
+ import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
34694
+ import { homedir as homedir16 } from "os";
34695
+ import { join as join16 } from "path";
34696
+ function formatWindowMinutes(minutes) {
34697
+ if (!Number.isFinite(minutes) || minutes <= 0)
34698
+ return "";
34699
+ if (minutes % 1440 === 0)
34700
+ return `${minutes / 1440}d`;
34701
+ if (minutes % 60 === 0)
34702
+ return `${minutes / 60}h`;
34703
+ if (minutes < 60)
34704
+ return `${minutes}m`;
34705
+ const hours = Math.floor(minutes / 60);
34706
+ return `${hours}h${minutes % 60}m`;
34707
+ }
34708
+ function credentialsPath() {
34709
+ return join16(homedir16(), ".claudish", "codex-oauth.json");
34710
+ }
34711
+ function planLabel(planType) {
34712
+ if (!planType)
34713
+ return "Codex";
34714
+ const pretty = planType.charAt(0).toUpperCase() + planType.slice(1);
34715
+ return `Codex ${pretty}`;
34716
+ }
34717
+ function windowFrom(headers, slot) {
34718
+ const raw = headers.get(slot.pct);
34719
+ if (raw === null)
34720
+ return;
34721
+ const pct = toUsedPct(Number.parseFloat(raw));
34722
+ if (pct === undefined)
34723
+ return;
34724
+ const minutesRaw = headers.get(slot.minutes);
34725
+ let id = slot.fallbackId;
34726
+ if (minutesRaw !== null) {
34727
+ const minutes = Number.parseInt(minutesRaw, 10);
34728
+ if (Number.isFinite(minutes) && minutes <= 0)
34729
+ return;
34730
+ const formatted = formatWindowMinutes(minutes);
34731
+ if (formatted)
34732
+ id = formatted;
34733
+ }
34734
+ const window2 = { id, used_pct: pct };
34735
+ const resetRaw = headers.get(slot.reset);
34736
+ if (resetRaw !== null) {
34737
+ const iso = epochSecondsToIso(Number.parseInt(resetRaw, 10));
34738
+ if (iso)
34739
+ window2.resets_at = iso;
34740
+ }
34741
+ return window2;
34742
+ }
34743
+ function scrapeCodexHeaders(headers) {
34744
+ const windows = [];
34745
+ for (const slot of WINDOW_SLOTS) {
34746
+ const w = windowFrom(headers, slot);
34747
+ if (w)
34748
+ windows.push(w);
34749
+ }
34750
+ if (windows.length === 0)
34751
+ return;
34752
+ return {
34753
+ label: planLabel(headers.get(H_PLAN)),
34754
+ windows,
34755
+ source: "provider",
34756
+ observed_at: new Date().toISOString()
34757
+ };
34758
+ }
34759
+ function resolveProbeModel() {
34760
+ try {
34761
+ const cachePath = join16(homedir16(), ".codex", "models_cache.json");
34762
+ if (!existsSync14(cachePath))
34763
+ return;
34764
+ const cache2 = JSON.parse(readFileSync11(cachePath, "utf-8"));
34765
+ for (const m of cache2.models ?? []) {
34766
+ const slug = m?.slug ?? m?.id;
34767
+ if (typeof slug === "string" && slug.length > 0)
34768
+ return slug;
34769
+ }
34770
+ } catch {}
34771
+ return;
34772
+ }
34773
+ function readCodexCredentials() {
34774
+ try {
34775
+ const path = credentialsPath();
34776
+ if (!existsSync14(path))
34777
+ return;
34778
+ return JSON.parse(readFileSync11(path, "utf-8"));
34779
+ } catch {
34780
+ return;
34781
+ }
34782
+ }
34783
+ var H_PLAN = "x-codex-plan-type", WINDOW_SLOTS, codexQuotaAdapter;
34784
+ var init_codex = __esm(() => {
34785
+ init_logger();
34786
+ init_types2();
34787
+ WINDOW_SLOTS = [
34788
+ {
34789
+ pct: "x-codex-primary-used-percent",
34790
+ reset: "x-codex-primary-reset-at",
34791
+ minutes: "x-codex-primary-window-minutes",
34792
+ fallbackId: "primary"
34793
+ },
34794
+ {
34795
+ pct: "x-codex-secondary-used-percent",
34796
+ reset: "x-codex-secondary-reset-at",
34797
+ minutes: "x-codex-secondary-window-minutes",
34798
+ fallbackId: "secondary"
34799
+ }
34800
+ ];
34801
+ codexQuotaAdapter = {
34802
+ providerId: "openai-codex",
34803
+ label: "Codex",
34804
+ capability() {
34805
+ return { kind: "headers" };
34806
+ },
34807
+ isAvailable() {
34808
+ try {
34809
+ return existsSync14(credentialsPath());
34810
+ } catch {
34811
+ return false;
34812
+ }
34813
+ },
34814
+ scrape(response) {
34815
+ return scrapeCodexHeaders(response.headers);
34816
+ },
34817
+ async fetchExplicit(_ctx) {
34818
+ const creds = readCodexCredentials();
34819
+ if (!creds?.access_token)
34820
+ return;
34821
+ const model = resolveProbeModel();
34822
+ if (!model) {
34823
+ log("[quota:codex] no model available to probe with \u2014 is the Codex CLI signed in?");
34824
+ return;
34825
+ }
34826
+ try {
34827
+ const res = await fetch("https://chatgpt.com/backend-api/codex/responses", {
34828
+ method: "POST",
34829
+ headers: {
34830
+ Authorization: `Bearer ${creds.access_token}`,
34831
+ "chatgpt-account-id": creds.account_id || "",
34832
+ "Content-Type": "application/json",
34833
+ Accept: "text/event-stream",
34834
+ originator: "codex",
34835
+ "OpenAI-Beta": "responses"
34836
+ },
34837
+ body: JSON.stringify({
34838
+ model,
34839
+ instructions: "Reply with just: ok",
34840
+ input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] }],
34841
+ stream: true,
34842
+ store: false
34843
+ })
34844
+ });
34845
+ const plan = scrapeCodexHeaders(res.headers);
34846
+ try {
34847
+ await res.text();
34848
+ } catch {}
34849
+ return plan;
34850
+ } catch (err) {
34851
+ log(`[quota:codex] explicit fetch failed: ${err}`);
34852
+ return;
34853
+ }
34854
+ }
34855
+ };
34856
+ });
34857
+
34858
+ // src/auth/quota/registry.ts
34859
+ function unsupported(providerId, label, evidence) {
34860
+ return {
34861
+ providerId,
34862
+ label,
34863
+ capability() {
34864
+ return { kind: "none", evidence };
34865
+ },
34866
+ isAvailable: () => false
34867
+ };
34868
+ }
34869
+ function resolveQuotaAdapter(providerId) {
34870
+ if (!providerId)
34871
+ return;
34872
+ return BY_ID.get(providerId);
34873
+ }
34874
+ function allQuotaAdapters() {
34875
+ return ADAPTERS;
34876
+ }
34877
+ var PROBED_ON = "2026-08-05", NO_SURFACE, ADAPTERS, BY_ID;
34878
+ var init_registry = __esm(() => {
34879
+ init_antigravity2();
34880
+ init_codex();
34881
+ NO_SURFACE = [
34882
+ {
34883
+ id: "glm-coding",
34884
+ label: "GLM Coding Plan",
34885
+ evidence: {
34886
+ researched_at: PROBED_ON,
34887
+ probed: [
34888
+ {
34889
+ what: "10 candidate usage endpoints under api.z.ai",
34890
+ result: "404, or HTTP 200 wrapping an error envelope"
34891
+ },
34892
+ {
34893
+ what: "/api/biz/customer/{usage,info,quota,package,subscription,balance}",
34894
+ result: 'all six return an identical {"code":500,"msg":"\u7CFB\u7EDF\u5F02\u5E38"} under HTTP 200 \u2014 a catch-all handler, not six routes'
34895
+ },
34896
+ {
34897
+ what: "POST /api/coding/paas/v4/chat/completions (200)",
34898
+ result: "11 response headers, none quota-related"
34899
+ }
34900
+ ],
34901
+ conclusion: "no-surface",
34902
+ recheck_if: "Z.AI opens the biz/customer prefix to API keys \u2014 it exists but appears to require a portal session token"
34903
+ }
34904
+ },
34905
+ {
34906
+ id: "kimi-coding",
34907
+ label: "Kimi Coding Plan",
34908
+ evidence: {
34909
+ researched_at: PROBED_ON,
34910
+ probed: [
34911
+ {
34912
+ what: "18 candidate paths on api.kimi.com and api.moonshot.ai",
34913
+ result: "404 except /coding/v1/me"
34914
+ },
34915
+ {
34916
+ what: "GET /coding/v1/me (200)",
34917
+ result: 'profile only \u2014 carries a plan LABEL (user_level_name, e.g. "Vivace") but no usage numbers'
34918
+ },
34919
+ {
34920
+ what: "POST /coding/v1/messages (200)",
34921
+ result: "11 response headers, none quota-related"
34922
+ },
34923
+ {
34924
+ what: "POST /coding/v1/messages once the plan was exhausted (403)",
34925
+ result: `the error BODY reports exhaustion \u2014 "You've reached your usage limit for this billing cycle" \u2014 so the binary exhausted/not-exhausted state is observable, but no percentage and no reset timestamp is ever exposed`
34926
+ }
34927
+ ],
34928
+ conclusion: "no-surface",
34929
+ recheck_if: "Moonshot adds a usage endpoint beside the working /coding/v1/me"
34930
+ }
34931
+ },
34932
+ {
34933
+ id: "minimax-coding",
34934
+ label: "MiniMax Coding Plan",
34935
+ evidence: {
34936
+ researched_at: PROBED_ON,
34937
+ probed: [
34938
+ {
34939
+ what: "7 candidate usage endpoints on api.minimax.io",
34940
+ result: "404 page not found (plain text \u2014 a router miss)"
34941
+ },
34942
+ {
34943
+ what: "POST /anthropic/v1/messages (200)",
34944
+ result: "15 response headers, all transport/tracing"
34945
+ }
34946
+ ],
34947
+ conclusion: "no-surface",
34948
+ recheck_if: "re-probe with MINIMAX_CODING_API_KEY \u2014 the 2026-08-05 run fell back to MINIMAX_API_KEY, though a 404 is a routing verdict rather than an auth one"
34949
+ }
34950
+ },
34951
+ {
34952
+ id: "opencode-zen-go",
34953
+ label: "OpenCode Zen Go",
34954
+ evidence: {
34955
+ researched_at: PROBED_ON,
34956
+ probed: [
34957
+ {
34958
+ what: "6 candidate usage endpoints under opencode.ai/zen",
34959
+ result: "the marketing site's HTML 404 \u2014 no API route exists there"
34960
+ },
34961
+ {
34962
+ what: "POST /zen/go/v1/chat/completions (200)",
34963
+ result: "8 response headers, all Cloudflare/transport"
34964
+ }
34965
+ ],
34966
+ conclusion: "no-surface"
34967
+ }
34968
+ },
34969
+ {
34970
+ id: "sakana-subscription",
34971
+ label: "Sakana Fugu Subscription",
34972
+ evidence: {
34973
+ researched_at: PROBED_ON,
34974
+ probed: [
34975
+ {
34976
+ what: "5 candidate usage endpoints on api.sakana.ai",
34977
+ result: "clean OpenAI-style JSON 404s"
34978
+ },
34979
+ {
34980
+ what: "POST /v1/chat/completions (200, max_tokens=16)",
34981
+ result: "6 response headers, none quota-related \u2014 re-run after a max_tokens=1 attempt was rejected with 400"
34982
+ }
34983
+ ],
34984
+ conclusion: "no-surface"
34985
+ }
34986
+ },
34987
+ {
34988
+ id: "qwen-cloud",
34989
+ label: "Qwen Plan",
34990
+ evidence: {
34991
+ researched_at: "2026-08-03",
34992
+ probed: [
34993
+ {
34994
+ what: "8 candidate usage endpoints on token-plan.ap-southeast-1.maas.aliyuncs.com",
34995
+ result: "all 404"
34996
+ },
34997
+ {
34998
+ what: "POST /v1/messages (200)",
34999
+ result: "no x-ratelimit-* headers \u2014 only x-envoy-upstream-service-time and x-request-id"
35000
+ }
35001
+ ],
35002
+ conclusion: "no-surface",
35003
+ recheck_if: "Alibaba Model Studio ships a usage surface, or a console/portal API is found"
35004
+ }
35005
+ }
35006
+ ];
35007
+ ADAPTERS = [
35008
+ codexQuotaAdapter,
35009
+ antigravityQuotaAdapter,
35010
+ ...NO_SURFACE.map((p) => unsupported(p.id, p.label, p.evidence))
35011
+ ];
35012
+ BY_ID = new Map(ADAPTERS.map((a) => [a.providerId, a]));
35013
+ });
35014
+
34565
35015
  // src/behavior/config.ts
34566
35016
  function parseBehaviorConfig(raw) {
34567
35017
  if (raw === undefined || raw === null)
@@ -34737,8 +35187,8 @@ var init_harness = __esm(() => {
34737
35187
 
34738
35188
  // src/behavior/journal.ts
34739
35189
  import { appendFile as appendFile2, mkdir, readFile, rename, stat, writeFile } from "fs/promises";
34740
- import { homedir as homedir16 } from "os";
34741
- import { dirname as dirname6, join as join16 } from "path";
35190
+ import { homedir as homedir17 } from "os";
35191
+ import { dirname as dirname6, join as join17 } from "path";
34742
35192
  function classifyPath(observed, expected) {
34743
35193
  if (!observed)
34744
35194
  return "not_applicable";
@@ -34750,7 +35200,7 @@ function classifyPath(observed, expected) {
34750
35200
  return dirOf(observed) === dirOf(expected) ? "same_dir_wrong_name" : "outside_expected_dir";
34751
35201
  }
34752
35202
  function journalPath() {
34753
- return join16(homedir16(), ".claudish", "behavior-journal.jsonl");
35203
+ return join17(homedir17(), ".claudish", "behavior-journal.jsonl");
34754
35204
  }
34755
35205
  async function prune(path) {
34756
35206
  const content = await readFile(path, "utf8");
@@ -34811,8 +35261,8 @@ __export(exports_aggregate, {
34811
35261
  });
34812
35262
  import { createHash as createHash4, randomBytes as randomBytes4 } from "crypto";
34813
35263
  import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync7 } from "fs";
34814
- import { homedir as homedir17 } from "os";
34815
- import { dirname as dirname7, join as join17 } from "path";
35264
+ import { homedir as homedir18 } from "os";
35265
+ import { dirname as dirname7, join as join18 } from "path";
34816
35266
  function contextBucket(inputTokens) {
34817
35267
  if (inputTokens < 50000)
34818
35268
  return "0-50k";
@@ -34930,7 +35380,7 @@ function pendingReports() {
34930
35380
  return [...sessions.values()].map(toReport);
34931
35381
  }
34932
35382
  function outboxPath() {
34933
- return join17(homedir17(), ".claudish", "behavior-outbox.jsonl");
35383
+ return join18(homedir18(), ".claudish", "behavior-outbox.jsonl");
34934
35384
  }
34935
35385
  function spoolPendingSync(path = outboxPath()) {
34936
35386
  if (sessions.size === 0)
@@ -35153,10 +35603,10 @@ __export(exports_live_log, {
35153
35603
  recordLiveDivergence: () => recordLiveDivergence
35154
35604
  });
35155
35605
  import { appendFile as appendFile3 } from "fs/promises";
35156
- import { homedir as homedir18 } from "os";
35157
- import { join as join18 } from "path";
35606
+ import { homedir as homedir19 } from "os";
35607
+ import { join as join19 } from "path";
35158
35608
  function defaultPath() {
35159
- return join18(homedir18(), ".claudish", "behavior-divergences.jsonl");
35609
+ return join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
35160
35610
  }
35161
35611
  async function recordLiveDivergence(entry, path = defaultPath()) {
35162
35612
  try {
@@ -35813,9 +36263,9 @@ var init_hooks = __esm(() => {
35813
36263
  });
35814
36264
 
35815
36265
  // src/behavior/observer/corpus.ts
35816
- import { appendFileSync as appendFileSync3, readFileSync as readFileSync11, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
35817
- import { homedir as homedir19 } from "os";
35818
- import { join as join19 } from "path";
36266
+ import { appendFileSync as appendFileSync3, readFileSync as readFileSync12, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
36267
+ import { homedir as homedir20 } from "os";
36268
+ import { join as join20 } from "path";
35819
36269
  function directoryOf2(filePath) {
35820
36270
  const slash = filePath.lastIndexOf("/");
35821
36271
  return slash > 0 ? filePath.slice(0, slash) : undefined;
@@ -35837,7 +36287,7 @@ function writeTargetsOf(row) {
35837
36287
  function replayTranscript(file2) {
35838
36288
  let text;
35839
36289
  try {
35840
- text = readFileSync11(file2, "utf8");
36290
+ text = readFileSync12(file2, "utf8");
35841
36291
  } catch {
35842
36292
  return [];
35843
36293
  }
@@ -35894,26 +36344,26 @@ function listTranscripts(root) {
35894
36344
  return files;
35895
36345
  }
35896
36346
  for (const project of projects) {
35897
- const dir = join19(root, project);
36347
+ const dir = join20(root, project);
35898
36348
  try {
35899
36349
  if (!statSync2(dir).isDirectory())
35900
36350
  continue;
35901
36351
  for (const f of readdirSync2(dir)) {
35902
36352
  if (f.endsWith(".jsonl"))
35903
- files.push(join19(dir, f));
36353
+ files.push(join20(dir, f));
35904
36354
  }
35905
36355
  } catch {}
35906
36356
  }
35907
36357
  return files;
35908
36358
  }
35909
36359
  function buildCorpus(options = {}) {
35910
- const root = options.projectsRoot ?? join19(homedir19(), ".claude", "projects");
36360
+ const root = options.projectsRoot ?? join20(homedir20(), ".claude", "projects");
35911
36361
  const files = listTranscripts(root);
35912
36362
  const records = [];
35913
36363
  for (const f of files)
35914
36364
  records.push(...replayTranscript(f));
35915
36365
  if (options.write && records.length > 0) {
35916
- const outputPath = options.outputPath ?? join19(homedir19(), ".claudish", "behavior-divergences.jsonl");
36366
+ const outputPath = options.outputPath ?? join20(homedir20(), ".claudish", "behavior-divergences.jsonl");
35917
36367
  try {
35918
36368
  appendFileSync3(outputPath, `${records.map((r) => JSON.stringify(r)).join(`
35919
36369
  `)}
@@ -36646,25 +37096,25 @@ var init_model_parser = __esm(() => {
36646
37096
 
36647
37097
  // src/stats-buffer.ts
36648
37098
  import {
36649
- existsSync as existsSync14,
37099
+ existsSync as existsSync15,
36650
37100
  mkdirSync as mkdirSync8,
36651
- readFileSync as readFileSync12,
37101
+ readFileSync as readFileSync13,
36652
37102
  renameSync,
36653
37103
  unlinkSync as unlinkSync5,
36654
37104
  writeFileSync as writeFileSync7
36655
37105
  } from "fs";
36656
- import { homedir as homedir20 } from "os";
36657
- import { join as join20 } from "path";
37106
+ import { homedir as homedir21 } from "os";
37107
+ import { join as join21 } from "path";
36658
37108
  function ensureDir() {
36659
- if (!existsSync14(CLAUDISH_DIR)) {
37109
+ if (!existsSync15(CLAUDISH_DIR)) {
36660
37110
  mkdirSync8(CLAUDISH_DIR, { recursive: true });
36661
37111
  }
36662
37112
  }
36663
37113
  function readFromDisk() {
36664
37114
  try {
36665
- if (!existsSync14(BUFFER_FILE))
37115
+ if (!existsSync15(BUFFER_FILE))
36666
37116
  return [];
36667
- const raw = readFileSync12(BUFFER_FILE, "utf-8");
37117
+ const raw = readFileSync13(BUFFER_FILE, "utf-8");
36668
37118
  const parsed = JSON.parse(raw);
36669
37119
  if (!Array.isArray(parsed.events))
36670
37120
  return [];
@@ -36689,7 +37139,7 @@ function writeToDisk(events) {
36689
37139
  ensureDir();
36690
37140
  const trimmed2 = enforceSizeCap([...events]);
36691
37141
  const payload = { version: 1, events: trimmed2 };
36692
- const tmpFile = join20(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
37142
+ const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
36693
37143
  writeFileSync7(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
36694
37144
  renameSync(tmpFile, BUFFER_FILE);
36695
37145
  memoryCache = trimmed2;
@@ -36733,7 +37183,7 @@ function clearBuffer() {
36733
37183
  try {
36734
37184
  memoryCache = [];
36735
37185
  eventsSinceLastFlush = 0;
36736
- if (existsSync14(BUFFER_FILE)) {
37186
+ if (existsSync15(BUFFER_FILE)) {
36737
37187
  unlinkSync5(BUFFER_FILE);
36738
37188
  }
36739
37189
  } catch {}
@@ -36762,8 +37212,8 @@ function syncFlushOnExit() {
36762
37212
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
36763
37213
  var init_stats_buffer = __esm(() => {
36764
37214
  BUFFER_MAX_BYTES = 64 * 1024;
36765
- CLAUDISH_DIR = join20(homedir20(), ".claudish");
36766
- BUFFER_FILE = join20(CLAUDISH_DIR, "stats-buffer.json");
37215
+ CLAUDISH_DIR = join21(homedir21(), ".claudish");
37216
+ BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
36767
37217
  process.on("exit", syncFlushOnExit);
36768
37218
  process.on("SIGTERM", () => {
36769
37219
  try {
@@ -37877,9 +38327,9 @@ function compareByReleaseDateDesc(a, b) {
37877
38327
  }
37878
38328
 
37879
38329
  // src/model-loader.ts
37880
- import { existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
37881
- import { homedir as homedir21 } from "os";
37882
- import { join as join21 } from "path";
38330
+ import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
38331
+ import { homedir as homedir22 } from "os";
38332
+ import { join as join22 } from "path";
37883
38333
  function groupRecommendedModels(entries) {
37884
38334
  const byId = new Map;
37885
38335
  const categoryOrder = new Map;
@@ -37989,9 +38439,9 @@ async function getRecommendedModels(opts = {}) {
37989
38439
  if (!forceRefresh && _cachedRecommendedModels) {
37990
38440
  return _cachedRecommendedModels;
37991
38441
  }
37992
- if (!forceRefresh && existsSync15(RECOMMENDED_MODELS_CACHE_PATH)) {
38442
+ if (!forceRefresh && existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
37993
38443
  try {
37994
- const cacheData = JSON.parse(readFileSync13(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38444
+ const cacheData = JSON.parse(readFileSync14(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
37995
38445
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
37996
38446
  _cachedRecommendedModels = cacheData;
37997
38447
  return cacheData;
@@ -38007,7 +38457,7 @@ async function getRecommendedModels(opts = {}) {
38007
38457
  if (data.models && data.models.length > 0) {
38008
38458
  _cachedRecommendedModels = data;
38009
38459
  try {
38010
- const cacheDir = join21(homedir21(), ".claudish");
38460
+ const cacheDir = join22(homedir22(), ".claudish");
38011
38461
  mkdirSync9(cacheDir, { recursive: true });
38012
38462
  writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
38013
38463
  } catch {}
@@ -38020,9 +38470,9 @@ async function getRecommendedModels(opts = {}) {
38020
38470
  function getRecommendedModelsSync() {
38021
38471
  if (_cachedRecommendedModels)
38022
38472
  return _cachedRecommendedModels;
38023
- if (existsSync15(RECOMMENDED_MODELS_CACHE_PATH)) {
38473
+ if (existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
38024
38474
  try {
38025
- const cacheData = JSON.parse(readFileSync13(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38475
+ const cacheData = JSON.parse(readFileSync14(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38026
38476
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
38027
38477
  _cachedRecommendedModels = cacheData;
38028
38478
  return cacheData;
@@ -38146,7 +38596,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
38146
38596
  var init_model_loader = __esm(() => {
38147
38597
  init_cache_ttl();
38148
38598
  FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
38149
- RECOMMENDED_MODELS_CACHE_PATH = join21(homedir21(), ".claudish", "recommended-models-cache.json");
38599
+ RECOMMENDED_MODELS_CACHE_PATH = join22(homedir22(), ".claudish", "recommended-models-cache.json");
38150
38600
  FIREBASE_SLUG_TO_PROVIDER_NAME = {
38151
38601
  openai: "openai",
38152
38602
  google: "google",
@@ -38214,6 +38664,28 @@ var init_context_window_fallback = __esm(() => {
38214
38664
  inFlight2 = new Map;
38215
38665
  });
38216
38666
 
38667
+ // src/handlers/shared/quota-exhaustion.ts
38668
+ function isQuotaExhaustionError(status, errorBody) {
38669
+ if (status !== 401 && status !== 403 && status !== 429)
38670
+ return false;
38671
+ const lower = (errorBody || "").toLowerCase();
38672
+ return EXHAUSTION_PHRASES.some((phrase) => lower.includes(phrase));
38673
+ }
38674
+ var EXHAUSTION_PHRASES;
38675
+ var init_quota_exhaustion = __esm(() => {
38676
+ EXHAUSTION_PHRASES = [
38677
+ "usage limit",
38678
+ "billing cycle",
38679
+ "quota",
38680
+ "insufficient balance",
38681
+ "insufficient_quota",
38682
+ "upgrade your plan",
38683
+ "exceeded your current",
38684
+ "out of credits",
38685
+ "credit balance"
38686
+ ];
38687
+ });
38688
+
38217
38689
  // src/handlers/shared/stream-head-sniffer.ts
38218
38690
  function isRetryableStreamError(code, type, message) {
38219
38691
  if (RETRYABLE_ERROR_CODES.has(code))
@@ -39496,8 +39968,8 @@ var init_openai_responses_sse = __esm(() => {
39496
39968
 
39497
39969
  // src/handlers/shared/token-tracker.ts
39498
39970
  import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
39499
- import { homedir as homedir22 } from "os";
39500
- import { dirname as dirname8, join as join22 } from "path";
39971
+ import { homedir as homedir23 } from "os";
39972
+ import { dirname as dirname8, join as join23 } from "path";
39501
39973
  function stripProviderPrefix(name) {
39502
39974
  const at = name.indexOf("@");
39503
39975
  return at === -1 ? name : name.slice(at + 1);
@@ -39511,7 +39983,8 @@ class TokenTracker {
39511
39983
  sessionOutputTokens = 0;
39512
39984
  lastInputTokens = 0;
39513
39985
  modelNameOverride;
39514
- quotaRemaining;
39986
+ planUsage;
39987
+ lastPlanSerialized = "";
39515
39988
  constructor(port, config2) {
39516
39989
  this.port = port;
39517
39990
  this.config = config2;
@@ -39522,8 +39995,13 @@ class TokenTracker {
39522
39995
  setProviderDisplayName(name) {
39523
39996
  this.config.providerDisplayName = name;
39524
39997
  }
39525
- setQuotaRemaining(fraction) {
39526
- this.quotaRemaining = fraction;
39998
+ setPlanUsage(plan) {
39999
+ const next = plan ? JSON.stringify(plan) : "";
40000
+ if (next === this.lastPlanSerialized)
40001
+ return;
40002
+ this.planUsage = plan;
40003
+ this.lastPlanSerialized = next;
40004
+ this.rewrite();
39527
40005
  }
39528
40006
  rewrite() {
39529
40007
  this.writeFile(this.getLastInputTokens(), this.sessionOutputTokens);
@@ -39645,11 +40123,15 @@ class TokenTracker {
39645
40123
  if (displayModel) {
39646
40124
  data.model_name = displayModel;
39647
40125
  }
39648
- if (this.quotaRemaining !== undefined) {
39649
- data.quota_remaining = this.quotaRemaining;
40126
+ if (this.planUsage && !isPlanStale(this.planUsage)) {
40127
+ data.plan = {
40128
+ label: this.planUsage.label,
40129
+ windows: this.planUsage.windows,
40130
+ source: this.planUsage.source
40131
+ };
39650
40132
  }
39651
40133
  const override = process.env.CLAUDISH_TOKEN_FILE;
39652
- const outPath = override || join22(homedir22(), ".claudish", `tokens-${this.port}.json`);
40134
+ const outPath = override || join23(homedir23(), ".claudish", `tokens-${this.port}.json`);
39653
40135
  mkdirSync10(dirname8(outPath), { recursive: true });
39654
40136
  writeFileSync9(outPath, JSON.stringify(data), "utf-8");
39655
40137
  } catch (e) {
@@ -39658,6 +40140,7 @@ class TokenTracker {
39658
40140
  }
39659
40141
  }
39660
40142
  var init_token_tracker = __esm(() => {
40143
+ init_types2();
39661
40144
  init_logger();
39662
40145
  init_remote_provider_types();
39663
40146
  });
@@ -39684,6 +40167,7 @@ class ComposedHandler {
39684
40167
  options;
39685
40168
  isInteractive;
39686
40169
  pendingFallbackMeta;
40170
+ lastPlanPollAt = 0;
39687
40171
  constructor(provider, targetModel, modelName, port, options = {}) {
39688
40172
  if (modelName.includes("@")) {
39689
40173
  throw new Error(`ComposedHandler: modelName must not contain '@' (got "${modelName}"). Strip the provider routing prefix before passing modelName. If you need the full routed form, pass it as targetModel.`);
@@ -39849,12 +40333,6 @@ class ComposedHandler {
39849
40333
  if (this.provider.displayName) {
39850
40334
  this.tokenTracker.setProviderDisplayName(this.provider.displayName);
39851
40335
  }
39852
- if (typeof this.provider.getQuotaRemaining === "function") {
39853
- await Promise.race([
39854
- this.fetchQuotaForStatusLine(),
39855
- new Promise((r) => setTimeout(r, 2000))
39856
- ]).catch(() => {});
39857
- }
39858
40336
  } catch (err) {
39859
40337
  log(`[${this.provider.displayName}] Auth/health check failed: ${err.message}`);
39860
40338
  logStderr(`Error [${this.provider.displayName}]: Auth/health check failed \u2014 ${err.message}. Check credentials and server.`);
@@ -39949,6 +40427,7 @@ class ComposedHandler {
39949
40427
  log(`[ComposedHandler] Transport fell back to model: ${activeModel}`);
39950
40428
  }
39951
40429
  log(`[${this.provider.displayName}] Response status: ${response.status}`);
40430
+ this.capturePlanUsage(response);
39952
40431
  if (!response.ok) {
39953
40432
  if (response.status === 401 && this.provider.forceRefreshAuth) {
39954
40433
  log(`[${this.provider.displayName}] Got 401, forcing auth refresh and retrying`);
@@ -40142,6 +40621,7 @@ class ComposedHandler {
40142
40621
  }
40143
40622
  latencyMs = Math.round(performance.now() - startTime);
40144
40623
  const httpStatus = response.status;
40624
+ this.capturePlanUsage(response);
40145
40625
  let streamApiError = null;
40146
40626
  const onStreamComplete = () => {
40147
40627
  try {
@@ -40315,18 +40795,31 @@ class ComposedHandler {
40315
40795
  getTokenTracker() {
40316
40796
  return this.tokenTracker;
40317
40797
  }
40318
- async fetchQuotaForStatusLine() {
40798
+ capturePlanUsage(response) {
40319
40799
  try {
40320
- const fn = this.provider.getQuotaRemaining;
40321
- if (typeof fn !== "function")
40800
+ const adapter = resolveQuotaAdapter(this.provider.name);
40801
+ if (!adapter)
40802
+ return;
40803
+ const plan = adapter.scrape?.(response);
40804
+ if (plan) {
40805
+ this.tokenTracker.setPlanUsage(plan);
40322
40806
  return;
40323
- const remaining = await fn.call(this.provider, this.bareModelName);
40324
- if (typeof remaining === "number") {
40325
- this.tokenTracker.setQuotaRemaining(remaining);
40326
- this.tokenTracker.rewrite();
40327
40807
  }
40808
+ this.maybePollPlanUsage(adapter);
40328
40809
  } catch {}
40329
40810
  }
40811
+ maybePollPlanUsage(adapter) {
40812
+ if (!adapter.poll)
40813
+ return;
40814
+ const now = Date.now();
40815
+ if (now - this.lastPlanPollAt < PLAN_POLL_INTERVAL_MS)
40816
+ return;
40817
+ this.lastPlanPollAt = now;
40818
+ adapter.poll({ modelId: this.bareModelName }).then((plan) => {
40819
+ if (plan)
40820
+ this.tokenTracker.setPlanUsage(plan);
40821
+ }).catch(() => {});
40822
+ }
40330
40823
  setFallbackMeta(chain, attempts) {
40331
40824
  this.pendingFallbackMeta = { chain, attempts };
40332
40825
  }
@@ -40351,6 +40844,9 @@ function getRecoveryHint(status, errorText, providerName) {
40351
40844
  if (lower.includes("not supported") || lower.includes("unsupported model") || lower.includes("model not found")) {
40352
40845
  return "Model not supported by this provider. Verify model name.";
40353
40846
  }
40847
+ if (isQuotaExhaustionError(status, errorText)) {
40848
+ return "Out of quota \u2014 check your plan & billing details. This won't recover on retry.";
40849
+ }
40354
40850
  return "Check API key / OAuth credentials.";
40355
40851
  }
40356
40852
  if (status === 404) {
@@ -40374,6 +40870,8 @@ var STREAM_RETRY_DELAYS_MS;
40374
40870
  var init_composed_handler = __esm(() => {
40375
40871
  init_dialect_manager();
40376
40872
  init_model_catalog();
40873
+ init_registry();
40874
+ init_types2();
40377
40875
  init_behavior();
40378
40876
  init_logger();
40379
40877
  init_middleware();
@@ -40386,6 +40884,7 @@ var init_composed_handler = __esm(() => {
40386
40884
  init_connection_error();
40387
40885
  init_context_window_fallback();
40388
40886
  init_openai_compat();
40887
+ init_quota_exhaustion();
40389
40888
  init_stream_head_sniffer();
40390
40889
  init_anthropic_sse();
40391
40890
  init_gemini_sse();
@@ -41748,7 +42247,7 @@ var init_default_routing_rules = __esm(() => {
41748
42247
  "gpt-*": ["openai-codex", "openai", "openrouter"],
41749
42248
  "o1-*": ["openai-codex", "openai", "openrouter"],
41750
42249
  "o3-*": ["openai-codex", "openai", "openrouter"],
41751
- "gemini-*": ["gemini-codeassist", "google", "openrouter"],
42250
+ "gemini-*": ["antigravity", "google", "openrouter"],
41752
42251
  "grok-*": ["x-ai", "openrouter"],
41753
42252
  "kimi-*": ["kimi-coding", "kimi", "openrouter"],
41754
42253
  "k3*": ["kimi-coding", "kimi", "openrouter"],
@@ -42598,8 +43097,8 @@ var init_signal_watcher = __esm(() => {
42598
43097
  import { spawn } from "child_process";
42599
43098
  import { randomUUID as randomUUID4 } from "crypto";
42600
43099
  import { createWriteStream, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
42601
- import { homedir as homedir23 } from "os";
42602
- import { join as join23 } from "path";
43100
+ import { homedir as homedir24 } from "os";
43101
+ import { join as join24 } from "path";
42603
43102
 
42604
43103
  class SessionManager {
42605
43104
  sessions = new Map;
@@ -42611,7 +43110,7 @@ class SessionManager {
42611
43110
  constructor(options) {
42612
43111
  this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
42613
43112
  this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
42614
- this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join23(homedir23(), ".claudish", "sessions");
43113
+ this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join24(homedir24(), ".claudish", "sessions");
42615
43114
  this.onStateChange = options?.onStateChange;
42616
43115
  }
42617
43116
  createSession(opts) {
@@ -42621,10 +43120,10 @@ class SessionManager {
42621
43120
  const sessionId2 = randomUUID4().slice(0, 8);
42622
43121
  const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
42623
43122
  const startedAt = new Date().toISOString();
42624
- const sessionDir = join23(this.sessionsDir, sessionId2);
43123
+ const sessionDir = join24(this.sessionsDir, sessionId2);
42625
43124
  mkdirSync11(sessionDir, { recursive: true });
42626
43125
  if (opts.prompt) {
42627
- writeFileSync10(join23(sessionDir, "prompt.md"), opts.prompt, "utf-8");
43126
+ writeFileSync10(join24(sessionDir, "prompt.md"), opts.prompt, "utf-8");
42628
43127
  }
42629
43128
  const args = [
42630
43129
  "--model",
@@ -42658,7 +43157,7 @@ class SessionManager {
42658
43157
  });
42659
43158
  }
42660
43159
  });
42661
- const outputLogStream = createWriteStream(join23(sessionDir, "output.log"));
43160
+ const outputLogStream = createWriteStream(join24(sessionDir, "output.log"));
42662
43161
  const entry = {
42663
43162
  info: {
42664
43163
  sessionId: sessionId2,
@@ -42705,9 +43204,9 @@ class SessionManager {
42705
43204
  watcher.processExited(code);
42706
43205
  outputLogStream.end();
42707
43206
  if (entry.stderr) {
42708
- writeFileSync10(join23(sessionDir, "stderr.log"), entry.stderr, "utf-8");
43207
+ writeFileSync10(join24(sessionDir, "stderr.log"), entry.stderr, "utf-8");
42709
43208
  }
42710
- writeFileSync10(join23(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
43209
+ writeFileSync10(join24(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
42711
43210
  this.cleanupSigint();
42712
43211
  });
42713
43212
  proc.on("error", (err) => {
@@ -44942,6 +45441,8 @@ ${summary}`);
44942
45441
  }
44943
45442
  }
44944
45443
  function isRetryableError(status, errorBody) {
45444
+ if (isQuotaExhaustionError(status, errorBody))
45445
+ return false;
44945
45446
  if (status === 401 || status === 403)
44946
45447
  return true;
44947
45448
  if (status === 402)
@@ -44986,6 +45487,7 @@ function truncate(s, max) {
44986
45487
  var init_fallback_handler = __esm(() => {
44987
45488
  init_logger();
44988
45489
  init_composed_handler();
45490
+ init_quota_exhaustion();
44989
45491
  });
44990
45492
 
44991
45493
  // src/handlers/native-handler-advisor.ts
@@ -45734,11 +46236,11 @@ var init_ollama_api_format = __esm(() => {
45734
46236
  });
45735
46237
 
45736
46238
  // src/providers/api-key-provenance.ts
45737
- import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
45738
- import { homedir as homedir24 } from "os";
45739
- import { join as join24, resolve as resolve2 } from "path";
46239
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
46240
+ import { homedir as homedir25 } from "os";
46241
+ import { join as join25, resolve as resolve2 } from "path";
45740
46242
  function activeConfigPath() {
45741
- return activeGlobalConfigFile(join24(homedir24(), ".claudish", "config.json"));
46243
+ return activeGlobalConfigFile(join25(homedir25(), ".claudish", "config.json"));
45742
46244
  }
45743
46245
  function configLayerLabel() {
45744
46246
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -45815,9 +46317,9 @@ function formatProvenanceLog(p) {
45815
46317
  function readDotenvKey(envVars) {
45816
46318
  try {
45817
46319
  const dotenvPath = resolve2(".env");
45818
- if (!existsSync16(dotenvPath))
46320
+ if (!existsSync17(dotenvPath))
45819
46321
  return null;
45820
- const parsed = import_dotenv.parse(readFileSync14(dotenvPath, "utf-8"));
46322
+ const parsed = import_dotenv.parse(readFileSync15(dotenvPath, "utf-8"));
45821
46323
  for (const v of envVars) {
45822
46324
  if (parsed[v])
45823
46325
  return parsed[v];
@@ -45830,9 +46332,9 @@ function readDotenvKey(envVars) {
45830
46332
  function readConfigKey(envVar) {
45831
46333
  try {
45832
46334
  const configPath = activeConfigPath();
45833
- if (!existsSync16(configPath))
46335
+ if (!existsSync17(configPath))
45834
46336
  return null;
45835
- const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
46337
+ const cfg = JSON.parse(readFileSync15(configPath, "utf-8"));
45836
46338
  return cfg.apiKeys?.[envVar] || null;
45837
46339
  } catch {
45838
46340
  return null;
@@ -47305,9 +47807,9 @@ var init_poe = __esm(() => {
47305
47807
  });
47306
47808
 
47307
47809
  // src/services/pricing-cache.ts
47308
- import { existsSync as existsSync17, readFileSync as readFileSync15, statSync as statSync4 } from "fs";
47309
- import { homedir as homedir25 } from "os";
47310
- import { join as join25 } from "path";
47810
+ import { existsSync as existsSync18, readFileSync as readFileSync16, statSync as statSync4 } from "fs";
47811
+ import { homedir as homedir26 } from "os";
47812
+ import { join as join26 } from "path";
47311
47813
  function prefixMatch(modelName) {
47312
47814
  for (const [key, pricing] of pricingMap) {
47313
47815
  if (modelName.startsWith(key))
@@ -47345,12 +47847,12 @@ async function warmPricingCache() {
47345
47847
  }
47346
47848
  function loadDiskCache() {
47347
47849
  try {
47348
- if (!existsSync17(CACHE_FILE))
47850
+ if (!existsSync18(CACHE_FILE))
47349
47851
  return false;
47350
47852
  const stat2 = statSync4(CACHE_FILE);
47351
47853
  const age = Date.now() - stat2.mtimeMs;
47352
47854
  const isFresh = age < CACHE_TTL_MS3;
47353
- const raw2 = readFileSync15(CACHE_FILE, "utf-8");
47855
+ const raw2 = readFileSync16(CACHE_FILE, "utf-8");
47354
47856
  const data = JSON.parse(raw2);
47355
47857
  for (const [key, pricing] of Object.entries(data)) {
47356
47858
  pricingMap.set(key, pricing);
@@ -47366,8 +47868,8 @@ var init_pricing_cache = __esm(() => {
47366
47868
  init_logger();
47367
47869
  init_catalog_query();
47368
47870
  pricingMap = new Map;
47369
- CACHE_DIR = join25(homedir25(), ".claudish");
47370
- CACHE_FILE = join25(CACHE_DIR, "pricing-cache.json");
47871
+ CACHE_DIR = join26(homedir26(), ".claudish");
47872
+ CACHE_FILE = join26(CACHE_DIR, "pricing-cache.json");
47371
47873
  CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
47372
47874
  });
47373
47875
 
@@ -47862,20 +48364,20 @@ var init_redact = __esm(() => {
47862
48364
  });
47863
48365
 
47864
48366
  // src/team-stats.ts
47865
- import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
47866
- import { join as join26 } from "path";
48367
+ import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync11 } from "fs";
48368
+ import { join as join27 } from "path";
47867
48369
  function statsDir(sessionPath) {
47868
- return join26(sessionPath, "stats");
48370
+ return join27(sessionPath, "stats");
47869
48371
  }
47870
48372
  function tokenFileFor(sessionPath, anonId) {
47871
- return join26(statsDir(sessionPath), `${anonId}.json`);
48373
+ return join27(statsDir(sessionPath), `${anonId}.json`);
47872
48374
  }
47873
48375
  function readTokenStats(sessionPath, anonId) {
47874
48376
  const path = tokenFileFor(sessionPath, anonId);
47875
- if (!existsSync18(path))
48377
+ if (!existsSync19(path))
47876
48378
  return null;
47877
48379
  try {
47878
- return JSON.parse(readFileSync16(path, "utf-8"));
48380
+ return JSON.parse(readFileSync17(path, "utf-8"));
47879
48381
  } catch {
47880
48382
  return null;
47881
48383
  }
@@ -48023,7 +48525,7 @@ ${segs.join(" \xB7 ")}`;
48023
48525
  }
48024
48526
  function writeStatusFile(sessionPath, manifest, status, opts) {
48025
48527
  try {
48026
- writeFileSync11(join26(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
48528
+ writeFileSync11(join27(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
48027
48529
  `, "utf-8");
48028
48530
  } catch {}
48029
48531
  }
@@ -48049,13 +48551,13 @@ __export(exports_team_orchestrator, {
48049
48551
  import { spawn as spawn2 } from "child_process";
48050
48552
  import {
48051
48553
  createWriteStream as createWriteStream2,
48052
- existsSync as existsSync19,
48554
+ existsSync as existsSync20,
48053
48555
  mkdirSync as mkdirSync12,
48054
- readFileSync as readFileSync17,
48556
+ readFileSync as readFileSync18,
48055
48557
  readdirSync as readdirSync3,
48056
48558
  writeFileSync as writeFileSync12
48057
48559
  } from "fs";
48058
- import { join as join27, resolve as resolve3 } from "path";
48560
+ import { join as join28, resolve as resolve3 } from "path";
48059
48561
  function classifyRunOutput(opts) {
48060
48562
  const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
48061
48563
  const apiError = API_ERROR_RE.exec(stdoutTail);
@@ -48116,18 +48618,18 @@ function setupSession(sessionPath, models, input) {
48116
48618
  if (models.length === 0) {
48117
48619
  throw new Error("At least one model is required");
48118
48620
  }
48119
- if (existsSync19(join27(sessionPath, "manifest.json"))) {
48621
+ if (existsSync20(join28(sessionPath, "manifest.json"))) {
48120
48622
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
48121
48623
  }
48122
48624
  const sentinels = models.filter(isSentinelModel);
48123
48625
  if (sentinels.length > 0) {
48124
48626
  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.`);
48125
48627
  }
48126
- mkdirSync12(join27(sessionPath, "work"), { recursive: true });
48127
- mkdirSync12(join27(sessionPath, "errors"), { recursive: true });
48628
+ mkdirSync12(join28(sessionPath, "work"), { recursive: true });
48629
+ mkdirSync12(join28(sessionPath, "errors"), { recursive: true });
48128
48630
  if (input !== undefined) {
48129
- writeFileSync12(join27(sessionPath, "input.md"), input, "utf-8");
48130
- } else if (!existsSync19(join27(sessionPath, "input.md"))) {
48631
+ writeFileSync12(join28(sessionPath, "input.md"), input, "utf-8");
48632
+ } else if (!existsSync20(join28(sessionPath, "input.md"))) {
48131
48633
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
48132
48634
  }
48133
48635
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -48144,9 +48646,9 @@ function setupSession(sessionPath, models, input) {
48144
48646
  model: models[i],
48145
48647
  assignedAt: now
48146
48648
  };
48147
- mkdirSync12(join27(sessionPath, "work", anonId), { recursive: true });
48649
+ mkdirSync12(join28(sessionPath, "work", anonId), { recursive: true });
48148
48650
  }
48149
- writeFileSync12(join27(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
48651
+ writeFileSync12(join28(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
48150
48652
  const status = {
48151
48653
  startedAt: now,
48152
48654
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -48160,17 +48662,17 @@ function setupSession(sessionPath, models, input) {
48160
48662
  }
48161
48663
  ]))
48162
48664
  };
48163
- writeFileSync12(join27(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
48665
+ writeFileSync12(join28(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
48164
48666
  return manifest;
48165
48667
  }
48166
48668
  async function runModels(sessionPath, opts = {}) {
48167
48669
  const timeoutMs = (opts.timeout ?? 300) * 1000;
48168
- const manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
48169
- const statusPath = join27(sessionPath, "status.json");
48170
- const inputPath = join27(sessionPath, "input.md");
48171
- const inputContent = readFileSync17(inputPath, "utf-8");
48670
+ const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48671
+ const statusPath = join28(sessionPath, "status.json");
48672
+ const inputPath = join28(sessionPath, "input.md");
48673
+ const inputContent = readFileSync18(inputPath, "utf-8");
48172
48674
  const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
48173
- const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
48675
+ const statusCache = JSON.parse(readFileSync18(statusPath, "utf-8"));
48174
48676
  function updateModelStatus(id, update) {
48175
48677
  statusCache.models[id] = { ...statusCache.models[id], ...update };
48176
48678
  writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
@@ -48189,8 +48691,8 @@ async function runModels(sessionPath, opts = {}) {
48189
48691
  process.on("SIGINT", sigintHandler);
48190
48692
  const completionPromises = [];
48191
48693
  for (const [anonId, entry] of Object.entries(manifest.models)) {
48192
- const outputPath = join27(sessionPath, `response-${anonId}.md`);
48193
- const errorLogPath = join27(sessionPath, "errors", `${anonId}.log`);
48694
+ const outputPath = join28(sessionPath, `response-${anonId}.md`);
48695
+ const errorLogPath = join28(sessionPath, "errors", `${anonId}.log`);
48194
48696
  const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
48195
48697
  const args = ["--model", spawnModel, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
48196
48698
  updateModelStatus(anonId, {
@@ -48380,23 +48882,23 @@ async function judgeResponses(sessionPath, opts = {}) {
48380
48882
  const responses = {};
48381
48883
  for (const file2 of responseFiles) {
48382
48884
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
48383
- responses[id] = readFileSync17(join27(sessionPath, file2), "utf-8");
48885
+ responses[id] = readFileSync18(join28(sessionPath, file2), "utf-8");
48384
48886
  }
48385
- const input = readFileSync17(join27(sessionPath, "input.md"), "utf-8");
48887
+ const input = readFileSync18(join28(sessionPath, "input.md"), "utf-8");
48386
48888
  const judgePrompt = buildJudgePrompt(input, responses);
48387
- writeFileSync12(join27(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48889
+ writeFileSync12(join28(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48388
48890
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
48389
- const judgePath = join27(sessionPath, "judging");
48891
+ const judgePath = join28(sessionPath, "judging");
48390
48892
  mkdirSync12(judgePath, { recursive: true });
48391
48893
  setupSession(judgePath, judgeModels, judgePrompt);
48392
48894
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
48393
48895
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
48394
48896
  const verdict = aggregateVerdict(votes, Object.keys(responses));
48395
- writeFileSync12(join27(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48897
+ writeFileSync12(join28(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48396
48898
  return verdict;
48397
48899
  }
48398
48900
  function getStatus(sessionPath) {
48399
- return JSON.parse(readFileSync17(join27(sessionPath, "status.json"), "utf-8"));
48901
+ return JSON.parse(readFileSync18(join28(sessionPath, "status.json"), "utf-8"));
48400
48902
  }
48401
48903
  function fisherYatesShuffle(arr) {
48402
48904
  for (let i = arr.length - 1;i > 0; i--) {
@@ -48406,7 +48908,7 @@ function fisherYatesShuffle(arr) {
48406
48908
  return arr;
48407
48909
  }
48408
48910
  function getDefaultJudgeModels(sessionPath) {
48409
- const manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
48911
+ const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48410
48912
  return Object.values(manifest.models).map((e) => e.model);
48411
48913
  }
48412
48914
  function buildJudgePrompt(input, responses) {
@@ -48469,7 +48971,7 @@ function parseJudgeVotes(judgePath, responseIds) {
48469
48971
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
48470
48972
  let content;
48471
48973
  try {
48472
- content = readFileSync17(join27(judgePath, file2), "utf-8");
48974
+ content = readFileSync18(join28(judgePath, file2), "utf-8");
48473
48975
  } catch {
48474
48976
  continue;
48475
48977
  }
@@ -48521,7 +49023,7 @@ function aggregateVerdict(votes, responseIds) {
48521
49023
  function formatVerdict(verdict, sessionPath) {
48522
49024
  let manifest = null;
48523
49025
  try {
48524
- manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
49026
+ manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48525
49027
  } catch {}
48526
49028
  let output = `# Team Verdict
48527
49029
 
@@ -48576,14 +49078,14 @@ __export(exports_mcp_server, {
48576
49078
  parseAnthropicSse: () => parseAnthropicSse,
48577
49079
  formatTeamResult: () => formatTeamResult
48578
49080
  });
48579
- import { existsSync as existsSync20, mkdirSync as mkdirSync13, readFileSync as readFileSync18, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
48580
- import { homedir as homedir26 } from "os";
48581
- import { dirname as dirname9, join as join28, resolve as resolve4 } from "path";
49081
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync19, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
49082
+ import { homedir as homedir27 } from "os";
49083
+ import { dirname as dirname9, join as join29, resolve as resolve4 } from "path";
48582
49084
  import { fileURLToPath } from "url";
48583
49085
  async function loadAllModels(forceRefresh = false) {
48584
- if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH2)) {
49086
+ if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
48585
49087
  try {
48586
- const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
49088
+ const cacheData = JSON.parse(readFileSync19(ALL_MODELS_CACHE_PATH2, "utf-8"));
48587
49089
  const lastUpdated = new Date(cacheData.lastUpdated);
48588
49090
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
48589
49091
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -48601,8 +49103,8 @@ async function loadAllModels(forceRefresh = false) {
48601
49103
  writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
48602
49104
  return models;
48603
49105
  } catch {
48604
- if (existsSync20(ALL_MODELS_CACHE_PATH2)) {
48605
- const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
49106
+ if (existsSync21(ALL_MODELS_CACHE_PATH2)) {
49107
+ const cacheData = JSON.parse(readFileSync19(ALL_MODELS_CACHE_PATH2, "utf-8"));
48606
49108
  return cacheData.models || [];
48607
49109
  }
48608
49110
  return [];
@@ -49184,7 +49686,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49184
49686
  let stderrFull = stderr_snippet || "";
49185
49687
  if (error_log_path) {
49186
49688
  try {
49187
- stderrFull = readFileSync18(error_log_path, "utf-8");
49689
+ stderrFull = readFileSync19(error_log_path, "utf-8");
49188
49690
  } catch {}
49189
49691
  }
49190
49692
  const sessionData = {};
@@ -49192,16 +49694,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49192
49694
  const sp = session_path;
49193
49695
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
49194
49696
  try {
49195
- sessionData[file2] = readFileSync18(join28(sp, file2), "utf-8");
49697
+ sessionData[file2] = readFileSync19(join29(sp, file2), "utf-8");
49196
49698
  } catch {}
49197
49699
  }
49198
49700
  try {
49199
- const errorDir = join28(sp, "errors");
49200
- if (existsSync20(errorDir)) {
49701
+ const errorDir = join29(sp, "errors");
49702
+ if (existsSync21(errorDir)) {
49201
49703
  for (const f of readdirSync4(errorDir)) {
49202
49704
  if (f.endsWith(".log")) {
49203
49705
  try {
49204
- sessionData[`errors/${f}`] = readFileSync18(join28(errorDir, f), "utf-8");
49706
+ sessionData[`errors/${f}`] = readFileSync19(join29(errorDir, f), "utf-8");
49205
49707
  } catch {}
49206
49708
  }
49207
49709
  }
@@ -49211,7 +49713,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49211
49713
  for (const f of readdirSync4(sp)) {
49212
49714
  if (f.startsWith("response-") && f.endsWith(".md")) {
49213
49715
  try {
49214
- const content = readFileSync18(join28(sp, f), "utf-8");
49716
+ const content = readFileSync19(join29(sp, f), "utf-8");
49215
49717
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
49216
49718
  } catch {}
49217
49719
  }
@@ -49220,9 +49722,9 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49220
49722
  }
49221
49723
  let version2 = "unknown";
49222
49724
  try {
49223
- const pkgPath = join28(__dirname2, "../package.json");
49224
- if (existsSync20(pkgPath)) {
49225
- version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
49725
+ const pkgPath = join29(__dirname2, "../package.json");
49726
+ if (existsSync21(pkgPath)) {
49727
+ version2 = JSON.parse(readFileSync19(pkgPath, "utf-8")).version;
49226
49728
  }
49227
49729
  } catch {}
49228
49730
  const report = {
@@ -49626,8 +50128,8 @@ var init_mcp_server = __esm(() => {
49626
50128
  import_dotenv2.config({ quiet: true });
49627
50129
  __filename2 = fileURLToPath(import.meta.url);
49628
50130
  __dirname2 = dirname9(__filename2);
49629
- CLAUDISH_CACHE_DIR = join28(homedir26(), ".claudish");
49630
- ALL_MODELS_CACHE_PATH2 = join28(CLAUDISH_CACHE_DIR, "all-models.json");
50131
+ CLAUDISH_CACHE_DIR = join29(homedir27(), ".claudish");
50132
+ ALL_MODELS_CACHE_PATH2 = join29(CLAUDISH_CACHE_DIR, "all-models.json");
49631
50133
  NEXT_STEP = {
49632
50134
  nonzero_exit: "read the evidence log, then retry or drop the model",
49633
50135
  timeout: "raise `timeout`, or pick a faster model",
@@ -49652,7 +50154,7 @@ var exports_serve_command = {};
49652
50154
  __export(exports_serve_command, {
49653
50155
  serveCommand: () => serveCommand
49654
50156
  });
49655
- import { existsSync as existsSync21, readFileSync as readFileSync19 } from "fs";
50157
+ import { existsSync as existsSync22, readFileSync as readFileSync20 } from "fs";
49656
50158
  function parseServeArgs(args) {
49657
50159
  const out = {};
49658
50160
  for (let i = 0;i < args.length; i++) {
@@ -49671,12 +50173,12 @@ function parseServeArgs(args) {
49671
50173
  return out;
49672
50174
  }
49673
50175
  function loadModelMap(path) {
49674
- if (!existsSync21(path)) {
50176
+ if (!existsSync22(path)) {
49675
50177
  throw new Error(`--models file not found: ${path}`);
49676
50178
  }
49677
50179
  let raw2;
49678
50180
  try {
49679
- raw2 = readFileSync19(path, "utf-8");
50181
+ raw2 = readFileSync20(path, "utf-8");
49680
50182
  } catch (e) {
49681
50183
  throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
49682
50184
  }
@@ -49753,7 +50255,7 @@ var exports_behavior_command = {};
49753
50255
  __export(exports_behavior_command, {
49754
50256
  behaviorCommand: () => behaviorCommand
49755
50257
  });
49756
- import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
50258
+ import { existsSync as existsSync23, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
49757
50259
  function severityColor(sev) {
49758
50260
  if (sev === "fix")
49759
50261
  return green(sev);
@@ -49851,8 +50353,8 @@ function setTelemetryEnabled(value) {
49851
50353
  const path = getConfigPath();
49852
50354
  let cfg = {};
49853
50355
  try {
49854
- if (existsSync22(path)) {
49855
- const parsed = JSON.parse(readFileSync20(path, "utf-8"));
50356
+ if (existsSync23(path)) {
50357
+ const parsed = JSON.parse(readFileSync21(path, "utf-8"));
49856
50358
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
49857
50359
  cfg = parsed;
49858
50360
  }
@@ -49873,8 +50375,8 @@ function showTelemetry(action, json2) {
49873
50375
  let pending = 0;
49874
50376
  try {
49875
50377
  const path = outboxPath();
49876
- if (existsSync22(path)) {
49877
- pending = readFileSync20(path, "utf8").split(`
50378
+ if (existsSync23(path)) {
50379
+ pending = readFileSync21(path, "utf8").split(`
49878
50380
  `).filter(Boolean).length;
49879
50381
  }
49880
50382
  } catch {}
@@ -61343,7 +61845,7 @@ var init_RemoveFileError = __esm(() => {
61343
61845
 
61344
61846
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
61345
61847
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
61346
- import { readFileSync as readFileSync21, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
61848
+ import { readFileSync as readFileSync22, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
61347
61849
  import path from "path";
61348
61850
  import os from "os";
61349
61851
  import { randomUUID as randomUUID6 } from "crypto";
@@ -61459,7 +61961,7 @@ class ExternalEditor {
61459
61961
  }
61460
61962
  readTemporaryFile() {
61461
61963
  try {
61462
- const tempFileBuffer = readFileSync21(this.tempFile);
61964
+ const tempFileBuffer = readFileSync22(this.tempFile);
61463
61965
  if (tempFileBuffer.length === 0) {
61464
61966
  this.text = "";
61465
61967
  } else {
@@ -62440,9 +62942,9 @@ var init_dist16 = __esm(() => {
62440
62942
 
62441
62943
  // src/auth/antigravity-oauth.ts
62442
62944
  import { spawnSync as spawnSync3 } from "child_process";
62443
- import { existsSync as existsSync23, unlinkSync as unlinkSync7 } from "fs";
62444
- import { homedir as homedir27 } from "os";
62445
- import { join as join29 } from "path";
62945
+ import { existsSync as existsSync24, unlinkSync as unlinkSync7 } from "fs";
62946
+ import { homedir as homedir28 } from "os";
62947
+ import { join as join30 } from "path";
62446
62948
  async function defaultSuggestModel() {
62447
62949
  try {
62448
62950
  const tok = readSharedAntigravityToken();
@@ -62563,8 +63065,8 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
62563
63065
  async logout(deps) {
62564
63066
  deleteSharedAntigravityToken(deps);
62565
63067
  try {
62566
- const tokenFile = join29(homedir27(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
62567
- if (existsSync23(tokenFile))
63068
+ const tokenFile = join30(homedir28(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
63069
+ if (existsSync24(tokenFile))
62568
63070
  unlinkSync7(tokenFile);
62569
63071
  } catch {}
62570
63072
  log("[AntigravityOAuth] Antigravity session cleared (keychain + agy token file)");
@@ -62700,267 +63202,145 @@ var init_auth_commands = __esm(() => {
62700
63202
  // src/auth/quota-command.ts
62701
63203
  var exports_quota_command = {};
62702
63204
  __export(exports_quota_command, {
62703
- quotaCommand: () => quotaCommand
63205
+ quotaCommand: () => quotaCommand,
63206
+ formatRelativeReset: () => formatRelativeReset,
63207
+ buildUsageBar: () => buildUsageBar
62704
63208
  });
62705
63209
  async function quotaCommand(provider) {
62706
- if (!provider) {
62707
- const { select } = await Promise.resolve().then(() => (init_dist16(), exports_dist));
62708
- const choices = QUOTA_ADAPTERS.map((a) => ({
62709
- name: `${a.name} \u2014 ${a.isAvailable() ? "logged in" : "not logged in"}`,
62710
- value: a
62711
- }));
62712
- const selected = await select({ message: "Select provider:", choices });
62713
- return selected.handler();
62714
- }
62715
- const target = provider.toLowerCase();
62716
- const adapter = QUOTA_ADAPTERS.find((a) => a.aliases.includes(target));
63210
+ const adapter = provider ? resolveAdapterFromInput(provider) : await promptForAdapter();
62717
63211
  if (!adapter) {
62718
- const allAliases = QUOTA_ADAPTERS.flatMap((a) => a.aliases);
62719
- console.error(`Unknown provider: ${provider}`);
62720
- console.error(`Available: ${allAliases.join(", ")}`);
63212
+ printUnknownProvider(provider ?? "");
62721
63213
  process.exit(1);
62722
63214
  }
63215
+ const capability = adapter.capability();
63216
+ if (capability.kind === "none") {
63217
+ printUnsupported(adapter, capability.evidence);
63218
+ return;
63219
+ }
63220
+ if (capability.kind === "unknown") {
63221
+ console.log(`
63222
+ ${WHT}${adapter.label}${R} \u2014 usage support has not been researched yet.
63223
+ `);
63224
+ return;
63225
+ }
62723
63226
  if (!adapter.isAvailable()) {
62724
- console.error(`${RED}Not logged in for ${adapter.name}.${R} Run: ${B}claudish login${R}`);
63227
+ console.error(`${RED}Not logged in for ${adapter.label}.${R} Run: ${B}claudish login${R}
63228
+ `);
62725
63229
  process.exit(1);
62726
63230
  }
62727
- return adapter.handler();
62728
- }
62729
- async function geminiQuotaHandler() {
62730
- if (!hasOAuthCredentials("google") && !hasOAuthCredentials("gemini-codeassist")) {
62731
- console.error(`${RED}Not logged in.${R} Run: ${B}claudish login gemini${R}`);
62732
- process.exit(1);
63231
+ const fetch2 = adapter.fetchExplicit ?? adapter.poll;
63232
+ if (!fetch2) {
63233
+ console.log(`
63234
+ ${WHT}${adapter.label}${R} \u2014 no way to read usage.
63235
+ `);
63236
+ return;
62733
63237
  }
63238
+ let plan;
62734
63239
  try {
62735
- const accessToken = await getValidAccessToken();
62736
- const { projectId } = await setupGeminiUser(accessToken);
62737
- const tierName = getGeminiTierFullName();
62738
- const quota = await retrieveUserQuota(accessToken, projectId);
62739
- if (!quota?.buckets?.length) {
62740
- console.log(`
62741
- ${D}No quota data available.${R}
62742
- `);
62743
- process.exit(0);
62744
- }
62745
- const W = 58;
62746
- console.log("");
62747
- console.log(` ${CYN}\u256D${"\u2500".repeat(W)}\u256E${R}`);
62748
- console.log(` ${CYN}\u2502${R} ${B}${WHT}Gemini Code Assist Quota${R}${" ".repeat(W - 25)}${CYN}\u2502${R}`);
62749
- console.log(` ${CYN}\u251C${"\u2500".repeat(W)}\u2524${R}`);
62750
- console.log(` ${CYN}\u2502${R} ${GRY}Tier${R} ${WHT}${tierName}${R}${" ".repeat(Math.max(0, W - 10 - tierName.length))}${CYN}\u2502${R}`);
62751
- console.log(` ${CYN}\u2502${R} ${GRY}Project${R} ${WHT}${projectId}${R}${" ".repeat(Math.max(0, W - 10 - projectId.length))}${CYN}\u2502${R}`);
62752
- console.log(` ${CYN}\u2570${"\u2500".repeat(W)}\u256F${R}`);
62753
- const groups = groupByVersion(quota.buckets);
62754
- const allBuckets = quota.buckets.filter((b) => typeof b.remainingFraction === "number");
62755
- const avgRemaining = allBuckets.length > 0 ? allBuckets.reduce((sum, b) => sum + (b.remainingFraction ?? 0), 0) / allBuckets.length : 1;
62756
- const avgUsed = 1 - avgRemaining;
62757
- const summaryColor = avgUsed < 0.5 ? GRN : avgUsed < 0.8 ? YEL : RED;
62758
- console.log("");
62759
- console.log(` ${summaryColor}${B}${(avgUsed * 100).toFixed(1)}%${R} ${D}overall usage across ${allBuckets.length} models${R}`);
62760
- console.log("");
62761
- const remainingByModel = new Map;
62762
- for (const b of quota.buckets) {
62763
- if (b.modelId && typeof b.remainingFraction === "number") {
62764
- remainingByModel.set(b.modelId, b.remainingFraction);
62765
- }
62766
- }
62767
- for (const group of groups) {
62768
- console.log(` ${MAG}${B}${group.title}${R}`);
62769
- for (const bucket of group.buckets) {
62770
- const model = bucket.modelId || "unknown";
62771
- const remaining = typeof bucket.remainingFraction === "number" ? bucket.remainingFraction : null;
62772
- const used = remaining !== null ? 1 - remaining : null;
62773
- const reset = bucket.resetTime ? formatRelativeReset(bucket.resetTime) : "";
62774
- const color = used === null ? GRY : used < 0.5 ? GRN : used < 0.8 ? YEL : RED;
62775
- const bar = remaining !== null ? buildUsageBar(used, color, 24) : `${GRY}${"\xB7".repeat(24)}${R}`;
62776
- const pct = used !== null ? `${(used * 100).toFixed(1)}%` : "?";
62777
- const nameStr = ` ${GRY}\u2502${R} ${WHT}${model}${R}`;
62778
- const padLen = Math.max(1, 30 - model.length);
62779
- console.log(`${nameStr}${" ".repeat(padLen)}${bar} ${color}${pct.padStart(6)}${R} ${GRY}${I}${reset}${R}`);
62780
- }
62781
- console.log("");
62782
- }
62783
- const fallbackChain = quota.buckets.map((b) => b.modelId).filter((m) => typeof m === "string" && m.length > 0).sort((a, b) => rankCodeAssistModel(a) - rankCodeAssistModel(b));
62784
- console.log(` ${B}${CYN}Fallback Chain${R} ${D}(on capacity exhaustion)${R}`);
62785
- for (let i = 0;i < fallbackChain.length; i++) {
62786
- const model = fallbackChain[i];
62787
- const rem = remainingByModel.get(model);
62788
- const pct = rem !== undefined ? `${((1 - rem) * 100).toFixed(0)}%` : "?";
62789
- const color = rem === undefined ? GRY : rem > 0.5 ? GRN : rem > 0.2 ? YEL : RED;
62790
- const arrow = i < fallbackChain.length - 1 ? ` ${GRY}\u2192${R}` : "";
62791
- const marker = i === 0 ? `${CYN}\u25B8${R} ` : " ";
62792
- console.log(` ${marker}${WHT}${model}${R} ${color}${pct}${R}${arrow}`);
62793
- }
62794
- console.log("");
62795
- let geminiExamples;
62796
- try {
62797
- const recs = await getRecommendedModels();
62798
- const seen = new Set;
62799
- geminiExamples = recs.models.filter((e) => (e.provider ?? "").toLowerCase() === "google").filter((e) => {
62800
- if (seen.has(e.id))
62801
- return false;
62802
- seen.add(e.id);
62803
- return true;
62804
- }).slice(0, 2).map((e) => e.id);
62805
- if (geminiExamples.length === 0) {
62806
- geminiExamples = ["gemini-3.1-pro-preview"];
62807
- }
62808
- } catch {
62809
- geminiExamples = ["gemini-3.1-pro-preview"];
62810
- }
62811
- console.log(` ${B}${CYN}Usage${R}`);
62812
- for (const ex of geminiExamples) {
62813
- console.log(` ${WHT}claudish --model ${ex}${R}`);
62814
- }
62815
- console.log("");
62816
- console.log(` ${GRN}\u2588${R}${GRY} <50%${R} ${YEL}\u2588${R}${GRY} 50-80%${R} ${RED}\u2588${R}${GRY} >80%${R} ${D}\u2591 available${R}`);
62817
- console.log("");
63240
+ plan = await fetch2.call(adapter);
62818
63241
  } catch (err) {
62819
- console.error(`Failed to fetch quota: ${err.message}`);
63242
+ console.error(`
63243
+ ${RED}Failed to fetch usage:${R} ${err?.message ?? err}
63244
+ `);
62820
63245
  process.exit(1);
62821
63246
  }
62822
- }
62823
- async function codexQuotaHandler() {
62824
- const { readFileSync: readFileSync22, existsSync: existsSync24 } = await import("fs");
62825
- const { join: join30 } = await import("path");
62826
- const { homedir: homedir28 } = await import("os");
62827
- const credPath = join30(homedir28(), ".claudish", "codex-oauth.json");
62828
- if (!existsSync24(credPath)) {
62829
- console.error(`${RED}No Codex credentials found.${R} Run: ${B}claudish login codex${R}`);
62830
- process.exit(1);
63247
+ if (!plan || plan.windows.length === 0) {
63248
+ console.log(`
63249
+ ${D}No usage data returned for ${adapter.label}.${R}
63250
+ `);
63251
+ return;
62831
63252
  }
62832
- const creds = JSON.parse(readFileSync22(credPath, "utf-8"));
62833
- let email3 = "";
62834
- try {
62835
- const parts = creds.access_token.split(".");
62836
- if (parts.length >= 2) {
62837
- let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/");
62838
- while (payload.length % 4)
62839
- payload += "=";
62840
- const claims = JSON.parse(Buffer.from(payload, "base64").toString());
62841
- email3 = claims?.["https://api.openai.com/profile"]?.email || "";
62842
- }
62843
- } catch {}
62844
- let probeModel = "gpt-5";
62845
- try {
62846
- const doc2 = await getModelByIdFromFirebase("gpt-5");
62847
- if (doc2?.modelId)
62848
- probeModel = doc2.modelId;
62849
- } catch {}
62850
- const resp = await fetch("https://chatgpt.com/backend-api/codex/responses", {
62851
- method: "POST",
62852
- headers: {
62853
- Authorization: `Bearer ${creds.access_token}`,
62854
- "chatgpt-account-id": creds.account_id || "",
62855
- "Content-Type": "application/json",
62856
- Accept: "text/event-stream",
62857
- originator: "codex",
62858
- "OpenAI-Beta": "responses"
62859
- },
62860
- body: JSON.stringify({
62861
- model: probeModel,
62862
- instructions: "Reply with just: ok",
62863
- input: [{ type: "message", role: "user", content: [{ type: "input_text", text: "hi" }] }],
62864
- stream: true,
62865
- store: false
62866
- })
62867
- });
62868
- const planType = resp.headers.get("x-codex-plan-type") || "unknown";
62869
- const primaryUsed = Number.parseInt(resp.headers.get("x-codex-primary-used-percent") || "", 10);
62870
- const secondaryUsed = Number.parseInt(resp.headers.get("x-codex-secondary-used-percent") || "", 10);
62871
- const primaryResetAt = Number.parseInt(resp.headers.get("x-codex-primary-reset-at") || "0", 10);
62872
- const secondaryResetAt = Number.parseInt(resp.headers.get("x-codex-secondary-reset-at") || "0", 10);
62873
- const hasCredits = resp.headers.get("x-codex-credits-has-credits") === "True";
62874
- const creditsBalance = resp.headers.get("x-codex-credits-balance") || "";
62875
- try {
62876
- await resp.text();
62877
- } catch {}
62878
- if (Number.isNaN(primaryUsed)) {
62879
- console.error(`${RED}Could not fetch usage data.${R} Headers missing from response.`);
62880
- process.exit(1);
63253
+ renderPlan(adapter, plan);
63254
+ }
63255
+ function resolveAdapterFromInput(input) {
63256
+ const raw2 = input.toLowerCase().replace(/@+$/, "");
63257
+ const direct = resolveQuotaAdapter(raw2);
63258
+ if (direct)
63259
+ return direct;
63260
+ const friendly = FRIENDLY_NAMES[raw2];
63261
+ if (friendly) {
63262
+ const viaFriendly = resolveQuotaAdapter(friendly);
63263
+ if (viaFriendly)
63264
+ return viaFriendly;
63265
+ }
63266
+ const canonical = getShortcuts()[raw2];
63267
+ if (canonical) {
63268
+ const viaShortcut = resolveQuotaAdapter(canonical);
63269
+ if (viaShortcut)
63270
+ return viaShortcut;
62881
63271
  }
62882
- let modelSlugs = [];
62883
- try {
62884
- const modelsPath = join30(homedir28(), ".codex", "models_cache.json");
62885
- if (existsSync24(modelsPath)) {
62886
- const cache2 = JSON.parse(readFileSync22(modelsPath, "utf-8"));
62887
- modelSlugs = (cache2.models || []).map((m) => m.slug || m.id).filter(Boolean);
62888
- }
62889
- } catch {}
62890
- const W = 58;
62891
- const planLabel = planType.charAt(0).toUpperCase() + planType.slice(1);
62892
- console.log("");
62893
- console.log(` ${CYN}\u256D${"\u2500".repeat(W)}\u256E${R}`);
62894
- console.log(` ${CYN}\u2502${R} ${B}${WHT}Codex Subscription Quota${R}${" ".repeat(W - 25)}${CYN}\u2502${R}`);
62895
- console.log(` ${CYN}\u251C${"\u2500".repeat(W)}\u2524${R}`);
62896
- const boxRow = (label, value) => {
62897
- const paddedLabel = label.padEnd(9);
62898
- const visLen = paddedLabel.length + value.length;
62899
- console.log(` ${CYN}\u2502${R} ${GRY}${paddedLabel}${R}${WHT}${value}${R}${" ".repeat(Math.max(0, W - 1 - visLen))}${CYN}\u2502${R}`);
62900
- };
62901
- boxRow("Plan", planLabel);
62902
- if (email3)
62903
- boxRow("Account", email3);
62904
- if (creds.account_id)
62905
- boxRow("ID", creds.account_id);
62906
- if (hasCredits && creditsBalance)
62907
- boxRow("Credits", creditsBalance);
62908
- console.log(` ${CYN}\u2570${"\u2500".repeat(W)}\u256F${R}`);
62909
- const overallUsed = Math.max(primaryUsed, secondaryUsed);
62910
- const summaryColor = overallUsed < 50 ? GRN : overallUsed < 80 ? YEL : RED;
63272
+ return;
63273
+ }
63274
+ async function promptForAdapter() {
63275
+ const { select } = await Promise.resolve().then(() => (init_dist16(), exports_dist));
63276
+ const choices = allQuotaAdapters().map((a) => {
63277
+ const kind = a.capability().kind;
63278
+ const status = kind === "none" ? `${GRY}not supported${R}` : a.isAvailable() ? `${GRN}logged in${R}` : `${GRY}not logged in${R}`;
63279
+ return { name: `${a.label} \u2014 ${status}`, value: a };
63280
+ });
63281
+ return select({ message: "Select provider:", choices });
63282
+ }
63283
+ function renderPlan(adapter, plan) {
62911
63284
  console.log("");
62912
- console.log(` ${summaryColor}${B}${overallUsed}%${R} ${D}peak usage across rate windows${R}`);
63285
+ boxTop(plan.label);
63286
+ boxRow("Provider", adapter.providerId);
63287
+ boxRow("Windows", String(plan.windows.length));
63288
+ boxBottom();
63289
+ const peak = plan.windows.reduce((m, w) => Math.max(m, w.used_pct), 0);
63290
+ const peakColor = colorFor(peak);
62913
63291
  console.log("");
62914
- const primaryColor = primaryUsed < 50 ? GRN : primaryUsed < 80 ? YEL : RED;
62915
- const primaryBar = buildUsageBar(primaryUsed / 100, primaryColor, 24);
62916
- const primaryReset = primaryResetAt > 0 ? formatRelativeReset(new Date(primaryResetAt * 1000).toISOString()) : "";
62917
- const secondaryColor = secondaryUsed < 50 ? GRN : secondaryUsed < 80 ? YEL : RED;
62918
- const secondaryBar = buildUsageBar(secondaryUsed / 100, secondaryColor, 24);
62919
- const secondaryReset = secondaryResetAt > 0 ? formatRelativeReset(new Date(secondaryResetAt * 1000).toISOString()) : "";
62920
- console.log(` ${GRY}\u2502${R} ${WHT}${"5h window".padEnd(14)}${R}${primaryBar} ${primaryColor}${String(primaryUsed).padStart(3)}%${R} ${GRY}${I}${primaryReset}${R}`);
62921
- console.log(` ${GRY}\u2502${R} ${WHT}${"Weekly".padEnd(14)}${R}${secondaryBar} ${secondaryColor}${String(secondaryUsed).padStart(3)}%${R} ${GRY}${I}${secondaryReset}${R}`);
63292
+ console.log(` ${peakColor}${B}${peak}%${R} ${D}peak usage across ${plan.windows.length} window${plan.windows.length === 1 ? "" : "s"}${R}`);
62922
63293
  console.log("");
62923
- if (modelSlugs.length > 0) {
62924
- console.log(` ${B}${CYN}Available Models${R}`);
62925
- for (const slug of modelSlugs) {
62926
- console.log(` ${WHT}claudish --model cx@${slug}${R}`);
62927
- }
63294
+ for (const w of plan.windows) {
63295
+ const color = colorFor(w.used_pct);
63296
+ const bar = buildUsageBar(w.used_pct / 100, color, 24);
63297
+ const reset = w.resets_at ? formatRelativeReset(w.resets_at) : "";
63298
+ const name = w.id.length > 14 ? `${w.id.slice(0, 13)}\u2026` : w.id;
63299
+ console.log(` ${GRY}\u2502${R} ${WHT}${name.padEnd(14)}${R}${bar} ${color}${String(w.used_pct).padStart(3)}%${R} ${GRY}${I}${reset}${R}`);
62928
63300
  }
62929
63301
  console.log("");
62930
63302
  console.log(` ${GRN}\u2588${R}${GRY} <50%${R} ${YEL}\u2588${R}${GRY} 50-80%${R} ${RED}\u2588${R}${GRY} >80%${R} ${D}\u2591 available${R}`);
62931
- console.log(` ${D}https://chatgpt.com/codex/settings/usage${R}`);
62932
63303
  console.log("");
62933
63304
  }
62934
- function groupByVersion(buckets) {
62935
- const groups = new Map;
62936
- const sorted = [...buckets].sort((a, b) => (a.modelId || "").localeCompare(b.modelId || ""));
62937
- for (const bucket of sorted) {
62938
- const version2 = extractVersion(bucket.modelId || "");
62939
- const key = version2 || "__other__";
62940
- const existing = groups.get(key);
62941
- if (existing) {
62942
- existing.buckets.push(bucket);
62943
- } else {
62944
- groups.set(key, {
62945
- title: version2 ? `Gemini ${version2}` : "Other",
62946
- version: version2,
62947
- buckets: [bucket]
62948
- });
62949
- }
63305
+ function printUnsupported(adapter, evidence) {
63306
+ console.log("");
63307
+ console.log(` ${WHT}${B}${adapter.label}${R} ${D}\u2014 usage reporting not supported${R}`);
63308
+ console.log("");
63309
+ console.log(` ${GRY}This provider exposes no usage endpoint and returns no rate-limit${R}`);
63310
+ console.log(` ${GRY}headers, so there is nothing for claudish to report.${R}`);
63311
+ console.log("");
63312
+ console.log(` ${D}Probed ${evidence.researched_at}:${R}`);
63313
+ for (const p of evidence.probed) {
63314
+ console.log(` ${GRY}\xB7 ${p.what}${R}`);
63315
+ console.log(` ${D}\u2192 ${p.result}${R}`);
62950
63316
  }
62951
- return [...groups.values()].sort((a, b) => {
62952
- if (!a.version && !b.version)
62953
- return 0;
62954
- if (!a.version)
62955
- return 1;
62956
- if (!b.version)
62957
- return -1;
62958
- return b.version.localeCompare(a.version);
62959
- });
63317
+ if (evidence.recheck_if) {
63318
+ console.log("");
63319
+ console.log(` ${D}Re-check if: ${evidence.recheck_if}${R}`);
63320
+ }
63321
+ console.log("");
62960
63322
  }
62961
- function extractVersion(modelId) {
62962
- const match2 = modelId.match(/^gemini-([0-9]+(?:\.[0-9]+)*)-/i);
62963
- return match2?.[1];
63323
+ function printUnknownProvider(input) {
63324
+ const known = allQuotaAdapters().map((a) => a.providerId);
63325
+ console.error(`Unknown provider: ${input}`);
63326
+ console.error(`Available: ${known.join(", ")}`);
63327
+ }
63328
+ function boxTop(title) {
63329
+ console.log(` ${CYN}\u256D${"\u2500".repeat(W)}\u256E${R}`);
63330
+ const t = title.length > W - 2 ? title.slice(0, W - 3) : title;
63331
+ console.log(` ${CYN}\u2502${R} ${B}${WHT}${t}${R}${" ".repeat(Math.max(0, W - 1 - t.length))}${CYN}\u2502${R}`);
63332
+ console.log(` ${CYN}\u251C${"\u2500".repeat(W)}\u2524${R}`);
63333
+ }
63334
+ function boxRow(label, value) {
63335
+ const paddedLabel = label.padEnd(9);
63336
+ const visLen = paddedLabel.length + value.length;
63337
+ console.log(` ${CYN}\u2502${R} ${GRY}${paddedLabel}${R}${WHT}${value}${R}${" ".repeat(Math.max(0, W - 1 - visLen))}${CYN}\u2502${R}`);
63338
+ }
63339
+ function boxBottom() {
63340
+ console.log(` ${CYN}\u2570${"\u2500".repeat(W)}\u256F${R}`);
63341
+ }
63342
+ function colorFor(usedPct) {
63343
+ return usedPct < 50 ? GRN : usedPct < 80 ? YEL : RED;
62964
63344
  }
62965
63345
  function buildUsageBar(usedFraction, color, width = 24) {
62966
63346
  const clamped = Math.max(0, Math.min(1, usedFraction));
@@ -62986,25 +63366,26 @@ function formatRelativeReset(resetTime) {
62986
63366
  return `resets ${hours}h`;
62987
63367
  return `resets ${minutes}m`;
62988
63368
  }
62989
- var R = "\x1B[0m", B = "\x1B[1m", D = "\x1B[2m", I = "\x1B[3m", RED = "\x1B[31m", GRN = "\x1B[32m", YEL = "\x1B[33m", MAG = "\x1B[35m", CYN = "\x1B[36m", WHT = "\x1B[37m", GRY = "\x1B[90m", QUOTA_ADAPTERS;
63369
+ var R = "\x1B[0m", B = "\x1B[1m", D = "\x1B[2m", I = "\x1B[3m", RED = "\x1B[31m", GRN = "\x1B[32m", YEL = "\x1B[33m", CYN = "\x1B[36m", WHT = "\x1B[37m", GRY = "\x1B[90m", W = 58, FRIENDLY_NAMES;
62990
63370
  var init_quota_command = __esm(() => {
62991
- init_model_loader();
62992
- init_gemini_oauth();
62993
- init_oauth_registry();
62994
- QUOTA_ADAPTERS = [
62995
- {
62996
- name: "Gemini Code Assist",
62997
- aliases: ["gemini", "google", "go", "gemini-codeassist"],
62998
- isAvailable: () => hasOAuthCredentials("google") || hasOAuthCredentials("gemini-codeassist"),
62999
- handler: geminiQuotaHandler
63000
- },
63001
- {
63002
- name: "Codex (ChatGPT Plus/Pro)",
63003
- aliases: ["codex", "openai", "gpt", "cx", "chatgpt", "openai-codex"],
63004
- isAvailable: () => hasOAuthCredentials("openai-codex"),
63005
- handler: codexQuotaHandler
63006
- }
63007
- ];
63371
+ init_provider_definitions();
63372
+ init_registry();
63373
+ FRIENDLY_NAMES = {
63374
+ gpt: "openai-codex",
63375
+ chatgpt: "openai-codex",
63376
+ openai: "openai-codex",
63377
+ gemini: "antigravity",
63378
+ google: "antigravity",
63379
+ glm: "glm-coding",
63380
+ zai: "glm-coding",
63381
+ kimi: "kimi-coding",
63382
+ moonshot: "kimi-coding",
63383
+ minimax: "minimax-coding",
63384
+ sakana: "sakana-subscription",
63385
+ fugu: "sakana-subscription",
63386
+ zen: "opencode-zen-go",
63387
+ qwen: "qwen-cloud"
63388
+ };
63008
63389
  });
63009
63390
 
63010
63391
  // src/config.ts
@@ -66771,22 +67152,22 @@ __export(exports_cli, {
66771
67152
  });
66772
67153
  import {
66773
67154
  copyFileSync as copyFileSync2,
66774
- existsSync as existsSync24,
67155
+ existsSync as existsSync25,
66775
67156
  mkdirSync as mkdirSync14,
66776
- readFileSync as readFileSync22,
67157
+ readFileSync as readFileSync23,
66777
67158
  readdirSync as readdirSync5,
66778
67159
  unlinkSync as unlinkSync8,
66779
67160
  writeFileSync as writeFileSync16
66780
67161
  } from "fs";
66781
- import { homedir as homedir28 } from "os";
66782
- import { dirname as dirname10, join as join30 } from "path";
67162
+ import { homedir as homedir29 } from "os";
67163
+ import { dirname as dirname10, join as join31 } from "path";
66783
67164
  import { fileURLToPath as fileURLToPath2 } from "url";
66784
67165
  function getVersion3() {
66785
67166
  return VERSION;
66786
67167
  }
66787
67168
  function clearAllModelCaches() {
66788
- const cacheDir = join30(homedir28(), ".claudish");
66789
- if (!existsSync24(cacheDir))
67169
+ const cacheDir = join31(homedir29(), ".claudish");
67170
+ if (!existsSync25(cacheDir))
66790
67171
  return;
66791
67172
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
66792
67173
  let cleared = 0;
@@ -66794,7 +67175,7 @@ function clearAllModelCaches() {
66794
67175
  const files = readdirSync5(cacheDir);
66795
67176
  for (const file2 of files) {
66796
67177
  if (cachePatterns.includes(file2)) {
66797
- unlinkSync8(join30(cacheDir, file2));
67178
+ unlinkSync8(join31(cacheDir, file2));
66798
67179
  cleared++;
66799
67180
  }
66800
67181
  }
@@ -67204,8 +67585,8 @@ Usage: claudish --models --provider <slug>`);
67204
67585
  });
67205
67586
  config3.resolvedDefaultProvider = resolved;
67206
67587
  if (resolved.legacyAutoPromoted && !config3.quiet) {
67207
- const markerFile = join30(homedir28(), ".claudish", ".legacy-litellm-hint-shown");
67208
- if (!existsSync24(markerFile)) {
67588
+ const markerFile = join31(homedir29(), ".claudish", ".legacy-litellm-hint-shown");
67589
+ if (!existsSync25(markerFile)) {
67209
67590
  const hint = buildLegacyHint(resolved);
67210
67591
  if (hint) {
67211
67592
  console.error(hint);
@@ -68279,8 +68660,8 @@ ${h("MORE INFO")}
68279
68660
  }
68280
68661
  function printAIAgentGuide() {
68281
68662
  try {
68282
- const guidePath = join30(__dirname3, "../AI_AGENT_GUIDE.md");
68283
- const guideContent = readFileSync22(guidePath, "utf-8");
68663
+ const guidePath = join31(__dirname3, "../AI_AGENT_GUIDE.md");
68664
+ const guideContent = readFileSync23(guidePath, "utf-8");
68284
68665
  console.log(guideContent);
68285
68666
  } catch (error46) {
68286
68667
  console.error("Error reading AI Agent Guide:");
@@ -68296,19 +68677,19 @@ async function initializeClaudishSkill() {
68296
68677
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
68297
68678
  `);
68298
68679
  const cwd = process.cwd();
68299
- const claudeDir = join30(cwd, ".claude");
68300
- const skillsDir = join30(claudeDir, "skills");
68301
- const claudishSkillDir = join30(skillsDir, "claudish-usage");
68302
- const skillFile = join30(claudishSkillDir, "SKILL.md");
68303
- if (existsSync24(skillFile)) {
68680
+ const claudeDir = join31(cwd, ".claude");
68681
+ const skillsDir = join31(claudeDir, "skills");
68682
+ const claudishSkillDir = join31(skillsDir, "claudish-usage");
68683
+ const skillFile = join31(claudishSkillDir, "SKILL.md");
68684
+ if (existsSync25(skillFile)) {
68304
68685
  console.log("\u2705 Claudish skill already installed at:");
68305
68686
  console.log(` ${skillFile}
68306
68687
  `);
68307
68688
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
68308
68689
  return;
68309
68690
  }
68310
- const sourceSkillPath = join30(__dirname3, "../skills/claudish-usage/SKILL.md");
68311
- if (!existsSync24(sourceSkillPath)) {
68691
+ const sourceSkillPath = join31(__dirname3, "../skills/claudish-usage/SKILL.md");
68692
+ if (!existsSync25(sourceSkillPath)) {
68312
68693
  console.error("\u274C Error: Claudish skill file not found in installation.");
68313
68694
  console.error(` Expected at: ${sourceSkillPath}`);
68314
68695
  console.error(`
@@ -68317,15 +68698,15 @@ async function initializeClaudishSkill() {
68317
68698
  process.exit(1);
68318
68699
  }
68319
68700
  try {
68320
- if (!existsSync24(claudeDir)) {
68701
+ if (!existsSync25(claudeDir)) {
68321
68702
  mkdirSync14(claudeDir, { recursive: true });
68322
68703
  console.log("\uD83D\uDCC1 Created .claude/ directory");
68323
68704
  }
68324
- if (!existsSync24(skillsDir)) {
68705
+ if (!existsSync25(skillsDir)) {
68325
68706
  mkdirSync14(skillsDir, { recursive: true });
68326
68707
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
68327
68708
  }
68328
- if (!existsSync24(claudishSkillDir)) {
68709
+ if (!existsSync25(claudishSkillDir)) {
68329
68710
  mkdirSync14(claudishSkillDir, { recursive: true });
68330
68711
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
68331
68712
  }
@@ -68410,33 +68791,33 @@ __export(exports_update_checker, {
68410
68791
  clearCache: () => clearCache,
68411
68792
  checkForUpdates: () => checkForUpdates
68412
68793
  });
68413
- import { existsSync as existsSync25, mkdirSync as mkdirSync15, readFileSync as readFileSync23, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
68414
- import { homedir as homedir29, platform as platform2, tmpdir } from "os";
68415
- import { join as join31 } from "path";
68794
+ import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
68795
+ import { homedir as homedir30, platform as platform2, tmpdir } from "os";
68796
+ import { join as join32 } from "path";
68416
68797
  function getCacheFilePath() {
68417
68798
  let cacheDir;
68418
68799
  if (isWindows) {
68419
- const localAppData = process.env.LOCALAPPDATA || join31(homedir29(), "AppData", "Local");
68420
- cacheDir = join31(localAppData, "claudish");
68800
+ const localAppData = process.env.LOCALAPPDATA || join32(homedir30(), "AppData", "Local");
68801
+ cacheDir = join32(localAppData, "claudish");
68421
68802
  } else {
68422
- cacheDir = join31(homedir29(), ".cache", "claudish");
68803
+ cacheDir = join32(homedir30(), ".cache", "claudish");
68423
68804
  }
68424
68805
  try {
68425
- if (!existsSync25(cacheDir)) {
68806
+ if (!existsSync26(cacheDir)) {
68426
68807
  mkdirSync15(cacheDir, { recursive: true });
68427
68808
  }
68428
- return join31(cacheDir, "update-check.json");
68809
+ return join32(cacheDir, "update-check.json");
68429
68810
  } catch {
68430
- return join31(tmpdir(), "claudish-update-check.json");
68811
+ return join32(tmpdir(), "claudish-update-check.json");
68431
68812
  }
68432
68813
  }
68433
68814
  function readCache() {
68434
68815
  try {
68435
68816
  const cachePath = getCacheFilePath();
68436
- if (!existsSync25(cachePath)) {
68817
+ if (!existsSync26(cachePath)) {
68437
68818
  return null;
68438
68819
  }
68439
- const data = JSON.parse(readFileSync23(cachePath, "utf-8"));
68820
+ const data = JSON.parse(readFileSync24(cachePath, "utf-8"));
68440
68821
  return data;
68441
68822
  } catch {
68442
68823
  return null;
@@ -68459,7 +68840,7 @@ function isCacheValid(cache2) {
68459
68840
  function clearCache() {
68460
68841
  try {
68461
68842
  const cachePath = getCacheFilePath();
68462
- if (existsSync25(cachePath)) {
68843
+ if (existsSync26(cachePath)) {
68463
68844
  unlinkSync9(cachePath);
68464
68845
  }
68465
68846
  } catch {}
@@ -69344,15 +69725,15 @@ var init_local_liveness = __esm(() => {
69344
69725
  });
69345
69726
 
69346
69727
  // src/providers/probe-catalog.ts
69347
- import { existsSync as existsSync26, mkdirSync as mkdirSync16, readFileSync as readFileSync24, writeFileSync as writeFileSync18 } from "fs";
69348
- import { homedir as homedir30 } from "os";
69349
- import { dirname as dirname11, join as join32 } from "path";
69728
+ import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync25, writeFileSync as writeFileSync18 } from "fs";
69729
+ import { homedir as homedir31 } from "os";
69730
+ import { dirname as dirname11, join as join33 } from "path";
69350
69731
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
69351
- if (!existsSync26(path2))
69732
+ if (!existsSync27(path2))
69352
69733
  return null;
69353
69734
  let raw2;
69354
69735
  try {
69355
- raw2 = JSON.parse(readFileSync24(path2, "utf-8"));
69736
+ raw2 = JSON.parse(readFileSync25(path2, "utf-8"));
69356
69737
  } catch {
69357
69738
  return null;
69358
69739
  }
@@ -69481,7 +69862,7 @@ function isValidResponse(raw2) {
69481
69862
  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;
69482
69863
  var init_probe_catalog = __esm(() => {
69483
69864
  CACHE_TTL_MS4 = 60 * 60 * 1000;
69484
- PROBE_MODELS_CACHE_PATH = join32(homedir30(), ".claudish", "probe-models.json");
69865
+ PROBE_MODELS_CACHE_PATH = join33(homedir31(), ".claudish", "probe-models.json");
69485
69866
  });
69486
69867
 
69487
69868
  // src/tui/constants.ts
@@ -75835,17 +76216,17 @@ __export(exports_claude_runner, {
75835
76216
  import { spawn as spawn4 } from "child_process";
75836
76217
  import {
75837
76218
  closeSync as closeSync5,
75838
- existsSync as existsSync27,
76219
+ existsSync as existsSync28,
75839
76220
  mkdirSync as mkdirSync17,
75840
76221
  openSync as openSync5,
75841
- readFileSync as readFileSync25,
76222
+ readFileSync as readFileSync26,
75842
76223
  readdirSync as readdirSync6,
75843
76224
  statSync as statSync5,
75844
76225
  unlinkSync as unlinkSync10,
75845
76226
  writeFileSync as writeFileSync19
75846
76227
  } from "fs";
75847
- import { homedir as homedir31, tmpdir as tmpdir2 } from "os";
75848
- import { dirname as dirname12, join as join33 } from "path";
76228
+ import { homedir as homedir32, tmpdir as tmpdir2 } from "os";
76229
+ import { dirname as dirname12, join as join34 } from "path";
75849
76230
  import { isatty } from "tty";
75850
76231
  function releaseTerminalIsolation() {
75851
76232
  if (!restoreTerminal)
@@ -75880,14 +76261,14 @@ function isProxyAuthMode(config3) {
75880
76261
  }
75881
76262
  function managedSettingsPath() {
75882
76263
  if (isWindows2()) {
75883
- return join33(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
76264
+ return join34(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
75884
76265
  }
75885
76266
  if (process.platform === "darwin") {
75886
76267
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
75887
76268
  }
75888
76269
  return "/etc/claude-code/managed-settings.json";
75889
76270
  }
75890
- function managedSettingsForcesClaudeAi(readFile3 = readFileSync25) {
76271
+ function managedSettingsForcesClaudeAi(readFile3 = readFileSync26) {
75891
76272
  try {
75892
76273
  const raw2 = readFile3(managedSettingsPath(), "utf-8");
75893
76274
  const parsed = JSON.parse(raw2);
@@ -75901,9 +76282,9 @@ function isWindows2() {
75901
76282
  }
75902
76283
  function createStatusLineScript(tokenFilePath) {
75903
76284
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
75904
- const claudishDir = join33(homeDir, ".claudish");
76285
+ const claudishDir = join34(homeDir, ".claudish");
75905
76286
  const timestamp = Date.now();
75906
- const scriptPath = join33(claudishDir, `status-${timestamp}.js`);
76287
+ const scriptPath = join34(claudishDir, `status-${timestamp}.js`);
75907
76288
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
75908
76289
  const script = `
75909
76290
  const fs = require('fs');
@@ -75967,7 +76348,9 @@ process.stdin.on('end', () => {
75967
76348
  isEstimated = tokens.is_estimated || false;
75968
76349
  providerName = tokens.provider_name || '';
75969
76350
  if (tokens.model_name) model = tokens.model_name;
75970
- var quotaRemaining = tokens.quota_remaining;
76351
+ // Plan usage for the subscription actually being spent. Replaces the old
76352
+ // scalar quota_remaining, which only ever covered a single model.
76353
+ var plan = tokens.plan;
75971
76354
  } catch (e) {
75972
76355
  try {
75973
76356
  const json = JSON.parse(input);
@@ -76009,11 +76392,18 @@ process.stdin.on('end', () => {
76009
76392
  ctxDisplay = ctx + '%';
76010
76393
  }
76011
76394
  let quotaDisplay = '';
76012
- if (typeof quotaRemaining === 'number') {
76013
- const usedPct = ((1 - quotaRemaining) * 100).toFixed(0);
76014
- const remainPct = (quotaRemaining * 100).toFixed(0);
76015
- const qColor = quotaRemaining > 0.5 ? GREEN : quotaRemaining > 0.2 ? YELLOW : RED;
76016
- quotaDisplay = ' ' + DIM + '\u2022' + RESET + ' ' + qColor + remainPct + '% quota' + RESET;
76395
+ if (plan && Array.isArray(plan.windows)) {
76396
+ // Show the window closest to its limit \u2014 the one that cuts you off first.
76397
+ let worst = null;
76398
+ for (const w of plan.windows) {
76399
+ if (!w || typeof w.used_pct !== 'number') continue;
76400
+ if (!worst || w.used_pct > worst.used_pct) worst = w;
76401
+ }
76402
+ if (worst) {
76403
+ const usedPct = Math.round(worst.used_pct);
76404
+ const qColor = usedPct < 50 ? GREEN : usedPct < 80 ? YELLOW : RED;
76405
+ quotaDisplay = ' ' + DIM + '\u2022' + RESET + ' ' + qColor + worst.id + ':' + usedPct + '%' + RESET;
76406
+ }
76017
76407
  }
76018
76408
  console.log(\`\${CYAN}\${BOLD}\${dir}\${RESET} \${DIM}\u2022\${RESET} \${YELLOW}\${modelDisplay}\${RESET} \${DIM}\u2022\${RESET} \${GREEN}\${costDisplay}\${RESET} \${DIM}\u2022\${RESET} \${MAGENTA}\${ctxDisplay}\${RESET}\${quotaDisplay}\`);
76019
76409
  } catch (e) {
@@ -76058,7 +76448,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
76058
76448
  if (!name.startsWith("tokens-") || !name.endsWith(".json"))
76059
76449
  continue;
76060
76450
  scanned++;
76061
- const full = join33(dir, name);
76451
+ const full = join34(dir, name);
76062
76452
  try {
76063
76453
  if (statSync5(full).mtimeMs >= cutoff)
76064
76454
  continue;
@@ -76075,7 +76465,7 @@ function parseSettingsArg(value) {
76075
76465
  if (value.trimStart().startsWith("{")) {
76076
76466
  return JSON.parse(value);
76077
76467
  }
76078
- return JSON.parse(readFileSync25(value, "utf-8"));
76468
+ return JSON.parse(readFileSync26(value, "utf-8"));
76079
76469
  }
76080
76470
  function parseSettingsArgSafe(value) {
76081
76471
  try {
@@ -76087,13 +76477,13 @@ function parseSettingsArgSafe(value) {
76087
76477
  }
76088
76478
  function userSettingsFileCandidates(cwd) {
76089
76479
  return [
76090
- join33(homedir31(), ".claude", "settings.json"),
76091
- join33(cwd, ".claude", "settings.json"),
76092
- join33(cwd, ".claude", "settings.local.json")
76480
+ join34(homedir32(), ".claude", "settings.json"),
76481
+ join34(cwd, ".claude", "settings.json"),
76482
+ join34(cwd, ".claude", "settings.local.json")
76093
76483
  ];
76094
76484
  }
76095
76485
  function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
76096
- const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync27(file2));
76486
+ const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync28(file2));
76097
76487
  const idx = claudeArgs.indexOf("--settings");
76098
76488
  const settingsArg = idx === -1 ? undefined : claudeArgs[idx + 1];
76099
76489
  if (settingsArg)
@@ -76130,13 +76520,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
76130
76520
  }
76131
76521
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
76132
76522
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
76133
- const claudishDir = join33(homeDir, ".claudish");
76523
+ const claudishDir = join34(homeDir, ".claudish");
76134
76524
  try {
76135
76525
  mkdirSync17(claudishDir, { recursive: true });
76136
76526
  } catch {}
76137
76527
  const timestamp = Date.now();
76138
- const tempPath = join33(claudishDir, `settings-${timestamp}.json`);
76139
- const tokenFilePath = join33(claudishDir, `tokens-${port}.json`);
76528
+ const tempPath = join34(claudishDir, `settings-${timestamp}.json`);
76529
+ const tokenFilePath = join34(claudishDir, `tokens-${port}.json`);
76140
76530
  cleanupStaleTokenFiles(claudishDir);
76141
76531
  initializeTokenFile(tokenFilePath);
76142
76532
  let statusCommand;
@@ -76407,8 +76797,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
76407
76797
  console.error("Install it from: https://claude.com/claude-code");
76408
76798
  console.error(`
76409
76799
  Or set CLAUDE_PATH to your custom installation:`);
76410
- const home = homedir31();
76411
- const localPath = isWindows2() ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
76800
+ const home = homedir32();
76801
+ const localPath = isWindows2() ? join34(home, ".claude", "local", "claude.exe") : join34(home, ".claude", "local", "claude");
76412
76802
  console.error(` export CLAUDE_PATH=${localPath}`);
76413
76803
  process.exit(1);
76414
76804
  }
@@ -76488,23 +76878,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
76488
76878
  async function findClaudeBinary() {
76489
76879
  const isWindows3 = process.platform === "win32";
76490
76880
  if (process.env.CLAUDE_PATH) {
76491
- if (existsSync27(process.env.CLAUDE_PATH)) {
76881
+ if (existsSync28(process.env.CLAUDE_PATH)) {
76492
76882
  return process.env.CLAUDE_PATH;
76493
76883
  }
76494
76884
  }
76495
- const home = homedir31();
76496
- const localPath = isWindows3 ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
76497
- if (existsSync27(localPath)) {
76885
+ const home = homedir32();
76886
+ const localPath = isWindows3 ? join34(home, ".claude", "local", "claude.exe") : join34(home, ".claude", "local", "claude");
76887
+ if (existsSync28(localPath)) {
76498
76888
  return localPath;
76499
76889
  }
76500
76890
  if (isWindows3) {
76501
76891
  const windowsPaths = [
76502
- join33(home, "AppData", "Roaming", "npm", "claude.cmd"),
76503
- join33(home, ".npm-global", "claude.cmd"),
76504
- join33(home, "node_modules", ".bin", "claude.cmd")
76892
+ join34(home, "AppData", "Roaming", "npm", "claude.cmd"),
76893
+ join34(home, ".npm-global", "claude.cmd"),
76894
+ join34(home, "node_modules", ".bin", "claude.cmd")
76505
76895
  ];
76506
76896
  for (const path2 of windowsPaths) {
76507
- if (existsSync27(path2)) {
76897
+ if (existsSync28(path2)) {
76508
76898
  return path2;
76509
76899
  }
76510
76900
  }
@@ -76512,14 +76902,14 @@ async function findClaudeBinary() {
76512
76902
  const commonPaths = [
76513
76903
  "/usr/local/bin/claude",
76514
76904
  "/opt/homebrew/bin/claude",
76515
- join33(home, ".npm-global/bin/claude"),
76516
- join33(home, ".local/bin/claude"),
76517
- join33(home, "node_modules/.bin/claude"),
76905
+ join34(home, ".npm-global/bin/claude"),
76906
+ join34(home, ".local/bin/claude"),
76907
+ join34(home, "node_modules/.bin/claude"),
76518
76908
  "/data/data/com.termux/files/usr/bin/claude",
76519
- join33(home, "../usr/bin/claude")
76909
+ join34(home, "../usr/bin/claude")
76520
76910
  ];
76521
76911
  for (const path2 of commonPaths) {
76522
- if (existsSync27(path2)) {
76912
+ if (existsSync28(path2)) {
76523
76913
  return path2;
76524
76914
  }
76525
76915
  }
@@ -76580,17 +76970,17 @@ __export(exports_diag_output, {
76580
76970
  LogFileDiagOutput: () => LogFileDiagOutput
76581
76971
  });
76582
76972
  import { createWriteStream as createWriteStream3, mkdirSync as mkdirSync18, unlinkSync as unlinkSync11, writeFileSync as writeFileSync20 } from "fs";
76583
- import { homedir as homedir32 } from "os";
76584
- import { join as join34 } from "path";
76973
+ import { homedir as homedir33 } from "os";
76974
+ import { join as join35 } from "path";
76585
76975
  function getClaudishDir() {
76586
- const dir = join34(homedir32(), ".claudish");
76976
+ const dir = join35(homedir33(), ".claudish");
76587
76977
  try {
76588
76978
  mkdirSync18(dir, { recursive: true });
76589
76979
  } catch {}
76590
76980
  return dir;
76591
76981
  }
76592
76982
  function getDiagLogPath() {
76593
- return join34(getClaudishDir(), `diag-${process.pid}.log`);
76983
+ return join35(getClaudishDir(), `diag-${process.pid}.log`);
76594
76984
  }
76595
76985
 
76596
76986
  class LogFileDiagOutput {
@@ -76801,9 +77191,9 @@ __export(exports_team_grid, {
76801
77191
  });
76802
77192
  import { spawn as spawn5 } from "child_process";
76803
77193
  import { execSync as execSync2 } from "child_process";
76804
- import { existsSync as existsSync28, readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "fs";
77194
+ import { existsSync as existsSync29, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
76805
77195
  import { connect as netConnect } from "net";
76806
- import { dirname as dirname13, join as join35 } from "path";
77196
+ import { dirname as dirname13, join as join36 } from "path";
76807
77197
  import { setTimeout as wait } from "timers/promises";
76808
77198
  import { fileURLToPath as fileURLToPath3 } from "url";
76809
77199
  function resolveRouteInfo(modelId) {
@@ -76897,18 +77287,18 @@ function buildPaneHeader(model, prompt, bg) {
76897
77287
  function findMagmuxBinary() {
76898
77288
  const thisFile = fileURLToPath3(import.meta.url);
76899
77289
  const thisDir = dirname13(thisFile);
76900
- const pkgRoot = join35(thisDir, "..");
77290
+ const pkgRoot = join36(thisDir, "..");
76901
77291
  const platform3 = process.platform;
76902
77292
  const arch = process.arch;
76903
- const bundledMagmux = join35(pkgRoot, "native", `magmux-${platform3}-${arch}`);
76904
- if (existsSync28(bundledMagmux))
77293
+ const bundledMagmux = join36(pkgRoot, "native", `magmux-${platform3}-${arch}`);
77294
+ if (existsSync29(bundledMagmux))
76905
77295
  return bundledMagmux;
76906
77296
  try {
76907
77297
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
76908
77298
  let searchDir = pkgRoot;
76909
77299
  for (let i = 0;i < 5; i++) {
76910
- const candidate = join35(searchDir, "node_modules", pkgName, "bin", "magmux");
76911
- if (existsSync28(candidate))
77300
+ const candidate = join36(searchDir, "node_modules", pkgName, "bin", "magmux");
77301
+ if (existsSync29(candidate))
76912
77302
  return candidate;
76913
77303
  const parent = dirname13(searchDir);
76914
77304
  if (parent === searchDir)
@@ -76927,7 +77317,7 @@ function findMagmuxBinary() {
76927
77317
  async function subscribeToMagmux(sockPath, onEvent) {
76928
77318
  let client = null;
76929
77319
  for (let attempt = 0;attempt < 40; attempt++) {
76930
- if (existsSync28(sockPath)) {
77320
+ if (existsSync29(sockPath)) {
76931
77321
  try {
76932
77322
  client = await new Promise((resolve5, reject) => {
76933
77323
  const s = netConnect(sockPath);
@@ -77014,9 +77404,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
77014
77404
  const keep = opts?.keep ?? false;
77015
77405
  const manifest = setupSession(sessionPath, models, input);
77016
77406
  const startedAt = new Date().toISOString();
77017
- const gridfilePath = join35(sessionPath, "gridfile.txt");
77018
- const prompt = readFileSync26(join35(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
77019
- const rawPrompt = readFileSync26(join35(sessionPath, "input.md"), "utf-8");
77407
+ const gridfilePath = join36(sessionPath, "gridfile.txt");
77408
+ const prompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
77409
+ const rawPrompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8");
77020
77410
  const usedBannerColors = new Set;
77021
77411
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
77022
77412
  const model = manifest.models[anonId].model;
@@ -77047,7 +77437,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
77047
77437
  });
77048
77438
  const [{ results: results2 }] = await Promise.all([subscription, procExit]);
77049
77439
  const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
77050
- const statusPath = join35(sessionPath, "status.json");
77440
+ const statusPath = join36(sessionPath, "status.json");
77051
77441
  writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
77052
77442
  return status;
77053
77443
  }
@@ -77071,8 +77461,8 @@ var init_team_grid = __esm(() => {
77071
77461
  init_op_source();
77072
77462
  init_startup_trace();
77073
77463
  var import_dotenv3 = __toESM(require_main(), 1);
77074
- import { existsSync as existsSync29, readFileSync as readFileSync27 } from "fs";
77075
- import { join as join36, resolve as resolve5 } from "path";
77464
+ import { existsSync as existsSync30, readFileSync as readFileSync28 } from "fs";
77465
+ import { join as join37, resolve as resolve5 } from "path";
77076
77466
  import_dotenv3.config({ quiet: true });
77077
77467
  function classifyStartupKind() {
77078
77468
  const argv = process.argv.slice(2);
@@ -77171,7 +77561,7 @@ async function applyConfigOverride() {
77171
77561
  const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
77172
77562
  const plan = planConfigOverride2(process.argv.slice(2), process.env, {
77173
77563
  resolve: resolve5,
77174
- exists: existsSync29
77564
+ exists: existsSync30
77175
77565
  });
77176
77566
  if (plan.kind === "none")
77177
77567
  return;
@@ -77319,14 +77709,14 @@ async function runCli() {
77319
77709
  if (cliConfig.team && cliConfig.team.length > 0) {
77320
77710
  let prompt = cliConfig.claudeArgs.join(" ");
77321
77711
  if (cliConfig.inputFile) {
77322
- prompt = readFileSync27(cliConfig.inputFile, "utf-8");
77712
+ prompt = readFileSync28(cliConfig.inputFile, "utf-8");
77323
77713
  }
77324
77714
  if (!prompt.trim()) {
77325
77715
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
77326
77716
  process.exit(1);
77327
77717
  }
77328
77718
  const mode = cliConfig.teamMode ?? "default";
77329
- const sessionPath = join36(process.cwd(), `.claudish-team-${Date.now()}`);
77719
+ const sessionPath = join37(process.cwd(), `.claudish-team-${Date.now()}`);
77330
77720
  if (mode === "json") {
77331
77721
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
77332
77722
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -77336,9 +77726,9 @@ async function runCli() {
77336
77726
  });
77337
77727
  const result = { ...status2, responses: {} };
77338
77728
  for (const anonId of Object.keys(status2.models)) {
77339
- const responsePath = join36(sessionPath, `response-${anonId}.md`);
77729
+ const responsePath = join37(sessionPath, `response-${anonId}.md`);
77340
77730
  try {
77341
- const raw2 = readFileSync27(responsePath, "utf-8").trim();
77731
+ const raw2 = readFileSync28(responsePath, "utf-8").trim();
77342
77732
  try {
77343
77733
  result.responses[anonId] = JSON.parse(raw2);
77344
77734
  } catch {