Mirrowel commited on
Commit
06b3f7d
·
1 Parent(s): 1af1879

feat(quota): restructure quota aggregation with cumulative counts and tier registry

Browse files

Remove averaged percentage calculations in favor of summing actual request counts across all credentials in a group. Introduce per-tier credential registries that distinguish active from exhausted allocations. Simplify viewer presentation to show absolute usage totals alongside compact tier status markers, deprecating the previous exhaustion counting approach.

src/proxy_app/quota_viewer.py CHANGED
@@ -417,25 +417,51 @@ class QuotaViewer:
417
  if quota_groups:
418
  quota_lines = []
419
  for group_name, group_stats in quota_groups.items():
420
- avg_pct = group_stats.get("avg_remaining_pct", 0)
421
- exhausted = group_stats.get("credentials_exhausted", 0)
422
- total = group_stats.get("credentials_total", 0)
423
-
424
- # Determine color based on remaining
425
- if exhausted > 0:
426
- color = "red"
427
- status = f"({exhausted}/{total} exhausted)"
428
- elif avg_pct < 20:
429
- color = "yellow"
430
- status = ""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
  else:
432
- color = "green"
433
- status = ""
434
 
435
- bar = create_progress_bar(avg_pct)
436
- display_name = group_name[:10]
 
 
 
 
 
 
437
  quota_lines.append(
438
- f"[{color}]{display_name}: {avg_pct}% {bar}[/{color}] {status}"
439
  )
440
 
441
  # First line goes in the main row
 
417
  if quota_groups:
418
  quota_lines = []
419
  for group_name, group_stats in quota_groups.items():
420
+ # Use total requests for global view
421
+ total_used = group_stats.get("total_requests_used", 0)
422
+ total_max = group_stats.get("total_requests_max", 0)
423
+ total_pct = group_stats.get("total_remaining_pct")
424
+ tiers = group_stats.get("tiers", {})
425
+
426
+ # Format tier info: "5(15)f/2s" = 5 active out of 15 free, 2 standard all active
427
+ tier_parts = []
428
+ for tier_name, tier_info in sorted(tiers.items()):
429
+ if tier_name == "unknown":
430
+ continue # Skip unknown tiers in display
431
+ total_t = tier_info.get("total", 0)
432
+ active_t = tier_info.get("active", 0)
433
+ # Use first letter: standard-tier -> s, free-tier -> f
434
+ short = tier_name.replace("-tier", "")[0]
435
+
436
+ if active_t < total_t:
437
+ # Some exhausted - show active(total)
438
+ tier_parts.append(f"{active_t}({total_t}){short}")
439
+ else:
440
+ # All active - just show total
441
+ tier_parts.append(f"{total_t}{short}")
442
+ tier_str = "/".join(tier_parts) if tier_parts else ""
443
+
444
+ # Determine color based purely on remaining percentage
445
+ if total_pct is not None:
446
+ if total_pct <= 10:
447
+ color = "red"
448
+ elif total_pct < 30:
449
+ color = "yellow"
450
+ else:
451
+ color = "green"
452
  else:
453
+ color = "dim"
 
454
 
455
+ bar = create_progress_bar(total_pct)
456
+ display_name = group_name[:11]
457
+ pct_str = f"{total_pct}%" if total_pct is not None else "?"
458
+
459
+ # Build status suffix (just tiers now, no outer parens)
460
+ status = tier_str
461
+
462
+ # Compact format: "claude: 1228/1625 24% ████░░░░░░ (5(15)f/2s)"
463
  quota_lines.append(
464
+ f"[{color}]{display_name}: {total_used}/{total_max} {pct_str} {bar}[/{color}] {status}"
465
  )
466
 
467
  # First line goes in the main row
src/rotator_library/client.py CHANGED
@@ -2657,6 +2657,11 @@ class RotatingClient:
2657
  "credentials_exhausted": 0,
2658
  "avg_remaining_pct": 0,
2659
  "total_remaining_pcts": [],
 
 
 
 
 
2660
  }
2661
 
2662
  # Calculate per-credential quota for this group
@@ -2664,17 +2669,44 @@ class RotatingClient:
2664
  models_data = cred.get("models", {})
2665
  group_stats["credentials_total"] += 1
2666
 
2667
- # Find any model from this group (try all with alias fallback)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2668
  model_stats = None
2669
  for model in group_models:
2670
- model_stats = self._find_model_stats_in_data(
2671
  models_data, model, provider, provider_instance
2672
  )
2673
- if model_stats:
2674
- break
 
 
 
 
 
 
2675
 
2676
  if model_stats:
2677
  baseline = model_stats.get("baseline_remaining_fraction")
 
 
 
 
 
 
 
2678
  if baseline is not None:
2679
  remaining_pct = int(baseline * 100)
2680
  group_stats["total_remaining_pcts"].append(
@@ -2682,8 +2714,11 @@ class RotatingClient:
2682
  )
2683
  if baseline <= 0:
2684
  group_stats["credentials_exhausted"] += 1
 
 
 
2685
 
2686
- # Calculate average remaining percentage
2687
  if group_stats["total_remaining_pcts"]:
2688
  group_stats["avg_remaining_pct"] = int(
2689
  sum(group_stats["total_remaining_pcts"])
@@ -2691,6 +2726,16 @@ class RotatingClient:
2691
  )
