Files
codex/codex-rs/tui/src/local_settings.rs
T
Eric Traut 9d57be71ba Separate TUI preferences from server configuration (#42202)
## Why

TUI preferences and persistence paths belong to the local client, while thread
configuration and account requirements may come from the active app server.
Keeping both in the same resolved `Config` can replace live local preferences
when a thread is resumed, forked, reconnected, or switched.

## What changed

- Add `LocalSettings` as the TUI-owned source for UI, history, notice, and local
  persistence settings, and preserve it across session lifecycle transitions.
- Write preference changes to the selected user config file and reload local
  settings from disk when changing roots.
- Use the app server's account response for authentication-dependent onboarding
  and status UI instead of the local model-provider configuration.
- Retain platform family and OS metadata reported by remote app servers.

## Testing

- Cover local setting defaults, overrides, persistence destinations, reloads,
  and preservation across widget replacement and root switching.
- Cover remote platform metadata and server-controlled authentication UI.

GitOrigin-RevId: dbc2965fb1d6cbecb3f973f6133f3dcd4467b753
2026-09-02 04:20:38 +00:00

79 lines
3.3 KiB
Rust

//! Client-owned preferences and persistence paths, independent of active server settings.
//!
//! The resolved core config is a temporary input at local load/reload boundaries. Server thread
//! responses must never refresh these values; live preference changes belong here. The remaining
//! Config-based lifecycle adapters also use this conversion until their interfaces are migrated.
use crate::legacy_core::config::Config;
use crate::legacy_core::config::TerminalResizeReflowConfig;
use crate::legacy_core::config::TerminalResizeReflowMaxRows;
use codex_config::types::History;
use codex_config::types::Notice;
use codex_config::types::Tui;
use codex_utils_absolute_path::AbsolutePathBuf;
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct LocalSettings {
pub(crate) tui: Tui,
pub(crate) history: History,
pub(crate) notices: Notice,
pub(crate) codex_home: AbsolutePathBuf,
pub(crate) user_config_path: AbsolutePathBuf,
}
impl From<&Config> for LocalSettings {
fn from(config: &Config) -> Self {
Self {
tui: Tui {
notification_settings: config.tui_notifications.clone(),
animations: config.animations,
show_tooltips: config.show_tooltips,
auto_recap: config.tui_auto_recap,
disable_paste_burst: Some(config.disable_paste_burst),
vim_mode_default: config.tui_vim_mode_default,
raw_output_mode: config.tui_raw_output_mode,
alternate_screen: config.tui_alternate_screen,
status_line: config.tui_status_line.clone(),
status_line_use_colors: config.tui_status_line_use_colors,
terminal_title: config.tui_terminal_title.clone(),
theme: config.tui_theme.clone(),
pet: config.tui_pet.clone(),
pet_anchor: config.tui_pet_anchor,
session_picker_view: Some(config.tui_session_picker_view),
resume_cwd: config.tui_resume_cwd,
keymap: config.tui_keymap.clone(),
model_availability_nux: config.model_availability_nux.clone(),
terminal_resize_reflow_max_rows: match config.terminal_resize_reflow.max_rows {
TerminalResizeReflowMaxRows::Auto => None,
TerminalResizeReflowMaxRows::Disabled => Some(0),
TerminalResizeReflowMaxRows::Limit(rows) => Some(rows),
},
},
history: config.history.clone(),
notices: config.notices.clone(),
codex_home: config.codex_home.clone(),
user_config_path: config
.config_layer_stack
.get_user_config_file()
.cloned()
.unwrap_or_else(|| config.codex_home.join("config.toml")),
}
}
}
impl LocalSettings {
pub(crate) fn terminal_resize_reflow(&self) -> TerminalResizeReflowConfig {
TerminalResizeReflowConfig {
max_rows: match self.tui.terminal_resize_reflow_max_rows {
None => TerminalResizeReflowMaxRows::Auto,
Some(0) => TerminalResizeReflowMaxRows::Disabled,
Some(rows) => TerminalResizeReflowMaxRows::Limit(rows),
},
}
}
}
#[cfg(test)]
#[path = "local_settings_tests.rs"]
mod tests;