@narumitw/pi-usage 0.60.0 → 0.60.1
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/README.md +27 -19
- package/dist/index.ts +754 -300
- package/dist/index.ts.map +4 -4
- package/package.json +1 -1
- package/src/core.ts +28 -2
- package/src/format.ts +3 -0
- package/src/index.ts +13 -0
- package/src/providers/fireworks.ts +112 -0
- package/src/query.ts +110 -150
- package/src/settings.ts +155 -8
- package/src/types.ts +39 -2
- package/src/usage-settings-ui.ts +88 -183
- package/src/usage-targets.ts +143 -0
- package/src/usage.ts +413 -101
package/dist/index.ts
CHANGED
|
@@ -136,7 +136,20 @@ var UsageCache = class {
|
|
|
136
136
|
};
|
|
137
137
|
function fingerprintResolvedAuth(auth, salt) {
|
|
138
138
|
const headers = Object.entries(auth.headers ?? {}).map(([name, value]) => [name.toLowerCase(), value]).sort(([left], [right]) => left.localeCompare(right));
|
|
139
|
-
const
|
|
139
|
+
const env = Object.entries(auth.env ?? {}).sort(([left], [right]) => left.localeCompare(right));
|
|
140
|
+
const providerHeaders = Object.entries(auth.providerAuth?.headers ?? {}).map(([name, value]) => [name.toLowerCase(), value]).sort(([left], [right]) => left.localeCompare(right));
|
|
141
|
+
const canonical = JSON.stringify({
|
|
142
|
+
apiKey: auth.apiKey ?? "",
|
|
143
|
+
headers,
|
|
144
|
+
baseUrl: auth.baseUrl ?? "",
|
|
145
|
+
env,
|
|
146
|
+
source: auth.source ?? "",
|
|
147
|
+
providerAuth: {
|
|
148
|
+
apiKey: auth.providerAuth?.apiKey ?? "",
|
|
149
|
+
headers: providerHeaders,
|
|
150
|
+
baseUrl: auth.providerAuth?.baseUrl ?? ""
|
|
151
|
+
}
|
|
152
|
+
});
|
|
140
153
|
return createHmac("sha256", salt).update(canonical).digest("hex");
|
|
141
154
|
}
|
|
142
155
|
async function runWithConcurrency(items, limit, worker, signal) {
|
|
@@ -572,6 +585,9 @@ var INT64_MIN = -(2n ** 63n);
|
|
|
572
585
|
var INT64_MAX = 2n ** 63n - 1n;
|
|
573
586
|
var MAX_UNITS_CHARS = 20;
|
|
574
587
|
var MAX_NANOS_CHARS = 11;
|
|
588
|
+
var FIREWORKS_BILLING_SUMMARY_ORIGIN = "https://api.fireworks.ai";
|
|
589
|
+
var FIREWORKS_SPEND_WINDOW_DAYS = 30;
|
|
590
|
+
var FIREWORKS_MAX_ACCOUNT_PAGES = 5;
|
|
575
591
|
var SERIES_KEYS = ["serverless", "dedicated", "training", "other"];
|
|
576
592
|
var SERIES_LABELS = {
|
|
577
593
|
serverless: "Serverless",
|
|
@@ -605,6 +621,67 @@ function normalizeFireworksAccountsPayload(payload) {
|
|
|
605
621
|
}
|
|
606
622
|
return accounts;
|
|
607
623
|
}
|
|
624
|
+
function createFireworksAdapter(fetchProviderJson2) {
|
|
625
|
+
return {
|
|
626
|
+
id: "fireworks",
|
|
627
|
+
displayName: "Fireworks",
|
|
628
|
+
semantics: { kind: "api-key", label: "Fireworks API spend" },
|
|
629
|
+
targets: {
|
|
630
|
+
singularLabel: "account",
|
|
631
|
+
pluralLabel: "accounts",
|
|
632
|
+
async list(auth, signal, timeoutMs, guard) {
|
|
633
|
+
const startedAt = Date.now();
|
|
634
|
+
const accounts = [];
|
|
635
|
+
let pageToken;
|
|
636
|
+
for (let page = 0; page < FIREWORKS_MAX_ACCOUNT_PAGES; page += 1) {
|
|
637
|
+
await guard();
|
|
638
|
+
const payload = await fetchProviderJson2(
|
|
639
|
+
fireworksAccountsUrl(pageToken),
|
|
640
|
+
auth,
|
|
641
|
+
signal,
|
|
642
|
+
remainingTimeout(timeoutMs, startedAt, "fetching Fireworks accounts"),
|
|
643
|
+
"Fireworks accounts endpoint",
|
|
644
|
+
{ redirect: "error" }
|
|
645
|
+
);
|
|
646
|
+
await guard();
|
|
647
|
+
for (const accountId of normalizeFireworksAccountsPayload(payload)) {
|
|
648
|
+
if (accounts.includes(accountId)) {
|
|
649
|
+
throw new Error(`Fireworks accounts listing repeated ${accountId}.`);
|
|
650
|
+
}
|
|
651
|
+
accounts.push(accountId);
|
|
652
|
+
}
|
|
653
|
+
pageToken = fireworksNextPageToken(payload.nextPageToken);
|
|
654
|
+
if (!pageToken) break;
|
|
655
|
+
}
|
|
656
|
+
if (pageToken) {
|
|
657
|
+
throw new Error(
|
|
658
|
+
`Fireworks account listing exceeded ${FIREWORKS_MAX_ACCOUNT_PAGES} pages.`
|
|
659
|
+
);
|
|
660
|
+
}
|
|
661
|
+
return accounts.map((id) => ({ id, label: id }));
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
async query(auth, signal, timeoutMs, guard, targetId) {
|
|
665
|
+
if (!guard) throw new Error("Fireworks API spend requires request-boundary revalidation.");
|
|
666
|
+
if (!isFireworksAccountId(targetId)) {
|
|
667
|
+
throw new Error("Fireworks billing requires a safe selected account slug.");
|
|
668
|
+
}
|
|
669
|
+
const startedAt = Date.now();
|
|
670
|
+
await guard();
|
|
671
|
+
const billingWindowAt = Date.now();
|
|
672
|
+
const payload = await fetchProviderJson2(
|
|
673
|
+
fireworksBillingSummaryUrl(targetId, billingWindowAt),
|
|
674
|
+
auth,
|
|
675
|
+
signal,
|
|
676
|
+
remainingTimeout(timeoutMs, startedAt, "fetching Fireworks rated spend"),
|
|
677
|
+
"Fireworks billing summary endpoint",
|
|
678
|
+
{ redirect: "error" }
|
|
679
|
+
);
|
|
680
|
+
await guard();
|
|
681
|
+
return normalizeFireworksBillingSummaryPayload(payload, targetId, Date.now());
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
}
|
|
608
685
|
function normalizeFireworksBillingSummaryPayload(payload, accountId, capturedAt) {
|
|
609
686
|
if (!isFireworksAccountId(accountId)) {
|
|
610
687
|
throw new Error("Fireworks billing summary received an unsafe account identifier.");
|
|
@@ -711,6 +788,38 @@ function formatMoneyAmount(amount2) {
|
|
|
711
788
|
const nanos = (magnitude % NANOS_PER_UNIT).toString().padStart(9, "0").replace(/0+$/u, "");
|
|
712
789
|
return `${negative ? "-" : ""}${units.toString()}${nanos ? `.${nanos}` : ""}`;
|
|
713
790
|
}
|
|
791
|
+
function fireworksAccountsUrl(pageToken) {
|
|
792
|
+
const url = new URL("/v1/accounts", FIREWORKS_BILLING_SUMMARY_ORIGIN);
|
|
793
|
+
url.searchParams.set("pageSize", "200");
|
|
794
|
+
if (pageToken !== void 0) url.searchParams.set("pageToken", pageToken);
|
|
795
|
+
return url.toString();
|
|
796
|
+
}
|
|
797
|
+
function fireworksNextPageToken(value) {
|
|
798
|
+
if (value === void 0 || value === null) return void 0;
|
|
799
|
+
if (typeof value !== "string" || !value || value.length > 512) {
|
|
800
|
+
throw new Error("Fireworks accounts listing returned an invalid page token.");
|
|
801
|
+
}
|
|
802
|
+
return value;
|
|
803
|
+
}
|
|
804
|
+
function fireworksBillingSummaryUrl(accountId, startedAt) {
|
|
805
|
+
const dayMs = 24 * 60 * 60 * 1e3;
|
|
806
|
+
const dayFloor = (time) => `${new Date(time).toISOString().slice(0, 10)}T00:00:00Z`;
|
|
807
|
+
const url = new URL(
|
|
808
|
+
`/v1/accounts/${accountId}/billing/summary`,
|
|
809
|
+
FIREWORKS_BILLING_SUMMARY_ORIGIN
|
|
810
|
+
);
|
|
811
|
+
url.searchParams.set(
|
|
812
|
+
"startTime",
|
|
813
|
+
dayFloor(startedAt - (FIREWORKS_SPEND_WINDOW_DAYS - 1) * dayMs)
|
|
814
|
+
);
|
|
815
|
+
url.searchParams.set("endTime", dayFloor(startedAt + dayMs));
|
|
816
|
+
return url.toString();
|
|
817
|
+
}
|
|
818
|
+
function remainingTimeout(timeoutMs, startedAt, description) {
|
|
819
|
+
const remaining = timeoutMs - (Date.now() - startedAt);
|
|
820
|
+
if (remaining <= 0) throw new Error(`Timed out while ${description}.`);
|
|
821
|
+
return remaining;
|
|
822
|
+
}
|
|
714
823
|
function asObject4(value) {
|
|
715
824
|
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
716
825
|
return value;
|
|
@@ -1787,14 +1896,104 @@ function clampPercent3(value) {
|
|
|
1787
1896
|
return Math.min(100, Math.max(0, value));
|
|
1788
1897
|
}
|
|
1789
1898
|
|
|
1899
|
+
// src/usage-targets.ts
|
|
1900
|
+
var MAX_TARGETS = 1e3;
|
|
1901
|
+
var MAX_TARGET_ID_CHARS = 256;
|
|
1902
|
+
var MAX_TARGET_LABEL_CHARS = 120;
|
|
1903
|
+
var MAX_TARGET_DESCRIPTION_CHARS = 180;
|
|
1904
|
+
async function resolveUsageTarget(adapter, auth, rememberedTargetId, signal, timeoutMs, guard) {
|
|
1905
|
+
if (!adapter.targets) return { kind: "selected" };
|
|
1906
|
+
if (rememberedTargetId !== void 0 && !isBoundedTargetId(rememberedTargetId)) {
|
|
1907
|
+
throw new Error(`The remembered ${adapter.targets.singularLabel} identifier was invalid.`);
|
|
1908
|
+
}
|
|
1909
|
+
const choices = await listUsageTargets(adapter, auth, signal, timeoutMs, guard);
|
|
1910
|
+
if (rememberedTargetId) {
|
|
1911
|
+
return choices.some((choice) => choice.id === rememberedTargetId) ? { kind: "selected", targetId: rememberedTargetId } : { kind: "selection-required", choices };
|
|
1912
|
+
}
|
|
1913
|
+
if (choices.length === 1) return { kind: "selected", targetId: choices[0]?.id };
|
|
1914
|
+
return { kind: "selection-required", choices };
|
|
1915
|
+
}
|
|
1916
|
+
async function listUsageTargets(adapter, auth, signal, timeoutMs, guard) {
|
|
1917
|
+
if (!adapter.targets) return [];
|
|
1918
|
+
const startedAt = Date.now();
|
|
1919
|
+
await guard();
|
|
1920
|
+
const listed = await adapter.targets.list(
|
|
1921
|
+
auth,
|
|
1922
|
+
signal,
|
|
1923
|
+
remainingTargetTimeout(timeoutMs, startedAt),
|
|
1924
|
+
guard
|
|
1925
|
+
);
|
|
1926
|
+
await guard();
|
|
1927
|
+
remainingTargetTimeout(timeoutMs, startedAt);
|
|
1928
|
+
const choices = normalizeUsageTargets(listed);
|
|
1929
|
+
if (choices.length === 0) {
|
|
1930
|
+
throw new Error(`${adapter.targets.pluralLabel} discovery returned no choices.`);
|
|
1931
|
+
}
|
|
1932
|
+
return choices;
|
|
1933
|
+
}
|
|
1934
|
+
function normalizeUsageTargets(targets) {
|
|
1935
|
+
if (!Array.isArray(targets)) throw new Error("Target discovery did not return a choices array.");
|
|
1936
|
+
if (targets.length > MAX_TARGETS) {
|
|
1937
|
+
throw new Error(`Target discovery exceeded ${MAX_TARGETS} choices.`);
|
|
1938
|
+
}
|
|
1939
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1940
|
+
return targets.map((target) => {
|
|
1941
|
+
if (!target || typeof target !== "object" || Array.isArray(target)) {
|
|
1942
|
+
throw new Error("Target discovery returned an invalid choice.");
|
|
1943
|
+
}
|
|
1944
|
+
const { id, label, description } = target;
|
|
1945
|
+
if (!isBoundedTargetId(id)) throw new Error("Target discovery returned an invalid ID.");
|
|
1946
|
+
if (seen.has(id)) throw new Error(`Target discovery repeated ${id}.`);
|
|
1947
|
+
seen.add(id);
|
|
1948
|
+
if (typeof label !== "string") {
|
|
1949
|
+
throw new Error("Target discovery returned an invalid display label.");
|
|
1950
|
+
}
|
|
1951
|
+
if (description !== void 0 && typeof description !== "string") {
|
|
1952
|
+
throw new Error("Target discovery returned an invalid description.");
|
|
1953
|
+
}
|
|
1954
|
+
const safeLabel2 = sanitizeDisplayText(label, MAX_TARGET_LABEL_CHARS);
|
|
1955
|
+
if (!safeLabel2) throw new Error("Target discovery returned an empty display label.");
|
|
1956
|
+
const safeDescription = description ? sanitizeDisplayText(description, MAX_TARGET_DESCRIPTION_CHARS) : void 0;
|
|
1957
|
+
return { id, label: safeLabel2, ...safeDescription ? { description: safeDescription } : {} };
|
|
1958
|
+
});
|
|
1959
|
+
}
|
|
1960
|
+
function createUsageTargetSelectOptions(targets) {
|
|
1961
|
+
const normalized = normalizeUsageTargets(targets);
|
|
1962
|
+
const ids = /* @__PURE__ */ new Map();
|
|
1963
|
+
const options = normalized.map((target) => {
|
|
1964
|
+
const base = target.description ? `${target.label} \u2014 ${target.description}` : target.label;
|
|
1965
|
+
let option = base;
|
|
1966
|
+
if (ids.has(option)) {
|
|
1967
|
+
const safeId = sanitizeDisplayText(target.id, 80) || "target";
|
|
1968
|
+
option = `${base} \xB7 ${safeId}`;
|
|
1969
|
+
let duplicate = 2;
|
|
1970
|
+
while (ids.has(option)) {
|
|
1971
|
+
option = `${base} \xB7 ${safeId} (${duplicate})`;
|
|
1972
|
+
duplicate += 1;
|
|
1973
|
+
}
|
|
1974
|
+
}
|
|
1975
|
+
ids.set(option, target.id);
|
|
1976
|
+
return option;
|
|
1977
|
+
});
|
|
1978
|
+
return { options, targetIdFor: (option) => ids.get(option) };
|
|
1979
|
+
}
|
|
1980
|
+
function remainingTargetTimeout(timeoutMs, startedAt) {
|
|
1981
|
+
const remaining = timeoutMs - (Date.now() - startedAt);
|
|
1982
|
+
if (remaining <= 0) throw new Error("Timed out while discovering provider targets.");
|
|
1983
|
+
return remaining;
|
|
1984
|
+
}
|
|
1985
|
+
function isBoundedTargetId(value) {
|
|
1986
|
+
return typeof value === "string" && value.length > 0 && value.length <= MAX_TARGET_ID_CHARS && ![...value].some((character) => {
|
|
1987
|
+
const codePoint = character.codePointAt(0) ?? 0;
|
|
1988
|
+
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159;
|
|
1989
|
+
});
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1790
1992
|
// src/query.ts
|
|
1791
1993
|
var BASETEN_BILLING_USAGE_URL = "https://api.baseten.co/v1/billing/usage_summary";
|
|
1792
1994
|
var BASETEN_USAGE_WINDOW_DAYS = 30;
|
|
1793
1995
|
var CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
|
|
1794
1996
|
var DEEPSEEK_BALANCE_URL = "https://api.deepseek.com/user/balance";
|
|
1795
|
-
var FIREWORKS_BILLING_SUMMARY_ORIGIN = "https://api.fireworks.ai";
|
|
1796
|
-
var FIREWORKS_SPEND_WINDOW_DAYS = 30;
|
|
1797
|
-
var FIREWORKS_MAX_ACCOUNT_PAGES = 5;
|
|
1798
1997
|
var GITHUB_COPILOT_USAGE_URL = "https://api.github.com/copilot_internal/user";
|
|
1799
1998
|
var OPENROUTER_KEY_URL = "https://openrouter.ai/api/v1/key";
|
|
1800
1999
|
var VERCEL_AI_GATEWAY_CREDITS_URL = "https://ai-gateway.vercel.sh/v1/credits";
|
|
@@ -1833,7 +2032,7 @@ var SUPPORTED_ADAPTERS = [
|
|
|
1833
2032
|
basetenBillingUsageUrl(windowAt),
|
|
1834
2033
|
auth,
|
|
1835
2034
|
signal,
|
|
1836
|
-
|
|
2035
|
+
remainingTimeout2(timeoutMs, startedAt, "fetching Baseten billing usage"),
|
|
1837
2036
|
"Baseten billing usage endpoint",
|
|
1838
2037
|
{ redirect: "error" }
|
|
1839
2038
|
);
|
|
@@ -1926,7 +2125,7 @@ var SUPPORTED_ADAPTERS = [
|
|
|
1926
2125
|
VERCEL_AI_GATEWAY_CREDITS_URL,
|
|
1927
2126
|
auth,
|
|
1928
2127
|
signal,
|
|
1929
|
-
|
|
2128
|
+
remainingTimeout2(timeoutMs, startedAt, "fetching Vercel AI Gateway credits"),
|
|
1930
2129
|
"Vercel AI Gateway credits endpoint",
|
|
1931
2130
|
{ redirect: "error" }
|
|
1932
2131
|
);
|
|
@@ -1934,35 +2133,7 @@ var SUPPORTED_ADAPTERS = [
|
|
|
1934
2133
|
return normalizeVercelAIGatewayCreditsPayload(payload, Date.now());
|
|
1935
2134
|
}
|
|
1936
2135
|
},
|
|
1937
|
-
|
|
1938
|
-
id: "fireworks",
|
|
1939
|
-
displayName: "Fireworks",
|
|
1940
|
-
semantics: { kind: "api-key", label: "Fireworks API spend" },
|
|
1941
|
-
async query(auth, signal, timeoutMs, guard, settings) {
|
|
1942
|
-
if (!guard) throw new Error("Fireworks API spend requires request-boundary revalidation.");
|
|
1943
|
-
const startedAt = Date.now();
|
|
1944
|
-
await guard();
|
|
1945
|
-
const accountId = await resolveFireworksAccountId(
|
|
1946
|
-
auth,
|
|
1947
|
-
signal,
|
|
1948
|
-
remainingTimeout(timeoutMs, startedAt, "resolving the Fireworks account"),
|
|
1949
|
-
guard,
|
|
1950
|
-
settings?.fireworksAccountId
|
|
1951
|
-
);
|
|
1952
|
-
await guard();
|
|
1953
|
-
const billingWindowAt = Date.now();
|
|
1954
|
-
const payload = await fetchProviderJson(
|
|
1955
|
-
fireworksBillingSummaryUrl(accountId, billingWindowAt),
|
|
1956
|
-
auth,
|
|
1957
|
-
signal,
|
|
1958
|
-
remainingTimeout(timeoutMs, startedAt, "fetching Fireworks rated spend"),
|
|
1959
|
-
"Fireworks billing summary endpoint",
|
|
1960
|
-
{ redirect: "error" }
|
|
1961
|
-
);
|
|
1962
|
-
await guard();
|
|
1963
|
-
return normalizeFireworksBillingSummaryPayload(payload, accountId, Date.now());
|
|
1964
|
-
}
|
|
1965
|
-
},
|
|
2136
|
+
createFireworksAdapter(fetchProviderJson),
|
|
1966
2137
|
{
|
|
1967
2138
|
id: "opencode-go",
|
|
1968
2139
|
displayName: "OpenCode Go",
|
|
@@ -2063,7 +2234,7 @@ var XAI_ADAPTER = {
|
|
|
2063
2234
|
XAI_USER_URL,
|
|
2064
2235
|
clientAuth,
|
|
2065
2236
|
signal,
|
|
2066
|
-
|
|
2237
|
+
remainingTimeout2(timeoutMs, startedAt),
|
|
2067
2238
|
"xAI consumer identity endpoint",
|
|
2068
2239
|
{ redirect: "error", userAgent: false }
|
|
2069
2240
|
);
|
|
@@ -2079,7 +2250,7 @@ var XAI_ADAPTER = {
|
|
|
2079
2250
|
XAI_BILLING_URL,
|
|
2080
2251
|
billingAuth,
|
|
2081
2252
|
signal,
|
|
2082
|
-
|
|
2253
|
+
remainingTimeout2(timeoutMs, startedAt),
|
|
2083
2254
|
"xAI consumer billing endpoint",
|
|
2084
2255
|
{ redirect: "error", userAgent: false }
|
|
2085
2256
|
);
|
|
@@ -2107,6 +2278,12 @@ async function resolveUsageAuth(ctx, adapter, salt = AUTH_FINGERPRINT_SALT, cred
|
|
|
2107
2278
|
);
|
|
2108
2279
|
if (!model) return void 0;
|
|
2109
2280
|
const registry = ctx.modelRegistry;
|
|
2281
|
+
const provider = registry.getProvider?.(adapter.id);
|
|
2282
|
+
if (provider?.baseUrl && !hasOfficialUrlOrigin(provider.baseUrl, adapter.id)) {
|
|
2283
|
+
throw new Error(
|
|
2284
|
+
`${adapter.displayName} usage cannot send an overridden provider credential to the official usage endpoint.`
|
|
2285
|
+
);
|
|
2286
|
+
}
|
|
2110
2287
|
let modelAuth;
|
|
2111
2288
|
const currentModel = ctx.model?.provider === adapter.id ? ctx.model : void 0;
|
|
2112
2289
|
const resolveCurrentModelAuth = async () => {
|
|
@@ -2129,25 +2306,64 @@ async function resolveUsageAuth(ctx, adapter, salt = AUTH_FINGERPRINT_SALT, cred
|
|
|
2129
2306
|
);
|
|
2130
2307
|
}
|
|
2131
2308
|
if (resolveSelectedAuthLast) modelAuth = await resolveCurrentModelAuth();
|
|
2309
|
+
if (modelAuth?.baseUrl && !hasOfficialUrlOrigin(modelAuth.baseUrl, adapter.id)) {
|
|
2310
|
+
throw new Error(
|
|
2311
|
+
`${adapter.displayName} usage cannot send model-resolved proxy credentials to the official usage endpoint.`
|
|
2312
|
+
);
|
|
2313
|
+
}
|
|
2132
2314
|
const auth = modelAuth ?? providerResult?.auth;
|
|
2133
2315
|
if (!auth) return void 0;
|
|
2316
|
+
const finalize = (resolved) => {
|
|
2317
|
+
const preservedAuth = { ...providerResult?.auth ?? auth };
|
|
2318
|
+
const env = providerResult?.env ?? modelAuth?.env;
|
|
2319
|
+
const source = providerResult?.source;
|
|
2320
|
+
const effectiveBaseUrl = modelAuth?.baseUrl ?? providerResult?.auth.baseUrl ?? provider?.baseUrl ?? model.baseUrl;
|
|
2321
|
+
const redactionInputs = [
|
|
2322
|
+
preservedAuth.apiKey,
|
|
2323
|
+
...Object.values(preservedAuth.headers ?? {}),
|
|
2324
|
+
...Object.values(env ?? {}),
|
|
2325
|
+
modelAuth?.apiKey,
|
|
2326
|
+
...Object.values(modelAuth?.headers ?? {})
|
|
2327
|
+
].filter((value) => typeof value === "string" && value.length > 0);
|
|
2328
|
+
return {
|
|
2329
|
+
...resolved,
|
|
2330
|
+
auth: preservedAuth,
|
|
2331
|
+
...env ? { env: { ...env } } : {},
|
|
2332
|
+
...source ? { source } : {},
|
|
2333
|
+
effectiveBaseUrl,
|
|
2334
|
+
secrets: [.../* @__PURE__ */ new Set([...resolved.secrets, ...redactionInputs])],
|
|
2335
|
+
fingerprint: fingerprintResolvedAuth(
|
|
2336
|
+
{
|
|
2337
|
+
apiKey: resolved.apiKey,
|
|
2338
|
+
headers: resolved.headers,
|
|
2339
|
+
baseUrl: effectiveBaseUrl,
|
|
2340
|
+
env,
|
|
2341
|
+
source,
|
|
2342
|
+
providerAuth: preservedAuth
|
|
2343
|
+
},
|
|
2344
|
+
salt
|
|
2345
|
+
)
|
|
2346
|
+
};
|
|
2347
|
+
};
|
|
2134
2348
|
if (adapter.id === "github-copilot") {
|
|
2135
2349
|
const offered = candidateReader ? candidateReader(ctx, adapter.id) : fallbackOAuthCredentialCandidates(adapter.id, credentialReader);
|
|
2136
2350
|
if (!offered.ok) {
|
|
2137
2351
|
throw new Error("GitHub Copilot OAuth credential discovery failed closed.");
|
|
2138
2352
|
}
|
|
2139
|
-
return
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2353
|
+
return finalize(
|
|
2354
|
+
resolveGitHubCopilotUsageAuth(
|
|
2355
|
+
auth,
|
|
2356
|
+
model,
|
|
2357
|
+
salt,
|
|
2358
|
+
offered.candidates,
|
|
2359
|
+
offered.offeredCount === 0
|
|
2360
|
+
)
|
|
2145
2361
|
);
|
|
2146
2362
|
}
|
|
2147
2363
|
if (adapter.id === "xai") {
|
|
2148
2364
|
const offered = candidateReader ? candidateReader(ctx, adapter.id) : fallbackOAuthCredentialCandidates(adapter.id, credentialReader);
|
|
2149
2365
|
if (!offered.ok) throw new Error("xAI OAuth credential discovery failed closed.");
|
|
2150
|
-
return resolveXaiUsageAuth(auth, model, salt, offered.candidates);
|
|
2366
|
+
return finalize(resolveXaiUsageAuth(auth, model, salt, offered.candidates));
|
|
2151
2367
|
}
|
|
2152
2368
|
if (adapter.id === "deepseek") {
|
|
2153
2369
|
const resolvedAuthorization = authorizationFrom(auth);
|
|
@@ -2155,10 +2371,10 @@ async function resolveUsageAuth(ctx, adapter, salt = AUTH_FINGERPRINT_SALT, cred
|
|
|
2155
2371
|
if (!access) throw new Error("DeepSeek API balance requires Bearer authentication.");
|
|
2156
2372
|
const authorization2 = `Bearer ${access}`;
|
|
2157
2373
|
const headers2 = { Authorization: authorization2 };
|
|
2158
|
-
return {
|
|
2374
|
+
return finalize({
|
|
2159
2375
|
apiKey: access,
|
|
2160
2376
|
headers: headers2,
|
|
2161
|
-
fingerprint:
|
|
2377
|
+
fingerprint: "",
|
|
2162
2378
|
secrets: [
|
|
2163
2379
|
access,
|
|
2164
2380
|
auth.apiKey,
|
|
@@ -2167,7 +2383,7 @@ async function resolveUsageAuth(ctx, adapter, salt = AUTH_FINGERPRINT_SALT, cred
|
|
|
2167
2383
|
authorization2
|
|
2168
2384
|
].filter((value) => Boolean(value)),
|
|
2169
2385
|
model
|
|
2170
|
-
};
|
|
2386
|
+
});
|
|
2171
2387
|
}
|
|
2172
2388
|
const authorization = authorizationFrom(auth);
|
|
2173
2389
|
if (!authorization) return void 0;
|
|
@@ -2175,17 +2391,41 @@ async function resolveUsageAuth(ctx, adapter, salt = AUTH_FINGERPRINT_SALT, cred
|
|
|
2175
2391
|
const secrets = [auth.apiKey, headerValue(auth.headers, "Authorization"), authorization].filter(
|
|
2176
2392
|
(value) => Boolean(value)
|
|
2177
2393
|
);
|
|
2178
|
-
return {
|
|
2394
|
+
return finalize({
|
|
2179
2395
|
apiKey: auth.apiKey,
|
|
2180
2396
|
headers,
|
|
2181
|
-
fingerprint:
|
|
2397
|
+
fingerprint: "",
|
|
2182
2398
|
secrets,
|
|
2183
2399
|
model
|
|
2184
|
-
};
|
|
2400
|
+
});
|
|
2185
2401
|
}
|
|
2186
|
-
async function queryProviderUsage(adapter, auth, signal, timeoutMs, guard,
|
|
2402
|
+
async function queryProviderUsage(adapter, auth, signal, timeoutMs, guard, targetOrSettings) {
|
|
2403
|
+
const startedAt = Date.now();
|
|
2404
|
+
let targetId = typeof targetOrSettings === "string" ? targetOrSettings : adapter.id === "fireworks" ? targetOrSettings?.fireworksAccountId : void 0;
|
|
2405
|
+
let resolvedLegacyFireworksTarget = false;
|
|
2187
2406
|
try {
|
|
2188
|
-
|
|
2407
|
+
if (adapter.id === "fireworks" && typeof targetOrSettings !== "string" && adapter.targets && guard) {
|
|
2408
|
+
const target = await resolveUsageTarget(
|
|
2409
|
+
adapter,
|
|
2410
|
+
auth,
|
|
2411
|
+
targetId,
|
|
2412
|
+
signal,
|
|
2413
|
+
remainingTimeout2(timeoutMs, startedAt, "resolving the Fireworks account"),
|
|
2414
|
+
guard
|
|
2415
|
+
);
|
|
2416
|
+
if (target.kind === "selection-required") {
|
|
2417
|
+
throw new Error("Fireworks account selection is required.");
|
|
2418
|
+
}
|
|
2419
|
+
targetId = target.targetId;
|
|
2420
|
+
resolvedLegacyFireworksTarget = true;
|
|
2421
|
+
}
|
|
2422
|
+
return await adapter.query(
|
|
2423
|
+
auth,
|
|
2424
|
+
signal,
|
|
2425
|
+
resolvedLegacyFireworksTarget ? remainingTimeout2(timeoutMs, startedAt, `querying ${adapter.displayName} usage`) : timeoutMs,
|
|
2426
|
+
guard,
|
|
2427
|
+
targetId
|
|
2428
|
+
);
|
|
2189
2429
|
} catch (error) {
|
|
2190
2430
|
if (isStaleExtensionContextError(error) || isAbortError(error)) throw error;
|
|
2191
2431
|
throw new Error(redactUsageError(errorMessage(error), auth.secrets));
|
|
@@ -2484,7 +2724,7 @@ function hasOfficialUrlOrigin(value, providerId) {
|
|
|
2484
2724
|
}
|
|
2485
2725
|
if (providerId === "openai-codex") return url.origin === "https://chatgpt.com";
|
|
2486
2726
|
if (providerId === "deepseek") return url.origin === "https://api.deepseek.com";
|
|
2487
|
-
if (providerId === "fireworks") return url.origin ===
|
|
2727
|
+
if (providerId === "fireworks") return url.origin === "https://api.fireworks.ai";
|
|
2488
2728
|
if (providerId === "openrouter") return url.origin === "https://openrouter.ai";
|
|
2489
2729
|
if (providerId === "vercel-ai-gateway") return url.origin === "https://ai-gateway.vercel.sh";
|
|
2490
2730
|
if (providerId === "opencode-go") return url.origin === "https://opencode.ai";
|
|
@@ -2540,7 +2780,7 @@ async function queryMiniMaxUsage(providerId, auth, signal, timeoutMs, guard) {
|
|
|
2540
2780
|
`${MINIMAX_API_ROOTS[providerId]}${path}`,
|
|
2541
2781
|
auth,
|
|
2542
2782
|
signal,
|
|
2543
|
-
|
|
2783
|
+
remainingTimeout2(timeoutMs, startedAt, "fetching MiniMax usage"),
|
|
2544
2784
|
"MiniMax usage endpoint",
|
|
2545
2785
|
{ redirect: "error" }
|
|
2546
2786
|
);
|
|
@@ -2555,94 +2795,18 @@ async function queryMoonshotBalance(providerId, auth, signal, timeoutMs, guard)
|
|
|
2555
2795
|
MOONSHOT_BALANCE_URLS[providerId],
|
|
2556
2796
|
auth,
|
|
2557
2797
|
signal,
|
|
2558
|
-
|
|
2798
|
+
remainingTimeout2(timeoutMs, startedAt, "fetching Moonshot AI balance"),
|
|
2559
2799
|
"Moonshot AI balance endpoint",
|
|
2560
2800
|
{ redirect: "error" }
|
|
2561
2801
|
);
|
|
2562
2802
|
await guard();
|
|
2563
2803
|
return normalizeMoonshotBalancePayload(providerId, payload, Date.now());
|
|
2564
2804
|
}
|
|
2565
|
-
function
|
|
2805
|
+
function remainingTimeout2(timeoutMs, startedAt, description = "fetching xAI consumer usage") {
|
|
2566
2806
|
const remaining = timeoutMs - (Date.now() - startedAt);
|
|
2567
2807
|
if (remaining <= 0) throw new Error(`Timed out while ${description}.`);
|
|
2568
2808
|
return remaining;
|
|
2569
2809
|
}
|
|
2570
|
-
async function resolveFireworksAccountId(auth, signal, timeoutMs, guard, configuredAccountId) {
|
|
2571
|
-
if (configuredAccountId !== void 0 && !isFireworksAccountId(configuredAccountId)) {
|
|
2572
|
-
throw new Error("The Fireworks account setting was not a safe account slug.");
|
|
2573
|
-
}
|
|
2574
|
-
const startedAt = Date.now();
|
|
2575
|
-
const accounts = [];
|
|
2576
|
-
let pageToken;
|
|
2577
|
-
for (let page = 0; page < FIREWORKS_MAX_ACCOUNT_PAGES; page += 1) {
|
|
2578
|
-
await guard();
|
|
2579
|
-
const payload = await fetchProviderJson(
|
|
2580
|
-
fireworksAccountsUrl(pageToken),
|
|
2581
|
-
auth,
|
|
2582
|
-
signal,
|
|
2583
|
-
remainingTimeout(timeoutMs, startedAt, "fetching Fireworks accounts"),
|
|
2584
|
-
"Fireworks accounts endpoint",
|
|
2585
|
-
{ redirect: "error" }
|
|
2586
|
-
);
|
|
2587
|
-
for (const accountId of normalizeFireworksAccountsPayload(
|
|
2588
|
-
payload
|
|
2589
|
-
)) {
|
|
2590
|
-
if (accounts.includes(accountId)) {
|
|
2591
|
-
throw new Error(`Fireworks accounts listing repeated ${accountId}.`);
|
|
2592
|
-
}
|
|
2593
|
-
accounts.push(accountId);
|
|
2594
|
-
if (configuredAccountId === accountId) return accountId;
|
|
2595
|
-
}
|
|
2596
|
-
pageToken = fireworksNextPageToken(payload.nextPageToken);
|
|
2597
|
-
if (!pageToken) break;
|
|
2598
|
-
}
|
|
2599
|
-
if (pageToken) {
|
|
2600
|
-
throw new Error(
|
|
2601
|
-
configuredAccountId ? `The configured Fireworks account was not found within the first ${FIREWORKS_MAX_ACCOUNT_PAGES} listing pages.` : `Fireworks account listing exceeded ${FIREWORKS_MAX_ACCOUNT_PAGES} pages; set fireworksAccountId in pi-usage.json to an account returned in those pages.`
|
|
2602
|
-
);
|
|
2603
|
-
}
|
|
2604
|
-
if (accounts.length === 0) {
|
|
2605
|
-
throw new Error("Fireworks account discovery returned no accounts for this API key.");
|
|
2606
|
-
}
|
|
2607
|
-
if (configuredAccountId) {
|
|
2608
|
-
throw new Error(
|
|
2609
|
-
"The configured Fireworks account does not match an account visible to this API key."
|
|
2610
|
-
);
|
|
2611
|
-
}
|
|
2612
|
-
if (accounts.length === 1) return accounts[0];
|
|
2613
|
-
const preview = accounts.slice(0, 8).join(", ");
|
|
2614
|
-
const suffix = accounts.length > 8 ? ` \u2026and ${accounts.length - 8} more` : "";
|
|
2615
|
-
throw new Error(
|
|
2616
|
-
`The Fireworks key can see ${accounts.length} accounts (${preview}${suffix}); set fireworksAccountId in pi-usage.json to one of them.`
|
|
2617
|
-
);
|
|
2618
|
-
}
|
|
2619
|
-
function fireworksAccountsUrl(pageToken) {
|
|
2620
|
-
const url = new URL("/v1/accounts", FIREWORKS_BILLING_SUMMARY_ORIGIN);
|
|
2621
|
-
url.searchParams.set("pageSize", "200");
|
|
2622
|
-
if (pageToken !== void 0) url.searchParams.set("pageToken", pageToken);
|
|
2623
|
-
return url.toString();
|
|
2624
|
-
}
|
|
2625
|
-
function fireworksNextPageToken(value) {
|
|
2626
|
-
if (value === void 0 || value === null) return void 0;
|
|
2627
|
-
if (typeof value !== "string" || !value || value.length > 512) {
|
|
2628
|
-
throw new Error("Fireworks accounts listing returned an invalid page token.");
|
|
2629
|
-
}
|
|
2630
|
-
return value;
|
|
2631
|
-
}
|
|
2632
|
-
function fireworksBillingSummaryUrl(accountId, startedAt) {
|
|
2633
|
-
const dayMs = 24 * 60 * 60 * 1e3;
|
|
2634
|
-
const dayFloor = (time) => `${new Date(time).toISOString().slice(0, 10)}T00:00:00Z`;
|
|
2635
|
-
const url = new URL(
|
|
2636
|
-
`/v1/accounts/${accountId}/billing/summary`,
|
|
2637
|
-
FIREWORKS_BILLING_SUMMARY_ORIGIN
|
|
2638
|
-
);
|
|
2639
|
-
url.searchParams.set(
|
|
2640
|
-
"startTime",
|
|
2641
|
-
dayFloor(startedAt - (FIREWORKS_SPEND_WINDOW_DAYS - 1) * dayMs)
|
|
2642
|
-
);
|
|
2643
|
-
url.searchParams.set("endTime", dayFloor(startedAt + dayMs));
|
|
2644
|
-
return url.toString();
|
|
2645
|
-
}
|
|
2646
2810
|
function zaiOrigin(baseUrl) {
|
|
2647
2811
|
const base = baseUrl?.trim();
|
|
2648
2812
|
if (!base) throw new Error("Z.AI model base URL is unavailable.");
|
|
@@ -2665,7 +2829,7 @@ async function queryZaiUsage(providerId, providerName, auth, signal, timeoutMs,
|
|
|
2665
2829
|
zaiMonitorUrl(auth.model.baseUrl),
|
|
2666
2830
|
zaiMonitorAuth(auth),
|
|
2667
2831
|
signal,
|
|
2668
|
-
|
|
2832
|
+
remainingTimeout2(timeoutMs, startedAt, `fetching ${providerName} quota`),
|
|
2669
2833
|
`${providerName} quota endpoint`
|
|
2670
2834
|
);
|
|
2671
2835
|
await guard();
|
|
@@ -3016,6 +3180,10 @@ function formatProviderStates(states) {
|
|
|
3016
3180
|
return states.map((state) => {
|
|
3017
3181
|
if (state.status === "ready") return formatUsageReport(state.report, state.displayState);
|
|
3018
3182
|
const label = state.displayState === "current" ? "Current" : "Configured";
|
|
3183
|
+
if (state.status === "selection-required") {
|
|
3184
|
+
return `${state.providerName} \xB7 ${label}
|
|
3185
|
+
Selection required: choose this provider's ${state.singularLabel} by viewing it individually.`;
|
|
3186
|
+
}
|
|
3019
3187
|
const status = state.status === "auth-unavailable" ? "Authentication unavailable" : state.status === "unsupported" ? "Unsupported" : "Query failed";
|
|
3020
3188
|
return `${state.providerName} \xB7 ${label}
|
|
3021
3189
|
${status}: ${state.message}`;
|
|
@@ -3552,7 +3720,8 @@ var USAGE_SETTINGS_FILE = "pi-usage.json";
|
|
|
3552
3720
|
var MAX_USAGE_SETTINGS_BYTES = 64 * 1024;
|
|
3553
3721
|
var DEFAULT_USAGE_SETTINGS = Object.freeze({
|
|
3554
3722
|
codexFastMode: false,
|
|
3555
|
-
codexStatusResetCountdown: true
|
|
3723
|
+
codexStatusResetCountdown: true,
|
|
3724
|
+
selectedTargets: Object.freeze({})
|
|
3556
3725
|
});
|
|
3557
3726
|
function usageSettingsPath() {
|
|
3558
3727
|
return join(getAgentDir(), USAGE_SETTINGS_FILE);
|
|
@@ -3568,10 +3737,16 @@ function normalizeUsageSettings(value) {
|
|
|
3568
3737
|
if (Object.hasOwn(value, "fireworksAccountId") && !isFireworksAccountId(value.fireworksAccountId)) {
|
|
3569
3738
|
return void 0;
|
|
3570
3739
|
}
|
|
3740
|
+
const selectedTargets = normalizeSelectedTargets(value.selectedTargets);
|
|
3741
|
+
if (Object.hasOwn(value, "selectedTargets") && !selectedTargets) return void 0;
|
|
3742
|
+
const effectiveTargets = { ...selectedTargets ?? {} };
|
|
3743
|
+
if (!effectiveTargets.fireworks && isFireworksAccountId(value.fireworksAccountId)) {
|
|
3744
|
+
effectiveTargets.fireworks = value.fireworksAccountId;
|
|
3745
|
+
}
|
|
3571
3746
|
return {
|
|
3572
3747
|
codexFastMode: typeof value.codexFastMode === "boolean" ? value.codexFastMode : DEFAULT_USAGE_SETTINGS.codexFastMode,
|
|
3573
3748
|
codexStatusResetCountdown: typeof value.codexStatusResetCountdown === "boolean" ? value.codexStatusResetCountdown : DEFAULT_USAGE_SETTINGS.codexStatusResetCountdown,
|
|
3574
|
-
|
|
3749
|
+
selectedTargets: effectiveTargets
|
|
3575
3750
|
};
|
|
3576
3751
|
}
|
|
3577
3752
|
async function loadUsageSettings(path = usageSettingsPath(), signal) {
|
|
@@ -3647,19 +3822,84 @@ function createUsageSettingsRuntime(options = {}) {
|
|
|
3647
3822
|
state = saved;
|
|
3648
3823
|
return structuredClone(state);
|
|
3649
3824
|
}),
|
|
3825
|
+
updateSelectedTarget: (providerId, targetId, signal, checkPublishedSelection) => enqueue(async () => {
|
|
3826
|
+
const transaction = await saveUsageTargetSelection(
|
|
3827
|
+
path,
|
|
3828
|
+
providerId,
|
|
3829
|
+
targetId,
|
|
3830
|
+
operations,
|
|
3831
|
+
signal
|
|
3832
|
+
);
|
|
3833
|
+
try {
|
|
3834
|
+
await checkPublishedSelection?.();
|
|
3835
|
+
throwIfAborted(signal);
|
|
3836
|
+
} catch (error) {
|
|
3837
|
+
try {
|
|
3838
|
+
await restoreUsageSettingsState(
|
|
3839
|
+
path,
|
|
3840
|
+
transaction.saved,
|
|
3841
|
+
transaction.previous,
|
|
3842
|
+
operations
|
|
3843
|
+
);
|
|
3844
|
+
state = transaction.previous;
|
|
3845
|
+
} catch (rollbackError) {
|
|
3846
|
+
state = await loadUsageSettings(path);
|
|
3847
|
+
throw new AggregateError(
|
|
3848
|
+
[error, rollbackError],
|
|
3849
|
+
"Target selection changed after publication and pi-usage.json rollback failed"
|
|
3850
|
+
);
|
|
3851
|
+
}
|
|
3852
|
+
throw error;
|
|
3853
|
+
}
|
|
3854
|
+
state = transaction.saved;
|
|
3855
|
+
return structuredClone(state);
|
|
3856
|
+
}),
|
|
3650
3857
|
flush: () => queue
|
|
3651
3858
|
};
|
|
3652
3859
|
}
|
|
3653
3860
|
async function saveUsageSettingsPatch(path, patch, operations, signal) {
|
|
3861
|
+
return saveUsageSettingsDocument(
|
|
3862
|
+
path,
|
|
3863
|
+
(document) => {
|
|
3864
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
3865
|
+
if (value === void 0) delete document[key];
|
|
3866
|
+
else document[key] = value;
|
|
3867
|
+
}
|
|
3868
|
+
},
|
|
3869
|
+
operations,
|
|
3870
|
+
signal
|
|
3871
|
+
);
|
|
3872
|
+
}
|
|
3873
|
+
async function saveUsageTargetSelection(path, providerId, targetId, operations, signal) {
|
|
3874
|
+
if (!isProviderId(providerId) || !isBoundedTargetId(targetId)) {
|
|
3875
|
+
throw new Error("Refusing to save an invalid usage target selection");
|
|
3876
|
+
}
|
|
3877
|
+
const previous = await loadUsageSettings(path, signal);
|
|
3878
|
+
const saved = await saveUsageSettingsDocument(
|
|
3879
|
+
path,
|
|
3880
|
+
(document) => {
|
|
3881
|
+
document.selectedTargets = {
|
|
3882
|
+
...normalizeSelectedTargets(document.selectedTargets) ?? {},
|
|
3883
|
+
[providerId]: targetId
|
|
3884
|
+
};
|
|
3885
|
+
if (providerId === "fireworks") delete document.fireworksAccountId;
|
|
3886
|
+
},
|
|
3887
|
+
operations,
|
|
3888
|
+
signal,
|
|
3889
|
+
previous
|
|
3890
|
+
);
|
|
3891
|
+
return { saved, previous };
|
|
3892
|
+
}
|
|
3893
|
+
async function saveUsageSettingsDocument(path, mutate, operations, signal, expected) {
|
|
3654
3894
|
const latest = await loadUsageSettings(path, signal);
|
|
3655
3895
|
if (latest.kind === "invalid") {
|
|
3656
3896
|
throw new Error("Cannot overwrite an invalid pi-usage.json; repair it and reload first");
|
|
3657
3897
|
}
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
if (value === void 0) delete document[key];
|
|
3661
|
-
else document[key] = value;
|
|
3898
|
+
if (expected && !sameUsageSettingsDocument(latest, expected)) {
|
|
3899
|
+
throw new Error("pi-usage.json changed while saving; retry the action");
|
|
3662
3900
|
}
|
|
3901
|
+
const document = { ...latest.document };
|
|
3902
|
+
mutate(document);
|
|
3663
3903
|
const settings = normalizeUsageSettings(document);
|
|
3664
3904
|
if (!settings) throw new Error("Refusing to save invalid pi-usage settings");
|
|
3665
3905
|
const directory = dirname(path);
|
|
@@ -3686,6 +3926,32 @@ async function saveUsageSettingsPatch(path, patch, operations, signal) {
|
|
|
3686
3926
|
}
|
|
3687
3927
|
return { kind: "loaded", path, settings, document };
|
|
3688
3928
|
}
|
|
3929
|
+
async function restoreUsageSettingsState(path, published, previous, operations) {
|
|
3930
|
+
if (previous.kind === "missing") {
|
|
3931
|
+
const current = await loadUsageSettings(path);
|
|
3932
|
+
if (!sameUsageSettingsDocument(current, published)) {
|
|
3933
|
+
throw new Error("pi-usage.json changed before target selection rollback");
|
|
3934
|
+
}
|
|
3935
|
+
await rm(path);
|
|
3936
|
+
return;
|
|
3937
|
+
}
|
|
3938
|
+
if (previous.kind !== "loaded" || !previous.document) {
|
|
3939
|
+
throw new Error("Cannot restore invalid prior pi-usage.json settings");
|
|
3940
|
+
}
|
|
3941
|
+
await saveUsageSettingsDocument(
|
|
3942
|
+
path,
|
|
3943
|
+
(document) => {
|
|
3944
|
+
for (const key of Object.keys(document)) delete document[key];
|
|
3945
|
+
Object.assign(document, previous.document);
|
|
3946
|
+
},
|
|
3947
|
+
operations,
|
|
3948
|
+
void 0,
|
|
3949
|
+
published
|
|
3950
|
+
);
|
|
3951
|
+
}
|
|
3952
|
+
function sameUsageSettingsDocument(left, right) {
|
|
3953
|
+
return left.kind === right.kind && JSON.stringify(left.document) === JSON.stringify(right.document);
|
|
3954
|
+
}
|
|
3689
3955
|
async function chmodPrivate(path) {
|
|
3690
3956
|
await chmod(path, 384);
|
|
3691
3957
|
}
|
|
@@ -3698,6 +3964,19 @@ function isRecord3(value) {
|
|
|
3698
3964
|
function isNodeError(error) {
|
|
3699
3965
|
return error instanceof Error && "code" in error;
|
|
3700
3966
|
}
|
|
3967
|
+
function normalizeSelectedTargets(value) {
|
|
3968
|
+
if (value === void 0) return {};
|
|
3969
|
+
if (!isRecord3(value)) return void 0;
|
|
3970
|
+
const targets = {};
|
|
3971
|
+
for (const [providerId, targetId] of Object.entries(value)) {
|
|
3972
|
+
if (!isProviderId(providerId) || !isBoundedTargetId(targetId)) return void 0;
|
|
3973
|
+
targets[providerId] = targetId;
|
|
3974
|
+
}
|
|
3975
|
+
return targets;
|
|
3976
|
+
}
|
|
3977
|
+
function isProviderId(value) {
|
|
3978
|
+
return /^[A-Za-z0-9][A-Za-z0-9._~-]{0,127}$/u.test(value);
|
|
3979
|
+
}
|
|
3701
3980
|
|
|
3702
3981
|
// src/usage.ts
|
|
3703
3982
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -3908,8 +4187,6 @@ import {
|
|
|
3908
4187
|
SettingsList,
|
|
3909
4188
|
Text
|
|
3910
4189
|
} from "@earendil-works/pi-tui";
|
|
3911
|
-
var AUTO = "Auto";
|
|
3912
|
-
var EDIT = "Edit\u2026";
|
|
3913
4190
|
var OFF = "Off";
|
|
3914
4191
|
var ON = "On";
|
|
3915
4192
|
async function showUsageSettings(ctx, settingsRuntime, parentSignal, isCurrent, onApplied) {
|
|
@@ -3917,31 +4194,13 @@ async function showUsageSettings(ctx, settingsRuntime, parentSignal, isCurrent,
|
|
|
3917
4194
|
if (ctx.hasUI) ctx.ui.notify(`Edit settings manually: ${settingsRuntime.get().path}`, "info");
|
|
3918
4195
|
return false;
|
|
3919
4196
|
}
|
|
3920
|
-
|
|
3921
|
-
while (!parentSignal.aborted && isCurrent()) {
|
|
3922
|
-
const result = await showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, onApplied);
|
|
3923
|
-
if (!result) return changed;
|
|
3924
|
-
changed ||= result.changed;
|
|
3925
|
-
if (!result.editFireworksAccount) return changed;
|
|
3926
|
-
changed ||= await editFireworksAccount(
|
|
3927
|
-
ctx,
|
|
3928
|
-
settingsRuntime,
|
|
3929
|
-
parentSignal,
|
|
3930
|
-
isCurrent,
|
|
3931
|
-
onApplied
|
|
3932
|
-
);
|
|
3933
|
-
}
|
|
3934
|
-
return changed;
|
|
3935
|
-
}
|
|
3936
|
-
async function showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, onApplied) {
|
|
3937
|
-
return ctx.ui.custom((tui, theme, _keybindings, done) => {
|
|
4197
|
+
return await ctx.ui.custom((tui, theme, _keybindings, done) => {
|
|
3938
4198
|
const localController = new AbortController();
|
|
3939
4199
|
const signal = AbortSignal.any([parentSignal, localController.signal]);
|
|
3940
4200
|
let changed = false;
|
|
3941
4201
|
let closing = false;
|
|
3942
4202
|
let saveQueue = Promise.resolve();
|
|
3943
4203
|
const state = settingsRuntime.get();
|
|
3944
|
-
const fireworksValue = state.settings.fireworksAccountId ?? AUTO;
|
|
3945
4204
|
const items = [
|
|
3946
4205
|
{
|
|
3947
4206
|
id: "codexFastMode",
|
|
@@ -3956,13 +4215,6 @@ async function showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, o
|
|
|
3956
4215
|
description: "Show time remaining until each Codex usage limit resets.",
|
|
3957
4216
|
currentValue: state.settings.codexStatusResetCountdown ? ON : OFF,
|
|
3958
4217
|
values: [OFF, ON]
|
|
3959
|
-
},
|
|
3960
|
-
{
|
|
3961
|
-
id: "fireworksAccountId",
|
|
3962
|
-
label: "Fireworks account",
|
|
3963
|
-
description: "Select Edit to enter a visible account slug, or submit blank to clear it.",
|
|
3964
|
-
currentValue: fireworksValue,
|
|
3965
|
-
values: state.settings.fireworksAccountId ? [state.settings.fireworksAccountId, EDIT] : [AUTO, EDIT]
|
|
3966
4218
|
}
|
|
3967
4219
|
];
|
|
3968
4220
|
const container = new Container();
|
|
@@ -3972,13 +4224,13 @@ async function showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, o
|
|
|
3972
4224
|
if (closing) return;
|
|
3973
4225
|
closing = true;
|
|
3974
4226
|
localController.abort();
|
|
3975
|
-
done(
|
|
4227
|
+
done(changed);
|
|
3976
4228
|
};
|
|
3977
4229
|
const queueUpdate = (id, requested, display) => {
|
|
3978
4230
|
saveQueue = saveQueue.then(async () => {
|
|
3979
4231
|
const previous = settingsRuntime.get().settings[id];
|
|
3980
4232
|
if (settingsRuntime.get().kind === "invalid") {
|
|
3981
|
-
settingsList.updateValue(id,
|
|
4233
|
+
settingsList.updateValue(id, previous ? ON : OFF);
|
|
3982
4234
|
if (!signal.aborted && isCurrent()) {
|
|
3983
4235
|
ctx.ui.notify("Repair pi-usage.json and reload before changing settings.", "error");
|
|
3984
4236
|
tui.requestRender();
|
|
@@ -3989,7 +4241,7 @@ async function showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, o
|
|
|
3989
4241
|
await settingsRuntime.update({ [id]: requested }, signal);
|
|
3990
4242
|
} catch (error) {
|
|
3991
4243
|
if (signal.aborted || !isCurrent()) return;
|
|
3992
|
-
settingsList.updateValue(id,
|
|
4244
|
+
settingsList.updateValue(id, previous ? ON : OFF);
|
|
3993
4245
|
ctx.ui.notify(`Could not save pi-usage.json: ${errorMessage(error)}`, "error");
|
|
3994
4246
|
tui.requestRender();
|
|
3995
4247
|
return;
|
|
@@ -4009,18 +4261,7 @@ async function showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, o
|
|
|
4009
4261
|
getSettingsListTheme(),
|
|
4010
4262
|
(id, value) => {
|
|
4011
4263
|
if (closing || signal.aborted || !isCurrent()) return;
|
|
4012
|
-
|
|
4013
|
-
if (value === EDIT) {
|
|
4014
|
-
saveQueue = saveQueue.then(() => {
|
|
4015
|
-
if (closing || signal.aborted || !isCurrent()) return;
|
|
4016
|
-
closing = true;
|
|
4017
|
-
done({ changed, editFireworksAccount: true });
|
|
4018
|
-
});
|
|
4019
|
-
}
|
|
4020
|
-
return;
|
|
4021
|
-
}
|
|
4022
|
-
const settingId = id;
|
|
4023
|
-
queueUpdate(settingId, value !== OFF, value);
|
|
4264
|
+
queueUpdate(id, value !== OFF, value);
|
|
4024
4265
|
},
|
|
4025
4266
|
cancel
|
|
4026
4267
|
);
|
|
@@ -4040,43 +4281,7 @@ async function showSettingsList(ctx, settingsRuntime, parentSignal, isCurrent, o
|
|
|
4040
4281
|
parentSignal.removeEventListener("abort", cancel);
|
|
4041
4282
|
}
|
|
4042
4283
|
};
|
|
4043
|
-
});
|
|
4044
|
-
}
|
|
4045
|
-
async function editFireworksAccount(ctx, settingsRuntime, signal, isCurrent, onApplied) {
|
|
4046
|
-
while (!signal.aborted && isCurrent()) {
|
|
4047
|
-
const state = settingsRuntime.get();
|
|
4048
|
-
if (state.kind === "invalid") {
|
|
4049
|
-
ctx.ui.notify("Repair pi-usage.json and reload before changing settings.", "error");
|
|
4050
|
-
return false;
|
|
4051
|
-
}
|
|
4052
|
-
const entered = await ctx.ui.input(
|
|
4053
|
-
"Fireworks account slug \xB7 submit blank for Auto",
|
|
4054
|
-
state.settings.fireworksAccountId ?? "Example: acme",
|
|
4055
|
-
{ signal }
|
|
4056
|
-
);
|
|
4057
|
-
if (signal.aborted || !isCurrent() || entered === void 0) return false;
|
|
4058
|
-
const normalized = entered.trim();
|
|
4059
|
-
const requested = normalized || void 0;
|
|
4060
|
-
if (requested !== void 0 && !isFireworksAccountId(requested)) {
|
|
4061
|
-
ctx.ui.notify("Enter a URL-safe Fireworks account slug.", "warning");
|
|
4062
|
-
continue;
|
|
4063
|
-
}
|
|
4064
|
-
if (requested === state.settings.fireworksAccountId) return false;
|
|
4065
|
-
try {
|
|
4066
|
-
await settingsRuntime.update({ fireworksAccountId: requested }, signal);
|
|
4067
|
-
} catch (error) {
|
|
4068
|
-
if (signal.aborted || !isCurrent()) return false;
|
|
4069
|
-
ctx.ui.notify(`Could not save pi-usage.json: ${errorMessage(error)}`, "error");
|
|
4070
|
-
return false;
|
|
4071
|
-
}
|
|
4072
|
-
onApplied("fireworksAccountId");
|
|
4073
|
-
return true;
|
|
4074
|
-
}
|
|
4075
|
-
return false;
|
|
4076
|
-
}
|
|
4077
|
-
function displaySetting(id, value) {
|
|
4078
|
-
if (id === "fireworksAccountId") return typeof value === "string" ? value : AUTO;
|
|
4079
|
-
return value ? ON : OFF;
|
|
4284
|
+
}) ?? false;
|
|
4080
4285
|
}
|
|
4081
4286
|
|
|
4082
4287
|
// src/usage.ts
|
|
@@ -4093,6 +4298,9 @@ var VIEW_ALL = "View all configured providers\u2026";
|
|
|
4093
4298
|
var CLOSE = "Close";
|
|
4094
4299
|
var SETTINGS = "Settings";
|
|
4095
4300
|
var REDEEM_CODEX_RESET = "Redeem usage limit reset\u2026";
|
|
4301
|
+
var UsageTargetSelectionChangedError = class extends Error {
|
|
4302
|
+
name = "UsageTargetSelectionChangedError";
|
|
4303
|
+
};
|
|
4096
4304
|
function usageExtension(pi, dependencies = {}) {
|
|
4097
4305
|
const credentialReader = dependencies.credentialReader;
|
|
4098
4306
|
const credentialCandidates = createOAuthCredentialCandidateReader(pi, credentialReader);
|
|
@@ -4164,7 +4372,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4164
4372
|
if (outcome.state.status !== "ready") {
|
|
4165
4373
|
if (safeSetStatus(
|
|
4166
4374
|
ctx,
|
|
4167
|
-
outcome.state.status === "auth-unavailable" ? "auth unavailable" : "usage error"
|
|
4375
|
+
outcome.state.status === "auth-unavailable" ? "auth unavailable" : outcome.state.status === "selection-required" ? "selection required" : "usage error"
|
|
4168
4376
|
)) {
|
|
4169
4377
|
if (shouldSchedule && sessionActive) scheduleStatusRefresh(ctx, model);
|
|
4170
4378
|
}
|
|
@@ -4217,8 +4425,8 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4217
4425
|
const expectedSessionGeneration = sessionGeneration;
|
|
4218
4426
|
const expectedSessionId = ctx.sessionManager.getSessionId();
|
|
4219
4427
|
const expectedModelIdentity = modelIdentity(ctx.model);
|
|
4220
|
-
const
|
|
4221
|
-
const
|
|
4428
|
+
const expectedTargetId = adapter.targets ? settingsRuntime.get().settings.selectedTargets[adapter.id] : void 0;
|
|
4429
|
+
const providerName = providerDisplayName(ctx, adapter.id);
|
|
4222
4430
|
let auth;
|
|
4223
4431
|
try {
|
|
4224
4432
|
auth = await awaitWithDeadline(
|
|
@@ -4235,17 +4443,16 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4235
4443
|
return {
|
|
4236
4444
|
state: {
|
|
4237
4445
|
providerId: adapter.id,
|
|
4238
|
-
providerName
|
|
4446
|
+
providerName,
|
|
4239
4447
|
displayState,
|
|
4240
4448
|
status: isTimeoutError(error) ? "query-failed" : "auth-unavailable",
|
|
4241
4449
|
message: errorMessage(error)
|
|
4242
4450
|
}
|
|
4243
4451
|
};
|
|
4244
4452
|
}
|
|
4245
|
-
const requiresRequestBoundaryGuard = [
|
|
4453
|
+
const requiresRequestBoundaryGuard = adapter.targets !== void 0 || [
|
|
4246
4454
|
"baseten",
|
|
4247
4455
|
"deepseek",
|
|
4248
|
-
"fireworks",
|
|
4249
4456
|
"minimax",
|
|
4250
4457
|
"minimax-cn",
|
|
4251
4458
|
"moonshotai",
|
|
@@ -4255,7 +4462,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4255
4462
|
"zai",
|
|
4256
4463
|
"zai-coding-cn"
|
|
4257
4464
|
].includes(adapter.id);
|
|
4258
|
-
const requestContextChanged = () => expectedSessionGeneration !== sessionGeneration || ctx.sessionManager.getSessionId() !== expectedSessionId || modelIdentity(ctx.model) !== expectedModelIdentity || adapter.
|
|
4465
|
+
const requestContextChanged = () => expectedSessionGeneration !== sessionGeneration || ctx.sessionManager.getSessionId() !== expectedSessionId || modelIdentity(ctx.model) !== expectedModelIdentity || adapter.targets !== void 0 && settingsRuntime.get().settings.selectedTargets[adapter.id] !== expectedTargetId;
|
|
4259
4466
|
if (requiresRequestBoundaryGuard && requestContextChanged()) throw abortError();
|
|
4260
4467
|
if (!auth) {
|
|
4261
4468
|
if (displayState === "current") {
|
|
@@ -4264,98 +4471,145 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4264
4471
|
return {
|
|
4265
4472
|
state: {
|
|
4266
4473
|
providerId: adapter.id,
|
|
4267
|
-
providerName
|
|
4474
|
+
providerName,
|
|
4268
4475
|
displayState,
|
|
4269
4476
|
status: "auth-unavailable",
|
|
4270
|
-
message: `No runtime credential is configured for ${
|
|
4477
|
+
message: `No runtime credential is configured for ${providerName}.`
|
|
4271
4478
|
},
|
|
4272
4479
|
authState: "unavailable"
|
|
4273
4480
|
};
|
|
4274
4481
|
}
|
|
4275
|
-
const queryFingerprint = adapter.id === "fireworks" ? `${auth.fingerprint}:account:${expectedFireworksAccountId ?? "auto"}` : auth.fingerprint;
|
|
4276
|
-
if (displayState === "current") {
|
|
4277
|
-
transitionCurrentIdentity(`${adapter.id}:${queryFingerprint}`, adapter.id);
|
|
4278
|
-
}
|
|
4279
|
-
const cached = !force ? cache.get(adapter.id, queryFingerprint) : void 0;
|
|
4280
|
-
if (cached) {
|
|
4281
|
-
return {
|
|
4282
|
-
state: {
|
|
4283
|
-
providerId: adapter.id,
|
|
4284
|
-
providerName: adapter.displayName,
|
|
4285
|
-
displayState,
|
|
4286
|
-
status: "ready",
|
|
4287
|
-
report: cached
|
|
4288
|
-
},
|
|
4289
|
-
fingerprint: auth.fingerprint
|
|
4290
|
-
};
|
|
4291
|
-
}
|
|
4292
|
-
const failureKey = `${adapter.id}:${queryFingerprint}`;
|
|
4293
|
-
const previousFailure = failureBackoff.get(failureKey);
|
|
4294
|
-
if (!force && previousFailure && previousFailure.until > Date.now()) {
|
|
4295
|
-
return {
|
|
4296
|
-
state: {
|
|
4297
|
-
providerId: adapter.id,
|
|
4298
|
-
providerName: adapter.displayName,
|
|
4299
|
-
displayState,
|
|
4300
|
-
status: "query-failed",
|
|
4301
|
-
message: previousFailure.message
|
|
4302
|
-
},
|
|
4303
|
-
fingerprint: auth.fingerprint
|
|
4304
|
-
};
|
|
4305
|
-
}
|
|
4306
|
-
failureBackoff.delete(failureKey);
|
|
4307
|
-
querySequence += 1;
|
|
4308
|
-
const queryId = querySequence;
|
|
4309
|
-
setBoundedMap(latestQueries, failureKey, queryId, MAX_ACCOUNT_STATES);
|
|
4310
4482
|
let retryableAuthChanged = false;
|
|
4483
|
+
const guard = async () => {
|
|
4484
|
+
if (signal.aborted || requestContextChanged()) throw abortError();
|
|
4485
|
+
if (!requiresRequestBoundaryGuard) return;
|
|
4486
|
+
const revalidated = await awaitWithDeadline(
|
|
4487
|
+
resolveUsageAuth(ctx, adapter, void 0, credentialReader, credentialCandidates),
|
|
4488
|
+
signal,
|
|
4489
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
4490
|
+
`revalidating ${providerName} runtime auth`
|
|
4491
|
+
);
|
|
4492
|
+
if (signal.aborted || requestContextChanged()) throw abortError();
|
|
4493
|
+
if (revalidated?.fingerprint !== auth.fingerprint) {
|
|
4494
|
+
if (["deepseek", "minimax", "minimax-cn"].includes(adapter.id)) {
|
|
4495
|
+
retryableAuthChanged = true;
|
|
4496
|
+
throw new Error(`${providerName} runtime credential changed during the usage query.`);
|
|
4497
|
+
}
|
|
4498
|
+
throw abortError();
|
|
4499
|
+
}
|
|
4500
|
+
};
|
|
4501
|
+
let queryFingerprint = adapter.targets ? `${auth.fingerprint}:target:${expectedTargetId ?? "unresolved"}` : auth.fingerprint;
|
|
4502
|
+
let failureKey = `${adapter.id}:${queryFingerprint}`;
|
|
4503
|
+
let queryId;
|
|
4311
4504
|
try {
|
|
4312
|
-
const
|
|
4313
|
-
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
|
|
4323
|
-
|
|
4324
|
-
|
|
4325
|
-
|
|
4326
|
-
|
|
4327
|
-
|
|
4328
|
-
|
|
4329
|
-
|
|
4505
|
+
const previousDiscoveryFailure = failureBackoff.get(failureKey);
|
|
4506
|
+
if (!force && previousDiscoveryFailure && previousDiscoveryFailure.until > Date.now()) {
|
|
4507
|
+
return {
|
|
4508
|
+
state: {
|
|
4509
|
+
providerId: adapter.id,
|
|
4510
|
+
providerName,
|
|
4511
|
+
displayState,
|
|
4512
|
+
status: "query-failed",
|
|
4513
|
+
message: previousDiscoveryFailure.message
|
|
4514
|
+
},
|
|
4515
|
+
fingerprint: auth.fingerprint,
|
|
4516
|
+
rememberedTargetId: expectedTargetId
|
|
4517
|
+
};
|
|
4518
|
+
}
|
|
4519
|
+
const target = await resolveUsageTarget(
|
|
4520
|
+
adapter,
|
|
4521
|
+
auth,
|
|
4522
|
+
expectedTargetId,
|
|
4523
|
+
signal,
|
|
4524
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
4525
|
+
guard
|
|
4526
|
+
);
|
|
4527
|
+
if (target.kind === "selection-required") {
|
|
4528
|
+
if (displayState === "current") {
|
|
4529
|
+
transitionCurrentIdentity(`${adapter.id}:${queryFingerprint}`, adapter.id);
|
|
4330
4530
|
}
|
|
4331
|
-
|
|
4531
|
+
return {
|
|
4532
|
+
state: {
|
|
4533
|
+
providerId: adapter.id,
|
|
4534
|
+
providerName,
|
|
4535
|
+
displayState,
|
|
4536
|
+
status: "selection-required",
|
|
4537
|
+
singularLabel: adapter.targets?.singularLabel ?? "target",
|
|
4538
|
+
pluralLabel: adapter.targets?.pluralLabel ?? "targets",
|
|
4539
|
+
choices: target.choices
|
|
4540
|
+
},
|
|
4541
|
+
fingerprint: auth.fingerprint,
|
|
4542
|
+
rememberedTargetId: expectedTargetId
|
|
4543
|
+
};
|
|
4544
|
+
}
|
|
4545
|
+
queryFingerprint = adapter.targets ? `${auth.fingerprint}:target:${target.targetId ?? "none"}` : auth.fingerprint;
|
|
4546
|
+
failureKey = `${adapter.id}:${queryFingerprint}`;
|
|
4547
|
+
if (displayState === "current") {
|
|
4548
|
+
transitionCurrentIdentity(`${adapter.id}:${queryFingerprint}`, adapter.id);
|
|
4549
|
+
}
|
|
4550
|
+
const cached = !force ? cache.get(adapter.id, queryFingerprint) : void 0;
|
|
4551
|
+
if (cached) {
|
|
4552
|
+
return {
|
|
4553
|
+
state: {
|
|
4554
|
+
providerId: adapter.id,
|
|
4555
|
+
providerName,
|
|
4556
|
+
displayState,
|
|
4557
|
+
status: "ready",
|
|
4558
|
+
report: cached
|
|
4559
|
+
},
|
|
4560
|
+
fingerprint: auth.fingerprint,
|
|
4561
|
+
rememberedTargetId: expectedTargetId
|
|
4562
|
+
};
|
|
4563
|
+
}
|
|
4564
|
+
const previousFailure = failureBackoff.get(failureKey);
|
|
4565
|
+
if (!force && previousFailure && previousFailure.until > Date.now()) {
|
|
4566
|
+
return {
|
|
4567
|
+
state: {
|
|
4568
|
+
providerId: adapter.id,
|
|
4569
|
+
providerName,
|
|
4570
|
+
displayState,
|
|
4571
|
+
status: "query-failed",
|
|
4572
|
+
message: previousFailure.message
|
|
4573
|
+
},
|
|
4574
|
+
fingerprint: auth.fingerprint,
|
|
4575
|
+
rememberedTargetId: expectedTargetId
|
|
4576
|
+
};
|
|
4577
|
+
}
|
|
4578
|
+
failureBackoff.delete(failureKey);
|
|
4579
|
+
querySequence += 1;
|
|
4580
|
+
queryId = querySequence;
|
|
4581
|
+
setBoundedMap(latestQueries, failureKey, queryId, MAX_ACCOUNT_STATES);
|
|
4332
4582
|
const report2 = await queryProviderUsage(
|
|
4333
4583
|
adapter,
|
|
4334
4584
|
auth,
|
|
4335
4585
|
signal,
|
|
4336
|
-
|
|
4337
|
-
guard,
|
|
4338
|
-
|
|
4586
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
4587
|
+
requiresRequestBoundaryGuard ? guard : void 0,
|
|
4588
|
+
target.targetId
|
|
4339
4589
|
);
|
|
4340
|
-
if (
|
|
4590
|
+
if (requiresRequestBoundaryGuard) await guard();
|
|
4591
|
+
const effectiveReport = { ...report2, providerName };
|
|
4341
4592
|
if (latestQueries.get(failureKey) === queryId) {
|
|
4342
|
-
cache.set(adapter.id, queryFingerprint,
|
|
4593
|
+
cache.set(adapter.id, queryFingerprint, effectiveReport);
|
|
4343
4594
|
failureBackoff.delete(failureKey);
|
|
4344
4595
|
}
|
|
4345
4596
|
return {
|
|
4346
4597
|
state: {
|
|
4347
4598
|
providerId: adapter.id,
|
|
4348
|
-
providerName
|
|
4599
|
+
providerName,
|
|
4349
4600
|
displayState,
|
|
4350
4601
|
status: "ready",
|
|
4351
|
-
report:
|
|
4602
|
+
report: effectiveReport
|
|
4352
4603
|
},
|
|
4353
|
-
fingerprint: auth.fingerprint
|
|
4604
|
+
fingerprint: auth.fingerprint,
|
|
4605
|
+
rememberedTargetId: expectedTargetId
|
|
4354
4606
|
};
|
|
4355
4607
|
} catch (error) {
|
|
4356
4608
|
if (isStaleExtensionContextError(error) || isAbortError3(error)) throw error;
|
|
4357
4609
|
if (retryableAuthChanged && authRetry === 0 && !signal.aborted && !requestContextChanged() && Date.now() < deadlineAt) {
|
|
4358
|
-
if (latestQueries.get(failureKey) === queryId)
|
|
4610
|
+
if (queryId !== void 0 && latestQueries.get(failureKey) === queryId) {
|
|
4611
|
+
latestQueries.delete(failureKey);
|
|
4612
|
+
}
|
|
4359
4613
|
return queryAdapterState(
|
|
4360
4614
|
ctx,
|
|
4361
4615
|
adapter,
|
|
@@ -4371,7 +4625,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4371
4625
|
for (const [key, failure] of failureBackoff) {
|
|
4372
4626
|
if (failure.until <= now) failureBackoff.delete(key);
|
|
4373
4627
|
}
|
|
4374
|
-
if (latestQueries.get(failureKey) === queryId) {
|
|
4628
|
+
if (queryId === void 0 || latestQueries.get(failureKey) === queryId) {
|
|
4375
4629
|
setBoundedMap(
|
|
4376
4630
|
failureBackoff,
|
|
4377
4631
|
failureKey,
|
|
@@ -4382,15 +4636,52 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4382
4636
|
return {
|
|
4383
4637
|
state: {
|
|
4384
4638
|
providerId: adapter.id,
|
|
4385
|
-
providerName
|
|
4639
|
+
providerName,
|
|
4386
4640
|
displayState,
|
|
4387
4641
|
status: "query-failed",
|
|
4388
4642
|
message
|
|
4389
4643
|
},
|
|
4390
|
-
fingerprint: auth.fingerprint
|
|
4644
|
+
fingerprint: auth.fingerprint,
|
|
4645
|
+
rememberedTargetId: expectedTargetId
|
|
4391
4646
|
};
|
|
4392
4647
|
}
|
|
4393
4648
|
};
|
|
4649
|
+
const loadTargetChoices = async (ctx, adapter, signal) => {
|
|
4650
|
+
if (!adapter.targets) throw new Error("Provider does not support usage targets.");
|
|
4651
|
+
const expectedSessionGeneration = sessionGeneration;
|
|
4652
|
+
const expectedSessionId = ctx.sessionManager.getSessionId();
|
|
4653
|
+
const expectedModel = modelIdentity(ctx.model);
|
|
4654
|
+
const expectedTargetId = settingsRuntime.get().settings.selectedTargets[adapter.id];
|
|
4655
|
+
const deadlineAt = Date.now() + DEFAULT_TIMEOUT_MS;
|
|
4656
|
+
const changed = () => expectedSessionGeneration !== sessionGeneration || ctx.sessionManager.getSessionId() !== expectedSessionId || modelIdentity(ctx.model) !== expectedModel || settingsRuntime.get().settings.selectedTargets[adapter.id] !== expectedTargetId;
|
|
4657
|
+
const auth = await awaitWithDeadline(
|
|
4658
|
+
resolveUsageAuth(ctx, adapter, void 0, credentialReader, credentialCandidates),
|
|
4659
|
+
signal,
|
|
4660
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
4661
|
+
`resolving ${providerDisplayName(ctx, adapter.id)} runtime auth`
|
|
4662
|
+
);
|
|
4663
|
+
if (!auth || signal.aborted || changed()) throw abortError();
|
|
4664
|
+
const guard = async () => {
|
|
4665
|
+
if (signal.aborted || changed()) throw abortError();
|
|
4666
|
+
const revalidated = await awaitWithDeadline(
|
|
4667
|
+
resolveUsageAuth(ctx, adapter, void 0, credentialReader, credentialCandidates),
|
|
4668
|
+
signal,
|
|
4669
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
4670
|
+
`revalidating ${providerDisplayName(ctx, adapter.id)} runtime auth`
|
|
4671
|
+
);
|
|
4672
|
+
if (signal.aborted || changed() || revalidated?.fingerprint !== auth.fingerprint) {
|
|
4673
|
+
throw abortError();
|
|
4674
|
+
}
|
|
4675
|
+
};
|
|
4676
|
+
const choices = await listUsageTargets(
|
|
4677
|
+
adapter,
|
|
4678
|
+
auth,
|
|
4679
|
+
signal,
|
|
4680
|
+
Math.max(1, deadlineAt - Date.now()),
|
|
4681
|
+
guard
|
|
4682
|
+
);
|
|
4683
|
+
return { choices, fingerprint: auth.fingerprint };
|
|
4684
|
+
};
|
|
4394
4685
|
const queryCurrentState = async (ctx, model, force, signal) => {
|
|
4395
4686
|
const adapter = adapterForProvider(model?.provider);
|
|
4396
4687
|
if (!adapter) {
|
|
@@ -4474,6 +4765,8 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4474
4765
|
return false;
|
|
4475
4766
|
}
|
|
4476
4767
|
const adapter = adapterForProvider(model?.provider);
|
|
4768
|
+
const selectionStillCurrent = !adapter?.targets || settingsRuntime.get().settings.selectedTargets[adapter.id] === outcome.rememberedTargetId;
|
|
4769
|
+
if (!selectionStillCurrent) return false;
|
|
4477
4770
|
if (outcome.authState === "unavailable") {
|
|
4478
4771
|
if (!adapter) return false;
|
|
4479
4772
|
try {
|
|
@@ -4483,7 +4776,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4483
4776
|
DEFAULT_TIMEOUT_MS,
|
|
4484
4777
|
`revalidating ${adapter.displayName} runtime auth`
|
|
4485
4778
|
);
|
|
4486
|
-
return generation === statusGeneration && modelIdentity(ctx.model) === modelIdentity(model) && auth === void 0;
|
|
4779
|
+
return generation === statusGeneration && modelIdentity(ctx.model) === modelIdentity(model) && (!adapter.targets || settingsRuntime.get().settings.selectedTargets[adapter.id] === outcome.rememberedTargetId) && auth === void 0;
|
|
4487
4780
|
} catch (error) {
|
|
4488
4781
|
if (isAbortError3(error) || isStaleExtensionContextError(error)) throw error;
|
|
4489
4782
|
return false;
|
|
@@ -4498,7 +4791,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4498
4791
|
DEFAULT_TIMEOUT_MS,
|
|
4499
4792
|
`revalidating ${adapter.displayName} runtime auth`
|
|
4500
4793
|
);
|
|
4501
|
-
return generation === statusGeneration && modelIdentity(ctx.model) === modelIdentity(model) && auth?.fingerprint === outcome.fingerprint;
|
|
4794
|
+
return generation === statusGeneration && modelIdentity(ctx.model) === modelIdentity(model) && (!adapter.targets || settingsRuntime.get().settings.selectedTargets[adapter.id] === outcome.rememberedTargetId) && auth?.fingerprint === outcome.fingerprint;
|
|
4502
4795
|
} catch (error) {
|
|
4503
4796
|
if (isAbortError3(error) || isStaleExtensionContextError(error)) throw error;
|
|
4504
4797
|
return false;
|
|
@@ -4554,6 +4847,88 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4554
4847
|
let redemptionId;
|
|
4555
4848
|
let resetOutcome;
|
|
4556
4849
|
let resetFailure;
|
|
4850
|
+
const actionableTargetState = () => {
|
|
4851
|
+
if (visibleStates.length !== 1) return void 0;
|
|
4852
|
+
const state = visibleStates[0];
|
|
4853
|
+
return state && (state.status === "ready" || state.status === "selection-required") && adapterForProvider(state.providerId)?.targets ? state : void 0;
|
|
4854
|
+
};
|
|
4855
|
+
const promptForTarget = async (state, stateFingerprint) => {
|
|
4856
|
+
const adapter = adapterForProvider(state.providerId);
|
|
4857
|
+
if (!adapter?.targets) return false;
|
|
4858
|
+
const expectedRememberedTargetId = settingsRuntime.get().settings.selectedTargets[adapter.id];
|
|
4859
|
+
const snapshot = state.status === "selection-required" && stateFingerprint ? { choices: state.choices, fingerprint: stateFingerprint } : await runMenuOperation(
|
|
4860
|
+
ctx,
|
|
4861
|
+
`Loading ${adapter.targets.pluralLabel}\u2026`,
|
|
4862
|
+
controller.signal,
|
|
4863
|
+
(signal) => loadTargetChoices(ctx, adapter, signal)
|
|
4864
|
+
);
|
|
4865
|
+
if (!snapshot || controller.signal.aborted || statusGeneration !== menuGeneration) {
|
|
4866
|
+
return false;
|
|
4867
|
+
}
|
|
4868
|
+
const selectOptions = createUsageTargetSelectOptions(snapshot.choices);
|
|
4869
|
+
const selected = await ctx.ui.select(
|
|
4870
|
+
`Select ${adapter.targets.singularLabel} for ${providerDisplayName(ctx, adapter.id)}`,
|
|
4871
|
+
[...selectOptions.options],
|
|
4872
|
+
{ signal: controller.signal }
|
|
4873
|
+
);
|
|
4874
|
+
if (selected === void 0 || controller.signal.aborted || statusGeneration !== menuGeneration || settingsRuntime.get().settings.selectedTargets[adapter.id] !== expectedRememberedTargetId) {
|
|
4875
|
+
return false;
|
|
4876
|
+
}
|
|
4877
|
+
const targetId = selectOptions.targetIdFor(selected);
|
|
4878
|
+
if (!targetId) return false;
|
|
4879
|
+
const revalidated = await runMenuOperation(
|
|
4880
|
+
ctx,
|
|
4881
|
+
`Revalidating ${adapter.targets.singularLabel}\u2026`,
|
|
4882
|
+
controller.signal,
|
|
4883
|
+
(signal) => loadTargetChoices(ctx, adapter, signal)
|
|
4884
|
+
);
|
|
4885
|
+
if (!revalidated || controller.signal.aborted || statusGeneration !== menuGeneration || settingsRuntime.get().settings.selectedTargets[adapter.id] !== expectedRememberedTargetId) {
|
|
4886
|
+
return false;
|
|
4887
|
+
}
|
|
4888
|
+
if (revalidated.fingerprint !== snapshot.fingerprint || !revalidated.choices.some((choice) => choice.id === targetId)) {
|
|
4889
|
+
ctx.ui.notify(
|
|
4890
|
+
`${providerDisplayName(ctx, adapter.id)} ${adapter.targets.pluralLabel} changed; choose again.`,
|
|
4891
|
+
"warning"
|
|
4892
|
+
);
|
|
4893
|
+
return false;
|
|
4894
|
+
}
|
|
4895
|
+
let saved;
|
|
4896
|
+
try {
|
|
4897
|
+
saved = await runMenuOperation(
|
|
4898
|
+
ctx,
|
|
4899
|
+
`Saving ${adapter.targets.singularLabel}\u2026`,
|
|
4900
|
+
controller.signal,
|
|
4901
|
+
(signal) => settingsRuntime.updateSelectedTarget(adapter.id, targetId, signal, async () => {
|
|
4902
|
+
let published;
|
|
4903
|
+
try {
|
|
4904
|
+
published = await loadTargetChoices(ctx, adapter, signal);
|
|
4905
|
+
} catch (error) {
|
|
4906
|
+
if (signal.aborted || controller.signal.aborted || statusGeneration !== menuGeneration || isStaleExtensionContextError(error)) {
|
|
4907
|
+
throw error;
|
|
4908
|
+
}
|
|
4909
|
+
throw new UsageTargetSelectionChangedError();
|
|
4910
|
+
}
|
|
4911
|
+
if (published.fingerprint !== snapshot.fingerprint || !published.choices.some((choice) => choice.id === targetId)) {
|
|
4912
|
+
throw new UsageTargetSelectionChangedError();
|
|
4913
|
+
}
|
|
4914
|
+
})
|
|
4915
|
+
);
|
|
4916
|
+
} catch (error) {
|
|
4917
|
+
if (error instanceof UsageTargetSelectionChangedError) {
|
|
4918
|
+
ctx.ui.notify(
|
|
4919
|
+
`${providerDisplayName(ctx, adapter.id)} ${adapter.targets.pluralLabel} changed; choose again.`,
|
|
4920
|
+
"warning"
|
|
4921
|
+
);
|
|
4922
|
+
return false;
|
|
4923
|
+
}
|
|
4924
|
+
throw error;
|
|
4925
|
+
}
|
|
4926
|
+
if (!saved || controller.signal.aborted || statusGeneration !== menuGeneration) {
|
|
4927
|
+
return false;
|
|
4928
|
+
}
|
|
4929
|
+
invalidateProviderState(adapter.id);
|
|
4930
|
+
return true;
|
|
4931
|
+
};
|
|
4557
4932
|
const { defineMenu, runMenu } = await import("@narumitw/pi-tui-kit");
|
|
4558
4933
|
if (controller.signal.aborted || statusGeneration !== menuGeneration) return;
|
|
4559
4934
|
const menu = defineMenu({
|
|
@@ -4561,6 +4936,8 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4561
4936
|
screens: {
|
|
4562
4937
|
main: () => {
|
|
4563
4938
|
const fastAvailability = fastRuntime.availability(ctx.model);
|
|
4939
|
+
const targetState = actionableTargetState();
|
|
4940
|
+
const targetAdapter = adapterForProvider(targetState?.providerId);
|
|
4564
4941
|
const fastLines = fastAvailability.kind === "available" ? [`Fast mode: ${fastAvailability.enabled ? "On" : "Off"}`, FAST_USAGE_WARNING] : fastAvailability.kind === "unavailable" ? [`Fast mode: Unavailable \xB7 ${fastAvailability.reason}`] : [];
|
|
4565
4942
|
return {
|
|
4566
4943
|
kind: "actions",
|
|
@@ -4569,6 +4946,13 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4569
4946
|
items: [
|
|
4570
4947
|
{ id: "refresh", label: REFRESH_CURRENT, action: "refresh" },
|
|
4571
4948
|
{ id: "settings", label: SETTINGS, action: "settings" },
|
|
4949
|
+
...targetState && targetAdapter?.targets ? [
|
|
4950
|
+
{
|
|
4951
|
+
id: "target",
|
|
4952
|
+
label: `${targetState.status === "selection-required" ? "Select" : "Change"} ${targetAdapter.targets.singularLabel}\u2026`,
|
|
4953
|
+
action: "target"
|
|
4954
|
+
}
|
|
4955
|
+
] : [],
|
|
4572
4956
|
...fastAvailability.kind === "available" ? [
|
|
4573
4957
|
{
|
|
4574
4958
|
id: "toggle-fast",
|
|
@@ -4599,7 +4983,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4599
4983
|
title: "Select a configured provider",
|
|
4600
4984
|
items: configuredAdapters(ctx).filter((adapter) => adapter.id !== ctx.model?.provider).map((adapter) => ({
|
|
4601
4985
|
id: adapter.id,
|
|
4602
|
-
label: adapter.
|
|
4986
|
+
label: providerDisplayName(ctx, adapter.id),
|
|
4603
4987
|
action: "provider"
|
|
4604
4988
|
})),
|
|
4605
4989
|
hint: "back"
|
|
@@ -4661,6 +5045,58 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4661
5045
|
})
|
|
4662
5046
|
},
|
|
4663
5047
|
actions: {
|
|
5048
|
+
target: async () => {
|
|
5049
|
+
const targetState = actionableTargetState();
|
|
5050
|
+
if (!targetState) return { kind: "rejected" };
|
|
5051
|
+
try {
|
|
5052
|
+
const stateFingerprint = targetState === current.state ? current.fingerprint : void 0;
|
|
5053
|
+
if (!await promptForTarget(targetState, stateFingerprint)) {
|
|
5054
|
+
return { kind: "stay" };
|
|
5055
|
+
}
|
|
5056
|
+
const adapter = adapterForProvider(targetState.providerId);
|
|
5057
|
+
if (!adapter) return { kind: "rejected" };
|
|
5058
|
+
if (targetState.providerId === ctx.model?.provider) {
|
|
5059
|
+
const refreshed = await queryStableCurrent(
|
|
5060
|
+
ctx,
|
|
5061
|
+
true,
|
|
5062
|
+
controller,
|
|
5063
|
+
`Checking ${providerDisplayName(ctx, adapter.id)} usage\u2026`
|
|
5064
|
+
);
|
|
5065
|
+
if (!refreshed) return { kind: "stay" };
|
|
5066
|
+
stableCurrent = refreshed;
|
|
5067
|
+
current = refreshed.outcome;
|
|
5068
|
+
visibleStates = [current.state];
|
|
5069
|
+
publishStableCurrent(ctx, refreshed);
|
|
5070
|
+
return { kind: "stay" };
|
|
5071
|
+
}
|
|
5072
|
+
const outcome = await runMenuOperation(
|
|
5073
|
+
ctx,
|
|
5074
|
+
`Checking ${providerDisplayName(ctx, adapter.id)} usage\u2026`,
|
|
5075
|
+
controller.signal,
|
|
5076
|
+
(signal) => queryAdapterState(ctx, adapter, "configured", true, signal)
|
|
5077
|
+
);
|
|
5078
|
+
if (!outcome) return { kind: "stay" };
|
|
5079
|
+
const revalidated = await queryStableCurrent(
|
|
5080
|
+
ctx,
|
|
5081
|
+
false,
|
|
5082
|
+
controller,
|
|
5083
|
+
"Revalidating current usage\u2026"
|
|
5084
|
+
);
|
|
5085
|
+
if (!revalidated) return { kind: "stay" };
|
|
5086
|
+
stableCurrent = revalidated;
|
|
5087
|
+
current = revalidated.outcome;
|
|
5088
|
+
visibleStates = [
|
|
5089
|
+
outcome.state.providerId === current.state.providerId ? current.state : { ...outcome.state, displayState: "configured" }
|
|
5090
|
+
];
|
|
5091
|
+
return { kind: "stay" };
|
|
5092
|
+
} catch (error) {
|
|
5093
|
+
if (isAbortError3(error) || isStaleExtensionContextError(error)) {
|
|
5094
|
+
return { kind: "stay" };
|
|
5095
|
+
}
|
|
5096
|
+
ctx.ui.notify(`Could not select target: ${errorMessage(error)}`, "error");
|
|
5097
|
+
return { kind: "stay" };
|
|
5098
|
+
}
|
|
5099
|
+
},
|
|
4664
5100
|
settings: async () => {
|
|
4665
5101
|
await showUsageSettings(
|
|
4666
5102
|
ctx,
|
|
@@ -4869,13 +5305,25 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4869
5305
|
(candidate) => candidate.id === itemId && candidate.id !== ctx.model?.provider
|
|
4870
5306
|
);
|
|
4871
5307
|
if (!adapter) return { kind: "back" };
|
|
4872
|
-
|
|
5308
|
+
let outcome = await runMenuOperation(
|
|
4873
5309
|
ctx,
|
|
4874
|
-
`Checking ${adapter.
|
|
5310
|
+
`Checking ${providerDisplayName(ctx, adapter.id)} usage\u2026`,
|
|
4875
5311
|
controller.signal,
|
|
4876
5312
|
(signal) => queryAdapterState(ctx, adapter, "configured", false, signal)
|
|
4877
5313
|
);
|
|
4878
5314
|
if (!outcome) return { kind: "back" };
|
|
5315
|
+
if (outcome.state.status === "selection-required") {
|
|
5316
|
+
if (!await promptForTarget(outcome.state, outcome.fingerprint)) {
|
|
5317
|
+
return { kind: "back" };
|
|
5318
|
+
}
|
|
5319
|
+
outcome = await runMenuOperation(
|
|
5320
|
+
ctx,
|
|
5321
|
+
`Checking ${providerDisplayName(ctx, adapter.id)} usage\u2026`,
|
|
5322
|
+
controller.signal,
|
|
5323
|
+
(signal) => queryAdapterState(ctx, adapter, "configured", true, signal)
|
|
5324
|
+
);
|
|
5325
|
+
if (!outcome) return { kind: "back" };
|
|
5326
|
+
}
|
|
4879
5327
|
const revalidated = await queryStableCurrent(
|
|
4880
5328
|
ctx,
|
|
4881
5329
|
false,
|
|
@@ -4918,7 +5366,7 @@ function usageExtension(pi, dependencies = {}) {
|
|
|
4918
5366
|
const adapter = adapters[index];
|
|
4919
5367
|
return {
|
|
4920
5368
|
providerId: adapter.id,
|
|
4921
|
-
providerName: adapter.
|
|
5369
|
+
providerName: providerDisplayName(ctx, adapter.id),
|
|
4922
5370
|
displayState: "configured",
|
|
4923
5371
|
status: "query-failed",
|
|
4924
5372
|
message: errorMessage(result.reason)
|
|
@@ -5032,15 +5480,19 @@ export {
|
|
|
5032
5480
|
codexFastStatusLabel,
|
|
5033
5481
|
consumeCodexResetCredit,
|
|
5034
5482
|
correctCodexFastMessageCost,
|
|
5483
|
+
createFireworksAdapter,
|
|
5035
5484
|
createUsageSettingsRuntime,
|
|
5485
|
+
createUsageTargetSelectOptions,
|
|
5036
5486
|
usageExtension as default,
|
|
5037
5487
|
errorMessage,
|
|
5038
5488
|
fingerprintResolvedAuth,
|
|
5039
5489
|
formatProviderStates,
|
|
5040
5490
|
formatUsageReport,
|
|
5041
5491
|
formatUsageStatusline,
|
|
5492
|
+
isBoundedTargetId,
|
|
5042
5493
|
isStaleExtensionContextError,
|
|
5043
5494
|
listCodexResetCredits,
|
|
5495
|
+
listUsageTargets,
|
|
5044
5496
|
loadUsageSettings,
|
|
5045
5497
|
miniMaxUsageKind,
|
|
5046
5498
|
normalizeBasetenBillingUsagePayload,
|
|
@@ -5056,6 +5508,7 @@ export {
|
|
|
5056
5508
|
normalizeOpenCodeZenPayload,
|
|
5057
5509
|
normalizeOpenRouterKeyPayload,
|
|
5058
5510
|
normalizeUsageSettings,
|
|
5511
|
+
normalizeUsageTargets,
|
|
5059
5512
|
normalizeVercelAIGatewayCreditsPayload,
|
|
5060
5513
|
normalizeXaiBillingPayload,
|
|
5061
5514
|
normalizeZaiQuotaPayload,
|
|
@@ -5065,6 +5518,7 @@ export {
|
|
|
5065
5518
|
redactUsageError,
|
|
5066
5519
|
resolveCodexResetAuth,
|
|
5067
5520
|
resolveUsageAuth,
|
|
5521
|
+
resolveUsageTarget,
|
|
5068
5522
|
rewriteCodexFastPayload,
|
|
5069
5523
|
runWithConcurrency,
|
|
5070
5524
|
sanitizeDisplayText,
|