fix(codex): raise default quota threshold from 90% to 99% to avoid premature account blocking (#1697)

The previous 90% default treated Codex accounts as unavailable while they
still had ~10% quota remaining. A 99% threshold reserves only a minimal
safety margin near true exhaustion while preserving usable quota.

- Export DEFAULT_QUOTA_THRESHOLD_PERCENT=99 from quotaCache.ts
- Replace CODEX_QUOTA_THRESHOLD_PERCENT in auth.ts with shared constant
- Update quota policy tests to match new default

Co-authored-by: dhaern <manker_lol@hotmail.com>
This commit is contained in:
diegosouzapw
2026-04-28 00:18:30 -03:00
parent f23f301547
commit 8100b53fd7
4 changed files with 14 additions and 6 deletions

View File

@@ -49,6 +49,7 @@ const ACTIVE_TTL_MS = 5 * 60 * 1000; // 5 minutes for active accounts
const EXHAUSTED_TTL_MS = 5 * 60 * 1000; // 5 minutes for 429-sourced entries (no resetAt)
const EXHAUSTED_REFRESH_MS = 5 * 60 * 1000; // 5 minutes: recheck exhausted accounts (aligned with TTL)
const REFRESH_INTERVAL_MS = 60 * 1000; // Background tick every 1 minute
export const DEFAULT_QUOTA_THRESHOLD_PERCENT = 99;
// ─── State ──────────────────────────────────────────────────────────────────
@@ -260,7 +261,7 @@ export function isAccountQuotaExhausted(connectionId: string): boolean {
export function getQuotaWindowStatus(
connectionId: string,
windowName: string,
thresholdPercent = 90
thresholdPercent = DEFAULT_QUOTA_THRESHOLD_PERCENT
): QuotaWindowStatus | null {
const entry = cache.get(connectionId);
if (!entry) return null;

View File

@@ -6,7 +6,12 @@ import {
getSettings,
getCachedSettings,
} from "@/lib/localDb";
import { getQuotaCache, getQuotaWindowStatus, isAccountQuotaExhausted } from "@/domain/quotaCache";
import {
DEFAULT_QUOTA_THRESHOLD_PERCENT,
getQuotaCache,
getQuotaWindowStatus,
isAccountQuotaExhausted,
} from "@/domain/quotaCache";
import {
isAccountUnavailable,
getUnavailableUntil,
@@ -82,7 +87,6 @@ interface CooldownInspectionState {
retryableModelCooldownMs: number | null;
}
const CODEX_QUOTA_THRESHOLD_PERCENT = 90;
const MIN_QUOTA_THRESHOLD_PERCENT = 1;
const MAX_QUOTA_THRESHOLD_PERCENT = 100;
const NON_RETRYABLE_MODEL_LOCKOUT_REASONS = new Set(["not_found", "not_found_local"]);
@@ -168,7 +172,10 @@ interface QuotaCacheView {
>;
}
function normalizeQuotaThreshold(value: unknown, fallback = CODEX_QUOTA_THRESHOLD_PERCENT): number {
function normalizeQuotaThreshold(
value: unknown,
fallback = DEFAULT_QUOTA_THRESHOLD_PERCENT
): number {
const parsed = toNumber(value, fallback);
return Math.min(MAX_QUOTA_THRESHOLD_PERCENT, Math.max(MIN_QUOTA_THRESHOLD_PERCENT, parsed));
}

View File

@@ -18,7 +18,7 @@ test("resolveQuotaLimitPolicy keeps codex legacy defaults when generic policy is
assert.equal(policy.enabled, true);
assert.deepEqual(policy.windows, ["session"]);
assert.equal(policy.thresholdPercent, 90);
assert.equal(policy.thresholdPercent, 99);
});
test("resolveQuotaLimitPolicy enforces codex weekly window when weekly toggle is enabled", () => {

View File

@@ -264,7 +264,7 @@ test("resolveQuotaLimitPolicy normalizes Codex windows, thresholds, and defaults
});
assert.deepEqual(defaults, {
enabled: true,
thresholdPercent: 90,
thresholdPercent: 99,
windows: ["session", "weekly"],
});
assert.deepEqual(generic, {