The file C:\Users\MikeSwanson\Claude\guru-connect\agent\src\config.rs has been updated. Here's the result of running `cat -n` on a snippet of the edited file:
    45→    /// Unknown/default mode
    46→    Default,
    47→}
    48→
    49→/// Agent configuration
    50→#[derive(Debug, Clone, Serialize, Deserialize)]
    51→pub struct Config {
    52→    /// Server WebSocket URL (e.g., wss://connect.example.com/ws)
    53→    pub server_url: String,
    54→
    55→    /// Agent API key for authentication
    56→    pub api_key: String,
    57→
    58→    /// Unique agent identifier (generated on first run)
    59→    #[serde(default = "generate_agent_id")]
    60→    pub agent_id: String,
    61→
    62→    /// Optional hostname override
    63→    pub hostname_override: Option<String>,
    64→
    65→    /// Company/organization name (from embedded config)
    66→    #[serde(default)]
    67→    pub company: Option<String>,
    68→
    69→    /// Site/location name (from embedded config)
    70→    #[serde(default)]
    71→    pub site: Option<String>,
    72→
    73→    /// Tags for categorization (from embedded config)
    74→    #[serde(default)]
    75→    pub tags: Vec<String>,
    76→
    77→    /// Support code for one-time support sessions (set via command line or filename)
    78→    #[serde(skip)]
    79→    pub support_code: Option<String>,
    80→
    81→    /// Capture settings
    82→    #[serde(default)]
    83→    pub capture: CaptureConfig,
    84→
    85→    /// Encoding settings
    86→    #[serde(default)]
    87→    pub encoding: EncodingConfig,
    88→}
    89→
    90→fn generate_agent_id() -> String {
    91→    Uuid::new_v4().to_string()
    92→}

/// Agent configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// Server WebSocket URL (e.g., wss://connect.example.com/ws)
    pub server_url: String,

    /// Agent API key for authentication
    pub api_key: String,

    /// Unique agent identifier (generated on first run)
    #[serde(default = "generate_agent_id")]
    pub agent_id: String,

    /// Optional hostname override
    pub hostname_override: Option<String>,

    /// Company/organization name (from embedded config)
    #[serde(default)]
    pub company: Option<String>,

    /// Site/location name (from embedded config)
    #[serde(default)]
    pub site: Option<String>,

    /// Tags for categorization (from embedded config)
    #[serde(default)]
    pub tags: Vec<String>,

    /// Support code for one-time support sessions (set via command line or filename)
    #[serde(skip)]
    pub support_code: Option<String>,

    /// Capture settings
    #[serde(default)]
    pub capture: CaptureConfig,

    /// Encoding settings
    #[serde(default)]
    pub encoding: EncodingConfig,
}

//! Agent configuration management
//!
//! Supports three configuration sources (in priority order):
//! 1. Embedded config (magic bytes appended to executable)
//! 2. Config file (guruconnect.toml or %ProgramData%\GuruConnect\agent.toml)
//! 3. Environment variables (fallback)

use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use std::io::{Read, Seek, SeekFrom};
use std::path::PathBuf;
use tracing::{info, warn};
use uuid::Uuid;

/// Magic marker for embedded configuration (10 bytes)
const MAGIC_MARKER: &[u8] = b"GURUCONFIG";

/// Embedded configuration data (appended to executable)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmbeddedConfig {
    /// Server WebSocket URL
    pub server_url: String,
    /// API key for authentication
    pub api_key: String,
    /// Company/organization name
    #[serde(default)]
    pub company: Option<String>,
    /// Site/location name
    #[serde(default)]
    pub site: Option<String>,
    /// Tags for categorization
    #[serde(default)]
    pub tags: Vec<String>,
}

/// Detected run mode based on filename
#[derive(Debug, Clone, PartialEq)]
pub enum RunMode {
    /// Viewer-only installation (filename contains "Viewer")
    Viewer,
    /// Temporary support session (filename contains 6-digit code)
    TempSupport(String),
    /// Permanent agent with embedded config
    PermanentAgent,
    /// Unknown/default mode
    Default,
}

/// Agent configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// Server WebSocket URL (e.g., wss://connect.example.com/ws)
    pub server_url: String,

    /// Agent API key for authentication
    pub api_key: String,

    /// Unique agent identifier (generated on first run)
    #[serde(default = "generate_agent_id")]
    pub agent_id: String,

    /// Optional hostname override
    pub hostname_override: Option<String>,

    /// Support code for one-time support sessions (set via command line)
    #[serde(skip)]
    pub support_code: Option<String>,

    /// Capture settings
    #[serde(default)]
    pub capture: CaptureConfig,

    /// Encoding settings
    #[serde(default)]
    pub encoding: EncodingConfig,
}

fn generate_agent_id() -> String {
    Uuid::new_v4().to_string()
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CaptureConfig {
    /// Target frames per second (1-60)
    #[serde(default = "default_fps")]
    pub fps: u32,

    /// Use DXGI Desktop Duplication (recommended)
    #[serde(default = "default_true")]
    pub use_dxgi: bool,

    /// Fall back to GDI if DXGI fails
    #[serde(default = "default_true")]
    pub gdi_fallback: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncodingConfig {
    /// Preferred codec (auto, raw, vp9, h264)
    #[serde(default = "default_codec")]
    pub codec: String,

    /// Quality (1-100, higher = better quality, more bandwidth)
    #[serde(default = "default_quality")]
    pub quality: u32,

    /// Use hardware encoding if available
    #[serde(default = "default_true")]
    pub hardware_encoding: bool,
}

fn default_fps() -> u32 {
    30
}

fn default_true() -> bool {
    true
}

fn default_codec() -> String {
    "auto".to_string()
}

fn default_quality() -> u32 {
    75
}

impl Default for CaptureConfig {
    fn default() -> Self {
        Self {
            fps: default_fps(),
            use_dxgi: true,
            gdi_fallback: true,
        }
    }
}

impl Default for EncodingConfig {
    fn default() -> Self {
        Self {
            codec: default_codec(),
            quality: default_quality(),
            hardware_encoding: true,
        }
    }
}

impl Config {
    /// Check if an explicit agent configuration file exists
    /// This returns true only if there's a real config file, not generated defaults
    pub fn has_agent_config() -> bool {
        // Check for config in current directory
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return true;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return true;
                }
            }
        }

        false
    }

    /// Load configuration from file or environment
    pub fn load() -> Result<Self> {
        // Try loading from config file
        let config_path = Self::config_path();

        if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .with_context(|| format!("Failed to read config from {:?}", config_path))?;

            let mut config: Config = toml::from_str(&contents)
                .with_context(|| "Failed to parse config file")?;

            // Ensure agent_id is set and saved
            if config.agent_id.is_empty() {
                config.agent_id = generate_agent_id();
                let _ = config.save();
            }

            // support_code is always None when loading from file (set via CLI)
            config.support_code = None;

            return Ok(config);
        }

        // Fall back to environment variables
        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());

        let api_key = std::env::var("GURUCONNECT_API_KEY")
            .unwrap_or_else(|_| "dev-key".to_string());

        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
            .unwrap_or_else(|_| generate_agent_id());

        let config = Config {
            server_url,
            api_key,
            agent_id,
            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
            support_code: None, // Set via CLI
            capture: CaptureConfig::default(),
            encoding: EncodingConfig::default(),
        };

        // Save config with generated agent_id for persistence
        let _ = config.save();

        Ok(config)
    }

    /// Get the configuration file path
    fn config_path() -> PathBuf {
        // Check for config in current directory first
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return local_config;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return path;
                }
            }
        }

        // Default to local config
        local_config
    }

    /// Get the hostname to use
    pub fn hostname(&self) -> String {
        self.hostname_override
            .clone()
            .unwrap_or_else(|| {
                hostname::get()
                    .map(|h| h.to_string_lossy().to_string())
                    .unwrap_or_else(|_| "unknown".to_string())
            })
    }

    /// Save current configuration to file
    pub fn save(&self) -> Result<()> {
        let config_path = Self::config_path();

        // Ensure parent directory exists
        if let Some(parent) = config_path.parent() {
            std::fs::create_dir_all(parent)?;
        }

        let contents = toml::to_string_pretty(self)?;
        std::fs::write(&config_path, contents)?;

        Ok(())
    }
}

