mod browse;
mod config;
mod llm;
use std::sync::Arc;
use std::time::Duration;
use ikigai_core::{Fallback, Kernel, Space};
use ikigai_throttle::{Rate, RateLimit};
use ikigai_vocab::TurtleRenderer;
fn main() {
let settings = config::settings();
let browse = settings.browse.as_ref().map(browse::wire);
let sparql_space: Arc<dyn Space> = match &browse {
Some(b) => Arc::new(ikigai_sparql::space_with_store(Arc::clone(&b.store))),
None => Arc::new(ikigai_sparql::space()),
};
let mut spaces: Vec<Arc<dyn Space>> = vec![
Arc::new(ikigai_repo::space()) as Arc<dyn Space>,
Arc::new(ikigai_rdf::space()) as Arc<dyn Space>,
sparql_space,
];
if let Some(b) = browse {
spaces.push(Arc::new(b.space) as Arc<dyn Space>);
spaces.push(Arc::new(llm::space()) as Arc<dyn Space>);
}
let browse_on = spaces.len() > 3;
let curated = Fallback::new(spaces);
let space = RateLimit::new(curated)
.limit("urn:system:exec", Rate::new(30, Duration::from_secs(60)))
.limit("urn:repo:", Rate::new(120, Duration::from_secs(60)))
.limit("urn:llm:", Rate::new(30, Duration::from_secs(60)));
let kernel = Kernel::with_meta_renderer(Arc::new(space), Arc::new(TurtleRenderer));
if let Some(parent) = settings.socket.parent() {
if let Err(e) = std::fs::create_dir_all(parent) {
eprintln!("ikigai-dev: creating {}: {e}", parent.display());
std::process::exit(1);
}
}
eprintln!(
"ikigai-dev: serving the dev seam (repo · rdf · sparql{}; exec ≤ 30/min) on {}",
if browse_on {
" · browse · llm ≤ 30/min"
} else {
""
},
settings.socket.display()
);
eprintln!(
" connect with: ikigai --connect {}",
settings.socket.display()
);
if let Err(e) = ikigai_ipc::serve(kernel, &settings.socket) {
eprintln!("ikigai-dev: serve error: {e}");
std::process::exit(1);
}
}