class TerminalConsole extends HTMLElement { constructor() { super(); this.attachShadow({ mode: 'open' }); this.lines = []; this.maxLines = 200; } connectedCallback() { this.render(); this.startSimulation(); } addLine(text, type = 'info') { const colors = { info: '#94a3b8', success: '#10b981', warning: '#f97316', error: '#ef4444', accent: '#3b82f6' }; const time = new Date().toISOString().split('T')[1].split('.')[0]; this.lines.push({ time, text, type, color: colors[type] }); if (this.lines.length > this.maxLines) { this.lines.shift(); } this.updateDisplay(); } updateDisplay() { const container = this.shadowRoot.getElementById('terminal-content'); container.innerHTML = this.lines.map(line => `
[${line.time}] ${line.text}
`).join(''); container.scrollTop = container.scrollHeight; } render() { const height = this.getAttribute('height') || '300px'; this.shadowRoot.innerHTML = `
omniloop@core:~$
`; } startSimulation() { const logTypes = { info: [ 'Starting training batch {batch}...', 'Loading checkpoint from epoch {epoch}', 'Gradient computation complete', 'Optimizer step executed', 'Learning rate adjusted: {lr}', 'Batch {batch} loss: {loss}', 'Validation accuracy: {acc}', 'Saving model checkpoint...', 'Memory usage: {mem}GB', 'GPU utilization: {gpu}%' ], success: [ 'Model checkpoint saved successfully', 'Validation completed: {acc}% accuracy', 'Training batch {batch} completed', 'Gradient clipping applied: {val}', 'Early stopping condition not met' ], warning: [ 'GPU memory usage above 90%', 'Learning rate decay applied', 'Gradient norm exceeded threshold: {norm}', 'Mixed precision enabled', 'Checkpoint file size: {size}GB' ], error: [ 'NaN detected in loss - skipping batch', 'CUDA out of memory - reducing batch size', 'Connection timeout to storage server', 'Invalid tensor shape detected' ], accent: [ '=== Starting Epoch {epoch} ===', '=== Model Architecture ===', '=== Training Configuration ===', '=== Validation Phase ===', '=== Saving Final Model ===' ] }; const formatMessage = (msg) => { return msg .replace('{batch}', Math.floor(Math.random() * 1000 + 1)) .replace('{epoch}', Math.floor(Math.random() * 100 + 1)) .replace('{lr}', (Math.random() * 0.001).toExponential(2)) .replace('{loss}', (Math.random() * 0.5).toFixed(4)) .replace('{acc}', (85 + Math.random() * 14).toFixed(2)) .replace('{mem}', (Math.random() * 32 + 16).toFixed(1)) .replace('{gpu}', Math.floor(Math.random() * 30 + 70)) .replace('{val}', Math.random().toFixed(2)) .replace('{size}', (Math.random() * 5 + 1).toFixed(1)) .replace('{norm}', (Math.random() * 10).toFixed(2)); }; // Initial logs this.addLine('Terminal initialized. Waiting for training output...', 'info'); this.addLine('Connected to training node: gpu-cluster-01', 'success'); this.addLine('', 'info'); // Simulate ongoing logs setInterval(() => { if (Math.random() > 0.3) { const type = Object.keys(logTypes)[Math.floor(Math.random() * 5)]; const messages = logTypes[type]; const message = formatMessage(messages[Math.floor(Math.random() * messages.length)]); this.addLine(message, type); } }, 800); } } customElements.define('terminal-console', TerminalConsole);