Skip to main content

gproxy_protocol/wire/gemini/live/
mod.rs

1//! Gemini Developer Live BidiGenerateContent wire models, checked 2026-09-13.
2//! https://ai.google.dev/api/live
3//! googleapis/googleapis generative_service.proto commit
4//! efc9e8f560a5f1b9b08b62823bfa7955c656cb74;
5//! googleapis/python-genai types.py and _live_converters.py commit
6//! 9052efddccae9f91e699d9b76e0d5a3e032637f5.
7//! The current reference/SDK include fields absent from the public proto; mldev
8//! converter mappings determine Developer API wire placement. Vertex-only options
9//! are not added. Optional ProtoJSON null is treated as unset; explicit false/0
10//! remains present. Sibling oneof keys are retained without engine validation.
11use crate::Rest;
12use crate::gemini::FunctionResponse;
13use crate::{WireRequest, WireResponse};
14use serde::{Deserialize, Serialize};
15mod content;
16pub use content::*;
17mod generation;
18mod realtime;
19mod server;
20mod setup;
21pub use generation::*;
22pub use realtime::*;
23pub use server::*;
24pub use setup::*;
25/// HTTP handshake metadata; the established link is crate::WebSocket.
26pub type LiveRequest = WireRequest<()>;
27pub type LiveResponse = WireResponse<()>;
28/// ProtoJSON int64 fields allow decimal strings and numeric JSON inputs.
29#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30#[serde(untagged)]
31#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
32#[derive(gproxy_protocol_macros::DeclaredFields)]
33pub enum LiveInt64 {
34    String(#[serde(deserialize_with = "decimal_i64")] String),
35    Number(i64),
36}
37fn decimal_i64<'de, D: serde::Deserializer<'de>>(d: D) -> Result<String, D::Error> {
38    let v = String::deserialize(d)?;
39    v.parse::<i64>().map_err(serde::de::Error::custom)?;
40    Ok(v)
41}
42
43#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
44#[serde(rename_all = "camelCase")]
45#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
46#[derive(gproxy_protocol_macros::DeclaredFields)]
47pub struct LiveClientMessage {
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    pub setup: Option<BidiGenerateContentSetup>,
50    #[serde(alias = "client_content")]
51    #[serde(default, skip_serializing_if = "Option::is_none")]
52    pub client_content: Option<BidiGenerateContentClientContent>,
53    #[serde(alias = "realtime_input")]
54    #[serde(default, skip_serializing_if = "Option::is_none")]
55    pub realtime_input: Option<BidiGenerateContentRealtimeInput>,
56    #[serde(alias = "tool_response")]
57    #[serde(default, skip_serializing_if = "Option::is_none")]
58    pub tool_response: Option<BidiGenerateContentToolResponse>,
59    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
60    pub rest: Rest,
61}
62
63#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
64#[serde(rename_all = "camelCase")]
65#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
66#[derive(gproxy_protocol_macros::DeclaredFields)]
67pub struct LiveServerMessage {
68    #[serde(alias = "setup_complete")]
69    #[serde(default, skip_serializing_if = "Option::is_none")]
70    pub setup_complete: Option<BidiGenerateContentSetupComplete>,
71    #[serde(alias = "server_content")]
72    #[serde(default, skip_serializing_if = "Option::is_none")]
73    pub server_content: Option<BidiGenerateContentServerContent>,
74    #[serde(alias = "tool_call")]
75    #[serde(default, skip_serializing_if = "Option::is_none")]
76    pub tool_call: Option<BidiGenerateContentToolCall>,
77    #[serde(alias = "tool_call_cancellation")]
78    #[serde(default, skip_serializing_if = "Option::is_none")]
79    pub tool_call_cancellation: Option<BidiGenerateContentToolCallCancellation>,
80    #[serde(alias = "go_away")]
81    #[serde(default, skip_serializing_if = "Option::is_none")]
82    pub go_away: Option<GoAway>,
83    #[serde(alias = "session_resumption_update")]
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    pub session_resumption_update: Option<SessionResumptionUpdate>,
86    #[serde(alias = "usage_metadata")]
87    #[serde(default, skip_serializing_if = "Option::is_none")]
88    pub usage_metadata: Option<LiveUsageMetadata>,
89    #[serde(alias = "voice_activity_detection_signal")]
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub voice_activity_detection_signal: Option<VoiceActivityDetectionSignal>,
92    #[serde(alias = "voice_activity")]
93    #[serde(default, skip_serializing_if = "Option::is_none")]
94    pub voice_activity: Option<VoiceActivity>,
95    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
96    pub rest: Rest,
97}
98
99#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
100#[serde(rename_all = "camelCase")]
101#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
102#[derive(gproxy_protocol_macros::DeclaredFields)]
103pub struct BidiGenerateContentClientContent {
104    #[serde(default, skip_serializing_if = "Option::is_none")]
105    pub turns: Option<Vec<LiveContent>>,
106    #[serde(alias = "turn_complete")]
107    #[serde(default, skip_serializing_if = "Option::is_none")]
108    pub turn_complete: Option<bool>,
109    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
110    pub rest: Rest,
111}
112
113#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
114#[serde(rename_all = "camelCase")]
115#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
116#[derive(gproxy_protocol_macros::DeclaredFields)]
117pub struct BidiGenerateContentToolResponse {
118    #[serde(alias = "function_responses")]
119    #[serde(default, skip_serializing_if = "Option::is_none")]
120    pub function_responses: Option<Vec<FunctionResponse>>,
121    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
122    pub rest: Rest,
123}