import os import sys import logging import requests as _requests from dotenv import load_dotenv from groq import Groq load_dotenv() # Логгер — ошибки в файл + короткое сообщение в консоль LOG_FILE = os.getenv("LOG_FILE", "errors.log") logging.basicConfig( level=logging.WARNING, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", handlers=[ logging.FileHandler(LOG_FILE, encoding="utf-8"), ], ) log = logging.getLogger("cosmo") # OpenClaw Gateway — Cosmo (по умолчанию) # Роутинг к нужному агенту делается через x-openclaw-session-key, поэтому AGENT не нужен. GATEWAY_URL = os.getenv("GATEWAY_URL", "http://192.168.31.103:18789") GATEWAY_TOKEN = os.getenv("GATEWAY_TOKEN") VOICE_MODEL = os.getenv("VOICE_MODEL", "openai/gpt-4o-mini") # OpenClaw Gateway — Люся LUSYA_GATEWAY_URL = os.getenv("LUSYA_GATEWAY_URL", "http://192.168.31.103:18790") LUSYA_GATEWAY_TOKEN = os.getenv("LUSYA_GATEWAY_TOKEN", GATEWAY_TOKEN) LUSYA_VOICE_MODEL = os.getenv("LUSYA_VOICE_MODEL", VOICE_MODEL) # Keep-alive HTTP сессии — переиспользуют TCP/TLS соединения def _make_session(token: str) -> _requests.Session: s = _requests.Session() s.headers.update({ "Authorization": f"Bearer {token}", "Content-Type": "application/json", }) return s # Конфиги агентов по имени AGENTS = { "cosmo": { "name": "Cosmo", "gateway_url": GATEWAY_URL, "voice_model": VOICE_MODEL, "session_key": os.getenv("COSMO_SESSION_KEY", "agent:main:voice:home"), "tts_voice": os.getenv("COSMO_TTS_VOICE", ""), "session": _make_session(GATEWAY_TOKEN), }, "lusya": { "name": "Люся", "gateway_url": LUSYA_GATEWAY_URL, "voice_model": LUSYA_VOICE_MODEL, "session_key": os.getenv("LUSYA_SESSION_KEY", "agent:wife:voice:home"), "tts_voice": os.getenv("LUSYA_TTS_VOICE", ""), "session": _make_session(LUSYA_GATEWAY_TOKEN), }, } # Audio (на Pi: PulseAudio BT sink) AUDIO_SINK = os.getenv("AUDIO_SINK", "") # VAD SILENCE_THRESHOLD = int(os.getenv("SILENCE_THRESHOLD", "500")) SILENCE_DURATION = float(os.getenv("SILENCE_DURATION", "1.5")) MAX_DURATION = int(os.getenv("MAX_DURATION", "15")) FOLLOWUP_TIMEOUT = float(os.getenv("FOLLOWUP_TIMEOUT", "8")) VAD_AGGRESSIVENESS = int(os.getenv("VAD_AGGRESSIVENESS", "2")) # webrtcvad 0..3 # LLM VOICE_MAX_TOKENS = int(os.getenv("VOICE_MAX_TOKENS", "300")) LLM_RETRIES = int(os.getenv("LLM_RETRIES", "3")) # Barge-in (прерывание TTS голосом) # Работает только при разнесённых колонке/мике или в наушниках — иначе эхо собственного TTS # будет триггерить прерывание. По умолчанию выключен. BARGE_IN_ENABLED = os.getenv("BARGE_IN_ENABLED", "false").lower() in ("1", "true", "yes") BARGE_IN_THRESHOLD = int(os.getenv("BARGE_IN_THRESHOLD", "1500")) # RMS, обычно > SILENCE_THRESHOLD BARGE_IN_WARMUP = float(os.getenv("BARGE_IN_WARMUP", "0.8")) # сек пропуска в начале TTS # Groq client groq_client = Groq(api_key=os.getenv("GROQ_API_KEY")) if not GATEWAY_TOKEN: print("❌ GATEWAY_TOKEN не задан в .env") sys.exit(1)