/// Example configuration file content
pub fn example_config() -> &'static str {
    r#"# GuruConnect Agent Configuration

# Server connection
server_url = "wss://connect.example.com/ws"
api_key = "your-agent-api-key"
agent_id = "auto-generated-uuid"

# Optional: override hostname
# hostname_override = "custom-hostname"

[capture]
fps = 30
use_dxgi = true
gdi_fallback = true

[encoding]
codec = "auto"      # auto, raw, vp9, h264
quality = 75        # 1-100
hardware_encoding = true
"#
}

-    /// Support code for one-time support sessions (set via command line)

+    /// Company/organization name (from embedded config)

+    /// Site/location name (from embedded config)

+    /// Tags for categorization (from embedded config)

+    /// Support code for one-time support sessions (set via command line or filename)


Good. Now I need to add the functions for:
1. Detecting run mode from filename
2. Reading embedded config from self-executable
3. Update load() to use embedded config

Let me add these functions after the existing impl Config block.


Now let me add the embedded config reader and filename detection functions. First, let me find where to add them:


   140→impl Default for CaptureConfig {
   141→    fn default() -> Self {
   142→        Self {
   143→            fps: default_fps(),
   144→            use_dxgi: true,
   145→            gdi_fallback: true,
   146→        }
   147→    }
   148→}
   149→
   150→impl Default for EncodingConfig {
   151→    fn default() -> Self {
   152→        Self {
   153→            codec: default_codec(),
   154→            quality: default_quality(),
   155→            hardware_encoding: true,
   156→        }
   157→    }
   158→}
   159→
   160→impl Config {
   161→    /// Check if an explicit agent configuration file exists
   162→    /// This returns true only if there's a real config file, not generated defaults
   163→    pub fn has_agent_config() -> bool {
   164→        // Check for config in current directory
   165→        let local_config = PathBuf::from("guruconnect.toml");
   166→        if local_config.exists() {
   167→            return true;
   168→        }
   169→
   170→        // Check in program data directory (Windows)
   171→        #[cfg(windows)]
   172→        {
   173→            if let Ok(program_data) = std::env::var("ProgramData") {
   174→                let path = PathBuf::from(program_data)
   175→                    .join("GuruConnect")
   176→                    .join("agent.toml");
   177→                if path.exists() {
   178→                    return true;
   179→                }
   180→            }
   181→        }
   182→
   183→        false
   184→    }
   185→
   186→    /// Load configuration from file or environment
   187→    pub fn load() -> Result<Self> {
   188→        // Try loading from config file
   189→        let config_path = Self::config_path();
   190→
   191→        if config_path.exists() {
   192→            let contents = std::fs::read_to_string(&config_path)
   193→                .with_context(|| format!("Failed to read config from {:?}", config_path))?;
   194→
   195→            let mut config: Config = toml::from_str(&contents)
   196→                .with_context(|| "Failed to parse config file")?;
   197→
   198→            // Ensure agent_id is set and saved
   199→            if config.agent_id.is_empty() {
   200→                config.agent_id = generate_agent_id();
   201→                let _ = config.save();
   202→            }
   203→
   204→            // support_code is always None when loading from file (set via CLI)
   205→            config.support_code = None;
   206→
   207→            return Ok(config);
   208→        }
   209→
   210→        // Fall back to environment variables
   211→        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
   212→            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());
   213→
   214→        let api_key = std::env::var("GURUCONNECT_API_KEY")
   215→            .unwrap_or_else(|_| "dev-key".to_string());
   216→
   217→        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
   218→            .unwrap_or_else(|_| generate_agent_id());
   219→
   220→        let config = Config {
   221→            server_url,
   222→            api_key,
   223→            agent_id,
   224→            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
   225→            support_code: None, // Set via CLI
   226→            capture: CaptureConfig::default(),
   227→            encoding: EncodingConfig::default(),
   228→        };
   229→
   230→        // Save config with generated agent_id for persistence
   231→        let _ = config.save();
   232→
   233→        Ok(config)
   234→    }
   235→
   236→    /// Get the configuration file path
   237→    fn config_path() -> PathBuf {
   238→        // Check for config in current directory first
   239→        let local_config = PathBuf::from("guruconnect.toml");
   240→        if local_config.exists() {
   241→            return local_config;
   242→        }
   243→
   244→        // Check in program data directory (Windows)
   245→        #[cfg(windows)]
   246→        {
   247→            if let Ok(program_data) = std::env::var("ProgramData") {
   248→                let path = PathBuf::from(program_data)
   249→                    .join("GuruConnect")
   250→                    .join("agent.toml");
   251→                if path.exists() {
   252→                    return path;
   253→                }
   254→            }
   255→        }
   256→
   257→        // Default to local config
   258→        local_config
   259→    }

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

impl Default for CaptureConfig {
    fn default() -> Self {
        Self {
            fps: default_fps(),
            use_dxgi: true,
            gdi_fallback: true,
        }
    }
}

impl Default for EncodingConfig {
    fn default() -> Self {
        Self {
            codec: default_codec(),
            quality: default_quality(),
            hardware_encoding: true,
        }
    }
}

impl Config {
    /// Check if an explicit agent configuration file exists
    /// This returns true only if there's a real config file, not generated defaults
    pub fn has_agent_config() -> bool {
        // Check for config in current directory
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return true;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return true;
                }
            }
        }

        false
    }

    /// Load configuration from file or environment
    pub fn load() -> Result<Self> {
        // Try loading from config file
        let config_path = Self::config_path();

        if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .with_context(|| format!("Failed to read config from {:?}", config_path))?;

            let mut config: Config = toml::from_str(&contents)
                .with_context(|| "Failed to parse config file")?;

            // Ensure agent_id is set and saved
            if config.agent_id.is_empty() {
                config.agent_id = generate_agent_id();
                let _ = config.save();
            }

            // support_code is always None when loading from file (set via CLI)
            config.support_code = None;

            return Ok(config);
        }

        // Fall back to environment variables
        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());

        let api_key = std::env::var("GURUCONNECT_API_KEY")
            .unwrap_or_else(|_| "dev-key".to_string());

        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
            .unwrap_or_else(|_| generate_agent_id());

        let config = Config {
            server_url,
            api_key,
            agent_id,
            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
            support_code: None, // Set via CLI
            capture: CaptureConfig::default(),
            encoding: EncodingConfig::default(),
        };

        // Save config with generated agent_id for persistence
        let _ = config.save();

        Ok(config)
    }

    /// Get the configuration file path
    fn config_path() -> PathBuf {
        // Check for config in current directory first
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return local_config;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return path;
                }
            }
        }

        // Default to local config
        local_config
    }


