mirror of
https://github.com/openai/codex.git
synced 2026-10-19 17:28:46 +00:00
Add compaction counts to TUI status line and title
This commit is contained in:
@@ -139,6 +139,7 @@ fn terminal_title_item_id(item: &str) -> Option<&'static str> {
|
||||
"used-tokens" => Some("used-tokens"),
|
||||
"total-input-tokens" => Some("total-input-tokens"),
|
||||
"total-output-tokens" => Some("total-output-tokens"),
|
||||
"compactions" => Some("compactions"),
|
||||
"thread-id" | "session-id" => Some("thread-id"),
|
||||
"fast-mode" => Some("fast-mode"),
|
||||
"model" | "model-name" => Some("model"),
|
||||
|
||||
@@ -1125,22 +1125,34 @@ async fn replayed_interrupted_turn_restores_queued_input_to_composer() {
|
||||
async fn token_usage_update_refreshes_status_line_with_runtime_context_window() {
|
||||
let mut app = make_test_app().await;
|
||||
app.chat_widget.setup_status_line(
|
||||
vec![crate::bottom_pane::StatusLineItem::ContextWindowSize],
|
||||
vec![
|
||||
crate::bottom_pane::StatusLineItem::ContextWindowSize,
|
||||
crate::bottom_pane::StatusLineItem::Compactions,
|
||||
],
|
||||
/*use_theme_colors*/ true,
|
||||
);
|
||||
app.chat_widget
|
||||
.setup_terminal_title(vec![crate::bottom_pane::TerminalTitleItem::Compactions]);
|
||||
|
||||
assert_eq!(app.chat_widget.status_line_text(), None);
|
||||
assert_eq!(
|
||||
app.chat_widget.status_line_text(),
|
||||
Some("0 compactions".into())
|
||||
);
|
||||
|
||||
app.handle_thread_event_now(ThreadBufferedEvent::Notification(token_usage_notification(
|
||||
ThreadId::new(),
|
||||
"turn-1",
|
||||
Some(950_000),
|
||||
/*window_number*/ 0,
|
||||
/*window_number*/ 3,
|
||||
)));
|
||||
|
||||
assert_eq!(
|
||||
app.chat_widget.status_line_text(),
|
||||
Some("950K window".into())
|
||||
Some("950K window · 3 compactions".into())
|
||||
);
|
||||
assert_eq!(
|
||||
app.chat_widget.last_terminal_title,
|
||||
Some("3 compactions".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//! - Context usage (remaining %, used %, window size)
|
||||
//! - Usage limits (primary, secondary)
|
||||
//! - Session info (thread title, thread ID, tokens used)
|
||||
//! - Context compaction count
|
||||
//! - Application version
|
||||
|
||||
use ratatui::buffer::Buffer;
|
||||
@@ -124,6 +125,9 @@ pub(crate) enum StatusLineItem {
|
||||
/// Total output tokens generated.
|
||||
TotalOutputTokens,
|
||||
|
||||
/// Number of context compactions in the current thread.
|
||||
Compactions,
|
||||
|
||||
/// Full thread UUID.
|
||||
#[strum(to_string = "thread-id", serialize = "session-id")]
|
||||
SessionId,
|
||||
@@ -182,6 +186,7 @@ impl StatusLineItem {
|
||||
StatusLineItem::UsedTokens => "Total tokens used in session (omitted when zero)",
|
||||
StatusLineItem::TotalInputTokens => "Total input tokens used in session",
|
||||
StatusLineItem::TotalOutputTokens => "Total output tokens used in session",
|
||||
StatusLineItem::Compactions => "Number of context compactions in the current thread",
|
||||
StatusLineItem::SessionId => "Current thread identifier (omitted until thread starts)",
|
||||
StatusLineItem::FastMode => "Whether Fast mode is currently active",
|
||||
StatusLineItem::RawOutput => "Whether raw scrollback mode is active",
|
||||
@@ -219,6 +224,7 @@ impl StatusLineItem {
|
||||
StatusLineItem::UsedTokens => StatusSurfacePreviewItem::UsedTokens,
|
||||
StatusLineItem::TotalInputTokens => StatusSurfacePreviewItem::TotalInputTokens,
|
||||
StatusLineItem::TotalOutputTokens => StatusSurfacePreviewItem::TotalOutputTokens,
|
||||
StatusLineItem::Compactions => StatusSurfacePreviewItem::Compactions,
|
||||
StatusLineItem::SessionId => StatusSurfacePreviewItem::SessionId,
|
||||
StatusLineItem::FastMode => StatusSurfacePreviewItem::FastMode,
|
||||
StatusLineItem::RawOutput => StatusSurfacePreviewItem::RawOutput,
|
||||
|
||||
@@ -43,7 +43,8 @@ impl StatusLineAccent {
|
||||
| StatusLineItem::ContextWindowSize
|
||||
| StatusLineItem::UsedTokens
|
||||
| StatusLineItem::TotalInputTokens
|
||||
| StatusLineItem::TotalOutputTokens => Self::Usage,
|
||||
| StatusLineItem::TotalOutputTokens
|
||||
| StatusLineItem::Compactions => Self::Usage,
|
||||
StatusLineItem::FiveHourLimit | StatusLineItem::WeeklyLimit => Self::Limit,
|
||||
StatusLineItem::CodexVersion | StatusLineItem::SessionId => Self::Metadata,
|
||||
StatusLineItem::FastMode | StatusLineItem::RawOutput => Self::Mode,
|
||||
|
||||
@@ -27,6 +27,7 @@ pub(crate) enum StatusSurfacePreviewItem {
|
||||
UsedTokens,
|
||||
TotalInputTokens,
|
||||
TotalOutputTokens,
|
||||
Compactions,
|
||||
SessionId,
|
||||
FastMode,
|
||||
RawOutput,
|
||||
@@ -60,6 +61,7 @@ impl StatusSurfacePreviewItem {
|
||||
StatusSurfacePreviewItem::UsedTokens => "0 used",
|
||||
StatusSurfacePreviewItem::TotalInputTokens => "0 in",
|
||||
StatusSurfacePreviewItem::TotalOutputTokens => "0 out",
|
||||
StatusSurfacePreviewItem::Compactions => "0 compactions",
|
||||
StatusSurfacePreviewItem::SessionId => "550e8400-e29b-41d4",
|
||||
StatusSurfacePreviewItem::FastMode => "Fast on",
|
||||
StatusSurfacePreviewItem::RawOutput => "raw output",
|
||||
@@ -93,6 +95,7 @@ impl StatusSurfacePreviewItem {
|
||||
Self::UsedTokens,
|
||||
Self::TotalInputTokens,
|
||||
Self::TotalOutputTokens,
|
||||
Self::Compactions,
|
||||
Self::SessionId,
|
||||
Self::FastMode,
|
||||
Self::RawOutput,
|
||||
|
||||
@@ -72,6 +72,8 @@ pub(crate) enum TerminalTitleItem {
|
||||
TotalInputTokens,
|
||||
/// Total output tokens generated.
|
||||
TotalOutputTokens,
|
||||
/// Number of context compactions in the current thread.
|
||||
Compactions,
|
||||
/// Full thread UUID.
|
||||
#[strum(to_string = "thread-id", serialize = "session-id")]
|
||||
SessionId,
|
||||
@@ -118,6 +120,7 @@ impl TerminalTitleItem {
|
||||
TerminalTitleItem::UsedTokens => "Total tokens used in session (omitted when zero)",
|
||||
TerminalTitleItem::TotalInputTokens => "Total input tokens used in session",
|
||||
TerminalTitleItem::TotalOutputTokens => "Total output tokens used in session",
|
||||
TerminalTitleItem::Compactions => "Number of context compactions in the current thread",
|
||||
TerminalTitleItem::SessionId => {
|
||||
"Current thread identifier (omitted until thread starts)"
|
||||
}
|
||||
@@ -150,6 +153,7 @@ impl TerminalTitleItem {
|
||||
TerminalTitleItem::TotalOutputTokens => {
|
||||
Some(StatusSurfacePreviewItem::TotalOutputTokens)
|
||||
}
|
||||
TerminalTitleItem::Compactions => Some(StatusSurfacePreviewItem::Compactions),
|
||||
TerminalTitleItem::SessionId => Some(StatusSurfacePreviewItem::SessionId),
|
||||
TerminalTitleItem::FastMode => Some(StatusSurfacePreviewItem::FastMode),
|
||||
TerminalTitleItem::Model => Some(StatusSurfacePreviewItem::Model),
|
||||
|
||||
@@ -551,7 +551,6 @@ pub(crate) struct ChatWidget {
|
||||
runtime_model_provider_base_url: Option<String>,
|
||||
pub(crate) remote_connection: Option<RemoteConnectionStatus>,
|
||||
token_info: Option<TokenUsageInfo>,
|
||||
#[cfg_attr(not(test), allow(dead_code))]
|
||||
window_number: u64,
|
||||
rate_limit_snapshots_by_limit_id: BTreeMap<String, RateLimitSnapshotDisplay>,
|
||||
refreshing_status_outputs: Vec<(u64, StatusHistoryHandle)>,
|
||||
|
||||
+2
-2
@@ -12,9 +12,9 @@ expression: status_line_popup_snapshot(&mut chat)
|
||||
[x] project-name Project name (omitted when unavailable)
|
||||
[x] git-branch Current Git branch (omitted when unavailable)
|
||||
[x] thread-title Current thread title, or thread identifier when unnamed
|
||||
[x] compactions Number of context compactions in the current thread
|
||||
[ ] model Current model name
|
||||
[ ] model-with-reasoning Current model name with reasoning level
|
||||
[ ] reasoning Current reasoning level
|
||||
|
||||
preview-live-root · feature/live-preview-branch · Live preview thread
|
||||
preview-live-root · feature/live-preview-branch · Live preview thread · 3 compactions
|
||||
Press space to toggle; ←/→ to move; enter to confirm and close; esc to close
|
||||
|
||||
+2
-2
@@ -2,5 +2,5 @@
|
||||
source: tui/src/chatwidget/tests/status_surface_previews.rs
|
||||
expression: snapshot
|
||||
---
|
||||
status line: preview-live-root · feature/live-preview-branch · Live preview thread
|
||||
terminal title: preview-live-root | Live preview thread | feature/live-preview-branch | Tasks 2/5
|
||||
status line: preview-live-root · feature/live-preview-branch · Live preview thread · 3 compactions
|
||||
terminal title: preview-live-root | Live preview thread | feature/live-preview-branch | Tasks 2/5 | 3 compactions
|
||||
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
---
|
||||
source: tui/src/chatwidget/tests/status_surface_previews.rs
|
||||
expression: terminal_title_popup_snapshot(&mut chat)
|
||||
---
|
||||
Configure Terminal Title
|
||||
Select which items to display in the terminal title.
|
||||
|
||||
Type to search
|
||||
>
|
||||
› [x] app-name Codex app name
|
||||
[x] model Current model name
|
||||
[x] reasoning Current reasoning level
|
||||
[x] fast-mode Whether Fast mode is currently active
|
||||
[x] compactions Number of context compactions in the current thread
|
||||
[ ] project-name Project name (falls back to current directory name)
|
||||
[ ] current-dir Current working directory
|
||||
[ ] activity Spinner while working, action-required message while blocked.
|
||||
|
||||
codex | gpt-5.5 | default | Fast off | 3 compactions
|
||||
Press space to toggle; ←/→ to move; enter to confirm and close; esc to close
|
||||
@@ -727,6 +727,7 @@ impl ChatWidget {
|
||||
"{} out",
|
||||
format_tokens_compact(self.status_line_total_usage().output_tokens)
|
||||
)),
|
||||
StatusLineItem::Compactions => Some(format!("{} compactions", self.window_number)),
|
||||
StatusLineItem::SessionId => self.thread_id.map(|id| id.to_string()),
|
||||
StatusLineItem::FastMode => Some(
|
||||
if self.current_service_tier() == Some(ServiceTier::Fast.request_value()) {
|
||||
@@ -785,6 +786,7 @@ impl ChatWidget {
|
||||
StatusSurfacePreviewItem::UsedTokens => StatusLineItem::UsedTokens,
|
||||
StatusSurfacePreviewItem::TotalInputTokens => StatusLineItem::TotalInputTokens,
|
||||
StatusSurfacePreviewItem::TotalOutputTokens => StatusLineItem::TotalOutputTokens,
|
||||
StatusSurfacePreviewItem::Compactions => StatusLineItem::Compactions,
|
||||
StatusSurfacePreviewItem::SessionId => StatusLineItem::SessionId,
|
||||
StatusSurfacePreviewItem::FastMode => StatusLineItem::FastMode,
|
||||
StatusSurfacePreviewItem::RawOutput => StatusLineItem::RawOutput,
|
||||
@@ -843,6 +845,9 @@ impl ChatWidget {
|
||||
TerminalTitleItem::TotalOutputTokens => self
|
||||
.status_line_value_for_item(StatusLineItem::TotalOutputTokens)
|
||||
.map(|value| Self::truncate_terminal_title_part(value, /*max_chars*/ 32)),
|
||||
TerminalTitleItem::Compactions => self
|
||||
.status_line_value_for_item(StatusLineItem::Compactions)
|
||||
.map(|value| Self::truncate_terminal_title_part(value, /*max_chars*/ 32)),
|
||||
TerminalTitleItem::SessionId => self
|
||||
.status_line_value_for_item(StatusLineItem::SessionId)
|
||||
.map(|value| Self::truncate_terminal_title_part(value, /*max_chars*/ 32)),
|
||||
|
||||
@@ -89,6 +89,13 @@ async fn status_surface_preview_lines_live_only_snapshot() {
|
||||
chat.status_line_branch = Some("feature/live-preview-branch".to_string());
|
||||
chat.thread_name = Some("Live preview thread".to_string());
|
||||
chat.transcript.last_plan_progress = Some((2, 5));
|
||||
handle_token_count_with_window_number(
|
||||
&mut chat,
|
||||
Some(make_token_info(
|
||||
/*total_tokens*/ 1, /*context_window*/ 100,
|
||||
)),
|
||||
/*window_number*/ 3,
|
||||
);
|
||||
|
||||
let snapshot = combined_preview_snapshot(
|
||||
&mut chat,
|
||||
@@ -96,12 +103,14 @@ async fn status_surface_preview_lines_live_only_snapshot() {
|
||||
StatusLineItem::ProjectRoot,
|
||||
StatusLineItem::GitBranch,
|
||||
StatusLineItem::ThreadTitle,
|
||||
StatusLineItem::Compactions,
|
||||
],
|
||||
&[
|
||||
TerminalTitleItem::Project,
|
||||
TerminalTitleItem::Thread,
|
||||
TerminalTitleItem::GitBranch,
|
||||
TerminalTitleItem::TaskProgress,
|
||||
TerminalTitleItem::Compactions,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -114,10 +123,18 @@ async fn status_line_setup_popup_live_only_snapshot() {
|
||||
cache_project_root(&mut chat, "preview-live-root");
|
||||
chat.status_line_branch = Some("feature/live-preview-branch".to_string());
|
||||
chat.thread_name = Some("Live preview thread".to_string());
|
||||
handle_token_count_with_window_number(
|
||||
&mut chat,
|
||||
Some(make_token_info(
|
||||
/*total_tokens*/ 1, /*context_window*/ 100,
|
||||
)),
|
||||
/*window_number*/ 3,
|
||||
);
|
||||
chat.config.tui_status_line = Some(vec![
|
||||
"project-name".to_string(),
|
||||
"git-branch".to_string(),
|
||||
"thread-title".to_string(),
|
||||
"compactions".to_string(),
|
||||
]);
|
||||
|
||||
assert_chatwidget_snapshot!(
|
||||
@@ -326,6 +343,30 @@ async fn terminal_title_setup_popup_live_only_snapshot() {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn terminal_title_setup_popup_compactions_snapshot() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
handle_token_count_with_window_number(
|
||||
&mut chat,
|
||||
Some(make_token_info(
|
||||
/*total_tokens*/ 1, /*context_window*/ 100,
|
||||
)),
|
||||
/*window_number*/ 3,
|
||||
);
|
||||
chat.config.tui_terminal_title = Some(vec![
|
||||
"app-name".to_string(),
|
||||
"model".to_string(),
|
||||
"reasoning".to_string(),
|
||||
"fast-mode".to_string(),
|
||||
"compactions".to_string(),
|
||||
]);
|
||||
|
||||
assert_chatwidget_snapshot!(
|
||||
"terminal_title_setup_popup_compactions",
|
||||
terminal_title_popup_snapshot(&mut chat)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn terminal_title_setup_popup_hardcoded_only_snapshot() {
|
||||
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
|
||||
|
||||
Reference in New Issue
Block a user