Files
FabledScribe/src/fabledassistant/services/voice_config.py
T
bvandeusen eaf70500b8 feat: move voice enable/model config to admin UI
Replace VOICE_ENABLED env var gate with DB-backed admin setting.

- services/voice_config.py: reads voice_enabled + voice_stt_model from
  admin user's settings row (falls back to env var defaults)
- routes/admin.py: GET/PUT /api/admin/voice for admin configuration
- routes/voice.py, services/stt.py, services/tts.py: read enabled/model
  from DB via voice_config instead of Config directly
- app.py: always schedule model loaders at startup; they self-gate on
  the DB setting so no conditional needed at the call site
- SettingsView.vue: Voice section in Admin → Config tab (enable toggle +
  STT model dropdown); user Voice tab now points to admin panel when disabled

No env var required to test — enable via Settings → Admin → Config → Voice.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-29 20:22:18 -04:00

41 lines
1.4 KiB
Python

"""System-wide voice configuration stored in the admin user's settings row.
Falls back to Config env vars so operators can still seed defaults via the
environment without touching the UI.
"""
from sqlalchemy import select
from fabledassistant.config import Config
from fabledassistant.models import async_session
from fabledassistant.models.setting import Setting
from fabledassistant.models.user import User
VOICE_SETTING_KEYS = ("voice_enabled", "voice_stt_model")
async def get_voice_config() -> dict[str, str]:
"""Return voice config, preferring DB values over env-var defaults."""
config: dict[str, str] = {
"voice_enabled": "true" if Config.VOICE_ENABLED else "false",
"voice_stt_model": Config.STT_MODEL,
}
async with async_session() as session:
result = await session.execute(
select(Setting)
.join(User, Setting.user_id == User.id)
.where(User.role == "admin", Setting.key.in_(VOICE_SETTING_KEYS))
)
for setting in result.scalars().all():
config[setting.key] = setting.value
return config
async def is_voice_enabled() -> bool:
config = await get_voice_config()
return config.get("voice_enabled", "false").lower() in ("1", "true", "yes")
async def get_stt_model() -> str:
config = await get_voice_config()
return config.get("voice_stt_model", Config.STT_MODEL)