agent_engine/runtime/openai/catalog/
google_gemini.rs1use super::{
19 CatalogModel, CatalogProviderKind, CatalogSource, Modality, PricingSummary, ReasoningSupport,
20};
21
22pub const PROVIDER_KEY: &str = "google-gemini";
23pub const PROVIDER_NAME: &str = "Google Gemini (Code Assist)";
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq)]
26pub struct GoogleGeminiModelDescriptor {
27 pub id: &'static str,
29 pub label: &'static str,
30 pub context_tokens: Option<u64>,
31 pub thinking: bool,
34}
35
36pub const GOOGLE_GEMINI_TEXT_MODELS: &[GoogleGeminiModelDescriptor] = &[
40 GoogleGeminiModelDescriptor {
41 id: "gemini-3.1-pro-preview",
42 label: "Gemini 3.1 Pro (Preview)",
43 context_tokens: Some(1_048_576),
44 thinking: true,
45 },
46 GoogleGeminiModelDescriptor {
47 id: "gemini-3-pro-preview",
48 label: "Gemini 3 Pro (Preview)",
49 context_tokens: Some(1_048_576),
50 thinking: true,
51 },
52 GoogleGeminiModelDescriptor {
53 id: "gemini-3.5-flash",
54 label: "Gemini 3.5 Flash",
55 context_tokens: Some(1_048_576),
56 thinking: true,
57 },
58 GoogleGeminiModelDescriptor {
59 id: "gemini-3-flash-preview",
60 label: "Gemini 3 Flash (Preview)",
61 context_tokens: Some(1_048_576),
62 thinking: true,
63 },
64 GoogleGeminiModelDescriptor {
65 id: "gemini-3.1-flash-lite",
66 label: "Gemini 3.1 Flash Lite",
67 context_tokens: Some(1_048_576),
68 thinking: true,
69 },
70 GoogleGeminiModelDescriptor {
71 id: "gemini-2.5-pro",
72 label: "Gemini 2.5 Pro",
73 context_tokens: Some(1_048_576),
74 thinking: true,
75 },
76 GoogleGeminiModelDescriptor {
77 id: "gemini-2.5-flash",
78 label: "Gemini 2.5 Flash",
79 context_tokens: Some(1_048_576),
80 thinking: true,
81 },
82];
83
84pub fn google_gemini_model(id: &str) -> Option<&'static GoogleGeminiModelDescriptor> {
85 GOOGLE_GEMINI_TEXT_MODELS.iter().find(|m| m.id == id)
86}
87
88pub fn google_gemini_static_catalog_models() -> Vec<CatalogModel> {
89 GOOGLE_GEMINI_TEXT_MODELS
90 .iter()
91 .map(|d| CatalogModel {
92 provider_key: PROVIDER_KEY.into(),
93 provider_name: PROVIDER_NAME.into(),
94 provider_kind: CatalogProviderKind::Generic {
95 key: PROVIDER_KEY.into(),
96 },
97 id: d.id.into(),
98 label: Some(d.label.into()),
99 context_tokens: d.context_tokens,
100 max_output_tokens: None,
101 input_modalities: vec![Modality::Text],
102 pricing: PricingSummary::default(),
103 reasoning: if d.thinking {
104 ReasoningSupport::GenericOpenAi
105 } else {
106 ReasoningSupport::None
107 },
108 source: CatalogSource::StaticFallback,
109 })
110 .collect()
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 #[test]
118 fn catalog_exposes_all_official_reference_text_ids() {
119 assert_eq!(
120 GOOGLE_GEMINI_TEXT_MODELS
121 .iter()
122 .map(|m| m.id)
123 .collect::<Vec<_>>(),
124 vec![
125 "gemini-3.1-pro-preview",
126 "gemini-3-pro-preview",
127 "gemini-3.5-flash",
128 "gemini-3-flash-preview",
129 "gemini-3.1-flash-lite",
130 "gemini-2.5-pro",
131 "gemini-2.5-flash",
132 ]
133 );
134 }
135
136 #[test]
143 fn catalog_excludes_public_api_alias_gemini_pro_latest() {
144 assert!(
145 google_gemini_model("gemini-pro-latest").is_none(),
146 "gemini-pro-latest is not a Code Assist wire ID (404 upstream)"
147 );
148 assert!(!google_gemini_static_catalog_models()
149 .iter()
150 .any(|model| model.runtime_id() == "google-gemini/gemini-pro-latest"));
151 }
152
153 #[test]
154 fn catalog_is_text_only_and_excludes_non_chat_models() {
155 let models = google_gemini_static_catalog_models();
156 assert!(models
157 .iter()
158 .all(|m| m.input_modalities == vec![Modality::Text]));
159 for banned in [
160 "auto-gemini-2.5",
161 "auto-gemini-3",
162 "text-embedding-004",
163 "embedding-001",
164 "gemini-2.5-image",
165 "gemini-2.5-video",
166 "gemini-2.5-voice",
167 ] {
168 assert!(
169 !models.iter().any(|m| m.id == banned),
170 "{banned} must not be in the text/tool catalog"
171 );
172 }
173 }
174
175 #[test]
176 fn google_gemini_model_lookup_is_exact_match_only() {
177 assert!(google_gemini_model("gemini-2.5-pro").is_some());
178 assert!(google_gemini_model("gemini-2.5-flash").is_some());
179 assert!(google_gemini_model("gemini-2.5").is_none());
181 assert!(google_gemini_model("Gemini-2.5-Pro").is_none());
182 assert!(google_gemini_model("").is_none());
183 }
184}