Welle 3 · Lucys Freiheiten je Aktionsart, Rückfragen mit „ja 7“, Lucy untersucht rote Hinweise, Wochenbericht
- 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>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
dd23f3fb4c
commit
12cefb427a
+70
-24
@@ -3,13 +3,15 @@
|
||||
Homelab Orchestrator — MCP-Server für Lucy (Hermes), seit 25.09.2026.
|
||||
|
||||
Stdio-MCP-Server, von Hermes Gateway als Unterprozess gestartet (auf der KI-Box, mit dem venv von MC2). Gibt Lucy die
|
||||
Knöpfe des Orchestrators: Lage lesen, Updates starten, „Alle aktualisieren“, Dienste neu starten, Kernel aufräumen,
|
||||
Host neu starten, Modell-Radar. Die Logik steht in orchestrator_werkzeuge.py (ohne MCP testbar); alles geht über die
|
||||
REST-API von MC2 mit denselben Leitplanken wie die Knöpfe der Oberfläche.
|
||||
Knöpfe des Orchestrators: Lage lesen, Protokolle lesen, Updates und Sicherheitsupdates starten, „Alle aktualisieren“,
|
||||
Dienste neu starten, Snapshots zurückspielen, Kernel aufräumen, Host neu starten, Modell-Radar — und die Rückfragen
|
||||
an den Commander. Die Logik steht in orchestrator_werkzeuge.py (ohne MCP testbar); alles geht über die REST-API von MC2
|
||||
mit denselben Leitplanken wie die Knöpfe der Oberfläche.
|
||||
|
||||
Die Beschreibungen sind bewusst als Leitplanken formuliert (Lesen jederzeit, Handeln nur auf Bitte des Commanders),
|
||||
damit das Modell nicht auf eigene Faust Updates oder Neustarts auslöst — der Grund jeder Aktion wird protokolliert.
|
||||
FastMCP liest die Beschreibung beim Anmelden, deshalb steht sie in description= (orchestrator_werkzeuge.BESCHREIBUNG).
|
||||
Handeln: auf ausdrückliche Bitte des Commanders (auf_bitte=true) oder nach Lucys Freiheiten je Aktionsart (seit dem
|
||||
Abend des 25.09.2026, Einstellungen → Lucy) — selbst mit Meldung danach, als Rückfrage oder gar nicht. Grund und
|
||||
Stufe jeder Aktion werden protokolliert. FastMCP liest die Beschreibung beim Anmelden, deshalb steht sie in
|
||||
description= (orchestrator_werkzeuge.BESCHREIBUNG). Neue Werkzeuge sieht Hermes erst nach einem Neustart des Gateways.
|
||||
|
||||
Einrichten auf der Box (einmal): hermes mcp add homelab-orchestrator --command <venv>/bin/python --args <dieses Skript>
|
||||
"""
|
||||
@@ -21,6 +23,8 @@ mcp = FastMCP("homelab-orchestrator")
|
||||
B = w.BESCHREIBUNG
|
||||
|
||||
|
||||
# --- Lesen ----------------------------------------------------------------------------------------------------
|
||||
|
||||
@mcp.tool(description=B["lage"])
|
||||
def lage() -> str:
|
||||
return w.lage()
|
||||
@@ -37,8 +41,8 @@ def speicher() -> str:
|
||||
|
||||
|
||||
@mcp.tool(description=B["protokoll"])
|
||||
def protokoll(anzahl: int = 15) -> str:
|
||||
return w.protokoll(anzahl)
|
||||
def protokoll(anzahl: int = 15, ziel: str | None = None) -> str:
|
||||
return w.protokoll(anzahl, ziel)
|
||||
|
||||
|
||||
@mcp.tool(description=B["radar"])
|
||||
@@ -46,44 +50,86 @@ def radar() -> str:
|
||||
return w.radar()
|
||||
|
||||
|
||||
@mcp.tool(description=B["freiheiten"])
|
||||
def freiheiten() -> str:
|
||||
return w.freiheiten()
|
||||
|
||||
|
||||
@mcp.tool(description=B["rueckfragen"])
|
||||
def rueckfragen() -> str:
|
||||
return w.rueckfragen()
|
||||
|
||||
|
||||
@mcp.tool(description=B["geraet_logs"])
|
||||
def geraet_logs(ziel: str, zeilen: int = 80) -> str:
|
||||
return w.geraet_logs(ziel, zeilen)
|
||||
|
||||
|
||||
@mcp.tool(description=B["dienst_logs"])
|
||||
def dienst_logs(dienst: str, zeilen: int = 80) -> str:
|
||||
return w.dienst_logs(dienst, zeilen)
|
||||
|
||||
|
||||
@mcp.tool(description=B["snapshots"])
|
||||
def snapshots(ziel: str) -> str:
|
||||
return w.snapshots(ziel)
|
||||
|
||||
|
||||
# --- Handeln --------------------------------------------------------------------------------------------------
|
||||
|
||||
@mcp.tool(description=B["update_starten"])
|
||||
def update_starten(ziel: str, baustein: str, grund: str) -> str:
|
||||
return w.update_starten(ziel, baustein, grund)
|
||||
def update_starten(ziel: str, baustein: str, grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.update_starten(ziel, baustein, grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["sicherheitsupdates_einspielen"])
|
||||
def sicherheitsupdates_einspielen(ziel: str, grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.sicherheitsupdates_einspielen(ziel, grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["alle_aktualisieren"])
|
||||
def alle_aktualisieren(bereich: str, grund: str) -> str:
|
||||
return w.alle_aktualisieren(bereich, grund)
|
||||
def alle_aktualisieren(bereich: str, grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.alle_aktualisieren(bereich, grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["nach_updates_suchen"])
|
||||
def nach_updates_suchen(grund: str) -> str:
|
||||
return w.nach_updates_suchen(grund)
|
||||
def nach_updates_suchen(grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.nach_updates_suchen(grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["dienst_neustarten"])
|
||||
def dienst_neustarten(dienst: str, grund: str) -> str:
|
||||
return w.dienst_neustarten(dienst, grund)
|
||||
def dienst_neustarten(dienst: str, grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.dienst_neustarten(dienst, grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["snapshot_zurueckspielen"])
|
||||
def snapshot_zurueckspielen(ziel: str, snapshot: str, grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.snapshot_zurueckspielen(ziel, snapshot, grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["kernel_aufraeumen"])
|
||||
def kernel_aufraeumen(grund: str) -> str:
|
||||
return w.kernel_aufraeumen(grund)
|
||||
def kernel_aufraeumen(grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.kernel_aufraeumen(grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["host_neustarten"])
|
||||
def host_neustarten(grund: str) -> str:
|
||||
return w.host_neustarten(grund)
|
||||
def host_neustarten(grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.host_neustarten(grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["radar_testen"])
|
||||
def radar_testen(kandidat: str, grund: str) -> str:
|
||||
return w.radar_testen(kandidat, grund)
|
||||
def radar_testen(kandidat: str, grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.radar_testen(kandidat, grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["radar_suchen"])
|
||||
def radar_suchen(grund: str) -> str:
|
||||
return w.radar_suchen(grund)
|
||||
def radar_suchen(grund: str, auf_bitte: bool = False) -> str:
|
||||
return w.radar_suchen(grund, auf_bitte)
|
||||
|
||||
|
||||
@mcp.tool(description=B["rueckfrage_beantworten"])
|
||||
def rueckfrage_beantworten(antwort: str, nr: int | None = None) -> str:
|
||||
return w.rueckfrage_beantworten(antwort, nr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user