1use crate::error::GresiqError;
16use serde::{Deserialize, Serialize};
17use smbcloud_network::environment::Environment;
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct OndeApp {
22 pub id: String,
23 pub name: String,
24 pub status: Option<String>,
25 pub app_secret: Option<String>,
26 pub current_model_id: Option<String>,
27 #[serde(alias = "activeModel")]
28 pub active_model: Option<String>,
29 pub created_at: Option<String>,
30 pub updated_at: Option<String>,
31}
32
33#[derive(Debug, Clone, Serialize, Deserialize)]
35pub struct OndeModel {
36 pub id: String,
37 pub name: Option<String>,
38 pub hf_repo_id: Option<String>,
39 pub gguf_file: Option<String>,
40 pub family: Option<String>,
41 pub parameter_class: Option<String>,
42 pub format: Option<String>,
43 pub approx_size_bytes: Option<i64>,
44 pub description: Option<String>,
45}
46
47#[derive(Deserialize)]
49struct ModelsEnvelope {
50 models: Vec<OndeModel>,
51}
52
53#[derive(Serialize)]
55struct CreateAppBody<'a> {
56 gresiq_app: CreateAppParams<'a>,
57}
58
59#[derive(Serialize)]
60struct CreateAppParams<'a> {
61 name: &'a str,
62}
63
64fn endpoint(environment: &Environment, path: &str, app_id: &str, app_secret: &str) -> String {
65 format!(
66 "{}://{}/v1/client/gresiq/{}?client_id={}&client_secret={}",
67 environment.api_protocol(),
68 environment.api_host(),
69 path,
70 app_id,
71 app_secret,
72 )
73}
74
75fn bearer(token: &str) -> String {
76 format!("Bearer {token}")
77}
78
79async fn check(response: reqwest::Response) -> Result<reqwest::Response, GresiqError> {
82 if response.status().is_success() {
83 return Ok(response);
84 }
85 let status = response.status().as_u16();
86 let message = response
87 .text()
88 .await
89 .unwrap_or_else(|_| "unreadable response body".to_string());
90 Err(GresiqError::Api { status, message })
91}
92
93pub async fn list_apps(
97 environment: &Environment,
98 app_id: &str,
99 app_secret: &str,
100 access_token: &str,
101) -> Result<Vec<OndeApp>, GresiqError> {
102 let url = endpoint(environment, "apps", app_id, app_secret);
103 let response = reqwest::Client::new()
104 .get(&url)
105 .header("Authorization", bearer(access_token))
106 .header("Content-Type", "application/json")
107 .send()
108 .await?;
109 Ok(check(response).await?.json::<Vec<OndeApp>>().await?)
110}
111
112pub async fn create_app(
116 environment: &Environment,
117 app_id: &str,
118 app_secret: &str,
119 access_token: &str,
120 name: &str,
121) -> Result<OndeApp, GresiqError> {
122 let url = endpoint(environment, "apps", app_id, app_secret);
123 let body = CreateAppBody {
124 gresiq_app: CreateAppParams { name },
125 };
126 let response = reqwest::Client::new()
127 .post(&url)
128 .header("Authorization", bearer(access_token))
129 .header("Content-Type", "application/json")
130 .json(&body)
131 .send()
132 .await?;
133 Ok(check(response).await?.json::<OndeApp>().await?)
134}
135
136pub async fn assign_model(
140 environment: &Environment,
141 app_id: &str,
142 app_secret: &str,
143 access_token: &str,
144 onde_app_id: &str,
145 model_id: &str,
146) -> Result<(), GresiqError> {
147 let path = format!("apps/{}/model", onde_app_id);
148 let url = endpoint(environment, &path, app_id, app_secret);
149 let body = serde_json::json!({ "model_id": model_id });
150 let response = reqwest::Client::new()
151 .patch(&url)
152 .header("Authorization", bearer(access_token))
153 .header("Content-Type", "application/json")
154 .json(&body)
155 .send()
156 .await?;
157 check(response).await?;
158 Ok(())
159}
160
161pub async fn list_models(
165 environment: &Environment,
166 app_id: &str,
167 app_secret: &str,
168 access_token: &str,
169) -> Result<Vec<OndeModel>, GresiqError> {
170 let url = endpoint(environment, "models", app_id, app_secret);
171 let response = reqwest::Client::new()
172 .get(&url)
173 .header("Authorization", bearer(access_token))
174 .header("Content-Type", "application/json")
175 .send()
176 .await?;
177 Ok(check(response)
178 .await?
179 .json::<ModelsEnvelope>()
180 .await?
181 .models)
182}
183
184pub async fn rename_app(
188 environment: &Environment,
189 app_id: &str,
190 app_secret: &str,
191 access_token: &str,
192 onde_app_id: &str,
193 new_name: &str,
194) -> Result<OndeApp, GresiqError> {
195 let path = format!("apps/{}", onde_app_id);
196 let url = endpoint(environment, &path, app_id, app_secret);
197 let body = CreateAppBody {
198 gresiq_app: CreateAppParams { name: new_name },
199 };
200 let response = reqwest::Client::new()
201 .patch(&url)
202 .header("Authorization", bearer(access_token))
203 .header("Content-Type", "application/json")
204 .json(&body)
205 .send()
206 .await?;
207 Ok(check(response).await?.json::<OndeApp>().await?)
208}