import { useEffect, useMemo, useState } from 'react' import api from '@/services/api' interface ServerRow { server_id: number identifier: string display_name: string online: boolean openclaw_version?: string | null cpu_pct?: number | null mem_pct?: number | null disk_pct?: number | null swap_pct?: number | null agents: Array<{ id?: string; name?: string; status?: string }> last_seen_at?: string | null } interface OverviewData { issues: { total_issues: number new_issues_24h: number processed_issues_24h: number computed_at: string } servers: ServerRow[] generated_at: string } interface AdminUser { id: number is_admin: boolean } interface ServerItem { server_id: number identifier: string display_name: string online: boolean } export default function MonitorPage() { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [isAdmin, setIsAdmin] = useState(false) const [servers, setServers] = useState([]) const [serverForm, setServerForm] = useState({ identifier: '', display_name: '' }) const canAdmin = useMemo(() => !!localStorage.getItem('token') && isAdmin, [isAdmin]) const load = async () => { try { const res = await api.get('/monitor/public/overview') setData(res.data) const token = localStorage.getItem('token') if (token) { try { const me = await api.get('/auth/me') setIsAdmin(!!me.data.is_admin) } catch { setIsAdmin(false) } } else { setIsAdmin(false) } } finally { setLoading(false) } } const loadAdminData = async () => { if (!canAdmin) return const s = await api.get('/monitor/admin/servers') setServers(s.data) } useEffect(() => { load() const t = setInterval(load, 30000) return () => clearInterval(t) }, []) useEffect(() => { loadAdminData() }, [canAdmin]) const addServer = async () => { await api.post('/monitor/admin/servers', serverForm) setServerForm({ identifier: '', display_name: '' }) await loadAdminData() } const deleteServer = async (id: number) => { await api.delete('/monitor/admin/servers/' + id) await loadAdminData() } const createChallenge = async (id: number) => { const r = await api.post<{ identifier: string; challenge_uuid: string; expires_at: string }>('/monitor/admin/servers/' + id + '/challenge') alert('identifier=' + r.data.identifier + ' | challenge_uuid=' + r.data.challenge_uuid + ' | expires_at=' + r.data.expires_at) } if (loading) return
Monitor loading...
if (!data) return
Monitor load failed
return (

📡 Monitor

{data.issues.total_issues} Total Tasks
{data.issues.new_issues_24h} New (24h)
{data.issues.processed_issues_24h} Processed (24h)

Server Monitoring

{data.servers.length === 0 ?

No monitored servers

: (
{data.servers.map((s) => (
{s.display_name}
{s.identifier}
{s.online ? 'online' : 'offline'}
CPU {s.cpu_pct ?? '-'}% · MEM {s.mem_pct ?? '-'}% · DISK {s.disk_pct ?? '-'}% · SWAP {s.swap_pct ?? '-'}%
OpenClaw: {s.openclaw_version || '-'}
Agents: {s.agents?.length || 0}
))}
)}
{canAdmin && (

Admin

Servers

setServerForm({ ...serverForm, identifier: e.target.value })} /> setServerForm({ ...serverForm, display_name: e.target.value })} />
    {servers.map((s) => (
  • {s.display_name} ({s.identifier})
  • ))}
)}
) }