diff --git a/.agents/skills/impeccable/scripts/live-browser.js b/.agents/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.agents/skills/impeccable/scripts/live-browser.js +++ b/.agents/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.claude/skills/impeccable/scripts/live-browser.js b/.claude/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.claude/skills/impeccable/scripts/live-browser.js +++ b/.claude/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.codex/skills/impeccable/scripts/live-browser.js b/.codex/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.codex/skills/impeccable/scripts/live-browser.js +++ b/.codex/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.cursor/skills/impeccable/scripts/live-browser.js b/.cursor/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.cursor/skills/impeccable/scripts/live-browser.js +++ b/.cursor/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.gemini/skills/impeccable/scripts/live-browser.js b/.gemini/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.gemini/skills/impeccable/scripts/live-browser.js +++ b/.gemini/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.kiro/skills/impeccable/scripts/live-browser.js b/.kiro/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.kiro/skills/impeccable/scripts/live-browser.js +++ b/.kiro/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.opencode/skills/impeccable/scripts/live-browser.js b/.opencode/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.opencode/skills/impeccable/scripts/live-browser.js +++ b/.opencode/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.pi/skills/impeccable/scripts/live-browser.js b/.pi/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.pi/skills/impeccable/scripts/live-browser.js +++ b/.pi/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.rovodev/skills/impeccable/scripts/live-browser.js b/.rovodev/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.rovodev/skills/impeccable/scripts/live-browser.js +++ b/.rovodev/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.trae-cn/skills/impeccable/scripts/live-browser.js b/.trae-cn/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.trae-cn/skills/impeccable/scripts/live-browser.js +++ b/.trae-cn/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/.trae/skills/impeccable/scripts/live-browser.js b/.trae/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/.trae/skills/impeccable/scripts/live-browser.js +++ b/.trae/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/bin/cli.js b/bin/cli.js index b3aa1f37c..881f964f8 100755 --- a/bin/cli.js +++ b/bin/cli.js @@ -5,8 +5,6 @@ * * Usage: * npx impeccable detect [file-or-dir-or-url...] - * npx impeccable live [--port=PORT] - * npx impeccable live stop * npx impeccable skills help|install|update * npx impeccable --help */ @@ -24,11 +22,6 @@ if (!command || command === '--help' || command === '-h') { Commands: detect [file-or-dir-or-url...] Scan for UI anti-patterns and design quality issues - live [--port=PORT] Start live variant server (element picker + variant cycling) - live stop Stop a running live server - poll Wait for a browser event from the live server - poll --reply Reply to a pending event (done, error) - wrap --id ID --count N --query Q Find element in source and create variant wrapper skills help List all available skills and commands skills install Install impeccable skills into your project skills update Update skills to the latest version @@ -52,18 +45,6 @@ if (command === 'detect') { process.argv = [process.argv[0], process.argv[1], ...args.slice(1)]; const { detectCli } = await import('../src/detect-antipatterns.mjs'); await detectCli(); -} else if (command === 'live') { - // Delegate to the self-contained skill script (also works via node scripts_path/live-server.mjs) - process.argv = [process.argv[0], process.argv[1], ...args.slice(1)]; - await import('../source/skills/impeccable/scripts/live-server.mjs'); -} else if (command === 'poll') { - process.argv = [process.argv[0], process.argv[1], ...args.slice(1)]; - const { pollCli } = await import('../source/skills/impeccable/scripts/live-poll.mjs'); - await pollCli(); -} else if (command === 'wrap') { - process.argv = [process.argv[0], process.argv[1], ...args.slice(1)]; - const { wrapCli } = await import('../source/skills/impeccable/scripts/live-wrap.mjs'); - await wrapCli(); } else if (command === 'skills') { const { run } = await import('./commands/skills.mjs'); await run(args.slice(1)); diff --git a/source/skills/impeccable/scripts/live-browser.js b/source/skills/impeccable/scripts/live-browser.js index 7a26c9829..72534661b 100644 --- a/source/skills/impeccable/scripts/live-browser.js +++ b/source/skills/impeccable/scripts/live-browser.js @@ -870,11 +870,14 @@ // --------------------------------------------------------------------------- let evtSource = null; + let sseRetries = 0; + const SSE_MAX_RETRIES = 5; function connectSSE() { evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN); evtSource.onmessage = (e) => { + sseRetries = 0; // reset on any successful message let msg; try { msg = JSON.parse(e.data); } catch { return; } switch (msg.type) { case 'connected': @@ -918,11 +921,35 @@ }; evtSource.onerror = () => { - // EventSource auto-reconnects. Log once. - console.log('[impeccable] SSE connection lost. Reconnecting...'); + sseRetries++; + if (sseRetries <= SSE_MAX_RETRIES) { + console.log('[impeccable] SSE connection lost. Retry ' + sseRetries + '/' + SSE_MAX_RETRIES + '...'); + return; // EventSource auto-reconnects + } + // Server is gone. Clean up gracefully. + console.log('[impeccable] Live server unreachable. Cleaning up UI.'); + evtSource.close(); + evtSource = null; + handleServerLost(); }; } + /** Server died or became unreachable. Reset UI to a clean state. */ + function handleServerLost() { + if (state === 'GENERATING' || state === 'CYCLING' || state === 'SAVING') { + showToast('Live server disconnected. Session ended.', 5000); + } + hideBar(); + hideHighlight(); + stopScrollTracking(); + if (variantObserver) { variantObserver.disconnect(); variantObserver = null; } + clearSession(); + selectedElement = null; + currentSessionId = null; + selectedAction = 'impeccable'; + state = 'IDLE'; + } + function sendEvent(msg) { msg.token = TOKEN; fetch('http://localhost:' + PORT + '/events', { diff --git a/src/detect-antipatterns.mjs b/src/detect-antipatterns.mjs index b0d861ac3..8c4a22a15 100644 --- a/src/detect-antipatterns.mjs +++ b/src/detect-antipatterns.mjs @@ -3442,15 +3442,6 @@ async function main() { process.exit(0); } -// --------------------------------------------------------------------------- -// Live detection server -// --------------------------------------------------------------------------- - -async function liveCli() { - const { startLiveServer } = await import('./live/server.mjs'); - await startLiveServer(); -} - // --------------------------------------------------------------------------- // Entry point // --------------------------------------------------------------------------- @@ -3475,7 +3466,6 @@ export { buildImportGraph, resolveImport, detectFrameworkConfig, isPortListening, FRAMEWORK_CONFIGS, main as detectCli, - liveCli, }; // @browser-strip-end diff --git a/src/live/browser.js b/src/live/browser.js deleted file mode 100644 index 7a26c9829..000000000 --- a/src/live/browser.js +++ /dev/null @@ -1,1220 +0,0 @@ -/** - * Impeccable Live Variant Mode — Browser Script - * - * Injected into the user's page via