From aa726c01af3a9a189577a710d8a6ec86d32fc1de Mon Sep 17 00:00:00 2001 From: Hitonabi Date: Wed, 24 Jun 2026 17:30:29 +0200 Subject: [PATCH] fix(v9): Cron-Parser fuer echtes Block-Format (Cockpit zeigte Jobs nicht) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `hermes cron list` nutzt bei vorhandenen Jobs kein │-Tabellenformat, sondern "id [status]" + eingerueckte Label:value-Zeilen. Eigener _parse_cron statt _parse_rich_table → Memory-Kurator-Job erscheint jetzt im Cockpit. Co-Authored-By: Claude Opus 4.8 --- hermes_control.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/hermes_control.py b/hermes_control.py index 0917ed6..8deb727 100644 --- a/hermes_control.py +++ b/hermes_control.py @@ -127,9 +127,34 @@ def agent_status() -> dict: return _cached("agent", _load) +def _parse_cron(text: str) -> list[dict]: + """`hermes cron list` parsen. Format pro Job (KEINE Rich-Tabelle): + + 7ac183295470 [active] + Name: Memory-Kurator + Schedule: 0 4 * * 0 + Next run: 2026-06-28T04:00:00+00:00 + Deliver: local + """ + jobs: list[dict] = [] + cur: dict | None = None + for ln in text.splitlines(): + m = re.match(r"\s*([0-9a-fA-F]{6,})\s+\[(\w+)\]\s*$", ln) + if m: + cur = {"id": m.group(1), "status": m.group(2)} + jobs.append(cur) + continue + if cur is not None: + kv = re.match(r"\s+([A-Za-z][\w ]*?):\s+(.+?)\s*$", ln) + if kv: + key = kv.group(1).strip().lower().replace(" ", "_") + cur[key] = kv.group(2).strip() + return jobs + + def cron_jobs() -> list[dict]: """Geplante Jobs (inkl. pausierter).""" - return _cached("cron", lambda: _parse_rich_table(_run_cli(["cron", "list", "--all"]))) # type: ignore[return-value] + return _cached("cron", lambda: _parse_cron(_run_cli(["cron", "list", "--all"]))) # type: ignore[return-value] def skills() -> list[dict]: