MC2-Diät: Hermes-Fenster-Rolle an Hermes Desktop abgegeben
Der "Hermes GUI"-Tab (iframe auf /hermes-ui/) und das Hermes-Terminal-ttyd (:7681) entfallen — die Agent-Oberfläche ist jetzt die Hermes-Desktop-App, die über den BESTEHENDEN MC2-Proxy /hermes-ui/ (WS inklusive) an die Box andockt. hermes-builtin-ui (:9119) bleibt als Desktop-Gateway erhalten und wird im Dienste-Drawer + /api/system/services erstklassig geführt (statt hermes-terminal); Wartungs-Allowlist kann ihn jetzt neu starten. - Frontend: Tab/View raus (nav.ts, App.tsx, TerminalView.tsx gelöscht), AgentView + (Legacy-)AgentStatusCard zeigen Desktop-Gateway statt ttyd, Dienste-Zeile hermes-terminal → hermes-builtin-ui, Versions-Zeile "Hermes UI" (nesquena-Karteileiche ~/hermes-webui) entfernt. - Backend: terminal_url/terminal_reachable + HERMES_TERMINAL_* raus, console.py proxyt nur noch die Box-Konsole, /api/system/services führt hermes-builtin-ui, USER_SERVICES getauscht, hermes-webui-GitInfo raus. - deploy.sh: legt hermes-terminal + hermes-webui idempotent still (disable --now + Unit-Löschung). deploy/hermes-terminal.service bleibt EINEN Zyklus im Repo (das laufende alte deploy.sh kopiert es noch — Selbst-Reset-Falle); Aufräum-Commit folgt nach dem nächsten Deploy. - frontend/dist mit-committet (Box baut nicht selbst). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
File diff suppressed because one or more lines are too long
+169
-174
File diff suppressed because one or more lines are too long
Vendored
+15
-15
@@ -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-1tNxUTCg.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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" },
|
||||
]
|
||||
|
||||
|
||||
@@ -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
@@ -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 },
|
||||
]
|
||||
|
||||
@@ -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 & 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>
|
||||
|
||||
@@ -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 & 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>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user