2692
  del group_stats["total_remaining_pcts"]
2693
 
 
 
 
 
 
 
 
 
 
 
2694
  prov_stats["quota_groups"][group_name] = group_stats
2695
 
2696
  # Also enrich each credential with formatted quota group info
@@ -2699,14 +2744,20 @@ class RotatingClient:
2699
  models_data = cred.get("models", {})
2700
 
2701
  for group_name, group_models in quota_groups.items():
2702
- # Find representative model from this group (try all with alias fallback)
2703
  model_stats = None
2704
  for model in group_models:
2705
- model_stats = self._find_model_stats_in_data(
2706
  models_data, model, provider, provider_instance
2707
  )
2708
- if model_stats:
2709
- break
 
 
 
 
 
 
2710
 
2711
  if model_stats:
2712
  baseline = model_stats.get("baseline_remaining_fraction")
 
2657
  "credentials_exhausted": 0,
2658
  "avg_remaining_pct": 0,
2659
  "total_remaining_pcts": [],
2660
+ # Total requests tracking across all credentials
2661
+ "total_requests_used": 0,
2662
+ "total_requests_max": 0,
2663
+ # Tier breakdown: tier_name -> {"total": N, "active": M}
2664
+ "tiers": {},
2665
  }
2666
 
2667
  # Calculate per-credential quota for this group
 
2669
  models_data = cred.get("models", {})
2670
  group_stats["credentials_total"] += 1
2671
 
2672
+ # Track tier - get directly from provider cache since cred["tier"] not set yet
2673
+ tier = cred.get("tier")
2674
+ if not tier and hasattr(
2675
+ provider_instance, "project_tier_cache"
2676
+ ):
2677
+ cred_path = cred.get("full_path", "")
2678
+ tier = provider_instance.project_tier_cache.get(cred_path)
2679
+ tier = tier or "unknown"
2680
+
2681
+ # Initialize tier entry if needed
2682
+ if tier not in group_stats["tiers"]:
2683
+ group_stats["tiers"][tier] = {"total": 0, "active": 0}
2684
+ group_stats["tiers"][tier]["total"] += 1
2685
+
2686
+ # Find model with VALID baseline (not just any model with stats)
2687
  model_stats = None
2688
  for model in group_models:
2689
+ candidate = self._find_model_stats_in_data(
2690
  models_data, model, provider, provider_instance
2691
  )
2692
+ if candidate:
2693
+ baseline = candidate.get("baseline_remaining_fraction")
2694
+ if baseline is not None:
2695
+ model_stats = candidate
2696
+ break
2697
+ # Keep first found as fallback (for request counts)
2698
+ if model_stats is None:
2699
+ model_stats = candidate
2700
 
2701
  if model_stats:
2702
  baseline = model_stats.get("baseline_remaining_fraction")
2703
+ req_count = model_stats.get("request_count", 0)
2704
+ max_req = model_stats.get("quota_max_requests") or 0
2705
+
2706
+ # Accumulate totals (one model per group per credential)
2707
+ group_stats["total_requests_used"] += req_count
2708
+ group_stats["total_requests_max"] += max_req
2709
+
2710
  if baseline is not None:
2711
  remaining_pct = int(baseline * 100)
2712
  group_stats["total_remaining_pcts"].append(
 
2714
  )
2715
  if baseline <= 0:
2716
  group_stats["credentials_exhausted"] += 1
2717
+ else:
2718
+ # Credential is active (has quota remaining)
2719
+ group_stats["tiers"][tier]["active"] += 1
2720
 
2721
+ # Calculate average remaining percentage (per-credential average)
2722
  if group_stats["total_remaining_pcts"]:
2723
  group_stats["avg_remaining_pct"] = int(
2724
  sum(group_stats["total_remaining_pcts"])
 
2726
  )
2727
  del group_stats["total_remaining_pcts"]
2728
 
2729
+ # Calculate total remaining percentage (global)
2730
+ if group_stats["total_requests_max"] > 0:
2731
+ used = group_stats["total_requests_used"]
2732
+ max_r = group_stats["total_requests_max"]
2733
+ group_stats["total_remaining_pct"] = max(
2734
+ 0, int((1 - used / max_r) * 100)
2735
+ )
2736
+ else:
2737
+ group_stats["total_remaining_pct"] = None
2738
+
2739
  prov_stats["quota_groups"][group_name] = group_stats
2740
 
2741
  # Also enrich each credential with formatted quota group info
 
2744
  models_data = cred.get("models", {})
2745
 
2746
  for group_name, group_models in quota_groups.items():
2747
+ # Find model with VALID baseline (prefer over any model with stats)
2748
  model_stats = None
2749
  for model in group_models:
2750
+ candidate = self._find_model_stats_in_data(
2751
  models_data, model, provider, provider_instance
2752
  )
2753
+ if candidate:
2754
+ baseline = candidate.get("baseline_remaining_fraction")
2755
+ if baseline is not None:
2756
+ model_stats = candidate
2757
+ break
2758
+ # Keep first found as fallback
2759
+ if model_stats is None:
2760
+ model_stats = candidate
2761
 
2762
  if model_stats:
2763
  baseline = model_stats.get("baseline_remaining_fraction")