From 32a8c9bf87e60000be54cdce2c3ab5eaa0937d2d Mon Sep 17 00:00:00 2001 From: jesus Date: Tue, 8 Sep 2026 00:50:40 +0000 Subject: [PATCH 1/2] fix(bedrock_mantle): route unmapped openai.gpt-* models to /openai/v1 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/llms/bedrock_mantle/common_utils.py | 13 +++++++++++-- ...st_bedrock_mantle_responses_transformation.py | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/litellm/llms/bedrock_mantle/common_utils.py b/litellm/llms/bedrock_mantle/common_utils.py index 850738bc320..8b0ff086bd1 100644 --- a/litellm/llms/bedrock_mantle/common_utils.py +++ b/litellm/llms/bedrock_mantle/common_utils.py @@ -31,6 +31,9 @@ BEDROCK_MANTLE_DEFAULT_REGION: Final = "us-east-1" # Standard Mantle host: https://bedrock-mantle..api.aws (group 1 = region). MANTLE_HOST_RE: Final = re.compile(r"^https?://bedrock-mantle\.([^/.]+)\.api\.aws(?=/|$)", re.IGNORECASE) +# OpenAI models on Mantle served from the /openai/v1 base; gpt-oss stays on /v1. +OPENAI_V1_FAMILY_RE: Final = re.compile(r"^openai\.gpt-(?!oss)") + def resolve_mantle_bearer_token(api_key: str | None) -> str | None: return api_key or get_secret_str("BEDROCK_MANTLE_API_KEY") or get_secret_str("AWS_BEARER_TOKEN_BEDROCK") @@ -145,7 +148,13 @@ def mantle_base_segment(model: str | None, model_cost: dict) -> str: /openai/v1 base (.../openai/v1/responses and .../openai/v1/chat/completions); every other model including gpt-oss uses the standard /v1 base. The segment is the base for the model's whole OpenAI-compatible surface, so both the chat and - responses configs derive from it -- there is no separate model-name rule. + responses configs derive from it. When the flag is absent (no price-map entry, + or a bare entry the Router registers for an unmapped deployment) a family rule + keeps day-0 OpenAI model IDs working before their cost-map entry lands: every + openai.gpt-* model except gpt-oss is on /openai/v1. """ entry: Final = model_cost.get(f"bedrock_mantle/{model}", {}) - return "openai/v1" if entry.get("use_openai_responses_path") is True else "v1" + flag: Final = entry.get("use_openai_responses_path") + if flag is None: + return "openai/v1" if model and OPENAI_V1_FAMILY_RE.match(model) else "v1" + return "openai/v1" if flag is True else "v1" diff --git a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py index 1f23d39c631..32ea91048ad 100644 --- a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py +++ b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py @@ -1188,7 +1188,8 @@ class TestBedrockMantleResponsesRegistry: class TestMantleBaseSegment: """The wire-path helper is data-driven from the price-map use_openai_responses_path flag (NOT a model-name match): flagged models are on - the /openai/v1 base, everything else on /v1. An unmapped model defaults to /v1. + the /openai/v1 base, everything else on /v1. An unmapped model defaults to /v1 + unless it is a non-gpt-oss openai.gpt-* ID, which falls back to /openai/v1. """ @pytest.mark.parametrize( @@ -1215,6 +1216,19 @@ class TestMantleBaseSegment: ), ("openai.gpt-oss-120b", {}, "v1"), (None, {}, "v1"), + # unmapped openai.gpt-* (not gpt-oss) -> family fallback to /openai/v1 + ("openai.gpt-daybreak-blue-5.6-sol", {}, "openai/v1"), + ("openai.gpt-5.7", {}, "openai/v1"), + ("openai.gpt-oss-safeguard-20b", {}, "v1"), + ("somelab.unmapped", {}, "v1"), + # the Router registers a bare {} entry for unmapped deployments; the + # family fallback must still apply, while an explicit False wins + ("openai.gpt-5.7", {"bedrock_mantle/openai.gpt-5.7": {}}, "openai/v1"), + ( + "openai.gpt-5.7", + {"bedrock_mantle/openai.gpt-5.7": {"use_openai_responses_path": False}}, + "v1", + ), ], ) def test_base_segment(self, model, model_cost, expected): From 28b39d5a2e2c65edd2460ba403a50aa762636721 Mon Sep 17 00:00:00 2001 From: jesus Date: Tue, 8 Sep 2026 01:02:36 +0000 Subject: [PATCH 2/2] refactor(bedrock_mantle): drop explanatory comments from route fallback Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- litellm/llms/bedrock_mantle/common_utils.py | 1 - .../test_bedrock_mantle_responses_transformation.py | 3 --- 2 files changed, 4 deletions(-) diff --git a/litellm/llms/bedrock_mantle/common_utils.py b/litellm/llms/bedrock_mantle/common_utils.py index 8b0ff086bd1..ac834daedfa 100644 --- a/litellm/llms/bedrock_mantle/common_utils.py +++ b/litellm/llms/bedrock_mantle/common_utils.py @@ -31,7 +31,6 @@ BEDROCK_MANTLE_DEFAULT_REGION: Final = "us-east-1" # Standard Mantle host: https://bedrock-mantle..api.aws (group 1 = region). MANTLE_HOST_RE: Final = re.compile(r"^https?://bedrock-mantle\.([^/.]+)\.api\.aws(?=/|$)", re.IGNORECASE) -# OpenAI models on Mantle served from the /openai/v1 base; gpt-oss stays on /v1. OPENAI_V1_FAMILY_RE: Final = re.compile(r"^openai\.gpt-(?!oss)") diff --git a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py index 32ea91048ad..8f4f3f09b0c 100644 --- a/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py +++ b/tests/test_litellm/llms/bedrock_mantle/test_bedrock_mantle_responses_transformation.py @@ -1216,13 +1216,10 @@ class TestMantleBaseSegment: ), ("openai.gpt-oss-120b", {}, "v1"), (None, {}, "v1"), - # unmapped openai.gpt-* (not gpt-oss) -> family fallback to /openai/v1 ("openai.gpt-daybreak-blue-5.6-sol", {}, "openai/v1"), ("openai.gpt-5.7", {}, "openai/v1"), ("openai.gpt-oss-safeguard-20b", {}, "v1"), ("somelab.unmapped", {}, "v1"), - # the Router registers a bare {} entry for unmapped deployments; the - # family fallback must still apply, while an explicit False wins ("openai.gpt-5.7", {"bedrock_mantle/openai.gpt-5.7": {}}, "openai/v1"), ( "openai.gpt-5.7",