import React, { useState, useEffect } from 'react'; import { Form, Typography, Select, Input, Switch, Modal, message, Divider } from 'antd'; import { Button, TextInput } from '@tremor/react'; import { GuardrailProviders, guardrail_provider_map, guardrailLogoMap } from './guardrail_info_helpers'; import { getGuardrailUISettings } from '../networking'; import PiiConfiguration from './pii_configuration'; const { Title, Text } = Typography; const { Option } = Select; interface EditGuardrailFormProps { visible: boolean; onClose: () => void; accessToken: string | null; onSuccess: () => void; guardrailId: string; initialValues: { guardrail_name: string; provider: string; mode: string; default_on: boolean; pii_entities_config?: {[key: string]: string}; [key: string]: any; }; } interface GuardrailSettings { supported_entities: string[]; supported_actions: string[]; supported_modes: string[]; pii_entity_categories: Array<{ category: string; entities: string[]; }>; } const EditGuardrailForm: React.FC = ({ visible, onClose, accessToken, onSuccess, guardrailId, initialValues }) => { const [form] = Form.useForm(); const [loading, setLoading] = useState(false); const [selectedProvider, setSelectedProvider] = useState(initialValues?.provider || null); const [guardrailSettings, setGuardrailSettings] = useState(null); const [selectedEntities, setSelectedEntities] = useState([]); const [selectedActions, setSelectedActions] = useState<{[key: string]: string}>({}); // Fetch guardrail settings when the component mounts useEffect(() => { const fetchGuardrailSettings = async () => { try { if (!accessToken) return; const data = await getGuardrailUISettings(accessToken); setGuardrailSettings(data); } catch (error) { console.error('Error fetching guardrail settings:', error); message.error('Failed to load guardrail settings'); } }; fetchGuardrailSettings(); }, [accessToken]); // Initialize selected entities and actions from initialValues useEffect(() => { if (initialValues?.pii_entities_config && Object.keys(initialValues.pii_entities_config).length > 0) { const entities = Object.keys(initialValues.pii_entities_config); setSelectedEntities(entities); setSelectedActions(initialValues.pii_entities_config); } }, [initialValues]); const handleProviderChange = (value: string) => { setSelectedProvider(value); // Reset form fields that are provider-specific form.setFieldsValue({ config: undefined }); // Reset PII selections when changing provider setSelectedEntities([]); setSelectedActions({}); }; const handleEntitySelect = (entity: string) => { setSelectedEntities(prev => { if (prev.includes(entity)) { return prev.filter(e => e !== entity); } else { return [...prev, entity]; } }); }; const handleActionSelect = (entity: string, action: string) => { setSelectedActions(prev => ({ ...prev, [entity]: action })); }; const handleSubmit = async () => { try { setLoading(true); const values = await form.validateFields(); // Get the guardrail provider value from the map const guardrailProvider = guardrail_provider_map[values.provider]; // Prepare the guardrail data with proper types for litellm_params const guardrailData: { guardrail_id: string; guardrail: { guardrail_name: string; litellm_params: { guardrail: string; mode: string; default_on: boolean; [key: string]: any; // Allow dynamic properties }; guardrail_info: any; } } = { guardrail_id: guardrailId, guardrail: { guardrail_name: values.guardrail_name, litellm_params: { guardrail: guardrailProvider, mode: values.mode, default_on: values.default_on }, guardrail_info: {} } }; // For Presidio PII, add the entity and action configurations if (values.provider === 'PresidioPII' && selectedEntities.length > 0) { const piiEntitiesConfig: {[key: string]: string} = {}; selectedEntities.forEach(entity => { piiEntitiesConfig[entity] = selectedActions[entity] || 'MASK'; // Default to MASK if no action selected }); guardrailData.guardrail.litellm_params.pii_entities_config = piiEntitiesConfig; } // Add config values to the guardrail_info if provided else if (values.config) { try { const configObj = JSON.parse(values.config); // For some guardrails, the config values need to be in litellm_params // Especially for providers like Bedrock that need guardrailIdentifier and guardrailVersion if (values.provider === 'Bedrock' && configObj) { if (configObj.guardrail_id) { guardrailData.guardrail.litellm_params.guardrailIdentifier = configObj.guardrail_id; } if (configObj.guardrail_version) { guardrailData.guardrail.litellm_params.guardrailVersion = configObj.guardrail_version; } } else { // For other providers, add the config to guardrail_info guardrailData.guardrail.guardrail_info = configObj; } } catch (error) { message.error('Invalid JSON in configuration'); setLoading(false); return; } } if (!accessToken) { throw new Error("No access token available"); } console.log("Sending guardrail update data:", JSON.stringify(guardrailData)); // Call the update endpoint const url = `/guardrails/${guardrailId}`; const response = await fetch(url, { method: "PUT", headers: { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json", }, body: JSON.stringify(guardrailData), }); if (!response.ok) { const errorData = await response.text(); throw new Error(errorData || "Failed to update guardrail"); } message.success('Guardrail updated successfully'); // Reset and close onSuccess(); onClose(); } catch (error) { console.error("Failed to update guardrail:", error); message.error('Failed to update guardrail: ' + (error instanceof Error ? error.message : String(error))); } finally { setLoading(false); } }; const renderPiiConfiguration = () => { if (!guardrailSettings || !selectedProvider || selectedProvider !== 'PresidioPII') return null; return ( ); }; const renderProviderSpecificFields = () => { if (!selectedProvider) return null; // For Presidio, we use the new PII configuration UI if (selectedProvider === 'PresidioPII') { return renderPiiConfiguration(); } switch (selectedProvider) { case 'Aporia': return ( ); case 'AimSecurity': return ( ); case 'Bedrock': return ( ); case 'GuardrailsAI': return ( ); case 'LakeraAI': return ( ); case 'PromptInjection': return ( ); default: return ( ); } }; return (
{renderProviderSpecificFields()}
); }; export default EditGuardrailForm;