pub mod request {
use url::Url;
use crate::{
errors::OapiError,
rest::get::{Get, GetNoStream},
};
#[derive(Debug, Clone, Copy, Default)]
pub struct ListModelsRequest;
impl Get for ListModelsRequest {
fn build_url(&self, base_url: &str) -> Result<String, OapiError> {
let mut url =
Url::parse(base_url.trim_end_matches('/')).map_err(OapiError::UrlError)?;
url.path_segments_mut()
.map_err(|_| OapiError::UrlCannotBeBase(base_url.to_string()))?
.push("models");
Ok(url.to_string())
}
}
impl GetNoStream for ListModelsRequest {
type Response = super::response::ListModelsResponse;
}
}
pub mod response {
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub struct ListModelsResponse {
pub data: Vec<crate::models::Model>,
pub object: Option<String>,
}
crate::impl_from_str!(ListModelsResponse);
}
#[cfg(test)]
mod tests {
use super::request::ListModelsRequest;
use crate::rest::get::{Get, GetNoStream};
#[test]
fn test_build_url() {
let request = ListModelsRequest;
let url = request.build_url("https://api.openai.com/v1/").unwrap();
assert_eq!(url, "https://api.openai.com/v1/models");
}
#[test]
fn test_parse_list_response() {
let content = r#"{"object":"list","data":[{"id":"deepseek-v4-flash","object":"model","owned_by":"deepseek"},{"id":"deepseek-v4-pro","object":"model","owned_by":"deepseek"},{"id":"deepseek-v4-flash-vision-exp","object":"model","owned_by":"deepseek"}]}"#;
let response: super::response::ListModelsResponse = content.parse().unwrap();
assert_eq!(response.data.len(), 3);
assert_eq!(response.data[0].id, "deepseek-v4-flash");
assert_eq!(response.data[0].object, crate::models::ModelObject::Model);
assert_eq!(response.data[0].owned_by, "deepseek");
assert_eq!(response.data[0].created, None);
assert_eq!(response.data[0].shutdown_date, None);
assert_eq!(response.data[2].id, "deepseek-v4-flash-vision-exp");
}
#[tokio::test]
async fn test_query_deepseek_models() -> Result<(), anyhow::Error> {
let Some(api_key) = std::env::var("DEEPSEEK_API_KEY")
.ok()
.map(|key| key.trim().to_string())
.filter(|key| !key.is_empty())
else {
println!("Skipping: set DEEPSEEK_API_KEY to run this test");
return Ok(());
};
const DEEPSEEK_BASE_URL: &str = "https://api.deepseek.com";
let response = ListModelsRequest
.get_response(&crate::rest::default_client(), DEEPSEEK_BASE_URL, &api_key)
.await?;
assert!(!response.data.is_empty());
println!("DeepSeek models: {:?}", response.data);
Ok(())
}
}