use std::path::PathBuf;
use std::sync::Arc;
use agentstatedeveloper_core::Engine;
use agentstatedeveloper_mcp::build_router;
use anyhow::{Context, Result};
use tokio::sync::Mutex;
#[tokio::main]
async fn main() -> Result<()> {
tracing_subscriber::fmt()
.with_env_filter(
tracing_subscriber::EnvFilter::try_from_default_env()
.unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info,tower_http=info")),
)
.init();
let db_path =
PathBuf::from(std::env::var("ASD_DB").unwrap_or_else(|_| "./.asd-state.db".to_string()));
let addr = std::env::var("ASD_SERVE_ADDR").unwrap_or_else(|_| "0.0.0.0:4120".to_string());
let lens_dir = std::env::var("ASD_LENS_DIR").ok().map(PathBuf::from);
let cors_permissive = std::env::var("ASD_CORS_PERMISSIVE")
.map(|v| v == "1" || v.eq_ignore_ascii_case("true"))
.unwrap_or(false);
tracing::info!(?db_path, %addr, ?lens_dir, "starting asd-serve");
let engine = Engine::open_sqlite(&db_path)
.with_context(|| format!("failed to open ASD db at {}", db_path.display()))?;
let audit_log_path: Option<PathBuf> = std::env::var("ASD_AUDIT_LOG").ok().map(PathBuf::from);
if audit_log_path.is_some() {
tracing::warn!(
"ASD_AUDIT_LOG set but asd-serve is OSS — no new events \
will be written (tamper-evident sink is a commercial \
feature; install asd-pro). Existing logs are readable \
via /audit."
);
}
let shared = Arc::new(Mutex::new(engine));
let app = build_router(shared, db_path, lens_dir, audit_log_path, cors_permissive);
let listener = tokio::net::TcpListener::bind(&addr)
.await
.with_context(|| format!("failed to bind {}", addr))?;
let bound = listener
.local_addr()
.map(|a| a.to_string())
.unwrap_or_else(|_| addr.clone());
tracing::info!("listening on {}", bound);
axum::serve(listener, app).await?;
Ok(())
}