diff --git a/api/models/Agent.js b/api/models/Agent.js
index d33ca8a8bf..04ba8b020e 100644
--- a/api/models/Agent.js
+++ b/api/models/Agent.js
@@ -70,6 +70,9 @@ const loadEphemeralAgent = async ({ req, agent_id, endpoint, model_parameters: _
if (ephemeralAgent?.execute_code === true) {
tools.push(Tools.execute_code);
}
+ if (ephemeralAgent?.file_search === true) {
+ tools.push(Tools.file_search);
+ }
if (ephemeralAgent?.web_search === true) {
tools.push(Tools.web_search);
}
diff --git a/client/src/components/Chat/Input/CodeInterpreter.tsx b/client/src/components/Chat/Input/CodeInterpreter.tsx
index 411f1e27b3..f4b380f5b1 100644
--- a/client/src/components/Chat/Input/CodeInterpreter.tsx
+++ b/client/src/components/Chat/Input/CodeInterpreter.tsx
@@ -1,5 +1,5 @@
import debounce from 'lodash/debounce';
-import React, { memo, useMemo, useCallback, useRef } from 'react';
+import React, { memo, useMemo, useCallback, useEffect, useRef } from 'react';
import { useRecoilState } from 'recoil';
import { TerminalSquareIcon } from 'lucide-react';
import {
@@ -45,6 +45,9 @@ function CodeInterpreter({ conversationId }: { conversationId?: string | null })
return ephemeralAgent?.execute_code ?? false;
}, [ephemeralAgent?.execute_code]);
+ /** Track previous value to prevent infinite loops */
+ const prevIsCodeToggleEnabled = useRef(isCodeToggleEnabled);
+
const { data } = useVerifyAgentToolAuth(
{ toolId: Tools.execute_code },
{
@@ -60,7 +63,7 @@ function CodeInterpreter({ conversationId }: { conversationId?: string | null })
(isChecked: boolean) => {
setEphemeralAgent((prev) => ({
...prev,
- execute_code: isChecked,
+ [Tools.execute_code]: isChecked,
}));
},
[setEphemeralAgent],
@@ -90,6 +93,13 @@ function CodeInterpreter({ conversationId }: { conversationId?: string | null })
[handleChange],
);
+ useEffect(() => {
+ if (prevIsCodeToggleEnabled.current !== isCodeToggleEnabled) {
+ setRunCode(isCodeToggleEnabled);
+ }
+ prevIsCodeToggleEnabled.current = isCodeToggleEnabled;
+ }, [isCodeToggleEnabled, runCode, setRunCode]);
+
if (!canRunCode) {
return null;
}
diff --git a/client/src/components/Chat/Input/Files/AttachFileChat.tsx b/client/src/components/Chat/Input/Files/AttachFileChat.tsx
index 11bca082fe..f120b4f8f1 100644
--- a/client/src/components/Chat/Input/Files/AttachFileChat.tsx
+++ b/client/src/components/Chat/Input/Files/AttachFileChat.tsx
@@ -1,32 +1,20 @@
-import { memo, useMemo } from 'react';
-import { useRecoilValue } from 'recoil';
+import { memo } from 'react';
import {
Constants,
supportsFiles,
mergeFileConfig,
- isAgentsEndpoint,
- isEphemeralAgent,
EndpointFileConfig,
fileConfig as defaultFileConfig,
} from 'librechat-data-provider';
import { useChatContext } from '~/Providers';
import { useGetFileConfig } from '~/data-provider';
-import { ephemeralAgentByConvoId } from '~/store';
import AttachFileMenu from './AttachFileMenu';
-import AttachFile from './AttachFile';
function AttachFileChat({ disableInputs }: { disableInputs: boolean }) {
const { conversation } = useChatContext();
-
+ const conversationId = conversation?.conversationId ?? Constants.NEW_CONVO;
const { endpoint: _endpoint, endpointType } = conversation ?? { endpoint: null };
- const key = conversation?.conversationId ?? Constants.NEW_CONVO;
- const ephemeralAgent = useRecoilValue(ephemeralAgentByConvoId(key));
- const isAgents = useMemo(
- () => isAgentsEndpoint(_endpoint) || isEphemeralAgent(_endpoint, ephemeralAgent),
- [_endpoint, ephemeralAgent],
- );
-
const { data: fileConfig = defaultFileConfig } = useGetFileConfig({
select: (data) => mergeFileConfig(data),
});
@@ -38,11 +26,8 @@ function AttachFileChat({ disableInputs }: { disableInputs: boolean }) {
const endpointSupportsFiles: boolean = supportsFiles[endpointType ?? _endpoint ?? ''] ?? false;
const isUploadDisabled = (disableInputs || endpointFileConfig?.disabled) ?? false;
- if (isAgents) {
- return ;
- }
if (endpointSupportsFiles && !isUploadDisabled) {
- return ;
+ return ;
}
return null;
diff --git a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx
index 85df07f24f..dbb794849d 100644
--- a/client/src/components/Chat/Input/Files/AttachFileMenu.tsx
+++ b/client/src/components/Chat/Input/Files/AttachFileMenu.tsx
@@ -1,21 +1,25 @@
+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 { 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';
-interface AttachFileProps {
+interface AttachFileMenuProps {
+ conversationId: string;
disabled?: boolean | null;
}
-const AttachFile = ({ disabled }: AttachFileProps) => {
+const AttachFileMenu = ({ disabled, conversationId }: AttachFileMenuProps) => {
const localize = useLocalize();
const isUploadDisabled = disabled ?? false;
const inputRef = useRef(null);
const [isPopoverActive, setIsPopoverActive] = useState(false);
+ const setEphemeralAgent = useSetRecoilState(ephemeralAgentByConvoId(conversationId));
const [toolResource, setToolResource] = useState();
const { data: endpointsConfig } = useGetEndpointsQuery();
const { handleFileChange } = useFileHandling({
@@ -69,6 +73,10 @@ const AttachFile = ({ disabled }: AttachFileProps) => {
label: localize('com_ui_upload_file_search'),
onClick: () => {
setToolResource(EToolResources.file_search);
+ setEphemeralAgent((prev) => ({
+ ...prev,
+ [EToolResources.file_search]: true,
+ }));
handleUploadClick();
},
icon: ,
@@ -80,6 +88,10 @@ const AttachFile = ({ disabled }: AttachFileProps) => {
label: localize('com_ui_upload_code_files'),
onClick: () => {
setToolResource(EToolResources.execute_code);
+ setEphemeralAgent((prev) => ({
+ ...prev,
+ [EToolResources.execute_code]: true,
+ }));
handleUploadClick();
},
icon: ,
@@ -87,7 +99,7 @@ const AttachFile = ({ disabled }: AttachFileProps) => {
}
return items;
- }, [capabilities, localize, setToolResource]);
+ }, [capabilities, localize, setToolResource, setEphemeralAgent]);
const menuTrigger = (
{
);
};
-export default React.memo(AttachFile);
+export default React.memo(AttachFileMenu);
diff --git a/packages/data-provider/src/types.ts b/packages/data-provider/src/types.ts
index 275c405c1a..469c378aba 100644
--- a/packages/data-provider/src/types.ts
+++ b/packages/data-provider/src/types.ts
@@ -98,6 +98,7 @@ export type TEndpointOption = Pick<
export type TEphemeralAgent = {
mcp?: string[];
web_search?: boolean;
+ file_search?: boolean;
execute_code?: boolean;
};