fix: Auto-expire auth profile cooldowns when timestamp expires

Fixes #3604

Auth profiles were getting stuck in cooldown even after the cooldownUntil
timestamp had expired. This happened because the cooldown check only happened
during profile selection, but expired cooldowns were never cleared from the
store.

Changes:
- Added auto-expiry logic in profile ordering (both explicit and round-robin paths)
- When now >= cooldownUntil, clear both cooldownUntil and disabledUntil
- Ensures profiles become available immediately after cooldown expires

Tested by manually setting expired cooldown and verifying it clears on next
profile resolution attempt.
This commit is contained in:
ClawdBot 2026-01-28 22:18:06 +00:00
parent a7534dc223
commit 28f9f226f0

View File

@ -98,14 +98,23 @@ export function resolveAuthProfileOrder(params: {
const inCooldown: Array<{ profileId: string; cooldownUntil: number }> = []; const inCooldown: Array<{ profileId: string; cooldownUntil: number }> = [];
for (const profileId of deduped) { for (const profileId of deduped) {
const cooldownUntil = resolveProfileUnusableUntil(store.usageStats?.[profileId] ?? {}) ?? 0; const stats = store.usageStats?.[profileId];
const cooldownUntil = resolveProfileUnusableUntil(stats ?? {}) ?? 0;
// Auto-expire cooldowns that have passed
if (stats && cooldownUntil > 0 && now >= cooldownUntil) {
stats.cooldownUntil = undefined;
stats.disabledUntil = undefined;
}
const updatedCooldownUntil = resolveProfileUnusableUntil(stats ?? {}) ?? 0;
if ( if (
typeof cooldownUntil === "number" && typeof updatedCooldownUntil === "number" &&
Number.isFinite(cooldownUntil) && Number.isFinite(updatedCooldownUntil) &&
cooldownUntil > 0 && updatedCooldownUntil > 0 &&
now < cooldownUntil now < updatedCooldownUntil
) { ) {
inCooldown.push({ profileId, cooldownUntil }); inCooldown.push({ profileId, cooldownUntil: updatedCooldownUntil });
} else { } else {
available.push(profileId); available.push(profileId);
} }
@ -144,6 +153,16 @@ function orderProfilesByMode(order: string[], store: AuthProfileStore): string[]
const inCooldown: string[] = []; const inCooldown: string[] = [];
for (const profileId of order) { for (const profileId of order) {
const stats = store.usageStats?.[profileId];
if (stats) {
const unusableUntil = resolveProfileUnusableUntil(stats);
// Auto-expire cooldowns that have passed
if (unusableUntil && unusableUntil > 0 && now >= unusableUntil) {
stats.cooldownUntil = undefined;
stats.disabledUntil = undefined;
}
}
if (isProfileInCooldown(store, profileId)) { if (isProfileInCooldown(store, profileId)) {
inCooldown.push(profileId); inCooldown.push(profileId);
} else { } else {