mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-07 08:26:10 +00:00
Revert "Litellm dev 01 10 2025 p2 (#7679)"
This reverts commit c4780479a9.
This commit is contained in:
parent
8f7b9ae1af
commit
a609139dde
14 changed files with 67 additions and 285 deletions
|
|
@ -105,7 +105,7 @@ jobs:
|
|||
command: |
|
||||
pwd
|
||||
ls
|
||||
python -m pytest -vv tests/local_testing --cov=litellm --cov-report=xml -x --junitxml=test-results/junit.xml --durations=5 -k "not test_python_38.py and not test_basic_python_version.py and not router and not assistants and not langfuse and not caching and not cache" -n 4
|
||||
python -m pytest -vv tests/local_testing --cov=litellm --cov-report=xml -x --junitxml=test-results/junit.xml --durations=5 -k "not test_python_38.py and not router and not assistants and not langfuse and not caching and not cache" -n 4
|
||||
no_output_timeout: 120m
|
||||
- run:
|
||||
name: Rename the coverage files
|
||||
|
|
@ -895,7 +895,6 @@ jobs:
|
|||
pip install "pytest-retry==1.6.3"
|
||||
pip install "pytest-asyncio==0.21.1"
|
||||
pip install "pytest-cov==5.0.0"
|
||||
pip install "tomli==2.2.1"
|
||||
- run:
|
||||
name: Run tests
|
||||
command: |
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ poetry install -E extra_proxy -E proxy
|
|||
Step 3: Test your change:
|
||||
|
||||
```
|
||||
cd tests # pwd: Documents/litellm/litellm/tests
|
||||
cd litellm/tests # pwd: Documents/litellm/litellm/tests
|
||||
poetry run flake8
|
||||
poetry run pytest .
|
||||
```
|
||||
|
|
|
|||
BIN
dist/litellm-1.57.6.tar.gz
vendored
BIN
dist/litellm-1.57.6.tar.gz
vendored
Binary file not shown.
|
|
@ -72,20 +72,6 @@ general_settings:
|
|||
prefix_for_stored_virtual_keys: "litellm/" # OPTIONAL. If set, this prefix will be used for stored virtual keys in the secret manager
|
||||
access_mode: "write_only" # Literal["read_only", "write_only", "read_and_write"]
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="read_and_write" label="Read + Write Keys with AWS Secret Manager">
|
||||
|
||||
```yaml
|
||||
general_settings:
|
||||
master_key: os.environ/litellm_master_key
|
||||
key_management_system: "aws_secret_manager" # 👈 KEY CHANGE
|
||||
key_management_settings:
|
||||
store_virtual_keys: true # OPTIONAL. Defaults to False, when True will store virtual keys in secret manager
|
||||
prefix_for_stored_virtual_keys: "litellm/" # OPTIONAL. If set, this prefix will be used for stored virtual keys in the secret manager
|
||||
access_mode: "read_and_write" # Literal["read_only", "write_only", "read_and_write"]
|
||||
hosted_keys: ["litellm_master_key"] # OPTIONAL. Specify which env keys you stored on AWS
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
|
|
@ -200,6 +186,34 @@ LiteLLM stores secret under the `prefix_for_stored_virtual_keys` path (default:
|
|||
|
||||
|
||||
## Azure Key Vault
|
||||
<!--
|
||||
### Quick Start
|
||||
|
||||
```python
|
||||
### Instantiate Azure Key Vault Client ###
|
||||
from azure.keyvault.secrets import SecretClient
|
||||
from azure.identity import ClientSecretCredential
|
||||
|
||||
# Set your Azure Key Vault URI
|
||||
KVUri = os.getenv("AZURE_KEY_VAULT_URI")
|
||||
|
||||
# Set your Azure AD application/client ID, client secret, and tenant ID - create an application with permission to call your key vault
|
||||
client_id = os.getenv("AZURE_CLIENT_ID")
|
||||
client_secret = os.getenv("AZURE_CLIENT_SECRET")
|
||||
tenant_id = os.getenv("AZURE_TENANT_ID")
|
||||
|
||||
# Initialize the ClientSecretCredential
|
||||
credential = ClientSecretCredential(client_id=client_id, client_secret=client_secret, tenant_id=tenant_id)
|
||||
|
||||
# Create the SecretClient using the credential
|
||||
client = SecretClient(vault_url=KVUri, credential=credential)
|
||||
|
||||
### Connect to LiteLLM ###
|
||||
import litellm
|
||||
litellm.secret_manager = client
|
||||
|
||||
litellm.get_secret("your-test-key")
|
||||
``` -->
|
||||
|
||||
#### Usage with LiteLLM Proxy Server
|
||||
|
||||
|
|
|
|||
1
litellm/proxy/_experimental/out/404.html
Normal file
1
litellm/proxy/_experimental/out/404.html
Normal file
File diff suppressed because one or more lines are too long
1
litellm/proxy/_experimental/out/model_hub.html
Normal file
1
litellm/proxy/_experimental/out/model_hub.html
Normal file
File diff suppressed because one or more lines are too long
1
litellm/proxy/_experimental/out/onboarding.html
Normal file
1
litellm/proxy/_experimental/out/onboarding.html
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -2097,13 +2097,12 @@ class TeamMemberDeleteRequest(MemberDeleteRequest):
|
|||
|
||||
|
||||
class TeamMemberUpdateRequest(TeamMemberDeleteRequest):
|
||||
max_budget_in_team: Optional[float] = None
|
||||
role: Optional[Literal["admin", "user"]] = None
|
||||
max_budget_in_team: float
|
||||
|
||||
|
||||
class TeamMemberUpdateResponse(MemberUpdateResponse):
|
||||
team_id: str
|
||||
max_budget_in_team: Optional[float] = None
|
||||
max_budget_in_team: float
|
||||
|
||||
|
||||
# Organization Member Requests
|
||||
|
|
|
|||
|
|
@ -920,7 +920,7 @@ async def team_member_update(
|
|||
"""
|
||||
[BETA]
|
||||
|
||||
Update team member budgets and team member role
|
||||
Update team member budgets
|
||||
"""
|
||||
from litellm.proxy.proxy_server import prisma_client
|
||||
|
||||
|
|
@ -970,8 +970,6 @@ async def team_member_update(
|
|||
user_api_key_dict=user_api_key_dict,
|
||||
)
|
||||
|
||||
team_table = returned_team_info["team_info"]
|
||||
|
||||
## get user id
|
||||
received_user_id: Optional[str] = None
|
||||
if data.user_id is not None:
|
||||
|
|
@ -997,50 +995,26 @@ async def team_member_update(
|
|||
break
|
||||
|
||||
### upsert new budget
|
||||
if data.max_budget_in_team is not None:
|
||||
if identified_budget_id is None:
|
||||
new_budget = await prisma_client.db.litellm_budgettable.create(
|
||||
data={
|
||||
"max_budget": data.max_budget_in_team,
|
||||
"created_by": user_api_key_dict.user_id or "",
|
||||
"updated_by": user_api_key_dict.user_id or "",
|
||||
}
|
||||
)
|
||||
if identified_budget_id is None:
|
||||
new_budget = await prisma_client.db.litellm_budgettable.create(
|
||||
data={
|
||||
"max_budget": data.max_budget_in_team,
|
||||
"created_by": user_api_key_dict.user_id or "",
|
||||
"updated_by": user_api_key_dict.user_id or "",
|
||||
}
|
||||
)
|
||||
|
||||
await prisma_client.db.litellm_teammembership.create(
|
||||
data={
|
||||
"team_id": data.team_id,
|
||||
"user_id": received_user_id,
|
||||
"budget_id": new_budget.budget_id,
|
||||
},
|
||||
)
|
||||
elif identified_budget_id is not None:
|
||||
await prisma_client.db.litellm_budgettable.update(
|
||||
where={"budget_id": identified_budget_id},
|
||||
data={"max_budget": data.max_budget_in_team},
|
||||
)
|
||||
|
||||
### update team member role
|
||||
if data.role is not None:
|
||||
team_members: List[Member] = []
|
||||
for member in team_table.members_with_roles:
|
||||
if member.user_id == received_user_id:
|
||||
team_members.append(
|
||||
Member(
|
||||
user_id=member.user_id,
|
||||
role=data.role,
|
||||
user_email=data.user_email or member.user_email,
|
||||
)
|
||||
)
|
||||
else:
|
||||
team_members.append(member)
|
||||
|
||||
team_table.members_with_roles = team_members
|
||||
|
||||
_db_team_members: List[dict] = [m.model_dump() for m in team_members]
|
||||
await prisma_client.db.litellm_teamtable.update(
|
||||
where={"team_id": data.team_id},
|
||||
data={"members_with_roles": json.dumps(_db_team_members)}, # type: ignore
|
||||
await prisma_client.db.litellm_teammembership.create(
|
||||
data={
|
||||
"team_id": data.team_id,
|
||||
"user_id": received_user_id,
|
||||
"budget_id": new_budget.budget_id,
|
||||
},
|
||||
)
|
||||
else:
|
||||
await prisma_client.db.litellm_budgettable.update(
|
||||
where={"budget_id": identified_budget_id},
|
||||
data={"max_budget": data.max_budget_in_team},
|
||||
)
|
||||
|
||||
return TeamMemberUpdateResponse(
|
||||
|
|
|
|||
|
|
@ -37,51 +37,6 @@ def test_litellm_proxy_server():
|
|||
assert True
|
||||
|
||||
|
||||
def test_package_dependencies():
|
||||
try:
|
||||
import tomli
|
||||
import pathlib
|
||||
import litellm
|
||||
|
||||
# Get the litellm package root path
|
||||
litellm_path = pathlib.Path(litellm.__file__).parent.parent
|
||||
pyproject_path = litellm_path / "pyproject.toml"
|
||||
|
||||
# Read and parse pyproject.toml
|
||||
with open(pyproject_path, "rb") as f:
|
||||
pyproject = tomli.load(f)
|
||||
|
||||
# Get all optional dependencies from poetry.dependencies
|
||||
poetry_deps = pyproject["tool"]["poetry"]["dependencies"]
|
||||
optional_deps = {
|
||||
name.lower()
|
||||
for name, value in poetry_deps.items()
|
||||
if isinstance(value, dict) and value.get("optional", False)
|
||||
}
|
||||
print(optional_deps)
|
||||
# Get all packages listed in extras
|
||||
extras = pyproject["tool"]["poetry"]["extras"]
|
||||
all_extra_deps = set()
|
||||
for extra_group in extras.values():
|
||||
all_extra_deps.update(dep.lower() for dep in extra_group)
|
||||
print(all_extra_deps)
|
||||
# Check that all optional dependencies are in some extras group
|
||||
missing_from_extras = optional_deps - all_extra_deps
|
||||
assert (
|
||||
not missing_from_extras
|
||||
), f"Optional dependencies missing from extras: {missing_from_extras}"
|
||||
|
||||
print(
|
||||
f"All {len(optional_deps)} optional dependencies are correctly specified in extras"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
pytest.fail(
|
||||
f"Error occurred while checking dependencies: {str(e)}\n"
|
||||
+ traceback.format_exc()
|
||||
)
|
||||
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import time
|
||||
|
|
|
|||
|
|
@ -2321,47 +2321,6 @@ export const teamMemberAddCall = async (
|
|||
}
|
||||
};
|
||||
|
||||
export const teamMemberUpdateCall = async (
|
||||
accessToken: string,
|
||||
teamId: string,
|
||||
formValues: Member // Assuming formValues is an object
|
||||
) => {
|
||||
try {
|
||||
console.log("Form Values in teamMemberAddCall:", formValues); // Log the form values before making the API call
|
||||
|
||||
const url = proxyBaseUrl
|
||||
? `${proxyBaseUrl}/team/member_update`
|
||||
: `/team/member_update`;
|
||||
const response = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
[globalLitellmHeaderName]: `Bearer ${accessToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
team_id: teamId,
|
||||
role: formValues.role,
|
||||
user_id: formValues.user_id,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.text();
|
||||
handleError(errorData);
|
||||
console.error("Error response from the server:", errorData);
|
||||
throw new Error("Network response was not ok");
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log("API Response:", data);
|
||||
return data;
|
||||
// Handle success - you might want to update some state or UI based on the created key
|
||||
} catch (error) {
|
||||
console.error("Failed to create key:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const organizationMemberAddCall = async (
|
||||
accessToken: string,
|
||||
organizationId: string,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import React, { useState, useEffect } from "react";
|
|||
import Link from "next/link";
|
||||
import { Typography } from "antd";
|
||||
import { teamDeleteCall, teamUpdateCall, teamInfoCall } from "./networking";
|
||||
import TeamMemberModal, { TeamMember } from "@/components/team/edit_membership";
|
||||
import {
|
||||
InformationCircleIcon,
|
||||
PencilAltIcon,
|
||||
|
|
@ -66,12 +65,12 @@ interface EditTeamModalProps {
|
|||
import {
|
||||
teamCreateCall,
|
||||
teamMemberAddCall,
|
||||
teamMemberUpdateCall,
|
||||
Member,
|
||||
modelAvailableCall,
|
||||
teamListCall
|
||||
} from "./networking";
|
||||
|
||||
|
||||
const Team: React.FC<TeamProps> = ({
|
||||
teams,
|
||||
searchParams,
|
||||
|
|
@ -113,12 +112,11 @@ const Team: React.FC<TeamProps> = ({
|
|||
|
||||
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<string | null>(null);
|
||||
const [selectedEditMember, setSelectedEditMember] = useState<null | TeamMember>(null);
|
||||
|
||||
// store team info as {"team_id": team_info_object}
|
||||
const [perTeamInfo, setPerTeamInfo] = useState<Record<string, any>>({});
|
||||
|
||||
const EditTeamModal: React.FC<EditTeamModalProps> = ({
|
||||
|
|
@ -259,19 +257,16 @@ const Team: React.FC<TeamProps> = ({
|
|||
|
||||
const handleMemberOk = () => {
|
||||
setIsAddMemberModalVisible(false);
|
||||
setIsEditMemberModalVisible(false);
|
||||
memberForm.resetFields();
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
setIsTeamModalVisible(false);
|
||||
|
||||
form.resetFields();
|
||||
};
|
||||
|
||||
const handleMemberCancel = () => {
|
||||
setIsAddMemberModalVisible(false);
|
||||
setIsEditMemberModalVisible(false);
|
||||
memberForm.resetFields();
|
||||
};
|
||||
|
||||
|
|
@ -417,7 +412,7 @@ const Team: React.FC<TeamProps> = ({
|
|||
return false;
|
||||
}
|
||||
|
||||
const _common_member_update_call = async (formValues: Record<string, any>, callType: "add" | "edit") => {
|
||||
const handleMemberCreate = async (formValues: Record<string, any>) => {
|
||||
try {
|
||||
if (accessToken != null && teams != null) {
|
||||
message.info("Adding Member");
|
||||
|
|
@ -426,27 +421,13 @@ const Team: React.FC<TeamProps> = ({
|
|||
user_email: formValues.user_email,
|
||||
user_id: formValues.user_id,
|
||||
};
|
||||
let response: any;
|
||||
if (callType == "add") {
|
||||
response = await teamMemberAddCall(
|
||||
accessToken,
|
||||
selectedTeam["team_id"],
|
||||
user_role
|
||||
);
|
||||
message.success("Member added");
|
||||
} else {
|
||||
response = await teamMemberUpdateCall(
|
||||
accessToken,
|
||||
selectedTeam["team_id"],
|
||||
{
|
||||
"role": formValues.role,
|
||||
"user_id": formValues.id,
|
||||
"user_email": formValues.email
|
||||
}
|
||||
);
|
||||
message.success("Member updated");
|
||||
}
|
||||
|
||||
const response: any = await teamMemberAddCall(
|
||||
accessToken,
|
||||
selectedTeam["team_id"],
|
||||
user_role
|
||||
);
|
||||
message.success("Member added");
|
||||
console.log(`response for team create call: ${response["data"]}`);
|
||||
// Checking if the team exists in the list and updating or adding accordingly
|
||||
const foundIndex = teams.findIndex((team) => {
|
||||
console.log(
|
||||
|
|
@ -468,15 +449,7 @@ const Team: React.FC<TeamProps> = ({
|
|||
} catch (error) {
|
||||
console.error("Error creating the team:", error);
|
||||
}
|
||||
}
|
||||
|
||||
const handleMemberCreate = async (formValues: Record<string, any>) => {
|
||||
_common_member_update_call(formValues, "add");
|
||||
};
|
||||
|
||||
const handleMemberUpdate = async (formValues: Record<string, any>) => {
|
||||
_common_member_update_call(formValues, "edit");
|
||||
}
|
||||
return (
|
||||
<div className="w-full mx-4">
|
||||
<Grid numItems={1} className="gap-2 p-8 h-[75vh] w-full mt-2">
|
||||
|
|
@ -858,29 +831,6 @@ const Team: React.FC<TeamProps> = ({
|
|||
: null}
|
||||
</TableCell>
|
||||
<TableCell>{member["role"]}</TableCell>
|
||||
<TableCell>
|
||||
{userRole == "Admin" ? (
|
||||
<>
|
||||
<Icon
|
||||
icon={PencilAltIcon}
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setIsEditMemberModalVisible(true);
|
||||
setSelectedEditMember({
|
||||
"id": member["user_id"],
|
||||
"email": member["user_email"],
|
||||
"role": member["role"]
|
||||
})
|
||||
}}
|
||||
/>
|
||||
<Icon
|
||||
onClick={() => {}}
|
||||
icon={TrashIcon}
|
||||
size="sm"
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)
|
||||
)
|
||||
|
|
@ -888,13 +838,6 @@ const Team: React.FC<TeamProps> = ({
|
|||
</TableBody>
|
||||
</Table>
|
||||
</Card>
|
||||
<TeamMemberModal
|
||||
visible={isEditMemberModalVisible}
|
||||
onCancel={handleMemberCancel}
|
||||
onSubmit={handleMemberUpdate}
|
||||
initialData={selectedEditMember}
|
||||
mode="edit"
|
||||
/>
|
||||
{selectedTeam && (
|
||||
<EditTeamModal
|
||||
visible={editModalVisible}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
modelAvailableCall,
|
||||
getTotalSpendCall,
|
||||
getProxyUISettings,
|
||||
teamListCall,
|
||||
} from "./networking";
|
||||
import { Grid, Col, Card, Text, Title } from "@tremor/react";
|
||||
import CreateKey from "./create_key_button";
|
||||
|
|
@ -173,18 +172,6 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
|||
if (cachedUserModels) {
|
||||
setUserModels(JSON.parse(cachedUserModels));
|
||||
} else {
|
||||
const fetchTeams = async () => {
|
||||
let givenTeams;
|
||||
if (userRole != "Admin" && userRole != "Admin Viewer") {
|
||||
givenTeams = await teamListCall(accessToken, userID)
|
||||
} else {
|
||||
givenTeams = await teamListCall(accessToken)
|
||||
}
|
||||
|
||||
console.log(`givenTeams: ${givenTeams}`)
|
||||
|
||||
setTeams(givenTeams)
|
||||
}
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const proxy_settings: ProxySettings = await getProxyUISettings(accessToken);
|
||||
|
|
@ -207,6 +194,7 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
|||
setUserSpendData(response["user_info"]);
|
||||
console.log(`userSpendData: ${JSON.stringify(userSpendData)}`)
|
||||
setKeys(response["keys"]); // Assuming this is the correct path to your data
|
||||
setTeams(response["teams"]);
|
||||
const teamsArray = [...response["teams"]];
|
||||
if (teamsArray.length > 0) {
|
||||
console.log(`response['teams']: ${teamsArray}`);
|
||||
|
|
@ -247,7 +235,6 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
|||
}
|
||||
};
|
||||
fetchData();
|
||||
fetchTeams();
|
||||
}
|
||||
}
|
||||
}, [userID, token, accessToken, keys, userRole]);
|
||||
|
|
|
|||
|
|
@ -131,57 +131,6 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
|||
|
||||
const [knownTeamIDs, setKnownTeamIDs] = useState(initialKnownTeamIDs);
|
||||
|
||||
// Function to check if user is admin of a team
|
||||
const isUserTeamAdmin = (team: any) => {
|
||||
if (!team.members_with_roles) return false;
|
||||
return team.members_with_roles.some(
|
||||
(member: any) => member.role === "admin" && member.user_id === userID
|
||||
);
|
||||
};
|
||||
|
||||
// Combine all keys that user should have access to
|
||||
const all_keys_to_display = React.useMemo(() => {
|
||||
let allKeys: any[] = [];
|
||||
|
||||
// If no teams, return personal keys
|
||||
if (!teams || teams.length === 0) {
|
||||
return data;
|
||||
}
|
||||
|
||||
teams.forEach(team => {
|
||||
// For default team or when user is not admin, use personal keys (data)
|
||||
if (team.team_id === "default-team" || !isUserTeamAdmin(team)) {
|
||||
if (selectedTeam && selectedTeam.team_id === team.team_id && data) {
|
||||
allKeys = [...allKeys, ...data.filter(key => key.team_id === team.team_id)];
|
||||
}
|
||||
}
|
||||
// For teams where user is admin, use team keys
|
||||
else if (isUserTeamAdmin(team)) {
|
||||
if (selectedTeam && selectedTeam.team_id === team.team_id) {
|
||||
allKeys = [...allKeys, ...(team.keys || [])];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// If no team is selected, show all accessible keys
|
||||
if (!selectedTeam && data) {
|
||||
const personalKeys = data.filter(key => !key.team_id || key.team_id === "default-team");
|
||||
const adminTeamKeys = teams
|
||||
.filter(team => isUserTeamAdmin(team))
|
||||
.flatMap(team => team.keys || []);
|
||||
allKeys = [...personalKeys, ...adminTeamKeys];
|
||||
}
|
||||
|
||||
// Filter out litellm-dashboard keys
|
||||
allKeys = allKeys.filter(key => key.team_id !== "litellm-dashboard");
|
||||
|
||||
// Remove duplicates based on token
|
||||
const uniqueKeys = Array.from(
|
||||
new Map(allKeys.map(key => [key.token, key])).values()
|
||||
);
|
||||
|
||||
return uniqueKeys;
|
||||
}, [data, teams, selectedTeam, userID]);
|
||||
|
||||
useEffect(() => {
|
||||
const calculateNewExpiryTime = (duration: string | undefined) => {
|
||||
|
|
@ -909,7 +858,7 @@ const ViewKeyTable: React.FC<ViewKeyTableProps> = ({
|
|||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{all_keys_to_display && all_keys_to_display.map((item) => {
|
||||
{data.map((item) => {
|
||||
console.log(item);
|
||||
// skip item if item.team_id == "litellm-dashboard"
|
||||
if (item.team_id === "litellm-dashboard") {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue