seo-intel 1.2.2 → 1.2.3
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/CHANGELOG.md +3 -2
- package/package.json +1 -1
- package/reports/generate-html.js +1 -1
- package/server.js +22 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 1.2.
|
|
3
|
+
## 1.2.3 (2026-03-28)
|
|
4
4
|
|
|
5
5
|
### Dashboard
|
|
6
6
|
- Remove redundant Crawl/Extract buttons from status bar — terminal already has them
|
|
7
7
|
- Status bar now shows only Stop, Restart, and Stealth toggle (cleaner UI)
|
|
8
|
-
-
|
|
8
|
+
- Fix stealth toggle scoping in multi-project dashboard — each project panel reads its own toggle
|
|
9
|
+
- Stop button now clears crashed processes (dead PIDs) instead of showing stale "running" state
|
|
9
10
|
|
|
10
11
|
## 1.2.0 (2026-03-28)
|
|
11
12
|
|
package/package.json
CHANGED
package/reports/generate-html.js
CHANGED
|
@@ -2162,7 +2162,7 @@ function buildHtmlTemplate(data, opts = {}) {
|
|
|
2162
2162
|
var extra = scope ? { scope: scope } : {};
|
|
2163
2163
|
// Crawl/extract: read stealth toggle + update status bar
|
|
2164
2164
|
if (cmd === 'crawl' || cmd === 'extract') {
|
|
2165
|
-
var stealthEl =
|
|
2165
|
+
var stealthEl = btn.closest('.project-panel')?.querySelector('[id^="stealthToggle"]') || document.getElementById('stealthToggle' + suffix);
|
|
2166
2166
|
if (stealthEl?.checked) extra.stealth = true;
|
|
2167
2167
|
if (window._setButtonsState) window._setButtonsState(true, cmd);
|
|
2168
2168
|
if (window._startPolling) window._startPolling();
|
package/server.js
CHANGED
|
@@ -339,32 +339,39 @@ async function handleRequest(req, res) {
|
|
|
339
339
|
if (req.method === 'POST' && path === '/api/stop') {
|
|
340
340
|
try {
|
|
341
341
|
const progress = readProgress();
|
|
342
|
-
if (!progress ||
|
|
342
|
+
if (!progress || !progress.pid) {
|
|
343
343
|
json(res, 404, { error: 'No running job to stop' });
|
|
344
344
|
return;
|
|
345
345
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
346
|
+
|
|
347
|
+
// Check if process is actually alive
|
|
348
|
+
let isAlive = false;
|
|
349
|
+
try { process.kill(progress.pid, 0); isAlive = true; } catch { isAlive = false; }
|
|
350
|
+
|
|
351
|
+
if (isAlive) {
|
|
352
|
+
try {
|
|
353
|
+
// Graceful: SIGTERM lets the CLI close browsers / write progress
|
|
354
|
+
process.kill(progress.pid, 'SIGTERM');
|
|
355
|
+
// Escalate: SIGKILL after 5s if still alive (stealth browser cleanup needs time)
|
|
356
|
+
setTimeout(() => {
|
|
357
|
+
try { process.kill(progress.pid, 0); } catch { return; } // already dead
|
|
358
|
+
try { process.kill(progress.pid, 'SIGKILL'); } catch {}
|
|
359
|
+
}, 5000);
|
|
360
|
+
} catch (e) {
|
|
361
|
+
if (e.code !== 'ESRCH') throw e;
|
|
362
|
+
}
|
|
357
363
|
}
|
|
358
|
-
|
|
364
|
+
|
|
365
|
+
// Update progress file — clears both running and crashed states
|
|
359
366
|
try {
|
|
360
367
|
writeFileSync(PROGRESS_FILE, JSON.stringify({
|
|
361
368
|
...progress,
|
|
362
|
-
status: 'stopped',
|
|
369
|
+
status: isAlive ? 'stopped' : 'crashed_cleared',
|
|
363
370
|
stopped_at: Date.now(),
|
|
364
371
|
updated_at: Date.now(),
|
|
365
372
|
}, null, 2));
|
|
366
373
|
} catch { /* best-effort */ }
|
|
367
|
-
json(res, 200, { stopped: true, pid: progress.pid, command: progress.command });
|
|
374
|
+
json(res, 200, { stopped: true, pid: progress.pid, command: progress.command, wasAlive: isAlive });
|
|
368
375
|
} catch (e) {
|
|
369
376
|
json(res, 500, { error: e.message });
|
|
370
377
|
}
|