"use client"; import React, { useState, useEffect, useRef } from "react"; import { Button, TextInput, Grid, Col } from "@tremor/react"; import { Card, Metric, Text, Title, Subtitle, Accordion, AccordionHeader, AccordionBody, } from "@tremor/react"; import { CopyToClipboard } from "react-copy-to-clipboard"; import { Button as Button2, Modal, Form, Input, InputNumber, Select, message, Radio, } from "antd"; import { unfurlWildcardModelsInList, getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key"; import { keyCreateCall, slackBudgetAlertsHealthCheck, modelAvailableCall, getGuardrailsList, } from "./networking"; import { InfoCircleOutlined } from '@ant-design/icons'; import { Tooltip } from 'antd'; const { Option } = Select; interface CreateKeyProps { userID: string; team: any | null; userRole: string | null; accessToken: string; data: any[] | null; setData: React.Dispatch>; } const getPredefinedTags = (data: any[] | null) => { let allTags = []; console.log("data:", JSON.stringify(data)); 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, })); console.log("uniqueTags:", uniqueTags); return uniqueTags; } const CreateKey: React.FC = ({ userID, team, userRole, accessToken, data, setData, }) => { 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"); const [predefinedTags, setPredefinedTags] = useState(getPredefinedTags(data)); const [guardrailsList, setGuardrailsList] = useState([]); const handleOk = () => { setIsModalVisible(false); form.resetFields(); }; const handleCancel = () => { setIsModalVisible(false); setApiKey(null); form.resetFields(); }; useEffect(() => { const fetchUserModels = async () => { try { if (userID === null || userRole === null) { return; } if (accessToken !== null) { const model_available = await modelAvailableCall( accessToken, userID, userRole ); let available_model_names = model_available["data"].map( (element: { id: string }) => element.id ); console.log("available_model_names:", available_model_names); setUserModels(available_model_names); } } catch (error) { console.error("Error fetching user models:", error); } }; fetchUserModels(); }, [accessToken, userID, userRole]); useEffect(() => { const fetchGuardrails = async () => { try { const response = await getGuardrailsList(accessToken); const guardrailNames = response.guardrails.map( (g: { guardrail_name: string }) => g.guardrail_name ); setGuardrailsList(guardrailNames); } catch (error) { console.error("Failed to fetch guardrails:", error); } }; fetchGuardrails(); }, [accessToken]); const handleCreate = async (formValues: Record) => { try { const newKeyAlias = formValues?.key_alias ?? ""; const newKeyTeamId = formValues?.team_id ?? null; const existingKeyAliases = data ?.filter((k) => k.team_id === newKeyTeamId) .map((k) => k.key_alias) ?? []; if (existingKeyAliases.includes(newKeyAlias)) { throw new Error( `Key alias ${newKeyAlias} already exists for team with ID ${newKeyTeamId}, please provide another key alias` ); } message.info("Making API Call"); setIsModalVisible(true); // If it's a service account, add the service_account_id to the metadata if (keyOwner === "service_account") { // Parse existing metadata or create an empty object let metadata: Record = {}; try { metadata = JSON.parse(formValues.metadata || "{}"); } catch (error) { console.error("Error parsing metadata:", error); } metadata["service_account_id"] = formValues.key_alias; // Update the formValues with the new metadata formValues.metadata = JSON.stringify(metadata); } const response = await keyCreateCall(accessToken, userID, formValues); console.log("key create Response:", response); setData((prevData) => (prevData ? [...prevData, response] : [response])); // Check if prevData is null setApiKey(response["key"]); setSoftBudget(response["soft_budget"]); message.success("API Key Created"); form.resetFields(); localStorage.removeItem("userData" + userID); } catch (error) { console.log("error in create key:", error); message.error(`Error creating the key: ${error}`); } }; const handleCopy = () => { message.success("API Key copied to clipboard"); }; useEffect(() => { let tempModelsToPick = []; if (team) { if (team.models.length > 0) { if (team.models.includes("all-proxy-models")) { // if the team has all-proxy-models show all available models tempModelsToPick = userModels; } else { // show team models tempModelsToPick = team.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; } tempModelsToPick = unfurlWildcardModelsInList(tempModelsToPick, userModels); setModelsToPick(tempModelsToPick); }, [team, userModels]); return (
<> setKeyOwner(e.target.value)} value={keyOwner} > You Service Account {userRole === "Admin" && Another User} Optional Settings { if ( value && team && team.max_budget !== null && value > team.max_budget ) { throw new Error( `Budget cannot exceed team max budget: $${team.max_budget}` ); } }, }, ]} > { if ( value && team && team.tpm_limit !== null && value > team.tpm_limit ) { throw new Error( `TPM limit cannot exceed team TPM limit: ${team.tpm_limit}` ); } }, }, ]} > { if ( value && team && team.rpm_limit !== null && value > team.rpm_limit ) { throw new Error( `RPM limit cannot exceed team RPM limit: ${team.rpm_limit}` ); } }, }, ]} > Guardrails{' '} e.stopPropagation()} // Prevent accordion from collapsing when clicking link > } name="guardrails" className="mt-8" help="Select existing guardrails or enter new ones" >
Create Key
{apiKey && ( Save your Key

Please save this secret key somewhere safe and accessible. For security reasons, you will not be able to view it again{" "} through your LiteLLM account. If you lose this secret key, you will need to generate a new one.

{apiKey != null ? (
API Key:
                      {apiKey}
                    
{/* */}
) : ( Key being created, this might take 30s )}
)}
); }; export default CreateKey;