import { useCallback, useEffect, useMemo, useState } from 'react' import { ActivityFeed } from './components/ActivityFeed' import { AgentRoster } from './components/AgentRoster' import { AgentTerminalGrid } from './components/AgentTerminalGrid' import { ChatPanel } from './components/ChatPanel' import { CommandDock } from './components/CommandDock' import { GpuPanel } from './components/GpuPanel' import { AmbientBackground } from './components/AmbientBackground' import { LiveClusterMap } from './components/LiveClusterMap' import { LiveDomainGrid } from './components/LiveDomainGrid' import { ThemeToggle } from './components/ThemeToggle' import type { Agent, AgentAnim, Approval, ChatMessage, FeedEntry, GpuStatus, StatusData, TerminalLine, WorkloadData } from './types' const TABS = ['Overview', 'Terminals', 'Activity', 'Approvals', 'GPU'] as const type Tab = (typeof TABS)[number] function wsUrl() { const proto = window.location.protocol === 'https:' ? 'wss' : 'ws' return `${proto}://${window.location.host}/api/ws/ops` } function LiveClock() { const [now, setNow] = useState(new Date()) useEffect(() => { const t = setInterval(() => setNow(new Date()), 1000) return () => clearInterval(t) }, []) return ( {now.toLocaleTimeString()} ) } export default function App() { const [tab, setTab] = useState('Overview') const [agents, setAgents] = useState([]) const [status, setStatus] = useState(null) const [workload, setWorkload] = useState(null) const [gpu, setGpu] = useState(null) const [feed, setFeed] = useState([]) const [approvals, setApprovals] = useState([]) const [chat, setChat] = useState([]) const [anims, setAnims] = useState>({}) const [selectedId, setSelectedId] = useState(null) const [busy, setBusy] = useState(false) const [terminals, setTerminals] = useState>({}) const [terminalLayout, setTerminalLayout] = useState<'grid' | 'focus'>('grid') const appendTerminal = useCallback((line: TerminalLine) => { setTerminals((prev) => { const cur = prev[line.agent_id] || [] return { ...prev, [line.agent_id]: [...cur, line].slice(-300) } }) }, []) const selectedAgent = useMemo( () => agents.find((a) => a.id === selectedId) || null, [agents, selectedId], ) const load = useCallback(async () => { const [a, s, f, ap, g, t, w] = await Promise.all([ fetch('/api/agents').then((r) => r.json()), fetch('/api/status').then((r) => r.json()), fetch('/api/feed').then((r) => r.json()), fetch('/api/approvals').then((r) => r.json()), fetch('/api/gpu').then((r) => r.json()).catch(() => null), fetch('/api/terminals').then((r) => r.json()).catch(() => ({ terminals: {} })), fetch('/api/workload').then((r) => r.json()).catch(() => null), ]) setAgents(a.agents || []) setStatus(s) setGpu(g || s.gpu || null) setFeed(f.entries || []) setApprovals(ap.approvals || []) if (t.terminals) setTerminals(t.terminals) if (w?.zones) setWorkload(w) }, []) useEffect(() => { load() const ws = new WebSocket(wsUrl()) ws.onmessage = (ev) => { const msg = JSON.parse(ev.data) if (msg.type === 'status') { setStatus(msg.data) if (msg.data.gpu) setGpu(msg.data.gpu) } if (msg.type === 'workload') setWorkload(msg.data) if (msg.type === 'terminal') appendTerminal(msg.line) if (msg.type === 'terminal_history' && msg.terminals) setTerminals(msg.terminals) if (msg.type === 'feed') setFeed((prev) => [msg.entry, ...prev].slice(0, 100)) if (msg.type === 'agent_dispatch') { setSelectedId(msg.agent_id) setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'walk', zone: msg.zone } })) } if (msg.type === 'agent_fetch') { setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'fetch', zone: msg.zone } })) } if (msg.type === 'agent_return') { setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'return', zone: msg.zone } })) setTimeout(() => { setAnims((p) => ({ ...p, [msg.agent_id]: { agentId: msg.agent_id, state: 'idle' } })) }, 1200) } if (msg.type === 'prompt_result') { setChat((c) => [...c, { role: 'agent', text: msg.answer, agent: msg.agent_id, ts: new Date().toISOString() }]) setBusy(false) load() } } const iv = setInterval(load, 15000) return () => { ws.close(); clearInterval(iv) } }, [load, appendTerminal]) const sendPrompt = async (message: string, agentId?: string) => { setBusy(true) setChat((c) => [...c, { role: 'user', text: message, ts: new Date().toISOString() }]) if (agentId) setSelectedId(agentId) await fetch('/api/prompt', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message, agent_id: agentId || undefined }), }) } const decide = async (id: string, approved: boolean) => { await fetch(`/api/approvals/${id}/decide`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ approved }), }) load() } const allOk = status && Object.values(status.domains).every((d) => d.level === 'ok') const totalTasks = agents.reduce((n, a) => n + (a.stats?.tasks || 0), 0) return (
ATC

Command Center

{agents.length} agents · {totalTasks} missions · autonomous ops

{status && ( {allOk ? 'All systems operational' : 'Attention required'} )} {gpu?.ok && gpu.active_model && ( GPU · {gpu.active_model} )}
setSelectedId(a.id)} />

Live agent shells

Agent Terminals

Volg live hoe elke agent data ophaalt — HTTP probes, Dockhand, JMX, vLLM.

{tab === 'Overview' && (

Infrastructure

Live Cluster Workload

)} {tab === 'Terminals' && (

Mission trace

{selectedAgent ? `${selectedAgent.name} — full terminal` : 'Select an agent'}

{selectedAgent ? ( ) : (

Klik een agent in de roster of stuur een prompt.

)}
)} {tab === 'Activity' && (

Event stream

Agent Activity

{selectedAgent && ( )}
)} {tab === 'Approvals' && (
{approvals.length === 0 &&

Geen pending approvals.

} {approvals.map((a) => { const agent = agents.find((ag) => ag.id === a.agent_id) return (
{agent && {agent.icon}}
{a.action}
{a.reason}
via {agent?.name || a.agent_id}
) })}
)} {tab === 'GPU' && }
) }