gitory-cli 0.1.0

Build a story for your project based on your git history
use anyhow::Result;

use crate::git::GitCommitDiff;
use crate::llms::gemini::models::{
    Content, GeminiAPIConfig, GenerateContentRequest, GenerateContentResponse, GenerationConfig,
    Part,
};

pub async fn generate_text_from_text(
    commit_diff: &GitCommitDiff,
    api_config: &GeminiAPIConfig,
    // base_prompt: String,
    generation_config: GenerationConfig,
) -> Result<Vec<String>> {
    let endpoint_url = format!(
        "https://{api_endpoint}/v1beta/models/{model_name}:generateContent?key={api_key}",
        api_endpoint = api_config.endpoint,
        model_name = api_config.model_name,
        api_key = api_config.key
    );

    let commit_diff_instance = commit_diff.clone();

    let base_prompt = Part::Text("You are a technical story writer for a software team. Your job is to generate a summary that tells a story of the development progress till now.\nBased on the following context about the 'file_name', 'file_status', 'old_code_block', and 'new_code_block', generate a short, technical and to-the-point summary of the changes made.".to_string());

    let context_prompt = commit_diff_instance.code_diffs.into_iter().map(|file_diff| {
        Part::Text(format!("\n\n----- Context -----\nfile_name: {file_name}\nfile_status: {file_status:?}\nold_code_block: {old_code_block}\nnew_code_block: {new_code_block}\n------------\n", file_name=file_diff.file_name, file_status=file_diff.status, old_code_block=file_diff.old_code, new_code_block=file_diff.new_code))
    }).collect::<Vec<Part>>();

    let parts = vec![base_prompt]
        .into_iter()
        .chain(context_prompt)
        .collect::<Vec<Part>>();

    let payload = GenerateContentRequest {
        contents: vec![Content {
            role: "user".to_string(),
            parts: parts,
        }],
        generation_config: Some(generation_config),
        tools: None,
    };

    let resp = reqwest::Client::new()
        .post(&endpoint_url)
        .json(&payload)
        .send()
        .await?;

    let response = resp.json::<GenerateContentResponse>().await?;
    let mut content: Vec<String> = Vec::new();
    response.candidates.iter().for_each(|candidate| {
        candidate.content.parts.iter().for_each(|part| {
            if let Part::Text(text) = part {
                content.push(text.to_string());
            }
        });
    });

    Ok(content)
}