1use serde::Serialize;
4
5use crate::config::{CallOptions, Config};
6use crate::error::Error;
7use crate::question::Questions;
8use crate::request::{self, Prepared, Reply, Retries, Success};
9use crate::response::{Model, Response};
10
11#[derive(Clone, Debug)]
33pub struct Client {
34 config: Config,
35 http: reqwest::Client,
36}
37
38impl Default for Client {
39 fn default() -> Self {
40 Client::new()
41 }
42}
43
44impl Client {
45 pub fn new() -> Self {
52 Client::with_config(Config::from_env()).expect("the HTTP client could not be built")
53 }
54
55 pub fn with_config(config: Config) -> Result<Self, Error> {
56 let http = reqwest::Client::builder()
57 .build()
58 .map_err(Error::from_reqwest)?;
59 Ok(Client { config, http })
60 }
61
62 pub fn config(&self) -> &Config {
63 &self.config
64 }
65
66 pub fn is_configured(&self) -> bool {
68 self.config.is_configured()
69 }
70
71 pub async fn system_one<S: Serialize + ?Sized>(
76 &self,
77 state: &S,
78 questions: &Questions,
79 ) -> Result<Response, Error> {
80 self.system_one_with(state, questions, &CallOptions::default())
81 .await
82 }
83
84 pub async fn system_one_with<S: Serialize + ?Sized>(
86 &self,
87 state: &S,
88 questions: &Questions,
89 options: &CallOptions,
90 ) -> Result<Response, Error> {
91 let prepared = request::system_one(&self.config, state, questions, options)?;
92 let success = self.execute(prepared).await?;
93 request::decode_system_one(success, questions)
94 }
95
96 pub async fn models(&self) -> Result<Vec<Model>, Error> {
99 let prepared = request::models(&self.config)?;
100 let success = self.execute(prepared).await?;
101 request::decode_models(success)
102 }
103
104 async fn execute(&self, prepared: Prepared) -> Result<Success, Error> {
105 let mut retries = Retries::start(prepared.retry.clone());
106 loop {
107 retries.attempts += 1;
108 let result = self.attempt(&prepared, &retries).await;
109 match retries.after(&result) {
110 Some(delay) => tokio::time::sleep(delay).await,
111 None => return request::finish(result),
112 }
113 }
114 }
115
116 async fn attempt(&self, prepared: &Prepared, retries: &Retries) -> Result<Reply, Error> {
117 let mut builder = self
118 .http
119 .request(prepared.method.clone(), &prepared.url)
120 .headers(prepared.headers.clone())
121 .timeout(prepared.timeout);
122 if let Some((name, value)) = retries.retry_count_header() {
123 builder = builder.header(name, value);
124 }
125 if let Some(body) = &prepared.body {
126 builder = builder.body(body.clone());
127 }
128 let response = builder.send().await.map_err(Error::from_reqwest)?;
129 let status = response.status().as_u16();
130 let headers = response.headers().clone();
131 let body = response.bytes().await.map_err(Error::from_reqwest)?;
132 Ok(Reply {
133 status,
134 headers,
135 body: body.to_vec(),
136 })
137 }
138}