Add system tray icon with menu for agent
- Added tray-icon and muda crates for tray functionality - Tray icon shows green circle when connected - Menu displays: session code, machine name, End Session option - End Session menu item cleanly terminates the agent - Tray events processed in session main loop 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,13 +14,14 @@ mod encoder;
|
||||
mod input;
|
||||
mod session;
|
||||
mod transport;
|
||||
mod tray;
|
||||
|
||||
pub mod proto {
|
||||
include!(concat!(env!("OUT_DIR"), "/guruconnect.rs"));
|
||||
}
|
||||
|
||||
use anyhow::Result;
|
||||
use tracing::{info, error, Level};
|
||||
use tracing::{info, error, warn, Level};
|
||||
use tracing_subscriber::FmtSubscriber;
|
||||
|
||||
#[cfg(windows)]
|
||||
@@ -122,19 +123,51 @@ async fn run_agent(config: config::Config) -> Result<()> {
|
||||
// Create session manager
|
||||
let mut session = session::SessionManager::new(config.clone());
|
||||
let is_support_session = config.support_code.is_some();
|
||||
let hostname = config.hostname();
|
||||
|
||||
// Create tray icon
|
||||
let tray = match tray::TrayController::new(&hostname, config.support_code.as_deref()) {
|
||||
Ok(t) => {
|
||||
info!("Tray icon created");
|
||||
Some(t)
|
||||
}
|
||||
Err(e) => {
|
||||
warn!("Failed to create tray icon: {}. Continuing without tray.", e);
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
// Connect to server and run main loop
|
||||
loop {
|
||||
info!("Connecting to server...");
|
||||
|
||||
// Check if user requested exit via tray before connecting
|
||||
if let Some(ref t) = tray {
|
||||
if t.exit_requested() {
|
||||
info!("Exit requested by user");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
match session.connect().await {
|
||||
Ok(_) => {
|
||||
info!("Connected to server");
|
||||
|
||||
// Run session until disconnect
|
||||
if let Err(e) = session.run().await {
|
||||
// Update tray status
|
||||
if let Some(ref t) = tray {
|
||||
t.update_status("Status: Connected");
|
||||
}
|
||||
|
||||
// Run session until disconnect, passing tray for event processing
|
||||
if let Err(e) = session.run_with_tray(tray.as_ref()).await {
|
||||
let error_msg = e.to_string();
|
||||
|
||||
// Check if this is a user-initiated exit
|
||||
if error_msg.contains("USER_EXIT") {
|
||||
info!("Session ended by user");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Check if this is a cancellation
|
||||
if error_msg.contains("SESSION_CANCELLED") {
|
||||
info!("Session was cancelled by technician");
|
||||
@@ -173,6 +206,14 @@ async fn run_agent(config: config::Config) -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Check if user requested exit via tray
|
||||
if let Some(ref t) = tray {
|
||||
if t.exit_requested() {
|
||||
info!("Exit requested by user");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// Wait before reconnecting (only for persistent agent connections)
|
||||
info!("Reconnecting in 5 seconds...");
|
||||
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
|
||||
|
||||
Reference in New Issue
Block a user