"use client"; import { useState } from "react"; import { useTranslations } from "next-intl"; import { toast } from "sonner"; import { Key, Trash2, Check } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; type Provider = "openai" | "anthropic" | "openrouter" | "ollama"; const PROVIDERS: { id: Provider; label: string; placeholder: string }[] = [ { id: "openai", label: "OpenAI", placeholder: "sk-..." }, { id: "anthropic", label: "Anthropic", placeholder: "sk-ant-..." }, { id: "openrouter", label: "OpenRouter", placeholder: "sk-or-..." }, { id: "ollama", label: "Ollama (local)", placeholder: "Base URL uses env var" }, ]; export function ByokManager({ initialKeys }: { initialKeys: string[] }) { const t = useTranslations("settingsForm"); const [configuredKeys, setConfiguredKeys] = useState>(new Set(initialKeys)); const [inputs, setInputs] = useState>>({}); const [saving, setSaving] = useState(null); const [removing, setRemoving] = useState(null); async function saveKey(provider: Provider) { const apiKey = inputs[provider]?.trim(); if (!apiKey) return; setSaving(provider); try { const res = await fetch("/api/v1/ai-keys", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ provider, apiKey }), }); if (res.ok) { setConfiguredKeys((prev) => new Set([...prev, provider])); setInputs((prev) => ({ ...prev, [provider]: "" })); toast.success(t("byokSaved", { provider })); } else { toast.error(t("byokSaveFailed")); } } finally { setSaving(null); } } async function removeKey(provider: Provider) { setRemoving(provider); try { const res = await fetch(`/api/v1/ai-keys/${provider}`, { method: "DELETE" }); if (res.ok) { setConfiguredKeys((prev) => { const s = new Set(prev); s.delete(provider); return s; }); toast.success(t("byokRemoved", { provider })); } else { toast.error(t("byokRemoveFailed")); } } finally { setRemoving(null); } } return (
{PROVIDERS.map((p) => { const hasKey = configuredKeys.has(p.id); const isOllama = p.id === "ollama"; return (
{p.label}
{hasKey ? (
{t("byokConfigured")}
) : isOllama ? ( {t("byokOllamaHint")} ) : (
setInputs((prev) => ({ ...prev, [p.id]: e.target.value }))} className="h-8 text-sm" onKeyDown={(e) => { if (e.key === "Enter") { void saveKey(p.id); } }} />
)}
); })}

{t("byokFooter")}

); }