ai-provider-sdk 0.0.2

Async-first Rust SDK for OpenAI APIs
Documentation
use crate::common::{path_capture_server, test_client};
use httpmock::prelude::*;
use ai_provider_sdk::Error;
use serde_json::json;

#[tokio::test]
async fn models_list_sends_expected_request() {
    let server = MockServer::start();
    let mock = server.mock(|when, then| {
        when.method(GET)
            .path("/models")
            .query_param("api-version", "test")
            .header("authorization", "Bearer sk-test");
        then.status(200).json_body(json!({
            "object": "list",
            "data": [
                {
                    "id": "gpt-4.1-mini",
                    "object": "model",
                    "created": 1710000000,
                    "owned_by": "openai"
                }
            ]
        }));
    });

    let client = test_client(&server);
    let models = client.models().list().await.unwrap();

    mock.assert();
    assert_eq!(models.object.as_deref(), Some("list"));
    assert_eq!(models.data[0].id, "gpt-4.1-mini");
}

#[tokio::test]
async fn models_retrieve_url_encodes_model_id() {
    let (base_url, path_seen) = path_capture_server(
        "HTTP/1.1 200 OK",
        "{\"id\":\"fine/tuned model\",\"object\":\"model\"}",
    )
    .await;

    let client = ai_provider_sdk::OpenAI::with_options(ai_provider_sdk::ClientOptions {
        api_key: Some("sk-test".to_string()),
        organization: Some("org_123".to_string()),
        project: Some("proj_123".to_string()),
        base_url: Some(base_url),
        default_headers: std::collections::HashMap::from([("x-custom".to_string(), "custom".to_string())]),
        default_query: std::collections::HashMap::from([("api-version".to_string(), "test".to_string())]),
        max_retries: 0,
        timeout: std::time::Duration::from_secs(5),
    })
    .unwrap();

    let model = client.models().retrieve("fine/tuned model").await.unwrap();

    assert_eq!(
        path_seen.lock().unwrap().as_deref(),
        Some("/models/fine%2Ftuned%20model?api-version=test")
    );
    assert_eq!(model.id, "fine/tuned model");
}

#[tokio::test]
async fn models_retrieve_rejects_empty_id() {
    let server = MockServer::start();
    let client = test_client(&server);

    let err = client.models().retrieve("").await.unwrap_err();
    match err {
        Error::Config(message) => assert!(message.contains("must not be empty")),
        other => panic!("unexpected error: {other:?}"),
    }
}