Files
avatar/main.py
T

98 lines
3.4 KiB
Python

"""AvatarPy: assistente personale con volto animato (interfaccia da Mark-LIV, motori propri)."""
from __future__ import annotations
import json
import platform
import sys
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(BASE_DIR))
from avatar.settings import CONFIG_DIR, Settings # noqa: E402
def ensure_identity_file() -> None:
"""L'interfaccia legge config/api_keys.json per nome, colore e stato di configurazione."""
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
f = CONFIG_DIR / "api_keys.json"
data: dict = {}
if f.exists():
try:
data = json.loads(f.read_text(encoding="utf-8"))
except Exception:
data = {}
changed = False
if not data.get("os_system"):
data["os_system"] = {"Darwin": "mac", "Windows": "windows"}.get(platform.system(), "linux")
changed = True
if not data.get("assistant_name"):
data["assistant_name"] = "Ava"
changed = True
if changed:
f.write_text(json.dumps(data, indent=4, ensure_ascii=False), encoding="utf-8")
def main() -> None:
ensure_identity_file()
settings = Settings()
try:
from PyQt6 import QtWebEngineWidgets # noqa: F401 (va importato prima della QApplication)
except Exception as err:
print(f"[avatar3d] WebEngine non disponibile: {err}")
from ui import JarvisUI # crea la QApplication
from avatar.assistant import Assistant
from avatar.settings_dialog import SettingsDialog
ui = JarvisUI(str(BASE_DIR / "core" / "face_model.obj"))
ui._win._log._ai_name_lc = ui.assistant_name.lower()
assistant = Assistant(ui, settings)
ui.on_text_command = assistant.handle_text
ui.on_interrupt = assistant.interrupt
ui.on_voice_change = lambda: assistant.reload_voice(from_customise=True)
ui.on_audio_device_change = assistant.reopen_audio
ui.on_push_to_talk = assistant.set_push_to_talk
ui.ptt_hold = assistant.ptt_hold
ui.on_wake_toggle = assistant.on_wake_toggle
ui.on_wake_manual = assistant.on_wake_manual
ui.wake_get_state = assistant.wake_get_state
from avatar.plugins import registry
from core import confirm
confirm.bind(ui.show_confirm, ui.hide_confirm, ui.write_log)
registry.ctx = {"say": assistant.say, "log": ui.write_log, "confirm": confirm.request, "player": ui}
ui.get_plugins = registry.list_for_ui
from avatar.mcp_client import manager as mcp_manager
mcp_manager.start(registry, ui.write_log)
ui._app.aboutToQuit.connect(mcp_manager.stop)
ui.get_plugin_settings = lambda: []
ui.request_say = assistant.say
# Questi due sono attributi della finestra, non della facciata JarvisUI.
ui._win.on_new_conversation = assistant.reset_conversation
def open_settings() -> None:
SettingsDialog(settings, assistant.reconfigure, parent=ui._win).exec()
ui._win.on_engine_settings = open_settings
if "--smoke" in sys.argv:
from PyQt6.QtCore import QTimer
QTimer.singleShot(3000, lambda: (print("SMOKE OK"), ui._app.quit()))
else:
if not settings.ready:
from PyQt6.QtCore import QTimer
QTimer.singleShot(800, open_settings)
assistant.start()
try:
ui.root.mainloop()
finally:
try:
from avatar import whatsapp_bridge as wb
wb.stop()
except Exception:
pass
if __name__ == "__main__":
main()