use crate::error::GresiqError;
use serde::{Deserialize, Serialize};
use smbcloud_network::environment::Environment;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OndeApp {
pub id: String,
pub name: String,
pub status: Option<String>,
pub app_secret: Option<String>,
pub current_model_id: Option<String>,
#[serde(alias = "activeModel")]
pub active_model: Option<String>,
pub created_at: Option<String>,
pub updated_at: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OndeModel {
pub id: String,
pub name: Option<String>,
pub hf_repo_id: Option<String>,
pub gguf_file: Option<String>,
pub family: Option<String>,
pub parameter_class: Option<String>,
pub format: Option<String>,
pub approx_size_bytes: Option<i64>,
pub description: Option<String>,
}
#[derive(Deserialize)]
struct ModelsEnvelope {
models: Vec<OndeModel>,
}
#[derive(Serialize)]
struct CreateAppBody<'a> {
gresiq_app: CreateAppParams<'a>,
}
#[derive(Serialize)]
struct CreateAppParams<'a> {
name: &'a str,
}
fn endpoint(environment: &Environment, path: &str, app_id: &str, app_secret: &str) -> String {
format!(
"{}://{}/v1/client/gresiq/{}?client_id={}&client_secret={}",
environment.api_protocol(),
environment.api_host(),
path,
app_id,
app_secret,
)
}
fn bearer(token: &str) -> String {
format!("Bearer {token}")
}
async fn check(response: reqwest::Response) -> Result<reqwest::Response, GresiqError> {
if response.status().is_success() {
return Ok(response);
}
let status = response.status().as_u16();
let message = response
.text()
.await
.unwrap_or_else(|_| "unreadable response body".to_string());
Err(GresiqError::Api { status, message })
}
pub async fn list_apps(
environment: &Environment,
app_id: &str,
app_secret: &str,
access_token: &str,
) -> Result<Vec<OndeApp>, GresiqError> {
let url = endpoint(environment, "apps", app_id, app_secret);
let response = reqwest::Client::new()
.get(&url)
.header("Authorization", bearer(access_token))
.header("Content-Type", "application/json")
.send()
.await?;
Ok(check(response).await?.json::<Vec<OndeApp>>().await?)
}
pub async fn create_app(
environment: &Environment,
app_id: &str,
app_secret: &str,
access_token: &str,
name: &str,
) -> Result<OndeApp, GresiqError> {
let url = endpoint(environment, "apps", app_id, app_secret);
let body = CreateAppBody {
gresiq_app: CreateAppParams { name },
};
let response = reqwest::Client::new()
.post(&url)
.header("Authorization", bearer(access_token))
.header("Content-Type", "application/json")
.json(&body)
.send()
.await?;
Ok(check(response).await?.json::<OndeApp>().await?)
}
pub async fn assign_model(
environment: &Environment,
app_id: &str,
app_secret: &str,
access_token: &str,
onde_app_id: &str,
model_id: &str,
) -> Result<(), GresiqError> {
let path = format!("apps/{}/model", onde_app_id);
let url = endpoint(environment, &path, app_id, app_secret);
let body = serde_json::json!({ "model_id": model_id });
let response = reqwest::Client::new()
.patch(&url)
.header("Authorization", bearer(access_token))
.header("Content-Type", "application/json")
.json(&body)
.send()
.await?;
check(response).await?;
Ok(())
}
pub async fn list_models(
environment: &Environment,
app_id: &str,
app_secret: &str,
access_token: &str,
) -> Result<Vec<OndeModel>, GresiqError> {
let url = endpoint(environment, "models", app_id, app_secret);
let response = reqwest::Client::new()
.get(&url)
.header("Authorization", bearer(access_token))
.header("Content-Type", "application/json")
.send()
.await?;
Ok(check(response)
.await?
.json::<ModelsEnvelope>()
.await?
.models)
}
pub async fn rename_app(
environment: &Environment,
app_id: &str,
app_secret: &str,
access_token: &str,
onde_app_id: &str,
new_name: &str,
) -> Result<OndeApp, GresiqError> {
let path = format!("apps/{}", onde_app_id);
let url = endpoint(environment, &path, app_id, app_secret);
let body = CreateAppBody {
gresiq_app: CreateAppParams { name: new_name },
};
let response = reqwest::Client::new()
.patch(&url)
.header("Authorization", bearer(access_token))
.header("Content-Type", "application/json")
.json(&body)
.send()
.await?;
Ok(check(response).await?.json::<OndeApp>().await?)
}