Skip to main content

hanzo_client/apis/
openapi_api.rs

1/*
2 * Hanzo Cloud API
3 *
4 * The Hanzo Cloud API as a customer calls it: every operation under /v1/ except the operator's admin product, relay routes, legacy spellings and capabilities still reached by flag. Tagged by product: the first path segment after /v1/.
5 *
6 * The version of the OpenAPI document: v1
7 * 
8 * Generated by: https://openapi-generator.tech
9 */
10
11
12use reqwest;
13use serde::{Deserialize, Serialize, de::Error as _};
14use crate::{apis::ResponseContent, models};
15use super::{Error, configuration, ContentType};
16
17
18/// struct for typed errors of method [`get_capabilities`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum GetCapabilitiesError {
22    UnknownValue(serde_json::Value),
23}
24
25/// struct for typed errors of method [`get_capability`]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum GetCapabilityError {
29    UnknownValue(serde_json::Value),
30}
31
32/// struct for typed errors of method [`get_openapi_commands`]
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(untagged)]
35pub enum GetOpenapiCommandsError {
36    UnknownValue(serde_json::Value),
37}
38
39/// struct for typed errors of method [`get_openapi_period_json`]
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum GetOpenapiPeriodJsonError {
43    UnknownValue(serde_json::Value),
44}
45
46/// struct for typed errors of method [`post_mcp`]
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum PostMcpError {
50    UnknownValue(serde_json::Value),
51}
52
53
54/// The API root. One row per capability — its name, the address it answers under, whether it is generally available, and the sentence it says about itself — plus the links to the document at /v1/openapi.json and the agent MCP server.  It is a projection of that same document and carries the same surface a customer calls: the operator's admin product, the relays, the legacy spellings and any capability that is not yet generally available are in neither.  Unauthenticated by design, exactly as the document it derives from: a client has to be able to read the contract before it holds a credential, and a list of capability names grants nothing.
55pub async fn get_capabilities(configuration: &configuration::Configuration, ) -> Result<models::Root, Error<GetCapabilitiesError>> {
56
57    let uri_str = format!("{}/v1", configuration.base_path);
58    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
59
60    if let Some(ref user_agent) = configuration.user_agent {
61        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
62    }
63
64    let req = req_builder.build()?;
65    let resp = configuration.client.execute(req).await?;
66
67    let status = resp.status();
68    let content_type = resp
69        .headers()
70        .get("content-type")
71        .and_then(|v| v.to_str().ok())
72        .unwrap_or("application/octet-stream");
73    let content_type = super::ContentType::from(content_type);
74
75    if !status.is_client_error() && !status.is_server_error() {
76        let content = resp.text().await?;
77        match content_type {
78            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
79            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Root`"))),
80            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Root`")))),
81        }
82    } else {
83        let content = resp.text().await?;
84        let entity: Option<GetCapabilitiesError> = serde_json::from_str(&content).ok();
85        Err(Error::ResponseError(ResponseContent { status, content, entity }))
86    }
87}
88
89/// What the capability named in the path answers: every published operation, its operationId, its method and its address, and the sentence lifted from the handler that serves it — plus the way back to /v1.  It answers where the capability serves nothing at its own root. Where it does, that operation is the answer and is described at its own address; a client following the root index reaches the capability either way.  Unauthenticated, and scoped to the same customer surface the root is. A name that is not a published capability is answered exactly as any other unrouted address, so this cannot be asked whether something exists that it would not have listed.
90pub async fn get_capability(configuration: &configuration::Configuration, name: &str) -> Result<models::Index, Error<GetCapabilityError>> {
91    // add a prefix to parameters to efficiently prevent name collisions
92    let p_name = name;
93
94    let uri_str = format!("{}/v1/{name}", configuration.base_path, name=crate::apis::urlencode(p_name));
95    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
96
97    if let Some(ref user_agent) = configuration.user_agent {
98        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
99    }
100
101    let req = req_builder.build()?;
102    let resp = configuration.client.execute(req).await?;
103
104    let status = resp.status();
105    let content_type = resp
106        .headers()
107        .get("content-type")
108        .and_then(|v| v.to_str().ok())
109        .unwrap_or("application/octet-stream");
110    let content_type = super::ContentType::from(content_type);
111
112    if !status.is_client_error() && !status.is_server_error() {
113        let content = resp.text().await?;
114        match content_type {
115            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
116            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Index`"))),
117            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Index`")))),
118        }
119    } else {
120        let content = resp.text().await?;
121        let entity: Option<GetCapabilityError> = serde_json::from_str(&content).ok();
122        Err(Error::ResponseError(ResponseContent { status, content, entity }))
123    }
124}
125
126/// The command projection of the OpenAPI document at /v1/openapi.json — each operation reduced to what running it by name needs: its service and command token, its method and path, the prose lifted from the handler, its path parameters as positional arguments and its remaining inputs as typed flags.  It is a separate address for one measured reason: the fleet document is megabytes and a command palette cannot load it, while this projection of the same operations is several times smaller because it carries no schemas, responses or components.  Unauthenticated by design, exactly as the document it derives from: a client has to be able to read the contract before it holds a credential, and a list of operation names grants nothing. The list is TOTAL and is never filtered by caller — what you may run is decided per request by the authorizer, on the decoded input, so a filtered list would be a second claim about permission that is free to be wrong.  Rendered once and served as bytes thereafter, under a strong ETag.
127pub async fn get_openapi_commands(configuration: &configuration::Configuration, ) -> Result<(), Error<GetOpenapiCommandsError>> {
128
129    let uri_str = format!("{}/v1/openapi/commands", configuration.base_path);
130    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
131
132    if let Some(ref user_agent) = configuration.user_agent {
133        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
134    }
135
136    let req = req_builder.build()?;
137    let resp = configuration.client.execute(req).await?;
138
139    let status = resp.status();
140
141    if !status.is_client_error() && !status.is_server_error() {
142        Ok(())
143    } else {
144        let content = resp.text().await?;
145        let entity: Option<GetOpenapiCommandsError> = serde_json::from_str(&content).ok();
146        Err(Error::ResponseError(ResponseContent { status, content, entity }))
147    }
148}
149
150/// Serves the OpenAPI document for the routes this process actually answers — generated from the live router at request time, not from a checked-in file that can disagree with it.  On an app it is that app's own surface; on the fleet's public endpoint it is the composed document for every mounted app. Unauthenticated by design: a client has to be able to read the contract before it holds a credential, and the document grants nothing.  Rendered once and served as bytes thereafter, so the route table's immutability is what makes a repeat request a memcpy rather than a re-encode of a megabyte document.
151pub async fn get_openapi_period_json(configuration: &configuration::Configuration, ) -> Result<(), Error<GetOpenapiPeriodJsonError>> {
152
153    let uri_str = format!("{}/v1/openapi.json", configuration.base_path);
154    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
155
156    if let Some(ref user_agent) = configuration.user_agent {
157        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
158    }
159
160    let req = req_builder.build()?;
161    let resp = configuration.client.execute(req).await?;
162
163    let status = resp.status();
164
165    if !status.is_client_error() && !status.is_server_error() {
166        Ok(())
167    } else {
168        let content = resp.text().await?;
169        let entity: Option<GetOpenapiPeriodJsonError> = serde_json::from_str(&content).ok();
170        Err(Error::ResponseError(ResponseContent { status, content, entity }))
171    }
172}
173
174/// Model Context Protocol over JSON-RPC 2.0 — one POST per message, stateless, protocol revision 2026-07-28. tools/list answers without a credential with one tool per subsystem (its operations in the \"op\" enum) plus \"describe\", which returns one operation's input schema. tools/call names a subsystem tool and carries {\"op\": <operation>, \"input\": <its arguments>}; it takes the same bearer the REST API does, and a call that carries none is answered 401 with a WWW-Authenticate header naming the resource metadata at /.well-known/oauth-protected-resource, which names the authorization server to sign in at. The tool surface is the public contract: the operator's admin product is not offered, and a name that would disclose a secret or mutate an identity is withheld — the list says how many, under _meta.
175pub async fn post_mcp(configuration: &configuration::Configuration, mcp_request: Option<models::McpRequest>) -> Result<models::McpResponse, Error<PostMcpError>> {
176    // add a prefix to parameters to efficiently prevent name collisions
177    let p_mcp_request = mcp_request;
178
179    let uri_str = format!("{}/v1/mcp", configuration.base_path);
180    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
181
182    if let Some(ref user_agent) = configuration.user_agent {
183        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
184    }
185    if let Some(ref token) = configuration.bearer_access_token {
186        req_builder = req_builder.bearer_auth(token.to_owned());
187    };
188    req_builder = req_builder.json(&p_mcp_request);
189
190    let req = req_builder.build()?;
191    let resp = configuration.client.execute(req).await?;
192
193    let status = resp.status();
194    let content_type = resp
195        .headers()
196        .get("content-type")
197        .and_then(|v| v.to_str().ok())
198        .unwrap_or("application/octet-stream");
199    let content_type = super::ContentType::from(content_type);
200
201    if !status.is_client_error() && !status.is_server_error() {
202        let content = resp.text().await?;
203        match content_type {
204            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
205            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::McpResponse`"))),
206            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::McpResponse`")))),
207        }
208    } else {
209        let content = resp.text().await?;
210        let entity: Option<PostMcpError> = serde_json::from_str(&content).ok();
211        Err(Error::ResponseError(ResponseContent { status, content, entity }))
212    }
213}
214