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)]
33#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
34pub enum LiveInt64 {
35    String(#[serde(deserialize_with = "decimal_i64")] String),
36    Number(i64),
37}
38fn decimal_i64<'de, D: serde::Deserializer<'de>>(d: D) -> Result<String, D::Error> {
39    let v = String::deserialize(d)?;
40    v.parse::<i64>().map_err(serde::de::Error::custom)?;
41    Ok(v)
42}
43
44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
45#[serde(rename_all = "camelCase")]
46#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
47#[derive(gproxy_protocol_macros::DeclaredFields)]
48#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
49pub struct LiveClientMessage {
50    #[serde(default, skip_serializing_if = "Option::is_none")]
51    pub setup: Option<BidiGenerateContentSetup>,
52    #[serde(alias = "client_content")]
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    pub client_content: Option<BidiGenerateContentClientContent>,
55    #[serde(alias = "realtime_input")]
56    #[serde(default, skip_serializing_if = "Option::is_none")]
57    pub realtime_input: Option<BidiGenerateContentRealtimeInput>,
58    #[serde(alias = "tool_response")]
59    #[serde(default, skip_serializing_if = "Option::is_none")]
60    pub tool_response: Option<BidiGenerateContentToolResponse>,
61    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
62    pub rest: Rest,
63}
64
65#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
66#[serde(rename_all = "camelCase")]
67#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
68#[derive(gproxy_protocol_macros::DeclaredFields)]
69#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
70pub struct LiveServerMessage {
71    #[serde(alias = "setup_complete")]
72    #[serde(default, skip_serializing_if = "Option::is_none")]
73    pub setup_complete: Option<BidiGenerateContentSetupComplete>,
74    #[serde(alias = "server_content")]
75    #[serde(default, skip_serializing_if = "Option::is_none")]
76    pub server_content: Option<BidiGenerateContentServerContent>,
77    #[serde(alias = "tool_call")]
78    #[serde(default, skip_serializing_if = "Option::is_none")]
79    pub tool_call: Option<BidiGenerateContentToolCall>,
80    #[serde(alias = "tool_call_cancellation")]
81    #[serde(default, skip_serializing_if = "Option::is_none")]
82    pub tool_call_cancellation: Option<BidiGenerateContentToolCallCancellation>,
83    #[serde(alias = "go_away")]
84    #[serde(default, skip_serializing_if = "Option::is_none")]
85    pub go_away: Option<GoAway>,
86    #[serde(alias = "session_resumption_update")]
87    #[serde(default, skip_serializing_if = "Option::is_none")]
88    pub session_resumption_update: Option<SessionResumptionUpdate>,
89    #[serde(alias = "usage_metadata")]
90    #[serde(default, skip_serializing_if = "Option::is_none")]
91    pub usage_metadata: Option<LiveUsageMetadata>,
92    #[serde(alias = "voice_activity_detection_signal")]
93    #[serde(default, skip_serializing_if = "Option::is_none")]
94    pub voice_activity_detection_signal: Option<VoiceActivityDetectionSignal>,
95    #[serde(alias = "voice_activity")]
96    #[serde(default, skip_serializing_if = "Option::is_none")]
97    pub voice_activity: Option<VoiceActivity>,
98    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
99    pub rest: Rest,
100}
101
102#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
103#[serde(rename_all = "camelCase")]
104#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
105#[derive(gproxy_protocol_macros::DeclaredFields)]
106#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
107pub struct BidiGenerateContentClientContent {
108    #[serde(default, skip_serializing_if = "Option::is_none")]
109    pub turns: Option<Vec<LiveContent>>,
110    #[serde(alias = "turn_complete")]
111    #[serde(default, skip_serializing_if = "Option::is_none")]
112    pub turn_complete: Option<bool>,
113    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
114    pub rest: Rest,
115}
116
117#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, gproxy_protocol_macros::WireBuilder)]
118#[serde(rename_all = "camelCase")]
119#[cfg_attr(not(feature = "exhaustive"), non_exhaustive)]
120#[derive(gproxy_protocol_macros::DeclaredFields)]
121#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
122pub struct BidiGenerateContentToolResponse {
123    #[serde(alias = "function_responses")]
124    #[serde(default, skip_serializing_if = "Option::is_none")]
125    pub function_responses: Option<Vec<FunctionResponse>>,
126    #[serde(default, flatten, skip_serializing_if = "serde_json::Map::is_empty")]
127    pub rest: Rest,
128}