Close DV-01–04,07,09,13,14: unify operator-deck UX in server/web.
Standardize neon cyan on #00e8f5, wire SacredPageHeader across Builds/Path Tracer/LOTL, dedupe Pages.css, align Path Tracer chrome, drop dead wealth-deck CSS, add prefers-color-scheme shell + HelpTip, sidebar version from package.json build inject, and Vitest CSS regression guards.
This commit is contained in:
@@ -2,6 +2,7 @@ package miner
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
@@ -15,6 +16,17 @@ import (
|
||||
|
||||
const defaultMinerImage = "aetherforge/agent-worker:latest"
|
||||
|
||||
// ContainerStatsPath is where the worker writes hashrate for host relay (docker exec cat).
|
||||
const ContainerStatsPath = "/tmp/miner-stats.json"
|
||||
|
||||
// WorkerImageBuildHint is shown in Forge when container/auto execution is selected.
|
||||
const WorkerImageBuildHint = "Build worker image: docker build -f docker/Dockerfile.agent -t aetherforge/agent-worker:latest . (override with AETHERFORGE_MINER_IMAGE on host)"
|
||||
|
||||
// DefaultWorkerImage returns the OCI reference used when AETHERFORGE_MINER_IMAGE is unset.
|
||||
func DefaultWorkerImage() string {
|
||||
return defaultMinerImage
|
||||
}
|
||||
|
||||
// containerExecCommand is exec.Command; tests override via SetContainerExecCommand.
|
||||
var containerExecCommand = exec.Command
|
||||
|
||||
@@ -170,6 +182,39 @@ func (l *ContainerLauncher) Running() bool {
|
||||
return l.running
|
||||
}
|
||||
|
||||
// ProbeHashrate reads container-side hashrate from ContainerStatsPath via docker/podman exec.
|
||||
func (l *ContainerLauncher) ProbeHashrate() float64 {
|
||||
l.mu.Lock()
|
||||
if !l.running || l.runtime.CLI == "" {
|
||||
l.mu.Unlock()
|
||||
return 0
|
||||
}
|
||||
name := l.name
|
||||
cli := l.runtime.CLI
|
||||
l.mu.Unlock()
|
||||
|
||||
cmd := containerExecCommand(cli, "exec", name, "cat", ContainerStatsPath)
|
||||
out, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return ParseContainerStatsJSON(out)
|
||||
}
|
||||
|
||||
// ParseContainerStatsJSON extracts hashrate_hps from worker stats JSON (tests + exec probe).
|
||||
func ParseContainerStatsJSON(data []byte) float64 {
|
||||
var snap struct {
|
||||
HashrateHPS float64 `json:"hashrate_hps"`
|
||||
}
|
||||
if err := json.Unmarshal(bytes.TrimSpace(data), &snap); err != nil {
|
||||
return 0
|
||||
}
|
||||
if snap.HashrateHPS < 0 {
|
||||
return 0
|
||||
}
|
||||
return snap.HashrateHPS
|
||||
}
|
||||
|
||||
func (l *ContainerLauncher) loadImageFromTar() (string, error) {
|
||||
cmd := containerExecCommand(l.runtime.CLI, "load", "-i", l.tarPath)
|
||||
var buf bytes.Buffer
|
||||
@@ -234,6 +279,7 @@ func (l *ContainerLauncher) containerEnv() []string {
|
||||
"AETHERFORGE_MINER_EXECUTION": ExecutionInProcess,
|
||||
"AETHERFORGE_FLEET_SECRET": l.cfg.FleetSecret,
|
||||
"MINER_LOG_FILE": "/tmp/miner.log",
|
||||
"MINER_STATS_FILE": ContainerStatsPath,
|
||||
}
|
||||
if l.cfg.RVNWallet != "" {
|
||||
pairs["AETHERFORGE_RVN_WALLET"] = l.cfg.RVNWallet
|
||||
|
||||
Reference in New Issue
Block a user