use anyhow::Result;
use crate::Client;
#[derive(Clone, Debug, Default)]
pub struct ListTextToCadPartsForUserParams {
pub conversation_id: Option<uuid::Uuid>,
pub limit: Option<u32>,
pub no_models: Option<bool>,
pub no_parts: Option<bool>,
pub page_token: Option<String>,
pub sort_by: Option<crate::types::CreatedAtSortMode>,
}
#[derive(Clone, Debug)]
pub struct Ml {
pub client: Client,
}
impl Ml {
#[doc(hidden)]
pub fn new(client: Client) -> Self {
Self { client }
}
#[doc = "List conversations\n\nThis endpoint requires authentication by any Zoo user. It returns the conversations for the authenticated user.\n\nThe conversations are returned in order of creation, with the most recently created conversations first.\n\n**Parameters:**\n\n- `limit: Option<u32>`: Maximum number of items returned by a single call\n- `page_token: Option<String>`: Token returned by previous call to retrieve the subsequent page\n- `sort_by: Option<crate::types::CreatedAtSortMode>`\n\n```rust,no_run\nuse futures_util::TryStreamExt;\nasync fn example_ml_list_conversations_for_user_stream() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let mut ml = client.ml();\n let mut stream = ml.list_conversations_for_user_stream(\n Some(4 as u32),\n Some(kittycad::types::CreatedAtSortMode::CreatedAtDescending),\n );\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn list_conversations_for_user<'a>(
&'a self,
limit: Option<u32>,
page_token: Option<String>,
sort_by: Option<crate::types::CreatedAtSortMode>,
) -> Result<crate::types::ConversationResultsPage, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::GET,
format!("{}/{}", self.client.base_url, "ml/conversations"),
);
req = req.bearer_auth(&self.client.token);
let mut query_params = vec![];
if let Some(p) = limit {
query_params.push(("limit", format!("{}", p)));
}
if let Some(p) = page_token {
query_params.push(("page_token", p));
}
if let Some(p) = sort_by {
query_params.push(("sort_by", format!("{}", p)));
}
req = req.query(&query_params);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "List conversations\n\nThis endpoint requires authentication by any Zoo user. It returns the conversations for the authenticated user.\n\nThe conversations are returned in order of creation, with the most recently created conversations first.\n\n**Parameters:**\n\n- `limit: Option<u32>`: Maximum number of items returned by a single call\n- `page_token: Option<String>`: Token returned by previous call to retrieve the subsequent page\n- `sort_by: Option<crate::types::CreatedAtSortMode>`\n\n```rust,no_run\nuse futures_util::TryStreamExt;\nasync fn example_ml_list_conversations_for_user_stream() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let mut ml = client.ml();\n let mut stream = ml.list_conversations_for_user_stream(\n Some(4 as u32),\n Some(kittycad::types::CreatedAtSortMode::CreatedAtDescending),\n );\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
#[tracing::instrument]
#[cfg(not(feature = "js"))]
pub fn list_conversations_for_user_stream<'a>(
&'a self,
limit: Option<u32>,
sort_by: Option<crate::types::CreatedAtSortMode>,
) -> impl futures::Stream<Item = Result<crate::types::Conversation, crate::types::error::Error>>
+ Unpin
+ '_ {
use futures::{StreamExt, TryFutureExt, TryStreamExt};
use crate::types::paginate::Pagination;
let pagination_url_path = ("ml/conversations").to_string();
let mut pagination_query_params: Vec<(&str, String)> = Vec::new();
if let Some(p) = limit.as_ref() {
pagination_query_params.push(("limit", format!("{}", p)));
}
if let Some(p) = sort_by.as_ref() {
pagination_query_params.push(("sort_by", format!("{}", p)));
}
let stream = self
.list_conversations_for_user(limit, None, sort_by)
.map_ok(move |result| {
let items = futures::stream::iter(result.items().into_iter().map(Ok));
let next_pages = futures::stream::try_unfold(
(None, result),
move |(prev_page_token, new_result)| {
let pagination_url_path = pagination_url_path.clone();
let pagination_query_params = pagination_query_params.clone();
async move {
if new_result.has_more_pages()
&& !new_result.items().is_empty()
&& prev_page_token != new_result.next_page_token()
{
async {
let mut req = self.client.client.request(
http::Method::GET,
format!(
"{}/{}",
self.client.base_url,
pagination_url_path.clone()
),
);
req = req.bearer_auth(&self.client.token);
let query_params = pagination_query_params.clone();
req = req.query(&query_params);
let mut request = req.build()?;
request =
new_result.next_page_with_param(request, "page_token")?;
let resp = self.client.client.execute(request).await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(
text.to_string(),
err,
),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
.map_ok(|result: crate::types::ConversationResultsPage| {
Some((
futures::stream::iter(result.items().into_iter().map(Ok)),
(new_result.next_page_token(), result),
))
})
.await
} else {
Ok(None)
}
}
},
)
.try_flatten();
items.chain(next_pages)
})
.try_flatten_stream();
#[cfg(target_arch = "wasm32")]
{
stream.boxed_local()
}
#[cfg(not(target_arch = "wasm32"))]
{
stream.boxed()
}
}
#[doc = "Converts a proprietary CAD format to KCL.\n\nThis endpoint is used to convert a \
proprietary CAD format to KCL. The file passed MUST have feature tree data.\n\nA STEP \
file does not have feature tree data, so it will not work. A sldprt file does have \
feature tree data, so it will work.\n\nThis endpoint is designed to work with any \
native proprietary CAD format, for example: - SolidWorks (.sldprt) - Creo (.prt) - \
Catia (.catpart) - NX (.prt) - Fusion 360 (.f3d)\n\nThis endpoint is deterministic, \
it preserves the original design intent by using the feature tree data. This endpoint \
does not use any machine learning or AI.\n\nThis endpoint is currently in beta, and \
is only available to users with access to the feature. Please contact support if you \
are interested in getting access.\n\nThis endpoint might have limitations and bugs, \
please report any issues you encounter. It will be improved over time.\n\nInput \
filepaths will be normalized and re-canonicalized to be under the current working \
directory -- so returned paths may differ from provided paths, and care must be taken \
when handling user provided paths.\n\n**Parameters:**\n\n- `code_option: \
Option<crate::types::CodeOption>`: The options to run on the code. By default this is \
set to `execute`.\n\n```rust,no_run\nasync fn example_ml_create_proprietary_to_kcl() \
-> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let \
result: kittycad::types::KclModel = client\n .ml()\n \
.create_proprietary_to_kcl(\n vec![kittycad::types::multipart::Attachment \
{\n name: \"thing\".to_string(),\n filepath: \
Some(\"myfile.json\".into()),\n content_type: \
Some(\"application/json\".to_string()),\n data: \
std::fs::read(\"myfile.json\").unwrap(),\n }],\n \
Some(kittycad::types::CodeOption::MockExecute),\n )\n .await?;\n \
println!(\"{:?}\", result);\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn create_proprietary_to_kcl<'a>(
&'a self,
attachments: Vec<crate::types::multipart::Attachment>,
code_option: Option<crate::types::CodeOption>,
) -> Result<crate::types::KclModel, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::POST,
format!(
"{}/{}",
self.client.base_url, "ml/convert/proprietary-to-kcl"
),
);
req = req.bearer_auth(&self.client.token);
let mut query_params = vec![];
if let Some(p) = code_option {
query_params.push(("code_option", format!("{}", p)));
}
req = req.query(&query_params);
use std::convert::TryInto;
let mut form = reqwest::multipart::Form::new();
for attachment in attachments {
form = form.part(attachment.name.clone(), attachment.try_into()?);
}
req = req.multipart(form);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "Create a custom ML model that is backed by one or more org datasets.\n\nDataset \
readiness is enforced via `OrgDatasetFileConversion::status_counts_for_datasets`: - \
At least one conversion must have status `success`. - No conversions may remain in \
`queued`. If even a single file is still queued the dataset is treated as “not ready \
for training.” - A dataset consisting only of `canceled` or `error_*` entries is \
rejected because there’s nothing usable.\n\n```rust,no_run\nuse \
std::str::FromStr;\nasync fn example_ml_create_custom_model() -> anyhow::Result<()> \
{\n let client = kittycad::Client::new_from_env();\n let result: \
kittycad::types::CustomModel = client\n .ml()\n \
.create_custom_model(&kittycad::types::CreateCustomModel {\n dataset_ids: \
vec![uuid::Uuid::from_str(\n \
\"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?],\n name: \
\"some-string\".to_string(),\n system_prompt: \
Some(\"some-string\".to_string()),\n })\n .await?;\n \
println!(\"{:?}\", result);\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn create_custom_model<'a>(
&'a self,
body: &crate::types::CreateCustomModel,
) -> Result<crate::types::CustomModel, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::POST,
format!("{}/{}", self.client.base_url, "ml/custom/models"),
);
req = req.bearer_auth(&self.client.token);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "Retrieve the details of a single custom ML model so long as it belongs to the \
caller’s organization.\n\n**Parameters:**\n\n- `id: uuid::Uuid`: The identifier. \
(required)\n\n```rust,no_run\nuse std::str::FromStr;\nasync fn \
example_ml_get_custom_model() -> anyhow::Result<()> {\n let client = \
kittycad::Client::new_from_env();\n let result: kittycad::types::CustomModel = \
client\n .ml()\n .get_custom_model(uuid::Uuid::from_str(\n \
\"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?)\n .await?;\n \
println!(\"{:?}\", result);\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn get_custom_model<'a>(
&'a self,
id: uuid::Uuid,
) -> Result<crate::types::CustomModel, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::GET,
format!(
"{}/{}",
self.client.base_url,
"ml/custom/models/{id}".replace("{id}", &format!("{}", id))
),
);
req = req.bearer_auth(&self.client.token);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "Update mutable metadata (name, system prompt) for a custom ML model owned by the \
caller's organization.\n\n**Parameters:**\n\n- `id: uuid::Uuid`: The identifier. \
(required)\n\n```rust,no_run\nuse std::str::FromStr;\nasync fn \
example_ml_update_custom_model() -> anyhow::Result<()> {\n let client = \
kittycad::Client::new_from_env();\n let result: kittycad::types::CustomModel = \
client\n .ml()\n .update_custom_model(\n \
uuid::Uuid::from_str(\"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\")?,\n \
&kittycad::types::UpdateCustomModel {\n name: \
Some(\"some-string\".to_string()),\n system_prompt: \
Some(\"some-string\".to_string()),\n },\n )\n .await?;\n \
println!(\"{:?}\", result);\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn update_custom_model<'a>(
&'a self,
id: uuid::Uuid,
body: &crate::types::UpdateCustomModel,
) -> Result<crate::types::CustomModel, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::PUT,
format!(
"{}/{}",
self.client.base_url,
"ml/custom/models/{id}".replace("{id}", &format!("{}", id))
),
);
req = req.bearer_auth(&self.client.token);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "Generate code completions for KCL.\n\n```rust,no_run\nasync fn example_ml_create_kcl_code_completions() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let result: kittycad::types::KclCodeCompletionResponse = client\n .ml()\n .create_kcl_code_completions(&kittycad::types::KclCodeCompletionRequest {\n extra: Some(kittycad::types::KclCodeCompletionParams {\n language: Some(\"some-string\".to_string()),\n next_indent: Some(4 as u8),\n prompt_tokens: Some(4 as u32),\n suffix_tokens: Some(4 as u32),\n trim_by_indentation: true,\n }),\n max_tokens: Some(4 as u16),\n model_version: Some(\"some-string\".to_string()),\n n: Some(4 as u8),\n nwo: Some(\"some-string\".to_string()),\n prompt: Some(\"some-string\".to_string()),\n stop: Some(vec![\"some-string\".to_string()]),\n stream: true,\n suffix: Some(\"some-string\".to_string()),\n temperature: Some(3.14 as f64),\n top_p: Some(3.14 as f64),\n })\n .await?;\n println!(\"{:?}\", result);\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn create_kcl_code_completions<'a>(
&'a self,
body: &crate::types::KclCodeCompletionRequest,
) -> Result<crate::types::KclCodeCompletionResponse, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::POST,
format!("{}/{}", self.client.base_url, "ml/kcl/completions"),
);
req = req.bearer_auth(&self.client.token);
req = req.json(body);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "List text-to-CAD parts you've generated.\n\nThis will always return the STEP file contents as well as the format the user originally requested.\n\nThis endpoint requires authentication by any Zoo user. It returns the text-to-CAD parts for the authenticated user.\n\nThe text-to-CAD parts are returned in order of creation, with the most recently created text-to-CAD parts first.\n\n**Parameters:**\n\n- `conversation_id: Option<uuid::Uuid>`: If specified, only return the prompts for the conversation id given.\n- `limit: Option<u32>`: Maximum number of items returned by a single call\n- `no_models: Option<bool>`: DEPRECATED: This is the same as `no_parts`, and will be dropped in a future release. Please do not use this.\n- `no_parts: Option<bool>`: If we should return the part contents or just the metadata.\n- `page_token: Option<String>`: Token returned by previous call to retrieve the subsequent page\n- `sort_by: Option<crate::types::CreatedAtSortMode>`\n\n```rust,no_run\nuse std::str::FromStr;\nasync fn example_ml_list_text_to_cad_parts_for_user() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let result: kittycad::types::TextToCadResponseResultsPage = client\n .ml()\n .list_text_to_cad_parts_for_user(kittycad::ml::ListTextToCadPartsForUserParams {\n conversation_id: Some(uuid::Uuid::from_str(\n \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?),\n limit: Some(4 as u32),\n no_models: Some(true),\n no_parts: Some(true),\n page_token: Some(\"some-string\".to_string()),\n sort_by: Some(kittycad::types::CreatedAtSortMode::CreatedAtDescending),\n })\n .await?;\n println!(\"{:?}\", result);\n Ok(())\n}\n\n\n/// - OR -\n\n/// Get a stream of results.\n///\n/// This allows you to paginate through all the items.\nuse futures_util::TryStreamExt;\nasync fn example_ml_list_text_to_cad_parts_for_user_stream() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let mut ml = client.ml();\n let mut stream =\n ml.list_text_to_cad_parts_for_user_stream(kittycad::ml::ListTextToCadPartsForUserParams {\n conversation_id: Some(uuid::Uuid::from_str(\n \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?),\n limit: Some(4 as u32),\n no_models: Some(true),\n no_parts: Some(true),\n page_token: Some(\"some-string\".to_string()),\n sort_by: Some(kittycad::types::CreatedAtSortMode::CreatedAtDescending),\n });\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn list_text_to_cad_parts_for_user<'a>(
&'a self,
params: ListTextToCadPartsForUserParams,
) -> Result<crate::types::TextToCadResponseResultsPage, crate::types::error::Error> {
let ListTextToCadPartsForUserParams {
conversation_id,
limit,
no_models,
no_parts,
page_token,
sort_by,
} = params;
let mut req = self.client.client.request(
http::Method::GET,
format!("{}/{}", self.client.base_url, "user/text-to-cad"),
);
req = req.bearer_auth(&self.client.token);
let mut query_params = vec![];
if let Some(p) = conversation_id {
query_params.push(("conversation_id", format!("{}", p)));
}
if let Some(p) = limit {
query_params.push(("limit", format!("{}", p)));
}
if let Some(p) = no_models {
query_params.push(("no_models", format!("{}", p)));
}
if let Some(p) = no_parts {
query_params.push(("no_parts", format!("{}", p)));
}
if let Some(p) = page_token {
query_params.push(("page_token", p));
}
if let Some(p) = sort_by {
query_params.push(("sort_by", format!("{}", p)));
}
req = req.query(&query_params);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "List text-to-CAD parts you've generated.\n\nThis will always return the STEP file contents as well as the format the user originally requested.\n\nThis endpoint requires authentication by any Zoo user. It returns the text-to-CAD parts for the authenticated user.\n\nThe text-to-CAD parts are returned in order of creation, with the most recently created text-to-CAD parts first.\n\n**Parameters:**\n\n- `conversation_id: Option<uuid::Uuid>`: If specified, only return the prompts for the conversation id given.\n- `limit: Option<u32>`: Maximum number of items returned by a single call\n- `no_models: Option<bool>`: DEPRECATED: This is the same as `no_parts`, and will be dropped in a future release. Please do not use this.\n- `no_parts: Option<bool>`: If we should return the part contents or just the metadata.\n- `page_token: Option<String>`: Token returned by previous call to retrieve the subsequent page\n- `sort_by: Option<crate::types::CreatedAtSortMode>`\n\n```rust,no_run\nuse std::str::FromStr;\nasync fn example_ml_list_text_to_cad_parts_for_user() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let result: kittycad::types::TextToCadResponseResultsPage = client\n .ml()\n .list_text_to_cad_parts_for_user(kittycad::ml::ListTextToCadPartsForUserParams {\n conversation_id: Some(uuid::Uuid::from_str(\n \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?),\n limit: Some(4 as u32),\n no_models: Some(true),\n no_parts: Some(true),\n page_token: Some(\"some-string\".to_string()),\n sort_by: Some(kittycad::types::CreatedAtSortMode::CreatedAtDescending),\n })\n .await?;\n println!(\"{:?}\", result);\n Ok(())\n}\n\n\n/// - OR -\n\n/// Get a stream of results.\n///\n/// This allows you to paginate through all the items.\nuse futures_util::TryStreamExt;\nasync fn example_ml_list_text_to_cad_parts_for_user_stream() -> anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n let mut ml = client.ml();\n let mut stream =\n ml.list_text_to_cad_parts_for_user_stream(kittycad::ml::ListTextToCadPartsForUserParams {\n conversation_id: Some(uuid::Uuid::from_str(\n \"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?),\n limit: Some(4 as u32),\n no_models: Some(true),\n no_parts: Some(true),\n page_token: Some(\"some-string\".to_string()),\n sort_by: Some(kittycad::types::CreatedAtSortMode::CreatedAtDescending),\n });\n loop {\n match stream.try_next().await {\n Ok(Some(item)) => {\n println!(\"{:?}\", item);\n }\n Ok(None) => {\n break;\n }\n Err(err) => {\n return Err(err.into());\n }\n }\n }\n\n Ok(())\n}\n```"]
#[tracing::instrument]
#[cfg(not(feature = "js"))]
pub fn list_text_to_cad_parts_for_user_stream<'a>(
&'a self,
params: ListTextToCadPartsForUserParams,
) -> impl futures::Stream<
Item = Result<crate::types::TextToCadResponse, crate::types::error::Error>,
> + Unpin
+ '_ {
use futures::{StreamExt, TryFutureExt, TryStreamExt};
use crate::types::paginate::Pagination;
let mut params = params;
params.page_token = std::default::Default::default();
let params_for_call = params.clone();
let ListTextToCadPartsForUserParams {
conversation_id,
limit,
no_models,
no_parts,
sort_by,
..
} = params;
let pagination_url_path = ("user/text-to-cad").to_string();
let mut pagination_query_params: Vec<(&str, String)> = Vec::new();
if let Some(p) = conversation_id.as_ref() {
pagination_query_params.push(("conversation_id", format!("{}", p)));
}
if let Some(p) = limit.as_ref() {
pagination_query_params.push(("limit", format!("{}", p)));
}
if let Some(p) = no_models.as_ref() {
pagination_query_params.push(("no_models", format!("{}", p)));
}
if let Some(p) = no_parts.as_ref() {
pagination_query_params.push(("no_parts", format!("{}", p)));
}
if let Some(p) = sort_by.as_ref() {
pagination_query_params.push(("sort_by", format!("{}", p)));
}
let stream = self
.list_text_to_cad_parts_for_user(params_for_call)
.map_ok(move |result| {
let items = futures::stream::iter(result.items().into_iter().map(Ok));
let next_pages = futures::stream::try_unfold(
(None, result),
move |(prev_page_token, new_result)| {
let pagination_url_path = pagination_url_path.clone();
let pagination_query_params = pagination_query_params.clone();
async move {
if new_result.has_more_pages()
&& !new_result.items().is_empty()
&& prev_page_token != new_result.next_page_token()
{
async {
let mut req = self.client.client.request(
http::Method::GET,
format!(
"{}/{}",
self.client.base_url,
pagination_url_path.clone()
),
);
req = req.bearer_auth(&self.client.token);
let query_params = pagination_query_params.clone();
req = req.query(&query_params);
let mut request = req.build()?;
request =
new_result.next_page_with_param(request, "page_token")?;
let resp = self.client.client.execute(request).await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(
text.to_string(),
err,
),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
.map_ok(|result: crate::types::TextToCadResponseResultsPage| {
Some((
futures::stream::iter(result.items().into_iter().map(Ok)),
(new_result.next_page_token(), result),
))
})
.await
} else {
Ok(None)
}
}
},
)
.try_flatten();
items.chain(next_pages)
})
.try_flatten_stream();
#[cfg(target_arch = "wasm32")]
{
stream.boxed_local()
}
#[cfg(not(target_arch = "wasm32"))]
{
stream.boxed()
}
}
#[doc = "Get a text-to-CAD response.\n\nThis endpoint requires authentication by any Zoo user. \
The user must be the owner of the text-to-CAD model.\n\n**Parameters:**\n\n- `id: \
uuid::Uuid`: The id of the model to give feedback to. \
(required)\n\n```rust,no_run\nuse std::str::FromStr;\nasync fn \
example_ml_get_text_to_cad_part_for_user() -> anyhow::Result<()> {\n let client = \
kittycad::Client::new_from_env();\n let result: kittycad::types::TextToCadResponse \
= client\n .ml()\n \
.get_text_to_cad_part_for_user(uuid::Uuid::from_str(\n \
\"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\",\n )?)\n .await?;\n \
println!(\"{:?}\", result);\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn get_text_to_cad_part_for_user<'a>(
&'a self,
id: uuid::Uuid,
) -> Result<crate::types::TextToCadResponse, crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::GET,
format!(
"{}/{}",
self.client.base_url,
"user/text-to-cad/{id}".replace("{id}", &format!("{}", id))
),
);
req = req.bearer_auth(&self.client.token);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
let text = resp.text().await.unwrap_or_default();
serde_json::from_str(&text).map_err(|err| {
crate::types::error::Error::from_serde_error(
format_serde_error::SerdeError::new(text.to_string(), err),
status,
)
})
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "Give feedback to a specific ML response.\n\nThis can be a text-to-CAD creation or \
iteration.\n\nThis endpoint requires authentication by any Zoo user. The user must be \
the owner of the ML response, in order to give feedback.\n\n**Parameters:**\n\n- \
`feedback: crate::types::MlFeedback`: The feedback. (required)\n- `id: uuid::Uuid`: \
The id of the model to give feedback to. (required)\n\n```rust,no_run\nuse \
std::str::FromStr;\nasync fn example_ml_create_text_to_cad_part_feedback() -> \
anyhow::Result<()> {\n let client = kittycad::Client::new_from_env();\n \
client\n .ml()\n .create_text_to_cad_part_feedback(\n \
kittycad::types::MlFeedback::Accepted,\n \
uuid::Uuid::from_str(\"d9797f8d-9ad6-4e08-90d7-2ec17e13471c\")?,\n )\n \
.await?;\n Ok(())\n}\n```"]
#[tracing::instrument]
pub async fn create_text_to_cad_part_feedback<'a>(
&'a self,
feedback: crate::types::MlFeedback,
id: uuid::Uuid,
) -> Result<(), crate::types::error::Error> {
let mut req = self.client.client.request(
http::Method::POST,
format!(
"{}/{}",
self.client.base_url,
"user/text-to-cad/{id}".replace("{id}", &format!("{}", id))
),
);
req = req.bearer_auth(&self.client.token);
let query_params = vec![("feedback", format!("{}", feedback))];
req = req.query(&query_params);
let resp = req.send().await?;
let status = resp.status();
if status.is_success() {
Ok(())
} else {
let text = resp.text().await.unwrap_or_default();
Err(crate::types::error::Error::Server {
body: text.to_string(),
status,
})
}
}
#[doc = "Open a websocket to a Zookeeper agent instance.\n\nRemember to authenticate before \
sending messages. [For WebSockets it's a little \
different.](/docs/developer-tools/api/authentication?lang=curl#websockets)\n\nAs with \
all Zoo WebSockets, you must implement a ping-pong interval / heartbeat to keep the \
connection open. This involves a simple `{ type: \"ping\" }` every ~5s and **check \
that a `{ pong: {} } ` is received**.\n\nFor the \"standard experience\" where the \
agent continues off conversations, you'll want to set the `replay` query string param \
to `true` and record \"conversation ids\", which are then passed as the other query \
string parameter.\n\nA list of past conversations can be fetch from \
[/ml/conversations](/docs/developer-tools/api/ml/list-conversations?lang=curl).\n\\
nThe general use-case is to fire off `{ type: \"user\", content: \"my prompt goes \
here\" }` messages and interpret the various message types that return.\n\nNotable \
behavior: **ONLY KCL IS RETURNED.** It's a common misunderstanding that Zookeeper \
returns models in formats such as STEP and STL directly. This is incorrect. All \
outputs are in KCL, which can then be fed into the [Engine \
API](/docs/developer-tools/engine-api) (specifically the `exec_kcl_project` command) \
or the [Zoo CLI](/docs/developer-tools/cli/manual) (`zoo kcl snapshot ...`).\n\nIn \
the future we may add a more direct method, but you can always rely on \
those.\n\n**Parameters:**\n\n- `conversation_id: Option<uuid::Uuid>`: Conversation to \
replay (UUID). Required when `replay` is `true`.\n- `pr: Option<u64>`: Optional Pull \
Request number to route traffic.\n- `replay: Option<bool>`: If `true`, emit MsgPack \
Replay for the specified conversation and continue.\n- `replay_attachment_mode: \
Option<crate::types::MlCopilotReplayAttachmentMode>`: Controls whether replayed \
attachment payloads are sent in full or replaced with metadata that can be used with \
`FetchAttachments`."]
#[tracing::instrument]
#[cfg(not(target_arch = "wasm32"))]
pub async fn copilot_ws<'a>(
&'a self,
conversation_id: Option<uuid::Uuid>,
pr: Option<u64>,
replay: Option<bool>,
replay_attachment_mode: Option<crate::types::MlCopilotReplayAttachmentMode>,
) -> Result<(reqwest::Upgraded, http::HeaderMap), crate::types::error::Error> {
let mut req = self.client.client_http1_only.request(
http::Method::GET,
format!("{}/{}", self.client.base_url, "ws/ml/copilot"),
);
req = req.bearer_auth(&self.client.token);
let mut query_params = vec![];
if let Some(p) = conversation_id {
query_params.push(("conversation_id", format!("{}", p)));
}
if let Some(p) = pr {
query_params.push(("pr", format!("{}", p)));
}
if let Some(p) = replay {
query_params.push(("replay", format!("{}", p)));
}
if let Some(p) = replay_attachment_mode {
query_params.push(("replay_attachment_mode", format!("{}", p)));
}
req = req.query(&query_params);
req = req
.header(reqwest::header::CONNECTION, "Upgrade")
.header(reqwest::header::UPGRADE, "websocket")
.header(reqwest::header::SEC_WEBSOCKET_VERSION, "13")
.header(
reqwest::header::SEC_WEBSOCKET_KEY,
base64::Engine::encode(
&base64::engine::general_purpose::STANDARD,
rand::random::<[u8; 16]>(),
),
);
let resp = req.send().await?;
let headers = resp.headers().clone();
if resp.status().is_client_error() || resp.status().is_server_error() {
let status = resp.status();
let url = resp.url().to_string();
let body = resp
.text()
.await
.unwrap_or_else(|_| "<error reading body>".to_owned());
return Err(crate::types::error::Error::UnexpectedResponse {
url,
status,
body,
headers: Box::new(headers),
});
}
let upgraded = resp
.upgrade()
.await
.map_err(crate::types::error::Error::RequestError)?;
Ok((upgraded, headers))
}
#[doc = "Open a sponsored KCL migration connection. It cannot execute ordinary prompts."]
#[tracing::instrument]
#[cfg(not(target_arch = "wasm32"))]
pub async fn kcl_migration_ws<'a>(
&'a self,
) -> Result<(reqwest::Upgraded, http::HeaderMap), crate::types::error::Error> {
let mut req = self.client.client_http1_only.request(
http::Method::GET,
format!("{}/{}", self.client.base_url, "ws/ml/kcl-migration"),
);
req = req.bearer_auth(&self.client.token);
req = req
.header(reqwest::header::CONNECTION, "Upgrade")
.header(reqwest::header::UPGRADE, "websocket")
.header(reqwest::header::SEC_WEBSOCKET_VERSION, "13")
.header(
reqwest::header::SEC_WEBSOCKET_KEY,
base64::Engine::encode(
&base64::engine::general_purpose::STANDARD,
rand::random::<[u8; 16]>(),
),
);
let resp = req.send().await?;
let headers = resp.headers().clone();
if resp.status().is_client_error() || resp.status().is_server_error() {
let status = resp.status();
let url = resp.url().to_string();
let body = resp
.text()
.await
.unwrap_or_else(|_| "<error reading body>".to_owned());
return Err(crate::types::error::Error::UnexpectedResponse {
url,
status,
body,
headers: Box::new(headers),
});
}
let upgraded = resp
.upgrade()
.await
.map_err(crate::types::error::Error::RequestError)?;
Ok((upgraded, headers))
}
#[doc = "Open a websocket to prompt the ML copilot.\n\n**Parameters:**\n\n- `id: uuid::Uuid`: \
The ID of the async operation. (required)"]
#[tracing::instrument]
#[cfg(not(target_arch = "wasm32"))]
pub async fn reasoning_ws<'a>(
&'a self,
id: uuid::Uuid,
) -> Result<(reqwest::Upgraded, http::HeaderMap), crate::types::error::Error> {
let mut req = self.client.client_http1_only.request(
http::Method::GET,
format!(
"{}/{}",
self.client.base_url,
"ws/ml/reasoning/{id}".replace("{id}", &format!("{}", id))
),
);
req = req.bearer_auth(&self.client.token);
req = req
.header(reqwest::header::CONNECTION, "Upgrade")
.header(reqwest::header::UPGRADE, "websocket")
.header(reqwest::header::SEC_WEBSOCKET_VERSION, "13")
.header(
reqwest::header::SEC_WEBSOCKET_KEY,
base64::Engine::encode(
&base64::engine::general_purpose::STANDARD,
rand::random::<[u8; 16]>(),
),
);
let resp = req.send().await?;
let headers = resp.headers().clone();
if resp.status().is_client_error() || resp.status().is_server_error() {
let status = resp.status();
let url = resp.url().to_string();
let body = resp
.text()
.await
.unwrap_or_else(|_| "<error reading body>".to_owned());
return Err(crate::types::error::Error::UnexpectedResponse {
url,
status,
body,
headers: Box::new(headers),
});
}
let upgraded = resp
.upgrade()
.await
.map_err(crate::types::error::Error::RequestError)?;
Ok((upgraded, headers))
}
}