gmini 0.1.1

A modular and asynchronous Rust SDK for interacting with the Google Gemini API.
use crate::{api, config::*, models::*, utils};
use reqwest::Client;
use std::fs::File;
use std::io::Write;

pub struct Gemini {
    client: Client,
    env_vars: EnvVars,
    access_token: String,
}

#[async_trait::async_trait]
pub trait Think {
    async fn new() -> Result<Self, Box<dyn std::error::Error>>
    where
        Self: Sized;
    async fn think(&self, prompt: &str) -> Result<String, Box<dyn std::error::Error>>;
}

#[async_trait::async_trait]
impl Think for Gemini {
    async fn new() -> Result<Self, Box<dyn std::error::Error>> {
        let env_vars = load_env_vars()?;
        let access_token = get_access_token().await?;
        let client = Client::new();

        Ok(Self {
            client,
            env_vars,
            access_token,
        })
    }

    async fn think(&self, prompt: &str) -> Result<String, Box<dyn std::error::Error>> {
        // Create request with the provided prompt
        let mut request = utils::create_request();
        request.contents[0].parts[0].text = prompt.to_string();

        // Convert request to JSON
        let request_json_content = serde_json::to_string_pretty(&request)?;

        // Save request to file (optional, for debugging)
        let mut file = File::create("request.json")?;
        file.write_all(request_json_content.as_bytes())?;
        //dbg!("request.json file created");

        // Build API URL
        let api_url = build_api_url(&self.env_vars);
        //dbg!("API URL: {}", &api_url);

        // Make API request
        let response = api::make_api_request(
            &self.client,
            &api_url,
            &self.access_token,
            &request_json_content,
        )
        .await?;
        //dbg!("HTTP request sent.");

        // Process response
        //dbg!("Response Status: {}", &response.status());
        if response.status().is_success() {
            let response_body = response.text().await?;
            //dbg!("Raw response: {}", &response_body);

            // Parse response
            let responses: Vec<StreamResponse> = serde_json::from_str(&response_body)?;

            // Process chunks
            let final_text = api::process_response_chunks(responses);

            // Parse and format final response
            api::parse_final_response(&final_text)
        } else {
            let error_text = response.text().await?;
            Err(format!("Error Response: {}", error_text).into())
        }
    }
}