import React, { useState, useEffect } from "react"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, } from "@/components/ds/ui/dialog"; import { Button } from "@/components/ds/ui/button"; import { Label } from "@/components/ds/ui/label"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ds/ui/select"; import { Switch } from "@/components/ds/ui/switch"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@/components/ds/ui/tabs"; import { Cpu, Database, Volume2, Save, Loader2, Play } from "lucide-react"; import { useAISettings } from "../root/AISettingsProvider"; import type { AISettings } from "../root/AISettingsProvider"; import axios from "axios"; interface AISettingsModalProps { open: boolean; onOpenChange: (open: boolean) => void; } export function AISettingsModal({ open, onOpenChange }: AISettingsModalProps) { const { settings, updateSettings } = useAISettings(); const [localSettings, setLocalSettings] = useState(settings); const [saving, setSaving] = useState(false); const [testingTTS, setTestingTTS] = useState(false); // SDK Lists const [chatProviders, setChatProviders] = useState([]); const [embedProviders, setEmbedProviders] = useState([]); const [ttsProviders, setTtsProviders] = useState([]); const [loadingLists, setLoadingLists] = useState(false); useEffect(() => { if (open) { setLocalSettings(settings); fetchProviders(); } }, [open, settings]); const fetchProviders = async () => { setLoadingLists(true); try { const [chatRes, embedRes, ttsRes] = await Promise.all([ axios.get("/api/sdk/providers/chat"), axios.get("/api/sdk/providers/embed"), axios.get("/api/tts/providers"), ]); if (chatRes.data.success) setChatProviders(chatRes.data.providers || []); if (embedRes.data.success) setEmbedProviders(embedRes.data.providers || []); if (ttsRes.data.success) setTtsProviders(ttsRes.data.providers || []); } catch (error) { console.error("Failed to fetch providers:", error); } finally { setLoadingLists(false); } }; const handleSave = async () => { setSaving(true); try { await updateSettings(localSettings); onOpenChange(false); } catch { // Error handled by provider/notify } finally { setSaving(false); } }; const testTTS = async () => { setTestingTTS(true); try { const response = await axios.post( "/api/tts/speak", { text: "This is a test of the selected AI voice.", settings: { provider: localSettings.tts_provider, voice: localSettings.tts_voice, speed: localSettings.tts_speed, }, }, { responseType: "arraybuffer" }, ); const blob = new Blob([response.data], { type: "audio/mpeg" }); const url = URL.createObjectURL(blob); const audio = new Audio(url); audio.play(); } catch (error) { console.error("TTS test failed:", error); } finally { setTestingTTS(false); } }; const selectedChatProvider = chatProviders.find( (p) => p.provider === localSettings.llm_provider, ); const selectedEmbedProvider = embedProviders.find( (p) => p.provider === localSettings.embedding_provider, ); const selectedTTSProvider = ttsProviders.find( (p) => p.id === localSettings.tts_provider, ); return ( AI Settings Configure your preferred AI models and voices for the assistant. {chatProviders.length === 0 && !loadingLists && (

RealTimeX SDK Disconnected

Please ensure the RealTimeX Desktop App is running and connected.

)} LLM Embed TTS

Automatically play AI responses

setLocalSettings((prev) => ({ ...prev, tts_auto_play: v })) } />
); }