use anyhow::{Context, Result};
use daemon::persister::{DiskPersister, default_state_dir, migrate_from_claude_coord};
use myko_server::{BlackholePersister, CellServer};
use std::{net::SocketAddr, sync::Arc};
const DEFAULT_BIND: &str = "0.0.0.0:6155";
#[tokio::main]
async fn main() -> Result<()> {
init_logging();
let bind_addr: SocketAddr = std::env::var("MARSHAL_BIND")
.unwrap_or_else(|_| DEFAULT_BIND.to_string())
.parse()?;
marshal_entities::link();
daemon::link();
let state_dir = default_state_dir();
let log_path = state_dir.join("events.jsonl");
if let Err(e) = migrate_from_claude_coord(&log_path) {
log::warn!(
"[migrate] legacy claude-coord log migration failed: {e} \
(continuing with empty {})",
log_path.display(),
);
}
let persister = Arc::new(
DiskPersister::new(&log_path)
.with_context(|| format!("opening event log at {}", log_path.display()))?,
);
log::info!("marshal-daemon event log: {}", log_path.display());
let blackhole: Arc<dyn myko::server::Persister> = Arc::new(BlackholePersister);
let server = CellServer::builder()
.with_bind_addr(bind_addr)
.with_default_persister(persister.clone() as Arc<dyn myko::server::Persister>)
.with_persister_override("Client", blackhole.clone())
.with_persister_override("Server", blackhole)
.build();
let ctx = server.ctx();
let restored = persister
.replay(&ctx)
.with_context(|| format!("replaying event log {}", log_path.display()))?;
log::info!("marshal-daemon restored {restored} entities from disk");
let _watcher = persister
.start_watcher(server.ctx())
.with_context(|| format!("starting watcher on {}", log_path.display()))?;
tokio::spawn(daemon::cleanup::run_sweeper(server.ctx()));
log::info!("marshal-daemon listening on ws://{bind_addr}");
server.run().await.map_err(|e| anyhow::anyhow!(e))?;
Ok(())
}
fn init_logging() {
let mut b = env_logger::Builder::from_default_env();
if std::env::var("RUST_LOG").is_err() {
b.filter_level(log::LevelFilter::Info);
}
b.init();
}