Skip to main content
Glama
args.rs7.6 kB
use std::{ net::SocketAddr, path::PathBuf, time::Duration, }; use clap::{ ArgAction, Parser, }; use cyclone_server::{ Config, ConfigError, IncomingStream, }; const NAME: &str = "cyclone"; /// Parse, validate, and return the CLI arguments as a typed struct. pub(crate) fn parse() -> Args { Args::parse() } /// A function dispatch executor. /// /// Cyclone is a software component of the System Initiative which handles requested execution of /// small functions in a backing language server. #[derive(Debug, Parser)] #[command(name = NAME, max_term_width = 100)] #[allow(clippy::struct_excessive_bools)] pub(crate) struct Args { /// Sets the verbosity mode. /// /// Multiple -v options increase verbosity. The maximum is 6. #[arg(short = 'v', long = "verbose", action = ArgAction::Count)] pub(crate) verbose: u8, /// Disables ANSI coloring in log output, even if standard output refers to a terminal/TTY. /// /// For more details, visit: <http://no-color.org/>. #[arg( long = "no-color", default_value = "false", env = "SI_NO_COLOR", hide_env_values = true, conflicts_with = "force_color" )] pub(crate) no_color: bool, /// Forces ANSI coloring, even if standard output refers to a terminal/TTY. /// /// For more details, visit: <http://no-color.org/>. #[arg( long = "force-color", default_value = "false", env = "SI_FORCE_COLOR", hide_env_values = true, conflicts_with = "no_color" )] pub(crate) force_color: bool, /// Prints telemetry logging as JSON lines. /// /// For more details, visit: <https://jsonlines.org/>. #[arg( long = "log-json", default_value = "false", env = "SI_LOG_JSON", hide_env_values = true )] pub(crate) log_json: bool, /// Additionally appends logging to rolling files under the given directory. #[arg( long = "log-file-directory", env = "SI_LOG_FILE_DIRECTORY", hide_env_values = true )] pub(crate) log_file_directory: Option<PathBuf>, /// Enables support for emitting async runtime data to `tokio-console`. /// /// For more details, visit: <https://github.com/tokio-rs/console>. #[arg( long = "tokio-console", default_value = "false", env = "SI_TOKIO_CONSOLE", hide_env_values = true )] pub(crate) tokio_console: bool, /// Binds service to a socket address [example: 0.0.0.0:5157] #[arg(long, group = "bind")] pub(crate) bind_addr: Option<SocketAddr>, /// Binds service to a unix domain socket [example: /var/run/cyclone.sock] #[arg(long, group = "bind")] pub(crate) bind_uds: Option<PathBuf>, /// Binds service to a vsock socket [example: 3:52] #[arg(long, group = "bind")] pub(crate) bind_vsock: Option<String>, /// Enables active/watch behavior. #[arg(long, group = "watch")] pub(crate) enable_watch: bool, /// Disables active/watch behavior. #[arg(long, group = "watch")] pub(crate) disable_watch: bool, /// Active/watch timeout in seconds. #[arg(long, default_value = "10")] pub(crate) watch_timeout: u64, /// Enables ping endpoint. #[arg(long, group = "ping")] pub(crate) enable_ping: bool, /// Disables ping endpoint. #[arg(long, group = "ping")] pub(crate) disable_ping: bool, /// Enables resolver endpoint. #[arg(long, group = "resolver")] pub(crate) enable_resolver: bool, /// Disables resolver endpoint. #[arg(long, group = "resolver")] pub(crate) disable_resolver: bool, /// Enables command run endpoint. #[arg(long, group = "action_run")] pub(crate) enable_action_run: bool, /// Disables command run endpoint. #[arg(long, group = "action_run")] pub(crate) disable_action_run: bool, /// Enables configuration endpoint. #[arg(long, group = "configuration")] pub(crate) enable_configuration: bool, /// Disables configuration endpoint. #[arg(long, group = "configuration")] pub(crate) disable_configuration: bool, /// Path to the lang server program. #[arg(long, env = "SI_LANG_SERVER", hide_env = true)] pub(crate) lang_server: PathBuf, /// Overrides the default function timeout of the lang server program. #[arg(long)] pub(crate) lang_server_function_timeout: Option<usize>, /// Limits execution requests to 1 before shutting down #[arg(long, group = "request_limiting")] pub(crate) oneshot: bool, /// Limits execution requests to the given value before shutting down #[arg(long, group = "request_limiting")] pub(crate) limit_requests: Option<u32>, /// Enables vsock forwarder. #[arg(long, group = "forwarder")] pub(crate) enable_forwarder: bool, /// Disables vsock forwarder. #[arg(long, group = "forwarder")] pub(crate) disable_forwarder: bool, /// Enables process gatherer. #[arg(long, group = "gatherer")] pub(crate) enable_process_gatherer: bool, /// Disables process gatherer. #[arg(long, group = "gatherer")] pub(crate) disable_process_gatherer: bool, } impl TryFrom<Args> for Config { type Error = ConfigError; fn try_from(args: Args) -> Result<Self, Self::Error> { let mut builder = Self::builder(); if let Some(socket_addr) = args.bind_addr { builder.incoming_stream(IncomingStream::HTTPSocket(socket_addr)); } if let Some(pathbuf) = args.bind_uds { builder.incoming_stream(IncomingStream::UnixDomainSocket(pathbuf)); } #[cfg(target_os = "linux")] if let Some(addr) = args.bind_vsock { // todo(scott): check the format before attempting to parse let split = addr.split(':').collect::<Vec<&str>>(); let vsock_addr = cyclone_server::VsockAddr::new( split[0].parse::<u32>().unwrap(), split[1].parse::<u32>().unwrap(), ); builder.incoming_stream(IncomingStream::VsockSocket(vsock_addr)); } builder.try_lang_server_path(args.lang_server)?; builder.lang_server_function_timeout(args.lang_server_function_timeout); if args.enable_watch { builder.watch(Some(Duration::from_secs(args.watch_timeout))); } else if args.disable_watch { builder.watch(None); } if args.enable_ping { builder.enable_ping(true); } else if args.disable_ping { builder.enable_ping(false); } if args.enable_resolver { builder.enable_resolver(true); } else if args.disable_resolver { builder.enable_resolver(false); } if args.oneshot { builder.limit_requests(1); } else if let Some(limit_requests) = args.limit_requests { builder.limit_requests(limit_requests); } if args.enable_forwarder { builder.enable_forwarder(true); } else if args.disable_forwarder { builder.enable_forwarder(false); } if args.enable_process_gatherer { builder.enable_process_gatherer(true); } else if args.disable_process_gatherer { builder.enable_forwarder(false); } builder.build().map_err(Into::into) } } #[cfg(test)] mod tests { use super::*; #[test] fn verify_command() { use clap::CommandFactory; Args::command().debug_assert() } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/systeminit/si'

If you have feedback or need assistance with the MCP directory API, please join our Discord server