claudish 7.38.0 → 7.40.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 +932 -522
  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.40.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
  `)}
@@ -36233,6 +36683,33 @@ var init_middleware = __esm(() => {
36233
36683
  init_gemini_thought_signature();
36234
36684
  });
36235
36685
 
36686
+ // src/handlers/shared/quota-exhaustion.ts
36687
+ function hasQuotaExhaustionWording(errorBody) {
36688
+ const lower = (errorBody || "").toLowerCase();
36689
+ return EXHAUSTION_PHRASES.some((phrase) => lower.includes(phrase));
36690
+ }
36691
+ function isQuotaExhaustionError(status, errorBody) {
36692
+ if (status !== 401 && status !== 403 && status !== 429)
36693
+ return false;
36694
+ return hasQuotaExhaustionWording(errorBody);
36695
+ }
36696
+ var EXHAUSTION_PHRASES;
36697
+ var init_quota_exhaustion = __esm(() => {
36698
+ EXHAUSTION_PHRASES = [
36699
+ "usage limit",
36700
+ "billing cycle",
36701
+ "quota",
36702
+ "insufficient balance",
36703
+ "insufficient_quota",
36704
+ "upgrade your plan",
36705
+ "exceeded your current",
36706
+ "out of credits",
36707
+ "credit balance",
36708
+ "daily limit",
36709
+ "plan limit"
36710
+ ];
36711
+ });
36712
+
36236
36713
  // src/providers/transport/openai.ts
36237
36714
  class OpenAIProviderTransport {
36238
36715
  name;
@@ -36318,11 +36795,14 @@ class OpenAIProviderTransport {
36318
36795
  function isTerminal429(body) {
36319
36796
  if (!body)
36320
36797
  return false;
36798
+ if (isQuotaExhaustionError(429, body))
36799
+ return true;
36321
36800
  const lower = body.toLowerCase();
36322
36801
  return lower.includes("insufficient balance") || lower.includes("insufficient_balance") || lower.includes("insufficient_quota") || lower.includes("insufficient quota") || lower.includes("billing_not_active") || lower.includes("billing not active") || lower.includes("quota_exceeded") || lower.includes("exceeded your current quota") || lower.includes("out of credits") || lower.includes('"code":"1113"') || lower.includes('"code":1113');
36323
36802
  }
36324
36803
  var OpenAITimeoutError, OpenAIConnectionError;
36325
36804
  var init_openai = __esm(() => {
36805
+ init_quota_exhaustion();
36326
36806
  init_logger();
36327
36807
  OpenAITimeoutError = class OpenAITimeoutError extends Error {
36328
36808
  constructor(baseUrl) {
@@ -36646,25 +37126,25 @@ var init_model_parser = __esm(() => {
36646
37126
 
36647
37127
  // src/stats-buffer.ts
36648
37128
  import {
36649
- existsSync as existsSync14,
37129
+ existsSync as existsSync15,
36650
37130
  mkdirSync as mkdirSync8,
36651
- readFileSync as readFileSync12,
37131
+ readFileSync as readFileSync13,
36652
37132
  renameSync,
36653
37133
  unlinkSync as unlinkSync5,
36654
37134
  writeFileSync as writeFileSync7
36655
37135
  } from "fs";
36656
- import { homedir as homedir20 } from "os";
36657
- import { join as join20 } from "path";
37136
+ import { homedir as homedir21 } from "os";
37137
+ import { join as join21 } from "path";
36658
37138
  function ensureDir() {
36659
- if (!existsSync14(CLAUDISH_DIR)) {
37139
+ if (!existsSync15(CLAUDISH_DIR)) {
36660
37140
  mkdirSync8(CLAUDISH_DIR, { recursive: true });
36661
37141
  }
36662
37142
  }
36663
37143
  function readFromDisk() {
36664
37144
  try {
36665
- if (!existsSync14(BUFFER_FILE))
37145
+ if (!existsSync15(BUFFER_FILE))
36666
37146
  return [];
36667
- const raw = readFileSync12(BUFFER_FILE, "utf-8");
37147
+ const raw = readFileSync13(BUFFER_FILE, "utf-8");
36668
37148
  const parsed = JSON.parse(raw);
36669
37149
  if (!Array.isArray(parsed.events))
36670
37150
  return [];
@@ -36689,7 +37169,7 @@ function writeToDisk(events) {
36689
37169
  ensureDir();
36690
37170
  const trimmed2 = enforceSizeCap([...events]);
36691
37171
  const payload = { version: 1, events: trimmed2 };
36692
- const tmpFile = join20(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
37172
+ const tmpFile = join21(CLAUDISH_DIR, `stats-buffer.tmp.${process.pid}.json`);
36693
37173
  writeFileSync7(tmpFile, JSON.stringify(payload, null, 2), "utf-8");
36694
37174
  renameSync(tmpFile, BUFFER_FILE);
36695
37175
  memoryCache = trimmed2;
@@ -36733,7 +37213,7 @@ function clearBuffer() {
36733
37213
  try {
36734
37214
  memoryCache = [];
36735
37215
  eventsSinceLastFlush = 0;
36736
- if (existsSync14(BUFFER_FILE)) {
37216
+ if (existsSync15(BUFFER_FILE)) {
36737
37217
  unlinkSync5(BUFFER_FILE);
36738
37218
  }
36739
37219
  } catch {}
@@ -36762,8 +37242,8 @@ function syncFlushOnExit() {
36762
37242
  var BUFFER_MAX_BYTES, CLAUDISH_DIR, BUFFER_FILE, memoryCache = null, eventsSinceLastFlush = 0, flushScheduled = false;
36763
37243
  var init_stats_buffer = __esm(() => {
36764
37244
  BUFFER_MAX_BYTES = 64 * 1024;
36765
- CLAUDISH_DIR = join20(homedir20(), ".claudish");
36766
- BUFFER_FILE = join20(CLAUDISH_DIR, "stats-buffer.json");
37245
+ CLAUDISH_DIR = join21(homedir21(), ".claudish");
37246
+ BUFFER_FILE = join21(CLAUDISH_DIR, "stats-buffer.json");
36767
37247
  process.on("exit", syncFlushOnExit);
36768
37248
  process.on("SIGTERM", () => {
36769
37249
  try {
@@ -37877,9 +38357,9 @@ function compareByReleaseDateDesc(a, b) {
37877
38357
  }
37878
38358
 
37879
38359
  // 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";
38360
+ import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync14, writeFileSync as writeFileSync8 } from "fs";
38361
+ import { homedir as homedir22 } from "os";
38362
+ import { join as join22 } from "path";
37883
38363
  function groupRecommendedModels(entries) {
37884
38364
  const byId = new Map;
37885
38365
  const categoryOrder = new Map;
@@ -37989,9 +38469,9 @@ async function getRecommendedModels(opts = {}) {
37989
38469
  if (!forceRefresh && _cachedRecommendedModels) {
37990
38470
  return _cachedRecommendedModels;
37991
38471
  }
37992
- if (!forceRefresh && existsSync15(RECOMMENDED_MODELS_CACHE_PATH)) {
38472
+ if (!forceRefresh && existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
37993
38473
  try {
37994
- const cacheData = JSON.parse(readFileSync13(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38474
+ const cacheData = JSON.parse(readFileSync14(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
37995
38475
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
37996
38476
  _cachedRecommendedModels = cacheData;
37997
38477
  return cacheData;
@@ -38007,7 +38487,7 @@ async function getRecommendedModels(opts = {}) {
38007
38487
  if (data.models && data.models.length > 0) {
38008
38488
  _cachedRecommendedModels = data;
38009
38489
  try {
38010
- const cacheDir = join21(homedir21(), ".claudish");
38490
+ const cacheDir = join22(homedir22(), ".claudish");
38011
38491
  mkdirSync9(cacheDir, { recursive: true });
38012
38492
  writeFileSync8(RECOMMENDED_MODELS_CACHE_PATH, JSON.stringify(data), "utf-8");
38013
38493
  } catch {}
@@ -38020,9 +38500,9 @@ async function getRecommendedModels(opts = {}) {
38020
38500
  function getRecommendedModelsSync() {
38021
38501
  if (_cachedRecommendedModels)
38022
38502
  return _cachedRecommendedModels;
38023
- if (existsSync15(RECOMMENDED_MODELS_CACHE_PATH)) {
38503
+ if (existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
38024
38504
  try {
38025
- const cacheData = JSON.parse(readFileSync13(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38505
+ const cacheData = JSON.parse(readFileSync14(RECOMMENDED_MODELS_CACHE_PATH, "utf-8"));
38026
38506
  if (cacheData.models && cacheData.models.length > 0 && isFreshEnough(cacheData)) {
38027
38507
  _cachedRecommendedModels = cacheData;
38028
38508
  return cacheData;
@@ -38146,7 +38626,7 @@ var _cachedModelInfo = null, _cachedModelIds = null, _cachedRecommendedModels =
38146
38626
  var init_model_loader = __esm(() => {
38147
38627
  init_cache_ttl();
38148
38628
  FIREBASE_RECOMMENDED_URL = `${FIREBASE_BASE_URL}?catalog=recommended`;
38149
- RECOMMENDED_MODELS_CACHE_PATH = join21(homedir21(), ".claudish", "recommended-models-cache.json");
38629
+ RECOMMENDED_MODELS_CACHE_PATH = join22(homedir22(), ".claudish", "recommended-models-cache.json");
38150
38630
  FIREBASE_SLUG_TO_PROVIDER_NAME = {
38151
38631
  openai: "openai",
38152
38632
  google: "google",
@@ -39496,8 +39976,8 @@ var init_openai_responses_sse = __esm(() => {
39496
39976
 
39497
39977
  // src/handlers/shared/token-tracker.ts
39498
39978
  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";
39979
+ import { homedir as homedir23 } from "os";
39980
+ import { dirname as dirname8, join as join23 } from "path";
39501
39981
  function stripProviderPrefix(name) {
39502
39982
  const at = name.indexOf("@");
39503
39983
  return at === -1 ? name : name.slice(at + 1);
@@ -39511,7 +39991,8 @@ class TokenTracker {
39511
39991
  sessionOutputTokens = 0;
39512
39992
  lastInputTokens = 0;
39513
39993
  modelNameOverride;
39514
- quotaRemaining;
39994
+ planUsage;
39995
+ lastPlanSerialized = "";
39515
39996
  constructor(port, config2) {
39516
39997
  this.port = port;
39517
39998
  this.config = config2;
@@ -39522,8 +40003,13 @@ class TokenTracker {
39522
40003
  setProviderDisplayName(name) {
39523
40004
  this.config.providerDisplayName = name;
39524
40005
  }
39525
- setQuotaRemaining(fraction) {
39526
- this.quotaRemaining = fraction;
40006
+ setPlanUsage(plan) {
40007
+ const next = plan ? JSON.stringify(plan) : "";
40008
+ if (next === this.lastPlanSerialized)
40009
+ return;
40010
+ this.planUsage = plan;
40011
+ this.lastPlanSerialized = next;
40012
+ this.rewrite();
39527
40013
  }
39528
40014
  rewrite() {
39529
40015
  this.writeFile(this.getLastInputTokens(), this.sessionOutputTokens);
@@ -39645,11 +40131,15 @@ class TokenTracker {
39645
40131
  if (displayModel) {
39646
40132
  data.model_name = displayModel;
39647
40133
  }
39648
- if (this.quotaRemaining !== undefined) {
39649
- data.quota_remaining = this.quotaRemaining;
40134
+ if (this.planUsage && !isPlanStale(this.planUsage)) {
40135
+ data.plan = {
40136
+ label: this.planUsage.label,
40137
+ windows: this.planUsage.windows,
40138
+ source: this.planUsage.source
40139
+ };
39650
40140
  }
39651
40141
  const override = process.env.CLAUDISH_TOKEN_FILE;
39652
- const outPath = override || join22(homedir22(), ".claudish", `tokens-${this.port}.json`);
40142
+ const outPath = override || join23(homedir23(), ".claudish", `tokens-${this.port}.json`);
39653
40143
  mkdirSync10(dirname8(outPath), { recursive: true });
39654
40144
  writeFileSync9(outPath, JSON.stringify(data), "utf-8");
39655
40145
  } catch (e) {
@@ -39658,6 +40148,7 @@ class TokenTracker {
39658
40148
  }
39659
40149
  }
39660
40150
  var init_token_tracker = __esm(() => {
40151
+ init_types2();
39661
40152
  init_logger();
39662
40153
  init_remote_provider_types();
39663
40154
  });
@@ -39684,6 +40175,7 @@ class ComposedHandler {
39684
40175
  options;
39685
40176
  isInteractive;
39686
40177
  pendingFallbackMeta;
40178
+ lastPlanPollAt = 0;
39687
40179
  constructor(provider, targetModel, modelName, port, options = {}) {
39688
40180
  if (modelName.includes("@")) {
39689
40181
  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 +40341,6 @@ class ComposedHandler {
39849
40341
  if (this.provider.displayName) {
39850
40342
  this.tokenTracker.setProviderDisplayName(this.provider.displayName);
39851
40343
  }
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
40344
  } catch (err) {
39859
40345
  log(`[${this.provider.displayName}] Auth/health check failed: ${err.message}`);
39860
40346
  logStderr(`Error [${this.provider.displayName}]: Auth/health check failed \u2014 ${err.message}. Check credentials and server.`);
@@ -39949,6 +40435,7 @@ class ComposedHandler {
39949
40435
  log(`[ComposedHandler] Transport fell back to model: ${activeModel}`);
39950
40436
  }
39951
40437
  log(`[${this.provider.displayName}] Response status: ${response.status}`);
40438
+ this.capturePlanUsage(response);
39952
40439
  if (!response.ok) {
39953
40440
  if (response.status === 401 && this.provider.forceRefreshAuth) {
39954
40441
  log(`[${this.provider.displayName}] Got 401, forcing auth refresh and retrying`);
@@ -40142,6 +40629,7 @@ class ComposedHandler {
40142
40629
  }
40143
40630
  latencyMs = Math.round(performance.now() - startTime);
40144
40631
  const httpStatus = response.status;
40632
+ this.capturePlanUsage(response);
40145
40633
  let streamApiError = null;
40146
40634
  const onStreamComplete = () => {
40147
40635
  try {
@@ -40315,18 +40803,31 @@ class ComposedHandler {
40315
40803
  getTokenTracker() {
40316
40804
  return this.tokenTracker;
40317
40805
  }
40318
- async fetchQuotaForStatusLine() {
40806
+ capturePlanUsage(response) {
40319
40807
  try {
40320
- const fn = this.provider.getQuotaRemaining;
40321
- if (typeof fn !== "function")
40808
+ const adapter = resolveQuotaAdapter(this.provider.name);
40809
+ if (!adapter)
40810
+ return;
40811
+ const plan = adapter.scrape?.(response);
40812
+ if (plan) {
40813
+ this.tokenTracker.setPlanUsage(plan);
40322
40814
  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
40815
  }
40816
+ this.maybePollPlanUsage(adapter);
40328
40817
  } catch {}
40329
40818
  }
40819
+ maybePollPlanUsage(adapter) {
40820
+ if (!adapter.poll)
40821
+ return;
40822
+ const now = Date.now();
40823
+ if (now - this.lastPlanPollAt < PLAN_POLL_INTERVAL_MS)
40824
+ return;
40825
+ this.lastPlanPollAt = now;
40826
+ adapter.poll({ modelId: this.bareModelName }).then((plan) => {
40827
+ if (plan)
40828
+ this.tokenTracker.setPlanUsage(plan);
40829
+ }).catch(() => {});
40830
+ }
40330
40831
  setFallbackMeta(chain, attempts) {
40331
40832
  this.pendingFallbackMeta = { chain, attempts };
40332
40833
  }
@@ -40344,6 +40845,9 @@ function getRecoveryHint(status, errorText, providerName) {
40344
40845
  if (status === 429 && isTerminal429(errorText)) {
40345
40846
  return "Out of quota \u2014 check your plan & billing details. This won't recover on retry.";
40346
40847
  }
40848
+ if (isQuotaExhaustionError(status, errorText)) {
40849
+ return "Subscription allowance spent \u2014 this refills on the provider's own schedule (see the message below). Reducing concurrency won't help; switch model/provider or wait.";
40850
+ }
40347
40851
  if (status === 429 || lower.includes("rate limit")) {
40348
40852
  return "Rate limited. Wait, reduce concurrency, or check plan limits.";
40349
40853
  }
@@ -40351,6 +40855,9 @@ function getRecoveryHint(status, errorText, providerName) {
40351
40855
  if (lower.includes("not supported") || lower.includes("unsupported model") || lower.includes("model not found")) {
40352
40856
  return "Model not supported by this provider. Verify model name.";
40353
40857
  }
40858
+ if (isQuotaExhaustionError(status, errorText)) {
40859
+ return "Out of quota \u2014 check your plan & billing details. This won't recover on retry.";
40860
+ }
40354
40861
  return "Check API key / OAuth credentials.";
40355
40862
  }
40356
40863
  if (status === 404) {
@@ -40374,6 +40881,8 @@ var STREAM_RETRY_DELAYS_MS;
40374
40881
  var init_composed_handler = __esm(() => {
40375
40882
  init_dialect_manager();
40376
40883
  init_model_catalog();
40884
+ init_registry();
40885
+ init_types2();
40377
40886
  init_behavior();
40378
40887
  init_logger();
40379
40888
  init_middleware();
@@ -40386,6 +40895,7 @@ var init_composed_handler = __esm(() => {
40386
40895
  init_connection_error();
40387
40896
  init_context_window_fallback();
40388
40897
  init_openai_compat();
40898
+ init_quota_exhaustion();
40389
40899
  init_stream_head_sniffer();
40390
40900
  init_anthropic_sse();
40391
40901
  init_gemini_sse();
@@ -41748,15 +42258,17 @@ var init_default_routing_rules = __esm(() => {
41748
42258
  "gpt-*": ["openai-codex", "openai", "openrouter"],
41749
42259
  "o1-*": ["openai-codex", "openai", "openrouter"],
41750
42260
  "o3-*": ["openai-codex", "openai", "openrouter"],
41751
- "gemini-*": ["gemini-codeassist", "google", "openrouter"],
42261
+ "gemini-*": ["antigravity", "google", "openrouter"],
41752
42262
  "grok-*": ["x-ai", "openrouter"],
41753
- "kimi-*": ["kimi-coding", "kimi", "openrouter"],
41754
- "k3*": ["kimi-coding", "kimi", "openrouter"],
41755
- "minimax-*": ["minimax-coding", "minimax", "openrouter"],
41756
- "glm-*": ["glm-coding", "glm", "openrouter"],
41757
- "qwen3.*": ["qwen-cloud", "openrouter"],
42263
+ "kimi-*": ["kimi-coding", "opencode-zen-go", "kimi", "openrouter"],
42264
+ "k3*": ["kimi-coding", "opencode-zen-go", "kimi", "openrouter"],
42265
+ "minimax-*": ["minimax-coding", "opencode-zen-go", "minimax", "openrouter"],
42266
+ "glm-*": ["glm-coding", "opencode-zen-go", "glm", "openrouter"],
42267
+ "qwen3.*": ["qwen-cloud", "opencode-zen-go", "openrouter"],
41758
42268
  "z-ai-*": ["z-ai", "openrouter"],
41759
- "deepseek-*": ["deepseek", "openrouter"],
42269
+ "deepseek-*": ["opencode-zen-go", "deepseek", "openrouter"],
42270
+ "mimo-*": ["opencode-zen-go", "openrouter"],
42271
+ "hy3*": ["opencode-zen-go", "openrouter"],
41760
42272
  fugu: ["sakana-subscription", "sakana"],
41761
42273
  "fugu-*": ["sakana-subscription", "sakana"],
41762
42274
  "*-zen": ["opencode-zen"],
@@ -42598,8 +43110,8 @@ var init_signal_watcher = __esm(() => {
42598
43110
  import { spawn } from "child_process";
42599
43111
  import { randomUUID as randomUUID4 } from "crypto";
42600
43112
  import { createWriteStream, mkdirSync as mkdirSync11, writeFileSync as writeFileSync10 } from "fs";
42601
- import { homedir as homedir23 } from "os";
42602
- import { join as join23 } from "path";
43113
+ import { homedir as homedir24 } from "os";
43114
+ import { join as join24 } from "path";
42603
43115
 
42604
43116
  class SessionManager {
42605
43117
  sessions = new Map;
@@ -42611,7 +43123,7 @@ class SessionManager {
42611
43123
  constructor(options) {
42612
43124
  this.maxSessions = options?.maxSessions ?? DEFAULT_MAX_SESSIONS;
42613
43125
  this.scrollbackCapacity = options?.scrollbackCapacity ?? DEFAULT_SCROLLBACK;
42614
- this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join23(homedir23(), ".claudish", "sessions");
43126
+ this.sessionsDir = options?.sessionsDir ?? process.env.CLAUDISH_SESSIONS_DIR ?? join24(homedir24(), ".claudish", "sessions");
42615
43127
  this.onStateChange = options?.onStateChange;
42616
43128
  }
42617
43129
  createSession(opts) {
@@ -42621,10 +43133,10 @@ class SessionManager {
42621
43133
  const sessionId2 = randomUUID4().slice(0, 8);
42622
43134
  const timeout = Math.min(opts.timeoutSeconds ?? DEFAULT_TIMEOUT, MAX_TIMEOUT);
42623
43135
  const startedAt = new Date().toISOString();
42624
- const sessionDir = join23(this.sessionsDir, sessionId2);
43136
+ const sessionDir = join24(this.sessionsDir, sessionId2);
42625
43137
  mkdirSync11(sessionDir, { recursive: true });
42626
43138
  if (opts.prompt) {
42627
- writeFileSync10(join23(sessionDir, "prompt.md"), opts.prompt, "utf-8");
43139
+ writeFileSync10(join24(sessionDir, "prompt.md"), opts.prompt, "utf-8");
42628
43140
  }
42629
43141
  const args = [
42630
43142
  "--model",
@@ -42658,7 +43170,7 @@ class SessionManager {
42658
43170
  });
42659
43171
  }
42660
43172
  });
42661
- const outputLogStream = createWriteStream(join23(sessionDir, "output.log"));
43173
+ const outputLogStream = createWriteStream(join24(sessionDir, "output.log"));
42662
43174
  const entry = {
42663
43175
  info: {
42664
43176
  sessionId: sessionId2,
@@ -42705,9 +43217,9 @@ class SessionManager {
42705
43217
  watcher.processExited(code);
42706
43218
  outputLogStream.end();
42707
43219
  if (entry.stderr) {
42708
- writeFileSync10(join23(sessionDir, "stderr.log"), entry.stderr, "utf-8");
43220
+ writeFileSync10(join24(sessionDir, "stderr.log"), entry.stderr, "utf-8");
42709
43221
  }
42710
- writeFileSync10(join23(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
43222
+ writeFileSync10(join24(sessionDir, "meta.json"), JSON.stringify(entry.info, null, 2), "utf-8");
42711
43223
  this.cleanupSigint();
42712
43224
  });
42713
43225
  proc.on("error", (err) => {
@@ -44905,7 +45417,11 @@ class FallbackHandler {
44905
45417
  }
44906
45418
  errors3.push({ provider: name, status: response.status, message: errorBody });
44907
45419
  if (!isLast) {
44908
- logStderr(`[Fallback] ${name} failed (HTTP ${response.status}), trying next provider...`);
45420
+ if (hasQuotaExhaustionWording(errorBody)) {
45421
+ logStderr(`[Fallback] ${name} subscription allowance is spent \u2014 falling through to the next provider, which is billed PER TOKEN. Use a provider prefix (e.g. \`zgo@model\`) to fail instead of switching.`);
45422
+ } else {
45423
+ logStderr(`[Fallback] ${name} failed (HTTP ${response.status}), trying next provider...`);
45424
+ }
44909
45425
  }
