gemini_live_api/client/
builder.rs1use super::handle::GeminiLiveClient;
2use super::handlers::{
3 EventHandlerSimple, Handlers, ServerContentContext, ToolHandler, UsageMetadataContext,
4};
5use crate::error::GeminiError;
6use crate::types::*;
7use std::sync::Arc;
8use tokio::sync::{mpsc, oneshot};
9
10pub struct GeminiLiveClientBuilder<S: Clone + Send + Sync + 'static> {
11 pub(crate) api_key: String,
12 pub(crate) initial_setup: BidiGenerateContentSetup,
13 pub(crate) handlers: Handlers<S>,
14 pub(crate) state: S,
15}
16
17impl<S: Clone + Send + Sync + 'static + Default> GeminiLiveClientBuilder<S> {
18 pub fn new(api_key: String, model: String) -> Self {
19 Self::new_with_state(api_key, model, S::default())
20 }
21}
22
23impl<S: Clone + Send + Sync + 'static> GeminiLiveClientBuilder<S> {
24 pub fn new_with_state(api_key: String, model: String, state: S) -> Self {
25 Self {
26 api_key,
27 initial_setup: BidiGenerateContentSetup {
28 model,
29 ..Default::default()
30 },
31 handlers: Handlers::default(),
32 state,
33 }
34 }
35
36 pub fn generation_config(mut self, config: GenerationConfig) -> Self {
37 self.initial_setup.generation_config = Some(config);
38 self
39 }
40
41 pub fn system_instruction(mut self, instruction: Content) -> Self {
42 self.initial_setup.system_instruction = Some(instruction);
43 self
44 }
45
46 #[doc(hidden)]
47 pub fn add_tool_declaration(mut self, declaration: FunctionDeclaration) -> Self {
48 let tools_vec = self.initial_setup.tools.get_or_insert_with(Vec::new);
49 if let Some(tool_struct) = tools_vec.first_mut() {
50 tool_struct.function_declarations.push(declaration);
51 } else {
52 tools_vec.push(Tool {
53 function_declarations: vec![declaration],
54 });
55 }
56 self
57 }
58
59 #[doc(hidden)]
60 pub fn on_tool_call<F>(mut self, tool_name: impl Into<String>, handler: F) -> Self
61 where
62 F: ToolHandler<S> + 'static,
63 {
64 self.handlers
65 .tool_handlers
66 .insert(tool_name.into(), Arc::new(handler));
67 self
68 }
69
70 pub fn on_server_content(
71 mut self,
72 handler: impl EventHandlerSimple<ServerContentContext, S> + 'static,
73 ) -> Self {
74 self.handlers.on_server_content = Some(Arc::new(handler));
75 self
76 }
77
78 pub fn on_usage_metadata(
79 mut self,
80 handler: impl EventHandlerSimple<UsageMetadataContext, S> + 'static,
81 ) -> Self {
82 self.handlers.on_usage_metadata = Some(Arc::new(handler));
83 self
84 }
85
86 pub fn realtime_input_config(mut self, config: RealtimeInputConfig) -> Self {
87 self.initial_setup.realtime_input_config = Some(config);
88 self
89 }
90
91 pub fn output_audio_transcription(mut self, config: AudioTranscriptionConfig) -> Self {
92 self.initial_setup.output_audio_transcription = Some(config);
93 self
94 }
95
96 pub async fn connect(self) -> Result<GeminiLiveClient<S>, GeminiError> {
97 let (shutdown_tx, shutdown_rx) = oneshot::channel();
98 let (outgoing_sender, outgoing_receiver) = mpsc::channel(100);
99
100 let state_arc = Arc::new(self.state);
101 let handlers_arc = Arc::new(self.handlers);
102
103 super::connection::spawn_processing_task(
104 self.api_key.clone(),
105 self.initial_setup,
106 handlers_arc,
107 state_arc.clone(),
108 shutdown_rx,
109 outgoing_receiver,
110 );
111 tokio::time::sleep(std::time::Duration::from_millis(50)).await;
112 Ok(GeminiLiveClient {
113 shutdown_tx: Some(shutdown_tx),
114 outgoing_sender: Some(outgoing_sender),
115 state: state_arc,
116 })
117 }
118}