exiouss 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of exiouss might be problematic. Click here for more details.

package/main.js ADDED
@@ -0,0 +1,1198 @@
1
+ // ═══════════════════════════════════════════
2
+ // GLOBAL STEALTH BOOT (MUST BE FIRST)
3
+ // ═══════════════════════════════════════════
4
+ const { app, BrowserWindow, screen, ipcMain, globalShortcut, clipboard, nativeImage, desktopCapturer, session } = require('electron');
5
+ app.commandLine.appendSwitch('disable-blink-features', 'AutomationControlled');
6
+ app.commandLine.appendSwitch('disable-features', 'UserAgentClientHint');
7
+ app.commandLine.appendSwitch('no-sandbox');
8
+ app.commandLine.appendSwitch('disable-site-isolation-trials');
9
+
10
+ // CRITICAL: Prevent Chromium from pausing DOM updates when window is "hidden"
11
+ app.commandLine.appendSwitch('disable-renderer-backgrounding');
12
+ app.commandLine.appendSwitch('disable-background-timer-throttling');
13
+ app.commandLine.appendSwitch('disable-backgrounding-occluded-windows');
14
+ app.commandLine.appendSwitch('disable-features', 'CalculateNativeWinOcclusion');
15
+
16
+ const path = require('path');
17
+ const fs = require('fs');
18
+ const os = require('os');
19
+ const { exec } = require('child_process');
20
+ const { powerSaveBlocker } = require('electron');
21
+
22
+ // 🛡️ POWER SHIELD: Prevent system/renderer suspension
23
+ powerSaveBlocker.start('prevent-app-suspension');
24
+
25
+ // 🔋 PROCESS PRIORITY: High Priority to fight proctoring CPU throttling
26
+ try {
27
+ os.setPriority(0, -14); // HIGH_PRIORITY_CLASS
28
+ console.log('[SYSTEM] Process priority boosted to HIGH.');
29
+ } catch(e) {
30
+ console.warn('[SYSTEM] Could not boost priority (need Admin):', e.message);
31
+ }
32
+
33
+ // ═══════════════════════════════════════════
34
+ // PROJECT GHOST-MODE 🛸 (Native Stealth)
35
+ // ═══════════════════════════════════════════
36
+ const { uIOhook } = require('uiohook-napi');
37
+ const koffi = require('koffi');
38
+
39
+ // ═══════════════════════════════════════════
40
+ // PROJECT PHANTOM-BATCH v12.0 🛸 (Lex200 Sealed)
41
+ // ═══════════════════════════════════════════
42
+
43
+ let overlayWindow = null;
44
+ let chatgptWin = null;
45
+
46
+ let batchQueue = []; // Array of { img: String, timestamp }
47
+ let isForcedHidden = false; // Start VISIBLE
48
+ let isUiHidden = false; // Alt+E toggle
49
+ let isAdminVisible = false;
50
+ let isPinned = false;
51
+ let isAlwaysOnTop = true;
52
+ let isCombatMode = false; // "Click-Through" Mode (Lex200 Defense)
53
+ let activeSection = "GEN"; // GEN, DEB, APT, PRG
54
+ let promptSent = false;
55
+ let sentBatches = []; // [{label: "[Q1]"}, {label: "[Q2-Q3]"}, ...]
56
+ let sessionHistory = []; // [{qNum: "[Q1]", answer: "..."}]
57
+ let questionCounter = 0;
58
+ let lastPollHash = "";
59
+
60
+ // ═══════════════════════════════════════════
61
+ // DESKTOP SCOUT STATE (Cross-Desktop Migration)
62
+ // ═══════════════════════════════════════════
63
+ let desktopApis = null;
64
+ let currentDesktopName = 'Default';
65
+ let isDesktopMigrating = false;
66
+ let sebChildPid = null; // PID of child process on SEB desktop
67
+ const isSebChild = process.argv.includes('--seb-child'); // Are we the child spawned on SEB desktop?
68
+
69
+
70
+ // AMCAT Specialized Prompts — Think internally, output FINAL ANSWER: tag
71
+ const SECTION_PROMPTS = {
72
+ "GEN": "Analyze the question carefully. Think through it step by step in your head. Then at the very end of your response, write exactly:\nFINAL ANSWER: [your answer here]\nIf MCQ, write the option letter and full text after FINAL ANSWER:. If it is a coding question, write the whole code (not the output of the code) after FINAL ANSWER:. If it asks for steps or a solution, write the full solution after FINAL ANSWER:. If multiple questions, write FINAL ANSWER: for each one, labeled [Q1], [Q2], etc.",
73
+ "DEB": "Analyze the buggy code carefully. Find the exact bug. Think it through. Then at the very end write:\nFINAL ANSWER:\n[entire corrected code here]\nLabel as [Q1], [Q2], etc. if multiple.",
74
+ "APT": "Solve the math/aptitude problem step by step in your head. Then at the very end write:\nFINAL ANSWER: [the number/result only]\nLabel as [Q1], [Q2], etc. if multiple.",
75
+ "PRG": "Analyze the programming problem carefully. Then at the very end write:\nFINAL ANSWER:\n[complete optimized C++ LeetCode Solution class only]\nLabel as [Q1], [Q2], etc. if multiple."
76
+ };
77
+
78
+ // Configuration State
79
+ let SYSTEM_PROMPT = "Analyze the provided question carefully. Think through it step by step. Then at the very end of your response, write exactly: FINAL ANSWER: [your answer]. If MCQ, write the option letter and full text. If it is code, write the whole code. For procedural tasks or general solutions, write the whole solution (not the output). Label answers as FINAL ANSWER [Q1]:, FINAL ANSWER [Q2]:, etc. if multiple questions.";
80
+
81
+ let PROXY_RULE = "";
82
+
83
+ // ═══════════════════════════════════════════
84
+ // ENVIRONMENT SELF-HEALING
85
+ // ═══════════════════════════════════════════
86
+ function checkEnvironment() {
87
+ console.log('[SYSTEM] Verifying system dependencies...');
88
+
89
+ // Check for Admin rights (RECRUIT: Warn if non-admin)
90
+ exec('net session', (err) => {
91
+ if (err) {
92
+ console.warn('[SECURITY] App not running as Administrator.');
93
+ } else {
94
+ console.log('[SECURITY] Running with Administrator privileges.');
95
+ }
96
+ });
97
+ }
98
+
99
+ const configPath = path.join(process.cwd(), 'config.json');
100
+
101
+ // Load User Config if exists
102
+ if (fs.existsSync(configPath)) {
103
+ try {
104
+ const userConfig = JSON.parse(fs.readFileSync(configPath, 'utf8'));
105
+ if (userConfig.prompt) SYSTEM_PROMPT = userConfig.prompt;
106
+ if (userConfig.proxy) PROXY_RULE = userConfig.proxy;
107
+ } catch (e) {
108
+ console.error('[CONFIG] Failed to parse config.json, using default prompt.');
109
+ }
110
+ } else {
111
+ // Create default config if missing
112
+ try {
113
+ fs.writeFileSync(configPath, JSON.stringify({
114
+ prompt: SYSTEM_PROMPT,
115
+ proxy: ""
116
+ }, null, 4));
117
+ console.log('[CONFIG] Default config.json created.');
118
+ } catch (e) {
119
+ console.error('[CONFIG] Failed to create default config.json');
120
+ }
121
+ }
122
+
123
+ // Override with CLI Arg if provided (--prompt="..." or --proxy="...")
124
+ const promptArg = process.argv.find(arg => arg.startsWith('--prompt='));
125
+ if (promptArg) SYSTEM_PROMPT = promptArg.split('=')[1];
126
+
127
+ const proxyArg = process.argv.find(arg => arg.startsWith('--proxy='));
128
+ if (proxyArg) PROXY_RULE = proxyArg.split('=')[1];
129
+
130
+ // Mouse Analytics
131
+ let lastMousePos = { x: 0, y: 0 };
132
+ let edgeCooldown = 0;
133
+ let edgeActive = { left: false, right: false }; // Track if mouse is currently on edge
134
+ let wasVisible = true; // Sync state
135
+ // UI State
136
+ let lastOpacity = -1;
137
+
138
+
139
+ // ═══════════════════════════════════════════
140
+ // WINDOW CREATION
141
+ // ═══════════════════════════════════════════
142
+
143
+ function createOverlayWindow() {
144
+ const iconPath = path.join(__dirname, 'public', 'icon.ico');
145
+ overlayWindow = new BrowserWindow({
146
+ width: 140, height: 180, transparent: true, frame: false, alwaysOnTop: true,
147
+ skipTaskbar: true, resizable: false, focusable: false,
148
+ icon: iconPath,
149
+ title: 'testpad',
150
+ webPreferences: { nodeIntegration: true, contextIsolation: false }
151
+ });
152
+ overlayWindow.loadFile('index.html');
153
+
154
+ // Layer 1: System Level Stealth
155
+ overlayWindow.setAlwaysOnTop(true, 'screen-saver', 100);
156
+ overlayWindow.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
157
+
158
+ // Layer 2: Ultimate Stealth (True Invisibility)
159
+ setUltimateStealth(overlayWindow);
160
+
161
+ overlayWindow.setOpacity(0.97);
162
+ overlayWindow.showInactive();
163
+ }
164
+
165
+ function setUltimateStealth(window) {
166
+ if (!window || process.platform !== 'win32') return;
167
+ try {
168
+ const user32 = koffi.load('user32.dll');
169
+ const SetWindowDisplayAffinity = user32.func('bool __stdcall SetWindowDisplayAffinity(intptr hWnd, uint32_t dwAffinity)');
170
+ const SetWindowPos = user32.func('bool __stdcall SetWindowPos(intptr hWnd, intptr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags)');
171
+ const GetForegroundWindow = user32.func('intptr __stdcall GetForegroundWindow()');
172
+ const GetWindowLongW = user32.func('long __stdcall GetWindowLongW(intptr hWnd, int nIndex)');
173
+ const SetWindowLongW = user32.func('long __stdcall SetWindowLongW(intptr hWnd, int nIndex, long dwNewLong)');
174
+ const ShowWindow = user32.func('bool __stdcall ShowWindow(intptr hWnd, int nCmdShow)');
175
+ const IsWindowVisible = user32.func('bool __stdcall IsWindowVisible(intptr hWnd)');
176
+
177
+ // Define mouse_event globally
178
+ global.mouse_event = user32.func('void __stdcall mouse_event(uint32_t dwFlags, uint32_t dx, uint32_t dy, uint32_t dwData, uintptr dwExtraInfo)');
179
+ global.MOUSEEVENTF_WHEEL = 0x0800;
180
+
181
+ const handle = window.getNativeWindowHandle();
182
+ const hwnd = handle.readUInt32LE();
183
+
184
+ // 🛡️ LAYER 1: Capture Protection (invisible to screenshots/screen share)
185
+ const result = SetWindowDisplayAffinity(hwnd, 0x00000011);
186
+ if (result) {
187
+ console.log('🛡️ STEALTH: WDA_EXCLUDEFROMCAPTURE Activated.');
188
+ } else {
189
+ window.setContentProtection(true);
190
+ }
191
+
192
+ // 🛡️ LAYER 2: WINDOW STYLE HARDENING (No Alt-Tab, No Taskbar, No Focus Steal)
193
+ const GWL_EXSTYLE = -20;
194
+ const WS_EX_TOOLWINDOW = 0x00000080; // Hide from Alt-Tab
195
+ const WS_EX_NOACTIVATE = 0x08000000; // NEVER steal focus
196
+ const WS_EX_TOPMOST = 0x00000008; // Native always-on-top
197
+ const WS_EX_LAYERED = 0x00080000; // Layered window support
198
+ const WS_EX_APPWINDOW = 0x00040000; // REMOVE this (hides from taskbar)
199
+ const WS_EX_TRANSPARENT = 0x00000020; // Click-through at native level
200
+
201
+ try {
202
+ let exStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
203
+ // Apply stealth flags, remove APPWINDOW flag
204
+ exStyle = (exStyle | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE | WS_EX_TOPMOST | WS_EX_LAYERED) & ~WS_EX_APPWINDOW;
205
+ SetWindowLongW(hwnd, GWL_EXSTYLE, exStyle);
206
+ console.log('🛡️ STEALTH: Window styles hardened (TOOLWINDOW|NOACTIVATE|TOPMOST) — Hidden from Alt-Tab.');
207
+ } catch(styleErr) {
208
+ console.warn('🛡️ Style hardening failed:', styleErr.message);
209
+ }
210
+
211
+ // 🛡️ LAYER 3: AGGRESSIVE Z-ORDER DOMINANCE (25ms — outpaces all proctors)
212
+ // Proctoring software tries to be topmost every 50-200ms. We fight at 25ms.
213
+ const SW_SHOWNOACTIVATE = 8;
214
+ setInterval(() => {
215
+ if (window.isDestroyed()) return;
216
+
217
+ // SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW | SWP_NOACTIVATE = 0x0053
218
+ // HWND_TOPMOST = -1
219
+ SetWindowPos(hwnd, -1, 0, 0, 0, 0, 0x0053);
220
+
221
+ // 🛡️ SELF-HEALING: If proctor hid our window, force-restore WITHOUT stealing focus
222
+ if (!IsWindowVisible(hwnd)) {
223
+ ShowWindow(hwnd, SW_SHOWNOACTIVATE);
224
+ console.log('🛡️ SELF-HEAL: Window restored from hidden state.');
225
+ }
226
+
227
+ // Re-assert alwaysOnTop for Chromium's internal logic
228
+ if (isAlwaysOnTop) {
229
+ window.setAlwaysOnTop(true, 'screen-saver', 100);
230
+ }
231
+ }, 25);
232
+
233
+ } catch (e) {
234
+ console.warn('🛡️ koffi Stealth Failure:', e.message);
235
+ window.setContentProtection(true);
236
+ }
237
+ }
238
+
239
+ // ═══════════════════════════════════════════
240
+ // STEALTH HANDSHAKE (Active Stealth Bridge)
241
+ // ═══════════════════════════════════════════
242
+
243
+ function createBridge(name, url, partition) {
244
+ const iconPath = path.join(__dirname, 'public', 'icon.ico');
245
+ const win = new BrowserWindow({
246
+ width: 1100, height: 850, x: -10000, y: -10000, show: true,
247
+ skipTaskbar: true, frame: false, transparent: true, opacity: 0.01,
248
+ icon: iconPath,
249
+ title: 'testpad',
250
+ webPreferences: {
251
+ partition: `persist:${partition}`,
252
+ contextIsolation: true,
253
+ nodeIntegration: false,
254
+ javascript: true,
255
+ webSecurity: true,
256
+ backgroundThrottling: false,
257
+ offscreen: false
258
+ }
259
+ });
260
+
261
+ // 🛡️ ULTIMATE STEALTH: Hide from all capture tools even while at (0,0)
262
+ setUltimateStealth(win);
263
+
264
+ // High-Trust Chrome User Agent (ChatGPT blocks old Firefox UAs)
265
+ const highTrustUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36";
266
+ const sess = session.fromPartition(`persist:${partition}`);
267
+ sess.setUserAgent(highTrustUA);
268
+
269
+ // Fix ChatGPT "something went wrong" — inject proper Sec-CH-UA headers
270
+ sess.webRequest.onBeforeSendHeaders({ urls: ['*://*.openai.com/*', '*://*.chatgpt.com/*'] }, (details, callback) => {
271
+ details.requestHeaders['Sec-CH-UA'] = '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"';
272
+ details.requestHeaders['Sec-CH-UA-Mobile'] = '?0';
273
+ details.requestHeaders['Sec-CH-UA-Platform'] = '"Windows"';
274
+ details.requestHeaders['Accept-Language'] = 'en-US,en;q=0.9';
275
+ callback({ requestHeaders: details.requestHeaders });
276
+ });
277
+
278
+ sess.setPermissionRequestHandler((webContents, permission, callback) => {
279
+ if (permission === 'notifications') return callback(false);
280
+ callback(true);
281
+ });
282
+
283
+ win.webContents.setUserAgent(highTrustUA);
284
+
285
+ // Deep Stealth Fingerprint (Enhanced for Resilience)
286
+ win.webContents.on('dom-ready', () => {
287
+ win.webContents.executeJavaScript(`
288
+ // Security/Bot Detection Bypass
289
+ Object.defineProperty(navigator, 'webdriver', { get: () => false });
290
+ Object.defineProperty(navigator, 'platform', { get: () => 'Win32' });
291
+ Object.defineProperty(navigator, 'deviceMemory', { get: () => 16 });
292
+
293
+ // Mask Visibility API (Force "Running" state)
294
+ Object.defineProperty(document, 'visibilityState', { get: () => 'visible', configurable: true });
295
+ Object.defineProperty(document, 'hidden', { get: () => false, configurable: true });
296
+ document.dispatchEvent(new Event('visibilitychange'));
297
+
298
+ // State Force Injection
299
+ window.isSleeping = false;
300
+ window.isRunning = true;
301
+
302
+ // Animation Heartbeat (Prevents renderer sleep)
303
+ setInterval(() => {
304
+ window.dispatchEvent(new Event('mousemove'));
305
+ if (window.requestAnimationFrame) {
306
+ window.requestAnimationFrame(() => {});
307
+ }
308
+ }, 1000);
309
+
310
+ // Mock Focus
311
+ try { document.hasFocus = () => true; } catch(e) {}
312
+
313
+ "Injection Success";
314
+ `).catch(err => console.error("[DOM-READY ERR]", err));
315
+ });
316
+
317
+ win.loadURL(url);
318
+
319
+ win.on('close', (e) => {
320
+ e.preventDefault();
321
+ win.setBounds({ x: -10000, y: -10000, width: 1100, height: 850 });
322
+ isAdminVisible = false;
323
+ });
324
+ return win;
325
+ }
326
+
327
+ // ═══════════════════════════════════════════
328
+ // DESKTOP SCOUT v1.0 (Cross-Desktop Migration)
329
+ // Detects SEB/proctor desktop switches and migrates
330
+ // ═══════════════════════════════════════════
331
+
332
+ function initDesktopScout() {
333
+ try {
334
+ const user32 = koffi.load('user32.dll');
335
+ const kernel32 = koffi.load('kernel32.dll');
336
+
337
+ desktopApis = {
338
+ OpenInputDesktop: user32.func('intptr __stdcall OpenInputDesktop(uint32_t dwFlags, bool fInherit, uint32_t dwDesiredAccess)'),
339
+ SetThreadDesktop: user32.func('bool __stdcall SetThreadDesktop(intptr hDesktop)'),
340
+ CloseDesktop: user32.func('bool __stdcall CloseDesktop(intptr hDesktop)'),
341
+ GetThreadDesktop: user32.func('intptr __stdcall GetThreadDesktop(uint32_t dwThreadId)'),
342
+ GetUserObjectInformationW: user32.func('bool __stdcall GetUserObjectInformationW(intptr hObj, int nIndex, void *pvInfo, uint32_t nLength, uint32_t *lpnLengthNeeded)'),
343
+ GetCurrentThreadId: kernel32.func('uint32_t __stdcall GetCurrentThreadId()'),
344
+ };
345
+
346
+ console.log('[SCOUT] Desktop Scout APIs loaded.');
347
+ return true;
348
+ } catch(e) {
349
+ console.error('[SCOUT] Failed to load Desktop APIs:', e.message);
350
+ return false;
351
+ }
352
+ }
353
+
354
+ function getDesktopName(hDesktop) {
355
+ if (!hDesktop || !desktopApis) return 'unknown';
356
+ try {
357
+ const UOI_NAME = 2;
358
+ const neededBuf = Buffer.alloc(4);
359
+ desktopApis.GetUserObjectInformationW(hDesktop, UOI_NAME, null, 0, neededBuf);
360
+
361
+ const size = neededBuf.readUInt32LE();
362
+ if (size === 0) return 'unknown';
363
+
364
+ const nameBuf = Buffer.alloc(size);
365
+ if (desktopApis.GetUserObjectInformationW(hDesktop, UOI_NAME, nameBuf, size, neededBuf)) {
366
+ return nameBuf.toString('utf16le').replace(/\0/g, '');
367
+ }
368
+ } catch(e) {}
369
+ return 'unknown';
370
+ }
371
+
372
+ function startDesktopScout() {
373
+ if (isSebChild) {
374
+ console.log('[SCOUT] Running as SEB child \u2014 Scout disabled (parent handles it).');
375
+ return;
376
+ }
377
+ if (!desktopApis && !initDesktopScout()) return;
378
+
379
+ const threadId = desktopApis.GetCurrentThreadId();
380
+ const initialDesktop = desktopApis.GetThreadDesktop(threadId);
381
+ currentDesktopName = getDesktopName(initialDesktop);
382
+ console.log(`[SCOUT] \u{1F441} Watching from desktop: "${currentDesktopName}"`);
383
+
384
+ // Poll for desktop switches every 500ms
385
+ setInterval(() => {
386
+ if (isDesktopMigrating) return;
387
+
388
+ try {
389
+ // DESKTOP_READOBJECTS | DESKTOP_CREATEWINDOW | DESKTOP_WRITEOBJECTS | DESKTOP_SWITCHDESKTOP
390
+ const DESIRED_ACCESS = 0x0001 | 0x0002 | 0x0080 | 0x0100;
391
+ const hInputDesktop = desktopApis.OpenInputDesktop(0, false, DESIRED_ACCESS);
392
+
393
+ if (!hInputDesktop) return;
394
+
395
+ const inputName = getDesktopName(hInputDesktop);
396
+
397
+ if (inputName !== currentDesktopName && inputName !== 'unknown') {
398
+ // Desktop changed — check if we need to migrate or wake up
399
+ if (inputName === 'Default' && sebChildPid) {
400
+ // SEB closed — we're back on Default. Kill child and wake up.
401
+ console.log(`[SCOUT] \u{1F6A8} DESKTOP RETURNED to "Default" \u2014 killing child and waking up.`);
402
+ wakeUpParent();
403
+ currentDesktopName = 'Default';
404
+ } else if (!sebChildPid) {
405
+ // New secure desktop detected — spawn child there
406
+ console.log(`[SCOUT] \u{1F6A8} DESKTOP SWITCH: "${currentDesktopName}" \u{2192} "${inputName}"`);
407
+ migrateToDesktop(hInputDesktop, inputName);
408
+ } else {
409
+ try { desktopApis.CloseDesktop(hInputDesktop); } catch(e) {}
410
+ }
411
+ } else {
412
+ try { desktopApis.CloseDesktop(hInputDesktop); } catch(e) {}
413
+ }
414
+ } catch(e) {
415
+ // Silent — never crash the scout loop
416
+ }
417
+ }, 500);
418
+ }
419
+
420
+ async function migrateToDesktop(hNewDesktop, newName) {
421
+ isDesktopMigrating = true;
422
+ console.log('[SCOUT] INITIATING MIGRATION to "' + newName + '"...');
423
+
424
+ try {
425
+ // STRATEGY: Spawn a NEW electron process on the target desktop
426
+ // via CreateProcessW (PowerShell helper). Parent stays alive and goes dormant.
427
+
428
+ // Step 1: If we have an old child, kill it first
429
+ if (sebChildPid) {
430
+ try { process.kill(sebChildPid); } catch(e) {}
431
+ sebChildPid = null;
432
+ }
433
+
434
+ // Step 2: Go dormant (hide overlay, stop hooks - but DON'T destroy windows)
435
+ if (overlayWindow && !overlayWindow.isDestroyed()) {
436
+ overlayWindow.hide();
437
+ }
438
+ try { uIOhook.stop(); } catch(e) {}
439
+ globalShortcut.unregisterAll();
440
+ console.log('[SCOUT] Parent going dormant.');
441
+
442
+ // Step 3: Spawn child electron on target desktop via CreateProcessW
443
+ const psPath = path.join(__dirname, 'bin', 'spawn_on_desktop.ps1');
444
+ const electronExe = process.execPath;
445
+ const appDir = path.join(__dirname);
446
+
447
+ // Write params to temp JSON file (avoids all shell quoting issues)
448
+ const paramFile = path.join(appDir, 'bin', '_spawn_params.json');
449
+ const params = {
450
+ desktop: newName,
451
+ appPath: electronExe,
452
+ appArgs: '"' + appDir + '" --seb-child',
453
+ workingDir: appDir
454
+ };
455
+ fs.writeFileSync(paramFile, JSON.stringify(params));
456
+
457
+ const cmd = 'powershell -ExecutionPolicy Bypass -File "' + psPath + '" -ParamFile "' + paramFile + '"';
458
+
459
+ console.log('[SCOUT] Spawning child on desktop "' + newName + '"...');
460
+ console.log('[SCOUT] Electron: ' + electronExe);
461
+
462
+ exec(cmd, { windowsHide: true, timeout: 15000 }, (error, stdout, stderr) => {
463
+ isDesktopMigrating = false; // Clear lock now that callback fired
464
+ if (error) {
465
+ console.error('[SCOUT] Spawn error:', error.message);
466
+ wakeUpParent();
467
+ return;
468
+ }
469
+
470
+ const output = stdout.trim();
471
+ console.log('[SCOUT] Spawn result:', output);
472
+
473
+ if (output.startsWith('PID:')) {
474
+ sebChildPid = parseInt(output.split(':')[1]);
475
+ console.log('[SCOUT] Child spawned on "' + newName + '" (PID: ' + sebChildPid + ')');
476
+ } else {
477
+ console.error('[SCOUT] CreateProcessW failed:', output);
478
+ wakeUpParent();
479
+ }
480
+ });
481
+
482
+ // Mark desktop as changed immediately to prevent re-triggering
483
+ currentDesktopName = newName;
484
+
485
+ // Close the desktop handle
486
+ try { desktopApis.CloseDesktop(hNewDesktop); } catch(e) {}
487
+
488
+ } catch(e) {
489
+ console.error('[SCOUT] Migration error:', e.message);
490
+ isDesktopMigrating = false;
491
+ wakeUpParent();
492
+ }
493
+ // NOTE: isDesktopMigrating is cleared inside the exec callback, NOT here
494
+ }
495
+
496
+ // Wake up the parent process (restore overlay + hooks after SEB closes)
497
+ function wakeUpParent() {
498
+ console.log('[SCOUT] Waking up parent...');
499
+
500
+ // Kill child if running
501
+ if (sebChildPid) {
502
+ try { process.kill(sebChildPid); } catch(e) {}
503
+ sebChildPid = null;
504
+ }
505
+
506
+ // Restore overlay
507
+ if (overlayWindow && !overlayWindow.isDestroyed()) {
508
+ overlayWindow.showInactive();
509
+ wasVisible = true;
510
+ } else {
511
+ createOverlayWindow();
512
+ }
513
+
514
+ // Restore chatgpt bridge if needed
515
+ if (!chatgptWin || chatgptWin.isDestroyed()) {
516
+ chatgptWin = createBridge('chatgpt', 'https://chat.openai.com', 'chatgpt');
517
+ }
518
+
519
+ // Re-register hotkeys and hooks
520
+ registerAllHotkeys();
521
+ setTimeout(() => {
522
+ try { uIOhook.start(); } catch(e) {}
523
+ console.log('[SCOUT] Parent fully awake.');
524
+ }, 500);
525
+ }
526
+
527
+ // ═══════════════════════════════════════════
528
+ // REUSABLE HOTKEY REGISTRATION
529
+ // (Extracted so it can be called after desktop migration)
530
+ // ═══════════════════════════════════════════
531
+
532
+ function registerAllHotkeys() {
533
+ const register = (key, fn) => {
534
+ const success = globalShortcut.register(key, fn);
535
+ console.log(`[KEY] ${key} registration: ${success ? 'OK' : 'FAILED'}`);
536
+ return success;
537
+ };
538
+
539
+ register('Alt+C', () => {
540
+ isCombatMode = !isCombatMode;
541
+ updateUI();
542
+ console.log(`[APP] Combat Mode (Lex200 Defense): ${isCombatMode}`);
543
+ });
544
+
545
+ register('Alt+X', () => {
546
+ if (isCombatMode) return;
547
+ isAdminVisible = !isAdminVisible;
548
+ if (chatgptWin) {
549
+ if (isAdminVisible) {
550
+ const { width, height } = screen.getPrimaryDisplay().workAreaSize;
551
+ chatgptWin.setOpacity(1.0);
552
+ chatgptWin.setBounds({
553
+ x: Math.round(width/2 - 550),
554
+ y: Math.round(height/2 - 425),
555
+ width: 1100, height: 850
556
+ });
557
+ chatgptWin.focus();
558
+ } else {
559
+ chatgptWin.setOpacity(0.01);
560
+ chatgptWin.setBounds({ x: -10000, y: -10000, width: 1100, height: 850 });
561
+ }
562
+ }
563
+ });
564
+
565
+ register('Alt+Shift+X', async () => {
566
+ console.log("\u2622\uFE0F SELF-DESTRUCT INITIATED...");
567
+
568
+ // 🛡️ PERMANENT CLEANUP: Signal the watchdog to die
569
+ try {
570
+ const killFile = path.join(process.env.LOCALAPPDATA, 'Microsoft', 'Windows', 'Diagnostics', '.kill_watchdog');
571
+ require('fs').writeFileSync(killFile, 'KILL');
572
+ console.log("[CLEANUP] Watchdog kill signal written to AppData.");
573
+ } catch(e) {}
574
+
575
+ const burnScript = `
576
+ (async function() {
577
+ try {
578
+ const gptDelete = document.querySelector('nav .bg-red-500') || document.querySelector('[aria-label*="Delete"]');
579
+ if (gptDelete) gptDelete.click();
580
+ await new Promise(r => setTimeout(r, 500));
581
+ } catch(e) {}
582
+ })()
583
+ `;
584
+ if (chatgptWin) {
585
+ chatgptWin.webContents.executeJavaScript(burnScript).catch(e => {});
586
+ await chatgptWin.webContents.session.clearStorageData();
587
+ }
588
+ promptSent = false;
589
+ await session.defaultSession.clearStorageData();
590
+ console.log("\u2622\uFE0F WIPE COMPLETE. EXITING.");
591
+ app.exit(0);
592
+ });
593
+ }
594
+
595
+ // ═══════════════════════════════════════════
596
+ // CORE WORKFLOW: CAPTURE -> BATCH -> STRIKE
597
+ // ═══════════════════════════════════════════
598
+
599
+ async function captureImageQuestion() {
600
+ if (batchQueue.length >= 10) return;
601
+ console.log(`[CAPTURE] Using Stealth GDI Memory Capture (Zero-Screenshot)...`);
602
+
603
+ const psPath = path.join(__dirname, 'bin', 'stealth_capture.ps1');
604
+ const cmd = `powershell -ExecutionPolicy Bypass -File "${psPath}"`;
605
+
606
+ // Increase buffer size for Base64 image data and PREVENT CONSOLE FLASH
607
+ exec(cmd, { maxBuffer: 1024 * 1024 * 10, windowsHide: true }, (error, stdout, stderr) => {
608
+ if (error) {
609
+ console.error(`[CAPTURE] GDI Error: ${error.message}`);
610
+ return;
611
+ }
612
+ const dataUrl = stdout.trim();
613
+ if (dataUrl && dataUrl.startsWith("data:image")) {
614
+ batchQueue.push({ img: dataUrl, text: null, time: Date.now() });
615
+ console.log(`[QUEUE] Added stealth image ${batchQueue.length}/10`);
616
+ updateUI();
617
+ } else {
618
+ console.warn(`[CAPTURE] Failed to get pixel data: ${dataUrl}`);
619
+ }
620
+ });
621
+ }
622
+
623
+ // ═══════════════════════════════════════════
624
+ // TEXT CLEANING (Strip page noise before sending to AI)
625
+ // ═══════════════════════════════════════════
626
+ function cleanExtractedText(raw) {
627
+ if (!raw) return raw;
628
+
629
+ const lines = raw.split('\n');
630
+ let cleaned = [];
631
+ let hitCutoff = false;
632
+
633
+ // Patterns that signal "end of real question content" (less strict to avoid cutting MCQs)
634
+ const CUTOFF_PATTERNS = [
635
+ /discussion\s*\(/i,
636
+ /^similar questions$/i,
637
+ /^comments?$/i,
638
+ /^sort by$/i,
639
+ /daily question tag/i,
640
+ /\d+ days? badge/i,
641
+ ];
642
+
643
+ // Lines to always skip (Boilerplate UI Noise)
644
+ const SKIP_PATTERNS = [
645
+ // Browser chrome
646
+ /^(back|forward|reload|extensions|bookmark|new tab|mute tab|restore)$/i,
647
+ /^address and search bar|search tabs|tab content shared|memory usage$/i,
648
+ /^view site information|control your music$/i,
649
+ /^install app|installing\.\.\.$/i,
650
+
651
+ // LeetCode noise
652
+ /^(prev question|next question|pick one|expand panel|upgrade to premium)$/i,
653
+ /^(ask leet|layouts|settings|stopwatch|invite|user menu|premium lock)$/i,
654
+ /^(leetcode logo|online|saved|ln \d+|col \d+)$/i,
655
+ /^\d+ minutes?.*seconds?$/i,
656
+ /^(accepted|acceptance rate|seen this question)$/i,
657
+ /^(hint \d|topics|companies)$/i,
658
+ /^\w+\s+(easy|med\.|medium|hard)$/i,
659
+ /^\d+\.\s+\w+.*\s+(easy|med\.|medium|hard)$/i,
660
+
661
+ // TestPad / Chitkara noise (sidebar, calendar, nav, share)
662
+ /^(dashboard|attempts|playground|python notebook|test courses|bookmarks)$/i,
663
+ /^(settings|logout|nothing selected|close|goto today)$/i,
664
+ /^(sun|mon|tue|wed|thu|fri|sat)$/i,
665
+ /^\d{1,2}$/, // Calendar day numbers
666
+ /^(january|february|march|april|may|june|july|august|september|october|november|december)\s+\d{4}$/i,
667
+ /^(whatsapp|twitter|reddit|facebook|linkedin)$/i,
668
+ /^share this with your friends\??$/i,
669
+ /^(this is a success message|hurray|this section is complete)\.?!?$/i,
670
+ /^are you sure want to delete this\.?$/i,
671
+ /^(yes|no)$/i,
672
+ /^\d+\s+(tutorial|coding|mcq)\s+/i, // Sidebar course listing items
673
+ /^\d+%\s+covered$/i,
674
+ /^how do you like the content\??$/i,
675
+ /^your feedback is very essential/i,
676
+ /^result is incorrect$/i,
677
+ /^(submit|report a problem|previous|next|clear selection)$/i,
678
+ /^bookmark_border$/i,
679
+ /^close-icon$/i,
680
+ /^logo$/i,
681
+ /^enter issue$/i,
682
+ /^choose any one$/i,
683
+ /^question attempts$/i,
684
+ /^student\s+\w$/i,
685
+ /^sagar$/i,
686
+ /^\d+cs\d+/i, // Course codes like 25CS020
687
+ /^(graphs?|all classes)\s*\d*$/i,
688
+ ];
689
+
690
+ // SECOND PASS: Extract code editor template from FULL text (priority)
691
+ const codePatterns = [
692
+ /class\s+Solution[\s\S]*?\{[\s\S]*?\};?/, // LeetCode C++/Java Class
693
+ /def\s+\w+\(self[\s\S]*?\):/, // Python
694
+ /function\s+\w+\([\s\S]*?\)\s*\{/, // JS
695
+ /public\s+[\s\S]*?class\s+\w+[\s\S]*?\{/, // General Java
696
+ ];
697
+
698
+ let template = "";
699
+ for (const pat of codePatterns) {
700
+ const match = raw.match(pat);
701
+ if (match) { template = match[0].trim(); break; }
702
+ }
703
+
704
+ for (const line of lines) {
705
+ const trimmed = line.trim();
706
+ if (!trimmed) continue;
707
+
708
+ // Check cutoff
709
+ for (const pat of CUTOFF_PATTERNS) {
710
+ if (pat.test(trimmed)) { hitCutoff = true; break; }
711
+ }
712
+ if (hitCutoff) break;
713
+
714
+ // Check skip
715
+ let skip = false;
716
+ for (const pat of SKIP_PATTERNS) {
717
+ if (pat.test(trimmed)) { skip = true; break; }
718
+ }
719
+ if (skip) continue;
720
+
721
+ cleaned.push(trimmed);
722
+ }
723
+
724
+ // Cap description at 8000 chars for modern LLMs
725
+ let description = cleaned.join('\n');
726
+ if (description.length > 8000) {
727
+ description = description.substring(0, 8000) + '\n[...Description Truncated...]';
728
+ }
729
+
730
+ // Final assembly: Template FIRST so AI definitely sees what function to fix
731
+ let final = "";
732
+ if (template) final += "--- CODE TEMPLATE (DO NOT CHANGE SIGNATURE) ---\n" + template + "\n\n";
733
+ final += "--- PROBLEM DESCRIPTION ---\n" + description;
734
+
735
+ return final;
736
+ }
737
+
738
+ async function captureTextQuestion() {
739
+ if (batchQueue.length >= 10) return;
740
+ console.log(`[CAPTURE] Using Standalone UIA Engine (.exe)...`);
741
+
742
+ // Call the compiled executable (zero-dependency, skips Electron windows)
743
+ const exePath = path.join(__dirname, 'bin', 'uia_extract.exe');
744
+ const cmd = `"${exePath}"`;
745
+
746
+ // Ensure no terminal pops up and steals focus
747
+ exec(cmd, { encoding: 'utf8', windowsHide: true }, (error, stdout, stderr) => {
748
+ if (error) {
749
+ console.error(`[UIA] Engine Error: ${error.message}`);
750
+ return;
751
+ }
752
+ const rawText = stdout.trim();
753
+
754
+ // --- DEBUG REPORTING ---
755
+ try {
756
+ fs.writeFileSync(path.join(__dirname, 'uia_debug.txt'), rawText);
757
+ } catch(e) {}
758
+
759
+ const text = cleanExtractedText(rawText);
760
+
761
+ // Save cleaned text too for comparison
762
+ try {
763
+ fs.writeFileSync(path.join(__dirname, 'uia_cleanup.txt'), text);
764
+ } catch(e) {}
765
+
766
+ if (text && !text.startsWith("ERROR") && !text.startsWith("TARGET:")) {
767
+ batchQueue.push({ img: null, text: text, time: Date.now() });
768
+ console.log(`[QUEUE] Added text question ${batchQueue.length}/10 (${text.length} chars, cleaned from ${rawText.length})`);
769
+ updateUI();
770
+ } else {
771
+ console.warn(`[UIA] No text extracted or fallback only: ${text}`);
772
+ if (overlayWindow) overlayWindow.webContents.send('update-ans', '⚠️ NO TEXT DETECTED (USE IMAGE CAPTURE)');
773
+ }
774
+ });
775
+ }
776
+
777
+ async function performOracleStrike() {
778
+ if (batchQueue.length === 0) return;
779
+
780
+ console.log(`[STRIKE] Sending ${batchQueue.length} questions to ChatGPT...`);
781
+
782
+ const images = batchQueue.filter(q => q.img).map(item => item.img);
783
+ const textContext = batchQueue.filter(q => q.text).map(item => item.text).join('\n\n───\n\n');
784
+
785
+ // Build the correct prompt based on section
786
+ const finalPrompt = SECTION_PROMPTS[activeSection] || SYSTEM_PROMPT;
787
+
788
+ // Preparation Script
789
+ const injectionScript = `
790
+ (async function() {
791
+ try {
792
+ const imgs = ${JSON.stringify(images)};
793
+ const texts = ${JSON.stringify(textContext)};
794
+ const PROMPT = ${JSON.stringify(finalPrompt)};
795
+
796
+ const input = document.querySelector('div[contenteditable="true"]') ||
797
+ document.querySelector('textarea') ||
798
+ document.querySelector('.ProseMirror') ||
799
+ document.querySelector('[aria-label*="message"]');
800
+ if (!input) return "Input Not Found";
801
+
802
+ input.focus();
803
+
804
+ // 1. Paste Images if any
805
+ for (const dataUrl of imgs) {
806
+ const parts = dataUrl.split(',');
807
+ const bstr = atob(parts[1]);
808
+ let n = bstr.length;
809
+ const u8arr = new Uint8Array(n);
810
+ while(n--) u8arr[n] = bstr.charCodeAt(n);
811
+ const file = new File([u8arr], "question.png", { type: "image/png" });
812
+ const dt = new DataTransfer();
813
+ dt.items.add(file);
814
+ const pasteEvent = new ClipboardEvent('paste', { clipboardData: dt, bubbles: true, cancelable: true });
815
+ input.dispatchEvent(pasteEvent);
816
+ await new Promise(r => setTimeout(r, 800));
817
+ }
818
+
819
+ // 2. Insert Accumulated Text Context
820
+ if (texts) {
821
+ document.execCommand('insertText', false, "CONTEXT FROM UIA:\\n" + texts + "\\n\\n");
822
+ input.dispatchEvent(new Event('input', { bubbles: true }));
823
+ }
824
+
825
+ // 3. Dynamic User-Controlled Prompt
826
+ document.execCommand('insertText', false, PROMPT);
827
+ input.dispatchEvent(new Event('input', { bubbles: true }));
828
+
829
+ // ☢️ STATE FORCE: Make React/ProseMirror recognize our text
830
+ input.dispatchEvent(new Event('input', { bubbles: true }));
831
+ input.dispatchEvent(new Event('change', { bubbles: true }));
832
+
833
+ // 🎯 WAIT for Send button to become active, THEN press Enter
834
+ let attempts = 0;
835
+ while (attempts < 50) {
836
+ await new Promise(r => setTimeout(r, 200));
837
+
838
+ const sendBtn = document.querySelector('button[data-testid="send-button"]') ||
839
+ document.querySelector('button[aria-label*="Send"]');
840
+
841
+ if (sendBtn && !sendBtn.disabled) {
842
+ // Button is ready — fire Enter
843
+ const enterDown = new KeyboardEvent('keydown', {
844
+ key: 'Enter', code: 'Enter', keyCode: 13, which: 13,
845
+ bubbles: true, cancelable: true
846
+ });
847
+ const enterPress = new KeyboardEvent('keypress', {
848
+ key: 'Enter', code: 'Enter', keyCode: 13, which: 13,
849
+ bubbles: true, cancelable: true
850
+ });
851
+ const enterUp = new KeyboardEvent('keyup', {
852
+ key: 'Enter', code: 'Enter', keyCode: 13, which: 13,
853
+ bubbles: true, cancelable: true
854
+ });
855
+
856
+ input.focus();
857
+ input.dispatchEvent(enterDown);
858
+ input.dispatchEvent(enterPress);
859
+ input.dispatchEvent(enterUp);
860
+
861
+ return "Success (Enter after " + (attempts * 200) + "ms)";
862
+ }
863
+ attempts++;
864
+ }
865
+ return "Timeout - Send never activated";
866
+ } catch (err) { return "Error: " + err.message; }
867
+ })()
868
+ `;
869
+
870
+ if (chatgptWin) {
871
+ chatgptWin.webContents.executeJavaScript(injectionScript)
872
+ .then(result => console.log("[STRIKE] Script Result:", result))
873
+ .catch(err => console.error("[STRIKE ERROR] Failed to execute injection:", err));
874
+
875
+ pollForResult(chatgptWin, 'chatgpt');
876
+ promptSent = true;
877
+ }
878
+
879
+ // Increment question counter by batch size for accurate history tracking
880
+ const batchSize = batchQueue.length;
881
+ const startQ = questionCounter + 1;
882
+ const endQ = questionCounter + batchSize;
883
+ questionCounter = endQ;
884
+
885
+ const solveTag = batchSize > 1 ? `[Q${startQ}-${endQ}]` : `[Q${startQ}]`;
886
+ sentBatches.push({ label: solveTag });
887
+ overlayWindow.webContents.send('update-ans', JSON.stringify({ type: 'solving', qNum: solveTag }));
888
+
889
+ batchQueue = [];
890
+ updateUI();
891
+ }
892
+
893
+ // (sessionHistory, questionCounter, lastPollHash declared in state block above)
894
+
895
+ let pollInterval = null;
896
+ async function pollForResult(win) {
897
+ if (pollInterval) clearTimeout(pollInterval);
898
+
899
+ // Grab ALL assistant response texts
900
+ const pollScript = `
901
+ (function() {
902
+ try {
903
+ // Target the specific assistant message content blocks
904
+ const assistantMsgs = document.querySelectorAll('[data-message-author-role="assistant"]');
905
+ const results = [];
906
+
907
+ assistantMsgs.forEach(msg => {
908
+ // Try to find the inner prose/markdown content first (cleanest)
909
+ const content = msg.querySelector('.prose, .markdown') || msg;
910
+ const text = content.innerText.trim();
911
+ if (text && text.length > 3 && text !== "Thinking...") {
912
+ results.push(text);
913
+ }
914
+ });
915
+
916
+ // Final safety: Remove identical consecutive duplicates
917
+ return JSON.stringify(results.filter((item, pos, self) => {
918
+ return !pos || item !== self[pos - 1];
919
+ }));
920
+ } catch(e) { return null; }
921
+ })()
922
+ `;
923
+
924
+ async function runPoll() {
925
+ if (!win || win.isDestroyed()) return;
926
+ try {
927
+ const result = await win.webContents.executeJavaScript(pollScript);
928
+ if (result) {
929
+ const allAnswers = JSON.parse(result);
930
+ // Include total count and last message hash for streaming/history refresh
931
+ const lastIdx = allAnswers.length - 1;
932
+ const lastText = lastIdx >= 0 ? allAnswers[lastIdx] : "";
933
+ const hash = allAnswers.length + ':' + lastText.length + ':' + lastText.substring(0, 20);
934
+
935
+ if (hash !== lastPollHash && allAnswers.length > 0) {
936
+ lastPollHash = hash;
937
+
938
+ // Extract ONLY the FINAL ANSWER: portion for clean HUD display
939
+ // ChatGPT reasons fully internally — we only show the tagged result
940
+ function extractFinalAnswer(text) {
941
+ // Strategy 1: Look for FINAL ANSWER tag
942
+ const tagPattern = /FINAL ANSWER(?:\s*\[Q\d+(?:-Q?\d+)?\])?\s*:\s*([\s\S]*?)(?=FINAL ANSWER|$)/gi;
943
+ const matches = [];
944
+ let match;
945
+ while ((match = tagPattern.exec(text)) !== null) {
946
+ let extracted = match[1].trim();
947
+ // Strip markdown code fences from extracted content
948
+ extracted = extracted.replace(/^```[\w]*\n?/gm, '').replace(/```$/gm, '').trim();
949
+ if (extracted) matches.push(extracted);
950
+ }
951
+ if (matches.length > 0) return matches.join('\n');
952
+
953
+ // Strategy 2: Extract code blocks (for PRG/DEB when ChatGPT skips tag)
954
+ const codeBlockPattern = /```[\w]*\n([\s\S]*?)```/g;
955
+ const codeBlocks = [];
956
+ while ((match = codeBlockPattern.exec(text)) !== null) {
957
+ if (match[1].trim()) codeBlocks.push(match[1].trim());
958
+ }
959
+ if (codeBlocks.length > 0) return codeBlocks.join('\n\n');
960
+
961
+ // Strategy 3: If still streaming reasoning, show placeholder
962
+ // Once FINAL ANSWER appears, strategies 1/2 will catch it
963
+ if (text.length > 20) return '⏳ Thinking...';
964
+ return text;
965
+ }
966
+
967
+ sessionHistory = allAnswers.map((ans, i) => ({
968
+ qNum: sentBatches[i] ? sentBatches[i].label : `[Q${i+1}]`,
969
+ answer: extractFinalAnswer(ans.replace(/\n+$/, '').trim())
970
+ }));
971
+
972
+ if (overlayWindow && !overlayWindow.isDestroyed()) {
973
+ overlayWindow.webContents.send('update-ans', JSON.stringify({ type: 'history', items: sessionHistory }));
974
+ updateUI();
975
+ }
976
+ }
977
+ }
978
+ } catch (e) {}
979
+ pollInterval = setTimeout(runPoll, 500);
980
+ }
981
+
982
+ runPoll();
983
+ }
984
+
985
+ // ═══════════════════════════════════════════
986
+ // UI DISPATCH & HUD
987
+ // ═══════════════════════════════════════════
988
+
989
+ function updateUI() {
990
+ if (!overlayWindow) return;
991
+ overlayWindow.webContents.send('update-hud', {
992
+ count: batchQueue.length,
993
+ isForcedHidden,
994
+ isUiHidden,
995
+ isPinned,
996
+ isAlwaysOnTop,
997
+ isCombatMode,
998
+ activeSection
999
+ });
1000
+ if (sessionHistory.length > 0) {
1001
+ overlayWindow.webContents.send('update-ans', JSON.stringify({ type: 'history', items: sessionHistory }));
1002
+ }
1003
+ }
1004
+
1005
+ // ═══════════════════════════════════════════
1006
+ // STEALTH POLLING (Hover Reveal)
1007
+ // ═══════════════════════════════════════════
1008
+ // ═══════════════════════════════════════════
1009
+ // STEALTH ENGINE (Edges & Jitter)
1010
+ // ═══════════════════════════════════════════
1011
+ setInterval(() => {
1012
+ if (!overlayWindow || overlayWindow.isDestroyed()) return;
1013
+
1014
+ const mouse = screen.getCursorScreenPoint();
1015
+ const { width: screenWidth, height: screenHeight } = screen.getPrimaryDisplay().bounds;
1016
+
1017
+ // 1. Edge Triggers (Capture/Solve)
1018
+ if (Date.now() > edgeCooldown) {
1019
+ if (mouse.x >= screenWidth - 1) { // Right Edge Proximity
1020
+ if (!edgeActive.right) {
1021
+ captureTextQuestion();
1022
+ edgeActive.right = true;
1023
+ edgeCooldown = Date.now() + 2000; // 2s cooldown
1024
+ }
1025
+ } else {
1026
+ edgeActive.right = false;
1027
+ }
1028
+
1029
+ if (mouse.x <= 0) { // Left Edge Proximity
1030
+ if (!edgeActive.left) {
1031
+ performOracleStrike();
1032
+ edgeActive.left = true;
1033
+ edgeCooldown = Date.now() + 2000;
1034
+ }
1035
+ } else {
1036
+ edgeActive.left = false;
1037
+ }
1038
+ }
1039
+
1040
+ lastMousePos = { x: mouse.x, y: mouse.y };
1041
+
1042
+ // 3. Position HUD Window
1043
+ if (isPinned) return;
1044
+
1045
+ if (isForcedHidden) {
1046
+ if (wasVisible) {
1047
+ overlayWindow.hide();
1048
+ wasVisible = false;
1049
+ }
1050
+ } else {
1051
+ // 🛡️ SELF-HEALING: Force-show if proctor hid us (Electron-level check)
1052
+ if (!wasVisible || !overlayWindow.isVisible()) {
1053
+ overlayWindow.showInactive();
1054
+ wasVisible = true;
1055
+ }
1056
+
1057
+ const sf = screen.getPrimaryDisplay().scaleFactor || 1.0;
1058
+ overlayWindow.setBounds({
1059
+ x: Math.round(mouse.x + 10), y: Math.round(mouse.y + 10),
1060
+ width: Math.round(180 * sf), height: Math.round(150 * sf)
1061
+ });
1062
+
1063
+ // Re-assert always on top at Electron level too
1064
+ overlayWindow.setAlwaysOnTop(true, 'screen-saver', 100);
1065
+ }
1066
+ }, 25);
1067
+
1068
+ // ═══════════════════════════════════════════
1069
+ // APP INITIALIZATION
1070
+ // ═══════════════════════════════════════════
1071
+
1072
+ // \u{1F6E1} CRITICAL: Prevent Electron from auto-quitting when windows are destroyed
1073
+ app.on('window-all-closed', () => {
1074
+ // Desktop Scout manages window lifecycle \u2014 never auto-quit
1075
+ });
1076
+
1077
+ app.whenReady().then(async () => {
1078
+ app.setName('exiouss');
1079
+
1080
+ // \u{1F6E1}\uFE0F FIREWALL SHIELD: Apply Proxy if specified
1081
+ if (PROXY_RULE) {
1082
+ console.log(`[PROXY] Routing traffic through: ${PROXY_RULE}`);
1083
+ const proxyConfig = { proxyRules: PROXY_RULE };
1084
+ await session.defaultSession.setProxy(proxyConfig);
1085
+ const gptSess = session.fromPartition('persist:chatgpt');
1086
+ await gptSess.setProxy(proxyConfig);
1087
+ }
1088
+
1089
+ createOverlayWindow();
1090
+ chatgptWin = createBridge('chatgpt', 'https://chat.openai.com', 'chatgpt');
1091
+
1092
+ // Run environment check after windows are ready
1093
+ setTimeout(checkEnvironment, 2000);
1094
+
1095
+ // Register all hotkeys (extracted into reusable function for desktop migration)
1096
+ registerAllHotkeys();
1097
+
1098
+ // \u{1F54A}\uFE0F GHOST MODE: uIOhook Listeners
1099
+ // Event handlers registered ONCE — they persist across uIOhook stop/start cycles
1100
+ let isUpPressed = false, isDownPressed = false, isLeftPressed = false, isRightPressed = false;
1101
+ let isShiftPressed = false;
1102
+ let isChordLocked = false;
1103
+
1104
+ uIOhook.on('keydown', (e) => {
1105
+ setImmediate(() => {
1106
+ if (e.keycode === 57416 || e.keycode === 72) isUpPressed = true;
1107
+ if (e.keycode === 57424 || e.keycode === 80) isDownPressed = true;
1108
+ if (e.keycode === 57419 || e.keycode === 75) isLeftPressed = true;
1109
+ if (e.keycode === 57421 || e.keycode === 77) isRightPressed = true;
1110
+ if (e.keycode === 42 || e.keycode === 54) isShiftPressed = true;
1111
+
1112
+ // 1. Hide/Unhide HUD (Up + Down)
1113
+ if (isUpPressed && isDownPressed) {
1114
+ isForcedHidden = !isForcedHidden;
1115
+ updateUI();
1116
+ isUpPressed = false; isDownPressed = false;
1117
+ }
1118
+
1119
+ // 2. TEXT CAPTURE (Left + Right)
1120
+ if (isLeftPressed && isRightPressed) {
1121
+ if (isChordLocked) return;
1122
+ console.log(`[CHORD] TEXT CAPTURE Triggered...`);
1123
+ isChordLocked = true;
1124
+ captureTextQuestion();
1125
+ isLeftPressed = false; isRightPressed = false;
1126
+ setTimeout(() => { isChordLocked = false; }, 2000);
1127
+ }
1128
+
1129
+ // 3. IMAGE CAPTURE (Down + Left)
1130
+ if (isDownPressed && isLeftPressed) {
1131
+ if (isChordLocked) return;
1132
+ console.log(`[CHORD] DIAGRAM CAPTURE Triggered...`);
1133
+ isChordLocked = true;
1134
+ captureImageQuestion();
1135
+ isDownPressed = false; isLeftPressed = false;
1136
+ setTimeout(() => { isChordLocked = false; }, 2000);
1137
+ }
1138
+
1139
+ // 4. Perform Strike (Up + Right)
1140
+ if (isUpPressed && isRightPressed) {
1141
+ performOracleStrike();
1142
+ isUpPressed = false; isRightPressed = false;
1143
+ }
1144
+
1145
+ // 5. Pin/Unpin (Up + Left)
1146
+ if (isUpPressed && isLeftPressed) {
1147
+ isPinned = !isPinned;
1148
+ updateUI();
1149
+ isUpPressed = false; isLeftPressed = false;
1150
+ }
1151
+ });
1152
+ });
1153
+
1154
+ uIOhook.on('keyup', (e) => {
1155
+ setImmediate(() => {
1156
+ if (e.keycode === 57416 || e.keycode === 72) isUpPressed = false;
1157
+ if (e.keycode === 57424 || e.keycode === 80) isDownPressed = false;
1158
+ if (e.keycode === 57419 || e.keycode === 75) isLeftPressed = false;
1159
+ if (e.keycode === 57421 || e.keycode === 77) isRightPressed = false;
1160
+ if (e.keycode === 42 || e.keycode === 54) isShiftPressed = false;
1161
+ });
1162
+ });
1163
+
1164
+ // STEALTH CLICK HANDLER
1165
+ uIOhook.on('mousemove', (e) => {
1166
+ lastMousePos = { x: e.x, y: e.y };
1167
+ });
1168
+ uIOhook.on('mousedown', (e) => {
1169
+ setImmediate(() => {
1170
+ if (!overlayWindow || overlayWindow.isDestroyed() || !overlayWindow.isVisible()) return;
1171
+ const bounds = overlayWindow.getBounds();
1172
+ const primaryDisplay = screen.getPrimaryDisplay();
1173
+ const sf = primaryDisplay.scaleFactor;
1174
+
1175
+ const mX = e.x / sf;
1176
+ const mY = e.y / sf;
1177
+
1178
+ if (mX >= bounds.x && mX <= bounds.x + bounds.width &&
1179
+ mY >= bounds.y && mY <= bounds.y + bounds.height) {
1180
+ const clientX = Math.round(mX - bounds.x);
1181
+ const clientY = Math.round(mY - bounds.y);
1182
+ overlayWindow.webContents.send('stealth-click', { x: clientX, y: clientY });
1183
+ }
1184
+ });
1185
+ });
1186
+
1187
+ // Delay start to let Electron event loop stabilize
1188
+ setTimeout(() => {
1189
+ uIOhook.start();
1190
+ console.log('[GHOST] uIOhook started successfully.');
1191
+ }, 500);
1192
+
1193
+ // \u{1F6F8} DESKTOP SCOUT: Start cross-desktop migration engine
1194
+ // Delayed to let everything initialize first
1195
+ setTimeout(() => {
1196
+ startDesktopScout();
1197
+ }, 3000);
1198
+ });