akribes-sdk 0.22.6

Rust client SDK for the Akribes workflow server
Documentation
//! Live-server integration tests. Run with:
//!
//! ```
//! AKRIBES_LIVE_URL=http://127.0.0.1:3001 \
//! AKRIBES_LIVE_TOKEN=test-secret \
//! cargo test -p akribes-sdk --test live -- --ignored --test-threads=1
//! ```
//!
//! Requires a running akribes-server with a wildcard-scoped service token and a
//! clean `projects` table. Skipped unless `AKRIBES_LIVE_URL` is set.

use akribes_sdk::AkribesClient;

fn live_client() -> Option<AkribesClient> {
    let url = std::env::var("AKRIBES_LIVE_URL").ok()?;
    let token = std::env::var("AKRIBES_LIVE_TOKEN").ok()?;
    Some(
        AkribesClient::builder(&url)
            .token(token)
            .name("sdk-live-test")
            .id(uuid::Uuid::new_v4().to_string())
            .build(),
    )
}

#[tokio::test]
#[ignore]
async fn live_full_surface() {
    let client = live_client().expect("set AKRIBES_LIVE_URL + AKRIBES_LIVE_TOKEN");

    let suffix = uuid::Uuid::new_v4().simple().to_string();
    let proj_name = format!("sdk-live-{}", &suffix[..8]);

    // Projects: create, get, update, duplicate, reorder, delete.
    let proj = client.projects().create(&proj_name).await.unwrap();
    let fetched = client.projects().get(proj.id).await.unwrap().unwrap();
    assert_eq!(fetched.name, proj.name);

    let dup = client.projects().duplicate(proj.id).await.unwrap();
    assert_ne!(dup.id, proj.id);

    // Reorder (must include both proj ids plus any pre-existing ones)
    let all: Vec<i64> = client
        .projects()
        .list()
        .await
        .unwrap()
        .into_iter()
        .map(|p| p.id)
        .collect();
    client.projects().reorder(all).await.unwrap();

    // Scripts scoped to the first project.
    let p = client.project(proj.id);
    let script = p.scripts().create("demo", "").await.unwrap();
    let got = p.scripts().get("demo").await.unwrap().unwrap();
    assert_eq!(got.id, script.id);

    let script_copy = p.scripts().duplicate("demo").await.unwrap();
    assert_ne!(script_copy.id, script.id);
    assert!(script_copy.name.starts_with("demo"));

    // Move the copy to the duplicated project
    let moved = p
        .scripts()
        .move_to(&script_copy.name, dup.id)
        .await
        .unwrap();
    assert_eq!(moved.project_id, dup.id);

    // Reorder scripts in the original project.
    let script_ids: Vec<i64> = p
        .scripts()
        .list()
        .await
        .unwrap()
        .into_iter()
        .map(|s| s.id)
        .collect();
    p.scripts().reorder(script_ids).await.unwrap();

    // MCP drift on non-pinned alias returns {drifted:false,reason:"not_pinned"}
    let drift = p.mcp().drift("nope").await.unwrap();
    assert!(!drift.drifted);

    // Clean up
    client.projects().delete(proj.id).await.unwrap();
    client.projects().delete(dup.id).await.unwrap();
}

#[tokio::test]
#[ignore]
async fn live_duplicate_404_surfaces_http_status() {
    let client = live_client().expect("set AKRIBES_LIVE_URL + AKRIBES_LIVE_TOKEN");
    // ID that definitely doesn't exist.
    let err = client.projects().duplicate(99_999_999).await.unwrap_err();
    match err {
        akribes_sdk::AkribesError::HttpStatus { status, .. } => {
            assert!(status == 404 || status == 500, "got {status}");
        }
        other => panic!("expected HttpStatus, got {:?}", other),
    }
}