mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-12 14:16:28 +03:00
Refresh the Impeccable product experience
Rework the landing page proof, steering demo, feature grid, slop catalog, detector coverage, theming, Live workflow, and responsive behavior.\n\nAI-assisted implementation by OpenAI Codex.
This commit is contained in:
+26
-309
@@ -29,14 +29,11 @@ import {
|
||||
resolveLiveBrowserScriptParts,
|
||||
} from './live/browser-script-parts.mjs';
|
||||
import { createLiveSessionStore } from './live/session-store.mjs';
|
||||
import { runGenerationPreflight } from './live/generation-preflight.mjs';
|
||||
import { validateEvent } from './live/event-validation.mjs';
|
||||
import { selectAvailablePendingEvent } from './live/poll-lanes.mjs';
|
||||
import { createManualEditRoutes } from './live/manual-edit-routes.mjs';
|
||||
import { LIVE_COMMANDS } from './live/vocabulary.mjs';
|
||||
import {
|
||||
getDesignSidecarPath,
|
||||
getLiveCodexWorkerStatePath,
|
||||
getLiveDir,
|
||||
getLiveAnnotationsDir,
|
||||
IMPECCABLE_COMMAND_PREFIX,
|
||||
@@ -54,7 +51,6 @@ import {
|
||||
applyDeferredSvelteComponentAccepts,
|
||||
removeAllSvelteComponentSessions,
|
||||
} from './live/svelte-component.mjs';
|
||||
import { removeAllVueComponentSessions } from './live/vue-component.mjs';
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
// PRODUCT.md / DESIGN.md live wherever context.mjs resolves. The generated
|
||||
@@ -160,135 +156,29 @@ function restorePendingEventsFromStore() {
|
||||
}
|
||||
}
|
||||
|
||||
function findAvailablePendingEvent(now = Date.now(), types = null) {
|
||||
return selectAvailablePendingEvent(state.pendingEvents, { now, types });
|
||||
function findAvailablePendingEvent(now = Date.now()) {
|
||||
for (const entry of state.pendingEvents) {
|
||||
if (entry.leaseUntil && entry.leaseUntil > now) continue;
|
||||
return entry;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function leaseEvent(entry, leaseMs) {
|
||||
prepareGenerateEventForLease(entry);
|
||||
if (!entry.event?.id) {
|
||||
const idx = state.pendingEvents.indexOf(entry);
|
||||
if (idx !== -1) state.pendingEvents.splice(idx, 1);
|
||||
return entry.event;
|
||||
}
|
||||
entry.leaseUntil = Date.now() + leaseMs;
|
||||
recordGenerateDelivery(entry);
|
||||
scheduleLeaseFlush();
|
||||
broadcastAgentPollingIfChanged();
|
||||
return entry.event;
|
||||
}
|
||||
|
||||
function recordGenerateDelivery(entry) {
|
||||
const event = entry?.event;
|
||||
if (!event || event.type !== 'generate' || event.generationReadyAt) return;
|
||||
const at = Date.now();
|
||||
entry.event = { ...event, generationReadyAt: at };
|
||||
state.sessionStore?.appendEvent(entry.event);
|
||||
recordAgentPhase(event.id, 'generation_ready', { at });
|
||||
}
|
||||
|
||||
function prepareGenerateEventForLease(entry) {
|
||||
const event = entry?.event;
|
||||
if (!event || event.type !== 'generate' || event.scaffoldAttempted) return;
|
||||
|
||||
recordAgentPhase(event.id, 'picked_up');
|
||||
recordAgentPhase(event.id, 'scaffolding');
|
||||
const worker = getCodexWorkerStatus();
|
||||
const result = runGenerationPreflight(event, {
|
||||
cwd: process.cwd(),
|
||||
scriptsDir: __dirname,
|
||||
isolated: worker?.mode === 'dedicated-app-server' && worker?.reachable === true,
|
||||
});
|
||||
entry.event = {
|
||||
...event,
|
||||
scaffoldAttempted: true,
|
||||
scaffoldDurationMs: result.durationMs ?? null,
|
||||
...(result.ok ? { scaffold: result.scaffold } : { scaffoldError: result.error || result.reason }),
|
||||
};
|
||||
state.sessionStore?.appendEvent(entry.event);
|
||||
recordAgentPhase(event.id, result.ok ? 'source_ready' : 'scaffold_fallback', {
|
||||
durationMs: result.durationMs ?? null,
|
||||
previewMode: result.scaffold?.previewMode || 'source',
|
||||
});
|
||||
}
|
||||
|
||||
function recordAgentPhase(id, phase, details = {}) {
|
||||
if (!id) return;
|
||||
const event = {
|
||||
type: 'agent_phase',
|
||||
id,
|
||||
phase,
|
||||
at: Date.now(),
|
||||
...details,
|
||||
};
|
||||
state.sessionStore?.appendEvent(event);
|
||||
broadcast(event);
|
||||
}
|
||||
|
||||
function recordGenerationCheckpoint(event) {
|
||||
if (!event?.id || event.type !== 'checkpoint') return;
|
||||
if (generationIsFenced(event.id)) return;
|
||||
const arrived = Number(event.arrivedVariants) || 0;
|
||||
const expected = Number(event.expectedVariants) || 0;
|
||||
if (arrived <= 0 || expected <= 0) return;
|
||||
const previewMode = event.previewMode || 'source';
|
||||
const previewFile = event.previewFile || event.file;
|
||||
if (previewFile) {
|
||||
broadcast({
|
||||
type: 'variant_progress',
|
||||
id: event.id,
|
||||
file: previewFile,
|
||||
sourceFile: event.sourceFile || (previewMode === 'source' ? previewFile : undefined),
|
||||
previewFile,
|
||||
previewMode,
|
||||
arrivedVariants: arrived,
|
||||
expectedVariants: expected,
|
||||
publicationKind: event.publicationKind || 'variants',
|
||||
});
|
||||
}
|
||||
const details = {
|
||||
arrivedVariants: arrived,
|
||||
expectedVariants: expected,
|
||||
checkpointReason: event.reason || null,
|
||||
};
|
||||
const at = Date.now();
|
||||
if (!generationPhaseAlreadyRecorded(event.id, 'first_reviewable')) {
|
||||
recordAgentPhase(event.id, 'first_reviewable', { ...details, at });
|
||||
}
|
||||
if (arrived >= 2 && expected >= 3 && !generationPhaseAlreadyRecorded(event.id, 'second_reviewable')) {
|
||||
recordAgentPhase(event.id, 'second_reviewable', { ...details, at });
|
||||
}
|
||||
if (arrived >= expected && !generationPhaseAlreadyRecorded(event.id, 'all_variants_ready')) {
|
||||
recordAgentPhase(event.id, 'all_variants_ready', { ...details, at });
|
||||
}
|
||||
}
|
||||
|
||||
function generationIsFenced(id) {
|
||||
if (!state.sessionStore || !id) return false;
|
||||
try {
|
||||
const snapshot = state.sessionStore.getSnapshot(id, { includeCompleted: true });
|
||||
return snapshot?.generationCanceled === true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function generationPhaseAlreadyRecorded(id, phase) {
|
||||
if (!state.sessionStore) return false;
|
||||
try {
|
||||
const snapshot = state.sessionStore.getSnapshot(id, { includeCompleted: true });
|
||||
return !!snapshot?.generationTimings?.[phase];
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function acknowledgePendingEvent(id, sourceEventType) {
|
||||
function acknowledgePendingEvent(id) {
|
||||
if (!id) return false;
|
||||
const idx = state.pendingEvents.findIndex((entry) => (
|
||||
entry.event?.id === id
|
||||
&& (!sourceEventType || entry.event?.type === sourceEventType)
|
||||
));
|
||||
const idx = state.pendingEvents.findIndex((entry) => entry.event?.id === id);
|
||||
if (idx === -1) return false;
|
||||
const acknowledged = state.pendingEvents[idx].event;
|
||||
state.pendingEvents.splice(idx, 1);
|
||||
@@ -297,39 +187,9 @@ function acknowledgePendingEvent(id, sourceEventType) {
|
||||
return acknowledged;
|
||||
}
|
||||
|
||||
function releasePendingEvent(id, sourceEventType) {
|
||||
const entry = state.pendingEvents.find((item) => (
|
||||
item.event?.id === id
|
||||
&& (!sourceEventType || item.event?.type === sourceEventType)
|
||||
));
|
||||
if (!entry) return null;
|
||||
entry.leaseUntil = 0;
|
||||
scheduleLeaseFlush();
|
||||
return entry.event;
|
||||
}
|
||||
|
||||
function retirePendingGeneration(id) {
|
||||
if (!id) return 0;
|
||||
let retired = 0;
|
||||
for (let index = state.pendingEvents.length - 1; index >= 0; index -= 1) {
|
||||
const event = state.pendingEvents[index]?.event;
|
||||
if (event?.id !== id || event.type !== 'generate') continue;
|
||||
state.pendingEvents.splice(index, 1);
|
||||
retired += 1;
|
||||
}
|
||||
if (retired > 0) {
|
||||
scheduleLeaseFlush();
|
||||
broadcastAgentPollingIfChanged();
|
||||
}
|
||||
return retired;
|
||||
}
|
||||
|
||||
function findPendingEventById(id, sourceEventType) {
|
||||
function findPendingEventById(id) {
|
||||
if (!id) return null;
|
||||
const entry = state.pendingEvents.find((item) => (
|
||||
item.event?.id === id
|
||||
&& (!sourceEventType || item.event?.type === sourceEventType)
|
||||
));
|
||||
const entry = state.pendingEvents.find((item) => item.event?.id === id);
|
||||
return entry?.event || null;
|
||||
}
|
||||
|
||||
@@ -364,13 +224,7 @@ function summarizeActiveSessionForClient(snapshot = {}) {
|
||||
arrivedVariants: snapshot.arrivedVariants ?? 0,
|
||||
visibleVariant: snapshot.visibleVariant ?? null,
|
||||
checkpointRevision: snapshot.checkpointRevision ?? 0,
|
||||
browserCheckpointRevision: snapshot.browserCheckpointRevision ?? snapshot.checkpointRevision ?? 0,
|
||||
publicationCheckpointRevision: snapshot.publicationCheckpointRevision ?? 0,
|
||||
paramValues: snapshot.paramValues || {},
|
||||
paramsPublished: snapshot.paramsPublished === true,
|
||||
generationPhase: snapshot.generationPhase ?? null,
|
||||
generationCanceled: snapshot.generationCanceled === true,
|
||||
cancelReason: snapshot.cancelReason ?? null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -415,21 +269,13 @@ function scheduleLeaseFlush() {
|
||||
function flushPendingPolls() {
|
||||
let changed = false;
|
||||
while (state.pendingPolls.length > 0) {
|
||||
let pollIndex = -1;
|
||||
let entry = null;
|
||||
for (let index = 0; index < state.pendingPolls.length; index += 1) {
|
||||
const candidate = findAvailablePendingEvent(Date.now(), state.pendingPolls[index].types);
|
||||
if (!candidate) continue;
|
||||
pollIndex = index;
|
||||
entry = candidate;
|
||||
break;
|
||||
}
|
||||
const entry = findAvailablePendingEvent();
|
||||
if (!entry) {
|
||||
scheduleLeaseFlush();
|
||||
broadcastAgentPollingIfChanged();
|
||||
return;
|
||||
}
|
||||
const [poll] = state.pendingPolls.splice(pollIndex, 1);
|
||||
const poll = state.pendingPolls.shift();
|
||||
poll.resolve(leaseEvent(entry, poll.leaseMs));
|
||||
changed = true;
|
||||
}
|
||||
@@ -438,10 +284,9 @@ function flushPendingPolls() {
|
||||
}
|
||||
|
||||
function agentPollingConnected() {
|
||||
// A leased event only proves that a poll returned once. The foreground task
|
||||
// may have ended immediately afterward, so only an actively waiting poll is
|
||||
// evidence that steering can wake the task right now.
|
||||
return state.pendingPolls.length > 0;
|
||||
const now = Date.now();
|
||||
return state.pendingPolls.length > 0
|
||||
|| state.pendingEvents.some((entry) => entry.leaseUntil && entry.leaseUntil > now);
|
||||
}
|
||||
|
||||
function broadcastAgentPollingIfChanged() {
|
||||
@@ -494,58 +339,6 @@ function getManualEditStatus() {
|
||||
}
|
||||
}
|
||||
|
||||
function getCodexWorkerStatus() {
|
||||
let worker;
|
||||
try {
|
||||
worker = JSON.parse(fs.readFileSync(getLiveCodexWorkerStatePath(process.cwd()), 'utf-8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
if (!worker || typeof worker !== 'object') return null;
|
||||
|
||||
const processActive = Number.isInteger(worker.pid) && worker.pid > 0 && pidReachable(worker.pid);
|
||||
const activeStatus = ['starting', 'ready', 'working'].includes(worker.status);
|
||||
const unavailable = activeStatus && !processActive;
|
||||
const error = unavailable ? 'codex_worker_unavailable' : stringOrNull(worker.error);
|
||||
const status = unavailable ? 'unavailable' : stringOrNull(worker.status) || 'unknown';
|
||||
return {
|
||||
status,
|
||||
mode: stringOrNull(worker.mode)
|
||||
|| (activeStatus && processActive ? 'dedicated-app-server' : 'foreground'),
|
||||
reachable: processActive,
|
||||
error,
|
||||
message: worker.error === 'codex_cli_unavailable'
|
||||
? 'Codex CLI not found. Live is using the main agent for generation.'
|
||||
: error
|
||||
? 'Background generation is unavailable. Live is using the main agent.'
|
||||
: null,
|
||||
command: stringOrNull(worker.command),
|
||||
setup: worker.error === 'codex_cli_unavailable' && worker.setup
|
||||
? {
|
||||
docsUrl: stringOrNull(worker.setup.docsUrl),
|
||||
afterInstall: stringOrNull(worker.setup.afterInstall),
|
||||
}
|
||||
: null,
|
||||
model: stringOrNull(worker.model),
|
||||
profile: stringOrNull(worker.profile),
|
||||
delivery: stringOrNull(worker.delivery),
|
||||
updatedAt: stringOrNull(worker.updatedAt),
|
||||
};
|
||||
}
|
||||
|
||||
function stringOrNull(value) {
|
||||
return typeof value === 'string' && value.trim() ? value : null;
|
||||
}
|
||||
|
||||
function pidReachable(pid) {
|
||||
try {
|
||||
process.kill(pid, 0);
|
||||
return true;
|
||||
} catch (error) {
|
||||
return error?.code === 'EPERM';
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Load scripts
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -728,7 +521,6 @@ function createRequestHandler({ detectScript, liveScriptParts }) {
|
||||
connectedClients: state.sseClients.size,
|
||||
pendingEvents: state.pendingEvents.map((entry) => summarizePendingEventForStatus(entry)),
|
||||
agentPolling: agentPollingConnected(),
|
||||
codexWorker: getCodexWorkerStatus(),
|
||||
activeSessions: sessions,
|
||||
manualEdits: getManualEditStatus(),
|
||||
}));
|
||||
@@ -838,7 +630,6 @@ function createRequestHandler({ detectScript, liveScriptParts }) {
|
||||
type: 'connected',
|
||||
hasProjectContext: hasProjectContext(),
|
||||
agentPolling: agentPollingConnected(),
|
||||
codexWorker: getCodexWorkerStatus(),
|
||||
activeSessions: activeSessionSummaries(),
|
||||
}) + '\n\n');
|
||||
|
||||
@@ -898,15 +689,6 @@ function createRequestHandler({ detectScript, liveScriptParts }) {
|
||||
res.end(JSON.stringify({ error }));
|
||||
return;
|
||||
}
|
||||
if (msg.type === 'agent_phase') {
|
||||
recordAgentPhase(msg.id, msg.phase, {
|
||||
...(Number.isFinite(msg.durationMs) ? { durationMs: msg.durationMs } : {}),
|
||||
owner: typeof msg.owner === 'string' ? msg.owner : undefined,
|
||||
});
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: true }));
|
||||
return;
|
||||
}
|
||||
if (state.sessionStore && msg.id) {
|
||||
try {
|
||||
state.sessionStore.appendEvent(msg);
|
||||
@@ -916,10 +698,6 @@ function createRequestHandler({ detectScript, liveScriptParts }) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (msg.type === 'accept' || msg.type === 'discard') {
|
||||
retirePendingGeneration(msg.id);
|
||||
}
|
||||
recordGenerationCheckpoint(msg);
|
||||
if (msg.type === 'exit') {
|
||||
cleanupSvelteComponentSessionsBeforeExit();
|
||||
}
|
||||
@@ -960,12 +738,6 @@ function createRequestHandler({ detectScript, liveScriptParts }) {
|
||||
// Agent poll endpoints (unchanged from WS version)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
function parsePollTypes(value) {
|
||||
if (!value) return null;
|
||||
const types = String(value).split(',').map((type) => type.trim()).filter(Boolean);
|
||||
return types.length > 0 ? new Set(types) : null;
|
||||
}
|
||||
|
||||
function handlePollGet(req, res, url) {
|
||||
const token = url.searchParams.get('token');
|
||||
if (token !== state.token) {
|
||||
@@ -976,14 +748,13 @@ function handlePollGet(req, res, url) {
|
||||
state.lastPollAt = Date.now();
|
||||
const timeout = parseInt(url.searchParams.get('timeout') || DEFAULT_POLL_TIMEOUT, 10);
|
||||
const leaseMs = parseInt(url.searchParams.get('leaseMs') || '30000', 10);
|
||||
const types = parsePollTypes(url.searchParams.get('types'));
|
||||
const available = findAvailablePendingEvent(Date.now(), types);
|
||||
const available = findAvailablePendingEvent();
|
||||
if (available) {
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify(leaseEvent(available, leaseMs)));
|
||||
return;
|
||||
}
|
||||
const poll = { resolve, leaseMs, types };
|
||||
const poll = { resolve, leaseMs };
|
||||
const timer = setTimeout(() => {
|
||||
const idx = state.pendingPolls.indexOf(poll);
|
||||
if (idx !== -1) state.pendingPolls.splice(idx, 1);
|
||||
@@ -1012,20 +783,12 @@ function sessionFileMetadataFromPollReply(file) {
|
||||
if (!file || typeof file !== 'string') return { file };
|
||||
const normalized = file.split(path.sep).join('/');
|
||||
const base = { file: normalized };
|
||||
const sourceArtifactPreview = normalized.includes('.impeccable/live/previews/')
|
||||
&& !normalized.endsWith('/manifest.json');
|
||||
const metadataFile = sourceArtifactPreview
|
||||
? normalized.slice(0, normalized.lastIndexOf('/') + 1) + 'manifest.json'
|
||||
: normalized;
|
||||
if (!metadataFile.endsWith('/manifest.json') && metadataFile !== 'manifest.json') return base;
|
||||
if (!metadataFile.includes('node_modules/.impeccable-live/')
|
||||
&& !metadataFile.includes('src/lib/impeccable/')
|
||||
&& !metadataFile.includes('/.impeccable-live/')
|
||||
&& !metadataFile.includes('.impeccable/live/previews/')) return base;
|
||||
if (!normalized.endsWith('/manifest.json') && normalized !== 'manifest.json') return base;
|
||||
if (!normalized.includes('node_modules/.impeccable-live/') && !normalized.includes('src/lib/impeccable/')) return base;
|
||||
|
||||
let full;
|
||||
try {
|
||||
full = path.resolve(process.cwd(), metadataFile);
|
||||
full = path.resolve(process.cwd(), normalized);
|
||||
const rel = path.relative(process.cwd(), full);
|
||||
if (!rel || rel.startsWith('..') || path.isAbsolute(rel)) return base;
|
||||
} catch {
|
||||
@@ -1034,40 +797,18 @@ function sessionFileMetadataFromPollReply(file) {
|
||||
|
||||
try {
|
||||
const manifest = JSON.parse(fs.readFileSync(full, 'utf-8'));
|
||||
if (!['svelte-component', 'vue-component', 'source-artifact'].includes(manifest?.previewMode)
|
||||
|| !manifest.sourceFile) return base;
|
||||
const previewFile = manifest.previewMode === 'source-artifact'
|
||||
? String(manifest.previewFile || normalized).split(path.sep).join('/')
|
||||
: normalized;
|
||||
if (manifest?.previewMode !== 'svelte-component' || !manifest.sourceFile) return base;
|
||||
return {
|
||||
file: String(manifest.sourceFile).split(path.sep).join('/'),
|
||||
sourceFile: String(manifest.sourceFile).split(path.sep).join('/'),
|
||||
previewFile,
|
||||
previewMode: manifest.previewMode,
|
||||
previewFile: normalized,
|
||||
previewMode: 'svelte-component',
|
||||
};
|
||||
} catch {
|
||||
return base;
|
||||
}
|
||||
}
|
||||
|
||||
function inferSourceEventType(msg = {}, pendingEvents = state.pendingEvents) {
|
||||
const pendingTypes = new Set(
|
||||
pendingEvents
|
||||
.filter((entry) => entry.event?.id === msg.id)
|
||||
.map((entry) => entry.event?.type),
|
||||
);
|
||||
if (msg.type === 'discarded' || msg.type === 'discard') return 'discard';
|
||||
if (msg.type === 'complete') {
|
||||
if (pendingTypes.has('carbonize_cleanup')) return 'carbonize_cleanup';
|
||||
return pendingTypes.has('accept') ? 'accept' : (pendingTypes.has('generate') ? 'generate' : undefined);
|
||||
}
|
||||
if (msg.type === 'steer_done') return 'steer';
|
||||
// `agent_done` can be the automatic acknowledgement for a carbonize Accept.
|
||||
// New pollers send sourceEventType explicitly; default to generate only for
|
||||
// older callers so a late worker cannot acknowledge a queued Accept.
|
||||
return msg.type === 'agent_done' || msg.type === 'done' ? 'generate' : undefined;
|
||||
}
|
||||
|
||||
function handlePollPost(req, res) {
|
||||
let body = '';
|
||||
req.on('data', (c) => { body += c; });
|
||||
@@ -1128,23 +869,7 @@ function handlePollPost(req, res) {
|
||||
res.end(JSON.stringify({ error: 'stale_manual_edit_apply_reply', ...rollback }));
|
||||
return;
|
||||
}
|
||||
const sourceEventType = msg.sourceEventType || inferSourceEventType(msg);
|
||||
if (msg.type === 'retry') {
|
||||
const releasedEvent = releasePendingEvent(msg.id, sourceEventType);
|
||||
if (!releasedEvent) {
|
||||
res.writeHead(msg.id ? 404 : 400, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({
|
||||
error: msg.id ? 'unknown_poll_retry_id' : 'missing_poll_retry_id',
|
||||
id: msg.id,
|
||||
}));
|
||||
return;
|
||||
}
|
||||
flushPendingPolls();
|
||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||
res.end(JSON.stringify({ ok: true, released: true }));
|
||||
return;
|
||||
}
|
||||
const pendingEventBeforeAck = findPendingEventById(msg.id, sourceEventType);
|
||||
const pendingEventBeforeAck = findPendingEventById(msg.id);
|
||||
if (pendingEventBeforeAck?.type === 'steer' && msg.type === 'steer_done'
|
||||
&& !msg.file && !(typeof msg.message === 'string' && msg.message.trim())) {
|
||||
res.writeHead(400, { 'Content-Type': 'application/json' });
|
||||
@@ -1154,7 +879,7 @@ function handlePollPost(req, res) {
|
||||
}));
|
||||
return;
|
||||
}
|
||||
const acknowledgedEvent = acknowledgePendingEvent(msg.id, sourceEventType);
|
||||
const acknowledgedEvent = acknowledgePendingEvent(msg.id);
|
||||
let skipJournalReply = false;
|
||||
let existingSession = null;
|
||||
if (!acknowledgedEvent && state.sessionStore && msg.id) {
|
||||
@@ -1246,11 +971,6 @@ function cleanupSvelteComponentSessionsBeforeExit() {
|
||||
} catch (err) {
|
||||
console.warn('[impeccable] Svelte component session cleanup failed:', err.message);
|
||||
}
|
||||
try {
|
||||
removeAllVueComponentSessions(process.cwd());
|
||||
} catch (err) {
|
||||
console.warn('[impeccable] Vue component session cleanup failed:', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
function applyLegacyDeferredAcceptsOnStartup() {
|
||||
@@ -1363,10 +1083,7 @@ if (args.includes('--background')) {
|
||||
process.exit(0);
|
||||
}
|
||||
} catch { /* not ready yet */ }
|
||||
// The detached child is typically listening in 35-45ms. A 200ms polling
|
||||
// floor dominated configured cold Live startup; poll cheaply and return
|
||||
// as soon as the child has written its ready record.
|
||||
await new Promise(r => setTimeout(r, 5));
|
||||
await new Promise(r => setTimeout(r, 200));
|
||||
}
|
||||
console.error('Timed out waiting for live server to start.');
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user