Files
home-voice-assistant/satellite/config.py
Cosmo 356543afdb config: make OpenClaw credentials optional when LLM_BACKEND=claude
Allows removing all GATEWAY_*, VOICE_MODEL, *_SESSION_KEY env vars
when running on the Claude direct backend. The OpenClaw hard-exit
check now only fires when that backend is actually selected.
2026-04-23 13:18:23 +00:00

94 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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")
# Какой LLM backend — openclaw (дефолт) или claude (прямой Anthropic).
# В конфиге используется для решения «требовать ли OpenClaw credentials».
LLM_BACKEND_CFG = os.getenv("LLM_BACKEND", "openclaw").lower()
# OpenClaw Gateway — Cosmo
# Нужны только если LLM_BACKEND=openclaw. При claude-бэкенде остаются пустыми — это ок.
GATEWAY_URL = os.getenv("GATEWAY_URL", "")
GATEWAY_TOKEN = os.getenv("GATEWAY_TOKEN", "")
VOICE_MODEL = os.getenv("VOICE_MODEL", "")
# OpenClaw Gateway — Люся
LUSYA_GATEWAY_URL = os.getenv("LUSYA_GATEWAY_URL", "")
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 LLM_BACKEND_CFG == "openclaw" and not GATEWAY_TOKEN:
print("❌ GATEWAY_TOKEN не задан в .env (нужен для LLM_BACKEND=openclaw)")
sys.exit(1)