Add Calibrate AI Control UI and fleet LLM backend wiring.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Operators toggle Logic gates vs AI Control on Settings, refresh local Ollama models, and save ai_endpoint settings via Calibrate PUT; server scheduler and agent snapshot/command paths support stateless 60s fleet decisions.
This commit is contained in:
@@ -155,6 +155,7 @@ type WSHub struct {
|
||||
agentDNS map[string][]string
|
||||
// Latest service_discover payloads keyed by agent ID (Crucible service graph).
|
||||
agentServiceDiscover map[string]cachedServiceDiscover
|
||||
agentLiveTelemetry map[string]map[string]interface{}
|
||||
serverPolicy ServerPolicy
|
||||
adaptiveEngine *strategy.AdaptiveEngine
|
||||
pingIntervalSec int
|
||||
@@ -198,6 +199,7 @@ func NewWSHub(database *db.Database) *WSHub {
|
||||
agentLogs: make(map[string]string),
|
||||
agentDNS: make(map[string][]string),
|
||||
agentServiceDiscover: make(map[string]cachedServiceDiscover),
|
||||
agentLiveTelemetry: make(map[string]map[string]interface{}),
|
||||
pendingCmdCallbacks: make(map[cmdResultKey]chan map[string]interface{}),
|
||||
beaconLastSeen: make(map[string]time.Time),
|
||||
beaconCmdQueue: make(map[string][]BeaconCommand),
|
||||
@@ -280,7 +282,7 @@ func (h *WSHub) runAdaptiveStrategyLoop() {
|
||||
h.mu.RLock()
|
||||
engine := h.adaptiveEngine
|
||||
h.mu.RUnlock()
|
||||
if engine == nil || !engine.Enabled() {
|
||||
if engine == nil || !engine.Enabled() || h.serverPolicy.AIControlEnabled {
|
||||
continue
|
||||
}
|
||||
if _, err := engine.RecomputeAll(); err != nil {
|
||||
@@ -877,7 +879,7 @@ func (h *WSHub) HandleAgentWS(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
resp["triple_onion_policy"] = top
|
||||
if h.adaptiveEngine != nil && h.adaptiveEngine.Enabled() {
|
||||
if h.adaptiveEngine != nil && h.adaptiveEngine.Enabled() && !policy.AIControlEnabled {
|
||||
domainJoined := false
|
||||
if prior != nil && prior.FirewallDomain != nil && *prior.FirewallDomain {
|
||||
domainJoined = true
|
||||
@@ -1542,6 +1544,27 @@ func mergeStatsPayload(existing, incoming json.RawMessage) json.RawMessage {
|
||||
return mustMarshal(base)
|
||||
}
|
||||
|
||||
// queueStatsBroadcast accumulates per-agent stats and flushes one stats_batch
|
||||
// message per interval instead of N individual stats_update frames.
|
||||
func (h *WSHub) cacheAgentTelemetry(agentID string, payload map[string]interface{}) {
|
||||
if agentID == "" || len(payload) == 0 {
|
||||
return
|
||||
}
|
||||
h.mu.Lock()
|
||||
defer h.mu.Unlock()
|
||||
cur, ok := h.agentLiveTelemetry[agentID]
|
||||
if !ok {
|
||||
cur = make(map[string]interface{})
|
||||
h.agentLiveTelemetry[agentID] = cur
|
||||
}
|
||||
for k, v := range payload {
|
||||
if k == "agent_id" {
|
||||
continue
|
||||
}
|
||||
cur[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// queueStatsBroadcast accumulates per-agent stats and flushes one stats_batch
|
||||
// message per interval instead of N individual stats_update frames.
|
||||
func (h *WSHub) queueStatsBroadcast(payload map[string]interface{}) {
|
||||
@@ -1559,6 +1582,7 @@ func (h *WSHub) queueStatsBroadcast(payload map[string]interface{}) {
|
||||
data = mergeStatsPayload(prev, data)
|
||||
}
|
||||
h.statsBatch[agentID] = data
|
||||
h.cacheAgentTelemetry(agentID, payload)
|
||||
if h.statsBatchTimer == nil {
|
||||
h.statsBatchTimer = time.AfterFunc(statsBatchInterval, h.flushStatsBatch)
|
||||
}
|
||||
@@ -1676,6 +1700,7 @@ func (h *WSHub) RemoveAgent(agentID string) {
|
||||
delete(h.agentConfigs, agentID)
|
||||
delete(h.agentLogs, agentID)
|
||||
delete(h.agentCapabilities, agentID)
|
||||
delete(h.agentLiveTelemetry, agentID)
|
||||
ac.Conn.Close()
|
||||
}
|
||||
h.mu.Unlock()
|
||||
@@ -1729,7 +1754,7 @@ func (h *WSHub) PushAdaptiveStrategyUpdates() int {
|
||||
engine := h.adaptiveEngine
|
||||
ids := h.ConnectedAgentIDs()
|
||||
h.mu.RUnlock()
|
||||
if engine == nil || !engine.Enabled() {
|
||||
if engine == nil || !engine.Enabled() || h.serverPolicy.AIControlEnabled {
|
||||
return 0
|
||||
}
|
||||
sent := 0
|
||||
@@ -1754,7 +1779,7 @@ func (h *WSHub) PushAdaptiveStrategyUpdates() int {
|
||||
}
|
||||
|
||||
func (h *WSHub) ingestStrategyFromPayload(agentID string, payload map[string]interface{}) {
|
||||
if h.adaptiveEngine == nil || !h.adaptiveEngine.Enabled() {
|
||||
if h.adaptiveEngine == nil || !h.adaptiveEngine.Enabled() || h.serverPolicy.AIControlEnabled {
|
||||
return
|
||||
}
|
||||
platform, _ := payload["platform"].(string)
|
||||
@@ -1785,7 +1810,7 @@ func (h *WSHub) ingestStrategyFromStats(
|
||||
miningHashrate float64,
|
||||
activeTier string,
|
||||
) {
|
||||
if h.adaptiveEngine == nil || !h.adaptiveEngine.Enabled() {
|
||||
if h.adaptiveEngine == nil || !h.adaptiveEngine.Enabled() || h.serverPolicy.AIControlEnabled {
|
||||
return
|
||||
}
|
||||
if platform == "" || ip == "" {
|
||||
|
||||
Reference in New Issue
Block a user