Auftragsbuch: 'wartung/mc2-diaet-desktop' angenommen (Ein-Klick-Gate)

This commit is contained in:
Auftragsbuch
2026-07-09 08:58:21 +02:00
18 changed files with 239 additions and 308 deletions
+1 -6
View File
@@ -94,12 +94,7 @@ HERMES_API_MODEL = os.environ.get("HERMES_API_MODEL", "hermes")
# --- Voice-Sidecar (STT faster-whisper + TTS Piper/Chatterbox) ---------------
# Eigenes Python-3.12-venv (~/.voice/venv), analog Mem0-Sidecar. MC2 proxyt nach außen.
VOICE_SERVICE_URL = os.environ.get("MC_VOICE_SERVICE_URL", "http://127.0.0.1:8650").rstrip("/")
# Hermes-Terminal: ttyd-Web-Terminal der interaktiven Agent-CLI. Wie die Box-Konsole bindet
# es NUR an Loopback (127.0.0.1:7681, base-path /hermes-terminal) und wird von MC2 same-origin
# durchgereicht (routers/console.py → /hermes-terminal/). Login per `su` (Box-Passwort).
HERMES_TERMINAL_UPSTREAM = os.environ.get("MC_HERMES_TERMINAL_UPSTREAM", "http://127.0.0.1:7681").rstrip("/")
HERMES_TERMINAL_PATH = "/hermes-terminal/"
# Box-Konsole: zweites ttyd-Web-Terminal (echte Login-Shell). Bindet NUR an Loopback
# Box-Konsole: ttyd-Web-Terminal (echte Login-Shell). Bindet NUR an Loopback
# (127.0.0.1:7682, base-path /console) und wird von MC2 über den ohnehin offenen Port 9001
# rückwärts geproxyt (routers/console.py → same-origin /console/). So braucht die Konsole
# KEINE eigene Firewall-Freigabe (Port 7682 ist von außen dicht) und keinen sudo-Eingriff.
+3 -3
View File
@@ -17,7 +17,7 @@ import websockets
from fastapi import APIRouter, Request, WebSocket
from starlette.responses import Response
from config import BOX_CONSOLE_UPSTREAM, HERMES_TERMINAL_UPSTREAM
from config import BOX_CONSOLE_UPSTREAM
log = logging.getLogger(__name__)
router = APIRouter()
@@ -83,6 +83,6 @@ def _register(base: str, upstream: str) -> None:
name=f"{base}_path")
# Box-Konsole (Login-Shell) und Hermes-Terminal (Agent-CLI) — beide Loopback-ttyd.
# Box-Konsole (Login-Shell) — Loopback-ttyd. (Das Hermes-Terminal-ttyd ist mit dem
# Umzug auf Hermes Desktop entfallen; die Agent-Oberfläche ist die Desktop-App bzw. /hermes-ui/.)
_register("console", BOX_CONSOLE_UPSTREAM)
_register("hermes-terminal", HERMES_TERMINAL_UPSTREAM)
+2 -2
View File
@@ -61,14 +61,14 @@ def services() -> dict:
{"name": "Engine (llama-swap)", "unit": "llama-swap", "url": LLAMA_SWAP_URL, "ok": engine_reachable()},
{"name": "Gateway (integriert)", "unit": "mission-control-2", "url": gw_url, "ok": gateway_reachable()},
{"name": "Hermes-Gateway", "unit": "hermes-gateway", "url": HERMES_API_URL, "ok": a["gateway_reachable"]},
{"name": "Hermes-Terminal", "unit": "hermes-terminal", "url": a["terminal_url"], "ok": a["terminal_reachable"]},
{"name": "Hermes-GUI (Desktop-Gateway)", "unit": "hermes-builtin-ui", "url": a["hermes_ui_url"], "ok": a["hermes_ui_reachable"]},
{"name": "Mem0 (Gedächtnis)", "unit": "mem0-service", "url": MEM0_SERVICE_URL, "ok": _mem0_reachable()},
{"name": "Voice (STT/TTS)", "unit": "voice-service", "url": VOICE_SERVICE_URL, "ok": _voice_reachable()},
],
"links": {
"engine_ui": f"{LLAMA_SWAP_URL}/ui",
"gateway": gw_url,
"hermes_terminal": a["terminal_url"],
"hermes_ui": a["hermes_ui_url"],
},
}
+4 -6
View File
@@ -11,7 +11,7 @@ import re
import httpx
import psutil
from config import (HERMES_TERMINAL_UPSTREAM, HERMES_TERMINAL_PATH, BOX_CONSOLE_UPSTREAM,
from config import (BOX_CONSOLE_UPSTREAM,
BOX_CONSOLE_PATH, HERMES_BUILTIN_UI_UPSTREAM, HERMES_BUILTIN_UI_PATH,
HERMES_API_URL, HERMES_HOME, PC_EXECUTOR_URL)
@@ -141,17 +141,15 @@ def agent_status() -> dict:
return {
"gateway_url": HERMES_API_URL,
# Interaktives Web-Terminal (ttyd → `hermes chat`): same-origin über MC2 geproxyt.
"terminal_url": HERMES_TERMINAL_PATH,
# Box-Konsole (ttyd → Login-Shell): same-origin über MC2 geproxyt (/console/).
"box_console_url": BOX_CONSOLE_PATH,
# Eingebaute Hermes-Web-GUI (hermes serve): same-origin über MC2 geproxyt (/hermes-ui/).
# Seit dem Umzug auf Hermes Desktop ist :9119 zugleich das Desktop-Gateway.
"hermes_ui_url": HERMES_BUILTIN_UI_PATH,
"gateway_reachable": _reach(HERMES_API_URL, "/health"),
# Erreichbarkeit der lokalen ttyd-Upstreams (Loopback, je base-path).
"terminal_reachable": _reach(HERMES_TERMINAL_UPSTREAM, "/hermes-terminal/"),
# Erreichbarkeit des lokalen ttyd-Upstreams (Loopback, base-path /console).
"box_console_reachable": _reach(BOX_CONSOLE_UPSTREAM, "/console/"),
# Erreichbarkeit der eingebauten Hermes-GUI (Loopback :9119).
# Erreichbarkeit der eingebauten Hermes-GUI / des Desktop-Gateways (Loopback :9119).
"hermes_ui_reachable": _reach(HERMES_BUILTIN_UI_UPSTREAM, "/"),
"home_exists": home.exists(),
"brain_model": brain_model,
+1 -1
View File
@@ -19,7 +19,7 @@ from services import catalog, discover, jobengine, llamaswap, system
# System-Dienste (root, via sudo -n NOPASSWD) vs. User-Dienste (systemctl --user).
SYSTEM_SERVICES = {"llama-swap"}
USER_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-terminal", "mem0-service", "voice-service"}
USER_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-builtin-ui", "mem0-service", "voice-service"}
# Engine-Update: lädt den neuesten Vulkan-Build (deploy/update-engine.sh, läuft als root).
_REPO_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))
-2
View File
@@ -117,7 +117,6 @@ def find_hermes_agent_git() -> dict | None:
candidates = [
"~/hermes-agent",
"~/.hermes/hermes-agent",
"~/hermes-webui/hermes-agent",
"~/.hermes"
]
for c in candidates:
@@ -179,7 +178,6 @@ def check_versions_cached() -> dict:
data = {
"mc2": get_git_info(mc2_path),
"engine": get_engine_version(),
"hermes_ui": get_git_info("~/hermes-webui"),
"hermes_agent": find_hermes_agent_git()
}
_VERSION_CACHE["ts"] = now
+6 -5
View File
@@ -49,9 +49,12 @@ fi
# systemd-USER-Units installieren/aktualisieren
mkdir -p "$HOME/.config/systemd/user"
cp "$SRC/deploy/mission-control-2.service" "$HOME/.config/systemd/user/mission-control-2.service"
# Hermes-Terminal (ttyd -> `hermes chat`), in MC2 als Terminal-Seite eingebettet.
# Einmalig manuell noetig: `sudo apt install -y ttyd` + `sudo systemctl disable --now ttyd` (apt-Default-Dienst).
cp "$SRC/deploy/hermes-terminal.service" "$HOME/.config/systemd/user/hermes-terminal.service"
# MC2-Diät (Hermes Desktop, 07/2026): das Hermes-Terminal-ttyd (:7681) und das standalone
# hermes-webui (nesquena, Karteileiche seit dem Built-in-UI-Umbau) sind entfallen — die
# Agent-Oberfläche ist die Desktop-App bzw. /hermes-ui/. Einmalige, idempotente Stilllegung:
systemctl --user disable --now hermes-terminal 2>/dev/null || true
systemctl --user disable --now hermes-webui 2>/dev/null || true
rm -f "$HOME/.config/systemd/user/hermes-terminal.service" "$HOME/.config/systemd/user/hermes-webui.service"
# Box-Konsole (ttyd -> Login-Shell auf :7682), in MC2 als Konsole-Seite eingebettet.
cp "$SRC/deploy/box-console.service" "$HOME/.config/systemd/user/box-console.service"
# Mem0-Sidecar-Unit (nur wenn das venv existiert).
@@ -110,7 +113,6 @@ if [ -d "$_HUI_WEB" ] && [ -x "$HOME/.hermes/node/bin/npx" ]; then
fi
systemctl --user daemon-reload
systemctl --user enable mission-control-2 >/dev/null 2>&1 || true
systemctl --user enable hermes-terminal >/dev/null 2>&1 || true
systemctl --user enable box-console >/dev/null 2>&1 || true
systemctl --user enable mem0-service >/dev/null 2>&1 || true
systemctl --user enable voice-service >/dev/null 2>&1 || true
@@ -128,7 +130,6 @@ loginctl enable-linger "$USER" >/dev/null 2>&1 || true
systemctl --user reset-failed hermes-builtin-ui 2>/dev/null || true
systemctl --user restart hermes-builtin-ui 2>/dev/null || true
systemctl --user restart mission-control-2
command -v ttyd >/dev/null 2>&1 && systemctl --user restart hermes-terminal 2>/dev/null || true
command -v ttyd >/dev/null 2>&1 && systemctl --user restart box-console 2>/dev/null || true
sleep 2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+15 -15
View File
@@ -1,16 +1,16 @@
<!doctype html>
<html lang="de" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0d1117" />
<link rel="manifest" href="/manifest.webmanifest" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>Mission Control 2.0</title>
<script type="module" crossorigin src="/assets/index-CcL1k1kt.js"></script>
<!doctype html>
<html lang="de" class="dark">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#0d1117" />
<link rel="manifest" href="/manifest.webmanifest" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>Mission Control 2.0</title>
<script type="module" crossorigin src="/assets/index-ieP3mTAf.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B7apENt0.css">
</head>
<body>
<div id="root"></div>
</body>
</html>
</head>
<body>
<div id="root"></div>
</body>
+1 -6
View File
@@ -7,7 +7,6 @@ import { ModelsView } from "@/views/ModelsView"
import { ConnectView } from "@/views/ConnectView"
import { MemoryView } from "@/views/MemoryView"
import { AgentView } from "@/views/AgentView"
import { TerminalView } from "@/views/TerminalView"
import { KonsoleView } from "@/views/KonsoleView"
import { GuideView } from "@/views/GuideView"
import { Placeholder } from "@/views/Placeholder"
@@ -188,9 +187,6 @@ export default function App() {
<div className="truncate" title={sysStatus.versions.engine?.type === "git" ? `${sysStatus.versions.engine.branch}-${sysStatus.versions.engine.hash}${sysStatus.versions.engine.dirty ? "*" : ""} (${sysStatus.versions.engine.date})` : sysStatus.versions.engine?.version_text || "unbekannt"}>
<strong>Engine:</strong> {sysStatus.versions.engine?.type === "git" ? `${sysStatus.versions.engine.hash}${sysStatus.versions.engine.dirty ? "*" : ""}` : (sysStatus.versions.engine?.version_text?.split(" ").pop() || "—")}
</div>
<div className="truncate" title={sysStatus.versions.hermes_ui ? `${sysStatus.versions.hermes_ui.branch}-${sysStatus.versions.hermes_ui.hash}${sysStatus.versions.hermes_ui.dirty ? "*" : ""} (${sysStatus.versions.hermes_ui.date})` : "nicht gefunden"}>
<strong>Hermes UI:</strong> {sysStatus.versions.hermes_ui ? `${sysStatus.versions.hermes_ui.hash}${sysStatus.versions.hermes_ui.dirty ? "*" : ""}` : "—"}
</div>
<div className="truncate" title={sysStatus.versions.hermes_agent ? `${sysStatus.versions.hermes_agent.branch}-${sysStatus.versions.hermes_agent.hash}${sysStatus.versions.hermes_agent.dirty ? "*" : ""} (${sysStatus.versions.hermes_agent.date})` : "nicht gefunden"}>
<strong>Hermes Agent:</strong> {sysStatus.versions.hermes_agent ? `${sysStatus.versions.hermes_agent.hash}${sysStatus.versions.hermes_agent.dirty ? "*" : ""}` : "—"}
</div>
@@ -240,10 +236,9 @@ export default function App() {
{view === "wissen" && <WissenView />}
{view === "chronik" && <ChronikView />}
{view === "agent" && <AgentView />}
{view === "terminal" && <TerminalView />}
{view === "konsole" && <KonsoleView />}
{view === "guide" && <GuideView />}
{!["dashboard", "auftraege", "models", "connect", "memory", "wissen", "chronik", "agent", "terminal", "konsole", "guide"].includes(view) && (
{!["dashboard", "auftraege", "models", "connect", "memory", "wissen", "chronik", "agent", "konsole", "guide"].includes(view) && (
<Placeholder title={active.label} hint={active.hint} />
)}
</main>
@@ -33,19 +33,19 @@ export function AgentStatusCard() {
<Bot className="h-4.5 w-4.5 text-primary" />
<h2 className="text-sm font-semibold tracking-wide uppercase text-foreground">Hermes Agent</h2>
</div>
{agent?.terminal_url && (
{agent?.hermes_ui_url && (
<a
href={resolveExternalUrl(agent.terminal_url)}
href={resolveExternalUrl(agent.hermes_ui_url)}
target="_blank"
rel="noopener"
className={cn(
"flex items-center gap-1 px-3 py-1 rounded-lg text-xs font-medium transition-all",
agent.terminal_reachable
agent.hermes_ui_reachable
? "bg-primary text-primary-foreground hover:opacity-90 shadow-md shadow-primary/20"
: "border border-border text-muted-foreground"
)}
>
<ExternalLink className="h-3 w-3" /> Terminal öffnen
<ExternalLink className="h-3 w-3" /> GUI öffnen
</a>
)}
</div>
@@ -60,10 +60,10 @@ export function AgentStatusCard() {
</div>
</div>
<div className="p-3 bg-background/20 rounded-xl border border-border/40">
<div className="text-[10px] text-muted-foreground uppercase font-semibold">Terminal</div>
<div className="text-[10px] text-muted-foreground uppercase font-semibold">Desktop-Gateway</div>
<div className="flex items-center gap-2 mt-1">
<span className={cn("h-2 w-2 rounded-full", agent.terminal_reachable ? "bg-emerald-500 animate-pulse" : "bg-amber-500")} />
<span className="text-xs font-medium">{agent.terminal_reachable ? "Online" : "Offline"}</span>
<span className={cn("h-2 w-2 rounded-full", agent.hermes_ui_reachable ? "bg-emerald-500 animate-pulse" : "bg-amber-500")} />
<span className="text-xs font-medium">{agent.hermes_ui_reachable ? "Online" : "Offline"}</span>
</div>
</div>
<div
+1 -1
View File
@@ -9,7 +9,7 @@ export const SERVICES = [
{ id: "hermes-gateway", label: "Hermes Gateway", type: "user", reach: "hermes-gateway" },
{ id: "mem0-service", label: "Mem0 (Gedächtnis)", type: "user", reach: "mem0" },
{ id: "voice-service", label: "Voice (Sprache)", type: "user", reach: "voice" },
{ id: "hermes-terminal", label: "Hermes Terminal", type: "user", reach: "hermes-terminal" },
{ id: "hermes-builtin-ui", label: "Hermes GUI (Desktop-Gateway)", type: "user", reach: "hermes-gui" },
{ id: "llama-swap", label: "Llama Swap", type: "system", reach: "llama-swap" },
]
+1 -4
View File
@@ -249,7 +249,6 @@ export interface ComponentVersion {
export interface Versions {
mc2: GitInfo | null
engine: ComponentVersion
hermes_ui: GitInfo | null
hermes_agent: GitInfo | null
}
@@ -270,7 +269,7 @@ export interface SystemStatus {
export interface ServicesResp {
services: { name: string; unit: string; url: string; ok: boolean }[]
links: { engine_ui: string; gateway: string; hermes_terminal: string }
links: { engine_ui: string; gateway: string; hermes_ui: string }
}
export interface ComponentUpdate {
@@ -371,11 +370,9 @@ export interface DedupeResult {
export interface AgentStatus {
gateway_url: string
terminal_url: string
box_console_url?: string
hermes_ui_url?: string
gateway_reachable: boolean
terminal_reachable: boolean
box_console_reachable?: boolean
hermes_ui_reachable?: boolean
home_exists: boolean
+1 -3
View File
@@ -7,13 +7,12 @@ import {
Library,
Plug,
Bot,
AppWindow,
SquareTerminal,
HelpCircle,
type LucideIcon,
} from "lucide-react"
export type ViewId = "dashboard" | "auftraege" | "models" | "memory" | "wissen" | "chronik" | "connect" | "agent" | "terminal" | "konsole" | "guide"
export type ViewId = "dashboard" | "auftraege" | "models" | "memory" | "wissen" | "chronik" | "connect" | "agent" | "konsole" | "guide"
export interface NavItem {
id: ViewId
@@ -32,7 +31,6 @@ export const NAV: NavItem[] = [
{ id: "chronik", label: "Chronik", hint: "Was die Box von allein getan hat + Zeitmaschine", icon: History },
{ id: "connect", label: "Verbinden", hint: "IDE-/Agent-Configs erzeugen", icon: Plug },
{ id: "agent", label: "Hermes", hint: "Agent-Status & Verdrahtung", icon: Bot },
{ id: "terminal", label: "Hermes GUI", hint: "Eingebaute Hermes-Weboberfläche (Threads & Tool-Calls)", icon: AppWindow },
{ id: "konsole", label: "Konsole", hint: "Direkte Box-Shell (SSH-artig)", icon: SquareTerminal },
{ id: "guide", label: "Anleitung", hint: "Einrichten & Vibe-Coding", icon: HelpCircle },
]
+11 -11
View File
@@ -56,20 +56,20 @@ export function AgentView() {
</p>
</div>
{s?.terminal_url && (
{s?.hermes_ui_url && (
<a
href={resolveExternalUrl(s.terminal_url)}
href={resolveExternalUrl(s.hermes_ui_url)}
target="_blank"
rel="noopener"
className={cn(
"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.terminal_reachable
s.hermes_ui_reachable
? "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" />
<span>Terminal öffnen</span>
<span>Hermes-GUI öffnen</span>
</a>
)}
</div>
@@ -92,16 +92,16 @@ export function AgentView() {
<div className="flex flex-col lg:flex-row lg:items-stretch gap-3">
{/* Quelle: Terminal/Clients */}
<button
onClick={() => s.terminal_reachable && window.open(resolveExternalUrl(s.terminal_url), "_blank")}
title={s.terminal_reachable ? "Hermes-Terminal öffnen" : "Terminal offline"}
onClick={() => s.hermes_ui_reachable && window.open(resolveExternalUrl(s.hermes_ui_url), "_blank")}
title={s.hermes_ui_reachable ? "Hermes-GUI öffnen" : "Desktop-Gateway offline"}
className="lg:w-40 shrink-0 rounded-xl border border-border/60 bg-background/30 p-3 text-left hover:border-primary/40 transition-all cursor-pointer flex flex-col justify-center"
>
<div className="flex items-center gap-1.5">
<Activity className={cn("h-3.5 w-3.5", s.terminal_reachable ? "text-emerald-400" : "text-amber-500")} />
<span className="text-xs font-semibold text-foreground">Terminal</span>
<span className={cn("ml-auto h-1.5 w-1.5 rounded-full animate-pulse", s.terminal_reachable ? "bg-emerald-500" : "bg-amber-500")} />
<Activity className={cn("h-3.5 w-3.5", s.hermes_ui_reachable ? "text-emerald-400" : "text-amber-500")} />
<span className="text-xs font-semibold text-foreground">Desktop &amp; GUI</span>
<span className={cn("ml-auto h-1.5 w-1.5 rounded-full animate-pulse", s.hermes_ui_reachable ? "bg-emerald-500" : "bg-amber-500")} />
</div>
<span className="text-[10px] text-muted-foreground font-mono mt-0.5">hermes chat · Clients</span>
<span className="text-[10px] text-muted-foreground font-mono mt-0.5">Hermes Desktop · Clients</span>
</button>
<div className="hidden lg:flex items-center text-muted-foreground text-lg select-none"></div>
@@ -235,7 +235,7 @@ export function AgentView() {
<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-terminal</div>
<div className="text-primary">systemctl --user status hermes-builtin-ui</div>
</div>
<p>
-56
View File
@@ -1,56 +0,0 @@
import { Bot, ExternalLink, AlertTriangle } from "lucide-react"
import { useAgentStatus } from "@/lib/queries"
import { resolveExternalUrl } from "@/lib/utils"
export function TerminalView() {
const { data: agent } = useAgentStatus(5_000)
const url = agent?.hermes_ui_url ? resolveExternalUrl(agent.hermes_ui_url) : undefined
const ok = agent?.hermes_ui_reachable
return (
<div className="flex h-full flex-col gap-4">
<div className="flex flex-wrap items-end justify-between gap-3">
<div>
<h1 className="bg-gradient-to-r from-foreground via-foreground to-primary bg-clip-text font-space text-2xl font-bold tracking-tight text-transparent">
Hermes GUI
</h1>
<p className="flex items-center gap-2 text-sm text-muted-foreground">
Die eingebaute Hermes-Weboberfläche Threads, sichtbare Tool-Calls &amp; Chat, direkt im Cockpit statt im Terminal.
</p>
</div>
<div className="flex items-center gap-3">
<span className="flex items-center gap-1.5 text-[11px] font-medium text-muted-foreground">
<span className={`h-2 w-2 rounded-full ${ok ? "bg-emerald-500 animate-pulse" : "bg-amber-500"}`} />
{ok ? "online" : "offline"}
</span>
{url && (
<a href={url} target="_blank" rel="noopener"
className="flex h-8 items-center gap-1.5 rounded-lg border border-border/60 bg-background/20 px-3 text-xs font-semibold text-muted-foreground transition-all hover:border-primary/50 hover:text-foreground">
<ExternalLink className="h-3.5 w-3.5" /> In neuem Tab
</a>
)}
</div>
</div>
{url ? (
<div className="relative min-h-[68vh] flex-1 overflow-hidden rounded-2xl border border-border/60 bg-black/50 shadow-lg shadow-black/25">
{ok === false && (
<div className="absolute inset-0 z-10 flex flex-col items-center justify-center gap-3 bg-black/70 text-center">
<AlertTriangle className="h-8 w-8 text-amber-400" />
<div className="text-sm font-semibold text-amber-300">Hermes-GUI nicht erreichbar</div>
<p className="max-w-sm text-[11px] leading-normal text-muted-foreground">
Der <code className="font-mono text-primary">hermes-builtin-ui</code>-Dienst (<code className="font-mono">hermes serve</code>) läuft nicht.
Auf der Box: <code className="font-mono">systemctl --user restart hermes-builtin-ui</code>.
</p>
</div>
)}
<iframe src={url} title="Hermes GUI" className="h-full w-full border-0" style={{ minHeight: "68vh" }} />
</div>
) : (
<div className="flex min-h-[68vh] flex-1 items-center justify-center rounded-2xl border border-border/60 bg-background/20 text-xs text-muted-foreground">
<Bot className="mr-2 h-4 w-4" /> Lade Hermes-GUI
</div>
)}
</div>
)
}
+11 -1
View File
@@ -1,5 +1,5 @@
import { useState } from "react"
import { Download, Star, Layers, Check, Zap, Eye, Code, Brain, BrainCircuit, Compass, ChevronDown, ChevronUp } from "lucide-react"
import { Download, Star, Layers, Check, Zap, Eye, Code, Brain, BrainCircuit, Compass, ChevronDown, ChevronUp, Scale, Search } from "lucide-react"
import { api } from "@/lib/api"
import { useModels, useUpdates, useDiscover } from "@/lib/queries"
import { cn } from "@/lib/utils"
@@ -38,6 +38,16 @@ const ROLE_METADATA: Record<string, { title: string; desc: string; icon: any }>
title: "Multimodal-Allrounder",
desc: "Multimodaler Allrounder für schnelle Antworten, Übersetzungen und Alltag.",
icon: Compass
},
kritiker: {
title: "Kritisches Prüf-Hirn",
desc: "Schärfer Blick für Fehler, Schwachstellen und Sicherheitslücken — denkt skeptisch, bevor du deployst.",
icon: Scale
},
reranker: {
title: "Gedächtnis-Sortierer",
desc: "Sortiert und gewichtet gespeicherte Fakten nach Relevanz — damit die richtige Info sofort da ist.",
icon: Search
}
}