vtcode_config/core/
anthropic_speed.rs1use serde::{Deserialize, Serialize};
4
5use crate::VTCodeConfig;
6use crate::constants::{env_vars, models::anthropic::normalize_model_id, urls};
7
8#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
11#[serde(rename_all = "lowercase")]
12pub enum AnthropicSpeed {
13 Standard,
14 Fast,
15}
16
17impl AnthropicSpeed {
18 pub const fn as_str(self) -> &'static str {
19 match self {
20 Self::Standard => "standard",
21 Self::Fast => "fast",
22 }
23 }
24
25 pub fn supports_model(model: &str) -> bool {
27 matches!(normalize_model_id(model), "claude-opus-5-5" | "claude-opus-5" | "claude-opus-4-8")
28 }
29
30 pub fn requires_beta(model: &str) -> bool {
32 matches!(normalize_model_id(model), "claude-opus-5" | "claude-opus-4-8")
33 }
34
35 pub fn is_native_endpoint(base_url: &str) -> bool {
37 let Ok(url) = url::Url::parse(base_url.trim()) else {
38 return false;
39 };
40 url.scheme() == "https"
41 && url.host_str() == Some("api.anthropic.com")
42 && url.port_or_known_default() == Some(443)
43 && url.username().is_empty()
44 && url.password().is_none()
45 && matches!(url.path(), "/v1" | "/v1/")
46 && url.query().is_none()
47 && url.fragment().is_none()
48 }
49
50 pub fn resolve_base_url(configured: Option<&str>) -> String {
52 configured
53 .map(str::trim)
54 .filter(|url| !url.is_empty())
55 .map(str::to_owned)
56 .or_else(|| {
57 std::env::var(env_vars::ANTHROPIC_BASE_URL)
58 .ok()
59 .map(|url| url.trim().to_owned())
60 .filter(|url| !url.is_empty())
61 })
62 .unwrap_or_else(|| urls::ANTHROPIC_API_BASE.to_owned())
63 }
64}
65
66impl VTCodeConfig {
67 pub fn anthropic_speed_supported(&self, provider: &str, model: &str) -> bool {
69 vtcode_commons::provider::Provider::Anthropic.name_matches(provider)
70 && self.custom_provider(provider).is_none()
71 && AnthropicSpeed::supports_model(model)
72 && AnthropicSpeed::is_native_endpoint(&AnthropicSpeed::resolve_base_url(
73 self.provider_overrides
74 .get("anthropic")
75 .and_then(|config| config.base_url.as_deref()),
76 ))
77 }
78}
79
80#[cfg(test)]
81mod tests;