From e406ebf0dd3f30cdf678087be50b7aed45f9f1a0 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Wed, 21 Jan 2026 18:14:45 -0800 Subject: [PATCH] Model Select for Create Team --- .../app/(dashboard)/hooks/models/useModels.ts | 2 +- .../components/modals/CreateTeamModal.tsx | 2 +- .../components/ModelSelect/ModelSelect.tsx | 92 ++++++++++--------- .../src/components/OldTeams.tsx | 32 ++++--- .../src/components/networking.tsx | 4 + 5 files changed, 70 insertions(+), 62 deletions(-) diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts index b9f67c1cac8..1dbd79eacf9 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts @@ -56,7 +56,7 @@ export const useAllProxyModels = () => { const { accessToken, userId, userRole } = useAuthorized(); return useQuery({ queryKey: allProxyModelsKeys.list({}), - queryFn: async () => await modelAvailableCall(accessToken!, userId!, userRole!, true), + queryFn: async () => await modelAvailableCall(accessToken!, userId!, userRole!, true, null, true, false, "expand"), enabled: Boolean(accessToken && userId && userRole), }); }; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/CreateTeamModal.tsx b/ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/CreateTeamModal.tsx index df6d8d3ea81..972c39d49d8 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/CreateTeamModal.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/teams/components/modals/CreateTeamModal.tsx @@ -526,7 +526,7 @@ const CreateTeamModal = ({ valuePropName="checked" help="Bypass global guardrails for this team" > - diff --git a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx index a3ddeff3221..b3881350448 100644 --- a/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx +++ b/ui/litellm-dashboard/src/components/ModelSelect/ModelSelect.tsx @@ -53,14 +53,13 @@ const contextFilters: Record { if (selectedOrganization) { - if (selectedOrganization.models.includes(MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value)) { + if (selectedOrganization.models.includes(MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value) || selectedOrganization.models.length === 0) { return allProxyModels; } - // Return organization's models (filtered from allProxyModels) return allProxyModels.filter((model) => selectedOrganization.models.includes(model)); } - return userModels ?? []; + return allProxyModels ?? []; }, organization: ({ allProxyModels, selectedOrganization, options }) => { @@ -102,9 +101,12 @@ export const ModelSelect = (props: ModelSelectProps) => { const isSpecialOption = (value: string) => MODEL_SELECT_SPECIAL_VALUES_ARRAY.some((sv) => sv.value === value); const hasSpecialOptionSelected = value.some(isSpecialOption); const isLoading = isLoadingAllProxyModels || isLoadingTeam || isLoadingOrganization || isCurrentUserLoading; + const organizationHasAllProxyModels = organization?.models.includes(MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value) || organization?.models.length === 0; + console.log("organization:", organization); + console.log("organizationHasAllProxyModels:", organizationHasAllProxyModels); const shouldShowAllProxyModels = showAllProxyModelsOverride || - (organization?.models.includes(MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value) && includeSpecialOptions); + (organizationHasAllProxyModels && includeSpecialOptions); if (isLoading) { return ; @@ -143,51 +145,51 @@ export const ModelSelect = (props: ModelSelectProps) => { options={[ includeSpecialOptions ? { - label: Special Options, - title: "Special Options", - options: [ - ...(shouldShowAllProxyModels - ? [ - { - label: All Proxy Models, - value: MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value, - disabled: - value.length > 0 && - value.some( - (v) => isSpecialOption(v) && v !== MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value, - ), - key: MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value, - }, - ] - : []), - { - label: No Default Models, - value: MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value, - disabled: - value.length > 0 && - value.some((v) => isSpecialOption(v) && v !== MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value), - key: MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value, - }, - ], - } + label: Special Options, + title: "Special Options", + options: [ + ...(shouldShowAllProxyModels + ? [ + { + label: All Proxy Models, + value: MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value, + disabled: + value.length > 0 && + value.some( + (v) => isSpecialOption(v) && v !== MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value, + ), + key: MODEL_SELECT_ALL_PROXY_MODELS_SPECIAL_VALUE.value, + }, + ] + : []), + { + label: No Default Models, + value: MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value, + disabled: + value.length > 0 && + value.some((v) => isSpecialOption(v) && v !== MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value), + key: MODEL_SELECT_NO_DEFAULT_MODELS_SPECIAL_VALUE.value, + }, + ], + } : [], ...(wildcard.length > 0 ? [ - { - label: Wildcard Options, - title: "Wildcard Options", - options: wildcard.map((model) => { - const provider = model.replace("/*", ""); - const capitalizedProvider = provider.charAt(0).toUpperCase() + provider.slice(1); + { + label: Wildcard Options, + title: "Wildcard Options", + options: wildcard.map((model) => { + const provider = model.replace("/*", ""); + const capitalizedProvider = provider.charAt(0).toUpperCase() + provider.slice(1); - return { - label: {`All ${capitalizedProvider} models`}, - value: model, - disabled: hasSpecialOptionSelected, - }; - }), - }, - ] + return { + label: {`All ${capitalizedProvider} models`}, + value: model, + disabled: hasSpecialOptionSelected, + }; + }), + }, + ] : []), { label: Models, diff --git a/ui/litellm-dashboard/src/components/OldTeams.tsx b/ui/litellm-dashboard/src/components/OldTeams.tsx index 5679788d30d..1202cc91697 100644 --- a/ui/litellm-dashboard/src/components/OldTeams.tsx +++ b/ui/litellm-dashboard/src/components/OldTeams.tsx @@ -85,6 +85,7 @@ import { updateExistingKeys } from "@/utils/dataUtils"; import DeleteResourceModal from "./common_components/DeleteResourceModal"; import TableIconActionButton from "./common_components/IconActionButton/TableIconActionButtons/TableIconActionButton"; import { Member, teamCreateCall, v2TeamListCall } from "./networking"; +import { ModelSelect } from "./ModelSelect/ModelSelect"; interface TeamInfo { members_with_roles: Member[]; @@ -1064,11 +1065,11 @@ const Teams: React.FC = ({ rules={ isOrgAdmin ? [ - { - required: true, - message: "Please select an organization", - }, - ] + { + required: true, + message: "Please select an organization", + }, + ] : [] } help={ @@ -1135,16 +1136,17 @@ const Teams: React.FC = ({ ]} name="models" > - - - No Default Models - - {modelsToPick.map((model) => ( - - {getModelDisplayName(model)} - - ))} - + form.setFieldValue("models", values)} + organizationID={form.getFieldValue("organization_id")} + options={{ + includeSpecialOptions: true, + showAllProxyModelsOverride: !form.getFieldValue("organization_id"), + }} + context="team" + dataTestId="create-team-models-select" + /> diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 46561bc9e1e..a4f2dfce3bd 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -2457,6 +2457,7 @@ export const modelAvailableCall = async ( teamID: string | null = null, include_model_access_groups: boolean = false, only_model_access_groups: boolean = false, + scope?: string ) => { /** * Get all the models user has access to @@ -2475,6 +2476,9 @@ export const modelAvailableCall = async ( if (teamID) { params.append("team_id", teamID.toString()); } + if (scope) { + params.append("scope", scope); + } if (params.toString()) { url += `?${params.toString()}`; }