mirror of
https://github.com/openai/codex.git
synced 2026-05-20 03:05:02 +00:00
## Why This stack moves `codex-tui` away from the core protocol event surface and toward app-server API shapes plus TUI-owned local models. This first PR sets up the lower-risk foundation: it introduces the local model surface and extracts app-server event routing into focused TUI modules while preserving the existing behavior for the larger migration in PR2. This PR is part 1 of a 2-PR stack: 1. Add TUI-owned replacement models and extract app-server event routing. 2. Move the active TUI flow to app-server notifications and delete obsolete adapter code. ## What changed - Added TUI-owned approval, diff, session state, session resume, token usage, and user-message models. - Added `app/app_server_event_targets.rs` and `app/app_server_events.rs` to hold app-server event targeting and dispatch logic outside `app.rs`. - Updated app/status tests to use the local model layer and added focused routing coverage. - Boxed a few large async TUI test futures so this base layer remains checkable without overflowing the default test stack. ## Verification - `cargo check -p codex-tui --tests`
88 lines
2.6 KiB
Rust
88 lines
2.6 KiB
Rust
//! TUI token usage models and display formatting.
|
|
|
|
use std::fmt;
|
|
|
|
use codex_protocol::num_format::format_with_separators;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
|
|
const BASELINE_TOKENS: i64 = 12000;
|
|
|
|
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub struct TokenUsage {
|
|
pub input_tokens: i64,
|
|
pub cached_input_tokens: i64,
|
|
pub output_tokens: i64,
|
|
pub reasoning_output_tokens: i64,
|
|
pub total_tokens: i64,
|
|
}
|
|
|
|
impl TokenUsage {
|
|
pub fn is_zero(&self) -> bool {
|
|
self.total_tokens == 0
|
|
}
|
|
|
|
pub(crate) fn cached_input(&self) -> i64 {
|
|
self.cached_input_tokens.max(0)
|
|
}
|
|
|
|
pub(crate) fn non_cached_input(&self) -> i64 {
|
|
(self.input_tokens - self.cached_input()).max(0)
|
|
}
|
|
|
|
pub(crate) fn blended_total(&self) -> i64 {
|
|
(self.non_cached_input() + self.output_tokens.max(0)).max(0)
|
|
}
|
|
|
|
pub(crate) fn tokens_in_context_window(&self) -> i64 {
|
|
self.total_tokens
|
|
}
|
|
|
|
pub(crate) fn percent_of_context_window_remaining(&self, context_window: i64) -> i64 {
|
|
if context_window <= BASELINE_TOKENS {
|
|
return 0;
|
|
}
|
|
let effective_window = context_window - BASELINE_TOKENS;
|
|
let used = (self.tokens_in_context_window() - BASELINE_TOKENS).max(0);
|
|
let remaining = (effective_window - used).max(0);
|
|
((remaining as f64 / effective_window as f64) * 100.0)
|
|
.clamp(0.0, 100.0)
|
|
.round() as i64
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub(crate) struct TokenUsageInfo {
|
|
pub(crate) total_token_usage: TokenUsage,
|
|
pub(crate) last_token_usage: TokenUsage,
|
|
pub(crate) model_context_window: Option<i64>,
|
|
}
|
|
|
|
impl fmt::Display for TokenUsage {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
write!(
|
|
f,
|
|
"Token usage: total={} input={}{} output={}{}",
|
|
format_with_separators(self.blended_total()),
|
|
format_with_separators(self.non_cached_input()),
|
|
if self.cached_input() > 0 {
|
|
format!(
|
|
" (+ {} cached)",
|
|
format_with_separators(self.cached_input())
|
|
)
|
|
} else {
|
|
String::new()
|
|
},
|
|
format_with_separators(self.output_tokens),
|
|
if self.reasoning_output_tokens > 0 {
|
|
format!(
|
|
" (reasoning {})",
|
|
format_with_separators(self.reasoning_output_tokens)
|
|
)
|
|
} else {
|
|
String::new()
|
|
}
|
|
)
|
|
}
|
|
}
|