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>
This commit is contained in:
@@ -19,6 +19,7 @@ from fabledassistant.services.backup import (
|
||||
restore_full_backup,
|
||||
)
|
||||
from fabledassistant.services.email import SMTP_SETTING_KEYS, get_base_url, get_smtp_config, is_smtp_configured, send_test_email
|
||||
from fabledassistant.services.voice_config import get_voice_config
|
||||
from fabledassistant.services.logging import get_logs, get_log_stats, log_audit
|
||||
from fabledassistant.services.notifications import send_invitation_email
|
||||
from fabledassistant.services.settings import set_setting, set_settings_batch
|
||||
@@ -200,6 +201,33 @@ async def update_base_url():
|
||||
return jsonify({"status": "ok"})
|
||||
|
||||
|
||||
@admin_bp.route("/voice", methods=["GET"])
|
||||
@admin_required
|
||||
async def get_voice_config_route():
|
||||
config = await get_voice_config()
|
||||
return jsonify(config)
|
||||
|
||||
|
||||
@admin_bp.route("/voice", methods=["PUT"])
|
||||
@admin_required
|
||||
async def update_voice_config():
|
||||
data = await request.get_json()
|
||||
uid = get_current_user_id()
|
||||
valid_models = {"tiny.en", "base.en", "small.en", "medium.en"}
|
||||
settings: dict[str, str] = {}
|
||||
if "voice_enabled" in data:
|
||||
settings["voice_enabled"] = "true" if data["voice_enabled"] else "false"
|
||||
if "voice_stt_model" in data:
|
||||
model = str(data["voice_stt_model"])
|
||||
if model not in valid_models:
|
||||
return jsonify({"error": f"Invalid STT model. Choose from: {', '.join(sorted(valid_models))}"}), 400
|
||||
settings["voice_stt_model"] = model
|
||||
if settings:
|
||||
await set_settings_batch(uid, settings)
|
||||
await log_audit("voice_config", user_id=uid, username=g.user.username, ip_address=request.remote_addr, details=settings)
|
||||
return jsonify({"status": "ok"})
|
||||
|
||||
|
||||
@admin_bp.route("/invitations", methods=["POST"])
|
||||
@admin_required
|
||||
async def create_invite():
|
||||
|
||||
Reference in New Issue
Block a user