use std::sync::Arc;
use crate::config::{ClientBuilder, Config};
use crate::error::OpenAIError;
use crate::resources::assistants::{Assistants, Threads};
use crate::resources::audio::Audio;
use crate::resources::batches::Batches;
use crate::resources::chat::Chat;
use crate::resources::completions::Completions;
use crate::resources::embeddings::Embeddings;
use crate::resources::files::Files;
use crate::resources::fine_tuning::FineTuning;
use crate::resources::images::Images;
use crate::resources::models::Models;
use crate::resources::moderations::Moderations;
use crate::resources::uploads::Uploads;
use crate::resources::vector_stores::VectorStores;
#[derive(Clone)]
pub struct Client {
inner: Arc<Inner>,
}
struct Inner {
http: reqwest::Client,
config: Config,
}
impl std::fmt::Debug for Client {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Client")
.field("config", &self.inner.config)
.finish()
}
}
impl Client {
pub fn new() -> Result<Self, OpenAIError> {
Self::builder().build()
}
pub fn builder() -> ClientBuilder {
ClientBuilder::new()
}
pub(crate) fn from_config(config: Config) -> Result<Self, OpenAIError> {
let http = reqwest::Client::builder()
.read_timeout(config.timeout)
.connect_timeout(config.connect_timeout)
.build()
.map_err(|e| OpenAIError::Config(format!("failed to build HTTP client: {e}")))?;
Ok(Self {
inner: Arc::new(Inner { http, config }),
})
}
pub(crate) fn http(&self) -> &reqwest::Client {
&self.inner.http
}
pub(crate) fn config(&self) -> &Config {
&self.inner.config
}
pub fn base_url(&self) -> &str {
&self.inner.config.base_url
}
pub fn chat(&self) -> Chat {
Chat::new(self.clone())
}
pub fn embeddings(&self) -> Embeddings {
Embeddings::new(self.clone())
}
pub fn models(&self) -> Models {
Models::new(self.clone())
}
pub fn moderations(&self) -> Moderations {
Moderations::new(self.clone())
}
pub fn completions(&self) -> Completions {
Completions::new(self.clone())
}
pub fn images(&self) -> Images {
Images::new(self.clone())
}
pub fn files(&self) -> Files {
Files::new(self.clone())
}
pub fn audio(&self) -> Audio {
Audio::new(self.clone())
}
pub fn batches(&self) -> Batches {
Batches::new(self.clone())
}
pub fn uploads(&self) -> Uploads {
Uploads::new(self.clone())
}
pub fn fine_tuning(&self) -> FineTuning {
FineTuning::new(self.clone())
}
pub fn vector_stores(&self) -> VectorStores {
VectorStores::new(self.clone())
}
pub fn assistants(&self) -> Assistants {
Assistants::new(self.clone())
}
pub fn threads(&self) -> Threads {
Threads::new(self.clone())
}
pub async fn connect_realtime(
&self,
model: &str,
) -> Result<crate::realtime::RealtimeSession, crate::realtime::RealtimeError> {
let config = self.config();
if config.azure.is_some() {
return Err(crate::realtime::RealtimeError::Connect(
"Azure realtime is not supported; use realtime::connect with explicit options"
.into(),
));
}
crate::realtime::connect(crate::realtime::RealtimeConnectOptions {
api_key: config.api_key.clone(),
base_url: config.base_url.clone(),
model: model.to_string(),
organization: config.organization.clone(),
project: config.project.clone(),
extra_headers: Vec::new(),
})
.await
}
}