Skip to main content

hanzo_client/apis/
benchmark_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_benchmark_catalog`]
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged)]
21pub enum GetBenchmarkCatalogError {
22    UnknownValue(serde_json::Value),
23}
24
25/// struct for typed errors of method [`get_benchmark_claims`]
26#[derive(Debug, Clone, Serialize, Deserialize)]
27#[serde(untagged)]
28pub enum GetBenchmarkClaimsError {
29    UnknownValue(serde_json::Value),
30}
31
32/// struct for typed errors of method [`get_benchmark_compare`]
33#[derive(Debug, Clone, Serialize, Deserialize)]
34#[serde(untagged)]
35pub enum GetBenchmarkCompareError {
36    UnknownValue(serde_json::Value),
37}
38
39/// struct for typed errors of method [`get_benchmark_history`]
40#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(untagged)]
42pub enum GetBenchmarkHistoryError {
43    UnknownValue(serde_json::Value),
44}
45
46/// struct for typed errors of method [`get_benchmark_leaderboard`]
47#[derive(Debug, Clone, Serialize, Deserialize)]
48#[serde(untagged)]
49pub enum GetBenchmarkLeaderboardError {
50    UnknownValue(serde_json::Value),
51}
52
53/// struct for typed errors of method [`get_benchmark_presets`]
54#[derive(Debug, Clone, Serialize, Deserialize)]
55#[serde(untagged)]
56pub enum GetBenchmarkPresetsError {
57    UnknownValue(serde_json::Value),
58}
59
60/// struct for typed errors of method [`post_benchmark_claims`]
61#[derive(Debug, Clone, Serialize, Deserialize)]
62#[serde(untagged)]
63pub enum PostBenchmarkClaimsError {
64    UnknownValue(serde_json::Value),
65}
66
67/// struct for typed errors of method [`post_benchmark_presets`]
68#[derive(Debug, Clone, Serialize, Deserialize)]
69#[serde(untagged)]
70pub enum PostBenchmarkPresetsError {
71    UnknownValue(serde_json::Value),
72}
73
74/// struct for typed errors of method [`post_benchmark_runs`]
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(untagged)]
77pub enum PostBenchmarkRunsError {
78    UnknownValue(serde_json::Value),
79}
80
81
82/// Is the canonical public benchmarks this arena runs — the id, title, axis, item count and upstream source of each, with native marking the ones the standardized harness runs today; the rest are registered and adapter-pending.  These ids are the vocabulary the rest of the surface takes: a run names them, and the leaderboard and compare read them from ?benchmark=. The catalog is deployment-wide and identical for every caller — there is no tenant in it.
83pub async fn get_benchmark_catalog(configuration: &configuration::Configuration, ) -> Result<models::BenchmarkCatalog, Error<GetBenchmarkCatalogError>> {
84
85    let uri_str = format!("{}/v1/benchmark/catalog", configuration.base_path);
86    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
87
88    if let Some(ref user_agent) = configuration.user_agent {
89        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
90    }
91    if let Some(ref token) = configuration.bearer_access_token {
92        req_builder = req_builder.bearer_auth(token.to_owned());
93    };
94
95    let req = req_builder.build()?;
96    let resp = configuration.client.execute(req).await?;
97
98    let status = resp.status();
99    let content_type = resp
100        .headers()
101        .get("content-type")
102        .and_then(|v| v.to_str().ok())
103        .unwrap_or("application/octet-stream");
104    let content_type = super::ContentType::from(content_type);
105
106    if !status.is_client_error() && !status.is_server_error() {
107        let content = resp.text().await?;
108        match content_type {
109            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
110            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::BenchmarkCatalog`"))),
111            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::BenchmarkCatalog`")))),
112        }
113    } else {
114        let content = resp.text().await?;
115        let entity: Option<GetBenchmarkCatalogError> = serde_json::from_str(&content).ok();
116        Err(Error::ResponseError(ResponseContent { status, content, entity }))
117    }
118}
119
120/// Lists the effective published claims: what the leaderboard will use for each (benchmark, model) after the seed, the import and any stored correction are layered. It answers the operator's question — what does this arena currently believe someone else reported, and did we ship that or fix it.  Effective values only. The history of a key lives in the append-only file and is not what this op is for; a list that returned every superseded row would make the common question the hard one.
121pub async fn get_benchmark_claims(configuration: &configuration::Configuration, benchmark: Option<&str>, model: Option<&str>, provider: Option<&str>, source: Option<&str>, protocol: Option<&str>) -> Result<models::ClaimsOut, Error<GetBenchmarkClaimsError>> {
122    // add a prefix to parameters to efficiently prevent name collisions
123    let p_benchmark = benchmark;
124    let p_model = model;
125    let p_provider = provider;
126    let p_source = source;
127    let p_protocol = protocol;
128
129    let uri_str = format!("{}/v1/benchmark/claims", configuration.base_path);
130    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
131
132    if let Some(ref param_value) = p_benchmark {
133        req_builder = req_builder.query(&[("Benchmark", &param_value.to_string())]);
134    }
135    if let Some(ref param_value) = p_model {
136        req_builder = req_builder.query(&[("Model", &param_value.to_string())]);
137    }
138    if let Some(ref param_value) = p_provider {
139        req_builder = req_builder.query(&[("Provider", &param_value.to_string())]);
140    }
141    if let Some(ref param_value) = p_source {
142        req_builder = req_builder.query(&[("Source", &param_value.to_string())]);
143    }
144    if let Some(ref param_value) = p_protocol {
145        req_builder = req_builder.query(&[("Protocol", &param_value.to_string())]);
146    }
147    if let Some(ref user_agent) = configuration.user_agent {
148        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
149    }
150    if let Some(ref token) = configuration.bearer_access_token {
151        req_builder = req_builder.bearer_auth(token.to_owned());
152    };
153
154    let req = req_builder.build()?;
155    let resp = configuration.client.execute(req).await?;
156
157    let status = resp.status();
158    let content_type = resp
159        .headers()
160        .get("content-type")
161        .and_then(|v| v.to_str().ok())
162        .unwrap_or("application/octet-stream");
163    let content_type = super::ContentType::from(content_type);
164
165    if !status.is_client_error() && !status.is_server_error() {
166        let content = resp.text().await?;
167        match content_type {
168            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
169            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::ClaimsOut`"))),
170            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::ClaimsOut`")))),
171        }
172    } else {
173        let content = resp.text().await?;
174        let entity: Option<GetBenchmarkClaimsError> = serde_json::from_str(&content).ok();
175        Err(Error::ResponseError(ResponseContent { status, content, entity }))
176    }
177}
178
179/// Is the ONLY valid arm-vs-arm test: it pairs the two models on the items BOTH completed, and answers rescue and damage counts with an exact-McNemar p.  Pairing is what prevents the subset artifact — comparing one model's easy subset against another's full run — so n_common, not either arm's own coverage, is the number to read this by.  Both a and b are required. The benchmark defaults to gpqa_diamond.
180pub async fn get_benchmark_compare(configuration: &configuration::Configuration, a: &str, b: &str, benchmark: Option<&str>) -> Result<models::Pairing, Error<GetBenchmarkCompareError>> {
181    // add a prefix to parameters to efficiently prevent name collisions
182    let p_a = a;
183    let p_b = b;
184    let p_benchmark = benchmark;
185
186    let uri_str = format!("{}/v1/benchmark/compare", configuration.base_path);
187    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
188
189    if let Some(ref param_value) = p_benchmark {
190        req_builder = req_builder.query(&[("benchmark", &param_value.to_string())]);
191    }
192    req_builder = req_builder.query(&[("a", &p_a.to_string())]);
193    req_builder = req_builder.query(&[("b", &p_b.to_string())]);
194    if let Some(ref user_agent) = configuration.user_agent {
195        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
196    }
197    if let Some(ref token) = configuration.bearer_access_token {
198        req_builder = req_builder.bearer_auth(token.to_owned());
199    };
200
201    let req = req_builder.build()?;
202    let resp = configuration.client.execute(req).await?;
203
204    let status = resp.status();
205    let content_type = resp
206        .headers()
207        .get("content-type")
208        .and_then(|v| v.to_str().ok())
209        .unwrap_or("application/octet-stream");
210    let content_type = super::ContentType::from(content_type);
211
212    if !status.is_client_error() && !status.is_server_error() {
213        let content = resp.text().await?;
214        match content_type {
215            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
216            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Pairing`"))),
217            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::Pairing`")))),
218        }
219    } else {
220        let content = resp.text().await?;
221        let entity: Option<GetBenchmarkCompareError> = serde_json::from_str(&content).ok();
222        Err(Error::ResponseError(ResponseContent { status, content, entity }))
223    }
224}
225
226/// Returns each model's measured score per run over time, oldest first, with the change between runs.  This is the counterweight to a leaderboard: the board shows the latest run because that is what \"how good is it\" means, and a single latest number cannot distinguish a model that has always been strong from one that just improved, or from one that regressed after a provider changed something. Both matter for routing, and only one of them is visible on a board.  Runs with no id — attempts recorded before runs existed — group under the empty run, which is honestly what they are: one undated measurement.
227pub async fn get_benchmark_history(configuration: &configuration::Configuration, benchmark: Option<&str>, model: Option<&str>) -> Result<models::HistoryOut, Error<GetBenchmarkHistoryError>> {
228    // add a prefix to parameters to efficiently prevent name collisions
229    let p_benchmark = benchmark;
230    let p_model = model;
231
232    let uri_str = format!("{}/v1/benchmark/history", configuration.base_path);
233    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
234
235    if let Some(ref param_value) = p_benchmark {
236        req_builder = req_builder.query(&[("Benchmark", &param_value.to_string())]);
237    }
238    if let Some(ref param_value) = p_model {
239        req_builder = req_builder.query(&[("Model", &param_value.to_string())]);
240    }
241    if let Some(ref user_agent) = configuration.user_agent {
242        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
243    }
244    if let Some(ref token) = configuration.bearer_access_token {
245        req_builder = req_builder.bearer_auth(token.to_owned());
246    };
247
248    let req = req_builder.build()?;
249    let resp = configuration.client.execute(req).await?;
250
251    let status = resp.status();
252    let content_type = resp
253        .headers()
254        .get("content-type")
255        .and_then(|v| v.to_str().ok())
256        .unwrap_or("application/octet-stream");
257    let content_type = super::ContentType::from(content_type);
258
259    if !status.is_client_error() && !status.is_server_error() {
260        let content = resp.text().await?;
261        match content_type {
262            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
263            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::HistoryOut`"))),
264            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::HistoryOut`")))),
265        }
266    } else {
267        let content = resp.text().await?;
268        let entity: Option<GetBenchmarkHistoryError> = serde_json::from_str(&content).ok();
269        Err(Error::ResponseError(ResponseContent { status, content, entity }))
270    }
271}
272
273/// Answers one row per model for the benchmark named — what our own harness measured, beside what the vendor claims, and the gap between them.  The gap is the point of the arena; provider-reported claims have run materially hot against one standardized harness.  The two planes are NEVER blended, and that is the rule to read the rows by: a model we have measured but no vendor has claimed for shows published null, a model with only a claim shows measured null, and gap exists only where both do.  n is coverage and is not decoration: two measured numbers taken over different item counts are not comparable, so read the row's n before reading its accuracy.
274pub async fn get_benchmark_leaderboard(configuration: &configuration::Configuration, benchmark: Option<&str>) -> Result<models::Leaderboard, Error<GetBenchmarkLeaderboardError>> {
275    // add a prefix to parameters to efficiently prevent name collisions
276    let p_benchmark = benchmark;
277
278    let uri_str = format!("{}/v1/benchmark/leaderboard", configuration.base_path);
279    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
280
281    if let Some(ref param_value) = p_benchmark {
282        req_builder = req_builder.query(&[("benchmark", &param_value.to_string())]);
283    }
284    if let Some(ref user_agent) = configuration.user_agent {
285        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
286    }
287    if let Some(ref token) = configuration.bearer_access_token {
288        req_builder = req_builder.bearer_auth(token.to_owned());
289    };
290
291    let req = req_builder.build()?;
292    let resp = configuration.client.execute(req).await?;
293
294    let status = resp.status();
295    let content_type = resp
296        .headers()
297        .get("content-type")
298        .and_then(|v| v.to_str().ok())
299        .unwrap_or("application/octet-stream");
300    let content_type = super::ContentType::from(content_type);
301
302    if !status.is_client_error() && !status.is_server_error() {
303        let content = resp.text().await?;
304        match content_type {
305            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
306            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Leaderboard`"))),
307            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::Leaderboard`")))),
308        }
309    } else {
310        let content = resp.text().await?;
311        let entity: Option<GetBenchmarkLeaderboardError> = serde_json::from_str(&content).ok();
312        Err(Error::ResponseError(ResponseContent { status, content, entity }))
313    }
314}
315
316/// Are the router blends available to compose from — a named set of model arms, the rank they escalate through and the panel width that bounds fan-out — each served by the model layer as enso-<name>.  Today it answers exactly one row, the reference blend: a worked example written in models we name, published as an example of the FORM. It is deliberately not the composition of a Hanzo-served tier — the tier name exists to abstract that — so fork it and swap arms by what the leaderboard measures on your own tasks rather than reading it as a disclosure.
317pub async fn get_benchmark_presets(configuration: &configuration::Configuration, ) -> Result<models::PresetList, Error<GetBenchmarkPresetsError>> {
318
319    let uri_str = format!("{}/v1/benchmark/presets", configuration.base_path);
320    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
321
322    if let Some(ref user_agent) = configuration.user_agent {
323        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
324    }
325    if let Some(ref token) = configuration.bearer_access_token {
326        req_builder = req_builder.bearer_auth(token.to_owned());
327    };
328
329    let req = req_builder.build()?;
330    let resp = configuration.client.execute(req).await?;
331
332    let status = resp.status();
333    let content_type = resp
334        .headers()
335        .get("content-type")
336        .and_then(|v| v.to_str().ok())
337        .unwrap_or("application/octet-stream");
338    let content_type = super::ContentType::from(content_type);
339
340    if !status.is_client_error() && !status.is_server_error() {
341        let content = resp.text().await?;
342        match content_type {
343            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
344            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PresetList`"))),
345            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::PresetList`")))),
346        }
347    } else {
348        let content = resp.text().await?;
349        let entity: Option<GetBenchmarkPresetsError> = serde_json::from_str(&content).ok();
350        Err(Error::ResponseError(ResponseContent { status, content, entity }))
351    }
352}
353
354/// Records published claims: one to correct a number, many to import a leaderboard. Every row must carry a Source, because a claim without its citation is a number nobody can check — and an unattributed number in the published plane is indistinguishable from a measurement, which is the one confusion this whole surface is built to prevent.  Writes are append-only, so this never destroys the value it replaces. A vendor restating a score leaves both rows on disk, which is how the restating itself becomes visible.
355pub async fn post_benchmark_claims(configuration: &configuration::Configuration, put_claims_in: models::PutClaimsIn) -> Result<models::PutClaimsOut, Error<PostBenchmarkClaimsError>> {
356    // add a prefix to parameters to efficiently prevent name collisions
357    let p_put_claims_in = put_claims_in;
358
359    let uri_str = format!("{}/v1/benchmark/claims", configuration.base_path);
360    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
361
362    if let Some(ref user_agent) = configuration.user_agent {
363        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
364    }
365    if let Some(ref token) = configuration.bearer_access_token {
366        req_builder = req_builder.bearer_auth(token.to_owned());
367    };
368    req_builder = req_builder.json(&p_put_claims_in);
369
370    let req = req_builder.build()?;
371    let resp = configuration.client.execute(req).await?;
372
373    let status = resp.status();
374    let content_type = resp
375        .headers()
376        .get("content-type")
377        .and_then(|v| v.to_str().ok())
378        .unwrap_or("application/octet-stream");
379    let content_type = super::ContentType::from(content_type);
380
381    if !status.is_client_error() && !status.is_server_error() {
382        let content = resp.text().await?;
383        match content_type {
384            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
385            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PutClaimsOut`"))),
386            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::PutClaimsOut`")))),
387        }
388    } else {
389        let content = resp.text().await?;
390        let entity: Option<PostBenchmarkClaimsError> = serde_json::from_str(&content).ok();
391        Err(Error::ResponseError(ResponseContent { status, content, entity }))
392    }
393}
394
395/// Validates a router blend — its name, its arms, the rank they escalate through and the panel fan-out width — and answers 202 with the preset and the enso-<name> it would be served as.  It VALIDATES AND ECHOES: the definition is not persisted yet, so a preset accepted here is not one the model layer will resolve. Treat the response as a check on the blend, not a promise to serve it.  Defaults fill the shape rather than refusing it: an omitted rank becomes the arms in declared order and a panel below 1 becomes 1. The one real invariant is that rank may only name arms the blend declares — the same rule the model catalog enforces — and a rank naming anything else is a 422 listing exactly which entries were undeclared. A blend with no name or no arms is a 400.
396pub async fn post_benchmark_presets(configuration: &configuration::Configuration, preset: models::Preset) -> Result<models::PresetAccepted, Error<PostBenchmarkPresetsError>> {
397    // add a prefix to parameters to efficiently prevent name collisions
398    let p_preset = preset;
399
400    let uri_str = format!("{}/v1/benchmark/presets", configuration.base_path);
401    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
402
403    if let Some(ref user_agent) = configuration.user_agent {
404        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
405    }
406    if let Some(ref token) = configuration.bearer_access_token {
407        req_builder = req_builder.bearer_auth(token.to_owned());
408    };
409    req_builder = req_builder.json(&p_preset);
410
411    let req = req_builder.build()?;
412    let resp = configuration.client.execute(req).await?;
413
414    let status = resp.status();
415    let content_type = resp
416        .headers()
417        .get("content-type")
418        .and_then(|v| v.to_str().ok())
419        .unwrap_or("application/octet-stream");
420    let content_type = super::ContentType::from(content_type);
421
422    if !status.is_client_error() && !status.is_server_error() {
423        let content = resp.text().await?;
424        match content_type {
425            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
426            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::PresetAccepted`"))),
427            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::PresetAccepted`")))),
428        }
429    } else {
430        let content = resp.text().await?;
431        let entity: Option<PostBenchmarkPresetsError> = serde_json::from_str(&content).ok();
432        Err(Error::ResponseError(ResponseContent { status, content, entity }))
433    }
434}
435
436/// Admits and queues a benchmark run against a model or your own endpoint, and answers 202 with the receipt.  It is an ADMISSION, not a result: the work is done by the harness afterwards and the numbers appear on the leaderboard as it completes them.  Cost is bounded by the store rather than by a quota: attempts are append-only and keyed by (benchmark, item, model), so an (item, model) pair already attempted is skipped instead of re-spent, and re-queuing the same run is close to free.  Validation is up front and total — a request with neither model nor endpoint is a 400, one with no benchmarks is a 400, and any benchmark id outside the catalog is a 422 naming exactly which ids were unknown, so a typo never silently queues a partial run.
437pub async fn post_benchmark_runs(configuration: &configuration::Configuration, suite: models::Suite) -> Result<models::Admission, Error<PostBenchmarkRunsError>> {
438    // add a prefix to parameters to efficiently prevent name collisions
439    let p_suite = suite;
440
441    let uri_str = format!("{}/v1/benchmark/runs", configuration.base_path);
442    let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
443
444    if let Some(ref user_agent) = configuration.user_agent {
445        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
446    }
447    if let Some(ref token) = configuration.bearer_access_token {
448        req_builder = req_builder.bearer_auth(token.to_owned());
449    };
450    req_builder = req_builder.json(&p_suite);
451
452    let req = req_builder.build()?;
453    let resp = configuration.client.execute(req).await?;
454
455    let status = resp.status();
456    let content_type = resp
457        .headers()
458        .get("content-type")
459        .and_then(|v| v.to_str().ok())
460        .unwrap_or("application/octet-stream");
461    let content_type = super::ContentType::from(content_type);
462
463    if !status.is_client_error() && !status.is_server_error() {
464        let content = resp.text().await?;
465        match content_type {
466            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
467            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Admission`"))),
468            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::Admission`")))),
469        }
470    } else {
471        let content = resp.text().await?;
472        let entity: Option<PostBenchmarkRunsError> = serde_json::from_str(&content).ok();
473        Err(Error::ResponseError(ResponseContent { status, content, entity }))
474    }
475}
476