"use client"; import { useState, useEffect } from "react"; import { getAIProviderSettings } from "@/actions/integrations/ai-providers"; type AIProvider = "openai" | "anthropic" | "google" | "xai" | "minimax" | "custom"; const PROVIDER_MODELS: Record, string[]> = { openai: ["gpt-4o", "gpt-4o-mini", "gpt-4-turbo", "gpt-3.5-turbo"], anthropic: ["claude-sonnet-4-5", "claude-sonnet-4-20250514", "claude-opus-4-1", "claude-opus-4-20250514", "claude-3-7-sonnet-20250219", "claude-3-5-haiku-20241022", "claude-3-haiku-20240307"], google: ["gemini-2.0-flash", "gemini-1.5-pro", "gemini-1.5-flash", "gemini-pro"], xai: ["grok-2", "grok-2-mini", "grok-1.5"], minimax: ["MiniMax-M3", "MiniMax-M3-highspeed", "MiniMax-M2.5", "MiniMax-M2.5-highspeed", "MiniMax-M2.7", "MiniMax-M2.1", "MiniMax-M2"], }; // Icons const SparkleIcon = ({ className }: { className?: string }) => ( ); const RobotIcon = ({ className }: { className?: string }) => ( ); const BrainIcon = ({ className }: { className?: string }) => ( ); const CircleIcon = ({ className }: { className?: string }) => ( ); const TornadoIcon = ({ className }: { className?: string }) => ( ); const WrenchIcon = ({ className }: { className?: string }) => ( ); const EyeIcon = ({ className }: { className?: string }) => ( ); const EyeOffIcon = ({ className }: { className?: string }) => ( ); const CheckIcon = ({ className }: { className?: string }) => ( ); const AlertIcon = ({ className }: { className?: string }) => ( ); const PROVIDERS: { id: AIProvider; name: string; icon: React.ReactNode; description: string; website: string; color: string }[] = [ { id: "openai", name: "OpenAI", icon: , description: "GPT-4o, GPT-4o-mini, GPT-4 Turbo. Industry standard.", website: "openai.com", color: "bg-emerald-500" }, { id: "anthropic", name: "Anthropic", icon: , description: "Claude 3.5 Sonnet, Claude 3 Opus. Best for reasoning.", website: "anthropic.com", color: "bg-amber-500" }, { id: "google", name: "Google", icon: , description: "Gemini 2.0 Flash, 1.5 Pro. Fast, cost-effective.", website: "ai.google", color: "bg-blue-500" }, { id: "xai", name: "xAI", icon: , description: "Grok-2, Grok-1.5. Real-time data, humor.", website: "x.ai", color: "bg-orange-500" }, { id: "minimax", name: "MiniMax", icon: , description: "MiniMax-M3, M2.5, M2. OpenAI-compatible.", website: "minimax.io", color: "bg-violet-500" }, { id: "custom", name: "Custom", icon: , description: "Any OpenAI-compatible API endpoint.", website: "", color: "bg-stone-500" }, ]; type Props = { brandId: string; }; export default function AIProviderPanel({ brandId }: Props) { const [provider, setProvider] = useState("openai"); const [apiKey, setApiKey] = useState(""); const [orgId, setOrgId] = useState(""); const [model, setModel] = useState("gpt-4o-mini"); const [customEndpoint, setCustomEndpoint] = useState(""); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [testResult, setTestResult] = useState<{ ok: boolean; message: string } | null>(null); const [showKey, setShowKey] = useState(false); useEffect(() => { let cancelled = false; void (async () => { try { const data = await getAIProviderSettings(brandId); if (cancelled) return; setProvider((data.provider as AIProvider) ?? "openai"); setApiKey(data.apiKey ?? ""); setOrgId(data.orgId ?? ""); setModel(data.model ?? "gpt-4o-mini"); setCustomEndpoint(data.customEndpoint ?? ""); } catch {} if (!cancelled) setLoading(false); })(); return () => { cancelled = true; }; }, [brandId]); async function handleSave() { setSaving(true); setTestResult(null); try { const res = await fetch("/api/integrations/ai-provider", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ brandId, provider, apiKey, orgId, model, customEndpoint }), }); const data = await res.json(); if (!res.ok) throw new Error(data.error ?? "Save failed"); setTestResult({ ok: true, message: "AI provider settings saved" }); } catch (err) { setTestResult({ ok: false, message: err instanceof Error ? err.message : "Save failed" }); } setSaving(false); } async function handleTest() { setTestResult(null); setSaving(true); try { const res = await fetch("/api/integrations/ai-provider/test", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ brandId }), }); const data = await res.json(); if (!res.ok) throw new Error(data.error ?? "Connection failed"); setTestResult({ ok: true, message: data.message ?? "Connection successful" }); } catch (err) { setTestResult({ ok: false, message: err instanceof Error ? err.message : "Test failed" }); } setSaving(false); } const models = provider === "custom" ? ["gpt-4o-mini"] : (PROVIDER_MODELS[provider] ?? []); if (loading) { return (
{[1,2,3,4,5].map(i =>
)}
); } return (
{/* Provider Selection Card */}

AI Provider

Choose your AI model provider for all AI tools

{PROVIDERS.map((p) => ( ))}
{/* Credentials Card */} {provider !== "custom" && (

Credentials

setApiKey(e.target.value)} placeholder={provider === "anthropic" ? "sk-ant-..." : provider === "google" ? "AIza..." : provider === "xai" ? "xai-..." : provider === "minimax" ? "ey..." : "sk-..."} className="w-full rounded-lg border border-[var(--admin-border)] bg-white px-3 py-2.5 text-sm text-[var(--admin-text-primary)] placeholder:text-stone-400 outline-none focus:border-emerald-500 focus:ring-1 focus:ring-emerald-500" />
{provider === "openai" && (
setOrgId(e.target.value)} placeholder="org-..." className="w-full rounded-lg border border-[var(--admin-border)] bg-white px-3 py-2.5 text-sm text-[var(--admin-text-primary)] placeholder:text-stone-400 outline-none focus:border-emerald-500 focus:ring-1 focus:ring-emerald-500" />
)}
)} {/* Custom Endpoint Card */} {provider === "custom" && (

Custom API Endpoint

Connect any OpenAI-compatible API

setApiKey(e.target.value)} placeholder="sk-..." className="w-full rounded-lg border border-[var(--admin-border)] bg-white px-3 py-2.5 text-sm text-[var(--admin-text-primary)] placeholder:text-stone-400 outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500" />
setCustomEndpoint(e.target.value)} placeholder="https://api.openai.com/v1 or http://localhost:11434/v1" className="w-full rounded-lg border border-[var(--admin-border)] bg-white px-3 py-2.5 text-sm text-[var(--admin-text-primary)] placeholder:text-stone-400 outline-none focus:border-violet-500 focus:ring-1 focus:ring-violet-500" />
)} {/* Model Selection Card */}

Model

{models.map((m) => ( ))}
{/* Test Result */} {testResult && (
{testResult.ok ? : } {testResult.message}
)} {/* Actions */}
); }