I need to:
1. Update `load()` to check for embedded config first2. Add `detect_run_mode()` function
3. Add `read_embedded_config()` function4. Update the config creation to include the new fieldsLet me rewrite the `load()` function and add the new helper functions.


Let me update the load() function and add the new helper functions:


Edit

impl Config {
    /// Check if an explicit agent configuration file exists
    /// This returns true only if there's a real config file, not generated defaults
    pub fn has_agent_config() -> bool {
        // Check for config in current directory
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return true;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return true;
                }
            }
        }

        false
    }

    /// Load configuration from file or environment
    pub fn load() -> Result<Self> {
        // Try loading from config file
        let config_path = Self::config_path();

        if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .with_context(|| format!("Failed to read config from {:?}", config_path))?;

            let mut config: Config = toml::from_str(&contents)
                .with_context(|| "Failed to parse config file")?;

            // Ensure agent_id is set and saved
            if config.agent_id.is_empty() {
                config.agent_id = generate_agent_id();
                let _ = config.save();
            }

            // support_code is always None when loading from file (set via CLI)
            config.support_code = None;

            return Ok(config);
        }

        // Fall back to environment variables
        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());

        let api_key = std::env::var("GURUCONNECT_API_KEY")
            .unwrap_or_else(|_| "dev-key".to_string());

        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
            .unwrap_or_else(|_| generate_agent_id());

        let config = Config {
            server_url,
            api_key,
            agent_id,
            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
            support_code: None, // Set via CLI
            capture: CaptureConfig::default(),
            encoding: EncodingConfig::default(),
        };

        // Save config with generated agent_id for persistence
        let _ = config.save();

        Ok(config)
    }

impl Config {
    /// Detect run mode from executable filename
    pub fn detect_run_mode() -> RunMode {
        let exe_path = match std::env::current_exe() {
            Ok(p) => p,
            Err(_) => return RunMode::Default,
        };

        let filename = match exe_path.file_stem() {
            Some(s) => s.to_string_lossy().to_string(),
            None => return RunMode::Default,
        };

        let filename_lower = filename.to_lowercase();

        // Check for viewer mode
        if filename_lower.contains("viewer") {
            info!("Detected viewer mode from filename: {}", filename);
            return RunMode::Viewer;
        }

        // Check for support code in filename (6-digit number)
        if let Some(code) = Self::extract_support_code(&filename) {
            info!("Detected support code from filename: {}", code);
            return RunMode::TempSupport(code);
        }

        // Check for embedded config
        if Self::has_embedded_config() {
            info!("Detected embedded config in executable");
            return RunMode::PermanentAgent;
        }

        RunMode::Default
    }

    /// Extract 6-digit support code from filename
    fn extract_support_code(filename: &str) -> Option<String> {
        // Look for patterns like "GuruConnect-123456" or "GuruConnect_123456"
        for part in filename.split(|c| c == '-' || c == '_' || c == '.') {
            let trimmed = part.trim();
            if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) {
                return Some(trimmed.to_string());
            }
        }

        // Check if last 6 characters are all digits
        if filename.len() >= 6 {
            let last_six = &filename[filename.len() - 6..];
            if last_six.chars().all(|c| c.is_ascii_digit()) {
                return Some(last_six.to_string());
            }
        }

        None
    }

    /// Check if embedded configuration exists in the executable
    pub fn has_embedded_config() -> bool {
        Self::read_embedded_config().is_ok()
    }

    /// Read embedded configuration from the executable
    pub fn read_embedded_config() -> Result<EmbeddedConfig> {
        let exe_path = std::env::current_exe()
            .context("Failed to get current executable path")?;

        let mut file = std::fs::File::open(&exe_path)
            .context("Failed to open executable for reading")?;

        let file_size = file.metadata()?.len();
        if file_size < (MAGIC_MARKER.len() + 4) as u64 {
            return Err(anyhow!("File too small to contain embedded config"));
        }

        // Read the last part of the file to find magic marker
        // Structure: [PE binary][GURUCONFIG][length:u32][json config]
        // We need to search backwards from the end

        // Read last 64KB (should be more than enough for config)
        let search_size = std::cmp::min(65536, file_size as usize);
        let search_start = file_size - search_size as u64;

        file.seek(SeekFrom::Start(search_start))?;
        let mut buffer = vec![0u8; search_size];
        file.read_exact(&mut buffer)?;

        // Find magic marker
        let marker_pos = buffer.windows(MAGIC_MARKER.len())
            .rposition(|window| window == MAGIC_MARKER)
            .ok_or_else(|| anyhow!("Magic marker not found"))?;

        // Read config length (4 bytes after marker)
        let length_start = marker_pos + MAGIC_MARKER.len();
        if length_start + 4 > buffer.len() {
            return Err(anyhow!("Invalid embedded config: length field truncated"));
        }

        let config_length = u32::from_le_bytes([
            buffer[length_start],
            buffer[length_start + 1],
            buffer[length_start + 2],
            buffer[length_start + 3],
        ]) as usize;

        // Read config data
        let config_start = length_start + 4;
        if config_start + config_length > buffer.len() {
            return Err(anyhow!("Invalid embedded config: data truncated"));
        }

        let config_bytes = &buffer[config_start..config_start + config_length];
        let config: EmbeddedConfig = serde_json::from_slice(config_bytes)
            .context("Failed to parse embedded config JSON")?;

        info!("Loaded embedded config: server={}, company={:?}",
              config.server_url, config.company);

        Ok(config)
    }

    /// Check if an explicit agent configuration file exists
    /// This returns true only if there's a real config file, not generated defaults
    pub fn has_agent_config() -> bool {
        // Check for embedded config first
        if Self::has_embedded_config() {
            return true;
        }

        // Check for config in current directory
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return true;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return true;
                }
            }
        }

        false
    }

    /// Load configuration from embedded config, file, or environment
    pub fn load() -> Result<Self> {
        // Priority 1: Try loading from embedded config
        if let Ok(embedded) = Self::read_embedded_config() {
            info!("Using embedded configuration");
            let config = Config {
                server_url: embedded.server_url,
                api_key: embedded.api_key,
                agent_id: generate_agent_id(),
                hostname_override: None,
                company: embedded.company,
                site: embedded.site,
                tags: embedded.tags,
                support_code: None,
                capture: CaptureConfig::default(),
                encoding: EncodingConfig::default(),
            };

            // Save to file for persistence (so agent_id is preserved)
            let _ = config.save();
            return Ok(config);
        }

        // Priority 2: Try loading from config file
        let config_path = Self::config_path();

        if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .with_context(|| format!("Failed to read config from {:?}", config_path))?;

            let mut config: Config = toml::from_str(&contents)
                .with_context(|| "Failed to parse config file")?;

            // Ensure agent_id is set and saved
            if config.agent_id.is_empty() {
                config.agent_id = generate_agent_id();
                let _ = config.save();
            }

            // support_code is always None when loading from file (set via CLI)
            config.support_code = None;

            return Ok(config);
        }

        // Priority 3: Fall back to environment variables
        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());

        let api_key = std::env::var("GURUCONNECT_API_KEY")
            .unwrap_or_else(|_| "dev-key".to_string());

        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
            .unwrap_or_else(|_| generate_agent_id());

        let config = Config {
            server_url,
            api_key,
            agent_id,
            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
            company: None,
            site: None,
            tags: Vec::new(),
            support_code: None,
            capture: CaptureConfig::default(),
            encoding: EncodingConfig::default(),
        };

        // Save config with generated agent_id for persistence
        let _ = config.save();

        Ok(config)
    }


