From c9fb06e26ca78b4cdcee515d5cee364e2119b76e Mon Sep 17 00:00:00 2001 From: "Bob.Hou" Date: Thu, 3 Sep 2026 11:37:54 -0400 Subject: [PATCH] fix(grok-cli): treat omitted SuperGrokPro creditUsagePercent as 0% (#12312) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Validado em lote numa worktree combinada com os 9 PRs desta leva sobre o tip de `release/v3.8.51`: `typecheck:core` limpo, `check:provider-consistency` OK (273 entradas REGISTRY, **356** providers canônicos), `check-docs-counts-sync` exit 0 e **300/300** nos testes que a leva toca. O crescimento de arquivo que os PRs empilham uns sobre os outros foi rebaselinado num único registro datado (`_rebaseline_2026_09_03_houminxi_batch`), com a decomposição por arquivo: `providers/page.tsx` +18 (import CSV do #12504 + busca do #12495 no mesmo painel), `accountFallback.ts` +6 (o #12566 sobre o rebaseline que o #12590 já registrou — os dois tocam `checkFallbackError`) e `chatCore.ts` +3 (invalidez de cache de quota no 429 do #12325). As violações restantes (`codex.ts`, `stream.ts`) foram medidas também no tip puro e são drift da base, não desta leva. --- .../fixes/12312-grok-cli-supergrok-quota.md | 1 + open-sse/services/usage/grokCli.ts | 9 +- tests/unit/grok-cli-provider-limits.test.ts | 92 +++++++++++++++++-- 3 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 changelog.d/fixes/12312-grok-cli-supergrok-quota.md diff --git a/changelog.d/fixes/12312-grok-cli-supergrok-quota.md b/changelog.d/fixes/12312-grok-cli-supergrok-quota.md new file mode 100644 index 0000000000..1fed5df39e --- /dev/null +++ b/changelog.d/fixes/12312-grok-cli-supergrok-quota.md @@ -0,0 +1 @@ +- **fix(grok-cli):** treat omitted SuperGrokPro `creditUsagePercent` as 0% used so Provider Limits still renders a weekly bar (proto3 zero-elision) ([#12312](https://github.com/diegosouzapw/OmniRoute/pull/12312)) — thanks @HouMinXi diff --git a/open-sse/services/usage/grokCli.ts b/open-sse/services/usage/grokCli.ts index 08396cfb2f..bbd76199b8 100644 --- a/open-sse/services/usage/grokCli.ts +++ b/open-sse/services/usage/grokCli.ts @@ -239,9 +239,12 @@ export async function getGrokCliUsage(accessToken?: string) { const config = billing.config; const resetAt = config.currentPeriod?.end || null; const quotas: Record> = {}; - if (config.creditUsagePercent != null) { - quotas.weekly = percentageQuota(config.creditUsagePercent, resetAt); - } + // SuperGrokPro (and proto3 omit-zero) billing configs often omit + // creditUsagePercent / productUsage. A present config object is a + // successful billing read, so treat a missing percent as 0% used and + // still render a weekly bar. A missing config still returns + // "Grok Build billing status unavailable" above — that path is unchanged. + quotas.weekly = percentageQuota(config.creditUsagePercent ?? 0, resetAt); Object.assign(quotas, buildProductQuotas(config.productUsage, resetAt)); const autoTopUpResponse = userId diff --git a/tests/unit/grok-cli-provider-limits.test.ts b/tests/unit/grok-cli-provider-limits.test.ts index 081d403f5f..72e7c2b2da 100644 --- a/tests/unit/grok-cli-provider-limits.test.ts +++ b/tests/unit/grok-cli-provider-limits.test.ts @@ -38,6 +38,10 @@ function successFixtures( userId?: unknown; prepaidBalance?: Record | null | undefined; productUsage?: unknown; + creditUsagePercent?: number | null; + omitCreditUsagePercent?: boolean; + omitProductUsage?: boolean; + currentPeriod?: Record | null; } = {} ) { const tier = "tier" in options ? options.tier : "SuperGrok Heavy"; @@ -51,6 +55,14 @@ function successFixtures( { product: "API", usagePercent: 12.5 }, { product: "Grok Code", usagePercent: 44 }, ]; + const currentPeriod = + "currentPeriod" in options + ? options.currentPeriod + : { + type: "WEEKLY", + start: "2026-07-27T00:00:00.000Z", + end: "2026-08-03T00:00:00.000Z", + }; return async (input: string | URL | Request) => { const url = String(input); @@ -64,13 +76,14 @@ function successFixtures( if (url.endsWith("/billing?format=credits")) { return response({ config: { - creditUsagePercent: 37.25, - currentPeriod: { - type: "WEEKLY", - start: "2026-07-27T00:00:00.000Z", - end: "2026-08-03T00:00:00.000Z", - }, - productUsage, + ...(options.omitCreditUsagePercent + ? {} + : { + creditUsagePercent: + "creditUsagePercent" in options ? options.creditUsagePercent : 37.25, + }), + ...(currentPeriod === undefined ? {} : { currentPeriod }), + ...(options.omitProductUsage ? {} : { productUsage }), ...(prepaidBalance === undefined ? {} : { prepaidBalance }), }, }); @@ -492,3 +505,68 @@ test("Provider Limits cache persists only the public Grok billing contract", () test("grok-cli is registered on the public Provider Limits usage seam", () => { assert.ok((USAGE_FETCHER_PROVIDERS as readonly string[]).includes("grok-cli")); }); + +test("SuperGrokPro omitted creditUsagePercent still yields a weekly quota bar", async () => { + const usage = await getUsage( + successFixtures({ + tier: "SuperGrokPro", + omitCreditUsagePercent: true, + omitProductUsage: true, + prepaidBalance: { val: 0 }, + }) as typeof fetch + ); + + assert.equal(usage.plan, "SuperGrokPro"); + assert.deepEqual(usage.quotas?.weekly, { + used: 0, + total: 100, + remaining: 100, + remainingPercentage: 100, + resetAt: "2026-08-03T00:00:00.000Z", + isPercentageOnly: true, + }); + assert.equal(usage.message, undefined); +}); + +test("SuperGrokPro explicit null creditUsagePercent still yields a weekly quota bar", async () => { + const usage = await getUsage( + successFixtures({ + tier: "SuperGrokPro", + creditUsagePercent: null, + omitProductUsage: true, + prepaidBalance: { val: 0 }, + }) as typeof fetch + ); + + assert.equal(usage.plan, "SuperGrokPro"); + assert.deepEqual(usage.quotas?.weekly, { + used: 0, + total: 100, + remaining: 100, + remainingPercentage: 100, + resetAt: "2026-08-03T00:00:00.000Z", + isPercentageOnly: true, + }); +}); + +test("SuperGrokPro omitted currentPeriod still yields a weekly bar with null resetAt", async () => { + const usage = await getUsage( + successFixtures({ + tier: "SuperGrokPro", + omitCreditUsagePercent: true, + omitProductUsage: true, + currentPeriod: null, + prepaidBalance: { val: 0 }, + }) as typeof fetch + ); + + assert.equal(usage.plan, "SuperGrokPro"); + assert.deepEqual(usage.quotas?.weekly, { + used: 0, + total: 100, + remaining: 100, + remainingPercentage: 100, + resetAt: null, + isPercentageOnly: true, + }); +});