gh_models 0.2.0

A Rust client for GitHub-hosted AI models, compatible with the models.github.ai chat completion API.
Documentation
//! # client
//!
//! This module defines the `GHModels` client for interacting with the GitHub Models API.
//!
//! The client handles authentication using a GitHub personal access token (PAT) and provides
//! a method for sending chat completion requests to hosted models such as `openai/gpt-4o`.
//!
//! It is designed to be similar in usage to OpenAI's Python client, but tailored for Rust.
//!
//! ## Example
//!
//! ```rust
//! use gh_models::{GHModels, types::ChatMessage};
//! use std::env;
//!
//! #[tokio::main]
//! async fn main() {
//!     let token = env::var("GITHUB_TOKEN").expect("Missing GITHUB_TOKEN");
//!     let client = GHModels::new(token);
//!
//!     let messages = vec![
//!         ChatMessage { role: "system".into(), content: "You are a helpful assistant.".into() },
//!         ChatMessage { role: "user".into(), content: "What is the capital of France?".into() },
//!     ];
//!
//!     let response = client.chat_completion("openai/gpt-4o", messages, 1.0, 4096, 1.0).await.unwrap();
//!     println!("{}", response.choices[0].message.content);
//! }
//! ```

use reqwest::Client;
use serde_json::json;
use crate::types::{ChatMessage, ChatResponse};

/// A client for interacting with GitHub-hosted AI models.
///
/// This struct handles authentication and sending chat completion requests
/// to the GitHub Models API.
pub struct GHModels {
    /// The underlying HTTP client used to send requests.
    client: Client,

    /// GitHub personal access token used for authentication.
    token: String,

    /// Base URL for the GitHub Models chat completion endpoint.
    base_url: String,
}

impl GHModels {
    /// Creates a new `GHModels` client using the provided GitHub token.
    ///
    /// The token must have the `Models` permission enabled.
    pub fn new(token: String) -> Self {
        GHModels {
            client: Client::new(),
            token,
            base_url: "https://models.github.ai/inference/chat/completions".to_string(),
        }
    }

    /// Sends a chat completion request to the specified model.
    ///
    /// # Parameters
    /// - `model`: The model name (e.g., `"openai/gpt-4o"`).
    /// - `messages`: A sequence of chat messages forming the conversation.
    /// - `temperature`: Sampling temperature (higher = more random).
    /// - `max_tokens`: Maximum number of tokens to generate.
    /// - `top_p`: Nucleus sampling parameter.
    ///
    /// # Returns
    /// A `ChatResponse` containing the model's reply.
    pub async fn chat_completion(
        &self,
        model: &str,
        messages: &[ChatMessage],
        temperature: f32,
        max_tokens: usize,
        top_p: f32,
    ) -> Result<ChatResponse, reqwest::Error> {
        let body = json!({
            "model": model,
            "messages": messages,
            "temperature": temperature,
            "max_tokens": max_tokens,
            "top_p": top_p
        });

        let res = self.client
            .post(&self.base_url)
            .bearer_auth(&self.token)
            .json(&body)
            .send()
            .await?;

        let parsed = res.json::<ChatResponse>().await?;
        Ok(parsed)
    }
}