Skip to main content

gproxy_protocol/gemini/live/
types.rs

1use serde::{Deserialize, Serialize};
2use time::OffsetDateTime;
3
4pub use crate::gemini::count_tokens::types::{
5    GeminiBlob, GeminiContent, GeminiFunctionCall, GeminiFunctionResponse, GeminiGenerationConfig,
6    GeminiModalityTokenCount, GeminiTool, HttpMethod,
7};
8pub use crate::gemini::generate_content::types::{
9    GeminiGroundingMetadata, GeminiUrlContextMetadata,
10};
11pub use crate::gemini::types::{
12    GeminiApiError, GeminiApiErrorResponse, GeminiResponseHeaders, JsonObject,
13};
14
15/// Union envelope for client frames in `BidiGenerateContent`.
16#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
17pub struct GeminiBidiGenerateContentClientMessage {
18    /// Exactly one field should be set.
19    #[serde(flatten)]
20    pub message_type: GeminiBidiGenerateContentClientMessageType,
21}
22
23#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
24#[serde(untagged)]
25#[allow(clippy::large_enum_variant)]
26pub enum GeminiBidiGenerateContentClientMessageType {
27    Setup {
28        setup: GeminiBidiGenerateContentSetup,
29    },
30    ClientContent {
31        #[serde(rename = "clientContent")]
32        client_content: GeminiBidiGenerateContentClientContent,
33    },
34    RealtimeInput {
35        #[serde(rename = "realtimeInput")]
36        realtime_input: GeminiBidiGenerateContentRealtimeInput,
37    },
38    ToolResponse {
39        #[serde(rename = "toolResponse")]
40        tool_response: GeminiBidiGenerateContentToolResponse,
41    },
42}
43
44/// Message to configure one Live WebSocket session.
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
46pub struct GeminiBidiGenerateContentSetup {
47    /// Required model resource id in format `models/{model}`.
48    pub model: String,
49    #[serde(
50        rename = "generationConfig",
51        default,
52        skip_serializing_if = "Option::is_none"
53    )]
54    pub generation_config: Option<GeminiGenerationConfig>,
55    #[serde(
56        rename = "systemInstruction",
57        default,
58        skip_serializing_if = "Option::is_none"
59    )]
60    pub system_instruction: Option<GeminiContent>,
61    #[serde(default, skip_serializing_if = "Option::is_none")]
62    pub tools: Option<Vec<GeminiTool>>,
63    #[serde(
64        rename = "realtimeInputConfig",
65        default,
66        skip_serializing_if = "Option::is_none"
67    )]
68    pub realtime_input_config: Option<GeminiRealtimeInputConfig>,
69    #[serde(
70        rename = "sessionResumption",
71        default,
72        skip_serializing_if = "Option::is_none"
73    )]
74    pub session_resumption: Option<GeminiSessionResumptionConfig>,
75    #[serde(
76        rename = "contextWindowCompression",
77        default,
78        skip_serializing_if = "Option::is_none"
79    )]
80    pub context_window_compression: Option<GeminiContextWindowCompressionConfig>,
81    #[serde(
82        rename = "inputAudioTranscription",
83        default,
84        skip_serializing_if = "Option::is_none"
85    )]
86    pub input_audio_transcription: Option<GeminiAudioTranscriptionConfig>,
87    #[serde(
88        rename = "outputAudioTranscription",
89        default,
90        skip_serializing_if = "Option::is_none"
91    )]
92    pub output_audio_transcription: Option<GeminiAudioTranscriptionConfig>,
93    #[serde(default, skip_serializing_if = "Option::is_none")]
94    pub proactivity: Option<GeminiProactivityConfig>,
95    #[serde(
96        rename = "prefixTurns",
97        default,
98        skip_serializing_if = "Option::is_none"
99    )]
100    pub prefix_turns: Option<Vec<GeminiContent>>,
101    #[serde(
102        rename = "historyConfig",
103        default,
104        skip_serializing_if = "Option::is_none"
105    )]
106    pub history_config: Option<GeminiHistoryConfig>,
107}
108
109/// Incremental conversation content from client.
110#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
111pub struct GeminiBidiGenerateContentClientContent {
112    #[serde(default, skip_serializing_if = "Option::is_none")]
113    pub turns: Option<Vec<GeminiContent>>,
114    #[serde(
115        rename = "turnComplete",
116        default,
117        skip_serializing_if = "Option::is_none"
118    )]
119    pub turn_complete: Option<bool>,
120}
121
122/// Realtime (audio/video/text) user input stream chunk.
123#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
124pub struct GeminiBidiGenerateContentRealtimeInput {
125    /// Deprecated in upstream docs; prefer `audio`/`video`/`text`.
126    #[serde(
127        rename = "mediaChunks",
128        default,
129        skip_serializing_if = "Option::is_none"
130    )]
131    pub media_chunks: Option<Vec<GeminiBlob>>,
132    #[serde(default, skip_serializing_if = "Option::is_none")]
133    pub audio: Option<GeminiBlob>,
134    #[serde(default, skip_serializing_if = "Option::is_none")]
135    pub video: Option<GeminiBlob>,
136    #[serde(
137        rename = "activityStart",
138        default,
139        skip_serializing_if = "Option::is_none"
140    )]
141    pub activity_start: Option<GeminiActivityStart>,
142    #[serde(
143        rename = "activityEnd",
144        default,
145        skip_serializing_if = "Option::is_none"
146    )]
147    pub activity_end: Option<GeminiActivityEnd>,
148    #[serde(
149        rename = "audioStreamEnd",
150        default,
151        skip_serializing_if = "Option::is_none"
152    )]
153    pub audio_stream_end: Option<bool>,
154    #[serde(default, skip_serializing_if = "Option::is_none")]
155    pub text: Option<String>,
156}
157
158#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
159pub struct GeminiActivityStart {}
160
161#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
162pub struct GeminiActivityEnd {}
163
164#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
165pub struct GeminiBidiGenerateContentToolResponse {
166    #[serde(
167        rename = "functionResponses",
168        default,
169        skip_serializing_if = "Option::is_none"
170    )]
171    pub function_responses: Option<Vec<GeminiFunctionResponse>>,
172}
173
174/// Union envelope for server frames in `BidiGenerateContent`.
175#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
176pub struct GeminiBidiGenerateContentServerMessage {
177    #[serde(
178        rename = "usageMetadata",
179        default,
180        skip_serializing_if = "Option::is_none"
181    )]
182    pub usage_metadata: Option<GeminiLiveUsageMetadata>,
183    /// Exactly one field should be set.
184    #[serde(flatten)]
185    pub message_type: GeminiBidiGenerateContentServerMessageType,
186}
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189#[serde(untagged)]
190#[allow(clippy::large_enum_variant)]
191pub enum GeminiBidiGenerateContentServerMessageType {
192    SetupComplete {
193        #[serde(rename = "setupComplete")]
194        setup_complete: GeminiBidiGenerateContentSetupComplete,
195    },
196    ServerContent {
197        #[serde(rename = "serverContent")]
198        server_content: GeminiBidiGenerateContentServerContent,
199    },
200    ToolCall {
201        #[serde(rename = "toolCall")]
202        tool_call: GeminiBidiGenerateContentToolCall,
203    },
204    ToolCallCancellation {
205        #[serde(rename = "toolCallCancellation")]
206        tool_call_cancellation: GeminiBidiGenerateContentToolCallCancellation,
207    },
208    GoAway {
209        #[serde(rename = "goAway")]
210        go_away: GeminiGoAway,
211    },
212    SessionResumptionUpdate {
213        #[serde(rename = "sessionResumptionUpdate")]
214        session_resumption_update: GeminiSessionResumptionUpdate,
215    },
216}
217
218#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
219pub struct GeminiBidiGenerateContentSetupComplete {}
220
221#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
222pub struct GeminiBidiGenerateContentServerContent {
223    #[serde(
224        rename = "generationComplete",
225        default,
226        skip_serializing_if = "Option::is_none"
227    )]
228    pub generation_complete: Option<bool>,
229    #[serde(
230        rename = "turnComplete",
231        default,
232        skip_serializing_if = "Option::is_none"
233    )]
234    pub turn_complete: Option<bool>,
235    #[serde(default, skip_serializing_if = "Option::is_none")]
236    pub interrupted: Option<bool>,
237    #[serde(
238        rename = "groundingMetadata",
239        default,
240        skip_serializing_if = "Option::is_none"
241    )]
242    pub grounding_metadata: Option<GeminiGroundingMetadata>,
243    #[serde(
244        rename = "inputTranscription",
245        default,
246        skip_serializing_if = "Option::is_none"
247    )]
248    pub input_transcription: Option<GeminiBidiGenerateContentTranscription>,
249    #[serde(
250        rename = "outputTranscription",
251        default,
252        skip_serializing_if = "Option::is_none"
253    )]
254    pub output_transcription: Option<GeminiBidiGenerateContentTranscription>,
255    #[serde(
256        rename = "urlContextMetadata",
257        default,
258        skip_serializing_if = "Option::is_none"
259    )]
260    pub url_context_metadata: Option<GeminiUrlContextMetadata>,
261    #[serde(rename = "modelTurn", default, skip_serializing_if = "Option::is_none")]
262    pub model_turn: Option<GeminiContent>,
263}
264
265#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
266pub struct GeminiBidiGenerateContentTranscription {
267    pub text: String,
268}
269
270#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
271pub struct GeminiBidiGenerateContentToolCall {
272    #[serde(
273        rename = "functionCalls",
274        default,
275        skip_serializing_if = "Option::is_none"
276    )]
277    pub function_calls: Option<Vec<GeminiFunctionCall>>,
278}
279
280#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
281pub struct GeminiBidiGenerateContentToolCallCancellation {
282    #[serde(default, skip_serializing_if = "Option::is_none")]
283    pub ids: Option<Vec<String>>,
284}
285
286#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
287pub struct GeminiGoAway {
288    /// Protobuf `Duration` JSON string (example: `"15s"`).
289    #[serde(rename = "timeLeft")]
290    pub time_left: String,
291}
292
293#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
294pub struct GeminiLiveUsageMetadata {
295    #[serde(
296        rename = "promptTokenCount",
297        default,
298        skip_serializing_if = "Option::is_none"
299    )]
300    pub prompt_token_count: Option<u64>,
301    #[serde(
302        rename = "cachedContentTokenCount",
303        default,
304        skip_serializing_if = "Option::is_none"
305    )]
306    pub cached_content_token_count: Option<u64>,
307    #[serde(
308        rename = "responseTokenCount",
309        default,
310        skip_serializing_if = "Option::is_none"
311    )]
312    pub response_token_count: Option<u64>,
313    #[serde(
314        rename = "toolUsePromptTokenCount",
315        default,
316        skip_serializing_if = "Option::is_none"
317    )]
318    pub tool_use_prompt_token_count: Option<u64>,
319    #[serde(
320        rename = "thoughtsTokenCount",
321        default,
322        skip_serializing_if = "Option::is_none"
323    )]
324    pub thoughts_token_count: Option<u64>,
325    #[serde(
326        rename = "totalTokenCount",
327        default,
328        skip_serializing_if = "Option::is_none"
329    )]
330    pub total_token_count: Option<u64>,
331    #[serde(
332        rename = "promptTokensDetails",
333        default,
334        skip_serializing_if = "Option::is_none"
335    )]
336    pub prompt_tokens_details: Option<Vec<GeminiModalityTokenCount>>,
337    #[serde(
338        rename = "cacheTokensDetails",
339        default,
340        skip_serializing_if = "Option::is_none"
341    )]
342    pub cache_tokens_details: Option<Vec<GeminiModalityTokenCount>>,
343    #[serde(
344        rename = "responseTokensDetails",
345        default,
346        skip_serializing_if = "Option::is_none"
347    )]
348    pub response_tokens_details: Option<Vec<GeminiModalityTokenCount>>,
349    #[serde(
350        rename = "toolUsePromptTokensDetails",
351        default,
352        skip_serializing_if = "Option::is_none"
353    )]
354    pub tool_use_prompt_tokens_details: Option<Vec<GeminiModalityTokenCount>>,
355}
356
357#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
358pub struct GeminiHistoryConfig {
359    #[serde(
360        rename = "initialHistoryInClientContent",
361        default,
362        skip_serializing_if = "Option::is_none"
363    )]
364    pub initial_history_in_client_content: Option<bool>,
365}
366
367#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
368pub struct GeminiAudioTranscriptionConfig {}
369
370#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
371pub struct GeminiRealtimeInputConfig {
372    #[serde(
373        rename = "automaticActivityDetection",
374        default,
375        skip_serializing_if = "Option::is_none"
376    )]
377    pub automatic_activity_detection: Option<GeminiAutomaticActivityDetection>,
378    #[serde(
379        rename = "activityHandling",
380        default,
381        skip_serializing_if = "Option::is_none"
382    )]
383    pub activity_handling: Option<GeminiActivityHandling>,
384    #[serde(
385        rename = "turnCoverage",
386        default,
387        skip_serializing_if = "Option::is_none"
388    )]
389    pub turn_coverage: Option<GeminiTurnCoverage>,
390}
391
392#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
393pub struct GeminiAutomaticActivityDetection {
394    #[serde(default, skip_serializing_if = "Option::is_none")]
395    pub disabled: Option<bool>,
396    #[serde(
397        rename = "startOfSpeechSensitivity",
398        default,
399        skip_serializing_if = "Option::is_none"
400    )]
401    pub start_of_speech_sensitivity: Option<GeminiStartSensitivity>,
402    #[serde(
403        rename = "prefixPaddingMs",
404        default,
405        skip_serializing_if = "Option::is_none"
406    )]
407    pub prefix_padding_ms: Option<i32>,
408    #[serde(
409        rename = "endOfSpeechSensitivity",
410        default,
411        skip_serializing_if = "Option::is_none"
412    )]
413    pub end_of_speech_sensitivity: Option<GeminiEndSensitivity>,
414    #[serde(
415        rename = "silenceDurationMs",
416        default,
417        skip_serializing_if = "Option::is_none"
418    )]
419    pub silence_duration_ms: Option<i32>,
420}
421
422#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
423pub enum GeminiActivityHandling {
424    #[serde(rename = "ACTIVITY_HANDLING_UNSPECIFIED")]
425    ActivityHandlingUnspecified,
426    #[serde(rename = "START_OF_ACTIVITY_INTERRUPTS")]
427    StartOfActivityInterrupts,
428    #[serde(rename = "NO_INTERRUPTION")]
429    NoInterruption,
430}
431
432#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
433pub enum GeminiStartSensitivity {
434    #[serde(rename = "START_SENSITIVITY_UNSPECIFIED")]
435    StartSensitivityUnspecified,
436    #[serde(rename = "START_SENSITIVITY_HIGH")]
437    StartSensitivityHigh,
438    #[serde(rename = "START_SENSITIVITY_LOW")]
439    StartSensitivityLow,
440}
441
442#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
443pub enum GeminiEndSensitivity {
444    #[serde(rename = "END_SENSITIVITY_UNSPECIFIED")]
445    EndSensitivityUnspecified,
446    #[serde(rename = "END_SENSITIVITY_HIGH")]
447    EndSensitivityHigh,
448    #[serde(rename = "END_SENSITIVITY_LOW")]
449    EndSensitivityLow,
450}
451
452#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
453pub enum GeminiTurnCoverage {
454    #[serde(rename = "TURN_COVERAGE_UNSPECIFIED")]
455    TurnCoverageUnspecified,
456    #[serde(rename = "TURN_INCLUDES_ONLY_ACTIVITY")]
457    TurnIncludesOnlyActivity,
458    #[serde(rename = "TURN_INCLUDES_ALL_INPUT")]
459    TurnIncludesAllInput,
460    #[serde(rename = "TURN_INCLUDES_AUDIO_ACTIVITY_AND_ALL_VIDEO")]
461    TurnIncludesAudioActivityAndAllVideo,
462}
463
464#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
465pub struct GeminiSessionResumptionConfig {
466    #[serde(default, skip_serializing_if = "Option::is_none")]
467    pub handle: Option<String>,
468}
469
470#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
471pub struct GeminiSessionResumptionUpdate {
472    #[serde(rename = "newHandle", default, skip_serializing_if = "Option::is_none")]
473    pub new_handle: Option<String>,
474    #[serde(default, skip_serializing_if = "Option::is_none")]
475    pub resumable: Option<bool>,
476}
477
478#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
479pub struct GeminiContextWindowCompressionConfig {
480    #[serde(
481        rename = "slidingWindow",
482        default,
483        skip_serializing_if = "Option::is_none"
484    )]
485    pub sliding_window: Option<GeminiSlidingWindow>,
486    #[serde(
487        rename = "triggerTokens",
488        default,
489        skip_serializing_if = "Option::is_none"
490    )]
491    pub trigger_tokens: Option<i64>,
492}
493
494#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
495pub struct GeminiSlidingWindow {
496    #[serde(
497        rename = "targetTokens",
498        default,
499        skip_serializing_if = "Option::is_none"
500    )]
501    pub target_tokens: Option<i64>,
502}
503
504#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
505pub struct GeminiProactivityConfig {
506    #[serde(
507        rename = "proactiveAudio",
508        default,
509        skip_serializing_if = "Option::is_none"
510    )]
511    pub proactive_audio: Option<bool>,
512}
513
514/// Request for `AuthTokenService.CreateToken`.
515#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
516pub struct GeminiCreateAuthTokenRequest {
517    #[serde(rename = "authToken")]
518    pub auth_token: GeminiAuthToken,
519}
520
521/// Ephemeral authentication token configuration.
522#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
523pub struct GeminiAuthToken {
524    #[serde(default, skip_serializing_if = "Option::is_none")]
525    pub name: Option<String>,
526    #[serde(
527        rename = "expireTime",
528        default,
529        with = "time::serde::rfc3339::option",
530        skip_serializing_if = "Option::is_none"
531    )]
532    pub expire_time: Option<OffsetDateTime>,
533    #[serde(
534        rename = "newSessionExpireTime",
535        default,
536        with = "time::serde::rfc3339::option",
537        skip_serializing_if = "Option::is_none"
538    )]
539    pub new_session_expire_time: Option<OffsetDateTime>,
540    /// Protobuf `FieldMask` JSON string.
541    #[serde(rename = "fieldMask", default, skip_serializing_if = "Option::is_none")]
542    pub field_mask: Option<String>,
543    #[serde(
544        rename = "bidiGenerateContentSetup",
545        default,
546        skip_serializing_if = "Option::is_none"
547    )]
548    pub bidi_generate_content_setup: Option<GeminiBidiGenerateContentSetup>,
549    #[serde(default, skip_serializing_if = "Option::is_none")]
550    pub uses: Option<i32>,
551}