diff --git a/crates/google_ai/src/completion.rs b/crates/google_ai/src/completion.rs index bc28b5b9ed..60ee81751b 100644 --- a/crates/google_ai/src/completion.rs +++ b/crates/google_ai/src/completion.rs @@ -250,10 +250,11 @@ fn is_google_thinking_model(model_id: &str) -> bool { fn disabled_thinking_level(model_id: &str) -> Option { match model_id { - // `gemini-3.7-flash` rejects `MINIMAL` with a validation error, so `LOW` is - // the lowest level available to it. + // Gemini 3.7 and 3.8 Flash reject `MINIMAL` with a validation error, so + // `LOW` is the lowest level available to them. model_id if model_id.starts_with("gemini-3.7-flash") + || model_id.starts_with("gemini-3.8-flash") || (model_id.starts_with("gemini-3") && model_id.contains("-pro")) => { Some(ThinkingLevel::Low) @@ -749,6 +750,10 @@ mod tests { #[test] fn test_disabled_thinking_level_per_model() { + assert_eq!( + disabled_thinking_level("gemini-3.8-flash"), + Some(ThinkingLevel::Low) + ); assert_eq!( disabled_thinking_level("gemini-3.7-flash"), Some(ThinkingLevel::Low) diff --git a/crates/google_ai/src/google_ai.rs b/crates/google_ai/src/google_ai.rs index 5734bb2c15..00a195b43d 100644 --- a/crates/google_ai/src/google_ai.rs +++ b/crates/google_ai/src/google_ai.rs @@ -517,6 +517,8 @@ pub enum Model { Gemini36Flash, #[serde(rename = "gemini-3.7-flash")] Gemini37Flash, + #[serde(rename = "gemini-3.8-flash")] + Gemini38Flash, #[serde(rename = "gemini-3.1-pro-preview")] Gemini31Pro, #[serde(rename = "custom")] @@ -542,6 +544,7 @@ impl Model { Self::Gemini35Flash => "gemini-3.5-flash", Self::Gemini36Flash => "gemini-3.6-flash", Self::Gemini37Flash => "gemini-3.7-flash", + Self::Gemini38Flash => "gemini-3.8-flash", Self::Gemini31Pro => "gemini-3.1-pro-preview", Self::Custom { name, .. } => name, } @@ -553,6 +556,7 @@ impl Model { Self::Gemini35Flash => "gemini-3.5-flash", Self::Gemini36Flash => "gemini-3.6-flash", Self::Gemini37Flash => "gemini-3.7-flash", + Self::Gemini38Flash => "gemini-3.8-flash", Self::Gemini31Pro => "gemini-3.1-pro-preview", Self::Custom { name, .. } => name, } @@ -565,6 +569,7 @@ impl Model { Self::Gemini35Flash => "Gemini 3.5 Flash", Self::Gemini36Flash => "Gemini 3.6 Flash", Self::Gemini37Flash => "Gemini 3.7 Flash", + Self::Gemini38Flash => "Gemini 3.8 Flash", Self::Gemini31Pro => "Gemini 3.1 Pro", Self::Custom { name, display_name, .. @@ -579,6 +584,7 @@ impl Model { | Self::Gemini35Flash | Self::Gemini36Flash | Self::Gemini37Flash + | Self::Gemini38Flash | Self::Gemini31Pro => 1_048_576, Self::Custom { max_tokens, .. } => *max_tokens, } @@ -591,6 +597,7 @@ impl Model { | Model::Gemini35Flash | Model::Gemini36Flash | Model::Gemini37Flash + | Model::Gemini38Flash | Model::Gemini31Pro => Some(65_536), Model::Custom { .. } => None, } @@ -612,6 +619,7 @@ impl Model { | Self::Gemini35Flash | Self::Gemini36Flash | Self::Gemini37Flash + | Self::Gemini38Flash | Self::Gemini31Pro | Self::Custom { mode: GoogleModelMode::Thinking { .. }, @@ -631,7 +639,7 @@ impl Model { ThinkingLevel::Medium, ThinkingLevel::High, ], - Self::Gemini37Flash | Self::Gemini31Pro => &[ + Self::Gemini37Flash | Self::Gemini38Flash | Self::Gemini31Pro => &[ ThinkingLevel::Low, ThinkingLevel::Medium, ThinkingLevel::High, @@ -647,6 +655,7 @@ impl Model { Self::Gemini35Flash => Some(ThinkingLevel::Medium), Self::Gemini36Flash => Some(ThinkingLevel::Medium), Self::Gemini37Flash => Some(ThinkingLevel::Medium), + Self::Gemini38Flash => Some(ThinkingLevel::Medium), Self::Gemini31Pro => Some(ThinkingLevel::High), _ => None, } @@ -659,6 +668,7 @@ impl Model { | Self::Gemini35Flash | Self::Gemini36Flash | Self::Gemini37Flash + | Self::Gemini38Flash | Self::Gemini31Pro => GoogleModelMode::Thinking { budget_tokens: None, }, @@ -735,6 +745,31 @@ mod tests { assert_eq!(deserialized, Model::Gemini37Flash); } + #[test] + fn test_gemini_3_8_flash_model_metadata() { + let model = Model::Gemini38Flash; + assert_eq!(model.id(), "gemini-3.8-flash"); + assert_eq!(model.request_id(), "gemini-3.8-flash"); + assert_eq!(model.display_name(), "Gemini 3.8 Flash"); + assert_eq!(model.max_token_count(), 1_048_576); + assert_eq!(model.max_output_tokens(), Some(65_536)); + assert!(model.supports_thinking()); + assert_eq!( + model.supported_thinking_levels(), + &[ + ThinkingLevel::Low, + ThinkingLevel::Medium, + ThinkingLevel::High + ] + ); + assert_eq!(model.default_thinking_level(), Some(ThinkingLevel::Medium)); + + let serialized = serde_json::to_value(&model).unwrap(); + assert_eq!(serialized, json!("gemini-3.8-flash")); + let deserialized: Model = serde_json::from_value(json!("gemini-3.8-flash")).unwrap(); + assert_eq!(deserialized, Model::Gemini38Flash); + } + #[test] fn test_function_call_part_with_signature_serializes_correctly() { let part = FunctionCallPart {