model-provider/src/amazon_bedrock/catalog.rs
121 lines
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_protocol::openai_models::ModelInfo;use codex_protocol::openai_models::ModelsResponse;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 { with_default_only_service_tier(ModelsResponse { models: vec![ 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, ), ], })}pub(crate) fn with_default_only_service_tier(mut catalog: ModelsResponse) -> ModelsResponse { for model in &mut catalog.models { // Amazon Bedrock currently only supports the implicit "default" tier for GPT models. model.additional_speed_tiers.clear(); model.service_tiers.clear(); model.default_service_tier = None; } catalog}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}"))}#[cfg(test)]mod tests { use codex_protocol::config_types::SERVICE_TIER_DEFAULT_REQUEST_VALUE; use pretty_assertions::assert_eq; use super::*; #[test] fn catalog_uses_mantle_model_ids_as_slugs() { let catalog = static_model_catalog(); assert_eq!(catalog.models.len(), 2); 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); } #[test] fn gpt_5_bedrock_models_use_bedrock_context_window() { let catalog = static_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"); assert_eq!( (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) ) ); } #[test] fn gpt_5_bedrock_models_only_allow_default_service_tier() { let catalog = static_model_catalog(); for model in catalog.models { assert_eq!(model.additional_speed_tiers, Vec::<String>::new()); assert_eq!(model.service_tiers, Vec::new()); assert_eq!(model.default_service_tier, None); assert_eq!( model.service_tier_for_request(Some("priority".to_string())), None ); assert_eq!( model .service_tier_for_request(Some(SERVICE_TIER_DEFAULT_REQUEST_VALUE.to_string())), None ); } }}