Restrict the default Bedrock GovCloud model catalog (#47657)

## What changed

Use a dedicated default catalog for Bedrock Mantle endpoints whose host starts with `bedrock-mantle.us-gov-` and ends with `.api.aws`. Include only GPT-5.6 Terra, GPT-5.6 Luna, and GPT-5.4, with GPT-5.6 Terra as the default.

## Testing

Add model picker snapshot coverage for `us-gov-west-1` and `us-gov-east-1`. Update the configured-catalog test to use a GovCloud endpoint, verifying that a custom catalog is preserved while service tiers remain normalized.

GitOrigin-RevId: 5f22ba6983bd60be52d8845c9709112a4766839d
This commit is contained in:
jackz
2026-09-23 20:29:30 +00:00
committed by copyberry
parent 7e5054d32f
commit 5bae5b563e
5 changed files with 79 additions and 6 deletions
@@ -79,6 +79,19 @@ pub(crate) fn static_model_catalog() -> ModelsResponse {
})
}
pub(super) fn static_gov_model_catalog() -> ModelsResponse {
let mut catalog = static_model_catalog();
catalog.models.retain(|model| {
matches!(
model.slug.as_str(),
AMAZON_BEDROCK_GPT_5_6_TERRA_MODEL_ID
| AMAZON_BEDROCK_GPT_5_6_LUNA_MODEL_ID
| AMAZON_BEDROCK_GPT_5_4_MODEL_ID
)
});
catalog
}
pub(crate) fn normalize_bedrock_catalog(mut catalog: ModelsResponse) -> ModelsResponse {
for model in &mut catalog.models {
// Amazon Bedrock currently only supports the implicit "default" tier for GPT models.
@@ -43,6 +43,7 @@ use crate::shared_state::process_shared_state;
use auth::resolve_provider_auth as resolve_bedrock_provider_auth;
pub(crate) use auth_refresh::AwsAuthRecovery;
use catalog::normalize_bedrock_catalog;
use catalog::static_gov_model_catalog;
pub(crate) use catalog::static_model_catalog;
pub(crate) use credential_export::AwsCredentialExport;
use mantle::bedrock_mantle_runtime_base_url;
@@ -244,7 +245,25 @@ impl AmazonBedrockModelProvider {
fn default_model_catalog(&self) -> ModelsResponse {
match self.endpoint {
BedrockEndpoint::Mantle => static_model_catalog(),
BedrockEndpoint::Mantle => {
let endpoint = self
.info
.base_url
.as_deref()
.and_then(|base_url| url::Url::parse(base_url).ok());
let is_govcloud =
endpoint
.as_ref()
.and_then(url::Url::host_str)
.is_some_and(|host| {
host.starts_with("bedrock-mantle.us-gov-") && host.ends_with(".api.aws")
});
if is_govcloud {
static_gov_model_catalog()
} else {
static_model_catalog()
}
}
BedrockEndpoint::Runtime => static_runtime_model_catalog(),
}
}
+5 -4
View File
@@ -1348,10 +1348,11 @@ printf '%s\n' '{"AccessKeyId":"exported","SecretAccessKey":"secret"}'
assert!(!configured_model.additional_speed_tiers.is_empty());
assert!(!configured_model.service_tiers.is_empty());
let provider = create_model_provider(
ModelProviderInfo::create_amazon_bedrock_provider(/*aws*/ None),
/*auth_manager*/ None,
);
let mut provider_info =
ModelProviderInfo::create_amazon_bedrock_provider(/*aws*/ None);
provider_info.base_url =
Some("https://bedrock-mantle.us-gov-west-1.api.aws/openai/v1".to_string());
let provider = create_model_provider(provider_info, /*auth_manager*/ None);
let manager = provider.models_manager(
test_codex_home(),
Some(ModelsResponse {
@@ -0,0 +1,12 @@
---
source: tui/src/chatwidget/tests/bedrock_catalog_tests.rs
expression: "render_bottom_popup(&chat, 100)"
---
Select Model and Effort
› 1. GPT-5.6 Terra (current) Older balanced model for straightforward work.
2. GPT-5.6 Luna Older fast and efficient model.
3. GPT-5.4 Strong model for everyday coding.
enter select · esc back
@@ -1,4 +1,4 @@
//! Renders the provider catalog and Astra reasoning choices without changing the default model.
//! Renders Bedrock provider catalogs and Astra reasoning choices.
use super::*;
use codex_http_client::HttpClientFactory;
@@ -51,3 +51,31 @@ async fn bedrock_astra_model_and_reasoning_pickers() {
);
}
}
#[tokio::test]
async fn bedrock_govcloud_model_pickers() {
for region in ["us-gov-west-1", "us-gov-east-1"] {
let mut provider_info =
ModelProviderInfo::create_amazon_bedrock_provider(/*aws*/ None);
provider_info.base_url = Some(format!("https://bedrock-mantle.{region}.api.aws/openai/v1"));
let presets = create_model_provider(provider_info, /*auth_manager*/ None)
.models_manager_without_cache(/*config_model_catalog*/ None)
.list_models(
RefreshStrategy::Offline,
HttpClientFactory::new(OutboundProxyPolicy::ReqwestDefault),
)
.await;
let default_preset = presets
.iter()
.find(|preset| preset.is_default)
.expect("default Bedrock model");
let (mut chat, _events, _ops) = make_chatwidget_manual(Some(&default_preset.model)).await;
chat.thread_id = Some(ThreadId::new());
chat.model_catalog = Arc::new(ModelCatalog::new(presets));
chat.open_model_popup();
assert_chatwidget_snapshot!(
"bedrock_govcloud_models",
render_bottom_popup(&chat, /*width*/ 100)
);
}
}