import { getAgentDefs } from './agents.js'; import { AGENT_DEFS, colorToCss } from './agent-defs.js'; const $agentCount = document.getElementById('agent-count'); const $activeJobs = document.getElementById('active-jobs'); const $fps = document.getElementById('fps'); const $agentList = document.getElementById('agent-list'); const $connStatus = document.getElementById('connection-status'); const $chatPanel = document.getElementById('chat-panel'); const $clearBtn = document.getElementById('chat-clear-btn'); const MAX_CHAT_ENTRIES = 12; const MAX_STORED = 100; const STORAGE_PREFIX = 'matrix:chat:'; const chatEntries = []; const chatHistory = {}; const IDLE_COLOR = '#005500'; const ACTIVE_COLOR = '#00ff41'; /* ── localStorage chat history ────────────────────────── */ function storageKey(agentId) { return STORAGE_PREFIX + agentId; } export function loadChatHistory(agentId) { try { const raw = localStorage.getItem(storageKey(agentId)); if (!raw) return []; const parsed = JSON.parse(raw); if (!Array.isArray(parsed)) return []; return parsed.filter(m => m && typeof m.agentLabel === 'string' && typeof m.text === 'string' ); } catch { return []; } } export function saveChatHistory(agentId, messages) { try { localStorage.setItem(storageKey(agentId), JSON.stringify(messages.slice(-MAX_STORED))); } catch { /* quota exceeded or private mode */ } } function formatTimestamp(ts) { const d = new Date(ts); const hh = String(d.getHours()).padStart(2, '0'); const mm = String(d.getMinutes()).padStart(2, '0'); return `${hh}:${mm}`; } function loadAllHistories() { const all = []; const agentIds = [...AGENT_DEFS.map(d => d.id), 'sys']; for (const id of agentIds) { const msgs = loadChatHistory(id); chatHistory[id] = msgs; all.push(...msgs); } all.sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0)); for (const msg of all.slice(-MAX_CHAT_ENTRIES)) { const entry = buildChatEntry(msg.agentLabel, msg.text, msg.cssColor, msg.timestamp); chatEntries.push(entry); $chatPanel.appendChild(entry); } $chatPanel.scrollTop = $chatPanel.scrollHeight; } function clearAllHistories() { const agentIds = [...AGENT_DEFS.map(d => d.id), 'sys']; for (const id of agentIds) { localStorage.removeItem(storageKey(id)); chatHistory[id] = []; } while ($chatPanel.firstChild) $chatPanel.removeChild($chatPanel.firstChild); chatEntries.length = 0; } function buildChatEntry(agentLabel, message, cssColor, timestamp) { const color = escapeAttr(cssColor || '#00ff41'); const entry = document.createElement('div'); entry.className = 'chat-entry'; const ts = timestamp ? `[${formatTimestamp(timestamp)}] ` : ''; entry.innerHTML = `${ts}${escapeHtml(agentLabel)}: ${escapeHtml(message)}`; return entry; } export function initUI() { renderAgentList(); loadAllHistories(); if ($clearBtn) $clearBtn.addEventListener('click', clearAllHistories); } function renderAgentList() { const defs = getAgentDefs(); $agentList.innerHTML = defs.map(a => { const css = escapeAttr(colorToCss(a.color)); const safeLabel = escapeHtml(a.label); const safeId = escapeAttr(a.id); return `