// Dashboard Core Functionality class TetoDashboard { constructor() { this.currentTab = 'overview'; this.thoughtStream = []; this.isSimulating = false; this.memoryVisualization = null; this.init(); } init() { this.initNavigation(); this.initThoughtStream(); this.initMemoryExplorer(); this.startSystemMonitoring(); this.setupEventHandlers(); console.log('🧠 Teto Dashboard initialized'); } // Navigation System initNavigation() { const navItems = document.querySelectorAll('.nav-item'); const tabContents = document.querySelectorAll('.tab-content'); navItems.forEach(item => { item.addEventListener('click', () => { const tabId = item.getAttribute('data-tab'); // Update navigation navItems.forEach(nav => nav.classList.remove('active')); item.classList.add('active'); // Update content tabContents.forEach(content => content.classList.remove('active')); const targetTab = document.getElementById(`tab-${tabId}`); if (targetTab) { targetTab.classList.add('active'); this.currentTab = tabId; this.onTabChange(tabId); } }); }); } onTabChange(tabId) { switch(tabId) { case 'memory': // Small delay to ensure DOM is ready setTimeout(() => { this.initMemoryVisualization(); }, 100); break; case 'analytics': this.loadAnalytics(); break; case 'archives': this.loadArchives(); break; case 'profile': this.loadProfile(); break; } // Trigger synapse animation window.synapseSystem?.onTabChange(tabId); } // Live Thought Stream initThoughtStream() { this.thoughtContainer = document.getElementById('thought-stream'); this.startThoughtGeneration(); } startThoughtGeneration() { const thoughts = [ "Analyzing incoming Discord message...", "Context: User Alice mentioned 'French bread' again", "Retrieving personality traits: slightly sassy, loves French bread", "Checking conversation history for similar topics...", "Found 12 previous mentions of French bread preferences", "Generating response with 73% sass level", "Processing voice modulation parameters...", "Response crafted: 'Mon dieu, Alice! How many times must I say it?'", "Executing text-to-speech conversion...", "Message delivered to #general channel", "Monitoring user reactions and engagement...", "Alice reacted with 😄 - response was well received", "Updating conversation context in vector database...", "Learning: Alice enjoys my French bread jokes", "Memory consolidation complete", ]; let thoughtIndex = 0; const addThought = () => { if (this.thoughtContainer) { const timestamp = new Date().toLocaleTimeString(); const thought = thoughts[thoughtIndex % thoughts.length]; const thoughtElement = document.createElement('div'); thoughtElement.className = 'thought-line'; thoughtElement.innerHTML = `[${timestamp}] ${thought}`; this.thoughtContainer.appendChild(thoughtElement); this.thoughtContainer.scrollTop = this.thoughtContainer.scrollHeight; // Remove old thoughts to prevent memory buildup const maxThoughts = 50; if (this.thoughtContainer.children.length > maxThoughts) { this.thoughtContainer.removeChild(this.thoughtContainer.firstChild); } thoughtIndex++; } }; // Add initial thoughts for (let i = 0; i < 5; i++) { setTimeout(() => addThought(), i * 1000); } // Continue adding thoughts periodically setInterval(addThought, 3000 + Math.random() * 2000); } // Memory Explorer with 3D Visualization initMemoryExplorer() { // This will be expanded when the memory tab is accessed this.memoryPoints = this.generateMemoryData(); } initMemoryVisualization() { if (this.memoryVisualization) return; const container = document.getElementById('memory-3d'); if (!container) return; // Create Three.js scene const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, container.offsetWidth / container.offsetHeight, 0.1, 1000); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }); renderer.setSize(container.offsetWidth, container.offsetHeight); renderer.setClearColor(0x000000, 0); container.appendChild(renderer.domElement); // Create memory point cloud const geometry = new THREE.BufferGeometry(); const positions = []; const colors = []; const sizes = []; const colorPalette = { historical: new THREE.Color(0x6b7280), knowledge: new THREE.Color(0x3b82f6), textChat: new THREE.Color(0x10b981), voiceChat: new THREE.Color(0x8b5cf6), images: new THREE.Color(0xef4444), dms: new THREE.Color(0xeab308) }; // Generate memory points if not already generated if (!this.memoryPoints || this.memoryPoints.length === 0) { this.memoryPoints = this.generateMemoryData(); } this.memoryPoints.forEach(point => { positions.push(point.x, point.y, point.z); const color = colorPalette[point.type] || colorPalette.knowledge; colors.push(color.r, color.g, color.b); sizes.push(Math.random() * 3 + 2); }); geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3)); geometry.setAttribute('size', new THREE.Float32BufferAttribute(sizes, 1)); const material = new THREE.ShaderMaterial({ vertexShader: ` attribute float size; varying vec3 vColor; void main() { vColor = color; vec4 mvPosition = modelViewMatrix * vec4(position, 1.0); gl_PointSize = size * (300.0 / -mvPosition.z); gl_Position = projectionMatrix * mvPosition; } `, fragmentShader: ` varying vec3 vColor; void main() { float distance = length(gl_PointCoord - vec2(0.5)); if (distance > 0.5) discard; float alpha = 1.0 - distance * 2.0; gl_FragColor = vec4(vColor, alpha * 0.8); } `, vertexColors: true, transparent: true, blending: THREE.AdditiveBlending }); const points = new THREE.Points(geometry, material); scene.add(points); camera.position.set(0, 0, 50); // Animation loop const animate = () => { if (!this.memoryVisualization || !container.contains(renderer.domElement)) { return; // Stop animation if visualization is destroyed } requestAnimationFrame(animate); points.rotation.x += 0.001; points.rotation.y += 0.002; renderer.render(scene, camera); }; animate(); // Mouse interaction let mouseDown = false; let mouseX = 0; let mouseY = 0; const onMouseDown = (e) => { mouseDown = true; mouseX = e.clientX; mouseY = e.clientY; }; const onMouseMove = (e) => { if (!mouseDown) return; const deltaX = e.clientX - mouseX; const deltaY = e.clientY - mouseY; points.rotation.y += deltaX * 0.005; points.rotation.x += deltaY * 0.005; mouseX = e.clientX; mouseY = e.clientY; }; const onMouseUp = () => { mouseDown = false; }; const onWheel = (e) => { e.preventDefault(); camera.position.z += e.deltaY * 0.1; camera.position.z = Math.max(10, Math.min(200, camera.position.z)); }; container.addEventListener('mousedown', onMouseDown); container.addEventListener('mousemove', onMouseMove); container.addEventListener('mouseup', onMouseUp); container.addEventListener('wheel', onWheel); // Handle resize const handleResize = () => { if (container.offsetWidth > 0 && container.offsetHeight > 0) { camera.aspect = container.offsetWidth / container.offsetHeight; camera.updateProjectionMatrix(); renderer.setSize(container.offsetWidth, container.offsetHeight); } }; window.addEventListener('resize', handleResize); this.memoryVisualization = { scene, camera, renderer, points, container, cleanup: () => { container.removeEventListener('mousedown', onMouseDown); container.removeEventListener('mousemove', onMouseMove); container.removeEventListener('mouseup', onMouseUp); container.removeEventListener('wheel', onWheel); window.removeEventListener('resize', handleResize); if (container.contains(renderer.domElement)) { container.removeChild(renderer.domElement); } renderer.dispose(); geometry.dispose(); material.dispose(); } }; // Trigger initial render renderer.render(scene, camera); console.log('✨ Memory visualization initialized with', this.memoryPoints.length, 'points'); } generateMemoryData() { const points = []; const types = ['historical', 'knowledge', 'textChat', 'voiceChat', 'images', 'dms']; for (let i = 0; i < 1000; i++) { points.push({ x: (Math.random() - 0.5) * 100, y: (Math.random() - 0.5) * 100, z: (Math.random() - 0.5) * 100, type: types[Math.floor(Math.random() * types.length)], content: `Memory point ${i}`, timestamp: new Date(Date.now() - Math.random() * 30 * 24 * 60 * 60 * 1000) }); } return points; } // System Monitoring startSystemMonitoring() { this.updateMetrics(); this.initializeShutdownTimer(); setInterval(() => this.updateMetrics(), 5000); setInterval(() => this.updateShutdownTimer(), 60000); // Update every minute } updateMetrics() { // Simulate changing metrics const memoryUsage = 85 + Math.random() * 15; const vramUsage = 60 + Math.random() * 25; // Simulate response time components (should add up to total) const inputProcessing = 2 + Math.random() * 3; const memoryRetrieval = 5 + Math.random() * 8; const neuralProcessing = 7 + Math.random() * 10; const responseGeneration = 2 + Math.random() * 4; const totalResponseTime = inputProcessing + memoryRetrieval + neuralProcessing + responseGeneration; const memoryBar = document.querySelector('.metric-fill:not(.vram):not(.shutdown-fill)'); const vramBar = document.querySelector('.metric-fill.vram'); if (memoryBar) { memoryBar.style.width = `${memoryUsage}%`; memoryBar.parentElement.parentElement.querySelector('.metric-value').textContent = `${Math.round(memoryUsage)}%`; const memoryDetails = memoryBar.parentElement.parentElement.querySelector('.metric-details'); if (memoryDetails) { memoryDetails.textContent = `RAM: ${(memoryUsage * 0.08).toFixed(1)}GB / 8GB`; } } if (vramBar) { vramBar.style.width = `${vramUsage}%`; vramBar.parentElement.parentElement.querySelector('.metric-value').textContent = `${Math.round(vramUsage)}%`; const vramDetails = vramBar.parentElement.parentElement.querySelector('.metric-details'); if (vramDetails) { vramDetails.textContent = `VRAM: ${(vramUsage * 0.08).toFixed(1)}GB / 8GB`; } } // Update response time breakdown const responseMetric = document.querySelector('.response-metric .metric-value'); if (responseMetric) { responseMetric.textContent = `${Math.round(totalResponseTime)}ms`; } const breakdownItems = document.querySelectorAll('.breakdown-item'); const values = [inputProcessing, memoryRetrieval, neuralProcessing, responseGeneration]; const colors = ['#3b82f6', '#10b981', '#8b5cf6', '#ef4444']; breakdownItems.forEach((item, index) => { const value = values[index]; const percentage = (value / totalResponseTime) * 100; const valueElement = item.querySelector('.breakdown-value'); const fillElement = item.querySelector('.breakdown-fill'); if (valueElement) { valueElement.textContent = `${Math.round(value)}ms`; } if (fillElement) { fillElement.style.width = `${percentage}%`; fillElement.style.background = colors[index]; } }); } initializeShutdownTimer() { // Set shutdown time to 3 days from now this.shutdownTime = new Date(Date.now() + (3 * 24 * 60 * 60 * 1000)); // 3 days this.totalSessionTime = 7 * 24 * 60 * 60 * 1000; // 7 days total session this.updateShutdownTimer(); } updateShutdownTimer() { const now = new Date(); const timeLeft = this.shutdownTime - now; const timerElement = document.getElementById('shutdown-timer'); const progressElement = document.querySelector('.shutdown-fill'); if (timeLeft <= 0) { if (timerElement) timerElement.textContent = 'OFFLINE'; if (progressElement) progressElement.style.width = '100%'; return; } // Calculate days, hours, minutes const days = Math.floor(timeLeft / (24 * 60 * 60 * 1000)); const hours = Math.floor((timeLeft % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000)); const minutes = Math.floor((timeLeft % (60 * 60 * 1000)) / (60 * 1000)); let displayText = ''; if (days > 0) { displayText = `${days}d ${hours}h`; } else if (hours > 0) { displayText = `${hours}h ${minutes}m`; } else { displayText = `${minutes}m`; } if (timerElement) { timerElement.textContent = displayText; } // Update progress bar (session elapsed time) const sessionElapsed = this.totalSessionTime - timeLeft; const progressPercent = (sessionElapsed / this.totalSessionTime) * 100; if (progressElement) { progressElement.style.width = `${Math.max(0, Math.min(100, progressPercent))}%`; } // Update shutdown details const shutdownDetails = document.querySelector('.shutdown-details'); if (shutdownDetails) { const options = { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }; shutdownDetails.textContent = `Session ends: ${this.shutdownTime.toLocaleDateString('en-US', options)}`; } } // Load other tab content loadAnalytics() { console.log('Loading analytics data...'); this.generateActivityHeatmap(); this.animateAnalyticsCharts(); } loadArchives() { console.log('Loading archives data...'); this.setupArchiveBrowser(); } generateActivityHeatmap() { const heatmapContainer = document.getElementById('activity-heatmap'); if (!heatmapContainer) return; // Clear existing cells heatmapContainer.innerHTML = ''; // Generate 24 hour cells (representing hours of the day) for (let hour = 0; hour < 24; hour++) { const cell = document.createElement('div'); cell.className = 'heatmap-cell'; // Simulate activity intensity (higher during typical active hours) let intensity = 0.1; if (hour >= 8 && hour <= 10) intensity = 0.6; // Morning if (hour >= 12 && hour <= 14) intensity = 0.4; // Lunch if (hour >= 18 && hour <= 23) intensity = 0.8; // Evening if (hour >= 20 && hour <= 22) intensity = 1.0; // Peak evening // Add some randomness intensity += (Math.random() - 0.5) * 0.3; intensity = Math.max(0.1, Math.min(1, intensity)); const opacity = intensity; cell.style.backgroundColor = `rgba(229, 62, 62, ${opacity})`; // Add tooltip cell.title = `${hour}:00 - Activity level: ${Math.round(intensity * 100)}%`; heatmapContainer.appendChild(cell); } } animateAnalyticsCharts() { // Animate progress bars with delay setTimeout(() => { const bars = document.querySelectorAll('.bar-fill, .lang-fill'); bars.forEach((bar, index) => { setTimeout(() => { const targetWidth = bar.style.width; bar.style.width = '0%'; setTimeout(() => { bar.style.width = targetWidth; }, 100); }, index * 200); }); }, 300); } setupArchiveBrowser() { const archiveItems = document.querySelectorAll('.archive-item'); const archiveDisplays = document.querySelectorAll('.archive-display'); const placeholder = document.querySelector('.archive-placeholder'); archiveItems.forEach(item => { item.addEventListener('click', () => { // Remove active class from all items archiveItems.forEach(i => i.classList.remove('active')); item.classList.add('active'); // Hide placeholder and all displays if (placeholder) placeholder.style.display = 'none'; archiveDisplays.forEach(display => display.classList.add('hidden')); // Show selected archive const archiveId = item.getAttribute('data-archive'); const targetDisplay = document.getElementById(`archive-${archiveId}`); if (targetDisplay) { targetDisplay.classList.remove('hidden'); } }); }); // Setup voice player interactions this.setupVoicePlayer(); } setupVoicePlayer() { const playBtn = document.querySelector('.play-btn'); const progressFill = document.querySelector('.progress-fill'); const timeDisplay = document.querySelector('.time-display'); if (playBtn) { let isPlaying = false; let progress = 0.23; // Current position (23%) playBtn.addEventListener('click', () => { isPlaying = !isPlaying; playBtn.textContent = isPlaying ? '⏸️' : '▶️'; if (isPlaying) { // Simulate playback progress const interval = setInterval(() => { if (!isPlaying) { clearInterval(interval); return; } progress += 0.002; if (progress >= 1) { progress = 1; isPlaying = false; playBtn.textContent = '▶️'; clearInterval(interval); } if (progressFill) { progressFill.style.width = `${progress * 100}%`; } if (timeDisplay) { const currentMinutes = Math.floor(progress * 84.55); // 1h 24m 33s = 84.55 minutes const currentSeconds = Math.floor((progress * 84.55 * 60) % 60); timeDisplay.textContent = `${currentMinutes}:${currentSeconds.toString().padStart(2, '0')} / 1:24:33`; } }, 100); } }); } } loadProfile() { // Implement profile loading console.log('Loading profile data...'); } setupEventHandlers() { // Add various event handlers for interactivity document.addEventListener('keydown', (e) => { if (e.key === 'Tab') { // Cycle through tabs with Tab key e.preventDefault(); const navItems = document.querySelectorAll('.nav-item'); const currentIndex = Array.from(navItems).findIndex(item => item.classList.contains('active')); const nextIndex = (currentIndex + 1) % navItems.length; navItems[nextIndex].click(); } }); } // Public methods for synapse system triggerNeuralActivity(type = 'general') { const activityTypes = { input: ['reading', 'processing'], memory: ['fetching', 'remembering'], output: ['writing', 'speaking'], general: ['reading', 'fetching', 'reasoning', 'writing'] }; const activities = activityTypes[type] || activityTypes.general; window.synapseSystem?.simulateActivity(activities); } } // Initialize dashboard when DOM is loaded document.addEventListener('DOMContentLoaded', () => { window.tetoDashboard = new TetoDashboard(); });