feat(tray): desktop tray icon companion with Theta logo, color-coded status, and home LAN detection (#10)

- tray_icons.go / cmd/theta-agent-tray: Renders iconic Theta 42 logo in status colors:
    - 🔴 Red: Not connected to directory
    - 🟡 Yellow: Connected to directory, but not on home LAN
    - 🟢 Green: Connected to directory on home LAN
    - 🔵 Blue: Connected to directory with active WireGuard tunnel
- home_detect.go: Compares agent public IP with home site public IP
- tray_server.go / tray_ipc.go: Unix socket IPC daemon server (/run/theta/tray.sock or /tmp/theta-tray.sock)
- cmd/theta-agent-tray: Desktop GUI binary with system tray menu (Auto-connect toggle, Connect/Disconnect VPN)
- Auto-detects DISPLAY / WAYLAND_DISPLAY environment variables
This commit is contained in:
2026-08-08 23:16:20 -04:00
committed by GitHub
parent 34f6f685fc
commit c676c658ed
20 changed files with 470 additions and 5 deletions
+9 -5
View File
@@ -157,6 +157,7 @@ func connectWebSocket(cm *ConfigManager, exec Executor) {
}
log.Println("Successfully connected to SSO Manager.")
wsConnected.Store(true)
stopCh := make(chan struct{})
@@ -230,6 +231,7 @@ func connectWebSocket(cm *ConfigManager, exec Executor) {
}
// Cleanup on disconnect
wsConnected.Store(false)
close(stopCh)
c.Close()
@@ -336,11 +338,7 @@ func handleCommand(cm *ConfigManager, msg WSMessage, c MessageWriter, exec Execu
os.Exit(0)
case "config":
// A config frame carrying credentials means the server accepted our
// join key and enrolled this host. Persist what it issued -- our own
// per-agent token and the public key to pin -- so the next connection
// authenticates as this agent rather than re-enrolling, and so signed
// commands can be verified. This is what lets an install ship with only
// a join key and still end up fully configured.
// join key and enrolled this host.
if enrolled, _ := msg.Payload["enrolled"].(bool); enrolled {
token, _ := msg.Payload["auth_token"].(string)
pubKey, _ := msg.Payload["public_key"].(string)
@@ -353,6 +351,12 @@ func handleCommand(cm *ConfigManager, msg WSMessage, c MessageWriter, exec Execu
sendResponse("ok", "enrollment stored")
return
}
// Extract the home site's public IP if the server pushes it, so the
// tray icon can determine whether we are on the home LAN.
if sitePublicIP, ok := msg.Payload["site_public_ip"].(string); ok && sitePublicIP != "" {
SetHomePublicIP(sitePublicIP)
log.Printf("[home-detect] home site public IP: %s", sitePublicIP)
}
log.Printf("Received config payload: %v", msg.Payload)
sendResponse("ok", "Configuration received")
case "reboot":