mirror of
https://github.com/openai/codex.git
synced 2026-11-09 20:50:33 +00:00
feat: add gated ultra reasoning effort
This commit is contained in:
@@ -163,6 +163,13 @@ pub(crate) struct CompactConversationRequestSettings {
|
||||
pub(crate) service_tier: Option<String>,
|
||||
}
|
||||
|
||||
fn reasoning_effort_for_request(effort: ReasoningEffortConfig) -> ReasoningEffortConfig {
|
||||
match effort {
|
||||
ReasoningEffortConfig::Ultra => ReasoningEffortConfig::Custom("max".to_string()),
|
||||
effort => effort,
|
||||
}
|
||||
}
|
||||
|
||||
fn session_telemetry_for_request(
|
||||
session_telemetry: &SessionTelemetry,
|
||||
request: &ResponsesApiRequest,
|
||||
@@ -665,11 +672,13 @@ impl ModelClient {
|
||||
let payload = ApiMemorySummarizeInput {
|
||||
model: model_info.slug.clone(),
|
||||
raw_memories,
|
||||
reasoning: effort.map(|effort| Reasoning {
|
||||
effort: Some(effort),
|
||||
summary: None,
|
||||
context: None,
|
||||
}),
|
||||
reasoning: effort
|
||||
.map(reasoning_effort_for_request)
|
||||
.map(|effort| Reasoning {
|
||||
effort: Some(effort),
|
||||
summary: None,
|
||||
context: None,
|
||||
}),
|
||||
};
|
||||
|
||||
client
|
||||
@@ -768,7 +777,9 @@ impl ModelClient {
|
||||
) -> Option<Reasoning> {
|
||||
if model_info.supports_reasoning_summaries {
|
||||
Some(Reasoning {
|
||||
effort: effort.or_else(|| model_info.default_reasoning_level.clone()),
|
||||
effort: effort
|
||||
.or_else(|| model_info.default_reasoning_level.clone())
|
||||
.map(reasoning_effort_for_request),
|
||||
summary: if summary == ReasoningSummaryConfig::None {
|
||||
None
|
||||
} else {
|
||||
|
||||
@@ -31,6 +31,7 @@ use codex_protocol::auth::AuthMode;
|
||||
use codex_protocol::models::ContentItem;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::InternalSessionSource;
|
||||
use codex_protocol::protocol::SessionSource;
|
||||
use codex_protocol::protocol::SubAgentSource;
|
||||
@@ -154,6 +155,20 @@ fn test_session_telemetry() -> SessionTelemetry {
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ultra_reasoning_uses_max_for_requests() {
|
||||
assert_eq!(
|
||||
(
|
||||
super::reasoning_effort_for_request(ReasoningEffort::Ultra),
|
||||
super::reasoning_effort_for_request(ReasoningEffort::High),
|
||||
),
|
||||
(
|
||||
ReasoningEffort::Custom("max".to_string()),
|
||||
ReasoningEffort::High,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct TagCollectorVisitor {
|
||||
tags: BTreeMap<String, String>,
|
||||
|
||||
@@ -1461,6 +1461,7 @@ impl Config {
|
||||
tool_output_token_limit: self.tool_output_token_limit,
|
||||
base_instructions: self.base_instructions.clone(),
|
||||
personality_enabled: self.features.enabled(Feature::Personality),
|
||||
ultra_reasoning_enabled: self.features.enabled(Feature::MultiAgentMode),
|
||||
model_supports_reasoning_summaries: self.model_supports_reasoning_summaries,
|
||||
model_catalog: self.model_catalog.clone(),
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ use codex_analytics::GuardianReviewFailureReason;
|
||||
use codex_analytics::GuardianReviewTerminalStatus;
|
||||
use codex_analytics::GuardianReviewTrackContext;
|
||||
use codex_analytics::GuardianReviewedAction;
|
||||
use codex_features::Feature;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::CodexErrorInfo;
|
||||
@@ -684,11 +685,14 @@ pub(super) async fn guardian_review_session_config(
|
||||
Some(network_proxy) => Some(network_proxy.proxy().current_cfg().await?),
|
||||
None => None,
|
||||
};
|
||||
let available_models = session
|
||||
let mut available_models = session
|
||||
.services
|
||||
.models_manager
|
||||
.list_models(codex_models_manager::manager::RefreshStrategy::Offline)
|
||||
.await;
|
||||
if !turn.config.features.enabled(Feature::MultiAgentMode) {
|
||||
codex_models_manager::model_presets::hide_ultra_reasoning_effort(&mut available_models);
|
||||
}
|
||||
let default_review_model_id = turn.provider.approval_review_preferred_model();
|
||||
let preferred_reasoning_effort = |supports_low: bool, fallback| {
|
||||
if supports_low {
|
||||
|
||||
@@ -6,6 +6,7 @@ use crate::config::ManagedFeatures;
|
||||
use crate::config::NetworkProxySpec;
|
||||
use crate::config::test_config;
|
||||
use crate::guardian::approval_request::guardian_request_target_item_id;
|
||||
use crate::guardian::review::guardian_review_session_config;
|
||||
use crate::session::session::Session;
|
||||
use crate::session::turn_context::TurnContext;
|
||||
use crate::test_support;
|
||||
@@ -36,6 +37,7 @@ use codex_protocol::models::PermissionProfile;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ModelsResponse;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
use codex_protocol::permissions::FileSystemSandboxEntry;
|
||||
@@ -1420,6 +1422,44 @@ enum GuardianTestCatalog {
|
||||
ParentOnly,
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn guardian_review_does_not_select_ultra_when_feature_is_disabled() -> anyhow::Result<()> {
|
||||
let server = start_mock_server().await;
|
||||
let (mut session, turn) = guardian_test_session_and_turn(&server).await;
|
||||
assert!(!turn.config.features.enabled(Feature::MultiAgentMode));
|
||||
|
||||
let mut review_model = turn.model_info.clone();
|
||||
review_model.slug = turn.provider.approval_review_preferred_model().to_string();
|
||||
review_model.default_reasoning_level = Some(ReasoningEffort::Ultra);
|
||||
review_model.supported_reasoning_levels = vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::High,
|
||||
description: "High".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Ultra,
|
||||
description: "Ultra".to_string(),
|
||||
},
|
||||
];
|
||||
let models_manager = StaticModelsManager::new(
|
||||
Some(Arc::clone(&session.services.auth_manager)),
|
||||
ModelsResponse {
|
||||
models: vec![review_model],
|
||||
},
|
||||
);
|
||||
Arc::get_mut(&mut session)
|
||||
.expect("session should be unique")
|
||||
.services
|
||||
.models_manager = Arc::new(models_manager);
|
||||
|
||||
let guardian_config = guardian_review_session_config(&session, &turn).await?;
|
||||
assert_eq!(
|
||||
guardian_config.spawn_config.model_reasoning_effort,
|
||||
Some(ReasoningEffort::High)
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn guardian_request_model_for_auto_review(
|
||||
auto_review_model_override: Option<String>,
|
||||
catalog: GuardianTestCatalog,
|
||||
|
||||
@@ -24,11 +24,14 @@ pub(super) async fn spawn_review_thread(
|
||||
let _ = review_features.disable(Feature::WebSearchCached);
|
||||
let _ = review_features.disable(Feature::Goals);
|
||||
let review_web_search_mode = WebSearchMode::Disabled;
|
||||
let available_models = sess
|
||||
let mut available_models = sess
|
||||
.services
|
||||
.models_manager
|
||||
.list_models(RefreshStrategy::OnlineIfUncached)
|
||||
.await;
|
||||
if !review_features.enabled(Feature::MultiAgentMode) {
|
||||
codex_models_manager::model_presets::hide_ultra_reasoning_effort(&mut available_models);
|
||||
}
|
||||
let unified_exec_shell_mode = UnifiedExecShellMode::for_session(
|
||||
codex_tools::unified_exec_feature_mode_for_features(review_features.get()),
|
||||
crate::tools::tool_user_shell_type(sess.services.user_shell.as_ref()),
|
||||
|
||||
@@ -6,6 +6,7 @@ use codex_core_skills::HostSkillsSnapshot;
|
||||
use codex_file_system::FileSystemSandboxContext;
|
||||
use codex_model_provider::SharedModelProvider;
|
||||
use codex_model_provider::create_model_provider;
|
||||
use codex_models_manager::model_presets::hide_ultra_reasoning_effort;
|
||||
use codex_protocol::SessionId;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::models::AdditionalPermissionProfile;
|
||||
@@ -246,9 +247,12 @@ impl TurnContext {
|
||||
Some(reasoning_effort.clone()),
|
||||
/*developer_instructions*/ None,
|
||||
);
|
||||
let available_models = models_manager
|
||||
let mut available_models = models_manager
|
||||
.list_models(RefreshStrategy::OnlineIfUncached)
|
||||
.await;
|
||||
if !config.features.enabled(Feature::MultiAgentMode) {
|
||||
hide_ultra_reasoning_effort(&mut available_models);
|
||||
}
|
||||
|
||||
Self {
|
||||
sub_id: self.sub_id.clone(),
|
||||
@@ -506,7 +510,10 @@ impl Session {
|
||||
let auth_manager_for_context = auth_manager.clone();
|
||||
let provider_for_context = create_model_provider(provider, auth_manager);
|
||||
let session_telemetry_for_context = session_telemetry;
|
||||
let available_models = models_manager.try_list_models().unwrap_or_default();
|
||||
let mut available_models = models_manager.try_list_models().unwrap_or_default();
|
||||
if !per_turn_config.features.enabled(Feature::MultiAgentMode) {
|
||||
hide_ultra_reasoning_effort(&mut available_models);
|
||||
}
|
||||
let unified_exec_shell_mode = UnifiedExecShellMode::for_session(
|
||||
codex_tools::unified_exec_feature_mode_for_features(per_turn_config.features.get()),
|
||||
crate::tools::tool_user_shell_type(user_shell),
|
||||
|
||||
@@ -130,6 +130,10 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() ->
|
||||
effort: ReasoningEffort::High,
|
||||
description: "Deep dive".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Ultra,
|
||||
description: "Maximum reasoning with proactive delegation".to_string(),
|
||||
},
|
||||
],
|
||||
vec![ModelServiceTier {
|
||||
id: "priority".to_string(),
|
||||
@@ -167,6 +171,10 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() ->
|
||||
.features
|
||||
.enable(Feature::Collab)
|
||||
.expect("test config should allow feature update");
|
||||
config
|
||||
.features
|
||||
.enable(Feature::MultiAgentMode)
|
||||
.expect("test config should allow feature update");
|
||||
config.multi_agent_v2.hide_spawn_agent_metadata = false;
|
||||
});
|
||||
let test = builder.build(&server).await?;
|
||||
@@ -200,7 +208,7 @@ async fn spawn_agent_description_lists_visible_models_and_reasoning_efforts() ->
|
||||
"expected model override usage guidance in spawn_agent description: {description:?}"
|
||||
);
|
||||
assert!(
|
||||
description.contains("Reasoning efforts: low, medium (default), high."),
|
||||
description.contains("Reasoning efforts: low, medium (default), high, ultra."),
|
||||
"expected default reasoning effort in spawn_agent description: {description:?}"
|
||||
);
|
||||
assert!(
|
||||
|
||||
@@ -145,7 +145,7 @@ pub enum Feature {
|
||||
Collab,
|
||||
/// Enable task-path-based multi-agent routing.
|
||||
MultiAgentV2,
|
||||
/// Removed compatibility flag retained as a no-op.
|
||||
/// Enable Ultra reasoning effort and its proactive multi-agent behavior.
|
||||
MultiAgentMode,
|
||||
/// Enable CSV-backed agent job tools.
|
||||
SpawnCsv,
|
||||
@@ -1036,7 +1036,7 @@ pub const FEATURES: &[FeatureSpec] = &[
|
||||
FeatureSpec {
|
||||
id: Feature::MultiAgentMode,
|
||||
key: "multi_agent_mode",
|
||||
stage: Stage::Removed,
|
||||
stage: Stage::UnderDevelopment,
|
||||
default_enabled: false,
|
||||
},
|
||||
FeatureSpec {
|
||||
|
||||
@@ -7,6 +7,7 @@ pub struct ModelsManagerConfig {
|
||||
pub tool_output_token_limit: Option<usize>,
|
||||
pub base_instructions: Option<String>,
|
||||
pub personality_enabled: bool,
|
||||
pub ultra_reasoning_enabled: bool,
|
||||
pub model_supports_reasoning_summaries: Option<bool>,
|
||||
pub model_catalog: Option<ModelsResponse>,
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ use codex_protocol::openai_models::ModelInfo;
|
||||
use codex_protocol::openai_models::ModelInstructionsVariables;
|
||||
use codex_protocol::openai_models::ModelMessages;
|
||||
use codex_protocol::openai_models::ModelVisibility;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::openai_models::TruncationMode;
|
||||
use codex_protocol::openai_models::TruncationPolicyConfig;
|
||||
use codex_protocol::openai_models::WebSearchToolType;
|
||||
@@ -21,6 +22,17 @@ const LOCAL_PRAGMATIC_TEMPLATE: &str = "You are a deeply pragmatic, effective so
|
||||
const PERSONALITY_PLACEHOLDER: &str = "{{ personality }}";
|
||||
|
||||
pub fn with_config_overrides(mut model: ModelInfo, config: &ModelsManagerConfig) -> ModelInfo {
|
||||
if !config.ultra_reasoning_enabled {
|
||||
model
|
||||
.supported_reasoning_levels
|
||||
.retain(|preset| preset.effort != ReasoningEffort::Ultra);
|
||||
if model.default_reasoning_level == Some(ReasoningEffort::Ultra) {
|
||||
model.default_reasoning_level = model
|
||||
.supported_reasoning_levels
|
||||
.last()
|
||||
.map(|preset| preset.effort.clone());
|
||||
}
|
||||
}
|
||||
if let Some(supports_reasoning_summaries) = config.model_supports_reasoning_summaries
|
||||
&& supports_reasoning_summaries
|
||||
{
|
||||
|
||||
@@ -1,7 +1,42 @@
|
||||
use super::*;
|
||||
use crate::ModelsManagerConfig;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
#[test]
|
||||
fn ultra_reasoning_requires_feature() {
|
||||
let mut model = model_info_from_slug("unknown-model");
|
||||
model.default_reasoning_level = Some(ReasoningEffort::Ultra);
|
||||
model.supported_reasoning_levels = vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Low".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Ultra,
|
||||
description: "Ultra".to_string(),
|
||||
},
|
||||
];
|
||||
let mut expected_without_ultra = model.clone();
|
||||
expected_without_ultra.default_reasoning_level = Some(ReasoningEffort::Low);
|
||||
expected_without_ultra.supported_reasoning_levels.pop();
|
||||
|
||||
assert_eq!(
|
||||
with_config_overrides(model.clone(), &ModelsManagerConfig::default()),
|
||||
expected_without_ultra
|
||||
);
|
||||
assert_eq!(
|
||||
with_config_overrides(
|
||||
model.clone(),
|
||||
&ModelsManagerConfig {
|
||||
ultra_reasoning_enabled: true,
|
||||
..Default::default()
|
||||
},
|
||||
),
|
||||
model
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn reasoning_summaries_override_true_enables_support() {
|
||||
let model = model_info_from_slug("unknown-model");
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
|
||||
/// Legacy notice keys kept for config compatibility with older migration prompts.
|
||||
///
|
||||
/// Hardcoded model presets were removed; model listings are now derived from the active catalog.
|
||||
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";
|
||||
|
||||
/// Removes the gated Ultra effort from model presets exposed to clients or tools.
|
||||
pub fn hide_ultra_reasoning_effort(models: &mut [ModelPreset]) {
|
||||
for model in models {
|
||||
model
|
||||
.supported_reasoning_efforts
|
||||
.retain(|preset| preset.effort != ReasoningEffort::Ultra);
|
||||
if model.default_reasoning_effort == ReasoningEffort::Ultra {
|
||||
model.default_reasoning_effort = model
|
||||
.supported_reasoning_efforts
|
||||
.last()
|
||||
.map(|preset| preset.effort.clone())
|
||||
.unwrap_or(ReasoningEffort::None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ pub enum ReasoningEffort {
|
||||
Medium,
|
||||
High,
|
||||
XHigh,
|
||||
Ultra,
|
||||
/// A model-defined effort value that this client does not know yet.
|
||||
Custom(String),
|
||||
}
|
||||
@@ -59,6 +60,7 @@ impl ReasoningEffort {
|
||||
Self::Medium => "medium",
|
||||
Self::High => "high",
|
||||
Self::XHigh => "xhigh",
|
||||
Self::Ultra => "ultra",
|
||||
Self::Custom(effort) => effort,
|
||||
}
|
||||
}
|
||||
@@ -123,6 +125,7 @@ impl FromStr for ReasoningEffort {
|
||||
"medium" => Ok(Self::Medium),
|
||||
"high" => Ok(Self::High),
|
||||
"xhigh" => Ok(Self::XHigh),
|
||||
"ultra" => Ok(Self::Ultra),
|
||||
"" => Err("reasoning_effort must not be empty".to_string()),
|
||||
effort => Ok(Self::Custom(effort.to_string())),
|
||||
}
|
||||
@@ -701,20 +704,25 @@ mod tests {
|
||||
let deserialized = from_str::<ReasoningEffort>(r#""max""#)
|
||||
.expect("custom reasoning effort should deserialize");
|
||||
let serialized = to_string(&custom).expect("custom reasoning effort should serialize");
|
||||
let serialized_ultra = to_string(&ReasoningEffort::Ultra).expect("Ultra should serialize");
|
||||
|
||||
assert_eq!(
|
||||
(
|
||||
"high".parse(),
|
||||
"ultra".parse(),
|
||||
"max".parse(),
|
||||
deserialized,
|
||||
serialized,
|
||||
serialized_ultra,
|
||||
custom.to_string(),
|
||||
),
|
||||
(
|
||||
Ok(ReasoningEffort::High),
|
||||
Ok(ReasoningEffort::Ultra),
|
||||
Ok(custom.clone()),
|
||||
custom,
|
||||
r#""max""#.to_string(),
|
||||
r#""ultra""#.to_string(),
|
||||
"max".to_string(),
|
||||
)
|
||||
);
|
||||
|
||||
@@ -107,6 +107,7 @@ use codex_app_server_protocol::TurnStartResponse;
|
||||
use codex_app_server_protocol::TurnSteerParams;
|
||||
use codex_app_server_protocol::TurnSteerResponse;
|
||||
use codex_app_server_protocol::UserInput;
|
||||
use codex_features::Feature;
|
||||
use codex_otel::TelemetryAuthMode;
|
||||
use codex_protocol::ThreadId;
|
||||
use codex_protocol::approvals::GuardianAssessmentEvent;
|
||||
@@ -118,6 +119,7 @@ use codex_protocol::openai_models::ModelAvailabilityNux;
|
||||
use codex_protocol::openai_models::ModelPreset;
|
||||
use codex_protocol::openai_models::ModelServiceTier;
|
||||
use codex_protocol::openai_models::ModelUpgrade;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::openai_models::ReasoningEffortPreset;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
@@ -278,7 +280,9 @@ impl AppServerSession {
|
||||
let available_models = models
|
||||
.data
|
||||
.into_iter()
|
||||
.map(model_preset_from_api_model)
|
||||
.map(|model| {
|
||||
model_preset_from_api_model(model, config.features.enabled(Feature::MultiAgentMode))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let default_model = config
|
||||
.model
|
||||
@@ -1189,7 +1193,7 @@ pub(crate) fn status_account_display_from_auth_mode(
|
||||
}
|
||||
}
|
||||
|
||||
fn model_preset_from_api_model(model: ApiModel) -> ModelPreset {
|
||||
fn model_preset_from_api_model(model: ApiModel, ultra_reasoning_enabled: bool) -> ModelPreset {
|
||||
let upgrade = model.upgrade.map(|upgrade_id| {
|
||||
let upgrade_info = model.upgrade_info.clone();
|
||||
ModelUpgrade {
|
||||
@@ -1205,7 +1209,7 @@ fn model_preset_from_api_model(model: ApiModel) -> ModelPreset {
|
||||
}
|
||||
});
|
||||
|
||||
ModelPreset {
|
||||
let mut preset = ModelPreset {
|
||||
id: model.id,
|
||||
model: model.model,
|
||||
display_name: model.display_name,
|
||||
@@ -1240,7 +1244,24 @@ fn model_preset_from_api_model(model: ApiModel) -> ModelPreset {
|
||||
// `model/list` already returns models filtered for the active client/auth context.
|
||||
supported_in_api: true,
|
||||
input_modalities: model.input_modalities,
|
||||
};
|
||||
if ultra_reasoning_enabled {
|
||||
preset
|
||||
.supported_reasoning_efforts
|
||||
.sort_by_key(|preset| preset.effort == ReasoningEffort::Ultra);
|
||||
} else {
|
||||
preset
|
||||
.supported_reasoning_efforts
|
||||
.retain(|preset| preset.effort != ReasoningEffort::Ultra);
|
||||
if preset.default_reasoning_effort == ReasoningEffort::Ultra {
|
||||
preset.default_reasoning_effort = preset
|
||||
.supported_reasoning_efforts
|
||||
.last()
|
||||
.map(|preset| preset.effort.clone())
|
||||
.unwrap_or(ReasoningEffort::None);
|
||||
}
|
||||
}
|
||||
preset
|
||||
}
|
||||
|
||||
fn approvals_reviewer_override_from_config(
|
||||
@@ -1747,7 +1768,6 @@ mod tests {
|
||||
use codex_app_server_protocol::ThreadStatus;
|
||||
use codex_app_server_protocol::Turn;
|
||||
use codex_app_server_protocol::TurnStatus;
|
||||
use codex_features::Feature;
|
||||
use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
@@ -1756,7 +1776,6 @@ mod tests {
|
||||
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_READ_ONLY;
|
||||
use codex_protocol::models::BUILT_IN_PERMISSION_PROFILE_WORKSPACE;
|
||||
use codex_protocol::models::ManagedFileSystemPermissions;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::permissions::FileSystemAccessMode;
|
||||
use codex_protocol::permissions::FileSystemPath;
|
||||
use codex_protocol::permissions::FileSystemSandboxEntry;
|
||||
@@ -1793,6 +1812,83 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn model_preset_filters_ultra_for_tui_when_feature_is_disabled() {
|
||||
let api_model = ApiModel {
|
||||
id: "model-id".to_string(),
|
||||
model: "model-slug".to_string(),
|
||||
upgrade: None,
|
||||
upgrade_info: None,
|
||||
availability_nux: None,
|
||||
display_name: "Model".to_string(),
|
||||
description: "Description".to_string(),
|
||||
hidden: false,
|
||||
supported_reasoning_efforts: vec![
|
||||
codex_app_server_protocol::ReasoningEffortOption {
|
||||
reasoning_effort: ReasoningEffort::Ultra,
|
||||
description: "Ultra".to_string(),
|
||||
},
|
||||
codex_app_server_protocol::ReasoningEffortOption {
|
||||
reasoning_effort: ReasoningEffort::Low,
|
||||
description: "Low".to_string(),
|
||||
},
|
||||
codex_app_server_protocol::ReasoningEffortOption {
|
||||
reasoning_effort: ReasoningEffort::XHigh,
|
||||
description: "Extra high".to_string(),
|
||||
},
|
||||
],
|
||||
default_reasoning_effort: ReasoningEffort::Ultra,
|
||||
input_modalities: codex_protocol::openai_models::default_input_modalities(),
|
||||
supports_personality: false,
|
||||
additional_speed_tiers: Vec::new(),
|
||||
service_tiers: Vec::new(),
|
||||
default_service_tier: None,
|
||||
is_default: true,
|
||||
};
|
||||
|
||||
let filtered =
|
||||
model_preset_from_api_model(api_model.clone(), /*ultra_reasoning_enabled*/ false);
|
||||
let unfiltered =
|
||||
model_preset_from_api_model(api_model, /*ultra_reasoning_enabled*/ true);
|
||||
|
||||
assert_eq!(
|
||||
(
|
||||
filtered.default_reasoning_effort,
|
||||
filtered.supported_reasoning_efforts,
|
||||
unfiltered.default_reasoning_effort,
|
||||
unfiltered.supported_reasoning_efforts,
|
||||
),
|
||||
(
|
||||
ReasoningEffort::XHigh,
|
||||
vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Low".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::XHigh,
|
||||
description: "Extra high".to_string(),
|
||||
},
|
||||
],
|
||||
ReasoningEffort::Ultra,
|
||||
vec![
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Low,
|
||||
description: "Low".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::XHigh,
|
||||
description: "Extra high".to_string(),
|
||||
},
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffort::Ultra,
|
||||
description: "Ultra".to_string(),
|
||||
},
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn app_server_rate_limit_snapshots_deduplicates_top_level_limit_from_map() {
|
||||
let response = GetAccountRateLimitsResponse {
|
||||
|
||||
@@ -505,6 +505,7 @@ impl ChatWidget {
|
||||
ReasoningEffortConfig::Medium => "Medium".to_string(),
|
||||
ReasoningEffortConfig::High => "High".to_string(),
|
||||
ReasoningEffortConfig::XHigh => "Extra high".to_string(),
|
||||
ReasoningEffortConfig::Ultra => "Ultra".to_string(),
|
||||
ReasoningEffortConfig::Custom(value) => value.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ expression: popup
|
||||
|
||||
1. Low Fast responses with lighter reasoning
|
||||
2. Medium (default) Balances speed and reasoning depth for everyday tasks
|
||||
3. max Maximum available reasoning
|
||||
3. Ultra Maximum reasoning with proactive delegation
|
||||
› 4. High (current) Greater reasoning depth for complex problems
|
||||
5. Extra high Extra high reasoning depth for complex problems
|
||||
|
||||
|
||||
@@ -3018,8 +3018,8 @@ async fn model_reasoning_selection_popup_snapshot() {
|
||||
preset.supported_reasoning_efforts.insert(
|
||||
2,
|
||||
ReasoningEffortPreset {
|
||||
effort: ReasoningEffortConfig::Custom("max".to_string()),
|
||||
description: "Maximum available reasoning".to_string(),
|
||||
effort: ReasoningEffortConfig::Ultra,
|
||||
description: "Maximum reasoning with proactive delegation".to_string(),
|
||||
},
|
||||
);
|
||||
chat.open_reasoning_popup(preset);
|
||||
|
||||
Reference in New Issue
Block a user