Link support codes to agent sessions
- 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>
This commit is contained in:
@@ -21,6 +21,10 @@ pub struct Config {
|
||||
/// 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,
|
||||
@@ -119,6 +123,9 @@ impl Config {
|
||||
let _ = config.save();
|
||||
}
|
||||
|
||||
// support_code is always None when loading from file (set via CLI)
|
||||
config.support_code = None;
|
||||
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
@@ -137,6 +144,7 @@ impl Config {
|
||||
api_key,
|
||||
agent_id,
|
||||
hostname_override: std::env::var("GURUCONNECT_HOSTNAME").ok(),
|
||||
support_code: None, // Set via CLI
|
||||
capture: CaptureConfig::default(),
|
||||
encoding: EncodingConfig::default(),
|
||||
};
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
//! 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;
|
||||
@@ -28,8 +34,25 @@ async fn main() -> Result<()> {
|
||||
|
||||
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 config = config::Config::load()?;
|
||||
let mut config = config::Config::load()?;
|
||||
config.support_code = support_code;
|
||||
info!("Loaded configuration for server: {}", config.server_url);
|
||||
|
||||
// Run the agent
|
||||
|
||||
@@ -46,10 +46,13 @@ impl SessionManager {
|
||||
pub async fn connect(&mut self) -> Result<()> {
|
||||
self.state = SessionState::Connecting;
|
||||
|
||||
let hostname = self.config.hostname();
|
||||
let transport = WebSocketTransport::connect(
|
||||
&self.config.server_url,
|
||||
&self.config.agent_id,
|
||||
&self.config.api_key,
|
||||
Some(&hostname),
|
||||
self.config.support_code.as_deref(),
|
||||
).await?;
|
||||
|
||||
self.transport = Some(transport);
|
||||
|
||||
@@ -29,15 +29,35 @@ pub struct WebSocketTransport {
|
||||
|
||||
impl WebSocketTransport {
|
||||
/// Connect to the server
|
||||
pub async fn connect(url: &str, agent_id: &str, api_key: &str) -> Result<Self> {
|
||||
// Append agent_id and API key as query parameters
|
||||
pub async fn connect(
|
||||
url: &str,
|
||||
agent_id: &str,
|
||||
api_key: &str,
|
||||
hostname: Option<&str>,
|
||||
support_code: Option<&str>,
|
||||
) -> Result<Self> {
|
||||
// Build query parameters
|
||||
let mut params = format!("agent_id={}&api_key={}", agent_id, api_key);
|
||||
|
||||
if let Some(hostname) = hostname {
|
||||
params.push_str(&format!("&hostname={}", urlencoding::encode(hostname)));
|
||||
}
|
||||
|
||||
if let Some(code) = support_code {
|
||||
params.push_str(&format!("&support_code={}", code));
|
||||
}
|
||||
|
||||
// Append parameters to URL
|
||||
let url_with_params = if url.contains('?') {
|
||||
format!("{}&agent_id={}&api_key={}", url, agent_id, api_key)
|
||||
format!("{}&{}", url, params)
|
||||
} else {
|
||||
format!("{}?agent_id={}&api_key={}", url, agent_id, api_key)
|
||||
format!("{}?{}", url, params)
|
||||
};
|
||||
|
||||
tracing::info!("Connecting to {} as agent {}", url, agent_id);
|
||||
if let Some(code) = support_code {
|
||||
tracing::info!("Using support code: {}", code);
|
||||
}
|
||||
|
||||
let (ws_stream, response) = connect_async(&url_with_params)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user