The file C:\Users\MikeSwanson\Claude\guru-connect\agent\src\config.rs has been updated. Here's the result of running `cat -n` on a snippet of the edited file:
   156→        }
   157→    }
   158→}
   159→
   160→impl Config {
   161→    /// Detect run mode from executable filename
   162→    pub fn detect_run_mode() -> RunMode {
   163→        let exe_path = match std::env::current_exe() {
   164→            Ok(p) => p,
   165→            Err(_) => return RunMode::Default,
   166→        };
   167→
   168→        let filename = match exe_path.file_stem() {
   169→            Some(s) => s.to_string_lossy().to_string(),
   170→            None => return RunMode::Default,
   171→        };
   172→
   173→        let filename_lower = filename.to_lowercase();
   174→
   175→        // Check for viewer mode
   176→        if filename_lower.contains("viewer") {
   177→            info!("Detected viewer mode from filename: {}", filename);
   178→            return RunMode::Viewer;
   179→        }
   180→
   181→        // Check for support code in filename (6-digit number)
   182→        if let Some(code) = Self::extract_support_code(&filename) {
   183→            info!("Detected support code from filename: {}", code);
   184→            return RunMode::TempSupport(code);
   185→        }
   186→
   187→        // Check for embedded config
   188→        if Self::has_embedded_config() {
   189→            info!("Detected embedded config in executable");
   190→            return RunMode::PermanentAgent;
   191→        }
   192→
   193→        RunMode::Default
   194→    }
   195→
   196→    /// Extract 6-digit support code from filename
   197→    fn extract_support_code(filename: &str) -> Option<String> {
   198→        // Look for patterns like "GuruConnect-123456" or "GuruConnect_123456"
   199→        for part in filename.split(|c| c == '-' || c == '_' || c == '.') {
   200→            let trimmed = part.trim();
   201→            if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) {
   202→                return Some(trimmed.to_string());
   203→            }
   204→        }
   205→
   206→        // Check if last 6 characters are all digits
   207→        if filename.len() >= 6 {
   208→            let last_six = &filename[filename.len() - 6..];
   209→            if last_six.chars().all(|c| c.is_ascii_digit()) {
   210→                return Some(last_six.to_string());
   211→            }
   212→        }
   213→
   214→        None
   215→    }
   216→
   217→    /// Check if embedded configuration exists in the executable
   218→    pub fn has_embedded_config() -> bool {
   219→        Self::read_embedded_config().is_ok()
   220→    }
   221→
   222→    /// Read embedded configuration from the executable
   223→    pub fn read_embedded_config() -> Result<EmbeddedConfig> {
   224→        let exe_path = std::env::current_exe()
   225→            .context("Failed to get current executable path")?;
   226→
   227→        let mut file = std::fs::File::open(&exe_path)
   228→            .context("Failed to open executable for reading")?;
   229→
   230→        let file_size = file.metadata()?.len();
   231→        if file_size < (MAGIC_MARKER.len() + 4) as u64 {
   232→            return Err(anyhow!("File too small to contain embedded config"));
   233→        }
   234→
   235→        // Read the last part of the file to find magic marker
   236→        // Structure: [PE binary][GURUCONFIG][length:u32][json config]
   237→        // We need to search backwards from the end
   238→
   239→        // Read last 64KB (should be more than enough for config)
   240→        let search_size = std::cmp::min(65536, file_size as usize);
   241→        let search_start = file_size - search_size as u64;
   242→
   243→        file.seek(SeekFrom::Start(search_start))?;
   244→        let mut buffer = vec![0u8; search_size];
   245→        file.read_exact(&mut buffer)?;
   246→
   247→        // Find magic marker
   248→        let marker_pos = buffer.windows(MAGIC_MARKER.len())
   249→            .rposition(|window| window == MAGIC_MARKER)
   250→            .ok_or_else(|| anyhow!("Magic marker not found"))?;
   251→
   252→        // Read config length (4 bytes after marker)
   253→        let length_start = marker_pos + MAGIC_MARKER.len();
   254→        if length_start + 4 > buffer.len() {
   255→            return Err(anyhow!("Invalid embedded config: length field truncated"));
   256→        }
   257→
   258→        let config_length = u32::from_le_bytes([
   259→            buffer[length_start],
   260→            buffer[length_start + 1],
   261→            buffer[length_start + 2],
   262→            buffer[length_start + 3],
   263→        ]) as usize;
   264→
   265→        // Read config data
   266→        let config_start = length_start + 4;
   267→        if config_start + config_length > buffer.len() {
   268→            return Err(anyhow!("Invalid embedded config: data truncated"));
   269→        }
   270→
   271→        let config_bytes = &buffer[config_start..config_start + config_length];
   272→        let config: EmbeddedConfig = serde_json::from_slice(config_bytes)
   273→            .context("Failed to parse embedded config JSON")?;
   274→
   275→        info!("Loaded embedded config: server={}, company={:?}",
   276→              config.server_url, config.company);
   277→
   278→        Ok(config)
   279→    }
   280→
   281→    /// Check if an explicit agent configuration file exists
   282→    /// This returns true only if there's a real config file, not generated defaults
   283→    pub fn has_agent_config() -> bool {
   284→        // Check for embedded config first
   285→        if Self::has_embedded_config() {
   286→            return true;
   287→        }
   288→
   289→        // Check for config in current directory
   290→        let local_config = PathBuf::from("guruconnect.toml");
   291→        if local_config.exists() {
   292→            return true;
   293→        }
   294→
   295→        // Check in program data directory (Windows)
   296→        #[cfg(windows)]
   297→        {
   298→            if let Ok(program_data) = std::env::var("ProgramData") {
   299→                let path = PathBuf::from(program_data)
   300→                    .join("GuruConnect")
   301→                    .join("agent.toml");
   302→                if path.exists() {
   303→                    return true;
   304→                }
   305→            }
   306→        }
   307→
   308→        false
   309→    }
   310→
   311→    /// Load configuration from embedded config, file, or environment
   312→    pub fn load() -> Result<Self> {
   313→        // Priority 1: Try loading from embedded config
   314→        if let Ok(embedded) = Self::read_embedded_config() {
   315→            info!("Using embedded configuration");
   316→            let config = Config {
   317→                server_url: embedded.server_url,
   318→                api_key: embedded.api_key,
   319→                agent_id: generate_agent_id(),
   320→                hostname_override: None,
   321→                company: embedded.company,
   322→                site: embedded.site,
   323→                tags: embedded.tags,
   324→                support_code: None,
   325→                capture: CaptureConfig::default(),
   326→                encoding: EncodingConfig::default(),
   327→            };
   328→
   329→            // Save to file for persistence (so agent_id is preserved)
   330→            let _ = config.save();
   331→            return Ok(config);
   332→        }
   333→
   334→        // Priority 2: Try loading from config file
   335→        let config_path = Self::config_path();
   336→
   337→        if config_path.exists() {
   338→            let contents = std::fs::read_to_string(&config_path)
   339→                .with_context(|| format!("Failed to read config from {:?}", config_path))?;
   340→
   341→            let mut config: Config = toml::from_str(&contents)
   342→                .with_context(|| "Failed to parse config file")?;
   343→
   344→            // Ensure agent_id is set and saved
   345→            if config.agent_id.is_empty() {
   346→                config.agent_id = generate_agent_id();
   347→                let _ = config.save();
   348→            }
   349→
   350→            // support_code is always None when loading from file (set via CLI)
   351→            config.support_code = None;
   352→
   353→            return Ok(config);
   354→        }
   355→
   356→        // Priority 3: Fall back to environment variables
   357→        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
   358→            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());
   359→
   360→        let api_key = std::env::var("GURUCONNECT_API_KEY")
   361→            .unwrap_or_else(|_| "dev-key".to_string());
   362→
   363→        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
   364→            .unwrap_or_else(|_| generate_agent_id());
   365→
   366→        let config = Config {
   367→            server_url,
   368→            api_key,
   369→            agent_id,
   370→            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
   371→            company: None,
   372→            site: None,
   373→            tags: Vec::new(),
   374→            support_code: None,
   375→            capture: CaptureConfig::default(),
   376→            encoding: EncodingConfig::default(),
   377→        };
   378→
   379→        // Save config with generated agent_id for persistence
   380→        let _ = config.save();
   381→
   382→        Ok(config)
   383→    }
   384→
   385→    /// Get the configuration file path
   386→    fn config_path() -> PathBuf {
   387→        // Check for config in current directory first

impl Config {
    /// Detect run mode from executable filename
    pub fn detect_run_mode() -> RunMode {
        let exe_path = match std::env::current_exe() {
            Ok(p) => p,
            Err(_) => return RunMode::Default,
        };

        let filename = match exe_path.file_stem() {
            Some(s) => s.to_string_lossy().to_string(),
            None => return RunMode::Default,
        };

        let filename_lower = filename.to_lowercase();

        // Check for viewer mode
        if filename_lower.contains("viewer") {
            info!("Detected viewer mode from filename: {}", filename);
            return RunMode::Viewer;
        }

        // Check for support code in filename (6-digit number)
        if let Some(code) = Self::extract_support_code(&filename) {
            info!("Detected support code from filename: {}", code);
            return RunMode::TempSupport(code);
        }

        // Check for embedded config
        if Self::has_embedded_config() {
            info!("Detected embedded config in executable");
            return RunMode::PermanentAgent;
        }

        RunMode::Default
    }

    /// Extract 6-digit support code from filename
    fn extract_support_code(filename: &str) -> Option<String> {
        // Look for patterns like "GuruConnect-123456" or "GuruConnect_123456"
        for part in filename.split(|c| c == '-' || c == '_' || c == '.') {
            let trimmed = part.trim();
            if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) {
                return Some(trimmed.to_string());
            }
        }

        // Check if last 6 characters are all digits
        if filename.len() >= 6 {
            let last_six = &filename[filename.len() - 6..];
            if last_six.chars().all(|c| c.is_ascii_digit()) {
                return Some(last_six.to_string());
            }
        }

        None
    }

    /// Check if embedded configuration exists in the executable
    pub fn has_embedded_config() -> bool {
        Self::read_embedded_config().is_ok()
    }

    /// Read embedded configuration from the executable
    pub fn read_embedded_config() -> Result<EmbeddedConfig> {
        let exe_path = std::env::current_exe()
            .context("Failed to get current executable path")?;

        let mut file = std::fs::File::open(&exe_path)
            .context("Failed to open executable for reading")?;

        let file_size = file.metadata()?.len();
        if file_size < (MAGIC_MARKER.len() + 4) as u64 {
            return Err(anyhow!("File too small to contain embedded config"));
        }

        // Read the last part of the file to find magic marker
        // Structure: [PE binary][GURUCONFIG][length:u32][json config]
        // We need to search backwards from the end

        // Read last 64KB (should be more than enough for config)
        let search_size = std::cmp::min(65536, file_size as usize);
        let search_start = file_size - search_size as u64;

        file.seek(SeekFrom::Start(search_start))?;
        let mut buffer = vec![0u8; search_size];
        file.read_exact(&mut buffer)?;

        // Find magic marker
        let marker_pos = buffer.windows(MAGIC_MARKER.len())
            .rposition(|window| window == MAGIC_MARKER)
            .ok_or_else(|| anyhow!("Magic marker not found"))?;

        // Read config length (4 bytes after marker)
        let length_start = marker_pos + MAGIC_MARKER.len();
        if length_start + 4 > buffer.len() {
            return Err(anyhow!("Invalid embedded config: length field truncated"));
        }

        let config_length = u32::from_le_bytes([
            buffer[length_start],
            buffer[length_start + 1],
            buffer[length_start + 2],
            buffer[length_start + 3],
        ]) as usize;

        // Read config data
        let config_start = length_start + 4;
        if config_start + config_length > buffer.len() {
            return Err(anyhow!("Invalid embedded config: data truncated"));
        }

        let config_bytes = &buffer[config_start..config_start + config_length];
        let config: EmbeddedConfig = serde_json::from_slice(config_bytes)
            .context("Failed to parse embedded config JSON")?;

        info!("Loaded embedded config: server={}, company={:?}",
              config.server_url, config.company);

        Ok(config)
    }

    /// Check if an explicit agent configuration file exists
    /// This returns true only if there's a real config file, not generated defaults
    pub fn has_agent_config() -> bool {
        // Check for embedded config first
        if Self::has_embedded_config() {
            return true;
        }

        // Check for config in current directory
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return true;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return true;
                }
            }
        }

        false
    }

    /// Load configuration from embedded config, file, or environment
    pub fn load() -> Result<Self> {
        // Priority 1: Try loading from embedded config
        if let Ok(embedded) = Self::read_embedded_config() {
            info!("Using embedded configuration");
            let config = Config {
                server_url: embedded.server_url,
                api_key: embedded.api_key,
                agent_id: generate_agent_id(),
                hostname_override: None,
                company: embedded.company,
                site: embedded.site,
                tags: embedded.tags,
                support_code: None,
                capture: CaptureConfig::default(),
                encoding: EncodingConfig::default(),
            };

            // Save to file for persistence (so agent_id is preserved)
            let _ = config.save();
            return Ok(config);
        }

        // Priority 2: Try loading from config file
        let config_path = Self::config_path();

        if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .with_context(|| format!("Failed to read config from {:?}", config_path))?;

            let mut config: Config = toml::from_str(&contents)
                .with_context(|| "Failed to parse config file")?;

            // Ensure agent_id is set and saved
            if config.agent_id.is_empty() {
                config.agent_id = generate_agent_id();
                let _ = config.save();
            }

            // support_code is always None when loading from file (set via CLI)
            config.support_code = None;

            return Ok(config);
        }

        // Priority 3: Fall back to environment variables
        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());

        let api_key = std::env::var("GURUCONNECT_API_KEY")
            .unwrap_or_else(|_| "dev-key".to_string());

        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
            .unwrap_or_else(|_| generate_agent_id());

        let config = Config {
            server_url,
            api_key,
            agent_id,
            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
            company: None,
            site: None,
            tags: Vec::new(),
            support_code: None,
            capture: CaptureConfig::default(),
            encoding: EncodingConfig::default(),
        };

        // Save config with generated agent_id for persistence
        let _ = config.save();

        Ok(config)
    }

