# -*- coding: utf-8 -*- """ System-Intents für Trixy. Hardkodierte System-Intents die immer verfügbar sind, unabhängig von geladenen Plugins. Sicherheitsstufen: - PUBLIC: Für alle verfügbar - ADMIN: Nur mit "system_command" Wakeword und Login """ from enum import Enum, auto from dataclasses import dataclass, field from typing import Any class IntentSecurityLevel(Enum): """Sicherheitsstufe eines Intents.""" PUBLIC = auto() # Für alle verfügbar ADMIN = auto() # Erfordert system_command Wakeword + Login @dataclass class SystemIntentInfo: """ Definition eines System-Intents. Attributes: name: Intent-Name description: Beschreibung security: Sicherheitsstufe slots: Slot-Definitionen examples: Beispiel-Phrasen """ name: str description: str security: IntentSecurityLevel = IntentSecurityLevel.PUBLIC slots: dict[str, dict[str, Any]] = field(default_factory=dict) examples: list[str] = field(default_factory=list) patterns: list[str] = field(default_factory=list) def to_dict(self) -> dict[str, Any]: """Konvertiert zu Dictionary für NLP-Prompt.""" result = { "name": self.name, "description": self.description, "slots": self.slots, "examples": self.examples, "plugin": "_system", "security": self.security.name.lower(), } if self.patterns: result["patterns"] = self.patterns return result # ============================================================================= # Öffentliche System-Intents (PUBLIC) # ============================================================================= PUBLIC_SYSTEM_INTENTS: list[SystemIntentInfo] = [ SystemIntentInfo( name="health_check", description="Systemstatus und Wohlbefinden abfragen", examples=["Wie geht es dir?", "Alles okay?", "Bist du da?", "Status"], patterns=[ "(wie geht|wie gehts) [es] [dir]", "alles (okay|ok|klar)", "bist [du] da", ], ), SystemIntentInfo( name="get_time", description="Aktuelle Uhrzeit abfragen", examples=["Wie spät ist es?", "Uhrzeit", "Wie viel Uhr ist es?"], patterns=[ "wie (spaet|viel uhr) ist [es]", "uhrzeit", ], ), SystemIntentInfo( name="get_date", description="Aktuelles Datum abfragen", examples=["Welcher Tag ist heute?", "Datum", "Welches Datum haben wir?"], patterns=[ "welcher tag ist [heute]", "welches datum (haben wir|ist heute)", "datum", ], ), SystemIntentInfo( name="help", description="Hilfe und verfügbare Befehle anzeigen", examples=["Hilfe", "Was kannst du?", "Befehle"], patterns=[ "hilfe", "was kannst [du]", "befehle", ], ), SystemIntentInfo( name="cancel", description="Aktuelle Aktion abbrechen", examples=["Abbrechen", "Vergiss es", "Egal"], patterns=["abbrechen", "vergiss [es]", "egal"], ), SystemIntentInfo( name="repeat", description="Letzte Antwort wiederholen", examples=["Wiederhole das", "Nochmal", "Was hast du gesagt?"], patterns=[ "wiederhole [das]", "nochmal", "was hast [du] gesagt", ], ), SystemIntentInfo( name="stop", description="Stoppt alle aktiven Medien (Musik, TTS, Streams)", examples=["Stopp", "Halt", "Alles stoppen", "Sei still", "Ruhe"], patterns=["stopp", "halt", "alles stoppen", "sei still", "ruhe"], ), SystemIntentInfo( name="pause", description="Pausiert die aktuelle Wiedergabe", examples=["Pause", "Pausieren"], patterns=["pause", "pausieren"], ), SystemIntentInfo( name="resume", description="Setzt die pausierte Wiedergabe fort", examples=["Weiterspielen", "Fortsetzen", "Weiter machen", "Play"], patterns=[ "weiterspielen", "fortsetzen", "weiter [machen]", "play", ], ), SystemIntentInfo( name="volume_up", description="Lautstärke erhöhen", slots={"amount": {"type": "int", "description": "Prozent (optional)"}}, examples=["Lauter", "Lautstärke hoch", "Mach lauter"], patterns=[ "lauter", "lautstaerke (hoch|rauf)", "(mach|dreh) [es] lauter", ], ), SystemIntentInfo( name="volume_down", description="Lautstärke verringern", slots={"amount": {"type": "int", "description": "Prozent (optional)"}}, examples=["Leiser", "Lautstärke runter", "Mach leiser"], patterns=[ "leiser", "lautstaerke (runter|rauf)", "(mach|dreh) [es] leiser", ], ), SystemIntentInfo( name="volume_set", description="Lautstärke auf bestimmten Wert setzen", slots={"level": {"type": "int", "required": True, "description": "Prozent 0-100"}}, examples=["Lautstärke auf 50", "Setze Lautstärke auf 30 Prozent"], patterns=[ "lautstaerke [auf] {level}", "(setze|stelle) [die] lautstaerke [auf] {level}", ], ), SystemIntentInfo( name="mute", description="Ton stumm schalten", examples=["Stumm", "Mute", "Ton aus"], patterns=["stumm", "mute", "ton aus"], ), SystemIntentInfo( name="unmute", description="Stummschaltung aufheben", examples=["Ton an", "Unmute", "Stummschaltung aus"], patterns=["ton an", "unmute", "stummschaltung aus"], ), ] # ============================================================================= # Admin System-Intents (erfordern system_command + Login) # ============================================================================= ADMIN_SYSTEM_INTENTS: list[SystemIntentInfo] = [ SystemIntentInfo( name="system_login", description="Als Administrator anmelden (Passwort erforderlich)", security=IntentSecurityLevel.ADMIN, slots={"password": {"type": "str", "required": True, "description": "Admin-Passwort"}}, examples=["Anmelden", "Login", "Authentifizieren"], patterns=["(anmelden|login|authentifizieren)"], ), SystemIntentInfo( name="system_logout", description="Administrator-Sitzung beenden", security=IntentSecurityLevel.ADMIN, examples=["Abmelden", "Logout", "Sitzung beenden"], patterns=["(abmelden|logout)", "sitzung beenden"], ), SystemIntentInfo( name="system_shutdown", description="System herunterfahren", security=IntentSecurityLevel.ADMIN, examples=["Herunterfahren", "Shutdown", "System ausschalten"], patterns=["(herunterfahren|shutdown)", "system ausschalten"], ), SystemIntentInfo( name="system_reboot", description="System neu starten", security=IntentSecurityLevel.ADMIN, examples=["Neustart", "Reboot", "System neu starten"], patterns=["(neustart|reboot)", "system neu starten"], ), SystemIntentInfo( name="system_update", description="System aktualisieren", security=IntentSecurityLevel.ADMIN, examples=["Update", "Aktualisieren", "System updaten"], patterns=["(update|aktualisieren)", "system (updaten|aktualisieren)"], ), SystemIntentInfo( name="plugin_reload", description="Plugin neu laden", security=IntentSecurityLevel.ADMIN, slots={"plugin_name": {"type": "str", "required": True}}, examples=["Plugin neuladen", "Reload Plugin"], patterns=[ "plugin {plugin_name} (neuladen|reload)", "(reload|neuladen) [plugin] {plugin_name}", ], ), SystemIntentInfo( name="plugin_enable", description="Plugin aktivieren", security=IntentSecurityLevel.ADMIN, slots={"plugin_name": {"type": "str", "required": True}}, examples=["Plugin aktivieren", "Enable Plugin"], patterns=[ "plugin {plugin_name} (aktivieren|enable)", "(aktiviere|enable) [plugin] {plugin_name}", ], ), SystemIntentInfo( name="plugin_disable", description="Plugin deaktivieren", security=IntentSecurityLevel.ADMIN, slots={"plugin_name": {"type": "str", "required": True}}, examples=["Plugin deaktivieren", "Disable Plugin"], patterns=[ "plugin {plugin_name} (deaktivieren|disable)", "(deaktiviere|disable) [plugin] {plugin_name}", ], ), SystemIntentInfo( name="satellite_list", description="Verbundene Satellites auflisten", security=IntentSecurityLevel.ADMIN, examples=["Zeige Satellites", "Welche Geräte sind verbunden?"], patterns=[ "zeige satellites", "welche geraete sind verbunden", ], ), SystemIntentInfo( name="system_status", description="Detaillierten Systemstatus anzeigen", security=IntentSecurityLevel.ADMIN, examples=["Systemstatus", "Detaillierter Status", "System Info"], patterns=["systemstatus", "system (info|status)"], ), SystemIntentInfo( name="debug_mode", description="Debug-Modus ein/ausschalten", security=IntentSecurityLevel.ADMIN, slots={"enabled": {"type": "bool", "required": True}}, examples=["Debug an", "Debug aus", "Debug-Modus aktivieren"], patterns=["debug (an|aus|ein)", "debug modus (aktivieren|deaktivieren)"], ), ] # Alle System-Intents kombiniert ALL_SYSTEM_INTENTS: list[SystemIntentInfo] = PUBLIC_SYSTEM_INTENTS + ADMIN_SYSTEM_INTENTS def _load_system_yaml(language: str = "de") -> dict[str, dict[str, Any]]: """Laedt YAML-Overrides fuer System-Intents.""" try: from pathlib import Path from trixy_core.nlp.intent_loader import load_intent_yaml system_dir = Path(__file__).parent return load_intent_yaml(system_dir, language) except Exception: return {} def _apply_yaml_overrides( intent_dict: dict[str, Any], yaml_data: dict[str, dict[str, Any]], ) -> dict[str, Any]: """Wendet YAML-Overrides auf ein Intent-Dict an.""" name = intent_dict.get("name", "") if name in yaml_data: yaml_entry = yaml_data[name] if "patterns" in yaml_entry: intent_dict["patterns"] = yaml_entry["patterns"] if "examples" in yaml_entry: intent_dict["examples"] = yaml_entry["examples"] return intent_dict def get_system_intents_for_context( wakeword_type: str = "custom", is_authenticated: bool = False, language: str = "de", admin_wakewords: list[str] | None = None, ) -> list[dict[str, Any]]: """ Gibt die verfügbaren System-Intents für den aktuellen Kontext zurück. Laedt zusaetzlich Patterns/Examples aus intents_{language}.yml (falls vorhanden) und merged diese mit den hartkodierten Werten. Args: wakeword_type: Typ/Model-Name des Wakewords is_authenticated: Ist der Benutzer als Admin angemeldet? language: Sprachcode fuer YAML-Overrides admin_wakewords: Liste der Admin-Wakeword-Model-Names (aus Config) Returns: Liste der verfügbaren System-Intents als Dictionaries """ yaml_data = _load_system_yaml(language) intents = [] # Öffentliche Intents sind immer verfügbar for intent in PUBLIC_SYSTEM_INTENTS: d = intent.to_dict() if yaml_data: _apply_yaml_overrides(d, yaml_data) intents.append(d) # Admin-Intents nur bei Admin-Wakeword _admin_ww = set(admin_wakewords) if admin_wakewords else {"system_command"} if wakeword_type in _admin_ww: for intent in ADMIN_SYSTEM_INTENTS: # system_login ist immer verfügbar (um sich anzumelden) if intent.name == "system_login": d = intent.to_dict() if yaml_data: _apply_yaml_overrides(d, yaml_data) intents.append(d) # Andere Admin-Intents nur wenn authentifiziert elif is_authenticated: d = intent.to_dict() if yaml_data: _apply_yaml_overrides(d, yaml_data) intents.append(d) return intents def is_admin_intent(intent_name: str) -> bool: """Prüft ob ein Intent Admin-Rechte erfordert.""" for intent in ADMIN_SYSTEM_INTENTS: if intent.name == intent_name: return True return False def is_system_intent(intent_name: str) -> bool: """Prüft ob ein Intent ein System-Intent ist.""" for intent in ALL_SYSTEM_INTENTS: if intent.name == intent_name: return True return False def get_system_intent_info(intent_name: str) -> SystemIntentInfo | None: """Gibt die Info zu einem System-Intent zurück.""" for intent in ALL_SYSTEM_INTENTS: if intent.name == intent_name: return intent return None