1use std::sync::Arc;
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::models::{ArtifactsResponse, CursorParams, EventsResponse, JsonMap, ResourceList};
7use crate::openapi_paths;
8use crate::transport::Transport;
9use crate::types::Result;
10
11#[derive(Debug, Clone, Serialize, Deserialize, Default)]
12pub struct PolicyOptimizationSystem {
13 #[serde(default)]
14 pub system_id: Option<String>,
15 #[serde(default)]
16 pub id: Option<String>,
17 #[serde(default)]
18 pub status: Option<String>,
19 #[serde(flatten)]
20 pub extra: JsonMap,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize, Default)]
24pub struct PolicyOptimizationOfflineJob {
25 #[serde(default)]
26 pub job_id: Option<String>,
27 #[serde(default)]
28 pub id: Option<String>,
29 #[serde(default)]
30 pub status: Option<String>,
31 #[serde(flatten)]
32 pub extra: JsonMap,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize, Default)]
36pub struct PolicyOptimizationOnlineSession {
37 #[serde(default)]
38 pub session_id: Option<String>,
39 #[serde(default)]
40 pub id: Option<String>,
41 #[serde(default)]
42 pub status: Option<String>,
43 #[serde(flatten)]
44 pub extra: JsonMap,
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize, Default)]
48pub struct SystemCreateRequest {
49 #[serde(flatten)]
50 pub body: JsonMap,
51}
52
53#[derive(Debug, Clone, Serialize, Deserialize, Default)]
54pub struct SystemUpdateRequest {
55 #[serde(flatten)]
56 pub body: JsonMap,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize, Default)]
60pub struct OfflineJobCreateRequest {
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub system_id: Option<String>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub algorithm: Option<String>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub config: Option<Value>,
67 #[serde(flatten)]
68 pub extra: JsonMap,
69}
70
71#[derive(Debug, Clone, Serialize, Deserialize, Default)]
72pub struct OfflineJobUpdateRequest {
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub state: Option<String>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub reason: Option<String>,
77 #[serde(flatten)]
78 pub extra: JsonMap,
79}
80
81#[derive(Debug, Clone, Serialize, Deserialize, Default)]
82pub struct OnlineSessionCreateRequest {
83 #[serde(skip_serializing_if = "Option::is_none")]
84 pub system_id: Option<String>,
85 #[serde(skip_serializing_if = "Option::is_none")]
86 pub algorithm: Option<String>,
87 #[serde(skip_serializing_if = "Option::is_none")]
88 pub config: Option<Value>,
89 #[serde(flatten)]
90 pub extra: JsonMap,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize, Default)]
94pub struct OnlineSessionUpdateRequest {
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub state: Option<String>,
97 #[serde(skip_serializing_if = "Option::is_none")]
98 pub reason: Option<String>,
99 #[serde(flatten)]
100 pub extra: JsonMap,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize, Default)]
104pub struct OnlineRewardRequest {
105 pub trace_correlation_id: String,
106 pub reward_info: RewardInfo,
107 #[serde(flatten)]
108 pub extra: JsonMap,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize, Default)]
112pub struct RewardInfo {
113 pub outcome_reward: f64,
114 #[serde(skip_serializing_if = "Option::is_none")]
115 pub event_rewards: Option<Vec<f64>>,
116 #[serde(flatten)]
117 pub extra: JsonMap,
118}
119
120#[derive(Clone)]
121pub struct OptimizationClient {
122 transport: Arc<Transport>,
123}
124
125impl OptimizationClient {
126 pub(crate) fn new(transport: Arc<Transport>) -> Self {
127 Self { transport }
128 }
129
130 pub fn systems(&self) -> SystemsClient {
131 SystemsClient {
132 transport: self.transport.clone(),
133 }
134 }
135
136 pub fn offline(&self) -> OfflineJobsClient {
137 OfflineJobsClient {
138 transport: self.transport.clone(),
139 }
140 }
141
142 pub fn online(&self) -> OnlineSessionsClient {
143 OnlineSessionsClient {
144 transport: self.transport.clone(),
145 }
146 }
147}
148
149#[derive(Clone)]
150pub struct SystemsClient {
151 transport: Arc<Transport>,
152}
153
154impl SystemsClient {
155 pub async fn create(&self, request: &SystemCreateRequest) -> Result<PolicyOptimizationSystem> {
156 self.transport
157 .post_json(openapi_paths::V1_POLICY_OPTIMIZATION_SYSTEMS, request)
158 .await
159 }
160
161 pub async fn get(&self, system_id: &str) -> Result<PolicyOptimizationSystem> {
162 self.transport
163 .get_json(&openapi_paths::v1_policy_optimization_system(system_id))
164 .await
165 }
166
167 pub async fn list(&self, params: Option<&CursorParams>) -> Result<ResourceList<PolicyOptimizationSystem>> {
168 match params {
169 Some(query) => {
170 self.transport
171 .get_json_with_query(openapi_paths::V1_POLICY_OPTIMIZATION_SYSTEMS, query)
172 .await
173 }
174 None => {
175 self.transport
176 .get_json(openapi_paths::V1_POLICY_OPTIMIZATION_SYSTEMS)
177 .await
178 }
179 }
180 }
181
182 pub async fn update(
183 &self,
184 system_id: &str,
185 request: &SystemUpdateRequest,
186 ) -> Result<PolicyOptimizationSystem> {
187 self.transport
188 .patch_json(&openapi_paths::v1_policy_optimization_system(system_id), request)
189 .await
190 }
191
192 pub async fn delete(&self, system_id: &str) -> Result<()> {
193 self.transport
194 .delete_empty(&openapi_paths::v1_policy_optimization_system(system_id))
195 .await
196 }
197}
198
199#[derive(Clone)]
200pub struct OfflineJobsClient {
201 transport: Arc<Transport>,
202}
203
204impl OfflineJobsClient {
205 pub async fn create(&self, request: &OfflineJobCreateRequest) -> Result<PolicyOptimizationOfflineJob> {
206 self.transport
207 .post_json(openapi_paths::V1_OFFLINE_JOBS, request)
208 .await
209 }
210
211 pub async fn get(&self, job_id: &str) -> Result<PolicyOptimizationOfflineJob> {
212 self.transport
213 .get_json(&openapi_paths::v1_offline_job(job_id))
214 .await
215 }
216
217 pub async fn list(&self, params: Option<&CursorParams>) -> Result<ResourceList<PolicyOptimizationOfflineJob>> {
218 match params {
219 Some(query) => self
220 .transport
221 .get_json_with_query(openapi_paths::V1_OFFLINE_JOBS, query)
222 .await,
223 None => self.transport.get_json(openapi_paths::V1_OFFLINE_JOBS).await,
224 }
225 }
226
227 pub async fn update(
228 &self,
229 job_id: &str,
230 request: &OfflineJobUpdateRequest,
231 ) -> Result<PolicyOptimizationOfflineJob> {
232 self.transport
233 .patch_json(&openapi_paths::v1_offline_job(job_id), request)
234 .await
235 }
236
237 pub async fn events(&self, job_id: &str, params: Option<&CursorParams>) -> Result<EventsResponse> {
238 let path = openapi_paths::v1_offline_job_events(job_id);
239 match params {
240 Some(query) => self.transport.get_json_with_query(&path, query).await,
241 None => self.transport.get_json(&path).await,
242 }
243 }
244
245 pub async fn artifacts(&self, job_id: &str) -> Result<ArtifactsResponse> {
246 self.transport
247 .get_json(&openapi_paths::v1_offline_job_artifacts(job_id))
248 .await
249 }
250
251 pub async fn cancel(&self, job_id: &str, reason: Option<String>) -> Result<PolicyOptimizationOfflineJob> {
252 self.update(
253 job_id,
254 &OfflineJobUpdateRequest {
255 state: Some("cancelled".to_string()),
256 reason,
257 extra: JsonMap::new(),
258 },
259 )
260 .await
261 }
262
263 pub async fn pause(&self, job_id: &str, reason: Option<String>) -> Result<PolicyOptimizationOfflineJob> {
264 self.update(
265 job_id,
266 &OfflineJobUpdateRequest {
267 state: Some("paused".to_string()),
268 reason,
269 extra: JsonMap::new(),
270 },
271 )
272 .await
273 }
274
275 pub async fn resume(&self, job_id: &str, reason: Option<String>) -> Result<PolicyOptimizationOfflineJob> {
276 self.update(
277 job_id,
278 &OfflineJobUpdateRequest {
279 state: Some("running".to_string()),
280 reason,
281 extra: JsonMap::new(),
282 },
283 )
284 .await
285 }
286}
287
288#[derive(Clone)]
289pub struct OnlineSessionsClient {
290 transport: Arc<Transport>,
291}
292
293impl OnlineSessionsClient {
294 pub async fn create(
295 &self,
296 request: &OnlineSessionCreateRequest,
297 ) -> Result<PolicyOptimizationOnlineSession> {
298 self.transport
299 .post_json(openapi_paths::V1_ONLINE_SESSIONS, request)
300 .await
301 }
302
303 pub async fn get(&self, session_id: &str) -> Result<PolicyOptimizationOnlineSession> {
304 self.transport
305 .get_json(&openapi_paths::v1_online_session(session_id))
306 .await
307 }
308
309 pub async fn list(
310 &self,
311 params: Option<&CursorParams>,
312 ) -> Result<ResourceList<PolicyOptimizationOnlineSession>> {
313 match params {
314 Some(query) => self
315 .transport
316 .get_json_with_query(openapi_paths::V1_ONLINE_SESSIONS, query)
317 .await,
318 None => self.transport.get_json(openapi_paths::V1_ONLINE_SESSIONS).await,
319 }
320 }
321
322 pub async fn update(
323 &self,
324 session_id: &str,
325 request: &OnlineSessionUpdateRequest,
326 ) -> Result<PolicyOptimizationOnlineSession> {
327 self.transport
328 .patch_json(&openapi_paths::v1_online_session(session_id), request)
329 .await
330 }
331
332 pub async fn reward(
333 &self,
334 session_id: &str,
335 request: &OnlineRewardRequest,
336 ) -> Result<PolicyOptimizationOnlineSession> {
337 self.transport
338 .post_json(&openapi_paths::v1_online_session_reward(session_id), request)
339 .await
340 }
341
342 pub async fn events(
343 &self,
344 session_id: &str,
345 params: Option<&CursorParams>,
346 ) -> Result<EventsResponse> {
347 let path = openapi_paths::v1_online_session_events(session_id);
348 match params {
349 Some(query) => self.transport.get_json_with_query(&path, query).await,
350 None => self.transport.get_json(&path).await,
351 }
352 }
353
354 pub async fn cancel(
355 &self,
356 session_id: &str,
357 reason: Option<String>,
358 ) -> Result<PolicyOptimizationOnlineSession> {
359 self.update(
360 session_id,
361 &OnlineSessionUpdateRequest {
362 state: Some("cancelled".to_string()),
363 reason,
364 extra: JsonMap::new(),
365 },
366 )
367 .await
368 }
369
370 pub async fn pause(
371 &self,
372 session_id: &str,
373 reason: Option<String>,
374 ) -> Result<PolicyOptimizationOnlineSession> {
375 self.update(
376 session_id,
377 &OnlineSessionUpdateRequest {
378 state: Some("paused".to_string()),
379 reason,
380 extra: JsonMap::new(),
381 },
382 )
383 .await
384 }
385
386 pub async fn resume(
387 &self,
388 session_id: &str,
389 reason: Option<String>,
390 ) -> Result<PolicyOptimizationOnlineSession> {
391 self.update(
392 session_id,
393 &OnlineSessionUpdateRequest {
394 state: Some("running".to_string()),
395 reason,
396 extra: JsonMap::new(),
397 },
398 )
399 .await
400 }
401}