function showToast(message, type = 'info') { const container = document.getElementById('toastContainer'); const icons = { success: '✓', error: '✕', warning: '⚠', info: 'ℹ' }; const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.innerHTML = `${icons[type] || icons.info}${message}`; container.appendChild(toast); setTimeout(() => { toast.style.opacity = '0'; toast.style.transform = 'translateX(20px)'; setTimeout(() => toast.remove(), 300); }, 3500); } function escapeHtml(str) { if (!str) return ''; const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } function formatDate(iso) { if (!iso) return '-'; try { return new Date(iso).toLocaleDateString('en-US', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' }); } catch { return iso; } } function timeAgo(iso) { if (!iso) return '-'; const diff = Date.now() - new Date(iso).getTime(); const mins = Math.floor(diff / 60000); if (mins < 1) return 'just now'; if (mins < 60) return `${mins}m ago`; const hrs = Math.floor(mins / 60); if (hrs < 24) return `${hrs}h ago`; const days = Math.floor(hrs / 24); return `${days}d ago`; } function formatBytes(bytes) { if (!bytes || bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; } function statusColor(status) { const s = (status || '').toLowerCase(); if (['online', 'healthy', 'active', 'pass', 'ok'].includes(s)) return { bg: 'var(--green-dim)', dot: 'var(--green)', text: 'var(--green)' }; if (['warning', 'warn', 'degraded'].includes(s)) return { bg: 'var(--yellow-dim)', dot: 'var(--yellow)', text: 'var(--yellow)' }; if (['offline', 'error', 'fail', 'down'].includes(s)) return { bg: 'var(--red-dim)', dot: 'var(--red)', text: 'var(--red)' }; return { bg: 'var(--bg-card)', dot: 'var(--text-muted)', text: 'var(--text-muted)' }; } function toggleSidebar() { const sidebar = document.getElementById('sidebar'); const isCollapsed = sidebar.classList.toggle('collapsed'); localStorage.setItem('sidebarCollapsed', isCollapsed); const icon = sidebar.querySelector('.toggle-icon'); if (icon) { icon.style.transform = isCollapsed ? 'rotate(180deg)' : ''; } } function toggleTheme() { const html = document.documentElement; const next = html.getAttribute('data-theme') === 'dark' ? 'light' : 'dark'; html.setAttribute('data-theme', next); localStorage.setItem('theme', next); } function loadTheme() { const saved = localStorage.getItem('theme'); if (saved) document.documentElement.setAttribute('data-theme', saved); const sidebarCollapsed = localStorage.getItem('sidebarCollapsed'); if (sidebarCollapsed === 'true') { const sidebar = document.getElementById('sidebar'); sidebar.classList.add('collapsed'); const icon = sidebar.querySelector('.toggle-icon'); if (icon) icon.style.transform = 'rotate(180deg)'; } } function showModal(title, bodyHtml, footerHtml) { const container = document.getElementById('modalContainer'); container.innerHTML = ` `; } function closeModal() { document.getElementById('modalContainer').innerHTML = ''; } function handleGlobalSearch(value) { if (value.length < 2) return; if (window.location.hash !== '#skills') navigate('skills'); } function renderSkeleton(count = 3) { return Array(count).fill(0).map(() => `
` ).join(''); } const PAGE_TITLES = { dashboard: { title: 'Dashboard', breadcrumb: 'Overview' }, terminal: { title: 'Terminal', breadcrumb: 'Browser-based shell' }, skills: { title: 'Skills Hub', breadcrumb: 'Browse & execute skills' }, memory: { title: 'Memory', breadcrumb: 'Shared brain context' }, scheduler: { title: 'Scheduler', breadcrumb: 'Automated workflows' }, audit: { title: 'Audit Log', breadcrumb: 'System activity trail' }, cost: { title: 'Cost Analytics', breadcrumb: 'Usage & spending' }, 'agent-insights': { title: 'Agent Insights', breadcrumb: 'AI usage analytics' }, 'brain-search': { title: 'Brain Search', breadcrumb: 'Unified knowledge index' }, 'orchestration': { title: 'Multi-Agent Run', breadcrumb: 'Fan-out + converge agents' }, plugins: { title: 'Plugin Registry', breadcrumb: 'Manage plugins' }, backups: { title: 'Backups', breadcrumb: 'Disaster recovery' }, prompts: { title: 'Prompt Library', breadcrumb: 'Reusable templates' }, standards: { title: 'Standards', breadcrumb: 'Project conventions' }, settings: { title: 'Settings', breadcrumb: 'Configuration' }, 'setup-wizard': { title: 'Setup Wizard', breadcrumb: 'Guided configuration' }, chat: { title: 'AI Chat', breadcrumb: 'Multi-agent terminal' }, terminal: { title: 'Terminal', breadcrumb: 'Local shell access' }, kanban: { title: 'Kanban Board', breadcrumb: 'Multi-agent task management' }, goals: { title: 'Goals', breadcrumb: 'Project targets and progress' }, journal: { title: 'Journal', breadcrumb: 'Daily entries and notes' }, 'command-center': { title: 'Command Center', breadcrumb: 'Dispatch & live console' }, 'agent-health': { title: 'Agent Health', breadcrumb: 'Real-time agent monitoring' }, 'smart-router': { title: 'Smart Router', breadcrumb: 'Task routing intelligence' }, 'learning-analytics': { title: 'Learning Analytics', breadcrumb: 'Skill improvement tracking' }, 'session-replay': { title: 'Session Replay', breadcrumb: 'Conversation history playback' }, 'agent-time': { title: 'Agent Time', breadcrumb: 'Total agent effort on this project' }, };