Skip to content

Commit 2769276

Browse files
committed
fix(billing): scope rate limit display per-provider, remove unsolicited advice
Problem: Rate limit info was stored globally in session state, causing wrong provider's rate limit to appear in /usage (e.g. GitHub Copilot's weekly limit showing when viewing Z.AI billing). Also included unsolicited model advice ("Use GLM-4.7 for routine tasks") which is not appropriate. Solution: - Add _get_current_provider() helper to ResponseHandler to retrieve current provider from session state - Store rate limits in $state->{rate_limits}{$provider}{...} instead of flat $state->{rate_limit_code}/$state->{rate_limit_until} - Update _display_copilot_billing and _display_zai_billing to read from provider-scoped rate limit data - Remove GLM-5.x explanation line (already shown in Cost Rate field) - Remove "Use GLM-4.7 for routine tasks" advice (unsolicited) Files changed: - lib/CLIO/Core/API/ResponseHandler.pm (4 locations updated) - lib/CLIO/UI/Commands/Billing.pm (rate limit reads + removed advice)
1 parent f2d6b36 commit 2769276

2 files changed

Lines changed: 56 additions & 28 deletions

File tree

lib/CLIO/Core/API/ResponseHandler.pm

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ APIManager instance.
5454
5555
=cut
5656

