- Server: Accept support_code param in WebSocket connection - Server: Link code to session when agent connects, mark as connected - Server: Mark code as completed when agent disconnects - Agent: Accept support code from command line argument - Agent: Send hostname and support_code in WebSocket params - Portal: Trigger agent download with code in filename - Portal: Show code reminder in download instructions - Dashboard: Add machines list fetching (Access tab) - Add TODO.md for feature tracking 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
94 lines
2.5 KiB
Rust
94 lines
2.5 KiB
Rust
//! GuruConnect Agent - Remote Desktop Agent for Windows
|
|
//!
|
|
//! Provides screen capture, input injection, and remote control capabilities.
|
|
//!
|
|
//! Usage:
|
|
//! guruconnect-agent.exe [support_code]
|
|
//!
|
|
//! If a support code is provided, the agent will connect using that code
|
|
//! for a one-time support session.
|
|
|
|
mod capture;
|
|
mod config;
|
|
mod encoder;
|
|
mod input;
|
|
mod session;
|
|
mod transport;
|
|
|
|
pub mod proto {
|
|
include!(concat!(env!("OUT_DIR"), "/guruconnect.rs"));
|
|
}
|
|
|
|
use anyhow::Result;
|
|
use tracing::{info, error, Level};
|
|
use tracing_subscriber::FmtSubscriber;
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
// Initialize logging
|
|
let subscriber = FmtSubscriber::builder()
|
|
.with_max_level(Level::INFO)
|
|
.with_target(true)
|
|
.with_thread_ids(true)
|
|
.init();
|
|
|
|
info!("GuruConnect Agent v{}", env!("CARGO_PKG_VERSION"));
|
|
|
|
// Parse command line arguments
|
|
let args: Vec<String> = std::env::args().collect();
|
|
let support_code = if args.len() > 1 {
|
|
let code = args[1].trim().to_string();
|
|
// Validate it looks like a 6-digit code
|
|
if code.len() == 6 && code.chars().all(|c| c.is_ascii_digit()) {
|
|
info!("Support code provided: {}", code);
|
|
Some(code)
|
|
} else {
|
|
info!("Invalid support code format, ignoring: {}", code);
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// Load configuration
|
|
let mut config = config::Config::load()?;
|
|
config.support_code = support_code;
|
|
info!("Loaded configuration for server: {}", config.server_url);
|
|
|
|
// Run the agent
|
|
if let Err(e) = run_agent(config).await {
|
|
error!("Agent error: {}", e);
|
|
return Err(e);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
async fn run_agent(config: config::Config) -> Result<()> {
|
|
// Create session manager
|
|
let mut session = session::SessionManager::new(config.clone());
|
|
|
|
// Connect to server and run main loop
|
|
loop {
|
|
info!("Connecting to server...");
|
|
|
|
match session.connect().await {
|
|
Ok(_) => {
|
|
info!("Connected to server");
|
|
|
|
// Run session until disconnect
|
|
if let Err(e) = session.run().await {
|
|
error!("Session error: {}", e);
|
|
}
|
|
}
|
|
Err(e) => {
|
|
error!("Connection failed: {}", e);
|
|
}
|
|
}
|
|
|
|
// Wait before reconnecting
|
|
info!("Reconnecting in 5 seconds...");
|
|
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
|
}
|
|
}
|