Skip to main content

babelforce_manager_sdk/resources/
tasks.rs

1use std::collections::HashMap;
2use std::sync::Arc;
3
4use crate::error::{map_task_automation_err as map_err, ManagerError};
5use crate::gen::task_automation::apis::configuration::Configuration;
6use crate::gen::task_automation::apis::{
7    account_configuration_api as cfg_api, action_test_api, agent_api, logs_api, manager_api,
8    metrics_api, scripts_api, secrets_api, usage_api,
9};
10use crate::gen::task_automation::models;
11use crate::retry::{with_retry, RetryPolicy};
12
13/// Task automation (v3) — `/api/v3/tasks`, with nested `scripts`, `secrets`, `selection_config`,
14/// and `metrics` sub-resources.
15pub struct TasksResource {
16    pub(crate) cfg: Arc<Configuration>,
17    pub(crate) retry: RetryPolicy,
18    /// Custom scripts by type.
19    pub scripts: TaskScriptsResource,
20    /// Account secrets, grouped by prefix.
21    pub secrets: TaskSecretsResource,
22    /// Account task-selection configuration.
23    pub selection_config: TaskSelectionConfigResource,
24    /// Task & agent metrics.
25    pub metrics: TaskMetricsResource,
26}
27
28impl TasksResource {
29    /// List tasks (one page), optionally filtered.
30    pub async fn list(&self, filter: Option<&str>) -> Result<models::TaskList, ManagerError> {
31        with_retry(&self.retry, true, || {
32            manager_api::tasks(self.cfg.as_ref(), filter, None, None)
33        })
34        .await
35        .map_err(map_err)
36    }
37
38    /// Submit a new task.
39    pub async fn create(&self, body: models::SubmitTask) -> Result<models::Task, ManagerError> {
40        with_retry(&self.retry, false, || {
41            manager_api::submit_task(self.cfg.as_ref(), body.clone())
42        })
43        .await
44        .map_err(map_err)
45    }
46
47    /// Submit a task from a named template, supplying the template variables.
48    pub async fn create_from_template(
49        &self,
50        template: &str,
51        variables: serde_json::Value,
52    ) -> Result<models::Task, ManagerError> {
53        with_retry(&self.retry, false, || {
54            manager_api::submit_task_template(self.cfg.as_ref(), template, variables.clone(), None)
55        })
56        .await
57        .map_err(map_err)
58    }
59
60    /// Get a task by id.
61    pub async fn get(&self, task_id: &str) -> Result<models::Task, ManagerError> {
62        with_retry(&self.retry, true, || {
63            manager_api::task(self.cfg.as_ref(), task_id)
64        })
65        .await
66        .map_err(map_err)
67    }
68
69    /// Update a task.
70    pub async fn update(
71        &self,
72        task_id: &str,
73        body: models::Task,
74    ) -> Result<models::Task, ManagerError> {
75        with_retry(&self.retry, false, || {
76            manager_api::update_task(self.cfg.as_ref(), task_id, body.clone())
77        })
78        .await
79        .map_err(map_err)
80    }
81
82    /// Interrupt a task, moving it to a target state.
83    pub async fn interrupt(
84        &self,
85        task_id: &str,
86        interrupt_to: models::InterruptionTargetStates,
87        action: Option<models::ManualActionRequest>,
88    ) -> Result<(), ManagerError> {
89        with_retry(&self.retry, false, || {
90            manager_api::manager_interrupt_on_task(
91                self.cfg.as_ref(),
92                task_id,
93                interrupt_to,
94                action.clone(),
95            )
96        })
97        .await
98        .map_err(map_err)
99    }
100
101    /// Change a task's state.
102    ///
103    /// The underlying generated operation is marked deprecated upstream, but it remains part of the
104    /// spec and is wrapped here for parity with the TypeScript/Go SDKs.
105    #[allow(deprecated)]
106    pub async fn change_state(
107        &self,
108        task_id: &str,
109        state: models::TaskState,
110    ) -> Result<(), ManagerError> {
111        with_retry(&self.retry, false, || {
112            manager_api::change_task_state(self.cfg.as_ref(), task_id, state)
113        })
114        .await
115        .map_err(map_err)
116    }
117
118    /// Perform an agent action on a task (accept/reject/complete, …).
119    pub async fn agent_action(
120        &self,
121        task_id: &str,
122        action: models::AgentActions,
123        manual_action: Option<models::ManualActionRequest>,
124    ) -> Result<models::Task, ManagerError> {
125        with_retry(&self.retry, false, || {
126            agent_api::agent_action_on_task(
127                self.cfg.as_ref(),
128                task_id,
129                action,
130                manual_action.clone(),
131            )
132        })
133        .await
134        .map_err(map_err)
135    }
136
137    /// Lock or unlock the current agent.
138    pub async fn set_agent_lock(
139        &self,
140        lock_state: models::AgentLocking,
141    ) -> Result<models::AgentLockState, ManagerError> {
142        with_retry(&self.retry, false, || {
143            agent_api::change_agent_lock(self.cfg.as_ref(), lock_state)
144        })
145        .await
146        .map_err(map_err)
147    }
148
149    /// Task usage (time series).
150    pub async fn usage(&self) -> Result<models::TaskTimeSeries, ManagerError> {
151        with_retry(&self.retry, true, || {
152            usage_api::task_usage(self.cfg.as_ref(), None, None, None, None)
153        })
154        .await
155        .map_err(map_err)
156    }
157
158    /// The set of task usage types.
159    pub async fn usage_types(&self) -> Result<Vec<String>, ManagerError> {
160        with_retry(&self.retry, true, || {
161            usage_api::task_usage_types(self.cfg.as_ref(), None, None)
162        })
163        .await
164        .map_err(map_err)
165    }
166
167    /// Read the customer task logs.
168    pub async fn logs(&self) -> Result<models::LogsResponse, ManagerError> {
169        with_retry(&self.retry, true, || {
170            logs_api::list(self.cfg.as_ref(), None, None, None, None, None, None)
171        })
172        .await
173        .map_err(map_err)
174    }
175
176    /// Test an action without dispatching it.
177    pub async fn test_action(
178        &self,
179        body: models::TestAction,
180    ) -> Result<models::TestActionResult, ManagerError> {
181        with_retry(&self.retry, false, || {
182            action_test_api::testing(self.cfg.as_ref(), body.clone())
183        })
184        .await
185        .map_err(map_err)
186    }
187}
188
189/// Custom scripts by type — `/api/v3/scripts`.
190pub struct TaskScriptsResource {
191    pub(crate) cfg: Arc<Configuration>,
192    pub(crate) retry: RetryPolicy,
193}
194
195impl TaskScriptsResource {
196    /// List scripts of a type.
197    pub async fn list(
198        &self,
199        script_type: models::ScriptType,
200    ) -> Result<models::ScriptList, ManagerError> {
201        with_retry(&self.retry, true, || {
202            scripts_api::list_scripts(self.cfg.as_ref(), script_type, None, None, None)
203        })
204        .await
205        .map_err(map_err)
206    }
207
208    /// Get a script by id.
209    pub async fn get(
210        &self,
211        script_type: models::ScriptType,
212        code_id: &str,
213    ) -> Result<models::ScriptResponses, ManagerError> {
214        with_retry(&self.retry, true, || {
215            scripts_api::get_script(self.cfg.as_ref(), code_id, script_type, None)
216        })
217        .await
218        .map_err(map_err)
219    }
220
221    /// Submit a new script.
222    pub async fn submit(
223        &self,
224        script_type: models::ScriptType,
225        body: models::Script,
226    ) -> Result<models::ScriptResponses, ManagerError> {
227        with_retry(&self.retry, false, || {
228            scripts_api::submit_script(self.cfg.as_ref(), script_type, body.clone())
229        })
230        .await
231        .map_err(map_err)
232    }
233
234    /// Update a script.
235    pub async fn update(
236        &self,
237        script_type: models::ScriptType,
238        code_id: &str,
239        body: models::Script,
240    ) -> Result<models::ScriptResponses, ManagerError> {
241        with_retry(&self.retry, false, || {
242            scripts_api::update_script(self.cfg.as_ref(), code_id, script_type, body.clone())
243        })
244        .await
245        .map_err(map_err)
246    }
247
248    /// Delete a script.
249    pub async fn delete(
250        &self,
251        script_type: models::ScriptType,
252        code_id: &str,
253    ) -> Result<(), ManagerError> {
254        with_retry(&self.retry, false, || {
255            scripts_api::delete_script(self.cfg.as_ref(), code_id, script_type)
256        })
257        .await
258        .map_err(map_err)
259    }
260}
261
262/// Account secrets, grouped by prefix — `/api/v3/secrets`.
263pub struct TaskSecretsResource {
264    pub(crate) cfg: Arc<Configuration>,
265    pub(crate) retry: RetryPolicy,
266}
267
268impl TaskSecretsResource {
269    /// List the secret prefixes.
270    pub async fn list_prefixes(&self) -> Result<Vec<String>, ManagerError> {
271        with_retry(&self.retry, true, || {
272            secrets_api::list_secret_prefixes(self.cfg.as_ref())
273        })
274        .await
275        .map_err(map_err)
276    }
277
278    /// List the keys under a prefix.
279    pub async fn list_keys(&self, prefix: &str) -> Result<Vec<String>, ManagerError> {
280        with_retry(&self.retry, true, || {
281            secrets_api::list_secret_keys(self.cfg.as_ref(), prefix)
282        })
283        .await
284        .map_err(map_err)
285    }
286
287    /// Create secrets under a prefix.
288    pub async fn create(
289        &self,
290        prefix: &str,
291        secrets: HashMap<String, serde_json::Value>,
292    ) -> Result<(), ManagerError> {
293        with_retry(&self.retry, false, || {
294            secrets_api::create_secrets(self.cfg.as_ref(), prefix, Some(secrets.clone()))
295        })
296        .await
297        .map_err(map_err)
298    }
299
300    /// Patch (merge) secrets under a prefix.
301    pub async fn patch(
302        &self,
303        prefix: &str,
304        secrets: HashMap<String, serde_json::Value>,
305    ) -> Result<(), ManagerError> {
306        with_retry(&self.retry, false, || {
307            secrets_api::patch_secrets(self.cfg.as_ref(), prefix, Some(secrets.clone()))
308        })
309        .await
310        .map_err(map_err)
311    }
312
313    /// Delete keys under a prefix.
314    pub async fn delete_keys(&self, prefix: &str, keys: Vec<String>) -> Result<(), ManagerError> {
315        with_retry(&self.retry, false, || {
316            secrets_api::delete_secret_keys(self.cfg.as_ref(), prefix, Some(keys.clone()))
317        })
318        .await
319        .map_err(map_err)
320    }
321}
322
323/// Account task-selection configuration — `/api/v3/account/selection`.
324pub struct TaskSelectionConfigResource {
325    pub(crate) cfg: Arc<Configuration>,
326    pub(crate) retry: RetryPolicy,
327}
328
329impl TaskSelectionConfigResource {
330    /// Read the selection configuration.
331    pub async fn read(&self) -> Result<models::AccountSelectionConfiguration, ManagerError> {
332        with_retry(&self.retry, true, || {
333            cfg_api::read_selection_configuration(self.cfg.as_ref())
334        })
335        .await
336        .map_err(map_err)
337    }
338
339    /// Create the selection configuration.
340    pub async fn create(
341        &self,
342        body: models::AccountSelectionConfiguration,
343    ) -> Result<models::AccountSelectionConfiguration, ManagerError> {
344        with_retry(&self.retry, false, || {
345            cfg_api::create_selection_configuration(self.cfg.as_ref(), Some(body.clone()))
346        })
347        .await
348        .map_err(map_err)
349    }
350
351    /// Update the selection configuration.
352    pub async fn update(
353        &self,
354        body: models::AccountSelectionConfiguration,
355    ) -> Result<models::AccountSelectionConfiguration, ManagerError> {
356        with_retry(&self.retry, false, || {
357            cfg_api::update_selection_configuration(self.cfg.as_ref(), Some(body.clone()))
358        })
359        .await
360        .map_err(map_err)
361    }
362
363    /// Delete the selection configuration.
364    pub async fn delete(&self) -> Result<(), ManagerError> {
365        with_retry(&self.retry, false, || {
366            cfg_api::delete_selection_configuration(self.cfg.as_ref())
367        })
368        .await
369        .map_err(map_err)
370    }
371}
372
373/// Task & agent metrics — `/api/v3/metrics`.
374pub struct TaskMetricsResource {
375    pub(crate) cfg: Arc<Configuration>,
376    pub(crate) retry: RetryPolicy,
377}
378
379impl TaskMetricsResource {
380    /// The journal for a task.
381    pub async fn task_journal(&self, task_id: &str) -> Result<models::TaskJournal, ManagerError> {
382        with_retry(&self.retry, true, || {
383            metrics_api::task_journal(self.cfg.as_ref(), task_id)
384        })
385        .await
386        .map_err(map_err)
387    }
388
389    /// The interaction journal for an agent.
390    pub async fn agent_journal(
391        &self,
392        agent_id: &str,
393    ) -> Result<models::AgentJournal, ManagerError> {
394        with_retry(&self.retry, true, || {
395            metrics_api::agent_interactions(self.cfg.as_ref(), agent_id)
396        })
397        .await
398        .map_err(map_err)
399    }
400
401    /// An agent's interaction durations.
402    pub async fn agent_interaction_durations(
403        &self,
404        agent_id: &str,
405    ) -> Result<models::InteractionDurations, ManagerError> {
406        with_retry(&self.retry, true, || {
407            metrics_api::agent_interaction_duration(self.cfg.as_ref(), agent_id)
408        })
409        .await
410        .map_err(map_err)
411    }
412}