opencrabs 0.5.10

The autonomous, self-improving AI agent. Single Rust binary. Every channel. Recommended: the 40MB prebuilt binary for macOS, Linux and Windows: https://github.com/opencrabs/opencrabs/releases
Documentation
use crate::a2a::handler;
use crate::a2a::server::*;
use axum::body::Body;
use axum::http::Request;
use axum::http::StatusCode;
use tower::ServiceExt;

async fn test_state() -> A2aState {
    use crate::a2a::test_helpers::helpers;

    A2aState {
        task_store: handler::new_task_store(),
        cancel_store: handler::new_cancel_store(),
        host: "127.0.0.1".to_string(),
        port: 18790,
        agent_service: helpers::placeholder_agent_service().await,
        service_context: helpers::placeholder_service_context().await,
        api_key: None,
    }
}

#[tokio::test]
async fn test_health_endpoint() {
    let app = build_router(test_state().await, &[]);
    let req = Request::builder()
        .uri("/a2a/health")
        .body(Body::empty())
        .expect("request");

    let resp = app.oneshot(req).await.expect("response");
    assert_eq!(resp.status(), StatusCode::OK);
}

#[tokio::test]
async fn test_agent_card_endpoint() {
    let app = build_router(test_state().await, &[]);
    let req = Request::builder()
        .uri("/.well-known/agent.json")
        .body(Body::empty())
        .expect("request");

    let resp = app.oneshot(req).await.expect("response");
    assert_eq!(resp.status(), StatusCode::OK);
}

#[tokio::test]
async fn start_server_signals_readiness_once_bound() {
    use crate::a2a::test_helpers::helpers;
    use crate::config::A2aConfig;

    let config = A2aConfig {
        enabled: true,
        bind: "127.0.0.1".into(),
        port: 0,
        allowed_origins: vec![],
        advertise_url: None,
        api_key: None,
    };
    let agent_service = helpers::placeholder_agent_service().await;
    let service_context = helpers::placeholder_service_context().await;
    let (ready_tx, ready_rx) = tokio::sync::oneshot::channel();

    let handle = tokio::spawn(async move {
        let _ = start_server(&config, agent_service, service_context, Some(ready_tx)).await;
    });

    let res = tokio::time::timeout(std::time::Duration::from_secs(5), ready_rx).await;
    handle.abort();

    assert!(res.is_ok(), "Timed out waiting for readiness signal");
    assert!(
        res.unwrap().expect("oneshot channel open").is_ok(),
        "Expected Ok readiness"
    );
}

#[tokio::test]
async fn start_server_signals_refusal_on_gate_failure() {
    use crate::a2a::test_helpers::helpers;
    use crate::config::A2aConfig;

    let config = A2aConfig {
        enabled: true,
        bind: "0.0.0.0".into(),
        port: 0,
        allowed_origins: vec![],
        advertise_url: None,
        api_key: None,
    };
    let agent_service = helpers::placeholder_agent_service().await;
    let service_context = helpers::placeholder_service_context().await;
    let (ready_tx, ready_rx) = tokio::sync::oneshot::channel();

    let res = start_server(&config, agent_service, service_context, Some(ready_tx)).await;
    assert!(res.is_err(), "Expected gate failure to error");

    let ready_res = tokio::time::timeout(std::time::Duration::from_secs(5), ready_rx).await;
    assert!(ready_res.is_ok(), "Timed out waiting for readiness signal");
    assert!(
        ready_res.unwrap().expect("oneshot open").is_err(),
        "Expected Err readiness signal on gate failure"
    );
}

#[tokio::test]
async fn start_server_signals_ready_when_disabled() {
    use crate::a2a::test_helpers::helpers;
    use crate::config::A2aConfig;

    let config = A2aConfig {
        enabled: false,
        bind: "127.0.0.1".into(),
        port: 0,
        allowed_origins: vec![],
        advertise_url: None,
        api_key: None,
    };
    let agent_service = helpers::placeholder_agent_service().await;
    let service_context = helpers::placeholder_service_context().await;
    let (ready_tx, ready_rx) = tokio::sync::oneshot::channel();

    let res = start_server(&config, agent_service, service_context, Some(ready_tx)).await;
    assert!(res.is_ok(), "Expected disabled start_server to succeed");

    let ready_res = tokio::time::timeout(std::time::Duration::from_secs(5), ready_rx).await;
    assert!(ready_res.is_ok(), "Timed out waiting for readiness signal");
    assert!(
        ready_res.unwrap().expect("oneshot open").is_ok(),
        "Expected Ok readiness signal when disabled"
    );
}