1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
5#[serde(rename_all = "kebab-case")]
6pub enum SpeechLanguageCode {
7 #[serde(rename = "en-US")]
9 EnglishUS,
10 #[serde(rename = "en-GB")]
11 EnglishGB,
12 #[serde(rename = "en-AU")]
13 EnglishAU,
14 #[serde(rename = "en-IN")]
15 EnglishIN,
16
17 #[serde(rename = "es-ES")]
19 SpanishES,
20 #[serde(rename = "es-US")]
21 SpanishUS,
22
23 #[serde(rename = "de-DE")]
25 GermanDE,
26
27 #[serde(rename = "fr-FR")]
29 FrenchFR,
30 #[serde(rename = "fr-CA")]
31 FrenchCA,
32
33 #[serde(rename = "hi-IN")]
35 HindiIN,
36
37 #[serde(rename = "pt-BR")]
39 PortugueseBR,
40
41 #[serde(rename = "ar-XA")]
43 ArabicXA,
44
45 #[serde(rename = "id-ID")]
47 IndonesianID,
48
49 #[serde(rename = "it-IT")]
51 ItalianIT,
52
53 #[serde(rename = "ja-JP")]
55 JapaneseJP,
56
57 #[serde(rename = "tr-TR")]
59 TurkishTR,
60
61 #[serde(rename = "vi-VN")]
63 VietnameseVN,
64
65 #[serde(rename = "bn-IN")]
67 BengaliIN,
68
69 #[serde(rename = "gu-IN")]
71 GujaratiIN,
72
73 #[serde(rename = "kn-IN")]
75 KannadaIN,
76
77 #[serde(rename = "ml-IN")]
79 MalayalamIN,
80
81 #[serde(rename = "mr-IN")]
83 MarathiIN,
84
85 #[serde(rename = "ta-IN")]
87 TamilIN,
88
89 #[serde(rename = "te-IN")]
91 TeluguIN,
92
93 #[serde(rename = "nl-NL")]
95 DutchNL,
96
97 #[serde(rename = "ko-KR")]
99 KoreanKR,
100
101 #[serde(rename = "cmn-CN")]
103 MandarinCN,
104
105 #[serde(rename = "pl-PL")]
107 PolishPL,
108
109 #[serde(rename = "ru-RU")]
111 RussianRU,
112
113 #[serde(rename = "th-TH")]
115 ThaiTH,
116
117 #[serde(untagged)]
119 Other(String),
120}
121
122#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
123#[serde(rename_all = "camelCase")]
124pub struct SpeechConfig {
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub language_code: Option<SpeechLanguageCode>,
127 }
130
131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
132pub enum ResponseModality {
133 Text,
134 Audio,
135 Other(String),
136}
137
138impl Serialize for ResponseModality {
139 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
140 where
141 S: Serializer,
142 {
143 match self {
144 ResponseModality::Text => serializer.serialize_str("TEXT"),
145 ResponseModality::Audio => serializer.serialize_str("AUDIO"),
146 ResponseModality::Other(s) => serializer.serialize_str(s),
147 }
148 }
149}
150
151impl<'de> Deserialize<'de> for ResponseModality {
152 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
153 where
154 D: Deserializer<'de>,
155 {
156 let s = String::deserialize(deserializer)?;
157 match s.as_str() {
158 "TEXT" => Ok(ResponseModality::Text),
159 "AUDIO" => Ok(ResponseModality::Audio),
160 other => Ok(ResponseModality::Other(other.to_string())),
161 }
162 }
163}
164
165#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
166#[serde(rename_all = "lowercase")]
167pub enum Role {
168 #[default]
169 User,
170 Model,
171 Function,
172 System,
173 #[serde(untagged)]
174 Other(String),
175}
176
177#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
178#[serde(rename_all = "camelCase")]
179pub struct Content {
180 pub parts: Vec<Part>,
181 #[serde(skip_serializing_if = "Option::is_none")]
182 pub role: Option<Role>,
183}
184
185#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
186#[serde(rename_all = "camelCase")]
187pub struct Part {
188 #[serde(skip_serializing_if = "Option::is_none")]
189 pub text: Option<String>,
190 #[serde(skip_serializing_if = "Option::is_none")]
191 pub inline_data: Option<Blob>,
192 #[serde(skip_serializing_if = "Option::is_none")]
193 pub function_call: Option<FunctionCall>,
194 #[serde(skip_serializing_if = "Option::is_none")]
195 pub function_response: Option<FunctionResponse>,
196 #[serde(skip_serializing_if = "Option::is_none")]
197 pub executable_code: Option<ExecutableCode>,
198}
199
200#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
201#[serde(rename_all = "camelCase")]
202pub struct ExecutableCode {
203 #[serde(skip_serializing_if = "Option::is_none")]
204 pub language: Option<String>,
205 #[serde(skip_serializing_if = "Option::is_none")]
206 pub code: Option<String>,
207}
208
209#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
210#[serde(rename_all = "camelCase")]
211pub struct FunctionCall {
212 pub name: String,
213 #[serde(skip_serializing_if = "Option::is_none")]
214 pub args: Option<serde_json::Value>,
215 #[serde(skip_serializing_if = "Option::is_none")]
216 pub id: Option<String>,
217}
218
219#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
220#[serde(rename_all = "camelCase")]
221pub struct FunctionResponse {
222 pub name: String,
223 pub response: serde_json::Value,
224 #[serde(skip_serializing_if = "Option::is_none")]
225 pub id: Option<String>,
226}
227
228impl Default for FunctionResponse {
229 fn default() -> Self {
230 Self {
231 name: String::new(),
232 response: serde_json::Value::Null,
233 id: None,
234 }
235 }
236}
237
238#[derive(Deserialize, Debug, Clone, Default)]
239#[serde(rename_all = "camelCase")]
240pub struct BidiGenerateContentToolCall {
241 pub function_calls: Vec<FunctionCall>,
242}
243
244#[derive(Serialize, Debug, Clone)]
245#[serde(rename_all = "camelCase")]
246pub struct BidiGenerateContentToolResponse {
247 pub function_responses: Vec<FunctionResponse>,
248}
249
250#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
251#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
252pub enum ActivityHandling {
253 ActivityHandlingUnspecified,
254 StartOfActivityInterrupts,
255 NoInterruption,
256}
257
258#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
259#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
260pub enum StartSensitivity {
261 StartSensitivityUnspecified,
262 StartSensitivityHigh,
263 StartSensitivityLow,
264}
265
266#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
267#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
268pub enum EndSensitivity {
269 EndSensitivityUnspecified,
270 EndSensitivityHigh,
271 EndSensitivityLow,
272}
273
274#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
275#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
276pub enum TurnCoverage {
277 TurnCoverageUnspecified,
278 TurnIncludesOnlyActivity,
279 TurnIncludesAllInput,
280}
281
282#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
283#[serde(rename_all = "camelCase")]
284pub struct Blob {
285 pub mime_type: String,
286 pub data: String,
287}
288
289#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
290#[serde(rename_all = "camelCase")]
291pub struct GenerationConfig {
292 #[serde(skip_serializing_if = "Option::is_none")]
293 pub candidate_count: Option<i32>,
294 #[serde(skip_serializing_if = "Option::is_none")]
295 pub max_output_tokens: Option<i32>,
296 #[serde(skip_serializing_if = "Option::is_none")]
297 pub temperature: Option<f32>,
298 #[serde(skip_serializing_if = "Option::is_none")]
299 pub top_p: Option<f32>,
300 #[serde(skip_serializing_if = "Option::is_none")]
301 pub top_k: Option<i32>,
302 #[serde(skip_serializing_if = "Option::is_none")]
303 pub presence_penalty: Option<f32>,
304 #[serde(skip_serializing_if = "Option::is_none")]
305 pub frequency_penalty: Option<f32>,
306 #[serde(skip_serializing_if = "Option::is_none")]
307 pub response_modalities: Option<Vec<ResponseModality>>,
308 #[serde(skip_serializing_if = "Option::is_none")]
309 pub speech_config: Option<SpeechConfig>,
310}
311
312#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
313#[serde(rename_all = "camelCase")]
314pub struct Tool {
315 pub function_declarations: Vec<FunctionDeclaration>,
316}
317
318#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
319#[serde(rename_all = "camelCase")]
320pub struct FunctionDeclaration {
321 pub name: String,
322 pub description: String,
323 #[serde(skip_serializing_if = "Option::is_none")]
324 pub parameters: Option<Schema>,
325}
326
327#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
328#[serde(rename_all = "camelCase")]
329pub struct Schema {
330 #[serde(rename = "type")]
331 pub schema_type: String,
332 #[serde(skip_serializing_if = "Option::is_none")]
333 pub properties: Option<HashMap<String, Schema>>,
334 #[serde(skip_serializing_if = "Option::is_none")]
335 pub required: Option<Vec<String>>,
336 #[serde(skip_serializing_if = "Option::is_none")]
337 pub description: Option<String>,
338}
339
340#[derive(Serialize, Debug, Clone, Default)]
341#[serde(rename_all = "camelCase")]
342pub struct BidiGenerateContentSetup {
343 pub model: String,
344 #[serde(skip_serializing_if = "Option::is_none")]
345 pub generation_config: Option<GenerationConfig>,
346 #[serde(skip_serializing_if = "Option::is_none")]
347 pub system_instruction: Option<Content>,
348 #[serde(skip_serializing_if = "Option::is_none")]
349 pub tools: Option<Vec<Tool>>,
350 #[serde(skip_serializing_if = "Option::is_none")]
351 pub realtime_input_config: Option<RealtimeInputConfig>,
352 #[serde(skip_serializing_if = "Option::is_none")]
353 pub session_resumption: Option<SessionResumptionConfig>,
354 #[serde(skip_serializing_if = "Option::is_none")]
355 pub context_window_compression: Option<ContextWindowCompressionConfig>,
356 #[serde(skip_serializing_if = "Option::is_none")]
357 pub output_audio_transcription: Option<AudioTranscriptionConfig>,
358}
359
360#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
361#[serde(rename_all = "camelCase")]
362pub struct AudioTranscriptionConfig {}
363
364#[derive(Serialize, Debug, Clone, Default)]
365#[serde(rename_all = "camelCase")]
366pub struct BidiGenerateContentClientContent {
367 #[serde(skip_serializing_if = "Option::is_none")]
368 pub turns: Option<Vec<Content>>,
369 #[serde(skip_serializing_if = "Option::is_none")]
370 pub turn_complete: Option<bool>,
371}
372
373#[derive(Serialize, Debug, Clone, Default)]
374#[serde(rename_all = "camelCase")]
375pub struct BidiGenerateContentRealtimeInput {
376 #[serde(skip_serializing_if = "Option::is_none")]
377 pub audio: Option<Blob>,
378 #[serde(skip_serializing_if = "Option::is_none")]
379 pub video: Option<Blob>,
380 #[serde(skip_serializing_if = "Option::is_none")]
381 pub text: Option<String>,
382 #[serde(skip_serializing_if = "Option::is_none")]
383 pub activity_start: Option<ActivityStart>,
384 #[serde(skip_serializing_if = "Option::is_none")]
385 pub activity_end: Option<ActivityEnd>,
386 #[serde(skip_serializing_if = "Option::is_none")]
387 pub audio_stream_end: Option<bool>,
388}
389
390#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
391#[serde(rename_all = "camelCase")]
392pub struct ActivityStart {}
393
394#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
395#[serde(rename_all = "camelCase")]
396pub struct ActivityEnd {}
397
398#[derive(Serialize, Debug, Clone)]
399#[serde(rename_all = "camelCase")]
400pub enum ClientMessagePayload {
401 Setup(BidiGenerateContentSetup),
402 ClientContent(BidiGenerateContentClientContent),
403 RealtimeInput(BidiGenerateContentRealtimeInput),
404 ToolResponse(BidiGenerateContentToolResponse),
405}
406
407#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
408#[serde(rename_all = "camelCase")]
409pub struct BidiGenerateContentSetupComplete {}
410
411#[derive(Deserialize, Debug, Clone, Default)]
412#[serde(rename_all = "camelCase")]
413pub struct BidiGenerateContentServerContent {
414 #[serde(default)]
415 pub generation_complete: bool,
416 #[serde(default)]
417 pub turn_complete: bool,
418 #[serde(default)]
419 pub interrupted: bool,
420 #[serde(skip_serializing_if = "Option::is_none")]
421 pub grounding_metadata: Option<serde_json::Value>,
422 #[serde(skip_serializing_if = "Option::is_none")]
423 pub output_transcription: Option<BidiGenerateContentTranscription>,
424 #[serde(skip_serializing_if = "Option::is_none")]
425 pub model_turn: Option<Content>,
426}
427
428#[derive(Deserialize, Debug, Clone, Default)]
429#[serde(rename_all = "camelCase")]
430pub struct BidiGenerateContentTranscription {
431 pub text: String,
432}
433
434#[derive(Deserialize, Debug, Clone, Default)]
435#[serde(rename_all = "camelCase")]
436pub struct BidiGenerateContentToolCallCancellation {
437 pub ids: Vec<String>,
438}
439
440#[derive(Deserialize, Debug, Clone, Default)]
441#[serde(rename_all = "camelCase")]
442pub struct GoAway {
443 #[serde(skip_serializing_if = "Option::is_none")]
444 pub time_left: Option<String>,
445}
446
447#[derive(Deserialize, Debug, Clone, Default)]
448#[serde(rename_all = "camelCase")]
449pub struct SessionResumptionUpdate {
450 pub new_handle: String,
451 pub resumable: bool,
452}
453
454#[derive(Deserialize, Debug, Clone, Default)]
455#[serde(rename_all = "camelCase")]
456pub struct UsageMetadata {
457 #[serde(skip_serializing_if = "Option::is_none")]
458 pub prompt_token_count: Option<i32>,
459 #[serde(skip_serializing_if = "Option::is_none")]
460 pub cached_content_token_count: Option<i32>,
461 #[serde(skip_serializing_if = "Option::is_none")]
462 pub response_token_count: Option<i32>,
463 #[serde(skip_serializing_if = "Option::is_none")]
464 pub tool_use_prompt_token_count: Option<i32>,
465 #[serde(skip_serializing_if = "Option::is_none")]
466 pub thoughts_token_count: Option<i32>,
467 #[serde(skip_serializing_if = "Option::is_none")]
468 pub total_token_count: Option<i32>,
469}
470
471#[derive(Deserialize, Debug, Clone, Default)]
472#[serde(rename_all = "camelCase")]
473pub struct ServerMessage {
474 #[serde(skip_serializing_if = "Option::is_none")]
475 pub usage_metadata: Option<UsageMetadata>,
476 #[serde(skip_serializing_if = "Option::is_none")]
477 pub setup_complete: Option<BidiGenerateContentSetupComplete>,
478 #[serde(skip_serializing_if = "Option::is_none")]
479 pub server_content: Option<BidiGenerateContentServerContent>,
480 #[serde(skip_serializing_if = "Option::is_none")]
481 pub tool_call: Option<BidiGenerateContentToolCall>,
482 #[serde(skip_serializing_if = "Option::is_none")]
483 pub tool_call_cancellation: Option<BidiGenerateContentToolCallCancellation>,
484 #[serde(skip_serializing_if = "Option::is_none")]
485 pub go_away: Option<GoAway>,
486 #[serde(skip_serializing_if = "Option::is_none")]
487 pub session_resumption_update: Option<SessionResumptionUpdate>,
488}
489
490#[derive(Serialize, Deserialize, Debug, Clone, Default)]
491#[serde(rename_all = "camelCase")]
492pub struct RealtimeInputConfig {
493 #[serde(skip_serializing_if = "Option::is_none")]
494 pub automatic_activity_detection: Option<AutomaticActivityDetection>,
495 #[serde(skip_serializing_if = "Option::is_none")]
496 pub activity_handling: Option<ActivityHandling>,
497 #[serde(skip_serializing_if = "Option::is_none")]
498 pub turn_coverage: Option<TurnCoverage>,
499}
500
501#[derive(Serialize, Deserialize, Debug, Clone, Default)]
502#[serde(rename_all = "camelCase")]
503pub struct AutomaticActivityDetection {
504 #[serde(skip_serializing_if = "Option::is_none")]
505 pub disabled: Option<bool>,
506 #[serde(skip_serializing_if = "Option::is_none")]
507 pub start_of_speech_sensitivity: Option<StartSensitivity>,
508 #[serde(skip_serializing_if = "Option::is_none")]
509 pub prefix_padding_ms: Option<i32>,
510 #[serde(skip_serializing_if = "Option::is_none")]
511 pub end_of_speech_sensitivity: Option<EndSensitivity>,
512 #[serde(skip_serializing_if = "Option::is_none")]
513 pub silence_duration_ms: Option<i32>,
514}
515
516#[derive(Serialize, Deserialize, Debug, Clone, Default)]
517#[serde(rename_all = "camelCase")]
518pub struct SessionResumptionConfig {
519 #[serde(skip_serializing_if = "Option::is_none")]
520 pub handle: Option<String>,
521}
522
523#[derive(Serialize, Deserialize, Debug, Clone, Default)]
524#[serde(rename_all = "camelCase")]
525pub struct ContextWindowCompressionConfig {
526 #[serde(skip_serializing_if = "Option::is_none")]
527 pub sliding_window: Option<SlidingWindow>,
528 pub trigger_tokens: i64,
529}
530
531#[derive(Serialize, Deserialize, Debug, Clone, Default)]
532#[serde(rename_all = "camelCase")]
533pub struct SlidingWindow {
534 pub target_tokens: i64,
535}