Centralize TOML config deserialization (#58198)

## What changed

- Add a non-inlined `TryFrom<toml::Value>` implementation for `ConfigToml` and route callers through it to share the generated deserializer in `codex-config`.
- Reuse the ignored-field deserialization helper for strict validation, returning path-aware errors while preserving existing fallbacks for CLI validation and ignored-config warnings.

GitOrigin-RevId: 0208b314416ad4d3d7fbf3a30560a0c8c4035abd
This commit is contained in:
Dmitriy Kovalenko
2026-10-30 00:36:00 +00:00
committed by copyberry
parent 2f1e4f99e0
commit b91cedc080
6 changed files with 38 additions and 45 deletions
+6 -13
View File
@@ -1634,7 +1634,7 @@ impl ConfigBuilder {
async fn config_toml_from_layers(layers: &ConfigLayerStack) -> std::io::Result<ConfigToml> {
// The loader resolves paths relative to each layer's file before deserialization.
match layers.effective_config().try_into() {
match ConfigToml::try_from(layers.effective_config()) {
Ok(config_toml) => Ok(config_toml),
Err(err) => {
if let Some(config_error) = codex_config::first_layer_config_error::<ConfigToml>(
@@ -2240,8 +2240,7 @@ pub fn deserialize_config_toml_with_base(
// This guard ensures that any relative paths that is deserialized into an
// [AbsolutePathBuf] is resolved against `config_base_dir`.
let _guard = AbsolutePathBufGuard::new(config_base_dir);
root_value
.try_into()
ConfigToml::try_from(root_value)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))
}
@@ -4924,11 +4923,8 @@ impl Config {
&self,
profile_name: &str,
) -> std::io::Result<PermissionProfileToml> {
let cfg: ConfigToml = self
.config_layer_stack
.effective_config()
.try_into()
.map_err(|err| {
let cfg =
ConfigToml::try_from(self.config_layer_stack.effective_config()).map_err(|err| {
std::io::Error::new(
ErrorKind::InvalidInput,
format!(
@@ -4952,11 +4948,8 @@ impl Config {
) -> std::io::Result<Option<NetworkProxySpec>> {
let profile_allows_network_proxy =
profile_allows_configured_network_proxy(permission_profile);
let cfg: ConfigToml = self
.config_layer_stack
.effective_config()
.try_into()
.map_err(|err| {
let cfg =
ConfigToml::try_from(self.config_layer_stack.effective_config()).map_err(|err| {
std::io::Error::new(
ErrorKind::InvalidInput,
format!(
+2 -4
View File
@@ -4,6 +4,7 @@ use crate::config::Config;
use crate::config::TokenBudgetConfig;
use crate::config::resolve_token_budget_config;
use crate::context::ContextualUserFragment;
use codex_config::config_toml::ConfigToml;
use codex_features::Feature;
use codex_login::CodexAuth;
use codex_protocol::account::PlanType;
@@ -42,10 +43,7 @@ pub(super) fn apply_experimental_context(
}
if config.token_budget.is_none() {
let config_toml = config
.config_layer_stack
.effective_config()
.try_into()
let config_toml = ConfigToml::try_from(config.config_layer_stack.effective_config())
.map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))?;
config.token_budget = resolve_token_budget_config(&config_toml, &config.features)?;
}