icebear0828 Claude Opus 4.6 commited on
Commit
cba2903
·
1 Parent(s): 695eeba

fix: prevent false window rollover resets in syncRateLimitWindow

Browse files

Codex API reset_at drifts by hundreds of seconds between calls due to
activity-based sliding windows. The strict equality check misinterpreted
this drift as a window rollover, resetting window_request_count to 0
on every quota fetch. Now only resets when drift exceeds 50% of the
window size, correctly distinguishing real rollovers from API noise.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Files changed (1) hide show
  1. src/auth/account-pool.ts +13 -5
src/auth/account-pool.ts CHANGED
@@ -387,11 +387,19 @@ export class AccountPool {
387
 
388
  const oldResetAt = entry.usage.window_reset_at;
389
  if (oldResetAt != null && oldResetAt !== newResetAt) {
390
- console.log(`[AccountPool] Rate limit window rolled for ${entryId} (${entry.email ?? "?"}), resetting window counters`);
391
- entry.usage.window_request_count = 0;
392
- entry.usage.window_input_tokens = 0;
393
- entry.usage.window_output_tokens = 0;
394
- entry.usage.window_counters_reset_at = new Date().toISOString();
 
 
 
 
 
 
 
 
395
  }
396
  entry.usage.window_reset_at = newResetAt;
397
  if (limitWindowSeconds != null) {
 
387
 
388
  const oldResetAt = entry.usage.window_reset_at;
389
  if (oldResetAt != null && oldResetAt !== newResetAt) {
390
+ // Codex API reset_at drifts slightly between calls (activity-based sliding window).
391
+ // Only reset counters on a true window rollover: when reset_at jumps by a large amount
392
+ // (at least half the window size), not just a small drift of a few hundred seconds.
393
+ const drift = Math.abs(newResetAt - oldResetAt);
394
+ const windowSec = limitWindowSeconds ?? entry.usage.limit_window_seconds ?? 0;
395
+ const threshold = windowSec > 0 ? windowSec * 0.5 : 3600;
396
+ if (drift >= threshold) {
397
+ console.log(`[AccountPool] Rate limit window rolled for ${entryId} (${entry.email ?? "?"}), resetting window counters (drift=${drift}s, threshold=${threshold}s)`);
398
+ entry.usage.window_request_count = 0;
399
+ entry.usage.window_input_tokens = 0;
400
+ entry.usage.window_output_tokens = 0;
401
+ entry.usage.window_counters_reset_at = new Date().toISOString();
402
+ }
403
  }
404
  entry.usage.window_reset_at = newResetAt;
405
  if (limitWindowSeconds != null) {