const INFERENCE_PROFILE_PREFIXES: &[&str] = &["us.", "eu.", "apac."];
const ANTHROPIC_BEDROCK_PREFIX: &str = "anthropic.";
pub fn normalize_model_id(id: &str) -> &str {
let mut s = id;
if s.starts_with("arn:aws:bedrock:") {
if let Some(slash) = s.rfind('/') {
s = &s[slash + 1..];
}
}
for prefix in INFERENCE_PROFILE_PREFIXES {
if let Some(rest) = s.strip_prefix(prefix) {
s = rest;
break;
}
}
if let Some(rest) = s.strip_prefix(ANTHROPIC_BEDROCK_PREFIX) {
s = rest;
}
if let Some(idx) = s.rfind("-v") {
let tail = &s[idx + 2..];
if tail
.splitn(2, ':')
.all(|part| !part.is_empty() && part.chars().all(|c| c.is_ascii_digit()))
&& tail.contains(':')
{
s = &s[..idx];
}
}
s
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn passthrough_anthropic_api_name() {
assert_eq!(normalize_model_id("claude-sonnet-4-5"), "claude-sonnet-4-5");
}
#[test]
fn strips_anthropic_bedrock_prefix() {
assert_eq!(
normalize_model_id("anthropic.claude-sonnet-4-5"),
"claude-sonnet-4-5"
);
}
#[test]
fn strips_versioned_bedrock_id() {
assert_eq!(
normalize_model_id("anthropic.claude-sonnet-4-5-v1:0"),
"claude-sonnet-4-5"
);
}
#[test]
fn strips_inference_profile_us() {
assert_eq!(
normalize_model_id("us.anthropic.claude-sonnet-4-5"),
"claude-sonnet-4-5"
);
}
#[test]
fn strips_inference_profile_eu_with_version() {
assert_eq!(
normalize_model_id("eu.anthropic.claude-sonnet-4-5-v1:0"),
"claude-sonnet-4-5"
);
}
#[test]
fn strips_arn() {
let arn = "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-opus-4-7-v1:0";
assert_eq!(normalize_model_id(arn), "claude-opus-4-7");
}
#[test]
fn does_not_strip_non_version_suffix() {
assert_eq!(
normalize_model_id("claude-sonnet-4-5-vNext"),
"claude-sonnet-4-5-vNext"
);
}
}