diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json index 50b652ff57e..e5d17d49a33 100644 --- a/ui/litellm-dashboard/eslint-suppressions.json +++ b/ui/litellm-dashboard/eslint-suppressions.json @@ -42,9 +42,6 @@ }, "react-hooks/set-state-in-effect": { "count": 2 - }, - "unused-imports/no-unused-imports": { - "count": 1 } }, "src/app/(dashboard)/agents/_components/agent_card_discovery.tsx": { @@ -2440,7 +2437,7 @@ "count": 2 }, "react-hooks/set-state-in-effect": { - "count": 3 + "count": 1 } }, "src/components/TeamsPage/teamTableColumns.tsx": { @@ -2448,11 +2445,6 @@ "count": 1 } }, - "src/components/ToolDetail.tsx": { - "unused-imports/no-unused-imports": { - "count": 1 - } - }, "src/components/UIAccessControlForm.tsx": { "no-restricted-imports": { "count": 2 @@ -3383,7 +3375,7 @@ "count": 2 }, "prefer-const": { - "count": 4 + "count": 2 }, "react-hooks/set-state-in-effect": { "count": 4 @@ -4005,7 +3997,7 @@ "count": 1 }, "react-hooks/set-state-in-effect": { - "count": 2 + "count": 1 } }, "src/components/vector_store_management/VectorStoreSelector.test.tsx": { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/agents/_components/add_agent_form.tsx b/ui/litellm-dashboard/src/app/(dashboard)/agents/_components/add_agent_form.tsx index e35388b78da..677ba9e6285 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/agents/_components/add_agent_form.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/agents/_components/add_agent_form.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect } from "react"; -import { Modal, Form, Select, Input, Steps, Radio, Tag, Divider, Switch, InputNumber, Collapse } from "antd"; +import { Modal, Form, Select, Input, Steps, Radio, Tag, Divider, Switch, InputNumber } from "antd"; import MessageManager from "@/components/molecules/message_manager"; import { Logo } from "@/components/molecules/logo/Logo"; import { Button } from "@tremor/react"; @@ -47,7 +47,6 @@ const AddAgentForm: React.FC = ({ visible, onClose, accessTok const [isSubmitting, setIsSubmitting] = useState(false); const [agentType, setAgentType] = useState("a2a"); const [agentTypeMetadata, setAgentTypeMetadata] = useState([]); - const [loadingMetadata, setLoadingMetadata] = useState(false); // Step 3: key assignment state const [keyAssignOption, setKeyAssignOption] = useState<"create_new" | "existing_key" | "skip">("create_new"); @@ -82,14 +81,11 @@ const AddAgentForm: React.FC = ({ visible, onClose, accessTok // Fetch agent type metadata on mount useEffect(() => { const fetchMetadata = async () => { - setLoadingMetadata(true); try { const metadata = await getAgentCreateMetadata(); setAgentTypeMetadata(metadata); } catch (error) { console.error("Error fetching agent metadata:", error); - } finally { - setLoadingMetadata(false); } }; fetchMetadata(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_health.tsx b/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_health.tsx index 85649c1cf26..0f52bed874d 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_health.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/caching/_components/cache_health.tsx @@ -20,14 +20,11 @@ const deepParse = (input: any) => { // TableClickableErrorField component with copy-to-clipboard functionality const TableClickableErrorField: React.FC<{ label: string; value: string | null | undefined }> = ({ label, value }) => { const [isExpanded, setIsExpanded] = React.useState(false); - const [copied, setCopied] = React.useState(false); const safeValue = value?.toString() || "N/A"; const truncated = safeValue.length > 50 ? safeValue.substring(0, 50) + "..." : safeValue; const handleCopy = () => { navigator.clipboard.writeText(safeValue); - setCopied(true); - setTimeout(() => setCopied(false), 2000); }; return ( diff --git a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/add_guardrail_form.tsx b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/add_guardrail_form.tsx index 251ce631beb..5f15eaceb28 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/add_guardrail_form.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/guardrails/_components/add_guardrail_form.tsx @@ -1,4 +1,4 @@ -import { Form, Input, Modal, Select, Tag, Typography, Button } from "antd"; +import { Form, Input, Modal, Select, Tag, Button } from "antd"; import React, { useEffect, useMemo, useState } from "react"; import NotificationsManager from "@/components/molecules/notifications_manager"; import { @@ -30,7 +30,6 @@ import LLMJudgeFields from "./llm_judge/LLMJudgeFields"; import PiiConfiguration from "./pii_configuration"; import ToolPermissionRulesEditor, { ToolPermissionConfig } from "./tool_permission/ToolPermissionRulesEditor"; -const { Title, Text, Link } = Typography; const { Option } = Select; // Define human-friendly descriptions for each mode @@ -163,11 +162,6 @@ const AddGuardrailForm: React.FC = ({ visible, onClose, a const [currentStep, setCurrentStep] = useState(0); const [providerParams, setProviderParams] = useState(null); - // Azure Text Moderation state - const [selectedCategories, setSelectedCategories] = useState([]); - const [globalSeverityThreshold, setGlobalSeverityThreshold] = useState(2); - const [categorySpecificThresholds, setCategorySpecificThresholds] = useState<{ [key: string]: number }>({}); - // Content Filter state const [selectedPatterns, setSelectedPatterns] = useState([]); const [blockedWords, setBlockedWords] = useState([]); @@ -297,11 +291,6 @@ const AddGuardrailForm: React.FC = ({ visible, onClose, a setSelectedEntities([]); setSelectedActions({}); - // Reset Azure Text Moderation selections when changing provider - setSelectedCategories([]); - setGlobalSeverityThreshold(2); - setCategorySpecificThresholds({}); - // Reset Content Filter selections setSelectedPatterns([]); setBlockedWords([]); @@ -335,24 +324,6 @@ const AddGuardrailForm: React.FC = ({ visible, onClose, a })); }; - // Azure Text Moderation handlers - 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 nextStep = async () => { try { // Validate current step fields @@ -388,53 +359,11 @@ const AddGuardrailForm: React.FC = ({ visible, onClose, a setCurrentStep(currentStep - 1); }; - const handleAddAndContinue = (competitorIntentOnly?: boolean) => { - // Competitor intent only: just advance to next step (no category to add) - if (competitorIntentOnly) { - setCurrentStep(currentStep + 1); - return; - } - - if (!pendingCategorySelection || !guardrailSettings) return; - - const contentFilterSettings = guardrailSettings.content_filter_settings; - if (!contentFilterSettings) return; - - const category = contentFilterSettings.content_categories?.find((c) => c.name === pendingCategorySelection); - if (!category) return; - - // Check if already added - if (selectedContentCategories.some((c) => c.category === pendingCategorySelection)) { - setPendingCategorySelection(""); - setCurrentStep(currentStep + 1); - return; - } - - // Add the category - setSelectedContentCategories([ - ...selectedContentCategories, - { - id: `category-${Date.now()}`, - category: category.name, - display_name: category.display_name, - action: category.default_action as "BLOCK" | "MASK", - severity_threshold: "medium", - }, - ]); - - // Clear pending selection and advance to next step - setPendingCategorySelection(""); - setCurrentStep(currentStep + 1); - }; - const resetForm = () => { form.resetFields(); setSelectedProvider(null); setSelectedEntities([]); setSelectedActions({}); - setSelectedCategories([]); - setGlobalSeverityThreshold(2); - setCategorySpecificThresholds({}); setSelectedPatterns([]); setBlockedWords([]); setSelectedContentCategories([]); @@ -965,48 +894,6 @@ const AddGuardrailForm: React.FC = ({ visible, onClose, a } }; - const renderStepButtons = () => { - const totalSteps = shouldRenderContentFilterConfigSettings(selectedProvider) ? 5 : 2; - const isLastStep = currentStep === totalSteps - 1; - const isCategoriesStep = shouldRenderContentFilterConfigSettings(selectedProvider) && currentStep === 1; - const hasPendingCategory = pendingCategorySelection !== ""; - const hasCompetitorIntentConfigured = - competitorIntentEnabled && (competitorIntentConfig?.brand_self?.length ?? 0) > 0; - const canContinueFromCategoriesStep = hasPendingCategory || hasCompetitorIntentConfigured; - - return ( -
- {currentStep > 0 && } - {isCategoriesStep ? ( - <> - - - - ) : ( - <> - {!isLastStep && ( - - )} - {isLastStep && ( - - )} - - )} - -
- ); - }; - const renderEndpointSettings = () => { return (
diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/teams/useTeams.test.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/teams/useTeams.test.ts index 28320b76597..66dfc43cebb 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/hooks/teams/useTeams.test.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/teams/useTeams.test.ts @@ -436,9 +436,6 @@ describe("useTeam", () => { showSSOBanner: false, }); - // Import useQueryClient to get access to query client - const { useQueryClient } = await import("@tanstack/react-query"); - // Manually test the queryFn logic by calling it directly // This simulates what would happen if enabled check was bypassed const testQueryFn = async () => { diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/useAuthorized.test.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/useAuthorized.test.ts index bb14f6c3d21..1ca0581a391 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/hooks/useAuthorized.test.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/useAuthorized.test.ts @@ -305,7 +305,7 @@ describe("useAuthorized", () => { const token = createJwt(decodedPayload); document.cookie = `token=${token}; path=/;`; - const { result } = renderHook(() => useAuthorized(), { wrapper }); + renderHook(() => useAuthorized(), { wrapper }); await waitFor(() => { expect(clearTokenCookiesMock).toHaveBeenCalled(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/add_policy_form.tsx b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/add_policy_form.tsx index 8da2d3af36f..74e8bd3c6d9 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/add_policy_form.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/add_policy_form.tsx @@ -8,7 +8,6 @@ import NotificationsManager from "@/components/molecules/notifications_manager"; import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized"; const { Text } = Typography; -const { Option } = Select; interface AddPolicyFormProps { visible: boolean; @@ -162,7 +161,6 @@ const AddPolicyForm: React.FC = ({ const [form] = Form.useForm(); const [isSubmitting, setIsSubmitting] = useState(false); const [resolvedGuardrails, setResolvedGuardrails] = useState([]); - const [isLoadingResolved, setIsLoadingResolved] = useState(false); const [modelConditionType, setModelConditionType] = useState<"model" | "regex">("model"); const [availableModels, setAvailableModels] = useState([]); const [step, setStep] = useState<"pick_mode" | "simple_form">("pick_mode"); @@ -231,14 +229,11 @@ const AddPolicyForm: React.FC = ({ const loadResolvedGuardrails = async (policyId: string) => { if (!accessToken) return; - setIsLoadingResolved(true); try { const data = await getResolvedGuardrails(accessToken, policyId); setResolvedGuardrails(data.resolved_guardrails || []); } catch (error) { console.error("Failed to load resolved guardrails:", error); - } finally { - setIsLoadingResolved(false); } }; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/policy_info.tsx b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/policy_info.tsx index c49093f3238..0a5c7ef1186 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/policy_info.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/policies/_components/policy_info.tsx @@ -53,7 +53,6 @@ const PolicyInfoView: React.FC = ({ const [policy, setPolicy] = useState(null); const [isLoading, setIsLoading] = useState(true); const [resolvedGuardrails, setResolvedGuardrails] = useState([]); - const [isLoadingResolved, setIsLoadingResolved] = useState(false); const fetchPolicy = useCallback(async () => { if (!accessToken || !policyId) return; @@ -64,14 +63,11 @@ const PolicyInfoView: React.FC = ({ setPolicy(data); // Also fetch resolved guardrails - setIsLoadingResolved(true); try { const resolvedData = await getResolvedGuardrails(accessToken, policyId); setResolvedGuardrails(resolvedData.resolved_guardrails || []); } catch (error) { console.error("Error fetching resolved guardrails:", error); - } finally { - setIsLoadingResolved(false); } } catch (error) { console.error("Error fetching policy:", error); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/prompts/_components/prompt_editor_view/VersionHistorySidePanel.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/prompts/_components/prompt_editor_view/VersionHistorySidePanel.test.tsx index c76c64b89a6..97f671b1b71 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/prompts/_components/prompt_editor_view/VersionHistorySidePanel.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/prompts/_components/prompt_editor_view/VersionHistorySidePanel.test.tsx @@ -182,7 +182,7 @@ describe("VersionHistorySidePanel", () => { render(); await waitFor(() => { - const versionItems = screen.getAllByTestId("tag"); + screen.getAllByTestId("tag"); // Should have Active tag for the selected version expect(screen.getByText("Active")).toBeInTheDocument(); }); @@ -464,7 +464,7 @@ describe("VersionHistorySidePanel", () => { render(); await waitFor(() => { - const versionElements = screen.getAllByTestId("tag"); + screen.getAllByTestId("tag"); // Verify versions are displayed as they come from the API expect(screen.getByText("v2")).toBeInTheDocument(); }); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsageViewSelect/UsageViewSelect.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsageViewSelect/UsageViewSelect.test.tsx index b33129fcdb4..aa9ff921ee1 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsageViewSelect/UsageViewSelect.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/usage/_components/components/UsageViewSelect/UsageViewSelect.test.tsx @@ -7,13 +7,10 @@ vi.mock("antd", async () => { function Select(props: any) { const { value, onChange, options, optionRender, labelRender, ...rest } = props; - const selectedOption = options?.find((opt: any) => opt.value === value); - const renderedLabel = labelRender ? labelRender({ value, label: selectedOption?.label }) : selectedOption?.label; - const optionElements = options?.map((opt: any) => { - const rendered = optionRender ? optionRender({ value: opt.value, label: opt.label }) : opt.label; - return React.createElement("option", { key: opt.value, value: opt.value }, opt.label); - }); + const optionElements = options?.map((opt: any) => + React.createElement("option", { key: opt.value, value: opt.value }, opt.label), + ); const optionRenderOutputs = options ?.map((opt: any) => { diff --git a/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx b/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx index 42acfd94185..f29504fac50 100644 --- a/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx +++ b/ui/litellm-dashboard/src/components/AIHub/UsefulLinksManagement.tsx @@ -23,7 +23,6 @@ const UsefulLinksManagement: React.FC = ({ accessTok const [links, setLinks] = useState([]); const [newLink, setNewLink] = useState({ url: "", displayName: "" }); const [editingLink, setEditingLink] = useState(null); - const [loading, setLoading] = useState(false); const [isExpanded, setIsExpanded] = useState(true); const [isRearranging, setIsRearranging] = useState(false); const [originalLinksOrder, setOriginalLinksOrder] = useState([]); @@ -32,7 +31,6 @@ const UsefulLinksManagement: React.FC = ({ accessTok if (!accessToken) return; try { - setLoading(true); const response = await getPublicModelHubInfo(); if (response && response.useful_links) { @@ -73,8 +71,6 @@ const UsefulLinksManagement: React.FC = ({ accessTok } catch (error) { console.error("Error fetching useful links:", error); setLinks([]); - } finally { - setLoading(false); } }; diff --git a/ui/litellm-dashboard/src/components/EntityUsageExport/utils.test.ts b/ui/litellm-dashboard/src/components/EntityUsageExport/utils.test.ts index dfeecdc4fa6..e91b7b73a1e 100644 --- a/ui/litellm-dashboard/src/components/EntityUsageExport/utils.test.ts +++ b/ui/litellm-dashboard/src/components/EntityUsageExport/utils.test.ts @@ -1876,7 +1876,7 @@ describe("EntityUsageExport utils", () => { it("should create CSV file and trigger download", () => { const createObjectURLSpy = vi.spyOn(window.URL, "createObjectURL").mockReturnValue("blob:mock-url"); - const revokeObjectURLSpy = vi.spyOn(window.URL, "revokeObjectURL"); + vi.spyOn(window.URL, "revokeObjectURL"); const createElementSpy = vi.spyOn(document, "createElement"); const appendChildSpy = vi.spyOn(document.body, "appendChild"); const removeChildSpy = vi.spyOn(document.body, "removeChild"); @@ -1892,7 +1892,7 @@ describe("EntityUsageExport utils", () => { it("should generate correct filename", () => { const anchorElement = document.createElement("a"); - const createElementSpy = vi.spyOn(document, "createElement").mockReturnValue(anchorElement); + vi.spyOn(document, "createElement").mockReturnValue(anchorElement); const today = new Date().toISOString().split("T")[0]; @@ -1935,7 +1935,7 @@ describe("EntityUsageExport utils", () => { it("should create JSON file and trigger download", () => { const createObjectURLSpy = vi.spyOn(window.URL, "createObjectURL").mockReturnValue("blob:mock-url"); - const revokeObjectURLSpy = vi.spyOn(window.URL, "revokeObjectURL"); + vi.spyOn(window.URL, "revokeObjectURL"); const createElementSpy = vi.spyOn(document, "createElement"); const appendChildSpy = vi.spyOn(document.body, "appendChild"); const removeChildSpy = vi.spyOn(document.body, "removeChild"); @@ -1955,7 +1955,7 @@ describe("EntityUsageExport utils", () => { it("should generate correct filename", () => { const anchorElement = document.createElement("a"); - const createElementSpy = vi.spyOn(document, "createElement").mockReturnValue(anchorElement); + vi.spyOn(document, "createElement").mockReturnValue(anchorElement); const today = new Date().toISOString().split("T")[0]; const mockDateRange: DateRangePickerValue = { diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.test.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.test.tsx index 7415683af83..7536286b404 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.test.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/SSOSettings/Modals/EditSSOSettingsModal.test.tsx @@ -320,7 +320,7 @@ describe("EditSSOSettingsModal", () => { useEditSSOSettings: { mutateAsync: mockMutateAsync, isPending: false }, }); - const { mockOnSuccess } = renderComponent(); + renderComponent(); fireEvent.click(screen.getByTestId(TEST_IDS.TRIGGER_FORM_SUBMIT)); diff --git a/ui/litellm-dashboard/src/components/Teams.tsx b/ui/litellm-dashboard/src/components/Teams.tsx index edf376cb8d4..95642b93019 100644 --- a/ui/litellm-dashboard/src/components/Teams.tsx +++ b/ui/litellm-dashboard/src/components/Teams.tsx @@ -22,16 +22,13 @@ import AgentSelector from "./agent_management/AgentSelector"; import ModelAliasManager from "./common_components/ModelAliasManager"; import PremiumLoggingSettings from "./common_components/PremiumLoggingSettings"; import RouterSettingsAccordion, { RouterSettingsAccordionValue } from "./common_components/RouterSettingsAccordion"; -import { - fetchAvailableModelsForTeamOrKey, - unfurlWildcardModelsInList, -} from "./key_team_helpers/fetch_available_models_team_key"; +import { fetchAvailableModelsForTeamOrKey } from "./key_team_helpers/fetch_available_models_team_key"; import type { Team } from "./key_team_helpers/key_list"; import MCPServerSelector from "./mcp_server_management/MCPServerSelector"; import MCPToolPermissions from "./mcp_server_management/MCPToolPermissions"; import NotificationsManager from "./molecules/notifications_manager"; import { extractProxyErrorMessage } from "@/lib/http/client"; -import { Organization, fetchMCPAccessGroups, getGuardrailsList, getPoliciesList, teamDeleteCall } from "./networking"; +import { Organization, getGuardrailsList, getPoliciesList, teamDeleteCall } from "./networking"; import NumericalInput from "./shared/numerical_input"; import VectorStoreSelector from "./vector_store_management/VectorStoreSelector"; import SearchToolSelector from "./search_tools/SearchToolSelector"; @@ -43,35 +40,10 @@ interface TeamProps { premiumUser?: boolean; } -interface EditTeamModalProps { - visible: boolean; - onCancel: () => void; - team: any; // Assuming TeamType is a type representing your team object - onSubmit: (data: FormData) => void; // Assuming FormData is the type of data to be submitted -} - import DeleteResourceModal from "./common_components/DeleteResourceModal"; import { teamCreateCall } from "./networking"; import { ModelSelect } from "./ModelSelect/ModelSelect"; -const getOrganizationModels = (organization: Organization | null, userModels: string[]) => { - let tempModelsToPick = []; - - if (organization) { - if (organization.models.length > 0) { - tempModelsToPick = organization.models; - } else { - // show all available models if the team has no models set - tempModelsToPick = userModels; - } - } else { - // no team set, show all available models - tempModelsToPick = userModels; - } - - return unfurlWildcardModelsInList(tempModelsToPick, userModels); -}; - const canCreateOrManageTeams = ( userRole: string | null, userID: string | null, @@ -112,18 +84,6 @@ const getAdminOrganizations = ( return []; }; -const getOrganizationAlias = ( - organizationId: string | null | undefined, - organizations: Organization[] | null | undefined, -): string => { - if (!organizationId || !organizations) { - return organizationId || "N/A"; - } - - const organization = organizations.find((org) => org.organization_id === organizationId); - return organization?.organization_alias || organizationId; -}; - // @deprecated const Teams: React.FC = ({ accessToken, userID, userRole, premiumUser = false }) => { const { data: organizationsData } = useOrganizations(); @@ -135,35 +95,25 @@ const Teams: React.FC = ({ accessToken, userID, userRole, premiumUser const [currentOrgForCreateTeam, setCurrentOrgForCreateTeam] = useState(null); const [form] = Form.useForm(); - const [memberForm] = Form.useForm(); - const [value, setValue] = useState(""); - const [editModalVisible, setEditModalVisible] = useState(false); const [selectedTeam, setSelectedTeam] = useState(null); const [selectedTeamId, setSelectedTeamId] = useQueryState("team", parseAsString.withOptions({ history: "push" })); const [editTeam, setEditTeam] = useState(false); const [isTeamModalVisible, setIsTeamModalVisible] = useState(false); - const [isAddMemberModalVisible, setIsAddMemberModalVisible] = useState(false); - const [isEditMemberModalVisible, setIsEditMemberModalVisible] = useState(false); const [userModels, setUserModels] = useState([]); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [teamToDelete, setTeamToDelete] = useState(null); - const [modelsToPick, setModelsToPick] = useState([]); const [isTeamDeleting, setIsTeamDeleting] = useState(false); // Add this state near the other useState declarations const [guardrailsList, setGuardrailsList] = useState([]); const [policiesList, setPoliciesList] = useState([]); const [loggingSettings, setLoggingSettings] = useState([]); - const [mcpAccessGroups, setMcpAccessGroups] = useState([]); - const [mcpAccessGroupsLoaded, setMcpAccessGroupsLoaded] = useState(false); const [modelAliases, setModelAliases] = useState<{ [key: string]: string }>({}); const [routerSettings, setRouterSettings] = useState(null); const [routerSettingsKey, setRouterSettingsKey] = useState(0); useEffect(() => { - const models = getOrganizationModels(currentOrgForCreateTeam, userModels); - setModelsToPick(models); form.setFieldValue("models", []); }, [currentOrgForCreateTeam, userModels]); @@ -220,22 +170,6 @@ const Teams: React.FC = ({ accessToken, userID, userRole, premiumUser fetchPolicies(); }, [accessToken]); - const fetchMcpAccessGroups = async () => { - try { - if (accessToken == null) { - return; - } - const groups = await fetchMCPAccessGroups(accessToken); - setMcpAccessGroups(groups); - } catch (error) { - console.error("Failed to fetch MCP access groups:", error); - } - }; - - useEffect(() => { - fetchMcpAccessGroups(); - }, [accessToken]); - const handleOk = () => { setIsTeamModalVisible(false); form.resetFields(); @@ -245,12 +179,6 @@ const Teams: React.FC = ({ accessToken, userID, userRole, premiumUser setRouterSettingsKey((prev) => prev + 1); }; - const handleMemberOk = () => { - setIsAddMemberModalVisible(false); - setIsEditMemberModalVisible(false); - memberForm.resetFields(); - }; - const handleCancel = () => { setIsTeamModalVisible(false); form.resetFields(); @@ -260,12 +188,6 @@ const Teams: React.FC = ({ accessToken, userID, userRole, premiumUser setRouterSettingsKey((prev) => prev + 1); }; - const handleMemberCancel = () => { - setIsAddMemberModalVisible(false); - setIsEditMemberModalVisible(false); - memberForm.resetFields(); - }; - const handleDelete = async (team: Team) => { // Set the team to delete and open the confirmation modal setTeamToDelete(team); @@ -749,15 +671,7 @@ const Teams: React.FC = ({ accessToken, userID, userRole, premiumUser /> - { - if (!mcpAccessGroupsLoaded) { - fetchMcpAccessGroups(); - setMcpAccessGroupsLoaded(true); - } - }} - > + Additional Settings diff --git a/ui/litellm-dashboard/src/components/ToolDetail.tsx b/ui/litellm-dashboard/src/components/ToolDetail.tsx index 06f14638141..d90689fc627 100644 --- a/ui/litellm-dashboard/src/components/ToolDetail.tsx +++ b/ui/litellm-dashboard/src/components/ToolDetail.tsx @@ -24,12 +24,9 @@ import { fetchToolPolicyOptions, getToolUsageLogs, keyListCall, - teamListCall, updateToolPolicy, - type ToolPolicyOption, type ToolPolicyOverrideRow, } from "@/components/networking"; -import type { Team } from "@/components/key_team_helpers/key_list"; interface ToolDetailProps { toolName: string; @@ -87,12 +84,6 @@ export function ToolDetail({ toolName, onBack, accessToken }: ToolDetailProps) { staleTime: 60_000, }); - const { data: teamsData } = useQuery({ - queryKey: ["teams-list-tool-detail"], - queryFn: () => teamListCall(accessToken!, null, null), - enabled: !!accessToken, - }); - const { data: keysData } = useQuery({ queryKey: ["keys-list-tool-detail"], queryFn: () => keyListCall(accessToken!, null, null, null, null, null, 1, 100), @@ -122,24 +113,6 @@ export function ToolDetail({ toolName, onBack, accessToken }: ToolDetailProps) { })); }, [logsData?.logs]); - const teams: Team[] = useMemo(() => { - const arr = Array.isArray(teamsData) ? teamsData : teamsData?.data ?? []; - return arr.map((t: { team_id?: string; id?: string; team_alias?: string }) => ({ - team_id: t.team_id ?? t.id ?? "", - team_alias: t.team_alias ?? t.team_id ?? "", - models: [], - max_budget: null, - budget_duration: null, - tpm_limit: null, - rpm_limit: null, - organization_id: "", - created_at: "", - keys: [], - members_with_roles: [], - spend: 0, - })); - }, [teamsData]); - const keys: KeyOption[] = useMemo(() => { const keysRes = keysData?.keys ?? keysData?.data ?? []; return keysRes.map((k: { token?: string; api_key?: string; key_hash?: string; key_alias?: string }) => ({ diff --git a/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx b/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx index 71590660765..908a4c498dc 100644 --- a/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx +++ b/ui/litellm-dashboard/src/components/add_model/handle_add_model_submit.tsx @@ -197,7 +197,7 @@ export const handleAddModelSubmit = async (values: any, accessToken: string, for model_info: modelInfoObj, }; - const response: any = await modelCreateCall(accessToken, new_model); + await modelCreateCall(accessToken, new_model); } callback && callback(); diff --git a/ui/litellm-dashboard/src/components/add_model/model_connection_test.tsx b/ui/litellm-dashboard/src/components/add_model/model_connection_test.tsx index 5b284fd26f5..62bb5975478 100644 --- a/ui/litellm-dashboard/src/components/add_model/model_connection_test.tsx +++ b/ui/litellm-dashboard/src/components/add_model/model_connection_test.tsx @@ -24,7 +24,6 @@ const ModelConnectionTest: React.FC = ({ onTestComplete, }) => { const [error, setError] = React.useState(null); - const [rawRequest, setRawRequest] = React.useState(null); const [rawResponse, setRawResponse] = React.useState(null); const [isLoading, setIsLoading] = React.useState(true); const [isSuccess, setIsSuccess] = React.useState(false); @@ -34,7 +33,6 @@ const ModelConnectionTest: React.FC = ({ setIsLoading(true); setShowDetails(false); setError(null); - setRawRequest(null); setRawResponse(null); setIsSuccess(false); @@ -51,7 +49,7 @@ const ModelConnectionTest: React.FC = ({ return; } - const { litellmParamsObj, modelInfoObj, modelName: returnedModelName } = result[0]; + const { litellmParamsObj, modelInfoObj } = result[0]; const response = await testConnectionRequest(accessToken, litellmParamsObj, modelInfoObj, modelInfoObj?.mode); if (response.status === "success") { @@ -61,7 +59,6 @@ const ModelConnectionTest: React.FC = ({ } else { const errorMessage = response.result?.error || response.message || "Unknown error"; setError(errorMessage); - setRawRequest(litellmParamsObj); setRawResponse(response.result?.raw_request_typed_dict); setIsSuccess(false); } diff --git a/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx b/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx index f9005e099a5..cf1a5727948 100644 --- a/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx +++ b/ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.tsx @@ -158,8 +158,6 @@ const EditAutoRouterModal: React.FC = ({ const [loading, setLoading] = useState(false); const [modelAccessGroups, setModelAccessGroups] = useState([]); const [modelInfo, setModelInfo] = useState([]); - const [showCustomDefaultModel, setShowCustomDefaultModel] = useState(false); - const [showCustomEmbeddingModel, setShowCustomEmbeddingModel] = useState(false); const [showValidationErrors, setShowValidationErrors] = useState(false); const [routerConfig, setRouterConfig] = useState(null); const [customTechnicalKeywords, setCustomTechnicalKeywords] = useState([]); @@ -308,11 +306,6 @@ const EditAutoRouterModal: React.FC = ({ auto_router_embedding_model: modelData.litellm_params?.auto_router_embedding_model || "", model_access_group: modelData.model_info?.access_groups || [], }); - - // Check if using custom models - const allModelGroups = new Set(modelInfo.map((model) => model.model_group)); - setShowCustomDefaultModel(!allModelGroups.has(modelData.litellm_params?.auto_router_default_model)); - setShowCustomEmbeddingModel(!allModelGroups.has(modelData.litellm_params?.auto_router_embedding_model)); } catch (error) { console.error("Error parsing auto router config:", error); NotificationsManager.fromBackend("Error loading auto router configuration"); @@ -516,9 +509,6 @@ const EditAutoRouterModal: React.FC = ({ > { - setShowCustomDefaultModel(value === "custom"); - }} options={[...modelOptions, { value: "custom", label: "Enter custom model name" }]} showSearch={true} /> @@ -532,9 +522,6 @@ const EditAutoRouterModal: React.FC = ({ > { - setShowCustomEmbeddingModel(value === "custom"); - }} options={[...modelOptions, { value: "custom", label: "Enter custom model name" }]} showSearch={true} /> diff --git a/ui/litellm-dashboard/src/components/llm_calls/chat_completion.tsx b/ui/litellm-dashboard/src/components/llm_calls/chat_completion.tsx index c20d758fe91..549f309b4ea 100644 --- a/ui/litellm-dashboard/src/components/llm_calls/chat_completion.tsx +++ b/ui/litellm-dashboard/src/components/llm_calls/chat_completion.tsx @@ -73,10 +73,6 @@ export async function makeOpenAIChatCompletionRequest( let firstTokenReceived = false; let timeToFirstToken: number | undefined = undefined; - // For collecting complete response text - let fullResponseContent = ""; - let fullReasoningContent = ""; - // Track MCP metadata cumulatively across chunks let mcpMetadata: { mcp_list_tools?: any[]; @@ -167,7 +163,6 @@ export async function makeOpenAIChatCompletionRequest( if (chunk.choices[0]?.delta?.content) { const content = chunk.choices[0].delta.content; updateUI(content, chunk.model); - fullResponseContent += content; } // Process image generation if present @@ -181,7 +176,6 @@ export async function makeOpenAIChatCompletionRequest( if (onReasoningContent) { onReasoningContent(reasoningContent); } - fullReasoningContent += reasoningContent; } // Check for search results in provider_specific_fields diff --git a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx index 00f36f016b7..b167e44fe04 100644 --- a/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx +++ b/ui/litellm-dashboard/src/components/organisms/create_key_button.tsx @@ -93,26 +93,6 @@ interface UserOption { user: User; } -const getPredefinedTags = (data: any[] | null) => { - let allTags = []; - - if (data) { - for (let key of data) { - if (key["metadata"] && key["metadata"]["tags"]) { - allTags.push(...key["metadata"]["tags"]); - } - } - } - - // Deduplicate using Set - const uniqueTags = Array.from(new Set(allTags)).map((tag) => ({ - value: tag, - label: tag, - })); - - return uniqueTags; -}; - export const fetchTeamModels = async ( userID: string, userRole: string, @@ -178,7 +158,6 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp const [form] = Form.useForm(); const [isModalVisible, setIsModalVisible] = useState(false); const [apiKey, setApiKey] = useState(null); - const [softBudget, setSoftBudget] = useState(null); const [userModels, setUserModels] = useState([]); const [modelsToPick, setModelsToPick] = useState([]); const [keyOwner, setKeyOwner] = useState("you"); @@ -192,11 +171,9 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp const [selectedOrganizationId, setSelectedOrganizationId] = useState(null); const [selectedProjectId, setSelectedProjectId] = useState(null); const [isCreateUserModalVisible, setIsCreateUserModalVisible] = useState(false); - const [newlyCreatedUserId, setNewlyCreatedUserId] = useState(null); const [possibleUIRoles, setPossibleUIRoles] = useState>>({}); const [userOptions, setUserOptions] = useState([]); const [userSearchLoading, setUserSearchLoading] = useState(false); - const [mcpAccessGroups, setMcpAccessGroups] = useState([]); const [disabledCallbacks, setDisabledCallbacks] = useState([]); const [keyType, setKeyType] = useState("llm_api"); const [modelAliases, setModelAliases] = useState<{ [key: string]: string }>({}); @@ -578,7 +555,6 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp queryClient.invalidateQueries({ queryKey: keyKeys.lists() }); setApiKey(response["key"]); - setSoftBudget(response["soft_budget"]); NotificationsManager.success("Virtual Key Created"); form.resetFields(); setBudgetLimits([]); @@ -592,10 +568,6 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp } }; - const handleCopy = () => { - NotificationsManager.success("Virtual Key copied to clipboard"); - }; - // Fetch available models when team or auth changes. // Note: Model prefill from URL params is handled by the useEffect below, which // watches for pendingPrefillModels + modelsToPick to both be populated. @@ -657,7 +629,6 @@ const CreateKey: React.FC = ({ team, teams, data, addKey, autoOp // Add a callback function to handle user creation const handleUserCreated = (userId: string) => { - setNewlyCreatedUserId(userId); form.setFieldsValue({ user_id: userId }); setIsCreateUserModalVisible(false); }; diff --git a/ui/litellm-dashboard/src/components/organization/organization_view.tsx b/ui/litellm-dashboard/src/components/organization/organization_view.tsx index 10af5bc1a07..a9f79810e1d 100644 --- a/ui/litellm-dashboard/src/components/organization/organization_view.tsx +++ b/ui/litellm-dashboard/src/components/organization/organization_view.tsx @@ -69,7 +69,7 @@ const OrganizationInfoView: React.FC = ({ user_id: values.user_id, role: values.role, }; - const response = await organizationMemberAddCall(accessToken, organizationId, member); + await organizationMemberAddCall(accessToken, organizationId, member); NotificationsManager.success("Organization member added successfully"); setIsAddMemberModalVisible(false); @@ -90,7 +90,7 @@ const OrganizationInfoView: React.FC = ({ role: values.role, }; - const response = await organizationMemberUpdateCall(accessToken, organizationId, member); + await organizationMemberUpdateCall(accessToken, organizationId, member); NotificationsManager.success("Organization member updated successfully"); setIsEditMemberModalVisible(false); queryClient.invalidateQueries({ queryKey: organizationKeys.all }); diff --git a/ui/litellm-dashboard/src/components/per_user_usage.tsx b/ui/litellm-dashboard/src/components/per_user_usage.tsx index 30933700cf3..e542be8df8f 100644 --- a/ui/litellm-dashboard/src/components/per_user_usage.tsx +++ b/ui/litellm-dashboard/src/components/per_user_usage.tsx @@ -55,13 +55,11 @@ const PerUserUsage: React.FC = ({ accessToken, selectedTags, total_pages: 0, }); - const [loading, setLoading] = useState(false); const [currentPage, setCurrentPage] = useState(1); const fetchPerUserData = async () => { if (!accessToken) return; - setLoading(true); try { const response = await perUserAnalyticsCall( accessToken, @@ -72,8 +70,6 @@ const PerUserUsage: React.FC = ({ accessToken, selectedTags, setPerUserData(response); } catch (error) { console.error("Failed to fetch per-user data:", error); - } finally { - setLoading(false); } }; diff --git a/ui/litellm-dashboard/src/components/price_data_reload.tsx b/ui/litellm-dashboard/src/components/price_data_reload.tsx index e0ec0fb794d..f56387d283c 100644 --- a/ui/litellm-dashboard/src/components/price_data_reload.tsx +++ b/ui/litellm-dashboard/src/components/price_data_reload.tsx @@ -60,9 +60,7 @@ const PriceDataReload: React.FC = ({ const [showScheduleModal, setShowScheduleModal] = useState(false); const [hours, setHours] = useState(6); const [reloadStatus, setReloadStatus] = useState(null); - const [loadingStatus, setLoadingStatus] = useState(false); const [sourceInfo, setSourceInfo] = useState(null); - const [loadingSource, setLoadingSource] = useState(false); // Fetch status on component mount and periodically useEffect(() => { @@ -81,7 +79,6 @@ const PriceDataReload: React.FC = ({ const fetchReloadStatus = async () => { if (!accessToken) return; - setLoadingStatus(true); try { const status = await getModelCostMapReloadStatus(accessToken); setReloadStatus(status); @@ -94,22 +91,17 @@ const PriceDataReload: React.FC = ({ last_run: null, next_run: null, }); - } finally { - setLoadingStatus(false); } }; const fetchSourceInfo = async () => { if (!accessToken) return; - setLoadingSource(true); try { const info = await getModelCostMapSource(accessToken); setSourceInfo(info); } catch (error) { console.error("Failed to fetch cost map source info:", error); - } finally { - setLoadingSource(false); } }; diff --git a/ui/litellm-dashboard/src/components/shared/DataTable/columnMeta.ts b/ui/litellm-dashboard/src/components/shared/DataTable/columnMeta.ts index eff4e0cb7db..39a99f1e861 100644 --- a/ui/litellm-dashboard/src/components/shared/DataTable/columnMeta.ts +++ b/ui/litellm-dashboard/src/components/shared/DataTable/columnMeta.ts @@ -4,6 +4,7 @@ import type * as React from "react"; import type { ColumnPinnedSide, DataTableSkeletonShape } from "./types"; declare module "@tanstack/react-table" { + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- declaration merging requires the type parameters to match the upstream ColumnMeta signature exactly (TS2428) interface ColumnMeta { numeric?: boolean; className?: string; diff --git a/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx b/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx index e724e32d1c4..f998d7d3ecf 100644 --- a/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx +++ b/ui/litellm-dashboard/src/components/team/LoggingSettings.test.tsx @@ -1,6 +1,5 @@ import React from "react"; import { describe, it, expect, vi, beforeEach } from "vitest"; -import userEvent from "@testing-library/user-event"; import { renderWithProviders, screen, fireEvent } from "../../../tests/test-utils"; import LoggingSettings from "./LoggingSettings"; @@ -10,7 +9,6 @@ describe("LoggingSettings", () => { }); it("passes a number to updateCallbackVar when user inputs a number in NumericalInput", async () => { - const user = userEvent.setup(); const mockOnChange = vi.fn(); // Create initial config with a callback that has number parameters (LangSmith has langsmith_sampling_rate) diff --git a/ui/litellm-dashboard/src/components/team/TeamInfo.tsx b/ui/litellm-dashboard/src/components/team/TeamInfo.tsx index bbe5dc05a88..b7bbbba3aed 100644 --- a/ui/litellm-dashboard/src/components/team/TeamInfo.tsx +++ b/ui/litellm-dashboard/src/components/team/TeamInfo.tsx @@ -52,7 +52,6 @@ import MCPServerSelector from "../mcp_server_management/MCPServerSelector"; import MCPToolPermissions from "../mcp_server_management/MCPToolPermissions"; import { ModelSelect } from "../ModelSelect/ModelSelect"; import NotificationsManager from "../molecules/notifications_manager"; -import { fetchMCPAccessGroups } from "../networking"; import ObjectPermissionsView from "../object_permissions_view"; import NumericalInput from "../shared/numerical_input"; import VectorStoreSelector from "../vector_store_management/VectorStoreSelector"; @@ -161,29 +160,6 @@ export interface TeamInfoProps { premiumUser?: boolean; } -const getOrganizationModels = (organization: Organization | null, userModels: string[]) => { - let tempModelsToPick = []; - - if (organization) { - // Check if organization has "all-proxy-models" in its models array - if (organization.models.includes("all-proxy-models")) { - // Treat as all-proxy-models (use userModels) - tempModelsToPick = userModels; - } else if (organization.models.length > 0) { - // Organization has specific models - tempModelsToPick = organization.models; - } else { - // Empty array [] is treated as all-proxy-models - tempModelsToPick = userModels; - } - } else { - // No organization, show all available models - tempModelsToPick = userModels; - } - - return unfurlWildcardModelsInList(tempModelsToPick, userModels); -}; - const TeamInfoView: React.FC = ({ teamId, onClose, @@ -203,8 +179,6 @@ const TeamInfoView: React.FC = ({ const [isEditMemberModalVisible, setIsEditMemberModalVisible] = useState(false); const [selectedEditMember, setSelectedEditMember] = useState(null); const [isEditing, setIsEditing] = useState(false); - const [mcpAccessGroups, setMcpAccessGroups] = useState([]); - const [mcpAccessGroupsLoaded, setMcpAccessGroupsLoaded] = useState(false); const [copiedStates, setCopiedStates] = useState>({}); const { data: guardrailsData, isLoading: isGuardrailsLoading } = useGuardrails(); const globalGuardrailNames = guardrailsData?.globalGuardrailNames ?? new Set(); @@ -293,23 +267,6 @@ const TeamInfoView: React.FC = ({ fetchOrganization(); }, [accessToken, teamData?.team_info?.organization_id]); - // Compute modelsToPick based on organization and userModels - const modelsToPick = useMemo(() => { - return getOrganizationModels(organization, userModels); - }, [organization, userModels]); - - const fetchMcpAccessGroups = async () => { - if (!accessToken) return; - if (mcpAccessGroupsLoaded) return; - try { - const groups = await fetchMCPAccessGroups(accessToken); - setMcpAccessGroups(groups); - setMcpAccessGroupsLoaded(true); - } catch (error) { - console.error("Failed to fetch MCP access groups:", error); - } - }; - useEffect(() => { const fetchPolicies = async () => { try { @@ -653,7 +610,7 @@ const TeamInfoView: React.FC = ({ } } - const response = await teamUpdateCall(accessToken, updateData); + await teamUpdateCall(accessToken, updateData); queryClient.invalidateQueries({ queryKey: organizationKeys.all }); NotificationsManager.success("Team settings updated successfully"); diff --git a/ui/litellm-dashboard/src/components/templates/KeyInfoView.handleKeyUpdate.test.tsx b/ui/litellm-dashboard/src/components/templates/KeyInfoView.handleKeyUpdate.test.tsx index fa8ffcd7366..3b001e39a25 100644 --- a/ui/litellm-dashboard/src/components/templates/KeyInfoView.handleKeyUpdate.test.tsx +++ b/ui/litellm-dashboard/src/components/templates/KeyInfoView.handleKeyUpdate.test.tsx @@ -196,32 +196,28 @@ vi.mock("lucide-react", async () => { }); // Heavy children -> async factories & local React -vi.mock("../organisms/RegenerateKeyModal", async () => { - const React = await import("react"); +vi.mock("../organisms/RegenerateKeyModal", () => { function RegenerateKeyModal() { return null; } (RegenerateKeyModal as any).displayName = "RegenerateKeyModal"; return { RegenerateKeyModal }; }); -vi.mock("../object_permissions_view", async () => { - const React = await import("react"); +vi.mock("../object_permissions_view", () => { function ObjectPermissionsView() { return null; } (ObjectPermissionsView as any).displayName = "ObjectPermissionsView"; return { __esModule: true, default: ObjectPermissionsView }; }); -vi.mock("../logging_settings_view", async () => { - const React = await import("react"); +vi.mock("../logging_settings_view", () => { function LoggingSettingsView() { return null; } (LoggingSettingsView as any).displayName = "LoggingSettingsView"; return { __esModule: true, default: LoggingSettingsView }; }); -vi.mock("../common_components/AutoRotationView", async () => { - const React = await import("react"); +vi.mock("../common_components/AutoRotationView", () => { function AutoRotationView() { return null; } diff --git a/ui/litellm-dashboard/src/components/templates/key_edit_view.test.tsx b/ui/litellm-dashboard/src/components/templates/key_edit_view.test.tsx index 756481487e7..e93b28f4ea3 100644 --- a/ui/litellm-dashboard/src/components/templates/key_edit_view.test.tsx +++ b/ui/litellm-dashboard/src/components/templates/key_edit_view.test.tsx @@ -1007,7 +1007,7 @@ describe("KeyEditView", () => { }); it("should disable the organization dropdown for non-admin users", async () => { - const { container } = renderWithProviders( + renderWithProviders( {}} @@ -1029,7 +1029,7 @@ describe("KeyEditView", () => { }); it("should not disable the organization dropdown for admin users", async () => { - const { container } = renderWithProviders( + renderWithProviders( {}} diff --git a/ui/litellm-dashboard/src/components/templates/key_info_view.tsx b/ui/litellm-dashboard/src/components/templates/key_info_view.tsx index 280abb3dac7..f4803727875 100644 --- a/ui/litellm-dashboard/src/components/templates/key_info_view.tsx +++ b/ui/litellm-dashboard/src/components/templates/key_info_view.tsx @@ -6,7 +6,7 @@ import { formatNumberWithCommas } from "@/utils/dataUtils"; import { mapEmptyStringToNull } from "@/utils/keyUpdateUtils"; import { ArrowLeftIcon } from "@heroicons/react/outline"; import { Badge, Button, Card, Grid, Tab, TabGroup, TabList, TabPanel, TabPanels, Text, Title } from "@tremor/react"; -import { Form, Modal, Tag } from "antd"; +import { Modal, Tag } from "antd"; import { KeyInfoHeader } from "./KeyInfoHeader"; import { useEffect, useState } from "react"; import { isProxyAdminRole, isUserTeamAdminForSingleTeam, rolesWithWriteAccess } from "../../utils/roles"; @@ -74,10 +74,8 @@ export default function KeyInfoView({ const { data: uiSettingsData } = useUISettings(); const enableProjectsUI = Boolean(uiSettingsData?.values?.enable_projects_ui); const [isEditing, setIsEditing] = useState(false); - const [form] = Form.useForm(); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); const [deleteLoading, setDeleteLoading] = useState(false); - const [deleteConfirmInput, setDeleteConfirmInput] = useState(""); const [isRegenerateModalOpen, setIsRegenerateModalOpen] = useState(false); const [isResetSpendModalOpen, setIsResetSpendModalOpen] = useState(false); const [isBlockModalOpen, setIsBlockModalOpen] = useState(false); @@ -340,7 +338,6 @@ export default function KeyInfoView({ } finally { setDeleteLoading(false); setIsDeleteModalOpen(false); - setDeleteConfirmInput(""); } }; @@ -526,7 +523,6 @@ export default function KeyInfoView({ ]} onCancel={() => { setIsDeleteModalOpen(false); - setDeleteConfirmInput(""); }} onOk={handleDelete} confirmLoading={deleteLoading} diff --git a/ui/litellm-dashboard/src/components/user_dashboard.tsx b/ui/litellm-dashboard/src/components/user_dashboard.tsx index 1ed4e1d0bba..1de232fadb8 100644 --- a/ui/litellm-dashboard/src/components/user_dashboard.tsx +++ b/ui/litellm-dashboard/src/components/user_dashboard.tsx @@ -6,14 +6,7 @@ import React, { useEffect, useState } from "react"; import { fetchTeams } from "./common_components/fetch_teams"; import { KeyResponse, Team } from "./key_team_helpers/key_list"; import { effectiveSessionRole } from "@/utils/roles"; -import { - getProxyBaseUrl, - getProxyUISettings, - keyInfoCall, - modelAvailableCall, - Organization, - userGetInfoV2, -} from "./networking"; +import { getProxyBaseUrl, keyInfoCall, modelAvailableCall, Organization, userGetInfoV2 } from "./networking"; import CreateKey, { CreateKeyPrefillData } from "./organisms/create_key_button"; import { VirtualKeysTable } from "./VirtualKeysPage/VirtualKeysTable"; @@ -50,12 +43,6 @@ interface UserDashboardProps { prefillData?: CreateKeyPrefillData; } -type TeamInterface = { - models: any[]; - team_id: null; - team_alias: string; -}; - const UserDashboard: React.FC = ({ userID, userRole, @@ -73,15 +60,12 @@ const UserDashboard: React.FC = ({ prefillData, }) => { const [userSpendData, setUserSpendData] = useState(null); - const [currentOrg, setCurrentOrg] = useState(null); + const [currentOrg] = useState(null); const token = getCookie("token"); const [accessToken, setAccessToken] = useState(null); - const [teamSpend, setTeamSpend] = useState(null); - const [userModels, setUserModels] = useState([]); - const [proxySettings, setProxySettings] = useState(null); - const [selectedTeam, setSelectedTeam] = useState(null); + const [selectedTeam] = useState(null); // Clear session storage on page unload so next load fetches fresh data. // Note: MCP auth tokens are persistent and should not be cleared on page refresh @@ -123,14 +107,9 @@ const UserDashboard: React.FC = ({ } if (userID && accessToken && userRole && !userSpendData) { const cachedUserModels = sessionStorage.getItem("userModels" + userID); - if (cachedUserModels) { - setUserModels(JSON.parse(cachedUserModels)); - } else { + if (!cachedUserModels) { const fetchData = async () => { try { - const proxy_settings: ProxySettings = await getProxyUISettings(accessToken); - setProxySettings(proxy_settings); - const response = await userGetInfoV2(accessToken, userID); setUserSpendData(response); @@ -140,7 +119,6 @@ const UserDashboard: React.FC = ({ const model_available = await modelAvailableCall(accessToken, userID, userRole); // loop through model_info["data"] and create an array of element.model_name let available_model_names = model_available["data"].map((element: { id: string }) => element.id); - setUserModels(available_model_names); sessionStorage.setItem("userModels" + userID, JSON.stringify(available_model_names)); } catch (error: any) { @@ -162,7 +140,7 @@ const UserDashboard: React.FC = ({ if (accessToken) { const fetchKeyInfo = async () => { try { - const keyInfo = await keyInfoCall(accessToken, [accessToken]); + await keyInfoCall(accessToken, [accessToken]); } catch (error: any) { if (error.message.includes("Invalid proxy server token passed")) { gotoLogin(); @@ -179,26 +157,6 @@ const UserDashboard: React.FC = ({ } }, [currentOrg]); - useEffect(() => { - // This code will run every time selectedTeam changes - if (keys !== null && selectedTeam !== null && selectedTeam !== undefined && selectedTeam.team_id !== null) { - let sum = 0; - for (const key of keys) { - if (selectedTeam.hasOwnProperty("team_id") && key.team_id !== null && key.team_id === selectedTeam.team_id) { - sum += key.spend; - } - } - setTeamSpend(sum); - } else if (keys !== null) { - // sum the keys which don't have team-id set (default team) - let sum = 0; - for (const key of keys) { - sum += key.spend; - } - setTeamSpend(sum); - } - }, [selectedTeam]); - function gotoLogin() { // Clear token cookies using the utility function clearTokenCookies(); diff --git a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/SimpleToolCallBlock.test.tsx b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/SimpleToolCallBlock.test.tsx index 107b911e386..0eb61686b73 100644 --- a/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/SimpleToolCallBlock.test.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/SimpleToolCallBlock.test.tsx @@ -31,7 +31,7 @@ describe("SimpleToolCallBlock", () => { }); it("should not render arguments section when arguments are empty", () => { - const { container } = render(); + render(); // The tool name and "function" badge should be there, but no key: value pairs expect(screen.getByText("get_weather")).toBeInTheDocument(); expect(screen.queryByText(/:$/)).not.toBeInTheDocument(); diff --git a/ui/litellm-dashboard/src/components/view_logs/table.tsx b/ui/litellm-dashboard/src/components/view_logs/table.tsx index c96f34f9b93..d522478e370 100644 --- a/ui/litellm-dashboard/src/components/view_logs/table.tsx +++ b/ui/litellm-dashboard/src/components/view_logs/table.tsx @@ -14,6 +14,7 @@ import { import { Table, TableHeader, TableHead, TableBody, TableRow, TableCell } from "@/components/ui/table"; declare module "@tanstack/react-table" { + // eslint-disable-next-line @typescript-eslint/no-unused-vars -- declaration merging requires the type parameters to match the upstream ColumnMeta signature exactly (TS2428) interface ColumnMeta { numeric?: boolean; }