import { useState } from 'react' import { useNavigate } from 'react-router-dom' import styles from './AgentHealth.module.css' // Layout import { AppShell } from '../../design-system/layout/AppShell/AppShell' import { Sidebar } from '../../design-system/layout/Sidebar/Sidebar' import { TopBar } from '../../design-system/layout/TopBar/TopBar' // Composites import { LineChart } from '../../design-system/composites/LineChart/LineChart' // Primitives import { StatusDot } from '../../design-system/primitives/StatusDot/StatusDot' import { MonoText } from '../../design-system/primitives/MonoText/MonoText' import { Badge } from '../../design-system/primitives/Badge/Badge' import { Card } from '../../design-system/primitives/Card/Card' // Mock data import { agents } from '../../mocks/agents' import { routes } from '../../mocks/routes' // ─── Sidebar data (shared) ──────────────────────────────────────────────────── const APPS = [ { id: 'order-service', name: 'order-service', agentCount: 2, health: 'live' as const, exchangeCount: 1433 }, { id: 'payment-svc', name: 'payment-svc', agentCount: 1, health: 'live' as const, exchangeCount: 912 }, { id: 'shipment-tracker', name: 'shipment-tracker', agentCount: 2, health: 'live' as const, exchangeCount: 471 }, { id: 'notification-hub', name: 'notification-hub', agentCount: 1, health: 'stale' as const, exchangeCount: 128 }, ] const SIDEBAR_ROUTES = routes.slice(0, 3).map((r) => ({ id: r.id, name: r.name, exchangeCount: r.exchangeCount, })) // ─── Build trend data for each agent ───────────────────────────────────────── function buildAgentTrendSeries(agentId: string) { const baseValues: Record = { 'prod-1': { throughput: 14.2, errorRate: 0.2 }, 'prod-2': { throughput: 11.8, errorRate: 3.1 }, 'prod-3': { throughput: 12.1, errorRate: 0.5 }, 'prod-4': { throughput: 9.1, errorRate: 0.3 }, } const base = baseValues[agentId] ?? { throughput: 10, errorRate: 1 } const now = new Date('2026-03-18T09:15:00') const points = 20 const intervalMs = (3 * 60 * 60 * 1000) / points // 3 hours const throughputData = Array.from({ length: points }, (_, i) => ({ x: new Date(now.getTime() - (points - i) * intervalMs), y: Math.max(0, base.throughput + (Math.random() - 0.5) * 4), })) const errorRateData = Array.from({ length: points }, (_, i) => ({ x: new Date(now.getTime() - (points - i) * intervalMs), y: Math.max(0, base.errorRate + (Math.random() - 0.5) * 2), })) return { throughputData, errorRateData } } // ─── Summary stats ──────────────────────────────────────────────────────────── const liveCount = agents.filter((a) => a.status === 'live').length const totalTps = agents.reduce((sum, a) => sum + parseFloat(a.tps), 0) const totalActiveRoutes = agents.reduce((sum, a) => sum + a.activeRoutes, 0) // ─── AgentHealth page ───────────────────────────────────────────────────────── export function AgentHealth() { const navigate = useNavigate() const [activeItem, setActiveItem] = useState('agents') const [expandedAgent, setExpandedAgent] = useState(null) function handleItemClick(id: string) { setActiveItem(id) const route = routes.find((r) => r.id === id) if (route) navigate(`/routes/${id}`) } function toggleAgent(id: string) { setExpandedAgent((prev) => (prev === id ? null : id)) } return ( } > {/* Top bar */} {/* Scrollable content */}
{/* System overview strip */}
Total Agents
{agents.length}
Live
{liveCount}
Stale
a.status === 'stale') ? styles.valueStale : ''}`}> {agents.filter((a) => a.status === 'stale').length}
Dead
a.status === 'dead') ? styles.valueDead : ''}`}> {agents.filter((a) => a.status === 'dead').length}
Total TPS
{totalTps.toFixed(1)}/s
Active Routes
{totalActiveRoutes}
{/* Section header */}
Agent Details {liveCount}/{agents.length} live · Click to expand charts
{/* Agent cards grid */}
{agents.map((agent) => { const isExpanded = expandedAgent === agent.id const trendData = isExpanded ? buildAgentTrendSeries(agent.id) : null const statusVariant = agent.status === 'live' ? 'live' : agent.status === 'stale' ? 'stale' : 'dead' const cardAccent = agent.status === 'live' ? 'success' : agent.status === 'stale' ? 'warning' : 'error' return ( {/* Agent card header */}
toggleAgent(agent.id)} role="button" tabIndex={0} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') toggleAgent(agent.id) }} aria-expanded={isExpanded} >
{agent.name}
{agent.service} {agent.version}
{isExpanded ? '▲' : '▼'}
{/* Agent metrics row */}
TPS {agent.tps}
Uptime {agent.uptime}
Last Seen {agent.lastSeen}
{agent.errorRate && (
Error Rate {agent.errorRate}
)}
CPU 70 ? styles.metricValueWarn : styles.metricValue}> {agent.cpuUsagePct}%
Memory 80 ? styles.metricValueError : agent.memoryUsagePct > 70 ? styles.metricValueWarn : styles.metricValue}> {agent.memoryUsagePct}%
Routes {agent.activeRoutes}/{agent.totalRoutes}
{/* Expanded detail: trend charts */} {isExpanded && trendData && (
Throughput (msg/s)
Error Rate (err/h)
)}
) })}
) }