arqen 0.3.0

Backend infrastructure for agent-ready applications
Documentation
use crate::core::error::CorrelationId;
use crate::http::RuntimeInfo;
use axum::{Json, extract::Extension, http::StatusCode, response::IntoResponse};
use serde_json::{Value, json};

pub async fn health(Extension(correlation_id): Extension<CorrelationId>) -> impl IntoResponse {
    let body = Json(json!({
        "status": "ok",
        "correlation_id": correlation_id.to_string()
    }));
    (StatusCode::OK, body)
}

pub async fn ready(
    Extension(runtime): Extension<RuntimeInfo>,
    Extension(correlation_id): Extension<CorrelationId>,
) -> impl IntoResponse {
    let status = if runtime.thingd_ready {
        StatusCode::OK
    } else {
        StatusCode::SERVICE_UNAVAILABLE
    };
    let body = Json(json!({
        "status": if runtime.thingd_ready { "ready" } else { "not_ready" },
        "storage_mode": runtime.storage_mode,
        "checks": { "thingd": if runtime.thingd_ready { "ok" } else { "unavailable" } },
        "correlation_id": correlation_id.to_string()
    }));
    (status, body)
}

pub async fn agent(
    Extension(runtime): Extension<RuntimeInfo>,
    Extension(correlation_id): Extension<CorrelationId>,
) -> impl IntoResponse {
    let manifest = runtime.registry.generate_manifest();
    let body = Json(json!({
        "name": manifest.name,
        "version": manifest.version,
        "description": manifest.description,
        "storage_mode": manifest.storage_mode,
        "tools_count": manifest.tools.len(),
        "jobs_count": manifest.jobs.len(),
        "endpoints_count": manifest.endpoints.len(),
        "correlation_id": correlation_id.to_string()
    }));
    (StatusCode::OK, body)
}

pub async fn agent_manifest(
    Extension(runtime): Extension<RuntimeInfo>,
    Extension(correlation_id): Extension<CorrelationId>,
) -> impl IntoResponse {
    let manifest = runtime.registry.generate_manifest();
    let tools: Vec<Value> = manifest
        .tools
        .iter()
        .map(|t| {
            json!({
                "name": t.name,
                "description": t.description,
                "input": t.input,
                "output": t.output,
                "scopes": t.scopes,
                "effect": format!("{:?}", t.effect),
                "idempotent": t.idempotent,
                "enqueues_job": t.enqueues_job,
                "timeout": t.timeout
            })
        })
        .collect();

    let jobs: Vec<Value> = manifest
        .jobs
        .iter()
        .map(|j| {
            json!({
                "name": j.name,
                "queue": j.queue,
                "description": j.description,
                "max_retries": j.max_retries,
                "timeout": j.timeout
            })
        })
        .collect();

    let endpoints: Vec<Value> = manifest
        .endpoints
        .iter()
        .map(|e| {
            json!({
                "path": e.path,
                "method": e.method,
                "description": e.description,
                "authenticated": e.authenticated
            })
        })
        .collect();

    let body = Json(json!({
        "name": manifest.name,
        "version": manifest.version,
        "description": manifest.description,
        "storage_mode": manifest.storage_mode,
        "tools": tools,
        "jobs": jobs,
        "endpoints": endpoints,
        "correlation_id": correlation_id.to_string()
    }));
    (StatusCode::OK, body)
}

pub async fn docs(Extension(correlation_id): Extension<CorrelationId>) -> axum::response::Html<String> {
    axum::response::Html(
        format!(
            r#"<!DOCTYPE html>
<html>
<head>
    <title>Arqen API Documentation</title>
    <style>
        body {{ font-family: sans-serif; margin: 40px; }}
        h1 {{ color: #333; }}
        .endpoint {{ margin: 20px 0; padding: 10px; border: 1px solid #ddd; border-radius: 5px; }}
        .method {{ font-weight: bold; color: #007bff; }}
        .path {{ font-family: monospace; }}
        .correlation-id {{ font-family: monospace; color: #666; font-size: 0.9em; }}
    </style>
</head>
<body>
    <h1>Arqen API Documentation</h1>
    <p class="correlation-id">Request ID: {}</p>
    <div class="endpoint">
        <span class="method">GET</span> <span class="path">/health</span>
        <p>Liveness check</p>
    </div>
    <div class="endpoint">
        <span class="method">GET</span> <span class="path">/ready</span>
        <p>Readiness check</p>
    </div>
    <div class="endpoint">
        <span class="method">GET</span> <span class="path">/agent</span>
        <p>Agent description</p>
    </div>
    <div class="endpoint">
        <span class="method">GET</span> <span class="path">/agent/manifest</span>
        <p>Agent manifest with tool definitions</p>
    </div>
    <div class="endpoint">
        <span class="method">GET</span> <span class="path">/docs</span>
        <p>This documentation page</p>
    </div>
</body>
</html>"#,
            correlation_id
        )
        .to_string(),
    )
}