Skip to main content
Glama

MemOS-MCP

by qinshu1109
Apache 2.0
3
  • Linux
  • Apple
dashboard.js12.1 kB
/** * MemOS 迷你Dashboard JavaScript * 负责数据获取、更新和用户交互 */ // 配置 const CONFIG = { API_BASE_URL: 'http://localhost:8000', // API服务器地址 AUTO_REFRESH_INTERVAL: 30000, // 30秒自动刷新 REQUEST_TIMEOUT: 10000 // 10秒请求超时 }; // 全局状态 let autoRefreshTimer = null; let isLoading = false; /** * 初始化Dashboard */ document.addEventListener('DOMContentLoaded', function() { console.log('🚀 MemOS Dashboard 初始化中...'); // 首次加载数据 refreshAllData(); // 设置键盘快捷键 document.addEventListener('keydown', function(e) { if (e.key === 'F5' || (e.ctrlKey && e.key === 'r')) { e.preventDefault(); refreshAllData(); } }); console.log('✅ Dashboard 初始化完成'); }); /** * 发起API请求 */ async function apiRequest(endpoint, options = {}) { const url = `${CONFIG.API_BASE_URL}${endpoint}`; const defaultOptions = { method: 'GET', headers: { 'Content-Type': 'application/json', }, timeout: CONFIG.REQUEST_TIMEOUT }; try { const response = await fetch(url, { ...defaultOptions, ...options }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); return data; } catch (error) { console.error(`API请求失败 [${endpoint}]:`, error); throw error; } } /** * 刷新所有数据 */ async function refreshAllData() { if (isLoading) { console.log('⏳ 数据正在加载中,跳过本次刷新'); return; } isLoading = true; console.log('🔄 开始刷新所有数据...'); // 添加加载状态 document.body.classList.add('loading'); try { // 并行获取所有数据 const promises = [ loadSystemStatus(), loadMemoryStats(), loadPerformanceMetrics(), loadCapacityInfo(), loadTopicDriftInfo(), loadRecentActivity() ]; await Promise.allSettled(promises); // 更新最后更新时间 updateLastUpdateTime(); console.log('✅ 所有数据刷新完成'); } catch (error) { console.error('❌ 数据刷新失败:', error); showError('数据刷新失败,请检查API服务器状态'); } finally { isLoading = false; document.body.classList.remove('loading'); } } /** * 加载系统状态 */ async function loadSystemStatus() { try { const response = await apiRequest('/health'); if (response.success) { updateElement('serviceStatus', ` <span class="status-indicator status-online"></span>在线 `); // 获取详细状态 const statusResponse = await apiRequest('/status'); if (statusResponse.success && statusResponse.data) { const data = statusResponse.data; updateElement('runningMode', data.mode || '增强版'); updateElement('uptime', formatUptime(data.uptime || 0)); updateElement('apiVersion', data.version || 'v1.0.0'); } } else { throw new Error(response.message || '健康检查失败'); } } catch (error) { console.error('系统状态加载失败:', error); updateElement('serviceStatus', ` <span class="status-indicator status-offline"></span>离线 `); updateElement('runningMode', '未知'); updateElement('uptime', '未知'); updateElement('apiVersion', '未知'); } } /** * 加载记忆统计 */ async function loadMemoryStats() { try { const response = await apiRequest('/memories/stats'); if (response.success && response.data) { const data = response.data; updateElement('totalMemories', formatNumber(data.total_memories || 0)); updateElement('todayAdded', formatNumber(data.today_added || 0)); updateElement('recentSearches', formatNumber(data.recent_searches || 0)); updateElement('avgScore', formatScore(data.average_score || 0)); } else { throw new Error(response.message || '记忆统计获取失败'); } } catch (error) { console.error('记忆统计加载失败:', error); updateElement('totalMemories', '错误'); updateElement('todayAdded', '错误'); updateElement('recentSearches', '错误'); updateElement('avgScore', '错误'); } } /** * 加载性能指标 */ async function loadPerformanceMetrics() { try { const response = await apiRequest('/metrics'); if (response.success && response.data) { const data = response.data; updateElement('avgResponseTime', formatTime(data.avg_response_time || 0)); updateElement('searchSuccessRate', formatPercentage(data.search_success_rate || 0)); updateElement('memoryUsage', formatBytes(data.memory_usage || 0)); updateElement('cacheHitRate', formatPercentage(data.cache_hit_rate || 0)); } else { throw new Error(response.message || '性能指标获取失败'); } } catch (error) { console.error('性能指标加载失败:', error); updateElement('avgResponseTime', '错误'); updateElement('searchSuccessRate', '错误'); updateElement('memoryUsage', '错误'); updateElement('cacheHitRate', '错误'); } } /** * 加载容量信息 */ async function loadCapacityInfo() { try { const response = await apiRequest('/capacity/report'); if (response.success && response.data) { const data = response.data; updateElement('workingMemory', formatCapacity(data.working_memory || {})); updateElement('userMemory', formatCapacity(data.user_memory || {})); updateElement('longTermMemory', formatCapacity(data.long_term_memory || {})); updateElement('compressionStatus', data.compression_status || '正常'); } else { throw new Error(response.message || '容量信息获取失败'); } } catch (error) { console.error('容量信息加载失败:', error); updateElement('workingMemory', '错误'); updateElement('userMemory', '错误'); updateElement('longTermMemory', '错误'); updateElement('compressionStatus', '错误'); } } /** * 加载主题漂移信息 */ async function loadTopicDriftInfo() { try { const response = await apiRequest('/dashboard/topic-drift'); if (response.success && response.data) { const data = response.data; updateElement('totalQueries', formatNumber(data.total_queries || 0)); updateElement('driftCount', formatNumber(data.drift_count || 0)); updateElement('driftRate', data.drift_rate || '0.0%'); updateElement('windowSize', data.window_size || 5); } else { throw new Error(response.message || '主题漂移统计获取失败'); } } catch (error) { console.error('主题漂移信息加载失败:', error); // 如果API调用失败,使用模拟数据 updateElement('totalQueries', '0'); updateElement('driftCount', '0'); updateElement('driftRate', '0.0%'); updateElement('windowSize', '5'); } } /** * 加载最近活动 */ async function loadRecentActivity() { try { // 模拟最近活动数据 const activityHtml = ` <div style="padding: 10px; font-size: 0.9em;"> <div style="margin-bottom: 8px;"> <span style="color: #4CAF50;">✓</span> <span>15:32 - 成功检索"Python编程"相关记忆</span> </div> <div style="margin-bottom: 8px;"> <span style="color: #ff9800;">⚠</span> <span>15:28 - 检测到主题漂移</span> </div> <div style="margin-bottom: 8px;"> <span style="color: #4CAF50;">✓</span> <span>15:25 - 添加新记忆"机器学习基础"</span> </div> <div style="margin-bottom: 8px;"> <span style="color: #2196F3;">ℹ</span> <span>15:20 - 系统自动压缩完成</span> </div> <div> <span style="color: #4CAF50;">✓</span> <span>15:15 - 用户反馈记忆评分</span> </div> </div> `; updateElement('recentActivity', activityHtml); } catch (error) { console.error('最近活动加载失败:', error); updateElement('recentActivity', '<div class="error">加载失败</div>'); } } /** * 更新元素内容 */ function updateElement(id, content) { const element = document.getElementById(id); if (element) { element.innerHTML = content; } } /** * 格式化数字 */ function formatNumber(num) { if (typeof num !== 'number') return '0'; return num.toLocaleString(); } /** * 格式化分数 */ function formatScore(score) { if (typeof score !== 'number') return '0.000'; return score.toFixed(3); } /** * 格式化时间 */ function formatTime(ms) { if (typeof ms !== 'number') return '0ms'; if (ms < 1000) return `${ms.toFixed(0)}ms`; return `${(ms / 1000).toFixed(2)}s`; } /** * 格式化百分比 */ function formatPercentage(value) { if (typeof value !== 'number') return '0%'; return `${(value * 100).toFixed(1)}%`; } /** * 格式化字节 */ function formatBytes(bytes) { if (typeof bytes !== 'number') return '0B'; const sizes = ['B', 'KB', 'MB', 'GB']; if (bytes === 0) return '0B'; const i = Math.floor(Math.log(bytes) / Math.log(1024)); return `${(bytes / Math.pow(1024, i)).toFixed(1)}${sizes[i]}`; } /** * 格式化容量信息 */ function formatCapacity(capacity) { if (!capacity || typeof capacity !== 'object') return '0/0'; const used = capacity.used || 0; const total = capacity.total || 0; const percentage = total > 0 ? ((used / total) * 100).toFixed(1) : 0; return `${used}/${total} (${percentage}%)`; } /** * 格式化运行时间 */ function formatUptime(seconds) { if (typeof seconds !== 'number') return '0秒'; const days = Math.floor(seconds / 86400); const hours = Math.floor((seconds % 86400) / 3600); const minutes = Math.floor((seconds % 3600) / 60); if (days > 0) return `${days}天${hours}小时`; if (hours > 0) return `${hours}小时${minutes}分钟`; return `${minutes}分钟`; } /** * 更新最后更新时间 */ function updateLastUpdateTime() { const now = new Date(); const timeString = now.toLocaleTimeString('zh-CN'); updateElement('lastUpdate', timeString); } /** * 显示错误信息 */ function showError(message) { console.error('Dashboard错误:', message); // 可以在这里添加更友好的错误显示 } /** * 切换自动刷新 */ function toggleAutoRefresh() { const checkbox = document.getElementById('autoRefresh'); if (checkbox.checked) { // 启用自动刷新 autoRefreshTimer = setInterval(refreshAllData, CONFIG.AUTO_REFRESH_INTERVAL); console.log('✅ 自动刷新已启用'); } else { // 禁用自动刷新 if (autoRefreshTimer) { clearInterval(autoRefreshTimer); autoRefreshTimer = null; } console.log('❌ 自动刷新已禁用'); } } // 导出函数供HTML调用 window.refreshAllData = refreshAllData; window.toggleAutoRefresh = toggleAutoRefresh;

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/qinshu1109/memos-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server