From dceb8262332024d29485f1b8bdc61e784e214f3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AA=20T=E1=BA=A5n=20L=E1=BB=99c?= <26348718+letanloc1998@users.noreply.github.com> Date: Sun, 26 Oct 2025 00:25:21 +0700 Subject: [PATCH 1/2] Reduce cooldowns for all handlers by 1 minute when no valid provider is found. --- src/api/providers/virtual-quota-fallback.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/api/providers/virtual-quota-fallback.ts b/src/api/providers/virtual-quota-fallback.ts index 70f7d7f85f1..22f9ddb9fef 100644 --- a/src/api/providers/virtual-quota-fallback.ts +++ b/src/api/providers/virtual-quota-fallback.ts @@ -240,6 +240,14 @@ export class VirtualQuotaFallbackHandler implements ApiHandler { // No valid handler found if (this.activeProfileId) { await this.notifyHandlerSwitch(undefined, "No Valid Provider") + + // No valid handler found - reduce all cooldowns by 1 minute to gradually + // allow providers to become available again instead of blocking indefinitely + await Promise.all( + this.handlerConfigs.map((c) => + this.usage.reduceCooldown(c.profileId, 1 * 60 * 1000) + ) + ); } this.activeHandler = undefined this.activeProfileId = undefined From 9c3a3f799e8f5da1ad692d939769c8767b95c99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=AA=20T=E1=BA=A5n=20L=E1=BB=99c?= <26348718+letanloc1998@users.noreply.github.com> Date: Sun, 26 Oct 2025 00:27:17 +0700 Subject: [PATCH 2/2] Add reduceCooldown method to usage tracker --- src/utils/usage-tracker.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/utils/usage-tracker.ts b/src/utils/usage-tracker.ts index a6bed5489b0..8d6d5ce5131 100644 --- a/src/utils/usage-tracker.ts +++ b/src/utils/usage-tracker.ts @@ -109,6 +109,18 @@ export class UsageTracker { await this.memento.update(COOLDOWNS_STORAGE_KEY, allCooldowns) } + public async reduceCooldown(providerId: string, durationMs: number): Promise { + const allCooldowns = await this.getPrunedCooldowns() + const currentCooldown = allCooldowns[providerId] + + // Skip if provider has no active cooldown + if (!currentCooldown) return + + allCooldowns[providerId] = currentCooldown - durationMs + + await this.memento.update(COOLDOWNS_STORAGE_KEY, allCooldowns) + } + public async isUnderCooldown(providerId: string): Promise { const allCooldowns = await this.getPrunedCooldowns() const cooldownUntil = allCooldowns[providerId]