From 5a26c7c60e0dd1ad1a6a296ebdfd6745ad240069 Mon Sep 17 00:00:00 2001 From: Butterfly Dev Date: Tue, 7 Apr 2026 04:34:53 +0000 Subject: [PATCH] =?UTF-8?q?agent:=20config.rs=20=E2=80=94=20CLI=20args=20(?= =?UTF-8?q?server,=20session,=20fps,=20quality,=20display,=20audio,=20hear?= =?UTF-8?q?tbeat,=20reconnect)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- agent/src/config.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 agent/src/config.rs diff --git a/agent/src/config.rs b/agent/src/config.rs new file mode 100644 index 0000000..a3884d8 --- /dev/null +++ b/agent/src/config.rs @@ -0,0 +1,90 @@ +//! Agent configuration parsed from CLI arguments and environment variables. + +use clap::Parser; +use std::time::Duration; + +/// Butterfly Desktop Agent — captures display from this machine and streams +/// it to a Butterfly server. Also receives and executes HUD commands (mouse, +/// keyboard) from remote viewers for full remote control. +#[derive(Parser, Debug)] +#[command(name = "butterfly-agent", version, about)] +pub struct AgentConfig { + /// WebSocket URL of the Butterfly server. + /// + /// Example: ws://192.168.1.100:8080 + /// The agent will connect to ws:///ws/?client_type=agent + #[arg(long, default_value = "ws://localhost:8080", env = "BUTTERFLY_SERVER")] + pub server: String, + + /// Session ID to connect to. If not provided, the agent will request the + /// server to create a new session via REST API first. + #[arg(long, env = "BUTTERFLY_SESSION_ID")] + pub session_id: Option, + + /// Target capture frame rate (frames per second). + #[arg(long, default_value_t = 30, env = "BUTTERFLY_FPS")] + pub fps: u32, + + /// JPEG encoding quality (1–100). Lower = smaller frames, less quality. + #[arg(long, default_value_t = 60, env = "BUTTERFLY_QUALITY")] + pub quality: u8, + + /// Index of the display to capture (0 = primary, 1 = second, etc.). + #[arg(long, default_value_t = 0, env = "BUTTERFLY_DISPLAY")] + pub display: usize, + + /// Enable audio capture and streaming. + #[arg(long, default_value_t = false, env = "BUTTERFLY_AUDIO")] + pub audio: bool, + + /// Heartbeat interval in seconds. + #[arg(long, default_value_t = 15, env = "BUTTERFLY_HEARTBEAT")] + pub heartbeat_secs: u64, + + /// Reconnection delay in seconds (0 = no reconnect). + #[arg(long, default_value_t = 3, env = "BUTTERFLY_RECONNECT_DELAY")] + pub reconnect_delay_secs: u64, + + /// Maximum reconnection attempts (0 = infinite). + #[arg(long, default_value_t = 0, env = "BUTTERFLY_MAX_RECONNECT")] + pub max_reconnect: u32, +} + +impl AgentConfig { + /// Parse configuration from CLI arguments. + pub fn parse_args() -> Self { + Self::parse() + } + + /// Duration between captured frames. + pub fn frame_interval(&self) -> Duration { + Duration::from_secs_f64(1.0 / self.fps as f64) + } + + /// Duration between heartbeat messages. + pub fn heartbeat_interval(&self) -> Duration { + Duration::from_secs(self.heartbeat_secs) + } + + /// Duration to wait before reconnecting. + pub fn reconnect_delay(&self) -> Duration { + Duration::from_secs(self.reconnect_delay_secs) + } + + /// Build the full WebSocket URL for a given session ID. + pub fn ws_url(&self, session_id: &str) -> String { + format!( + "{}/ws/{}?client_type=agent", + self.server.trim_end_matches('/'), + session_id + ) + } + + /// Build the REST API base URL. + pub fn api_base(&self) -> String { + format!( + "{}/api", + self.server.replace("ws://", "http://").replace("wss://", "https://") + ) + } +}