From 487574c5b6afee541226e9c02a0433a1870fb3dc Mon Sep 17 00:00:00 2001 From: Drexuxux Date: Fri, 17 Jul 2026 01:26:44 +0300 Subject: [PATCH] fix(pricing): strip apac./au. Bedrock region prefixes so cost isn't unknown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _normalize_bedrock_model_name stripped ("us.", "global.", "eu.", "ap.", "jp.") before the pricing lookup, but AWS Bedrock's Asia-Pacific cross-region inference profiles are prefixed "apac." (and Australia "au."), not "ap.". A bare "ap." never matches an "apac.*" id (str.startswith stops at the 'a' where "ap." expects '.'), so "apac.anthropic.claude-*" and "au.anthropic.claude-*" fell through with the prefix intact, missed the bare "anthropic.claude-*" pricing key, and every Asia-Pacific / Australia Bedrock session priced as "unknown" — no cost estimate or tracking for two whole geographies, while us./eu./global. worked. Add "apac." and "au." to the strip list (mirrors the same fix landing in bedrock_adapter.is_anthropic_bedrock_model via #46297, which covers the prompt-caching capability gate but not this duplicated cost-lookup copy). Extends the existing cross-region pricing test to cover apac./au.; without the fix it fails with scoped == None for "apac.". --- agent/usage_pricing.py | 14 +++++++++----- tests/agent/test_usage_pricing.py | 12 ++++++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/agent/usage_pricing.py b/agent/usage_pricing.py index 2884381bf167..9825e4a27bd5 100644 --- a/agent/usage_pricing.py +++ b/agent/usage_pricing.py @@ -943,10 +943,13 @@ def _normalize_bedrock_model_name(model: str) -> str: """Normalize a Bedrock model id to its bare foundation-model form. Bedrock cross-region inference profiles prefix the foundation model id - with a region scope (``us.`` / ``global.`` / ``eu.`` / ``apac.`` / ...), - e.g. ``us.anthropic.claude-opus-4-7``. The pricing table is keyed on the - bare ``anthropic.claude-*`` id, so the prefix must be stripped before the - lookup or every cross-region session prices as unknown. Also normalizes + with a region scope (``us.`` / ``global.`` / ``eu.`` / ``apac.`` / ``au.`` + / ...), e.g. ``us.anthropic.claude-opus-4-7`` or + ``au.anthropic.claude-sonnet-4-5-20250929-v1:0``. The pricing table is + keyed on the bare ``anthropic.claude-*`` id, so the prefix must be + stripped before the lookup or every cross-region session prices as + unknown. Note Asia-Pacific uses ``apac.`` (a bare ``ap.`` never matches + an ``apac.*`` id) and Australia/New Zealand use ``au.``. Also normalizes dot-notation version numbers (``4.7`` → ``4-7``) and the documented trailing date, revision, and profile components (``-20250514-v1:0``). """ @@ -955,8 +958,9 @@ def _normalize_bedrock_model_name(model: str) -> str: "global.", "us.", "eu.", - "ap.", "apac.", + "ap.", + "au.", "jp.", "ca.", "sa.", diff --git a/tests/agent/test_usage_pricing.py b/tests/agent/test_usage_pricing.py index 9b82d2e2ad47..a1f853272bb4 100644 --- a/tests/agent/test_usage_pricing.py +++ b/tests/agent/test_usage_pricing.py @@ -386,16 +386,20 @@ def test_bedrock_current_gen_claude_rows_resolve(): def test_bedrock_cross_region_profile_prefix_resolves_to_pricing(): - """Cross-region inference profiles (us./global./eu. prefixes) must resolve - to the same pricing entry as the bare foundation-model id. Without prefix - normalization, ``us.anthropic.claude-*`` sessions price as unknown. + """Cross-region inference profiles must resolve to the same pricing entry + as the bare foundation-model id. Without prefix normalization a scoped + ``.anthropic.claude-*`` session prices as unknown. + + Asia-Pacific (``apac.``) and Australia (``au.``) are included because AWS + uses the full ``apac.`` prefix, not ``ap.`` — a bare ``ap.`` never matches + an ``apac.*`` id, so those geographies previously priced as unknown. """ bedrock_url = "https://bedrock-runtime.us-east-1.amazonaws.com" bare = get_pricing_entry( "anthropic.claude-sonnet-4-5", provider="bedrock", base_url=bedrock_url ) assert bare is not None - for prefix in ("us.", "global.", "eu."): + for prefix in ("us.", "global.", "eu.", "apac.", "au."): scoped = get_pricing_entry( f"{prefix}anthropic.claude-sonnet-4-5", provider="bedrock",