#[cfg(feature = "audio")]
#[cfg_attr(docsrs, doc(cfg(feature = "audio")))]
pub mod audio_generation;
pub mod cached_content;
pub mod caching;
pub mod completion;
pub mod embedding;
pub mod extension;
#[cfg(feature = "image")]
#[cfg_attr(docsrs, doc(cfg(feature = "image")))]
pub mod image_generation;
pub mod interactions_api;
pub mod model_listing;
mod options;
pub mod streaming;
pub mod transcription;
pub use crate::client::gemini::Gemini;
pub use crate::client::gemini_caching::Caching;
#[cfg(feature = "audio")]
pub use audio_generation::{GEMINI_3_8_FLASH_LITE_TTS, GEMINI_3_8_FLASH_TTS};
pub use cached_content::{CacheExpiry, CachedContent, CachedContents, NewCachedContent};
pub use caching::{AutoCache, CacheBook, CacheEvent, CacheReport, Clock, CreatedCache, Lease};
pub use completion::ThoughtReplay;
pub use embedding::{EMBEDDING_001, EMBEDDING_004};
#[cfg(feature = "image")]
pub use image_generation::{
GEMINI_2_5_FLASH_IMAGE, GEMINI_3_1_FLASH_IMAGE, GEMINI_3_1_FLASH_LITE_IMAGE,
GEMINI_3_PRO_IMAGE, GEMINI_NANO_BANANA_2_1,
};
pub use interactions_api::{DEEP_RESEARCH_MAX_PREVIEW_04_2026, DEEP_RESEARCH_PREVIEW_04_2026};
pub use model_listing::*;
use crate::client::env::{self, EnvError};
use crate::wire::Secret;
pub use completion::PROVIDER_NAME;
pub const BASE_URL: &str = "https://generativelanguage.googleapis.com";
pub const API_KEY_ENV: &str = "GEMINI_API_KEY";
#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct GeminiConfig {
pub api_key: Secret,
pub base_url: String,
}
impl GeminiConfig {
pub fn new(api_key: impl Into<Secret>) -> Self {
Self {
api_key: api_key.into(),
base_url: BASE_URL.to_owned(),
}
}
pub fn from_env() -> Result<Self, EnvError> {
Ok(Self::new(env::required(API_KEY_ENV)?))
}
pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
self.base_url = base_url.into();
self
}
pub(crate) fn uri(&self, path: &str) -> String {
let trimmed = path.trim_start_matches('/');
let separator = if trimmed.contains('?') { "&" } else { "?" };
let base = self.base_url.trim_end_matches('/');
format!("{base}/{trimmed}{separator}key={}", self.api_key.expose())
}
pub(crate) fn interactions_uri(&self, path: &str) -> String {
let base = self.base_url.trim_end_matches('/');
format!("{base}/{}", path.trim_start_matches('/'))
}
pub(crate) const INTERACTIONS_KEY_HEADER: &'static str = "x-goog-api-key";
pub(crate) fn completion(&self, model: impl Into<String>) -> completion::GenerateContent {
completion::GenerateContent::new(self.clone(), model)
}
pub(crate) fn interactions(&self, model: impl Into<String>) -> interactions_api::Interactions {
interactions_api::Interactions::new(self.clone(), model)
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
pub enum ImageSize {
#[serde(rename = "512")]
FiveTwelve,
#[serde(rename = "1K")]
OneK,
#[serde(rename = "2K")]
TwoK,
#[serde(rename = "4K")]
FourK,
}
#[cfg(test)]
mod tests;