feat(2.0): Phase 4 — Hermes-Schicht (MC-Seite + Runbook)
MC-Seite: services/agent.py + routers/agent.py (GET /api/agent/status: Gateway/WebUI-Reachability + Verdrahtungs-Hinweise), AgentView (Status- Tiles, Hermes-oeffnen-Button, Offline-Hinweis). deploy/hermes-webui.service (systemd-USER, :8787). Box-Runbook docs/HERMES_SETUP.md (hermes-webui installieren, Brain=model:auto via Gateway, Tools/MCP verdrahten inkl. mcp_mc+mcp_memory, SSH-Windows, LiteLLM-Caveat #26489). Lokal verifiziert: agent/status + Frontend-Build + Browser (Hermes-View). Box-Ausfuehrung der Verdrahtung steht aus (Runbook). Docs aktualisiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
-160
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+165
File diff suppressed because one or more lines are too long
Vendored
+2
-2
@@ -6,8 +6,8 @@
|
||||
<meta name="theme-color" content="#0d1117" />
|
||||
<link rel="manifest" href="/manifest.webmanifest" />
|
||||
<title>Mission Control 2.0</title>
|
||||
<script type="module" crossorigin src="/assets/index-ByXSUESS.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CE_qxW4X.css">
|
||||
<script type="module" crossorigin src="/assets/index-umMcKqw6.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-nVsgoG2p.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { RoutingView } from "@/views/RoutingView"
|
||||
import { SystemView } from "@/views/SystemView"
|
||||
import { ConnectView } from "@/views/ConnectView"
|
||||
import { MemoryView } from "@/views/MemoryView"
|
||||
import { AgentView } from "@/views/AgentView"
|
||||
import { Placeholder } from "@/views/Placeholder"
|
||||
import { api, type Health } from "@/lib/api"
|
||||
import { cn } from "@/lib/utils"
|
||||
@@ -96,7 +97,8 @@ export default function App() {
|
||||
{view === "system" && <SystemView />}
|
||||
{view === "connect" && <ConnectView />}
|
||||
{view === "memory" && <MemoryView />}
|
||||
{!["models", "routing", "system", "connect", "memory"].includes(view) && (
|
||||
{view === "agent" && <AgentView />}
|
||||
{!["models", "routing", "system", "connect", "memory", "agent"].includes(view) && (
|
||||
<Placeholder title={active.label} hint={active.hint} />
|
||||
)}
|
||||
</main>
|
||||
|
||||
@@ -116,6 +116,17 @@ export interface DedupeResult {
|
||||
applied: boolean
|
||||
}
|
||||
|
||||
export interface AgentStatus {
|
||||
gateway_url: string
|
||||
webui_url: string
|
||||
gateway_reachable: boolean
|
||||
webui_reachable: boolean
|
||||
home_exists: boolean
|
||||
has_config: boolean
|
||||
has_skills: boolean
|
||||
has_memories: boolean
|
||||
}
|
||||
|
||||
export interface Health {
|
||||
status: string
|
||||
version: string
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { ExternalLink } 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 }) {
|
||||
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>
|
||||
{detail && <div className="mt-1 text-xs text-muted-foreground">{detail}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function AgentView() {
|
||||
const [s, setS] = useState<AgentStatus | null>(null)
|
||||
const [error, setError] = useState("")
|
||||
|
||||
useEffect(() => {
|
||||
const load = () => api<AgentStatus>("/api/agent/status").then(setS).catch((e) => setError(String(e)))
|
||||
load()
|
||||
const t = setInterval(load, 8000)
|
||||
return () => clearInterval(t)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-start justify-between">
|
||||
<div>
|
||||
<h1 className="text-xl font-semibold">Hermes</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.
|
||||
</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",
|
||||
s.webui_reachable
|
||||
? "bg-primary text-primary-foreground hover:opacity-90"
|
||||
: "border border-border text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
<ExternalLink className="h-4 w-4" /> Hermes öffnen
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{error && <div className="text-sm text-muted-foreground">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: auto (über Gateway)" />
|
||||
<Tile label="Verdrahtung" ok={s.has_config} detail={`config ${s.has_config ? "✓" : "—"} · skills ${s.has_skills ? "✓" : "—"} · memories ${s.has_memories ? "✓" : "—"}`} />
|
||||
</div>
|
||||
|
||||
{!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>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user