from __future__ import annotations import json import os from pathlib import Path import streamlit as st from src.api.session_bootstrap import ensure_session_bootstrap_server from src.api.streamlit_routes import build_session_bootstrap_path from src.core.settings import settings UI_DIR = Path(__file__).parent / "ui" INDEX_TEMPLATE = UI_DIR / "index.html" MAIN_JS = UI_DIR / "main.js" def extract_display_name(model_id: str, provider: str) -> str: """Extract human-readable display name from model ID.""" # Get the model name (part after '/' if present) if "/" in model_id: name = model_id.split("/")[-1] else: name = model_id # Special cases for well-known models if "moonshine" in name.lower(): return "Moonshine STT" elif "qwen" in name.lower(): return name # Keep format like "Qwen2.5-3B-Instruct" elif "parakeet" in name.lower(): return "NVIDIA Parakeet" elif "llama" in name.lower(): parts = name.split("-") return f"Llama {parts[1]}" if len(parts) > 1 else name # Default: basic cleanup return name.replace("-", " ").title() def generate_footer_html() -> str: """Generate dynamic 'Powered by' footer HTML based on current settings.""" # STT Component stt_provider = settings.stt.STT_PROVIDER.lower() if stt_provider == "moonshine": stt_model_id = settings.stt.MOONSHINE_MODEL_ID stt_url = f"https://huggingface.co/{stt_model_id}" stt_display = extract_display_name(stt_model_id, "moonshine") elif stt_provider == "nvidia": stt_url = "https://build.nvidia.com/" stt_display = extract_display_name(settings.stt.NVIDIA_STT_MODEL, "nvidia") else: stt_url = "#" stt_display = f"Unknown STT ({stt_provider})" # LLM Component llm_provider = settings.llm.LLM_PROVIDER.lower() if llm_provider == "huggingface": llm_model_id = settings.llm.HUGGINGFACE_MODEL_ID llm_url = f"https://huggingface.co/{llm_model_id}" llm_display = extract_display_name(llm_model_id, "huggingface") elif llm_provider == "nvidia": llm_url = "https://build.nvidia.com/" llm_display = extract_display_name(settings.llm.NVIDIA_MODEL, "nvidia") else: llm_url = "#" llm_display = f"Unknown LLM ({llm_provider})" # Build footer HTML return f"""Powered by open-source core components: {stt_display} · {llm_display} · PocketTTS · LiveKit""" def render_client(*, livekit_url: str, session_bootstrap_url: str) -> None: template = INDEX_TEMPLATE.read_text(encoding="utf-8") js = MAIN_JS.read_text(encoding="utf-8") footer_html = generate_footer_html() html = ( template.replace("{{MAIN_JS}}", js) .replace("{{LIVEKIT_URL_JSON}}", json.dumps(livekit_url)) .replace("{{SESSION_BOOTSTRAP_URL_JSON}}", json.dumps(session_bootstrap_url)) .replace("{{FOOTER_POWERED_BY}}", footer_html) ) st.components.v1.html(html, height=900, scrolling=False) def main() -> None: st.set_page_config(page_title="Open Voice Agent", layout="wide") st.markdown( "", unsafe_allow_html=True, ) if not settings.livekit.LIVEKIT_URL: st.error("LIVEKIT_URL is not set in the environment.") st.stop() if not settings.livekit.LIVEKIT_API_KEY or not settings.livekit.LIVEKIT_API_SECRET: st.error("LIVEKIT_API_KEY or LIVEKIT_API_SECRET is not set.") st.stop() use_streamlit_route = os.getenv( "OPEN_VOICE_USE_STREAMLIT_BOOTSTRAP_ROUTE", "0" ).lower() in {"1", "true", "yes"} if use_streamlit_route: session_bootstrap_url = build_session_bootstrap_path() else: try: session_bootstrap_url = ensure_session_bootstrap_server() except Exception as exc: st.error(f"Failed to start session bootstrap service: {exc}") st.stop() render_client( livekit_url=settings.livekit.LIVEKIT_URL, session_bootstrap_url=session_bootstrap_url, ) if __name__ == "__main__": main()