systemprompt_wire/gemini/
wire.rs1use serde::{Deserialize, Serialize};
13use serde_json::Value;
14
15#[derive(Debug, Clone, Serialize)]
16#[serde(rename_all = "camelCase")]
17pub struct GeminiRequest {
18 pub contents: Vec<GeminiContent>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 pub system_instruction: Option<GeminiSystemInstruction>,
21 #[serde(skip_serializing_if = "Option::is_none")]
22 pub generation_config: Option<GeminiGenerationConfig>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub tools: Option<Vec<GeminiTool>>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub tool_config: Option<GeminiToolConfig>,
27}
28
29#[derive(Debug, Clone, Serialize)]
30pub struct GeminiSystemInstruction {
31 pub parts: Vec<GeminiPart>,
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35#[serde(rename_all = "camelCase")]
36pub struct GeminiContent {
37 pub role: String,
38 #[serde(default)]
39 pub parts: Vec<GeminiPart>,
40}
41
42#[derive(Debug, Clone, Serialize, Deserialize)]
43#[serde(untagged)]
44pub enum GeminiPart {
45 Text {
46 text: String,
47 #[serde(default, skip_serializing_if = "Option::is_none")]
48 thought: Option<bool>,
49 #[serde(
50 rename = "thoughtSignature",
51 default,
52 skip_serializing_if = "Option::is_none"
53 )]
54 thought_signature: Option<String>,
55 },
56 InlineData {
57 #[serde(rename = "inlineData")]
58 inline_data: GeminiInlineData,
59 },
60 FunctionCall {
61 #[serde(rename = "functionCall")]
62 function_call: GeminiFunctionCall,
63 #[serde(
66 rename = "thoughtSignature",
67 default,
68 skip_serializing_if = "Option::is_none"
69 )]
70 thought_signature: Option<String>,
71 },
72 FunctionResponse {
73 #[serde(rename = "functionResponse")]
74 function_response: GeminiFunctionResponse,
75 },
76 ExecutableCode {
77 #[serde(rename = "executableCode")]
78 executable_code: GeminiExecutableCode,
79 },
80 CodeExecutionResult {
81 #[serde(rename = "codeExecutionResult")]
82 code_execution_result: GeminiCodeExecutionResult,
83 },
84}
85
86#[derive(Debug, Clone, Serialize, Deserialize)]
87#[serde(rename_all = "camelCase")]
88pub struct GeminiInlineData {
89 pub mime_type: String,
90 pub data: String,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub struct GeminiFunctionCall {
96 pub name: String,
97 #[serde(default)]
98 pub args: Value,
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct GeminiFunctionResponse {
104 pub name: String,
105 pub response: Value,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct GeminiExecutableCode {
112 #[serde(default)]
113 pub language: Option<String>,
114 #[serde(default)]
115 pub code: String,
116}
117
118#[derive(Debug, Clone, Serialize, Deserialize)]
119#[serde(rename_all = "camelCase")]
120pub struct GeminiCodeExecutionResult {
121 #[serde(default)]
122 pub outcome: Option<String>,
123 #[serde(default)]
124 pub output: Option<String>,
125}
126
127#[derive(Debug, Clone, Default, Serialize)]
128#[serde(rename_all = "camelCase")]
129pub struct GeminiGenerationConfig {
130 #[serde(skip_serializing_if = "Option::is_none")]
131 pub temperature: Option<f32>,
132 #[serde(skip_serializing_if = "Option::is_none")]
133 pub top_p: Option<f32>,
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub top_k: Option<i32>,
136 #[serde(skip_serializing_if = "Option::is_none")]
137 pub max_output_tokens: Option<u32>,
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub stop_sequences: Option<Vec<String>>,
140 #[serde(skip_serializing_if = "Option::is_none")]
141 pub response_mime_type: Option<String>,
142 #[serde(skip_serializing_if = "Option::is_none")]
143 pub response_schema: Option<Value>,
145 #[serde(skip_serializing_if = "Option::is_none")]
146 pub thinking_config: Option<GeminiThinkingConfig>,
147 #[serde(skip_serializing_if = "Option::is_none")]
148 pub response_modalities: Option<Vec<String>>,
149 #[serde(skip_serializing_if = "Option::is_none")]
150 pub image_config: Option<GeminiImageConfig>,
151}
152
153#[derive(Debug, Clone, Serialize)]
154#[serde(rename_all = "camelCase")]
155pub struct GeminiImageConfig {
156 pub aspect_ratio: String,
157 #[serde(skip_serializing_if = "Option::is_none")]
158 pub image_size: Option<String>,
159}
160
161#[derive(Debug, Clone, Copy, Serialize)]
162#[serde(rename_all = "camelCase")]
163pub struct GeminiThinkingConfig {
164 #[serde(skip_serializing_if = "Option::is_none")]
165 pub thinking_budget: Option<u32>,
166 #[serde(skip_serializing_if = "Option::is_none")]
167 pub include_thoughts: Option<bool>,
168}
169
170#[derive(Debug, Clone, Serialize)]
171#[serde(untagged)]
172pub enum GeminiTool {
173 Functions {
174 #[serde(rename = "functionDeclarations")]
175 function_declarations: Vec<GeminiFunctionDeclaration>,
176 },
177 GoogleSearch {
178 #[serde(rename = "googleSearch")]
179 google_search: GeminiEmpty,
180 },
181 UrlContext {
182 #[serde(rename = "urlContext")]
183 url_context: GeminiEmpty,
184 },
185 CodeExecution {
186 #[serde(rename = "codeExecution")]
187 code_execution: GeminiEmpty,
188 },
189}
190
191#[derive(Debug, Clone, Copy, Serialize)]
192#[expect(
193 clippy::empty_structs_with_brackets,
194 reason = "Gemini expects these tool markers as an empty JSON object `{}`; a unit struct would \
195 serialize as `null`"
196)]
197pub struct GeminiEmpty {}
198
199#[derive(Debug, Clone, Serialize)]
200pub struct GeminiFunctionDeclaration {
201 pub name: String,
202 #[serde(skip_serializing_if = "Option::is_none")]
203 pub description: Option<String>,
204 pub parameters: Value,
206}
207
208#[derive(Debug, Clone, Serialize)]
209#[serde(rename_all = "camelCase")]
210pub struct GeminiToolConfig {
211 pub function_calling_config: GeminiFunctionCallingConfig,
212}
213
214#[derive(Debug, Clone, Serialize)]
215#[serde(rename_all = "camelCase")]
216pub struct GeminiFunctionCallingConfig {
217 pub mode: &'static str,
218 #[serde(skip_serializing_if = "Option::is_none")]
219 pub allowed_function_names: Option<Vec<String>>,
220}
221
222#[derive(Debug, Clone, Deserialize)]
223#[serde(rename_all = "camelCase")]
224pub struct GeminiResponse {
225 #[serde(default)]
226 pub candidates: Vec<GeminiCandidate>,
227 #[serde(default)]
228 pub prompt_feedback: Option<GeminiPromptFeedback>,
229 #[serde(default)]
230 pub usage_metadata: Option<GeminiUsageMetadata>,
231 #[serde(default)]
232 pub response_id: Option<String>,
233 #[serde(default)]
234 pub model_version: Option<String>,
235}
236
237#[derive(Debug, Clone, Deserialize)]
238#[serde(rename_all = "camelCase")]
239pub struct GeminiCandidate {
240 #[serde(default)]
241 pub content: Option<GeminiContent>,
242 #[serde(default)]
243 pub finish_reason: Option<String>,
244 #[serde(default)]
247 pub finish_message: Option<String>,
248 #[serde(default)]
249 pub grounding_metadata: Option<GeminiGroundingMetadata>,
250}
251
252#[derive(Debug, Clone, Deserialize)]
253#[serde(rename_all = "camelCase")]
254pub struct GeminiPromptFeedback {
255 #[serde(default)]
256 pub block_reason: Option<String>,
257 #[serde(default)]
258 pub block_reason_message: Option<String>,
259}
260
261#[derive(Debug, Clone, Deserialize)]
262#[serde(rename_all = "camelCase")]
263pub struct GeminiGroundingMetadata {
264 #[serde(default)]
265 pub grounding_chunks: Vec<GeminiGroundingChunk>,
266 #[serde(default)]
267 pub web_search_queries: Vec<String>,
268}
269
270#[derive(Debug, Clone, Deserialize)]
271pub struct GeminiGroundingChunk {
272 #[serde(default)]
273 pub web: Option<GeminiWebSource>,
274}
275
276#[derive(Debug, Clone, Deserialize)]
277pub struct GeminiWebSource {
278 #[serde(default)]
279 pub uri: String,
280 #[serde(default)]
281 pub title: Option<String>,
282}
283
284#[derive(Debug, Clone, Copy, Deserialize)]
285#[serde(rename_all = "camelCase")]
286pub struct GeminiUsageMetadata {
287 #[serde(default, rename = "promptTokenCount")]
288 pub prompt: u32,
289 #[serde(default, rename = "candidatesTokenCount")]
290 pub candidates: u32,
291 #[serde(default, rename = "totalTokenCount")]
292 pub total: u32,
293 #[serde(default, rename = "cachedContentTokenCount")]
294 pub cached: u32,
295 #[serde(default, rename = "thoughtsTokenCount")]
298 pub thoughts: u32,
299}