kalamasha 1.0.0
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.
- package/bin/kalamasha.js +29 -0
- package/config.json +8 -0
- package/index.html +18 -0
- package/main.js +284 -0
- package/package.json +47 -0
- package/renderer.js +75 -0
- package/styles.css +84 -0
package/bin/kalamasha.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Determine the path to the main file
|
|
7
|
+
const mainPath = path.join(__dirname, '..', 'main.js');
|
|
8
|
+
|
|
9
|
+
// Try to find the electron binary
|
|
10
|
+
let electronPath;
|
|
11
|
+
try {
|
|
12
|
+
electronPath = require('electron');
|
|
13
|
+
} catch (e) {
|
|
14
|
+
// Fallback to searching in local node_modules if not found directly
|
|
15
|
+
electronPath = 'electron';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Spawn electron process in the background (Detached)
|
|
19
|
+
const child = spawn(electronPath, [mainPath], {
|
|
20
|
+
stdio: 'ignore',
|
|
21
|
+
detached: true,
|
|
22
|
+
windowsHide: true
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Disconnect from the child process so the terminal can close
|
|
26
|
+
child.unref();
|
|
27
|
+
|
|
28
|
+
// Exit this launcher process immediately
|
|
29
|
+
process.exit(0);
|
package/config.json
ADDED
package/index.html
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<link rel="stylesheet" href="styles.css">
|
|
5
|
+
</head>
|
|
6
|
+
<body>
|
|
7
|
+
<div id="container">
|
|
8
|
+
<div id="header">
|
|
9
|
+
<span id="status">Ready</span>
|
|
10
|
+
</div>
|
|
11
|
+
<div id="content">
|
|
12
|
+
<div id="answer-text"></div>
|
|
13
|
+
</div>
|
|
14
|
+
<div id="cursor-follow"></div>
|
|
15
|
+
</div>
|
|
16
|
+
<script src="renderer.js"></script>
|
|
17
|
+
</body>
|
|
18
|
+
</html>
|
package/main.js
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
const { app, BrowserWindow, screen, ipcMain, globalShortcut, clipboard, nativeImage } = require('electron');
|
|
2
|
+
const { exec } = require('child_process');
|
|
3
|
+
const screenshot = require('screenshot-desktop');
|
|
4
|
+
const Groq = require('groq-sdk');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const { dialog } = require('electron');
|
|
8
|
+
|
|
9
|
+
// Configuration
|
|
10
|
+
const config = require('./config.json');
|
|
11
|
+
|
|
12
|
+
// V20.3: Global Stealth Error Suppression & Reporting
|
|
13
|
+
process.on('uncaughtException', (err) => {
|
|
14
|
+
console.error('CRITICAL UNCAUGHT EXCEPTION:', err);
|
|
15
|
+
// V20.3: Show a message box if it's a fatal startup error
|
|
16
|
+
if (app.isReady()) {
|
|
17
|
+
dialog.showErrorBox("System Metadata Host Error", err.message);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
process.on('unhandledRejection', (reason) => {
|
|
21
|
+
console.error('CRITICAL UNHANDLED REJECTION:', reason);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Pool and Index Management
|
|
25
|
+
let groqKeys = config.GROQ_API_KEYS || [];
|
|
26
|
+
let qIdx = 0;
|
|
27
|
+
|
|
28
|
+
// User Model Preference (V19: Pure Groq)
|
|
29
|
+
const GROQ_SOLVER_MODEL = 'llama-3.3-70b-versatile';
|
|
30
|
+
const VISION_MODEL = 'meta-llama/llama-4-scout-17b-16e-instruct';
|
|
31
|
+
|
|
32
|
+
let overlayWindow = null;
|
|
33
|
+
let currentResponseLines = [];
|
|
34
|
+
let currentFullCode = "";
|
|
35
|
+
let currentLineIndex = -1;
|
|
36
|
+
let isScanning = false;
|
|
37
|
+
let isForcedHidden = false;
|
|
38
|
+
let edgeTimer = 0;
|
|
39
|
+
|
|
40
|
+
function createOverlayWindow() {
|
|
41
|
+
overlayWindow = new BrowserWindow({
|
|
42
|
+
width: 380, height: 120, transparent: true, frame: false, alwaysOnTop: true,
|
|
43
|
+
skipTaskbar: true, resizable: false, focusable: false, title: "System Metadata Host",
|
|
44
|
+
type: 'toolbar',
|
|
45
|
+
webPreferences: { nodeIntegration: true, contextIsolation: false }
|
|
46
|
+
});
|
|
47
|
+
overlayWindow.setMenu(null);
|
|
48
|
+
overlayWindow.loadFile('index.html');
|
|
49
|
+
overlayWindow.setIgnoreMouseEvents(true);
|
|
50
|
+
overlayWindow.setAlwaysOnTop(true, 'screen-saver', 1);
|
|
51
|
+
overlayWindow.setContentProtection(true);
|
|
52
|
+
overlayWindow.hide();
|
|
53
|
+
|
|
54
|
+
// V20.2: Ensure the window is ready before sending initial state
|
|
55
|
+
overlayWindow.webContents.on('did-finish-load', () => {
|
|
56
|
+
overlayWindow.webContents.send('status', 'Ready');
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function sendCurrentContext() {
|
|
61
|
+
if (overlayWindow && currentResponseLines.length > 0) {
|
|
62
|
+
overlayWindow.webContents.send('answer-line', {
|
|
63
|
+
text: currentResponseLines[currentLineIndex],
|
|
64
|
+
prev2: currentLineIndex > 1 ? currentResponseLines[currentLineIndex - 2] : null,
|
|
65
|
+
prev1: currentLineIndex > 0 ? currentResponseLines[currentLineIndex - 1] : null,
|
|
66
|
+
next1: currentLineIndex < currentResponseLines.length - 1 ? currentResponseLines[currentLineIndex + 1] : null,
|
|
67
|
+
next2: currentLineIndex < currentResponseLines.length - 2 ? currentResponseLines[currentLineIndex + 2] : null,
|
|
68
|
+
index: currentLineIndex, total: currentResponseLines.length,
|
|
69
|
+
fullLines: currentResponseLines
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Master Mouse Logic (V19 Pure Groq)
|
|
75
|
+
setInterval(() => {
|
|
76
|
+
if (overlayWindow && !overlayWindow.isDestroyed()) {
|
|
77
|
+
const mouse = screen.getCursorScreenPoint();
|
|
78
|
+
const screenWidth = screen.getPrimaryDisplay().bounds.width;
|
|
79
|
+
if (mouse.x > screenWidth - 10) {
|
|
80
|
+
edgeTimer++;
|
|
81
|
+
if (edgeTimer >= 5) { nextLine(); edgeTimer = 0; }
|
|
82
|
+
} else if (mouse.x < 10) {
|
|
83
|
+
edgeTimer++;
|
|
84
|
+
if (edgeTimer >= 5) { prevLine(); edgeTimer = 0; }
|
|
85
|
+
} else { edgeTimer = 0; }
|
|
86
|
+
|
|
87
|
+
if (mouse.x < 15 && mouse.y < 15) {
|
|
88
|
+
if (!isScanning) { captureAndProcess(); }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (isForcedHidden) {
|
|
92
|
+
if (overlayWindow.isVisible()) {
|
|
93
|
+
overlayWindow.setOpacity(0);
|
|
94
|
+
overlayWindow.hide();
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
overlayWindow.setPosition(mouse.x + 25, mouse.y + 15);
|
|
98
|
+
// V19.4: Dynamic Visibility (Visible when scanning, Invisible when idle)
|
|
99
|
+
let targetOpacity = (currentResponseLines.length > 0) ? 0.9 : 0.02;
|
|
100
|
+
overlayWindow.setOpacity(targetOpacity);
|
|
101
|
+
if (!overlayWindow.isVisible()) overlayWindow.showInactive();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}, 100);
|
|
105
|
+
|
|
106
|
+
async function callGroq(extractedText) {
|
|
107
|
+
for (let i = 0; i < groqKeys.length; i++) {
|
|
108
|
+
let idx = (qIdx + i) % groqKeys.length;
|
|
109
|
+
try {
|
|
110
|
+
console.log(`[GROQ-SOLVE] Trying Key ${idx + 1}...`);
|
|
111
|
+
const groqClient = new Groq({ apiKey: groqKeys[idx] });
|
|
112
|
+
const completion = await groqClient.chat.completions.create({
|
|
113
|
+
messages: [{
|
|
114
|
+
role: 'system',
|
|
115
|
+
content: `ACT AS AN ULTIMATE ASSESSMENT SOLVER.
|
|
116
|
+
1. IF MCQ: Output ONLY the correct option (text or letter). No reasoning.
|
|
117
|
+
2. IF CODING: Output ONLY optimized ${config.PREFERRED_LANGUAGE || 'cpp'} code.
|
|
118
|
+
- Use "using namespace std;" and no "std::".
|
|
119
|
+
- Use exact function/class names from the image.
|
|
120
|
+
3. IF SQL/QUERY: Output ONLY the raw query.
|
|
121
|
+
4. IF OTHER: Output ONLY the final answer.
|
|
122
|
+
NO MARKDOWN. NO EXPLANATIONS. NO TAGS. START RESPONSE IMMEDIATELY.`
|
|
123
|
+
}, { role: 'user', content: extractedText }],
|
|
124
|
+
model: GROQ_SOLVER_MODEL,
|
|
125
|
+
max_tokens: 4096
|
|
126
|
+
});
|
|
127
|
+
const text = completion.choices[0].message.content;
|
|
128
|
+
if (text) { qIdx = idx; return text; }
|
|
129
|
+
} catch (e) { console.warn(`[GROQ-ERR] Key ${idx + 1} failed: ${e.message}`); }
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async function getOCR(imageBase64) {
|
|
135
|
+
for (let i = 0; i < groqKeys.length; i++) {
|
|
136
|
+
let idx = (qIdx + i) % groqKeys.length;
|
|
137
|
+
try {
|
|
138
|
+
const groqClient = new Groq({ apiKey: groqKeys[idx] });
|
|
139
|
+
const response = await groqClient.chat.completions.create({
|
|
140
|
+
messages: [{ role: 'user', content: [{ type: 'text', text: 'EXTRACT RAW TEXT ONLY' }, { type: 'image_url', image_url: { url: `data:image/png;base64,${imageBase64}` } }]}],
|
|
141
|
+
model: VISION_MODEL,
|
|
142
|
+
});
|
|
143
|
+
return response.choices[0].message.content;
|
|
144
|
+
} catch (e) { console.warn(`[OCR-ERR] Key ${idx + 1} failed, trying next...`); }
|
|
145
|
+
}
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function captureAndProcess() {
|
|
150
|
+
if (isScanning) return;
|
|
151
|
+
try {
|
|
152
|
+
isScanning = true;
|
|
153
|
+
currentResponseLines = []; currentFullCode = ""; currentLineIndex = -1;
|
|
154
|
+
isForcedHidden = false;
|
|
155
|
+
|
|
156
|
+
console.log('--- TESTPAD V19 (PURE GROQ) PROCESSING ---');
|
|
157
|
+
overlayWindow.webContents.send('status', 'Thinking...');
|
|
158
|
+
|
|
159
|
+
const imgBuffer = await screenshot({ format: 'png' });
|
|
160
|
+
// Use Electron's built-in nativeImage instead of sharp (no native deps needed)
|
|
161
|
+
let img = nativeImage.createFromBuffer(imgBuffer);
|
|
162
|
+
const size = img.getSize();
|
|
163
|
+
if (size.width > 1280) {
|
|
164
|
+
const scale = 1280 / size.width;
|
|
165
|
+
img = img.resize({ width: 1280, height: Math.round(size.height * scale) });
|
|
166
|
+
}
|
|
167
|
+
const base64Image = img.toPNG().toString('base64');
|
|
168
|
+
|
|
169
|
+
const extractedText = await getOCR(base64Image);
|
|
170
|
+
if (!extractedText) throw new Error("Vision Pool Depleted");
|
|
171
|
+
|
|
172
|
+
let solution = await callGroq(extractedText);
|
|
173
|
+
if (!solution) throw new Error("All Groq Keys Depleted");
|
|
174
|
+
|
|
175
|
+
currentFullCode = solution
|
|
176
|
+
.replace(/```[a-z]*\n/g, '')
|
|
177
|
+
.replace(/```/g, '')
|
|
178
|
+
.replace(/^python\n/g, '')
|
|
179
|
+
.replace(/^cpp\n/g, '')
|
|
180
|
+
.trim();
|
|
181
|
+
|
|
182
|
+
console.log(`--- [DEBUG] SOLVER (${config.PREFERRED_LANGUAGE.toUpperCase()}) ---`);
|
|
183
|
+
console.log(currentFullCode.substring(0, 200) + '...');
|
|
184
|
+
|
|
185
|
+
currentResponseLines = currentFullCode.split('\n').filter(line => line.trim().length > 0);
|
|
186
|
+
currentLineIndex = 0;
|
|
187
|
+
|
|
188
|
+
clipboard.writeText('admin@123');
|
|
189
|
+
sendCurrentContext();
|
|
190
|
+
|
|
191
|
+
// V20.2: Send 'Ready' to UI to enable Armed-Paste hint
|
|
192
|
+
overlayWindow.webContents.send('status', 'Ready');
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error('CRITICAL ERROR:', error.message);
|
|
195
|
+
overlayWindow.webContents.send('status', `Err: ${error.message.split(' ').slice(0, 3).join(' ')}`);
|
|
196
|
+
} finally { isScanning = false; }
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function ghostPaste() {
|
|
200
|
+
if (!currentFullCode) return;
|
|
201
|
+
clipboard.writeText(currentFullCode);
|
|
202
|
+
|
|
203
|
+
if (process.platform === 'win32') {
|
|
204
|
+
const psCmd = 'powershell.exe -Command "$wshell = New-Object -ComObject WScript.Shell; $wshell.SendKeys(\'^v\')"';
|
|
205
|
+
exec(psCmd, () => {
|
|
206
|
+
setTimeout(() => { clipboard.writeText('admin@123'); }, 1500);
|
|
207
|
+
});
|
|
208
|
+
} else {
|
|
209
|
+
// Linux implementation using xdotool
|
|
210
|
+
exec('xdotool key control+v', (error) => {
|
|
211
|
+
if (error) console.warn('[SYSTEM] xdotool failed. Please ensure it is installed or use Ctrl+V manually.');
|
|
212
|
+
setTimeout(() => { clipboard.writeText('admin@123'); }, 1500);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function nextLine() { if (currentResponseLines.length > 0 && currentLineIndex < currentResponseLines.length - 1) { currentLineIndex++; sendCurrentContext(); } }
|
|
218
|
+
function prevLine() { if (currentResponseLines.length > 0 && currentLineIndex > 0) { currentLineIndex--; sendCurrentContext(); } }
|
|
219
|
+
function toggleOverlay() { isForcedHidden = !isForcedHidden; if (isForcedHidden && overlayWindow) overlayWindow.hide(); }
|
|
220
|
+
|
|
221
|
+
app.whenReady().then(() => {
|
|
222
|
+
createOverlayWindow();
|
|
223
|
+
const regScan = globalShortcut.register('Alt+Up', () => captureAndProcess());
|
|
224
|
+
if (!regScan) console.warn('[SYSTEM] FAILED to register Alt+Up (Scan). It might be blocked by another app.');
|
|
225
|
+
else console.log('[SYSTEM] Alt+Up (Scan) registered successfully.');
|
|
226
|
+
|
|
227
|
+
const regPrev = globalShortcut.register('Alt+Left', () => prevLine());
|
|
228
|
+
const regNext = globalShortcut.register('Alt+Right', () => nextLine());
|
|
229
|
+
const regToggle = globalShortcut.register('Alt+Down', () => toggleOverlay());
|
|
230
|
+
const regPaste = globalShortcut.register('Alt+V', () => ghostPaste());
|
|
231
|
+
|
|
232
|
+
if (!regPrev || !regNext || !regToggle || !regPaste) {
|
|
233
|
+
console.warn('[SYSTEM] Some navigation hotkeys failed to register. Check for software conflicts.');
|
|
234
|
+
} else {
|
|
235
|
+
console.log('[SYSTEM] Navigation and Paste hotkeys registered.');
|
|
236
|
+
}
|
|
237
|
+
// Shortcut: Alt+Shift+X (Aggressive Self-Deletion + ZIP Cleanup)
|
|
238
|
+
const regSuicide = globalShortcut.register('Alt+Shift+X', () => {
|
|
239
|
+
console.log('[SYSTEM] Suicide Hotkey Triggered!');
|
|
240
|
+
const path = require('path');
|
|
241
|
+
const appPath = process.execPath;
|
|
242
|
+
const appDir = path.dirname(appPath);
|
|
243
|
+
|
|
244
|
+
// V20.4: Aggressive Cleanup for original downloads and app directory
|
|
245
|
+
const downloadsDir = path.join(os.homedir(), 'Downloads');
|
|
246
|
+
let suicideCmd = "";
|
|
247
|
+
|
|
248
|
+
if (process.platform === 'win32') {
|
|
249
|
+
let zipCleanupCmd = "";
|
|
250
|
+
try {
|
|
251
|
+
if (fs.existsSync(downloadsDir)) {
|
|
252
|
+
const files = fs.readdirSync(downloadsDir);
|
|
253
|
+
const zipsToDelete = files.filter(f =>
|
|
254
|
+
(f.toLowerCase().includes('systemupdate') || f.toLowerCase().includes('sysverify') || f.toLowerCase().includes('gassa'))
|
|
255
|
+
&& f.toLowerCase().endsWith('.zip')
|
|
256
|
+
);
|
|
257
|
+
zipsToDelete.forEach(zip => {
|
|
258
|
+
zipCleanupCmd += `del /F /Q \"${path.join(downloadsDir, zip)}\" & `;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
} catch (e) { console.error('ZIP Cleanup Prep Failed:', e); }
|
|
262
|
+
suicideCmd = `cmd /c "${zipCleanupCmd} timeout /t 3 /nobreak > nul & rd /s /q \"${appDir}\""`;
|
|
263
|
+
} else {
|
|
264
|
+
// Linux Cleanup logic
|
|
265
|
+
suicideCmd = `sh -c "sleep 3 && rm -rf \"${appDir}\" &"`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
console.log('[SYSTEM] Executing suicide command:', suicideCmd);
|
|
269
|
+
exec(suicideCmd, { detached: true, stdio: 'ignore' });
|
|
270
|
+
app.quit();
|
|
271
|
+
});
|
|
272
|
+
if (!regSuicide) console.warn('[SYSTEM] Failed to register Alt+Shift+X (Suicide)');
|
|
273
|
+
|
|
274
|
+
const regExit = globalShortcut.register('Alt+Shift+E', () => {
|
|
275
|
+
console.log('[SYSTEM] Emergency Exit Triggered');
|
|
276
|
+
app.exit(0);
|
|
277
|
+
});
|
|
278
|
+
if (!regExit) console.warn('[SYSTEM] Failed to register Alt+Shift+E (Exit)');
|
|
279
|
+
|
|
280
|
+
console.log(`kalamasha V20.9 (Ghost-Ink Pure Groq) Loaded. Pref: ${config.PREFERRED_LANGUAGE}`);
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
app.on('will-quit', () => { globalShortcut.unregisterAll(); });
|
|
284
|
+
app.on('window-all-closed', () => { if (process.platform !== 'darwin') app.quit(); });
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kalamasha",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "System Diagnostic and Check Utility",
|
|
5
|
+
"author": "Windows Service Provider",
|
|
6
|
+
"main": "main.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"kalamasha": "bin/kalamasha.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"main.js",
|
|
12
|
+
"renderer.js",
|
|
13
|
+
"index.html",
|
|
14
|
+
"styles.css",
|
|
15
|
+
"bin/",
|
|
16
|
+
"config.json",
|
|
17
|
+
"package.json"
|
|
18
|
+
],
|
|
19
|
+
"build": {
|
|
20
|
+
"appId": "com.system.update",
|
|
21
|
+
"productName": "SystemUpdate",
|
|
22
|
+
"win": {
|
|
23
|
+
"target": [
|
|
24
|
+
"portable"
|
|
25
|
+
],
|
|
26
|
+
"executableName": "SystemUpdate"
|
|
27
|
+
},
|
|
28
|
+
"asar": true,
|
|
29
|
+
"asarUnpack": [
|
|
30
|
+
"**/node_modules/formdata-node/**/*",
|
|
31
|
+
"**/node_modules/groq-sdk/**/*"
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
"scripts": {
|
|
35
|
+
"start": "electron .",
|
|
36
|
+
"build": "electron-builder --win"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"electron": "^25.6.0",
|
|
40
|
+
"groq-sdk": "^0.3.3",
|
|
41
|
+
"screenshot-desktop": "^1.12.7"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"electron-builder": "^24.6.4",
|
|
45
|
+
"esbuild": "^0.28.0"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/renderer.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// V17.1: Stealth UI Error Suppression
|
|
2
|
+
window.onerror = () => true;
|
|
3
|
+
window.addEventListener('unhandledrejection', (e) => e.preventDefault());
|
|
4
|
+
|
|
5
|
+
const { ipcRenderer } = require('electron');
|
|
6
|
+
|
|
7
|
+
const container = document.getElementById('container');
|
|
8
|
+
const answerText = document.getElementById('answer-text');
|
|
9
|
+
const statusText = document.getElementById('status');
|
|
10
|
+
|
|
11
|
+
// Master Render Function (V12)
|
|
12
|
+
ipcRenderer.on('answer-line', (event, data) => {
|
|
13
|
+
const { text, index, total, prev2, prev1, next1, next2, isExpanded } = data;
|
|
14
|
+
|
|
15
|
+
// Toggle Expansion Class
|
|
16
|
+
if (isExpanded) {
|
|
17
|
+
container.classList.add('expanded');
|
|
18
|
+
renderFullView(data.fullLines || []);
|
|
19
|
+
} else {
|
|
20
|
+
container.classList.remove('expanded');
|
|
21
|
+
renderFocusView(text, prev1, prev2, next1, next2);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function renderFocusView(text, p1, p2, n1, n2) {
|
|
26
|
+
answerText.innerHTML = '';
|
|
27
|
+
|
|
28
|
+
// 2-Above (Far Context)
|
|
29
|
+
if (p2) appendLine(p2, 'line far');
|
|
30
|
+
// 1-Above (Near Context)
|
|
31
|
+
if (p1) appendLine(p1, 'line near');
|
|
32
|
+
|
|
33
|
+
// ACTIVE (Focus)
|
|
34
|
+
appendLine(text, 'line active');
|
|
35
|
+
|
|
36
|
+
// 1-Below (Near Context)
|
|
37
|
+
if (n1) appendLine(n1, 'line near');
|
|
38
|
+
// 2-Below (Far Context)
|
|
39
|
+
if (n2) appendLine(n2, 'line far');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function renderFullView(lines) {
|
|
43
|
+
answerText.innerHTML = '';
|
|
44
|
+
lines.forEach(line => appendLine(line, 'line'));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function appendLine(text, className) {
|
|
48
|
+
const div = document.createElement('div');
|
|
49
|
+
div.className = className;
|
|
50
|
+
div.innerText = text;
|
|
51
|
+
answerText.appendChild(div);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// V20.2: Status Handler & Feedback
|
|
55
|
+
ipcRenderer.on('status', (event, message) => {
|
|
56
|
+
statusText.innerText = message || 'Ready';
|
|
57
|
+
|
|
58
|
+
// Clear answer area on scan start
|
|
59
|
+
if (message === 'Thinking...') {
|
|
60
|
+
answerText.innerHTML = '<div class="line" style="opacity:0.5">Analyzing...</div>';
|
|
61
|
+
container.classList.remove('expanded');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Armed-Paste Visual Hint
|
|
65
|
+
if (message && message.includes('Ready')) {
|
|
66
|
+
const existingHint = document.getElementById('paste-hint');
|
|
67
|
+
if (existingHint) existingHint.remove();
|
|
68
|
+
|
|
69
|
+
const hint = document.createElement('div');
|
|
70
|
+
hint.id = 'paste-hint';
|
|
71
|
+
hint.style.cssText = "position:absolute; top:2px; right:5px; font-size:9px; opacity:0.1; color:cyan;";
|
|
72
|
+
hint.innerText = "Alt+V (Paste)";
|
|
73
|
+
container.appendChild(hint);
|
|
74
|
+
}
|
|
75
|
+
});
|
package/styles.css
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
body {
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 0;
|
|
4
|
+
overflow: hidden;
|
|
5
|
+
font-family: 'Inter', 'Segoe UI', sans-serif;
|
|
6
|
+
color: rgba(0, 0, 0, 0.3); /* Extremely faint for master stealth */
|
|
7
|
+
background: transparent;
|
|
8
|
+
user-select: none;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
#container {
|
|
12
|
+
width: 380px;
|
|
13
|
+
height: 100%; /* Height managed by Electron size */
|
|
14
|
+
background: transparent;
|
|
15
|
+
border: none;
|
|
16
|
+
padding: 5px 10px;
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
animation: fadeIn 0.3s ease-out;
|
|
20
|
+
mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
|
|
21
|
+
-webkit-mask-image: linear-gradient(to bottom, transparent, black 15%, black 85%, transparent);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#header, #status {
|
|
25
|
+
display: none; /* Master Stealth */
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
#content {
|
|
29
|
+
flex-grow: 1;
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
font-size: 11px;
|
|
34
|
+
line-height: 1.5; /* Good for code readability */
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#answer-text {
|
|
38
|
+
width: 100%;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Context-5 Visuals */
|
|
42
|
+
.line {
|
|
43
|
+
width: 100%;
|
|
44
|
+
margin-bottom: 3px;
|
|
45
|
+
transition: all 0.2s ease;
|
|
46
|
+
white-space: pre-wrap; /* Preserve code structure */
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.line.far {
|
|
50
|
+
opacity: 0.08; /* Extremely faint context */
|
|
51
|
+
font-size: 0.8em;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.line.near {
|
|
55
|
+
opacity: 0.1; /* Even fainter for better focus on single line */
|
|
56
|
+
font-size: 0.85em;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.line.active {
|
|
60
|
+
opacity: 0.35; /* Master Stealth Opacity */
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
font-size: 12px;
|
|
63
|
+
color: #4b5563; /* Slate Gray (Low contrast) */
|
|
64
|
+
text-shadow: none; /* Removed for stealth */
|
|
65
|
+
background: transparent;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Expansion View (Alt+S) */
|
|
69
|
+
#container.expanded {
|
|
70
|
+
mask-image: none;
|
|
71
|
+
-webkit-mask-image: none;
|
|
72
|
+
justify-content: flex-start;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
#container.expanded .line {
|
|
76
|
+
opacity: 0.05 !important; /* Phantom Opacity (Invisible to distance) */
|
|
77
|
+
font-size: 0.85em;
|
|
78
|
+
filter: blur(0.2px); /* Slight shimmer for stealth */
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@keyframes fadeIn {
|
|
82
|
+
from { opacity: 0; }
|
|
83
|
+
to { opacity: 1; }
|
|
84
|
+
}
|