Fix: Hermes-Update-Check git-basiert (war an GitHub-Releases, falscher Kanal)

Bug: UI zeigte nie ein Hermes-Update, obwohl die CLI eins anzeigte. Ursache: MC2 verglich
das neueste GitHub-RELEASE (frozen v2026.6.19) gegen das installierte Commit — Hermes wird
aber aus git main aktualisiert (`hermes update` = git pull origin <branch>), und main laeuft
den Releases voraus. Darum war update immer false.

Fix: _hermes_agent_update() macht jetzt git fetch + zaehlt Commits HEAD..origin/<branch>
(genau wie `hermes update --check`). update=true wenn behind>0; latest = origin-Kurzhash +
behind-Count. Tote Release-Helfer (_gh_latest, _commit_ts) + HERMES_AGENT_REPO-Import entfernt.

Verifiziert: MC2 == CLI (beide "Update verfuegbar, 1 Commit hinter origin/main").
Frontend (UpdatesCard) rendert components bereits korrekt — nur das Backend-Signal war falsch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hitonabi
2026-06-27 21:41:18 +02:00
parent 46f108b6f3
commit b38e3360c5
+21 -30
View File
@@ -15,7 +15,6 @@ from datetime import datetime
import httpx
import psutil
from config import HERMES_AGENT_REPO
from services import catalog, discover, jobengine, llamaswap, system
# System-Dienste (root, via sudo -n NOPASSWD) vs. User-Dienste (systemctl --user).
@@ -89,42 +88,34 @@ def _engine_update_available() -> bool:
_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."""
"""Hermes-Agent wird aus **git** aktualisiert (CLI `hermes update` = git pull origin <branch>).
Darum HEAD vs. origin/<branch> prüfen (fetch + behind-count) — NICHT GitHub-Releases: die
werden selten getaggt, main läuft ihnen voraus → sonst zeigt das UI nie ein Update an."""
info = {"key": "hermes_agent", "name": "Hermes Agent", "current": None,
"latest": None, "update": False, "reachable": None}
git = system.find_hermes_agent_git()
if git:
if not git or not git.get("path"):
return info
path = git["path"]
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)
branch = (subprocess.run(["git", "-C", path, "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True, text=True, timeout=8).stdout.strip() or "main")
fetch = subprocess.run(["git", "-C", path, "fetch", "-q", "origin", branch],
capture_output=True, text=True, timeout=25)
info["reachable"] = (fetch.returncode == 0)
if fetch.returncode == 0:
cnt = subprocess.run(["git", "-C", path, "rev-list", "--count", f"HEAD..origin/{branch}"],
capture_output=True, text=True, timeout=8)
behind = int(cnt.stdout.strip() or "0") if cnt.returncode == 0 else 0
info["behind"] = behind
info["update"] = behind > 0
oh = subprocess.run(["git", "-C", path, "rev-parse", "--short", f"origin/{branch}"],
capture_output=True, text=True, timeout=8).stdout.strip()
info["latest"] = (f"{oh} ({behind} neu)" if behind else (oh or info["current"]))
except Exception:
pass
info["reachable"] = False
return info