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.
- package/dist/index.js +932 -522
- 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.
|
|
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
|
|
34741
|
-
import { dirname as dirname6, join as
|
|
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
|
|
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
|
|
34815
|
-
import { dirname as dirname7, join as
|
|
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
|
|
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
|
|
35157
|
-
import { join as
|
|
35606
|
+
import { homedir as homedir19 } from "os";
|
|
35607
|
+
import { join as join19 } from "path";
|
|
35158
35608
|
function defaultPath() {
|
|
35159
|
-
return
|
|
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
|
|
35817
|
-
import { homedir as
|
|
35818
|
-
import { join as
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 ??
|
|
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 ??
|
|
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
|
|
37129
|
+
existsSync as existsSync15,
|
|
36650
37130
|
mkdirSync as mkdirSync8,
|
|
36651
|
-
readFileSync as
|
|
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
|
|
36657
|
-
import { join as
|
|
37136
|
+
import { homedir as homedir21 } from "os";
|
|
37137
|
+
import { join as join21 } from "path";
|
|
36658
37138
|
function ensureDir() {
|
|
36659
|
-
if (!
|
|
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 (!
|
|
37145
|
+
if (!existsSync15(BUFFER_FILE))
|
|
36666
37146
|
return [];
|
|
36667
|
-
const raw =
|
|
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 =
|
|
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 (
|
|
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 =
|
|
36766
|
-
BUFFER_FILE =
|
|
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
|
|
37881
|
-
import { homedir as
|
|
37882
|
-
import { join as
|
|
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 &&
|
|
38472
|
+
if (!forceRefresh && existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
37993
38473
|
try {
|
|
37994
|
-
const cacheData = JSON.parse(
|
|
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 =
|
|
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 (
|
|
38503
|
+
if (existsSync16(RECOMMENDED_MODELS_CACHE_PATH)) {
|
|
38024
38504
|
try {
|
|
38025
|
-
const cacheData = JSON.parse(
|
|
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 =
|
|
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
|
|
39500
|
-
import { dirname as dirname8, join as
|
|
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
|
-
|
|
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
|
-
|
|
39526
|
-
|
|
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.
|
|
39649
|
-
data.
|
|
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 ||
|
|
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
|
-
|
|
40806
|
+
capturePlanUsage(response) {
|
|
40319
40807
|
try {
|
|
40320
|
-
const
|
|
40321
|
-
if (
|
|
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-*": ["
|
|
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
|
|
42602
|
-
import { join as
|
|
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 ??
|
|
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 =
|
|
43136
|
+
const sessionDir = join24(this.sessionsDir, sessionId2);
|
|
42625
43137
|
mkdirSync11(sessionDir, { recursive: true });
|
|
42626
43138
|
if (opts.prompt) {
|
|
42627
|
-
writeFileSync10(
|
|
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(
|
|
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(
|
|
43220
|
+
writeFileSync10(join24(sessionDir, "stderr.log"), entry.stderr, "utf-8");
|
|
42709
43221
|
}
|
|
42710
|
-
writeFileSync10(
|
|
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
|
-
|
|
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
|
|
45738
|
-
import { homedir as
|
|
45739
|
-
import { join as
|
|
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(
|
|
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 (!
|
|
46337
|
+
if (!existsSync17(dotenvPath))
|
|
45819
46338
|
return null;
|
|
45820
|
-
const parsed = import_dotenv.parse(
|
|
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 (!
|
|
46352
|
+
if (!existsSync17(configPath))
|
|
45834
46353
|
return null;
|
|
45835
|
-
const cfg = JSON.parse(
|
|
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
|
|
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
|
|
47309
|
-
import { homedir as
|
|
47310
|
-
import { join as
|
|
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 (!
|
|
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 =
|
|
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 =
|
|
47370
|
-
CACHE_FILE =
|
|
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
|
|
47866
|
-
import { join as
|
|
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
|
|
48388
|
+
return join27(sessionPath, "stats");
|
|
47869
48389
|
}
|
|
47870
48390
|
function tokenFileFor(sessionPath, anonId) {
|
|
47871
|
-
return
|
|
48391
|
+
return join27(statsDir(sessionPath), `${anonId}.json`);
|
|
47872
48392
|
}
|
|
47873
48393
|
function readTokenStats(sessionPath, anonId) {
|
|
47874
48394
|
const path = tokenFileFor(sessionPath, anonId);
|
|
47875
|
-
if (!
|
|
48395
|
+
if (!existsSync19(path))
|
|
47876
48396
|
return null;
|
|
47877
48397
|
try {
|
|
47878
|
-
return JSON.parse(
|
|
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(
|
|
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
|
|
48572
|
+
existsSync as existsSync20,
|
|
48053
48573
|
mkdirSync as mkdirSync12,
|
|
48054
|
-
readFileSync as
|
|
48574
|
+
readFileSync as readFileSync18,
|
|
48055
48575
|
readdirSync as readdirSync3,
|
|
48056
48576
|
writeFileSync as writeFileSync12
|
|
48057
48577
|
} from "fs";
|
|
48058
|
-
import { join as
|
|
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 (
|
|
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(
|
|
48127
|
-
mkdirSync12(
|
|
48646
|
+
mkdirSync12(join28(sessionPath, "work"), { recursive: true });
|
|
48647
|
+
mkdirSync12(join28(sessionPath, "errors"), { recursive: true });
|
|
48128
48648
|
if (input !== undefined) {
|
|
48129
|
-
writeFileSync12(
|
|
48130
|
-
} else if (!
|
|
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(
|
|
48667
|
+
mkdirSync12(join28(sessionPath, "work", anonId), { recursive: true });
|
|
48148
48668
|
}
|
|
48149
|
-
writeFileSync12(
|
|
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(
|
|
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(
|
|
48169
|
-
const statusPath =
|
|
48170
|
-
const inputPath =
|
|
48171
|
-
const inputContent =
|
|
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(
|
|
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 =
|
|
48193
|
-
const errorLogPath =
|
|
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] =
|
|
48903
|
+
responses[id] = readFileSync18(join28(sessionPath, file2), "utf-8");
|
|
48384
48904
|
}
|
|
48385
|
-
const input =
|
|
48905
|
+
const input = readFileSync18(join28(sessionPath, "input.md"), "utf-8");
|
|
48386
48906
|
const judgePrompt = buildJudgePrompt(input, responses);
|
|
48387
|
-
writeFileSync12(
|
|
48907
|
+
writeFileSync12(join28(sessionPath, "judge-prompt.md"), judgePrompt, "utf-8");
|
|
48388
48908
|
const judgeModels = opts.judges ?? getDefaultJudgeModels(sessionPath);
|
|
48389
|
-
const judgePath =
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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(
|
|
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
|
|
48580
|
-
import { homedir as
|
|
48581
|
-
import { dirname as dirname9, join as
|
|
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 &&
|
|
49104
|
+
if (!forceRefresh && existsSync21(ALL_MODELS_CACHE_PATH2)) {
|
|
48585
49105
|
try {
|
|
48586
|
-
const cacheData = JSON.parse(
|
|
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 (
|
|
48605
|
-
const cacheData = JSON.parse(
|
|
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 =
|
|
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] =
|
|
49715
|
+
sessionData[file2] = readFileSync19(join29(sp, file2), "utf-8");
|
|
49196
49716
|
} catch {}
|
|
49197
49717
|
}
|
|
49198
49718
|
try {
|
|
49199
|
-
const errorDir =
|
|
49200
|
-
if (
|
|
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}`] =
|
|
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 =
|
|
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 =
|
|
49224
|
-
if (
|
|
49225
|
-
version2 = JSON.parse(
|
|
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 =
|
|
49630
|
-
ALL_MODELS_CACHE_PATH2 =
|
|
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
|
|
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 (!
|
|
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 =
|
|
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
|
|
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 (
|
|
49855
|
-
const parsed = JSON.parse(
|
|
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 (
|
|
49877
|
-
pending =
|
|
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
|
|
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 =
|
|
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
|
|
62444
|
-
import { homedir as
|
|
62445
|
-
import { join as
|
|
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 =
|
|
62567
|
-
if (
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
62728
|
-
|
|
62729
|
-
|
|
62730
|
-
|
|
62731
|
-
|
|
62732
|
-
|
|
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
|
-
|
|
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(`
|
|
63260
|
+
console.error(`
|
|
63261
|
+
${RED}Failed to fetch usage:${R} ${err?.message ?? err}
|
|
63262
|
+
`);
|
|
62820
63263
|
process.exit(1);
|
|
62821
63264
|
}
|
|
62822
|
-
|
|
62823
|
-
|
|
62824
|
-
|
|
62825
|
-
|
|
62826
|
-
|
|
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
|
-
|
|
62833
|
-
|
|
62834
|
-
|
|
62835
|
-
|
|
62836
|
-
|
|
62837
|
-
|
|
62838
|
-
|
|
62839
|
-
|
|
62840
|
-
|
|
62841
|
-
|
|
62842
|
-
|
|
62843
|
-
|
|
62844
|
-
|
|
62845
|
-
|
|
62846
|
-
|
|
62847
|
-
|
|
62848
|
-
|
|
62849
|
-
|
|
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
|
-
|
|
62883
|
-
|
|
62884
|
-
|
|
62885
|
-
|
|
62886
|
-
|
|
62887
|
-
|
|
62888
|
-
}
|
|
62889
|
-
|
|
62890
|
-
|
|
62891
|
-
|
|
62892
|
-
|
|
62893
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
62924
|
-
|
|
62925
|
-
|
|
62926
|
-
|
|
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
|
|
62935
|
-
|
|
62936
|
-
|
|
62937
|
-
|
|
62938
|
-
|
|
62939
|
-
|
|
62940
|
-
|
|
62941
|
-
|
|
62942
|
-
|
|
62943
|
-
}
|
|
62944
|
-
|
|
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
|
-
|
|
62952
|
-
|
|
62953
|
-
|
|
62954
|
-
|
|
62955
|
-
|
|
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
|
|
62962
|
-
const
|
|
62963
|
-
|
|
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",
|
|
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
|
-
|
|
62992
|
-
|
|
62993
|
-
|
|
62994
|
-
|
|
62995
|
-
|
|
62996
|
-
|
|
62997
|
-
|
|
62998
|
-
|
|
62999
|
-
|
|
63000
|
-
|
|
63001
|
-
|
|
63002
|
-
|
|
63003
|
-
|
|
63004
|
-
|
|
63005
|
-
|
|
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
|
|
67173
|
+
existsSync as existsSync25,
|
|
66775
67174
|
mkdirSync as mkdirSync14,
|
|
66776
|
-
readFileSync as
|
|
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
|
|
66782
|
-
import { dirname as dirname10, join as
|
|
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 =
|
|
66789
|
-
if (!
|
|
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(
|
|
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 =
|
|
67208
|
-
if (!
|
|
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 =
|
|
68283
|
-
const guideContent =
|
|
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 =
|
|
68300
|
-
const skillsDir =
|
|
68301
|
-
const claudishSkillDir =
|
|
68302
|
-
const skillFile =
|
|
68303
|
-
if (
|
|
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 =
|
|
68311
|
-
if (!
|
|
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 (!
|
|
68719
|
+
if (!existsSync25(claudeDir)) {
|
|
68321
68720
|
mkdirSync14(claudeDir, { recursive: true });
|
|
68322
68721
|
console.log("\uD83D\uDCC1 Created .claude/ directory");
|
|
68323
68722
|
}
|
|
68324
|
-
if (!
|
|
68723
|
+
if (!existsSync25(skillsDir)) {
|
|
68325
68724
|
mkdirSync14(skillsDir, { recursive: true });
|
|
68326
68725
|
console.log("\uD83D\uDCC1 Created .claude/skills/ directory");
|
|
68327
68726
|
}
|
|
68328
|
-
if (!
|
|
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
|
|
68414
|
-
import { homedir as
|
|
68415
|
-
import { join as
|
|
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 ||
|
|
68420
|
-
cacheDir =
|
|
68818
|
+
const localAppData = process.env.LOCALAPPDATA || join32(homedir30(), "AppData", "Local");
|
|
68819
|
+
cacheDir = join32(localAppData, "claudish");
|
|
68421
68820
|
} else {
|
|
68422
|
-
cacheDir =
|
|
68821
|
+
cacheDir = join32(homedir30(), ".cache", "claudish");
|
|
68423
68822
|
}
|
|
68424
68823
|
try {
|
|
68425
|
-
if (!
|
|
68824
|
+
if (!existsSync26(cacheDir)) {
|
|
68426
68825
|
mkdirSync15(cacheDir, { recursive: true });
|
|
68427
68826
|
}
|
|
68428
|
-
return
|
|
68827
|
+
return join32(cacheDir, "update-check.json");
|
|
68429
68828
|
} catch {
|
|
68430
|
-
return
|
|
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 (!
|
|
68835
|
+
if (!existsSync26(cachePath)) {
|
|
68437
68836
|
return null;
|
|
68438
68837
|
}
|
|
68439
|
-
const data = JSON.parse(
|
|
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 (
|
|
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
|
|
69348
|
-
import { homedir as
|
|
69349
|
-
import { dirname as dirname11, join as
|
|
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 (!
|
|
69750
|
+
if (!existsSync27(path2))
|
|
69352
69751
|
return null;
|
|
69353
69752
|
let raw2;
|
|
69354
69753
|
try {
|
|
69355
|
-
raw2 = JSON.parse(
|
|
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 =
|
|
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
|
|
76237
|
+
existsSync as existsSync28,
|
|
75839
76238
|
mkdirSync as mkdirSync17,
|
|
75840
76239
|
openSync as openSync5,
|
|
75841
|
-
readFileSync as
|
|
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
|
|
75848
|
-
import { dirname as dirname12, join as
|
|
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
|
|
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 =
|
|
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 =
|
|
76303
|
+
const claudishDir = join34(homeDir, ".claudish");
|
|
75905
76304
|
const timestamp = Date.now();
|
|
75906
|
-
const scriptPath =
|
|
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
|
-
|
|
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 (
|
|
76013
|
-
|
|
76014
|
-
|
|
76015
|
-
const
|
|
76016
|
-
|
|
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 =
|
|
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(
|
|
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
|
-
|
|
76091
|
-
|
|
76092
|
-
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
76139
|
-
const tokenFilePath =
|
|
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
|
|
76159
|
-
const
|
|
76160
|
-
const
|
|
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 =
|
|
76411
|
-
const localPath = isWindows2() ?
|
|
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 (
|
|
76901
|
+
if (existsSync28(process.env.CLAUDE_PATH)) {
|
|
76492
76902
|
return process.env.CLAUDE_PATH;
|
|
76493
76903
|
}
|
|
76494
76904
|
}
|
|
76495
|
-
const home =
|
|
76496
|
-
const localPath = isWindows3 ?
|
|
76497
|
-
if (
|
|
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
|
-
|
|
76503
|
-
|
|
76504
|
-
|
|
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 (
|
|
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
|
-
|
|
76516
|
-
|
|
76517
|
-
|
|
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
|
-
|
|
76929
|
+
join34(home, "../usr/bin/claude")
|
|
76520
76930
|
];
|
|
76521
76931
|
for (const path2 of commonPaths) {
|
|
76522
|
-
if (
|
|
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
|
|
76584
|
-
import { join as
|
|
76993
|
+
import { homedir as homedir33 } from "os";
|
|
76994
|
+
import { join as join35 } from "path";
|
|
76585
76995
|
function getClaudishDir() {
|
|
76586
|
-
const dir =
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
77310
|
+
const pkgRoot = join36(thisDir, "..");
|
|
76901
77311
|
const platform3 = process.platform;
|
|
76902
77312
|
const arch = process.arch;
|
|
76903
|
-
const bundledMagmux =
|
|
76904
|
-
if (
|
|
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 =
|
|
76911
|
-
if (
|
|
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 (
|
|
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 =
|
|
77018
|
-
const prompt =
|
|
77019
|
-
const rawPrompt =
|
|
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 =
|
|
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
|
|
77075
|
-
import { join as
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
77749
|
+
const responsePath = join37(sessionPath, `response-${anonId}.md`);
|
|
77340
77750
|
try {
|
|
77341
|
-
const raw2 =
|
|
77751
|
+
const raw2 = readFileSync28(responsePath, "utf-8").trim();
|
|
77342
77752
|
try {
|
|
77343
77753
|
result.responses[anonId] = JSON.parse(raw2);
|
|
77344
77754
|
} catch {
|