import React, { useState, useEffect } from 'react'; import { useTranscriptionStore, LLMConfig } from '../../../../../stores/transcriptionStore'; const PROVIDERS = [ { value: 'openai', label: 'OpenAI' }, { value: 'anthropic', label: 'Anthropic' }, { value: 'ollama', label: 'Ollama (local)' }, { value: 'openrouter', label: 'OpenRouter' }, { value: 'google', label: 'Google Gemini' }, ] as const; const WHISPER_MODELS = [ { value: 'tiny', label: 'Tiny (fastest, least accurate)' }, { value: 'tiny.en', label: 'Tiny English' }, { value: 'base', label: 'Base' }, { value: 'base.en', label: 'Base English' }, { value: 'small', label: 'Small' }, { value: 'small.en', label: 'Small English' }, { value: 'medium', label: 'Medium' }, { value: 'medium.en', label: 'Medium English' }, { value: 'large-v2', label: 'Large v2' }, { value: 'large-v3', label: 'Large v3 (best accuracy)' }, ]; const fieldStyle: React.CSSProperties = { width: '100%', padding: '7px 10px', border: '1px solid var(--color-divider)', borderRadius: '6px', backgroundColor: 'var(--color-muted)', color: 'var(--color-text)', fontSize: '13px', outline: 'none', boxSizing: 'border-box', }; const labelStyle: React.CSSProperties = { display: 'block', fontSize: '12px', fontWeight: 600, color: 'var(--color-text-2)', marginBottom: '4px', textTransform: 'uppercase', letterSpacing: '0.05em', }; const LLMConfigModal: React.FC<{ isOpen: boolean; onClose: () => void }> = ({ isOpen, onClose }) => { const { llmConfig, setLLMConfig } = useTranscriptionStore(); const [form, setForm] = useState(llmConfig); const [saved, setSaved] = useState(false); useEffect(() => { if (isOpen) { setForm(useTranscriptionStore.getState().llmConfig); setSaved(false); } }, [isOpen]); const handleSave = () => { setLLMConfig(form); setSaved(true); setTimeout(() => { setSaved(false); onClose(); }, 1000); }; if (!isOpen) return null; return (
{ if (e.target === e.currentTarget) onClose(); }} > {/* Backdrop */}
{/* Modal panel */}
e.stopPropagation()} > {/* Header */}
Settings
{/* Content */}
{/* ── Transcription section ── */}
Transcription
Larger models are more accurate but slower to load. Server has large-v3 downloaded.
{/* ── LLM section ── */}
AI Summary Provider
setForm({ ...form, model: e.target.value })} placeholder={ form.provider === 'ollama' ? 'e.g. gemma4:e4b, llama3.2' : form.provider === 'anthropic' ? 'e.g. claude-sonnet-4-6' : form.provider === 'google' ? 'e.g. gemini-2.0-flash' : 'e.g. gpt-4o, gpt-4o-mini' } style={fieldStyle} />
{form.provider === 'ollama' && (
setForm({ ...form, baseUrl: e.target.value })} placeholder="https://ollama.kevlarai.com" style={fieldStyle} />
)}
setForm({ ...form, apiKey: e.target.value })} placeholder={form.provider === 'ollama' ? 'Leave blank or any value' : 'sk-...'} style={fieldStyle} />
API keys are stored in your browser only.
{/* Save button */}
); }; export default LLMConfigModal;