- services/lucy_autonomie.py: Stufe je Aktionsart (nur lesen, erst fragen, selbst handeln), Start „mehr Freiheit“;
Meldung danach (POST /api/lucy/gehandelt)
- services/rueckfragen.py: nummerierte Rückfragen, nur Knöpfe der Oberfläche (ERLAUBT), „ja“ führt genau die
gespeicherte Aktion aus, 24 h gültig, hinfällig wenn der Hinweis weg ist, Nachprüfung danach
- notify.sh -k: Antworttasten (Antworttastatur über den Direktweg, ohne Eingriff in Hermes)
- services/ermittlung.py: Wächter meldet rote Hinweise an Lucy; Knopf wird Rückfrage, Lucy sieht über den
api_server nach und schickt Ursache und Weg als eine Nachricht
- services/wochenbericht.py + mc2-wochenbericht.timer (So 07:30): feste Sätze, Absatz vom Modell, offene
App-Updates als Rückfragen
- MCP: Werkzeuge fragen die Freiheiten (auf_bitte), neu: freiheiten, rueckfragen, rueckfrage_beantworten,
sicherheitsupdates_einspielen, snapshot_zurueckspielen, snapshots, geraet_logs, dienst_logs
- Ausführer-Aktion journal (nur lesend), POST /api/homelab/ziele/{id}/sicherheitsupdates
- Läufe des Homelabs mit flock (Oberfläche und Steward schreiben beide)
- Skill homelab-orchestrator, SOUL-Abschnitt als Kopie in deploy/nur-box
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
29 lines
1.5 KiB
Python
29 lines
1.5 KiB
Python
"""Das Protokoll eines Containers für Lucy (seit 25.09.2026, Ausbauplan Welle 3, Punkt 14: „Lucy liest Logs und
|
|
Messwerte, erklärt den Befund“).
|
|
|
|
Über den Ausführer (Aktion journal, nur lesend): Warnungen und Fehler der letzten 24 Stunden aus dem Journal, ohne
|
|
systemd (Alpine) die letzten Zeilen von /var/log/messages. Nur für freigegebene Container — in eine VM kommt der
|
|
Ausführer nicht hinein. Lucys Werkzeug geraet_logs() liest es über GET /api/homelab/ziele/{id}/journal.
|
|
"""
|
|
|
|
from services.homelab import inventar, kanal
|
|
|
|
ZEITLIMIT_S = 90
|
|
|
|
|
|
def lesen(ziel_id: str, zeilen: int = 80) -> dict:
|
|
gast = inventar.gast(ziel_id)
|
|
if not gast:
|
|
return {"ok": False, "detail": "Dieses Gerät steht nicht im Bericht des Ausführers."}
|
|
if gast.get("art") != "lxc":
|
|
return {"ok": False, "detail": "Protokolle gibt es nur von Containern; in eine VM kommt der Ausführer nicht."}
|
|
if not gast.get("erlaubt"):
|
|
return {"ok": False, "detail": "Dieses Gerät ist nicht freigegeben (Etikett watcher fehlt)."}
|
|
auftrag = kanal.anlegen("journal", {"vmid": gast["vmid"], "zeilen": max(20, min(int(zeilen), 300))})
|
|
ergebnis = kanal.warten(auftrag, ZEITLIMIT_S)
|
|
if not ergebnis:
|
|
return {"ok": False, "detail": "Der Ausführer hat nicht rechtzeitig geantwortet."}
|
|
if ergebnis.get("status") != "fertig":
|
|
return {"ok": False, "detail": str(ergebnis.get("text") or "Das Protokoll ließ sich nicht lesen.")[:500]}
|
|
return {"ok": True, "text": str(ergebnis.get("text") or "").strip() or "(keine Warnungen oder Fehler)"}
|