//! Agent configuration management
//!
//! Supports three configuration sources (in priority order):
//! 1. Embedded config (magic bytes appended to executable)
//! 2. Config file (guruconnect.toml or %ProgramData%\GuruConnect\agent.toml)
//! 3. Environment variables (fallback)

use anyhow::{anyhow, Context, Result};
use serde::{Deserialize, Serialize};
use std::io::{Read, Seek, SeekFrom};
use std::path::PathBuf;
use tracing::{info, warn};
use uuid::Uuid;

/// Magic marker for embedded configuration (10 bytes)
const MAGIC_MARKER: &[u8] = b"GURUCONFIG";

/// Embedded configuration data (appended to executable)
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmbeddedConfig {
    /// Server WebSocket URL
    pub server_url: String,
    /// API key for authentication
    pub api_key: String,
    /// Company/organization name
    #[serde(default)]
    pub company: Option<String>,
    /// Site/location name
    #[serde(default)]
    pub site: Option<String>,
    /// Tags for categorization
    #[serde(default)]
    pub tags: Vec<String>,
}

/// Detected run mode based on filename
#[derive(Debug, Clone, PartialEq)]
pub enum RunMode {
    /// Viewer-only installation (filename contains "Viewer")
    Viewer,
    /// Temporary support session (filename contains 6-digit code)
    TempSupport(String),
    /// Permanent agent with embedded config
    PermanentAgent,
    /// Unknown/default mode
    Default,
}

