diff --git a/codex-rs/core/src/config/mod.rs b/codex-rs/core/src/config/mod.rs index e72907e4e6..51a1bd07f7 100644 --- a/codex-rs/core/src/config/mod.rs +++ b/codex-rs/core/src/config/mod.rs @@ -1972,10 +1972,7 @@ trust_level = "trusted" fn feature_table_overrides_legacy_flags() -> std::io::Result<()> { let codex_home = TempDir::new()?; let mut entries = BTreeMap::new(); - entries.insert( - "apply_patch_freeform".to_string(), - crate::features::FeatureValue::Bool(false), - ); + entries.insert("apply_patch_freeform".to_string(), false); let cfg = ConfigToml { features: Some(crate::features::FeaturesToml { entries }), ..Default::default() diff --git a/codex-rs/core/src/features.rs b/codex-rs/core/src/features.rs index 1cb4cf5d81..4085783106 100644 --- a/codex-rs/core/src/features.rs +++ b/codex-rs/core/src/features.rs @@ -8,7 +8,6 @@ use crate::config::ConfigToml; use crate::config::profile::ConfigProfile; use serde::Deserialize; -use serde::Serialize; use std::collections::BTreeMap; use std::collections::BTreeSet; @@ -130,7 +129,6 @@ pub struct LegacyFeatureUsage { pub struct Features { enabled: BTreeSet, legacy_usages: BTreeSet, - request_compression: RequestCompressionFeature, } #[derive(Debug, Clone, Default)] @@ -156,7 +154,6 @@ impl Features { let mut features = Self { enabled: BTreeSet::new(), legacy_usages: BTreeSet::new(), - request_compression: RequestCompressionFeature::Disabled, }; for spec in FEATURES { if spec.default_enabled { @@ -172,17 +169,11 @@ impl Features { pub fn enable(&mut self, f: Feature) -> &mut Self { self.enabled.insert(f); - if matches!(f, Feature::RequestCompression) { - self.request_compression = RequestCompressionFeature::Zstd; - } self } pub fn disable(&mut self, f: Feature) -> &mut Self { self.enabled.remove(&f); - if matches!(f, Feature::RequestCompression) { - self.request_compression = RequestCompressionFeature::Disabled; - } self } @@ -206,62 +197,18 @@ impl Features { .map(|usage| (usage.alias.as_str(), usage.feature)) } - pub fn request_compression(&self) -> RequestCompressionFeature { - self.request_compression - } - - pub fn set_request_compression( - &mut self, - request_compression: RequestCompressionFeature, - ) -> &mut Self { - self.request_compression = request_compression; - if self.request_compression == RequestCompressionFeature::Disabled { - self.enabled.remove(&Feature::RequestCompression); - } else { - self.enabled.insert(Feature::RequestCompression); - } - self - } - /// Apply a table of key -> value toggles (e.g. from TOML). - pub fn apply_map(&mut self, m: &BTreeMap) { + pub fn apply_map(&mut self, m: &BTreeMap) { for (k, v) in m { match feature_for_key(k) { Some(feat) => { if k != feat.key() { self.record_legacy_usage(k.as_str(), feat); } - if feat == Feature::RequestCompression { - match v { - FeatureValue::Bool(enabled) => { - let request_compression = if *enabled { - RequestCompressionFeature::Zstd - } else { - RequestCompressionFeature::Disabled - }; - self.set_request_compression(request_compression); - } - FeatureValue::String(value) => { - match RequestCompressionFeature::parse(value) { - Some(request_compression) => { - self.set_request_compression(request_compression); - } - None => { - tracing::warn!( - "unknown request_compression feature value in config: {value}" - ); - } - } - } - } - } else if let FeatureValue::Bool(enabled) = v { - if *enabled { - self.enable(feat); - } else { - self.disable(feat); - } + if *v { + self.enable(feat); } else { - tracing::warn!("feature key expects boolean value: {k}"); + self.disable(feat); } } None => { @@ -334,31 +281,7 @@ pub fn is_known_feature_key(key: &str) -> bool { #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] pub struct FeaturesToml { #[serde(flatten)] - pub entries: BTreeMap, -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(untagged)] -pub enum FeatureValue { - Bool(bool), - String(String), -} - -#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] -pub enum RequestCompressionFeature { - #[default] - Disabled, - Zstd, -} - -impl RequestCompressionFeature { - pub fn parse(value: &str) -> Option { - match value.to_ascii_lowercase().as_str() { - "none" | "disabled" => Some(Self::Disabled), - "zstd" => Some(Self::Zstd), - _ => None, - } - } + pub entries: BTreeMap, } /// Single, easy-to-read registry of all feature definitions. diff --git a/codex-rs/core/src/model_provider_info.rs b/codex-rs/core/src/model_provider_info.rs index 9aab61b289..237e182fe9 100644 --- a/codex-rs/core/src/model_provider_info.rs +++ b/codex-rs/core/src/model_provider_info.rs @@ -19,8 +19,8 @@ use std::env::VarError; use std::time::Duration; use crate::error::EnvVarError; +use crate::features::Feature; use crate::features::Features; -use crate::features::RequestCompressionFeature; const DEFAULT_STREAM_IDLE_TIMEOUT_MS: u64 = 300_000; const DEFAULT_STREAM_MAX_RETRIES: u64 = 5; const DEFAULT_REQUEST_MAX_RETRIES: u64 = 4; @@ -280,11 +280,11 @@ impl ModelProviderInfo { auth_mode: Option, features: &Features, ) -> RequestCompression { - if self.is_openai() && matches!(auth_mode, Some(AuthMode::ChatGPT)) { - match features.request_compression() { - RequestCompressionFeature::Zstd => RequestCompression::Zstd, - RequestCompressionFeature::Disabled => RequestCompression::None, - } + if self.is_openai() + && matches!(auth_mode, Some(AuthMode::ChatGPT)) + && features.enabled(Feature::RequestCompression) + { + RequestCompression::Zstd } else { RequestCompression::None } diff --git a/codex-rs/core/tests/responses_headers.rs b/codex-rs/core/tests/responses_headers.rs index 4625286308..57b9ca064e 100644 --- a/codex-rs/core/tests/responses_headers.rs +++ b/codex-rs/core/tests/responses_headers.rs @@ -12,7 +12,7 @@ use codex_core::ResponseEvent; use codex_core::ResponseItem; use codex_core::WireApi; use codex_core::models_manager::manager::ModelsManager; -use codex_core::features::RequestCompressionFeature; +use codex_core::features::Feature; use codex_otel::otel_manager::OtelManager; use codex_protocol::ConversationId; use codex_protocol::config_types::ReasoningSummary; @@ -356,9 +356,7 @@ async fn responses_request_body_is_zstd_encoded() { let mut config = load_default_config_for_test(&codex_home); config.model_provider_id = provider.name.clone(); config.model_provider = provider.clone(); - config - .features - .set_request_compression(RequestCompressionFeature::Zstd); + config.features.enable(Feature::RequestCompression); let effort = config.model_reasoning_effort; let summary = config.model_reasoning_summary; let model = ModelsManager::get_model_offline(config.model.as_deref());