cargo-c-build 0.4.0

An AI-enhanced git automation tool that builds and commits Rust projects with AI-generated commit messages for every build run.
// src/cm-client.rs
// This client is used to generate a commit message client with OpenAi.
// The X-Api-Key needs to be provided in a .env file.
use dotenv::dotenv;
use reqwest;
use reqwest::Client;
use serde::{Deserialize, Serialize};

pub struct ClientMessageClient {
    pub api_key: String,
    pub url: String,
    pub client: Client,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct OpenAiResponse {
    pub id: String,
    pub object: String,
    pub created: u64,
    pub model: String,
    pub choices: Vec<Choice>,
    pub usage: Usage,
    pub service_tier: String,
    pub system_fingerprint: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Choice {
    pub index: u32,
    pub message: Message,
    pub logprobs: Option<serde_json::Value>,
    pub finish_reason: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Message {
    pub role: String,
    pub content: String,
    pub refusal: Option<serde_json::Value>,
    pub annotations: Vec<serde_json::Value>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Usage {
    pub prompt_tokens: u32,
    pub completion_tokens: u32,
    pub total_tokens: u32,
    pub prompt_tokens_details: TokenDetails,
    pub completion_tokens_details: CompletionTokenDetails,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TokenDetails {
    pub cached_tokens: u32,
    pub audio_tokens: u32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct CompletionTokenDetails {
    pub reasoning_tokens: u32,
    pub audio_tokens: u32,
    pub accepted_prediction_tokens: u32,
    pub rejected_prediction_tokens: u32,
}

impl ClientMessageClient {
    pub fn create_client() -> Self {
        dotenv().ok();
        ClientMessageClient { 
            api_key: std::env::var("API_KEY").expect("Api Key Must Exist For Commit Message Generation."),
            url: std::env::var("API_URL").expect("Api URL Must Exist For Commit Message Generation."),
            client: reqwest::Client::new(),
        }
    }

    pub async fn create_commit_message(&mut self, input: String) -> Result<String, Box<dyn std::error::Error>> {
        let body = serde_json::json!({
            "model": "gpt-4.1-nano", // Add to .Env Later On.
            "messages": [
                { "role": "system", "content": 
                "You are a Git Assistant. 
                Your job is to generate git commit messages to be for auto saving functionality. 
                Your info with be based of the git diff which will be provided.
                Please provide as much detail as possible and if you recieve none. Response with Error." },
                { "role": "user", "content": input }
            ]
        });


        let response = self.client
            .post(self.url.clone())
            .header("Authorization", format!("Bearer {}", self.api_key))
            .header("Content-Type", "application/json")
            .json(&body)
            .send()
            .await?;

        let openai_response: OpenAiResponse = response.json().await?;

        if let Some(choice) = openai_response.choices.first() {
            Ok(choice.message.content.clone())
        } else {
            Err("No choices returned from OpenAI.".into())
        }
    }
}