"use client"; import { useParams, notFound } from "next/navigation"; import Link from "next/link"; import { useEffect, useState } from "react"; import { Card, Badge, Button, AddCustomEmbeddingModal } from "@/shared/components"; import ProviderIcon from "@/shared/components/ProviderIcon"; import { MEDIA_PROVIDER_KINDS, AI_PROVIDERS, getProvidersByKind } from "@/shared/constants/providers"; function getEffectiveStatus(conn) { const isCooldown = Object.entries(conn).some( ([k, v]) => k.startsWith("modelLock_") && v && new Date(v).getTime() > Date.now() ); return conn.testStatus === "unavailable" && !isCooldown ? "active" : conn.testStatus; } function MediaProviderCard({ provider, kind, connections, isCustom }) { const providerInfo = AI_PROVIDERS[provider.id]; const isNoAuth = !!providerInfo?.noAuth; const providerConns = connections.filter((c) => c.provider === provider.id); const connected = providerConns.filter((c) => { const s = getEffectiveStatus(c); return s === "active" || s === "success"; }).length; const error = providerConns.filter((c) => { const s = getEffectiveStatus(c); return s === "error" || s === "expired" || s === "unavailable"; }).length; const total = providerConns.length; const allDisabled = total > 0 && providerConns.every((c) => c.isActive === false); const renderStatus = () => { if (isNoAuth) return Ready; if (allDisabled) return Disabled; if (total === 0) return No connections; return ( <> {connected > 0 && {connected} Connected} {error > 0 && {error} Error} {connected === 0 && error === 0 && {total} Added} ); }; return (
7 ? provider.color : (provider.color ?? "#888") + "15"}` }} >

{provider.name}

{isCustom && Custom} {renderStatus()}
); } export default function MediaProviderKindPage() { const { kind } = useParams(); const [connections, setConnections] = useState([]); const [customNodes, setCustomNodes] = useState([]); const [showAddCustomEmbedding, setShowAddCustomEmbedding] = useState(false); const kindConfig = MEDIA_PROVIDER_KINDS.find((k) => k.id === kind); const isEmbedding = kind === "embedding"; useEffect(() => { if (!kindConfig) return; fetch("/api/providers", { cache: "no-store" }) .then((r) => r.json()) .then((d) => setConnections(d.connections || [])) .catch(() => {}); if (isEmbedding) { fetch("/api/provider-nodes", { cache: "no-store" }) .then((r) => r.json()) .then((d) => setCustomNodes((d.nodes || []).filter((n) => n.type === "custom-embedding"))) .catch(() => {}); } }, [isEmbedding, kindConfig]); if (!kindConfig) return notFound(); const providers = getProvidersByKind(kind); // Map custom nodes to MediaProviderCard shape const customProviders = customNodes.map((n) => ({ id: n.id, name: n.name || "Custom Embedding", color: "#6366F1", textIcon: "CE", })); const allProviders = [...providers, ...customProviders]; return (
{isEmbedding && (
)} {allProviders.length === 0 ? (
No providers support {kindConfig.label} yet.
) : (
{providers.map((provider) => ( ))} {customProviders.map((provider) => ( ))}
)} {isEmbedding && ( setShowAddCustomEmbedding(false)} onCreated={(node) => { setCustomNodes((prev) => [...prev, node]); setShowAddCustomEmbedding(false); }} /> )}
); }