Initial commit: Cosmo Voice Satellite

Two-agent voice assistant (Cosmo + Люся) via OpenClaw Gateway.
Streaming STT (Groq) + LLM + TTS (ElevenLabs) pipeline with
keep-alive sessions, barge-in, and daily conversation sessions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-12 13:34:08 +03:00
commit 7ca8268b78
16 changed files with 1143 additions and 0 deletions

85
satellite/config.py Normal file
View File

@@ -0,0 +1,85 @@
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 (по умолчанию)
GATEWAY_URL = os.getenv("GATEWAY_URL", "http://192.168.31.103:18789")
GATEWAY_TOKEN = os.getenv("GATEWAY_TOKEN")
AGENT = os.getenv("AGENT", "openclaw/main")
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_AGENT = os.getenv("LUSYA_AGENT", "openclaw/wife")
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,
"token": GATEWAY_TOKEN,
"agent": AGENT,
"voice_model": VOICE_MODEL,
"tts_voice": os.getenv("COSMO_TTS_VOICE", ""),
"session": _make_session(GATEWAY_TOKEN),
},
"lusya": {
"name": "Люся",
"gateway_url": LUSYA_GATEWAY_URL,
"token": LUSYA_GATEWAY_TOKEN,
"agent": LUSYA_AGENT,
"voice_model": LUSYA_VOICE_MODEL,
"tts_voice": os.getenv("LUSYA_TTS_VOICE", ""),
"session": _make_session(LUSYA_GATEWAY_TOKEN),
},
}
# STT
STT_PROVIDER = os.getenv("STT_PROVIDER", "groq")
WHISPER_MODEL = os.getenv("WHISPER_MODEL", "small")
WHISPER_LANG = os.getenv("WHISPER_LANGUAGE", "ru")
# 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"))
# Groq client
groq_client = Groq(api_key=os.getenv("GROQ_API_KEY"))
if not GATEWAY_TOKEN:
print("❌ GATEWAY_TOKEN не задан в .env")
sys.exit(1)