1use serde::{Deserialize, Serialize};
31
32use crate::client::{
33 endpoints::{ApiBase, EndpointConfig, build_query, join_url, paths},
34 http::{HttpClientConfig, parse_typed_response, send_empty_request, send_json_request},
35};
36
37pub mod request;
38pub mod response;
39
40pub use request::*;
41pub use response::*;
42
43pub const AGENT_API_PATH: &str = paths::AGENTS;
45
46pub struct AgentClient {
62 api_key: String,
63 endpoint_config: EndpointConfig,
64 api_base: ApiBase,
65 http_config: HttpClientConfig,
66}
67
68impl AgentClient {
69 pub fn new(api_key: impl Into<String>) -> Self {
71 let config = HttpClientConfig::default();
72 Self {
73 api_key: api_key.into(),
74 endpoint_config: EndpointConfig::default(),
75 api_base: ApiBase::PaasV4,
76 http_config: config,
77 }
78 }
79
80 pub fn with_base_url(mut self, base_url: impl Into<String>) -> Self {
82 self.api_base = ApiBase::Custom(base_url.into());
83 self
84 }
85
86 pub fn with_endpoint_config(mut self, endpoint_config: EndpointConfig) -> Self {
87 self.endpoint_config = endpoint_config;
88 self
89 }
90
91 pub fn with_http_config(mut self, config: HttpClientConfig) -> Self {
93 self.http_config = config;
94 self
95 }
96
97 fn url(&self, path: &str) -> String {
98 self.endpoint_config.url(&self.api_base, path)
99 }
100
101 pub async fn create_agent(
103 &self,
104 request: AgentCreateRequest,
105 ) -> crate::ZaiResult<AgentCreateResponse> {
106 self.send_request(&self.url(paths::AGENTS), &request).await
107 }
108
109 pub async fn get_agent(&self, agent_id: &str) -> crate::ZaiResult<AgentDetails> {
111 let url = self.url(&join_url(paths::AGENTS, agent_id));
112 self.send_get_request(&url).await
113 }
114
115 pub async fn update_agent(
117 &self,
118 agent_id: &str,
119 request: AgentUpdateRequest,
120 ) -> crate::ZaiResult<AgentUpdateResponse> {
121 let url = self.url(&join_url(paths::AGENTS, agent_id));
122 self.send_request(&url, &request).await
123 }
124
125 pub async fn delete_agent(&self, agent_id: &str) -> crate::ZaiResult<AgentDeleteResponse> {
127 let url = self.url(&join_url(paths::AGENTS, agent_id));
128 let response = send_empty_request(
129 reqwest::Method::DELETE,
130 url,
131 &self.api_key,
132 std::sync::Arc::new(self.http_config.clone()),
133 )
134 .await?;
135 parse_typed_response::<AgentDeleteResponse>(response).await
136 }
137
138 pub async fn chat(
140 &self,
141 agent_id: &str,
142 request: AgentChatRequest,
143 ) -> crate::ZaiResult<AgentChatResponse> {
144 let url = self.url(&join_url(&join_url(paths::AGENTS, agent_id), "chat"));
145 self.send_request(&url, &request).await
146 }
147
148 pub async fn get_history(
150 &self,
151 agent_id: &str,
152 limit: Option<u32>,
153 ) -> crate::ZaiResult<ConversationHistory> {
154 let base = self.url(&join_url(&join_url(paths::AGENTS, agent_id), "history"));
155 let url = match limit {
156 Some(l) => build_query(&base, [("limit", l.to_string())]),
157 None => base,
158 };
159 self.send_get_request(&url).await
160 }
161
162 async fn send_request<T: Serialize, R: for<'de> Deserialize<'de>>(
164 &self,
165 url: &str,
166 body: &T,
167 ) -> crate::ZaiResult<R> {
168 let response = send_json_request(
169 reqwest::Method::POST,
170 url.to_string(),
171 &self.api_key,
172 body,
173 std::sync::Arc::new(self.http_config.clone()),
174 )
175 .await?;
176 parse_typed_response::<R>(response).await
177 }
178
179 async fn send_get_request<R: for<'de> Deserialize<'de>>(
181 &self,
182 url: &str,
183 ) -> crate::ZaiResult<R> {
184 let response = send_empty_request(
185 reqwest::Method::GET,
186 url.to_string(),
187 &self.api_key,
188 std::sync::Arc::new(self.http_config.clone()),
189 )
190 .await?;
191 parse_typed_response::<R>(response).await
192 }
193}