Skip to main content

gemini_rust/interactions/
mod.rs

1//! Interactions API — the modern interface for Gemini models and agents.
2//!
3//! The Interactions API is the simplest and best way to use Gemini models and agents.
4//! It provides a unified interface for all use cases, including single-turn text generation,
5//! multimodal understanding, structured output, tool orchestration, and agentic workflows.
6//!
7//! # Key Advantages
8//!
9//! - Unified interface for models and agents
10//! - Server-side state management (`previous_interaction_id`)
11//! - Observable execution steps
12//! - Background execution
13//! - Higher cache hit rates
14//!
15//! # Quick Start
16//!
17//! ```no_run
18//! # use gemini_rust::prelude::*;
19//! # async fn example(gemini: &Gemini) -> Result<(), Box<dyn std::error::Error>> {
20//! let interaction = gemini.create_interaction()
21//!     .with_model("gemini-2.5-flash")
22//!     .with_text("Hello, world!")
23//!     .execute()
24//!     .await?;
25//!
26//! println!("{}", interaction.output_text());
27//! # Ok(())
28//! # }
29//! ```
30
31pub mod builder;
32pub mod handle;
33pub mod model;
34pub mod stream;
35
36pub use builder::InteractionBuilder;
37pub use handle::InteractionHandle;
38pub use model::*;
39pub use stream::{InteractionEvent, InteractionStream, StepDeltaData};
40
41/// Convenience methods on [`Interaction`].
42impl Interaction {
43    /// Get the concatenated final text output.
44    ///
45    /// Extracts text from the last `model_output` step's text content items.
46    pub fn output_text(&self) -> String {
47        self.steps
48            .iter()
49            .rev()
50            .find(|s| matches!(s, Step::ModelOutput { .. }))
51            .and_then(|s| {
52                if let Step::ModelOutput { content, .. } = s {
53                    Some(
54                        content
55                            .iter()
56                            .filter_map(|c| {
57                                if let InteractionContent::Text { text, .. } = c {
58                                    Some(text.clone())
59                                } else {
60                                    None
61                                }
62                            })
63                            .collect::<Vec<_>>()
64                            .join(""),
65                    )
66                } else {
67                    None
68                }
69            })
70            .unwrap_or_default()
71    }
72
73    /// Get all function_call steps.
74    pub fn function_calls(&self) -> Vec<&Step> {
75        self.steps
76            .iter()
77            .filter(|s| matches!(s, Step::FunctionCall { .. }))
78            .collect()
79    }
80
81    /// Get all model_output steps.
82    pub fn model_outputs(&self) -> Vec<&Step> {
83        self.steps
84            .iter()
85            .filter(|s| matches!(s, Step::ModelOutput { .. }))
86            .collect()
87    }
88
89    /// Get all thought steps.
90    pub fn thoughts(&self) -> Vec<&Step> {
91        self.steps
92            .iter()
93            .filter(|s| matches!(s, Step::Thought { .. }))
94            .collect()
95    }
96
97    /// Whether the interaction requires user action (e.g., function calling).
98    pub fn requires_action(&self) -> bool {
99        self.status == InteractionStatus::RequiresAction
100    }
101
102    /// Whether the interaction is completed.
103    pub fn is_completed(&self) -> bool {
104        self.status == InteractionStatus::Completed
105    }
106
107    /// Get the output image (last model-generated image).
108    pub fn output_image(&self) -> Option<&InteractionContent> {
109        self.steps.iter().rev().find_map(|s| {
110            if let Step::ModelOutput { content, .. } = s {
111                content
112                    .iter()
113                    .find(|c| matches!(c, InteractionContent::Image { .. }))
114            } else {
115                None
116            }
117        })
118    }
119
120    /// Get the output audio (last model-generated audio).
121    pub fn output_audio(&self) -> Option<&InteractionContent> {
122        self.steps.iter().rev().find_map(|s| {
123            if let Step::ModelOutput { content, .. } = s {
124                content
125                    .iter()
126                    .find(|c| matches!(c, InteractionContent::Audio { .. }))
127            } else {
128                None
129            }
130        })
131    }
132
133    /// Get the output video (last model-generated video).
134    pub fn output_video(&self) -> Option<&InteractionContent> {
135        self.steps.iter().rev().find_map(|s| {
136            if let Step::ModelOutput { content, .. } = s {
137                content
138                    .iter()
139                    .find(|c| matches!(c, InteractionContent::Video { .. }))
140            } else {
141                None
142            }
143        })
144    }
145
146    /// Get the output document (last model-generated document).
147    pub fn output_document(&self) -> Option<&InteractionContent> {
148        self.steps.iter().rev().find_map(|s| {
149            if let Step::ModelOutput { content, .. } = s {
150                content
151                    .iter()
152                    .find(|c| matches!(c, InteractionContent::Document { .. }))
153            } else {
154                None
155            }
156        })
157    }
158
159    /// Get all citation annotations from model outputs.
160    pub fn citations(&self) -> Vec<&Annotation> {
161        self.steps
162            .iter()
163            .filter_map(|s| {
164                if let Step::ModelOutput { content, .. } = s {
165                    Some(content.iter().flat_map(|c| {
166                        if let InteractionContent::Text { annotations, .. } = c {
167                            annotations.iter().collect::<Vec<_>>()
168                        } else {
169                            vec![]
170                        }
171                    }))
172                } else {
173                    None
174                }
175            })
176            .flatten()
177            .collect()
178    }
179
180    /// Get the total token count.
181    pub fn total_tokens(&self) -> Option<i64> {
182        self.usage.as_ref()?.total_tokens
183    }
184
185    /// Get the interaction ID.
186    pub fn id(&self) -> Option<&str> {
187        self.id.as_deref()
188    }
189}