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 = `
`;
}
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);