FN-8629: prevent false Grok usage percentages

Prevent omitted Grok billing percentages from being displayed as fully consumed credits.

- Require a finite CLI-supplied credit usage percentage before creating a billing window.
- Cover omitted, zero, invalid, and non-weekly Grok billing responses.
- Add a patch changeset for the corrected usage display.

Files changed:
 .changeset/fn-8629-grok-usage-percent.md       |  7 +++
 packages/dashboard/src/__tests__/usage.test.ts | 71 ++++++++++++++++++++++++--
 packages/dashboard/src/usage.ts                | 13 ++---
 3 files changed, 77 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-8629

Fusion-Task-Lineage: b5b7c83b-e34f-43d9-a31a-d1fd769c4eb8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-07-31 13:42:11 -07:00
parent 4bcaddafc5
commit f31a716a2a
3 changed files with 77 additions and 14 deletions

View File

@@ -0,0 +1,7 @@
---
"@runfusion/fusion": patch
---
summary: Prevent false 100% Grok usage when the CLI omits a credit percentage.
category: fix
dev: Grok billing windows now require a finite API-supplied creditUsagePercent value.

View File

@@ -3819,7 +3819,8 @@ describe("usage", () => {
expect(mockRequest).toHaveBeenCalledTimes(1);
});
it("treats an omitted exhausted percentage as 100% used for a valid weekly CLI billing period", async () => {
it("does not fabricate a weekly credit window when the CLI billing percentage is omitted", async () => {
vi.stubEnv("GROK_API_KEY", "env-grok-key");
mockReadFile.mockImplementation(async (filePath: string) => {
if (String(filePath).includes(".grok/auth.json")) return GROK_CLI_AUTH_JSON;
return Promise.reject(new Error("File not found"));
@@ -3843,14 +3844,74 @@ describe("usage", () => {
const grok = providers.find((provider) => provider.name === "Grok")!;
expect(grok.status).toBe("ok");
expect(grok.windows).toEqual([]);
expect(grok.windows.some((window) => window.percentUsed === 100)).toBe(false);
expect(mockRequest).toHaveBeenCalledTimes(2);
});
it("renders a zero-percent weekly CLI credit window", async () => {
mockReadFile.mockImplementation(async (filePath: string) => {
if (String(filePath).includes(".grok/auth.json")) return GROK_CLI_AUTH_JSON;
return Promise.reject(new Error("File not found"));
});
const periodEnd = new Date(Date.now() + 3 * 24 * 60 * 60 * 1000).toISOString();
mockGrokBillingResponse(200, {
config: {
currentPeriod: { type: "USAGE_PERIOD_TYPE_WEEKLY", end: periodEnd },
billingPeriodEnd: periodEnd,
creditUsagePercent: 0,
},
});
const providers = await fetchAllProviderUsage();
const grok = providers.find((provider) => provider.name === "Grok")!;
expect(grok.windows).toHaveLength(1);
expect(grok.windows[0]).toMatchObject({
label: "Weekly (credits)",
percentUsed: 100,
percentLeft: 0,
percentUsed: 0,
percentLeft: 100,
});
});
it.each(["not-a-number", null])("falls back without a CLI credit window for a non-numeric percentage: %j", async (creditUsagePercent) => {
mockReadFile.mockImplementation(async (filePath: string) => {
if (String(filePath).includes(".grok/auth.json")) return GROK_CLI_AUTH_JSON;
return Promise.reject(new Error("File not found"));
});
mockGrokBillingResponse(200, {
config: { creditUsagePercent },
});
const providers = await fetchAllProviderUsage();
const grok = providers.find((provider) => provider.name === "Grok")!;
expect(grok.status).toBe("error");
expect(grok.windows).toEqual([]);
expect(grok.error).toContain("grok login");
});
it("retains the Credits label for a non-weekly numeric CLI percentage", async () => {
mockReadFile.mockImplementation(async (filePath: string) => {
if (String(filePath).includes(".grok/auth.json")) return GROK_CLI_AUTH_JSON;
return Promise.reject(new Error("File not found"));
});
mockGrokBillingResponse(200, {
config: {
currentPeriod: { type: "USAGE_PERIOD_TYPE_MONTHLY" },
creditUsagePercent: 25,
},
});
const providers = await fetchAllProviderUsage();
const grok = providers.find((provider) => provider.name === "Grok")!;
expect(grok.windows).toHaveLength(1);
expect(grok.windows[0]).toMatchObject({
label: "Credits",
percentUsed: 25,
percentLeft: 75,
});
expect(grok.windows[0].resetText).toContain("resets in");
expect(mockRequest).toHaveBeenCalledTimes(1);
});
it("falls back to the xAI API-key validity card when CLI billing fails", async () => {

View File

@@ -1718,16 +1718,11 @@ async function fetchGrokCliBillingUsage(token: string, usage: ProviderUsage): Pr
const parsedReset = _parseResetTimestamp(config.billingPeriodEnd ?? config.currentPeriod?.end);
const isWeekly = config.currentPeriod?.type === "USAGE_PERIOD_TYPE_WEEKLY";
/*
FNXC:UsageProviders 2026-07-14-14:47:
Grok's billing endpoint omits `creditUsagePercent` when the weekly allowance is exhausted. Grok Build renders that valid reduced config as “Weekly limit: 0%” (zero allowance remaining), while Fusion's usage model stores percent consumed. Therefore the omitted exhausted value maps to 100% used—not 0% used. Only infer exhaustion when the response still proves a weekly billing period and reset boundary, so malformed payloads continue to fail closed.
FNXC:UsageProviders 2026-07-31-20:31:
A real account reported zero Grok credit usage while its billing response omitted `creditUsagePercent`, disproving the former omitted-field-to-100% inference. Emit a credits window only for a finite API-supplied percentage; field absence must fall through to the API-key validity or CLI-auth error card rather than fabricate consumption.
*/
const rawPercentUsed = config.creditUsagePercent;
const pctUsed = typeof rawPercentUsed === "number" && Number.isFinite(rawPercentUsed)
? rawPercentUsed
: isWeekly && parsedReset
? 100
: undefined;
if (pctUsed === undefined) return false;
const pctUsed = config.creditUsagePercent;
if (typeof pctUsed !== "number" || !Number.isFinite(pctUsed)) return false;
usage.windows.push({
label: isWeekly ? "Weekly (credits)" : "Credits",