fix(ai): strip every bare resource-exhausted token

parseConnectEndStream repeats the default status phrase in the message
body, so the trailer reads "resource_exhausted: resource exhausted".
Using a global strip removes both occurrences, so the leftover
"exhausted" no longer trips the generic quota branch and reintroduces
the 30-minute credential block for an otherwise bare status.

Fixes #7032

(cherry picked from commit 3d46a042c649e3892d9c68abbc3789a7719f0667)
This commit is contained in:
roboomp
2026-07-29 16:47:38 +00:00
committed by can1357
parent f144f5db36
commit ca8fcb25b8
2 changed files with 12 additions and 3 deletions
+3 -3
View File
@@ -25,7 +25,7 @@ const OPENROUTER_DAILY_FREE_LIMIT_PATTERN = /\bfree[-_ ]models[-_ ]per[-_ ]day\b
// while HTTP bodies use the phrase ("resource exhausted"). Strip either form
// before classifying explicit details; an otherwise opaque status is transient
// model capacity, while quota/rate-limit/server wording remains authoritative.
const RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/i;
const RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/gi;
/**
* Classify a rate-limit error message into a reason category.
@@ -38,8 +38,8 @@ const RESOURCE_EXHAUSTED_PATTERN = /resource.?exhausted/i;
*/
export function parseRateLimitReason(errorMessage: string): RateLimitReason {
const lowerWithStatus = errorMessage.toLowerCase();
const hasResourceExhaustedStatus = RESOURCE_EXHAUSTED_PATTERN.test(lowerWithStatus);
const lower = hasResourceExhaustedStatus ? lowerWithStatus.replace(RESOURCE_EXHAUSTED_PATTERN, "") : lowerWithStatus;
const lower = lowerWithStatus.replace(RESOURCE_EXHAUSTED_PATTERN, "");
const hasResourceExhaustedStatus = lower !== lowerWithStatus;
// Antigravity / Cloud Code Assist surface multi-hour daily-quota exhaustion as
// "You have exhausted your capacity on this model. Your quota will reset after …".
@@ -35,6 +35,15 @@ describe("parseRateLimitReason", () => {
expect(parseRateLimitReason("Connect error resource_exhausted: Error")).toBe("MODEL_CAPACITY_EXHAUSTED");
});
// parseConnectEndStream repeats the default status phrase in the message body:
// `Connect error resource_exhausted: resource exhausted`. Both tokens must be
// stripped so the leftover "exhausted" doesn't trip the generic quota branch.
it("classifies repeated bare resource-exhausted tokens as MODEL_CAPACITY_EXHAUSTED", () => {
expect(parseRateLimitReason("Connect error resource_exhausted: resource exhausted")).toBe(
"MODEL_CAPACITY_EXHAUSTED",
);
});
it("keeps explicit quota details authoritative after resource_exhausted", () => {
expect(parseRateLimitReason("Connect error resource_exhausted: Quota exceeded for this account")).toBe(
"QUOTA_EXHAUSTED",