use super::ProviderCapabilities;
pub const DEFAULT_CONTEXT_WINDOW: usize = 128_000;
pub fn context_window(model: &str, caps: Option<&ProviderCapabilities>) -> usize {
let m = model.to_ascii_lowercase();
if m.contains("claude-haiku") || m.contains("haiku-3") || m.contains("haiku-4") {
return 200_000;
}
if m.contains("claude-sonnet")
|| m.contains("sonnet-4")
|| m.contains("claude-opus")
|| m.contains("opus-4")
{
return 200_000;
}
if m.contains("gpt-4o") {
return 128_000;
}
caps.map(|c| c.max_context_window)
.unwrap_or(DEFAULT_CONTEXT_WINDOW)
}
#[cfg(test)]
mod tests {
use super::super::{ProviderId, capabilities};
use super::*;
#[test]
fn haiku_resolves_to_200k() {
assert_eq!(context_window("anthropic/claude-haiku-4-5", None), 200_000);
assert_eq!(context_window("claude-haiku-3-5", None), 200_000);
assert_eq!(
context_window("bedrock/us.anthropic.claude-haiku-4-5", None),
200_000
);
assert_ne!(
context_window("claude-haiku-4-5", None),
DEFAULT_CONTEXT_WINDOW
);
}
#[test]
fn sonnet_and_opus_200k() {
assert_eq!(
context_window("bedrock/us.anthropic.claude-sonnet-4-6", None),
200_000
);
assert_eq!(context_window("anthropic/claude-opus-4-1", None), 200_000);
}
#[test]
fn gpt4o_128k() {
assert_eq!(context_window("openai/gpt-4o-mini", None), 128_000);
}
#[test]
fn falls_back_to_provider_default() {
let fw = capabilities(ProviderId::Fireworks);
assert_eq!(
context_window("fireworks/some-new-model", Some(fw)),
128_000
);
assert_eq!(
context_window("some/unheard-of-model", None),
DEFAULT_CONTEXT_WINDOW
);
}
}