Skip to main content

chat_gemini/api/
completion.rs

1use crate::api::types::error::handle_gemini_error;
2use crate::api::types::request::GeminiRequest;
3use crate::api::types::response::GeminiCompletionResponse;
4use crate::client::GeminiClient;
5use chat_core::error::{ChatError, ChatFailure};
6use chat_core::traits::CompletionProvider;
7use chat_core::types::provider_meta::ProviderMeta;
8use chat_core::types::messages::Messages;
9use chat_core::types::options::ChatOptions;
10use chat_core::types::response::ChatResponse;
11use tools_rs::ToolCollection;
12
13#[async_trait::async_trait]
14impl CompletionProvider for GeminiClient {
15    async fn complete(
16        &mut self,
17        messages: &mut Messages,
18        tools: Option<&ToolCollection>,
19        options: Option<&ChatOptions>,
20        structured_output: Option<&schemars::Schema>,
21    ) -> Result<ChatResponse, ChatFailure> {
22        let url = format!(
23            "https://generativelanguage.googleapis.com/v1beta/models/{}:generateContent",
24            self.model_name
25        );
26
27        let request_body = GeminiRequest::from_core(
28            messages,
29            tools,
30            Some(self.native_tools.as_slice()),
31            self.function_config.as_ref(),
32            options,
33            structured_output,
34            self.include_thoughts,
35        )
36        .map_err(ChatFailure::from_err)?;
37
38        let res = self
39            .http_client
40            .post(&url)
41            .header("x-goog-api-key", &self.api_key)
42            .json(&request_body)
43            .send()
44            .await
45            .map_err(|e| ChatFailure::from_err(ChatError::Network(e.to_string())))?;
46
47        let res = handle_gemini_error(res).await?;
48
49        let gemini_data: GeminiCompletionResponse = res
50            .json()
51            .await
52            .map_err(|e| ChatFailure::from_err(ChatError::InvalidResponse(e.to_string())))?;
53
54        gemini_data
55            .into_core_chat_response()
56            .map_err(ChatFailure::from_err)
57    }
58
59    fn metadata(&self) -> Option<&ProviderMeta> {
60        Some(&self.meta)
61    }
62}