mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-06 07:12:12 +03:00
- Parse XhYmZs format from antigravity error messages (e.g., 27h41m36s) - Dynamic retry-after threshold (60s default) instead of hardcoded 10s - Add parseRetryFromErrorText() in accountFallback.ts for body parsing - Fix 403 'verify your account' to trigger permanent deactivation - Add keyword matching for 'quota will reset', 'exhausted capacity' - Add unit tests for retry parsing and keyword matching Fixes #858 (Antigravity 429 handling) Fixes #832 (Qwen quota 429 - same underlying bug)
57 lines
2.0 KiB
TypeScript
57 lines
2.0 KiB
TypeScript
import { isAccountDeactivated, isCreditsExhausted } from "./accountFallback.ts";
|
|
|
|
export const PROVIDER_ERROR_TYPES = {
|
|
RATE_LIMITED: "rate_limited", // 429 — transient, retry with backoff
|
|
UNAUTHORIZED: "unauthorized", // 401 — token expired, refresh
|
|
ACCOUNT_DEACTIVATED: "account_deactivated", // 401 + deactivation signal
|
|
FORBIDDEN: "forbidden", // 403 — account banned/revoked, disable node
|
|
SERVER_ERROR: "server_error", // 500/502/503 — retry limited
|
|
QUOTA_EXHAUSTED: "quota_exhausted", // 402/429/400 + billing signals
|
|
};
|
|
|
|
function responseBodyToString(responseBody: unknown): string {
|
|
if (typeof responseBody === "string") return responseBody;
|
|
if (responseBody !== null && typeof responseBody === "object") {
|
|
try {
|
|
return JSON.stringify(responseBody);
|
|
} catch {
|
|
return "";
|
|
}
|
|
}
|
|
return "";
|
|
}
|
|
|
|
export function classifyProviderError(statusCode: number, responseBody: unknown): string | null {
|
|
const bodyStr = responseBodyToString(responseBody);
|
|
const creditsExhausted = isCreditsExhausted(bodyStr);
|
|
const accountDeactivated = isAccountDeactivated(bodyStr);
|
|
|
|
// T10: credits exhausted is terminal and can appear as 400/402/429 depending on provider.
|
|
if (
|
|
creditsExhausted &&
|
|
(statusCode === 400 || statusCode === 402 || statusCode === 429 || statusCode === 403)
|
|
) {
|
|
return PROVIDER_ERROR_TYPES.QUOTA_EXHAUSTED;
|
|
}
|
|
|
|
if (statusCode === 429) {
|
|
return PROVIDER_ERROR_TYPES.RATE_LIMITED;
|
|
}
|
|
|
|
// T06: only deactivation-like 401s should be treated as permanent account expiry.
|
|
if (statusCode === 401) {
|
|
return accountDeactivated
|
|
? PROVIDER_ERROR_TYPES.ACCOUNT_DEACTIVATED
|
|
: PROVIDER_ERROR_TYPES.UNAUTHORIZED;
|
|
}
|
|
|
|
if (statusCode === 402) return PROVIDER_ERROR_TYPES.QUOTA_EXHAUSTED;
|
|
if (statusCode === 403 && accountDeactivated) {
|
|
return PROVIDER_ERROR_TYPES.ACCOUNT_DEACTIVATED;
|
|
}
|
|
if (statusCode === 403) return PROVIDER_ERROR_TYPES.FORBIDDEN;
|
|
if (statusCode >= 500) return PROVIDER_ERROR_TYPES.SERVER_ERROR;
|
|
|
|
return null;
|
|
}
|