use crate::claude::models as claude_models;
use crate::codex::models as codex_models;
use crate::gemini::models as gemini_models;
use agtrace_types::{ModelLimitResolver, ModelSpec};
use std::collections::HashMap;
pub struct ProviderModelLimitResolver;
impl ModelLimitResolver for ProviderModelLimitResolver {
fn resolve_model_limit(&self, model: &str) -> Option<ModelSpec> {
resolve_model_limit(model)
}
}
fn resolve_model_limit(model_name: &str) -> Option<ModelSpec> {
let all_limits: HashMap<&str, (u64, f64)> = [
claude_models::get_model_limits(),
codex_models::get_model_limits(),
gemini_models::get_model_limits(),
]
.into_iter()
.flat_map(|map| map.into_iter())
.collect();
let mut best_match: Option<(u64, f64)> = None;
let mut best_len = 0;
for (prefix, &(limit, buffer)) in &all_limits {
if model_name.starts_with(prefix) && prefix.len() > best_len {
best_match = Some((limit, buffer));
best_len = prefix.len();
}
}
best_match.map(|(max_tokens, compaction_buffer_pct)| ModelSpec {
max_tokens,
compaction_buffer_pct,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_claude_models() {
assert_eq!(
resolve_model_limit("claude-sonnet-4-5"),
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
assert_eq!(
resolve_model_limit("claude-sonnet-4-5-20250929"),
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
assert_eq!(
resolve_model_limit("claude-haiku-4-5-20251001"),
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
assert_eq!(
resolve_model_limit("claude-3-5-sonnet-20241022"),
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
assert_eq!(
resolve_model_limit("claude-3-opus-20240229"),
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
}
#[test]
fn test_codex_models() {
assert_eq!(
resolve_model_limit("gpt-5.2"),
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
assert_eq!(
resolve_model_limit("gpt-5.1-codex-max"),
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
assert_eq!(
resolve_model_limit("gpt-5.1-codex"),
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
assert_eq!(
resolve_model_limit("gpt-5-codex"),
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
assert_eq!(
resolve_model_limit("gpt-5"),
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
}
#[test]
fn test_gemini_models() {
assert_eq!(
resolve_model_limit("gemini-2.5-pro"),
Some(ModelSpec {
max_tokens: 1_048_576,
compaction_buffer_pct: 0.0
})
);
assert_eq!(
resolve_model_limit("gemini-2.5-flash"),
Some(ModelSpec {
max_tokens: 1_048_576,
compaction_buffer_pct: 0.0
})
);
assert_eq!(
resolve_model_limit("gemini-2.0-flash"),
Some(ModelSpec {
max_tokens: 1_048_576,
compaction_buffer_pct: 0.0
})
);
}
#[test]
fn test_unknown_model() {
assert_eq!(resolve_model_limit("unknown-model"), None);
assert_eq!(resolve_model_limit("gpt-3"), None);
assert_eq!(resolve_model_limit("claude-2"), None);
}
#[test]
fn test_longest_prefix_matching() {
let spec = resolve_model_limit("gpt-5.1-codex-max-2025");
assert_eq!(
spec,
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
let spec = resolve_model_limit("claude-sonnet-4-5-20250929");
assert_eq!(
spec,
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
}
#[test]
fn test_prefix_match_with_suffix() {
assert_eq!(
resolve_model_limit("claude-3-5-sonnet-custom-version"),
Some(ModelSpec {
max_tokens: 200_000,
compaction_buffer_pct: 22.5
})
);
assert_eq!(
resolve_model_limit("gpt-5.1-codex-experimental"),
Some(ModelSpec {
max_tokens: 400_000,
compaction_buffer_pct: 0.0
})
);
}
}