chore: cleanup Config instantiation codepaths (#8226)

This PR does various types of cleanup before I can proceed with more
ambitious changes to config loading.

First, I noticed duplicated code across these two methods:


https://github.com/openai/codex/blob/774bd9e432fa2e0f4e059e97648cf92216912e19/codex-rs/core/src/config/mod.rs#L314-L324


https://github.com/openai/codex/blob/774bd9e432fa2e0f4e059e97648cf92216912e19/codex-rs/core/src/config/mod.rs#L334-L344

This has now been consolidated in
`load_config_as_toml_with_cli_overrides()`.

Further, I noticed that `Config::load_with_cli_overrides()` took two
similar arguments:


https://github.com/openai/codex/blob/774bd9e432fa2e0f4e059e97648cf92216912e19/codex-rs/core/src/config/mod.rs#L308-L311

The difference between `cli_overrides` and `overrides` was not
immediately obvious to me. At first glance, it appears that one should
be able to be expressed in terms of the other, but it turns out that
some fields of `ConfigOverrides` (such as `cwd` and
`codex_linux_sandbox_exe`) are, by design, not configurable via a
`.toml` file or a command-line `--config` flag.

That said, I discovered that many callers of
`Config::load_with_cli_overrides()` were passing
`ConfigOverrides::default()` for `overrides`, so I created two separate
methods:

- `Config::load_with_cli_overrides(cli_overrides: Vec<(String,
TomlValue)>)`
- `Config::load_with_cli_overrides_and_harness_overrides(cli_overrides:
Vec<(String, TomlValue)>, harness_overrides: ConfigOverrides)`

The latter has a long name, as it is _not_ what should be used in the
common case, so the extra typing is designed to draw attention to this
fact. I tried to update the existing callsites to use the shorter name,
where possible.

Further, in the cases where `ConfigOverrides` is used, usually only a
limited subset of fields are actually set, so I updated the declarations
to leverage `..Default::default()` where possible.
This commit is contained in:
Michael Bolin authored and GitHub committed 2025-12-17 18:01:17 -08:00
1 parent 774bd9e432
commit a8797019a1
14 files changed
+60 -62

No files matched your search

@@ -282,7 +282,7 @@ impl CodexMessageProcessor {
} }
async fn load_latest_config(&self) -> Result<Config, JSONRPCErrorError> { async fn load_latest_config(&self) -> Result<Config, JSONRPCErrorError> {
Config::load_with_cli_overrides(self.cli_overrides.clone(), ConfigOverrides::default()) Config::load_with_cli_overrides(self.cli_overrides.clone())
.await .await
.map_err(|err| JSONRPCErrorError { .map_err(|err| JSONRPCErrorError {
code: INTERNAL_ERROR_CODE, code: INTERNAL_ERROR_CODE,
@@ -3348,7 +3348,7 @@ fn errors_to_info(
async fn derive_config_from_params( async fn derive_config_from_params(
overrides: ConfigOverrides, overrides: ConfigOverrides,
cli_overrides: Option<std::collections::HashMap<String, serde_json::Value>>, cli_overrides: Option<HashMap<String, serde_json::Value>>,
) -> std::io::Result<Config> { ) -> std::io::Result<Config> {
let cli_overrides = cli_overrides let cli_overrides = cli_overrides
.unwrap_or_default() .unwrap_or_default()
@@ -3356,7 +3356,7 @@ async fn derive_config_from_params(
.map(|(k, v)| (k, json_to_toml(v))) .map(|(k, v)| (k, json_to_toml(v)))
.collect(); .collect();
Config::load_with_cli_overrides(cli_overrides, overrides).await Config::load_with_cli_overrides_and_harness_overrides(cli_overrides, overrides).await
} }
async fn read_summary_from_rollout( async fn read_summary_from_rollout(
+5 -7
View File
@@ -2,7 +2,6 @@
use codex_common::CliConfigOverrides; use codex_common::CliConfigOverrides;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use std::io::ErrorKind; use std::io::ErrorKind;
use std::io::Result as IoResult; use std::io::Result as IoResult;
use std::path::PathBuf; use std::path::PathBuf;
@@ -81,12 +80,11 @@ pub async fn run_main(
format!("error parsing -c overrides: {e}"), format!("error parsing -c overrides: {e}"),
) )
})?; })?;
let config = let config = Config::load_with_cli_overrides(cli_kv_overrides.clone())
Config::load_with_cli_overrides(cli_kv_overrides.clone(), ConfigOverrides::default()) .await
.await .map_err(|e| {
.map_err(|e| { std::io::Error::new(ErrorKind::InvalidData, format!("error loading config: {e}"))
std::io::Error::new(ErrorKind::InvalidData, format!("error loading config: {e}")) })?;
})?;
let feedback = CodexFeedback::new(); let feedback = CodexFeedback::new();
-2
View File
@@ -3,7 +3,6 @@ use std::path::PathBuf;
use clap::Parser; use clap::Parser;
use codex_common::CliConfigOverrides; use codex_common::CliConfigOverrides;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use crate::chatgpt_token::init_chatgpt_token_from_auth; use crate::chatgpt_token::init_chatgpt_token_from_auth;
use crate::get_task::GetTaskResponse; use crate::get_task::GetTaskResponse;
@@ -28,7 +27,6 @@ pub async fn run_apply_command(
.config_overrides .config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?, .map_err(anyhow::Error::msg)?,
ConfigOverrides::default(),
) )
.await?; .await?;
+1 -1
View File
@@ -109,7 +109,7 @@ async fn run_command_under_sandbox(
log_denials: bool, log_denials: bool,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let sandbox_mode = create_sandbox_mode(full_auto); let sandbox_mode = create_sandbox_mode(full_auto);
let config = Config::load_with_cli_overrides( let config = Config::load_with_cli_overrides_and_harness_overrides(
config_overrides config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?, .map_err(anyhow::Error::msg)?,
+1 -3
View File
@@ -6,7 +6,6 @@ use codex_core::auth::CLIENT_ID;
use codex_core::auth::login_with_api_key; use codex_core::auth::login_with_api_key;
use codex_core::auth::logout; use codex_core::auth::logout;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use codex_login::ServerOptions; use codex_login::ServerOptions;
use codex_login::run_device_code_login; use codex_login::run_device_code_login;
use codex_login::run_login_server; use codex_login::run_login_server;
@@ -210,8 +209,7 @@ async fn load_config_or_exit(cli_config_overrides: CliConfigOverrides) -> Config
} }
}; };
let config_overrides = ConfigOverrides::default(); match Config::load_with_cli_overrides(cli_overrides).await {
match Config::load_with_cli_overrides(cli_overrides, config_overrides).await {
Ok(config) => config, Ok(config) => config,
Err(e) => { Err(e) => {
eprintln!("Error loading configuration: {e}"); eprintln!("Error loading configuration: {e}");
+5 -1
View File
@@ -631,7 +631,11 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
..Default::default() ..Default::default()
}; };
let config = Config::load_with_cli_overrides(cli_kv_overrides, overrides).await?; let config = Config::load_with_cli_overrides_and_harness_overrides(
cli_kv_overrides,
overrides,
)
.await?;
for def in codex_core::features::FEATURES.iter() { for def in codex_core::features::FEATURES.iter() {
let name = def.key; let name = def.key;
let stage = stage_str(def.stage); let stage = stage_str(def.stage);
+5 -6
View File
@@ -8,7 +8,6 @@ use clap::ArgGroup;
use codex_common::CliConfigOverrides; use codex_common::CliConfigOverrides;
use codex_common::format_env_display::format_env_display; use codex_common::format_env_display::format_env_display;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use codex_core::config::edit::ConfigEditsBuilder; use codex_core::config::edit::ConfigEditsBuilder;
use codex_core::config::find_codex_home; use codex_core::config::find_codex_home;
use codex_core::config::load_global_mcp_servers; use codex_core::config::load_global_mcp_servers;
@@ -200,7 +199,7 @@ async fn run_add(config_overrides: &CliConfigOverrides, add_args: AddArgs) -> Re
let overrides = config_overrides let overrides = config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?; .map_err(anyhow::Error::msg)?;
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default()) let config = Config::load_with_cli_overrides(overrides)
.await .await
.context("failed to load configuration")?; .context("failed to load configuration")?;
@@ -349,7 +348,7 @@ async fn run_login(config_overrides: &CliConfigOverrides, login_args: LoginArgs)
let overrides = config_overrides let overrides = config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?; .map_err(anyhow::Error::msg)?;
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default()) let config = Config::load_with_cli_overrides(overrides)
.await .await
.context("failed to load configuration")?; .context("failed to load configuration")?;
@@ -392,7 +391,7 @@ async fn run_logout(config_overrides: &CliConfigOverrides, logout_args: LogoutAr
let overrides = config_overrides let overrides = config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?; .map_err(anyhow::Error::msg)?;
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default()) let config = Config::load_with_cli_overrides(overrides)
.await .await
.context("failed to load configuration")?; .context("failed to load configuration")?;
@@ -421,7 +420,7 @@ async fn run_list(config_overrides: &CliConfigOverrides, list_args: ListArgs) ->
let overrides = config_overrides let overrides = config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?; .map_err(anyhow::Error::msg)?;
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default()) let config = Config::load_with_cli_overrides(overrides)
.await .await
.context("failed to load configuration")?; .context("failed to load configuration")?;
@@ -678,7 +677,7 @@ async fn run_get(config_overrides: &CliConfigOverrides, get_args: GetArgs) -> Re
let overrides = config_overrides let overrides = config_overrides
.parse_overrides() .parse_overrides()
.map_err(anyhow::Error::msg)?; .map_err(anyhow::Error::msg)?;
let config = Config::load_with_cli_overrides(overrides, ConfigOverrides::default()) let config = Config::load_with_cli_overrides(overrides)
.await .await
.context("failed to load configuration")?; .context("failed to load configuration")?;
+1 -4
View File
@@ -5,7 +5,6 @@ use chrono::Utc;
use reqwest::header::HeaderMap; use reqwest::header::HeaderMap;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use codex_login::AuthManager; use codex_login::AuthManager;
pub fn set_user_agent_suffix(suffix: &str) { pub fn set_user_agent_suffix(suffix: &str) {
@@ -62,9 +61,7 @@ pub fn extract_chatgpt_account_id(token: &str) -> Option<String> {
pub async fn load_auth_manager() -> Option<AuthManager> { pub async fn load_auth_manager() -> Option<AuthManager> {
// TODO: pass in cli overrides once cloud tasks properly support them. // TODO: pass in cli overrides once cloud tasks properly support them.
let config = Config::load_with_cli_overrides(Vec::new(), ConfigOverrides::default()) let config = Config::load_with_cli_overrides(Vec::new()).await.ok()?;
.await
.ok()?;
Some(AuthManager::new( Some(AuthManager::new(
config.codex_home, config.codex_home,
false, false,
+27 -15
View File
@@ -305,28 +305,40 @@ pub struct Config {
} }
impl Config { impl Config {
/// This is the preferred way to create an instance of [Config].
pub async fn load_with_cli_overrides( pub async fn load_with_cli_overrides(
cli_overrides: Vec<(String, TomlValue)>, cli_overrides: Vec<(String, TomlValue)>,
overrides: ConfigOverrides,
) -> std::io::Result<Self> { ) -> std::io::Result<Self> {
let codex_home = find_codex_home()?; let codex_home = find_codex_home()?;
let config_toml =
let root_value = load_resolved_config( load_config_as_toml_with_cli_overrides(&codex_home, cli_overrides).await?;
&codex_home, Self::load_from_base_config_with_overrides(
cli_overrides, config_toml,
crate::config_loader::LoaderOverrides::default(), ConfigOverrides::default(),
codex_home,
) )
.await?; }
let cfg = deserialize_config_toml_with_base(root_value, &codex_home).map_err(|e| { /// This is a secondary way of creating [Config], which is appropriate when
tracing::error!("Failed to deserialize overridden config: {e}"); /// the harness is meant to be used with a specific configuration that
e /// ignores user settings. For example, the `codex exec` subcommand is
})?; /// designed to use [AskForApproval::Never] exclusively.
///
Self::load_from_base_config_with_overrides(cfg, overrides, codex_home) /// Further, [ConfigOverrides] contains some options that are not supported
/// in [ConfigToml], such as `cwd` and `codex_linux_sandbox_exe`.
pub async fn load_with_cli_overrides_and_harness_overrides(
cli_overrides: Vec<(String, TomlValue)>,
harness_overrides: ConfigOverrides,
) -> std::io::Result<Self> {
let codex_home = find_codex_home()?;
let config_toml =
load_config_as_toml_with_cli_overrides(&codex_home, cli_overrides).await?;
Self::load_from_base_config_with_overrides(config_toml, harness_overrides, codex_home)
} }
} }
/// DEPRECATED: Use [Config::load_with_cli_overrides()] instead because this
/// codepath is not guaranteed to honor [ConfigRequirements].
pub async fn load_config_as_toml_with_cli_overrides( pub async fn load_config_as_toml_with_cli_overrides(
codex_home: &Path, codex_home: &Path,
cli_overrides: Vec<(String, TomlValue)>, cli_overrides: Vec<(String, TomlValue)>,
@@ -927,8 +939,8 @@ pub fn resolve_oss_provider(
} }
impl Config { impl Config {
/// Meant to be used exclusively for tests: `load_with_overrides()` should /// Meant to be used exclusively for tests:
/// be used in all other cases. /// [Config::load_with_cli_overrides()] should be used in all other cases.
pub fn load_from_base_config_with_overrides( pub fn load_from_base_config_with_overrides(
cfg: ConfigToml, cfg: ConfigToml,
overrides: ConfigOverrides, overrides: ConfigOverrides,
+2 -1
View File
@@ -202,7 +202,8 @@ pub async fn run_main(cli: Cli, codex_linux_sandbox_exe: Option<PathBuf>) -> any
additional_writable_roots: add_dir, additional_writable_roots: add_dir,
}; };
let config = Config::load_with_cli_overrides(cli_kv_overrides, overrides).await?; let config =
Config::load_with_cli_overrides_and_harness_overrides(cli_kv_overrides, overrides).await?;
if let Err(err) = enforce_login_restrictions(&config).await { if let Err(err) = enforce_login_restrictions(&config).await {
eprintln!("{err}"); eprintln!("{err}");
+6 -9
View File
@@ -1,5 +1,7 @@
//! Configuration object accepted by the `codex` MCP tool-call. //! Configuration object accepted by the `codex` MCP tool-call.
use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use codex_core::protocol::AskForApproval; use codex_core::protocol::AskForApproval;
use codex_protocol::config_types::SandboxMode; use codex_protocol::config_types::SandboxMode;
use codex_utils_json_to_toml::json_to_toml; use codex_utils_json_to_toml::json_to_toml;
@@ -139,7 +141,7 @@ impl CodexToolCallParam {
pub async fn into_config( pub async fn into_config(
self, self,
codex_linux_sandbox_exe: Option<PathBuf>, codex_linux_sandbox_exe: Option<PathBuf>,
) -> std::io::Result<(String, codex_core::config::Config)> { ) -> std::io::Result<(String, Config)> {
let Self { let Self {
prompt, prompt,
model, model,
@@ -154,22 +156,17 @@ impl CodexToolCallParam {
} = self; } = self;
// Build the `ConfigOverrides` recognized by codex-core. // Build the `ConfigOverrides` recognized by codex-core.
let overrides = codex_core::config::ConfigOverrides { let overrides = ConfigOverrides {
model, model,
review_model: None,
config_profile: profile, config_profile: profile,
cwd: cwd.map(PathBuf::from), cwd: cwd.map(PathBuf::from),
approval_policy: approval_policy.map(Into::into), approval_policy: approval_policy.map(Into::into),
sandbox_mode: sandbox.map(Into::into), sandbox_mode: sandbox.map(Into::into),
model_provider: None,
codex_linux_sandbox_exe, codex_linux_sandbox_exe,
base_instructions, base_instructions,
developer_instructions, developer_instructions,
compact_prompt, compact_prompt,
include_apply_patch_tool: None, ..Default::default()
show_raw_agent_reasoning: None,
tools_web_search_request: None,
additional_writable_roots: Vec::new(),
}; };
let cli_overrides = cli_overrides let cli_overrides = cli_overrides
@@ -179,7 +176,7 @@ impl CodexToolCallParam {
.collect(); .collect();
let cfg = let cfg =
codex_core::config::Config::load_with_cli_overrides(cli_overrides, overrides).await?; Config::load_with_cli_overrides_and_harness_overrides(cli_overrides, overrides).await?;
Ok((prompt, cfg)) Ok((prompt, cfg))
} }
+1 -2
View File
@@ -7,7 +7,6 @@ use std::path::PathBuf;
use codex_common::CliConfigOverrides; use codex_common::CliConfigOverrides;
use codex_core::config::Config; use codex_core::config::Config;
use codex_core::config::ConfigOverrides;
use mcp_types::JSONRPCMessage; use mcp_types::JSONRPCMessage;
use tokio::io::AsyncBufReadExt; use tokio::io::AsyncBufReadExt;
@@ -90,7 +89,7 @@ pub async fn run_main(
format!("error parsing -c overrides: {e}"), format!("error parsing -c overrides: {e}"),
) )
})?; })?;
let config = Config::load_with_cli_overrides(cli_kv_overrides, ConfigOverrides::default()) let config = Config::load_with_cli_overrides(cli_kv_overrides)
.await .await
.map_err(|e| { .map_err(|e| {
std::io::Error::new(ErrorKind::InvalidData, format!("error loading config: {e}")) std::io::Error::new(ErrorKind::InvalidData, format!("error loading config: {e}"))
+2 -7
View File
@@ -205,20 +205,15 @@ pub async fn run_main(
let overrides = ConfigOverrides { let overrides = ConfigOverrides {
model, model,
review_model: None,
approval_policy, approval_policy,
sandbox_mode, sandbox_mode,
cwd, cwd,
model_provider: model_provider_override.clone(), model_provider: model_provider_override.clone(),
config_profile: cli.config_profile.clone(), config_profile: cli.config_profile.clone(),
codex_linux_sandbox_exe, codex_linux_sandbox_exe,
base_instructions: None,
developer_instructions: None,
compact_prompt: None,
include_apply_patch_tool: None,
show_raw_agent_reasoning: cli.oss.then_some(true), show_raw_agent_reasoning: cli.oss.then_some(true),
tools_web_search_request: None,
additional_writable_roots: additional_dirs, additional_writable_roots: additional_dirs,
..Default::default()
}; };
let config = load_config_or_exit(cli_kv_overrides.clone(), overrides.clone()).await; let config = load_config_or_exit(cli_kv_overrides.clone(), overrides.clone()).await;
@@ -552,7 +547,7 @@ async fn load_config_or_exit(
overrides: ConfigOverrides, overrides: ConfigOverrides,
) -> Config { ) -> Config {
#[allow(clippy::print_stderr)] #[allow(clippy::print_stderr)]
match Config::load_with_cli_overrides(cli_kv_overrides, overrides).await { match Config::load_with_cli_overrides_and_harness_overrides(cli_kv_overrides, overrides).await {
Ok(config) => config, Ok(config) => config,
Err(err) => { Err(err) => {
eprintln!("Error loading configuration: {err}"); eprintln!("Error loading configuration: {err}");
+1 -1
View File
@@ -573,7 +573,7 @@ async fn load_config_or_exit(
overrides: ConfigOverrides, overrides: ConfigOverrides,
) -> Config { ) -> Config {
#[allow(clippy::print_stderr)] #[allow(clippy::print_stderr)]
match Config::load_with_cli_overrides(cli_kv_overrides, overrides).await { match Config::load_with_cli_overrides_and_harness_overrides(cli_kv_overrides, overrides).await {
Ok(config) => config, Ok(config) => config,
Err(err) => { Err(err) => {
eprintln!("Error loading configuration: {err}"); eprintln!("Error loading configuration: {err}");