origin-asset 0.1.0

Rust SDK for Origin platform — asset generation, AI search, and knowledge graph services
Documentation
pub mod types;
pub use types::*;

use serde::Deserialize;
use serde_json::{json, Value};

use crate::error::Result;
use crate::transport::HttpTransport;

#[derive(Debug, Clone)]
pub struct SearchClient {
    pub(crate) transport: HttpTransport,
}

impl SearchClient {
    pub fn new(transport: HttpTransport) -> Self {
        Self { transport }
    }

    pub async fn search(
        &self,
        query: &str,
        options: Option<SearchOptions>,
    ) -> Result<SearchResponse> {
        let options = options.unwrap_or(SearchOptions {
            mode: None,
            model: None,
            split: None,
            num: None,
        });

        let mut body = json!({ "query": query });
        let payload = body
            .as_object_mut()
            .expect("search request payload should be an object");

        if let Some(mode) = options.mode {
            payload.insert("mode".to_string(), serde_json::to_value(mode)?);
        }
        if let Some(model) = options.model {
            payload.insert("model".to_string(), Value::String(model));
        }
        if let Some(split) = options.split {
            payload.insert("split".to_string(), json!(split));
        }
        if let Some(num) = options.num {
            payload.insert("num".to_string(), json!(num));
        }

        self.transport.post("/api/search", &body).await
    }

    pub async fn search_fast(&self, query: &str) -> Result<SearchResponse> {
        self.search(
            query,
            Some(SearchOptions {
                mode: Some(SearchMode::Fast),
                model: None,
                split: None,
                num: None,
            }),
        )
        .await
    }

    pub async fn search_deep(&self, query: &str) -> Result<SearchResponse> {
        self.search(
            query,
            Some(SearchOptions {
                mode: Some(SearchMode::Deep),
                model: None,
                split: None,
                num: None,
            }),
        )
        .await
    }

    pub async fn search_answer(&self, query: &str) -> Result<SearchResponse> {
        self.search(
            query,
            Some(SearchOptions {
                mode: Some(SearchMode::Answer),
                model: None,
                split: None,
                num: None,
            }),
        )
        .await
    }

    pub async fn models(&self) -> Result<Vec<String>> {
        let response: ModelsResponse = self.transport.get("/api/models").await?;
        Ok(response.models)
    }

    pub async fn providers(&self) -> Result<Value> {
        self.transport.get("/api/providers").await
    }

    pub async fn health(&self) -> Result<bool> {
        let payload: Value = self.transport.get("/health").await?;

        let status = payload.get("status").and_then(Value::as_str).or_else(|| {
            payload
                .get("data")
                .and_then(|data| data.get("status"))
                .and_then(Value::as_str)
        });

        Ok(matches!(status, Some("ok")))
    }
}

#[derive(Debug, Deserialize)]
struct ModelsResponse {
    models: Vec<String>,
}