From a14c5b50a8841d774b25a4b68c1668b2cd419b57 Mon Sep 17 00:00:00 2001 From: Marco Beretta <81851188+berry-13@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:03:03 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9A=99=EF=B8=8F=20feat:=20add=20conditional?= =?UTF-8?q?=20visibility=20for=20model=20selector=20based=20on=20startup?= =?UTF-8?q?=20config=20(#10729)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Chat/Menus/Endpoints/ModelSelector.tsx | 13 ++++++++-- client/src/hooks/useNewConvo.ts | 24 ++++++++++++++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/client/src/components/Chat/Menus/Endpoints/ModelSelector.tsx b/client/src/components/Chat/Menus/Endpoints/ModelSelector.tsx index a6a6664d41..bee5a38ad4 100644 --- a/client/src/components/Chat/Menus/Endpoints/ModelSelector.tsx +++ b/client/src/components/Chat/Menus/Endpoints/ModelSelector.tsx @@ -1,14 +1,15 @@ import React, { useMemo } from 'react'; import { TooltipAnchor } from '@librechat/client'; +import { getConfigDefaults } from 'librechat-data-provider'; import type { ModelSelectorProps } from '~/common'; -import { ModelSelectorProvider, useModelSelectorContext } from './ModelSelectorContext'; -import { ModelSelectorChatProvider } from './ModelSelectorChatContext'; import { renderModelSpecs, renderEndpoints, renderSearchResults, renderCustomGroups, } from './components'; +import { ModelSelectorProvider, useModelSelectorContext } from './ModelSelectorContext'; +import { ModelSelectorChatProvider } from './ModelSelectorChatContext'; import { getSelectedIcon, getDisplayValue } from './utils'; import { CustomMenu as Menu } from './CustomMenu'; import DialogManager from './DialogManager'; @@ -122,6 +123,14 @@ function ModelSelectorContent() { } export default function ModelSelector({ startupConfig }: ModelSelectorProps) { + const interfaceConfig = startupConfig?.interface ?? getConfigDefaults().interface; + const modelSpecs = startupConfig?.modelSpecs?.list ?? []; + + // Hide the selector when modelSelect is false and there are no model specs to show + if (interfaceConfig.modelSelect === false && modelSpecs.length === 0) { + return null; + } + return ( diff --git a/client/src/hooks/useNewConvo.ts b/client/src/hooks/useNewConvo.ts index 33e26011f1..e6945fe6bc 100644 --- a/client/src/hooks/useNewConvo.ts +++ b/client/src/hooks/useNewConvo.ts @@ -10,6 +10,9 @@ import { getEndpointField, LocalStorageKeys, isAssistantsEndpoint, + isAgentsEndpoint, + PermissionTypes, + Permissions, } from 'librechat-data-provider'; import type { TPreset, @@ -32,6 +35,7 @@ import useAssistantListMap from './Assistants/useAssistantListMap'; import { useResetChatBadges } from './useChatBadges'; import { useApplyModelSpecEffects } from './Agents'; import { usePauseGlobalAudio } from './Audio'; +import { useHasAccess } from '~/hooks'; import store from '~/store'; const useNewConvo = (index = 0) => { @@ -48,6 +52,11 @@ const useNewConvo = (index = 0) => { const setSubmission = useSetRecoilState(store.submissionByIndex(index)); const { data: endpointsConfig = {} as TEndpointsConfig } = useGetEndpointsQuery(); + const hasAgentAccess = useHasAccess({ + permissionType: PermissionTypes.AGENTS, + permission: Permissions.USE, + }); + const modelsQuery = useGetModelsQuery(); const assistantsListMap = useAssistantListMap(); const { pauseGlobalAudio } = usePauseGlobalAudio(index); @@ -102,8 +111,21 @@ const useNewConvo = (index = 0) => { endpointsConfig, }); + // If the selected endpoint is agents but user doesn't have access, find an alternative + if (defaultEndpoint && isAgentsEndpoint(defaultEndpoint) && !hasAgentAccess) { + defaultEndpoint = Object.keys(endpointsConfig ?? {}).find( + (ep) => !isAgentsEndpoint(ep as EModelEndpoint) && endpointsConfig?.[ep], + ) as EModelEndpoint | undefined; + } + if (!defaultEndpoint) { - defaultEndpoint = Object.keys(endpointsConfig ?? {})[0] as EModelEndpoint; + // Find first available endpoint that's not agents (if no access) or any endpoint + defaultEndpoint = Object.keys(endpointsConfig ?? {}).find((ep) => { + if (isAgentsEndpoint(ep as EModelEndpoint) && !hasAgentAccess) { + return false; + } + return !!endpointsConfig?.[ep]; + }) as EModelEndpoint; } const endpointType = getEndpointField(endpointsConfig, defaultEndpoint, 'type');