From 511b6307f7a8508444897c78cf653886c928126f Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Mon, 25 May 2026 13:42:25 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=A9=B9=20fix:=20Address=20codex/copilot?= =?UTF-8?q?=20review=20on=20API=20Keys=20tab?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Exclude `userProvideURL` from the eligibility predicate. A user-provided baseURL alone does not imply a user key, but the tab would still prompt for one via `SetKeyDialog`'s required-fields validation. - Extract `isUserProvidedEndpointConfig` into a shared util so the predicate cannot drift between `Settings.tsx` (tab visibility) and `APIKeys.tsx` (row listing). - Drop the `endpoint as EModelEndpoint` cast in `APIKeyRow`. `SetKeyDialog` already accepts `EModelEndpoint | string`; the cast was unsafe for custom endpoint names. - Add a regression test pinning the baseURL-only exclusion. --- client/src/components/Nav/Settings.spec.tsx | 10 ++++++++++ client/src/components/Nav/Settings.tsx | 14 ++----------- .../Nav/SettingsTabs/APIKeys/APIKeyRow.tsx | 4 ++-- .../Nav/SettingsTabs/APIKeys/APIKeys.tsx | 13 ++---------- .../Nav/SettingsTabs/APIKeys/utils.ts | 20 +++++++++++++++++++ 5 files changed, 36 insertions(+), 25 deletions(-) create mode 100644 client/src/components/Nav/SettingsTabs/APIKeys/utils.ts diff --git a/client/src/components/Nav/Settings.spec.tsx b/client/src/components/Nav/Settings.spec.tsx index 6472d4ff57..20faef2191 100644 --- a/client/src/components/Nav/Settings.spec.tsx +++ b/client/src/components/Nav/Settings.spec.tsx @@ -101,6 +101,16 @@ describe('Settings', () => { expect(screen.getByText('com_nav_setting_api_keys')).toBeInTheDocument(); }); + it('hides the API Keys tab for endpoints with a user-provided baseURL but a fixed API key', () => { + mockUseGetEndpointsQuery.mockReturnValue({ + data: { LiteLLM: { userProvide: false, userProvideURL: true, order: 0 } }, + }); + + renderSettings(); + + expect(screen.queryByText('com_nav_setting_api_keys')).not.toBeInTheDocument(); + }); + it('resets the active tab when loaded config disables About', async () => { const user = userEvent.setup(); const { rerender } = renderSettings(); diff --git a/client/src/components/Nav/Settings.tsx b/client/src/components/Nav/Settings.tsx index 2f49229042..94b863be61 100644 --- a/client/src/components/Nav/Settings.tsx +++ b/client/src/components/Nav/Settings.tsx @@ -24,6 +24,7 @@ import { APIKeys, About, } from './SettingsTabs'; +import { isUserProvidedEndpointConfig } from './SettingsTabs/APIKeys/utils'; import usePersonalizationAccess from '~/hooks/usePersonalizationAccess'; import { useLocalize, TranslationKeys } from '~/hooks'; import { useGetEndpointsQuery, useGetStartupConfig } from '~/data-provider'; @@ -45,18 +46,7 @@ export default function Settings({ open, onOpenChange }: TDialogProps) { } const values = Object.values(endpointsConfig); for (let i = 0; i < values.length; i++) { - const config = values[i]; - if (!config) { - continue; - } - if ( - config.userProvide || - config.userProvideURL || - config.userProvideAccessKeyId || - config.userProvideSecretAccessKey || - config.userProvideSessionToken || - config.userProvideBearerToken - ) { + if (isUserProvidedEndpointConfig(values[i])) { return true; } } diff --git a/client/src/components/Nav/SettingsTabs/APIKeys/APIKeyRow.tsx b/client/src/components/Nav/SettingsTabs/APIKeys/APIKeyRow.tsx index ce9619bb40..8f93a8a5a5 100644 --- a/client/src/components/Nav/SettingsTabs/APIKeys/APIKeyRow.tsx +++ b/client/src/components/Nav/SettingsTabs/APIKeys/APIKeyRow.tsx @@ -1,7 +1,7 @@ import React, { useMemo, useState } from 'react'; import { Button } from '@librechat/client'; import { alternateName, getEndpointField } from 'librechat-data-provider'; -import type { EModelEndpoint, TEndpointsConfig } from 'librechat-data-provider'; +import type { TEndpointsConfig } from 'librechat-data-provider'; import { SetKeyDialog } from '~/components/Input/SetKeyDialog'; import { icons } from '~/hooks/Endpoint/Icons'; import { useUserKey, useLocalize } from '~/hooks'; @@ -62,7 +62,7 @@ const APIKeyRow = ({ endpoint, endpointsConfig }: APIKeyRowProps) => { { + if (!config) { + return false; + } + return ( + !!config.userProvide || + !!config.userProvideAccessKeyId || + !!config.userProvideSecretAccessKey || + !!config.userProvideSessionToken || + !!config.userProvideBearerToken + ); +};