'use client' import { useMissionControl } from '@/store' import { useEffect, useState } from 'react' import { useTranslations } from 'next-intl' import { Button } from '@/components/ui/button' export function LiveFeed() { const { logs, sessions, activities, connection, dashboardMode, toggleLiveFeed } = useMissionControl() const t = useTranslations('liveFeed') const isLocal = dashboardMode === 'local' const [expanded, setExpanded] = useState(false) const [hasCollapsed, setHasCollapsed] = useState(false) // Combine logs, activities, and (in local mode) session events into a unified feed const sessionItems = isLocal ? sessions.slice(0, 10).map(s => ({ id: `sess-${s.id}`, type: 'session' as const, level: 'info' as const, message: `${s.active ? t('activeSession') : t('idleSession')} session: ${s.key || s.id}`, source: s.model?.split('/').pop()?.split('-').slice(0, 2).join('-') || 'claude', timestamp: s.lastActivity || s.startTime || Date.now(), })) : [] const feedItems = [ ...logs.slice(0, 30).map(log => ({ id: `log-${log.id}`, type: 'log' as const, level: log.level, message: log.message, source: log.source, timestamp: log.timestamp, })), ...activities.slice(0, 20).map(act => ({ id: `act-${act.id}`, type: 'activity' as const, level: 'info' as const, message: act.description, source: act.actor, timestamp: act.created_at * 1000, })), ...sessionItems, ].sort((a, b) => b.timestamp - a.timestamp).slice(0, 40) if (!expanded) { return (
{/* Mini indicators */}
{feedItems.slice(0, 5).map((item) => (
))}
) } return (
{/* Header */}
{t('liveFeed')} {feedItems.length}
{/* Feed items */}
{feedItems.length === 0 ? (

{t('noActivityYet')}

{isLocal ? t('eventsAppearLocal') : t('eventsStreamGateway')}

) : (
{feedItems.map((item) => ( ))}
)}
{/* Active sessions mini-list */}
{t('activeSessions')}
{sessions.filter(s => s.active).slice(0, 4).map(session => (
{session.key || session.id} {session.model?.split('/').pop()?.slice(0, 8)}
))} {sessions.filter(s => s.active).length === 0 && (
{t('noActiveSessions')}
)}
) } function FeedItem({ item }: { item: { id: string; type: string; level: string; message: string; source: string; timestamp: number } }) { const levelIndicator = item.level === 'error' ? 'bg-red-500' : item.level === 'warn' ? 'bg-amber-500' : item.level === 'debug' ? 'bg-gray-500' : 'bg-blue-500/50' const timeStr = formatRelativeTime(item.timestamp) return (

{item.message.length > 120 ? item.message.slice(0, 120) + '...' : item.message}

{item.source} ยท {timeStr}
) } function formatRelativeTime(ts: number): string { const diff = Date.now() - ts if (diff < 60_000) return 'now' if (diff < 3_600_000) return `${Math.floor(diff / 60_000)}m` if (diff < 86_400_000) return `${Math.floor(diff / 3_600_000)}h` return `${Math.floor(diff / 86_400_000)}d` }