diff --git a/codex-rs/tui/src/config_update.rs b/codex-rs/tui/src/config_update.rs index 9d73bb1a2a..16ade0400c 100644 --- a/codex-rs/tui/src/config_update.rs +++ b/codex-rs/tui/src/config_update.rs @@ -122,6 +122,10 @@ pub(crate) fn build_memory_settings_edits( ] } +pub(crate) fn build_oss_provider_edit(provider: &str) -> ConfigEdit { + replace_config_value("oss_provider", serde_json::json!(provider)) +} + pub(crate) async fn write_config_batch( request_handle: AppServerRequestHandle, edits: Vec, diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index 2683d3796a..33b79b2785 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -1002,6 +1002,7 @@ pub async fn run_main( ) .await; + let mut manually_selected_oss_provider = None; let model_provider_override = if cli.oss { let resolved = resolve_oss_provider(cli.oss_provider.as_deref(), &config_toml); @@ -1009,12 +1010,16 @@ pub async fn run_main( Some(provider) } else { // No provider configured, prompt the user - let provider = oss_selection::select_oss_provider(&codex_home).await?; + let selection = oss_selection::select_oss_provider().await?; + let provider = selection.provider; if provider == "__CANCELLED__" { return Err(std::io::Error::other( "OSS provider selection was cancelled by user", )); } + if selection.manually_selected { + manually_selected_oss_provider = Some(provider.clone()); + } Some(provider) } } else { @@ -1256,6 +1261,7 @@ pub async fn run_main( app_server_target, remote_cwd_override, config, + manually_selected_oss_provider, overrides, cli_kv_overrides, cloud_requirements, @@ -1277,6 +1283,7 @@ async fn run_ratatui_app( app_server_target: AppServerTarget, remote_cwd_override: Option, initial_config: Config, + manually_selected_oss_provider: Option, overrides: ConfigOverrides, cli_kv_overrides: Vec<(String, toml::Value)>, mut cloud_requirements: CloudRequirementsLoader, @@ -1356,6 +1363,19 @@ async fn run_ratatui_app( } } .with_remote_cwd_override(remote_cwd_override.clone()); + if let Some(provider) = manually_selected_oss_provider.as_deref() + && let Err(err) = config_update::write_config_batch( + app_server_session.request_handle(), + vec![config_update::build_oss_provider_edit(provider)], + ) + .await + { + warn!( + %err, + provider, + "Failed to persist selected OSS provider preference" + ); + } let mut app_server = Some(app_server_session); let should_show_trust_screen_flag = diff --git a/codex-rs/tui/src/oss_selection.rs b/codex-rs/tui/src/oss_selection.rs index ab9176ffbe..cbb8e676f2 100644 --- a/codex-rs/tui/src/oss_selection.rs +++ b/codex-rs/tui/src/oss_selection.rs @@ -4,7 +4,6 @@ use std::sync::LazyLock; use crate::key_hint; use crate::key_hint::KeyBinding; use crate::key_hint::KeyBindingListExt; -use crate::legacy_core::config::set_default_oss_provider; use codex_model_provider_info::DEFAULT_LMSTUDIO_PORT; use codex_model_provider_info::DEFAULT_OLLAMA_PORT; use codex_model_provider_info::LMSTUDIO_OSS_PROVIDER_ID; @@ -309,7 +308,12 @@ fn get_status_symbol_and_color(status: &ProviderStatus) -> (&'static str, Color) } } -pub async fn select_oss_provider(codex_home: &std::path::Path) -> io::Result { +pub(crate) struct OssProviderSelection { + pub(crate) provider: String, + pub(crate) manually_selected: bool, +} + +pub async fn select_oss_provider() -> io::Result { // Check provider statuses first let lmstudio_status = check_lmstudio_status().await; let ollama_status = check_ollama_status().await; @@ -318,11 +322,17 @@ pub async fn select_oss_provider(codex_home: &std::path::Path) -> io::Result { let provider = LMSTUDIO_OSS_PROVIDER_ID.to_string(); - return Ok(provider); + return Ok(OssProviderSelection { + provider, + manually_selected: false, + }); } (ProviderStatus::NotRunning, ProviderStatus::Running) => { let provider = OLLAMA_OSS_PROVIDER_ID.to_string(); - return Ok(provider); + return Ok(OssProviderSelection { + provider, + manually_selected: false, + }); } _ => { // Both running or both not running - show UI @@ -346,21 +356,16 @@ pub async fn select_oss_provider(codex_home: &std::path::Path) -> io::Result