mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-17 08:36:25 +03:00
Add ADR for live variant mode architecture
Comprehensive architecture decision record covering the live variant mode: context, key decisions (source modification over DOM patching, SSE over WebSocket, self-contained skill scripts, HTTP long-poll for agent), full architecture diagram with message flows, variant wrapper format, browser UI states, session persistence, security model, server resilience, performance optimizations, test coverage, known limitations, and future work. Also picks up improvements from parallel thread: poll timeout bumped to 10 min, SSE heartbeat every 30s, and other minor fixes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
59bb3d35a5
commit
9b573de1fb
@@ -874,11 +874,15 @@
|
||||
|
||||
let evtSource = null;
|
||||
let sseRetries = 0;
|
||||
const SSE_MAX_RETRIES = 5;
|
||||
const SSE_MAX_RETRIES = 20; // generous: heartbeats keep the connection alive, so retries mean real trouble
|
||||
|
||||
function connectSSE() {
|
||||
evtSource = new EventSource('http://localhost:' + PORT + '/events?token=' + TOKEN);
|
||||
|
||||
evtSource.onopen = () => {
|
||||
sseRetries = 0; // reset on successful (re)connect
|
||||
};
|
||||
|
||||
evtSource.onmessage = (e) => {
|
||||
sseRetries = 0; // reset on any successful message
|
||||
let msg; try { msg = JSON.parse(e.data); } catch { return; }
|
||||
|
||||
@@ -93,7 +93,7 @@ Options:
|
||||
|
||||
// Poll mode: block until browser event
|
||||
const timeoutArg = args.find(a => a.startsWith('--timeout='));
|
||||
const timeout = timeoutArg ? parseInt(timeoutArg.split('=')[1], 10) : 120000;
|
||||
const timeout = timeoutArg ? parseInt(timeoutArg.split('=')[1], 10) : 600000;
|
||||
|
||||
try {
|
||||
const res = await fetch(`${base}/poll?token=${info.token}&timeout=${timeout}`);
|
||||
|
||||
@@ -24,7 +24,8 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
// PID file in the project root so both the server and agent can find it
|
||||
// predictably (os.tmpdir() varies across platforms).
|
||||
const LIVE_PID_FILE = path.join(process.cwd(), '.impeccable-live.json');
|
||||
const DEFAULT_POLL_TIMEOUT = 120_000;
|
||||
const DEFAULT_POLL_TIMEOUT = 600_000; // 10 min — agent re-polls on timeout anyway
|
||||
const SSE_HEARTBEAT_INTERVAL = 30_000; // keepalive ping every 30s
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Port detection
|
||||
@@ -206,7 +207,13 @@ function createRequestHandler({ detectScript, liveScriptWithToken }) {
|
||||
state.sseClients.add(res);
|
||||
clearTimeout(state.exitTimer);
|
||||
|
||||
// Keepalive: SSE comment every 30s prevents silent connection drops.
|
||||
const heartbeat = setInterval(() => {
|
||||
try { res.write(': keepalive\n\n'); } catch { clearInterval(heartbeat); }
|
||||
}, SSE_HEARTBEAT_INTERVAL);
|
||||
|
||||
req.on('close', () => {
|
||||
clearInterval(heartbeat);
|
||||
state.sseClients.delete(res);
|
||||
if (state.sseClients.size === 0) {
|
||||
clearTimeout(state.exitTimer);
|
||||
|
||||
Reference in New Issue
Block a user