| import { useRecoilState } from 'recoil'; | |
| import { EModelEndpoint, SettingsViews } from 'librechat-data-provider'; | |
| import { Button, MessagesSquared, GPTIcon, AssistantIcon, DataIcon } from '@librechat/client'; | |
| import type { ReactNode } from 'react'; | |
| import { useChatContext } from '~/Providers'; | |
| import { useLocalize } from '~/hooks'; | |
| import { cn } from '~/utils/'; | |
| import store from '~/store'; | |
| type TPopoverButton = { | |
| label: string; | |
| buttonClass: string; | |
| handler: () => void; | |
| type?: 'alternative'; | |
| icon: ReactNode; | |
| }; | |
| export default function PopoverButtons({ | |
| buttonClass, | |
| iconClass = '', | |
| endpoint: _overrideEndpoint, | |
| endpointType: overrideEndpointType, | |
| model: overrideModel, | |
| }: { | |
| buttonClass?: string; | |
| iconClass?: string; | |
| endpoint?: EModelEndpoint | string; | |
| endpointType?: EModelEndpoint | string | null; | |
| model?: string | null; | |
| }) { | |
| const { | |
| conversation, | |
| optionSettings, | |
| setOptionSettings, | |
| showAgentSettings, | |
| setShowAgentSettings, | |
| } = useChatContext(); | |
| const localize = useLocalize(); | |
| const [settingsView, setSettingsView] = useRecoilState(store.currentSettingsView); | |
| const { model: _model, endpoint: _endpoint, endpointType } = conversation ?? {}; | |
| const overrideEndpoint = overrideEndpointType ?? _overrideEndpoint; | |
| const endpoint = overrideEndpoint ?? endpointType ?? _endpoint ?? ''; | |
| const model = overrideModel ?? _model; | |
| const isGenerativeModel = /gemini|learnlm|gemma/.test(model ?? '') ?? false; | |
| const isChatModel = (!isGenerativeModel && model?.toLowerCase().includes('chat')) ?? false; | |
| const isTextModel = !isGenerativeModel && !isChatModel && /code|text/.test(model ?? ''); | |
| const { showExamples } = optionSettings; | |
| const showExamplesButton = !isGenerativeModel && !isTextModel && isChatModel; | |
| const triggerExamples = () => { | |
| setSettingsView(SettingsViews.default); | |
| setOptionSettings((prev) => ({ ...prev, showExamples: !(prev.showExamples ?? false) })); | |
| }; | |
| const endpointSpecificbuttons: { [key: string]: TPopoverButton[] } = { | |
| [EModelEndpoint.google]: [ | |
| { | |
| label: localize(showExamples === true ? 'com_hide_examples' : 'com_show_examples'), | |
| buttonClass: isGenerativeModel === true || isTextModel ? 'disabled' : '', | |
| handler: triggerExamples, | |
| icon: <MessagesSquared className={cn('mr-1 w-[14px]', iconClass)} />, | |
| }, | |
| ], | |
| [EModelEndpoint.gptPlugins]: [ | |
| { | |
| label: localize( | |
| showAgentSettings ? 'com_show_completion_settings' : 'com_show_agent_settings', | |
| ), | |
| buttonClass: '', | |
| handler: () => { | |
| setSettingsView(SettingsViews.default); | |
| setShowAgentSettings((prev) => !prev); | |
| }, | |
| icon: <GPTIcon className={cn('mr-1 w-[14px]', iconClass)} size={24} />, | |
| }, | |
| ], | |
| }; | |
| if (!endpoint) { | |
| return null; | |
| } | |
| if (endpoint === EModelEndpoint.google && !showExamplesButton) { | |
| return null; | |
| } | |
| const additionalButtons: { [key: string]: TPopoverButton[] } = { | |
| [SettingsViews.default]: [ | |
| { | |
| label: 'Context Settings', | |
| buttonClass: '', | |
| type: 'alternative', | |
| handler: () => setSettingsView(SettingsViews.advanced), | |
| icon: <DataIcon className={cn('mr-1 h-6 w-[14px]', iconClass)} />, | |
| }, | |
| ], | |
| [SettingsViews.advanced]: [ | |
| { | |
| label: 'Model Settings', | |
| buttonClass: '', | |
| type: 'alternative', | |
| handler: () => setSettingsView(SettingsViews.default), | |
| icon: <AssistantIcon className={cn('mr-1 h-6 w-[14px]', iconClass)} />, | |
| }, | |
| ], | |
| }; | |
| const endpointButtons = (endpointSpecificbuttons[endpoint] as TPopoverButton[] | null) ?? []; | |
| const disabled = true; | |
| return ( | |
| <div className="flex w-full justify-between"> | |
| <div className="flex items-center justify-start"> | |
| {endpointButtons.map((button, index) => ( | |
| <Button | |
| key={`button-${index}`} | |
| type="button" | |
| className={cn( | |
| button.buttonClass, | |
| 'border border-gray-300/50 focus:ring-1 focus:ring-green-500/90 dark:border-gray-500/50 dark:focus:ring-green-500', | |
| 'ml-1 h-full bg-transparent px-2 py-1 text-xs font-normal text-black hover:bg-gray-100 hover:text-black dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-white', | |
| buttonClass ?? '', | |
| )} | |
| onClick={button.handler} | |
| > | |
| {button.icon} | |
| {button.label} | |
| </Button> | |
| ))} | |
| </div> | |
| {disabled ? null : ( | |
| <div className="flex w-[150px] items-center justify-end"> | |
| {additionalButtons[settingsView].map((button, index) => ( | |
| <Button | |
| key={`button-${index}`} | |
| type="button" | |
| className={cn( | |
| button.buttonClass, | |
| 'flex justify-center border border-gray-300/50 focus:ring-1 focus:ring-green-500/90 dark:border-gray-500/50 dark:focus:ring-green-500', | |
| 'h-full w-full bg-transparent px-2 py-1 text-xs font-normal text-black hover:bg-gray-100 hover:text-black dark:bg-transparent dark:text-white dark:hover:bg-gray-600 dark:hover:text-white', | |
| buttonClass ?? '', | |
| )} | |
| onClick={button.handler} | |
| > | |
| {button.icon} | |
| {button.label} | |
| </Button> | |
| ))} | |
| </div> | |
| )} | |
| </div> | |
| ); | |
| } | |