diff --git a/src/main/rate-limits/grok-fetcher.test.ts b/src/main/rate-limits/grok-fetcher.test.ts index b077b880576..a88112c49e3 100644 --- a/src/main/rate-limits/grok-fetcher.test.ts +++ b/src/main/rate-limits/grok-fetcher.test.ts @@ -100,6 +100,31 @@ describe('fetchGrokRateLimits', () => { ) }) + it('maps an omitted protobuf percentage as zero for a weekly credits period', async () => { + authState.file = freshAuthJson() + netFetchMock.mockResolvedValueOnce( + jsonResponse({ + config: { + currentPeriod: { + type: 'USAGE_PERIOD_TYPE_WEEKLY', + start: '2026-07-17T19:38:56.948570+00:00', + end: '2026-07-24T19:38:56.948570+00:00' + }, + billingPeriodStart: '2026-07-17T19:38:56.948570+00:00', + billingPeriodEnd: '2026-07-24T19:38:56.948570+00:00', + isUnifiedBillingUser: true + } + }) + ) + + const result = await fetchGrokRateLimits() + expect(result.status).toBe('ok') + expect(result.weekly?.usedPercent).toBe(0) + expect(result.weekly?.resetsAt).toBe(Date.parse('2026-07-24T19:38:56.948570+00:00')) + expect(result.monthly).toBeUndefined() + expect(netFetchMock).toHaveBeenCalledTimes(1) + }) + it('returns unavailable when not signed in even if a token-less auth file exists', async () => { authState.file = JSON.stringify({}) const result = await fetchGrokRateLimits() @@ -119,17 +144,12 @@ describe('fetchGrokRateLimits', () => { expect(result.monthly).toBeUndefined() }) - it('maps monthly included usage for unified-billing accounts without weekly credits', async () => { + it('maps monthly included usage for unified-billing accounts without a weekly period', async () => { authState.file = freshAuthJson() netFetchMock .mockResolvedValueOnce( jsonResponse({ config: { - currentPeriod: { - type: 'USAGE_PERIOD_TYPE_WEEKLY', - start: '2026-07-10T19:38:56.948570+00:00', - end: '2026-07-17T19:38:56.948570+00:00' - }, isUnifiedBillingUser: true, subscriptionTier: 'SuperGrok' } diff --git a/src/main/rate-limits/grok-fetcher.ts b/src/main/rate-limits/grok-fetcher.ts index 1e6d20f5cce..7a514010dbe 100644 --- a/src/main/rate-limits/grok-fetcher.ts +++ b/src/main/rate-limits/grok-fetcher.ts @@ -82,7 +82,11 @@ function parseResetDescription(isoString: string | undefined): string | null { } function mapWeeklyCredits(config: GrokBillingConfig): RateLimitWindow | null { - const usedPercent = config.creditUsagePercent + // Why: Grok's protobuf JSON omits zero-valued percentages; a declared weekly + // period without this field is 0% usage, not an absent weekly allowance. + const usedPercent = + config.creditUsagePercent ?? + (config.currentPeriod?.type === 'USAGE_PERIOD_TYPE_WEEKLY' ? 0 : null) if (typeof usedPercent !== 'number' || !Number.isFinite(usedPercent)) { return null }