tui: only show fast status for gpt-5.4 (#14135)

This commit is contained in:
pash-openai
2026-03-09 21:12:05 -07:00
committed by GitHub
Unverified
parent 244b2d53f4
commit 63597d1b2d
5 changed files with 140 additions and 12 deletions
+31 -2
View File
@@ -918,8 +918,10 @@ impl App {
history_cell::SessionHeaderHistoryCell::new(
self.chat_widget.current_model().to_string(),
self.chat_widget.current_reasoning_effort(),
self.chat_widget
.should_show_fast_status(self.chat_widget.current_service_tier()),
self.chat_widget.should_show_fast_status(
self.chat_widget.current_model(),
self.chat_widget.current_service_tier(),
),
self.config.cwd.clone(),
version,
)
@@ -3790,6 +3792,7 @@ mod tests {
use crate::app_backtrack::BacktrackState;
use crate::app_backtrack::user_count;
use crate::chatwidget::tests::make_chatwidget_manual_with_sender;
use crate::chatwidget::tests::set_chatgpt_auth;
use crate::file_search::FileSearchManager;
use crate::history_cell::AgentMessageCell;
use crate::history_cell::HistoryCell;
@@ -5463,6 +5466,32 @@ mod tests {
assert_snapshot!("clear_ui_after_long_transcript_fresh_header_only", rendered);
}
#[tokio::test]
async fn clear_ui_header_shows_fast_status_only_for_gpt54() {
let mut app = make_test_app().await;
app.config.cwd = PathBuf::from("/tmp/project");
app.chat_widget.set_model("gpt-5.4");
app.chat_widget
.set_reasoning_effort(Some(ReasoningEffortConfig::XHigh));
app.chat_widget
.set_service_tier(Some(codex_protocol::config_types::ServiceTier::Fast));
set_chatgpt_auth(&mut app.chat_widget);
let rendered = app
.clear_ui_header_lines_with_version(80, "<VERSION>")
.iter()
.map(|line| {
line.spans
.iter()
.map(|span| span.content.as_ref())
.collect::<String>()
})
.collect::<Vec<_>>()
.join("\n");
assert_snapshot!("clear_ui_header_fast_status_gpt54_only", rendered);
}
async fn make_test_app() -> App {
let (chat_widget, app_event_tx, _rx, _op_rx) = make_chatwidget_manual_with_sender().await;
let config = chat_widget.config_ref().clone();
+17 -4
View File
@@ -306,6 +306,7 @@ use strum::IntoEnumIterator;
const USER_SHELL_COMMAND_HELP_TITLE: &str = "Prefix a command with ! to run it locally";
const USER_SHELL_COMMAND_HELP_HINT: &str = "Example: !ls";
const DEFAULT_OPENAI_BASE_URL: &str = "https://api.openai.com/v1";
const FAST_STATUS_MODEL: &str = "gpt-5.4";
const DEFAULT_STATUS_LINE_ITEMS: [&str; 3] =
["model-with-reasoning", "context-remaining", "current-dir"];
// Track information about an in-flight exec command.
@@ -1270,7 +1271,7 @@ impl ChatWidget {
self.sync_personality_command_enabled();
self.refresh_plugin_mentions();
let startup_tooltip_override = self.startup_tooltip_override.take();
let show_fast_status = self.should_show_fast_status(event.service_tier);
let show_fast_status = self.should_show_fast_status(&model_for_header, event.service_tier);
let session_info_cell = history_cell::new_session_info(
&self.config,
&model_for_header,
@@ -5424,7 +5425,14 @@ impl ChatWidget {
StatusLineItem::ModelWithReasoning => {
let label =
Self::status_line_reasoning_effort_label(self.effective_reasoning_effort());
Some(format!("{} {label}", self.model_display_name()))
let fast_label = if self
.should_show_fast_status(self.current_model(), self.config.service_tier)
{
" fast"
} else {
""
};
Some(format!("{} {label}{fast_label}", self.model_display_name()))
}
StatusLineItem::CurrentDir => {
Some(format_directory_display(self.status_line_cwd(), None))
@@ -7413,8 +7421,13 @@ impl ChatWidget {
self.config.service_tier
}
pub(crate) fn should_show_fast_status(&self, service_tier: Option<ServiceTier>) -> bool {
matches!(service_tier, Some(ServiceTier::Fast))
pub(crate) fn should_show_fast_status(
&self,
model: &str,
service_tier: Option<ServiceTier>,
) -> bool {
model == FAST_STATUS_MODEL
&& matches!(service_tier, Some(ServiceTier::Fast))
&& self
.auth_manager
.auth_cached()
@@ -0,0 +1,9 @@
---
source: tui/src/chatwidget/tests.rs
expression: terminal.backend()
---
" "
" "
" Ask Codex to do anything "
" "
" gpt-5.4 xhigh fast · 100% left · /tmp/project "
+73 -6
View File
@@ -1934,7 +1934,7 @@ fn assert_no_submit_op(op_rx: &mut tokio::sync::mpsc::UnboundedReceiver<Op>) {
}
}
fn set_chatgpt_auth(chat: &mut ChatWidget) {
pub(crate) fn set_chatgpt_auth(chat: &mut ChatWidget) {
chat.auth_manager = codex_core::test_support::auth_manager_from_auth(
CodexAuth::create_dummy_chatgpt_auth_for_testing(),
);
@@ -7787,22 +7787,31 @@ async fn user_turn_carries_service_tier_after_fast_toggle() {
#[tokio::test]
async fn fast_status_indicator_requires_chatgpt_auth() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.4")).await;
chat.set_service_tier(Some(ServiceTier::Fast));
assert!(!chat.should_show_fast_status(chat.current_service_tier()));
assert!(!chat.should_show_fast_status(chat.current_model(), chat.current_service_tier(),));
set_chatgpt_auth(&mut chat);
assert!(chat.should_show_fast_status(chat.current_service_tier()));
assert!(chat.should_show_fast_status(chat.current_model(), chat.current_service_tier(),));
}
#[tokio::test]
async fn fast_status_indicator_is_hidden_for_non_gpt54_model() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
chat.set_service_tier(Some(ServiceTier::Fast));
set_chatgpt_auth(&mut chat);
assert!(!chat.should_show_fast_status(chat.current_model(), chat.current_service_tier(),));
}
#[tokio::test]
async fn fast_status_indicator_is_hidden_when_fast_mode_is_off() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.3-codex")).await;
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.4")).await;
set_chatgpt_auth(&mut chat);
assert!(!chat.should_show_fast_status(chat.current_service_tier()));
assert!(!chat.should_show_fast_status(chat.current_model(), chat.current_service_tier(),));
}
#[tokio::test]
@@ -9552,6 +9561,64 @@ async fn status_line_fast_mode_footer_snapshot() {
assert_snapshot!("status_line_fast_mode_footer", terminal.backend());
}
#[tokio::test]
async fn status_line_model_with_reasoning_includes_fast_for_gpt54_only() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.4")).await;
chat.config.cwd = PathBuf::from("/tmp/project");
chat.config.tui_status_line = Some(vec![
"model-with-reasoning".to_string(),
"context-remaining".to_string(),
"current-dir".to_string(),
]);
chat.set_reasoning_effort(Some(ReasoningEffortConfig::XHigh));
chat.set_service_tier(Some(ServiceTier::Fast));
set_chatgpt_auth(&mut chat);
chat.refresh_status_line();
assert_eq!(
status_line_text(&chat),
Some("gpt-5.4 xhigh fast · 100% left · /tmp/project".to_string())
);
chat.set_model("gpt-5.3-codex");
chat.refresh_status_line();
assert_eq!(
status_line_text(&chat),
Some("gpt-5.3-codex xhigh · 100% left · /tmp/project".to_string())
);
}
#[tokio::test]
async fn status_line_model_with_reasoning_fast_footer_snapshot() {
use ratatui::Terminal;
use ratatui::backend::TestBackend;
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(Some("gpt-5.4")).await;
chat.show_welcome_banner = false;
chat.config.cwd = PathBuf::from("/tmp/project");
chat.config.tui_status_line = Some(vec![
"model-with-reasoning".to_string(),
"context-remaining".to_string(),
"current-dir".to_string(),
]);
chat.set_reasoning_effort(Some(ReasoningEffortConfig::XHigh));
chat.set_service_tier(Some(ServiceTier::Fast));
set_chatgpt_auth(&mut chat);
chat.refresh_status_line();
let width = 80;
let height = chat.desired_height(width);
let mut terminal = Terminal::new(TestBackend::new(width, height)).expect("create terminal");
terminal
.draw(|f| chat.render(f.area(), f.buffer_mut()))
.expect("draw model-with-reasoning footer");
assert_snapshot!(
"status_line_model_with_reasoning_fast_footer",
terminal.backend()
);
}
#[tokio::test]
async fn stream_recovery_restores_previous_status_header() {
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual(None).await;
@@ -0,0 +1,10 @@
---
source: tui/src/app.rs
expression: rendered
---
╭────────────────────────────────────────────────────╮
│ >_ OpenAI Codex (v<VERSION>) │
│ │
│ model: gpt-5.4 xhigh fast /model to change │
│ directory: /tmp/project │
╰────────────────────────────────────────────────────╯