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
+6 -1
View File
@@ -53,9 +53,14 @@ HF_DOWNLOAD_ENV = {"HF_HUB_DISABLE_XET": "1"}
GATEWAY_URL = os.environ.get("MC_GATEWAY_URL", f"http://127.0.0.1:{os.environ.get('MC_PORT', '9000')}").rstrip("/") GATEWAY_URL = os.environ.get("MC_GATEWAY_URL", f"http://127.0.0.1:{os.environ.get('MC_PORT', '9000')}").rstrip("/")
# --- Hermes Agent (eigener Dienst auf der Box) ------------------------------- # --- Hermes Agent (eigener Dienst auf der Box) -------------------------------
# Gateway (OpenAI-API des Agenten) + standalone Web-UI (nesquena/hermes-webui). # Gateway (OpenAI-API des Agenten) + Chat-WebUI = AnythingLLM (eigener Host).
HERMES_API_URL = os.environ.get("HERMES_API_URL", "http://127.0.0.1:8642").rstrip("/") HERMES_API_URL = os.environ.get("HERMES_API_URL", "http://127.0.0.1:8642").rstrip("/")
HERMES_WEBUI_URL = os.environ.get("HERMES_WEBUI_URL", "http://127.0.0.1:8787").rstrip("/") HERMES_WEBUI_URL = os.environ.get("HERMES_WEBUI_URL", "http://127.0.0.1:8787").rstrip("/")
# AnythingLLM = die Chat-WebUI (löst nesquena/hermes-webui ab). Eigener Host im LAN.
ANYTHINGLLM_URL = os.environ.get("MC_ANYTHINGLLM_URL", "http://192.168.178.155:3001").rstrip("/")
# GitHub-Repos für Update-Checks.
HERMES_AGENT_REPO = os.environ.get("MC_HERMES_AGENT_REPO", "NousResearch/hermes-agent")
ANYTHINGLLM_REPO = os.environ.get("MC_ANYTHINGLLM_REPO", "Mintplex-Labs/anything-llm")
HERMES_HOME = Path(os.path.expanduser(os.environ.get("HERMES_HOME", "~/.hermes"))) HERMES_HOME = Path(os.path.expanduser(os.environ.get("HERMES_HOME", "~/.hermes")))
# PC Executor — läuft auf dem Windows-PC, erreichbar über LAN. # PC Executor — läuft auf dem Windows-PC, erreichbar über LAN.
PC_EXECUTOR_URL = os.environ.get("MC_PC_EXECUTOR_URL", "http://192.168.178.98:7777").rstrip("/") PC_EXECUTOR_URL = os.environ.get("MC_PC_EXECUTOR_URL", "http://192.168.178.98:7777").rstrip("/")
+3 -3
View File
@@ -12,7 +12,7 @@ import subprocess
from fastapi import APIRouter, HTTPException from fastapi import APIRouter, HTTPException
from pydantic import BaseModel from pydantic import BaseModel
from config import GATEWAY_URL, HERMES_API_URL, HERMES_WEBUI_URL, LLAMA_SWAP_URL from config import GATEWAY_URL, HERMES_API_URL, LLAMA_SWAP_URL
from services import backup as backup_svc from services import backup as backup_svc
from services.agent import agent_status from services.agent import agent_status
from services.gateway import gateway_reachable from services.gateway import gateway_reachable
@@ -46,12 +46,12 @@ def services() -> dict:
{"name": "Engine (llama-swap)", "url": LLAMA_SWAP_URL, "ok": engine_reachable()}, {"name": "Engine (llama-swap)", "url": LLAMA_SWAP_URL, "ok": engine_reachable()},
{"name": "Gateway (integriert)", "url": gw_url, "ok": gateway_reachable()}, {"name": "Gateway (integriert)", "url": gw_url, "ok": gateway_reachable()},
{"name": "Hermes-Gateway", "url": HERMES_API_URL, "ok": a["gateway_reachable"]}, {"name": "Hermes-Gateway", "url": HERMES_API_URL, "ok": a["gateway_reachable"]},
{"name": "Hermes-WebUI", "url": HERMES_WEBUI_URL, "ok": a["webui_reachable"]}, {"name": "AnythingLLM", "url": a["webui_url"], "ok": a["webui_reachable"]},
], ],
"links": { "links": {
"engine_ui": f"{LLAMA_SWAP_URL}/ui", "engine_ui": f"{LLAMA_SWAP_URL}/ui",
"gateway": gw_url, "gateway": gw_url,
"hermes_webui": HERMES_WEBUI_URL, "hermes_webui": a["webui_url"],
}, },
} }
+4 -3
View File
@@ -9,7 +9,7 @@ import os
import httpx import httpx
from config import HERMES_API_URL, HERMES_HOME, HERMES_WEBUI_URL, PC_EXECUTOR_URL from config import ANYTHINGLLM_URL, HERMES_API_URL, HERMES_HOME, PC_EXECUTOR_URL
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@@ -59,9 +59,10 @@ def agent_status() -> dict:
return { return {
"gateway_url": HERMES_API_URL, "gateway_url": HERMES_API_URL,
"webui_url": HERMES_WEBUI_URL, # Chat-WebUI ist jetzt AnythingLLM (eigener Host), nicht mehr hermes-webui :8787.
"webui_url": ANYTHINGLLM_URL,
"gateway_reachable": _reach(HERMES_API_URL, "/health"), "gateway_reachable": _reach(HERMES_API_URL, "/health"),
"webui_reachable": _reach(HERMES_WEBUI_URL), "webui_reachable": _reach(ANYTHINGLLM_URL, "/api/ping"),
"home_exists": home.exists(), "home_exists": home.exists(),
"brain_model": brain_model, "brain_model": brain_model,
# Best-effort: welche Verdrahtung lokal sichtbar ist (auf der Box aussagekräftig). # Best-effort: welche Verdrahtung lokal sichtbar ist (auf der Box aussagekräftig).
+79 -5
View File
@@ -15,13 +15,17 @@ from datetime import datetime
import httpx import httpx
import psutil import psutil
from services import discover, jobengine, llamaswap from config import ANYTHINGLLM_REPO, ANYTHINGLLM_URL, HERMES_AGENT_REPO
from services import discover, jobengine, llamaswap, system
# System-Dienste (root, via sudo -n NOPASSWD) vs. User-Dienste (systemctl --user). # System-Dienste (root, via sudo -n NOPASSWD) vs. User-Dienste (systemctl --user).
SYSTEM_SERVICES = {"llama-swap"} SYSTEM_SERVICES = {"llama-swap"}
USER_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-dashboard", "hermes-webui"} USER_SERVICES = {"mission-control-2", "hermes-gateway", "hermes-dashboard", "hermes-webui"}
ENGINE_UPDATE_CMD = os.environ.get("MC_ENGINE_UPDATE_CMD", "") # 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__), "..", ".."))
ENGINE_UPDATE_CMD = os.environ.get(
"MC_ENGINE_UPDATE_CMD", f"sudo bash {_REPO_ROOT}/deploy/update-engine.sh")
# Engine = offizieller Vulkan-Build von ggml-org/llama.cpp (RADV auf Strix Halo). # Engine = offizieller Vulkan-Build von ggml-org/llama.cpp (RADV auf Strix Halo).
ENGINE_PATH = os.environ.get("MC_ENGINE_PATH", "/opt/llamacpp-vulkan") ENGINE_PATH = os.environ.get("MC_ENGINE_PATH", "/opt/llamacpp-vulkan")
ENGINE_REPO = os.environ.get("MC_ENGINE_REPO", "ggml-org/llama.cpp") ENGINE_REPO = os.environ.get("MC_ENGINE_REPO", "ggml-org/llama.cpp")
@@ -82,6 +86,74 @@ def _engine_update_available() -> bool:
return avail return avail
_comp_cache = {"ts": 0.0, "data": []}
def _gh_latest(repo: str) -> dict | None:
"""Neuestes GitHub-Release {tag, published} oder None."""
try:
rel = httpx.get(f"https://api.github.com/repos/{repo}/releases/latest",
timeout=6, headers={"User-Agent": "MissionControl2"}).json()
return {"tag": str(rel.get("tag_name", "")), "published": rel.get("published_at")}
except Exception:
return None
def _commit_ts(path: str) -> int | None:
try:
p = subprocess.run(["git", "-C", os.path.expanduser(path), "log", "-1", "--format=%ct"],
capture_output=True, text=True, timeout=8)
return int(p.stdout.strip()) if p.returncode == 0 and p.stdout.strip() else None
except Exception:
return None
def _hermes_agent_update() -> dict:
"""Hermes-Agent: neuestes Release vs. installiertes git-Commit-Datum."""
info = {"key": "hermes_agent", "name": "Hermes Agent", "current": None,
"latest": None, "update": False, "reachable": None}
git = system.find_hermes_agent_git()
if git:
info["current"] = git.get("hash")
gh = _gh_latest(HERMES_AGENT_REPO)
if gh:
info["latest"] = gh["tag"]
ts = _commit_ts(git["path"]) if (git and git.get("path")) else None
if gh["published"] and ts:
try:
pub = datetime.fromisoformat(gh["published"].replace("Z", "+00:00")).timestamp()
info["update"] = pub > ts + 86400 # Release > installiertes Commit (+1 Tag Toleranz)
except Exception:
pass
return info
def _anythingllm_update() -> dict:
"""AnythingLLM: erreichbar? + neueste verfügbare Version. Installierte Version ist
remote nicht unauth. abfragbar → update=None (nur Info: neueste verfügbar)."""
reachable = False
try:
reachable = httpx.get(f"{ANYTHINGLLM_URL}/api/ping", timeout=4).status_code == 200
except Exception:
reachable = False
info = {"key": "anythingllm", "name": "AnythingLLM", "current": None,
"latest": None, "update": None, "reachable": reachable}
gh = _gh_latest(ANYTHINGLLM_REPO)
if gh:
info["latest"] = gh["tag"]
return info
def _components_cached() -> list[dict]:
"""Update-Status von Hermes-Agent + AnythingLLM (1h-Cache → GitHub schonen)."""
now = time.time()
if now - _comp_cache["ts"] < 3600 and _comp_cache["data"]:
return _comp_cache["data"]
data = [_hermes_agent_update(), _anythingllm_update()]
_comp_cache.update(ts=now, data=data)
return data
def model_upgrades() -> list[dict]: def model_upgrades() -> list[dict]:
"""Dynamisch: je discover-Kategorie das empfohlene Modell, das NOCH NICHT installiert ist, """Dynamisch: je discover-Kategorie das empfohlene Modell, das NOCH NICHT installiert ist,
aber NUR wenn für diese Rolle bereits irgendein Modell konfiguriert ist. aber NUR wenn für diese Rolle bereits irgendein Modell konfiguriert ist.
@@ -135,7 +207,8 @@ def _last_apt_update() -> float | None:
def updates() -> dict: def updates() -> dict:
ups = model_upgrades() ups = model_upgrades()
return {"os": _os_upgradable(), "engine": 1 if _engine_update_available() else 0, return {"os": _os_upgradable(), "engine": 1 if _engine_update_available() else 0,
"models": len(ups), "model_list": ups, "last_check": _last_apt_update()} "models": len(ups), "model_list": ups, "last_check": _last_apt_update(),
"components": _components_cached()}
def _run(cmd: list[str], sudo_password: str | None = None) -> dict: def _run(cmd: list[str], sudo_password: str | None = None) -> dict:
@@ -233,8 +306,9 @@ def engine_update_job(sudo_password: str | None = None) -> dict | None:
return None return None
if err := check_sudo_needs_password(sudo_password): if err := check_sudo_needs_password(sudo_password):
return err return err
cmd = f"{ENGINE_UPDATE_CMD} && sudo systemctl restart llama-swap" # update-engine.sh läuft via sudo als root und startet llama-swap am Ende selbst neu.
job_id = jobengine.start_job(["bash", "-c", cmd], "Engine-Update (llama.cpp)", sudo_password=sudo_password) job_id = jobengine.start_job(["bash", "-c", ENGINE_UPDATE_CMD],
"Engine-Update (llama.cpp Vulkan)", sudo_password=sudo_password)
return {"ok": True, "job_id": job_id} return {"ok": True, "job_id": job_id}
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Aktualisiert den Vulkan-llama.cpp-Build auf den neuesten ggml-org-Release.
# Wird vom MC2-„Engine Update"-Button via `sudo bash …` als ROOT aufgerufen
# (deshalb KEIN internes sudo). Startet llama-swap am Ende neu.
set -euo pipefail
VULKAN_DIR=/opt/llamacpp-vulkan
PIN_BUILD="${MC_ENGINE_BUILD:-}" # leer = neuester Release
if [ -n "$PIN_BUILD" ]; then
TAG="$PIN_BUILD"
else
TAG="$(curl -s https://api.github.com/repos/ggml-org/llama.cpp/releases/latest | jq -r .tag_name)"
fi
[ -n "$TAG" ] && [ "$TAG" != "null" ] || { echo "Konnte neuesten Release-Tag nicht ermitteln"; exit 1; }
ASSET="llama-${TAG}-bin-ubuntu-vulkan-x64.tar.gz"
URL="https://github.com/ggml-org/llama.cpp/releases/download/${TAG}/${ASSET}"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
echo "Lade Engine ${TAG}"
curl -fsSL -o "$TMP/v.tgz" "$URL"
tar xzf "$TMP/v.tgz" -C "$TMP"
mkdir -p "$VULKAN_DIR"
cp -rf "$TMP"/llama-*/. "$VULKAN_DIR"/
test -x "$VULKAN_DIR/llama-server"
ln -sfn "$VULKAN_DIR/llama-server" /usr/local/bin/llama-server
systemctl restart llama-swap
echo "Engine aktualisiert auf ${TAG} und llama-swap neugestartet."
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="manifest" href="/manifest.webmanifest" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<title>Mission Control 2.0</title> <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"> <link rel="stylesheet" crossorigin href="/assets/index-CjZVMvhL.css">
</head> </head>
<body> <body>
@@ -45,7 +45,7 @@ export function AgentStatusCard() {
: "border border-border text-muted-foreground" : "border border-border text-muted-foreground"
)} )}
> >
<ExternalLink className="h-3 w-3" /> Hermes öffnen <ExternalLink className="h-3 w-3" /> AnythingLLM öffnen
</a> </a>
)} )}
</div> </div>
@@ -60,7 +60,7 @@ export function AgentStatusCard() {
</div> </div>
</div> </div>
<div className="p-3 bg-background/20 rounded-xl border border-border/40"> <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"> <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={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> <span className="text-xs font-medium">{agent.webui_reachable ? "Online" : "Offline"}</span>
@@ -210,6 +210,35 @@ export function UpdatesCard() {
<span>Modell-Upgrades</span> <span>Modell-Upgrades</span>
<span className="font-mono">{updates.models > 0 ? `${updates.models} verfügbar` : "aktuell"}</span> <span className="font-mono">{updates.models > 0 ? `${updates.models} verfügbar` : "aktuell"}</span>
</div> </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>
<div className="grid grid-cols-2 gap-2 border-t border-border/20 pt-3"> <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 } 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 { export interface UpdatesResp {
os: number os: number
engine: number engine: number
models: number models: number
model_list: { role: string; title: string; repo: string }[] model_list: { role: string; title: string; repo: string }[]
last_check?: number | null last_check?: number | null
components?: ComponentUpdate[]
} }
export interface ConnectTool { 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: "system", label: "Diagnose", hint: "Metriken, Dienste, Logs", icon: Cpu },
{ id: "memory", label: "Gedächtnis", hint: "Geteiltes Memory verwalten", icon: Brain }, { id: "memory", label: "Gedächtnis", hint: "Geteiltes Memory verwalten", icon: Brain },
{ id: "connect", label: "Verbinden", hint: "IDE-/Agent-Configs erzeugen", icon: Plug }, { 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 }, { 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" /> <ExternalLink className="h-4 w-4" />
<span>Hermes WebUI öffnen</span> <span>AnythingLLM öffnen</span>
</a> </a>
)} )}
</div> </div>
@@ -169,11 +169,11 @@ export function AgentView() {
detail="Port :8642 (REST API)" detail="Port :8642 (REST API)"
icon={Bot} icon={Bot}
/> />
<Tile <Tile
label="Agent WebUI" label="AnythingLLM"
ok={s.webui_reachable} ok={s.webui_reachable}
detail="Port :8787 (Chat UI)" detail="Chat-UI (AnythingLLM)"
icon={Activity} icon={Activity}
/> />
<Tile <Tile
label="Aktives Gehirn" label="Aktives Gehirn"
@@ -239,10 +239,10 @@ export function AgentView() {
onMouseEnter={() => setHoveredNode("webui")} onMouseEnter={() => setHoveredNode("webui")}
onMouseLeave={() => setHoveredNode(null)} onMouseLeave={() => setHoveredNode(null)}
onClick={() => s.webui_reachable && window.open(resolveExternalUrl(s.webui_url), "_blank")} 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")} /> <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")} /> <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> </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"> <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>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>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> </ul>
</div> </div>
</> </>
@@ -474,7 +474,7 @@ description: Drive development with strict TDD practices
<ul className="list-disc pl-4 space-y-1"> <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>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>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> </ul>
</div> </div>
</div> </div>