omniference 0.1.8

A multi-protocol inference engine with provider adapters
Documentation
//! Google Gemini API request and response types
//!
//! This module contains all data structures for interacting with Google's Gemini API,
//! including generateContent requests, responses, streaming events, and models API.

use serde::{Deserialize, Serialize};

// ============================================================================
// Gemini API Request Types
// ============================================================================

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiGenerateContentRequest {
	pub contents: Vec<GeminiContent>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub tools: Option<Vec<GeminiTool>>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub tool_config: Option<GeminiToolConfig>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub system_instruction: Option<GeminiContent>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub generation_config: Option<GeminiGenerationConfig>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub safety_settings: Option<Vec<GeminiSafetySetting>>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GeminiContent {
	#[serde(skip_serializing_if = "Option::is_none")]
	pub role: Option<String>,
	pub parts: Vec<GeminiPart>,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum GeminiPart {
	ThoughtText {
		text: String,
		thought: bool,
	},
	Text {
		text: String,
	},
	InlineData {
		#[serde(rename = "inlineData")]
		inline_data: GeminiBlob,
	},
	FileData {
		#[serde(rename = "fileData")]
		file_data: GeminiFileData,
	},
	FunctionCall {
		#[serde(rename = "functionCall")]
		function_call: GeminiFunctionCall,
	},
	FunctionResponse {
		#[serde(rename = "functionResponse")]
		function_response: GeminiFunctionResponse,
	},
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiBlob {
	pub mime_type: String,
	pub data: String, // Base64 encoded
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiFileData {
	pub mime_type: Option<String>,
	pub file_uri: String,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GeminiFunctionCall {
	pub name: String,
	#[serde(default)]
	pub args: serde_json::Value,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GeminiFunctionResponse {
	pub name: String,
	pub response: serde_json::Value,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiTool {
	pub function_declarations: Vec<GeminiFunctionDeclaration>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiFunctionDeclaration {
	pub name: String,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub description: Option<String>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub parameters: Option<serde_json::Value>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiToolConfig {
	pub function_calling_config: GeminiFunctionCallingConfig,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiFunctionCallingConfig {
	pub mode: GeminiFunctionCallingMode,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub allowed_function_names: Option<Vec<String>>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GeminiFunctionCallingMode {
	ModeUnspecified,
	Auto,
	Any,
	None,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiThinkingConfig {
	#[serde(skip_serializing_if = "Option::is_none")]
	pub thinking_level: Option<String>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub thinking_budget: Option<i32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub include_thoughts: Option<bool>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiGenerationConfig {
	#[serde(skip_serializing_if = "Option::is_none")]
	pub stop_sequences: Option<Vec<String>>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub response_mime_type: Option<String>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub response_schema: Option<serde_json::Value>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub candidate_count: Option<u32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub max_output_tokens: Option<u32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub temperature: Option<f32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub top_p: Option<f32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub top_k: Option<u32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub presence_penalty: Option<f32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub frequency_penalty: Option<f32>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub seed: Option<i64>,
	#[serde(skip_serializing_if = "Option::is_none")]
	pub thinking_config: Option<GeminiThinkingConfig>,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiSafetySetting {
	pub category: GeminiHarmCategory,
	pub threshold: GeminiHarmBlockThreshold,
}

#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GeminiHarmCategory {
	HarmCategoryUnspecified,
	HarmCategoryHateSpeech,
	HarmCategorySexuallyExplicit,
	HarmCategoryDangerousContent,
	HarmCategoryHarassment,
	HarmCategoryCivicIntegrity,
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GeminiHarmBlockThreshold {
	HarmBlockThresholdUnspecified,
	BlockLowAndAbove,
	BlockMediumAndAbove,
	BlockOnlyHigh,
	BlockNone,
	Off,
}

// ============================================================================
// Gemini API Response Types
// ============================================================================

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiGenerateContentResponse {
	#[serde(default)]
	pub candidates: Vec<GeminiCandidate>,
	#[serde(default)]
	pub prompt_feedback: Option<GeminiPromptFeedback>,
	#[serde(default)]
	pub usage_metadata: Option<GeminiUsageMetadata>,
	#[serde(default)]
	pub model_version: Option<String>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiCandidate {
	#[serde(default)]
	pub content: Option<GeminiContent>,
	#[serde(default)]
	pub finish_reason: Option<GeminiFinishReason>,
	#[serde(default)]
	pub safety_ratings: Vec<GeminiSafetyRating>,
	#[serde(default)]
	pub citation_metadata: Option<GeminiCitationMetadata>,
	#[serde(default)]
	pub token_count: Option<u32>,
	#[serde(default)]
	pub index: Option<u32>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GeminiFinishReason {
	FinishReasonUnspecified,
	Stop,
	MaxTokens,
	Safety,
	Recitation,
	Language,
	Other,
	Blocklist,
	ProhibitedContent,
	Spii,
	MalformedFunctionCall,
	ImageSafety,
	#[serde(other)]
	Unknown,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiSafetyRating {
	pub category: GeminiHarmCategory,
	pub probability: GeminiHarmProbability,
	#[serde(default)]
	pub blocked: Option<bool>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GeminiHarmProbability {
	HarmProbabilityUnspecified,
	Negligible,
	Low,
	Medium,
	High,
	#[serde(other)]
	Unknown,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiCitationMetadata {
	#[serde(default)]
	pub citation_sources: Vec<GeminiCitationSource>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiCitationSource {
	#[serde(default)]
	pub start_index: Option<u32>,
	#[serde(default)]
	pub end_index: Option<u32>,
	#[serde(default)]
	pub uri: Option<String>,
	#[serde(default)]
	pub license: Option<String>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiPromptFeedback {
	#[serde(default)]
	pub block_reason: Option<GeminiBlockReason>,
	#[serde(default)]
	pub safety_ratings: Vec<GeminiSafetyRating>,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum GeminiBlockReason {
	BlockReasonUnspecified,
	Safety,
	Other,
	Blocklist,
	ProhibitedContent,
	#[serde(other)]
	Unknown,
}

#[derive(Debug, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
pub struct GeminiUsageMetadata {
	#[serde(default)]
	pub prompt_token_count: u32,
	#[serde(default)]
	pub candidates_token_count: u32,
	#[serde(default)]
	pub total_token_count: u32,
	#[serde(default)]
	pub cached_content_token_count: u32,
	#[serde(default)]
	pub thoughts_token_count: u32,
}

// ============================================================================
// Gemini Error Types
// ============================================================================

#[derive(Debug, Deserialize)]
pub struct GeminiErrorResponse {
	pub error: GeminiError,
}

#[derive(Debug, Deserialize)]
pub struct GeminiError {
	pub code: i32,
	pub message: String,
	#[serde(default)]
	pub status: Option<String>,
}

// ============================================================================
// Gemini Models API Types
// ============================================================================

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiModelsResponse {
	#[serde(default)]
	pub models: Vec<GeminiModelInfo>,
	#[serde(default)]
	pub next_page_token: Option<String>,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GeminiModelInfo {
	pub name: String,
	#[serde(default)]
	pub base_model_id: Option<String>,
	#[serde(default)]
	pub version: Option<String>,
	#[serde(default)]
	pub display_name: Option<String>,
	#[serde(default)]
	pub description: Option<String>,
	#[serde(default)]
	pub input_token_limit: Option<u32>,
	#[serde(default)]
	pub output_token_limit: Option<u32>,
	#[serde(default)]
	pub supported_generation_methods: Vec<String>,
	#[serde(default)]
	pub thinking: Option<bool>,
	#[serde(default)]
	pub temperature: Option<f32>,
	#[serde(default)]
	pub max_temperature: Option<f32>,
	#[serde(default)]
	pub top_p: Option<f32>,
	#[serde(default)]
	pub top_k: Option<u32>,
}