gemini_live_api/
types.rs

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    // English
8    #[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    // Spanish
18    #[serde(rename = "es-ES")]
19    SpanishES,
20    #[serde(rename = "es-US")]
21    SpanishUS,
22
23    // German
24    #[serde(rename = "de-DE")]
25    GermanDE,
26
27    // French
28    #[serde(rename = "fr-FR")]
29    FrenchFR,
30    #[serde(rename = "fr-CA")]
31    FrenchCA,
32
33    // Hindi
34    #[serde(rename = "hi-IN")]
35    HindiIN,
36
37    // Portuguese
38    #[serde(rename = "pt-BR")]
39    PortugueseBR,
40
41    // Arabic (generic regional)
42    #[serde(rename = "ar-XA")]
43    ArabicXA,
44
45    // Indonesian
46    #[serde(rename = "id-ID")]
47    IndonesianID,
48
49    // Italian
50    #[serde(rename = "it-IT")]
51    ItalianIT,
52
53    // Japanese
54    #[serde(rename = "ja-JP")]
55    JapaneseJP,
56
57    // Turkish
58    #[serde(rename = "tr-TR")]
59    TurkishTR,
60
61    // Vietnamese
62    #[serde(rename = "vi-VN")]
63    VietnameseVN,
64
65    // Bengali
66    #[serde(rename = "bn-IN")]
67    BengaliIN,
68
69    // Gujarati
70    #[serde(rename = "gu-IN")]
71    GujaratiIN,
72
73    // Kannada
74    #[serde(rename = "kn-IN")]
75    KannadaIN,
76
77    // Malayalam
78    #[serde(rename = "ml-IN")]
79    MalayalamIN,
80
81    // Marathi
82    #[serde(rename = "mr-IN")]
83    MarathiIN,
84
85    // Tamil
86    #[serde(rename = "ta-IN")]
87    TamilIN,
88
89    // Telugu
90    #[serde(rename = "te-IN")]
91    TeluguIN,
92
93    // Dutch
94    #[serde(rename = "nl-NL")]
95    DutchNL,
96
97    // Korean
98    #[serde(rename = "ko-KR")]
99    KoreanKR,
100
101    // Mandarin Chinese (China)
102    #[serde(rename = "cmn-CN")]
103    MandarinCN,
104
105    // Polish
106    #[serde(rename = "pl-PL")]
107    PolishPL,
108
109    // Russian
110    #[serde(rename = "ru-RU")]
111    RussianRU,
112
113    // Thai
114    #[serde(rename = "th-TH")]
115    ThaiTH,
116
117    // For other codes
118    #[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    // #[serde(skip_serializing_if = "Option::is_none")]
128    // pub voice_config: Option<VoiceConfig>,
129}
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}