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.
94 lines
3.6 KiB
Python
94 lines
3.6 KiB
Python
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)
|