use std::collections::HashMap;
use std::sync::LazyLock;
static ANTHROPIC_TO_BEDROCK: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
HashMap::from([
("claude-opus-4-6", "us.anthropic.claude-opus-4-6-v1"),
(
"claude-sonnet-4-5-20250929",
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
),
(
"claude-sonnet-4-5",
"us.anthropic.claude-sonnet-4-5-20250929-v1:0",
),
(
"claude-opus-4-5-20251101",
"us.anthropic.claude-opus-4-5-20251101-v1:0",
),
(
"claude-opus-4-5",
"us.anthropic.claude-opus-4-5-20251101-v1:0",
),
(
"claude-haiku-4-5-20251001",
"us.anthropic.claude-haiku-4-5-20251001-v1:0",
),
(
"claude-haiku-4-5",
"us.anthropic.claude-haiku-4-5-20251001-v1:0",
),
(
"claude-opus-4-1-20250805",
"us.anthropic.claude-opus-4-1-20250805-v1:0",
),
(
"claude-opus-4-1",
"us.anthropic.claude-opus-4-1-20250805-v1:0",
),
(
"claude-sonnet-4-20250514",
"us.anthropic.claude-sonnet-4-20250514-v1:0",
),
(
"claude-sonnet-4-0",
"us.anthropic.claude-sonnet-4-20250514-v1:0",
),
(
"claude-opus-4-20250514",
"us.anthropic.claude-opus-4-20250514-v1:0",
),
(
"claude-opus-4-0",
"us.anthropic.claude-opus-4-20250514-v1:0",
),
(
"claude-3-7-sonnet-20250219",
"us.anthropic.claude-3-7-sonnet-20250219-v1:0",
),
(
"claude-3-7-sonnet-latest",
"us.anthropic.claude-3-7-sonnet-20250219-v1:0",
),
(
"claude-3-5-sonnet-20241022",
"us.anthropic.claude-3-5-sonnet-20241022-v2:0",
),
(
"claude-3-5-sonnet-20240620",
"us.anthropic.claude-3-5-sonnet-20240620-v1:0",
),
(
"claude-3-5-haiku-20241022",
"us.anthropic.claude-3-5-haiku-20241022-v1:0",
),
(
"claude-3-5-haiku-latest",
"us.anthropic.claude-3-5-haiku-20241022-v1:0",
),
(
"claude-3-opus-20240229",
"us.anthropic.claude-3-opus-20240229-v1:0",
),
(
"claude-3-sonnet-20240229",
"us.anthropic.claude-3-sonnet-20240229-v1:0",
),
(
"claude-3-haiku-20240307",
"us.anthropic.claude-3-haiku-20240307-v1:0",
),
])
});
pub fn resolve_bedrock_model_id(model_id: &str) -> String {
if model_id.contains("anthropic.") {
return model_id.to_string();
}
if has_region_prefix(model_id) {
return model_id.to_string();
}
if let Some(&bedrock_id) = ANTHROPIC_TO_BEDROCK.get(model_id) {
return bedrock_id.to_string();
}
format!("us.anthropic.{}-v1:0", model_id)
}
fn has_region_prefix(model_id: &str) -> bool {
let prefixes = ["us.", "eu.", "ap.", "global."];
prefixes.iter().any(|p| model_id.starts_with(p))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_anthropic_style_maps_to_bedrock() {
assert_eq!(
resolve_bedrock_model_id("claude-sonnet-4-5-20250929"),
"us.anthropic.claude-sonnet-4-5-20250929-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-3-5-haiku-20241022"),
"us.anthropic.claude-3-5-haiku-20241022-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-3-opus-20240229"),
"us.anthropic.claude-3-opus-20240229-v1:0"
);
}
#[test]
fn test_latest_aliases_map_correctly() {
assert_eq!(
resolve_bedrock_model_id("claude-sonnet-4-5"),
"us.anthropic.claude-sonnet-4-5-20250929-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-haiku-4-5"),
"us.anthropic.claude-haiku-4-5-20251001-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-opus-4-0"),
"us.anthropic.claude-opus-4-20250514-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-3-5-haiku-latest"),
"us.anthropic.claude-3-5-haiku-20241022-v1:0"
);
}
#[test]
fn test_claude_4_family() {
assert_eq!(
resolve_bedrock_model_id("claude-sonnet-4-20250514"),
"us.anthropic.claude-sonnet-4-20250514-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-opus-4-20250514"),
"us.anthropic.claude-opus-4-20250514-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-opus-4-1-20250805"),
"us.anthropic.claude-opus-4-1-20250805-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("claude-opus-4-5-20251101"),
"us.anthropic.claude-opus-4-5-20251101-v1:0"
);
}
#[test]
fn test_v2_model_mapping() {
assert_eq!(
resolve_bedrock_model_id("claude-3-5-sonnet-20241022"),
"us.anthropic.claude-3-5-sonnet-20241022-v2:0"
);
}
#[test]
fn test_bedrock_id_passthrough() {
assert_eq!(
resolve_bedrock_model_id("anthropic.claude-sonnet-4-5-20250929-v1:0"),
"anthropic.claude-sonnet-4-5-20250929-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("anthropic.claude-3-5-haiku-20241022-v1:0"),
"anthropic.claude-3-5-haiku-20241022-v1:0"
);
}
#[test]
fn test_cross_region_passthrough() {
assert_eq!(
resolve_bedrock_model_id("us.anthropic.claude-sonnet-4-5-20250929-v1:0"),
"us.anthropic.claude-sonnet-4-5-20250929-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("eu.anthropic.claude-3-5-sonnet-20241022-v2:0"),
"eu.anthropic.claude-3-5-sonnet-20241022-v2:0"
);
assert_eq!(
resolve_bedrock_model_id("ap.anthropic.claude-3-haiku-20240307-v1:0"),
"ap.anthropic.claude-3-haiku-20240307-v1:0"
);
assert_eq!(
resolve_bedrock_model_id("global.anthropic.claude-sonnet-4-5-20250929-v1:0"),
"global.anthropic.claude-sonnet-4-5-20250929-v1:0"
);
}
#[test]
fn test_unknown_model_fallback() {
assert_eq!(
resolve_bedrock_model_id("claude-future-model-20260101"),
"us.anthropic.claude-future-model-20260101-v1:0"
);
}
}