From 1a220ad77dc436082de5efc4e1f7fc30d711ab87 Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Fri, 20 Feb 2026 23:19:29 -0800 Subject: [PATCH] chore: move config diagnostics out of codex-core (#12427) ## Why Compiling `codex-rs/core` is a bottleneck for local iteration, so this change continues the ongoing extraction of config-related functionality out of `codex-core` and into `codex-config`. The goal is not just to move code, but to reduce `codex-core` ownership and indirection so more code depends on `codex-config` directly. ## What Changed - Moved config diagnostics logic from `core/src/config_loader/diagnostics.rs` into `config/src/diagnostics.rs`. - Updated `codex-core` to use `codex-config` diagnostics types/functions directly where possible. - Removed the `core/src/config_loader/diagnostics.rs` shim module entirely; the remaining `ConfigToml`-specific calls are in `core/src/config_loader/mod.rs`. - Moved `CONFIG_TOML_FILE` into `codex-config` and updated existing references to use `codex_config::CONFIG_TOML_FILE` directly. - Added a direct `codex-config` dependency to `codex-cli` for its `CONFIG_TOML_FILE` use. --- codex-rs/Cargo.lock | 5 ++- codex-rs/cli/Cargo.toml | 1 + codex-rs/cli/src/main.rs | 2 +- codex-rs/config/Cargo.toml | 4 ++ .../src}/diagnostics.rs | 44 +++++++++++-------- codex-rs/config/src/lib.rs | 14 ++++++ codex-rs/core/Cargo.toml | 1 - codex-rs/core/src/codex.rs | 2 +- codex-rs/core/src/config/edit.rs | 2 +- codex-rs/core/src/config/mod.rs | 3 +- codex-rs/core/src/config/service.rs | 2 +- codex-rs/core/src/config_loader/layer_io.rs | 4 +- codex-rs/core/src/config_loader/mod.rs | 32 +++++++++----- codex-rs/core/src/config_loader/tests.rs | 6 +-- codex-rs/core/src/features.rs | 2 +- codex-rs/core/src/network_proxy_loader.rs | 2 +- codex-rs/core/src/skills/loader.rs | 2 +- .../tests/suite/unstable_features_warning.rs | 2 +- 18 files changed, 82 insertions(+), 48 deletions(-) rename codex-rs/{core/src/config_loader => config/src}/diagnostics.rs (90%) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index f05879a24..4ef13ad84 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1470,6 +1470,7 @@ dependencies = [ "codex-arg0", "codex-chatgpt", "codex-cloud-tasks", + "codex-config", "codex-core", "codex-exec", "codex-execpolicy", @@ -1600,10 +1601,13 @@ dependencies = [ "pretty_assertions", "serde", "serde_json", + "serde_path_to_error", "sha2", "thiserror 2.0.18", "tokio", "toml 0.9.11+spec-1.1.0", + "toml_edit 0.24.0+spec-1.1.0", + "tracing", ] [[package]] @@ -1681,7 +1685,6 @@ dependencies = [ "seccompiler", "serde", "serde_json", - "serde_path_to_error", "serde_yaml", "serial_test", "sha1", diff --git a/codex-rs/cli/Cargo.toml b/codex-rs/cli/Cargo.toml index fd15f8791..1d955bbaa 100644 --- a/codex-rs/cli/Cargo.toml +++ b/codex-rs/cli/Cargo.toml @@ -26,6 +26,7 @@ codex-arg0 = { workspace = true } codex-chatgpt = { workspace = true } codex-cloud-tasks = { path = "../cloud-tasks" } codex-utils-cli = { workspace = true } +codex-config = { workspace = true } codex-core = { workspace = true } codex-exec = { workspace = true } codex-execpolicy = { workspace = true } diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 33c9f161b..98a5ab077 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -870,7 +870,7 @@ fn maybe_print_under_development_feature_warning( return; } - let config_path = codex_home.join(codex_core::config::CONFIG_TOML_FILE); + let config_path = codex_home.join(codex_config::CONFIG_TOML_FILE); eprintln!( "Under-development features enabled: {feature}. Under-development features are incomplete and may behave unpredictably. To suppress this warning, set `suppress_unstable_features_warning = true` in {}.", config_path.display() diff --git a/codex-rs/config/Cargo.toml b/codex-rs/config/Cargo.toml index 1c804fb8d..02446ed6f 100644 --- a/codex-rs/config/Cargo.toml +++ b/codex-rs/config/Cargo.toml @@ -16,9 +16,13 @@ futures = { workspace = true, features = ["alloc", "std"] } multimap = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } +serde_path_to_error = { workspace = true } sha2 = { workspace = true } thiserror = { workspace = true } +tokio = { workspace = true, features = ["fs"] } toml = { workspace = true } +toml_edit = { workspace = true } +tracing = { workspace = true } [dev-dependencies] anyhow = { workspace = true } diff --git a/codex-rs/core/src/config_loader/diagnostics.rs b/codex-rs/config/src/diagnostics.rs similarity index 90% rename from codex-rs/core/src/config_loader/diagnostics.rs rename to codex-rs/config/src/diagnostics.rs index 64f9c8388..be6e123d3 100644 --- a/codex-rs/core/src/config_loader/diagnostics.rs +++ b/codex-rs/config/src/diagnostics.rs @@ -1,10 +1,12 @@ //! Helpers for mapping config parse/validation failures to file locations and //! rendering them in a user-friendly way. -use crate::config::CONFIG_TOML_FILE; -use crate::config::ConfigToml; +use crate::ConfigLayerEntry; +use crate::ConfigLayerStack; +use crate::ConfigLayerStackOrdering; use codex_app_server_protocol::ConfigLayerSource; use codex_utils_absolute_path::AbsolutePathBufGuard; +use serde::de::DeserializeOwned; use serde_path_to_error::Path as SerdePath; use serde_path_to_error::Segment as SerdeSegment; use std::fmt; @@ -17,10 +19,6 @@ use toml_edit::Item; use toml_edit::Table; use toml_edit::Value; -use super::ConfigLayerEntry; -use super::ConfigLayerStack; -use super::ConfigLayerStackOrdering; - #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct TextPosition { pub line: usize, @@ -88,7 +86,7 @@ impl std::error::Error for ConfigLoadError { } } -pub(crate) fn io_error_from_config_error( +pub fn io_error_from_config_error( kind: io::ErrorKind, error: ConfigError, source: Option, @@ -96,7 +94,7 @@ pub(crate) fn io_error_from_config_error( io::Error::new(kind, ConfigLoadError::new(error, source)) } -pub(crate) fn config_error_from_toml( +pub fn config_error_from_toml( path: impl AsRef, contents: &str, err: toml::de::Error, @@ -108,7 +106,7 @@ pub(crate) fn config_error_from_toml( ConfigError::new(path.as_ref().to_path_buf(), range, err.message()) } -pub(crate) fn config_error_from_config_toml( +pub fn config_error_from_typed_toml( path: impl AsRef, contents: &str, ) -> Option { @@ -117,7 +115,7 @@ pub(crate) fn config_error_from_config_toml( Err(err) => return Some(config_error_from_toml(path, contents, err)), }; - let result: Result = serde_path_to_error::deserialize(deserializer); + let result: Result = serde_path_to_error::deserialize(deserializer); match result { Ok(_) => None, Err(err) => { @@ -136,28 +134,36 @@ pub(crate) fn config_error_from_config_toml( } } -pub(crate) async fn first_layer_config_error(layers: &ConfigLayerStack) -> Option { +pub async fn first_layer_config_error( + layers: &ConfigLayerStack, + config_toml_file: &str, +) -> Option { // When the merged config fails schema validation, we surface the first concrete // per-file error to point users at a specific file and range rather than an // opaque merged-layer failure. - first_layer_config_error_for_entries( + first_layer_config_error_for_entries::( layers.get_layers(ConfigLayerStackOrdering::LowestPrecedenceFirst, false), + config_toml_file, ) .await } -pub(crate) async fn first_layer_config_error_from_entries( +pub async fn first_layer_config_error_from_entries( layers: &[ConfigLayerEntry], + config_toml_file: &str, ) -> Option { - first_layer_config_error_for_entries(layers.iter()).await + first_layer_config_error_for_entries::(layers.iter(), config_toml_file).await } -async fn first_layer_config_error_for_entries<'a, I>(layers: I) -> Option +async fn first_layer_config_error_for_entries<'a, T: DeserializeOwned, I>( + layers: I, + config_toml_file: &str, +) -> Option where I: IntoIterator, { for layer in layers { - let Some(path) = config_path_for_layer(layer) else { + let Some(path) = config_path_for_layer(layer, config_toml_file) else { continue; }; let contents = match tokio::fs::read_to_string(&path).await { @@ -174,7 +180,7 @@ where continue; }; let _guard = AbsolutePathBufGuard::new(parent); - if let Some(error) = config_error_from_config_toml(&path, &contents) { + if let Some(error) = config_error_from_typed_toml::(&path, &contents) { return Some(error); } } @@ -182,12 +188,12 @@ where None } -fn config_path_for_layer(layer: &ConfigLayerEntry) -> Option { +fn config_path_for_layer(layer: &ConfigLayerEntry, config_toml_file: &str) -> Option { match &layer.name { ConfigLayerSource::System { file } => Some(file.to_path_buf()), ConfigLayerSource::User { file } => Some(file.to_path_buf()), ConfigLayerSource::Project { dot_codex_folder } => { - Some(dot_codex_folder.as_path().join(CONFIG_TOML_FILE)) + Some(dot_codex_folder.as_path().join(config_toml_file)) } ConfigLayerSource::LegacyManagedConfigTomlFromFile { file } => Some(file.to_path_buf()), ConfigLayerSource::Mdm { .. } diff --git a/codex-rs/config/src/lib.rs b/codex-rs/config/src/lib.rs index 42f3ad76a..41b9a3ae0 100644 --- a/codex-rs/config/src/lib.rs +++ b/codex-rs/config/src/lib.rs @@ -1,12 +1,15 @@ mod cloud_requirements; mod config_requirements; mod constraint; +mod diagnostics; mod fingerprint; mod merge; mod overrides; mod requirements_exec_policy; mod state; +pub const CONFIG_TOML_FILE: &str = "config.toml"; + pub use cloud_requirements::CloudRequirementsLoader; pub use config_requirements::ConfigRequirements; pub use config_requirements::ConfigRequirementsToml; @@ -24,6 +27,17 @@ pub use config_requirements::WebSearchModeRequirement; pub use constraint::Constrained; pub use constraint::ConstraintError; pub use constraint::ConstraintResult; +pub use diagnostics::ConfigError; +pub use diagnostics::ConfigLoadError; +pub use diagnostics::TextPosition; +pub use diagnostics::TextRange; +pub use diagnostics::config_error_from_toml; +pub use diagnostics::config_error_from_typed_toml; +pub use diagnostics::first_layer_config_error; +pub use diagnostics::first_layer_config_error_from_entries; +pub use diagnostics::format_config_error; +pub use diagnostics::format_config_error_with_source; +pub use diagnostics::io_error_from_config_error; pub use fingerprint::version_for_toml; pub use merge::merge_toml_values; pub use overrides::build_cli_overrides_layer; diff --git a/codex-rs/core/Cargo.toml b/codex-rs/core/Cargo.toml index 2b62d9625..bda19d78e 100644 --- a/codex-rs/core/Cargo.toml +++ b/codex-rs/core/Cargo.toml @@ -78,7 +78,6 @@ rmcp = { workspace = true, default-features = false, features = [ schemars = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -serde_path_to_error = { workspace = true } serde_yaml = { workspace = true } sha1 = { workspace = true } sha2 = { workspace = true } diff --git a/codex-rs/core/src/codex.rs b/codex-rs/core/src/codex.rs index 90d496973..6c9c9a678 100644 --- a/codex-rs/core/src/codex.rs +++ b/codex-rs/core/src/codex.rs @@ -120,7 +120,6 @@ use crate::client_common::Prompt; use crate::client_common::ResponseEvent; use crate::codex_thread::ThreadConfigSnapshot; use crate::compact::collect_user_messages; -use crate::config::CONFIG_TOML_FILE; use crate::config::Config; use crate::config::Constrained; use crate::config::ConstraintResult; @@ -136,6 +135,7 @@ use crate::error::CodexErr; use crate::error::Result as CodexResult; #[cfg(test)] use crate::exec::StreamOutput; +use codex_config::CONFIG_TOML_FILE; #[derive(Debug, PartialEq)] pub enum SteerInputError { diff --git a/codex-rs/core/src/config/edit.rs b/codex-rs/core/src/config/edit.rs index 07443fa66..0dfb4efd8 100644 --- a/codex-rs/core/src/config/edit.rs +++ b/codex-rs/core/src/config/edit.rs @@ -1,9 +1,9 @@ -use crate::config::CONFIG_TOML_FILE; use crate::config::types::McpServerConfig; use crate::config::types::Notice; use crate::path_utils::resolve_symlink_write_paths; use crate::path_utils::write_atomically; use anyhow::Context; +use codex_config::CONFIG_TOML_FILE; use codex_protocol::config_types::Personality; use codex_protocol::config_types::TrustLevel; use codex_protocol::openai_models::ReasoningEffort; diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index edaabed1f..ca3978b73 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -117,8 +117,6 @@ pub(crate) const PROJECT_DOC_MAX_BYTES: usize = 32 * 1024; // 32 KiB pub(crate) const DEFAULT_AGENT_MAX_THREADS: Option = Some(6); pub(crate) const DEFAULT_AGENT_MAX_DEPTH: i32 = 1; -pub const CONFIG_TOML_FILE: &str = "config.toml"; - #[cfg(test)] pub(crate) fn test_config() -> Config { let codex_home = tempdir().expect("create temp dir"); @@ -2302,6 +2300,7 @@ mod tests { use crate::config::types::Notifications; use crate::config_loader::RequirementSource; use crate::features::Feature; + use codex_config::CONFIG_TOML_FILE; use super::*; use core_test_support::test_absolute_path; diff --git a/codex-rs/core/src/config/service.rs b/codex-rs/core/src/config/service.rs index 1033db728..da675d238 100644 --- a/codex-rs/core/src/config/service.rs +++ b/codex-rs/core/src/config/service.rs @@ -1,4 +1,3 @@ -use super::CONFIG_TOML_FILE; use super::ConfigToml; use crate::config::edit::ConfigEdit; use crate::config::edit::ConfigEditsBuilder; @@ -26,6 +25,7 @@ use codex_app_server_protocol::ConfigWriteResponse; use codex_app_server_protocol::MergeStrategy; use codex_app_server_protocol::OverriddenMetadata; use codex_app_server_protocol::WriteStatus; +use codex_config::CONFIG_TOML_FILE; use codex_utils_absolute_path::AbsolutePathBuf; use serde_json::Value as JsonValue; use std::borrow::Cow; diff --git a/codex-rs/core/src/config_loader/layer_io.rs b/codex-rs/core/src/config_loader/layer_io.rs index a97f28554..5caebdf52 100644 --- a/codex-rs/core/src/config_loader/layer_io.rs +++ b/codex-rs/core/src/config_loader/layer_io.rs @@ -1,10 +1,10 @@ use super::LoaderOverrides; -use super::diagnostics::config_error_from_toml; -use super::diagnostics::io_error_from_config_error; #[cfg(target_os = "macos")] use super::macos::ManagedAdminConfigLayer; #[cfg(target_os = "macos")] use super::macos::load_managed_admin_config_layer; +use codex_config::config_error_from_toml; +use codex_config::io_error_from_config_error; use codex_utils_absolute_path::AbsolutePathBuf; use std::io; use std::path::Path; diff --git a/codex-rs/core/src/config_loader/mod.rs b/codex-rs/core/src/config_loader/mod.rs index f30a627c4..70014c03b 100644 --- a/codex-rs/core/src/config_loader/mod.rs +++ b/codex-rs/core/src/config_loader/mod.rs @@ -1,4 +1,3 @@ -mod diagnostics; mod layer_io; #[cfg(target_os = "macos")] mod macos; @@ -6,12 +5,12 @@ mod macos; #[cfg(test)] mod tests; -use crate::config::CONFIG_TOML_FILE; use crate::config::ConfigToml; use crate::config::deserialize_config_toml_with_base; use crate::config_loader::layer_io::LoadedConfigLayers; use crate::git_info::resolve_root_git_project_for_trust; use codex_app_server_protocol::ConfigLayerSource; +use codex_config::CONFIG_TOML_FILE; use codex_config::ConfigRequirementsWithSources; use codex_protocol::config_types::SandboxMode; use codex_protocol::config_types::TrustLevel; @@ -27,9 +26,11 @@ use std::path::PathBuf; use toml::Value as TomlValue; pub use codex_config::CloudRequirementsLoader; +pub use codex_config::ConfigError; pub use codex_config::ConfigLayerEntry; pub use codex_config::ConfigLayerStack; pub use codex_config::ConfigLayerStackOrdering; +pub use codex_config::ConfigLoadError; pub use codex_config::ConfigRequirements; pub use codex_config::ConfigRequirementsToml; pub use codex_config::ConstrainedWithSource; @@ -42,21 +43,17 @@ pub use codex_config::RequirementSource; pub use codex_config::ResidencyRequirement; pub use codex_config::SandboxModeRequirement; pub use codex_config::Sourced; +pub use codex_config::TextPosition; +pub use codex_config::TextRange; pub use codex_config::WebSearchModeRequirement; pub(crate) use codex_config::build_cli_overrides_layer; +pub(crate) use codex_config::config_error_from_toml; +pub use codex_config::format_config_error; +pub use codex_config::format_config_error_with_source; +pub(crate) use codex_config::io_error_from_config_error; pub use codex_config::merge_toml_values; #[cfg(test)] pub(crate) use codex_config::version_for_toml; -pub use diagnostics::ConfigError; -pub use diagnostics::ConfigLoadError; -pub use diagnostics::TextPosition; -pub use diagnostics::TextRange; -pub(crate) use diagnostics::config_error_from_toml; -pub(crate) use diagnostics::first_layer_config_error; -pub(crate) use diagnostics::first_layer_config_error_from_entries; -pub use diagnostics::format_config_error; -pub use diagnostics::format_config_error_with_source; -pub(crate) use diagnostics::io_error_from_config_error; /// On Unix systems, load default settings from this file path, if present. /// Note that /etc/codex/ is treated as a "config folder," so subfolders such @@ -68,6 +65,17 @@ const DEFAULT_PROGRAM_DATA_DIR_WINDOWS: &str = r"C:\ProgramData"; const DEFAULT_PROJECT_ROOT_MARKERS: &[&str] = &[".git"]; +pub(crate) async fn first_layer_config_error(layers: &ConfigLayerStack) -> Option { + codex_config::first_layer_config_error::(layers, CONFIG_TOML_FILE).await +} + +pub(crate) async fn first_layer_config_error_from_entries( + layers: &[ConfigLayerEntry], +) -> Option { + codex_config::first_layer_config_error_from_entries::(layers, CONFIG_TOML_FILE) + .await +} + /// To build up the set of admin-enforced constraints, we build up from multiple /// configuration layers in the following order, but a constraint defined in an /// earlier layer cannot be overridden by a later layer: diff --git a/codex-rs/core/src/config_loader/tests.rs b/codex-rs/core/src/config_loader/tests.rs index 08bbb5304..3eab05ba1 100644 --- a/codex-rs/core/src/config_loader/tests.rs +++ b/codex-rs/core/src/config_loader/tests.rs @@ -1,6 +1,5 @@ use super::LoaderOverrides; use super::load_config_layers_state; -use crate::config::CONFIG_TOML_FILE; use crate::config::ConfigBuilder; use crate::config::ConfigOverrides; use crate::config::ConfigToml; @@ -15,6 +14,7 @@ use crate::config_loader::ConfigRequirementsWithSources; use crate::config_loader::RequirementSource; use crate::config_loader::load_requirements_toml; use crate::config_loader::version_for_toml; +use codex_config::CONFIG_TOML_FILE; use codex_protocol::config_types::TrustLevel; use codex_protocol::config_types::WebSearchMode; use codex_protocol::protocol::AskForApproval; @@ -153,7 +153,7 @@ async fn returns_config_error_for_schema_error_in_user_config() { let config_error = config_error_from_io(&err); let _guard = codex_utils_absolute_path::AbsolutePathBufGuard::new(tmp.path()); let expected_config_error = - super::diagnostics::config_error_from_config_toml(&config_path, contents) + codex_config::config_error_from_typed_toml::(&config_path, contents) .expect("schema error"); assert_eq!(config_error, &expected_config_error); } @@ -166,7 +166,7 @@ fn schema_error_points_to_feature_value() { std::fs::write(&config_path, contents).expect("write config"); let _guard = codex_utils_absolute_path::AbsolutePathBufGuard::new(tmp.path()); - let error = super::diagnostics::config_error_from_config_toml(&config_path, contents) + let error = codex_config::config_error_from_typed_toml::(&config_path, contents) .expect("schema error"); let value_line = contents.lines().nth(1).expect("value line"); diff --git a/codex-rs/core/src/features.rs b/codex-rs/core/src/features.rs index a4be91046..4cefe4b21 100644 --- a/codex-rs/core/src/features.rs +++ b/codex-rs/core/src/features.rs @@ -5,13 +5,13 @@ //! booleans through multiple types, call sites consult a single `Features` //! container attached to `Config`. -use crate::config::CONFIG_TOML_FILE; use crate::config::Config; use crate::config::ConfigToml; use crate::config::profile::ConfigProfile; use crate::protocol::Event; use crate::protocol::EventMsg; use crate::protocol::WarningEvent; +use codex_config::CONFIG_TOML_FILE; use codex_otel::OtelManager; use schemars::JsonSchema; use serde::Deserialize; diff --git a/codex-rs/core/src/network_proxy_loader.rs b/codex-rs/core/src/network_proxy_loader.rs index 1af36b2ac..15d4e4166 100644 --- a/codex-rs/core/src/network_proxy_loader.rs +++ b/codex-rs/core/src/network_proxy_loader.rs @@ -1,4 +1,3 @@ -use crate::config::CONFIG_TOML_FILE; use crate::config::NetworkToml; use crate::config::PermissionsToml; use crate::config::find_codex_home; @@ -11,6 +10,7 @@ use anyhow::Context; use anyhow::Result; use async_trait::async_trait; use codex_app_server_protocol::ConfigLayerSource; +use codex_config::CONFIG_TOML_FILE; use codex_network_proxy::ConfigReloader; use codex_network_proxy::ConfigState; use codex_network_proxy::NetworkProxyConfig; diff --git a/codex-rs/core/src/skills/loader.rs b/codex-rs/core/src/skills/loader.rs index 3c497bfcf..1ad231438 100644 --- a/codex-rs/core/src/skills/loader.rs +++ b/codex-rs/core/src/skills/loader.rs @@ -806,7 +806,6 @@ fn extract_frontmatter(contents: &str) -> Option { #[cfg(test)] mod tests { use super::*; - use crate::config::CONFIG_TOML_FILE; use crate::config::ConfigBuilder; use crate::config::ConfigOverrides; use crate::config::ConfigToml; @@ -817,6 +816,7 @@ mod tests { use crate::config_loader::ConfigLayerStack; use crate::config_loader::ConfigRequirements; use crate::config_loader::ConfigRequirementsToml; + use codex_config::CONFIG_TOML_FILE; use codex_protocol::config_types::TrustLevel; use codex_protocol::protocol::SkillScope; use codex_utils_absolute_path::AbsolutePathBuf; diff --git a/codex-rs/core/tests/suite/unstable_features_warning.rs b/codex-rs/core/tests/suite/unstable_features_warning.rs index 1cb07c1f4..e5fdf61fd 100644 --- a/codex-rs/core/tests/suite/unstable_features_warning.rs +++ b/codex-rs/core/tests/suite/unstable_features_warning.rs @@ -1,8 +1,8 @@ #![allow(clippy::unwrap_used, clippy::expect_used)] +use codex_config::CONFIG_TOML_FILE; use codex_core::CodexAuth; use codex_core::NewThread; -use codex_core::config::CONFIG_TOML_FILE; use codex_core::features::Feature; use codex_core::protocol::EventMsg; use codex_core::protocol::InitialHistory;