Feat: Engine-Update-Mechanismus + Update-Checks (Hermes Agent/AnythingLLM) + WebUI->AnythingLLM

- Engine-Update: deploy/update-engine.sh laedt neuesten ggml-org Vulkan-Build + restart;
  MC_ENGINE_UPDATE_CMD verdrahtet, engine_update_job nutzt es (Script macht Restart selbst).
- Update-Checks: Hermes Agent (NousResearch/hermes-agent, Release-Datum vs. installiertes Commit)
  + AnythingLLM (Mintplex-Labs/anything-llm, neueste Version + /api/ping-Health), 1h-Cache.
  Neues Feld /api/maintenance/updates.components; UpdatesCard zeigt beide Zeilen.
- WebUI -> AnythingLLM: agent_status.webui_* zeigt jetzt auf ANYTHINGLLM_URL (192.168.178.155:3001,
  /api/ping); alle "Hermes WebUI"-Buttons/Labels (AgentView, AgentStatusCard, nav, GuideView,
  Services-Liste) -> "AnythingLLM". Lokaler hermes-webui-Dienst bleibt als Service-Control im SystemDrawer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-27 02:12:56 +02:00
parent c48e583790
commit 65d8ab5fe3
14 changed files with 571 additions and 421 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -7,7 +7,7 @@
<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-DPqptZjm.js"></script>
<script type="module" crossorigin src="/assets/index-D9tRIUA4.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CjZVMvhL.css">
</head>
<body>
@@ -45,7 +45,7 @@ export function AgentStatusCard() {
: "border border-border text-muted-foreground"
)}
>
<ExternalLink className="h-3 w-3" /> Hermes öffnen
<ExternalLink className="h-3 w-3" /> AnythingLLM öffnen
</a>
)}
</div>
@@ -60,7 +60,7 @@ 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">WebUI</div>
<div className="text-[10px] text-muted-foreground uppercase font-semibold">AnythingLLM</div>
<div className="flex items-center gap-2 mt-1">
<span className={cn("h-2 w-2 rounded-full", agent.webui_reachable ? "bg-emerald-500 animate-pulse" : "bg-amber-500")} />
<span className="text-xs font-medium">{agent.webui_reachable ? "Online" : "Offline"}</span>
@@ -210,6 +210,35 @@ export function UpdatesCard() {
<span>Modell-Upgrades</span>
<span className="font-mono">{updates.models > 0 ? `${updates.models} verfügbar` : "aktuell"}</span>
</div>
{/* Komponenten: Hermes Agent + AnythingLLM */}
{updates.components?.map((c) => {
const isUpdate = c.update === true
return (
<div key={c.key} className={cn(
"flex items-center justify-between px-3 py-1.5 rounded-lg border text-xs",
isUpdate
? "border-amber-500/30 bg-amber-500/5 text-amber-400 font-semibold"
: "border-border/30 bg-background/25 text-muted-foreground"
)}>
<span className="flex items-center gap-1.5">
{c.name}
{c.reachable === false && (
<span className="text-[8px] font-bold uppercase text-red-400/80">offline</span>
)}
</span>
<span className="font-mono text-[10px]" title={c.current ? `installiert: ${c.current}` : undefined}>
{isUpdate
? `Update: ${c.latest}`
: c.update === false
? "aktuell"
: c.latest
? `neueste: ${c.latest}`
: "—"}
</span>
</div>
)
})}
</div>
<div className="grid grid-cols-2 gap-2 border-t border-border/20 pt-3">
+10
View File
@@ -202,12 +202,22 @@ export interface ServicesResp {
links: { engine_ui: string; gateway: string; hermes_webui: string }
}
export interface ComponentUpdate {
key: string // "hermes_agent" | "anythingllm"
name: string
current: string | null
latest: string | null
update: boolean | null // null = unbestimmbar (z.B. AnythingLLM-Version remote nicht abfragbar)
reachable: boolean | null
}
export interface UpdatesResp {
os: number
engine: number
models: number
model_list: { role: string; title: string; repo: string }[]
last_check?: number | null
components?: ComponentUpdate[]
}
export interface ConnectTool {
+1 -1
View File
@@ -25,7 +25,7 @@ export const NAV: NavItem[] = [
{ id: "system", label: "Diagnose", hint: "Metriken, Dienste, Logs", icon: Cpu },
{ id: "memory", label: "Gedächtnis", hint: "Geteiltes Memory verwalten", icon: Brain },
{ id: "connect", label: "Verbinden", hint: "IDE-/Agent-Configs erzeugen", icon: Plug },
{ id: "agent", label: "Hermes", hint: "Agent-Status & WebUI öffnen", icon: Bot },
{ id: "agent", label: "Hermes", hint: "Agent-Status & AnythingLLM öffnen", icon: Bot },
{ id: "guide", label: "Anleitung", hint: "Einrichten & Vibe-Coding", icon: HelpCircle },
]
+8 -8
View File
@@ -148,7 +148,7 @@ export function AgentView() {
)}
>
<ExternalLink className="h-4 w-4" />
<span>Hermes WebUI öffnen</span>
<span>AnythingLLM öffnen</span>
</a>
)}
</div>
@@ -169,11 +169,11 @@ export function AgentView() {
detail="Port :8642 (REST API)"
icon={Bot}
/>
<Tile
label="Agent WebUI"
ok={s.webui_reachable}
detail="Port :8787 (Chat UI)"
icon={Activity}
<Tile
label="AnythingLLM"
ok={s.webui_reachable}
detail="Chat-UI (AnythingLLM)"
icon={Activity}
/>
<Tile
label="Aktives Gehirn"
@@ -239,10 +239,10 @@ export function AgentView() {
onMouseEnter={() => setHoveredNode("webui")}
onMouseLeave={() => setHoveredNode(null)}
onClick={() => s.webui_reachable && window.open(resolveExternalUrl(s.webui_url), "_blank")}
title={s.webui_reachable ? "Klicken um Chat-WebUI zu öffnen" : "WebUI Offline"}
title={s.webui_reachable ? "Klicken um AnythingLLM zu öffnen" : "AnythingLLM offline"}
>
<Activity className={cn("h-3.5 w-3.5", s.webui_reachable ? "text-emerald-400" : "text-amber-500")} />
<span>Agent WebUI</span>
<span>AnythingLLM</span>
<span className={cn("w-1.5 h-1.5 rounded-full animate-pulse ml-auto", s.webui_reachable ? "bg-emerald-500" : "bg-amber-500")} />
</div>
+2 -2
View File
@@ -329,7 +329,7 @@ export function GuideView() {
<ul className="text-[11px] text-muted-foreground space-y-2 list-disc pl-4 leading-relaxed">
<li><strong>Keine Verbindung?</strong> Überprüfe im Live-Verbindungsprüfer oben, ob die Box-IP erreichbar ist. Stelle sicher, dass dein lokaler PC im selben WLAN/LAN-Netzwerk wie die Box eingeloggt ist.</li>
<li><strong>Modell antwortet nicht?</strong> Schaue unter <strong>Diagnose</strong>, ob der Dienst `llama-swap` aktiv (grün) is. Wenn nicht, klicke daneben auf <strong>Restart</strong>.</li>
<li><strong>Hermes Agent reagiert merkwürdig?</strong> Starte in der Hermes WebUI einfach eine frische Session (neuen Chat). Ältere Chats sammeln Kontext-Müll an.</li>
<li><strong>Hermes Agent reagiert merkwürdig?</strong> Starte in AnythingLLM einfach eine frische Session (neuen Chat). Ältere Chats sammeln Kontext-Müll an.</li>
</ul>
</div>
</>
@@ -474,7 +474,7 @@ description: Drive development with strict TDD practices
<ul className="list-disc pl-4 space-y-1">
<li><strong>Chat-Kontext sauber halten:</strong> Starte regelmäßig neue Chats. Zu große Historien verlangsamen den Agenten und führen zu Halluzinationen.</li>
<li><strong>Gehirn festlegen:</strong> Konfiguriere im Gateway die Modell-Rolle <code>brain</code> für Hermes, damit er automatisch das passende Modell per Llama Swap lädt.</li>
<li><strong>Sandbox umgehen:</strong> Erweitere Hermes' System-Prompt (WebUI-Einstellungen), um Befehle über SSH an deinen Windows-PC zu leiten.</li>
<li><strong>Sandbox umgehen:</strong> Erweitere Hermes' System-Prompt (AnythingLLM-Einstellungen), um Befehle über SSH an deinen Windows-PC zu leiten.</li>
</ul>
</div>
</div>