mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] suppress low usage remaining warnings when credits are available (#28593)
## Why The TUI computed proactive `Heads up, you have less than ...` warnings before considering workspace credits. As a result, users could see included-limit warnings even when they could continue using Codex with workspace credits. `has_credits` alone is not sufficient to determine whether finite credits are usable: a spend-control hard limit can cap the reported balance to zero while `has_credits` still reflects the workspace's raw balance. Unlimited credits are the opposite case: they are usable even though no numeric balance is reported. ## What changed - suppress proactive TUI rate-limit usage warnings and the lower-cost model nudge when usable workspace credits are available - treat credits as usable when `has_credits` is true and either `unlimited` is true or the parsed balance is positive - continue showing warnings when the usable balance is zero, including when a spend-control limit has capped otherwise available workspace credits - add regression coverage for zero-balance, positive-balance, and unlimited workspace-credit snapshots ## Validation - `just test -p codex-tui rate_limit_usage_warnings_`
This commit is contained in:
committed by
GitHub
Unverified
parent
a781761eda
commit
5013d10824
@@ -210,7 +210,19 @@ impl ChatWidget {
|
||||
{
|
||||
self.codex_rate_limit_reached_type = Some(rate_limit_reached_type);
|
||||
}
|
||||
let warnings = if is_codex_limit {
|
||||
|
||||
let has_workspace_credits = snapshot.credits.as_ref().is_some_and(|credits| {
|
||||
credits.has_credits
|
||||
&& (credits.unlimited
|
||||
|| credits.balance.as_deref().is_some_and(|balance| {
|
||||
balance
|
||||
.trim()
|
||||
.parse::<f64>()
|
||||
.is_ok_and(|balance| balance > 0.0)
|
||||
}))
|
||||
});
|
||||
let should_warn_about_rate_limit_usage = is_codex_limit && !has_workspace_credits;
|
||||
let warnings = if should_warn_about_rate_limit_usage {
|
||||
self.rate_limit_warnings.take_warnings(
|
||||
snapshot
|
||||
.secondary
|
||||
@@ -245,12 +257,6 @@ impl ChatWidget {
|
||||
.map(|w| f64::from(w.used_percent) >= RATE_LIMIT_SWITCH_PROMPT_THRESHOLD)
|
||||
.unwrap_or(false));
|
||||
|
||||
let has_workspace_credits = snapshot
|
||||
.credits
|
||||
.as_ref()
|
||||
.map(|credits| credits.has_credits)
|
||||
.unwrap_or(false);
|
||||
|
||||
if high_usage
|
||||
&& !has_workspace_credits
|
||||
&& !self.rate_limit_switch_prompt_hidden()
|
||||
|
||||
@@ -1009,6 +1009,82 @@ async fn rate_limit_switch_prompt_skips_non_codex_limit() {
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn rate_limit_usage_warnings_show_when_workspace_credits_zero_balance() {
|
||||
let (mut chat, mut rx, _) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.has_chatgpt_account = true;
|
||||
|
||||
let mut rate_limit_snapshot = snapshot(/*percent*/ 95.0);
|
||||
rate_limit_snapshot.credits = Some(CreditsSnapshot {
|
||||
has_credits: true,
|
||||
unlimited: false,
|
||||
balance: Some("0".to_string()),
|
||||
});
|
||||
|
||||
chat.on_rate_limit_snapshot(Some(rate_limit_snapshot));
|
||||
|
||||
assert!(
|
||||
!drain_insert_history(&mut rx).is_empty(),
|
||||
"zero-balance workspace credits should not suppress proactive usage warnings"
|
||||
);
|
||||
assert!(matches!(
|
||||
chat.rate_limit_switch_prompt,
|
||||
RateLimitSwitchPromptState::Pending
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn rate_limit_usage_warnings_skip_when_workspace_credits_are_available() {
|
||||
let (mut chat, mut rx, _) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.has_chatgpt_account = true;
|
||||
|
||||
let mut rate_limit_snapshot = snapshot(/*percent*/ 95.0);
|
||||
rate_limit_snapshot.credits = Some(CreditsSnapshot {
|
||||
has_credits: true,
|
||||
unlimited: false,
|
||||
balance: Some("25.00".to_string()),
|
||||
});
|
||||
|
||||
chat.on_rate_limit_snapshot(Some(rate_limit_snapshot));
|
||||
|
||||
assert!(
|
||||
drain_insert_history(&mut rx).is_empty(),
|
||||
"workspace credits should suppress proactive usage warnings"
|
||||
);
|
||||
assert!(matches!(
|
||||
chat.rate_limit_switch_prompt,
|
||||
RateLimitSwitchPromptState::Idle
|
||||
));
|
||||
assert_eq!(
|
||||
chat.rate_limit_warnings.primary_index, 0,
|
||||
"suppressed warnings should not consume warning thresholds"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn rate_limit_usage_warnings_skip_with_unlimited_workspace_credits() {
|
||||
let (mut chat, mut rx, _) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
chat.has_chatgpt_account = true;
|
||||
|
||||
let mut rate_limit_snapshot = snapshot(/*percent*/ 95.0);
|
||||
rate_limit_snapshot.credits = Some(CreditsSnapshot {
|
||||
has_credits: true,
|
||||
unlimited: true,
|
||||
balance: None,
|
||||
});
|
||||
|
||||
chat.on_rate_limit_snapshot(Some(rate_limit_snapshot));
|
||||
|
||||
assert!(
|
||||
drain_insert_history(&mut rx).is_empty(),
|
||||
"unlimited workspace credits should suppress proactive usage warnings"
|
||||
);
|
||||
assert!(matches!(
|
||||
chat.rate_limit_switch_prompt,
|
||||
RateLimitSwitchPromptState::Idle
|
||||
));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn rate_limit_switch_prompt_shows_once_per_session() {
|
||||
let (mut chat, _, _) = make_chatwidget_manual(Some("gpt-5")).await;
|
||||
|
||||
Reference in New Issue
Block a user