use std::collections::HashMap; use codex_app_server_protocol::AuthMode; use codex_core::protocol_config_types::ReasoningEffort; use once_cell::sync::Lazy; pub const HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG: &str = "hide_gpt5_1_migration_prompt"; pub const HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG: &str = "hide_gpt-5.1-codex-max_migration_prompt"; /// A reasoning effort option that can be surfaced for a model. #[derive(Debug, Clone, Copy)] pub struct ReasoningEffortPreset { /// Effort level that the model supports. pub effort: ReasoningEffort, /// Short human description shown next to the effort in UIs. pub description: &'static str, } #[derive(Debug, Clone)] pub struct ModelUpgrade { pub id: &'static str, pub reasoning_effort_mapping: Option>, pub migration_config_key: &'static str, } /// Metadata describing a Codex-supported model. #[derive(Debug, Clone)] pub struct ModelPreset { /// Stable identifier for the preset. pub id: &'static str, /// Model slug (e.g., "gpt-5"). pub model: &'static str, /// Display name shown in UIs. pub display_name: &'static str, /// Short human description shown in UIs. pub description: &'static str, /// Reasoning effort applied when none is explicitly chosen. pub default_reasoning_effort: ReasoningEffort, /// Supported reasoning effort options. pub supported_reasoning_efforts: &'static [ReasoningEffortPreset], /// Whether this is the default model for new users. pub is_default: bool, /// recommended upgrade model pub upgrade: Option, /// Whether this preset should appear in the picker UI. pub show_in_picker: bool, } static PRESETS: Lazy> = Lazy::new(|| { vec![ ModelPreset { id: "gpt-5.1-codex-max", model: "gpt-5.1-codex-max", display_name: "gpt-5.1-codex-max", description: "Latest Codex-optimized flagship for deep and fast reasoning.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Low, description: "Fast responses with lighter reasoning", }, ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Balances speed and reasoning depth for everyday tasks", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex problems", }, ReasoningEffortPreset { effort: ReasoningEffort::XHigh, description: "Extra high reasoning depth for complex problems", }, ], is_default: true, upgrade: None, show_in_picker: true, }, ModelPreset { id: "gpt-5.1-codex", model: "gpt-5.1-codex", display_name: "gpt-5.1-codex", description: "Optimized for codex.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Low, description: "Fastest responses with limited reasoning", }, ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Dynamically adjusts reasoning based on the task", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex or ambiguous problems", }, ], is_default: false, upgrade: Some(ModelUpgrade { id: "gpt-5.1-codex-max", reasoning_effort_mapping: None, migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG, }), show_in_picker: true, }, ModelPreset { id: "gpt-5.1-codex-mini", model: "gpt-5.1-codex-mini", display_name: "gpt-5.1-codex-mini", description: "Optimized for codex. Cheaper, faster, but less capable.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Dynamically adjusts reasoning based on the task", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex or ambiguous problems", }, ], is_default: false, upgrade: Some(ModelUpgrade { id: "gpt-5.1-codex-max", reasoning_effort_mapping: None, migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG, }), show_in_picker: true, }, ModelPreset { id: "gpt-5.1", model: "gpt-5.1", display_name: "gpt-5.1", description: "Broad world knowledge with strong general reasoning.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Low, description: "Balances speed with some reasoning; useful for straightforward queries and short explanations", }, ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Provides a solid balance of reasoning depth and latency for general-purpose tasks", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex or ambiguous problems", }, ], is_default: false, upgrade: Some(ModelUpgrade { id: "gpt-5.1-codex-max", reasoning_effort_mapping: None, migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG, }), show_in_picker: true, }, // Deprecated models. ModelPreset { id: "gpt-5-codex", model: "gpt-5-codex", display_name: "gpt-5-codex", description: "Optimized for codex.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Low, description: "Fastest responses with limited reasoning", }, ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Dynamically adjusts reasoning based on the task", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex or ambiguous problems", }, ], is_default: false, upgrade: Some(ModelUpgrade { id: "gpt-5.1-codex-max", reasoning_effort_mapping: None, migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG, }), show_in_picker: false, }, ModelPreset { id: "gpt-5-codex-mini", model: "gpt-5-codex-mini", display_name: "gpt-5-codex-mini", description: "Optimized for codex. Cheaper, faster, but less capable.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Dynamically adjusts reasoning based on the task", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex or ambiguous problems", }, ], is_default: false, upgrade: Some(ModelUpgrade { id: "gpt-5.1-codex-mini", reasoning_effort_mapping: None, migration_config_key: HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG, }), show_in_picker: false, }, ModelPreset { id: "gpt-5", model: "gpt-5", display_name: "gpt-5", description: "Broad world knowledge with strong general reasoning.", default_reasoning_effort: ReasoningEffort::Medium, supported_reasoning_efforts: &[ ReasoningEffortPreset { effort: ReasoningEffort::Minimal, description: "Fastest responses with little reasoning", }, ReasoningEffortPreset { effort: ReasoningEffort::Low, description: "Balances speed with some reasoning; useful for straightforward queries and short explanations", }, ReasoningEffortPreset { effort: ReasoningEffort::Medium, description: "Provides a solid balance of reasoning depth and latency for general-purpose tasks", }, ReasoningEffortPreset { effort: ReasoningEffort::High, description: "Maximizes reasoning depth for complex or ambiguous problems", }, ], is_default: false, upgrade: Some(ModelUpgrade { id: "gpt-5.1-codex-max", reasoning_effort_mapping: None, migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG, }), show_in_picker: false, }, ] }); pub fn builtin_model_presets(auth_mode: Option) -> Vec { PRESETS .iter() .filter(|preset| match auth_mode { Some(AuthMode::ApiKey) => preset.show_in_picker && preset.id != "gpt-5.1-codex-max", _ => preset.show_in_picker, }) .cloned() .collect() } pub fn all_model_presets() -> &'static Vec { &PRESETS } #[cfg(test)] mod tests { use super::*; use codex_app_server_protocol::AuthMode; #[test] fn only_one_default_model_is_configured() { let default_models = PRESETS.iter().filter(|preset| preset.is_default).count(); assert!(default_models == 1); } #[test] fn gpt_5_1_codex_max_hidden_for_api_key_auth() { let presets = builtin_model_presets(Some(AuthMode::ApiKey)); assert!( presets .iter() .all(|preset| preset.id != "gpt-5.1-codex-max") ); } }