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