Merge PR #8325: fix(ai): handle omitted creditUsagePercent in fresh xAI weekly periods (@bubua12)

This commit is contained in:
can1357
2026-08-13 01:14:53 +02:00
3 changed files with 160 additions and 10 deletions
+1
View File
@@ -7,6 +7,7 @@
- Fixed OpenAI Responses turns ending silently after a provider-hosted web search that produced no visible answer: the turn is now classified as `pause_turn` so the agent automatically continues with the search results instead of stopping.
- Fixed completed model streams retaining their provider concurrency permit until after completion became observable, without replacing provider results when lease cleanup fails ([#8284](https://github.com/can1357/oh-my-pi/pull/8284) by [@ethancawse](https://github.com/ethancawse)).
- Fixed the DashScope compatible-mode text-only Qwen override (issue #1859) stripping images from `qwen3.8-max`, which became multimodal in the bundled catalog (image input, #8019). The `-max` guard now only vetoes image content for pre-3.8 SKUs, so `qwen3.8-max`/`qwen3.8-max-preview` and later flagships send `image_url` content — restoring `inspect_image` on those models configured against `dashscope.aliyuncs.com/compatible-mode/v1` ([#8305](https://github.com/can1357/oh-my-pi/issues/8305)).
- Fixed xAI (`xai-oauth`) usage reporting falling back to a stale exhausted cache when a fresh weekly cycle with 0% consumed credits omits the `creditUsagePercent` field ([#8325](https://github.com/can1357/oh-my-pi/pull/8325) by [@bubua12](https://github.com/bubua12)).
## [17.2.15] - 2026-08-12
+46 -8
View File
@@ -50,6 +50,7 @@ interface XaiWeeklyBillingConfig {
productUsage: XaiProductUsage[];
onDemandCap?: number;
onDemandUsed?: number;
inferredPercent?: boolean;
}
/**
@@ -137,7 +138,16 @@ function parseWeeklyBillingConfig(raw: Record<string, unknown>): XaiWeeklyBillin
return null;
}
const creditUsagePercent = parsePercent(raw.creditUsagePercent);
// Fresh weekly periods (or accounts with 0 usage) omit creditUsagePercent;
// default to 0 only when the weekly period is active (end > now).
// Expired periods without explicit usage data are rejected to retain last good cache.
const inferredPercent = raw.creditUsagePercent === undefined || raw.creditUsagePercent === null;
let creditUsagePercent: number | undefined;
if (inferredPercent) {
creditUsagePercent = end > Date.now() ? 0 : undefined;
} else {
creditUsagePercent = parsePercent(raw.creditUsagePercent);
}
if (creditUsagePercent === undefined) return null;
const productUsage: XaiProductUsage[] = [];
@@ -146,7 +156,8 @@ function parseWeeklyBillingConfig(raw: Record<string, unknown>): XaiWeeklyBillin
for (const item of raw.productUsage) {
if (!isRecord(item)) continue;
const product = typeof item.product === "string" ? item.product.trim() : "";
const usagePercent = parsePercent(item.usagePercent);
const usagePercent =
item.usagePercent === undefined || item.usagePercent === null ? 0 : parsePercent(item.usagePercent);
if (!product || usagePercent === undefined) continue;
productUsage.push({ product, usagePercent });
}
@@ -163,6 +174,7 @@ function parseWeeklyBillingConfig(raw: Record<string, unknown>): XaiWeeklyBillin
productUsage,
onDemandCap: parseOnDemandAmount(raw.onDemandCap),
onDemandUsed: parseOnDemandAmount(raw.onDemandUsed),
inferredPercent,
};
}
@@ -190,6 +202,10 @@ function parseMonthlyBillingConfig(raw: Record<string, unknown>): XaiMonthlyBill
onDemandUsed: parseOnDemandAmount(raw.onDemandUsed),
};
}
function hasPositiveMonthlyLimit(raw: Record<string, unknown>): boolean {
const limit = parseOnDemandAmount(raw.monthlyLimit);
return limit !== undefined && limit > 0;
}
function buildOnDemandLimit(
onDemandCap: number | undefined,
@@ -361,10 +377,31 @@ export const xaiOauthUsageProvider: UsageProvider = {
: null;
}
if (!weekly && !monthly) return null;
// When an account is marked unified billing and weekly credits were only inferred
// from an omitted percentage field:
// - If a positive monthly quota is returned, use the monthly quota alone.
// - If the monthly endpoint returned a valid config without positive monthly quota,
// confirm that this account relies on the weekly reset cycle and use weekly.
// - If the monthly fetch failed (transient network error), reject inferred weekly
// so AuthStorage's retain-last-good cache preserves the previous valid snapshot.
let effectiveWeekly = weekly;
if (weekly?.inferredPercent && creditsLooksUnified) {
if (monthly) {
effectiveWeekly = null;
} else {
const monthlyConfig =
monthlyPayload && isRecord(monthlyPayload) && isRecord(monthlyPayload.config)
? monthlyPayload.config
: null;
if (!monthlyConfig || hasPositiveMonthlyLimit(monthlyConfig)) {
effectiveWeekly = null;
}
}
}
if (!effectiveWeekly && !monthly) return null;
const limits: UsageLimit[] = [];
if (weekly) limits.push(...buildLimits(weekly, accountId));
if (effectiveWeekly) limits.push(...buildLimits(effectiveWeekly, accountId));
if (monthly) limits.push(...buildLimits(monthly, accountId));
// Deduplicate on-demand if both shapes carried the same cap (keep first).
const seen = new Set<string>();
@@ -375,12 +412,13 @@ export const xaiOauthUsageProvider: UsageProvider = {
});
if (deduped.length === 0) return null;
const billingKind = weekly && monthly ? "unified" : weekly ? "weekly" : "monthly";
const endpoint = weekly && monthly ? `${creditsUrl} + ${monthlyUrl}` : weekly ? creditsUrl : monthlyUrl;
const billingKind = effectiveWeekly && monthly ? "unified" : effectiveWeekly ? "weekly" : "monthly";
const endpoint =
effectiveWeekly && monthly ? `${creditsUrl} + ${monthlyUrl}` : effectiveWeekly ? creditsUrl : monthlyUrl;
const raw =
weekly && monthly
effectiveWeekly && monthly
? { credits: creditsPayload, monthly: monthlyPayload }
: weekly
: effectiveWeekly
? creditsPayload
: monthlyPayload;
+113 -2
View File
@@ -125,6 +125,9 @@ function dualBillingFetch(
});
}
const payload = url.includes("format=credits") ? creditsPayload : monthlyPayload;
if (payload === null) {
return new Response("internal error", { status: 500 });
}
return new Response(JSON.stringify(payload), {
status: 200,
headers: { "content-type": "application/json" },
@@ -224,6 +227,114 @@ describe("xai-oauth usage provider", () => {
expect(report?.limits[0]?.id).toBe("xai-oauth:credits:1w");
expect(report?.limits[0]?.window?.resetsAt).toBe(Date.parse(periodEnd));
});
it("rejects an expired weekly period when creditUsagePercent is omitted", async () => {
const periodEnd = new Date(Date.now() - 60_000).toISOString();
const periodStart = new Date(Date.now() - 8 * 24 * 60 * 60 * 1000).toISOString();
const report = await xaiOauthUsageProvider.fetchUsage(
{ provider: "xai-oauth", credential: makeCredential() },
{
fetch: capturingFetch({
config: {
currentPeriod: {
end: periodEnd,
start: periodStart,
type: "USAGE_PERIOD_TYPE_WEEKLY",
},
},
}).fetch,
},
);
expect(report).toBeNull();
});
it("reports zero usage when weekly period is active but creditUsagePercent is omitted (fresh reset)", async () => {
const periodEnd = new Date(Date.now() + 6 * 24 * 60 * 60 * 1000).toISOString();
const periodStart = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
const report = await xaiOauthUsageProvider.fetchUsage(
{ provider: "xai-oauth", credential: makeCredential() },
{
fetch: capturingFetch({
config: {
currentPeriod: {
end: periodEnd,
start: periodStart,
type: "USAGE_PERIOD_TYPE_WEEKLY",
},
isUnifiedBillingUser: true,
onDemandCap: { val: 0 },
onDemandUsed: { val: 0 },
},
}).fetch,
},
);
expect(report?.metadata?.billingKind).toBe("weekly");
expect(report?.limits.map(limit => limit.id)).toEqual(["xai-oauth:credits:1w"]);
const credits = report?.limits[0];
expect(credits?.amount.used).toBe(0);
expect(credits?.amount.limit).toBe(100);
expect(credits?.amount.remaining).toBe(100);
expect(credits?.amount.usedFraction).toBe(0);
expect(credits?.amount.remainingFraction).toBe(1);
expect(credits?.status).toBe("ok");
expect(credits?.window?.resetsAt).toBe(Date.parse(periodEnd));
});
it("rejects inferred unified weekly usage when the monthly probe encounters a network error", async () => {
const periodEnd = new Date(Date.now() + 6 * 24 * 60 * 60 * 1000).toISOString();
const periodStart = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
const report = await xaiOauthUsageProvider.fetchUsage(
{ provider: "xai-oauth", credential: makeCredential() },
{
fetch: dualBillingFetch(
{
config: {
currentPeriod: {
end: periodEnd,
start: periodStart,
type: "USAGE_PERIOD_TYPE_WEEKLY",
},
isUnifiedBillingUser: true,
},
},
null,
).fetch,
},
);
expect(report).toBeNull();
});
it("rejects inferred unified weekly usage when monthly config has a positive limit but malformed fields", async () => {
const periodEnd = new Date(Date.now() + 6 * 24 * 60 * 60 * 1000).toISOString();
const periodStart = new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
const report = await xaiOauthUsageProvider.fetchUsage(
{ provider: "xai-oauth", credential: makeCredential() },
{
fetch: dualBillingFetch(
{
config: {
currentPeriod: {
end: periodEnd,
start: periodStart,
type: "USAGE_PERIOD_TYPE_WEEKLY",
},
isUnifiedBillingUser: true,
},
},
{
config: {
isUnifiedBillingUser: true,
monthlyLimit: { val: 15000 },
// Missing 'used' and billingPeriod dates
},
},
).fetch,
},
);
expect(report).toBeNull();
});
it("falls back to monthly included quota when credits has no percent fields", async () => {
const { fetch, calls } = dualBillingFetch(makeUnifiedCreditsPayload(), makeUnifiedMonthlyPayload());
@@ -290,7 +401,6 @@ describe("xai-oauth usage provider", () => {
).fetch,
},
);
expect(report?.limits.map(limit => limit.id)).toEqual(["xai-oauth:included:1mo", "xai-oauth:on-demand"]);
const onDemand = report?.limits.find(limit => limit.id === "xai-oauth:on-demand");
expect(onDemand?.amount.used).toBe(25);
@@ -299,10 +409,11 @@ describe("xai-oauth usage provider", () => {
});
it("returns null when both credits and monthly billing shapes are unusable", async () => {
const creditsUnusable = { config: { isUnifiedBillingUser: true, onDemandCap: { val: 0 } } };
const report = await xaiOauthUsageProvider.fetchUsage(
{ provider: "xai-oauth", credential: makeCredential() },
{
fetch: dualBillingFetch(makeUnifiedCreditsPayload(), {
fetch: dualBillingFetch(creditsUnusable, {
config: { isUnifiedBillingUser: true, monthlyLimit: { val: 0 }, used: { val: 0 } },
}).fetch,
},