44910
45426
  } catch (err) {
44911
45427
  errors3.push({ provider: name, status: 0, message: err.message });
@@ -44942,6 +45458,8 @@ ${summary}`);
44942
45458
  }
44943
45459
  }
44944
45460
  function isRetryableError(status, errorBody) {
45461
+ if (hasQuotaExhaustionWording(errorBody))
45462
+ return true;
44945
45463
  if (status === 401 || status === 403)
44946
45464
  return true;
44947
45465
  if (status === 402)
@@ -44986,6 +45504,7 @@ function truncate(s, max) {
44986
45504
  var init_fallback_handler = __esm(() => {
44987
45505
  init_logger();
44988
45506
  init_composed_handler();
45507
+ init_quota_exhaustion();
44989
45508
  });
44990
45509
 
44991
45510
  // src/handlers/native-handler-advisor.ts
@@ -45635,7 +46154,7 @@ var init_api_key_map = __esm(() => {
45635
46154
  "qwen-cloud": { envVar: "QWEN_CLOUD_PLAN_API_KEY" },
45636
46155
  ollamacloud: { envVar: "OLLAMA_API_KEY" },
45637
46156
  "opencode-zen": { envVar: "OPENCODE_API_KEY" },
45638
- "opencode-zen-go": { envVar: "OPENCODE_API_KEY" },
46157
+ "opencode-zen-go": { envVar: "OPENCODE_GO_API_KEY", aliases: ["OPENCODE_API_KEY"] },
45639
46158
  "gemini-codeassist": { envVar: "GEMINI_API_KEY" },
45640
46159
  vertex: { envVar: "VERTEX_API_KEY", aliases: ["VERTEX_PROJECT"] },
45641
46160
  poe: { envVar: "POE_API_KEY" }
@@ -45734,11 +46253,11 @@ var init_ollama_api_format = __esm(() => {
45734
46253
  });
45735
46254
 
45736
46255
  // 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";
46256
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "fs";
46257
+ import { homedir as homedir25 } from "os";
46258
+ import { join as join25, resolve as resolve2 } from "path";
45740
46259
  function activeConfigPath() {
45741
- return activeGlobalConfigFile(join24(homedir24(), ".claudish", "config.json"));
46260
+ return activeGlobalConfigFile(join25(homedir25(), ".claudish", "config.json"));
45742
46261
  }
45743
46262
  function configLayerLabel() {
45744
46263
  return getConfigFileOverride() ? activeConfigPath() : "~/.claudish/config.json";
@@ -45815,9 +46334,9 @@ function formatProvenanceLog(p) {
45815
46334
  function readDotenvKey(envVars) {
45816
46335
  try {
45817
46336
  const dotenvPath = resolve2(".env");
45818
- if (!existsSync16(dotenvPath))
46337
+ if (!existsSync17(dotenvPath))
45819
46338
  return null;
45820
- const parsed = import_dotenv.parse(readFileSync14(dotenvPath, "utf-8"));
46339
+ const parsed = import_dotenv.parse(readFileSync15(dotenvPath, "utf-8"));
45821
46340
  for (const v of envVars) {
45822
46341
  if (parsed[v])
45823
46342
  return parsed[v];
@@ -45830,9 +46349,9 @@ function readDotenvKey(envVars) {
45830
46349
  function readConfigKey(envVar) {
45831
46350
  try {
45832
46351
  const configPath = activeConfigPath();
45833
- if (!existsSync16(configPath))
46352
+ if (!existsSync17(configPath))
45834
46353
  return null;
45835
- const cfg = JSON.parse(readFileSync14(configPath, "utf-8"));
46354
+ const cfg = JSON.parse(readFileSync15(configPath, "utf-8"));
45836
46355
  return cfg.apiKeys?.[envVar] || null;
45837
46356
  } catch {
45838
46357
  return null;
@@ -46456,7 +46975,8 @@ var init_provider_profiles = __esm(() => {
46456
46975
  const zenApiKey = ctx.apiKey;
46457
46976
  const isGoProvider = ctx.provider.name === "opencode-zen-go";
46458
46977
  if (ctx.modelName.toLowerCase().includes("minimax")) {
46459
- const transport2 = new AnthropicProviderTransport(ctx.provider, zenApiKey);
46978
+ const bearerProvider = { ...ctx.provider, authScheme: "bearer" };
46979
+ const transport2 = new AnthropicProviderTransport(bearerProvider, zenApiKey);
46460
46980
  const adapter2 = new AnthropicAPIFormat(ctx.modelName, ctx.provider.name);
46461
46981
  const handler2 = new ComposedHandler(transport2, ctx.targetModel, ctx.modelName, ctx.port, {
46462
46982
  adapter: adapter2,
@@ -47305,9 +47825,9 @@ var init_poe = __esm(() => {
47305
47825
  });
47306
47826
 
47307
47827
  // 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";
47828
+ import { existsSync as existsSync18, readFileSync as readFileSync16, statSync as statSync4 } from "fs";
47829
+ import { homedir as homedir26 } from "os";
47830
+ import { join as join26 } from "path";
47311
47831
  function prefixMatch(modelName) {
47312
47832
  for (const [key, pricing] of pricingMap) {
47313
47833
  if (modelName.startsWith(key))
@@ -47345,12 +47865,12 @@ async function warmPricingCache() {
47345
47865
  }
47346
47866
  function loadDiskCache() {
47347
47867
  try {
47348
- if (!existsSync17(CACHE_FILE))
47868
+ if (!existsSync18(CACHE_FILE))
47349
47869
  return false;
47350
47870
  const stat2 = statSync4(CACHE_FILE);
47351
47871
  const age = Date.now() - stat2.mtimeMs;
47352
47872
  const isFresh = age < CACHE_TTL_MS3;
47353
- const raw2 = readFileSync15(CACHE_FILE, "utf-8");
47873
+ const raw2 = readFileSync16(CACHE_FILE, "utf-8");
47354
47874
  const data = JSON.parse(raw2);
47355
47875
  for (const [key, pricing] of Object.entries(data)) {
47356
47876
  pricingMap.set(key, pricing);
@@ -47366,8 +47886,8 @@ var init_pricing_cache = __esm(() => {
47366
47886
  init_logger();
47367
47887
  init_catalog_query();
47368
47888
  pricingMap = new Map;
47369
- CACHE_DIR = join25(homedir25(), ".claudish");
47370
- CACHE_FILE = join25(CACHE_DIR, "pricing-cache.json");
47889
+ CACHE_DIR = join26(homedir26(), ".claudish");
47890
+ CACHE_FILE = join26(CACHE_DIR, "pricing-cache.json");
47371
47891
  CACHE_TTL_MS3 = 24 * 60 * 60 * 1000;
47372
47892
  });
47373
47893
 
@@ -47862,20 +48382,20 @@ var init_redact = __esm(() => {
47862
48382
  });
47863
48383
 
47864
48384
  // src/team-stats.ts
47865
- import { existsSync as existsSync18, readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "fs";
47866
- import { join as join26 } from "path";
48385
+ import { existsSync as existsSync19, readFileSync as readFileSync17, writeFileSync as writeFileSync11 } from "fs";
48386
+ import { join as join27 } from "path";
47867
48387
  function statsDir(sessionPath) {
47868
- return join26(sessionPath, "stats");
48388
+ return join27(sessionPath, "stats");
47869
48389
  }
47870
48390
  function tokenFileFor(sessionPath, anonId) {
47871
- return join26(statsDir(sessionPath), `${anonId}.json`);
48391
+ return join27(statsDir(sessionPath), `${anonId}.json`);
47872
48392
  }
47873
48393
  function readTokenStats(sessionPath, anonId) {
47874
48394
  const path = tokenFileFor(sessionPath, anonId);
47875
- if (!existsSync18(path))
48395
+ if (!existsSync19(path))
47876
48396
  return null;
47877
48397
  try {
47878
- return JSON.parse(readFileSync16(path, "utf-8"));
48398
+ return JSON.parse(readFileSync17(path, "utf-8"));
47879
48399
  } catch {
47880
48400
  return null;
47881
48401
  }
@@ -48023,7 +48543,7 @@ ${segs.join(" \xB7 ")}`;
48023
48543
  }
