import React, { useState, useEffect } from "react"; import { Card, Title, Text, Grid, Badge, Button as TremorButton, Tab, TabGroup, TabList, TabPanel, TabPanels, TextInput, } from "@tremor/react"; import { Button, Form, Input, Select, message, Tooltip, Divider } from "antd"; import { InfoCircleOutlined } from '@ant-design/icons'; import { getGuardrailInfo, updateGuardrailCall, getGuardrailUISettings } from "@/components/networking"; import { getGuardrailLogoAndName } from "./guardrail_info_helpers"; import PiiConfiguration from "./pii_configuration"; export interface GuardrailInfoProps { guardrailId: string; onClose: () => void; accessToken: string | null; isAdmin: boolean; } const GuardrailInfoView: React.FC = ({ guardrailId, onClose, accessToken, isAdmin }) => { const [guardrailData, setGuardrailData] = useState(null); const [loading, setLoading] = useState(true); const [isEditing, setIsEditing] = useState(false); const [form] = Form.useForm(); const [selectedPiiEntities, setSelectedPiiEntities] = useState([]); const [selectedPiiActions, setSelectedPiiActions] = useState<{[key: string]: string}>({}); const [guardrailSettings, setGuardrailSettings] = useState<{ supported_entities: string[]; supported_actions: string[]; pii_entity_categories: Array<{ category: string; entities: string[]; }>; supported_modes: string[]; } | null>(null); const fetchGuardrailInfo = async () => { try { setLoading(true); if (!accessToken) return; const response = await getGuardrailInfo(accessToken, guardrailId); setGuardrailData(response); // Initialize PII configuration from guardrail data if (response.litellm_params?.pii_entities_config) { const piiConfig = response.litellm_params.pii_entities_config; // Clear previous selections setSelectedPiiEntities([]); setSelectedPiiActions({}); // Only if there are entities configured if (Object.keys(piiConfig).length > 0) { const entities: string[] = []; const actions: {[key: string]: string} = {}; Object.entries(piiConfig).forEach(([entity, action]: [string, any]) => { entities.push(entity); actions[entity] = typeof action === 'string' ? action : "MASK"; }); setSelectedPiiEntities(entities); setSelectedPiiActions(actions); } } else { // Clear selections if no PII config exists setSelectedPiiEntities([]); setSelectedPiiActions({}); } } catch (error) { message.error("Failed to load guardrail information"); console.error("Error fetching guardrail info:", error); } finally { setLoading(false); } }; const fetchGuardrailUISettings = async () => { try { if (!accessToken) return; const uiSettings = await getGuardrailUISettings(accessToken); setGuardrailSettings(uiSettings); } catch (error) { console.error("Error fetching guardrail UI settings:", error); } }; useEffect(() => { fetchGuardrailInfo(); fetchGuardrailUISettings(); }, [guardrailId, accessToken]); const handlePiiEntitySelect = (entity: string) => { setSelectedPiiEntities(prev => { if (prev.includes(entity)) { return prev.filter(e => e !== entity); } else { return [...prev, entity]; } }); }; const handlePiiActionSelect = (entity: string, action: string) => { setSelectedPiiActions(prev => ({ ...prev, [entity]: action })); }; const handleGuardrailUpdate = async (values: any) => { try { if (!accessToken) return; // Prepare update data object const updateData: any = { guardrail_name: values.guardrail_name, litellm_params: { default_on: values.default_on, }, guardrail_info: values.guardrail_info ? JSON.parse(values.guardrail_info) : undefined }; // Only add PII entities config if we have selected entities if (selectedPiiEntities.length > 0) { // Create PII config object only with selected entities const piiEntitiesConfig: {[key: string]: string} = {}; selectedPiiEntities.forEach(entity => { piiEntitiesConfig[entity] = selectedPiiActions[entity] || "MASK"; }); // Add to litellm_params only if we have entities updateData.litellm_params.pii_entities_config = piiEntitiesConfig; } else { // If no entities selected, explicitly set to empty object // This will clear any existing PII config updateData.litellm_params.pii_entities_config = {}; } await updateGuardrailCall(accessToken, guardrailId, updateData); message.success("Guardrail updated successfully"); fetchGuardrailInfo(); setIsEditing(false); } catch (error) { console.error("Error updating guardrail:", error); message.error("Failed to update guardrail"); } }; if (loading) { return
Loading...
; } if (!guardrailData) { return
Guardrail not found
; } // Format date helper function const formatDate = (dateString?: string) => { if (!dateString) return "-"; const date = new Date(dateString); return date.toLocaleString(); }; // Format the provider display name and logo const { logo, displayName } = getGuardrailLogoAndName(guardrailData.litellm_params?.guardrail || ""); return (
{guardrailData.guardrail_name || "Unnamed Guardrail"} {guardrailData.guardrail_id}
Overview {isAdmin ? Settings : <>} {/* Overview Panel */} Provider
{logo && ( {`${displayName} { // Hide broken image (e.target as HTMLImageElement).style.display = 'none'; }} /> )} {displayName}
Mode
{guardrailData.litellm_params?.mode || "-"} {guardrailData.litellm_params?.default_on ? "Default On" : "Default Off"}
Created At
{formatDate(guardrailData.created_at)} Last Updated: {formatDate(guardrailData.updated_at)}
{guardrailData.litellm_params?.pii_entities_config && Object.keys(guardrailData.litellm_params.pii_entities_config).length > 0 && (
PII Protection {Object.keys(guardrailData.litellm_params.pii_entities_config).length} PII entities configured
)} {guardrailData.guardrail_info && Object.keys(guardrailData.guardrail_info).length > 0 && ( Guardrail Info
{Object.entries(guardrailData.guardrail_info).map(([key, value]) => (
{key} {typeof value === 'object' ? JSON.stringify(value, null, 2) : String(value)}
))}
)}
{/* Settings Panel (only for admins) */} {isAdmin && (
Guardrail Settings {!isEditing && ( setIsEditing(true)} > Edit Settings )}
{isEditing ? (
PII Protection
{guardrailSettings && ( )}
Advanced Settings
Save Changes
) : (
Guardrail ID
{guardrailData.guardrail_id}
Guardrail Name
{guardrailData.guardrail_name || "Unnamed Guardrail"}
Provider
{displayName}
Mode
{guardrailData.litellm_params?.mode || "-"}
Default On {guardrailData.litellm_params?.default_on ? "Yes" : "No"}
{guardrailData.litellm_params?.pii_entities_config && Object.keys(guardrailData.litellm_params.pii_entities_config).length > 0 && (
PII Protection
{Object.keys(guardrailData.litellm_params.pii_entities_config).length} PII entities configured
)}
Created At
{formatDate(guardrailData.created_at)}
Last Updated
{formatDate(guardrailData.updated_at)}
)}
)}
); }; export default GuardrailInfoView;