ai-cortex-sdk 0.1.1

Rust client SDK for AI Cortex server: PAT auth, device binding, software store, offline license (Ed25519), and auto-update (check-update pull + SSE push).
Documentation
use ai_cortex_sdk::{CortexClient, CortexConfig};

/// Demonstrates the PAT-based SDK workflow: browse software -> download -> list devices.
///
/// PAT 由用户在 web 端创建(POST /api/access-tokens)后填入。不再需要 app_key/app_secret 或登录。
#[tokio::main]
async fn main() {
    let server_url = "http://localhost:40404";
    let pat = std::env::args()
        .nth(1)
        .unwrap_or_else(|| "REPLACE_WITH_YOUR_PAT".to_string());

    // software_id:SDK 以哪个软件身份心跳/下载,需与用户持有的有效 auth_record.software_id 一致。
    let software_id = "00000000-0000-0000-0000-000000000000".to_string();

    let config = CortexConfig::new(server_url, pat, software_id).with_timeout(30);
    let client = CortexClient::new(config);

    // --- List Software ---
    println!("=== Software Store ===");
    match client.list_software().await {
        Ok(items) => {
            if items.is_empty() {
                println!("No software available.");
            }
            for (i, item) in items.iter().enumerate() {
                let version_str = item
                    .latest_version
                    .as_ref()
                    .map(|v| format!("v{} ({} bytes)", v.version, v.file_size))
                    .unwrap_or_else(|| "no version".to_string());
                println!(
                    "{}. {}{}  [{}]",
                    i + 1,
                    item.software.name,
                    item.software.description,
                    version_str
                );
            }

            // --- Download first software's latest version ---
            if let Some(item) = items.first() {
                if let Some(version) = &item.latest_version {
                    println!("\n=== Download ===");
                    match client.download(&version.id).await {
                        Ok(info) => {
                            println!(
                                "Download: v{}, size={} bytes\n  URL: {}",
                                info.version, info.file_size, info.download_url
                            );
                        }
                        Err(e) => eprintln!("Download failed: {e}"),
                    }
                }
            }
        }
        Err(e) => eprintln!("List software failed: {e}"),
    }

    // --- List Devices (PAT 所属用户的设备;心跳在后台自动绑定) ---
    println!("\n=== My Devices ===");
    match client.list_devices().await {
        Ok(devices) => {
            if devices.is_empty() {
                println!("No bound devices yet (heartbeat may not have fired yet).");
            }
            for d in devices {
                println!(
                    "- id={}, fingerprint={}, last_active={}",
                    d.id, d.fingerprint, d.last_active_time
                );
            }
        }
        Err(e) => eprintln!("List devices failed: {e}"),
    }
}