feat: structured startup header with privileges, device, session

This commit is contained in:
Helios Agent 2026-03-05 20:22:58 +01:00
parent b37eec24bc
commit 03d80067a8
No known key found for this signature in database
GPG key ID: C8259547CD8309B5
2 changed files with 22 additions and 20 deletions

View file

@ -100,19 +100,13 @@ pub fn cmd_done(action: &str, name: &str, payload: &str, success: bool, result:
crate::logger::write_line(if success { "OK" } else { "ERROR" }, &format!("{name} {payload}{result}"));
}
/// Plain status line (banner / connection info), not in table format.
/// Uses 2 leading spaces + emoji + 2 spaces + message (no tab).
pub fn status(emoji: &str, msg: &str) {
println!(" {} {}", emoji, msg);
}
/// Same as status() but also logs to file.
pub fn ok(emoji: &str, msg: &str) {
println!(" {} {}", emoji, msg);
crate::logger::write_line("OK", msg);
/// Info line for the startup header (not in table format).
/// Aligns key to a fixed width so values line up.
pub fn info_line(emoji: &str, key: &str, value: &str) {
println!(" {} {:<12} {}", emoji_cell(emoji), key, value);
}
pub fn err(emoji: &str, msg: &str) {
println!(" {} {}", emoji, msg.red());
println!(" {} {}", emoji_cell(emoji), msg.red());
crate::logger::write_line("ERROR", msg);
}

View file

@ -26,16 +26,24 @@ use display::trunc;
fn banner() {
println!();
println!(" {} HELIOS REMOTE ({})", "".yellow().bold(), env!("GIT_COMMIT"));
}
fn print_session_info(label: &str, sid: &uuid::Uuid) {
#[cfg(windows)]
{
let admin = is_admin();
let (icon, admin_str) = if admin {
("👑", "admin".green().bold().to_string())
let priv_str = if admin {
"admin".green().bold().to_string()
} else {
("👤", "user (no admin)".yellow().to_string())
"no admin".yellow().to_string()
};
println!(" {} {}", icon, admin_str);
display::info_line("👤", "privileges:", &priv_str);
}
#[cfg(not(windows))]
display::info_line("👤", "privileges:", &"no admin".yellow().to_string());
display::info_line("🖥", "device:", &label.bold().to_string());
display::info_line("#️⃣", "session:", &sid.to_string().dimmed().to_string());
println!();
}
@ -154,14 +162,14 @@ async fn main() {
let config = match Config::load() {
Some(c) => c,
None => {
display::status("", "No config found — first-time setup");
display::info_line("", "setup:", "No config found — first-time setup");
println!();
let c = prompt_config();
println!();
if let Err(e) = c.save() {
display::err("", &format!("Failed to save config: {e}"));
} else {
display::ok("", "Config saved");
display::info_line("", "config:", "saved");
}
c
}
@ -181,6 +189,9 @@ async fn main() {
}
};
let label = config.label.clone().unwrap_or_else(|| hostname());
print_session_info(&label, &sid);
let config = Arc::new(config);
let shell = Arc::new(Mutex::new(shell::PersistentShell::new()));
@ -206,10 +217,7 @@ async fn main() {
match connect_async_tls_with_config(&config.relay_url, None, false, Some(connector)).await {
Ok((ws_stream, _)) => {
let label = config.label.clone().unwrap_or_else(|| hostname());
display::cmd_done("🌐", "connecting", host, true, "connected");
display::cmd_start("", "session", &label);
display::cmd_done("", "session", &label, true, &sid.to_string());
println!();
backoff = Duration::from_secs(1);