mullama 0.3.0

Comprehensive Rust bindings for llama.cpp with memory-safe API and advanced features
use axum::{
    http::StatusCode,
    response::{IntoResponse, Response},
    Json,
};

use super::types::{ErrorDetail, ErrorResponse};
use crate::daemon::protocol::ErrorCode;

pub struct ApiError {
    pub(super) message: String,
    pub(super) status: StatusCode,
}

impl ApiError {
    pub(super) fn new(message: impl Into<String>) -> Self {
        Self {
            message: message.into(),
            status: StatusCode::INTERNAL_SERVER_ERROR,
        }
    }

    pub(super) fn bad_request(message: impl Into<String>) -> Self {
        Self {
            message: message.into(),
            status: StatusCode::BAD_REQUEST,
        }
    }

    pub(super) fn from_protocol_error(code: ErrorCode, message: impl Into<String>) -> Self {
        let message = message.into();
        let status = match code {
            ErrorCode::ModelNotFound => StatusCode::NOT_FOUND,
            ErrorCode::InvalidRequest => StatusCode::BAD_REQUEST,
            ErrorCode::RateLimited => StatusCode::TOO_MANY_REQUESTS,
            ErrorCode::Timeout => StatusCode::GATEWAY_TIMEOUT,
            ErrorCode::Cancelled => StatusCode::CONFLICT,
            ErrorCode::ModelLoadFailed
            | ErrorCode::NoDefaultModel
            | ErrorCode::GenerationFailed
            | ErrorCode::Internal => StatusCode::INTERNAL_SERVER_ERROR,
        };
        Self { message, status }
    }

    pub(super) fn not_found(model: &str) -> Self {
        Self {
            message: format!("Model '{}' not found", model),
            status: StatusCode::NOT_FOUND,
        }
    }
}

impl IntoResponse for ApiError {
    fn into_response(self) -> Response {
        let body = Json(ErrorResponse {
            error: ErrorDetail {
                message: self.message,
                error_type: "api_error".to_string(),
                code: None,
            },
        });
        (self.status, body).into_response()
    }
}