{"repo": "chris-davisson/ai-pentesting", "files": {"frontend/src/components/settings/ProviderSelect.jsx": {"9dbd81e1318e64afe12075d0a99c13a0e7cf7e83": {"t": 1786068460.45591, "n": 7523, "h": "ee4c97f5505bb3cc", "c": "import { useState, useEffect, useCallback } from 'react'\nimport { api, apiPut } from '../../api'\n\nconst PROVIDERS = {\n deepseek: {\n label: 'DeepSeek (API)',\n backend: 'api',\n model: 'deepseek-chat',\n host: 'https://api.deepseek.com',\n },\n local: {\n label: 'Local (vLLM)',\n backend: 'vllm',\n model: 'Qwen/Qwen2.5-7B-Instruct',\n host: '', // filled from IP/port inputs\n },\n ollama: {\n label: 'Local (Ollama)',\n backend: 'ollama',\n model: 'llama3',\n host: '', // filled from IP/port inputs\n },\n}\n\nconst DEFAULT_LOCAL_IP = 'localhost'\nconst DEFAULT_LOCAL_PORT = '8000'\n\nexport default function ProviderSelect() {\n const [provider, setProvider] = useState('deepseek')\n const [localIp, setLocalIp] = useState(DEFAULT_LOCAL_IP)\n const [localPort, setLocalPort] = useState(DEFAULT_LOCAL_PORT)\n const [localModel, setLocalModel] = useState(PROVIDERS.local.model)\n const [apiKey, setApiKey] = useState('')\n const [status, setStatus] = useState(null) // null | 'saving' | 'saved' | 'error'\n const [ollamaLocal, setOllamaLocal] = useState([]) // pulled models\n const [ollamaLibrary, setOllamaLibrary] = useState([]) // available to pull\n const [ollamaLoading, setOllamaLoading] = useState(false)\n const [customModel, setCustomModel] = useState(false) // typing a custom model name\n\n const fetchOllamaModels = useCallback((ip, port) => {\n const host = `http://${ip || localIp}:${port || localPort}`\n setOllamaLoading(true)\n api(`/ollama/models?host=${encodeURIComponent(host)}`)\n .then(data => {\n setOllamaLocal(data.local || [])\n setOllamaLibrary(data.library || [])\n })\n .catch(() => {\n setOllamaLocal([])\n setOllamaLibrary([])\n })\n .finally(() => setOllamaLoading(false))\n }, [localIp, localPort])\n\n // Load current settings on mount\n useEffect(() => {\n api('/settings').then(data => {\n if (data.backend === 'api') {\n setProvider('deepseek')\n } else if (data.backend === 'ollama') {\n setProvider('ollama')\n let ip = DEFAULT_LOCAL_IP, port = '11434'\n try {\n const url = new URL(data.host)\n ip = url.hostname\n port = url.port || '11434'\n } catch { /* keep defaults */ }\n setLocalIp(ip)\n setLocalPort(port)\n if (data.model) setLocalModel(data.model)\n // Fetch available models from this Ollama instance\n fetchOllamaModels(ip, port)\n } else {\n setProvider('local')\n try {\n const url = new URL(data.host)\n setLocalIp(url.hostname)\n setLocalPort(url.port || '8000')\n } catch {\n // keep defaults\n }\n if (data.model) setLocalModel(data.model)\n }\n }).catch(() => {})\n }, [fetchOllamaModels])\n\n const save = async () => {\n setStatus('saving')\n try {\n let body\n if (provider === 'deepseek') {\n body = {\n backend: 'api',\n model: PROVIDERS.deepseek.model,\n host: PROVIDERS.deepseek.host,\n api_key: apiKey,\n }\n } else {\n body = {\n backend: PROVIDERS[provider].backend,\n model: localModel,\n host: `http://${localIp}:${localPort}`,\n api_key: 'EMPTY',\n }\n }\n await apiPut('/settings', body)\n setStatus('saved')\n setTimeout(() => setStatus(null), 2000)\n } catch {\n setStatus('error')\n setTimeout(() => setStatus(null), 3000)\n }\n }\n\n return (\n
\n {\n const v = e.target.value\n setProvider(v)\n setStatus(null)\n setCustomModel(false)\n if (v === 'ollama') {\n setLocalPort('11434')\n setLocalModel(PROVIDERS.ollama.model)\n fetchOllamaModels(localIp, '11434')\n }\n if (v === 'local') { setLocalPort('8000'); setLocalModel(PROVIDERS.local.model) }\n }}\n >\n {Object.entries(PROVIDERS).map(([key, p]) => (\n \n ))}\n \n\n {(provider === 'local' || provider === 'ollama') && (\n
\n setLocalIp(e.target.value)}\n placeholder=\"IP address\"\n />\n :\n setLocalPort(e.target.value)}\n placeholder=\"Port\"\n />\n {provider === 'ollama' && !customModel ? (\n
\n {\n if (e.target.value === '__custom__') {\n setCustomModel(true)\n setLocalModel('')\n } else {\n setLocalModel(e.target.value)\n }\n }}\n >\n {ollamaLocal.length > 0 && (\n \n {ollamaLocal.map(m => )}\n \n )}\n {ollamaLibrary.length > 0 && (\n \n {ollamaLibrary.map(m => )}\n \n )}\n \n \n fetchOllamaModels()}\n disabled={ollamaLoading}\n title=\"Refresh model list\"\n >\n {ollamaLoading ? '...' : '\\u21BB'}\n \n
\n ) : (\n
\n setLocalModel(e.target.value)}\n placeholder=\"Model name\"\n />\n {provider === 'ollama' && (\n { setCustomModel(false); fetchOllamaModels() }}\n title=\"Back to model list\"\n >\n List\n \n )}\n
\n )}\n
\n )}\n\n {provider === 'deepseek' && (\n
\n setApiKey(e.target.value)}\n placeholder=\"API key (leave blank to keep current)\"\n />\n
\n )}\n\n \n {status === 'saving' ? 'Saving...' : status === 'saved' ? 'Saved' : status === 'error' ? 'Error' : 'Apply'}\n \n
\n )\n}\n"}}}}