use std::sync::Arc;
use serde_json::Value;
use crate::error::{map_manager_err, ManagerError};
use crate::gen::manager::apis::configuration::Configuration;
use crate::gen::manager::apis::{application_api as api, local_automation_api, manager_api};
use crate::gen::manager::models;
use crate::http::{collect_all, fetch_page, Page};
use crate::resources::raw::{get_json, post_json, post_json_body};
use crate::retry::{with_retry, RetryPolicy};
fn decode_application(v: Value) -> Result<models::Application, ManagerError> {
use models::Application as App;
fn var<T: serde::de::DeserializeOwned>(v: Value) -> Result<Box<T>, ManagerError> {
serde_json::from_value(v)
.map(Box::new)
.map_err(|e| ManagerError::Decode(e.to_string()))
}
let module = v
.get("module")
.and_then(Value::as_str)
.unwrap_or_default()
.to_string();
Ok(match module.as_str() {
"agentQueue" => App::AgentQueue(var(v)?),
"agentic" => App::Agentic(var(v)?),
"audioPlayer" => App::AudioPlayer(var(v)?),
"consumerQueue" => App::ConsumerQueue(var(v)?),
"inputReader" => App::InputReader(var(v)?),
"inputReader.v2" => App::InputReaderV2(var(v)?),
"promptPlayer" => App::PromptPlayer(var(v)?),
"recording" => App::Recording(var(v)?),
"simpleMenu" => App::SimpleMenu(var(v)?),
"speechToText" => App::SpeechToText(var(v)?),
"switchNode" => App::SwitchNode(var(v)?),
"textToSpeech" => App::TextToSpeech(var(v)?),
"transfer" => App::Transfer(var(v)?),
other => {
return Err(ManagerError::Decode(format!(
"unknown application module '{other}'"
)))
}
})
}
async fn applications_page(
cfg: &Configuration,
page: i32,
per_page: Option<i32>,
) -> Result<(Vec<models::Application>, i32, i32, Option<i32>), ManagerError> {
let mut path = format!("/api/v2/applications?page={page}");
if let Some(max) = per_page {
path.push_str(&format!("&max={max}"));
}
let v = get_json(cfg, &path).await?;
let items = v
.get("items")
.and_then(Value::as_array)
.cloned()
.unwrap_or_default()
.into_iter()
.map(decode_application)
.collect::<Result<Vec<_>, _>>()?;
let p = v.get("pagination").cloned().unwrap_or(Value::Null);
let num = |k: &str| p.get(k).and_then(Value::as_i64).map(|n| n as i32);
Ok((
items,
num("pages").unwrap_or(1),
num("current").unwrap_or(page),
num("total"),
))
}
pub struct ApplicationsResource {
pub(crate) cfg: Arc<Configuration>,
pub(crate) retry: RetryPolicy,
pub local_automations: LocalAutomationsResource,
}
impl ApplicationsResource {
pub async fn list_all(&self) -> Result<Vec<models::Application>, ManagerError> {
collect_all(
&self.retry,
|e| e,
|page| async move {
applications_page(self.cfg.as_ref(), page, None)
.await
.map(|(items, pages, current, _)| (items, pages, current))
},
)
.await
}
pub async fn list_page(
&self,
page: i32,
per_page: Option<i32>,
) -> Result<Page<models::Application>, ManagerError> {
fetch_page(
&self.retry,
|e| e,
|| async move { applications_page(self.cfg.as_ref(), page, per_page).await },
)
.await
}
pub async fn all_local_automations(
&self,
) -> Result<Vec<models::LocalAutomation>, ManagerError> {
collect_all(&self.retry, map_manager_err, |page| async move {
let r = local_automation_api::list_all_local_automations(
self.cfg.as_ref(),
Some(page),
None,
)
.await?;
Ok((r.items, r.pagination.pages, r.pagination.current))
})
.await
}
pub async fn create(
&self,
body: models::ApplicationCreateBody,
) -> Result<models::ApplicationItemResponse, ManagerError> {
with_retry(&self.retry, false, || {
api::create_application(self.cfg.as_ref(), body.clone())
})
.await
.map_err(map_manager_err)
}
pub async fn create_raw(&self, body: Value) -> Result<Value, ManagerError> {
with_retry(&self.retry, false, || {
post_json_body(self.cfg.as_ref(), "/api/v2/applications", &body)
})
.await
}
pub async fn get(&self, id: &str) -> Result<models::ApplicationItemResponse, ManagerError> {
let path = format!(
"/api/v2/applications/{}",
crate::gen::manager::apis::urlencode(id)
);
with_retry(&self.retry, true, || async {
let v = get_json(self.cfg.as_ref(), &path).await?;
let success = v.get("success").and_then(Value::as_bool).unwrap_or(true);
let item = v
.get("item")
.cloned()
.ok_or_else(|| ManagerError::Decode("response had no `item`".into()))?;
Ok(models::ApplicationItemResponse::new(
decode_application(item)?,
success,
))
})
.await
}
pub async fn update(
&self,
id: &str,
body: models::ApplicationUpdateBody,
) -> Result<models::ApplicationItemResponse, ManagerError> {
with_retry(&self.retry, false, || {
api::update_application(self.cfg.as_ref(), id, body.clone())
})
.await
.map_err(map_manager_err)
}
pub async fn delete(&self, id: &str) -> Result<(), ManagerError> {
with_retry(&self.retry, false, || {
api::delete_application(self.cfg.as_ref(), id)
})
.await
.map_err(map_manager_err)?;
Ok(())
}
pub async fn delete_many(
&self,
ids: Vec<String>,
) -> Result<models::DefaultV2MessageResponse, ManagerError> {
let body = models::DeleteManyApplicationsRequest { ids };
with_retry(&self.retry, false, || {
api::delete_many_applications(self.cfg.as_ref(), body.clone())
})
.await
.map_err(map_manager_err)
}
pub async fn list_modules(&self) -> Result<models::ListModulesResponse, ManagerError> {
with_retry(&self.retry, true, || api::list_modules(self.cfg.as_ref()))
.await
.map_err(map_manager_err)
}
pub async fn dispatch(
&self,
id: &str,
position: &str,
is_async: bool,
body: models::LocalAutomationDispatch,
) -> Result<models::DispatchLocalAutomationsResponse, ManagerError> {
with_retry(&self.retry, false, || {
manager_api::dispatch_local_automations(
self.cfg.as_ref(),
id,
position,
is_async,
Some(body.clone()),
)
})
.await
.map_err(map_manager_err)
}
pub async fn clone(&self, id: &str) -> Result<models::ApplicationItemResponse, ManagerError> {
with_retry(&self.retry, false, || {
api::clone_application(self.cfg.as_ref(), id)
})
.await
.map_err(map_manager_err)
}
pub async fn clone_raw(&self, id: &str) -> Result<Value, ManagerError> {
let path = format!(
"/api/v2/applications/{}/clone",
crate::gen::manager::apis::urlencode(id)
);
with_retry(&self.retry, false, || post_json(self.cfg.as_ref(), &path)).await
}
pub async fn bulk_update(
&self,
body: models::BulkUpdateApplicationsRequest,
) -> Result<models::DefaultV2MessageResponse, ManagerError> {
with_retry(&self.retry, false, || {
api::bulk_update_applications(self.cfg.as_ref(), body.clone())
})
.await
.map_err(map_manager_err)
}
pub async fn list_app_actions(&self) -> Result<models::ObjectListResponse, ManagerError> {
with_retry(&self.retry, true, || {
api::list_application_actions(self.cfg.as_ref(), None, None)
})
.await
.map_err(map_manager_err)
}
pub async fn list_errors(&self) -> Result<models::ObjectListResponse, ManagerError> {
with_retry(&self.retry, true, || {
api::list_application_errors(self.cfg.as_ref())
})
.await
.map_err(map_manager_err)
}
}
pub struct LocalAutomationsResource {
pub(crate) cfg: Arc<Configuration>,
pub(crate) retry: RetryPolicy,
}
impl LocalAutomationsResource {
pub async fn list_all(
&self,
application_id: &str,
) -> Result<Vec<models::LocalAutomation>, ManagerError> {
collect_all(&self.retry, map_manager_err, |page| async move {
let r = local_automation_api::list_local_automations(
self.cfg.as_ref(),
application_id,
Some(page),
None,
)
.await?;
Ok((r.items, r.pagination.pages, r.pagination.current))
})
.await
}
pub async fn create(
&self,
application_id: &str,
body: models::RestCreateLocalAutomation,
) -> Result<models::LocalAutomationItemResponse, ManagerError> {
with_retry(&self.retry, false, || {
local_automation_api::create_local_automation(
self.cfg.as_ref(),
application_id,
body.clone(),
)
})
.await
.map_err(map_manager_err)
}
pub async fn get(
&self,
application_id: &str,
id: &str,
) -> Result<models::LocalAutomationItemResponse, ManagerError> {
with_retry(&self.retry, true, || {
local_automation_api::get_local_automation(self.cfg.as_ref(), application_id, id)
})
.await
.map_err(map_manager_err)
}
pub async fn update(
&self,
application_id: &str,
id: &str,
body: models::RestUpdateLocalAutomation,
) -> Result<models::LocalAutomationItemResponse, ManagerError> {
with_retry(&self.retry, false, || {
local_automation_api::update_local_automation(
self.cfg.as_ref(),
application_id,
id,
body.clone(),
)
})
.await
.map_err(map_manager_err)
}
pub async fn delete(&self, application_id: &str, id: &str) -> Result<(), ManagerError> {
with_retry(&self.retry, false, || {
local_automation_api::delete_local_automation(self.cfg.as_ref(), application_id, id)
})
.await
.map_err(map_manager_err)?;
Ok(())
}
}