mirror of
https://github.com/BerriAI/litellm.git
synced 2026-08-28 05:25:59 +00:00
Merge branch 'litellm_internal_staging' into litellm_dead_locals_5_8
This commit is contained in:
commit
6e434c926b
33 changed files with 25 additions and 249 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { screen, within } from "@testing-library/react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { renderWithProviders } from "../../../../../../tests/test-utils";
|
||||
import MultiCostResults from "./multi_cost_results";
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { screen, fireEvent } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { renderWithProviders } from "../../../../../../tests/test-utils";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { screen, within } from "@testing-library/react";
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { renderWithProviders } from "../../../../../tests/test-utils";
|
||||
import ProviderDiscountTable from "./provider_discount_table";
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ describe("Guardrail Info", () => {
|
|||
vi.mocked(networking.getGuardrailProviderSpecificParams).mockResolvedValue({});
|
||||
vi.mocked(networking.updateGuardrailCall).mockResolvedValue({ status: "success" });
|
||||
|
||||
const { getByText, getByRole, getAllByRole, getByLabelText } = render(
|
||||
const { getByText, getByLabelText } = render(
|
||||
<GuardrailInfoView guardrailId="123" onClose={() => {}} accessToken="123" isAdmin={true} />,
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import { render, screen, fireEvent } from "@testing-library/react";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import MCPLogoSelector from "./MCPLogoSelector";
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ describe("ChatUI", () => {
|
|||
});
|
||||
|
||||
it("should show the voice selector when the endpoint type is audio_speech", async () => {
|
||||
const { getByText, container } = render(
|
||||
const { getByText } = render(
|
||||
<ChatUI
|
||||
accessToken="1234567890"
|
||||
token="1234567890"
|
||||
|
|
@ -110,7 +110,7 @@ describe("ChatUI", () => {
|
|||
});
|
||||
|
||||
it("should allow the user to select a model", async () => {
|
||||
const { getByText, container } = render(
|
||||
const { getByText } = render(
|
||||
<ChatUI
|
||||
accessToken="1234567890"
|
||||
token="1234567890"
|
||||
|
|
@ -148,7 +148,7 @@ describe("ChatUI", () => {
|
|||
{ model_group: "ResponsesModel", mode: "responses" },
|
||||
]);
|
||||
|
||||
const { getByText, baseElement } = render(
|
||||
const { getByText } = render(
|
||||
<ChatUI
|
||||
accessToken="1234567890"
|
||||
token="1234567890"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ interface UIThemeSettingsProps {
|
|||
}
|
||||
|
||||
const UIThemeSettings: React.FC<UIThemeSettingsProps> = ({ userID, userRole, accessToken }) => {
|
||||
const { logoUrl, setLogoUrl, faviconUrl, setFaviconUrl } = useTheme();
|
||||
const { setLogoUrl, setFaviconUrl } = useTheme();
|
||||
const [logoUrlInput, setLogoUrlInput] = useState<string>("");
|
||||
const [faviconUrlInput, setFaviconUrlInput] = useState<string>("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
Tooltip,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
import BulkCreateUsers from "./bulk_create_users_button";
|
||||
import TeamDropdown from "./common_components/team_dropdown";
|
||||
import { getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key";
|
||||
|
|
@ -29,7 +29,7 @@ import {
|
|||
} from "./networking";
|
||||
import OnboardingModal, { InvitationLink } from "./onboarding_link";
|
||||
const { Option } = Select;
|
||||
const { Text, Link, Title } = Typography;
|
||||
const { Text, Link } = Typography;
|
||||
// Helper function to generate UUID compatible across all environments
|
||||
const generateUUID = (): string => {
|
||||
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
||||
|
|
@ -80,11 +80,6 @@ export const CreateUserButton: React.FC<CreateuserProps> = ({
|
|||
const { data: organizations = [] } = useOrganizations();
|
||||
|
||||
// Derive teams from the user's organizations, falling back to the teams prop
|
||||
const availableTeams = useMemo(() => {
|
||||
const orgTeams = organizations.flatMap((org) => org.teams || []);
|
||||
if (orgTeams.length > 0) return orgTeams;
|
||||
return teams || [];
|
||||
}, [organizations, teams]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { describe, it, expect } from "vitest";
|
||||
import { screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { renderWithProviders } from "../../tests/test-utils";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { ProxyModel, useAllProxyModels } from "@/app/(dashboard)/hooks/models/us
|
|||
import { useOrganization } from "@/app/(dashboard)/hooks/organizations/useOrganizations";
|
||||
import { useTeam } from "@/app/(dashboard)/hooks/teams/useTeams";
|
||||
import { useCurrentUser } from "@/app/(dashboard)/hooks/users/useCurrentUser";
|
||||
import { Select, Skeleton, Tooltip, type SelectProps } from "antd";
|
||||
import { Select, Skeleton, Tooltip } from "antd";
|
||||
import { Organization, Team } from "../networking";
|
||||
import { splitWildcardModels } from "./modelUtils";
|
||||
|
||||
|
|
@ -93,8 +93,7 @@ const filterModels = (
|
|||
|
||||
export const ModelSelect = (props: ModelSelectProps) => {
|
||||
const { teamID, organizationID, options, context, dataTestId, value = [], onChange, style } = props;
|
||||
const { includeUserModels, showAllTeamModelsOption, showAllProxyModelsOverride, includeSpecialOptions } =
|
||||
options || {};
|
||||
const { showAllProxyModelsOverride, includeSpecialOptions } = options || {};
|
||||
const { data: allProxyModels, isLoading: isLoadingAllProxyModels } = useAllProxyModels();
|
||||
const { data: team, isLoading: isLoadingTeam } = useTeam(teamID);
|
||||
const { data: organization, isLoading: isLoadingOrganization } = useOrganization(organizationID);
|
||||
|
|
@ -113,10 +112,6 @@ export const ModelSelect = (props: ModelSelectProps) => {
|
|||
return <Skeleton.Input active block />;
|
||||
}
|
||||
|
||||
const optionRender: NonNullable<SelectProps["optionRender"]> = (option) => {
|
||||
return <span>{option.label}</span>;
|
||||
};
|
||||
|
||||
const handleChange = (values: string[]) => {
|
||||
const specialValues = values.filter(isSpecialOption);
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ interface TopKeyViewProps {
|
|||
}
|
||||
|
||||
const TopKeyView: React.FC<TopKeyViewProps> = ({ topKeys, teams, showTags = false, topKeysLimit, setTopKeysLimit }) => {
|
||||
const { accessToken, userRole, userId: userID, premiumUser } = useAuthorized();
|
||||
const { accessToken } = useAuthorized();
|
||||
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
|
||||
const [selectedKey, setSelectedKey] = useState<string | null>(null);
|
||||
const [keyData, setKeyData] = useState<any | undefined>(undefined);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ const AddModelForm: React.FC<AddModelFormProps> = ({
|
|||
} = useProviderFields();
|
||||
const { data: guardrailsData } = useGuardrails();
|
||||
const guardrailsList = guardrailsData?.guardrails.map((g) => g.guardrail_name);
|
||||
const { data: tagsList, isLoading: isTagsLoading, error: tagsError } = useTags();
|
||||
const { data: tagsList } = useTags();
|
||||
|
||||
const handleTestConnection = async () => {
|
||||
setIsTestingConnection(true);
|
||||
|
|
|
|||
|
|
@ -126,13 +126,6 @@ const RouterConfigBuilder: React.FC<RouterConfigBuilderProps> = ({ modelInfo, va
|
|||
};
|
||||
|
||||
// Handle utterances change (convert textarea string to array)
|
||||
const handleUtterancesChange = (routeId: string, utterancesText: string) => {
|
||||
const utterancesArray = utterancesText
|
||||
.split("\n")
|
||||
.map((line) => line.trim()) // Only trims leading/trailing whitespace, preserves internal spaces
|
||||
.filter((line) => line.length > 0);
|
||||
updateRoute(routeId, "utterances", utterancesArray);
|
||||
};
|
||||
|
||||
// Prepare model options for dropdowns
|
||||
const modelOptions = modelInfo.map((model) => ({
|
||||
|
|
|
|||
|
|
@ -191,11 +191,6 @@ const AddAutoRouterTab: React.FC<AddAutoRouterTabProps> = ({
|
|||
|
||||
const isAdmin = all_admin_roles.includes(userRole);
|
||||
|
||||
const modelGroupOptions = Array.from(new Set(modelInfo.map((option) => option.model_group))).map((model_group) => ({
|
||||
value: model_group,
|
||||
label: model_group,
|
||||
}));
|
||||
|
||||
const availability = React.useMemo(
|
||||
() =>
|
||||
buildModelAvailability(
|
||||
|
|
|
|||
|
|
@ -37,7 +37,6 @@ const AddPassThroughEndpoint: React.FC<AddFallbacksProps> = ({
|
|||
const [form] = Form.useForm();
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [selectedModel, setSelectedModel] = useState("");
|
||||
const [pathValue, setPathValue] = useState("");
|
||||
const [targetValue, setTargetValue] = useState("");
|
||||
const [includeSubpath, setIncludeSubpath] = useState(true);
|
||||
|
|
@ -107,11 +106,6 @@ const AddPassThroughEndpoint: React.FC<AddFallbacksProps> = ({
|
|||
}
|
||||
};
|
||||
|
||||
const copyToClipboard = (text: string) => {
|
||||
navigator.clipboard.writeText(text);
|
||||
NotificationsManager.success("Copied to clipboard!");
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button className="mx-auto mb-4 mt-4" onClick={() => setIsModalVisible(true)}>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it, vi, beforeEach } from "vitest";
|
||||
|
||||
// Mock networking module
|
||||
|
|
|
|||
|
|
@ -80,24 +80,6 @@ const BulkCreateUsersButton: React.FC<BulkCreateUsersProps> = ({
|
|||
setBaseUrl(base.toString());
|
||||
}, [accessToken]);
|
||||
|
||||
const downloadTemplate = () => {
|
||||
const template = [
|
||||
["user_email", "user_role", "teams", "max_budget", "budget_duration", "models"],
|
||||
["user@example.com", "internal_user", "team-id-1,team-id-2", "100", "30d", "gpt-3.5-turbo,gpt-4"],
|
||||
];
|
||||
|
||||
const csv = Papa.unparse(template);
|
||||
const blob = new Blob([csv], { type: "text/csv" });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
a.href = url;
|
||||
a.download = "bulk_users_template.csv";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
};
|
||||
|
||||
const handleFileUpload = (file: File) => {
|
||||
// Reset all error states
|
||||
setParseError(null);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@ export const generateCodeSnippet = (params: GenerateCodeParams): string => {
|
|||
selectedVectorStores,
|
||||
selectedGuardrails,
|
||||
selectedPolicies,
|
||||
selectedMCPServers,
|
||||
mcpServers,
|
||||
mcpServerToolRestrictions,
|
||||
selectedVoice,
|
||||
endpointType,
|
||||
selectedModel,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import React from "react";
|
||||
import { Typography, Collapse } from "antd";
|
||||
import { Collapse } from "antd";
|
||||
import type { MCPEvent } from "@/components/mcp_tools/types";
|
||||
|
||||
const { Text } = Typography;
|
||||
const { Panel } = Collapse;
|
||||
|
||||
interface MCPEventsDisplayProps {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export default function DeleteResourceModal({
|
|||
confirmLoading,
|
||||
requiredConfirmation,
|
||||
}: DeleteResourceModalProps) {
|
||||
const { Title, Text } = Typography;
|
||||
const { Text } = Typography;
|
||||
const { token } = theme.useToken();
|
||||
const [requiredConfirmationInput, setRequiredConfirmationInput] = useState("");
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from "react";
|
|||
import { Form, Button, Tooltip, Typography, Modal } from "antd";
|
||||
import { TextInput } from "@tremor/react";
|
||||
import { CredentialItem } from "../networking";
|
||||
const { Title, Link } = Typography;
|
||||
const { Link } = Typography;
|
||||
|
||||
interface ReuseCredentialsModalProps {
|
||||
isVisible: boolean;
|
||||
|
|
|
|||
|
|
@ -121,13 +121,6 @@ const ModelFilters: React.FC<ModelFiltersProps> = ({
|
|||
};
|
||||
|
||||
// Expose filter values and reset function
|
||||
const filterValues = {
|
||||
searchTerm,
|
||||
selectedProvider,
|
||||
selectedMode,
|
||||
selectedFeature,
|
||||
resetFilters,
|
||||
};
|
||||
|
||||
const filtersContent = (
|
||||
<div className="flex flex-wrap gap-4 items-center">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import userEvent from "@testing-library/user-event";
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import { renderWithProviders, screen, waitFor } from "../../tests/test-utils";
|
||||
import Navbar from "./navbar";
|
||||
|
|
|
|||
|
|
@ -390,7 +390,6 @@ export const getAgentCreateMetadata = async (): Promise<AgentCreateInfo[]> => {
|
|||
|
||||
// Global variable for the header name
|
||||
let globalLitellmHeaderName: string = "Authorization";
|
||||
const MCP_AUTH_HEADER: string = "x-mcp-auth";
|
||||
|
||||
// Function to set the global header name
|
||||
export function setGlobalLitellmHeaderName(headerName: string = "Authorization") {
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export default function OnboardingModal({
|
|||
invitationLinkData,
|
||||
modalType = "invitation",
|
||||
}: OnboardingProps) {
|
||||
const { Title, Paragraph } = Typography;
|
||||
const { Paragraph } = Typography;
|
||||
const handleInvitationOk = () => {
|
||||
setIsInvitationLinkModalVisible(false);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ const PassThroughInfoView: React.FC<PassThroughInfoProps> = ({
|
|||
onEndpointUpdated,
|
||||
}) => {
|
||||
const [endpointData, setEndpointData] = useState<PassThroughEndpoint | null>(initialEndpointData);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [loading] = useState(false);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [authEnabled, setAuthEnabled] = useState(initialEndpointData?.auth || false);
|
||||
const [selectedMethods, setSelectedMethods] = useState<string[]>(initialEndpointData?.methods || []);
|
||||
|
|
|
|||
|
|
@ -20,13 +20,11 @@ import {
|
|||
} from "@tremor/react";
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
import { Button as Button2, Form, Input, Modal, Select, Typography } from "antd";
|
||||
import { Button as Button2, Form, Input, Modal, Select } from "antd";
|
||||
import EmailSettings from "./email_settings";
|
||||
import { Logo } from "@/components/molecules/logo/Logo";
|
||||
import NotificationsManager from "./molecules/notifications_manager";
|
||||
|
||||
const { Title, Paragraph } = Typography;
|
||||
|
||||
import FormItem from "antd/es/form/FormItem";
|
||||
import AlertingSettings from "./alerting/alerting_settings";
|
||||
import CloudZeroCostTracking from "./CloudZeroCostTracking/CloudZeroCostTracking";
|
||||
|
|
@ -48,12 +46,6 @@ interface SettingsPageProps {
|
|||
premiumUser: boolean;
|
||||
}
|
||||
|
||||
interface genericCallbackParams {
|
||||
litellm_callback_name: string; // what to send in request
|
||||
ui_callback_name: string; // what to show on UI
|
||||
litellm_callback_params: string[] | null; // known required params for this callback
|
||||
}
|
||||
|
||||
const assetsLogoFolder = "/ui/assets/logos/";
|
||||
|
||||
export const backendCallbackLogoSrc = (logo: string | null | undefined): string | undefined => {
|
||||
|
|
@ -214,7 +206,6 @@ const Settings: React.FC<SettingsPageProps> = ({ accessToken, userRole, userID,
|
|||
const [callbacks, setCallbacks] = useState<AlertingObject[]>([]);
|
||||
const [isLoadingCallbacks, setIsLoadingCallbacks] = useState(true);
|
||||
const [alerts, setAlerts] = useState<any[]>([]);
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
const [addForm] = Form.useForm();
|
||||
const [editForm] = Form.useForm();
|
||||
const [selectedCallback, setSelectedCallback] = useState<string | null>(null);
|
||||
|
|
@ -418,119 +409,6 @@ const Settings: React.FC<SettingsPageProps> = ({ accessToken, userRole, userID,
|
|||
}
|
||||
NotificationsManager.success("Alerts updated successfully");
|
||||
};
|
||||
const handleSaveChanges = (callback: any) => {
|
||||
if (!accessToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedVariables = Object.fromEntries(
|
||||
Object.entries(callback.variables).map(([key, value]) => [
|
||||
key,
|
||||
(document.querySelector(`input[name="${key}"]`) as HTMLInputElement)?.value || value,
|
||||
]),
|
||||
);
|
||||
|
||||
const payload = {
|
||||
environment_variables: updatedVariables,
|
||||
litellm_settings: {
|
||||
success_callback: [callback.name],
|
||||
},
|
||||
};
|
||||
|
||||
try {
|
||||
setCallbacksCall(accessToken, payload);
|
||||
} catch (error) {
|
||||
NotificationsManager.fromBackend(error);
|
||||
}
|
||||
NotificationsManager.success("Callback updated successfully");
|
||||
};
|
||||
|
||||
const handleOk = () => {
|
||||
if (!accessToken) {
|
||||
return;
|
||||
}
|
||||
// Handle form submission
|
||||
addForm.validateFields().then((values) => {
|
||||
// Call API to add the callback
|
||||
let payload;
|
||||
if (values.callback === "langfuse" || values.callback === "langfuse_otel") {
|
||||
payload = {
|
||||
environment_variables: {
|
||||
LANGFUSE_PUBLIC_KEY: values.langfusePublicKey,
|
||||
LANGFUSE_SECRET_KEY: values.langfusePrivateKey,
|
||||
},
|
||||
litellm_settings: {
|
||||
success_callback: [values.callback],
|
||||
},
|
||||
};
|
||||
setCallbacksCall(accessToken, payload);
|
||||
let newCallback: AlertingObject = {
|
||||
name: values.callback,
|
||||
variables: {
|
||||
SLACK_WEBHOOK_URL: null,
|
||||
LANGFUSE_HOST: null,
|
||||
LANGFUSE_PUBLIC_KEY: values.langfusePublicKey,
|
||||
LANGFUSE_SECRET_KEY: values.langfusePrivateKey,
|
||||
OPENMETER_API_KEY: null,
|
||||
},
|
||||
};
|
||||
// add langfuse to callbacks
|
||||
setCallbacks(callbacks ? [...callbacks, newCallback] : [newCallback]);
|
||||
} else if (values.callback === "slack") {
|
||||
payload = {
|
||||
general_settings: {
|
||||
alerting: ["slack"],
|
||||
alerting_threshold: 300,
|
||||
},
|
||||
environment_variables: {
|
||||
SLACK_WEBHOOK_URL: values.slackWebhookUrl,
|
||||
},
|
||||
};
|
||||
setCallbacksCall(accessToken, payload);
|
||||
|
||||
let newCallback: AlertingObject = {
|
||||
name: values.callback,
|
||||
variables: {
|
||||
SLACK_WEBHOOK_URL: values.slackWebhookUrl,
|
||||
LANGFUSE_HOST: null,
|
||||
LANGFUSE_PUBLIC_KEY: null,
|
||||
LANGFUSE_SECRET_KEY: null,
|
||||
OPENMETER_API_KEY: null,
|
||||
},
|
||||
};
|
||||
setCallbacks(callbacks ? [...callbacks, newCallback] : [newCallback]);
|
||||
} else if (values.callback == "openmeter") {
|
||||
payload = {
|
||||
environment_variables: {
|
||||
OPENMETER_API_KEY: values.openMeterApiKey,
|
||||
},
|
||||
litellm_settings: {
|
||||
success_callback: [values.callback],
|
||||
},
|
||||
};
|
||||
setCallbacksCall(accessToken, payload);
|
||||
let newCallback: AlertingObject = {
|
||||
name: values.callback,
|
||||
variables: {
|
||||
SLACK_WEBHOOK_URL: null,
|
||||
LANGFUSE_HOST: null,
|
||||
LANGFUSE_PUBLIC_KEY: null,
|
||||
LANGFUSE_SECRET_KEY: null,
|
||||
OPENMETER_API_KEY: values.openMeterAPIKey,
|
||||
},
|
||||
};
|
||||
// add langfuse to callbacks
|
||||
setCallbacks(callbacks ? [...callbacks, newCallback] : [newCallback]);
|
||||
} else {
|
||||
payload = {
|
||||
error: "Invalid callback value",
|
||||
};
|
||||
}
|
||||
setIsModalVisible(false);
|
||||
addForm.resetFields();
|
||||
setSelectedCallback(null);
|
||||
});
|
||||
};
|
||||
|
||||
const handleDeleteCallback = (callback: any) => {
|
||||
setCallbackToDelete(callback);
|
||||
|
|
|
|||
|
|
@ -50,22 +50,6 @@ interface KeyEditViewProps {
|
|||
}
|
||||
|
||||
// Add this helper function
|
||||
const getAvailableModelsForKey = (keyData: KeyResponse, teams: any[] | null): string[] => {
|
||||
// If no teams data is available, return empty array
|
||||
if (!teams || !keyData.team_id) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Find the team that matches the key's team_id
|
||||
const keyTeam = teams.find((team) => team.team_id === keyData.team_id);
|
||||
|
||||
// If team found and has models, return those models
|
||||
if (keyTeam?.models) {
|
||||
return keyTeam.models;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
// Helper function to determine key_type display value from allowed_routes
|
||||
const getKeyTypeFromRoutes = (allowedRoutes: string[] | null | undefined): string => {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,9 @@
|
|||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
import { useProjects } from "@/app/(dashboard)/hooks/projects/useProjects";
|
||||
import useTeams from "@/app/(dashboard)/hooks/useTeams";
|
||||
import { renderWithProviders } from "../../../tests/test-utils";
|
||||
import { screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { useResetKeySpend } from "@/app/(dashboard)/hooks/keys/useResetKeySpend";
|
||||
import { KeyResponse, Team } from "../key_team_helpers/key_list";
|
||||
import { keyDeleteCall, keyUpdateCall } from "../networking";
|
||||
import { QueryClient } from "@tanstack/react-query";
|
||||
|
|
|
|||
|
|
@ -38,10 +38,6 @@ interface DistinctTagResponse {
|
|||
tag: string;
|
||||
}
|
||||
|
||||
interface DistinctTagsResponse {
|
||||
results: DistinctTagResponse[];
|
||||
}
|
||||
|
||||
interface UserAgentActivityProps {
|
||||
accessToken: string | null;
|
||||
userRole: string | null;
|
||||
|
|
@ -59,7 +55,7 @@ const UserAgentActivity: React.FC<UserAgentActivityProps> = ({ accessToken, user
|
|||
const [mauData, setMauData] = useState<ActiveUsersAnalyticsResponse>({ results: [] });
|
||||
const [summaryData, setSummaryData] = useState<TagSummaryResponse>({ results: [] });
|
||||
|
||||
const [userAgentFilter, setUserAgentFilter] = useState<string>("");
|
||||
const [userAgentFilter] = useState<string>("");
|
||||
|
||||
// Tag filtering state
|
||||
const [availableTags, setAvailableTags] = useState<string[]>([]);
|
||||
|
|
|
|||
|
|
@ -235,18 +235,6 @@ const DownloadIcon = () => (
|
|||
</svg>
|
||||
);
|
||||
|
||||
const ExternalLinkIcon = () => (
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" className="inline ml-1">
|
||||
<path
|
||||
d="M6 2H3a1 1 0 00-1 1v8a1 1 0 001 1h8a1 1 0 001-1V8M8 2h4m0 0v4m0-4L6.5 7.5"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
|
||||
// ── Sub-components ──────────────────────────────────────────────────────────
|
||||
|
||||
const MatchDetailsTable = ({ matchDetails }: { matchDetails: MatchDetail[] }) => {
|
||||
|
|
@ -647,10 +635,6 @@ const GuardrailViewer = ({ data, accessToken, logEntry }: GuardrailViewerProps)
|
|||
return Math.round(guardrailEntries.reduce((sum, e) => sum + (e.duration ?? 0), 0) * 1000);
|
||||
}, [guardrailEntries]);
|
||||
|
||||
const policyTemplates = useMemo(() => {
|
||||
return Array.from(new Set(guardrailEntries.map((e) => e.policy_template).filter(Boolean)));
|
||||
}, [guardrailEntries]);
|
||||
|
||||
if (guardrailEntries.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from "react";
|
||||
import { render, screen, fireEvent, act, waitFor } from "@testing-library/react";
|
||||
import { render, screen, waitFor } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { RealtimePrettyView, isRealtimeResponse } from "./RealtimePrettyView";
|
||||
|
|
|
|||
|
|
@ -5,11 +5,6 @@ import { formatNumberWithCommas } from "@/utils/dataUtils";
|
|||
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
|
||||
|
||||
// Define the props type
|
||||
interface UserSpendData {
|
||||
spend: number; // Adjust the type accordingly based on your data
|
||||
max_budget?: number | null; // Optional property with a default of null
|
||||
// Add other properties if needed
|
||||
}
|
||||
interface ViewUserSpendProps {
|
||||
userSpend: number | null;
|
||||
userMaxBudget: number | null;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue