pub mod auth;
pub mod middleware;
pub mod routes;
use std::sync::Arc;
use axum::{
routing::{get, post},
Router,
};
use axocoatl_daemon::AxocoatlDaemon;
use tokio::sync::RwLock;
pub type AppState = Arc<RwLock<AxocoatlDaemon>>;
pub fn build_router(state: AppState) -> Router {
Router::new()
.route("/health", get(routes::health))
.route("/health/ready", get(routes::health_ready))
.route("/health/live", get(routes::health_live))
.route("/api/agents", get(routes::list_agents))
.route(
"/api/agents/{agent_id}/execute",
post(routes::execute_agent),
)
.route("/api/agents/{agent_id}/status", get(routes::agent_status))
.route("/api/tokens/report", get(routes::token_report))
.route("/ws", get(routes::ws_handler))
.layer(axum::middleware::from_fn(middleware::request_logging))
.layer(middleware::cors_headers())
.with_state(state)
}
pub async fn serve(daemon: AxocoatlDaemon, host: &str, port: u16) -> std::io::Result<()> {
let state: AppState = Arc::new(RwLock::new(daemon));
serve_shared(state, host, port).await
}
pub async fn serve_shared(state: AppState, host: &str, port: u16) -> std::io::Result<()> {
let app = build_router(state);
let addr = format!("{host}:{port}");
tracing::info!(addr = %addr, "Starting Axocoatl API server");
let listener = tokio::net::TcpListener::bind(&addr).await?;
axum::serve(listener, app).await?;
Ok(())
}