bedrock: Add GPT-5.6 Sol, Terra, and Luna Mantle models (#61008)

# Objective

- Adds the three GPT-5.6 models (Sol, Terra, and Luna) that OpenAI now
serves through AWS Bedrock's `bedrock-mantle` endpoint, so they can be
selected as built-in models under the Amazon Bedrock provider.
- Follows up on the native Bedrock Mantle support added in #60480.
- Addresses the feature request in
https://github.com/zed-industries/zed/discussions/61003.

## Solution

- Adds `Gpt5_6Sol`, `Gpt5_6Terra`, and `Gpt5_6Luna` variants to
`MantleModel` in `crates/bedrock/src/models.rs`, with per-model
`id`/`request_id`/`display_name` and shared capability arms.
- All three are Responses-API, `bedrock-mantle`-only models, so they
reuse the existing Mantle request/response plumbing, region gating,
bearer-token auth, and model-picker wiring (`MantleModel::iter()`) with
no other changes required.
- Metadata mirrors the AWS Bedrock model cards
([Sol](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-56-sol.html),
[Terra](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-56-terra.html),
[Luna](https://docs.aws.amazon.com/bedrock/latest/userguide/model-card-openai-gpt-56-luna.html)):
272K context window, image input, tool and thinking support, and
`openai.gpt-5.6-{sol,terra,luna}` request IDs.
- Updates the Amazon Bedrock section of "Use a Gateway" to mention the
GPT-5.6 family.

## Testing

- `cargo test -p bedrock` — adds `test_gpt_5_6_mantle_model_metadata`
and extends `test_builtin_mantle_models_use_responses_protocol`; all
pass.
- `cargo test -p language_models mantle` — the consumer crate compiles
and all Mantle tests pass.
- `./script/clippy -p bedrock` passes with no new warnings; docs pass
`prettier --check`.

## Self-Review Checklist:

- [x] I've reviewed my own diff for quality, security, and reliability
- [x] Unsafe blocks (if any) have justifying comments — N/A, no unsafe
code
- [x] The content adheres to Zed's UI standards — N/A, no UI change
- [x] Tests cover the new/changed behavior
- [x] Performance impact has been considered and is acceptable

---

Release Notes:

- Added GPT-5.6 Sol, Terra, and Luna models to the Amazon Bedrock
provider via the `bedrock-mantle` endpoint.

---------

Co-authored-by: Anant Goel <anant@zed.dev>
This commit is contained in:
Ibrahim KhanandAnant Goel authored and GitHub committed 2026-07-15 16:31:19 +00:00
1 parent 7862fff55c
commit 48ba4bada2
4 files changed
+140 -9

No files matched your search

+123 -7
View File
@@ -834,6 +834,12 @@ pub enum MantleProtocol {
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, EnumIter)]
pub enum MantleModel {
#[serde(rename = "gpt-5.6-sol")]
Gpt5_6Sol,
#[serde(rename = "gpt-5.6-terra")]
Gpt5_6Terra,
#[serde(rename = "gpt-5.6-luna")]
Gpt5_6Luna,
#[serde(rename = "gpt-5.5")]
Gpt5_5,
#[serde(rename = "gpt-5.4")]
@@ -857,6 +863,9 @@ impl MantleModel {
/// The model id Zed uses internally (also used as the `name` in settings).
pub fn id(&self) -> &str {
match self {
Self::Gpt5_6Sol => "gpt-5.6-sol",
Self::Gpt5_6Terra => "gpt-5.6-terra",
Self::Gpt5_6Luna => "gpt-5.6-luna",
Self::Gpt5_5 => "gpt-5.5",
Self::Gpt5_4 => "gpt-5.4",
Self::Grok4_3 => "grok-4.3",
@@ -867,6 +876,9 @@ impl MantleModel {
/// The model id as expected in Bedrock Mantle request bodies, e.g. `openai.gpt-5.5`.
pub fn request_id(&self) -> &str {
match self {
Self::Gpt5_6Sol => "openai.gpt-5.6-sol",
Self::Gpt5_6Terra => "openai.gpt-5.6-terra",
Self::Gpt5_6Luna => "openai.gpt-5.6-luna",
Self::Gpt5_5 => "openai.gpt-5.5",
Self::Gpt5_4 => "openai.gpt-5.4",
Self::Grok4_3 => "xai.grok-4.3",
@@ -876,6 +888,9 @@ impl MantleModel {
pub fn display_name(&self) -> &str {
match self {
Self::Gpt5_6Sol => "GPT-5.6 Sol",
Self::Gpt5_6Terra => "GPT-5.6 Terra",
Self::Gpt5_6Luna => "GPT-5.6 Luna",
Self::Gpt5_5 => "GPT-5.5",
Self::Gpt5_4 => "GPT-5.4",
Self::Grok4_3 => "Grok 4.3",
@@ -888,14 +903,23 @@ impl MantleModel {
/// Which OpenAI-compatible API this model must be called through.
pub fn protocol(&self) -> MantleProtocol {
match self {
Self::Gpt5_5 | Self::Gpt5_4 | Self::Grok4_3 => MantleProtocol::Responses,
Self::Gpt5_6Sol
| Self::Gpt5_6Terra
| Self::Gpt5_6Luna
| Self::Gpt5_5
| Self::Gpt5_4
| Self::Grok4_3 => MantleProtocol::Responses,
Self::Custom { protocol, .. } => *protocol,
}
}
pub fn max_token_count(&self) -> u64 {
match self {
Self::Gpt5_5 | Self::Gpt5_4 => 272_000,
Self::Gpt5_6Sol
| Self::Gpt5_6Terra
| Self::Gpt5_6Luna
| Self::Gpt5_5
| Self::Gpt5_4 => 272_000,
Self::Grok4_3 => 1_000_000,
Self::Custom { max_tokens, .. } => *max_tokens,
}
@@ -903,8 +927,12 @@ impl MantleModel {
pub fn max_output_tokens(&self) -> u64 {
match self {
// AWS doesn't document a hard cap for GPT-5.5/5.4 on Mantle.
Self::Gpt5_5 | Self::Gpt5_4 => 128_000,
// AWS doesn't document a hard cap for the GPT-5.x models on Mantle.
Self::Gpt5_6Sol
| Self::Gpt5_6Terra
| Self::Gpt5_6Luna
| Self::Gpt5_5
| Self::Gpt5_4 => 128_000,
Self::Grok4_3 => 131_072,
Self::Custom {
max_output_tokens, ..
@@ -914,14 +942,24 @@ impl MantleModel {
pub fn supports_tools(&self) -> bool {
match self {
Self::Gpt5_5 | Self::Gpt5_4 | Self::Grok4_3 => true,
Self::Gpt5_6Sol
| Self::Gpt5_6Terra
| Self::Gpt5_6Luna
| Self::Gpt5_5
| Self::Gpt5_4
| Self::Grok4_3 => true,
Self::Custom { supports_tools, .. } => *supports_tools,
}
}
pub fn supports_images(&self) -> bool {
match self {
Self::Gpt5_5 | Self::Gpt5_4 | Self::Grok4_3 => true,
Self::Gpt5_6Sol
| Self::Gpt5_6Terra
| Self::Gpt5_6Luna
| Self::Gpt5_5
| Self::Gpt5_4
| Self::Grok4_3 => true,
Self::Custom {
supports_images, ..
} => *supports_images,
@@ -930,7 +968,12 @@ impl MantleModel {
pub fn supports_thinking(&self) -> bool {
match self {
Self::Gpt5_5 | Self::Gpt5_4 | Self::Grok4_3 => true,
Self::Gpt5_6Sol
| Self::Gpt5_6Terra
| Self::Gpt5_6Luna
| Self::Gpt5_5
| Self::Gpt5_4
| Self::Grok4_3 => true,
Self::Custom {
supports_thinking, ..
} => *supports_thinking,
@@ -944,11 +987,84 @@ mod tests {
#[test]
fn test_builtin_mantle_models_use_responses_protocol() {
assert_eq!(MantleModel::Gpt5_6Sol.protocol(), MantleProtocol::Responses);
assert_eq!(
MantleModel::Gpt5_6Terra.protocol(),
MantleProtocol::Responses
);
assert_eq!(
MantleModel::Gpt5_6Luna.protocol(),
MantleProtocol::Responses
);
assert_eq!(MantleModel::Gpt5_5.protocol(), MantleProtocol::Responses);
assert_eq!(MantleModel::Gpt5_4.protocol(), MantleProtocol::Responses);
assert_eq!(MantleModel::Grok4_3.protocol(), MantleProtocol::Responses);
}
#[test]
fn test_gpt_5_6_mantle_model_metadata() {
// Values mirror the AWS Bedrock model cards for GPT-5.6 Sol/Terra/Luna,
// which are served only through the `bedrock-mantle` Responses API.
for (model, id, request_id, display_name) in [
(
MantleModel::Gpt5_6Sol,
"gpt-5.6-sol",
"openai.gpt-5.6-sol",
"GPT-5.6 Sol",
),
(
MantleModel::Gpt5_6Terra,
"gpt-5.6-terra",
"openai.gpt-5.6-terra",
"GPT-5.6 Terra",
),
(
MantleModel::Gpt5_6Luna,
"gpt-5.6-luna",
"openai.gpt-5.6-luna",
"GPT-5.6 Luna",
),
] {
assert_eq!(model.id(), id);
assert_eq!(model.request_id(), request_id);
assert_eq!(model.display_name(), display_name);
assert_eq!(model.max_token_count(), 272_000);
assert!(model.supports_tools());
assert!(model.supports_images());
assert!(model.supports_thinking());
}
}
#[test]
fn test_builtin_mantle_models_have_unique_ids_and_sane_token_limits() {
use std::collections::HashSet;
use strum::IntoEnumIterator;
let mut ids = HashSet::new();
let mut request_ids = HashSet::new();
for model in
MantleModel::iter().filter(|model| !matches!(model, MantleModel::Custom { .. }))
{
assert!(
ids.insert(model.id().to_string()),
"duplicate MantleModel id: {}",
model.id()
);
assert!(
request_ids.insert(model.request_id().to_string()),
"duplicate MantleModel request_id: {}",
model.request_id()
);
assert!(
model.max_output_tokens() <= model.max_token_count(),
"{} has max_output_tokens ({}) greater than max_token_count ({})",
model.id(),
model.max_output_tokens(),
model.max_token_count()
);
}
}
#[test]
fn test_us_region_inference_ids() -> anyhow::Result<()> {
assert_eq!(
@@ -2606,9 +2606,24 @@ mod tests {
#[test]
fn test_builtin_mantle_models_support_thinking() {
assert!(MantleModel::Gpt5_6Sol.supports_thinking());
assert!(MantleModel::Gpt5_6Terra.supports_thinking());
assert!(MantleModel::Gpt5_6Luna.supports_thinking());
assert!(MantleModel::Gpt5_5.supports_thinking());
assert!(MantleModel::Gpt5_4.supports_thinking());
assert!(MantleModel::Grok4_3.supports_thinking());
assert_eq!(
mantle_default_reasoning_effort(&MantleModel::Gpt5_6Sol),
Some(ReasoningEffort::Medium)
);
assert_eq!(
mantle_default_reasoning_effort(&MantleModel::Gpt5_6Terra),
Some(ReasoningEffort::Medium)
);
assert_eq!(
mantle_default_reasoning_effort(&MantleModel::Gpt5_6Luna),
Some(ReasoningEffort::Medium)
);
assert_eq!(
mantle_default_reasoning_effort(&MantleModel::Gpt5_5),
Some(ReasoningEffort::Medium)
@@ -118,7 +118,7 @@ pub struct AmazonBedrockSettingsContent {
pub available_models: Option<Vec<BedrockAvailableModel>>,
/// Custom models served through the `bedrock-mantle` endpoint's
/// OpenAI-compatible APIs, in addition to the built-in Mantle models
/// (GPT-5.5, GPT-5.4, Grok 4.3).
/// (GPT-5.6 Sol, GPT-5.6 Terra, GPT-5.6 Luna, GPT-5.5, GPT-5.4, Grok 4.3).
pub mantle_available_models: Option<Vec<BedrockMantleAvailableModel>>,
pub custom_headers: Option<HashMap<String, String>>,
pub endpoint_url: Option<String>,
+1 -1
View File
@@ -215,7 +215,7 @@ Some AWS environments require a guardrail on every Bedrock API call. Add `guardr
### Bedrock Mantle Models {#bedrock-mantle-models}
Some models, such as GPT-5.5, GPT-5.4, and Grok 4.3, aren't available through Bedrock's Converse API and are only reachable through `bedrock-mantle`, AWS's OpenAI-compatible inference endpoint. Zed routes these models through `bedrock-mantle` automatically; they appear alongside the rest of the Bedrock models in the model picker once you're authenticated, with no extra configuration required.
Some models, such as the GPT-5.6 family (Sol, Terra, and Luna), GPT-5.5, GPT-5.4, and Grok 4.3, aren't available through Bedrock's Converse API and are only reachable through `bedrock-mantle`, AWS's OpenAI-compatible inference endpoint. Zed routes these models through `bedrock-mantle` automatically; they appear alongside the rest of the Bedrock models in the model picker once you're authenticated, with no extra configuration required.
Mantle models require IAM permissions for the `bedrock-mantle` endpoint (for example via the `AmazonBedrockMantleInferenceAccess` managed policy) in addition to whatever permissions your existing Bedrock credentials already have, and `bedrock-mantle` is only available in [some AWS Regions](https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-mantle.html#regions). Zed surfaces an error naming the current Region and the supported ones if you try to use a Mantle model outside of them.