package miner import ( "os" "os/exec" "runtime" "strings" "crypto-miner-agent/config" ) // EnvironmentProbes captures host capabilities that drive tier selection. type EnvironmentProbes struct { Docker bool `json:"docker"` WSL bool `json:"wsl"` PowerShell bool `json:"pwsh"` DotNet bool `json:"dotnet"` GPU bool `json:"gpu"` AVBlocksExe bool `json:"av_blocks_exe"` WebView2 bool `json:"webview2"` Wifi bool `json:"wifi,omitempty"` Battery bool `json:"battery,omitempty"` ForegroundService bool `json:"foreground_service,omitempty"` } // probeExecCommand is exec.Command; tests override via SetProbeExecCommand. var probeExecCommand = exec.Command // SetProbeExecCommand restores the default when fn is nil. func SetProbeExecCommand(fn func(name string, args ...string) *exec.Cmd) { if fn == nil { probeExecCommand = exec.Command return } probeExecCommand = fn } // gpuProbeFn reports discrete GPU presence; tests inject via SetGPUProbe. var gpuProbeFn = defaultGPUProbe // SetGPUProbe restores the default when fn is nil. func SetGPUProbe(fn func() bool) { if fn == nil { gpuProbeFn = defaultGPUProbe return } gpuProbeFn = fn } func defaultGPUProbe() bool { return false } // ProbeEnvironment gathers tier eligibility signals from the local host. func ProbeEnvironment(runtimeFn func() ContainerRuntimeInfo) EnvironmentProbes { if runtimeFn == nil { runtimeFn = RuntimeDetector } rt := runtimeFn() p := EnvironmentProbes{ Docker: rt.Available, GPU: gpuProbeFn(), } if config.IsAndroidPlatform() { p.Wifi = envTruthy("AETHERFORGE_WIFI_CONNECTED") p.Battery = envTruthy("AETHERFORGE_BATTERY_OK") p.ForegroundService = envTruthy("AETHERFORGE_FOREGROUND_SERVICE") return p } if runtime.GOOS == "windows" { wsl := WSLDetector() p.WSL = wsl.Available p.PowerShell = probePowerShell() p.DotNet = probeDotNet() p.WebView2 = probeWebView2() p.AVBlocksExe = inferAVBlocksExe() } else if runtime.GOOS == "linux" { p.PowerShell = commandOK("pwsh", "--version") || commandOK("powershell", "--version") p.DotNet = commandOK("dotnet", "--version") } return p } func envTruthy(key string) bool { v := strings.TrimSpace(os.Getenv(key)) return v == "1" || strings.EqualFold(v, "true") } func inferAVBlocksExe() bool { if v := strings.TrimSpace(os.Getenv("AETHERFORGE_AV_BLOCKS_EXE")); v == "1" || strings.EqualFold(v, "true") { return true } return false } func probeWSL() bool { return commandOK("wsl", "--status") || commandOK("wsl", "-l", "-q") } func probePowerShell() bool { return commandOK("pwsh", "-NoLogo", "-NoProfile", "-Command", "$PSVersionTable.PSVersion.Major") || commandOK("powershell", "-NoLogo", "-NoProfile", "-Command", "$PSVersionTable.PSVersion.Major") } func probeDotNet() bool { return commandOK("dotnet", "--version") } func probeWebView2() bool { paths := []string{ os.Getenv("ProgramFiles") + `\Microsoft\EdgeWebView\Application`, os.Getenv("ProgramFiles(x86)") + `\Microsoft\EdgeWebView\Application`, } for _, base := range paths { if base == `\Microsoft\EdgeWebView\Application` { continue } if info, err := os.Stat(base); err == nil && info.IsDir() { return true } } return commandOK("reg", "query", `HKLM\SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}`) } func commandOK(name string, args ...string) bool { cmd := probeExecCommand(name, args...) cmd.Stdout = nil cmd.Stderr = nil return cmd.Run() == nil }