From b51d2f198a0ab53b380f0f814f2728732f2c6022 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Fri, 10 Jan 2025 18:48:11 -0500 Subject: [PATCH 1/2] refactor: improve typing --- client/src/common/types.ts | 9 +++- .../components/Chat/Menus/Endpoints/Icons.tsx | 6 +-- client/src/utils/endpoints.ts | 4 +- client/src/utils/presets.ts | 42 +++++++++---------- 4 files changed, 32 insertions(+), 29 deletions(-) diff --git a/client/src/common/types.ts b/client/src/common/types.ts index f952cd28328..292d4a73045 100644 --- a/client/src/common/types.ts +++ b/client/src/common/types.ts @@ -91,7 +91,14 @@ export type IconMapProps = { size?: number; }; -export type AgentIconMapProps = IconMapProps & { agentName: string }; +export type IconComponent = React.ComponentType; +export type AgentIconComponent = React.ComponentType; +export type IconComponentTypes = IconComponent | AgentIconComponent; +export type IconsRecord = { + [key in t.EModelEndpoint | 'unknown' | string]: IconComponentTypes | null | undefined; +}; + +export type AgentIconMapProps = IconMapProps & { agentName?: string }; export type NavLink = { title: string; diff --git a/client/src/components/Chat/Menus/Endpoints/Icons.tsx b/client/src/components/Chat/Menus/Endpoints/Icons.tsx index a8910625f67..3fbae8e010e 100644 --- a/client/src/components/Chat/Menus/Endpoints/Icons.tsx +++ b/client/src/components/Chat/Menus/Endpoints/Icons.tsx @@ -1,5 +1,5 @@ import { EModelEndpoint } from 'librechat-data-provider'; -import type { IconMapProps, AgentIconMapProps } from '~/common'; +import type { IconMapProps, AgentIconMapProps, IconsRecord } from '~/common'; import { Feather } from 'lucide-react'; import { MinimalPlugin, @@ -42,7 +42,7 @@ const AssistantAvatar = ({ }; const AgentAvatar = ({ className = '', avatar = '', agentName, size }: AgentIconMapProps) => { - if (agentName && avatar) { + if (agentName != null && agentName && avatar) { return ( { return ; }; -export const icons = { +export const icons: IconsRecord = { [EModelEndpoint.azureOpenAI]: AzureMinimalIcon, [EModelEndpoint.openAI]: GPTIcon, [EModelEndpoint.gptPlugins]: MinimalPlugin, diff --git a/client/src/utils/endpoints.ts b/client/src/utils/endpoints.ts index 83d0dfc4614..0df88a0fa16 100644 --- a/client/src/utils/endpoints.ts +++ b/client/src/utils/endpoints.ts @@ -7,7 +7,7 @@ import { isAssistantsEndpoint, } from 'librechat-data-provider'; import type * as t from 'librechat-data-provider'; -import type { LocalizeFunction } from '~/common'; +import type { LocalizeFunction, IconsRecord } from '~/common'; export const getEntityName = ({ name = '', @@ -222,7 +222,7 @@ export function getIconKey({ endpointsConfig?: t.TEndpointsConfig; endpointType?: string | null; endpointIconURL?: string; -}) { +}): keyof IconsRecord { const endpointType = _eType ?? getEndpointField(endpointsConfig, endpoint, 'type') ?? ''; const endpointIconURL = iconURL ?? getEndpointField(endpointsConfig, endpoint, 'iconURL') ?? ''; if (endpointIconURL && EModelEndpoint[endpointIconURL] != null) { diff --git a/client/src/utils/presets.ts b/client/src/utils/presets.ts index 6a157b4dcf6..552977423a2 100644 --- a/client/src/utils/presets.ts +++ b/client/src/utils/presets.ts @@ -1,17 +1,6 @@ import type { TPreset, TPlugin } from 'librechat-data-provider'; import { EModelEndpoint } from 'librechat-data-provider'; -export const getPresetIcon = (preset: TPreset, Icon) => { - return Icon({ - size: 20, - endpoint: preset?.endpoint, - model: preset?.model, - error: false, - className: 'icon-md', - isCreatedByUser: false, - }); -}; - type TEndpoints = Array; export const getPresetTitle = (preset: TPreset, mention?: boolean) => { @@ -27,7 +16,7 @@ export const getPresetTitle = (preset: TPreset, mention?: boolean) => { toneStyle, } = preset; let title = ''; - let modelInfo = model || ''; + let modelInfo = model ?? ''; let label = ''; const usesChatGPTLabel: TEndpoints = [ @@ -37,24 +26,31 @@ export const getPresetTitle = (preset: TPreset, mention?: boolean) => { ]; const usesModelLabel: TEndpoints = [EModelEndpoint.google, EModelEndpoint.anthropic]; - if (endpoint && usesChatGPTLabel.includes(endpoint)) { - label = chatGptLabel || ''; - } else if (endpoint && usesModelLabel.includes(endpoint)) { - label = modelLabel || ''; + if (endpoint != null && endpoint && usesChatGPTLabel.includes(endpoint)) { + label = chatGptLabel ?? ''; + } else if (endpoint != null && endpoint && usesModelLabel.includes(endpoint)) { + label = modelLabel ?? ''; } else if (endpoint === EModelEndpoint.bingAI) { - modelInfo = jailbreak ? 'Sydney' : modelInfo; - label = toneStyle ? `: ${toneStyle}` : ''; + modelInfo = jailbreak === true ? 'Sydney' : modelInfo; + label = toneStyle != null && toneStyle ? `: ${toneStyle}` : ''; } - if (label && presetTitle && label.toLowerCase().includes(presetTitle.toLowerCase())) { + if ( + label && + presetTitle != null && + presetTitle && + label.toLowerCase().includes(presetTitle.toLowerCase()) + ) { title = label + ': '; label = ''; - } else if (presetTitle && presetTitle.trim() !== 'New Chat') { + } else if (presetTitle != null && presetTitle && presetTitle.trim() !== 'New Chat') { title = presetTitle + ': '; } - if (mention) { - return `${modelInfo}${label ? ` | ${label}` : ''}${promptPrefix ? ` | ${promptPrefix}` : ''}${ + if (mention === true) { + return `${modelInfo}${label ? ` | ${label}` : ''}${ + promptPrefix != null && promptPrefix ? ` | ${promptPrefix}` : '' + }${ tools ? ` | ${tools .map((tool: TPlugin | string) => { @@ -74,7 +70,7 @@ export const getPresetTitle = (preset: TPreset, mention?: boolean) => { /** Remove unavailable tools from the preset */ export const removeUnavailableTools = ( preset: TPreset, - availableTools: Record, + availableTools: Record, ) => { const newPreset = { ...preset }; From 2b7a182e0dec7b98f5c8cbf118d6c8d7a57bacc1 Mon Sep 17 00:00:00 2001 From: Danny Avila Date: Fri, 10 Jan 2025 18:51:02 -0500 Subject: [PATCH 2/2] fix: "TypeError: Icon is not a function" with proper use of Functional Component and Improved Typing --- .../Chat/Menus/Presets/PresetItems.tsx | 41 +++++++++++-------- .../src/components/Chat/Menus/PresetsMenu.tsx | 4 +- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/client/src/components/Chat/Menus/Presets/PresetItems.tsx b/client/src/components/Chat/Menus/Presets/PresetItems.tsx index 90021188c8d..d5df89a0626 100644 --- a/client/src/components/Chat/Menus/Presets/PresetItems.tsx +++ b/client/src/components/Chat/Menus/Presets/PresetItems.tsx @@ -16,7 +16,7 @@ import { cn } from '~/utils'; import store from '~/store'; const PresetItems: FC<{ - presets: TPreset[]; + presets?: Array; onSetDefaultPreset: (preset: TPreset, remove?: boolean) => void; onSelectPreset: (preset: TPreset) => void; onChangePreset: (preset: TPreset) => void; @@ -110,11 +110,17 @@ const PresetItems: FC<{ )} - presetId).join('.')}> + preset?.presetId) + .filter((p) => p) + .join('.')} + > {presets && presets.length > 0 && presets.map((preset, i) => { - if (!preset || !preset.presetId) { + const presetId = preset?.presetId ?? ''; + if (!preset || !presetId) { return null; } @@ -122,22 +128,23 @@ const PresetItems: FC<{ const Icon = icons[iconKey]; return ( - -
- + +
+ onSelectPreset(preset)} icon={ - Icon && - Icon({ - context: 'menu-item', - iconURL: getEndpointField(endpointsConfig, preset.endpoint, 'iconURL'), - className: 'icon-md mr-1 dark:text-white', - endpoint: preset.endpoint, - }) + Icon != null && ( + + ) } selected={false} data-testid={`preset-item-${preset}`} @@ -146,17 +153,17 @@ const PresetItems: FC<{