import React, { useRef, useEffect } from 'react' const typeConfig = { message: { icon: '💬', color: '#22d3ee', label: 'Message' }, tool: { icon: '🔧', color: '#a78bfa', label: 'Tool' }, knowledge: { icon: '🧠', color: '#34d399', label: 'Knowledge' }, lifecycle: { icon: '⚡', color: '#f472b6', label: 'Lifecycle' }, other: { icon: '📦', color: '#94a3b8', label: 'Other' } } function formatTime(date) { return date.toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit', second: '2-digit', fractionalSecondDigits: 3 }) } function formatSubject(subject) { // openclaw.events.agent.conversation_message_out -> conversation_message_out const parts = subject.split('.') return parts.slice(-1)[0] } function formatAgent(subject) { // openclaw.events.agent.xxx -> agent // openclaw.events.claudia.xxx -> claudia const parts = subject.split('.') return parts[2] || 'unknown' } export default function EventTable({ events, onSelect }) { const tableRef = useRef(null) const autoScrollRef = useRef(true) // Auto-scroll to top when new events arrive useEffect(() => { if (autoScrollRef.current && tableRef.current) { tableRef.current.scrollTop = 0 } }, [events.length]) return (
{/* Header */}

âš¡ Live Event Stream {events.length} events

Auto-updating
{/* Table Header */}
Time
Type
Subject
Content
{/* Table Body - Scrollable */}
{ // Disable auto-scroll if user scrolls away from top autoScrollRef.current = e.target.scrollTop < 50 }} > {events.length === 0 ? (
👀

Waiting for events...

Neural activity will stream here in real-time

) : ( events.map((event, index) => { const config = typeConfig[event.type] || typeConfig.other const isNew = index < 3 && (Date.now() - event.timestamp.getTime()) < 5000 return ( ) }) )}
) }