use std::{future::Future, path::Path, sync::Arc};
use uuid::Uuid;
use crate::{
AgentRunResult, GenerationResult, IntoGeneration, RunAgentOptions, SubmitOptions,
UploadOptions, WaitOptions,
api::types,
error::{Error, Result},
};
#[derive(Debug, Clone)]
pub struct Client {
inner: crate::Client,
runtime: Arc<tokio::runtime::Runtime>,
}
impl Client {
pub fn new(api_key: impl Into<String>) -> Result<Self> {
Self::from_async(crate::Client::new(api_key)?)
}
pub fn from_env() -> Result<Self> {
Self::from_async(crate::Client::from_env()?)
}
pub fn from_async(inner: crate::Client) -> Result<Self> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|err| Error::Config(format!("could not start a runtime: {err}")))?;
Ok(Self {
inner,
runtime: Arc::new(runtime),
})
}
pub fn api(&self) -> &crate::Client {
&self.inner
}
pub fn block_on<F: Future>(&self, future: F) -> F::Output {
self.runtime.block_on(future)
}
pub fn submit(&self, request: impl IntoGeneration) -> Result<types::Job> {
self.block_on(async { Ok(self.inner.submit(request).await?.job().clone()) })
}
pub fn submit_with(
&self,
request: impl IntoGeneration,
options: SubmitOptions,
) -> Result<types::Job> {
self.block_on(async {
Ok(self
.inner
.submit_with(request, options)
.await?
.job()
.clone())
})
}
pub fn subscribe(&self, request: impl IntoGeneration) -> Result<GenerationResult> {
self.block_on(self.inner.subscribe(request))
}
pub fn quote(&self, request: impl IntoGeneration) -> Result<types::JobCostQuote> {
self.block_on(self.inner.quote(request))
}
pub fn wait_job(&self, job_id: Uuid, options: WaitOptions) -> Result<types::Job> {
self.block_on(self.inner.wait_job(job_id, options))
}
pub fn job_media(&self, job: &types::Job) -> Vec<crate::Media> {
self.block_on(self.inner.job_media(job))
}
pub fn cancel_job(&self, job_id: Uuid) -> Result<types::Job> {
use crate::Typed;
self.block_on(self.inner.cancel_job().id(job_id).send().typed())
}
pub fn upload_file(
&self,
path: impl AsRef<Path>,
options: UploadOptions,
) -> Result<types::Asset> {
self.block_on(self.inner.upload_file(path, options))
}
pub fn download(&self, url: &str, path: impl AsRef<Path>) -> Result<u64> {
self.block_on(self.inner.download(url, path))
}
pub fn download_bytes(&self, url: &str) -> Result<Vec<u8>> {
self.block_on(self.inner.download_bytes(url))
}
pub fn run_agent(&self, options: RunAgentOptions) -> Result<AgentRunResult> {
self.block_on(self.inner.run_agent(options))
}
pub fn assets<'a>(
&'a self,
configure: impl Fn(crate::api::builder::ListAssets<'a>) -> crate::api::builder::ListAssets<'a>
+ 'a,
) -> impl Iterator<Item = Result<types::Asset>> + 'a {
let mut stream = Box::pin(self.inner.paginate_assets(configure));
std::iter::from_fn(move || {
use futures_util::StreamExt;
self.runtime.block_on(stream.next())
})
}
}