57+
=head2 _get_current_provider
58+
59+
Get the current provider from session state.
60+
61+
Returns: Provider string (e.g. 'github_copilot', 'zai_coding') or 'unknown'
62+
63+
=cut
64+
65+
sub _get_current_provider {
66+
my ($self) = @_;
67+
if ($self->{session}) {
68+
if ($self->{session}->can('state') && $self->{session}->state() && $self->{session}->state()->{selected_provider}) {
69+
return $self->{session}->state()->{selected_provider};
70+
}
71+
return $self->{session}{selected_provider} if $self->{session}{selected_provider};
72+
}
73+
return 'unknown';
74+
}
75+
5776
sub new {
5877
my ($class, %opts) = @_;
5978
return bless {
@@ -413,11 +432,14 @@ sub handle_error_response {
413432
# is misleading and the /usage display would show wrong info
414433
$self->{rate_limit_until} = 0;
415434

416-
# But DO propagate rate_limit_code to session for /usage display
435+
# Store rate limit per-provider for /usage display
436+
my $rl_provider = $self->_get_current_provider();
417437
if ($self->{session} && $self->{session}->can('state')) {
418438
my $state = $self->{session}->state();
419-
$state->{rate_limit_until} = 0; # Clear cooldown - this is weekly/monthly
420-
$state->{rate_limit_code} = $detected_rate_limit_code;
439+
$state->{rate_limits} //= {};
440+
$state->{rate_limits}{$rl_provider} //= {};
441+
$state->{rate_limits}{$rl_provider}{rate_limit_until} = 0;
442+
$state->{rate_limits}{$rl_provider}{rate_limit_code} = $detected_rate_limit_code;
421443
} elsif ($self->{session}) {
422444
$self->{session}{rate_limit_until} = 0;
423445
$self->{session}{rate_limit_code} = $detected_rate_limit_code;
@@ -506,8 +528,11 @@ sub handle_error_response {
506528

507529
if ($self->{session} && $self->{session}->can('state')) {
508530
my $state = $self->{session}->state();
509-
$state->{rate_limit_until} = 0;
510-
$state->{rate_limit_code} = 'zai_usage_limit';
531+
my $rl_provider = $self->_get_current_provider();
532+
$state->{rate_limits} //= {};
533+
$state->{rate_limits}{$rl_provider} //= {};
534+
$state->{rate_limits}{$rl_provider}{rate_limit_until} = 0;
535+
$state->{rate_limits}{$rl_provider}{rate_limit_code} = 'zai_usage_limit';
511536
# Store human-readable reset time for /usage display
512537
if ($reset_str) {
513538
$state->{zai_reset_time} = $reset_str . " CST";
@@ -895,10 +920,13 @@ sub process_rate_limit_headers {
895920

896921
# Store quota_used in session for UI display (mirrors Broker.pm behavior)
897922
if (defined $rate_limit{quota_used} && $self->{session}) {
923+
my $rl_provider = $self->_get_current_provider();
898924
if ($self->{session}->can('state')) {
899925
my $state = $self->{session}->state();
900-
$state->{rate_limit_quota_used} = $rate_limit{quota_used};
901-
$state->{rate_limit_quota_timestamp} = $rate_limit{quota_timestamp};
926+
$state->{rate_limits} //= {};
927+
$state->{rate_limits}{$rl_provider} //= {};
928+
$state->{rate_limits}{$rl_provider}{rate_limit_quota_used} = $rate_limit{quota_used};
929+
$state->{rate_limits}{$rl_provider}{rate_limit_quota_timestamp} = $rate_limit{quota_timestamp};
902930
} else {
903931
$self->{session}{rate_limit_quota_used} = $rate_limit{quota_used};
904932
$self->{session}{rate_limit_quota_timestamp} = $rate_limit{quota_timestamp};
@@ -982,10 +1010,13 @@ sub process_rate_limit_headers {
9821010
my $retry_after = $rate_limit{retry_after};
9831011
if ($retry_after =~ /^\d+$/) {
9841012
$self->{rate_limit_until} = time() + $retry_after;
985-
# Propagate to session state for /usage display
1013+
# Propagate to session state per-provider for /usage display
1014+
my $rl_provider = $self->_get_current_provider();
9861015
if ($self->{session} && $self->{session}->can('state')) {
9871016
my $state = $self->{session}->state();
988-
$state->{rate_limit_until} = $self->{rate_limit_until};
1017+
$state->{rate_limits} //= {};
1018+
$state->{rate_limits}{$rl_provider} //= {};
1019+
$state->{rate_limits}{$rl_provider}{rate_limit_until} = $self->{rate_limit_until};
9891020
} elsif ($self->{session}) {
9901021
$self->{session}{rate_limit_until} = $self->{rate_limit_until};
9911022
}

lib/CLIO/UI/Commands/Billing.pm

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ Display GitHub Copilot-specific billing with account info, multipliers, and quot
141141

142142
sub _display_copilot_billing {
143143
my ($self, $billing) = @_;
144-
144+
145+
my $provider = 'github_copilot';
146+
145147
# Try cache first, fall back to fresh fetch to ensure current quota data
146148
# This is important when returning from a wait state or at session start
147149
my $user_data;
@@ -239,18 +241,15 @@ sub _display_copilot_billing {
239241
}
240242
}
241243

242-
# Rate limit status section
243-
# Check both session (direct) and session state (persisted)
244-
my $rate_limit_used = $self->{session}{rate_limit_quota_used};
245-
my $rate_limit_until = $self->{session}{rate_limit_until};
246-
my $rate_limit_code = $self->{session}{rate_limit_code};
244+
# Rate limit status section (scoped to current provider)
245+
my ($rate_limit_used, $rate_limit_until, $rate_limit_code);
247246

248-
# Check session state for persisted rate limit info
249247
if ($self->{session}->can('state')) {
250248
my $state = $self->{session}->state();
251-
$rate_limit_used = $state->{rate_limit_quota_used} if !defined $rate_limit_used && $state->{rate_limit_quota_used};
252-
$rate_limit_until = $state->{rate_limit_until} if !$rate_limit_until && $state->{rate_limit_until};
253-
$rate_limit_code = $state->{rate_limit_code} if !$rate_limit_code && $state->{rate_limit_code};
249+
my $rl = $state->{rate_limits} && $state->{rate_limits}{$provider} ? $state->{rate_limits}{$provider} : {};
250+
$rate_limit_used = $rl->{rate_limit_quota_used};
251+
$rate_limit_until = $rl->{rate_limit_until};
252+
$rate_limit_code = $rl->{rate_limit_code};
254253
}
255254

256255
if (defined $rate_limit_used || $rate_limit_until || $rate_limit_code) {
@@ -447,20 +446,18 @@ sub _display_zai_billing {
447446
$self->writeline(sprintf(" %-25s %s", "Quota Window:",
448447
$self->colorize("Rolling 5-hour", 'DATA')), markdown => 0);
449448
$self->writeline("", markdown => 0);
450-
$self->writeline($self->colorize("GLM-5.x models: 3x during peak (14:00-18:00 CST), 2x off-peak.", 'DIM'), markdown => 0);
451-
$self->writeline($self->colorize("Use GLM-4.7 for routine tasks to conserve quota.", 'DIM'), markdown => 0);
452449
}
453-
450+
454451
# Rate limit status section
455-
my $rate_limit_until = $self->{session}{rate_limit_until};
456-
my $rate_limit_code = $self->{session}{rate_limit_code};
457-
452+
my ($rate_limit_until, $rate_limit_code);
453+
458454
if ($self->{session}->can('state')) {
459455
my $state = $self->{session}->state();
460-
$rate_limit_until = $state->{rate_limit_until} if !$rate_limit_until && $state->{rate_limit_until};
461-
$rate_limit_code = $state->{rate_limit_code} if !$rate_limit_code && $state->{rate_limit_code};
456+
my $rl = $state->{rate_limits} && $state->{rate_limits}{$provider} ? $state->{rate_limits}{$provider} : {};
457+
$rate_limit_until = $rl->{rate_limit_until};
458+
$rate_limit_code = $rl->{rate_limit_code};
462459
}
463-
460+
464461
if (defined $rate_limit_until || $rate_limit_code) {
465462
$self->display_section_header("Rate Limit Status");
466463

0 commit comments

Comments
 (0)