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:
@@ -20,6 +20,7 @@ import (
|
||||
"crypto-miner-server/internal/builder"
|
||||
"crypto-miner-server/internal/cloudflared"
|
||||
"crypto-miner-server/internal/db"
|
||||
fleetai "crypto-miner-server/internal/ai"
|
||||
"crypto-miner-server/internal/maintenance"
|
||||
"crypto-miner-server/internal/pool"
|
||||
"crypto-miner-server/internal/scheduler"
|
||||
@@ -268,6 +269,17 @@ func main() {
|
||||
defer fleetSched.Stop()
|
||||
wsHub.SetConnectTaskRunner(fleetSched)
|
||||
|
||||
fleetAISched := fleetai.NewScheduler(
|
||||
&api.ConfigAIAdapter{Src: configProvider},
|
||||
&api.WSHubSnapshotAdapter{Hub: wsHub},
|
||||
&api.FleetAIExecutor{Hub: wsHub},
|
||||
&api.DatabaseAIDecisionStore{DB: database},
|
||||
)
|
||||
fleetAISched.Start()
|
||||
defer fleetAISched.Stop()
|
||||
fleetAIHandler := api.NewFleetAIHandler(configProvider, database)
|
||||
log.Println("Fleet AI Control scheduler initialized")
|
||||
|
||||
// Initialize blueprint handler (config presets)
|
||||
blueprintHandler := api.NewBlueprintHandler(cfg.DataDir)
|
||||
log.Println("Blueprint handler initialized")
|
||||
@@ -305,7 +317,7 @@ func main() {
|
||||
log.Printf("Web root: %s", webRoot)
|
||||
|
||||
// Initialize router
|
||||
router := api.NewRouter(database, wsHub, configHandler, builderHandler, blueprintHandler, aiHandler, fleetHandler, dropperHandler, spreadHandler, spreadCredHandler, deployPlanHandler, publicHandler, pathForgeHandler, pathTracerHandler, webRoot, cfg.DataDir, func() string {
|
||||
router := api.NewRouter(database, wsHub, configHandler, builderHandler, blueprintHandler, aiHandler, fleetHandler, fleetAIHandler, dropperHandler, spreadHandler, spreadCredHandler, deployPlanHandler, publicHandler, pathForgeHandler, pathTracerHandler, webRoot, cfg.DataDir, func() string {
|
||||
return configProvider.PublicURL()
|
||||
}, cfg.Port, func() bool {
|
||||
return cfg.ConnectorToken() != ""
|
||||
@@ -379,6 +391,7 @@ func applyRuntimeConfig(cfg *Config, wsHub *api.WSHub, poolManager *pool.Manager
|
||||
ReconTiers: cfg.Server.TripleOnionPolicy.ReconTiers,
|
||||
DeployLanes: cfg.Server.TripleOnionPolicy.DeployLanes,
|
||||
},
|
||||
AIControlEnabled: cfg.Server.AIControlEnabled,
|
||||
})
|
||||
}
|
||||
if poolManager != nil {
|
||||
@@ -479,6 +492,46 @@ func (p *serverConfigProvider) UpdateConfigFromJSON(data json.RawMessage) error
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *serverConfigProvider) GetFleetAIConfig() api.FleetAIConfigView {
|
||||
if p == nil || p.config == nil {
|
||||
return api.FleetAIConfigView{}
|
||||
}
|
||||
s := p.config.Server
|
||||
interval := s.AIDecisionIntervalSec
|
||||
if interval <= 0 {
|
||||
interval = 60
|
||||
}
|
||||
return api.FleetAIConfigView{
|
||||
AIControlEnabled: s.AIControlEnabled,
|
||||
AIEndpoint: s.AIEndpoint,
|
||||
AIModel: s.AIModel,
|
||||
AINoContext: s.AINoContext,
|
||||
AIDecisionIntervalSec: interval,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *serverConfigProvider) UpdateFleetAIConfig(v api.FleetAIConfigView) error {
|
||||
if p == nil || p.config == nil {
|
||||
return fmt.Errorf("config unavailable")
|
||||
}
|
||||
if v.AIDecisionIntervalSec < 0 {
|
||||
return fmt.Errorf("ai_decision_interval_sec must be ≥ 0")
|
||||
}
|
||||
payload, err := json.Marshal(map[string]interface{}{
|
||||
"server": map[string]interface{}{
|
||||
"ai_control_enabled": v.AIControlEnabled,
|
||||
"ai_endpoint": v.AIEndpoint,
|
||||
"ai_model": v.AIModel,
|
||||
"ai_no_context": v.AINoContext,
|
||||
"ai_decision_interval_sec": v.AIDecisionIntervalSec,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.UpdateConfigFromJSON(payload)
|
||||
}
|
||||
|
||||
// findAgentSourceDir locates the agent source code directory
|
||||
// It searches relative to the server binary location and the current working directory
|
||||
func findAgentSourceDir() string {
|
||||
|
||||
Reference in New Issue
Block a user