const os = require("os"); const fs = require("fs"); const { spawnSync } = require("child_process"); const { PLUGIN_DATA, PLUGIN_ROOT } = require("./paths"); function detectHardware(models) { const freeDisk = getFreeDisk(); const totalRamMb = Math.floor(os.totalmem() / 1048576); const availableRamMb = Math.floor(os.freemem() / 1048576); const gpu = detectGpu(); const writable = testWritable(); const recommendation = [...models] .filter((model) => model.ram_gb * 1024 <= totalRamMb && model.size / 1048576 <= freeDisk) .sort((a, b) => b.ram_gb - a.ram_gb)[0]?.tier || "tiny"; return { platform: os.platform(), architecture: os.arch(), cpu_threads: os.cpus().length, total_ram_mb: totalRamMb, available_ram_mb: availableRamMb, free_disk_mb: freeDisk, gpu, subprocess_allowed: true, plugin_writable: writable, recommended_tier: recommendation, plugin_path: PLUGIN_ROOT, path_length: PLUGIN_ROOT.length, long_path_warning: os.platform()==="win32" && PLUGIN_ROOT.length > 220, network_path_warning: os.platform()==="win32" && PLUGIN_ROOT.startsWith("\\\\") }; } function getFreeDisk() { try { if (typeof fs.statfsSync === "function") { const stat = fs.statfsSync(PLUGIN_DATA); return Math.floor((Number(stat.bavail) * Number(stat.bsize)) / 1048576); } } catch {} return 0; } function detectGpu() { try { const result = spawnSync("nvidia-smi", ["--query-gpu=name,memory.total", "--format=csv,noheader,nounits"], { encoding: "utf8", timeout: 3000 }); if (result.status === 0 && result.stdout.trim()) { const [name, vram] = result.stdout.trim().split(",").map((v) => v.trim()); return { present: true, name, vram_mb: Number(vram) || null }; } } catch {} return { present: false, name: null, vram_mb: null }; } function testWritable() { try { const file = require("path").join(PLUGIN_DATA, ".write-test"); fs.writeFileSync(file, "ok"); fs.unlinkSync(file); return true; } catch { return false; } } module.exports = { detectHardware };