mod json;
mod types;
pub use json::{JSON_STREAM_METHODS, JSON_UNARY_METHODS, TYPED_ONLY_METHODS};
pub use types::*;
#[cfg(not(any(target_arch = "wasm32", feature = "web")))]
mod native;
#[cfg(not(any(target_arch = "wasm32", feature = "web")))]
pub use native::*;
#[doc(hidden)]
#[cfg(not(any(target_arch = "wasm32", feature = "web")))]
pub mod support {
use std::future::Future;
use std::time::Instant;
pub async fn run<T, F>(fut: F) -> crate::Result<T>
where
T: Send + 'static,
F: Future<Output = crate::Result<T>> + Send + 'static,
{
crate::native::run(fut).await
}
pub fn spawn<F>(fut: F)
where
F: Future<Output = ()> + Send + 'static,
{
crate::native::runtime().spawn(fut);
}
pub fn record_teleport<T>(
app: &str,
capability: &str,
move_kind: &str,
started: Instant,
r: &crate::Result<T>,
items: u64,
) {
crate::native::telemetry::teleport(app, capability, move_kind, started, r, items)
}
}
#[cfg(any(target_arch = "wasm32", feature = "web"))]
mod web;
#[cfg(any(target_arch = "wasm32", feature = "web"))]
pub use web::*;
uniffi::setup_scaffolding!("cua_sdk");
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, uniffi::Error)]
#[uniffi(flat_error)]
pub enum CuaError {
#[error("invalid argument: {0}")]
InvalidArgument(String),
#[error("invalid placement: {0}")]
InvalidPlacement(String),
#[error("not found: {0}")]
NotFound(String),
#[error("provider not configured: {0}")]
ProviderNotConfigured(String),
#[error("unsupported: {0}")]
Unsupported(String),
#[error("cua-spacesd is not available: {0}")]
SpacesdNotAvailable(String),
#[error("timed out: {0}")]
Timeout(String),
#[error("local runtime: {0}")]
Runtime(String),
#[error("env: {0}")]
Env(String),
#[error("http: {0}")]
Http(String),
#[error("unauthenticated: {0}")]
Unauthenticated(String),
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("transport: {0}")]
Transport(String),
#[error("{0}")]
DaemonNotRunning(String),
#[error("closed: {0}")]
Closed(String),
#[error("capability missing: {0}")]
CapabilityMissing(String),
#[error("host capability missing: {0}")]
HostCapabilityMissing(String),
#[error("teleport refused: {0}")]
TeleportRefused(String),
#[error("internal: {0}")]
Internal(String),
#[error("ambiguous sandbox name: {0}")]
AmbiguousSandbox(String),
#[error("insufficient disk: {0}")]
InsufficientDisk(String),
#[error("image not published: {0}")]
ImageNotPublished(String),
#[error("cancelled: {0}")]
Cancelled(String),
#[error("your cloud: {0}")]
Cloud(String),
}
pub type Result<T, E = CuaError> = std::result::Result<T, E>;
pub const ERRORS_DOC_URL: &str = "https://cua.ai/docs/cua-sdk/reference/errors";
impl CuaError {
pub fn variant(&self) -> &'static str {
match self {
CuaError::InvalidArgument(_) => "InvalidArgument",
CuaError::InvalidPlacement(_) => "InvalidPlacement",
CuaError::NotFound(_) => "NotFound",
CuaError::ProviderNotConfigured(_) => "ProviderNotConfigured",
CuaError::Unsupported(_) => "Unsupported",
CuaError::SpacesdNotAvailable(_) => "SpacesdNotAvailable",
CuaError::Timeout(_) => "Timeout",
CuaError::Runtime(_) => "Runtime",
CuaError::Env(_) => "Env",
CuaError::Http(_) => "Http",
CuaError::Unauthenticated(_) => "Unauthenticated",
CuaError::PermissionDenied(_) => "PermissionDenied",
CuaError::Transport(_) => "Transport",
CuaError::DaemonNotRunning(_) => "DaemonNotRunning",
CuaError::Closed(_) => "Closed",
CuaError::CapabilityMissing(_) => "CapabilityMissing",
CuaError::HostCapabilityMissing(_) => "HostCapabilityMissing",
CuaError::TeleportRefused(_) => "TeleportRefused",
CuaError::Internal(_) => "Internal",
CuaError::AmbiguousSandbox(_) => "AmbiguousSandbox",
CuaError::InsufficientDisk(_) => "InsufficientDisk",
CuaError::ImageNotPublished(_) => "ImageNotPublished",
CuaError::Cancelled(_) => "Cancelled",
CuaError::Cloud(_) => "Cloud",
}
}
pub fn doc_url(&self) -> String {
error_doc_url(self.variant().to_string())
}
}
#[uniffi::export]
pub fn error_doc_url(variant: String) -> String {
let anchor: String = variant
.trim()
.chars()
.filter(char::is_ascii_alphanumeric)
.map(|c| c.to_ascii_lowercase())
.collect();
if anchor.is_empty() {
ERRORS_DOC_URL.to_string()
} else {
format!("{ERRORS_DOC_URL}#{anchor}")
}
}
impl From<serde_json::Error> for CuaError {
fn from(e: serde_json::Error) -> Self {
CuaError::InvalidArgument(format!("json: {e}"))
}
}
pub const VERSION: &str = env!("CUA_SDK_VERSION");
#[uniffi::export]
pub fn cua_sdk_version() -> String {
VERSION.to_string()
}
#[cfg(test)]
mod doc_url_tests {
use super::*;
#[test]
fn every_variant_links_to_its_errors_entry() {
let e = CuaError::InvalidArgument("x".into());
assert_eq!(e.variant(), "InvalidArgument");
assert_eq!(
e.doc_url(),
"https://cua.ai/docs/cua-sdk/reference/errors#invalidargument"
);
assert_eq!(
CuaError::SpacesdNotAvailable(String::new()).doc_url(),
format!("{ERRORS_DOC_URL}#spacesdnotavailable")
);
assert_eq!(error_doc_url(" ".into()), ERRORS_DOC_URL);
assert_eq!(
error_doc_url("InsufficientDisk".into()),
format!("{ERRORS_DOC_URL}#insufficientdisk")
);
}
}
#[cfg(test)]
mod version_tests {
#[test]
fn sdk_version_is_the_released_version() {
let expected = option_env!("CUA_SDK_RELEASE_VERSION")
.map(str::trim)
.filter(|v| !v.is_empty())
.unwrap_or(include_str!("../../../VERSION").trim());
assert_eq!(super::cua_sdk_version(), expected);
assert_ne!(super::cua_sdk_version(), "");
}
}