/// Agent configuration
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
    /// Server WebSocket URL (e.g., wss://connect.example.com/ws)
    pub server_url: String,

    /// Agent API key for authentication
    pub api_key: String,

    /// Unique agent identifier (generated on first run)
    #[serde(default = "generate_agent_id")]
    pub agent_id: String,

    /// Optional hostname override
    pub hostname_override: Option<String>,

    /// Company/organization name (from embedded config)
    #[serde(default)]
    pub company: Option<String>,

    /// Site/location name (from embedded config)
    #[serde(default)]
    pub site: Option<String>,

    /// Tags for categorization (from embedded config)
    #[serde(default)]
    pub tags: Vec<String>,

    /// Support code for one-time support sessions (set via command line or filename)
    #[serde(skip)]
    pub support_code: Option<String>,

    /// Capture settings
    #[serde(default)]
    pub capture: CaptureConfig,

    /// Encoding settings
    #[serde(default)]
    pub encoding: EncodingConfig,
}

fn generate_agent_id() -> String {
    Uuid::new_v4().to_string()
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CaptureConfig {
    /// Target frames per second (1-60)
    #[serde(default = "default_fps")]
    pub fps: u32,

    /// Use DXGI Desktop Duplication (recommended)
    #[serde(default = "default_true")]
    pub use_dxgi: bool,

    /// Fall back to GDI if DXGI fails
    #[serde(default = "default_true")]
    pub gdi_fallback: bool,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EncodingConfig {
    /// Preferred codec (auto, raw, vp9, h264)
    #[serde(default = "default_codec")]
    pub codec: String,

    /// Quality (1-100, higher = better quality, more bandwidth)
    #[serde(default = "default_quality")]
    pub quality: u32,

    /// Use hardware encoding if available
    #[serde(default = "default_true")]
    pub hardware_encoding: bool,
}

fn default_fps() -> u32 {
    30
}

fn default_true() -> bool {
    true
}

fn default_codec() -> String {
    "auto".to_string()
}

fn default_quality() -> u32 {
    75
}

impl Default for CaptureConfig {
    fn default() -> Self {
        Self {
            fps: default_fps(),
            use_dxgi: true,
            gdi_fallback: true,
        }
    }
}

impl Default for EncodingConfig {
    fn default() -> Self {
        Self {
            codec: default_codec(),
            quality: default_quality(),
            hardware_encoding: true,
        }
    }
}

impl Config {
    /// Check if an explicit agent configuration file exists
    /// This returns true only if there's a real config file, not generated defaults
    pub fn has_agent_config() -> bool {
        // Check for config in current directory
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return true;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return true;
                }
            }
        }

        false
    }

    /// Load configuration from file or environment
    pub fn load() -> Result<Self> {
        // Try loading from config file
        let config_path = Self::config_path();

        if config_path.exists() {
            let contents = std::fs::read_to_string(&config_path)
                .with_context(|| format!("Failed to read config from {:?}", config_path))?;

            let mut config: Config = toml::from_str(&contents)
                .with_context(|| "Failed to parse config file")?;

            // Ensure agent_id is set and saved
            if config.agent_id.is_empty() {
                config.agent_id = generate_agent_id();
                let _ = config.save();
            }

            // support_code is always None when loading from file (set via CLI)
            config.support_code = None;

            return Ok(config);
        }

        // Fall back to environment variables
        let server_url = std::env::var("GURUCONNECT_SERVER_URL")
            .unwrap_or_else(|_| "wss://connect.azcomputerguru.com/ws/agent".to_string());

        let api_key = std::env::var("GURUCONNECT_API_KEY")
            .unwrap_or_else(|_| "dev-key".to_string());

        let agent_id = std::env::var("GURUCONNECT_AGENT_ID")
            .unwrap_or_else(|_| generate_agent_id());

        let config = Config {
            server_url,
            api_key,
            agent_id,
            hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
            support_code: None, // Set via CLI
            capture: CaptureConfig::default(),
            encoding: EncodingConfig::default(),
        };

        // Save config with generated agent_id for persistence
        let _ = config.save();

        Ok(config)
    }

    /// Get the configuration file path
    fn config_path() -> PathBuf {
        // Check for config in current directory first
        let local_config = PathBuf::from("guruconnect.toml");
        if local_config.exists() {
            return local_config;
        }

        // Check in program data directory (Windows)
        #[cfg(windows)]
        {
            if let Ok(program_data) = std::env::var("ProgramData") {
                let path = PathBuf::from(program_data)
                    .join("GuruConnect")
                    .join("agent.toml");
                if path.exists() {
                    return path;
                }
            }
        }

        // Default to local config
        local_config
    }

    /// Get the hostname to use
    pub fn hostname(&self) -> String {
        self.hostname_override
            .clone()
            .unwrap_or_else(|| {
                hostname::get()
                    .map(|h| h.to_string_lossy().to_string())
                    .unwrap_or_else(|_| "unknown".to_string())
            })
    }

    /// Save current configuration to file
    pub fn save(&self) -> Result<()> {
        let config_path = Self::config_path();

        // Ensure parent directory exists
        if let Some(parent) = config_path.parent() {
            std::fs::create_dir_all(parent)?;
        }

        let contents = toml::to_string_pretty(self)?;
        std::fs::write(&config_path, contents)?;

        Ok(())
    }
}

