diff --git a/api/server/services/Config/getEndpointsConfig.js b/api/server/services/Config/getEndpointsConfig.js index 8ae022e4b3..670bc22d11 100644 --- a/api/server/services/Config/getEndpointsConfig.js +++ b/api/server/services/Config/getEndpointsConfig.js @@ -1,4 +1,10 @@ -const { CacheKeys, EModelEndpoint, orderEndpointsConfig } = require('librechat-data-provider'); +const { + CacheKeys, + EModelEndpoint, + isAgentsEndpoint, + orderEndpointsConfig, + defaultAgentCapabilities, +} = require('librechat-data-provider'); const loadDefaultEndpointsConfig = require('./loadDefaultEConfig'); const loadConfigEndpoints = require('./loadConfigEndpoints'); const getLogStores = require('~/cache/getLogStores'); @@ -80,8 +86,12 @@ async function getEndpointsConfig(req) { * @returns {Promise} */ const checkCapability = async (req, capability) => { + const isAgents = isAgentsEndpoint(req.body?.original_endpoint || req.body?.endpoint); const endpointsConfig = await getEndpointsConfig(req); - const capabilities = endpointsConfig?.[EModelEndpoint.agents]?.capabilities ?? []; + const capabilities = + isAgents || endpointsConfig?.[EModelEndpoint.agents]?.capabilities != null + ? (endpointsConfig?.[EModelEndpoint.agents]?.capabilities ?? []) + : defaultAgentCapabilities; return capabilities.includes(capability); }; diff --git a/client/src/Providers/AgentPanelContext.tsx b/client/src/Providers/AgentPanelContext.tsx index b15d334078..409d8998fb 100644 --- a/client/src/Providers/AgentPanelContext.tsx +++ b/client/src/Providers/AgentPanelContext.tsx @@ -1,9 +1,9 @@ import React, { createContext, useContext, useState } from 'react'; import { Constants, EModelEndpoint } from 'librechat-data-provider'; -import type { TPlugin, AgentToolType, Action, MCP } from 'librechat-data-provider'; +import type { MCP, Action, TPlugin, AgentToolType } from 'librechat-data-provider'; import type { AgentPanelContextType } from '~/common'; import { useAvailableToolsQuery, useGetActionsQuery } from '~/data-provider'; -import { useLocalize } from '~/hooks'; +import { useLocalize, useGetAgentsConfig } from '~/hooks'; import { Panel } from '~/common'; const AgentPanelContext = createContext(undefined); @@ -75,21 +75,25 @@ export function AgentPanelProvider({ children }: { children: React.ReactNode }) {} as Record, ); - const value = { - action, - setAction, + const { agentsConfig, endpointsConfig } = useGetAgentsConfig(); + + const value: AgentPanelContextType = { mcp, - setMcp, mcps, - setMcps, - activePanel, - setActivePanel, - setCurrentAgentId, - agent_id, - groupedTools, /** Query data for actions and tools */ - actions, tools, + action, + setMcp, + actions, + setMcps, + agent_id, + setAction, + activePanel, + groupedTools, + agentsConfig, + setActivePanel, + endpointsConfig, + setCurrentAgentId, }; return {children}; diff --git a/client/src/Providers/BadgeRowContext.tsx b/client/src/Providers/BadgeRowContext.tsx index 266d0895ba..e54411ed84 100644 --- a/client/src/Providers/BadgeRowContext.tsx +++ b/client/src/Providers/BadgeRowContext.tsx @@ -1,17 +1,25 @@ import React, { createContext, useContext, useEffect, useRef } from 'react'; -import { Tools, LocalStorageKeys, AgentCapabilities, Constants } from 'librechat-data-provider'; -import { useMCPSelect, useToolToggle, useCodeApiKeyForm, useSearchApiKeyForm } from '~/hooks'; -import { useGetStartupConfig } from '~/data-provider'; import { useSetRecoilState } from 'recoil'; +import { Tools, Constants, LocalStorageKeys, AgentCapabilities } from 'librechat-data-provider'; +import type { TAgentsEndpoint } from 'librechat-data-provider'; +import { + useSearchApiKeyForm, + useGetAgentsConfig, + useCodeApiKeyForm, + useToolToggle, + useMCPSelect, +} from '~/hooks'; +import { useGetStartupConfig } from '~/data-provider'; import { ephemeralAgentByConvoId } from '~/store'; interface BadgeRowContextType { conversationId?: string | null; + agentsConfig?: TAgentsEndpoint | null; mcpSelect: ReturnType; webSearch: ReturnType; - codeInterpreter: ReturnType; - fileSearch: ReturnType; artifacts: ReturnType; + fileSearch: ReturnType; + codeInterpreter: ReturnType; codeApiKeyForm: ReturnType; searchApiKeyForm: ReturnType; startupConfig: ReturnType['data']; @@ -40,6 +48,7 @@ export default function BadgeRowProvider({ }: BadgeRowProviderProps) { const hasInitializedRef = useRef(false); const lastKeyRef = useRef(''); + const { agentsConfig } = useGetAgentsConfig(); const key = conversationId ?? Constants.NEW_CONVO; const setEphemeralAgent = useSetRecoilState(ephemeralAgentByConvoId(key)); @@ -165,8 +174,9 @@ export default function BadgeRowProvider({ const value: BadgeRowContextType = { mcpSelect, webSearch, - fileSearch, artifacts, + fileSearch, + agentsConfig, startupConfig, conversationId, codeApiKeyForm, diff --git a/client/src/common/types.ts b/client/src/common/types.ts index 9349b7695e..52575e180d 100644 --- a/client/src/common/types.ts +++ b/client/src/common/types.ts @@ -206,9 +206,7 @@ export type AgentPanelProps = { setActivePanel: React.Dispatch>; setMcp: React.Dispatch>; setAction: React.Dispatch>; - endpointsConfig?: t.TEndpointsConfig; setCurrentAgentId: React.Dispatch>; - agentsConfig?: t.TAgentsEndpoint | null; }; export type AgentPanelContextType = { @@ -225,6 +223,8 @@ export type AgentPanelContextType = { setCurrentAgentId: React.Dispatch>; groupedTools?: Record; agent_id?: string; + agentsConfig?: t.TAgentsEndpoint | null; + endpointsConfig?: t.TEndpointsConfig | null; }; export type AgentModelPanelProps = { diff --git a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx index c038f30114..9fe2988606 100644 --- a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx +++ b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx @@ -2,11 +2,10 @@ import { useSetRecoilState } from 'recoil'; import * as Ariakit from '@ariakit/react'; import React, { useRef, useState, useMemo } from 'react'; import { FileSearch, ImageUpIcon, TerminalSquareIcon, FileType2Icon } from 'lucide-react'; +import { EToolResources, EModelEndpoint, defaultAgentCapabilities } from 'librechat-data-provider'; import type { EndpointFileConfig } from 'librechat-data-provider'; +import { useLocalize, useGetAgentsConfig, useFileHandling, useAgentCapabilities } from '~/hooks'; import { FileUpload, TooltipAnchor, DropdownPopup, AttachmentIcon } from '~/components'; -import { EToolResources, EModelEndpoint } from 'librechat-data-provider'; -import { useGetEndpointsQuery } from '~/data-provider'; -import { useLocalize, useFileHandling } from '~/hooks'; import { ephemeralAgentByConvoId } from '~/store'; import { cn } from '~/utils'; @@ -23,20 +22,17 @@ const AttachFileMenu = ({ disabled, conversationId, endpointFileConfig }: Attach const [isPopoverActive, setIsPopoverActive] = useState(false); const setEphemeralAgent = useSetRecoilState(ephemeralAgentByConvoId(conversationId)); const [toolResource, setToolResource] = useState(); - const { data: endpointsConfig } = useGetEndpointsQuery(); const { handleFileChange } = useFileHandling({ overrideEndpoint: EModelEndpoint.agents, overrideEndpointFileConfig: endpointFileConfig, }); + const { agentsConfig } = useGetAgentsConfig(); /** TODO: Ephemeral Agent Capabilities * Allow defining agent capabilities on a per-endpoint basis * Use definition for agents endpoint for ephemeral agents * */ - const capabilities = useMemo( - () => endpointsConfig?.[EModelEndpoint.agents]?.capabilities ?? [], - [endpointsConfig], - ); + const capabilities = useAgentCapabilities(agentsConfig?.capabilities ?? defaultAgentCapabilities); const handleUploadClick = (isImage?: boolean) => { if (!inputRef.current) { @@ -60,7 +56,7 @@ const AttachFileMenu = ({ disabled, conversationId, endpointFileConfig }: Attach }, ]; - if (capabilities.includes(EToolResources.ocr)) { + if (capabilities.ocrEnabled) { items.push({ label: localize('com_ui_upload_ocr_text'), onClick: () => { @@ -71,7 +67,7 @@ const AttachFileMenu = ({ disabled, conversationId, endpointFileConfig }: Attach }); } - if (capabilities.includes(EToolResources.file_search)) { + if (capabilities.fileSearchEnabled) { items.push({ label: localize('com_ui_upload_file_search'), onClick: () => { @@ -83,7 +79,7 @@ const AttachFileMenu = ({ disabled, conversationId, endpointFileConfig }: Attach }); } - if (capabilities.includes(EToolResources.execute_code)) { + if (capabilities.codeEnabled) { items.push({ label: localize('com_ui_upload_code_files'), onClick: () => { diff --git a/client/src/components/Chat/Input/ToolsDropdown.tsx b/client/src/components/Chat/Input/ToolsDropdown.tsx index 84e03cd30b..859a7be745 100644 --- a/client/src/components/Chat/Input/ToolsDropdown.tsx +++ b/client/src/components/Chat/Input/ToolsDropdown.tsx @@ -2,12 +2,18 @@ import React, { useState, useMemo, useCallback } from 'react'; import * as Ariakit from '@ariakit/react'; import { Globe, Settings, Settings2, TerminalSquareIcon } from 'lucide-react'; import type { MenuItemProps } from '~/common'; -import { Permissions, PermissionTypes, AuthType, ArtifactModes } from 'librechat-data-provider'; +import { + AuthType, + Permissions, + ArtifactModes, + PermissionTypes, + defaultAgentCapabilities, +} from 'librechat-data-provider'; import { TooltipAnchor, DropdownPopup } from '~/components'; +import { useLocalize, useHasAccess, useAgentCapabilities } from '~/hooks'; import ArtifactsSubMenu from '~/components/Chat/Input/ArtifactsSubMenu'; import MCPSubMenu from '~/components/Chat/Input/MCPSubMenu'; import { PinIcon, VectorIcon } from '~/components/svg'; -import { useLocalize, useHasAccess } from '~/hooks'; import { useBadgeRowContext } from '~/Providers'; import { cn } from '~/utils'; @@ -24,11 +30,15 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => { mcpSelect, artifacts, fileSearch, + agentsConfig, startupConfig, codeApiKeyForm, codeInterpreter, searchApiKeyForm, } = useBadgeRowContext(); + const { codeEnabled, webSearchEnabled, artifactsEnabled, fileSearchEnabled } = + useAgentCapabilities(agentsConfig?.capabilities ?? defaultAgentCapabilities); + const { setIsDialogOpen: setIsCodeDialogOpen, menuTriggerRef: codeMenuTriggerRef } = codeApiKeyForm; const { setIsDialogOpen: setIsSearchDialogOpen, menuTriggerRef: searchMenuTriggerRef } = @@ -128,9 +138,10 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => { const mcpPlaceholder = startupConfig?.interface?.mcpServers?.placeholder; - const dropdownItems = useMemo(() => { - const items: MenuItemProps[] = []; - items.push({ + const dropdownItems: MenuItemProps[] = []; + + if (fileSearchEnabled) { + dropdownItems.push({ onClick: handleFileSearchToggle, hideOnClick: false, render: (props) => ( @@ -159,117 +170,118 @@ const ToolsDropdown = ({ disabled }: ToolsDropdownProps) => { ), }); + } - if (canUseWebSearch) { - items.push({ - onClick: handleWebSearchToggle, - hideOnClick: false, - render: (props) => ( -
-
- - {localize('com_ui_web_search')} -
-
- {showWebSearchSettings && ( - - )} + if (canUseWebSearch && webSearchEnabled) { + dropdownItems.push({ + onClick: handleWebSearchToggle, + hideOnClick: false, + render: (props) => ( +
+
+ + {localize('com_ui_web_search')} +
+
+ {showWebSearchSettings && ( -
-
- ), - }); - } - - if (canRunCode) { - items.push({ - onClick: handleCodeInterpreterToggle, - hideOnClick: false, - render: (props) => ( -
-
- - {localize('com_assistants_code_interpreter')} -
-
- {showCodeSettings && ( - + )} + +
+
+ ), + }); + } + + if (canRunCode && codeEnabled) { + dropdownItems.push({ + onClick: handleCodeInterpreterToggle, + hideOnClick: false, + render: (props) => ( +
+
+ + {localize('com_assistants_code_interpreter')} +
+
+ {showCodeSettings && ( -
+ )} +
- ), - }); - } +
+ ), + }); + } - // Add Artifacts option - items.push({ + if (artifactsEnabled) { + dropdownItems.push({ hideOnClick: false, render: (props) => ( { /> ), }); + } - if (mcpServerNames && mcpServerNames.length > 0) { - items.push({ - hideOnClick: false, - render: (props) => ( - - ), - }); - } - - return items; - }, [ - localize, - mcpValues, - canRunCode, - isMCPPinned, - isCodePinned, - mcpPlaceholder, - mcpServerNames, - isSearchPinned, - setIsMCPPinned, - canUseWebSearch, - setIsCodePinned, - handleMCPToggle, - showCodeSettings, - setIsSearchPinned, - handleShadcnToggle, - handleCustomToggle, - isFileSearchPinned, - isArtifactsPinned, - codeMenuTriggerRef, - setIsCodeDialogOpen, - searchMenuTriggerRef, - showWebSearchSettings, - setIsFileSearchPinned, - artifacts.toggleState, - setIsArtifactsPinned, - handleWebSearchToggle, - setIsSearchDialogOpen, - handleFileSearchToggle, - handleArtifactsToggle, - handleCodeInterpreterToggle, - ]); + if (mcpServerNames && mcpServerNames.length > 0) { + dropdownItems.push({ + hideOnClick: false, + render: (props) => ( + + ), + }); + } const menuTrigger = ( ) { +export default function AdvancedPanel() { const localize = useLocalize(); const methods = useFormContext(); const { control, watch } = methods; const currentAgentId = watch('id'); + + const { agentsConfig, setActivePanel } = useAgentPanelContext(); const chainEnabled = useMemo( () => agentsConfig?.capabilities.includes(AgentCapabilities.chain) ?? false, [agentsConfig], diff --git a/client/src/components/SidePanel/Agents/AgentConfig.tsx b/client/src/components/SidePanel/Agents/AgentConfig.tsx index b622868acd..c2b621e35b 100644 --- a/client/src/components/SidePanel/Agents/AgentConfig.tsx +++ b/client/src/components/SidePanel/Agents/AgentConfig.tsx @@ -1,9 +1,10 @@ import React, { useState, useMemo, useCallback } from 'react'; +import { EModelEndpoint } from 'librechat-data-provider'; import { Controller, useWatch, useFormContext } from 'react-hook-form'; -import { EModelEndpoint, AgentCapabilities } from 'librechat-data-provider'; import type { AgentForm, AgentPanelProps, IconComponentTypes } from '~/common'; import { cn, defaultTextProps, removeFocusOutlines, getEndpointField, getIconKey } from '~/utils'; import { useToastContext, useFileMapContext, useAgentPanelContext } from '~/Providers'; +import useAgentCapabilities from '~/hooks/Agents/useAgentCapabilities'; import Action from '~/components/SidePanel/Builder/Action'; import { ToolSelectDialog } from '~/components/Tools'; import { icons } from '~/hooks/Endpoint/Icons'; @@ -26,17 +27,20 @@ const inputClass = cn( removeFocusOutlines, ); -export default function AgentConfig({ - agentsConfig, - createMutation, - endpointsConfig, -}: Pick) { +export default function AgentConfig({ createMutation }: Pick) { const localize = useLocalize(); const fileMap = useFileMapContext(); const { showToast } = useToastContext(); const methods = useFormContext(); const [showToolDialog, setShowToolDialog] = useState(false); - const { actions, setAction, groupedTools: allTools, setActivePanel } = useAgentPanelContext(); + const { + actions, + setAction, + agentsConfig, + setActivePanel, + endpointsConfig, + groupedTools: allTools, + } = useAgentPanelContext(); const { control } = methods; const provider = useWatch({ control, name: 'provider' }); @@ -45,34 +49,15 @@ export default function AgentConfig({ const tools = useWatch({ control, name: 'tools' }); const agent_id = useWatch({ control, name: 'id' }); - const toolsEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.tools) ?? false, - [agentsConfig], - ); - const actionsEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.actions) ?? false, - [agentsConfig], - ); - const artifactsEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.artifacts) ?? false, - [agentsConfig], - ); - const ocrEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.ocr) ?? false, - [agentsConfig], - ); - const fileSearchEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.file_search) ?? false, - [agentsConfig], - ); - const webSearchEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.web_search) ?? false, - [agentsConfig], - ); - const codeEnabled = useMemo( - () => agentsConfig?.capabilities?.includes(AgentCapabilities.execute_code) ?? false, - [agentsConfig], - ); + const { + ocrEnabled, + codeEnabled, + toolsEnabled, + actionsEnabled, + artifactsEnabled, + webSearchEnabled, + fileSearchEnabled, + } = useAgentCapabilities(agentsConfig?.capabilities); const context_files = useMemo(() => { if (typeof agent === 'string') { diff --git a/client/src/components/SidePanel/Agents/AgentPanel.tsx b/client/src/components/SidePanel/Agents/AgentPanel.tsx index 78874e41c5..1df54f829d 100644 --- a/client/src/components/SidePanel/Agents/AgentPanel.tsx +++ b/client/src/components/SidePanel/Agents/AgentPanel.tsx @@ -7,8 +7,6 @@ import { Constants, SystemRoles, EModelEndpoint, - TAgentsEndpoint, - TEndpointsConfig, isAssistantsEndpoint, } from 'librechat-data-provider'; import type { AgentForm, StringOption } from '~/common'; @@ -30,19 +28,15 @@ import { Button } from '~/components'; import ModelPanel from './ModelPanel'; import { Panel } from '~/common'; -export default function AgentPanel({ - agentsConfig, - endpointsConfig, -}: { - agentsConfig: TAgentsEndpoint | null; - endpointsConfig: TEndpointsConfig; -}) { +export default function AgentPanel() { const localize = useLocalize(); const { user } = useAuthContext(); const { showToast } = useToastContext(); const { activePanel, + agentsConfig, setActivePanel, + endpointsConfig, setCurrentAgentId, agent_id: current_agent_id, } = useAgentPanelContext(); @@ -323,14 +317,10 @@ export default function AgentPanel({ )} {canEditAgent && !agentQuery.isInitialLoading && activePanel === Panel.builder && ( - + )} {canEditAgent && !agentQuery.isInitialLoading && activePanel === Panel.advanced && ( - + )} {canEditAgent && !agentQuery.isInitialLoading && ( (() => { - const config = endpointsConfig?.[EModelEndpoint.agents] ?? null; - if (!config) return null; - - return { - ...(config as TConfig), - capabilities: Array.isArray(config.capabilities) - ? config.capabilities.map((cap) => cap as unknown as AgentCapabilities) - : ([] as AgentCapabilities[]), - } as TAgentsEndpoint; - }, [endpointsConfig]); - useEffect(() => { const agent_id = conversation?.agent_id ?? ''; if (agent_id) { @@ -57,5 +39,5 @@ function AgentPanelSwitchWithContext() { if (activePanel === Panel.mcp) { return ; } - return ; + return ; } diff --git a/client/src/hooks/Agents/index.ts b/client/src/hooks/Agents/index.ts index 08c0a61666..2aeba8a34c 100644 --- a/client/src/hooks/Agents/index.ts +++ b/client/src/hooks/Agents/index.ts @@ -1,2 +1,4 @@ export { default as useAgentsMap } from './useAgentsMap'; export { default as useSelectAgent } from './useSelectAgent'; +export { default as useAgentCapabilities } from './useAgentCapabilities'; +export { default as useGetAgentsConfig } from './useGetAgentsConfig'; diff --git a/client/src/hooks/Agents/useAgentCapabilities.ts b/client/src/hooks/Agents/useAgentCapabilities.ts new file mode 100644 index 0000000000..4a14d9db0f --- /dev/null +++ b/client/src/hooks/Agents/useAgentCapabilities.ts @@ -0,0 +1,61 @@ +import { useMemo } from 'react'; +import { AgentCapabilities } from 'librechat-data-provider'; + +interface AgentCapabilitiesResult { + toolsEnabled: boolean; + actionsEnabled: boolean; + artifactsEnabled: boolean; + ocrEnabled: boolean; + fileSearchEnabled: boolean; + webSearchEnabled: boolean; + codeEnabled: boolean; +} + +export default function useAgentCapabilities( + capabilities: AgentCapabilities[] | undefined, +): AgentCapabilitiesResult { + const toolsEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.tools) ?? false, + [capabilities], + ); + + const actionsEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.actions) ?? false, + [capabilities], + ); + + const artifactsEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.artifacts) ?? false, + [capabilities], + ); + + const ocrEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.ocr) ?? false, + [capabilities], + ); + + const fileSearchEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.file_search) ?? false, + [capabilities], + ); + + const webSearchEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.web_search) ?? false, + [capabilities], + ); + + const codeEnabled = useMemo( + () => capabilities?.includes(AgentCapabilities.execute_code) ?? false, + [capabilities], + ); + + return { + ocrEnabled, + codeEnabled, + toolsEnabled, + actionsEnabled, + artifactsEnabled, + webSearchEnabled, + fileSearchEnabled, + }; +} diff --git a/client/src/hooks/Agents/useGetAgentsConfig.ts b/client/src/hooks/Agents/useGetAgentsConfig.ts new file mode 100644 index 0000000000..ce9d22f5f5 --- /dev/null +++ b/client/src/hooks/Agents/useGetAgentsConfig.ts @@ -0,0 +1,35 @@ +import { useMemo } from 'react'; +import { EModelEndpoint, AgentCapabilities } from 'librechat-data-provider'; +import type { TAgentsEndpoint, TEndpointsConfig, TConfig } from 'librechat-data-provider'; +import { useGetEndpointsQuery } from '~/data-provider'; + +interface UseGetAgentsConfigOptions { + endpointsConfig?: TEndpointsConfig; +} + +export default function useGetAgentsConfig(options?: UseGetAgentsConfigOptions): { + agentsConfig?: TAgentsEndpoint | null; + endpointsConfig?: TEndpointsConfig | null; +} { + const { endpointsConfig: providedConfig } = options || {}; + + const { data: queriedConfig } = useGetEndpointsQuery({ + enabled: !providedConfig, + }); + + const endpointsConfig = providedConfig || queriedConfig; + + const agentsConfig = useMemo(() => { + const config = endpointsConfig?.[EModelEndpoint.agents] ?? null; + if (!config) return null; + + return { + ...(config as TConfig), + capabilities: Array.isArray(config.capabilities) + ? config.capabilities.map((cap) => cap as unknown as AgentCapabilities) + : ([] as AgentCapabilities[]), + } as TAgentsEndpoint; + }, [endpointsConfig]); + + return { agentsConfig, endpointsConfig }; +} diff --git a/client/src/hooks/Files/useFileHandling.ts b/client/src/hooks/Files/useFileHandling.ts index cd1c5834c8..3438417769 100644 --- a/client/src/hooks/Files/useFileHandling.ts +++ b/client/src/hooks/Files/useFileHandling.ts @@ -25,10 +25,10 @@ import useUpdateFiles from './useUpdateFiles'; type UseFileHandling = { fileSetter?: FileSetter; - fileFilter?: (file: File) => boolean; - additionalMetadata?: Record; overrideEndpoint?: EModelEndpoint; + fileFilter?: (file: File) => boolean; overrideEndpointFileConfig?: EndpointFileConfig; + additionalMetadata?: Record; }; const useFileHandling = (params?: UseFileHandling) => { @@ -151,6 +151,10 @@ const useFileHandling = (params?: UseFileHandling) => { const formData = new FormData(); formData.append('endpoint', endpoint); + formData.append( + 'original_endpoint', + conversation?.endpointType || conversation?.endpoint || '', + ); formData.append('file', extendedFile.file as File, encodeURIComponent(filename)); formData.append('file_id', extendedFile.file_id); diff --git a/client/src/utils/endpoints.ts b/client/src/utils/endpoints.ts index 497c76aca6..60585132d4 100644 --- a/client/src/utils/endpoints.ts +++ b/client/src/utils/endpoints.ts @@ -59,7 +59,7 @@ export const getAvailableEndpoints = ( /** Get the specified field from the endpoint config */ export function getEndpointField( - endpointsConfig: t.TEndpointsConfig | undefined, + endpointsConfig: t.TEndpointsConfig | undefined | null, endpoint: EModelEndpoint | string | null | undefined, property: K, ): t.TConfig[K] | undefined { @@ -246,7 +246,7 @@ export function getIconKey({ endpointIconURL: iconURL, }: { endpoint?: string | null; - endpointsConfig?: t.TEndpointsConfig; + endpointsConfig?: t.TEndpointsConfig | null; endpointType?: string | null; endpointIconURL?: string; }): keyof IconsRecord {