authorgravatar for jakeleventhal@me.comJake Leventhal <jakeleventhal@me.com> 2026-09-24 21:38:21-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-09-24 18:38:21-07:00
log0cab7d5ab978a8adaee6827f81693249d0dfeee5
tree3c265af716cd15a5e1fd63be98b7bc40ada43b17
parentd23eab13d9d91697c5d4e7a458213b3f6473bc96
signature Signed by PGP key B5690EEEBB952194

fix(server): Grok accounts with no usage yet no longer vanish from Limits (#12799)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>

2 files changed, 13 insertions(+), 2 deletions(-)

apps/server/src/provider/Layers/GrokProvider.test.ts+4-1
......@@ -564,7 +564,10 @@ describe("Grok usage limits", () => {
564564 for (const response of [{}, { config: {} }, { config: { creditUsagePercent: NaN } }]) {
565565 const limits = grokUsageResponseToLimits(response, checkedAt);
566566 expect(limits.windows).toEqual([]);
567 expect(limits.unavailable?.reason).toBe("unsupported");
567 // Nothing metered yet, which xAI reports by omitting the field until
568 // usage registers. Marking it `unsupported` would drop the account from
569 // the Limits view for good; leaving the marker off keeps it listed.
570 expect(limits.unavailable).toBeUndefined();
568571 }
569572 expect(
570573 grokUsageResponseToLimits({ config: { creditUsagePercent: 0 } }, checkedAt).windows,
apps/server/src/provider/Layers/grokUsageLimits.ts+9-1
......@@ -41,7 +41,15 @@ export function grokUsageResponseToLimits(
4141) {
4242 const usedPercent = response.config?.creditUsagePercent;
4343 if (usedPercent === undefined || !Number.isFinite(usedPercent)) {
44 return makeUnavailableUsageLimits({ checkedAt, reason: "unsupported" });
44 // A billing read that succeeded but carries no percentage is an account
45 // with nothing metered yet, not one that can never report: xAI omits the
46 // field entirely (rather than sending 0) until usage registers, then fills
47 // it in. Calling that `unsupported` would strand the account — the Limits
48 // view drops unsupported entries and deliberately mutes their notice, so a
49 // freshly signed-in Grok account would vanish with no explanation until it
50 // happened to be used, and `applyUsageLimitsUpdate` would refuse the
51 // mid-turn windows that could have recovered it.
52 return makeUsageLimits({ checkedAt, windows: [] });
4553 }
4654 const period = response.config?.currentPeriod;
4755 const periodType = period?.type?.replace(/^USAGE_PERIOD_TYPE_/, "");