mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
Migrate model preset (#7542)
- Introduce `openai_models` in `/core` - Move `PRESETS` under it - Move `ModelPreset`, `ModelUpgrade`, `ReasoningEffortPreset`, `ReasoningEffortPreset`, and `ReasoningEffortPreset` to `protocol` - Introduce `Op::ListModels` and `EventMsg::AvailableModels` Next steps: - migrate `app-server` and `tui` to use the introduced Operation
This commit is contained in:
Generated
-2
@@ -1117,12 +1117,10 @@ name = "codex-common"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"codex-app-server-protocol",
|
||||
"codex-core",
|
||||
"codex-lmstudio",
|
||||
"codex-ollama",
|
||||
"codex-protocol",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"toml",
|
||||
]
|
||||
|
||||
@@ -3,11 +3,11 @@ use std::path::PathBuf;
|
||||
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
|
||||
@@ -4,11 +4,11 @@ use std::path::PathBuf;
|
||||
use crate::protocol::common::AuthMode;
|
||||
use codex_protocol::account::PlanType;
|
||||
use codex_protocol::approvals::SandboxCommandAssessment as CoreSandboxCommandAssessment;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::items::AgentMessageContent as CoreAgentMessageContent;
|
||||
use codex_protocol::items::TurnItem as CoreTurnItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::parse_command::ParsedCommand as CoreParsedCommand;
|
||||
use codex_protocol::plan_tool::PlanItemArg as CorePlanItemArg;
|
||||
use codex_protocol::plan_tool::StepStatus as CorePlanStepStatus;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_app_server_protocol::Model;
|
||||
use codex_app_server_protocol::ReasoningEffortOption;
|
||||
use codex_common::model_presets::ModelPreset;
|
||||
use codex_common::model_presets::ReasoningEffortPreset;
|
||||
use codex_common::model_presets::builtin_model_presets;
|
||||
use codex_core::openai_models::model_presets::builtin_model_presets;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
|
||||
pub fn supported_models(auth_mode: Option<AuthMode>) -> Vec<Model> {
|
||||
builtin_model_presets(auth_mode)
|
||||
@@ -27,7 +27,7 @@ fn model_from_preset(preset: ModelPreset) -> Model {
|
||||
}
|
||||
|
||||
fn reasoning_efforts_from_preset(
|
||||
efforts: &'static [ReasoningEffortPreset],
|
||||
efforts: Vec<ReasoningEffortPreset>,
|
||||
) -> Vec<ReasoningEffortOption> {
|
||||
efforts
|
||||
.iter()
|
||||
|
||||
@@ -23,10 +23,10 @@ use codex_app_server_protocol::SendUserTurnResponse;
|
||||
use codex_app_server_protocol::ServerRequest;
|
||||
use codex_core::protocol::AskForApproval;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol_config_types::ReasoningEffort;
|
||||
use codex_core::protocol_config_types::ReasoningSummary;
|
||||
use codex_core::spawn::CODEX_SANDBOX_NETWORK_DISABLED_ENV_VAR;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use codex_protocol::protocol::Event;
|
||||
use codex_protocol::protocol::EventMsg;
|
||||
|
||||
@@ -10,10 +10,10 @@ use codex_app_server_protocol::Tools;
|
||||
use codex_app_server_protocol::UserSavedConfig;
|
||||
use codex_core::protocol::AskForApproval;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -11,7 +11,7 @@ use codex_app_server_protocol::ModelListParams;
|
||||
use codex_app_server_protocol::ModelListResponse;
|
||||
use codex_app_server_protocol::ReasoningEffortOption;
|
||||
use codex_app_server_protocol::RequestId;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::timeout;
|
||||
|
||||
@@ -30,8 +30,8 @@ use codex_app_server_protocol::TurnStartResponse;
|
||||
use codex_app_server_protocol::TurnStartedNotification;
|
||||
use codex_app_server_protocol::TurnStatus;
|
||||
use codex_app_server_protocol::UserInput as V2UserInput;
|
||||
use codex_core::protocol_config_types::ReasoningEffort;
|
||||
use codex_core::protocol_config_types::ReasoningSummary;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use core_test_support::skip_if_no_network;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::path::Path;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use crate::error::ApiError;
|
||||
use codex_protocol::config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use codex_protocol::config_types::Verbosity as VerbosityConfig;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::RateLimitSnapshot;
|
||||
use codex_protocol::protocol::TokenUsage;
|
||||
use futures::Stream;
|
||||
|
||||
@@ -9,12 +9,10 @@ workspace = true
|
||||
|
||||
[dependencies]
|
||||
clap = { workspace = true, features = ["derive", "wrap_help"], optional = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-core = { workspace = true }
|
||||
codex-lmstudio = { workspace = true }
|
||||
codex-ollama = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
once_cell = { workspace = true }
|
||||
serde = { workspace = true, optional = true }
|
||||
toml = { workspace = true, optional = true }
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@ mod config_summary;
|
||||
pub use config_summary::create_config_summary_entries;
|
||||
// Shared fuzzy matcher (used by TUI selection popups and other UI filtering)
|
||||
pub mod fuzzy_match;
|
||||
// Shared model presets used by TUI and MCP server
|
||||
pub mod model_presets;
|
||||
// Shared approval presets (AskForApproval + Sandbox) used by TUI and MCP server
|
||||
// Not to be confused with AskForApproval, which we should probably rename to EscalationPolicy.
|
||||
pub mod approval_presets;
|
||||
|
||||
@@ -20,9 +20,9 @@ use codex_api::error::ApiError;
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_otel::otel_event_manager::OtelEventManager;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use eventsource_stream::Event;
|
||||
use eventsource_stream::EventStreamError;
|
||||
|
||||
@@ -22,6 +22,7 @@ use crate::user_notification::UserNotifier;
|
||||
use crate::util::error_or_panic;
|
||||
use async_channel::Receiver;
|
||||
use async_channel::Sender;
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::items::TurnItem;
|
||||
use codex_protocol::protocol::FileChange;
|
||||
@@ -126,12 +127,12 @@ use crate::util::backoff;
|
||||
use codex_async_utils::OrCancelExt;
|
||||
use codex_execpolicy::Policy as ExecPolicy;
|
||||
use codex_otel::otel_event_manager::OtelEventManager;
|
||||
use codex_protocol::config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::CodexErrorInfo;
|
||||
use codex_protocol::protocol::InitialHistory;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
@@ -638,6 +639,14 @@ impl Session {
|
||||
Ok(sess)
|
||||
}
|
||||
|
||||
pub(crate) fn get_auth_mode(&self) -> AuthMode {
|
||||
self.services
|
||||
.auth_manager
|
||||
.auth()
|
||||
.map(|a| a.mode)
|
||||
.unwrap_or(AuthMode::ApiKey)
|
||||
}
|
||||
|
||||
pub(crate) fn get_tx_event(&self) -> Sender<Event> {
|
||||
self.tx_event.clone()
|
||||
}
|
||||
@@ -1478,6 +1487,9 @@ async fn submission_loop(sess: Arc<Session>, config: Arc<Config>, rx_sub: Receiv
|
||||
Op::Review { review_request } => {
|
||||
handlers::review(&sess, &config, sub.id.clone(), review_request).await;
|
||||
}
|
||||
Op::ListModels => {
|
||||
handlers::list_models(&sess, sub.id.clone(), Some(sess.get_auth_mode())).await;
|
||||
}
|
||||
_ => {} // Ignore unknown ops; enum is non_exhaustive to allow extensions.
|
||||
}
|
||||
}
|
||||
@@ -1494,12 +1506,15 @@ mod handlers {
|
||||
use crate::config::Config;
|
||||
use crate::mcp::auth::compute_auth_statuses;
|
||||
use crate::mcp::collect_mcp_snapshot_from_manager;
|
||||
use crate::openai_models::model_presets::builtin_model_presets;
|
||||
use crate::review_prompts::resolve_review_request;
|
||||
use crate::tasks::CompactTask;
|
||||
use crate::tasks::RegularTask;
|
||||
use crate::tasks::UndoTask;
|
||||
use crate::tasks::UserShellCommandTask;
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_protocol::custom_prompts::CustomPrompt;
|
||||
use codex_protocol::openai_models::AvailableModelsEvent;
|
||||
use codex_protocol::protocol::CodexErrorInfo;
|
||||
use codex_protocol::protocol::ErrorEvent;
|
||||
use codex_protocol::protocol::Event;
|
||||
@@ -1814,6 +1829,15 @@ mod handlers {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_models(sess: &Arc<Session>, sub_id: String, auth_mode: Option<AuthMode>) {
|
||||
let models = builtin_model_presets(auth_mode);
|
||||
let event = Event {
|
||||
id: sub_id,
|
||||
msg: EventMsg::ListModelsResponse(AvailableModelsEvent { models }),
|
||||
};
|
||||
sess.send_event_raw(event).await;
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn a review thread using the given prompt.
|
||||
|
||||
@@ -2,8 +2,8 @@ use crate::config::CONFIG_TOML_FILE;
|
||||
use crate::config::types::McpServerConfig;
|
||||
use crate::config::types::Notice;
|
||||
use anyhow::Context;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::TrustLevel;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
@@ -574,7 +574,7 @@ impl ConfigEditsBuilder {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::config::types::McpServerTransportConfig;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::tempdir;
|
||||
use tokio::runtime::Builder;
|
||||
|
||||
@@ -38,11 +38,11 @@ use crate::util::resolve_path;
|
||||
use codex_app_server_protocol::Tools;
|
||||
use codex_app_server_protocol::UserSavedConfig;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use codex_protocol::config_types::TrustLevel;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_rmcp_client::OAuthCredentialsStoreMode;
|
||||
use dirs::home_dir;
|
||||
use dunce::canonicalize;
|
||||
|
||||
@@ -2,10 +2,10 @@ use serde::Deserialize;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::protocol::AskForApproval;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
|
||||
/// Collection of common configuration options that a user can define as a unit
|
||||
/// in `config.toml`.
|
||||
|
||||
@@ -32,6 +32,7 @@ pub mod git_info;
|
||||
pub mod landlock;
|
||||
pub mod mcp;
|
||||
mod mcp_connection_manager;
|
||||
pub mod openai_models;
|
||||
pub use mcp_connection_manager::MCP_SANDBOX_STATE_CAPABILITY;
|
||||
pub use mcp_connection_manager::MCP_SANDBOX_STATE_NOTIFICATION;
|
||||
pub use mcp_connection_manager::SandboxState;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
|
||||
use crate::config::types::ReasoningSummaryFormat;
|
||||
use crate::tools::handlers::apply_patch::ApplyPatchToolType;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod model_presets;
|
||||
+74
-110
@@ -1,76 +1,38 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_core::protocol_config_types::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ModelUpgrade;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
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<HashMap<ReasoningEffort, ReasoningEffort>>,
|
||||
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<ModelUpgrade>,
|
||||
/// Whether this preset should appear in the picker UI.
|
||||
pub show_in_picker: bool,
|
||||
}
|
||||
|
||||
static PRESETS: Lazy<Vec<ModelPreset>> = 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.",
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
model: "gpt-5.1-codex-max".to_string(),
|
||||
display_name: "gpt-5.1-codex-max".to_string(),
|
||||
description: "Latest Codex-optimized flagship for deep and fast reasoning.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Fast responses with lighter reasoning",
|
||||
description: "Fast responses with lighter reasoning".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Balances speed and reasoning depth for everyday tasks",
|
||||
description: "Balances speed and reasoning depth for everyday tasks".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex problems",
|
||||
description: "Maximizes reasoning depth for complex problems".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::XHigh,
|
||||
description: "Extra high reasoning depth for complex problems",
|
||||
description: "Extra high reasoning depth for complex problems".to_string(),
|
||||
},
|
||||
],
|
||||
is_default: true,
|
||||
@@ -78,167 +40,169 @@ static PRESETS: Lazy<Vec<ModelPreset>> = Lazy::new(|| {
|
||||
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.",
|
||||
id: "gpt-5.1-codex".to_string(),
|
||||
model: "gpt-5.1-codex".to_string(),
|
||||
display_name: "gpt-5.1-codex".to_string(),
|
||||
description: "Optimized for codex.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Fastest responses with limited reasoning",
|
||||
description: "Fastest responses with limited reasoning".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Dynamically adjusts reasoning based on the task",
|
||||
description: "Dynamically adjusts reasoning based on the task".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems"
|
||||
.to_string(),
|
||||
},
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(ModelUpgrade {
|
||||
id: "gpt-5.1-codex-max",
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG.to_string(),
|
||||
}),
|
||||
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.",
|
||||
id: "gpt-5.1-codex-mini".to_string(),
|
||||
model: "gpt-5.1-codex-mini".to_string(),
|
||||
display_name: "gpt-5.1-codex-mini".to_string(),
|
||||
description: "Optimized for codex. Cheaper, faster, but less capable.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Dynamically adjusts reasoning based on the task",
|
||||
description: "Dynamically adjusts reasoning based on the task".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems"
|
||||
.to_string(),
|
||||
},
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(ModelUpgrade {
|
||||
id: "gpt-5.1-codex-max",
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG.to_string(),
|
||||
}),
|
||||
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.",
|
||||
id: "gpt-5.1".to_string(),
|
||||
model: "gpt-5.1".to_string(),
|
||||
display_name: "gpt-5.1".to_string(),
|
||||
description: "Broad world knowledge with strong general reasoning.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Balances speed with some reasoning; useful for straightforward queries and short explanations",
|
||||
description: "Balances speed with some reasoning; useful for straightforward queries and short explanations".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Provides a solid balance of reasoning depth and latency for general-purpose tasks",
|
||||
description: "Provides a solid balance of reasoning depth and latency for general-purpose tasks".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems".to_string(),
|
||||
},
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(ModelUpgrade {
|
||||
id: "gpt-5.1-codex-max",
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG.to_string(),
|
||||
}),
|
||||
show_in_picker: true,
|
||||
},
|
||||
// Deprecated models.
|
||||
ModelPreset {
|
||||
id: "gpt-5-codex",
|
||||
model: "gpt-5-codex",
|
||||
display_name: "gpt-5-codex",
|
||||
description: "Optimized for codex.",
|
||||
id: "gpt-5-codex".to_string(),
|
||||
model: "gpt-5-codex".to_string(),
|
||||
display_name: "gpt-5-codex".to_string(),
|
||||
description: "Optimized for codex.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Fastest responses with limited reasoning",
|
||||
description: "Fastest responses with limited reasoning".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Dynamically adjusts reasoning based on the task",
|
||||
description: "Dynamically adjusts reasoning based on the task".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems".to_string(),
|
||||
},
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(ModelUpgrade {
|
||||
id: "gpt-5.1-codex-max",
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG.to_string(),
|
||||
}),
|
||||
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.",
|
||||
id: "gpt-5-codex-mini".to_string(),
|
||||
model: "gpt-5-codex-mini".to_string(),
|
||||
display_name: "gpt-5-codex-mini".to_string(),
|
||||
description: "Optimized for codex. Cheaper, faster, but less capable.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Dynamically adjusts reasoning based on the task",
|
||||
description: "Dynamically adjusts reasoning based on the task".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems".to_string(),
|
||||
},
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(ModelUpgrade {
|
||||
id: "gpt-5.1-codex-mini",
|
||||
id: "gpt-5.1-codex-mini".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG,
|
||||
migration_config_key: HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG.to_string(),
|
||||
}),
|
||||
show_in_picker: false,
|
||||
},
|
||||
ModelPreset {
|
||||
id: "gpt-5",
|
||||
model: "gpt-5",
|
||||
display_name: "gpt-5",
|
||||
description: "Broad world knowledge with strong general reasoning.",
|
||||
id: "gpt-5".to_string(),
|
||||
model: "gpt-5".to_string(),
|
||||
display_name: "gpt-5".to_string(),
|
||||
description: "Broad world knowledge with strong general reasoning.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: &[
|
||||
supported_reasoning_efforts: vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Minimal,
|
||||
description: "Fastest responses with little reasoning",
|
||||
description: "Fastest responses with little reasoning".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Balances speed with some reasoning; useful for straightforward queries and short explanations",
|
||||
description: "Balances speed with some reasoning; useful for straightforward queries and short explanations".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Medium,
|
||||
description: "Provides a solid balance of reasoning depth and latency for general-purpose tasks",
|
||||
description: "Provides a solid balance of reasoning depth and latency for general-purpose tasks".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems".to_string(),
|
||||
},
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(ModelUpgrade {
|
||||
id: "gpt-5.1-codex-max",
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG,
|
||||
migration_config_key: HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG.to_string(),
|
||||
}),
|
||||
show_in_picker: false,
|
||||
},
|
||||
@@ -51,6 +51,7 @@ pub(crate) fn should_persist_event_msg(ev: &EventMsg) -> bool {
|
||||
| EventMsg::Warning(_)
|
||||
| EventMsg::TaskStarted(_)
|
||||
| EventMsg::TaskComplete(_)
|
||||
| EventMsg::ListModelsResponse(_)
|
||||
| EventMsg::AgentMessageDelta(_)
|
||||
| EventMsg::AgentReasoningDelta(_)
|
||||
| EventMsg::AgentReasoningRawContentDelta(_)
|
||||
|
||||
@@ -14,9 +14,9 @@ use crate::protocol::SandboxPolicy;
|
||||
use askama::Template;
|
||||
use codex_otel::otel_event_manager::OtelEventManager;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::protocol::SandboxCommandAssessment;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use futures::StreamExt;
|
||||
|
||||
@@ -22,11 +22,11 @@ use codex_core::protocol::Op;
|
||||
use codex_core::protocol::SessionSource;
|
||||
use codex_otel::otel_event_manager::OtelEventManager;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::Verbosity;
|
||||
use codex_protocol::models::ReasoningItemContent;
|
||||
use codex_protocol::models::ReasoningItemReasoningSummary;
|
||||
use codex_protocol::models::WebSearchAction;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use core_test_support::load_default_config_for_test;
|
||||
use core_test_support::load_sse_fixture_with_id;
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
use anyhow::Result;
|
||||
use codex_core::CodexAuth;
|
||||
use codex_core::protocol::EventMsg;
|
||||
use codex_core::protocol::Op;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
use core_test_support::responses::start_mock_server;
|
||||
use core_test_support::test_codex::test_codex;
|
||||
use core_test_support::wait_for_event_match;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn list_models_returns_api_key_models() -> Result<()> {
|
||||
let server = start_mock_server().await;
|
||||
let mut builder = test_codex().with_auth(CodexAuth::from_api_key("sk-test"));
|
||||
let test = builder.build(&server).await?;
|
||||
|
||||
test.codex.submit(Op::ListModels).await?;
|
||||
|
||||
let event = wait_for_event_match(&test.codex, |event| match event {
|
||||
EventMsg::ListModelsResponse(models) => Some(models.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.await;
|
||||
|
||||
let expected_models = expected_models_for_api_key();
|
||||
assert_eq!(expected_models, event.models);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
async fn list_models_returns_chatgpt_models() -> Result<()> {
|
||||
let server = start_mock_server().await;
|
||||
let mut builder = test_codex().with_auth(CodexAuth::create_dummy_chatgpt_auth_for_testing());
|
||||
let test = builder.build(&server).await?;
|
||||
|
||||
test.codex.submit(Op::ListModels).await?;
|
||||
|
||||
let event = wait_for_event_match(&test.codex, |event| match event {
|
||||
EventMsg::ListModelsResponse(models) => Some(models.clone()),
|
||||
_ => None,
|
||||
})
|
||||
.await;
|
||||
|
||||
let expected_models = expected_models_for_chatgpt();
|
||||
assert_eq!(expected_models, event.models);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn expected_models_for_api_key() -> Vec<ModelPreset> {
|
||||
vec![gpt_5_1_codex(), gpt_5_1_codex_mini(), gpt_5_1()]
|
||||
}
|
||||
|
||||
fn expected_models_for_chatgpt() -> Vec<ModelPreset> {
|
||||
vec![
|
||||
gpt_5_1_codex_max(),
|
||||
gpt_5_1_codex(),
|
||||
gpt_5_1_codex_mini(),
|
||||
gpt_5_1(),
|
||||
]
|
||||
}
|
||||
|
||||
fn gpt_5_1_codex_max() -> ModelPreset {
|
||||
ModelPreset {
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
model: "gpt-5.1-codex-max".to_string(),
|
||||
display_name: "gpt-5.1-codex-max".to_string(),
|
||||
description: "Latest Codex-optimized flagship for deep and fast reasoning.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: vec![
|
||||
effort(
|
||||
ReasoningEffort::Low,
|
||||
"Fast responses with lighter reasoning",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::Medium,
|
||||
"Balances speed and reasoning depth for everyday tasks",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::High,
|
||||
"Maximizes reasoning depth for complex problems",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::XHigh,
|
||||
"Extra high reasoning depth for complex problems",
|
||||
),
|
||||
],
|
||||
is_default: true,
|
||||
upgrade: None,
|
||||
show_in_picker: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn gpt_5_1_codex() -> ModelPreset {
|
||||
ModelPreset {
|
||||
id: "gpt-5.1-codex".to_string(),
|
||||
model: "gpt-5.1-codex".to_string(),
|
||||
display_name: "gpt-5.1-codex".to_string(),
|
||||
description: "Optimized for codex.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: vec![
|
||||
effort(
|
||||
ReasoningEffort::Low,
|
||||
"Fastest responses with limited reasoning",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::Medium,
|
||||
"Dynamically adjusts reasoning based on the task",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::High,
|
||||
"Maximizes reasoning depth for complex or ambiguous problems",
|
||||
),
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(gpt_5_1_codex_max_upgrade()),
|
||||
show_in_picker: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn gpt_5_1_codex_mini() -> ModelPreset {
|
||||
ModelPreset {
|
||||
id: "gpt-5.1-codex-mini".to_string(),
|
||||
model: "gpt-5.1-codex-mini".to_string(),
|
||||
display_name: "gpt-5.1-codex-mini".to_string(),
|
||||
description: "Optimized for codex. Cheaper, faster, but less capable.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: vec![
|
||||
effort(
|
||||
ReasoningEffort::Medium,
|
||||
"Dynamically adjusts reasoning based on the task",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::High,
|
||||
"Maximizes reasoning depth for complex or ambiguous problems",
|
||||
),
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(gpt_5_1_codex_max_upgrade()),
|
||||
show_in_picker: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn gpt_5_1() -> ModelPreset {
|
||||
ModelPreset {
|
||||
id: "gpt-5.1".to_string(),
|
||||
model: "gpt-5.1".to_string(),
|
||||
display_name: "gpt-5.1".to_string(),
|
||||
description: "Broad world knowledge with strong general reasoning.".to_string(),
|
||||
default_reasoning_effort: ReasoningEffort::Medium,
|
||||
supported_reasoning_efforts: vec![
|
||||
effort(
|
||||
ReasoningEffort::Low,
|
||||
"Balances speed with some reasoning; useful for straightforward queries and short explanations",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::Medium,
|
||||
"Provides a solid balance of reasoning depth and latency for general-purpose tasks",
|
||||
),
|
||||
effort(
|
||||
ReasoningEffort::High,
|
||||
"Maximizes reasoning depth for complex or ambiguous problems",
|
||||
),
|
||||
],
|
||||
is_default: false,
|
||||
upgrade: Some(gpt_5_1_codex_max_upgrade()),
|
||||
show_in_picker: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn gpt_5_1_codex_max_upgrade() -> codex_protocol::openai_models::ModelUpgrade {
|
||||
codex_protocol::openai_models::ModelUpgrade {
|
||||
id: "gpt-5.1-codex-max".to_string(),
|
||||
reasoning_effort_mapping: None,
|
||||
migration_config_key: "hide_gpt-5.1-codex-max_migration_prompt".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
fn effort(reasoning_effort: ReasoningEffort, description: &str) -> ReasoningEffortPreset {
|
||||
ReasoningEffortPreset {
|
||||
effort: reasoning_effort,
|
||||
description: description.to_string(),
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ mod grep_files;
|
||||
mod items;
|
||||
mod json_result;
|
||||
mod list_dir;
|
||||
mod list_models;
|
||||
mod live_cli;
|
||||
mod model_overrides;
|
||||
mod model_tools;
|
||||
|
||||
@@ -2,7 +2,7 @@ use codex_core::CodexAuth;
|
||||
use codex_core::ConversationManager;
|
||||
use codex_core::protocol::EventMsg;
|
||||
use codex_core::protocol::Op;
|
||||
use codex_core::protocol_config_types::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use core_test_support::load_default_config_for_test;
|
||||
use core_test_support::wait_for_event;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
@@ -7,10 +7,10 @@ use codex_core::protocol::ENVIRONMENT_CONTEXT_OPEN_TAG;
|
||||
use codex_core::protocol::EventMsg;
|
||||
use codex_core::protocol::Op;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol_config_types::ReasoningEffort;
|
||||
use codex_core::protocol_config_types::ReasoningSummary;
|
||||
use codex_core::shell::Shell;
|
||||
use codex_core::shell::default_user_shell;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::user_input::UserInput;
|
||||
use core_test_support::load_sse_fixture_with_id;
|
||||
use core_test_support::responses::mount_sse_once;
|
||||
|
||||
@@ -583,6 +583,7 @@ impl EventProcessor for EventProcessorWithHumanOutput {
|
||||
| EventMsg::ReasoningContentDelta(_)
|
||||
| EventMsg::ReasoningRawContentDelta(_)
|
||||
| EventMsg::UndoCompleted(_)
|
||||
| EventMsg::ListModelsResponse(_)
|
||||
| EventMsg::UndoStarted(_) => {}
|
||||
}
|
||||
CodexStatus::Running
|
||||
|
||||
@@ -307,6 +307,7 @@ async fn run_codex_tool_session_inner(
|
||||
| EventMsg::UndoCompleted(_)
|
||||
| EventMsg::ExitedReviewMode(_)
|
||||
| EventMsg::ContextCompacted(_)
|
||||
| EventMsg::ListModelsResponse(_)
|
||||
| EventMsg::DeprecationNotice(_) => {
|
||||
// For now, we do not do anything extra for these
|
||||
// events. Note that
|
||||
|
||||
@@ -239,7 +239,7 @@ mod tests {
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol::SessionConfiguredEvent;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use tempfile::NamedTempFile;
|
||||
|
||||
@@ -2,9 +2,9 @@ use chrono::SecondsFormat;
|
||||
use chrono::Utc;
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::ReviewDecision;
|
||||
use codex_protocol::protocol::SandboxPolicy;
|
||||
|
||||
@@ -2,37 +2,8 @@ use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum_macros::Display;
|
||||
use strum_macros::EnumIter;
|
||||
use ts_rs::TS;
|
||||
|
||||
/// See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning
|
||||
#[derive(
|
||||
Debug,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Display,
|
||||
JsonSchema,
|
||||
TS,
|
||||
EnumIter,
|
||||
Hash,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum ReasoningEffort {
|
||||
None,
|
||||
Minimal,
|
||||
Low,
|
||||
#[default]
|
||||
Medium,
|
||||
High,
|
||||
XHigh,
|
||||
}
|
||||
|
||||
/// A summary of the reasoning performed by the model. This can be useful for
|
||||
/// debugging and understanding the model's reasoning process.
|
||||
/// See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries
|
||||
|
||||
@@ -8,6 +8,7 @@ pub mod items;
|
||||
pub mod message_history;
|
||||
pub mod models;
|
||||
pub mod num_format;
|
||||
pub mod openai_models;
|
||||
pub mod parse_command;
|
||||
pub mod plan_tool;
|
||||
pub mod protocol;
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
use std::collections::HashMap;
|
||||
|
||||
use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum_macros::Display;
|
||||
use strum_macros::EnumIter;
|
||||
use ts_rs::TS;
|
||||
|
||||
/// See https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning
|
||||
#[derive(
|
||||
Debug,
|
||||
Serialize,
|
||||
Deserialize,
|
||||
Default,
|
||||
Clone,
|
||||
Copy,
|
||||
PartialEq,
|
||||
Eq,
|
||||
Display,
|
||||
JsonSchema,
|
||||
TS,
|
||||
EnumIter,
|
||||
Hash,
|
||||
)]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum ReasoningEffort {
|
||||
None,
|
||||
Minimal,
|
||||
Low,
|
||||
#[default]
|
||||
Medium,
|
||||
High,
|
||||
XHigh,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema)]
|
||||
pub struct AvailableModelsEvent {
|
||||
pub models: Vec<ModelPreset>,
|
||||
}
|
||||
|
||||
/// A reasoning effort option that can be surfaced for a model.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct ReasoningEffortPreset {
|
||||
/// Effort level that the model supports.
|
||||
pub effort: ReasoningEffort,
|
||||
/// Short human description shown next to the effort in UIs.
|
||||
pub description: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct ModelUpgrade {
|
||||
pub id: String,
|
||||
pub reasoning_effort_mapping: Option<HashMap<ReasoningEffort, ReasoningEffort>>,
|
||||
pub migration_config_key: String,
|
||||
}
|
||||
|
||||
/// Metadata describing a Codex-supported model.
|
||||
#[derive(Debug, Clone, Deserialize, Serialize, TS, JsonSchema, PartialEq)]
|
||||
pub struct ModelPreset {
|
||||
/// Stable identifier for the preset.
|
||||
pub id: String,
|
||||
/// Model slug (e.g., "gpt-5").
|
||||
pub model: String,
|
||||
/// Display name shown in UIs.
|
||||
pub display_name: String,
|
||||
/// Short human description shown in UIs.
|
||||
pub description: String,
|
||||
/// Reasoning effort applied when none is explicitly chosen.
|
||||
pub default_reasoning_effort: ReasoningEffort,
|
||||
/// Supported reasoning effort options.
|
||||
pub supported_reasoning_efforts: Vec<ReasoningEffortPreset>,
|
||||
/// Whether this is the default model for new users.
|
||||
pub is_default: bool,
|
||||
/// recommended upgrade model
|
||||
pub upgrade: Option<ModelUpgrade>,
|
||||
/// Whether this preset should appear in the picker UI.
|
||||
pub show_in_picker: bool,
|
||||
}
|
||||
@@ -12,7 +12,6 @@ use std::time::Duration;
|
||||
|
||||
use crate::ConversationId;
|
||||
use crate::approvals::ElicitationRequestEvent;
|
||||
use crate::config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use crate::config_types::ReasoningSummary as ReasoningSummaryConfig;
|
||||
use crate::custom_prompts::CustomPrompt;
|
||||
use crate::items::TurnItem;
|
||||
@@ -20,6 +19,8 @@ use crate::message_history::HistoryEntry;
|
||||
use crate::models::ContentItem;
|
||||
use crate::models::ResponseItem;
|
||||
use crate::num_format::format_with_separators;
|
||||
use crate::openai_models::AvailableModelsEvent;
|
||||
use crate::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use crate::parse_command::ParsedCommand;
|
||||
use crate::plan_tool::UpdatePlanArgs;
|
||||
use crate::user_input::UserInput;
|
||||
@@ -208,6 +209,9 @@ pub enum Op {
|
||||
/// The raw command string after '!'
|
||||
command: String,
|
||||
},
|
||||
|
||||
/// Request the list of available models.
|
||||
ListModels,
|
||||
}
|
||||
|
||||
/// Determines the conditions under which the user is consulted to approve
|
||||
@@ -578,6 +582,7 @@ pub enum EventMsg {
|
||||
AgentMessageContentDelta(AgentMessageContentDeltaEvent),
|
||||
ReasoningContentDelta(ReasoningContentDeltaEvent),
|
||||
ReasoningRawContentDelta(ReasoningRawContentDeltaEvent),
|
||||
ListModelsResponse(AvailableModelsEvent),
|
||||
}
|
||||
|
||||
/// Codex errors that we expose to clients.
|
||||
|
||||
@@ -21,10 +21,6 @@ use crate::tui::TuiEvent;
|
||||
use crate::update_action::UpdateAction;
|
||||
use codex_ansi_escape::ansi_escape_line;
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_common::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_common::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_common::model_presets::ModelUpgrade;
|
||||
use codex_common::model_presets::all_model_presets;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::ConversationManager;
|
||||
use codex_core::config::Config;
|
||||
@@ -32,14 +28,18 @@ use codex_core::config::edit::ConfigEditsBuilder;
|
||||
#[cfg(target_os = "windows")]
|
||||
use codex_core::features::Feature;
|
||||
use codex_core::model_family::find_family_for_model;
|
||||
use codex_core::openai_models::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_core::openai_models::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_core::openai_models::model_presets::all_model_presets;
|
||||
use codex_core::protocol::EventMsg;
|
||||
use codex_core::protocol::FinalOutput;
|
||||
use codex_core::protocol::Op;
|
||||
use codex_core::protocol::SessionSource;
|
||||
use codex_core::protocol::TokenUsage;
|
||||
use codex_core::protocol_config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_core::skills::load_skills;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::openai_models::ModelUpgrade;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use color_eyre::eyre::Result;
|
||||
use color_eyre::eyre::WrapErr;
|
||||
use crossterm::event::KeyCode;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_common::approval_presets::ApprovalPreset;
|
||||
use codex_common::model_presets::ModelPreset;
|
||||
use codex_core::protocol::ConversationPathResponseEvent;
|
||||
use codex_core::protocol::Event;
|
||||
use codex_core::protocol::RateLimitSnapshot;
|
||||
use codex_file_search::FileMatch;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
|
||||
use crate::bottom_pane::ApprovalRequest;
|
||||
use crate::history_cell::HistoryCell;
|
||||
|
||||
use codex_core::protocol::AskForApproval;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol_config_types::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
|
||||
#[allow(clippy::large_enum_variant)]
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -122,15 +122,15 @@ use std::path::Path;
|
||||
use chrono::Local;
|
||||
use codex_common::approval_presets::ApprovalPreset;
|
||||
use codex_common::approval_presets::builtin_approval_presets;
|
||||
use codex_common::model_presets::ModelPreset;
|
||||
use codex_common::model_presets::builtin_model_presets;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::CodexAuth;
|
||||
use codex_core::ConversationManager;
|
||||
use codex_core::openai_models::model_presets::builtin_model_presets;
|
||||
use codex_core::protocol::AskForApproval;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol_config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_file_search::FileMatch;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::plan_tool::UpdatePlanArgs;
|
||||
use strum::IntoEnumIterator;
|
||||
|
||||
@@ -1833,6 +1833,7 @@ impl ChatWidget {
|
||||
| EventMsg::ItemCompleted(_)
|
||||
| EventMsg::AgentMessageContentDelta(_)
|
||||
| EventMsg::ReasoningContentDelta(_)
|
||||
| EventMsg::ListModelsResponse(_)
|
||||
| EventMsg::ReasoningRawContentDelta(_) => {}
|
||||
}
|
||||
}
|
||||
@@ -2074,7 +2075,7 @@ impl ChatWidget {
|
||||
let description = if preset.description.is_empty() {
|
||||
Some("Uses fewer credits for upcoming turns.".to_string())
|
||||
} else {
|
||||
Some(preset.description.to_string())
|
||||
Some(preset.description)
|
||||
};
|
||||
|
||||
let items = vec![
|
||||
@@ -2210,9 +2211,9 @@ impl ChatWidget {
|
||||
|
||||
if choices.len() == 1 {
|
||||
if let Some(effort) = choices.first().and_then(|c| c.stored) {
|
||||
self.apply_model_and_effort(preset.model.to_string(), Some(effort));
|
||||
self.apply_model_and_effort(preset.model, Some(effort));
|
||||
} else {
|
||||
self.apply_model_and_effort(preset.model.to_string(), None);
|
||||
self.apply_model_and_effort(preset.model, None);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ use crate::test_backend::VT100Backend;
|
||||
use crate::tui::FrameRequester;
|
||||
use assert_matches::assert_matches;
|
||||
use codex_common::approval_presets::builtin_approval_presets;
|
||||
use codex_common::model_presets::ModelPreset;
|
||||
use codex_common::model_presets::ReasoningEffortPreset;
|
||||
use codex_core::AuthManager;
|
||||
use codex_core::CodexAuth;
|
||||
use codex_core::config::Config;
|
||||
@@ -48,6 +46,8 @@ use codex_core::protocol::UndoStartedEvent;
|
||||
use codex_core::protocol::ViewImageToolCallEvent;
|
||||
use codex_core::protocol::WarningEvent;
|
||||
use codex_protocol::ConversationId;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
use codex_protocol::parse_command::ParsedCommand;
|
||||
use codex_protocol::plan_tool::PlanItemArg;
|
||||
use codex_protocol::plan_tool::StepStatus;
|
||||
@@ -1805,17 +1805,17 @@ fn reasoning_popup_shows_extra_high_with_space() {
|
||||
fn single_reasoning_option_skips_selection() {
|
||||
let (mut chat, mut rx, _op_rx) = make_chatwidget_manual();
|
||||
|
||||
static SINGLE_EFFORT: [ReasoningEffortPreset; 1] = [ReasoningEffortPreset {
|
||||
let single_effort = vec![ReasoningEffortPreset {
|
||||
effort: ReasoningEffortConfig::High,
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems",
|
||||
description: "Maximizes reasoning depth for complex or ambiguous problems".to_string(),
|
||||
}];
|
||||
let preset = ModelPreset {
|
||||
id: "model-with-single-reasoning",
|
||||
model: "model-with-single-reasoning",
|
||||
display_name: "model-with-single-reasoning",
|
||||
description: "",
|
||||
id: "model-with-single-reasoning".to_string(),
|
||||
model: "model-with-single-reasoning".to_string(),
|
||||
display_name: "model-with-single-reasoning".to_string(),
|
||||
description: "".to_string(),
|
||||
default_reasoning_effort: ReasoningEffortConfig::High,
|
||||
supported_reasoning_efforts: &SINGLE_EFFORT,
|
||||
supported_reasoning_efforts: single_effort,
|
||||
is_default: false,
|
||||
upgrade: None,
|
||||
show_in_picker: true,
|
||||
|
||||
@@ -31,7 +31,7 @@ use codex_core::protocol::FileChange;
|
||||
use codex_core::protocol::McpAuthStatus;
|
||||
use codex_core::protocol::McpInvocation;
|
||||
use codex_core::protocol::SessionConfiguredEvent;
|
||||
use codex_core::protocol_config_types::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
|
||||
use codex_protocol::plan_tool::PlanItemArg;
|
||||
use codex_protocol::plan_tool::StepStatus;
|
||||
use codex_protocol::plan_tool::UpdatePlanArgs;
|
||||
|
||||
@@ -7,8 +7,8 @@ use crate::selection_list::selection_option_row;
|
||||
use crate::tui::FrameRequester;
|
||||
use crate::tui::Tui;
|
||||
use crate::tui::TuiEvent;
|
||||
use codex_common::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_common::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_core::openai_models::model_presets::HIDE_GPT_5_1_CODEX_MAX_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_core::openai_models::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use crossterm::event::KeyEventKind;
|
||||
@@ -329,7 +329,7 @@ mod tests {
|
||||
use crate::custom_terminal::Terminal;
|
||||
use crate::test_backend::VT100Backend;
|
||||
use crate::tui::FrameRequester;
|
||||
use codex_common::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG;
|
||||
use codex_core::openai_models::model_presets::HIDE_GPT5_1_MIGRATION_PROMPT_CONFIG;
|
||||
use crossterm::event::KeyCode;
|
||||
use crossterm::event::KeyEvent;
|
||||
use insta::assert_snapshot;
|
||||
|
||||
@@ -13,8 +13,8 @@ use codex_core::protocol::RateLimitSnapshot;
|
||||
use codex_core::protocol::RateLimitWindow;
|
||||
use codex_core::protocol::SandboxPolicy;
|
||||
use codex_core::protocol::TokenUsage;
|
||||
use codex_protocol::config_types::ReasoningEffort;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use insta::assert_snapshot;
|
||||
use ratatui::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
||||
Reference in New Issue
Block a user