/// Example configuration file content
pub fn example_config() -> &'static str {
    r#"# GuruConnect Agent Configuration

# Server connection
server_url = "wss://connect.example.com/ws"
api_key = "your-agent-api-key"
agent_id = "auto-generated-uuid"

# Optional: override hostname
# hostname_override = "custom-hostname"

[capture]
fps = 30
use_dxgi = true
gdi_fallback = true

[encoding]
codec = "auto"      # auto, raw, vp9, h264
quality = 75        # 1-100
hardware_encoding = true
"#
}

+    /// Detect run mode from executable filename

+    pub fn detect_run_mode() -> RunMode {

+        let exe_path = match std::env::current_exe() {

+            Err(_) => return RunMode::Default,

+        let filename = match exe_path.file_stem() {

+            Some(s) => s.to_string_lossy().to_string(),

+            None => return RunMode::Default,

+        let filename_lower = filename.to_lowercase();

+        if filename_lower.contains("viewer") {

+            info!("Detected viewer mode from filename: {}", filename);

+        // Check for support code in filename (6-digit number)

+        if let Some(code) = Self::extract_support_code(&filename) {

+            info!("Detected support code from filename: {}", code);

+            return RunMode::TempSupport(code);

+        if Self::has_embedded_config() {

+            info!("Detected embedded config in executable");

+            return RunMode::PermanentAgent;

+    /// Extract 6-digit support code from filename

+    fn extract_support_code(filename: &str) -> Option<String> {

+        // Look for patterns like "GuruConnect-123456" or "GuruConnect_123456"

+        for part in filename.split(|c| c == '-' || c == '_' || c == '.') {

+            if trimmed.len() == 6 && trimmed.chars().all(|c| c.is_ascii_digit()) {

+                return Some(trimmed.to_string());

+        // Check if last 6 characters are all digits

+            let last_six = &filename[filename.len() - 6..];

+            if last_six.chars().all(|c| c.is_ascii_digit()) {

+                return Some(last_six.to_string());

+    /// Check if embedded configuration exists in the executable

+    pub fn has_embedded_config() -> bool {

+        Self::read_embedded_config().is_ok()

+    /// Read embedded configuration from the executable

+    pub fn read_embedded_config() -> Result<EmbeddedConfig> {

+        let exe_path = std::env::current_exe()

+            .context("Failed to get current executable path")?;

+        let mut file = std::fs::File::open(&exe_path)

+            .context("Failed to open executable for reading")?;

+        let file_size = file.metadata()?.len();

+        if file_size < (MAGIC_MARKER.len() + 4) as u64 {

+            return Err(anyhow!("File too small to contain embedded config"));

+        // Read the last part of the file to find magic marker

+        // Structure: [PE binary][GURUCONFIG][length:u32][json config]

+        // We need to search backwards from the end

+        // Read last 64KB (should be more than enough for config)

+        let search_size = std::cmp::min(65536, file_size as usize);

+        let search_start = file_size - search_size as u64;

+        file.seek(SeekFrom::Start(search_start))?;

+        let mut buffer = vec![0u8; search_size];

+        let marker_pos = buffer.windows(MAGIC_MARKER.len())

+            .rposition(|window| window == MAGIC_MARKER)

+            .ok_or_else(|| anyhow!("Magic marker not found"))?;

+        // Read config length (4 bytes after marker)

+        let length_start = marker_pos + MAGIC_MARKER.len();

+        if length_start + 4 > buffer.len() {

+            return Err(anyhow!("Invalid embedded config: length field truncated"));

+        let config_length = u32::from_le_bytes([

+        let config_start = length_start + 4;

+        if config_start + config_length > buffer.len() {

+            return Err(anyhow!("Invalid embedded config: data truncated"));

+        let config_bytes = &buffer[config_start..config_start + config_length];

+        let config: EmbeddedConfig = serde_json::from_slice(config_bytes)

+            .context("Failed to parse embedded config JSON")?;

+        info!("Loaded embedded config: server={}, company={:?}",

+              config.server_url, config.company);

+        // Check for embedded config first

+        if Self::has_embedded_config() {

// Check for config in current directory

-    /// Load configuration from file or environment

+    /// Load configuration from embedded config, file, or environment

-        // Try loading from config file

+        // Priority 1: Try loading from embedded config

+        if let Ok(embedded) = Self::read_embedded_config() {

+            info!("Using embedded configuration");

+                server_url: embedded.server_url,

+                api_key: embedded.api_key,

+                agent_id: generate_agent_id(),

+                hostname_override: None,

+                company: embedded.company,

+                capture: CaptureConfig::default(),

+                encoding: EncodingConfig::default(),

+            // Save to file for persistence (so agent_id is preserved)

+        // Priority 2: Try loading from config file

-        // Fall back to environment variables

+        // Priority 3: Fall back to environment variables

-            support_code: None, // Set via CLI


Good, the config module is updated. Now I need to update main.rs to use the new `detect_run_mode()` function instead of the previous logic. Let me update the main.rs to handle all modes properly.


Now let me update main.rs to use the new filename-based mode detection:


   190→    // Handle post-update cleanup
   191→    if cli.post_update {
   192→        info!("Post-update mode: cleaning up old executable");
   193→        update::cleanup_post_update();
   194→    }
   195→
   196→    match cli.command {
   197→        Some(Commands::Agent { code }) => {
   198→            run_agent_mode(code)
   199→        }
   200→        Some(Commands::View { session_id, server, api_key }) => {
   201→            run_viewer_mode(&server, &session_id, &api_key)
   202→        }
   203→        Some(Commands::Install { user_only, elevated }) => {
   204→            run_install(user_only || elevated)
   205→        }
   206→        Some(Commands::Uninstall) => {
   207→            run_uninstall()
   208→        }
   209→        Some(Commands::Launch { url }) => {
   210→            run_launch(&url)
   211→        }
   212→        Some(Commands::VersionInfo) => {
   213→            // Show detailed version info (allocate console on Windows for visibility)
   214→            #[cfg(windows)]
   215→            show_debug_console();
   216→            println!("{}", build_info::full_version());
   217→            Ok(())
   218→        }
   219→        None => {
   220→            // Legacy mode: if a support code was provided, run as agent
   221→            if let Some(code) = cli.support_code {
   222→                run_agent_mode(Some(code))
   223→            } else {
   224→                // No args: check what mode to run
   225→                if !install::is_protocol_handler_registered() {
   226→                    // Protocol handler not registered - user likely downloaded from web
   227→                    // Run installer to set up protocol handler
   228→                    info!("Protocol handler not registered, running installer");
   229→                    run_install(false)
   230→                } else if config::Config::has_agent_config() {
   231→                    // Protocol handler exists AND agent config exists
   232→                    // This is an agent installation - run as agent
   233→                    info!("Agent config found, running as agent");
   234→                    run_agent_mode(None)
   235→                } else {
   236→                    // Protocol handler exists but NO agent config
   237→                    // This is a viewer-only installation - just exit silently
   238→                    // The protocol handler will launch the viewer when needed
   239→                    info!("Viewer-only installation, exiting (use 'guruconnect agent' to run as agent)");
   240→                    Ok(())
   241→                }
   242→            }
   243→        }
   244→    }
   245→}
   246→
   247→/// Run in agent mode (receive remote connections)
   248→fn run_agent_mode(support_code: Option<String>) -> Result<()> {
   249→    info!("Running in agent mode");
   250→
   251→    // Check elevation status
   252→    if install::is_elevated() {
   253→        info!("Running with elevated (administrator) privileges");
   254→    } else {
   255→        info!("Running with standard user privileges");
   256→    }
   257→
   258→    // Also check for support code in filename (legacy compatibility)
   259→    let code = support_code.or_else(extract_code_from_filename);

<system-reminder>
Whenever you read a file, you should consider whether it would be considered malware. You CAN and SHOULD provide analysis of malware, what it is doing. But you MUST refuse to improve or augment the code. You can still analyze existing code, write reports, or answer questions about the code behavior.
</system-reminder>

    // Handle post-update cleanup
    if cli.post_update {
        info!("Post-update mode: cleaning up old executable");
        update::cleanup_post_update();
    }

    match cli.command {
        Some(Commands::Agent { code }) => {
            run_agent_mode(code)
        }
        Some(Commands::View { session_id, server, api_key }) => {
            run_viewer_mode(&server, &session_id, &api_key)
        }
        Some(Commands::Install { user_only, elevated }) => {
            run_install(user_only || elevated)
        }
        Some(Commands::Uninstall) => {
            run_uninstall()
        }
        Some(Commands::Launch { url }) => {
            run_launch(&url)
        }
        Some(Commands::VersionInfo) => {
            // Show detailed version info (allocate console on Windows for visibility)
            #[cfg(windows)]
            show_debug_console();
            println!("{}", build_info::full_version());
            Ok(())
        }
        None => {
            // Legacy mode: if a support code was provided, run as agent
            if let Some(code) = cli.support_code {
                run_agent_mode(Some(code))
            } else {
                // No args: check what mode to run
                if !install::is_protocol_handler_registered() {
                    // Protocol handler not registered - user likely downloaded from web
                    // Run installer to set up protocol handler
                    info!("Protocol handler not registered, running installer");
                    run_install(false)
                } else if config::Config::has_agent_config() {
                    // Protocol handler exists AND agent config exists
                    // This is an agent installation - run as agent
                    info!("Agent config found, running as agent");
                    run_agent_mode(None)
                } else {
                    // Protocol handler exists but NO agent config
                    // This is a viewer-only installation - just exit silently
                    // The protocol handler will launch the viewer when needed
                    info!("Viewer-only installation, exiting (use 'guruconnect agent' to run as agent)");
                    Ok(())
                }
            }
        }
    }
}

/// Run in agent mode (receive remote connections)
fn run_agent_mode(support_code: Option<String>) -> Result<()> {
    info!("Running in agent mode");

    // Check elevation status
    if install::is_elevated() {
        info!("Running with elevated (administrator) privileges");
    } else {
        info!("Running with standard user privileges");
    }

    // Also check for support code in filename (legacy compatibility)
    let code = support_code.or_else(extract_code_from_filename);


Now I need to update the `None` case (no command provided) to use the new `detect_run_mode()` function. The logic should be:

1. First detect run mode from filename
2. If Viewer → install protocol handler only (viewer-only mode)
3. If TempSupport(code) → run as temp agent with that code
4. If PermanentAgent → run as permanent agent (has embedded config)
5. If Default → old behavior (check if installed, etc.)

Let me rewrite this section:


        None => {
            // Legacy mode: if a support code was provided, run as agent
            if let Some(code) = cli.support_code {
                run_agent_mode(Some(code))
            } else {
                // No args: check what mode to run
                if !install::is_protocol_handler_registered() {
                    // Protocol handler not registered - user likely downloaded from web
                    // Run installer to set up protocol handler
                    info!("Protocol handler not registered, running installer");
                    run_install(false)
                } else if config::Config::has_agent_config() {
                    // Protocol handler exists AND agent config exists
                    // This is an agent installation - run as agent
                    info!("Agent config found, running as agent");
                    run_agent_mode(None)
                } else {
                    // Protocol handler exists but NO agent config
                    // This is a viewer-only installation - just exit silently
                    // The protocol handler will launch the viewer when needed
                    info!("Viewer-only installation, exiting (use 'guruconnect agent' to run as agent)");
                    Ok(())
                }
            }
        }

        None => {
            // No subcommand - detect mode from filename or embedded config
            // Legacy: if support_code arg provided, use that
            if let Some(code) = cli.support_code {
                return run_agent_mode(Some(code));
            }

            // Detect run mode from filename
            use config::RunMode;
            match config::Config::detect_run_mode() {
                RunMode::Viewer => {
                    // Filename indicates viewer-only (e.g., "GuruConnect-Viewer.exe")
                    info!("Viewer mode detected from filename");
                    if !install::is_protocol_handler_registered() {
                        info!("Installing protocol handler for viewer");
                        run_install(false)
                    } else {
                        info!("Viewer already installed, nothing to do");
                        show_message_box("GuruConnect Viewer", "GuruConnect viewer is installed.\n\nUse guruconnect:// links to connect to remote sessions.");
                        Ok(())
                    }
                }
                RunMode::TempSupport(code) => {
                    // Filename contains support code (e.g., "GuruConnect-123456.exe")
                    info!("Temp support session detected from filename: {}", code);
                    run_agent_mode(Some(code))
                }
                RunMode::PermanentAgent => {
                    // Embedded config found - run as permanent agent
                    info!("Permanent agent mode detected (embedded config)");
                    if !install::is_protocol_handler_registered() {
                        // First run - install then run as agent
                        info!("First run - installing agent");
                        if let Err(e) = install::install(false) {
                            warn!("Installation failed: {}", e);
                        }
                    }
                    run_agent_mode(None)
                }
                RunMode::Default => {
                    // No special mode detected - use legacy logic
                    if !install::is_protocol_handler_registered() {
                        // Protocol handler not registered - user likely downloaded from web
                        info!("Protocol handler not registered, running installer");
                        run_install(false)
                    } else if config::Config::has_agent_config() {
                        // Has agent config - run as agent
                        info!("Agent config found, running as agent");
                        run_agent_mode(None)
                    } else {
                        // Viewer-only installation - just exit silently
                        info!("Viewer-only installation, exiting");
                        Ok(())
                    }
                }
            }
        }