Skip to main content

gemini_rust/interactions/
stream.rs

1use std::pin::Pin;
2
3use futures::Stream;
4use serde::Deserialize;
5
6use crate::client::Error;
7use crate::interactions::model::*;
8
9/// Interaction stream — yields `InteractionEvent` items.
10pub type InteractionStream = Pin<Box<dyn Stream<Item = Result<InteractionEvent, Error>> + Send>>;
11
12/// SSE event from the Interactions API stream.
13///
14/// Each event represents a lifecycle event in the interaction:
15/// interaction creation/completion, step start/delta/stop, status updates, or errors.
16#[derive(Debug, Clone, Deserialize)]
17#[serde(tag = "event_type")]
18pub enum InteractionEvent {
19    #[serde(rename = "interaction.created")]
20    InteractionCreated {
21        interaction: StreamInteraction,
22        #[serde(default)]
23        event_id: Option<String>,
24        #[serde(default)]
25        metadata: Option<StreamMetadata>,
26    },
27
28    #[serde(rename = "interaction.completed")]
29    InteractionCompleted {
30        interaction: StreamInteraction,
31        #[serde(default)]
32        event_id: Option<String>,
33        #[serde(default)]
34        metadata: Option<StreamMetadata>,
35    },
36
37    #[serde(rename = "interaction.status_update")]
38    InteractionStatusUpdate {
39        interaction_id: String,
40        status: InteractionStatus,
41        #[serde(default)]
42        event_id: Option<String>,
43        #[serde(default)]
44        metadata: Option<StreamMetadata>,
45    },
46
47    #[serde(rename = "error")]
48    Error {
49        error: InteractionError,
50        #[serde(default)]
51        event_id: Option<String>,
52        #[serde(default)]
53        metadata: Option<StreamMetadata>,
54    },
55
56    #[serde(rename = "step.start")]
57    StepStart {
58        index: usize,
59        step: Step,
60        #[serde(default)]
61        event_id: Option<String>,
62        #[serde(default)]
63        metadata: Option<StepDeltaMetadata>,
64    },
65
66    #[serde(rename = "step.delta")]
67    StepDelta {
68        index: usize,
69        delta: StepDeltaData,
70        #[serde(default)]
71        event_id: Option<String>,
72        #[serde(default)]
73        metadata: Option<StepDeltaMetadata>,
74    },
75
76    #[serde(rename = "step.stop")]
77    StepStop {
78        index: usize,
79        #[serde(default)]
80        usage: Option<InteractionUsage>,
81        #[serde(default)]
82        step_usage: Option<InteractionUsage>,
83        #[serde(default)]
84        event_id: Option<String>,
85        #[serde(default)]
86        metadata: Option<StreamMetadata>,
87    },
88}
89
90/// Partial Interaction resource in stream events (may omit some fields).
91#[derive(Debug, Clone, Default, Deserialize)]
92#[serde(rename_all = "snake_case")]
93pub struct StreamInteraction {
94    pub id: Option<String>,
95    pub object: Option<String>,
96    pub model: Option<String>,
97    pub agent: Option<String>,
98    #[serde(default)]
99    pub status: InteractionStatus,
100    pub created: Option<String>,
101    pub updated: Option<String>,
102    pub service_tier: Option<ServiceTier>,
103    pub usage: Option<InteractionUsage>,
104    #[serde(default)]
105    pub steps: Vec<Step>,
106}
107
108#[derive(Debug, Clone, Deserialize)]
109pub struct StreamMetadata {
110    #[serde(default)]
111    pub total_usage: Option<InteractionUsage>,
112}
113
114#[derive(Debug, Clone, Deserialize)]
115pub struct StepDeltaMetadata {
116    #[serde(default)]
117    pub total_usage: Option<InteractionUsage>,
118}
119
120/// Step delta data — type-tagged polymorphic.
121///
122/// Represents incremental updates to a step during streaming.
123#[derive(Debug, Clone, Deserialize, PartialEq)]
124#[serde(tag = "type", rename_all = "snake_case")]
125pub enum StepDeltaData {
126    Text {
127        text: String,
128    },
129
130    Image {
131        #[serde(default)]
132        data: Option<String>,
133        #[serde(default)]
134        uri: Option<String>,
135        #[serde(default)]
136        mime_type: Option<ImageMimeType>,
137        #[serde(default)]
138        resolution: Option<MediaResolution>,
139    },
140
141    Audio {
142        #[serde(default)]
143        data: Option<String>,
144        #[serde(default)]
145        uri: Option<String>,
146        #[serde(default)]
147        mime_type: Option<AudioMimeType>,
148        #[serde(default)]
149        sample_rate: Option<i32>,
150        #[serde(default)]
151        channels: Option<i32>,
152    },
153
154    Document {
155        #[serde(default)]
156        data: Option<String>,
157        #[serde(default)]
158        uri: Option<String>,
159        #[serde(default)]
160        mime_type: Option<DocumentMimeType>,
161    },
162
163    Video {
164        #[serde(default)]
165        data: Option<String>,
166        #[serde(default)]
167        uri: Option<String>,
168        #[serde(default)]
169        mime_type: Option<VideoMimeType>,
170        #[serde(default)]
171        resolution: Option<MediaResolution>,
172    },
173
174    ThoughtSummary {
175        #[serde(default)]
176        content: Option<InteractionContent>,
177    },
178
179    ThoughtSignature {
180        #[serde(default)]
181        signature: Option<String>,
182    },
183
184    TextAnnotationDelta {
185        annotations: Vec<Annotation>,
186    },
187
188    ArgumentsDelta {
189        #[serde(default)]
190        arguments: Option<String>,
191    },
192
193    CodeExecutionCall {
194        arguments: CodeExecutionCallArguments,
195    },
196
197    CodeExecutionResult {
198        result: String,
199        #[serde(default)]
200        is_error: Option<bool>,
201    },
202
203    UrlContextCall {
204        arguments: UrlContextCallArguments,
205    },
206
207    UrlContextResult {
208        result: UrlContextResultData,
209        #[serde(default)]
210        is_error: Option<bool>,
211    },
212
213    GoogleSearchCall {
214        arguments: GoogleSearchCallArguments,
215    },
216
217    GoogleSearchResult {
218        result: GoogleSearchResultItem,
219        #[serde(default)]
220        is_error: Option<bool>,
221    },
222
223    GoogleMapsCall {
224        #[serde(default)]
225        arguments: Option<GoogleMapsCallArguments>,
226    },
227
228    GoogleMapsResult {
229        #[serde(default)]
230        result: Option<GoogleMapsResultItem>,
231    },
232
233    FileSearchCall,
234
235    FileSearchResult {
236        #[serde(default)]
237        result: Option<FileSearchResultData>,
238    },
239
240    McpServerToolCall {
241        name: String,
242        server_name: String,
243        arguments: serde_json::Value,
244    },
245
246    McpServerToolResult {
247        #[serde(default)]
248        name: Option<String>,
249        #[serde(default)]
250        server_name: Option<String>,
251        result: StepResult,
252    },
253
254    FunctionResult {
255        #[serde(default)]
256        name: Option<String>,
257        #[serde(default)]
258        is_error: Option<bool>,
259        call_id: String,
260        result: StepResult,
261    },
262}
263
264/// File search result data (for streaming deltas).
265#[derive(Debug, Clone, Default, Deserialize, PartialEq)]
266pub struct FileSearchResultData {
267    #[serde(default, skip_serializing_if = "Vec::is_empty")]
268    pub citations: Vec<Annotation>,
269}