Skip to main content

crabtalk_command/
lib.rs

1pub use anyhow;
2pub use crabtalk_command_codegen::command;
3pub use wcore;
4
5pub mod service;
6pub use service::{Service, install, render_service_template, uninstall, view_logs};
7
8#[cfg(feature = "mcp")]
9pub use axum;
10#[cfg(feature = "mcp")]
11pub use service::{McpService, run_mcp};
12
13/// Shared entry point: init tracing from `RUST_LOG`, build a tokio runtime,
14/// run the given async closure, and exit on error.
15pub fn run<F, Fut>(f: F)
16where
17    F: FnOnce() -> Fut,
18    Fut: std::future::Future<Output = anyhow::Result<()>>,
19{
20    if let Some(level) = std::env::var("RUST_LOG").ok().map(|v| {
21        match v.rsplit('=').next().unwrap_or(&v).to_lowercase().as_str() {
22            "trace" => tracing::Level::TRACE,
23            "debug" => tracing::Level::DEBUG,
24            "info" => tracing::Level::INFO,
25            "error" => tracing::Level::ERROR,
26            _ => tracing::Level::WARN,
27        }
28    }) {
29        tracing_subscriber::fmt()
30            .with_writer(std::io::stderr)
31            .with_max_level(level)
32            .init();
33    }
34
35    let rt = match tokio::runtime::Runtime::new() {
36        Ok(rt) => rt,
37        Err(e) => {
38            eprintln!("Error: failed to create tokio runtime: {e}");
39            std::process::exit(1);
40        }
41    };
42    if let Err(e) = rt.block_on(f()) {
43        eprintln!("Error: {e}");
44        std::process::exit(1);
45    }
46}