"use client"; import { useState, useEffect, useCallback, useRef } from "react"; import { Card, Button, Toggle, ProxyConfigModal } from "@/shared/components"; import { useTranslations } from "next-intl"; type GlobalProxyConfig = { type: string; host: string; port: number } | null; type HealthcheckResult = { proxyUrl: string; ok: boolean; latencyMs: number | null; }; type HealthcheckSummary = { total: number; working: number; failed: number; }; export default function GlobalConfigTab() { const [proxyModalOpen, setProxyModalOpen] = useState(false); const [globalProxy, setGlobalProxy] = useState(null); const [perKeyProxyEnabled, setPerKeyProxyEnabled] = useState(false); const [perKeyLoading, setPerKeyLoading] = useState(true); const [targetUrl, setTargetUrl] = useState("https://api.openai.com/v1/models"); const [testing, setTesting] = useState(false); const [results, setResults] = useState(null); const [summary, setSummary] = useState(null); const [error, setError] = useState(null); const mountedRef = useRef(true); const t = useTranslations("settings"); const tc = useTranslations("common"); const loadGlobalProxy = useCallback(async () => { try { const res = await fetch("/api/settings/proxy?level=global"); if (res.ok) { const data = await res.json(); setGlobalProxy(data.proxy || null); } } catch {} }, []); const loadPerKeyProxyEnabled = useCallback(async () => { try { const res = await fetch("/api/settings", { cache: "no-store" }); if (res.ok) { const data = await res.json(); if (mountedRef.current) setPerKeyProxyEnabled(data.perKeyProxyEnabled === true); } } catch { /* leave default */ } finally { if (mountedRef.current) setPerKeyLoading(false); } }, []); useEffect(() => { mountedRef.current = true; loadGlobalProxy(); loadPerKeyProxyEnabled(); return () => { mountedRef.current = false; }; }, [loadGlobalProxy, loadPerKeyProxyEnabled]); const handleTogglePerKeyProxyEnabled = async () => { const newValue = !perKeyProxyEnabled; try { const res = await fetch("/api/settings", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ perKeyProxyEnabled: newValue }), }); if (res.ok) { setPerKeyProxyEnabled(newValue); } } catch (err) { console.error("Failed to update per-key proxy setting:", err); } }; const runHealthcheck = async () => { setTesting(true); setResults(null); setSummary(null); setError(null); try { const res = await fetch("/api/proxy-fallback/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ targetUrl }), }); if (!res.ok) { const err = await res.json().catch(() => ({ error: "Request failed" })); setError(err.error || `HTTP ${res.status}`); return; } const data = await res.json(); setResults(data.results); setSummary(data.summary); } catch (err: unknown) { setError(err instanceof Error ? err.message : t("healthcheckFailed")); } finally { setTesting(false); } }; return ( <>

{t("globalProxy")}

{t("globalProxyDesc")}

{globalProxy ? ( {globalProxy.type}://{globalProxy.host}:{globalProxy.port} ) : ( {t("noGlobalProxy")} )}

{t("perKeyProxyEnabled")}

{t("perKeyProxyEnabledDesc")}

{t("bulkHealthcheck")}

{t("bulkHealthcheckDesc")}

setTargetUrl(e.target.value)} placeholder="https://api.openai.com/v1/models" className="flex-1 px-3 py-2 rounded-lg bg-black/5 dark:bg-white/5 border border-black/10 dark:border-white/10 text-sm font-mono focus:outline-none focus:ring-2 focus:ring-primary/50" />
{error && (
{error}
)} {testing && !results && (
refresh {t("healthcheckTestingAll")}
)} {summary && (
{t("healthcheckTotal")}: {summary.total} {t("healthcheckWorking")}: {summary.working} {t("healthcheckFailedLabel")}: {summary.failed}
)} {results && results.length > 0 && (
{results.map((r, i) => ( ))}
{t("healthcheckStatus")} {t("healthcheckProxyUrl")} {t("healthcheckLatency")}
{r.ok ? ( ) : ( )} {r.proxyUrl} {r.latencyMs !== null ? `${r.latencyMs}ms` : "—"}
)}
setProxyModalOpen(false)} level="global" levelLabel={t("globalLabel")} onSaved={loadGlobalProxy} /> ); }