diff --git a/codex-rs/model-provider-info/src/lib.rs b/codex-rs/model-provider-info/src/lib.rs index 65f71851d..c20a51a3a 100644 --- a/codex-rs/model-provider-info/src/lib.rs +++ b/codex-rs/model-provider-info/src/lib.rs @@ -37,6 +37,7 @@ pub const OPENAI_PROVIDER_ID: &str = "openai"; pub const CHATGPT_CODEX_BASE_URL: &str = "https://chatgpt.com/backend-api/codex"; const AMAZON_BEDROCK_PROVIDER_NAME: &str = "Amazon Bedrock"; pub const AMAZON_BEDROCK_PROVIDER_ID: &str = "amazon-bedrock"; +pub const AMAZON_BEDROCK_GPT_5_5_MODEL_ID: &str = "openai.gpt-5.5"; pub const AMAZON_BEDROCK_GPT_5_4_MODEL_ID: &str = "openai.gpt-5.4"; pub const AMAZON_BEDROCK_DEFAULT_BASE_URL: &str = "https://bedrock-mantle.us-east-1.api.aws/openai/v1"; diff --git a/codex-rs/model-provider/src/amazon_bedrock/catalog.rs b/codex-rs/model-provider/src/amazon_bedrock/catalog.rs index 8fec7f835..6ebb736fc 100644 --- a/codex-rs/model-provider/src/amazon_bedrock/catalog.rs +++ b/codex-rs/model-provider/src/amazon_bedrock/catalog.rs @@ -1,83 +1,66 @@ use codex_model_provider_info::AMAZON_BEDROCK_GPT_5_4_MODEL_ID; +use codex_model_provider_info::AMAZON_BEDROCK_GPT_5_5_MODEL_ID; +use codex_models_manager::bundled_models_response; use codex_models_manager::model_info::BASE_INSTRUCTIONS; use codex_protocol::config_types::ReasoningSummary; -use codex_protocol::config_types::ServiceTier; -use codex_protocol::config_types::Verbosity; -use codex_protocol::openai_models::ApplyPatchToolType; use codex_protocol::openai_models::ConfigShellToolType; use codex_protocol::openai_models::InputModality; use codex_protocol::openai_models::ModelInfo; -use codex_protocol::openai_models::ModelServiceTier; use codex_protocol::openai_models::ModelVisibility; use codex_protocol::openai_models::ModelsResponse; use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::openai_models::ReasoningEffortPreset; -use codex_protocol::openai_models::SPEED_TIER_FAST; use codex_protocol::openai_models::TruncationPolicyConfig; use codex_protocol::openai_models::WebSearchToolType; const GPT_OSS_CONTEXT_WINDOW: i64 = 128_000; -const GPT_5_4_CONTEXT_WINDOW: i64 = 272_000; -const GPT_5_4_MAX_CONTEXT_WINDOW: i64 = 1_000_000; +const GPT_5_BEDROCK_CONTEXT_WINDOW: i64 = 272_000; +const GPT_5_5_OPENAI_MODEL_ID: &str = "gpt-5.5"; +const GPT_5_4_OPENAI_MODEL_ID: &str = "gpt-5.4"; pub(crate) fn static_model_catalog() -> ModelsResponse { ModelsResponse { models: vec![ - gpt_5_4_cmb_bedrock_model(/*priority*/ 0), + gpt_5_bedrock_model( + GPT_5_5_OPENAI_MODEL_ID, + AMAZON_BEDROCK_GPT_5_5_MODEL_ID, + /*priority*/ 0, + ), + gpt_5_bedrock_model( + GPT_5_4_OPENAI_MODEL_ID, + AMAZON_BEDROCK_GPT_5_4_MODEL_ID, + /*priority*/ 1, + ), bedrock_oss_model( "openai.gpt-oss-120b", "GPT OSS 120B on Bedrock", - /*priority*/ 1, + /*priority*/ 2, ), bedrock_oss_model( "openai.gpt-oss-20b", "GPT OSS 20B on Bedrock", - /*priority*/ 2, + /*priority*/ 3, ), ], } } -fn gpt_5_4_cmb_bedrock_model(priority: i32) -> ModelInfo { - ModelInfo { - slug: AMAZON_BEDROCK_GPT_5_4_MODEL_ID.to_string(), - display_name: "gpt-5.4".to_string(), - description: Some("Strong model for everyday coding.".to_string()), - default_reasoning_level: Some(ReasoningEffort::Medium), - supported_reasoning_levels: gpt_5_4_cmb_reasoning_levels(), - shell_type: ConfigShellToolType::ShellCommand, - visibility: ModelVisibility::List, - supported_in_api: true, - priority, - additional_speed_tiers: Vec::new(), - service_tiers: vec![ModelServiceTier { - id: ServiceTier::Fast.request_value().to_string(), - name: SPEED_TIER_FAST.to_string(), - description: "Fastest inference with increased plan usage".to_string(), - }], - default_service_tier: None, - availability_nux: None, - upgrade: None, - base_instructions: BASE_INSTRUCTIONS.to_string(), - model_messages: None, - supports_reasoning_summaries: true, - default_reasoning_summary: ReasoningSummary::None, - support_verbosity: true, - default_verbosity: Some(Verbosity::Medium), - apply_patch_tool_type: Some(ApplyPatchToolType::Freeform), - web_search_tool_type: WebSearchToolType::TextAndImage, - truncation_policy: TruncationPolicyConfig::tokens(/*limit*/ 10_000), - supports_parallel_tool_calls: true, - supports_image_detail_original: true, - context_window: Some(GPT_5_4_CONTEXT_WINDOW), - max_context_window: Some(GPT_5_4_MAX_CONTEXT_WINDOW), - auto_compact_token_limit: None, - effective_context_window_percent: 95, - experimental_supported_tools: Vec::new(), - input_modalities: vec![InputModality::Text, InputModality::Image], - used_fallback_model_metadata: false, - supports_search_tool: true, - } +fn gpt_5_bedrock_model(openai_slug: &str, bedrock_slug: &str, priority: i32) -> ModelInfo { + let mut model = bundled_openai_model(openai_slug); + model.slug = bedrock_slug.to_string(); + model.priority = priority; + model.context_window = Some(GPT_5_BEDROCK_CONTEXT_WINDOW); + model.max_context_window = Some(GPT_5_BEDROCK_CONTEXT_WINDOW); + model +} + +fn bundled_openai_model(slug: &str) -> ModelInfo { + bundled_models_response() + .unwrap_or_else(|err| panic!("bundled models.json should parse: {err}")) + .models + .into_iter() + .find(|model| model.slug == slug) + .unwrap_or_else(|| panic!("bundled models.json should include {slug}")) } fn bedrock_oss_model(slug: &str, display_name: &str, priority: i32) -> ModelInfo { @@ -122,15 +105,6 @@ fn bedrock_oss_model(slug: &str, display_name: &str, priority: i32) -> ModelInfo } } -fn gpt_5_4_cmb_reasoning_levels() -> Vec { - vec![ - reasoning_effort_preset(ReasoningEffort::Minimal), - reasoning_effort_preset(ReasoningEffort::Low), - reasoning_effort_preset(ReasoningEffort::Medium), - reasoning_effort_preset(ReasoningEffort::High), - ] -} - fn reasoning_effort_preset(effort: ReasoningEffort) -> ReasoningEffortPreset { ReasoningEffortPreset { effort, @@ -156,24 +130,40 @@ mod tests { fn catalog_uses_mantle_model_ids_as_slugs() { let catalog = static_model_catalog(); - assert_eq!(catalog.models.len(), 3); - assert_eq!(catalog.models[0].slug, AMAZON_BEDROCK_GPT_5_4_MODEL_ID); - assert_eq!(catalog.models[1].slug, "openai.gpt-oss-120b"); - assert_eq!(catalog.models[2].slug, "openai.gpt-oss-20b"); + assert_eq!(catalog.models.len(), 4); + assert_eq!(catalog.models[0].slug, AMAZON_BEDROCK_GPT_5_5_MODEL_ID); + assert_eq!(catalog.models[1].slug, AMAZON_BEDROCK_GPT_5_4_MODEL_ID); + assert_eq!(catalog.models[2].slug, "openai.gpt-oss-120b"); + assert_eq!(catalog.models[3].slug, "openai.gpt-oss-20b"); } #[test] - fn gpt_5_4_cmb_advertises_only_bedrock_supported_reasoning_levels() { + fn gpt_5_bedrock_models_use_bedrock_context_window() { let catalog = static_model_catalog(); - let cmb_model = catalog + let gpt_5_5 = catalog + .models + .iter() + .find(|model| model.slug == AMAZON_BEDROCK_GPT_5_5_MODEL_ID) + .expect("Bedrock catalog should include GPT-5.5"); + let gpt_5_4 = catalog .models .iter() .find(|model| model.slug == AMAZON_BEDROCK_GPT_5_4_MODEL_ID) - .expect("Bedrock catalog should include GPT-5.4 CMB"); + .expect("Bedrock catalog should include GPT-5.4"); assert_eq!( - cmb_model.supported_reasoning_levels, - gpt_5_4_cmb_reasoning_levels() + (gpt_5_5.context_window, gpt_5_5.max_context_window), + ( + Some(GPT_5_BEDROCK_CONTEXT_WINDOW), + Some(GPT_5_BEDROCK_CONTEXT_WINDOW) + ) + ); + assert_eq!( + (gpt_5_4.context_window, gpt_5_4.max_context_window), + ( + Some(GPT_5_BEDROCK_CONTEXT_WINDOW), + Some(GPT_5_BEDROCK_CONTEXT_WINDOW) + ) ); } } diff --git a/codex-rs/model-provider/src/provider.rs b/codex-rs/model-provider/src/provider.rs index 1ef7c2296..8230c0163 100644 --- a/codex-rs/model-provider/src/provider.rs +++ b/codex-rs/model-provider/src/provider.rs @@ -510,6 +510,7 @@ mod tests { assert_eq!( model_ids, vec![ + "openai.gpt-5.5", "openai.gpt-5.4", "openai.gpt-oss-120b", "openai.gpt-oss-20b" @@ -523,7 +524,7 @@ mod tests { .find(|preset| preset.is_default) .expect("Bedrock catalog should have a default model"); - assert_eq!(default_model.model, "openai.gpt-5.4"); + assert_eq!(default_model.model, "openai.gpt-5.5"); } #[tokio::test]