const { app, BrowserWindow, ipcMain, shell, powerMonitor } = require('electron'); const path = require('path'); const { spawn, exec } = require('child_process'); const fs = require('fs'); const os = require('os'); const si = require('systeminformation'); let mainWindow; let apiProcess; // Empty function to prevent crashes since logging is disabled function logToDesktop(message) {} function createWindow() { mainWindow = new BrowserWindow({ width: 1300, height: 900, backgroundColor: '#ffffff', icon: path.join(__dirname, 'remiai.ico'), webPreferences: { nodeIntegration: true, contextIsolation: false, webviewTag: true // RESTORED: This allows your browsing feature to work }, autoHideMenuBar: true, title: "RemiAI - bujji" }); mainWindow.loadFile('index.html'); // --- FEATURE: TASK REMINDER SYSTEM --- mainWindow.webContents.on('did-finish-load', () => { mainWindow.webContents.send('check-tasks'); }); powerMonitor.on('resume', () => { if (mainWindow) mainWindow.webContents.send('check-tasks'); }); powerMonitor.on('unlock-screen', () => { if (mainWindow) mainWindow.webContents.send('check-tasks'); }); // ALLOW INTERNAL NAVIGATION mainWindow.webContents.setWindowOpenHandler(({ url }) => { return { action: 'allow' }; }); mainWindow.on('closed', function () { mainWindow = null; }); } // --- AI ENGINE BACKEND LOGIC (STRICT CPU ONLY) --- async function selectEngine() { try { const cpuFlags = await si.cpuFlags(); const flagsStr = JSON.stringify(cpuFlags).toLowerCase(); const basePath = app.isPackaged ? process.resourcesPath : __dirname; const engineBaseDir = path.join(basePath, 'engine'); const hasFolder = (f) => fs.existsSync(path.join(engineBaseDir, f)); // 1. Check for AVX2 (Priority for speed) if (flagsStr.includes('avx2') && hasFolder('cpu_avx2')) { return 'cpu_avx2'; } // 2. Fallback to standard AVX return 'cpu_avx'; } catch (e) { return 'cpu_avx'; } } async function startNativeBackend() { killProcess(); await new Promise(resolve => setTimeout(resolve, 500)); const engineSubfolder = await selectEngine(); const basePath = app.isPackaged ? process.resourcesPath : __dirname; const workingDir = path.join(basePath, 'engine', engineSubfolder); let exeName = fs.existsSync(path.join(workingDir, 'bujji_engine.exe')) ? 'bujji_engine.exe' : 'llama-server.exe'; const exePath = path.join(workingDir, exeName); // --- SPEED & CPU CONTROL --- // Your i5 has 8 logical threads. // Setting this to 4 uses 50% of your CPU capacity, ensuring fast 3-4s responses. const optimizedThreads = 4; const args = [ '-m', '../model.gguf', '-c', '2048', // Keeps memory usage low and response snappy '--batch-size', '512', // Increases prompt processing speed '--port', '5000', '-t', optimizedThreads.toString(), '--n-gpu-layers', '0', // Forced CPU only '--no-mmap' // Pre-loads model into RAM for zero lag ]; try { apiProcess = spawn(exePath, args, { cwd: workingDir, windowsHide: true, stdio: ['ignore', 'pipe', 'pipe'] }); apiProcess.stderr.on('data', (data) => logToDesktop(data.toString())); } catch (e) { logToDesktop(`Catch Error: ${e.message}`); } } function killProcess() { try { exec('taskkill /IM bujji_engine.exe /F /T'); exec('taskkill /IM llama-server.exe /F /T'); } catch(e) {} } ipcMain.on('restart-brain', () => { startNativeBackend(); if(mainWindow) mainWindow.webContents.send('brain-restarted'); }); ipcMain.on('reload-window', () => { if(mainWindow) mainWindow.reload(); }); // --- APP LIFECYCLE --- app.whenReady().then(() => { startNativeBackend(); createWindow(); }); app.on('window-all-closed', () => { killProcess(); if (process.platform !== 'darwin') app.quit(); }); app.on('will-quit', () => { killProcess(); });