lazyBoy/crates/api/src/main.rs

84 lines
2.5 KiB
Rust
Raw Normal View History

2026-09-03 23:43:37 +00:00
mod auth;
2026-09-03 12:46:14 +00:00
mod computer;
mod db;
2026-09-04 05:41:09 +00:00
mod mcp;
2026-09-04 09:08:56 +00:00
mod mcp_catalog;
2026-09-03 23:43:37 +00:00
mod memory;
2026-09-04 05:41:09 +00:00
mod rooms;
2026-09-03 12:46:14 +00:00
mod routes;
mod runs;
mod screen_proxy;
2026-09-03 23:43:37 +00:00
mod sessions;
2026-09-03 12:46:14 +00:00
mod state;
mod tools;
2026-09-04 09:08:56 +00:00
mod workspace;
2026-09-03 12:46:14 +00:00
use std::net::SocketAddr;
use std::sync::Arc;
use axum::Router;
use state::AppState;
use tower_http::services::ServeDir;
use tracing_subscriber::EnvFilter;
#[tokio::main]
async fn main() {
let _ = dotenvy::dotenv();
2026-09-04 09:08:56 +00:00
let _ =
dotenvy::from_path(std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../../.env"));
2026-09-03 12:46:14 +00:00
tracing_subscriber::fmt()
.with_env_filter(EnvFilter::from_default_env().add_directive("info".parse().unwrap()))
.init();
if std::env::var("XAI_API_KEY")
.ok()
.filter(|value| !value.is_empty())
.is_none()
{
tracing::warn!("XAI_API_KEY is not set; chat will fail until it is");
}
let database_url = std::env::var("DATABASE_URL")
.unwrap_or_else(|_| "postgres://lazyboy:lazyboy@127.0.0.1:5434/lazyboy".into());
2026-09-04 09:08:56 +00:00
let state = AppState::connect(&database_url).await.expect("database");
2026-09-04 05:41:09 +00:00
let actor = state.bootstrap().await.expect("bootstrap");
let mcp_state = state.clone();
tokio::spawn(async move {
mcp_state.mcp.reconnect_all(mcp_state.pool(), &actor).await;
});
2026-09-03 12:46:14 +00:00
let worker_state = state.clone();
tokio::spawn(async move {
runs::worker_loop(worker_state).await;
});
let idle_state = state.clone();
tokio::spawn(async move {
computer::idle_loop(idle_state).await;
});
2026-09-03 23:43:37 +00:00
let bind = std::env::var("API_BIND").unwrap_or_else(|_| "127.0.0.1:3101".into());
let addr: SocketAddr = bind.parse().expect("API_BIND");
if !addr.ip().is_loopback() && !state.auth.strong_enough_for_network() {
2026-09-04 09:08:56 +00:00
panic!(
"LAZYBOY_APP_TOKEN must be set to at least 32 characters when API_BIND is not loopback"
);
2026-09-03 23:43:37 +00:00
}
2026-09-03 12:46:14 +00:00
let web_dir = std::env::var("LAZYBOY_WEB_DIR").unwrap_or_else(|_| "apps/web".into());
let app = Router::new()
2026-09-04 09:08:56 +00:00
.route(
"/api/health",
axum::routing::get(|| async { axum::Json(serde_json::json!({"ok": true})) }),
)
2026-09-03 23:43:37 +00:00
.merge(auth::public_router(state.clone()))
2026-09-03 12:46:14 +00:00
.merge(routes::router(state))
2026-09-03 23:43:37 +00:00
.fallback_service(ServeDir::new(web_dir));
2026-09-03 12:46:14 +00:00
tracing::info!("api listening on {addr}");
let listener = tokio::net::TcpListener::bind(addr).await.expect("bind");
axum::serve(listener, app).await.expect("serve");
}
fn _keep_arc() {
let _: Option<Arc<()>> = None;
}