import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, } from "@/components/ui/alertDialog"; import { Button } from "@/components/ui/button"; import { CardHeader, CardTitle } from "@/components/ui/card"; import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdownMenu"; import { Switch } from "@/components/ui/switch"; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"; import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"; import { getErrorMessage } from "@/lib/store"; import { useDeleteProviderKeyMutation, useGetProviderKeysQuery, useUpdateProviderKeyMutation } from "@/lib/store/apis/providersApi"; import { ModelProvider } from "@/lib/types/config"; import { cn } from "@/lib/utils"; import { RbacOperation, RbacResource, useRbac } from "@enterprise/lib"; import { AlertCircle, CheckCircle2, EllipsisIcon, PencilIcon, PlusIcon, TrashIcon } from "lucide-react"; import { ReactNode, useState } from "react"; import { toast } from "sonner"; import AddNewKeySheet from "../dialogs/addNewKeySheet"; interface Props { className?: string; provider: ModelProvider; headerActions?: ReactNode; isKeyless?: boolean; } export default function ModelProviderKeysTableView({ provider, className, headerActions, isKeyless }: Props) { const providerName = provider.name?.toLowerCase() ?? ""; const isVLLM = providerName === "vllm"; const isOllamaOrSGL = providerName === "ollama" || providerName === "sgl"; const entityLabel = isVLLM ? "model" : isOllamaOrSGL ? "server" : "key"; const entityLabelPlural = isVLLM ? "models" : isOllamaOrSGL ? "servers" : "keys"; const EntityLabel = entityLabel.charAt(0).toUpperCase() + entityLabel.slice(1); const hasUpdateProviderAccess = useRbac(RbacResource.ModelProvider, RbacOperation.Update); const hasDeleteProviderAccess = useRbac(RbacResource.ModelProvider, RbacOperation.Delete); const [updateProviderKey, { isLoading: isUpdatingProviderKey }] = useUpdateProviderKeyMutation(); const [deleteProviderKey, { isLoading: isDeletingProviderKey }] = useDeleteProviderKeyMutation(); const { data: keys = [] } = useGetProviderKeysQuery(provider.name); const isMutatingProviderKey = isUpdatingProviderKey || isDeletingProviderKey; const [togglingKeyIds, setTogglingKeyIds] = useState>(new Set()); const [showAddNewKeyDialog, setShowAddNewKeyDialog] = useState<{ show: boolean; keyId: string | null } | undefined>(undefined); const [showDeleteKeyDialog, setShowDeleteKeyDialog] = useState<{ show: boolean; keyId: string } | undefined>(undefined); function handleAddKey() { setShowAddNewKeyDialog({ show: true, keyId: null }); } return (
{showDeleteKeyDialog && ( e.stopPropagation()}> Delete {EntityLabel} Are you sure you want to delete this {entityLabel}. This action cannot be undone. setShowDeleteKeyDialog(undefined)} disabled={isMutatingProviderKey}> Cancel { deleteProviderKey({ provider: provider.name, keyId: showDeleteKeyDialog.keyId, }) .unwrap() .then(() => { toast.success(`${EntityLabel} deleted successfully`); setShowDeleteKeyDialog(undefined); }) .catch((err) => { toast.error(`Failed to delete ${entityLabel}`, { description: getErrorMessage(err), }); }); }} > Delete )} {showAddNewKeyDialog && ( setShowAddNewKeyDialog(undefined)} provider={provider} keyId={showAddNewKeyDialog.keyId} providerName={providerName} /> )}
Configured {entityLabelPlural}
{headerActions} {!isKeyless && ( )}
{isKeyless ? (

This is a keyless provider - no API keys are required.

You can edit the provider configuration using the button above.

) : (
{isVLLM ? "Model" : isOllamaOrSGL ? "Server" : "API Key"} Weight Enabled {keys.length === 0 && ( No {entityLabelPlural} found. )} {keys.map((key) => { const isKeyEnabled = key.enabled ?? true; return ( {}} >
{key.status === "success" && ( List models working )} {key.status === "list_models_failed" && (() => { // Check if the failure might be due to an env var that the server couldn't resolve const hasEnvVarConfig = key.azure_key_config?.endpoint?.from_env || key.vertex_key_config?.project_id?.from_env || key.vertex_key_config?.region?.from_env || key.bedrock_key_config?.region?.from_env || key.vllm_key_config?.url?.from_env || key.value?.from_env; const isEnvResolutionError = hasEnvVarConfig && key.description && /not set|empty|missing/i.test(key.description); return isEnvResolutionError ? ( {key.description} — verify the environment variable is set on the server ) : ( {key.description || "Model discovery failed for this key"} ); })()} {key.name}
{key.weight}
{ setTogglingKeyIds((prev) => new Set(prev).add(key.id)); await updateProviderKey({ provider: provider.name, keyId: key.id, key: { ...key, enabled: checked }, }) .unwrap() .then(() => { toast.success(`${EntityLabel} ${checked ? "enabled" : "disabled"} successfully`); }) .catch((err) => { toast.error(`Failed to update ${entityLabel}`, { description: getErrorMessage(err) }); }) .finally(() => { setTogglingKeyIds((prev) => { const next = new Set(prev); next.delete(key.id); return next; }); }); }} />
{ setShowAddNewKeyDialog({ show: true, keyId: key.id }); }} disabled={!hasUpdateProviderAccess} > Edit { setShowDeleteKeyDialog({ show: true, keyId: key.id }); }} disabled={!hasDeleteProviderAccess} > Delete
); })}
)}
); }