Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing $BaseDir = "C:\MinerOpsAgent" $ConfigPath = Join-Path $BaseDir "agent-config.json" $StatePath = Join-Path $BaseDir "agent-state.json" $LogPath = Join-Path $BaseDir "logs\agent.log" $TaskName = "MinerOpsAgent" function Read-Config { if (Test-Path $ConfigPath) { return Get-Content $ConfigPath -Raw | ConvertFrom-Json } return $null } function Read-ConfigText { if (Test-Path $ConfigPath) { return Get-Content $ConfigPath -Raw } return "" } function Save-ConfigObject { param([object]$Config) $Config | ConvertTo-Json -Depth 10 | Set-Content -Path $ConfigPath -Encoding UTF8 } function Save-ConfigText { param([string]$Text) $Text | Set-Content -Path $ConfigPath -Encoding UTF8 } function Get-AgentTaskText { $task = Get-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue if (!$task) { return "Scheduled task not installed" } $info = Get-ScheduledTaskInfo -TaskName $TaskName -ErrorAction SilentlyContinue return "$($task.State) | Last result: $($info.LastTaskResult) | Last run: $($info.LastRunTime)" } $form = New-Object System.Windows.Forms.Form $form.Text = "MinerOps Agent" $form.Size = New-Object System.Drawing.Size(950, 780) $form.StartPosition = "CenterScreen" $statusLabel = New-Object System.Windows.Forms.Label $statusLabel.Location = New-Object System.Drawing.Point(15, 15) $statusLabel.Size = New-Object System.Drawing.Size(900, 24) $statusLabel.Text = "Task: " + (Get-AgentTaskText) $form.Controls.Add($statusLabel) $startButton = New-Object System.Windows.Forms.Button $startButton.Text = "Start" $startButton.Location = New-Object System.Drawing.Point(15, 45) $startButton.Size = New-Object System.Drawing.Size(100, 32) $form.Controls.Add($startButton) $stopButton = New-Object System.Windows.Forms.Button $stopButton.Text = "Stop" $stopButton.Location = New-Object System.Drawing.Point(125, 45) $stopButton.Size = New-Object System.Drawing.Size(100, 32) $form.Controls.Add($stopButton) $restartButton = New-Object System.Windows.Forms.Button $restartButton.Text = "Restart" $restartButton.Location = New-Object System.Drawing.Point(235, 45) $restartButton.Size = New-Object System.Drawing.Size(100, 32) $form.Controls.Add($restartButton) $testButton = New-Object System.Windows.Forms.Button $testButton.Text = "Test Hub" $testButton.Location = New-Object System.Drawing.Point(345, 45) $testButton.Size = New-Object System.Drawing.Size(100, 32) $form.Controls.Add($testButton) $saveButton = New-Object System.Windows.Forms.Button $saveButton.Text = "Save Config" $saveButton.Location = New-Object System.Drawing.Point(455, 45) $saveButton.Size = New-Object System.Drawing.Size(120, 32) $form.Controls.Add($saveButton) $secretLabel = New-Object System.Windows.Forms.Label $secretLabel.Text = "Agent Secret:" $secretLabel.Location = New-Object System.Drawing.Point(15, 90) $secretLabel.Size = New-Object System.Drawing.Size(100, 22) $form.Controls.Add($secretLabel) $secretBox = New-Object System.Windows.Forms.TextBox $secretBox.Location = New-Object System.Drawing.Point(115, 87) $secretBox.Size = New-Object System.Drawing.Size(570, 24) $secretBox.UseSystemPasswordChar = $true $form.Controls.Add($secretBox) $showSecretCheck = New-Object System.Windows.Forms.CheckBox $showSecretCheck.Text = "Show" $showSecretCheck.Location = New-Object System.Drawing.Point(695, 88) $showSecretCheck.Size = New-Object System.Drawing.Size(70, 24) $form.Controls.Add($showSecretCheck) $saveSecretButton = New-Object System.Windows.Forms.Button $saveSecretButton.Text = "Save Secret" $saveSecretButton.Location = New-Object System.Drawing.Point(775, 84) $saveSecretButton.Size = New-Object System.Drawing.Size(120, 30) $form.Controls.Add($saveSecretButton) $configBox = New-Object System.Windows.Forms.TextBox $configBox.Location = New-Object System.Drawing.Point(15, 125) $configBox.Size = New-Object System.Drawing.Size(900, 350) $configBox.Multiline = $true $configBox.ScrollBars = "Both" $configBox.Font = New-Object System.Drawing.Font("Consolas", 10) $configBox.Text = Read-ConfigText $form.Controls.Add($configBox) $stateBox = New-Object System.Windows.Forms.TextBox $stateBox.Location = New-Object System.Drawing.Point(15, 490) $stateBox.Size = New-Object System.Drawing.Size(900, 85) $stateBox.Multiline = $true $stateBox.ScrollBars = "Vertical" $stateBox.Font = New-Object System.Drawing.Font("Consolas", 9) $form.Controls.Add($stateBox) $logBox = New-Object System.Windows.Forms.TextBox $logBox.Location = New-Object System.Drawing.Point(15, 590) $logBox.Size = New-Object System.Drawing.Size(900, 130) $logBox.Multiline = $true $logBox.ScrollBars = "Vertical" $logBox.Font = New-Object System.Drawing.Font("Consolas", 9) $form.Controls.Add($logBox) function Refresh-Display { $statusLabel.Text = "Task: " + (Get-AgentTaskText) $config = Read-Config if ($config -and $secretBox.Text.Length -eq 0) { $secretBox.Text = [string]$config.agent_secret } if (Test-Path $StatePath) { $stateBox.Text = Get-Content $StatePath -Raw } else { $stateBox.Text = "No state file yet." } if (Test-Path $LogPath) { $logBox.Text = (Get-Content $LogPath -Tail 30) -join [Environment]::NewLine } else { $logBox.Text = "No log file yet." } } $showSecretCheck.Add_CheckedChanged({ $secretBox.UseSystemPasswordChar = -not $showSecretCheck.Checked }) $saveSecretButton.Add_Click({ try { $config = $configBox.Text | ConvertFrom-Json $config.agent_secret = $secretBox.Text $config | ConvertTo-Json -Depth 10 | Set-Content -Path $ConfigPath -Encoding UTF8 $configBox.Text = Get-Content $ConfigPath -Raw [System.Windows.Forms.MessageBox]::Show("Secret saved. Restart the agent to apply changes.") } catch { [System.Windows.Forms.MessageBox]::Show("Could not save secret: " + $_.Exception.Message) } }) $startButton.Add_Click({ Start-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 Refresh-Display }) $stopButton.Add_Click({ Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 Refresh-Display }) $restartButton.Add_Click({ Stop-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Start-Sleep -Seconds 2 Start-ScheduledTask -TaskName $TaskName -ErrorAction SilentlyContinue Start-Sleep -Seconds 1 Refresh-Display }) $saveButton.Add_Click({ try { $null = $configBox.Text | ConvertFrom-Json Save-ConfigText -Text $configBox.Text [System.Windows.Forms.MessageBox]::Show("Config saved. Restart the agent to apply changes.") } catch { [System.Windows.Forms.MessageBox]::Show("Invalid JSON: " + $_.Exception.Message) } }) $testButton.Add_Click({ try { $config = $configBox.Text | ConvertFrom-Json if ($secretBox.Text.Length -gt 0) { $config.agent_secret = $secretBox.Text } $hub = [string]$config.hub_url $agentId = [string]$config.agent_id $secret = [string]$config.agent_secret $headers = @{ "X-MinerOps-Agent-ID" = $agentId "X-MinerOps-Agent-Secret" = $secret } $result = Invoke-RestMethod -Uri ($hub.TrimEnd("/") + "/api/agent/config") -Headers $headers -TimeoutSec 20 [System.Windows.Forms.MessageBox]::Show("Hub test OK.`nSite: " + $result.site_name) } catch { [System.Windows.Forms.MessageBox]::Show("Hub test failed: " + $_.Exception.Message) } }) $timer = New-Object System.Windows.Forms.Timer $timer.Interval = 3000 $timer.Add_Tick({ Refresh-Display }) $timer.Start() Refresh-Display [void]$form.ShowDialog()