feat: complete UI/UX Rework into Sleek Glassmorphic AI OS (June 2026)
This commit is contained in:
@@ -1,20 +1,31 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { ExternalLink } from "lucide-react"
|
||||
import { Bot, ExternalLink, Activity, Cpu, Wrench, Shield } from "lucide-react"
|
||||
import { api, type AgentStatus } from "@/lib/api"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Dot({ ok }: { ok: boolean }) {
|
||||
return <span className={cn("h-2 w-2 rounded-full", ok ? "bg-emerald-500" : "bg-amber-500")} />
|
||||
}
|
||||
|
||||
function Tile({ label, ok, detail }: { label: string; ok: boolean; detail?: string }) {
|
||||
function Tile({ label, ok, detail, icon: Icon }: { label: string; ok: boolean; detail?: string; icon: any }) {
|
||||
return (
|
||||
<div className="rounded-lg border border-border bg-card p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Dot ok={ok} />
|
||||
<span className="text-sm font-medium">{label}</span>
|
||||
<div className={cn(
|
||||
"rounded-2xl border bg-card/45 backdrop-blur-md p-5 shadow-lg shadow-black/10 flex flex-col justify-between gap-3 hover:border-primary/40 transition-all duration-300",
|
||||
ok ? "border-border/60" : "border-amber-500/30"
|
||||
)}>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">{label}</span>
|
||||
<Icon className={cn("h-4.5 w-4.5", ok ? "text-primary" : "text-amber-500")} />
|
||||
</div>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={cn(
|
||||
"h-2 w-2 rounded-full ring-2 ring-black/40",
|
||||
ok ? "bg-emerald-500 animate-pulse" : "bg-amber-500"
|
||||
)} />
|
||||
<span className="text-xs font-semibold text-foreground">
|
||||
{ok ? "Bereit / Online" : "Offline / Inaktiv"}
|
||||
</span>
|
||||
</div>
|
||||
{detail && <div className="text-[10px] font-mono text-muted-foreground truncate max-w-[200px]" title={detail}>{detail}</div>}
|
||||
</div>
|
||||
{detail && <div className="mt-1 text-xs text-muted-foreground">{detail}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -26,60 +37,107 @@ export function AgentView() {
|
||||
useEffect(() => {
|
||||
const load = () => api<AgentStatus>("/api/agent/status").then(setS).catch((e) => setError(String(e)))
|
||||
load()
|
||||
const t = setInterval(load, 8000)
|
||||
const t = setInterval(load, 5000)
|
||||
return () => clearInterval(t)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="space-y-6">
|
||||
{/* Header */}
|
||||
<div className="flex flex-col sm:flex-row justify-between sm:items-center gap-4">
|
||||
<div>
|
||||
<h1 className="text-xl font-semibold">Hermes</h1>
|
||||
<h1 className="text-2xl font-space font-bold tracking-tight bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text text-transparent">
|
||||
Hermes Agenten-Cockpit
|
||||
</h1>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Der autonome Agent läuft eigenständig (Gateway :8642) und hat seine eigene Oberfläche
|
||||
(hermes-webui :8787). Mission Control verlinkt nur — Chat & Steuerung leben dort.
|
||||
Hermes ist ein autonomer Agent, der im Hintergrund der Box läuft (Port <code>:8642</code>) und seine eigene UI besitzt.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{s?.webui_url && (
|
||||
<a
|
||||
href={s.webui_url}
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
className={cn(
|
||||
"flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium",
|
||||
"flex h-9 px-4 items-center gap-1.5 text-xs font-semibold rounded-lg transition-all cursor-pointer shadow-md shrink-0 self-start",
|
||||
s.webui_reachable
|
||||
? "bg-primary text-primary-foreground hover:opacity-90"
|
||||
: "border border-border text-muted-foreground",
|
||||
? "bg-primary text-primary-foreground hover:opacity-90 shadow-primary/10"
|
||||
: "border border-border/60 text-muted-foreground bg-background/20"
|
||||
)}
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" /> Hermes öffnen
|
||||
<ExternalLink className="h-4 w-4" />
|
||||
<span>Hermes WebUI öffnen</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{error && <div className="text-sm text-muted-foreground">Status nicht lesbar ({error}).</div>}
|
||||
{error && (
|
||||
<div className="rounded-xl border border-red-500/20 bg-red-500/5 p-4 text-xs text-red-400 font-mono">
|
||||
Status nicht lesbar ({error}).
|
||||
</div>
|
||||
)}
|
||||
|
||||
{s && (
|
||||
<>
|
||||
<div className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<Tile label="Gateway (:8642)" ok={s.gateway_reachable} detail={s.gateway_reachable ? "erreichbar" : "offline"} />
|
||||
<Tile label="WebUI (:8787)" ok={s.webui_reachable} detail={s.webui_reachable ? "erreichbar" : "offline"} />
|
||||
<Tile label="Brain" ok={s.gateway_reachable} detail={`model: ${s.brain_model || "auto"}`} />
|
||||
<Tile label="Verdrahtung" ok={s.has_config} detail={`config ${s.has_config ? "✓" : "—"} · skills ${s.has_skills ? "✓" : "—"} · memories ${s.has_memories ? "✓" : "—"}`} />
|
||||
<div className="space-y-6">
|
||||
{/* Tile Grid */}
|
||||
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<Tile
|
||||
label="Agent Gateway"
|
||||
ok={s.gateway_reachable}
|
||||
detail="Port :8642 (REST API)"
|
||||
icon={Bot}
|
||||
/>
|
||||
<Tile
|
||||
label="Agent WebUI"
|
||||
ok={s.webui_reachable}
|
||||
detail="Port :8787 (Chat UI)"
|
||||
icon={Activity}
|
||||
/>
|
||||
<Tile
|
||||
label="Aktives Gehirn"
|
||||
ok={s.gateway_reachable}
|
||||
detail={s.brain_model ? `Model: ${s.brain_model}` : "Model: auto"}
|
||||
icon={Cpu}
|
||||
/>
|
||||
<Tile
|
||||
label="Verdrahtung"
|
||||
ok={s.has_config}
|
||||
detail={`Config: ${s.has_config ? "✓" : "—"} · Skills: ${s.has_skills ? "✓" : "—"} · Memory: ${s.has_memories ? "✓" : "—"}`}
|
||||
icon={Wrench}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Diagnostic Details if Offline */}
|
||||
{!s.gateway_reachable && (
|
||||
<div className="rounded-xl border border-dashed border-border bg-card/50 p-5 text-sm">
|
||||
<div className="mb-2 font-medium">Hermes ist (hier) offline</div>
|
||||
<p className="text-muted-foreground">
|
||||
Der Agent + hermes-webui laufen auf der Box. Einrichtung & volle Verdrahtung
|
||||
(Brain = <code>model: auto</code>, Tools/MCP inkl. <code>mcp_mc</code> + <code>mcp_memory</code>,
|
||||
SSH→Windows, lokale Browser-/Such-MCP) sind im Runbook beschrieben:
|
||||
<code className="ml-1">docs/HERMES_SETUP.md</code>.
|
||||
</p>
|
||||
<div className="rounded-2xl border border-border/60 bg-card/45 backdrop-blur-md p-6 space-y-4 shadow-lg shadow-black/10">
|
||||
<div className="flex items-center gap-2">
|
||||
<Shield className="h-5 w-5 text-amber-500" />
|
||||
<h3 className="text-sm font-bold uppercase tracking-wider text-foreground">Hermes-Agent Diagnostics</h3>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-muted-foreground space-y-3 leading-relaxed">
|
||||
<p>
|
||||
Der Hermes-Dienst ist auf der Box derzeit offline oder kann sich nicht mit dem lokalen llama-swap verbinden.
|
||||
</p>
|
||||
<p>
|
||||
Stelle sicher, dass die systemd-Dienste auf der Box laufen. Du kannst den Status im <strong>OS & Updates Drawer</strong> prüfen und die Dienste bei Bedarf neu starten.
|
||||
</p>
|
||||
|
||||
<div className="p-3.5 bg-background/25 rounded-xl border border-border/30 font-mono text-[10px] space-y-1">
|
||||
<div className="text-muted-foreground/60"># Dienste manuell auf der Box prüfen:</div>
|
||||
<div className="text-primary">systemctl --user status hermes-gateway</div>
|
||||
<div className="text-primary">systemctl --user status hermes-webui</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Weitere Einrichtungsdetails (Brain-Konfiguration, MCP-Kopplungen, SSH-Tunneling und Such-Engines) findest du in der Dokumentationsdatei:
|
||||
<code className="ml-1 px-1.5 py-0.5 rounded bg-muted/40 text-foreground border border-border/30">docs/HERMES_SETUP.md</code>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user