diff --git a/ui/litellm-dashboard/src/components/AIHub/marketplace/PluginCard.tsx b/ui/litellm-dashboard/src/components/AIHub/marketplace/PluginCard.tsx deleted file mode 100644 index f7f00a2e3c..0000000000 --- a/ui/litellm-dashboard/src/components/AIHub/marketplace/PluginCard.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import { - formatInstallCommand, - getCategoryBadgeColor, - getSourceLink -} from "@/components/claude_code_plugins/helpers"; -import { MarketplacePluginEntry } from "@/components/claude_code_plugins/types"; -import NotificationsManager from "@/components/molecules/notifications_manager"; -import { ExternalLinkIcon } from "@heroicons/react/outline"; -import { CopyOutlined } from "@ant-design/icons"; -import { Badge, Button, Card, Text } from "@tremor/react"; -import { Tooltip } from "antd"; -import React from "react"; - -interface PluginCardProps { - plugin: MarketplacePluginEntry; -} - -const PluginCard: React.FC = ({ plugin }) => { - const installCommand = formatInstallCommand(plugin); - const sourceLink = getSourceLink(plugin.source); - const categoryBadgeColor = getCategoryBadgeColor(plugin.category); - - const copyToClipboard = (text: string) => { - navigator.clipboard.writeText(text); - NotificationsManager.success("Install command copied!"); - }; - - // Limit keywords display to first 5 - const displayKeywords = plugin.keywords?.slice(0, 5) || []; - const remainingKeywords = (plugin.keywords?.length || 0) - 5; - - return ( - - {/* Header */} -
-
-
-

- {plugin.name} -

- {plugin.version && ( - - v{plugin.version} - - )} - {plugin.category && ( - - {plugin.category} - - )} -
-
- {sourceLink && ( - - e.stopPropagation()} - > - - - - )} -
- - {/* Description */} -
- {plugin.description ? ( - - {plugin.description} - - ) : ( - - No description available - - )} -
- - {/* Keywords */} - {displayKeywords.length > 0 && ( -
- {displayKeywords.map((keyword, index) => ( - - {keyword} - - ))} - {remainingKeywords > 0 && ( - - +{remainingKeywords} more - - )} -
- )} - - {/* Author */} - {plugin.author && ( -
- - By {plugin.author.name} - {plugin.author.email && ` (${plugin.author.email})`} - -
- )} - - {/* Homepage Link */} - {plugin.homepage && ( -
- e.stopPropagation()} - > - Visit homepage - - -
- )} - - {/* Install Command */} -
-
-
- Install command - - - {installCommand} - - -
- -
-
-
- ); -}; - -export default PluginCard; diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/cost_results.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/cost_results.tsx deleted file mode 100644 index 03d5ca0e51..0000000000 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/cost_results.tsx +++ /dev/null @@ -1,203 +0,0 @@ -import React from "react"; -import { Text } from "@tremor/react"; -import { Card, Statistic, Row, Col, Divider, Spin } from "antd"; -import { DollarOutlined, LoadingOutlined } from "@ant-design/icons"; -import { CostEstimateResponse } from "../types"; -import { formatNumberWithCommas } from "@/utils/dataUtils"; -import ExportDropdown from "./export_dropdown"; - -interface CostResultsProps { - result: CostEstimateResponse | null; - loading: boolean; -} - -const formatCost = (value: number | null | undefined): string => { - if (value === null || value === undefined) return "-"; - if (value === 0) return "$0"; - if (value < 0.0001) return `$${value.toExponential(2)}`; - if (value < 1) return `$${value.toFixed(4)}`; - return `$${formatNumberWithCommas(value, 2, true)}`; -}; - -const formatRequests = (value: number | null | undefined): string => { - if (value === null || value === undefined) return "-"; - return formatNumberWithCommas(value, 0, true); -}; - -const CostResults: React.FC = ({ result, loading }) => { - if (!result && !loading) { - return ( -
- - Select a model to see cost estimates - -
- ); - } - - if (loading && !result) { - return ( -
- } /> - Calculating costs... -
- ); - } - - if (!result) return null; - - return ( -
- - -
-
- Cost Estimate - - Model: {result.model} {result.provider && `(${result.provider})`} - -
-
- {loading && } size="small" />} - -
-
- - - - - } - /> - - - - - - - - - 0 ? "#faad14" : undefined, - }} - /> - - - - - {result.daily_cost !== null && ( - - - - } - /> - - - - - - - - - 0 ? "#faad14" : undefined, - }} - /> - - - - )} - - {result.monthly_cost !== null && ( - - - - } - /> - - - - - - - - - 0 ? "#faad14" : undefined, - }} - /> - - - - )} - - {(result.input_cost_per_token || result.output_cost_per_token) && ( -
- Token Pricing: - {result.input_cost_per_token && ( - Input: ${formatNumberWithCommas(result.input_cost_per_token * 1_000_000, 2)}/1M tokens - )} - {result.input_cost_per_token && result.output_cost_per_token && " | "} - {result.output_cost_per_token && ( - Output: ${formatNumberWithCommas(result.output_cost_per_token * 1_000_000, 2)}/1M tokens - )} -
- )} -
- ); -}; - -export default CostResults; diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/export_dropdown.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/export_dropdown.tsx deleted file mode 100644 index e8a681021d..0000000000 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/export_dropdown.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import React, { useState, useRef, useEffect } from "react"; -import { Button } from "@tremor/react"; -import { DownloadOutlined, FilePdfOutlined, FileExcelOutlined } from "@ant-design/icons"; -import { CostEstimateResponse } from "../types"; -import { exportToPDF, exportToCSV } from "./export_utils"; - -interface ExportDropdownProps { - result: CostEstimateResponse; -} - -const ExportDropdown: React.FC = ({ result }) => { - const [isOpen, setIsOpen] = useState(false); - const menuRef = useRef(null); - - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if (menuRef.current && !menuRef.current.contains(event.target as Node)) { - setIsOpen(false); - } - }; - - if (isOpen) { - document.addEventListener("mousedown", handleClickOutside); - } - - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; - }, [isOpen]); - - return ( -
- - - {isOpen && ( -
- - -
- )} -
- ); -}; - -export default ExportDropdown; - diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/export_utils.ts b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/export_utils.ts deleted file mode 100644 index a205efa3bf..0000000000 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/export_utils.ts +++ /dev/null @@ -1,276 +0,0 @@ -import { CostEstimateResponse } from "../types"; -import { formatNumberWithCommas } from "@/utils/dataUtils"; - -const formatCostForExport = (value: number | null | undefined): string => { - if (value === null || value === undefined) return "-"; - if (value === 0) return "$0.00"; - if (value < 0.01) return `$${value.toFixed(6)}`; - if (value < 1) return `$${value.toFixed(4)}`; - return `$${formatNumberWithCommas(value, 2)}`; -}; - -const formatRequestsForExport = (value: number | null | undefined): string => { - if (value === null || value === undefined) return "-"; - return formatNumberWithCommas(value, 0); -}; - -export const exportToPDF = (result: CostEstimateResponse): void => { - const printWindow = window.open("", "_blank"); - if (!printWindow) { - alert("Please allow popups to export PDF"); - return; - } - - const html = ` - - - - Cost Estimate Report - ${result.model} - - - -

🚅 LiteLLM Cost Estimate Report

- -
-

Model: ${result.model}

- ${result.provider ? `

Provider: ${result.provider}

` : ""} -

Input Tokens per Request: ${formatRequestsForExport(result.input_tokens)}

-

Output Tokens per Request: ${formatRequestsForExport(result.output_tokens)}

- ${result.num_requests_per_day ? `

Requests per Day: ${formatRequestsForExport(result.num_requests_per_day)}

` : ""} - ${result.num_requests_per_month ? `

Requests per Month: ${formatRequestsForExport(result.num_requests_per_month)}

` : ""} -
- -

Per-Request Cost Breakdown

- - - - - - - - - - - - - - - - - - - - - -
Cost TypeAmount
Input Cost${formatCostForExport(result.input_cost_per_request)}
Output Cost${formatCostForExport(result.output_cost_per_request)}
Margin/Fee${formatCostForExport(result.margin_cost_per_request)}
Total per Request${formatCostForExport(result.cost_per_request)}
- - ${result.daily_cost !== null ? ` -

Daily Cost Estimate (${formatRequestsForExport(result.num_requests_per_day)} requests/day)

- - - - - - - - - - - - - - - - - - - - - -
Cost TypeAmount
Input Cost${formatCostForExport(result.daily_input_cost)}
Output Cost${formatCostForExport(result.daily_output_cost)}
Margin/Fee${formatCostForExport(result.daily_margin_cost)}
Total Daily${formatCostForExport(result.daily_cost)}
- ` : ""} - - ${result.monthly_cost !== null ? ` -

Monthly Cost Estimate (${formatRequestsForExport(result.num_requests_per_month)} requests/month)

- - - - - - - - - - - - - - - - - - - - - -
Cost TypeAmount
Input Cost${formatCostForExport(result.monthly_input_cost)}
Output Cost${formatCostForExport(result.monthly_output_cost)}
Margin/Fee${formatCostForExport(result.monthly_margin_cost)}
Total Monthly${formatCostForExport(result.monthly_cost)}
- ` : ""} - - ${result.input_cost_per_token || result.output_cost_per_token ? ` -

Token Pricing

- - - - - - ${result.input_cost_per_token ? ` - - - - - ` : ""} - ${result.output_cost_per_token ? ` - - - - - ` : ""} -
Token TypePrice per 1M Tokens
Input Tokens$${(result.input_cost_per_token * 1000000).toFixed(2)}
Output Tokens$${(result.output_cost_per_token * 1000000).toFixed(2)}
- ` : ""} - - - - - `; - - printWindow.document.write(html); - printWindow.document.close(); - printWindow.onload = () => { - printWindow.print(); - }; -}; - -export const exportToCSV = (result: CostEstimateResponse): void => { - const rows = [ - ["🚅 LiteLLM Cost Estimate Report"], - [""], - ["Configuration"], - ["Model", result.model], - ["Provider", result.provider || "-"], - ["Input Tokens per Request", result.input_tokens.toString()], - ["Output Tokens per Request", result.output_tokens.toString()], - ["Requests per Day", result.num_requests_per_day?.toString() || "-"], - ["Requests per Month", result.num_requests_per_month?.toString() || "-"], - [""], - ["Per-Request Costs"], - ["Input Cost", result.input_cost_per_request.toString()], - ["Output Cost", result.output_cost_per_request.toString()], - ["Margin/Fee", result.margin_cost_per_request.toString()], - ["Total per Request", result.cost_per_request.toString()], - ]; - - if (result.daily_cost !== null) { - rows.push( - [""], - ["Daily Costs"], - ["Daily Input Cost", result.daily_input_cost?.toString() || "-"], - ["Daily Output Cost", result.daily_output_cost?.toString() || "-"], - ["Daily Margin/Fee", result.daily_margin_cost?.toString() || "-"], - ["Total Daily", result.daily_cost.toString()] - ); - } - - if (result.monthly_cost !== null) { - rows.push( - [""], - ["Monthly Costs"], - ["Monthly Input Cost", result.monthly_input_cost?.toString() || "-"], - ["Monthly Output Cost", result.monthly_output_cost?.toString() || "-"], - ["Monthly Margin/Fee", result.monthly_margin_cost?.toString() || "-"], - ["Total Monthly", result.monthly_cost.toString()] - ); - } - - if (result.input_cost_per_token || result.output_cost_per_token) { - rows.push( - [""], - ["Token Pricing (per 1M tokens)"], - ["Input Token Price", result.input_cost_per_token ? `$${(result.input_cost_per_token * 1000000).toFixed(2)}` : "-"], - ["Output Token Price", result.output_cost_per_token ? `$${(result.output_cost_per_token * 1000000).toFixed(2)}` : "-"] - ); - } - - const csv = rows.map(row => row.join(",")).join("\n"); - const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" }); - const url = window.URL.createObjectURL(blob); - const a = document.createElement("a"); - a.href = url; - a.download = `cost_estimate_${result.model.replace(/\//g, "_")}_${new Date().toISOString().split("T")[0]}.csv`; - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); - window.URL.revokeObjectURL(url); -}; - diff --git a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/pricing_form.tsx b/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/pricing_form.tsx deleted file mode 100644 index c91a19e551..0000000000 --- a/ui/litellm-dashboard/src/components/CostTrackingSettings/pricing_calculator/pricing_form.tsx +++ /dev/null @@ -1,104 +0,0 @@ -import React from "react"; -import { Form, InputNumber, Select, Row, Col } from "antd"; -import { PricingFormValues } from "./types"; - -interface PricingFormProps { - models: string[]; - onValuesChange: (changedValues: Partial, allValues: PricingFormValues) => void; -} - -const PricingForm: React.FC = ({ models, onValuesChange }) => { - return ( -
- - - - setNewKey(e.target.value)} - placeholder={keyPlaceholder} - size="middle" - /> - -
- - setNewValue(e.target.value)} - placeholder={valuePlaceholder} - size="middle" - /> -
-
- -
- - - - {/* Manage Existing Items Section */} - -
- Manage Existing {keyLabel}s - {showSaveButton && ( - - )} -
- -
-
- - - - {keyLabel} - {valueLabel} - Actions - - - - {items.map((item) => ( - - {editingItem && editingItem.id === item.id ? ( - <> - - setEditingKey(e.target.value)} size="small" /> - - - setEditingValue(e.target.value)} - size="small" - /> - - -
- - -
-
- - ) : ( - <> - {item.key} - {item.value} - -
- {additionalActions && additionalActions(item)} - - -
-
- - )} -
- ))} - {items.length === 0 && ( - - - No {keyLabel.toLowerCase()}s added yet. Add a new {keyLabel.toLowerCase()} above. - - - )} -
-
-
-
-
- - {/* Configuration Example */} - {configExample && ( - - Configuration Example - {configExample} - - )} - - ), - [ - keyLabel, - valueLabel, - keyPlaceholder, - valuePlaceholder, - newKey, - newValue, - items, - editingItem, - editingKey, - editingValue, - showSaveButton, - configExample, - additionalActions, - handleAddItem, - handleSave, - handleEditItem, - handleSaveEdit, - handleCancelEdit, - handleDeleteItem, - ], - ); - - if (isCollapsible) { - return ( - -
setIsExpanded(!isExpanded)}> -
- {title} -

{description}

-
-
- {isExpanded ? ( - - ) : ( - - )} -
-
- - {isExpanded && ( -
- -
- )} -
- ); - } - - return ( -
-
- {title} - {description} -
-
- -
-
- ); -}; - -export default GenericKeyValueManager; diff --git a/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_configuration.tsx b/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_configuration.tsx deleted file mode 100644 index 05705cfa5d..0000000000 --- a/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_configuration.tsx +++ /dev/null @@ -1,243 +0,0 @@ -import React, { useState } from "react"; -import { Typography, Badge, Card, Checkbox, Select, Slider, Tooltip, Divider, Row, Col } from "antd"; -import { - AzureTextModerationConfigurationProps, - AZURE_TEXT_MODERATION_CATEGORIES, - SEVERITY_LEVELS, -} from "./azure_text_moderation_types"; -import { InfoCircleOutlined, SafetyOutlined } from "@ant-design/icons"; - -const { Title, Text, Paragraph } = Typography; -const { Option } = Select; - -/** - * A reusable component for configuring Azure Text Moderation guardrail settings - * Allows configuration of categories, global severity threshold, and per-category thresholds - */ -const AzureTextModerationConfiguration: React.FC = ({ - selectedCategories, - globalSeverityThreshold, - categorySpecificThresholds, - onCategorySelect, - onGlobalSeverityChange, - onCategorySeverityChange, -}) => { - const [showAdvanced, setShowAdvanced] = useState(false); - - const getSeverityLabel = (value: number) => { - const level = SEVERITY_LEVELS.find((l) => l.value === value); - return level ? level.label : `Level ${value}`; - }; - - const getSeverityColor = (value: number) => { - if (value === 0) return "#52c41a"; // green - if (value === 2) return "#faad14"; // orange - if (value === 4) return "#fa8c16"; // dark orange - return "#f5222d"; // red - }; - - const handleSelectAll = () => { - AZURE_TEXT_MODERATION_CATEGORIES.forEach((category) => { - if (!selectedCategories.includes(category.name)) { - onCategorySelect(category.name); - } - }); - }; - - const handleUnselectAll = () => { - selectedCategories.forEach((category) => { - onCategorySelect(category); - }); - }; - - return ( -
-
-
- - - Azure Text Moderation - -
- 0 ? "#1890ff" : "#d9d9d9" }} - overflowCount={999} - > - {selectedCategories.length} categories selected - -
- - - - - Select which content categories to monitor and filter - - - {AZURE_TEXT_MODERATION_CATEGORIES.map((category) => ( - - onCategorySelect(category.name)} - > -
- onCategorySelect(category.name)} - className="mr-3 mt-1" - /> -
- - {category.name} - -
- {category.description} -
-
-
- - ))} -
-
- - -
- - Global Severity Threshold - - - - -
- - - Set the minimum severity level that will trigger the guardrail for all selected categories - - -
- - - getSeverityLabel(value || 0), - }} - /> - - -
-
- {getSeverityLabel(globalSeverityThreshold)} -
-
- -
-
-
- - - - - {showAdvanced && ( - <> - - Set custom severity thresholds for individual categories. Leave empty to use the global threshold. - - - {selectedCategories.length === 0 ? ( -
- Please select at least one category to configure per-category thresholds -
- ) : ( -
- {selectedCategories.map((category) => ( -
-
- {category} - -
- - {AZURE_TEXT_MODERATION_CATEGORIES.find((c) => c.name === category)?.description} - - {category !== selectedCategories[selectedCategories.length - 1] && } -
- ))} -
- )} - - )} -
-
- ); -}; - -export default AzureTextModerationConfiguration; diff --git a/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_example.tsx b/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_example.tsx deleted file mode 100644 index 9ff867b111..0000000000 --- a/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_example.tsx +++ /dev/null @@ -1,92 +0,0 @@ -import React, { useState } from "react"; -import { Button, Space, Card } from "antd"; -import AzureTextModerationConfiguration from "./azure_text_moderation_configuration"; -import NotificationsManager from "../molecules/notifications_manager"; - -/** - * Example component showing how to use the AzureTextModerationConfiguration - * This demonstrates the state management and event handling required - */ -const AzureTextModerationExample: React.FC = () => { - const [selectedCategories, setSelectedCategories] = useState(["Hate", "Violence"]); - const [globalSeverityThreshold, setGlobalSeverityThreshold] = useState(2); - const [categorySpecificThresholds, setCategorySpecificThresholds] = useState<{ [key: string]: number }>({ - Hate: 4, - }); - - const handleCategorySelect = (category: string) => { - setSelectedCategories((prev) => - prev.includes(category) ? prev.filter((c) => c !== category) : [...prev, category], - ); - }; - - const handleGlobalSeverityChange = (threshold: number) => { - setGlobalSeverityThreshold(threshold); - }; - - const handleCategorySeverityChange = (category: string, threshold: number) => { - setCategorySpecificThresholds((prev) => ({ - ...prev, - [category]: threshold, - })); - }; - - const handleSave = () => { - // Example of how to construct the configuration object - const config = { - categories: selectedCategories, - severity_threshold: globalSeverityThreshold, - severity_threshold_by_category: categorySpecificThresholds, - }; - - console.log("Azure Text Moderation Configuration:", config); - NotificationsManager.success("Configuration saved successfully!"); - }; - - const handleReset = () => { - setSelectedCategories(["Hate", "Violence"]); - setGlobalSeverityThreshold(2); - setCategorySpecificThresholds({ Hate: 4 }); - NotificationsManager.info("Configuration reset to defaults"); - }; - - return ( -
- - - -
- - - - -
-
- - -
-          {JSON.stringify(
-            {
-              categories: selectedCategories,
-              severity_threshold: globalSeverityThreshold,
-              severity_threshold_by_category: categorySpecificThresholds,
-            },
-            null,
-            2,
-          )}
-        
-
-
- ); -}; - -export default AzureTextModerationExample; diff --git a/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_types.ts b/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_types.ts deleted file mode 100644 index eefeffdca7..0000000000 --- a/ui/litellm-dashboard/src/components/guardrails/azure_text_moderation_types.ts +++ /dev/null @@ -1,74 +0,0 @@ -export interface AzureTextModerationCategory { - name: string; - description: string; - enabled: boolean; - severityThreshold?: number; -} - -export interface AzureTextModerationConfigurationProps { - selectedCategories: string[]; - globalSeverityThreshold: number; - categorySpecificThresholds: { [key: string]: number }; - onCategorySelect: (category: string) => void; - onGlobalSeverityChange: (threshold: number) => void; - onCategorySeverityChange: (category: string, threshold: number) => void; -} - -export interface AzureTextModerationGuardrail { - guardrail_id: string; - guardrail_name: string | null; - litellm_params: { - guardrail: string; - mode: string; - default_on: boolean; - categories?: string[]; - severity_threshold?: number; - severity_threshold_by_category?: { [key: string]: number }; - [key: string]: any; - }; - guardrail_info: Record | null; - created_at?: string; - updated_at?: string; -} - -export const AZURE_TEXT_MODERATION_CATEGORIES = [ - { - name: "Hate", - description: "Content that attacks or uses discriminatory language based on protected characteristics", - }, - { - name: "Sexual", - description: "Content that describes sexual activity or other sexual content", - }, - { - name: "SelfHarm", - description: "Content that promotes, encourages, or depicts acts of self-harm", - }, - { - name: "Violence", - description: "Content that depicts death, violence, or physical injury", - }, -]; - -export const SEVERITY_LEVELS = [ - { - value: 0, - label: "Level 0 - Safe", - description: "Content is appropriate and safe", - }, - { - value: 2, - label: "Level 2 - Low", - description: "Content may be inappropriate in some contexts", - }, - { - value: 4, - label: "Level 4 - Medium", - description: "Content is inappropriate and should be filtered", - }, - { - value: 6, - label: "Level 6 - High", - description: "Content is harmful and should be blocked", - }, -]; diff --git a/ui/litellm-dashboard/src/components/guardrails/content_filter/types.ts b/ui/litellm-dashboard/src/components/guardrails/content_filter/types.ts deleted file mode 100644 index 26e4478dc1..0000000000 --- a/ui/litellm-dashboard/src/components/guardrails/content_filter/types.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Type definitions for Content Filter Configuration - */ - -export interface PrebuiltPattern { - name: string; - display_name: string; - category: string; - description: string; -} - -export interface Pattern { - id: string; - type: "prebuilt" | "custom"; - name: string; - display_name?: string; - pattern?: string; - action: "BLOCK" | "MASK"; -} - -export interface BlockedWord { - id: string; - keyword: string; - action: "BLOCK" | "MASK"; - description?: string; -} - -export interface ContentFilterSettings { - prebuilt_patterns: PrebuiltPattern[]; - pattern_categories: string[]; - supported_actions: string[]; -} - -export interface ContentFilterConfigurationProps { - prebuiltPatterns: PrebuiltPattern[]; - categories: string[]; - selectedPatterns: Pattern[]; - blockedWords: BlockedWord[]; - blockedWordsFile?: string; - onPatternAdd: (pattern: Pattern) => void; - onPatternRemove: (id: string) => void; - onPatternActionChange: (id: string, action: "BLOCK" | "MASK") => void; - onBlockedWordAdd: (word: BlockedWord) => void; - onBlockedWordRemove: (id: string) => void; - onBlockedWordUpdate: (id: string, field: string, value: any) => void; - onFileUpload: (content: string) => void; - accessToken: string | null; -} - diff --git a/ui/litellm-dashboard/src/components/guardrails/custom_code/CustomCodeEditor.tsx b/ui/litellm-dashboard/src/components/guardrails/custom_code/CustomCodeEditor.tsx deleted file mode 100644 index ae96668cbc..0000000000 --- a/ui/litellm-dashboard/src/components/guardrails/custom_code/CustomCodeEditor.tsx +++ /dev/null @@ -1,188 +0,0 @@ -import React, { useRef, useState } from "react"; -import { Input, Tabs, Typography } from "antd"; -import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; -import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism"; -import { CodeOutlined, EyeOutlined } from "@ant-design/icons"; - -const { TextArea } = Input; -const { Text } = Typography; - -interface CustomCodeEditorProps { - value: string; - onChange: (value: string) => void; - height?: string; - placeholder?: string; - disabled?: boolean; -} - -const CustomCodeEditor: React.FC = ({ - value, - onChange, - height = "350px", - placeholder = `def apply_guardrail(inputs, request_data, input_type): - # inputs: contains texts, images, tools, tool_calls, structured_messages, model - # request_data: contains model, user_id, team_id, end_user_id, metadata - # input_type: "request" or "response" - - for text in inputs["texts"]: - # Example: Block if SSN pattern is detected - if regex_match(text, r"\\d{3}-\\d{2}-\\d{4}"): - return block("SSN detected in message") - - return allow()`, - disabled = false, -}) => { - const textareaRef = useRef(null); - const [activeTab, setActiveTab] = useState("edit"); - const [cursorPosition, setCursorPosition] = useState({ line: 1, column: 1 }); - - // Calculate cursor position - const updateCursorPosition = () => { - if (textareaRef.current) { - const textarea = textareaRef.current; - const textBeforeCursor = value.substring(0, textarea.selectionStart); - const lines = textBeforeCursor.split("\n"); - const line = lines.length; - const column = lines[lines.length - 1].length + 1; - setCursorPosition({ line, column }); - } - }; - - // Handle tab key for indentation - const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Tab") { - e.preventDefault(); - const textarea = e.currentTarget; - const start = textarea.selectionStart; - const end = textarea.selectionEnd; - - // Insert 4 spaces at cursor position - const newValue = value.substring(0, start) + " " + value.substring(end); - onChange(newValue); - - // Move cursor after the inserted spaces - setTimeout(() => { - textarea.selectionStart = textarea.selectionEnd = start + 4; - }, 0); - } - }; - - const lineCount = value.split("\n").length; - - const tabItems = [ - { - key: "edit", - label: ( - - - Edit - - ), - children: ( -
- {/* Line numbers */} -
- {Array.from({ length: Math.max(lineCount, 15) }, (_, i) => ( -
- {i + 1} -
- ))} -
- - {/* Code editor */} -