diff --git a/litellm/proxy/_new_secret_config.yaml b/litellm/proxy/_new_secret_config.yaml index 6f527e268b2..fc0785904db 100644 --- a/litellm/proxy/_new_secret_config.yaml +++ b/litellm/proxy/_new_secret_config.yaml @@ -14,14 +14,388 @@ model_list: litellm_params: model: openai/gpt-4.1-mini +# ============================================================================== +# GUARDRAILS - PII Detection for Fortescue (Australian Mining Company) +# ============================================================================== + guardrails: - - guardrail_name: redact-ssn + # -------------------------------------------------------------------------- + # 1. AUSTRALIAN-SPECIFIC PII PATTERNS + # -------------------------------------------------------------------------- + - guardrail_name: au-pii-tax-identifiers + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # Australian Tax File Number (8-9 digits) + - pattern_type: prebuilt + pattern_name: au_tfn + action: MASK + # Australian Business Number (11 digits) + - pattern_type: prebuilt + pattern_name: au_abn + action: MASK + # Australian Medicare Number + - pattern_type: prebuilt + pattern_name: au_medicare + action: MASK + pattern_redaction_format: "[{pattern_name}_REDACTED]" + + - guardrail_name: au-pii-passports + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # Australian passport (critical for mining contractors/fly-in-fly-out workers) + - pattern_type: prebuilt + pattern_name: passport_australia + action: MASK + pattern_redaction_format: "[PASSPORT_REDACTED]" + + # -------------------------------------------------------------------------- + # 2. INTERNATIONAL PII (for global workforce) + # -------------------------------------------------------------------------- + - guardrail_name: international-pii-identifiers + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # US employees/contractors + - pattern_type: prebuilt + pattern_name: us_ssn + action: MASK + - pattern_type: prebuilt + pattern_name: us_ssn_no_dash + action: MASK + - pattern_type: prebuilt + pattern_name: passport_us + action: MASK + # UK operations + - pattern_type: prebuilt + pattern_name: passport_uk + action: MASK + # European operations + - pattern_type: prebuilt + pattern_name: passport_germany + action: MASK + - pattern_type: prebuilt + pattern_name: passport_france + action: MASK + - pattern_type: prebuilt + pattern_name: passport_netherlands + action: MASK + # Dutch BSN (contextual) + - pattern_type: prebuilt + pattern_name: nl_bsn_contextual + action: MASK + # Asian Pacific operations + - pattern_type: prebuilt + pattern_name: passport_china + action: MASK + - pattern_type: prebuilt + pattern_name: passport_india + action: MASK + - pattern_type: prebuilt + pattern_name: passport_japan + action: MASK + # Canadian operations + - pattern_type: prebuilt + pattern_name: passport_canada + action: MASK + # South American operations (mining companies often have Brazilian presence) + - pattern_type: prebuilt + pattern_name: br_cpf + action: MASK + - pattern_type: prebuilt + pattern_name: br_cpf_unformatted + action: MASK + - pattern_type: prebuilt + pattern_name: br_rg + action: MASK + - pattern_type: prebuilt + pattern_name: br_cnpj + action: MASK + pattern_redaction_format: "[{pattern_name}_REDACTED]" + + # -------------------------------------------------------------------------- + # 3. CONTACT INFORMATION + # -------------------------------------------------------------------------- + - guardrail_name: contact-information-pii + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # Email addresses (employees, contractors, suppliers) + - pattern_type: prebuilt + pattern_name: email + action: MASK + # Phone numbers (US format, commonly used internationally) + - pattern_type: prebuilt + pattern_name: us_phone + action: MASK + # Brazilian phones (if applicable) + - pattern_type: prebuilt + pattern_name: br_phone_landline + action: MASK + - pattern_type: prebuilt + pattern_name: br_phone_mobile + action: MASK + # Street addresses (mining sites, offices, residential) + - pattern_type: prebuilt + pattern_name: street_address + action: MASK + # Postal codes + - pattern_type: prebuilt + pattern_name: br_cep + action: MASK + pattern_redaction_format: "[{pattern_name}_REDACTED]" + + # -------------------------------------------------------------------------- + # 4. FINANCIAL & PAYMENT INFORMATION + # -------------------------------------------------------------------------- + - guardrail_name: financial-pii + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # Credit cards (corporate cards, employee expenses) + - pattern_type: prebuilt + pattern_name: visa + action: MASK + - pattern_type: prebuilt + pattern_name: mastercard + action: MASK + - pattern_type: prebuilt + pattern_name: amex + action: MASK + - pattern_type: prebuilt + pattern_name: discover + action: MASK + - pattern_type: prebuilt + pattern_name: credit_card + action: MASK + # International banking (IBAN for international payments) + - pattern_type: prebuilt + pattern_name: iban + action: MASK + pattern_redaction_format: "[{pattern_name}_REDACTED]" + + # -------------------------------------------------------------------------- + # 5. CREDENTIALS & API KEYS (BLOCK - High Risk) + # -------------------------------------------------------------------------- + - guardrail_name: credentials-api-keys + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # AWS credentials (critical infrastructure access) + - pattern_type: prebuilt + pattern_name: aws_access_key + action: BLOCK + - pattern_type: prebuilt + pattern_name: aws_secret_key + action: BLOCK + # GitHub tokens (code repository access) + - pattern_type: prebuilt + pattern_name: github_token + action: BLOCK + # Slack tokens (internal communications) + - pattern_type: prebuilt + pattern_name: slack_token + action: BLOCK + # Generic API keys + - pattern_type: prebuilt + pattern_name: generic_api_key + action: BLOCK + pattern_redaction_format: "[{pattern_name}_REDACTED]" + + # -------------------------------------------------------------------------- + # 6. NETWORK INFORMATION (Mining operations, remote sites) + # -------------------------------------------------------------------------- + - guardrail_name: network-infrastructure-pii + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # IP addresses (internal network, mining site infrastructure) + - pattern_type: prebuilt + pattern_name: ipv4 + action: MASK + - pattern_type: prebuilt + pattern_name: ipv6 + action: MASK + pattern_redaction_format: "[INTERNAL_IP_REDACTED]" + + # -------------------------------------------------------------------------- + # 7. PROTECTED CLASS INFORMATION (Fair Lending, HR Compliance) + # Critical for mining industry with diverse workforce + # -------------------------------------------------------------------------- + - guardrail_name: protected-class-information + litellm_params: + guardrail: litellm_content_filter + mode: pre_call + patterns: + # Gender and sexual orientation (workplace discrimination prevention) + - pattern_type: prebuilt + pattern_name: gender_sexual_orientation + action: MASK + # Race, ethnicity, national origin (diversity/inclusion compliance) + - pattern_type: prebuilt + pattern_name: race_ethnicity_national_origin + action: MASK + # Religion and creed + - pattern_type: prebuilt + pattern_name: religion + action: MASK + # Age discrimination (important for mining workforce management) + - pattern_type: prebuilt + pattern_name: age_discrimination + action: MASK + # Disability status (safety accommodations, worker's compensation) + - pattern_type: prebuilt + pattern_name: disability + action: MASK + # Marital and family status (relocation, benefits) + - pattern_type: prebuilt + pattern_name: marital_family_status + action: MASK + # Military status + - pattern_type: prebuilt + pattern_name: military_status + action: MASK + # Public assistance status + - pattern_type: prebuilt + pattern_name: public_assistance + action: MASK + pattern_redaction_format: "[PROTECTED_CLASS_INFO_REDACTED]" + + # -------------------------------------------------------------------------- + # 8. CUSTOM CODE GUARDRAIL - Mining Industry Specific PII + # -------------------------------------------------------------------------- + - guardrail_name: mining-industry-custom-pii litellm_params: guardrail: custom_code mode: pre_call custom_code: | def apply_guardrail(inputs, request_data, input_type): + """ + Custom PII detection for mining industry: + - Australian Company Numbers (ACN) + - Mining License Numbers + - Site-specific employee IDs + - Geological coordinates (sensitive mine locations) + """ + import re + for text in inputs["texts"]: - if regex_match(text, r"\d{3}-\d{2}-\d{4}"): - return block("SSN detected in message") - return allow() \ No newline at end of file + # Australian Company Number (ACN) - 9 digits, space-separated + # Format: XXX XXX XXX + acn_pattern = r'\b\d{3}\s\d{3}\s\d{3}\b' + if re.search(acn_pattern, text): + # Mask ACNs + text = re.sub(acn_pattern, '[ACN_REDACTED]', text) + + # Mining tenement/license numbers (Australian format) + # Format: M/E/P + numbers (e.g., M12345, EL6789) + mining_license_pattern = r'\b[MEP][A-Z]?\s?\d{4,6}\b' + if re.search(mining_license_pattern, text, re.IGNORECASE): + text = re.sub(mining_license_pattern, '[MINING_LICENSE_REDACTED]', text, flags=re.IGNORECASE) + + # Precise GPS coordinates (sensitive mine locations) + # Format: latitude, longitude with high precision + gps_pattern = r'-?\d{1,3}\.\d{4,}\s*,\s*-?\d{1,3}\.\d{4,}' + if re.search(gps_pattern, text): + text = re.sub(gps_pattern, '[GPS_COORDINATES_REDACTED]', text) + + # FIFO/DIDO roster numbers or employee mining IDs + # Format: Common mining employee ID patterns + employee_id_pattern = r'\b(?:EMP|FIF|DID|MIN)[_-]?\d{5,8}\b' + if re.search(employee_id_pattern, text, re.IGNORECASE): + text = re.sub(employee_id_pattern, '[EMPLOYEE_ID_REDACTED]', text, flags=re.IGNORECASE) + + # Update the text in inputs if any modifications were made + if text != inputs["texts"][inputs["texts"].index(inputs["texts"][next(i for i, t in enumerate(inputs["texts"]) if t == text)])]: + inputs["texts"][inputs["texts"].index(inputs["texts"][next(i for i, t in enumerate(inputs["texts"]) if t == text)])] = text + + return allow() + +# ============================================================================== +# POLICIES - Combining PII Guardrails +# ============================================================================== + +policies: + # Comprehensive PII policy for Fortescue mining operations + fortescue-pii-protection: + description: > + Comprehensive PII detection and masking policy for Fortescue. + Protects Australian-specific identifiers, international employee data, + financial information, credentials, protected class information, + and mining industry-specific sensitive data. + guardrails: + add: + # Australian-specific + - au-pii-tax-identifiers + - au-pii-passports + # International workforce + - international-pii-identifiers + # Contact information + - contact-information-pii + # Financial data + - financial-pii + # Credentials (blocks instead of masks) + - credentials-api-keys + # Network infrastructure + - network-infrastructure-pii + # Protected class compliance + - protected-class-information + # Mining industry custom + - mining-industry-custom-pii + + # Baseline policy for non-sensitive internal use + fortescue-pii-baseline: + description: > + Baseline PII protection for internal tools and testing. + Focuses on credentials and high-risk identifiers only. + guardrails: + add: + - au-pii-tax-identifiers + - credentials-api-keys + - financial-pii + + # HR and recruiting policy (extra strict on protected class) + fortescue-pii-hr-recruiting: + description: > + Strict PII protection for HR, recruiting, and workforce management. + Emphasizes protected class information to ensure compliance with + anti-discrimination laws and workplace regulations. + inherit: fortescue-pii-protection + guardrails: + add: + # Already includes protected-class-information from parent + # This policy ensures all PII filters are active for HR use cases + +# ============================================================================== +# POLICY ATTACHMENTS - Apply Policies to Teams/Keys/Models +# ============================================================================== + +policy_attachments: + # Apply comprehensive PII protection globally + - policy: fortescue-pii-protection + scope: "*" # Applies to all requests by default + + # Override for HR team with stricter policy + # Uncomment and modify team alias after creating teams + # - policy: fortescue-pii-hr-recruiting + # teams: + # - hr-team + # - recruiting-team + # - workforce-management + + # Override for internal development/testing with baseline policy + # - policy: fortescue-pii-baseline + # teams: + # - internal-dev + # - testing-team + # keys: + # - dev-* + # - test-* \ No newline at end of file diff --git a/litellm/proxy/management_endpoints/policy_endpoints.py b/litellm/proxy/management_endpoints/policy_endpoints.py index f9487dc2e59..5b615217f65 100644 --- a/litellm/proxy/management_endpoints/policy_endpoints.py +++ b/litellm/proxy/management_endpoints/policy_endpoints.py @@ -6,8 +6,13 @@ All /policy management endpoints /policy/validate - Validate a policy configuration /policy/list - List all loaded policies /policy/info - Get information about a specific policy +/policy/templates - Get available policy templates """ +import json +import os +from typing import Any, List + from fastapi import APIRouter, Depends, HTTPException, Request from litellm._logging import verbose_proxy_logger @@ -257,3 +262,52 @@ async def test_policy_matching( matching_policies=matching_policy_names, resolved_guardrails=resolved_guardrails, ) + + +@router.get( + "/policy/templates", + tags=["policy management"], + dependencies=[Depends(user_api_key_auth)], +) +@management_endpoint_wrapper +async def get_policy_templates( + request: Request, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +) -> List[Any]: + """ + Get available policy templates for quick policy setup. + + Returns a list of pre-configured policy templates that users can use + as a starting point for creating their own policies. + """ + try: + # Get the path to the policy_templates.json file + current_dir = os.path.dirname(os.path.abspath(__file__)) + templates_path = os.path.join( + os.path.dirname(current_dir), "policy_templates.json" + ) + + # Read and return the templates + with open(templates_path, "r") as f: + templates = json.load(f) + + verbose_proxy_logger.debug(f"Loaded {len(templates)} policy templates") + return templates + + except FileNotFoundError: + raise HTTPException( + status_code=404, + detail="Policy templates file not found", + ) + except json.JSONDecodeError as e: + verbose_proxy_logger.error(f"Error parsing policy templates JSON: {e}") + raise HTTPException( + status_code=500, + detail="Error parsing policy templates file", + ) + except Exception as e: + verbose_proxy_logger.error(f"Error loading policy templates: {e}") + raise HTTPException( + status_code=500, + detail=f"Error loading policy templates: {str(e)}", + ) diff --git a/litellm/proxy/policy_templates.json b/litellm/proxy/policy_templates.json new file mode 100644 index 00000000000..96d7a2192c7 --- /dev/null +++ b/litellm/proxy/policy_templates.json @@ -0,0 +1,140 @@ +[ + { + "id": "advanced-pii-protection", + "title": "Advanced PII Protection (Australia)", + "description": "Comprehensive PII detection and masking policy. Protects Australian-specific identifiers, international employee data, financial information, credentials, protected class information, and industry-specific sensitive data.", + "icon": "ShieldCheckIcon", + "iconColor": "text-purple-500", + "iconBg": "bg-purple-50", + "guardrails": [ + "au-pii-tax-identifiers", + "au-pii-passports", + "international-pii-identifiers", + "contact-information-pii", + "financial-pii", + "credentials-api-keys", + "network-infrastructure-pii", + "protected-class-information", + "mining-industry-custom-pii" + ], + "complexity": "High", + "templateData": { + "policy_name": "fortescue-pii-protection", + "description": "Comprehensive PII detection and masking policy for Fortescue. Protects Australian-specific identifiers, international employee data, financial information, credentials, protected class information, and mining industry-specific sensitive data.", + "guardrails": { + "add": [ + "au-pii-tax-identifiers", + "au-pii-passports", + "international-pii-identifiers", + "contact-information-pii", + "financial-pii", + "credentials-api-keys", + "network-infrastructure-pii", + "protected-class-information", + "mining-industry-custom-pii" + ] + } + } + }, + { + "id": "baseline-pii-protection", + "title": "Baseline PII Protection", + "description": "Baseline PII protection for internal tools and testing. Focuses on credentials and high-risk identifiers only. Suitable for non-sensitive internal use.", + "icon": "ShieldCheckIcon", + "iconColor": "text-blue-500", + "iconBg": "bg-blue-50", + "guardrails": [ + "au-pii-tax-identifiers", + "credentials-api-keys", + "financial-pii" + ], + "complexity": "Low", + "templateData": { + "policy_name": "baseline-pii-protection", + "description": "Baseline PII protection for internal tools and testing. Focuses on credentials and high-risk identifiers only.", + "guardrails": { + "add": [ + "au-pii-tax-identifiers", + "credentials-api-keys", + "financial-pii" + ] + } + } + }, + { + "id": "hr-recruiting-policy", + "title": "HR & Recruiting Policy", + "description": "Strict PII protection for HR, recruiting, and workforce management. Emphasizes protected class information to ensure compliance with anti-discrimination laws and workplace regulations.", + "icon": "ShieldExclamationIcon", + "iconColor": "text-indigo-500", + "iconBg": "bg-indigo-50", + "guardrails": [ + "au-pii-tax-identifiers", + "au-pii-passports", + "international-pii-identifiers", + "contact-information-pii", + "financial-pii", + "credentials-api-keys", + "network-infrastructure-pii", + "protected-class-information" + ], + "inherits": "Fortescue PII Protection", + "complexity": "High", + "templateData": { + "policy_name": "hr-recruiting-policy", + "description": "Strict PII protection for HR, recruiting, and workforce management. Emphasizes protected class information to ensure compliance with anti-discrimination laws and workplace regulations.", + "inherit": "fortescue-pii-protection", + "guardrails": { + "add": [] + } + } + }, + { + "id": "cost-control-policy", + "title": "Cost Control Policy", + "description": "Budget-focused guardrails to prevent unexpected spend. Routes expensive queries to cheaper models and enforces rate limiting.", + "icon": "CurrencyDollarIcon", + "iconColor": "text-green-500", + "iconBg": "bg-green-50", + "guardrails": [ + "budget-limit", + "model-routing", + "rate-limit" + ], + "complexity": "Medium", + "templateData": { + "policy_name": "cost-control-policy", + "description": "Budget-focused guardrails to prevent unexpected spend. Routes expensive queries to cheaper models.", + "guardrails": { + "add": [ + "budget-limit", + "model-routing", + "rate-limit" + ] + } + } + }, + { + "id": "development-testing-policy", + "title": "Development / Testing", + "description": "Relaxed guardrails for development environments. Enables full logging for debugging purposes with minimal restrictions.", + "icon": "BeakerIcon", + "iconColor": "text-orange-500", + "iconBg": "bg-orange-50", + "guardrails": [ + "debug-logging", + "latency-monitoring" + ], + "complexity": "Low", + "templateData": { + "policy_name": "development-testing-policy", + "description": "Relaxed guardrails for development environments. Enables full logging for debugging purposes.", + "guardrails": { + "add": [ + "debug-logging", + "latency-monitoring" + ] + } + } + } +] diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 162fdb9bc69..6d85e85acfa 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -5438,6 +5438,32 @@ export const getPolicyInfoWithGuardrails = async (accessToken: string, policyNam } }; +export const getPolicyTemplates = async (accessToken: string) => { + try { + const url = proxyBaseUrl ? `${proxyBaseUrl}/policy/templates` : `/policy/templates`; + const response = await fetch(url, { + method: "GET", + headers: { + [globalLitellmHeaderName]: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + }); + + if (!response.ok) { + const errorData = await response.json(); + const errorMessage = deriveErrorMessage(errorData); + handleError(errorMessage); + throw new Error(errorMessage); + } + + const data = await response.json(); + return data; + } catch (error) { + console.error("Failed to get policy templates:", error); + throw error; + } +}; + export const createPolicyCall = async (accessToken: string, policyData: any) => { try { const url = proxyBaseUrl ? `${proxyBaseUrl}/policies` : `/policies`; diff --git a/ui/litellm-dashboard/src/components/policies/index.tsx b/ui/litellm-dashboard/src/components/policies/index.tsx index 204f32e4491..419eb684a3c 100644 --- a/ui/litellm-dashboard/src/components/policies/index.tsx +++ b/ui/litellm-dashboard/src/components/policies/index.tsx @@ -9,6 +9,7 @@ import AddPolicyForm from "./add_policy_form"; import AttachmentTable from "./attachment_table"; import AddAttachmentForm from "./add_attachment_form"; import PolicyTestPanel from "./policy_test_panel"; +import PolicyTemplates from "./policy_templates"; import { getPoliciesList, deletePolicyCall, @@ -172,6 +173,13 @@ const PoliciesPanel: React.FC = ({ fetchAttachments(); }; + const handleUseTemplate = (templateData: any) => { + // Pre-fill the add policy form with template data + setEditingPolicy(templateData as Policy); + setIsAddPolicyModalVisible(true); + setActiveTab(0); // Switch to Policies tab + }; + return (
@@ -179,6 +187,7 @@ const PoliciesPanel: React.FC = ({ Policies Attachments Policy Simulator + Templates @@ -338,6 +347,10 @@ const PoliciesPanel: React.FC = ({ + + + +
diff --git a/ui/litellm-dashboard/src/components/policies/policy_templates.tsx b/ui/litellm-dashboard/src/components/policies/policy_templates.tsx new file mode 100644 index 00000000000..8b5cfd1cec8 --- /dev/null +++ b/ui/litellm-dashboard/src/components/policies/policy_templates.tsx @@ -0,0 +1,181 @@ +import React, { useState, useEffect } from "react"; +import { Card, Button, Spin, message } from "antd"; +import { + ShieldCheckIcon, + ShieldExclamationIcon, + BeakerIcon, + CurrencyDollarIcon, + CheckCircleIcon, +} from "@heroicons/react/outline"; +import { getPolicyTemplates } from "../networking"; + +interface PolicyTemplateCardProps { + title: string; + description: string; + icon: React.ComponentType>; + iconColor: string; + iconBg: string; + guardrails: string[]; + inherits?: string; + complexity: "Low" | "Medium" | "High"; + onUseTemplate: () => void; +} + +const PolicyTemplateCard: React.FC = ({ + title, + description, + icon: Icon, + iconColor, + iconBg, + guardrails, + inherits, + complexity, + onUseTemplate, +}) => { + const getComplexityStyle = () => { + switch (complexity) { + case "Low": + return "bg-gray-50 text-gray-600 border-gray-200"; + case "Medium": + return "bg-blue-50 text-blue-600 border-blue-100"; + case "High": + return "bg-purple-50 text-purple-600 border-purple-100"; + } + }; + + return ( + +
+
+ +
+ + {complexity} Complexity + +
+ +

{title}

+

{description}

+ + {inherits && ( +
+ Inherits from: + + {inherits} + +
+ )} + +
+ + Included Guardrails + +
+ {guardrails.map((g) => ( + + {g} + + ))} +
+
+ + +
+ ); +}; + +interface PolicyTemplatesProps { + onUseTemplate: (templateData: any) => void; + accessToken: string | null; +} + +// Map icon names from JSON to actual icon components +const iconMap: Record>> = { + ShieldCheckIcon: ShieldCheckIcon, + ShieldExclamationIcon: ShieldExclamationIcon, + BeakerIcon: BeakerIcon, + CurrencyDollarIcon: CurrencyDollarIcon, + CheckCircleIcon: CheckCircleIcon, +}; + +const PolicyTemplates: React.FC = ({ onUseTemplate, accessToken }) => { + const [templates, setTemplates] = useState([]); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + const fetchTemplates = async () => { + if (!accessToken) return; + + setIsLoading(true); + try { + const data = await getPolicyTemplates(accessToken); + setTemplates(data); + } catch (error) { + console.error("Error fetching policy templates:", error); + message.error("Failed to fetch policy templates"); + } finally { + setIsLoading(false); + } + }; + + fetchTemplates(); + }, [accessToken]); + + if (isLoading) { + return ( +
+ +
+ ); + } + + return ( +
+
+
+

+ Policy Templates +

+

+ Start with a pre-configured policy template to quickly set up + guardrails for your organization. +

+
+
+ +
+ {templates.map((template, index) => ( + onUseTemplate(template.templateData)} + /> + ))} +
+
+ ); +}; + +export default PolicyTemplates; diff --git a/ui/litellm-dashboard/tsconfig.json b/ui/litellm-dashboard/tsconfig.json index d24bdd340f7..5b0352feb98 100644 --- a/ui/litellm-dashboard/tsconfig.json +++ b/ui/litellm-dashboard/tsconfig.json @@ -14,7 +14,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "react-jsx", + "jsx": "preserve", "incremental": true, "plugins": [ {