| author | |
| committer | |
| log | 0cab7d5ab978a8adaee6827f81693249d0dfeee5 |
| tree | 3c265af716cd15a5e1fd63be98b7bc40ada43b17 |
| parent | d23eab13d9d91697c5d4e7a458213b3f6473bc96 |
| signature | Signed by PGP key B5690EEEBB952194 |
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", () => { | ... | @@ -564,7 +564,10 @@ describe("Grok usage limits", () => { |
| 564 | for (const response of [{}, { config: {} }, { config: { creditUsagePercent: NaN } }]) { | 564 | for (const response of [{}, { config: {} }, { config: { creditUsagePercent: NaN } }]) { |
| 565 | const limits = grokUsageResponseToLimits(response, checkedAt); | 565 | const limits = grokUsageResponseToLimits(response, checkedAt); |
| 566 | expect(limits.windows).toEqual([]); | 566 | 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(); | ||
| 568 | } | 571 | } |
| 569 | expect( | 572 | expect( |
| 570 | grokUsageResponseToLimits({ config: { creditUsagePercent: 0 } }, checkedAt).windows, | 573 | grokUsageResponseToLimits({ config: { creditUsagePercent: 0 } }, checkedAt).windows, |
apps/server/src/provider/Layers/grokUsageLimits.ts+9-1| ... | @@ -41,7 +41,15 @@ export function grokUsageResponseToLimits( | ... | @@ -41,7 +41,15 @@ export function grokUsageResponseToLimits( |
| 41 | ) { | 41 | ) { |
| 42 | const usedPercent = response.config?.creditUsagePercent; | 42 | const usedPercent = response.config?.creditUsagePercent; |
| 43 | if (usedPercent === undefined || !Number.isFinite(usedPercent)) { | 43 | 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: [] }); | ||
| 45 | } | 53 | } |
| 46 | const period = response.config?.currentPeriod; | 54 | const period = response.config?.currentPeriod; |
| 47 | const periodType = period?.type?.replace(/^USAGE_PERIOD_TYPE_/, ""); | 55 | const periodType = period?.type?.replace(/^USAGE_PERIOD_TYPE_/, ""); |