48024
48544
  function writeStatusFile(sessionPath, manifest, status, opts) {
48025
48545
  try {
48026
- writeFileSync11(join26(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
48546
+ writeFileSync11(join27(sessionPath, "status.txt"), `${renderTeamStats(sessionPath, manifest, status, opts)}
48027
48547
  `, "utf-8");
48028
48548
  } catch {}
48029
48549
  }
@@ -48049,13 +48569,13 @@ __export(exports_team_orchestrator, {
48049
48569
  import { spawn as spawn2 } from "child_process";
48050
48570
  import {
48051
48571
  createWriteStream as createWriteStream2,
48052
- existsSync as existsSync19,
48572
+ existsSync as existsSync20,
48053
48573
  mkdirSync as mkdirSync12,
48054
- readFileSync as readFileSync17,
48574
+ readFileSync as readFileSync18,
48055
48575
  readdirSync as readdirSync3,
48056
48576
  writeFileSync as writeFileSync12
48057
48577
  } from "fs";
48058
- import { join as join27, resolve as resolve3 } from "path";
48578
+ import { join as join28, resolve as resolve3 } from "path";
48059
48579
  function classifyRunOutput(opts) {
48060
48580
  const { outputSize, stdoutTail, stderr, minOutputBytes } = opts;
48061
48581
  const apiError = API_ERROR_RE.exec(stdoutTail);
@@ -48116,18 +48636,18 @@ function setupSession(sessionPath, models, input) {
48116
48636
  if (models.length === 0) {
48117
48637
  throw new Error("At least one model is required");
48118
48638
  }
48119
- if (existsSync19(join27(sessionPath, "manifest.json"))) {
48639
+ if (existsSync20(join28(sessionPath, "manifest.json"))) {
48120
48640
  throw new Error(`Session already exists at ${sessionPath}. Use a new directory path or delete the existing session first.`);
48121
48641
  }
48122
48642
  const sentinels = models.filter(isSentinelModel);
48123
48643
  if (sentinels.length > 0) {
48124
48644
  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
48645
  }
48126
- mkdirSync12(join27(sessionPath, "work"), { recursive: true });
48127
- mkdirSync12(join27(sessionPath, "errors"), { recursive: true });
48646
+ mkdirSync12(join28(sessionPath, "work"), { recursive: true });
48647
+ mkdirSync12(join28(sessionPath, "errors"), { recursive: true });
48128
48648
  if (input !== undefined) {
48129
- writeFileSync12(join27(sessionPath, "input.md"), input, "utf-8");
48130
- } else if (!existsSync19(join27(sessionPath, "input.md"))) {
48649
+ writeFileSync12(join28(sessionPath, "input.md"), input, "utf-8");
48650
+ } else if (!existsSync20(join28(sessionPath, "input.md"))) {
48131
48651
  throw new Error(`No input.md found at ${sessionPath} and no input provided`);
48132
48652
  }
48133
48653
  const ids = models.map((_, i) => String(i + 1).padStart(2, "0"));
@@ -48144,9 +48664,9 @@ function setupSession(sessionPath, models, input) {
48144
48664
  model: models[i],
48145
48665
  assignedAt: now
48146
48666
  };
48147
- mkdirSync12(join27(sessionPath, "work", anonId), { recursive: true });
48667
+ mkdirSync12(join28(sessionPath, "work", anonId), { recursive: true });
48148
48668
  }
48149
- writeFileSync12(join27(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
48669
+ writeFileSync12(join28(sessionPath, "manifest.json"), JSON.stringify(manifest, null, 2), "utf-8");
48150
48670
  const status = {
48151
48671
  startedAt: now,
48152
48672
  models: Object.fromEntries(Object.keys(manifest.models).map((id) => [
@@ -48160,17 +48680,17 @@ function setupSession(sessionPath, models, input) {
48160
48680
  }
48161
48681
  ]))
48162
48682
  };
48163
- writeFileSync12(join27(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
48683
+ writeFileSync12(join28(sessionPath, "status.json"), JSON.stringify(status, null, 2), "utf-8");
48164
48684
  return manifest;
48165
48685
  }
48166
48686
  async function runModels(sessionPath, opts = {}) {
48167
48687
  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");
48688
+ const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48689
+ const statusPath = join28(sessionPath, "status.json");
48690
+ const inputPath = join28(sessionPath, "input.md");
48691
+ const inputContent = readFileSync18(inputPath, "utf-8");
48172
48692
  const spawnPlan = await (opts.spawnPlanner ?? prehydrateCredentialsForSpawn)(Object.values(manifest.models).map((m) => m.model));
48173
- const statusCache = JSON.parse(readFileSync17(statusPath, "utf-8"));
48693
+ const statusCache = JSON.parse(readFileSync18(statusPath, "utf-8"));
48174
48694
  function updateModelStatus(id, update) {
48175
48695
  statusCache.models[id] = { ...statusCache.models[id], ...update };
48176
48696
  writeFileSync12(statusPath, JSON.stringify(statusCache, null, 2), "utf-8");
@@ -48189,8 +48709,8 @@ async function runModels(sessionPath, opts = {}) {
48189
48709
  process.on("SIGINT", sigintHandler);
48190
48710
  const completionPromises = [];
48191
48711
  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`);
48712
+ const outputPath = join28(sessionPath, `response-${anonId}.md`);
48713
+ const errorLogPath = join28(sessionPath, "errors", `${anonId}.log`);
48194
48714
  const spawnModel = spawnPlan.pinned.get(entry.model) ?? entry.model;
48195
48715
  const args = ["--model", spawnModel, "-y", "--stdin", "--quiet", ...opts.claudeFlags ?? []];
48196
48716
  updateModelStatus(anonId, {
@@ -48380,23 +48900,23 @@ async function judgeResponses(sessionPath, opts = {}) {
48380
48900
  const responses = {};
48381
48901
  for (const file2 of responseFiles) {
48382
48902
  const id = file2.replace(/^response-/, "").replace(/\.md$/, "");
48383
- responses[id] = readFileSync17(join27(sessionPath, file2), "utf-8");
48903
+ responses[id] = readFileSync18(join28(sessionPath, file2), "utf-8");
48384
48904
  }
48385
- const input = readFileSync17(join27(sessionPath, "input.md"), "utf-8");
48905
+ const input = readFileSync18(join28(sessionPath, "input.md"), "utf-8");
48386
48906
  const judgePrompt = buildJudgePrompt(input, responses);
48387
- writeFileSync12(join27(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48907
+ writeFileSync12(join28(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
48388
48908
  const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
48389
- const judgePath = join27(sessionPath, "judging");
48909
+ const judgePath = join28(sessionPath, "judging");
48390
48910
  mkdirSync12(judgePath, { recursive: true });
48391
48911
  setupSession(judgePath, judgeModels, judgePrompt);
48392
48912
  await runModels(judgePath, { claudeFlags: opts.claudeFlags });
48393
48913
  const votes = parseJudgeVotes(judgePath, Object.keys(responses));
48394
48914
  const verdict = aggregateVerdict(votes, Object.keys(responses));
48395
- writeFileSync12(join27(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48915
+ writeFileSync12(join28(sessionPath, "verdict.md"), formatVerdict(verdict, sessionPath), "utf-8");
48396
48916
  return verdict;
48397
48917
  }
48398
48918
  function getStatus(sessionPath) {
48399
- return JSON.parse(readFileSync17(join27(sessionPath, "status.json"), "utf-8"));
48919
+ return JSON.parse(readFileSync18(join28(sessionPath, "status.json"), "utf-8"));
48400
48920
  }
48401
48921
  function fisherYatesShuffle(arr) {
48402
48922
  for (let i = arr.length - 1;i > 0; i--) {
@@ -48406,7 +48926,7 @@ function fisherYatesShuffle(arr) {
48406
48926
  return arr;
48407
48927
  }
48408
48928
  function getDefaultJudgeModels(sessionPath) {
48409
- const manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
48929
+ const manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48410
48930
  return Object.values(manifest.models).map((e) => e.model);
48411
48931
  }
48412
48932
  function buildJudgePrompt(input, responses) {
@@ -48469,7 +48989,7 @@ function parseJudgeVotes(judgePath, responseIds) {
48469
48989
  const judgeId = file2.replace(/^response-/, "").replace(/\.md$/, "");
48470
48990
  let content;
48471
48991
  try {
48472
- content = readFileSync17(join27(judgePath, file2), "utf-8");
48992
+ content = readFileSync18(join28(judgePath, file2), "utf-8");
48473
48993
  } catch {
48474
48994
  continue;
48475
48995
  }
@@ -48521,7 +49041,7 @@ function aggregateVerdict(votes, responseIds) {
48521
49041
  function formatVerdict(verdict, sessionPath) {
48522
49042
  let manifest = null;
48523
49043
  try {
48524
- manifest = JSON.parse(readFileSync17(join27(sessionPath, "manifest.json"), "utf-8"));
49044
+ manifest = JSON.parse(readFileSync18(join28(sessionPath, "manifest.json"), "utf-8"));
48525
49045
  } catch {}
48526
49046
  let output = `# Team Verdict
48527
49047
 
@@ -48576,14 +49096,14 @@ __export(exports_mcp_server, {
48576
49096
  parseAnthropicSse: () => parseAnthropicSse,
48577
49097
  formatTeamResult: () => formatTeamResult
48578
49098
  });
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";
49099
+ import { existsSync as existsSync21, mkdirSync as mkdirSync13, readFileSync as readFileSync19, readdirSync as readdirSync4, writeFileSync as writeFileSync13 } from "fs";
49100
+ import { homedir as homedir27 } from "os";
49101
+ import { dirname as dirname9, join as join29, resolve as resolve4 } from "path";
48582
49102
  import { fileURLToPath } from "url";
48583
49103
  async function loadAllModels(forceRefresh = false) {
48584
- if (!forceRefresh && existsSync20(ALL_MODELS_CACHE_PATH2)) {
49104
+ if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
48585
49105
  try {
48586
- const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
49106
+ const cacheData = JSON.parse(readFileSync19(ALL_MODELS_CACHE_PATH2, "utf-8"));
48587
49107
  const lastUpdated = new Date(cacheData.lastUpdated);
48588
49108
  const ageInDays = (Date.now() - lastUpdated.getTime()) / (1000 * 60 * 60 * 24);
48589
49109
  if (ageInDays <= CACHE_MAX_AGE_DAYS) {
@@ -48601,8 +49121,8 @@ async function loadAllModels(forceRefresh = false) {
48601
49121
  writeFileSync13(ALL_MODELS_CACHE_PATH2, JSON.stringify({ lastUpdated: new Date().toISOString(), models }), "utf-8");
48602
49122
  return models;
48603
49123
  } catch {
48604
- if (existsSync20(ALL_MODELS_CACHE_PATH2)) {
48605
- const cacheData = JSON.parse(readFileSync18(ALL_MODELS_CACHE_PATH2, "utf-8"));
49124
+ if (existsSync21(ALL_MODELS_CACHE_PATH2)) {
49125
+ const cacheData = JSON.parse(readFileSync19(ALL_MODELS_CACHE_PATH2, "utf-8"));
48606
49126
  return cacheData.models || [];
48607
49127
  }
48608
49128
  return [];
@@ -49184,7 +49704,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49184
49704
  let stderrFull = stderr_snippet || "";
49185
49705
  if (error_log_path) {
49186
49706
  try {
49187
- stderrFull = readFileSync18(error_log_path, "utf-8");
49707
+ stderrFull = readFileSync19(error_log_path, "utf-8");
49188
49708
  } catch {}
49189
49709
  }
49190
49710
  const sessionData = {};
@@ -49192,16 +49712,16 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49192
49712
  const sp = session_path;
49193
49713
  for (const file2 of ["status.json", "manifest.json", "input.md"]) {
49194
49714
  try {
49195
- sessionData[file2] = readFileSync18(join28(sp, file2), "utf-8");
49715
+ sessionData[file2] = readFileSync19(join29(sp, file2), "utf-8");
49196
49716
  } catch {}
49197
49717
  }
49198
49718
  try {
49199
- const errorDir = join28(sp, "errors");
49200
- if (existsSync20(errorDir)) {
49719
+ const errorDir = join29(sp, "errors");
49720
+ if (existsSync21(errorDir)) {
49201
49721
  for (const f of readdirSync4(errorDir)) {
49202
49722
  if (f.endsWith(".log")) {
49203
49723
  try {
49204
- sessionData[`errors/${f}`] = readFileSync18(join28(errorDir, f), "utf-8");
49724
+ sessionData[`errors/${f}`] = readFileSync19(join29(errorDir, f), "utf-8");
49205
49725
  } catch {}
49206
49726
  }
49207
49727
  }
@@ -49211,7 +49731,7 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49211
49731
  for (const f of readdirSync4(sp)) {
49212
49732
  if (f.startsWith("response-") && f.endsWith(".md")) {
49213
49733
  try {
49214
- const content = readFileSync18(join28(sp, f), "utf-8");
49734
+ const content = readFileSync19(join29(sp, f), "utf-8");
49215
49735
  sessionData[f] = content.slice(0, 200) + (content.length > 200 ? "... (truncated)" : "");
49216
49736
  } catch {}
49217
49737
  }
@@ -49220,9 +49740,9 @@ Use with: run_prompt(model="${results2[0].model.id}", prompt="your prompt")`;
49220
49740
  }
49221
49741
  let version2 = "unknown";
49222
49742
  try {
49223
- const pkgPath = join28(__dirname2, "../package.json");
49224
- if (existsSync20(pkgPath)) {
49225
- version2 = JSON.parse(readFileSync18(pkgPath, "utf-8")).version;
49743
+ const pkgPath = join29(__dirname2, "../package.json");
49744
+ if (existsSync21(pkgPath)) {
49745
+ version2 = JSON.parse(readFileSync19(pkgPath, "utf-8")).version;
49226
49746
  }
49227
49747
  } catch {}
49228
49748
  const report = {
@@ -49626,8 +50146,8 @@ var init_mcp_server = __esm(() => {
49626
50146
  import_dotenv2.config({ quiet: true });
49627
50147
  __filename2 = fileURLToPath(import.meta.url);
49628
50148
  __dirname2 = dirname9(__filename2);
49629
- CLAUDISH_CACHE_DIR = join28(homedir26(), ".claudish");
49630
- ALL_MODELS_CACHE_PATH2 = join28(CLAUDISH_CACHE_DIR, "all-models.json");
50149
+ CLAUDISH_CACHE_DIR = join29(homedir27(), ".claudish");
50150
+ ALL_MODELS_CACHE_PATH2 = join29(CLAUDISH_CACHE_DIR, "all-models.json");
49631
50151
  NEXT_STEP = {
49632
50152
  nonzero_exit: "read the evidence log, then retry or drop the model",
49633
50153
  timeout: "raise `timeout`, or pick a faster model",
@@ -49652,7 +50172,7 @@ var exports_serve_command = {};
49652
50172
  __export(exports_serve_command, {
49653
50173
  serveCommand: () => serveCommand
49654
50174
  });
49655
- import { existsSync as existsSync21, readFileSync as readFileSync19 } from "fs";
50175
+ import { existsSync as existsSync22, readFileSync as readFileSync20 } from "fs";
49656
50176
  function parseServeArgs(args) {
49657
50177
  const out = {};
49658
50178
  for (let i = 0;i < args.length; i++) {
@@ -49671,12 +50191,12 @@ function parseServeArgs(args) {
49671
50191
  return out;
49672
50192
  }
49673
50193
  function loadModelMap(path) {
49674
- if (!existsSync21(path)) {
50194
+ if (!existsSync22(path)) {
49675
50195
  throw new Error(`--models file not found: ${path}`);
49676
50196
  }
49677
50197
  let raw2;
49678
50198
  try {
49679
- raw2 = readFileSync19(path, "utf-8");
50199
+ raw2 = readFileSync20(path, "utf-8");
49680
50200
  } catch (e) {
49681
50201
  throw new Error(`failed to read --models file ${path}: ${e instanceof Error ? e.message : String(e)}`);
49682
50202
  }
@@ -49753,7 +50273,7 @@ var exports_behavior_command = {};
49753
50273
  __export(exports_behavior_command, {
49754
50274
  behaviorCommand: () => behaviorCommand
49755
50275
  });
49756
- import { existsSync as existsSync22, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "fs";
50276
+ import { existsSync as existsSync23, readFileSync as readFileSync21, writeFileSync as writeFileSync14 } from "fs";
49757
50277
  function severityColor(sev) {
49758
50278
  if (sev === "fix")
49759
50279
  return green(sev);
@@ -49851,8 +50371,8 @@ function setTelemetryEnabled(value) {
49851
50371
  const path = getConfigPath();
49852
50372
  let cfg = {};
49853
50373
  try {
49854
- if (existsSync22(path)) {
49855
- const parsed = JSON.parse(readFileSync20(path, "utf-8"));
50374
+ if (existsSync23(path)) {
50375
+ const parsed = JSON.parse(readFileSync21(path, "utf-8"));
49856
50376
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
49857
50377
  cfg = parsed;
49858
50378
  }
@@ -49873,8 +50393,8 @@ function showTelemetry(action, json2) {
49873
50393
  let pending = 0;
49874
50394
  try {
49875
50395
  const path = outboxPath();
49876
- if (existsSync22(path)) {
49877
- pending = readFileSync20(path, "utf8").split(`
50396
+ if (existsSync23(path)) {
50397
+ pending = readFileSync21(path, "utf8").split(`
49878
50398
  `).filter(Boolean).length;
49879
50399
  }
49880
50400
  } catch {}
@@ -61343,7 +61863,7 @@ var init_RemoveFileError = __esm(() => {
61343
61863
 
61344
61864
  // ../../node_modules/.bun/@inquirer+external-editor@2.0.1+04f2146be16c61ef/node_modules/@inquirer/external-editor/dist/index.js
61345
61865
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
61346
- import { readFileSync as readFileSync21, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
61866
+ import { readFileSync as readFileSync22, unlinkSync as unlinkSync6, writeFileSync as writeFileSync15 } from "fs";
61347
61867
  import path from "path";
61348
61868
  import os from "os";
61349
61869
  import { randomUUID as randomUUID6 } from "crypto";
@@ -61459,7 +61979,7 @@ class ExternalEditor {
61459
61979
  }
61460
61980
  readTemporaryFile() {
61461
61981
  try {
61462
- const tempFileBuffer = readFileSync21(this.tempFile);
61982
+ const tempFileBuffer = readFileSync22(this.tempFile);
61463
61983
  if (tempFileBuffer.length === 0) {
61464
61984
  this.text = "";
61465
61985
  } else {
@@ -62440,9 +62960,9 @@ var init_dist16 = __esm(() => {
62440
62960
 
62441
62961
  // src/auth/antigravity-oauth.ts
62442
62962
  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";
62963
+ import { existsSync as existsSync24, unlinkSync as unlinkSync7 } from "fs";
62964
+ import { homedir as homedir28 } from "os";
62965
+ import { join as join30 } from "path";
62446
62966
  async function defaultSuggestModel() {
62447
62967
  try {
62448
62968
  const tok = readSharedAntigravityToken();
@@ -62563,8 +63083,8 @@ No session detected yet. Starting the Antigravity CLI interactively \u2014
62563
63083
  async logout(deps) {
62564
63084
  deleteSharedAntigravityToken(deps);
62565
63085
  try {
62566
- const tokenFile = join29(homedir27(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
62567
- if (existsSync23(tokenFile))
63086
+ const tokenFile = join30(homedir28(), ".gemini", "antigravity-cli", "antigravity-oauth-token");
63087
+ if (existsSync24(tokenFile))
62568
63088
  unlinkSync7(tokenFile);
62569
63089
  } catch {}
62570
63090
  log("[AntigravityOAuth] Antigravity session cleared (keychain + agy token file)");
@@ -62700,267 +63220,145 @@ var init_auth_commands = __esm(() => {
62700
63220
  // src/auth/quota-command.ts
62701
63221
  var exports_quota_command = {};
62702
63222
  __export(exports_quota_command, {
62703
- quotaCommand: () => quotaCommand
63223
+ quotaCommand: () => quotaCommand,
63224
+ formatRelativeReset: () => formatRelativeReset,
63225
+ buildUsageBar: () => buildUsageBar
62704
63226
  });
62705
63227
  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));
63228
+ const adapter = provider ? resolveAdapterFromInput(provider) : await promptForAdapter();
62717
63229
  if (!adapter) {
62718
- const allAliases = QUOTA_ADAPTERS.flatMap((a) => a.aliases);
62719
- console.error(`Unknown provider: ${provider}`);
62720
- console.error(`Available: ${allAliases.join(", ")}`);
63230
+ printUnknownProvider(provider ?? "");
62721
63231
  process.exit(1);
62722
63232
  }
63233
+ const capability = adapter.capability();
63234
+ if (capability.kind === "none") {
63235
+ printUnsupported(adapter, capability.evidence);
63236
+ return;
63237
+ }
63238
+ if (capability.kind === "unknown") {
63239
+ console.log(`
63240
+ ${WHT}${adapter.label}${R} \u2014 usage support has not been researched yet.
63241
+ `);
63242
+ return;
63243
+ }
62723
63244
  if (!adapter.isAvailable()) {
62724
- console.error(`${RED}Not logged in for ${adapter.name}.${R} Run: ${B}claudish login${R}`);
63245
+ console.error(`${RED}Not logged in for ${adapter.label}.${R} Run: ${B}claudish login${R}
63246
+ `);
62725
63247
  process.exit(1);
62726
63248
  }
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);
63249
+ const fetch2 = adapter.fetchExplicit ?? adapter.poll;
63250
+ if (!fetch2) {
63251
+ console.log(`
63252
+ ${WHT}${adapter.label}${R} \u2014 no way to read usage.
63253
+ `);
63254
+ return;
62733
63255
  }
63256
+ let plan;
62734
63257
  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("");
63258
+ plan = await fetch2.call(adapter);
62818
63259
  } catch (err) {
62819
- console.error(`Failed to fetch quota: ${err.message}`);
63260
+ console.error(`
63261
+ ${RED}Failed to fetch usage:${R} ${err?.message ?? err}
63262
+ `);
62820
63263
  process.exit(1);
62821
63264
  }
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);
63265
+ if (!plan || plan.windows.length === 0) {
63266
+ console.log(`
63267
+ ${D}No usage data returned for ${adapter.label}.${R}
63268
+ `);
63269
+ return;
62831
63270
  }
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);
63271
+ renderPlan(adapter, plan);
63272
+ }
63273
+ function resolveAdapterFromInput(input) {
63274
+ const raw2 = input.toLowerCase().replace(/@+$/, "");
63275
+ const direct = resolveQuotaAdapter(raw2);
63276
+ if (direct)
63277
+ return direct;
63278
+ const friendly = FRIENDLY_NAMES[raw2];
63279
+ if (friendly) {
63280
+ const viaFriendly = resolveQuotaAdapter(friendly);
63281
+ if (viaFriendly)
63282
+ return viaFriendly;
63283
+ }
63284
+ const canonical = getShortcuts()[raw2];
63285
+ if (canonical) {
63286
+ const viaShortcut = resolveQuotaAdapter(canonical);
63287
+ if (viaShortcut)
63288
+ return viaShortcut;
62881
63289
  }
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;
63290
+ return;
63291
+ }
63292
+ async function promptForAdapter() {
63293
+ const { select } = await Promise.resolve().then(() => (init_dist16(), exports_dist));
63294
+ const choices = allQuotaAdapters().map((a) => {
63295
+ const kind = a.capability().kind;
63296
+ const status = kind === "none" ? `${GRY}not supported${R}` : a.isAvailable() ? `${GRN}logged in${R}` : `${GRY}not logged in${R}`;
63297
+ return { name: `${a.label} \u2014 ${status}`, value: a };
63298
+ });
63299
+ return select({ message: "Select provider:", choices });
63300
+ }
63301
+ function renderPlan(adapter, plan) {
62911
63302
  console.log("");
62912
- console.log(` ${summaryColor}${B}${overallUsed}%${R} ${D}peak usage across rate windows${R}`);
63303
+ boxTop(plan.label);
63304
+ boxRow("Provider", adapter.providerId);
63305
+ boxRow("Windows", String(plan.windows.length));
63306
+ boxBottom();
63307
+ const peak = plan.windows.reduce((m, w) => Math.max(m, w.used_pct), 0);
63308
+ const peakColor = colorFor(peak);
62913
63309
  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}`);
63310
+ console.log(` ${peakColor}${B}${peak}%${R} ${D}peak usage across ${plan.windows.length} window${plan.windows.length === 1 ? "" : "s"}${R}`);
62922
63311
  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
- }
63312
+ for (const w of plan.windows) {
63313
+ const color = colorFor(w.used_pct);
63314
+ const bar = buildUsageBar(w.used_pct / 100, color, 24);
63315
+ const reset = w.resets_at ? formatRelativeReset(w.resets_at) : "";
63316
+ const name = w.id.length > 14 ? `${w.id.slice(0, 13)}\u2026` : w.id;
63317
+ console.log(` ${GRY}\u2502${R} ${WHT}${name.padEnd(14)}${R}${bar} ${color}${String(w.used_pct).padStart(3)}%${R} ${GRY}${I}${reset}${R}`);
62928
63318
  }
62929
63319
  console.log("");
62930
63320
  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
63321
  console.log("");
62933
63322
  }
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
- }
63323
+ function printUnsupported(adapter, evidence) {
63324
+ console.log("");
63325
+ console.log(` ${WHT}${B}${adapter.label}${R} ${D}\u2014 usage reporting not supported${R}`);
63326
+ console.log("");
63327
+ console.log(` ${GRY}This provider exposes no usage endpoint and returns no rate-limit${R}`);
63328
+ console.log(` ${GRY}headers, so there is nothing for claudish to report.${R}`);
63329
+ console.log("");
63330
+ console.log(` ${D}Probed ${evidence.researched_at}:${R}`);
63331
+ for (const p of evidence.probed) {
63332
+ console.log(` ${GRY}\xB7 ${p.what}${R}`);
63333
+ console.log(` ${D}\u2192 ${p.result}${R}`);
62950
63334
  }
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
- });
63335
+ if (evidence.recheck_if) {
63336
+ console.log("");
63337
+ console.log(` ${D}Re-check if: ${evidence.recheck_if}${R}`);
63338
+ }
63339
+ console.log("");
62960
63340
  }
62961
- function extractVersion(modelId) {
62962
- const match2 = modelId.match(/^gemini-([0-9]+(?:\.[0-9]+)*)-/i);
62963
- return match2?.[1];
63341
+ function printUnknownProvider(input) {
63342
+ const known = allQuotaAdapters().map((a) => a.providerId);
63343
+ console.error(`Unknown provider: ${input}`);
63344
+ console.error(`Available: ${known.join(", ")}`);
63345
+ }
63346
+ function boxTop(title) {
63347
+ console.log(` ${CYN}\u256D${"\u2500".repeat(W)}\u256E${R}`);
63348
+ const t = title.length > W - 2 ? title.slice(0, W - 3) : title;
63349
+ console.log(` ${CYN}\u2502${R} ${B}${WHT}${t}${R}${" ".repeat(Math.max(0, W - 1 - t.length))}${CYN}\u2502${R}`);
63350
+ console.log(` ${CYN}\u251C${"\u2500".repeat(W)}\u2524${R}`);
63351
+ }
63352
+ function boxRow(label, value) {
63353
+ const paddedLabel = label.padEnd(9);
63354
+ const visLen = paddedLabel.length + value.length;
63355
+ console.log(` ${CYN}\u2502${R} ${GRY}${paddedLabel}${R}${WHT}${value}${R}${" ".repeat(Math.max(0, W - 1 - visLen))}${CYN}\u2502${R}`);
63356
+ }
63357
+ function boxBottom() {
63358
+ console.log(` ${CYN}\u2570${"\u2500".repeat(W)}\u256F${R}`);
63359
+ }
63360
+ function colorFor(usedPct) {
63361
+ return usedPct < 50 ? GRN : usedPct < 80 ? YEL : RED;
62964
63362
  }
62965
63363
  function buildUsageBar(usedFraction, color, width = 24) {
62966
63364
  const clamped = Math.max(0, Math.min(1, usedFraction));
@@ -62986,25 +63384,26 @@ function formatRelativeReset(resetTime) {
62986
63384
  return `resets ${hours}h`;
62987
63385
  return `resets ${minutes}m`;
62988
63386
  }
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;
63387
+ 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
63388
  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
- ];
63389
+ init_provider_definitions();
63390
+ init_registry();
63391
+ FRIENDLY_NAMES = {
63392
+ gpt: "openai-codex",
63393
+ chatgpt: "openai-codex",
63394
+ openai: "openai-codex",
63395
+ gemini: "antigravity",
63396
+ google: "antigravity",
63397
+ glm: "glm-coding",
63398
+ zai: "glm-coding",
63399
+ kimi: "kimi-coding",
63400
+ moonshot: "kimi-coding",
63401
+ minimax: "minimax-coding",
63402
+ sakana: "sakana-subscription",
63403
+ fugu: "sakana-subscription",
63404
+ zen: "opencode-zen-go",
63405
+ qwen: "qwen-cloud"
63406
+ };
63008
63407
  });
63009
63408
 
63010
63409
  // src/config.ts
@@ -66771,22 +67170,22 @@ __export(exports_cli, {
66771
67170
  });
66772
67171
  import {
66773
67172
  copyFileSync as copyFileSync2,
66774
- existsSync as existsSync24,
67173
+ existsSync as existsSync25,
66775
67174
  mkdirSync as mkdirSync14,
66776
- readFileSync as readFileSync22,
67175
+ readFileSync as readFileSync23,
66777
67176
  readdirSync as readdirSync5,
66778
67177
  unlinkSync as unlinkSync8,
66779
67178
  writeFileSync as writeFileSync16
66780
67179
  } from "fs";
66781
- import { homedir as homedir28 } from "os";
66782
- import { dirname as dirname10, join as join30 } from "path";
67180
+ import { homedir as homedir29 } from "os";
67181
+ import { dirname as dirname10, join as join31 } from "path";
66783
67182
  import { fileURLToPath as fileURLToPath2 } from "url";
66784
67183
  function getVersion3() {
66785
67184
  return VERSION;
66786
67185
  }
66787
67186
  function clearAllModelCaches() {
66788
- const cacheDir = join30(homedir28(), ".claudish");
66789
- if (!existsSync24(cacheDir))
67187
+ const cacheDir = join31(homedir29(), ".claudish");
67188
+ if (!existsSync25(cacheDir))
66790
67189
  return;
66791
67190
  const cachePatterns = ["pricing-cache.json", "recommended-models-cache.json"];
66792
67191
  let cleared = 0;
@@ -66794,7 +67193,7 @@ function clearAllModelCaches() {
66794
67193
  const files = readdirSync5(cacheDir);
66795
67194
  for (const file2 of files) {
66796
67195
  if (cachePatterns.includes(file2)) {
66797
- unlinkSync8(join30(cacheDir, file2));
67196
+ unlinkSync8(join31(cacheDir, file2));
66798
67197
  cleared++;
66799
67198
  }
66800
67199
  }
@@ -67204,8 +67603,8 @@ Usage: claudish --models --provider <slug>`);
67204
67603
  });
67205
67604
  config3.resolvedDefaultProvider = resolved;
67206
67605
  if (resolved.legacyAutoPromoted && !config3.quiet) {
67207
- const markerFile = join30(homedir28(), ".claudish", ".legacy-litellm-hint-shown");
67208
- if (!existsSync24(markerFile)) {
67606
+ const markerFile = join31(homedir29(), ".claudish", ".legacy-litellm-hint-shown");
67607
+ if (!existsSync25(markerFile)) {
67209
67608
  const hint = buildLegacyHint(resolved);
67210
67609
  if (hint) {
67211
67610
  console.error(hint);
@@ -68279,8 +68678,8 @@ ${h("MORE INFO")}
68279
68678
  }
68280
68679
  function printAIAgentGuide() {
68281
68680
  try {
68282
- const guidePath = join30(__dirname3, "../AI_AGENT_GUIDE.md");
68283
- const guideContent = readFileSync22(guidePath, "utf-8");
68681
+ const guidePath = join31(__dirname3, "../AI_AGENT_GUIDE.md");
68682
+ const guideContent = readFileSync23(guidePath, "utf-8");
68284
68683
  console.log(guideContent);
68285
68684
  } catch (error46) {
68286
68685
  console.error("Error reading AI Agent Guide:");
@@ -68296,19 +68695,19 @@ async function initializeClaudishSkill() {
68296
68695
  console.log(`\uD83D\uDD27 Initializing Claudish skill in current project...
68297
68696
  `);
68298
68697
  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)) {
68698
+ const claudeDir = join31(cwd, ".claude");
68699
+ const skillsDir = join31(claudeDir, "skills");
68700
+ const claudishSkillDir = join31(skillsDir, "claudish-usage");
68701
+ const skillFile = join31(claudishSkillDir, "SKILL.md");
68702
+ if (existsSync25(skillFile)) {
68304
68703
  console.log("\u2705 Claudish skill already installed at:");
68305
68704
  console.log(` ${skillFile}
68306
68705
  `);
68307
68706
  console.log("\uD83D\uDCA1 To reinstall, delete the file and run 'claudish --init' again.");
68308
68707
  return;
68309
68708
  }
68310
- const sourceSkillPath = join30(__dirname3, "../skills/claudish-usage/SKILL.md");
68311
- if (!existsSync24(sourceSkillPath)) {
68709
+ const sourceSkillPath = join31(__dirname3, "../skills/claudish-usage/SKILL.md");
68710
+ if (!existsSync25(sourceSkillPath)) {
68312
68711
  console.error("\u274C Error: Claudish skill file not found in installation.");
68313
68712
  console.error(` Expected at: ${sourceSkillPath}`);
68314
68713
  console.error(`
@@ -68317,15 +68716,15 @@ async function initializeClaudishSkill() {
68317
68716
  process.exit(1);
68318
68717
  }
68319
68718
  try {
68320
- if (!existsSync24(claudeDir)) {
68719
+ if (!existsSync25(claudeDir)) {
68321
68720
  mkdirSync14(claudeDir, { recursive: true });
68322
68721
  console.log("\uD83D\uDCC1 Created .claude/ directory");
68323
68722
  }
68324
- if (!existsSync24(skillsDir)) {
68723
+ if (!existsSync25(skillsDir)) {
68325
68724
  mkdirSync14(skillsDir, { recursive: true });
68326
68725
  console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
68327
68726
  }
68328
- if (!existsSync24(claudishSkillDir)) {
68727
+ if (!existsSync25(claudishSkillDir)) {
68329
68728
  mkdirSync14(claudishSkillDir, { recursive: true });
68330
68729
  console.log("\uD83D\uDCC1 Created .claude/skills/claudish-usage/ directory");
68331
68730
  }
@@ -68410,33 +68809,33 @@ __export(exports_update_checker, {
68410
68809
  clearCache: () => clearCache,
68411
68810
  checkForUpdates: () => checkForUpdates
68412
68811
  });
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";
68812
+ import { existsSync as existsSync26, mkdirSync as mkdirSync15, readFileSync as readFileSync24, unlinkSync as unlinkSync9, writeFileSync as writeFileSync17 } from "fs";
68813
+ import { homedir as homedir30, platform as platform2, tmpdir } from "os";
68814
+ import { join as join32 } from "path";
68416
68815
  function getCacheFilePath() {
68417
68816
  let cacheDir;
68418
68817
  if (isWindows) {
68419
- const localAppData = process.env.LOCALAPPDATA || join31(homedir29(), "AppData", "Local");
68420
- cacheDir = join31(localAppData, "claudish");
68818
+ const localAppData = process.env.LOCALAPPDATA || join32(homedir30(), "AppData", "Local");
68819
+ cacheDir = join32(localAppData, "claudish");
68421
68820
  } else {
68422
- cacheDir = join31(homedir29(), ".cache", "claudish");
68821
+ cacheDir = join32(homedir30(), ".cache", "claudish");
68423
68822
  }
68424
68823
  try {
68425
- if (!existsSync25(cacheDir)) {
68824
+ if (!existsSync26(cacheDir)) {
68426
68825
  mkdirSync15(cacheDir, { recursive: true });
68427
68826
  }
68428
- return join31(cacheDir, "update-check.json");
68827
+ return join32(cacheDir, "update-check.json");
68429
68828
  } catch {
68430
- return join31(tmpdir(), "claudish-update-check.json");
68829
+ return join32(tmpdir(), "claudish-update-check.json");
68431
68830
  }
68432
68831
  }
68433
68832
  function readCache() {
68434
68833
  try {
68435
68834
  const cachePath = getCacheFilePath();
68436
- if (!existsSync25(cachePath)) {
68835
+ if (!existsSync26(cachePath)) {
68437
68836
  return null;
68438
68837
  }
68439
- const data = JSON.parse(readFileSync23(cachePath, "utf-8"));
68838
+ const data = JSON.parse(readFileSync24(cachePath, "utf-8"));
68440
68839
  return data;
68441
68840
  } catch {
68442
68841
  return null;
@@ -68459,7 +68858,7 @@ function isCacheValid(cache2) {
68459
68858
  function clearCache() {
68460
68859
  try {
68461
68860
  const cachePath = getCacheFilePath();
68462
- if (existsSync25(cachePath)) {
68861
+ if (existsSync26(cachePath)) {
68463
68862
  unlinkSync9(cachePath);
68464
68863
  }
68465
68864
  } catch {}
@@ -69344,15 +69743,15 @@ var init_local_liveness = __esm(() => {
69344
69743
  });
69345
69744
 
69346
69745
  // 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";
69746
+ import { existsSync as existsSync27, mkdirSync as mkdirSync16, readFileSync as readFileSync25, writeFileSync as writeFileSync18 } from "fs";
69747
+ import { homedir as homedir31 } from "os";
69748
+ import { dirname as dirname11, join as join33 } from "path";
69350
69749
  function readProbeModelsCache(path2 = PROBE_MODELS_CACHE_PATH) {
69351
- if (!existsSync26(path2))
69750
+ if (!existsSync27(path2))
69352
69751
  return null;
69353
69752
  let raw2;
69354
69753
  try {
69355
- raw2 = JSON.parse(readFileSync24(path2, "utf-8"));
69754
+ raw2 = JSON.parse(readFileSync25(path2, "utf-8"));
69356
69755
  } catch {
69357
69756
  return null;
69358
69757
  }
@@ -69481,7 +69880,7 @@ function isValidResponse(raw2) {
69481
69880
  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
69881
  var init_probe_catalog = __esm(() => {
69483
69882
  CACHE_TTL_MS4 = 60 * 60 * 1000;
69484
- PROBE_MODELS_CACHE_PATH = join32(homedir30(), ".claudish", "probe-models.json");
69883
+ PROBE_MODELS_CACHE_PATH = join33(homedir31(), ".claudish", "probe-models.json");
69485
69884
  });
69486
69885
 
69487
69886
  // src/tui/constants.ts
@@ -75835,17 +76234,17 @@ __export(exports_claude_runner, {
75835
76234
  import { spawn as spawn4 } from "child_process";
75836
76235
  import {
75837
76236
  closeSync as closeSync5,
75838
- existsSync as existsSync27,
76237
+ existsSync as existsSync28,
75839
76238
  mkdirSync as mkdirSync17,
75840
76239
  openSync as openSync5,
75841
- readFileSync as readFileSync25,
76240
+ readFileSync as readFileSync26,
75842
76241
  readdirSync as readdirSync6,
75843
76242
  statSync as statSync5,
75844
76243
  unlinkSync as unlinkSync10,
75845
76244
  writeFileSync as writeFileSync19
75846
76245
  } from "fs";
75847
- import { homedir as homedir31, tmpdir as tmpdir2 } from "os";
75848
- import { dirname as dirname12, join as join33 } from "path";
76246
+ import { homedir as homedir32, tmpdir as tmpdir2 } from "os";
76247
+ import { dirname as dirname12, join as join34 } from "path";
75849
76248
  import { isatty } from "tty";
75850
76249
  function releaseTerminalIsolation() {
75851
76250
  if (!restoreTerminal)
@@ -75880,14 +76279,14 @@ function isProxyAuthMode(config3) {
75880
76279
  }
75881
76280
  function managedSettingsPath() {
75882
76281
  if (isWindows2()) {
75883
- return join33(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
76282
+ return join34(process.env.PROGRAMDATA || "C:\\ProgramData", "ClaudeCode", "managed-settings.json");
75884
76283
  }
75885
76284
  if (process.platform === "darwin") {
75886
76285
  return "/Library/Application Support/ClaudeCode/managed-settings.json";
75887
76286
  }
75888
76287
  return "/etc/claude-code/managed-settings.json";
75889
76288
  }
75890
- function managedSettingsForcesClaudeAi(readFile3 = readFileSync25) {
76289
+ function managedSettingsForcesClaudeAi(readFile3 = readFileSync26) {
75891
76290
  try {
75892
76291
  const raw2 = readFile3(managedSettingsPath(), "utf-8");
75893
76292
  const parsed = JSON.parse(raw2);
@@ -75901,9 +76300,9 @@ function isWindows2() {
75901
76300
  }
75902
76301
  function createStatusLineScript(tokenFilePath) {
75903
76302
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
75904
- const claudishDir = join33(homeDir, ".claudish");
76303
+ const claudishDir = join34(homeDir, ".claudish");
75905
76304
  const timestamp = Date.now();
75906
- const scriptPath = join33(claudishDir, `status-${timestamp}.js`);
76305
+ const scriptPath = join34(claudishDir, `status-${timestamp}.js`);
75907
76306
  const escapedTokenPath = tokenFilePath.replace(/\\/g, "\\\\");
75908
76307
  const script = `
75909
76308
  const fs = require('fs');
@@ -75967,7 +76366,9 @@ process.stdin.on('end', () => {
75967
76366
  isEstimated = tokens.is_estimated || false;
75968
76367
  providerName = tokens.provider_name || '';
75969
76368
  if (tokens.model_name) model = tokens.model_name;
75970
- var quotaRemaining = tokens.quota_remaining;
76369
+ // Plan usage for the subscription actually being spent. Replaces the old
76370
+ // scalar quota_remaining, which only ever covered a single model.
76371
+ var plan = tokens.plan;
75971
76372
  } catch (e) {
75972
76373
  try {
75973
76374
  const json = JSON.parse(input);
@@ -76009,11 +76410,18 @@ process.stdin.on('end', () => {
76009
76410
  ctxDisplay = ctx + '%';
76010
76411
  }
76011
76412
  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;
76413
+ if (plan && Array.isArray(plan.windows)) {
76414
+ // Show the window closest to its limit \u2014 the one that cuts you off first.
76415
+ let worst = null;
76416
+ for (const w of plan.windows) {
76417
+ if (!w || typeof w.used_pct !== 'number') continue;
76418
+ if (!worst || w.used_pct > worst.used_pct) worst = w;
76419
+ }
76420
+ if (worst) {
76421
+ const usedPct = Math.round(worst.used_pct);
76422
+ const qColor = usedPct < 50 ? GREEN : usedPct < 80 ? YELLOW : RED;
76423
+ quotaDisplay = ' ' + DIM + '\u2022' + RESET + ' ' + qColor + worst.id + ':' + usedPct + '%' + RESET;
76424
+ }
76017
76425
  }
76018
76426
  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
76427
  } catch (e) {
@@ -76058,7 +76466,7 @@ function cleanupStaleTokenFiles(dir, now = Date.now(), maxAgeMs = STALE_TOKEN_FI
76058
76466
  if (!name.startsWith("tokens-") || !name.endsWith(".json"))
76059
76467
  continue;
76060
76468
  scanned++;
76061
- const full = join33(dir, name);
76469
+ const full = join34(dir, name);
76062
76470
  try {
76063
76471
  if (statSync5(full).mtimeMs >= cutoff)
76064
76472
  continue;
@@ -76075,7 +76483,7 @@ function parseSettingsArg(value) {
76075
76483
  if (value.trimStart().startsWith("{")) {
76076
76484
  return JSON.parse(value);
76077
76485
  }
76078
- return JSON.parse(readFileSync25(value, "utf-8"));
76486
+ return JSON.parse(readFileSync26(value, "utf-8"));
76079
76487
  }
76080
76488
  function parseSettingsArgSafe(value) {
76081
76489
  try {
@@ -76087,13 +76495,13 @@ function parseSettingsArgSafe(value) {
76087
76495
  }
76088
76496
  function userSettingsFileCandidates(cwd) {
76089
76497
  return [
76090
- join33(homedir31(), ".claude", "settings.json"),
76091
- join33(cwd, ".claude", "settings.json"),
76092
- join33(cwd, ".claude", "settings.local.json")
76498
+ join34(homedir32(), ".claude", "settings.json"),
76499
+ join34(cwd, ".claude", "settings.json"),
76500
+ join34(cwd, ".claude", "settings.local.json")
76093
76501
  ];
76094
76502
  }
76095
76503
  function discoverUserStatusLineCommand(claudeArgs = [], cwd = process.cwd()) {
76096
- const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync27(file2));
76504
+ const sources = userSettingsFileCandidates(cwd).filter((file2) => existsSync28(file2));
76097
76505
  const idx = claudeArgs.indexOf("--settings");
76098
76506
  const settingsArg = idx === -1 ? undefined : claudeArgs[idx + 1];
76099
76507
  if (settingsArg)
@@ -76130,13 +76538,13 @@ function buildChainedStatusCommand(userCommand, claudishBody, claudishSegment) {
76130
76538
  }
76131
76539
  function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLineCommand) {
76132
76540
  const homeDir = process.env.HOME || process.env.USERPROFILE || tmpdir2();
76133
- const claudishDir = join33(homeDir, ".claudish");
76541
+ const claudishDir = join34(homeDir, ".claudish");
76134
76542
  try {
76135
76543
  mkdirSync17(claudishDir, { recursive: true });
76136
76544
  } catch {}
76137
76545
  const timestamp = Date.now();
76138
- const tempPath = join33(claudishDir, `settings-${timestamp}.json`);
76139
- const tokenFilePath = join33(claudishDir, `tokens-${port}.json`);
76546
+ const tempPath = join34(claudishDir, `settings-${timestamp}.json`);
76547
+ const tokenFilePath = join34(claudishDir, `tokens-${port}.json`);
76140
76548
  cleanupStaleTokenFiles(claudishDir);
76141
76549
  initializeTokenFile(tokenFilePath);
76142
76550
  let statusCommand;
@@ -76151,13 +76559,15 @@ function createTempSettingsFile(_modelDisplay, port, proxyAuthMode, userStatusLi
76151
76559
  const DIM4 = "\\033[2m";
76152
76560
  const RESET4 = "\\033[0m";
76153
76561
  const BOLD4 = "\\033[1m";
76562
+ const readPlanBash = `PLAN_PAIR=$(echo "$TOKENS" | grep -o '"id": *"[^"]*", *"used_pct": *[0-9]*' | sed 's/"id": *"\\([^"]*\\)", *"used_pct": *\\([0-9]*\\)/\\2 \\1/' | sort -rn | head -1); if [ -n "$PLAN_PAIR" ]; then PLAN_PCT="\${PLAN_PAIR%% *}"; PLAN_ID="\${PLAN_PAIR#* }"; case "$PLAN_PCT" in ''|*[!0-9]*) PLAN_PCT="" ;; esac; [ -n "$PLAN_PCT" ] && PLAN_DISPLAY="$PLAN_ID:$PLAN_PCT%"; fi;`;
76154
76563
  const formatTokensBash = `fmt_tok() { local n=\${1:-0}; if [ "$n" -ge 1000000 ]; then echo "$((n/1000000))M"; elif [ "$n" -ge 1000 ]; then echo "$((n/1000))k"; else echo "$n"; fi; }`;
76155
76564
  const effWinBash = `eff_win() { local w=\${1:-0}; local m=\${CLAUDE_CODE_MAX_CONTEXT_TOKENS:-}; local a=\${CLAUDE_CODE_AUTO_COMPACT_WINDOW:-}; case "$m" in ''|*[!0-9]*) m=${CLAUDE_CODE_DEFAULT_MAX_CONTEXT};; esac; case "$a" in ''|*[!0-9]*) a=0;; esac; case "$w" in ''|*[!0-9]*) w=0;; esac; if [ "$w" -gt 0 ]; then if [ "$m" -gt 0 ] && [ "$m" -lt "$w" ]; then w=$m; fi; if [ "$a" -gt 0 ] && [ "$a" -lt "$w" ]; then w=$a; fi; fi; echo "$w"; }`;
76156
76565
  const dirPrelude = `DIR=$(basename "$(pwd)"); [ \${#DIR} -gt 15 ] && DIR="\${DIR:0:12}..." || true; `;
76157
- const readState = `CTX=-1; COST="0"; IS_FREE="false"; IS_EST="false"; PROVIDER=""; TOKEN_MODEL=""; IN_TOK=0; CTX_WIN=0; ${formatTokensBash}; ${effWinBash}; if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d '\\n\\r'); V=$(echo "$TOKENS" | grep -o '"context_left_percent": *-\\?[0-9]*' | grep -o '\\-\\?[0-9]*'); [ -n "$V" ] && CTX="$V"; V=$(echo "$TOKENS" | grep -o '"total_cost": *[0-9.]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && COST="$V"; V=$(echo "$TOKENS" | grep -o '"input_tokens": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && IN_TOK="$V"; V=$(echo "$TOKENS" | grep -o '"context_window": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && CTX_WIN="$V"; V=$(echo "$TOKENS" | grep -o '"is_free": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_FREE="$V"; V=$(echo "$TOKENS" | grep -o '"is_estimated": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_EST="$V"; V=$(echo "$TOKENS" | grep -o '"provider_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && PROVIDER="$V"; V=$(echo "$TOKENS" | grep -o '"model_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && TOKEN_MODEL="$V"; fi; if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi; MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}"; if [ -n "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi; EFF_WIN=$(eff_win $CTX_WIN); if [ "$EFF_WIN" -gt 0 ] 2>/dev/null && [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX=$(( ((EFF_WIN - IN_TOK) * 200 / EFF_WIN + 1) / 2 )); if [ "$CTX" -lt 0 ]; then CTX=0; fi; fi; if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$EFF_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null; then if [ "$EFF_WIN" -lt "$CTX_WIN" ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN) of $(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN))"; fi; else CTX_DISPLAY="$CTX%"; fi`;
76158
- const segmentWithDir = `printf "${CYAN4}${BOLD4}%s${RESET4} ${DIM4}\u2022${RESET4} ${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}\\n" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"`;
76159
- const segmentNoDirWithProvider = `printf "${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}\\n" "$PROVIDER" "$COST_DISPLAY" "$CTX_DISPLAY"`;
76160
- const segmentNoDirNoProvider = `printf "${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}\\n" "$COST_DISPLAY" "$CTX_DISPLAY"`;
76566
+ const readState = `CTX=-1; COST="0"; IS_FREE="false"; IS_EST="false"; PROVIDER=""; TOKEN_MODEL=""; IN_TOK=0; CTX_WIN=0; PLAN_DISPLAY=""; ${formatTokensBash}; ${effWinBash}; if [ -f "${tokenFilePath}" ]; then TOKENS=$(cat "${tokenFilePath}" 2>/dev/null | tr -d '\\n\\r'); V=$(echo "$TOKENS" | grep -o '"context_left_percent": *-\\?[0-9]*' | grep -o '\\-\\?[0-9]*'); [ -n "$V" ] && CTX="$V"; V=$(echo "$TOKENS" | grep -o '"total_cost": *[0-9.]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && COST="$V"; V=$(echo "$TOKENS" | grep -o '"input_tokens": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && IN_TOK="$V"; V=$(echo "$TOKENS" | grep -o '"context_window": *[0-9]*' | grep -o '[0-9]*'); [ -n "$V" ] && CTX_WIN="$V"; V=$(echo "$TOKENS" | grep -o '"is_free": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_FREE="$V"; V=$(echo "$TOKENS" | grep -o '"is_estimated": *[a-z]*' | cut -d: -f2 | tr -d ' '); [ -n "$V" ] && IS_EST="$V"; V=$(echo "$TOKENS" | grep -o '"provider_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && PROVIDER="$V"; V=$(echo "$TOKENS" | grep -o '"model_name": *"[^"]*"' | cut -d'"' -f4); [ -n "$V" ] && TOKEN_MODEL="$V"; ${readPlanBash} fi; if [ "$CLAUDISH_IS_LOCAL" = "true" ]; then COST_DISPLAY="LOCAL"; elif [ "$IS_FREE" = "true" ]; then COST_DISPLAY="FREE"; elif [ "$IS_EST" = "true" ]; then COST_DISPLAY=$(printf "~\\$%.3f" "$COST"); else COST_DISPLAY=$(printf "\\$%.3f" "$COST"); fi; MODEL_DISPLAY="\${TOKEN_MODEL:-$CLAUDISH_ACTIVE_MODEL_NAME}"; if [ -n "$PROVIDER" ]; then MODEL_DISPLAY="$PROVIDER $MODEL_DISPLAY"; fi; EFF_WIN=$(eff_win $CTX_WIN); if [ "$EFF_WIN" -gt 0 ] 2>/dev/null && [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX=$(( ((EFF_WIN - IN_TOK) * 200 / EFF_WIN + 1) / 2 )); if [ "$CTX" -lt 0 ]; then CTX=0; fi; fi; if [ "$CTX" -lt 0 ] 2>/dev/null || [ "$EFF_WIN" -le 0 ] 2>/dev/null; then if [ "$IN_TOK" -gt 0 ] 2>/dev/null; then CTX_DISPLAY="$(fmt_tok $IN_TOK) tokens"; else CTX_DISPLAY="N/A"; fi; elif [ "$IN_TOK" -gt 0 ] 2>/dev/null; then if [ "$EFF_WIN" -lt "$CTX_WIN" ] 2>/dev/null; then CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN) of $(fmt_tok $CTX_WIN))"; else CTX_DISPLAY="$CTX% ($(fmt_tok $IN_TOK)/$(fmt_tok $EFF_WIN))"; fi; else CTX_DISPLAY="$CTX%"; fi`;
76567
+ const planSuffix = `if [ -n "$PLAN_DISPLAY" ]; then printf " ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4}" "$PLAN_DISPLAY"; fi`;
76568
+ const segmentWithDir = `printf "${CYAN4}${BOLD4}%s${RESET4} ${DIM4}\u2022${RESET4} ${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}" "$DIR" "$MODEL_DISPLAY" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
76569
+ const segmentNoDirWithProvider = `printf "${YELLOW3}%s${RESET4} ${DIM4}\u2022${RESET4} ${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}" "$PROVIDER" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
76570
+ const segmentNoDirNoProvider = `printf "${GREEN4}%s${RESET4} ${DIM4}\u2022${RESET4} ${MAGENTA3}%s${RESET4}" "$COST_DISPLAY" "$CTX_DISPLAY"; ${planSuffix}; printf "\\n"`;
76161
76571
  const segmentNoDir = `if [ -n "$PROVIDER" ]; then ${segmentNoDirWithProvider}; else ${segmentNoDirNoProvider}; fi`;
76162
76572
  statusCommand = userStatusLineCommand ? buildChainedStatusCommand(userStatusLineCommand, readState, segmentNoDir) : `JSON=$(cat); ${dirPrelude}${readState}; ${segmentWithDir}`;
76163
76573
  }
@@ -76407,8 +76817,8 @@ async function runClaudeWithProxy(config3, proxyUrl, onCleanup) {
76407
76817
  console.error("Install it from: https://claude.com/claude-code");
76408
76818
  console.error(`
76409
76819
  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");
76820
+ const home = homedir32();
76821
+ const localPath = isWindows2() ? join34(home, ".claude", "local", "claude.exe") : join34(home, ".claude", "local", "claude");
76412
76822
  console.error(` export CLAUDE_PATH=${localPath}`);
76413
76823
  process.exit(1);
76414
76824
  }
@@ -76488,23 +76898,23 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
76488
76898
  async function findClaudeBinary() {
76489
76899
  const isWindows3 = process.platform === "win32";
76490
76900
  if (process.env.CLAUDE_PATH) {
76491
- if (existsSync27(process.env.CLAUDE_PATH)) {
76901
+ if (existsSync28(process.env.CLAUDE_PATH)) {
76492
76902
  return process.env.CLAUDE_PATH;
76493
76903
  }
76494
76904
  }
76495
- const home = homedir31();
76496
- const localPath = isWindows3 ? join33(home, ".claude", "local", "claude.exe") : join33(home, ".claude", "local", "claude");
76497
- if (existsSync27(localPath)) {
76905
+ const home = homedir32();
76906
+ const localPath = isWindows3 ? join34(home, ".claude", "local", "claude.exe") : join34(home, ".claude", "local", "claude");
76907
+ if (existsSync28(localPath)) {
76498
76908
  return localPath;
76499
76909
  }
76500
76910
  if (isWindows3) {
76501
76911
  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")
76912
+ join34(home, "AppData", "Roaming", "npm", "claude.cmd"),
76913
+ join34(home, ".npm-global", "claude.cmd"),
76914
+ join34(home, "node_modules", ".bin", "claude.cmd")
76505
76915
  ];
76506
76916
  for (const path2 of windowsPaths) {
76507
- if (existsSync27(path2)) {
76917
+ if (existsSync28(path2)) {
76508
76918
  return path2;
76509
76919
  }
76510
76920
  }
@@ -76512,14 +76922,14 @@ async function findClaudeBinary() {
76512
76922
  const commonPaths = [
76513
76923
  "/usr/local/bin/claude",
76514
76924
  "/opt/homebrew/bin/claude",
76515
- join33(home, ".npm-global/bin/claude"),
76516
- join33(home, ".local/bin/claude"),
76517
- join33(home, "node_modules/.bin/claude"),
76925
+ join34(home, ".npm-global/bin/claude"),
76926
+ join34(home, ".local/bin/claude"),
76927
+ join34(home, "node_modules/.bin/claude"),
76518
76928
  "/data/data/com.termux/files/usr/bin/claude",
76519
- join33(home, "../usr/bin/claude")
76929
+ join34(home, "../usr/bin/claude")
76520
76930
  ];
76521
76931
  for (const path2 of commonPaths) {
76522
- if (existsSync27(path2)) {
76932
+ if (existsSync28(path2)) {
76523
76933
  return path2;
76524
76934
  }
76525
76935
  }
@@ -76580,17 +76990,17 @@ __export(exports_diag_output, {
76580
76990
  LogFileDiagOutput: () => LogFileDiagOutput
76581
76991
  });
76582
76992
  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";
76993
+ import { homedir as homedir33 } from "os";
76994
+ import { join as join35 } from "path";
76585
76995
  function getClaudishDir() {
76586
- const dir = join34(homedir32(), ".claudish");
76996
+ const dir = join35(homedir33(), ".claudish");
76587
76997
  try {
76588
76998
  mkdirSync18(dir, { recursive: true });
76589
76999
  } catch {}
76590
77000
  return dir;
76591
77001
  }
76592
77002
  function getDiagLogPath() {
76593
- return join34(getClaudishDir(), `diag-${process.pid}.log`);
77003
+ return join35(getClaudishDir(), `diag-${process.pid}.log`);
76594
77004
  }
76595
77005
 
76596
77006
  class LogFileDiagOutput {
@@ -76801,9 +77211,9 @@ __export(exports_team_grid, {
76801
77211
  });
76802
77212
  import { spawn as spawn5 } from "child_process";
76803
77213
  import { execSync as execSync2 } from "child_process";
76804
- import { existsSync as existsSync28, readFileSync as readFileSync26, writeFileSync as writeFileSync21 } from "fs";
77214
+ import { existsSync as existsSync29, readFileSync as readFileSync27, writeFileSync as writeFileSync21 } from "fs";
76805
77215
  import { connect as netConnect } from "net";
76806
- import { dirname as dirname13, join as join35 } from "path";
77216
+ import { dirname as dirname13, join as join36 } from "path";
76807
77217
  import { setTimeout as wait } from "timers/promises";
76808
77218
  import { fileURLToPath as fileURLToPath3 } from "url";
76809
77219
  function resolveRouteInfo(modelId) {
@@ -76897,18 +77307,18 @@ function buildPaneHeader(model, prompt, bg) {
76897
77307
  function findMagmuxBinary() {
76898
77308
  const thisFile = fileURLToPath3(import.meta.url);
76899
77309
  const thisDir = dirname13(thisFile);
76900
- const pkgRoot = join35(thisDir, "..");
77310
+ const pkgRoot = join36(thisDir, "..");
76901
77311
  const platform3 = process.platform;
76902
77312
  const arch = process.arch;
76903
- const bundledMagmux = join35(pkgRoot, "native", `magmux-${platform3}-${arch}`);
76904
- if (existsSync28(bundledMagmux))
77313
+ const bundledMagmux = join36(pkgRoot, "native", `magmux-${platform3}-${arch}`);
77314
+ if (existsSync29(bundledMagmux))
76905
77315
  return bundledMagmux;
76906
77316
  try {
76907
77317
  const pkgName = `@claudish/magmux-${platform3}-${arch}`;
76908
77318
  let searchDir = pkgRoot;
76909
77319
  for (let i = 0;i < 5; i++) {
76910
- const candidate = join35(searchDir, "node_modules", pkgName, "bin", "magmux");
76911
- if (existsSync28(candidate))
77320
+ const candidate = join36(searchDir, "node_modules", pkgName, "bin", "magmux");
77321
+ if (existsSync29(candidate))
76912
77322
  return candidate;
76913
77323
  const parent = dirname13(searchDir);
76914
77324
  if (parent === searchDir)
@@ -76927,7 +77337,7 @@ function findMagmuxBinary() {
76927
77337
  async function subscribeToMagmux(sockPath, onEvent) {
76928
77338
  let client = null;
76929
77339
  for (let attempt = 0;attempt < 40; attempt++) {
76930
- if (existsSync28(sockPath)) {
77340
+ if (existsSync29(sockPath)) {
76931
77341
  try {
76932
77342
  client = await new Promise((resolve5, reject) => {
76933
77343
  const s = netConnect(sockPath);
@@ -77014,9 +77424,9 @@ async function runWithGrid(sessionPath, models, input, opts) {
77014
77424
  const keep = opts?.keep ?? false;
77015
77425
  const manifest = setupSession(sessionPath, models, input);
77016
77426
  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");
77427
+ const gridfilePath = join36(sessionPath, "gridfile.txt");
77428
+ const prompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8").replace(/'/g, "'\\''").replace(/\n/g, " ");
77429
+ const rawPrompt = readFileSync27(join36(sessionPath, "input.md"), "utf-8");
77020
77430
  const usedBannerColors = new Set;
77021
77431
  const gridLines = Object.entries(manifest.models).map(([anonId]) => {
77022
77432
  const model = manifest.models[anonId].model;
@@ -77047,7 +77457,7 @@ async function runWithGrid(sessionPath, models, input, opts) {
77047
77457
  });
77048
77458
  const [{ results: results2 }] = await Promise.all([subscription, procExit]);
77049
77459
  const status = buildTeamStatus(manifest, startedAt, results2?.panes ?? null);
77050
- const statusPath = join35(sessionPath, "status.json");
77460
+ const statusPath = join36(sessionPath, "status.json");
77051
77461
  writeFileSync21(statusPath, JSON.stringify(status, null, 2), "utf-8");
77052
77462
  return status;
77053
77463
  }
@@ -77071,8 +77481,8 @@ var init_team_grid = __esm(() => {
77071
77481
  init_op_source();
77072
77482
  init_startup_trace();
77073
77483
  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";
77484
+ import { existsSync as existsSync30, readFileSync as readFileSync28 } from "fs";
77485
+ import { join as join37, resolve as resolve5 } from "path";
77076
77486
  import_dotenv3.config({ quiet: true });
77077
77487
  function classifyStartupKind() {
77078
77488
  const argv = process.argv.slice(2);
@@ -77171,7 +77581,7 @@ async function applyConfigOverride() {
77171
77581
  const { planConfigOverride: planConfigOverride2, setConfigFileOverride: setConfigFileOverride2 } = await Promise.resolve().then(() => exports_config_override);
77172
77582
  const plan = planConfigOverride2(process.argv.slice(2), process.env, {
77173
77583
  resolve: resolve5,
77174
- exists: existsSync29
77584
+ exists: existsSync30
77175
77585
  });
77176
77586
  if (plan.kind === "none")
77177
77587
  return;
@@ -77319,14 +77729,14 @@ async function runCli() {
77319
77729
  if (cliConfig.team && cliConfig.team.length > 0) {
77320
77730
  let prompt = cliConfig.claudeArgs.join(" ");
77321
77731
  if (cliConfig.inputFile) {
77322
- prompt = readFileSync27(cliConfig.inputFile, "utf-8");
77732
+ prompt = readFileSync28(cliConfig.inputFile, "utf-8");
77323
77733
  }
77324
77734
  if (!prompt.trim()) {
77325
77735
  console.error("Error: --team requires a prompt (positional args or -f <file>)");
77326
77736
  process.exit(1);
77327
77737
  }
77328
77738
  const mode = cliConfig.teamMode ?? "default";
77329
- const sessionPath = join36(process.cwd(), `.claudish-team-${Date.now()}`);
77739
+ const sessionPath = join37(process.cwd(), `.claudish-team-${Date.now()}`);
77330
77740
  if (mode === "json") {
77331
77741
  const { setupSession: setupSession2, runModels: runModels2 } = await Promise.resolve().then(() => (init_team_orchestrator(), exports_team_orchestrator));
77332
77742
  setupSession2(sessionPath, cliConfig.team, prompt);
@@ -77336,9 +77746,9 @@ async function runCli() {
77336
77746
  });
77337
77747
  const result = { ...status2, responses: {} };
77338
77748
  for (const anonId of Object.keys(status2.models)) {
77339
- const responsePath = join36(sessionPath, `response-${anonId}.md`);
77749
+ const responsePath = join37(sessionPath, `response-${anonId}.md`);
77340
77750
  try {
77341
- const raw2 = readFileSync27(responsePath, "utf-8").trim();
77751
+ const raw2 = readFileSync28(responsePath, "utf-8").trim();
77342
77752
  try {
77343
77753
  result.responses[anonId] = JSON.parse(raw2);
77344
77754
  } catch {