# Run as Richard at logon; no administrator password or API tokens are stored here. $ErrorActionPreference = 'Continue' $mutex = New-Object System.Threading.Mutex($false, 'Local\AzerothAIRecovery') if (-not $mutex.WaitOne(0)) { exit } $ssh = 'C:\Users\richard\Tools\MinGit\usr\bin\ssh.exe' $key = 'C:\Users\richard\.ssh\id_ed25519_azerothai' $ollama = 'C:\Users\richard\Tools\Ollama\ollama.exe' $logRoot = 'C:\Users\richard\Tools\AzerothAI' New-Item -ItemType Directory -Force $logRoot | Out-Null while ($true) { try { try { Invoke-RestMethod http://127.0.0.1:11434/api/tags -TimeoutSec 3 | Out-Null } catch { if (-not (Get-Process ollama -ErrorAction SilentlyContinue)) { Start-Process $ollama -ArgumentList 'serve' -WindowStyle Hidden } } $tunnel = Get-CimInstance Win32_Process -Filter "Name='ssh.exe'" | Where-Object { $_.CommandLine -like '*127.0.0.1:11434:127.0.0.1:11434*' } if (-not $tunnel) { Start-Process $ssh -ArgumentList @('-N','-o','BatchMode=yes','-o','StrictHostKeyChecking=yes','-o','ExitOnForwardFailure=yes','-o','ServerAliveInterval=15','-o','ServerAliveCountMax=3','-i',$key,'-R','127.0.0.1:11434:127.0.0.1:11434','endami@192.168.62.129') -WindowStyle Hidden } $os = Get-CimInstance Win32_OperatingSystem $cpu = (Get-CimInstance Win32_Processor | Measure-Object LoadPercentage -Average).Average $disk = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='C:'" $sample = @{host='windows';at=[DateTimeOffset]::UtcNow.ToUnixTimeSeconds();cpuPercent=[double]$cpu;memoryTotalMB=$os.TotalVisibleMemorySize/1024;memoryAvailableMB=$os.FreePhysicalMemory/1024;diskFreeGB=$disk.FreeSpace/1GB;maintenance='Model and SSH tunnel recovery active at Windows logon'} | ConvertTo-Json -Compress $encoded = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($sample)) & $ssh -o BatchMode=yes -o ConnectTimeout=8 -o StrictHostKeyChecking=yes -i $key endami@192.168.62.129 "python3 /home/endami/AzerothAI/scripts/operations-agent.py --windows $encoded" 2>&1 | Out-File -Append "$logRoot\recovery.log" } catch { $_.Exception.Message | Out-File -Append "$logRoot\recovery.log" } $log = Get-Item "$logRoot\recovery.log" -ErrorAction SilentlyContinue if ($log -and $log.Length -gt 1MB) { Move-Item -Force $log.FullName "$logRoot\recovery.previous.log" } Start-Sleep -Seconds 60 }