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::transport::Transport;
8use chat_core::types::messages::Messages;
9use chat_core::types::options::ChatOptions;
10use chat_core::types::provider_meta::ProviderMeta;
11use chat_core::types::response::ChatResponse;
12use chat_core::types::tools::ToolDeclarations;
13
14#[async_trait::async_trait]
15impl<T: Transport> CompletionProvider for GeminiClient<T> {
16    async fn complete(
17        &mut self,
18        messages: &mut Messages,
19        tool_declarations: Option<&dyn ToolDeclarations>,
20        options: Option<&ChatOptions>,
21        structured_output: Option<&schemars::Schema>,
22    ) -> Result<ChatResponse, ChatFailure> {
23        let path = format!(
24            "{}/models/{}:generateContent",
25            self.base_path, self.model_name
26        );
27
28        let request_body = GeminiRequest::from_core(
29            messages,
30            tool_declarations,
31            Some(self.native_tools.as_slice()),
32            self.function_config.as_ref(),
33            options,
34            structured_output,
35            self.include_thoughts,
36            self.response_modalities.as_deref(),
37        )
38        .map_err(ChatFailure::from_err)?;
39
40        let body = serde_json::to_vec(&request_body)
41            .map_err(|e| ChatFailure::from_err(ChatError::InvalidResponse(e.to_string())))?;
42
43        let req = chat_core::transport::Request {
44            scheme: self.scheme.clone(),
45            host: self.host.clone(),
46            path,
47            headers: vec![
48                ("x-goog-api-key".into(), self.api_key.clone()),
49                ("Content-Type".into(), "application/json".into()),
50            ],
51            body,
52        };
53
54        let res = self
55            .transport
56            .send(req)
57            .await
58            .map_err(ChatFailure::from_err)?;
59
60        let res = handle_gemini_error(res)?;
61
62        let gemini_data: GeminiCompletionResponse = serde_json::from_slice(&res.body)
63            .map_err(|e| ChatFailure::from_err(ChatError::InvalidResponse(e.to_string())))?;
64
65        gemini_data
66            .into_core_chat_response()
67            .map_err(ChatFailure::from_err)
68    }
69
70    fn metadata(&self) -> Option<&ProviderMeta> {
71        Some(&self.meta)
72    }
73}