/** * Compile Error Accumulator * * Module-level store for compilation errors (Handlebars and esbuild) detected by VirtualServer. * VirtualServer pushes errors during compileProject(); the `build` shell command drains them * to give the AI explicit compilation feedback. * * Errors are collated per compilation: each compileProject() call replaces the * previous set so `build` always sees the latest state. */ export interface CompileError { file: string; error: string; } let pendingErrors: CompileError[] = []; let stagingErrors: CompileError[] = []; /** * Called at the start of compileProject() to begin a fresh error collection. */ export function beginCompilation(): void { stagingErrors = []; } /** * Called during compilation when an error is caught. * Errors accumulate in staging during a single compilation. */ export function pushCompileError(file: string, error: string): void { stagingErrors.push({ file, error }); } /** * Called at the end of compileProject() to commit staged errors. * Replaces any previous pending errors (only latest compilation matters). */ export function commitCompilation(): void { pendingErrors = stagingErrors; stagingErrors = []; // Notify listeners (console panel, orchestrator sync) about compilation result if (typeof window !== 'undefined') { window.dispatchEvent(new CustomEvent('compilationComplete', { detail: { errors: [...pendingErrors], success: pendingErrors.length === 0, timestamp: Date.now(), }, })); } } /** * Called by the `build` shell command to consume accumulated errors. * Returns all errors and clears the buffer. */ export function drainCompileErrors(): CompileError[] { const errors = pendingErrors; pendingErrors = []; return errors; } /** * Format drained errors into a message suitable for the LLM. */ export function formatCompileErrors(errors: CompileError[]): string { const grouped = new Map(); for (const { file, error } of errors) { const list = grouped.get(file) || []; list.push(error); grouped.set(file, list); } const parts: string[] = []; for (const [file, errs] of grouped) { parts.push(`${file}:\n${errs.map(e => ` - ${e}`).join('\n')}`); } const hasEsbuildErrors = errors.some(e => e.error.startsWith('[esbuild]')); const hasScriptErrors = errors.some(e => e.file === 'script' || e.file.endsWith('.py') || e.file.endsWith('.lua')); const prefix = hasScriptErrors ? 'Runtime errors detected during script execution. Fix these issues:\n\n' : hasEsbuildErrors ? 'Build errors detected during compilation. Fix these issues:\n\n' : 'The preview detected possible Handlebars template issues after compilation. Verify whether these are still present — they may already be resolved by recent edits:\n\n'; return `${prefix}${parts.join('\n\n')}`; }