Skip to main content

vtcode_llm/providers/gemini/helpers/
capabilities.rs

1//! Gemini model capability predicates and token limits.
2
3use super::*;
4
5impl GeminiProvider {
6    pub(crate) fn is_gemini_3_pro_model(model: &str) -> bool {
7        let rest = match model.strip_prefix("gemini-") {
8            Some(r) => r,
9            None => return false,
10        };
11        let version_part = rest.split('-').next().unwrap_or("");
12        let Some(major_str) = version_part.split('.').next() else {
13            return false;
14        };
15        major_str == "3" && model.contains("pro") && !model.contains("flash")
16    }
17
18    /// Check if model supports context caching
19    pub fn supports_caching(model: &str) -> bool {
20        models::google::CACHING_MODELS.contains(&model)
21    }
22
23    /// Check if model supports code execution
24    pub fn supports_code_execution(model: &str) -> bool {
25        models::google::CODE_EXECUTION_MODELS.contains(&model)
26    }
27
28    /// Get maximum input token limit for a model
29    pub fn max_input_tokens(model: &str) -> usize {
30        if model.contains("gemini-4-argon") || model.contains("gemini-3.1") {
31            // Gemini 4 Argon: unified 1M limit shared by input, thinking, and output
32            1_048_576
33        } else if model.contains("3") || model.contains("4") || model.contains("1.5-pro") {
34            2_097_152 // 2M tokens for Gemini 1.5 Pro, 3.x, and 4.x models
35        } else {
36            1_048_576 // 1M tokens for other current models
37        }
38    }
39
40    /// Get maximum output token limit for a model
41    pub fn max_output_tokens(model: &str) -> usize {
42        if model.contains("3") || model.contains("4") {
43            65_536 // 65K tokens for Gemini 3 and 4 models
44        } else {
45            8_192 // Conservative default
46        }
47    }
48
49    /// Check if model supports extended thinking levels (minimal, medium)
50    /// Only Gemini 3 Flash Preview supports the `minimal` level; stable
51    /// Gemini 3.7/3.8 Flash support low/medium/high with medium as default.
52    pub(crate) fn supports_extended_thinking(model: &str) -> bool {
53        model.contains("gemini-3-flash-preview")
54    }
55
56    /// Determine whether a Gemini model uses the latest API behavior that
57    /// deprecates sampling parameters (`temperature`, `top_p`, `top_k`) and
58    /// disallows prefilled model turns (last turn with role `"model"`).
59    ///
60    /// Affected: all `gemini-3.5+` models and all future model releases.
61    pub(crate) fn uses_latest_gemini_api(model: &str) -> bool {
62        // Extract version from model name like "gemini-3.7-flash" -> "3.5"
63        let rest = match model.strip_prefix("gemini-") {
64            Some(r) => r,
65            None => return false,
66        };
67        let version_part = rest.split('-').next().unwrap_or("");
68        let mut parts = version_part.splitn(2, '.');
69        let major: u32 = match parts.next().and_then(|s| s.parse().ok()) {
70            Some(m) => m,
71            None => return false,
72        };
73        if major > 3 {
74            return true;
75        }
76        if major < 3 {
77            return false;
78        }
79        // major == 3: check minor >= 5 (3.5, 3.6, and all future 3.x)
80        match parts.next().and_then(|s| s.parse::<u32>().ok()) {
81            Some(minor) => minor >= 5,
82            None => false,
83        }
84    }
85
86    /// Get supported thinking levels for a model
87    /// Reference: <https://ai.google.dev/gemini-api/docs/gemini-3>
88    /// Gemini 3.8 Flash: low, medium (default), high — `minimal` is not supported and will error.
89    /// Gemini 4 Argon: low, medium (default), high.
90    pub(crate) fn supported_thinking_levels(model: &str) -> Vec<&'static str> {
91        if model.contains("gemini-3-flash-preview") {
92            // Preview supports all levels including minimal
93            vec!["minimal", "low", "medium", "high"]
94        } else if model.contains("gemini-4-argon") {
95            // Gemini 4 Argon supports low/medium/high (medium default)
96            vec!["low", "medium", "high"]
97        } else if model.contains("gemini-3") && model.contains("flash") {
98            // Stable Flash models (3.6, 3.7, 3.8) support low/medium/high (medium default)
99            vec!["low", "medium", "high"]
100        } else if model.contains("gemini-3") {
101            // Gemini 3 Pro supports low and high
102            vec!["low", "high"]
103        } else {
104            // Unknown model, conservative default
105            vec!["low", "high"]
106        }
107    }
108}